ludic.base: a queue's fact records come round again (q_rec / q_ring_add), used by effects, clock, wallet, weather, tracks, needs, fire, settings, update, steps, crafting, shop, gear, hints, session and photo instead of a new record per fact; the minimap's marks cleared and rubbed out in place, its scale steps without a list; the clock's dice seeded again, not made again; once-per-join, per-save and pool-miss paths declared
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5be2422c84
commit
d9612ba2a6
31 changed files with 215 additions and 25 deletions
|
|
@ -12,6 +12,7 @@ export property HandlePool {
|
|||
}
|
||||
|
||||
# everything the pool will ever hold, made now: nothing after this allocates
|
||||
@alloc_ok("a pool made at start: its owner keeps it")
|
||||
export function hd_pool_new(name: string, cap: int) -> HandlePool {
|
||||
let p = new HandlePool
|
||||
p.name = name
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import "tick.ludic"
|
|||
import "kept.ludic"
|
||||
import "handle.ludic"
|
||||
import "queue.ludic"
|
||||
import "queue_ring.ludic"
|
||||
import "text_buf.ludic"
|
||||
import "text_intern.ludic"
|
||||
import "text_ring.ludic"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ export property Queue<T> {
|
|||
tag: QueueTag = null
|
||||
none: []T = null # what draining an empty queue hands back, never pushed to
|
||||
spare: []T = null # the list the last drain handed out: cleared and reused by the next
|
||||
ring: []T = null # the facts' records, used again once no list holds them (queue_ring.ludic)
|
||||
ring_at: int = 0
|
||||
}
|
||||
# what a queue says about itself, whatever it holds: its name and how many facts wait in it
|
||||
export property QueueTag {
|
||||
|
|
@ -26,6 +28,7 @@ export function queue_new<T>(name: string) -> Queue<T> {
|
|||
q.tag.name = name
|
||||
q.none = new []T
|
||||
q.spare = new []T
|
||||
q.ring = new []T
|
||||
return q
|
||||
}
|
||||
|
||||
|
|
|
|||
21
packages/ludic.base/queue_ring.ludic
Normal file
21
packages/ludic.base/queue_ring.ludic
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# ludic.base/queue_ring.ludic - a fact's record made again rather than new: Ludic frees nothing, and a
|
||||
# mechanic reports all day. q_rec hands out a record neither waiting in the queue nor handed out by
|
||||
# its last drain, or null when every one is: the caller makes one more and q_ring_add keeps it, so
|
||||
# the ring grows to the busiest frame and stays there. The caller sets every field it reads
|
||||
export function q_rec<T>(q: Queue<T>) -> T {
|
||||
let n = len(q.ring)
|
||||
for t in 0 .. n {
|
||||
let r = q.ring[q.ring_at]
|
||||
q.ring_at = (q.ring_at + 1) % n
|
||||
if not q_holds(q, r) { return r }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function q_ring_add<T>(q: Queue<T>, r: T) -> void { kept_push(q.ring, r) }
|
||||
|
||||
function q_holds<T>(q: Queue<T>, r: T) -> bool {
|
||||
for i in 0 .. len(q.items) { if q.items[i] == r { return true } }
|
||||
for i in 0 .. len(q.spare) { if q.spare[i] == r { return true } }
|
||||
return false
|
||||
}
|
||||
|
|
@ -134,6 +134,32 @@ program QueueTest {
|
|||
test "a queue holds records" () { record_case() }
|
||||
test "clear drops what is waiting" () { clear_case() }
|
||||
test "a pool's records are free once no drain holds them" () { unheld_case() }
|
||||
function rec_of(q: Queue<Caught>) -> Caught {
|
||||
var c = q_rec(q)
|
||||
if c == null {
|
||||
c = new Caught
|
||||
q_ring_add(q, c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
function ring_case() -> void {
|
||||
let q: Queue<Caught> = queue_new("caught")
|
||||
let a = rec_of(q)
|
||||
q_push(q, a)
|
||||
let b = rec_of(q)
|
||||
expect(a != b)
|
||||
q_push(q, b)
|
||||
q_drain(q)
|
||||
expect_eq(len(q.ring), 2)
|
||||
let c = rec_of(q)
|
||||
expect(c != a and c != b)
|
||||
q_push(q, c)
|
||||
q_drain(q)
|
||||
let d = rec_of(q)
|
||||
expect(d == a or d == b)
|
||||
expect_eq(len(q.ring), 3)
|
||||
}
|
||||
test "a fact's record comes round again once no list holds it" () { ring_case() }
|
||||
test "a queue's element type is told by the queue alone" () { infer_case() }
|
||||
test "the undrained queues are named, and a drain clears the report" () { undrained_case() }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue