A mechanic package depends on ludic.base and nothing else: ports (records of function values for now) for questions, queues for facts, verbs for changes, phases for order and its own versioned save section. The runner inits, resets, saves and loads systems in the order added and ticks them phase by phase; a missing save section is a reset. Tests for each piece and a worked route between two toy mechanics live under tests/. The old ludic.core (engine ECS components) is used by examples/library and stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
1.5 KiB
Text
58 lines
1.5 KiB
Text
# ludic.base/queue.ludic - a mechanic reports what HAPPENED as facts in a queue it owns, and the
|
|
# game drains it in a later phase. First in, first out; nothing here rolls dice or reorders.
|
|
export property Queue<T> {
|
|
items: []T = null
|
|
id: int = -1
|
|
}
|
|
|
|
# every named queue's pending count, so a frame's end can say which facts nobody read
|
|
var qb_names: []string = null
|
|
var qb_pending: []int = null
|
|
|
|
function qb_init() -> void {
|
|
if qb_names != null { return }
|
|
qb_names = new []string
|
|
qb_pending = new []int
|
|
}
|
|
|
|
# a queue; the name is only for core_undrained
|
|
export function q_new<T>(name: string) -> Queue<T> {
|
|
qb_init()
|
|
let q = new Queue<T>
|
|
q.items = new []T
|
|
q.id = len(qb_names)
|
|
push(qb_names, name)
|
|
push(qb_pending, 0)
|
|
return q
|
|
}
|
|
|
|
export function q_push<T>(q: Queue<T>, v: T) -> void {
|
|
push(q.items, v)
|
|
qb_pending[q.id] = len(q.items)
|
|
}
|
|
|
|
# the facts in the order they were pushed; the queue is empty afterwards
|
|
export function q_drain<T>(q: Queue<T>) -> []T {
|
|
let out = q.items
|
|
q.items = new []T
|
|
qb_pending[q.id] = 0
|
|
return out
|
|
}
|
|
|
|
export function q_len<T>(q: Queue<T>) -> int { return len(q.items) }
|
|
|
|
export function q_clear<T>(q: Queue<T>) -> void {
|
|
q.items = new []T
|
|
qb_pending[q.id] = 0
|
|
}
|
|
|
|
# the names of the queues still holding facts; call it at the end of a frame, where a fact
|
|
# left behind is a route nobody wrote
|
|
export function core_undrained() -> []string {
|
|
qb_init()
|
|
let out = new []string
|
|
for i in 0 .. len(qb_names) {
|
|
if qb_pending[i] > 0 { push(out, qb_names[i]) }
|
|
}
|
|
return out
|
|
}
|