From 9e4f4edb92f4f3c89af58baaf0b247d4bd382f70 Mon Sep 17 00:00:00 2001 From: Orkuncakilkaya Date: Sun, 27 Sep 2026 01:29:32 +0300 Subject: [PATCH] refactor(packages): 0.R5 - jobs, session, settings, hints and net make their tables when the state is made, not on the first question (jobs__ensure, session__init and ply_init, sg_init, hn_mute_ensure, net__init gone); their questions read Co-Authored-By: Claude Opus 5.5 --- packages/ludic.hints/mute.ludic | 25 +++---- packages/ludic.hints/rail.ludic | 5 +- packages/ludic.jobs/boards.ludic | 7 +- packages/ludic.jobs/count.ludic | 3 - packages/ludic.jobs/jobs.ludic | 17 ++--- packages/ludic.jobs/lists.ludic | 8 +-- packages/ludic.jobs/posts.ludic | 24 +++---- packages/ludic.jobs/save.ludic | 1 - packages/ludic.jobs/state.ludic | 72 +++++++++---------- packages/ludic.jobs/system.ludic | 6 +- packages/ludic.net/codec.ludic | 5 +- packages/ludic.net/room.ludic | 1 - packages/ludic.net/session.ludic | 5 -- packages/ludic.net/state.ludic | 30 ++++---- packages/ludic.session/README.md | 2 +- packages/ludic.session/roster.ludic | 2 - packages/ludic.session/state.ludic | 15 ++-- .../ludic.session/tests/session_test.ludic | 7 -- packages/ludic.settings/file.ludic | 4 +- packages/ludic.settings/rules.ludic | 3 - packages/ludic.settings/store.ludic | 19 ++--- 21 files changed, 98 insertions(+), 163 deletions(-) diff --git a/packages/ludic.hints/mute.ludic b/packages/ludic.hints/mute.ludic index ae57306c..6c5eb26f 100644 --- a/packages/ludic.hints/mute.ludic +++ b/packages/ludic.hints/mute.ludic @@ -1,27 +1,18 @@ # mute.ludic - the cards a player has said they know, kept BY KEY: a card added, removed or moved in # the registry leaves every other mute where it was, and a key this build does not know is carried -function hn_mute_ensure(hints_st: mut HintsState) -> void { - if hints_st.hn_mute != null { return } - hints_st.hn_mute = new []bool - for i in 0 .. HINT_COUNT { push(hints_st.hn_mute, false) } - hints_st.hn_foreign = new []string -} -export function hints_muted(hints_st: mut HintsState, id: int) -> bool { - hn_mute_ensure(hints_st) +export function hints_muted(hints_st: HintsState, id: int) -> bool { if id < 0 or id >= HINT_COUNT { return false } return hints_st.hn_mute[id] } export function hints_mute(hints_st: mut HintsState, id: int, on: bool) -> void { - hn_mute_ensure(hints_st) if id < 0 or id >= HINT_COUNT { return } hints_st.hn_mute[id] = on } -export function hints_mute_count(hints_st: mut HintsState) -> int { - hn_mute_ensure(hints_st) +export function hints_mute_count(hints_st: HintsState) -> int { var n = 0 for i in 0 .. HINT_COUNT { if hints_st.hn_mute[i] { n += 1 } } return n @@ -29,7 +20,6 @@ export function hints_mute_count(hints_st: mut HintsState) -> int { # every muted card given back, from the next pass export function hints_unmute_all(hints_st: mut HintsState) -> void { - hn_mute_ensure(hints_st) for i in 0 .. HINT_COUNT { hints_st.hn_mute[i] = false } hints_st.hn_foreign = new []string hints_st.hn_t = 0.0 @@ -37,8 +27,7 @@ export function hints_unmute_all(hints_st: mut HintsState) -> void { } # the mutes as a list of keys, for wherever the game keeps the player's own choices -export function hints_mutes_save(hints_st: mut HintsState) -> Val { - hn_mute_ensure(hints_st) +export function hints_mutes_save(hints_st: HintsState) -> Val { let l = Value.list() for i in 0 .. HINT_COUNT { if hints_st.hn_mute[i] { Value.add(l, Value.str(Hints[i].key)) } } for i in 0 .. len(hints_st.hn_foreign) { Value.add(l, Value.str(hints_st.hn_foreign[i])) } @@ -47,8 +36,7 @@ export function hints_mutes_save(hints_st: mut HintsState) -> Val { # a list of keys read back; anything that is not a list is no mutes export function hints_mutes_load(hints_st: mut HintsState, l: Val) -> void { - hints_st.hn_mute = null - hn_mute_ensure(hints_st) + hints_st.hn_mute = hn_mutes() if l == null or Value.kind(l) != 5 { return } for i in 0 .. Value.count(l) { let e = Value.at(l, i) @@ -58,3 +46,8 @@ export function hints_mutes_load(hints_st: mut HintsState, l: Val) -> void { if id >= 0 { hints_st.hn_mute[id] = true } else { push(hints_st.hn_foreign, k) } } } +function hn_mutes() -> []bool { + let out = new []bool + for i in 0 .. HINT_COUNT { push(out, false) } + return out +} diff --git a/packages/ludic.hints/rail.ludic b/packages/ludic.hints/rail.ludic index 20943b0b..5dcdf044 100644 --- a/packages/ludic.hints/rail.ludic +++ b/packages/ludic.hints/rail.ludic @@ -1,8 +1,8 @@ # rail.ludic - the rail: once a pass (a second by default) the most urgent true cards, up to a few, # muted ones left out; in a tie the registry's order decides export state HintsState { - hn_mute: []bool = null - hn_foreign: []string = null # muted keys with no card in this build, written back as read + hn_mute: []bool = hn_mutes() + hn_foreign: []string = new []string # muted keys with no card in this build, written back as read hn_shown: int = 3 # how many the rail holds hn_every: float = 1.0 # seconds between passes hn_top: []int = null # the cards on the rail this pass @@ -36,7 +36,6 @@ function hn_ensure(hints_st: mut HintsState) -> void { hints_st.hn_top = new []int for i in 0 .. hints_st.hn_shown { push(hints_st.hn_top, -1) } } - hn_mute_ensure(hints_st) } # the next pass comes on the next tick rather than in a second diff --git a/packages/ludic.jobs/boards.ludic b/packages/ludic.jobs/boards.ludic index e3947460..d87e9d86 100644 --- a/packages/ludic.jobs/boards.ludic +++ b/packages/ludic.jobs/boards.ludic @@ -2,14 +2,12 @@ # the jobs' own dice seeded by the day, so a board never moves anyone else's rolls export function jobs_board_ok(b: int) -> bool { return b >= 0 and b < BOARD_COUNT } -function jobs__at(jobs_st: mut JobsState, b: int, s: int) -> int { - jobs__ensure(jobs_st) +function jobs__at(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__off[b] + s } # a whole number in [lo, hi] from the jobs' dice: what JobsWorld.roll draws with -export function jobs_roll(jobs_st: mut JobsState, lo: int, hi: int) -> int { - jobs__ensure(jobs_st) +export function jobs_roll(jobs_st: JobsState, lo: int, hi: int) -> int { return rng_between(jobs_st.jobs__dice, lo, hi) } @@ -51,7 +49,6 @@ function jobs__repost(jobs_st: mut JobsState, b: int, s: int) -> void { # a new day, on the boards this machine keeps: an empty or stale post is replaced, and one # finished on an earlier day export function jobs_morning(jobs_st: mut JobsState) -> void { - jobs__ensure(jobs_st) let day = JobsWorld.day() for b in 0 .. BOARD_COUNT { let bd = JobBoards[b] diff --git a/packages/ludic.jobs/count.ludic b/packages/ludic.jobs/count.ludic index bb8a955d..4c4c9ea6 100644 --- a/packages/ludic.jobs/count.ludic +++ b/packages/ludic.jobs/count.ludic @@ -17,7 +17,6 @@ function jobs__takes(only: int, scope: int) -> bool { } function jobs__count(jobs_st: mut JobsState, only: int, kind: int, param: int, n: int) -> void { - jobs__ensure(jobs_st) for i in 0 .. JOB_COUNT { let d = Jobs[i] if jobs_st.jobs__st[i] != JOBS_ACTIVE or not jobs__takes(only, d.scope) { continue } @@ -49,7 +48,6 @@ function jobs__recheck_one(jobs_st: mut JobsState, i: int) -> void { # every job under way against what the state already proves: work done before it was taken counts # for a written job; a post counts only what came after it went up export function jobs_recheck(jobs_st: mut JobsState) -> void { - jobs__ensure(jobs_st) for i in 0 .. JOB_COUNT { jobs__recheck_one(jobs_st, i) } for b in 0 .. BOARD_COUNT { if not JobsWorld.owns(JobBoards[b].scope) { continue } @@ -64,7 +62,6 @@ export function jobs_recheck(jobs_st: mut JobsState) -> void { # offers newly open are said once; the first look after a reset says none of them function jobs__offers(jobs_st: mut JobsState) -> void { - jobs__ensure(jobs_st) for i in 0 .. JOB_COUNT { let now = jobs_offered(jobs_st, i) if now and not jobs_st.jobs__seen[i] and jobs_st.jobs__primed { jobs__fact(jobs_st, JOBS_F_OFFERED, i, -1, -1, 0, Jobs[i].need) } diff --git a/packages/ludic.jobs/jobs.ludic b/packages/ludic.jobs/jobs.ludic index d3656b0a..2ec1c933 100644 --- a/packages/ludic.jobs/jobs.ludic +++ b/packages/ludic.jobs/jobs.ludic @@ -1,26 +1,24 @@ # jobs.ludic - the written jobs: offered by standing and story, taken, readied, handed in and paid export function jobs_ok(i: int) -> bool { return i >= 0 and i < JOB_COUNT } -export function jobs_state(jobs_st: mut JobsState, i: int) -> int { - jobs__ensure(jobs_st) +export function jobs_state(jobs_st: JobsState, i: int) -> int { return jobs_st.jobs__st[i] } -export function jobs_have(jobs_st: mut JobsState, i: int) -> int { - jobs__ensure(jobs_st) +export function jobs_have(jobs_st: JobsState, i: int) -> int { return jobs_st.jobs__hv[i] } -export function jobs_ready_now(jobs_st: mut JobsState, i: int) -> bool { return jobs_state(jobs_st, i) == JOBS_READY } +export function jobs_ready_now(jobs_st: JobsState, i: int) -> bool { return jobs_state(jobs_st, i) == JOBS_READY } # taken and not yet paid -export function jobs_under_way(jobs_st: mut JobsState, i: int) -> bool { +export function jobs_under_way(jobs_st: JobsState, i: int) -> bool { let s = jobs_state(jobs_st, i) return s == JOBS_ACTIVE or s == JOBS_READY } # on offer: not taken, the scope's standing and the story far enough, and the game allowing it -export function jobs_offered(jobs_st: mut JobsState, i: int) -> bool { +export function jobs_offered(jobs_st: JobsState, i: int) -> bool { let d = Jobs[i] if jobs_state(jobs_st, i) != JOBS_OFFERED { return false } return JobsWorld.rep(d.scope) >= d.minrep and JobsWorld.stage() >= d.minstage and JobsWorld.open(i) @@ -79,18 +77,15 @@ export function jobs_complete(jobs_st: mut JobsState, i: int) -> bool { # the state outright: the host's word for a party job, a test export function jobs_set(jobs_st: mut JobsState, i: int, state: int, have: int) -> void { - jobs__ensure(jobs_st) jobs_st.jobs__st[i] = state jobs_st.jobs__hv[i] = have } -export function jobs_done(jobs_st: mut JobsState, group: int) -> int { - jobs__ensure(jobs_st) +export function jobs_done(jobs_st: JobsState, group: int) -> int { if group < 0 or group >= JOBS_GROUPS { return 0 } return jobs_st.jobs__done_n[group] } export function jobs_set_done(jobs_st: mut JobsState, group: int, n: int) -> void { - jobs__ensure(jobs_st) if group >= 0 and group < JOBS_GROUPS { jobs_st.jobs__done_n[group] = n } } diff --git a/packages/ludic.jobs/lists.ludic b/packages/ludic.jobs/lists.ludic index 6e827343..a50d3506 100644 --- a/packages/ludic.jobs/lists.ludic +++ b/packages/ludic.jobs/lists.ludic @@ -1,6 +1,6 @@ # lists.ludic - the written jobs as a screen lists them: a vendor's, the taken, the ones to show # a vendor's offers and the ones it can take back, in a group (-1 every vendor) -export function jobs_at(jobs_st: mut JobsState, group: int, vendor: int) -> []int { +export function jobs_at(jobs_st: JobsState, group: int, vendor: int) -> []int { let out = new []int for i in 0 .. JOB_COUNT { let d = Jobs[i] @@ -13,14 +13,14 @@ export function jobs_at(jobs_st: mut JobsState, group: int, vendor: int) -> []in } # every job of a group taken at some point, done ones too -export function jobs_taken(jobs_st: mut JobsState, group: int) -> []int { +export function jobs_taken(jobs_st: JobsState, group: int) -> []int { let out = new []int for i in 0 .. JOB_COUNT { if Jobs[i].group == group and jobs_state(jobs_st, i) != JOBS_OFFERED { push(out, i) } } return out } # the first `most` of a group under way -export function jobs_shown(jobs_st: mut JobsState, group: int, most: int) -> []int { +export function jobs_shown(jobs_st: JobsState, group: int, most: int) -> []int { let out = new []int for i in 0 .. JOB_COUNT { if len(out) >= most { break } @@ -30,7 +30,7 @@ export function jobs_shown(jobs_st: mut JobsState, group: int, most: int) -> []i } # the first under way and not yet met, or -1 -export function jobs_first_open(jobs_st: mut JobsState, group: int) -> int { +export function jobs_first_open(jobs_st: JobsState, group: int) -> int { for i in 0 .. JOB_COUNT { if Jobs[i].group == group and jobs_state(jobs_st, i) == JOBS_ACTIVE { return i } } return -1 } diff --git a/packages/ludic.jobs/posts.ludic b/packages/ludic.jobs/posts.ludic index e264ec2a..a56ff4c9 100644 --- a/packages/ludic.jobs/posts.ludic +++ b/packages/ludic.jobs/posts.ludic @@ -1,12 +1,12 @@ # posts.ludic - what is on a board, slot by slot, and a board as the host says it -export function jobs_post_kind(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__pk[jobs__at(jobs_st, b, s)] } -export function jobs_post_param(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__pp[jobs__at(jobs_st, b, s)] } -export function jobs_post_need(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__pn[jobs__at(jobs_st, b, s)] } -export function jobs_post_have(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__ph[jobs__at(jobs_st, b, s)] } -export function jobs_post_money(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__pm[jobs__at(jobs_st, b, s)] } -export function jobs_post_rep(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__pr[jobs__at(jobs_st, b, s)] } -export function jobs_post_state(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__ps[jobs__at(jobs_st, b, s)] } -export function jobs_post_day(jobs_st: mut JobsState, b: int, s: int) -> int { return jobs_st.jobs__pd[jobs__at(jobs_st, b, s)] } +export function jobs_post_kind(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__pk[jobs__at(jobs_st, b, s)] } +export function jobs_post_param(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__pp[jobs__at(jobs_st, b, s)] } +export function jobs_post_need(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__pn[jobs__at(jobs_st, b, s)] } +export function jobs_post_have(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__ph[jobs__at(jobs_st, b, s)] } +export function jobs_post_money(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__pm[jobs__at(jobs_st, b, s)] } +export function jobs_post_rep(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__pr[jobs__at(jobs_st, b, s)] } +export function jobs_post_state(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__ps[jobs__at(jobs_st, b, s)] } +export function jobs_post_day(jobs_st: JobsState, b: int, s: int) -> int { return jobs_st.jobs__pd[jobs__at(jobs_st, b, s)] } export function jobs_slots(b: int) -> int { if not jobs_board_ok(b) { return 0 } @@ -14,21 +14,20 @@ export function jobs_slots(b: int) -> int { } # the slots with something posted, in order -export function jobs_posted(jobs_st: mut JobsState, b: int) -> []int { +export function jobs_posted(jobs_st: JobsState, b: int) -> []int { let out = new []int for s in 0 .. jobs_slots(b) { if jobs_post_kind(jobs_st, b, s) >= 0 { push(out, s) } } return out } # how many of a board's posts are paid -export function jobs_posts_done(jobs_st: mut JobsState, b: int) -> int { +export function jobs_posts_done(jobs_st: JobsState, b: int) -> int { var n = 0 for s in 0 .. jobs_slots(b) { if jobs_post_kind(jobs_st, b, s) >= 0 and jobs_post_state(jobs_st, b, s) == JOBS_DONE { n += 1 } } return n } -export function jobs_total(jobs_st: mut JobsState, b: int) -> int { - jobs__ensure(jobs_st) +export function jobs_total(jobs_st: JobsState, b: int) -> int { return jobs_st.jobs__total[b] } @@ -46,6 +45,5 @@ export function jobs_post_set(jobs_st: mut JobsState, b: int, s: int, kind: int, } export function jobs_set_total(jobs_st: mut JobsState, b: int, n: int) -> void { - jobs__ensure(jobs_st) jobs_st.jobs__total[b] = n } diff --git a/packages/ludic.jobs/save.ludic b/packages/ludic.jobs/save.ludic index 375823cc..46a15a0e 100644 --- a/packages/ludic.jobs/save.ludic +++ b/packages/ludic.jobs/save.ludic @@ -1,7 +1,6 @@ # save.ludic - a scope's jobs and boards in a section of their own, by key: a job the game has since # removed is dropped, a new one starts offered function jobs__reset_scope(jobs_st: mut JobsState, sc: int) -> void { - jobs__ensure(jobs_st) for i in 0 .. JOB_COUNT { if Jobs[i].scope != sc { continue } jobs_st.jobs__st[i] = JOBS_OFFERED diff --git a/packages/ludic.jobs/state.ludic b/packages/ludic.jobs/state.ludic index da541b3d..c3c2b7d8 100644 --- a/packages/ludic.jobs/state.ludic +++ b/packages/ludic.jobs/state.ludic @@ -1,25 +1,25 @@ # state.ludic - each job's state and count, the posts on the boards, the done counts, the dice and -# the facts. Made on first use, so the registries are complete by then. +# the facts, each sized from the registries when the state is made. export state JobsState { - jobs__st: []int = null - jobs__hv: []int = null - jobs__seen: []bool = null # an offer already said + jobs__st: []int = jobs__ints(JOB_COUNT, JOBS_OFFERED) + jobs__hv: []int = jobs__ints(JOB_COUNT, 0) + jobs__seen: []bool = jobs__bools(JOB_COUNT) # an offer already said jobs__primed: bool = false # the first tick after a reset learns the offers quietly - jobs__done_n: []int = null # handed in, per group - jobs__off: []int = null - jobs__pk: []int = null # kind, -1 empty - jobs__pp: []int = null - jobs__pn: []int = null - jobs__ph: []int = null - jobs__pb: []int = null # the evidence when it went up - jobs__pm: []int = null - jobs__pr: []int = null - jobs__ps: []int = null - jobs__pd: []int = null # the day it went up - jobs__total: []int = null # handed in, per board - jobs__serial: []int = null # posts made, per board: each roll its own seed + jobs__done_n: []int = jobs__ints(JOBS_GROUPS, 0) # handed in, per group + jobs__off: []int = jobs__offsets() + jobs__pk: []int = jobs__ints(jobs__slots(), -1) # kind, -1 empty + jobs__pp: []int = jobs__ints(jobs__slots(), -1) + jobs__pn: []int = jobs__ints(jobs__slots(), 0) + jobs__ph: []int = jobs__ints(jobs__slots(), 0) + jobs__pb: []int = jobs__ints(jobs__slots(), 0) # the evidence when it went up + jobs__pm: []int = jobs__ints(jobs__slots(), 0) + jobs__pr: []int = jobs__ints(jobs__slots(), 0) + jobs__ps: []int = jobs__ints(jobs__slots(), JOBS_OFFERED) + jobs__pd: []int = jobs__ints(jobs__slots(), 0) # the day it went up + jobs__total: []int = jobs__ints(BOARD_COUNT, 0) # handed in, per board + jobs__serial: []int = jobs__ints(BOARD_COUNT, 0) # posts made, per board: each roll its own seed jobs__seed: int = 1000 - jobs__dice: Rng = null + jobs__dice: Rng = rng_new(1000) jobs__q: Queue = jobs__q__new() } @@ -32,31 +32,25 @@ function jobs__ints(n: int, v: int) -> []int { return out } -function jobs__ensure(jobs_st: mut JobsState) -> void { - if jobs_st.jobs__st != null { return } - jobs_st.jobs__st = jobs__ints(JOB_COUNT, JOBS_OFFERED) - jobs_st.jobs__hv = jobs__ints(JOB_COUNT, 0) - jobs_st.jobs__seen = new []bool - for i in 0 .. JOB_COUNT { push(jobs_st.jobs__seen, false) } - jobs_st.jobs__done_n = jobs__ints(JOBS_GROUPS, 0) - jobs_st.jobs__off = new []int +function jobs__bools(n: int) -> []bool { + let out = new []bool + for i in 0 .. n { push(out, false) } + return out +} +# every board's slots end to end: where each board's start, and how many in all +function jobs__offsets() -> []int { + let out = new []int var n = 0 for b in 0 .. BOARD_COUNT { - push(jobs_st.jobs__off, n) + push(out, n) n += JobBoards[b].slots } - jobs_st.jobs__pk = jobs__ints(n, -1) - jobs_st.jobs__pp = jobs__ints(n, -1) - jobs_st.jobs__pn = jobs__ints(n, 0) - jobs_st.jobs__ph = jobs__ints(n, 0) - jobs_st.jobs__pb = jobs__ints(n, 0) - jobs_st.jobs__pm = jobs__ints(n, 0) - jobs_st.jobs__pr = jobs__ints(n, 0) - jobs_st.jobs__ps = jobs__ints(n, JOBS_OFFERED) - jobs_st.jobs__pd = jobs__ints(n, 0) - jobs_st.jobs__total = jobs__ints(BOARD_COUNT, 0) - jobs_st.jobs__serial = jobs__ints(BOARD_COUNT, 0) - jobs_st.jobs__dice = rng_new(jobs_st.jobs__seed) + return out +} +function jobs__slots() -> int { + var n = 0 + for b in 0 .. BOARD_COUNT { n += JobBoards[b].slots } + return n } export function jobs_facts(jobs_st: JobsState) -> Queue { diff --git a/packages/ludic.jobs/system.ludic b/packages/ludic.jobs/system.ludic index f75641a8..936157ae 100644 --- a/packages/ludic.jobs/system.ludic +++ b/packages/ludic.jobs/system.ludic @@ -8,8 +8,7 @@ export function jobs_reset(jobs_st: mut JobsState) -> void { export function jobs_party_reset(jobs_st: mut JobsState) -> void { jobs__reset_scope(jobs_st, JOBS_PARTY) } -export function jobs_save(jobs_st: mut JobsState) -> Val { - jobs__ensure(jobs_st) +export function jobs_save(jobs_st: JobsState) -> Val { let v = jobs__save_scope(jobs_st, JOBS_SELF) sv_put_ints(v, "done", jobs_st.jobs__done_n) return v @@ -24,8 +23,7 @@ export function jobs_load(jobs_st: mut JobsState, v: Val, version: int) -> void } } -export function jobs_party_save(jobs_st: mut JobsState) -> Val { - jobs__ensure(jobs_st) +export function jobs_party_save(jobs_st: JobsState) -> Val { return jobs__save_scope(jobs_st, JOBS_PARTY) } diff --git a/packages/ludic.net/codec.ludic b/packages/ludic.net/codec.ludic index be7dd5a1..6be5b9fc 100644 --- a/packages/ludic.net/codec.ludic +++ b/packages/ludic.net/codec.ludic @@ -22,7 +22,6 @@ export function nb_copy(dst: []byte, d: int, src: []byte, s: int, n: int) -> voi # the writer: past the MTU it counts on and keeps nothing, and np_queue cuts the message there export function nw_begin(net_st: mut NetState) -> void { - net__init(net_st) net_st.net__wl = 0 } @@ -82,7 +81,6 @@ export function nr_bad(net_st: NetState) -> bool { return net_st.net__rbad } # a message that came in, made the one nr_* reads export function net_read(net_st: mut NetState, m: NetMessage) -> void { - net__init(net_st) nb_copy(net_st.net__rb, 0, m.data, 0, m.len) net_st.net__rl = m.len net_st.net__rp = 0 @@ -90,8 +88,7 @@ export function net_read(net_st: mut NetState, m: NetMessage) -> void { } # the message just written, as if it had come in (a loopback: a test, a host telling itself) -export function net_written(net_st: mut NetState) -> NetMessage { - net__init(net_st) +export function net_written(net_st: NetState) -> NetMessage { let m = new NetMessage m.from = net_st.net__my_pid m.len = min(net_st.net__wl, NET_MTU) diff --git a/packages/ludic.net/room.ludic b/packages/ludic.net/room.ludic index 62427a34..fb8e9e3e 100644 --- a/packages/ludic.net/room.ludic +++ b/packages/ludic.net/room.ludic @@ -29,7 +29,6 @@ export function net_room_join(net_st: mut NetState, code: string) -> bool { net_st.net__why = NET_WHY_NO_MATCHMAKER return false } - net__init(net_st) if not net__socket(net_st) { return false } net_st.net__r_role = 2 net_st.net__room = Text.upper(code) diff --git a/packages/ludic.net/session.ludic b/packages/ludic.net/session.ludic index 81641d10..22896df5 100644 --- a/packages/ludic.net/session.ludic +++ b/packages/ludic.net/session.ludic @@ -3,7 +3,6 @@ # open a socket on `port` and take guests; false (net_why) when the port is taken export function net_host(net_st: mut NetState, port: int, token: int) -> bool { - net__init(net_st) if net_live(net_st) { return true } net_st.net__sock = NetSocket.open(port) if net_st.net__sock <= 0 { @@ -20,7 +19,6 @@ export function net_host(net_st: mut NetState, port: int, token: int) -> bool { # dial a host at an address; the hello (net_hello_set) goes until a welcome or a refusal export function net_join(net_st: mut NetState, ip: int, port: int) -> bool { - net__init(net_st) if net_live(net_st) { return false } if not net__socket(net_st) { return false } for i in 0 .. NET_PEERS { np_close(net_st, i) } @@ -42,7 +40,6 @@ function net__socket(net_st: mut NetState) -> bool { # the message just written is the hello: what a host is asked to let this machine in with export function net_hello_set(net_st: mut NetState) -> void { - net__init(net_st) nb_copy(net_st.net__hello_b, 0, net_st.net__wb, 0, net_st.net__wl) net_st.net__hello_l = net_st.net__wl if net_st.net__hello_l > NET_MTU - 40 { net_st.net__hello_l = NET_MTU - 40 } @@ -50,7 +47,6 @@ export function net_hello_set(net_st: mut NetState) -> void { # (again) to that address, with a fresh connection and the hello sent anew export function net_dial(net_st: mut NetState, ip: int, port: int) -> void { - net__init(net_st) np_close(net_st, 0) net_st.net__join_ip = ip net_st.net__join_port = port @@ -70,7 +66,6 @@ export function net_follow(net_st: mut NetState, ip: int, port: int) -> void { export function net_stand_alone(net_st: mut NetState) -> void { net_st.net__state = NET_IDLE } export function net_become_host(net_st: mut NetState, token: int) -> void { - net__init(net_st) net_st.net__state = NET_HOSTING net_st.net__my_pid = 1 net_st.net__next_pid = 2 diff --git a/packages/ludic.net/state.ludic b/packages/ludic.net/state.ludic index 312fb3dc..4a0cdeff 100644 --- a/packages/ludic.net/state.ludic +++ b/packages/ludic.net/state.ludic @@ -79,17 +79,17 @@ export state NetState { net__token: int = 0 net__my_pid: int = 0 net__next_pid: int = 2 - net__peers: []NetPeer = null - net__in: []byte = null - net__out: []byte = null - net__wb: []byte = null # the message being written + net__peers: []NetPeer = net__peers_new() + net__in: []byte = buffer(NET_MTU + 64) + net__out: []byte = buffer(NET_MTU + 64) + net__wb: []byte = buffer(NET_MTU) # the message being written net__wl: int = 0 - net__rb: []byte = null # the message being read + net__rb: []byte = buffer(NET_MTU) # the message being read net__rl: int = 0 net__rp: int = 0 net__rbad: bool = false net__tb: []byte = buffer(NET_MTU) # text read out of a message, through one scratch buffer - net__hello_b: []byte = null # the game's hello, sent again on every dial + net__hello_b: []byte = buffer(NET_MTU) # the game's hello, sent again on every dial net__hello_l: int = 0 net__hello_t: float = 0.0 # seconds since it went; -1 not yet net__wait_more: int = 0 # extra seconds a slow host is given (a map switch, a matchmaker) @@ -111,19 +111,15 @@ export function net_inbox(net_st: NetState) -> Queue { return net_st.net__inbox } -function net__init(net_st: mut NetState) -> void { - if net_st.net__peers != null { return } - net_st.net__peers = new []NetPeer +function net__facts__new() -> Queue { return queue_new("net.facts") } +function net__inbox__new() -> Queue { return queue_new("net.inbox") } +# every peer slot, each with its own queue +function net__peers_new() -> []NetPeer { + let out = new []NetPeer for i in 0 .. NET_PEERS { let p = new NetPeer p.queue = new []NetMsg - push(net_st.net__peers, p) + push(out, p) } - net_st.net__in = buffer(NET_MTU + 64) - net_st.net__out = buffer(NET_MTU + 64) - net_st.net__wb = buffer(NET_MTU) - net_st.net__rb = buffer(NET_MTU) - net_st.net__hello_b = buffer(NET_MTU) + return out } -function net__facts__new() -> Queue { return queue_new("net.facts") } -function net__inbox__new() -> Queue { return queue_new("net.inbox") } diff --git a/packages/ludic.session/README.md b/packages/ludic.session/README.md index 6dc31662..e5e4b4d6 100644 --- a/packages/ludic.session/README.md +++ b/packages/ludic.session/README.md @@ -34,7 +34,7 @@ down ends the night). The transport says what this machine became (`ses_set_role | | | | --- | --- | -| `ply_init()`, `ply_join(pid) -> slot`, `ply_leave(p)`, `ply_leave_all()` | the roster (-1: full, or pid 0) | +| `ply_join(pid) -> slot`, `ply_leave(p)`, `ply_leave_all()` | the roster (-1: full, or pid 0) | | `ply_report(p, x, y, z, yaw, speed)`, `ply_report_rest(p, rest, sleeping)`, `ply_report_name(p, name)` | what a remote machine said | | `ply_on`, `ply_is_local`, `ply_slot_of(pid)`, `ply_count`, `ply_pid`, `ply_name`, `ply_x/y/z/yaw/speed/rest(p)`, `ply_sleeping(p)` | who and where | | `ply_near(x, z)`, `ply_near_d2`, `ply_near_i()`, `ply_dist(p, x, z)` | the nearest player | diff --git a/packages/ludic.session/roster.ludic b/packages/ludic.session/roster.ludic index 9e5e5e8e..2b176ad3 100644 --- a/packages/ludic.session/roster.ludic +++ b/packages/ludic.session/roster.ludic @@ -1,6 +1,5 @@ # roster.ludic - who is here. Slot 0 is this machine's player and reads the SessionLocal port # live; slots 1.. are remote players, filled by what their machines report. -export function ply_init(session_st: mut SessionState) -> void { session__init(session_st) } export function ply_on(session_st: SessionState, p: int) -> bool { if p == 0 { return true } @@ -26,7 +25,6 @@ export function ply_count(session_st: SessionState) -> int { # a remote player comes in, standing where this one stands until they say: the first free # slot, or -1 when the party is full export function ply_join(session_st: mut SessionState, pid: int) -> int { - session__init(session_st) 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 } diff --git a/packages/ludic.session/state.ludic b/packages/ludic.session/state.ludic index bb059151..cdd71ab5 100644 --- a/packages/ludic.session/state.ludic +++ b/packages/ludic.session/state.ludic @@ -61,7 +61,7 @@ function session__nameless() -> string { return "" } export state SessionState { session__me_sleeping: bool = false - session__slot: []PartyMember = null + session__slot: []PartyMember = session__slots() session__role: int = 0 session__max: int = 4 session__open: bool = true @@ -92,10 +92,11 @@ function session__fact(session_st: SessionState, what: int, slot: int, pid: int) return f } -function session__init(session_st: mut SessionState) -> void { - if session_st.session__slot != null { return } - session_st.session__slot = new []PartyMember - for i in 0 .. PLY_MAX { push(session_st.session__slot, new PartyMember) } - session_st.session__slot[0].on = true -} function session__facts__new() -> Queue { return queue_new("session.facts") } +# the roster's slots, slot 0 this machine's own and on +function session__slots() -> []PartyMember { + let out = new []PartyMember + for i in 0 .. PLY_MAX { push(out, new PartyMember) } + out[0].on = true + return out +} diff --git a/packages/ludic.session/tests/session_test.ludic b/packages/ludic.session/tests/session_test.ludic index dd7ce8da..a2429d2f 100644 --- a/packages/ludic.session/tests/session_test.ludic +++ b/packages/ludic.session/tests/session_test.ludic @@ -30,14 +30,12 @@ program SessionTest { # a host with n guests, pids 2.., facts drained function party(session_st: mut SessionState, n: int) -> void { - ply_init(session_st) ses_set_role(session_st, SES_HOST) for i in 0 .. n { ply_join(session_st, 2 + i) } q_clear(ses_facts(session_st)) } test "slot 0 is the local player, read live; others join at its feet and leave" (session_st: mut SessionState, session_test_st: mut SessionTestState) { - ply_init(session_st) session_test_st.me_x = 5.0 expect(ply_on(session_st, 0)) expect_near(ply_x(session_st, 0), 5.0, 0.001) @@ -58,14 +56,12 @@ program SessionTest { } test "the roster fills at twelve" (session_st: mut SessionState) { - ply_init(session_st) for i in 0 .. PLY_MAX - 1 { expect(ply_join(session_st, 10 + i) > 0) } expect_eq(ply_join(session_st, 99), -1) expect_eq(ply_count(session_st), PLY_MAX) } test "the nearest player, whoever it is" (session_st: mut SessionState, session_test_st: mut SessionTestState) { - ply_init(session_st) session_test_st.me_x = 100.0 let p = ply_join(session_st, 2) ply_report(session_st, p, 3.0, 0.0, 4.0, 0.0, 1.0) @@ -75,7 +71,6 @@ program SessionTest { } test "roles: alone owns the world, a guest does not, and a change is a fact" (session_st: mut SessionState) { - ply_init(session_st) expect(ses_owns_world(session_st)) expect(not ses_live(session_st)) expect(ses_night_passes(session_st)) @@ -115,7 +110,6 @@ program SessionTest { } test "a guest's turning in is a fact for the host to hear; alone a bed just sleeps" (session_st: mut SessionState) { - ply_init(session_st) expect(not ses_sleep(session_st, true)) ses_set_role(session_st, SES_GUEST) q_clear(ses_facts(session_st)) @@ -153,7 +147,6 @@ program SessionTest { } test "alone it may go; a guest may not, and its vote goes to the host" (session_st: mut SessionState) { - ply_init(session_st) expect_eq(ses_may(session_st, 1, 0, "x"), SES_MAY_GO) ses_set_role(session_st, SES_GUEST) expect_eq(ses_may(session_st, 1, 0, "x"), SES_MAY_HOSTS) diff --git a/packages/ludic.settings/file.ludic b/packages/ludic.settings/file.ludic index f50314d2..e58a0514 100644 --- a/packages/ludic.settings/file.ludic +++ b/packages/ludic.settings/file.ludic @@ -1,8 +1,7 @@ # ludic.settings/file.ludic - the store as a JSON object, by key: a switch is 0 or 1, a whole number # is itself, a float is thousandths (sv_put_float), text is a string. A key the file lacks keeps # what the store holds, and a key the store does not know is ignored. -export function settings_to_json(settings_st: mut SettingsState) -> Val { - sg_init(settings_st) +export function settings_to_json(settings_st: SettingsState) -> Val { let v = Value.object() for i in 0 .. len(settings_st.sg_defs) { settings_put(settings_st, v, i) } return v @@ -23,7 +22,6 @@ export function settings_put(settings_st: SettingsState, v: Val, id: int) -> voi # every key `v` names, held to its range; quiet, since a load is applied whole by its caller export function settings_from_json(settings_st: mut SettingsState, v: Val) -> void { - sg_init(settings_st) if v == null { return } for i in 0 .. len(settings_st.sg_defs) { sg_read(settings_st, v, i) } } diff --git a/packages/ludic.settings/rules.ludic b/packages/ludic.settings/rules.ludic index 48102475..e1d351c3 100644 --- a/packages/ludic.settings/rules.ludic +++ b/packages/ludic.settings/rules.ludic @@ -1,7 +1,6 @@ # ludic.settings/rules.ludic - the whole store at once: every setting to its default, every one # held to its range, and the rescue set. None of these is news: whoever calls them applies it all export function settings_reset_all(settings_st: mut SettingsState) -> void { - sg_init(settings_st) for i in 0 .. len(settings_st.sg_defs) { settings_st.sg_num[i] = settings_st.sg_defs[i].num settings_st.sg_text[i] = settings_st.sg_defs[i].text @@ -11,14 +10,12 @@ export function settings_reset_all(settings_st: mut SettingsState) -> void { # a hand-edited file, or one from a build with more choices, never hands the game a value it has # no case for export function settings_clamp_all(settings_st: mut SettingsState) -> void { - sg_init(settings_st) for i in 0 .. len(settings_st.sg_defs) { settings_st.sg_num[i] = settings_held(settings_st, i, settings_st.sg_num[i]) } } # the values every machine can run: each setting marked `rescue` back to its default, and the # rest (keys, language, volume) left the player's export function settings_rescue(settings_st: mut SettingsState) -> void { - sg_init(settings_st) for i in 0 .. len(settings_st.sg_defs) { if settings_st.sg_defs[i].rescue { settings_st.sg_num[i] = settings_st.sg_defs[i].num diff --git a/packages/ludic.settings/store.ludic b/packages/ludic.settings/store.ludic index fd8f0d81..fd44329c 100644 --- a/packages/ludic.settings/store.ludic +++ b/packages/ludic.settings/store.ludic @@ -1,18 +1,12 @@ # ludic.settings/store.ludic - the values, by id (a setting's place in the order it was added), # and the verbs: nothing else holds a setting, and every set that changes one is a fact export state SettingsState { - sg_defs: []SettingDef = null - sg_num: []float = null - sg_text: []string = null + sg_defs: []SettingDef = new []SettingDef + sg_num: []float = new []float + sg_text: []string = new []string sg_changes: Queue = sg_changes__new() } -function sg_init(settings_st: mut SettingsState) -> void { - if settings_st.sg_defs != null { return } - settings_st.sg_defs = new []SettingDef - settings_st.sg_num = new []float - settings_st.sg_text = new []string -} export function settings_changes(settings_st: SettingsState) -> Queue { return settings_st.sg_changes @@ -28,23 +22,20 @@ export function settings_clear(settings_st: mut SettingsState) -> void { # a setting, at its default; its id is its place in the order added export function settings_add(settings_st: mut SettingsState, d: SettingDef) -> int { - sg_init(settings_st) push(settings_st.sg_defs, d) push(settings_st.sg_num, d.num) push(settings_st.sg_text, d.text) return len(settings_st.sg_defs) - 1 } -export function settings_count(settings_st: mut SettingsState) -> int { - sg_init(settings_st) +export function settings_count(settings_st: SettingsState) -> int { return len(settings_st.sg_defs) } export function settings_def(settings_st: SettingsState, id: int) -> SettingDef { return settings_st.sg_defs[id] } # the id of `key`, or -1 -export function settings_id_of(settings_st: mut SettingsState, key: string) -> int { - sg_init(settings_st) +export function settings_id_of(settings_st: SettingsState, key: string) -> int { for i in 0 .. len(settings_st.sg_defs) { if settings_st.sg_defs[i].key == key { return i } } return -1 }