diff --git a/packages/ludic.things/README.md b/packages/ludic.things/README.md index cfdbb742..0c4a4adf 100644 --- a/packages/ludic.things/README.md +++ b/packages/ludic.things/README.md @@ -52,6 +52,9 @@ away Things all day, so `thing_remove` keeps the record and `thing_put` / `thing oldest one again - set back as new, with a new `uid` - once 32 are waiting. Hold a Thing across a removal only by its `uid` (`thing_by_uid`), never by the record. +A fact's record (`things_facts()`) is kept too: it comes back two drains after it was handed out, so +read a drained list before the drain after next, and copy what must last longer. + ## The port Every member has a default, so any may be left out of the `bind`: diff --git a/packages/ludic.things/dispatch.ludic b/packages/ludic.things/dispatch.ludic index 3c5a3f1e..f0a500f3 100644 --- a/packages/ludic.things/dispatch.ludic +++ b/packages/ludic.things/dispatch.ludic @@ -21,7 +21,7 @@ export function thing_prompt(t: Thing) -> string { } # the kind does what using it does; the use is a fact whatever the kind made of it -export function thing_use(things_st: ThingsState, t: Thing) -> void { +export function thing_use(things_st: mut ThingsState, t: Thing) -> void { if t == null or not thing_kind_ok(t.kind) { return } let k = ThingKinds[t.kind] th_fact(things_st, THING_USED, t) diff --git a/packages/ludic.things/facts.ludic b/packages/ludic.things/facts.ludic new file mode 100644 index 00000000..ff3ed08b --- /dev/null +++ b/packages/ludic.things/facts.ludic @@ -0,0 +1,23 @@ +# facts.ludic - what happened to a Thing, pushed on the package's queue for the game to drain +# a fact's record is one kept for it, not a new one: the halves swap whenever a fact finds the queue +# empty (everything before it drained or cleared), so a record comes back two drains after it was +# handed out - a reader placing a Thing while it reads the last drain's list never sees one change +function th_fact(things_st: mut ThingsState, what: int, t: Thing) -> void { + if q_len(things_st.th_facts) == 0 and things_st.th_fact_n > 0 { + things_st.th_fact_on_b = not things_st.th_fact_on_b + things_st.th_fact_n = 0 + } + var pool = things_st.th_fact_a + if things_st.th_fact_on_b { pool = things_st.th_fact_b } + if things_st.th_fact_n >= len(pool) { push(pool, new ThingFact) } + let f = pool[things_st.th_fact_n] + things_st.th_fact_n += 1 + f.what = what + f.uid = t.uid + f.kind = t.kind + f.id = t.id + f.owner = t.owner + f.x = t.x + f.z = t.z + q_push(things_facts(things_st), f) +} diff --git a/packages/ludic.things/index.ludic b/packages/ludic.things/index.ludic index 76661a7e..0c676826 100644 --- a/packages/ludic.things/index.ludic +++ b/packages/ludic.things/index.ludic @@ -6,6 +6,7 @@ import "ludic.base" import "kinds.ludic" import "port.ludic" import "store.ludic" +import "facts.ludic" import "verbs.ludic" import "moves.ludic" import "queries.ludic" diff --git a/packages/ludic.things/store.ludic b/packages/ludic.things/store.ludic index 4ec3fe18..fad05825 100644 --- a/packages/ludic.things/store.ludic +++ b/packages/ludic.things/store.ludic @@ -26,6 +26,10 @@ export state ThingsState { th_hs: words = words(0) # things_tick's handles, taken before any tick runs th_spare: []Thing = new []Thing # removed records, made again oldest first (spare.ludic) th_spare_at: int = 0 + th_fact_a: []ThingFact = new []ThingFact # the facts' records, two halves (th_fact) + th_fact_b: []ThingFact = new []ThingFact + th_fact_n: int = 0 + th_fact_on_b: bool = false } function th_facts__new() -> Queue { return queue_new("things.facts") } @@ -45,17 +49,6 @@ export function things_facts(things_st: ThingsState) -> Queue { return things_st.th_facts } -function th_fact(things_st: ThingsState, what: int, t: Thing) -> void { - let f = new ThingFact - f.what = what - f.uid = t.uid - f.kind = t.kind - f.id = t.id - f.owner = t.owner - f.x = t.x - f.z = t.z - q_push(things_facts(things_st), f) -} # whether a world has been set out (things_clear) since the program began export function things_ready(things_st: ThingsState) -> bool { return things_st.th.tab != null } diff --git a/packages/ludic.things/tests/things_test.ludic b/packages/ludic.things/tests/things_test.ludic index 806c1ecd..f2f14fb1 100644 --- a/packages/ludic.things/tests/things_test.ludic +++ b/packages/ludic.things/tests/things_test.ludic @@ -246,4 +246,24 @@ program ThingsTest { expect_eq(things_spare_count(things_st), 95) expect_eq(thing_nearest(things_st, TH_SIGN, 9.0, 9.0).uid, warm.uid) } + test "a fact's record is kept: a drained list holds still while its reader places a Thing, and comes back two drains on" (things_st: mut ThingsState) { + things_reset(things_st) + q_clear(things_facts(things_st)) + let a = thing_put(things_st, TH_SIGN, "sign", 1.0, 0.0, 0.0, 0.0, 2.0, 1) + thing_put(things_st, TH_SIGN, "sign", 2.0, 0.0, 0.0, 0.0, 2.0, 2) + let first = q_drain(things_facts(things_st)) + expect_eq(len(first), 2) + let r0: pointer = first[0] + thing_put(things_st, TH_BRANCH, "branch", 3.0, 0.0, 0.0, 0.0, 1.5, 0) + expect_eq(first[0].uid, a.uid) + expect_eq(first[0].what, THING_PLACED) + let second = q_drain(things_facts(things_st)) + expect_eq(len(second), 1) + expect_eq(second[0].kind, TH_BRANCH) + thing_put(things_st, TH_LURE, "lure", 4.0, 0.0, 0.0, 0.0, 2.0, 0) + let third = q_drain(things_facts(things_st)) + let r2: pointer = third[0] + expect(r2 == r0) + expect_eq(third[0].kind, TH_LURE) + } }