ludic.things: a Thing's dawn (the last day a restock reached it, saved); things_restock takes the day; things_catch_up restocks a chunk's Things that missed a dawn once a morning would reach them, as that morning would have
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0634116d59
commit
b053bf625c
7 changed files with 57 additions and 8 deletions
|
|
@ -22,6 +22,7 @@ property Thing {
|
|||
timer, used, n # state the kind decides the meaning of
|
||||
sx, sz, syaw # a heading or a point the kind decides the meaning of
|
||||
seat, seats, taken # its seats: the first of the game's seat rows, how many, a bit per one sat in
|
||||
dawn # the last day a restock reached it (saved), for the catch-up
|
||||
shared # the game copies it to others (a party)
|
||||
}
|
||||
```
|
||||
|
|
@ -89,7 +90,8 @@ the actor the moment the Thing exists (a caller often scales or tints it on the
|
|||
| `things_all()`, `things_count()`, `things_ready()`, `thing_by_uid(uid)` | every Thing, in the order placed; whether a world was ever set out |
|
||||
| `thing_find(kind, id)`, `thing_nearest(kind, x, z)`, `things_within(x, z, r)`, `things_each(kind)`, `things_each_all(kind)`, `thing_dist2(t, x, z)` | where they are: only active ones answer except the `_all`; a kind below 0 is any; `within` is nearest first |
|
||||
| `thing_name(t)`, `thing_prompt(t)`, `thing_use(t)`, `thing_can_use(t)`, `thing_reach(t)`, `thing_kind(t)`, `thing_is_personal(t)`, `thing_is_put_down(t)` | the dispatcher |
|
||||
| `things_tick(hours)`, `things_restock()` | every active kind that ticks; every Thing the world grew back and unused |
|
||||
| `things_tick(hours)`, `things_restock(day)` | every active kind that ticks; every Thing the world grew back and unused where a morning reaches (`ThingsWorld.restocks`), its `dawn` set to the day |
|
||||
| `things_catch_up(chunk, day, out)` | a chunk's Things that missed a dawn (`dawn < day`) and a morning now reaches, restocked as that morning would have (no dice), into the caller's list |
|
||||
| `things_facts() -> Queue<ThingFact>` | `{ what, uid, kind, id, owner, x, z }`: `THING_PLACED`, `THING_REMOVED`, `THING_USED` |
|
||||
| `thing_kind_ok(k)`, `thing_kind_by_key(key)` | the kinds |
|
||||
| `things_system() -> System` | `"things"`, `PH_COMMIT`: its save section - every active Thing the port keeps, its kind by KEY, so the game may reorder its kinds - and a reset that removes the kept ones for the load to put back |
|
||||
|
|
|
|||
|
|
@ -16,6 +16,20 @@ export function things_drop_chunk(things_st: mut ThingsState, chunk: int) -> int
|
|||
return n
|
||||
}
|
||||
|
||||
# the chunk's Things that missed a dawn and a morning would now reach, restocked as that morning
|
||||
# would have (no dice: a restock rolls none) and filed into the caller's list; how many
|
||||
export function things_catch_up(things_st: ThingsState, chunk: int, day: int, out: []Thing) -> int {
|
||||
List.clear(out)
|
||||
let rows = ix_rows(things_st.th.chunks, chunk)
|
||||
for i in 0 .. len(rows) {
|
||||
let t = things_st.th.tab.rec[rows[i]]
|
||||
if t.dawn >= day or thing_is_put_down(t) or not ThingsWorld.restocks(t.x, t.z) { continue }
|
||||
th_restock_one(t, day)
|
||||
kept_push(out, t)
|
||||
}
|
||||
return len(out)
|
||||
}
|
||||
|
||||
# change detection: the tick now, the table moving on to the next - a consumer keeps what this
|
||||
# returned and asks things_changed(since: it) for what was written after
|
||||
export function things_now(things_st: mut ThingsState) -> int {
|
||||
|
|
|
|||
|
|
@ -64,14 +64,18 @@ export function things_tick(things_st: mut ThingsState, hours: float) -> void {
|
|||
}
|
||||
}
|
||||
|
||||
# a restock: every Thing the world grew is back, and loses its `used` unless its kind keeps it;
|
||||
# what was put down is left as it is
|
||||
export function things_restock(things_st: ThingsState) -> void {
|
||||
# a restock on `day`: every Thing the world grew where a morning reaches is back, and loses its
|
||||
# `used` unless its kind keeps it; what was put down is left as it is
|
||||
export function things_restock(things_st: ThingsState, day: int) -> void {
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) {
|
||||
let t = all[i]
|
||||
if thing_is_put_down(t) or not ThingsWorld.restocks(t.x, t.z) { continue }
|
||||
if not ThingKinds[t.kind].keeps { t.used = 0 }
|
||||
if not t.active { thing_show(t) }
|
||||
th_restock_one(t, day)
|
||||
}
|
||||
}
|
||||
function th_restock_one(t: Thing, day: int) -> void {
|
||||
if not ThingKinds[t.kind].keeps { t.used = 0 }
|
||||
if not t.active { thing_show(t) }
|
||||
t.dawn = day
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export property Thing {
|
|||
seat: int = -1 # the first of its model's seat rows in the game's table; -1 none
|
||||
seats: int = 0 # how many seat rows follow it
|
||||
taken: int = 0 # a bit per seat someone is sitting in; never saved
|
||||
dawn: int = 0 # the last day a restock reached it (a morning, or a catch-up)
|
||||
shared: bool = false # the game copies it to others (a party)
|
||||
ent: int = -1 # its handle in the table, -1 once removed
|
||||
tab: Table<Thing> = null # the table holding it, so a verb on the Thing alone keeps the indexes
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ function th_clean(t: Thing) -> Thing {
|
|||
t.seat = -1
|
||||
t.seats = 0
|
||||
t.taken = 0
|
||||
t.dawn = 0
|
||||
t.shared = false
|
||||
t.ent = -1
|
||||
t.tab = null
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ function th_to_json(t: Thing) -> Val {
|
|||
sv_put_float(o, "syaw", t.syaw)
|
||||
sv_put_int(o, "seat", t.seat)
|
||||
sv_put_int(o, "seats", t.seats)
|
||||
sv_put_int(o, "dawn", t.dawn)
|
||||
return o
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +62,7 @@ function th_from_json(things_st: mut ThingsState, o: Val) -> void {
|
|||
t.syaw = sv_float(o, "syaw", 0.0)
|
||||
t.seat = sv_int(o, "seat", -1)
|
||||
t.seats = sv_int(o, "seats", 0)
|
||||
t.dawn = sv_int(o, "dawn", 0)
|
||||
let x = sv_float(o, "x", 0.0)
|
||||
let z = sv_float(o, "z", 0.0)
|
||||
let y = sv_float(o, "y", ThingsWorld.ground(x, z))
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ program ThingsTest {
|
|||
shows: int = 0
|
||||
back: int = 0
|
||||
wood: int = 0
|
||||
edge: float = 1000000.0 # a morning reaches x below this (the game's zones)
|
||||
}
|
||||
|
||||
function lit_prompt(t: Thing) -> string {
|
||||
|
|
@ -42,7 +43,8 @@ program ThingsTest {
|
|||
function on_removed(things_test_st: mut ThingsTestState, t: Thing) -> void { things_test_st.gone += 1 }
|
||||
function on_shown(things_test_st: mut ThingsTestState, t: Thing) -> void { things_test_st.shows += 1 }
|
||||
function on_restored(things_test_st: mut ThingsTestState, t: Thing) -> void { things_test_st.back += 1 }
|
||||
bind ThingsWorld { ground: fn hill, placed: fn on_placed, removed: fn on_removed, shown: fn on_shown, restored: fn on_restored }
|
||||
function in_reach(things_test_st: ThingsTestState, x: float, z: float) -> bool { return x < things_test_st.edge }
|
||||
bind ThingsWorld { restocks: fn in_reach, ground: fn hill, placed: fn on_placed, removed: fn on_removed, shown: fn on_shown, restored: fn on_restored }
|
||||
|
||||
function put(things_st: mut ThingsState, kind: int, x: float, z: float) -> Thing { return thing_spawn(things_st, kind, "m", x, 0.0, z, 0.0, 0) }
|
||||
function facts(things_st: ThingsState) -> []ThingFact { return q_drain(things_facts(things_st)) }
|
||||
|
|
@ -129,7 +131,7 @@ program ThingsTest {
|
|||
expect(l.active)
|
||||
things_tick(things_st, 0.6)
|
||||
expect(not l.active)
|
||||
things_restock(things_st)
|
||||
things_restock(things_st, 1)
|
||||
expect(b.active)
|
||||
expect(not l.active)
|
||||
expect_eq(f.used, 1)
|
||||
|
|
@ -292,4 +294,27 @@ program ThingsTest {
|
|||
expect_eq(t.seats, 2)
|
||||
expect_eq(t.taken, 0)
|
||||
}
|
||||
|
||||
test "a Thing a morning missed is restocked once a morning would reach it, and only once" (things_st: mut ThingsState, things_test_st: mut ThingsTestState) {
|
||||
things_clear(things_st)
|
||||
let near = put(things_st, TH_BRANCH, 0.0, 0.0)
|
||||
let far = put(things_st, TH_BRANCH, 500.0, 0.0)
|
||||
thing_use(things_st, near)
|
||||
thing_use(things_st, far)
|
||||
things_test_st.edge = 100.0
|
||||
things_restock(things_st, 3)
|
||||
expect(near.active)
|
||||
expect_eq(near.dawn, 3)
|
||||
expect(not far.active)
|
||||
let out = new []Thing
|
||||
expect_eq(things_catch_up(things_st, things_chunk(500.0, 0.0), 3, out), 0)
|
||||
expect(not far.active)
|
||||
things_test_st.edge = 1000000.0
|
||||
expect_eq(things_catch_up(things_st, things_chunk(500.0, 0.0), 3, out), 1)
|
||||
expect(far.active)
|
||||
expect_eq(far.dawn, 3)
|
||||
expect(out[0] == far)
|
||||
expect_eq(things_catch_up(things_st, things_chunk(500.0, 0.0), 3, out), 0)
|
||||
expect_eq(things_catch_up(things_st, things_chunk(0.0, 0.0), 3, out), 0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue