# store.ludic - the animals, their own dice, and the verbs that make and take one away const WL_TAU: float = 6.2831853 # every animal, one per row - the table's own list: read it, never push to it export function wildlife_all(wildlife_st: WildlifeState) -> []WildAnimal { return wildlife_st.wl.tab.rec } export function wildlife_count_all(wildlife_st: WildlifeState) -> int { return tb_len(wildlife_st.wl.tab) } # a new valley: every animal forgotten, quietly (the game has already let its drawings go) export function wildlife_clear(wildlife_st: mut WildlifeState) -> void { let tb = wildlife_st.wl.tab for r in 0 .. tb_len(tb) { tb.rec[r].ent = -1 } tb_clear(tb) imap_clear(wildlife_st.wl.nids) } function wl_rng(wildlife_st: WildlifeState) -> Rng { return wildlife_st.wl_dice } function wl_rnd(wildlife_st: WildlifeState) -> float { return rng_float(wl_rng(wildlife_st)) } # the package's dice from a known place (a spawn, a test) export function wildlife_seed(wildlife_st: WildlifeState, seed: int) -> void { rng_seed(wl_rng(wildlife_st), seed) } # an individual exactly as given: the host's own, or the host's on a guest export function wildlife_make(wildlife_st: mut WildlifeState, sp: int, x: float, z: float, legend: bool, yaw: float, variant: int, scale: float, nid: int) -> WildAnimal { let s = wildlife_species(wildlife_st, sp) if s == null { return null } var a = wl_reusable(wildlife_st.wl, sp) let again = a != null if again { wl_forget(wildlife_st.wl, a) } else { a = wl_record(wildlife_st) } a.nid = nid a.sp = sp a.x = x a.z = z a.home_x = x a.home_z = z a.tx = x a.tz = z a.y = WildlifeWorld.ground(x, z) a.yaw = yaw a.variant = variant a.scale = scale a.legend = legend a.state = WILD_IDLE if again { wl_refile_one(wildlife_st.wl, a) } else { wl_file(wildlife_st.wl, a) } WildlifeWorld.born(a) return a } # a new individual of a species at (x, z), off the package's dice export function wildlife_new(wildlife_st: mut WildlifeState, sp: int, x: float, z: float, legend: bool) -> WildAnimal { let s = wildlife_species(wildlife_st, sp) if s == null { return null } let yaw = wl_rnd(wildlife_st) * WL_TAU let variant = rng_between(wl_rng(wildlife_st), 0, 11) let scale = s.scale * (0.88 + wl_rnd(wildlife_st) * 0.24) let a = wildlife_make(wildlife_st, sp, x, z, legend, yaw, variant, scale, WildlifeWorld.next_id()) a.thirst = wl_rnd(wildlife_st) * 50.0 a.hunger = wl_rnd(wildlife_st) * 50.0 a.scat_t = 40.0 + wl_rnd(wildlife_st) * 180.0 if s.flies { a.state = WILD_FLY a.fly_h = 10.0 + wl_rnd(wildlife_st) * 20.0 } a.timer = wl_rnd(wildlife_st) * 6.0 return a } # gone for good: not drawn, not ticked export function wildlife_remove(a: WildAnimal) -> void { if a == null { return } wildlife_set_alive(a, false) a.shown = false } # staged for a picture: nobody thinks, and everybody keeps the speed they were given export function wildlife_hold(wildlife_st: mut WildlifeState, on: bool) -> void { wildlife_st.wl_hold = on } export function wildlife_by_nid(wildlife_st: WildlifeState, nid: int) -> WildAnimal { let tb = wildlife_st.wl.tab let r = tb_row(tb, imap_get(wildlife_st.wl.nids, nid, -1)) if r < 0 or tb.rec[r].nid != nid { return null } return tb.rec[r] } # how many of a species are alive, legends apart export function wildlife_count(wildlife_st: WildlifeState, sp: int) -> int { var n = 0 let rows = ix_rows(wildlife_st.wl.species, sp) for k in 0 .. len(rows) { if not wildlife_st.wl.tab.rec[rows[k]].legend { n += 1 } } return n } # room for `n` animals (both tables: this player's and the host's it draws) before anything grows: # a world that spawns in play sizes its table once, at the start export function wildlife_reserve(wildlife_st: mut WildlifeState, n: int) -> void { tb_reserve(wildlife_st.wl.tab, n) imap_reserve(wildlife_st.wl.nids, n) tb_reserve(wildlife_st.wl_host.tab, n) imap_reserve(wildlife_st.wl_host.nids, n) }