# store.ludic - the Things, rows of a ludic.base Table: where each stands and whether it is active # are columns a grid and two kind indexes are kept over, and only the verbs (verbs.ludic) make, # move, show, hide and remove one; each placing and removing is a fact the port hears at once export const TH_X: int = 0 # float columns export const TH_Z: int = 1 export const TH_KIND: int = 0 # int columns export const TH_ON: int = 1 # 1 while active export const TH_CHUNK: int = 2 # the chunk of the world it stands in (chunk_of, TH_CHUNK_M) export const TH_CHUNK_M: float = 256.0 const TH_CELL: float = 16.0 # the table and the indexes kept over it, made together export property ThingsTable { tab: Table = null grid: Grid = null kinds: IntIndex = null # active Things by kind every: IntIndex = null # every Thing by kind, active or not chunks: IntIndex = null # every Thing by the chunk it stands in: loaded and let go together } export state ThingsState { th: ThingsTable = th__new() th_uids: IntMap = imap_new() th_uid: int = 0 th_facts: Queue = th_facts__new() 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") } function th__new() -> ThingsTable { let th = new ThingsTable let tb: Table = table_new(2, 3) th.tab = tb th.grid = tb_grid(tb, TH_X, TH_Z, TH_ON, TH_CELL) th.kinds = tb_index(tb, TH_KIND, TH_ON) th.every = tb_index(tb, TH_KIND, -1) th.chunks = tb_index(tb, TH_CHUNK, -1) return th } export function things_facts(things_st: ThingsState) -> Queue { return things_st.th_facts } # 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 } # every Thing, one per row - the table's own list: read it, never push to it. A removal moves the # last Thing into the removed one's place, so the order is the table's, not the order placed. export function things_all(things_st: ThingsState) -> []Thing { return things_st.th.tab.rec } export function things_count(things_st: ThingsState) -> int { return tb_len(things_st.th.tab) } # a new world: every Thing forgotten, quietly (the game has already dropped its drawings) export function things_clear(things_st: mut ThingsState) -> void { let tb = things_st.th.tab for r in 0 .. tb_len(tb) { tb.rec[r].ent = -1 } tb_clear(tb) imap_clear(things_st.th_uids) } # the row a Thing stands in, or -1 when it is not in the table any more function th_row(t: Thing) -> int { if t == null or t.tab == null { return -1 } return tb_row(t.tab, t.ent) } # the columns say what the record says: a Thing's fields written around the verbs are caught here export function things_verify(things_st: ThingsState) -> int { let tb = things_st.th.tab var bad = 0 for r in 0 .. tb_len(tb) { let t = tb.rec[r] var on = 0 if t.active { on = 1 } if tb.f[TH_X][r] != t.x or tb.f[TH_Z][r] != t.z or tb.i[TH_KIND][r] != t.kind or tb.i[TH_ON][r] != on or tb.i[TH_CHUNK][r] != chunk_of(t.x, t.z, TH_CHUNK_M) or t.ent != tb.ent[r] { bad += 1 } } return bad }