# ludic.base/system.ludic - a system is a record of what it does at each verb, and the runner # calls them: init, reset, save and load in the order added, tick phase by phase. A null # function is a verb the system does not have. The game's list is the order co-op's dice need. export property System { key: string = "" phase: int = 2 version: int = 1 init: fn() -> void = null reset: fn() -> void = null tick: fn(Tick) -> void = null save: fn() -> Val = null load: fn(Val, int) -> void = null } # the declared list: a mechanic or the game writes `def Systems fishing { phase: PH_ACT, tick: fn # fishing_tick }` from its own module; the runner starts from these, then core_add appends export open registry Systems of System as SYS # the declared systems; a registry is not filled when a state's defaults are made, so on first ask @alloc_ok("once: the runner's list is made the first time it is asked, and kept") function cs_all(base_st: mut BaseState) -> []System { if base_st.cs_list == null { base_st.cs_list = new []System for i in 0 .. SYS_COUNT { push(base_st.cs_list, Systems[i]) } } return base_st.cs_list } @alloc_ok("at start: a system made for the runner") export function system_new(key: string, phase: int) -> System { let s = new System s.key = key s.phase = phase return s } # a key is a save section's name, so two systems may not share one @alloc_ok("at start: a system added to the runner") export function core_add(base_st: mut BaseState, s: System) -> void { let all = cs_all(base_st) for i in 0 .. len(all) { if all[i].key == s.key { print(`ludic.base: two systems are keyed "{s.key}"`) exit(1) } } push(all, s) } export function core_clear(base_st: mut BaseState) -> void { base_st.cs_list = new []System } export function core_count(base_st: mut BaseState) -> int { return len(cs_all(base_st)) } export function core_init_all(base_st: mut BaseState) -> void { let all = cs_all(base_st) for i in 0 .. len(all) { if all[i].init != null { all[i].init() } } } export function core_reset_all(base_st: mut BaseState) -> void { let all = cs_all(base_st) for i in 0 .. len(all) { if all[i].reset != null { all[i].reset() } } } export function core_tick_all(base_st: mut BaseState, t: Tick) -> void { let all = cs_all(base_st) for ph in 0 .. PH_COUNT { for i in 0 .. len(all) { if all[i].phase == ph and all[i].tick != null { all[i].tick(t) } } drain_actions() # 0.R: the phase's actions, reduced before the next } } # every system that saves, under its key with its version export function core_save_all(base_st: mut BaseState) -> Val { let root = save_tree() let all = cs_all(base_st) for i in 0 .. len(all) { if all[i].save != null { save_section(root, all[i].key, all[i].version, all[i].save()) } } return root } # each system its own section; one with no section (or no load) is reset instead export function core_load_all(base_st: mut BaseState, root: Val) -> void { let all = cs_all(base_st) for i in 0 .. len(all) { let n = load_section(root, all[i].key) if n.found and all[i].load != null { all[i].load(n.data, n.version) } else if all[i].reset != null { all[i].reset() } } }