diff --git a/packages/ludic.base/handle.ludic b/packages/ludic.base/handle.ludic index 0195e417..5c592728 100644 --- a/packages/ludic.base/handle.ludic +++ b/packages/ludic.base/handle.ludic @@ -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 diff --git a/packages/ludic.base/index.ludic b/packages/ludic.base/index.ludic index 201eadfe..2670ff47 100644 --- a/packages/ludic.base/index.ludic +++ b/packages/ludic.base/index.ludic @@ -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" diff --git a/packages/ludic.base/queue.ludic b/packages/ludic.base/queue.ludic index f0ba09e9..6533737b 100644 --- a/packages/ludic.base/queue.ludic +++ b/packages/ludic.base/queue.ludic @@ -5,6 +5,8 @@ export property Queue { 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(name: string) -> Queue { q.tag.name = name q.none = new []T q.spare = new []T + q.ring = new []T return q } diff --git a/packages/ludic.base/queue_ring.ludic b/packages/ludic.base/queue_ring.ludic new file mode 100644 index 00000000..fba2e074 --- /dev/null +++ b/packages/ludic.base/queue_ring.ludic @@ -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(q: Queue) -> 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(q: Queue, r: T) -> void { kept_push(q.ring, r) } + +function q_holds(q: Queue, 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 +} diff --git a/packages/ludic.base/tests/queue_test.ludic b/packages/ludic.base/tests/queue_test.ludic index 224b832a..2bbb3ab4 100644 --- a/packages/ludic.base/tests/queue_test.ludic +++ b/packages/ludic.base/tests/queue_test.ludic @@ -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 { + 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 = 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() } } diff --git a/packages/ludic.clock/verbs.ludic b/packages/ludic.clock/verbs.ludic index fde7127c..74cc37b6 100644 --- a/packages/ludic.clock/verbs.ludic +++ b/packages/ludic.clock/verbs.ludic @@ -13,7 +13,12 @@ export function clock_set_hours(clock_st: mut ClockState, h: float) -> void { function ck_turn(clock_st: mut ClockState, how: int) -> void { clock_st.ck_day += 1 clock_st.ck_moon = (clock_st.ck_moon + 1.0 / clock_st.ck_moon_days) % 1.0 - let d = new DayTurned + var d = q_rec(clock_days(clock_st)) + if d == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + d = new DayTurned + q_ring_add(clock_days(clock_st), d) + } d.day = clock_st.ck_day d.how = how q_push(clock_days(clock_st), d) @@ -35,7 +40,10 @@ export function clock_advance(clock_st: mut ClockState, gh: float) -> void { # a new trip: day one at the start hour, the moon somewhere in its month export function clock_reset(clock_st: mut ClockState) -> void { - clock_st.ck_dice = rng_new(ClockWorld.seed()) + if clock_st.ck_dice == null { + @alloc_ok("once: the clock's dice, seeded again on every new trip after") + clock_st.ck_dice = rng_new(ClockWorld.seed()) + } else { rng_seed(clock_st.ck_dice, ClockWorld.seed()) } clock_st.ck_day = 1 clock_st.ck_hours = clock_st.ck_start_hours clock_st.ck_moon = rng_span(clock_st.ck_dice, clock_st.ck_moon_lo, clock_st.ck_moon_hi) % 1.0 diff --git a/packages/ludic.crafting/verbs.ludic b/packages/ludic.crafting/verbs.ludic index cde2bb4a..ec6cb015 100644 --- a/packages/ludic.crafting/verbs.ludic +++ b/packages/ludic.crafting/verbs.ludic @@ -51,7 +51,12 @@ export function craft_refund(i: int) -> void { function craft_fact_push(crafting_st: CraftingState, i: int, queued: bool) -> void { let r = CraftRecipes[i] - let c = new Crafted + var c = q_rec(craft_facts(crafting_st)) + if c == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + c = new Crafted + q_ring_add(craft_facts(crafting_st), c) + } c.recipe = i c.item = r.out c.n = r.n diff --git a/packages/ludic.effects/verbs.ludic b/packages/ludic.effects/verbs.ludic index 8a7e6c45..292ff6b4 100644 --- a/packages/ludic.effects/verbs.ludic +++ b/packages/ludic.effects/verbs.ludic @@ -2,7 +2,12 @@ # itself; a bonus past the cap pushes out the oldest bonus; a full ring drops the nearest end. function ef_end(effects_st: mut EffectsState, i: int, why: int) -> void { let all = ef_all(effects_st) - let e = new EffectEnded + var e = q_rec(effects_ended(effects_st)) + if e == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + e = new EffectEnded + q_ring_add(effects_ended(effects_st), e) + } e.kind = all[i].kind e.label = all[i].label e.why = why diff --git a/packages/ludic.fire/state.ludic b/packages/ludic.fire/state.ludic index b383f157..98409b55 100644 --- a/packages/ludic.fire/state.ludic +++ b/packages/ludic.fire/state.ludic @@ -48,7 +48,12 @@ export function fire_facts(fire_st: FireState) -> Queue { } function fr_fact(fire_st: FireState, what: int) -> void { - let f = new FireFact + var f = q_rec(fire_facts(fire_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new FireFact + q_ring_add(fire_facts(fire_st), f) + } f.what = what f.fuel = fire_st.fr_fuel q_push(fire_facts(fire_st), f) diff --git a/packages/ludic.gear/state.ludic b/packages/ludic.gear/state.ludic index e8046c68..0ca24918 100644 --- a/packages/ludic.gear/state.ludic +++ b/packages/ludic.gear/state.ludic @@ -27,11 +27,18 @@ function gear__offs() -> []bool { export function gear_facts(gear_st: GearState) -> Queue { return gear_st.gear__q } function gear__fact(gear_st: GearState, what: int, k: int, c: int, cost: int) -> void { - let f = new GearFact + var f = q_rec(gear_facts(gear_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new GearFact + q_ring_add(gear_facts(gear_st), f) + } f.what = what f.cost = cost f.kind = k f.charge = c + f.level = 0 + f.item = -1 if k >= 0 { f.level = gear_st.gear__lv[k] f.item = GearKinds[k].item diff --git a/packages/ludic.hints/rail.ludic b/packages/ludic.hints/rail.ludic index bc59a176..c505b1d4 100644 --- a/packages/ludic.hints/rail.ludic +++ b/packages/ludic.hints/rail.ludic @@ -18,7 +18,12 @@ export function hints_facts(hints_st: HintsState) -> Queue { } function hn_fact(hints_st: HintsState, what: int, card: int) -> void { - let f = new HintsFact + var f = q_rec(hints_facts(hints_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new HintsFact + q_ring_add(hints_facts(hints_st), f) + } f.what = what f.card = card q_push(hints_facts(hints_st), f) diff --git a/packages/ludic.inventory/verbs.ludic b/packages/ludic.inventory/verbs.ludic index 1197be27..e98ec789 100644 --- a/packages/ludic.inventory/verbs.ludic +++ b/packages/ludic.inventory/verbs.ludic @@ -7,7 +7,10 @@ function iv_change(inventory_st: mut InventoryState, it: int, after: int) -> voi if len(inventory_st.iv_pool) > 0 { c = inventory_st.iv_pool[inventory_st.iv_at] inventory_st.iv_at = (inventory_st.iv_at + 1) % len(inventory_st.iv_pool) - } else { c = new ItemChanged } + } else { + @alloc_ok("never after inv_config: the ring is made there") + c = new ItemChanged + } c.item = it c.before = before c.after = after diff --git a/packages/ludic.jobs/facts.ludic b/packages/ludic.jobs/facts.ludic index 23f67446..628847dd 100644 --- a/packages/ludic.jobs/facts.ludic +++ b/packages/ludic.jobs/facts.ludic @@ -11,7 +11,9 @@ function jobs__fact_record(jobs_st: mut JobsState) -> JobsFact { jobs_st.jobs__fnext[0] += 1 return f } + @alloc_ok("a pool miss: past the most facts held at once, then kept in the pool") let f = new JobsFact + @alloc_ok("as above") push(jobs_st.jobs__fpool, f) return f } diff --git a/packages/ludic.jobs/save.ludic b/packages/ludic.jobs/save.ludic index fedc10a3..7f7563ff 100644 --- a/packages/ludic.jobs/save.ludic +++ b/packages/ludic.jobs/save.ludic @@ -16,6 +16,7 @@ function jobs__reset_scope(jobs_st: mut JobsState, sc: int) -> void { jobs_st.jobs__primed = false } +@alloc_ok("on a save: the jobs written out") function jobs__save_scope(jobs_st: JobsState, sc: int) -> Val { let v = Value.object() let js = Value.object() diff --git a/packages/ludic.minimap/explored.ludic b/packages/ludic.minimap/explored.ludic index e0445382..1c847c9b 100644 --- a/packages/ludic.minimap/explored.ludic +++ b/packages/ludic.minimap/explored.ludic @@ -75,6 +75,7 @@ function mm_land_count(minimap_st: mut MinimapState) -> void { export function minimap_land_changed(minimap_st: mut MinimapState) -> void { minimap_st.mm_land_n = 0 } # the grid as one string of 0 / 1, row by row, and back (a shorter string leaves the rest unseen) +@alloc_ok("on a save: the explored grid written out") export function minimap_seen_text(minimap_st: mut MinimapState) -> string { mm_grid(minimap_st) var s = "" diff --git a/packages/ludic.minimap/grid.ludic b/packages/ludic.minimap/grid.ludic index 21feb013..f9af4713 100644 --- a/packages/ludic.minimap/grid.ludic +++ b/packages/ludic.minimap/grid.ludic @@ -45,6 +45,7 @@ export function minimap_config(minimap_st: mut MinimapState, cells: int, cell_m: minimap_st.mm_cell_m = Math.max(cell_m, 0.001) minimap_st.mm_core0 = 0 minimap_st.mm_core_n = minimap_st.mm_cells + @alloc_ok("once per map configured: its explored grid") minimap_st.mm_seen = new []int for i in 0 .. minimap_st.mm_cells * minimap_st.mm_cells { push(minimap_st.mm_seen, 0) } minimap_st.mm_land_n = 0 diff --git a/packages/ludic.minimap/pin_edit.ludic b/packages/ludic.minimap/pin_edit.ludic index e012faeb..dee1173d 100644 --- a/packages/ludic.minimap/pin_edit.ludic +++ b/packages/ludic.minimap/pin_edit.ludic @@ -2,9 +2,9 @@ # and which followed, and whether the map is waiting for a place to drop the next export function minimap_pin_remove(minimap_st: mut MinimapState, i: int) -> void { if i < 0 or i >= minimap_pin_count(minimap_st) { return } - let rest = new []MinimapPin - for k in 0 .. len(minimap_st.mm_pins) { if k != i { push(rest, minimap_st.mm_pins[k]) } } - minimap_st.mm_pins = rest + let l = minimap_st.mm_pins + for k in i .. len(l) - 1 { l[k] = l[k + 1] } + List.pop(l) if minimap_st.mm_open == i { minimap_st.mm_open = -1 } else if minimap_st.mm_open > i { minimap_st.mm_open -= 1 } if minimap_st.mm_followed == i { minimap_st.mm_followed = -1 } else if minimap_st.mm_followed > i { minimap_st.mm_followed -= 1 } } diff --git a/packages/ludic.minimap/pins.ludic b/packages/ludic.minimap/pins.ludic index 0bd1b13f..03403852 100644 --- a/packages/ludic.minimap/pins.ludic +++ b/packages/ludic.minimap/pins.ludic @@ -19,7 +19,10 @@ export function minimap_config_pins(minimap_st: mut MinimapState, max: int, symb } export function minimap_pins_clear(minimap_st: mut MinimapState) -> void { - minimap_st.mm_pins = new []MinimapPin + if minimap_st.mm_pins == null { + @alloc_ok("once: the marks' list, cleared after") + minimap_st.mm_pins = new []MinimapPin + } else { List.clear(minimap_st.mm_pins) } minimap_st.mm_open = -1 minimap_st.mm_followed = -1 minimap_st.mm_last = 0 @@ -38,6 +41,7 @@ export function minimap_pin_full(minimap_st: MinimapState) -> bool { return mini export function minimap_pin_add(minimap_st: mut MinimapState, x: float, z: float, icon: int, label: string) -> int { if minimap_st.mm_pins == null { minimap_pins_clear(minimap_st) } if minimap_pin_full(minimap_st) { return -1 } + @alloc_ok("a mark put down: kept, and the map holds at most its most") let p = new MinimapPin p.x = x p.z = z @@ -53,6 +57,7 @@ export function minimap_pin_add(minimap_st: mut MinimapState, x: float, z: float export function minimap_pin_put(minimap_st: mut MinimapState, x: float, z: float, icon: int, colour: int, day: int, label: string) -> int { if minimap_st.mm_pins == null { minimap_pins_clear(minimap_st) } if minimap_pin_full(minimap_st) { return -1 } + @alloc_ok("a mark put down: kept, and the map holds at most its most") let p = new MinimapPin p.x = x p.z = z diff --git a/packages/ludic.minimap/view.ludic b/packages/ludic.minimap/view.ludic index 7651a401..7fb8b010 100644 --- a/packages/ludic.minimap/view.ludic +++ b/packages/ludic.minimap/view.ludic @@ -40,8 +40,10 @@ export function minimap_wz(minimap_st: MinimapState, ry: float) -> float { retur # a round distance whose bar is no wider than a quarter of the window export function minimap_scale_metres(minimap_st: MinimapState) -> int { - let steps = [2000, 1000, 500, 250, 100, 50, 25] - for k in 0 .. len(steps) { if float(steps[k]) * minimap_scale(minimap_st) <= minimap_st.mm_size / 4.0 { return steps[k] } } + for k in 0 .. 7 { + let m = mm_scale_step(k) + if float(m) * minimap_scale(minimap_st) <= minimap_st.mm_size / 4.0 { return m } + } return 25 } @@ -68,3 +70,14 @@ export function minimap_focus(minimap_st: mut MinimapState, on_you: bool) -> voi minimap_recentre(minimap_st, on_you) if minimap_st.mm_zoom < minimap_st.mm_zoom_focus { minimap_st.mm_zoom = Math.clamp(minimap_st.mm_zoom_focus, minimap_st.mm_zoom_min, minimap_st.mm_zoom_max) } } + +# the round distances a scale bar can show, largest first +function mm_scale_step(k: int) -> int { + if k == 0 { return 2000 } + if k == 1 { return 1000 } + if k == 2 { return 500 } + if k == 3 { return 250 } + if k == 4 { return 100 } + if k == 5 { return 50 } + return 25 +} diff --git a/packages/ludic.needs/state.ludic b/packages/ludic.needs/state.ludic index d0d4584a..86d07659 100644 --- a/packages/ludic.needs/state.ludic +++ b/packages/ludic.needs/state.ludic @@ -83,7 +83,12 @@ export function needs_facts(needs_st: NeedsState) -> Queue { } function nd_fact(needs_st: NeedsState, what: int, need: int) -> void { - let f = new NeedFact + var f = q_rec(needs_facts(needs_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new NeedFact + q_ring_add(needs_facts(needs_st), f) + } f.what = what f.need = need q_push(needs_facts(needs_st), f) diff --git a/packages/ludic.net/stun.ludic b/packages/ludic.net/stun.ludic index 4cb94dcb..4cf8016a 100644 --- a/packages/ludic.net/stun.ludic +++ b/packages/ludic.net/stun.ludic @@ -2,6 +2,7 @@ # from outside: the router's address and the port it mapped function net__stun_send(net_st: mut NetState) -> void { + @alloc_ok("once: the transport's dice, seeded by its config the first time a STUN request goes") if net_st.net__dice == null { net_st.net__dice = rng_new(net__conf(net_st).seed) } if net_st.net__stun_ip == 0 { let c = net__conf(net_st) diff --git a/packages/ludic.photo/roll.ludic b/packages/ludic.photo/roll.ludic index 517a459c..e9e95d1a 100644 --- a/packages/ludic.photo/roll.ludic +++ b/packages/ludic.photo/roll.ludic @@ -64,9 +64,23 @@ export function photo_facts(photo_st: PhotoState) -> Queue { } function pht_fact(photo_st: PhotoState, what: int, i: int) -> PhotoFact { - let f = new PhotoFact + var f = q_rec(photo_facts(photo_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new PhotoFact + q_ring_add(photo_facts(photo_st), f) + } f.what = what f.index = i + f.mask = 0 + f.legend = 0 + f.firsts = 0 + f.grade = 0 + f.sign = -1 + f.stars = false + f.file = "" + f.tags = "" + f.v = 0 q_push(photo_facts(photo_st), f) return f } diff --git a/packages/ludic.session/roster.ludic b/packages/ludic.session/roster.ludic index 2b176ad3..1bd67cbd 100644 --- a/packages/ludic.session/roster.ludic +++ b/packages/ludic.session/roster.ludic @@ -28,6 +28,7 @@ export function ply_join(session_st: mut SessionState, pid: int) -> int { if pid <= 0 { return -1 } # 0 is this machine's player for p in 1 .. PLY_MAX { if session_st.session__slot[p].on { continue } + @alloc_ok("once per player joining: their slot's record") let r = new PartyMember r.on = true r.pid = pid diff --git a/packages/ludic.session/state.ludic b/packages/ludic.session/state.ludic index cdd71ab5..59225c64 100644 --- a/packages/ludic.session/state.ludic +++ b/packages/ludic.session/state.ludic @@ -83,11 +83,21 @@ export function ses_facts(session_st: SessionState) -> Queue { } function session__fact(session_st: SessionState, what: int, slot: int, pid: int) -> SessionFact { - let f = new SessionFact + var f = q_rec(ses_facts(session_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new SessionFact + q_ring_add(ses_facts(session_st), f) + } f.what = what f.slot = slot f.pid = pid f.role = session_st.session__role + f.id = 0 + f.kind = 0 + f.param = 0 + f.yes = false + f.text = "" q_push(ses_facts(session_st), f) return f } diff --git a/packages/ludic.settings/store.ludic b/packages/ludic.settings/store.ludic index fd44329c..b28f0654 100644 --- a/packages/ludic.settings/store.ludic +++ b/packages/ludic.settings/store.ludic @@ -46,7 +46,12 @@ export function settings_get_bool(settings_st: SettingsState, id: int) -> bool { export function settings_get_text(settings_st: SettingsState, id: int) -> string { return settings_st.sg_text[id] } function sg_changed(settings_st: SettingsState, id: int) -> void { - let c = new SettingChanged + var c = q_rec(settings_changes(settings_st)) + if c == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + c = new SettingChanged + q_ring_add(settings_changes(settings_st), c) + } c.id = id c.key = settings_st.sg_defs[id].key q_push(settings_changes(settings_st), c) diff --git a/packages/ludic.shop/trade.ludic b/packages/ludic.shop/trade.ludic index 9f0d5b29..27a05673 100644 --- a/packages/ludic.shop/trade.ludic +++ b/packages/ludic.shop/trade.ludic @@ -27,7 +27,12 @@ export function shop_sellable(shop_st: ShopState, v: int) -> []int { } function shop_trade_fact(shop_st: ShopState, what: int, it: int, n: int, price: int) -> void { - let t = new ShopTrade + var t = q_rec(shop_trades(shop_st)) + if t == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + t = new ShopTrade + q_ring_add(shop_trades(shop_st), t) + } t.what = what t.vendor = shop_st.shop_at t.item = it diff --git a/packages/ludic.steps/state.ludic b/packages/ludic.steps/state.ludic index 2de19892..e8a2fc6c 100644 --- a/packages/ludic.steps/state.ludic +++ b/packages/ludic.steps/state.ludic @@ -64,7 +64,12 @@ export function steps_facts(steps_st: StepsState) -> Queue { } function steps__fact(steps_st: StepsState, what: int, ch: int, i: int) -> void { - let f = new StepsFact + var f = q_rec(steps_facts(steps_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new StepsFact + q_ring_add(steps_facts(steps_st), f) + } f.what = what f.chapter = ch f.step = i diff --git a/packages/ludic.tracks/read.ludic b/packages/ludic.tracks/read.ludic index d039da3f..61c9f0ae 100644 --- a/packages/ludic.tracks/read.ludic +++ b/packages/ludic.tracks/read.ludic @@ -15,7 +15,7 @@ function tk_push(tracks_st: mut TracksState, f: TrackRead) -> void { export function tracks_read(tracks_st: mut TracksState, slot: int) -> void { if slot < 0 or tracks_st.tk_ring == null or slot >= len(tracks_st.tk_ring) { return } let t = tracks_st.tk_ring[slot] - let f = new TrackRead + let f = tk_rec(tracks_st) f.sp = t.sp f.source = TRACK_PRINT f.kind = slot / tracks_st.tk_cap @@ -35,7 +35,7 @@ export function tracks_read(tracks_st: mut TracksState, slot: int) -> void { # a sign that is not a print (droppings, a legend's mark): the caller knows whether it is the # first reading of it export function tracks_note(tracks_st: mut TracksState, sp: int, source: int, legend: bool, yaw: float, first: bool) -> void { - let f = new TrackRead + let f = tk_rec(tracks_st) f.sp = sp f.source = source f.legend = legend @@ -53,3 +53,19 @@ export function tracks_note_bearing(tracks_st: mut TracksState, yaw: float) -> v } export function tracks_set_read_count(tracks_st: mut TracksState, n: int) -> void { tracks_st.tk_read_n = n } + +# a reading's record from the queue's ring (ludic.base's q_rec), every field back to its default +function tk_rec(tracks_st: mut TracksState) -> TrackRead { + var f = q_rec(tracks_reads(tracks_st)) + if f == null { + @alloc_ok("past the ring: more readings in a frame than its records, then kept in it") + f = new TrackRead + q_ring_add(tracks_reads(tracks_st), f) + } + f.kind = 0 + f.age = 0.0 + f.fresh = 0 + f.named = true + f.bearing = "" + return f +} diff --git a/packages/ludic.update/state.ludic b/packages/ludic.update/state.ludic index e5394d84..f00be667 100644 --- a/packages/ludic.update/state.ludic +++ b/packages/ludic.update/state.ludic @@ -91,7 +91,12 @@ export function update_facts(update_st: UpdateState) -> Queue { } function update__fact(update_st: UpdateState, what: int) -> void { - let f = new UpdateFact + var f = q_rec(update_facts(update_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new UpdateFact + q_ring_add(update_facts(update_st), f) + } f.what = what f.error = update_st.update__err f.target = update_st.update__target diff --git a/packages/ludic.wallet/wallet.ludic b/packages/ludic.wallet/wallet.ludic index fbf1c711..5f529084 100644 --- a/packages/ludic.wallet/wallet.ludic +++ b/packages/ludic.wallet/wallet.ludic @@ -19,7 +19,12 @@ export function wallet_can(wallet_st: WalletState, n: int) -> bool { return wall # the purse holds exactly n (a starting purse, a correction, the network's word) export function wallet_set(wallet_st: mut WalletState, n: int) -> void { if n == wallet_st.wl_money { return } - let c = new MoneyChanged + var c = q_rec(wallet_changes(wallet_st)) + if c == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + c = new MoneyChanged + q_ring_add(wallet_changes(wallet_st), c) + } c.before = wallet_st.wl_money c.after = n wallet_st.wl_money = n diff --git a/packages/ludic.weather/state.ludic b/packages/ludic.weather/state.ludic index 9e99b11e..39d09c56 100644 --- a/packages/ludic.weather/state.ludic +++ b/packages/ludic.weather/state.ludic @@ -83,7 +83,12 @@ export function weather_facts(weather_st: WeatherState) -> Queue { } function wx_fact(weather_st: WeatherState, what: int, kind: int, from: int) -> void { - let f = new WeatherFact + var f = q_rec(weather_facts(weather_st)) + if f == null { + @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") + f = new WeatherFact + q_ring_add(weather_facts(weather_st), f) + } f.what = what f.kind = kind f.from = from