refactor(packages): 0.R5 - a question no longer starts its state - 64 lazy starts ('if st.x == null { st.x = ... }' inside a getter) are the state's defaults, gear__ensure is gone, and ludic migrate state --tighten took mut off 208 package parameters: things_all, thing_find, gear_charge, gear_level, jobs_state and the rest read
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
54f5efb23f
commit
9862ec82e3
102 changed files with 320 additions and 351 deletions
|
|
@ -17,7 +17,7 @@ export property Clip {
|
|||
}
|
||||
|
||||
export state AnimState {
|
||||
clips: []Clip = null
|
||||
clips: []Clip = new []Clip
|
||||
positions: bool = false
|
||||
q_a: floats = null
|
||||
q_b: floats = null
|
||||
|
|
@ -31,19 +31,18 @@ export state AnimState {
|
|||
# Keyed translations are off unless asked for: baking keys location on every bone, and a skeleton
|
||||
# does not translate its joints, so applying them turns rounding into a pose.
|
||||
|
||||
function clips_init(anim_st: mut AnimState) -> void {
|
||||
if anim_st.clips == null { anim_st.clips = new []Clip }
|
||||
function clips_init() -> void {
|
||||
}
|
||||
|
||||
# the clip of that name, or null; names are per file (per body, per species), never shared
|
||||
export function anim_find(anim_st: mut AnimState, name: string) -> Clip {
|
||||
clips_init(anim_st)
|
||||
export function anim_find(anim_st: AnimState, name: string) -> Clip {
|
||||
clips_init()
|
||||
for i in 0 .. len(anim_st.clips) { if anim_st.clips[i].name == name { return anim_st.clips[i] } }
|
||||
return null
|
||||
}
|
||||
|
||||
export function anim_count(anim_st: mut AnimState) -> int {
|
||||
clips_init(anim_st)
|
||||
export function anim_count(anim_st: AnimState) -> int {
|
||||
clips_init()
|
||||
return len(anim_st.clips)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
# Call it straight after a load and before the next one: `gltf_doc` and `gltf_bin` point at
|
||||
# whichever file was read last, so a clip that is not taken now cannot be taken later.
|
||||
export function anim_read_doc(anim_st: mut AnimState, render3d_st: mut Render3dState, dir: string) -> int {
|
||||
clips_init(anim_st)
|
||||
clips_init()
|
||||
if render3d_st.gltf_doc == null { return 0 }
|
||||
if value_has(render3d_st.gltf_doc, "animations") == 0 { return 0 }
|
||||
# REOPEN THE .bin. `gltf_load` closes it before it returns, and an accessor read through a closed
|
||||
|
|
@ -39,7 +39,7 @@ function kept_path(ch: Val) -> string {
|
|||
return path
|
||||
}
|
||||
|
||||
function read_one(anim_st: mut AnimState, render3d_st: mut Render3dState, a: Val) -> Clip {
|
||||
function read_one(anim_st: AnimState, render3d_st: mut Render3dState, a: Val) -> Clip {
|
||||
var nm = ""
|
||||
if value_has(a, "name") != 0 { nm = value_as_str(value_get(a, "name")) }
|
||||
if anim_find(anim_st, nm) != null { return null } # a second rig's file, same clip
|
||||
|
|
|
|||
|
|
@ -35,12 +35,11 @@ export state ClockState {
|
|||
ck_moon_lo: float = 0.0
|
||||
ck_moon_hi: float = 1.0
|
||||
ck_dice: Rng = null
|
||||
ck_days: Queue<DayTurned> = null
|
||||
ck_days: Queue<DayTurned> = ck_days__new()
|
||||
}
|
||||
|
||||
# the facts: each day that turned, in order; the game drains it and runs its morning
|
||||
export function clock_days(clock_st: mut ClockState) -> Queue<DayTurned> {
|
||||
if clock_st.ck_days == null { clock_st.ck_days = queue_new("clock.days") }
|
||||
export function clock_days(clock_st: ClockState) -> Queue<DayTurned> {
|
||||
return clock_st.ck_days
|
||||
}
|
||||
|
||||
|
|
@ -61,3 +60,4 @@ export function clock_config_moon(clock_st: mut ClockState, days: float, lo: flo
|
|||
clock_st.ck_moon_lo = lo
|
||||
clock_st.ck_moon_hi = hi
|
||||
}
|
||||
function ck_days__new() -> Queue<DayTurned> { return queue_new("clock.days") }
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ program ClockTest {
|
|||
clock_reset(clock_st)
|
||||
}
|
||||
|
||||
function turned(clock_st: mut ClockState) -> []DayTurned { return q_drain(clock_days(clock_st)) }
|
||||
function waiting(clock_st: mut ClockState) -> int { return q_len(clock_days(clock_st)) }
|
||||
function turned(clock_st: ClockState) -> []DayTurned { return q_drain(clock_days(clock_st)) }
|
||||
function waiting(clock_st: ClockState) -> int { return q_len(clock_days(clock_st)) }
|
||||
function run_hours(h: float) -> void {
|
||||
let s = clock_system()
|
||||
s.tick(tick_new(0.016, 0, h))
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ program CraftingTest {
|
|||
craft_reset(crafting_st)
|
||||
}
|
||||
|
||||
function facts(crafting_st: mut CraftingState) -> []Crafted { return q_drain(craft_facts(crafting_st)) }
|
||||
function facts(crafting_st: CraftingState) -> []Crafted { return q_drain(craft_facts(crafting_st)) }
|
||||
|
||||
test "the registry is the game's, in the order written" {
|
||||
expect_eq(CRAFT_COUNT, 5)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
export state CraftingState {
|
||||
craft_hold_i: int = -1
|
||||
craft_hold_t: float = 0.0
|
||||
craft_fact_q: Queue<Crafted> = null
|
||||
craft_fact_q: Queue<Crafted> = craft_fact_q__new()
|
||||
}
|
||||
|
||||
export function craft_facts(crafting_st: mut CraftingState) -> Queue<Crafted> {
|
||||
if crafting_st.craft_fact_q == null { crafting_st.craft_fact_q = queue_new("crafting.crafted") }
|
||||
export function craft_facts(crafting_st: CraftingState) -> Queue<Crafted> {
|
||||
return crafting_st.craft_fact_q
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +49,7 @@ export function craft_refund(i: int) -> void {
|
|||
}
|
||||
}
|
||||
|
||||
function craft_fact_push(crafting_st: mut CraftingState, i: int, queued: bool) -> void {
|
||||
function craft_fact_push(crafting_st: CraftingState, i: int, queued: bool) -> void {
|
||||
let r = CraftRecipes[i]
|
||||
let c = new Crafted
|
||||
c.recipe = i
|
||||
|
|
@ -63,7 +62,7 @@ function craft_fact_push(crafting_st: mut CraftingState, i: int, queued: bool) -
|
|||
|
||||
# make it: a timed recipe at a station goes into the station (given back if it will not take it),
|
||||
# anything else is handed over at once. False, and the pack untouched, when it cannot be made.
|
||||
export function craft_make(crafting_st: mut CraftingState, i: int) -> bool {
|
||||
export function craft_make(crafting_st: CraftingState, i: int) -> bool {
|
||||
if not craft_can(i) { return false }
|
||||
let r = CraftRecipes[i]
|
||||
craft_take(i)
|
||||
|
|
@ -79,3 +78,4 @@ export function craft_make(crafting_st: mut CraftingState, i: int) -> bool {
|
|||
craft_fact_push(crafting_st, i, false)
|
||||
return true
|
||||
}
|
||||
function craft_fact_q__new() -> Queue<Crafted> { return queue_new("crafting.crafted") }
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@
|
|||
function ef_live(e: Effect) -> bool { return e.delay < 0.01 }
|
||||
|
||||
# what the rules should add for a kind right now (a delayed one counts only once it begins)
|
||||
export function effects_sum(effects_st: mut EffectsState, kind: int) -> float {
|
||||
export function effects_sum(effects_st: EffectsState, kind: int) -> float {
|
||||
let all = ef_all(effects_st)
|
||||
var t = 0.0
|
||||
for i in 0 .. len(all) { if all[i].kind == kind and ef_live(all[i]) { t = t + all[i].mag } }
|
||||
return t
|
||||
}
|
||||
|
||||
export function effects_has(effects_st: mut EffectsState, kind: int) -> bool {
|
||||
export function effects_has(effects_st: EffectsState, kind: int) -> bool {
|
||||
let all = ef_all(effects_st)
|
||||
for i in 0 .. len(all) { if all[i].kind == kind and ef_live(all[i]) { return true } }
|
||||
return false
|
||||
}
|
||||
|
||||
export function effects_bonus_count(effects_st: mut EffectsState) -> int {
|
||||
export function effects_bonus_count(effects_st: EffectsState) -> int {
|
||||
let all = ef_all(effects_st)
|
||||
var n = 0
|
||||
for i in 0 .. len(all) { if all[i].bonus { n += 1 } }
|
||||
|
|
@ -23,10 +23,10 @@ export function effects_bonus_count(effects_st: mut EffectsState) -> int {
|
|||
}
|
||||
|
||||
# everything held, delayed or not, in the order added
|
||||
export function effects_count(effects_st: mut EffectsState) -> int { return len(ef_all(effects_st)) }
|
||||
export function effects_count(effects_st: EffectsState) -> int { return len(ef_all(effects_st)) }
|
||||
|
||||
# a copy, so a reader cannot change the ring
|
||||
export function effects_at(effects_st: mut EffectsState, i: int) -> Effect {
|
||||
export function effects_at(effects_st: EffectsState, i: int) -> Effect {
|
||||
let src = ef_all(effects_st)[i]
|
||||
let e = new Effect
|
||||
e.kind = src.kind
|
||||
|
|
@ -39,7 +39,7 @@ export function effects_at(effects_st: mut EffectsState, i: int) -> Effect {
|
|||
}
|
||||
|
||||
# the indices of the ones that have begun, for a read-out
|
||||
export function effects_live(effects_st: mut EffectsState) -> []int {
|
||||
export function effects_live(effects_st: EffectsState) -> []int {
|
||||
let out = new []int
|
||||
let all = ef_all(effects_st)
|
||||
for i in 0 .. len(all) { if ef_live(all[i]) { push(out, i) } }
|
||||
|
|
|
|||
|
|
@ -21,20 +21,18 @@ export property EffectEnded {
|
|||
}
|
||||
|
||||
export state EffectsState {
|
||||
ef_list: []Effect = null
|
||||
ef_list: []Effect = new []Effect
|
||||
ef_max: int = 8
|
||||
ef_bonus_max: int = 3
|
||||
ef_ended: Queue<EffectEnded> = null
|
||||
ef_ended: Queue<EffectEnded> = ef_ended__new()
|
||||
}
|
||||
|
||||
function ef_all(effects_st: mut EffectsState) -> []Effect {
|
||||
if effects_st.ef_list == null { effects_st.ef_list = new []Effect }
|
||||
function ef_all(effects_st: EffectsState) -> []Effect {
|
||||
return effects_st.ef_list
|
||||
}
|
||||
|
||||
# the facts: what ended and why, oldest first; the game drains it
|
||||
export function effects_ended(effects_st: mut EffectsState) -> Queue<EffectEnded> {
|
||||
if effects_st.ef_ended == null { effects_st.ef_ended = queue_new("effects.ended") }
|
||||
export function effects_ended(effects_st: EffectsState) -> Queue<EffectEnded> {
|
||||
return effects_st.ef_ended
|
||||
}
|
||||
|
||||
|
|
@ -46,3 +44,4 @@ export function effects_config(effects_st: mut EffectsState, max: int, bonus_max
|
|||
|
||||
export function effects_capacity(effects_st: EffectsState) -> int { return effects_st.ef_max }
|
||||
export function effects_bonus_capacity(effects_st: EffectsState) -> int { return effects_st.ef_bonus_max }
|
||||
function ef_ended__new() -> Queue<EffectEnded> { return queue_new("effects.ended") }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export function effects_reset(effects_st: mut EffectsState) -> void {
|
|||
|
||||
function effects_tick(effects_st: mut EffectsState, t: Tick) -> void { effects_run(effects_st, t.hours * 60.0) }
|
||||
|
||||
export function effects_save(effects_st: mut EffectsState) -> Val {
|
||||
export function effects_save(effects_st: EffectsState) -> Val {
|
||||
let l = Value.list()
|
||||
let all = ef_all(effects_st)
|
||||
for i in 0 .. len(all) {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ program EffectsTest {
|
|||
effects_reset(effects_st)
|
||||
}
|
||||
|
||||
function ended(effects_st: mut EffectsState) -> []EffectEnded { return q_drain(effects_ended(effects_st)) }
|
||||
function waiting(effects_st: mut EffectsState) -> int { return q_len(effects_ended(effects_st)) }
|
||||
function ended(effects_st: EffectsState) -> []EffectEnded { return q_drain(effects_ended(effects_st)) }
|
||||
function waiting(effects_st: EffectsState) -> int { return q_len(effects_ended(effects_st)) }
|
||||
|
||||
function tick_minutes(m: float) -> void {
|
||||
let s = effects_system()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ function ef_drop(effects_st: mut EffectsState, i: int) -> void {
|
|||
}
|
||||
|
||||
# the one with the least time left (of the bonuses only, when asked); -1 when there is none
|
||||
function ef_nearest_end(effects_st: mut EffectsState, bonus_only: bool) -> int {
|
||||
function ef_nearest_end(effects_st: EffectsState, bonus_only: bool) -> int {
|
||||
let all = ef_all(effects_st)
|
||||
var at = -1
|
||||
for i in 0 .. len(all) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export state FireState {
|
|||
fr_lit: bool = false
|
||||
fr_fuel: float = 0.0 # game minutes left
|
||||
fr_rain_h: float = 0.0 # game hours today it burned in the rain under cover
|
||||
fr_facts: Queue<FireFact> = null
|
||||
fr_facts: Queue<FireFact> = fr_facts__new()
|
||||
}
|
||||
|
||||
# what lighting or feeding would come to, as the world stands
|
||||
|
|
@ -43,12 +43,11 @@ export property FireFact {
|
|||
|
||||
|
||||
# the facts, oldest first; the game drains them into its notices
|
||||
export function fire_facts(fire_st: mut FireState) -> Queue<FireFact> {
|
||||
if fire_st.fr_facts == null { fire_st.fr_facts = queue_new("fire.facts") }
|
||||
export function fire_facts(fire_st: FireState) -> Queue<FireFact> {
|
||||
return fire_st.fr_facts
|
||||
}
|
||||
|
||||
function fr_fact(fire_st: mut FireState, what: int) -> void {
|
||||
function fr_fact(fire_st: FireState, what: int) -> void {
|
||||
let f = new FireFact
|
||||
f.what = what
|
||||
f.fuel = fire_st.fr_fuel
|
||||
|
|
@ -68,3 +67,4 @@ export function fire_config_reach(fire_st: mut FireState, warm: float, cook: flo
|
|||
fire_st.fr_warm_radius = warm
|
||||
fire_st.fr_cook_radius = cook
|
||||
}
|
||||
function fr_facts__new() -> Queue<FireFact> { return queue_new("fire.facts") }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ program FireTest {
|
|||
fire_reset(fire_st)
|
||||
}
|
||||
|
||||
function facts(fire_st: mut FireState) -> []FireFact { return q_drain(fire_facts(fire_st)) }
|
||||
function facts(fire_st: FireState) -> []FireFact { return q_drain(fire_facts(fire_st)) }
|
||||
function count(fs: []FireFact, what: int) -> int {
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export state FishingState {
|
|||
fishing_run_left: int = 0
|
||||
fishing_run_next: float = 0.0
|
||||
fishing_dice: Rng = null
|
||||
fishing_fact_q: Queue<FishingFact> = null
|
||||
fishing_fact_q: Queue<FishingFact> = fishing_fact_q__new()
|
||||
fishing_n: int = 0 # the record: caught, the biggest (cm), a legend landed
|
||||
fishing_big: int = 0
|
||||
fishing_leg: bool = false
|
||||
|
|
@ -42,8 +42,7 @@ export function fishing_config(fishing_st: mut FishingState, min_depth: float, d
|
|||
fishing_st.fishing_dice = rng_new(seed)
|
||||
}
|
||||
|
||||
export function fishing_facts(fishing_st: mut FishingState) -> Queue<FishingFact> {
|
||||
if fishing_st.fishing_fact_q == null { fishing_st.fishing_fact_q = queue_new("fishing.facts") }
|
||||
export function fishing_facts(fishing_st: FishingState) -> Queue<FishingFact> {
|
||||
return fishing_st.fishing_fact_q
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +51,7 @@ function fishing_rand(fishing_st: mut FishingState) -> float {
|
|||
return rng_float(fishing_st.fishing_dice)
|
||||
}
|
||||
|
||||
function fishing_say(fishing_st: mut FishingState, what: int) -> void {
|
||||
function fishing_say(fishing_st: FishingState, what: int) -> void {
|
||||
let f = new FishingFact
|
||||
f.what = what
|
||||
f.species = fishing_st.fishing_sp
|
||||
|
|
@ -89,3 +88,4 @@ export function fishing_legend_caught(fishing_st: FishingState) -> bool { return
|
|||
export function fishing_water_at(fishing_st: FishingState, x: float, z: float) -> bool {
|
||||
return FishingWorld.afloat() or FishingWorld.depth(x, z) >= fishing_st.fishing_min_depth
|
||||
}
|
||||
function fishing_fact_q__new() -> Queue<FishingFact> { return queue_new("fishing.facts") }
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ program FishingTest {
|
|||
fishing_test_st.skill = 0.0
|
||||
}
|
||||
|
||||
function facts(fishing_st: mut FishingState) -> []FishingFact { return q_drain(fishing_facts(fishing_st)) }
|
||||
function facts(fishing_st: FishingState) -> []FishingFact { return q_drain(fishing_facts(fishing_st)) }
|
||||
function saw(fs: []FishingFact, what: int) -> bool {
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { return true } }
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ event Crit { target: int = 0, src: int = 0 } # the attacker's crit_pct fired
|
|||
state GameplayState {
|
||||
combat_reflecting: bool = false # thorns never reflect thorns
|
||||
combat_pending: int = 0
|
||||
fac_tbl: words = null
|
||||
fac_tbl: words = words(FAC_MAX * FAC_MAX)
|
||||
}
|
||||
|
||||
# the mutable channel for lever 6: listeners rewrite the pending damage here.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ const REL_HOSTILE: int = 2
|
|||
# A global var initialiser must be a literal, so it is allocated lazily.
|
||||
|
||||
function fac_ensure(gameplay_st: mut GameplayState) -> void {
|
||||
if gameplay_st.fac_tbl == null { gameplay_st.fac_tbl = words(FAC_MAX * FAC_MAX) }
|
||||
}
|
||||
|
||||
# Faction.set(a, b, rel) — record a symmetric relationship between two factions.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# buy.ludic - a tier bought with money once the standing is there; the kind's item follows
|
||||
export function gear_can_buy(gear_st: mut GearState, k: int) -> bool {
|
||||
export function gear_can_buy(gear_st: GearState, k: int) -> bool {
|
||||
if not gear_ok(k) or gear_best(gear_st, k) or GearWorld.hidden(k) { return false }
|
||||
return GearPurse.rep() >= gear_next_rep(gear_st, k) and GearPurse.money() >= gear_next_cost(gear_st, k)
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@ export function gear_buy(gear_st: mut GearState, k: int) -> bool {
|
|||
|
||||
# a kind whose item is already carried counts as its first tier
|
||||
export function gear_sync(gear_st: mut GearState) -> void {
|
||||
gear__ensure(gear_st)
|
||||
for k in 0 .. GEAR_COUNT {
|
||||
let it = GearKinds[k].item
|
||||
if it >= 0 and gear_st.gear__lv[k] == 0 and GearPack.count(it) > 0 { gear_st.gear__lv[k] = 1 }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ export function gear_hand(gear_st: GearState) -> int { return gear_st.gear__hand
|
|||
|
||||
# a new thing in the hand (-1 empty): whatever the old one was running goes out
|
||||
export function gear_set_hand(gear_st: mut GearState, it: int) -> void {
|
||||
gear__ensure(gear_st)
|
||||
gear_st.gear__hand = it
|
||||
for c in 0 .. CHARGE_COUNT { if GearCharges[c].hand { gear_st.gear__on[c] = false } }
|
||||
}
|
||||
|
|
@ -15,26 +14,22 @@ export function gear_charge_of(it: int) -> int {
|
|||
return -1
|
||||
}
|
||||
|
||||
export function gear_charge(gear_st: mut GearState, c: int) -> float {
|
||||
gear__ensure(gear_st)
|
||||
export function gear_charge(gear_st: GearState, c: int) -> float {
|
||||
return gear_st.gear__left[c]
|
||||
}
|
||||
|
||||
export function gear_charge_set(gear_st: mut GearState, c: int, v: float) -> void {
|
||||
gear__ensure(gear_st)
|
||||
gear_st.gear__left[c] = Math.clamp(v, 0.0, GearCharges[c].full)
|
||||
}
|
||||
|
||||
export function gear_charge_fill(gear_st: mut GearState, c: int) -> void { gear_charge_set(gear_st, c, GearCharges[c].full) }
|
||||
|
||||
export function gear_running(gear_st: mut GearState, c: int) -> bool {
|
||||
gear__ensure(gear_st)
|
||||
export function gear_running(gear_st: GearState, c: int) -> bool {
|
||||
return gear_st.gear__on[c]
|
||||
}
|
||||
|
||||
# on or off; false when it has nothing left, or is held and not in the hand
|
||||
export function gear_run(gear_st: mut GearState, c: int, on: bool) -> bool {
|
||||
gear__ensure(gear_st)
|
||||
if not on {
|
||||
gear_st.gear__on[c] = false
|
||||
return true
|
||||
|
|
@ -46,13 +41,13 @@ export function gear_run(gear_st: mut GearState, c: int, on: bool) -> bool {
|
|||
}
|
||||
|
||||
# the hand's own charge is running (a torch lit, a flashlight on)
|
||||
export function gear_lit(gear_st: mut GearState) -> bool {
|
||||
export function gear_lit(gear_st: GearState) -> bool {
|
||||
if gear_st.gear__hand < 0 { return false }
|
||||
let c = gear_charge_of(gear_st.gear__hand)
|
||||
return c >= 0 and GearCharges[c].hand and gear_running(gear_st, c)
|
||||
}
|
||||
|
||||
function gear__rate(gear_st: mut GearState, c: int) -> float {
|
||||
function gear__rate(gear_st: GearState, c: int) -> float {
|
||||
let d = GearCharges[c]
|
||||
if d.rate >= 0 { return gear_value(gear_st, d.rate) }
|
||||
return d.per_hour
|
||||
|
|
@ -60,7 +55,6 @@ function gear__rate(gear_st: mut GearState, c: int) -> float {
|
|||
|
||||
# the game hours of a tick burn every running charge; one that runs out stops and says so
|
||||
function gear__burn(gear_st: mut GearState, hours: float) -> void {
|
||||
gear__ensure(gear_st)
|
||||
for c in 0 .. CHARGE_COUNT {
|
||||
if not gear_st.gear__on[c] { continue }
|
||||
gear_st.gear__left[c] = gear_st.gear__left[c] - hours * gear__rate(gear_st, c)
|
||||
|
|
|
|||
|
|
@ -1,30 +1,32 @@
|
|||
# state.ludic - the level of each kind, the hand, each charge's units and whether it runs, the facts
|
||||
export state GearState {
|
||||
gear__lv: []int = null
|
||||
gear__lv: []int = gear__starts()
|
||||
gear__hand: int = -1
|
||||
gear__left: []float = null
|
||||
gear__on: []bool = null
|
||||
gear__q: Queue<GearFact> = null
|
||||
gear__left: []float = gear__fulls()
|
||||
gear__on: []bool = gear__offs()
|
||||
gear__q: Queue<GearFact> = gear__queue()
|
||||
}
|
||||
# what a new state starts with: every kind at its start, every charge full and off
|
||||
function gear__starts() -> []int {
|
||||
let xs = new []int
|
||||
for k in 0 .. GEAR_COUNT { push(xs, GearKinds[k].start) }
|
||||
return xs
|
||||
}
|
||||
function gear__fulls() -> []float {
|
||||
let xs = new []float
|
||||
for c in 0 .. CHARGE_COUNT { push(xs, GearCharges[c].full) }
|
||||
return xs
|
||||
}
|
||||
function gear__queue() -> Queue<GearFact> { return queue_new("gear.facts") }
|
||||
function gear__offs() -> []bool {
|
||||
let xs = new []bool
|
||||
for c in 0 .. CHARGE_COUNT { push(xs, false) }
|
||||
return xs
|
||||
}
|
||||
|
||||
function gear__ensure(gear_st: mut GearState) -> void {
|
||||
if gear_st.gear__lv != null { return }
|
||||
gear_st.gear__lv = new []int
|
||||
for k in 0 .. GEAR_COUNT { push(gear_st.gear__lv, GearKinds[k].start) }
|
||||
gear_st.gear__left = new []float
|
||||
gear_st.gear__on = new []bool
|
||||
for c in 0 .. CHARGE_COUNT {
|
||||
push(gear_st.gear__left, GearCharges[c].full)
|
||||
push(gear_st.gear__on, false)
|
||||
}
|
||||
}
|
||||
export function gear_facts(gear_st: GearState) -> Queue<GearFact> { return gear_st.gear__q }
|
||||
|
||||
export function gear_facts(gear_st: mut GearState) -> Queue<GearFact> {
|
||||
if gear_st.gear__q == null { gear_st.gear__q = queue_new("gear.facts") }
|
||||
return gear_st.gear__q
|
||||
}
|
||||
|
||||
function gear__fact(gear_st: mut GearState, what: int, k: int, c: int, cost: int) -> void {
|
||||
function gear__fact(gear_st: GearState, what: int, k: int, c: int, cost: int) -> void {
|
||||
let f = new GearFact
|
||||
f.what = what
|
||||
f.cost = cost
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
# system.ludic - gear as a system: the burn each tick, and the levels and charges saved by key (the
|
||||
# hand is not saved: a trip opens with empty hands)
|
||||
export function gear_reset(gear_st: mut GearState) -> void {
|
||||
gear__ensure(gear_st)
|
||||
for k in 0 .. GEAR_COUNT { gear_st.gear__lv[k] = GearKinds[k].start }
|
||||
for c in 0 .. CHARGE_COUNT {
|
||||
gear_st.gear__left[c] = GearCharges[c].full
|
||||
|
|
@ -11,8 +10,7 @@ export function gear_reset(gear_st: mut GearState) -> void {
|
|||
q_clear(gear_facts(gear_st))
|
||||
}
|
||||
|
||||
export function gear_save(gear_st: mut GearState) -> Val {
|
||||
gear__ensure(gear_st)
|
||||
export function gear_save(gear_st: GearState) -> Val {
|
||||
let v = Value.object()
|
||||
let lv = Value.object()
|
||||
for k in 0 .. GEAR_COUNT { sv_put_int(lv, GearKinds[k].key, gear_st.gear__lv[k]) }
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ program GearTest {
|
|||
gear_reset(gear_st)
|
||||
}
|
||||
|
||||
function ran_out(gear_st: mut GearState) -> int {
|
||||
function ran_out(gear_st: GearState) -> int {
|
||||
let fs = q_drain(gear_facts(gear_st))
|
||||
var n = -1
|
||||
for i in 0 .. len(fs) { if fs[i].what == GEAR_RAN_OUT { n = fs[i].charge } }
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
# tiers.ludic - what is owned and what a tier is worth
|
||||
export function gear_ok(k: int) -> bool { return k >= 0 and k < GEAR_COUNT }
|
||||
|
||||
export function gear_level(gear_st: mut GearState, k: int) -> int {
|
||||
gear__ensure(gear_st)
|
||||
export function gear_level(gear_st: GearState, k: int) -> int {
|
||||
return gear_st.gear__lv[k]
|
||||
}
|
||||
|
||||
# outright: staging, a test, a camera handed over with the trip
|
||||
export function gear_set_level(gear_st: mut GearState, k: int, lv: int) -> void {
|
||||
gear__ensure(gear_st)
|
||||
gear_st.gear__lv[k] = lv
|
||||
}
|
||||
|
||||
export function gear_owned(gear_st: mut GearState, k: int) -> bool { return gear_level(gear_st, k) > 0 }
|
||||
export function gear_owned(gear_st: GearState, k: int) -> bool { return gear_level(gear_st, k) > 0 }
|
||||
|
||||
export function gear_best(gear_st: mut GearState, k: int) -> bool { return gear_level(gear_st, k) >= GearKinds[k].tiers }
|
||||
export function gear_best(gear_st: GearState, k: int) -> bool { return gear_level(gear_st, k) >= GearKinds[k].tiers }
|
||||
|
||||
# a tier's name, "" for none
|
||||
export function gear_level_name(k: int, lv: int) -> string {
|
||||
|
|
@ -23,14 +21,14 @@ export function gear_level_name(k: int, lv: int) -> string {
|
|||
}
|
||||
|
||||
# the tier on offer next: its name, cost and the standing it wants
|
||||
export function gear_next_name(gear_st: mut GearState, k: int) -> string { return gear_level_name(k, gear_level(gear_st, k) + 1) }
|
||||
export function gear_next_name(gear_st: GearState, k: int) -> string { return gear_level_name(k, gear_level(gear_st, k) + 1) }
|
||||
|
||||
export function gear_next_cost(gear_st: mut GearState, k: int) -> int {
|
||||
export function gear_next_cost(gear_st: GearState, k: int) -> int {
|
||||
if gear_best(gear_st, k) { return 0 }
|
||||
return GearKinds[k].cost[gear_level(gear_st, k)]
|
||||
}
|
||||
|
||||
export function gear_next_rep(gear_st: mut GearState, k: int) -> int {
|
||||
export function gear_next_rep(gear_st: GearState, k: int) -> int {
|
||||
if gear_best(gear_st, k) { return 0 }
|
||||
return GearKinds[k].rep[gear_level(gear_st, k)]
|
||||
}
|
||||
|
|
@ -43,10 +41,10 @@ function gear__pick(xs: []float, lv: int, fallback: float) -> float {
|
|||
}
|
||||
|
||||
# the kind's own number at its level (1.0 when it has none)
|
||||
export function gear_mult(gear_st: mut GearState, k: int) -> float { return gear__pick(GearKinds[k].mult, gear_level(gear_st, k), 1.0) }
|
||||
export function gear_mult(gear_st: GearState, k: int) -> float { return gear__pick(GearKinds[k].mult, gear_level(gear_st, k), 1.0) }
|
||||
|
||||
# a value its kind's tier decides
|
||||
export function gear_value(gear_st: mut GearState, v: int) -> float {
|
||||
export function gear_value(gear_st: GearState, v: int) -> float {
|
||||
let d = GearValues[v]
|
||||
return gear__pick(d.at, gear_level(gear_st, d.gear), 0.0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,15 +10,14 @@ export state HintsState {
|
|||
hn_t: float = 0.0 # seconds to the next pass
|
||||
hn_pick: int = 0 # which chip the key would open
|
||||
hn_card: int = -1 # the card being read, or -1
|
||||
hn_facts: Queue<HintsFact> = null
|
||||
hn_facts: Queue<HintsFact> = hn_facts__new()
|
||||
}
|
||||
|
||||
export function hints_facts(hints_st: mut HintsState) -> Queue<HintsFact> {
|
||||
if hints_st.hn_facts == null { hints_st.hn_facts = queue_new("hints.facts") }
|
||||
export function hints_facts(hints_st: HintsState) -> Queue<HintsFact> {
|
||||
return hints_st.hn_facts
|
||||
}
|
||||
|
||||
function hn_fact(hints_st: mut HintsState, what: int, card: int) -> void {
|
||||
function hn_fact(hints_st: HintsState, what: int, card: int) -> void {
|
||||
let f = new HintsFact
|
||||
f.what = what
|
||||
f.card = card
|
||||
|
|
@ -104,3 +103,4 @@ export function hints_reset(hints_st: mut HintsState) -> void {
|
|||
hints_st.hn_card = -1
|
||||
q_clear(hints_facts(hints_st))
|
||||
}
|
||||
function hn_facts__new() -> Queue<HintsFact> { return queue_new("hints.facts") }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ program HintsTest {
|
|||
hints_mutes_load(hints_st, Value.list())
|
||||
}
|
||||
|
||||
function count(hints_st: mut HintsState, what: int) -> int {
|
||||
function count(hints_st: HintsState, what: int) -> int {
|
||||
let fs = q_drain(hints_facts(hints_st))
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export property ItemChanged {
|
|||
export state InventoryState {
|
||||
iv_keys: []string = null
|
||||
iv_counts: []int = null
|
||||
iv_changes: Queue<ItemChanged> = null
|
||||
iv_changes: Queue<ItemChanged> = iv_changes__new()
|
||||
}
|
||||
|
||||
# the kinds, by the name each is saved under; the pack starts empty
|
||||
|
|
@ -24,8 +24,7 @@ export function inv_config(inventory_st: mut InventoryState, keys: []string) ->
|
|||
inv_clear(inventory_st)
|
||||
}
|
||||
|
||||
export function inv_changes(inventory_st: mut InventoryState) -> Queue<ItemChanged> {
|
||||
if inventory_st.iv_changes == null { inventory_st.iv_changes = queue_new("inventory.changes") }
|
||||
export function inv_changes(inventory_st: InventoryState) -> Queue<ItemChanged> {
|
||||
return inventory_st.iv_changes
|
||||
}
|
||||
|
||||
|
|
@ -59,3 +58,4 @@ export function inv_total(inventory_st: InventoryState) -> int {
|
|||
for i in 0 .. len(inventory_st.iv_counts) { t += inventory_st.iv_counts[i] }
|
||||
return t
|
||||
}
|
||||
function iv_changes__new() -> Queue<ItemChanged> { return queue_new("inventory.changes") }
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ program InventoryTest {
|
|||
inv_reset(inventory_st)
|
||||
}
|
||||
|
||||
function changes(inventory_st: mut InventoryState) -> []ItemChanged { return q_drain(inv_changes(inventory_st)) }
|
||||
function waiting(inventory_st: mut InventoryState) -> int { return q_len(inv_changes(inventory_st)) }
|
||||
function changes(inventory_st: InventoryState) -> []ItemChanged { return q_drain(inv_changes(inventory_st)) }
|
||||
function waiting(inventory_st: InventoryState) -> int { return q_len(inv_changes(inventory_st)) }
|
||||
|
||||
test "add puts in what fits and says how many" (inventory_st: mut InventoryState) {
|
||||
fresh(inventory_st)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export state JobsState {
|
|||
jobs__serial: []int = null # posts made, per board: each roll its own seed
|
||||
jobs__seed: int = 1000
|
||||
jobs__dice: Rng = null
|
||||
jobs__q: Queue<JobsFact> = null
|
||||
jobs__q: Queue<JobsFact> = jobs__q__new()
|
||||
}
|
||||
|
||||
# the posts, every board's slots end to end from jobs__off[b]
|
||||
|
|
@ -59,12 +59,11 @@ function jobs__ensure(jobs_st: mut JobsState) -> void {
|
|||
jobs_st.jobs__dice = rng_new(jobs_st.jobs__seed)
|
||||
}
|
||||
|
||||
export function jobs_facts(jobs_st: mut JobsState) -> Queue<JobsFact> {
|
||||
if jobs_st.jobs__q == null { jobs_st.jobs__q = queue_new("jobs.facts") }
|
||||
export function jobs_facts(jobs_st: JobsState) -> Queue<JobsFact> {
|
||||
return jobs_st.jobs__q
|
||||
}
|
||||
|
||||
function jobs__fact(jobs_st: mut JobsState, what: int, job: int, b: int, s: int, have: int, need: int) -> void {
|
||||
function jobs__fact(jobs_st: JobsState, what: int, job: int, b: int, s: int, have: int, need: int) -> void {
|
||||
let f = new JobsFact
|
||||
f.what = what
|
||||
f.job = job
|
||||
|
|
@ -93,3 +92,4 @@ export function jobs_config_seed(jobs_st: mut JobsState, seed: int) -> void {
|
|||
jobs_st.jobs__seed = seed
|
||||
jobs_st.jobs__dice = rng_new(seed)
|
||||
}
|
||||
function jobs__q__new() -> Queue<JobsFact> { return queue_new("jobs.facts") }
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ program JobsTest {
|
|||
jobs_party_reset(jobs_st)
|
||||
}
|
||||
|
||||
function count_of(jobs_st: mut JobsState, what: int) -> int {
|
||||
function count_of(jobs_st: JobsState, what: int) -> int {
|
||||
let fs = q_drain(jobs_facts(jobs_st))
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export state NeedsState {
|
|||
nd_legs: float = 0.0 # seconds left before a collapse, 0 = none
|
||||
nd_last: int = 0 # the need the countdown is for
|
||||
nd_collapses: int = 0
|
||||
nd_facts: Queue<NeedFact> = null
|
||||
nd_facts: Queue<NeedFact> = nd_facts__new()
|
||||
}
|
||||
|
||||
function nd_lv(needs_st: mut NeedsState) -> []float {
|
||||
|
|
@ -75,12 +75,11 @@ function nd_fill(needs_st: mut NeedsState) -> void {
|
|||
}
|
||||
|
||||
# the facts, oldest first; the game drains them into its notices and its collapse
|
||||
export function needs_facts(needs_st: mut NeedsState) -> Queue<NeedFact> {
|
||||
if needs_st.nd_facts == null { needs_st.nd_facts = queue_new("needs.facts") }
|
||||
export function needs_facts(needs_st: NeedsState) -> Queue<NeedFact> {
|
||||
return needs_st.nd_facts
|
||||
}
|
||||
|
||||
function nd_fact(needs_st: mut NeedsState, what: int, need: int) -> void {
|
||||
function nd_fact(needs_st: NeedsState, what: int, need: int) -> void {
|
||||
let f = new NeedFact
|
||||
f.what = what
|
||||
f.need = need
|
||||
|
|
@ -88,3 +87,4 @@ function nd_fact(needs_st: mut NeedsState, what: int, need: int) -> void {
|
|||
}
|
||||
|
||||
function nd_ok(k: int) -> bool { return k >= 0 and k < NEED_COUNT }
|
||||
function nd_facts__new() -> Queue<NeedFact> { return queue_new("needs.facts") }
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ program NeedsTest {
|
|||
|
||||
function fresh(needs_st: mut NeedsState) -> void { needs_reset(needs_st) }
|
||||
function hours(needs_st: mut NeedsState, h: float) -> void { for i in 0 .. int(h * 10.0) { needs_run(needs_st, 0.1) } }
|
||||
function facts(needs_st: mut NeedsState) -> []NeedFact { return q_drain(needs_facts(needs_st)) }
|
||||
function facts(needs_st: NeedsState) -> []NeedFact { return q_drain(needs_facts(needs_st)) }
|
||||
|
||||
test "a new body is warm, rested, fed and watered" (needs_st: mut NeedsState) {
|
||||
fresh(needs_st)
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ export function nr_text(net_st: mut NetState, cap: int) -> string {
|
|||
net_st.net__rbad = true
|
||||
return ""
|
||||
}
|
||||
if net_st.net__tb == null { net_st.net__tb = buffer(NET_MTU) }
|
||||
nb_copy(net_st.net__tb, 0, net_st.net__rb, net_st.net__rp, n)
|
||||
net_st.net__rp += n
|
||||
return text_of(net_st.net__tb, n)
|
||||
|
|
|
|||
|
|
@ -61,17 +61,15 @@ export port NetSocket {
|
|||
|
||||
export function net_config(net_st: mut NetState, c: NetConfig) -> void { net_st.net__cfg = c }
|
||||
|
||||
function net__conf(net_st: mut NetState) -> NetConfig {
|
||||
if net_st.net__cfg == null { net_st.net__cfg = new NetConfig }
|
||||
function net__conf(net_st: NetState) -> NetConfig {
|
||||
return net_st.net__cfg
|
||||
}
|
||||
|
||||
export function net_facts(net_st: mut NetState) -> Queue<NetFact> {
|
||||
if net_st.net__facts == null { net_st.net__facts = queue_new("net.facts") }
|
||||
export function net_facts(net_st: NetState) -> Queue<NetFact> {
|
||||
return net_st.net__facts
|
||||
}
|
||||
|
||||
function net__fact(net_st: mut NetState, what: int, slot: int, pid: int, why: int, text: string) -> void {
|
||||
function net__fact(net_st: NetState, what: int, slot: int, pid: int, why: int, text: string) -> void {
|
||||
let f = new NetFact
|
||||
f.what = what
|
||||
f.slot = slot
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
function net__new_guest(net_st: mut NetState, pub: string, local: string) -> void {
|
||||
let key = `{pub}|{local}`
|
||||
if net_st.net__seen == null { net_st.net__seen = new []string }
|
||||
for i in 0 .. len(net_st.net__seen) { if net_st.net__seen[i] == key { return } }
|
||||
push(net_st.net__seen, key)
|
||||
net__log(`room {net_st.net__room}: a guest at {pub} / {local}`)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ function net__messages(net_st: mut NetState, slot: int, n: int) -> void {
|
|||
}
|
||||
|
||||
# onto the inbox - except a heartbeat, and on a host anything but a hello before its welcome
|
||||
function net__deliver(net_st: mut NetState, slot: int, from: int, kind: int, o: int, ml: int) -> void {
|
||||
function net__deliver(net_st: NetState, slot: int, from: int, kind: int, o: int, ml: int) -> void {
|
||||
if kind == NET_BEAT { return }
|
||||
if net_st.net__state == NET_HOSTING and net_st.net__peers[slot].pid < 2 and kind != NET_HELLO { return }
|
||||
let m = new NetMessage
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ function net__use_relay(net_st: mut NetState) -> void {
|
|||
|
||||
export function net_via_relay(net_st: NetState) -> bool { return net_st.net__via_relay }
|
||||
|
||||
function net__relayed(net_st: mut NetState, p: NetPeer) -> bool {
|
||||
function net__relayed(net_st: NetState, p: NetPeer) -> bool {
|
||||
return net_st.net__relay_ip != 0 and p.ip == net_st.net__relay_ip and (p.port >= net__conf(net_st).relay_port0 or net_st.net__via_relay)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const NET_R_DONE: int = 5 # a guest: the hello is on its way
|
|||
|
||||
|
||||
# room codes are on when the game named a matchmaker
|
||||
export function net_room_on(net_st: mut NetState) -> bool { return len(net__conf(net_st).signal_url) > 0 }
|
||||
export function net_room_on(net_st: NetState) -> bool { return len(net__conf(net_st).signal_url) > 0 }
|
||||
export function net_room(net_st: NetState) -> string { return net_st.net__room }
|
||||
export function net_room_asking(net_st: NetState) -> bool { return net_st.net__r_state == NET_R_STUN or net_st.net__r_state == NET_R_ASK }
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ export property NetMessage {
|
|||
}
|
||||
|
||||
export state NetState {
|
||||
net__cfg: NetConfig = null
|
||||
net__facts: Queue<NetFact> = null
|
||||
net__seen: []string = null # guests already punched for
|
||||
net__cfg: NetConfig = new NetConfig
|
||||
net__facts: Queue<NetFact> = net__facts__new()
|
||||
net__seen: []string = new []string # guests already punched for
|
||||
net__punch_ip: words = null
|
||||
net__punch_port: words = null
|
||||
net__punch_left: words = null
|
||||
|
|
@ -88,7 +88,7 @@ export state NetState {
|
|||
net__rl: int = 0
|
||||
net__rp: int = 0
|
||||
net__rbad: bool = false
|
||||
net__tb: []byte = null # text read out of a message, through one scratch buffer
|
||||
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_l: int = 0
|
||||
net__hello_t: float = 0.0 # seconds since it went; -1 not yet
|
||||
|
|
@ -100,15 +100,14 @@ export state NetState {
|
|||
net__code_port: int = 0
|
||||
net__bytes_out: int = 0
|
||||
net__kind_out: words = null
|
||||
net__inbox: Queue<NetMessage> = null
|
||||
net__inbox: Queue<NetMessage> = net__inbox__new()
|
||||
net__stun_ip: int = 0
|
||||
net__stun_port: int = 0
|
||||
net__txn: words = null
|
||||
net__txn: words = words(3)
|
||||
net__dice: Rng = null
|
||||
}
|
||||
|
||||
export function net_inbox(net_st: mut NetState) -> Queue<NetMessage> {
|
||||
if net_st.net__inbox == null { net_st.net__inbox = queue_new("net.inbox") }
|
||||
export function net_inbox(net_st: NetState) -> Queue<NetMessage> {
|
||||
return net_st.net__inbox
|
||||
}
|
||||
|
||||
|
|
@ -126,3 +125,5 @@ function net__init(net_st: mut NetState) -> void {
|
|||
net_st.net__rb = buffer(NET_MTU)
|
||||
net_st.net__hello_b = buffer(NET_MTU)
|
||||
}
|
||||
function net__facts__new() -> Queue<NetFact> { return queue_new("net.facts") }
|
||||
function net__inbox__new() -> Queue<NetMessage> { return queue_new("net.inbox") }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
# from outside: the router's address and the port it mapped
|
||||
|
||||
function net__stun_send(net_st: mut NetState) -> void {
|
||||
if net_st.net__txn == null { net_st.net__txn = words(3) }
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ program NetTest {
|
|||
return net_accept(net_st, got[0].slot)
|
||||
}
|
||||
|
||||
function facts_of(net_st: mut NetState, what: int) -> []NetFact {
|
||||
function facts_of(net_st: NetState, what: int) -> []NetFact {
|
||||
let all = q_drain(net_facts(net_st))
|
||||
let out = new []NetFact
|
||||
for i in 0 .. len(all) { if all[i].what == what { push(out, all[i]) } }
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ function np_turns(act: int) -> bool {
|
|||
}
|
||||
|
||||
# a player who came within notice since the last look is greeted - once, until they walk off
|
||||
export function npc_notice(npc_st: mut NpcState, p: NpcPerson) -> void {
|
||||
export function npc_notice(npc_st: NpcState, p: NpcPerson) -> void {
|
||||
let reach = NpcKinds[p.kind].notice
|
||||
for i in 0 .. NpcWorld.players() {
|
||||
if i >= 30 { break }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# census.ludic - making one (a slot reused before a new one, a look, a name, a start on its own
|
||||
# ground out of the players' sight where that can be had), a post's fixed person, and leaving
|
||||
export function npc_spawn(npc_st: mut NpcState, kind: int) -> NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
if npc_st.np_n >= npc_st.np_max or kind < 0 or kind >= NPCK_COUNT { return null }
|
||||
var p: NpcPerson = null
|
||||
for i in 0 .. len(npc_st.np_walkers) {
|
||||
|
|
@ -94,7 +94,7 @@ export function npc_set_at(p: NpcPerson, x: float, z: float) -> void {
|
|||
# somebody fixed at a post (a vendor behind the counter): never walks, never counted, never leaves,
|
||||
# turns to a player within its kind's notice and back to `yaw` when they go
|
||||
export function npc_place(npc_st: mut NpcState, kind: int, x: float, z: float, yaw: float, name: string, look: int) -> NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
let p = new NpcPerson
|
||||
p.slot = len(npc_st.np_posts)
|
||||
np_fresh(p, kind, look)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
# on: this machine's own walkers leave, and only the host's are drawn until it is turned off
|
||||
export function npc_mirror(npc_st: mut NpcState, on: bool) -> void {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
if npc_st.np_mirror == on { return }
|
||||
npc_st.np_mirror = on
|
||||
for i in 0 .. len(npc_st.np_walkers) { npc_retire(npc_st, npc_st.np_walkers[i]) }
|
||||
|
|
@ -14,7 +14,7 @@ export function npc_mirroring(npc_st: NpcState) -> bool { return npc_st.np_mirro
|
|||
|
||||
# the host's slot: somebody new in it (born), or nobody (gone)
|
||||
export function npc_put(npc_st: mut NpcState, slot: int, id: int, kind: int, look: int, seed: float, name: string, hx: float, hz: float) -> NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
if slot < 0 or slot >= npc_st.np_max or kind < 0 or kind >= NPCK_COUNT { return null }
|
||||
while len(npc_st.np_walkers) <= slot {
|
||||
let q = new NpcPerson
|
||||
|
|
@ -36,7 +36,7 @@ export function npc_put(npc_st: mut NpcState, slot: int, id: int, kind: int, loo
|
|||
}
|
||||
|
||||
# where the host says it is now, and what it is doing
|
||||
export function npc_heard(npc_st: mut NpcState, slot: int, x: float, y: float, z: float, yaw: float, speed: float, act: int, stalk: bool) -> void {
|
||||
export function npc_heard(npc_st: NpcState, slot: int, x: float, y: float, z: float, yaw: float, speed: float, act: int, stalk: bool) -> void {
|
||||
let p = npc_at(npc_st, slot)
|
||||
if p == null or not p.active { return }
|
||||
if not p.heard {
|
||||
|
|
@ -60,7 +60,7 @@ export function npc_heard(npc_st: mut NpcState, slot: int, x: float, y: float, z
|
|||
export function npc_heard_lately(npc_st: NpcState, p: NpcPerson) -> bool { return p.heard and npc_st.np_clock - p.heard_t <= 6.0 }
|
||||
|
||||
export function npc_mirror_tick(npc_st: mut NpcState, dt: float) -> void {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
npc_st.np_clock = npc_st.np_clock + dt
|
||||
let k = Math.min(1.0, dt * 8.0)
|
||||
for i in 0 .. len(npc_st.np_walkers) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# names.ludic - a name nobody else in the place is using: not another person, not one the place
|
||||
# keeps for itself (NpcWorld.taken: a vendor), and not somebody who left a little while ago
|
||||
|
||||
export function npc_name_used(npc_st: mut NpcState, n: string) -> bool {
|
||||
export function npc_name_used(npc_st: NpcState, n: string) -> bool {
|
||||
if NpcWorld.taken(n) { return true }
|
||||
let all = npc_walkers(npc_st)
|
||||
for i in 0 .. len(all) { if all[i].active and all[i].name == n { return true } }
|
||||
|
|
@ -12,7 +12,7 @@ export function npc_name_used(npc_st: mut NpcState, n: string) -> bool {
|
|||
}
|
||||
|
||||
# a free name from the body's pool, from a place in it the dice choose ("" when the pool is empty)
|
||||
export function npc_pick_name(npc_st: mut NpcState, body: int) -> string {
|
||||
export function npc_pick_name(npc_st: NpcState, body: int) -> string {
|
||||
let pool = new []string
|
||||
for i in 0 .. NPCN_COUNT { if NpcNames[i].body == body { push(pool, NpcNames[i].name) } }
|
||||
let n = len(pool)
|
||||
|
|
@ -26,7 +26,6 @@ export function npc_pick_name(npc_st: mut NpcState, body: int) -> string {
|
|||
}
|
||||
|
||||
function np_left(npc_st: mut NpcState, name: string) -> void {
|
||||
if npc_st.np_recent == null { npc_st.np_recent = new []string }
|
||||
push(npc_st.np_recent, name)
|
||||
if len(npc_st.np_recent) <= 8 { return }
|
||||
let keep = new []string
|
||||
|
|
@ -35,7 +34,7 @@ function np_left(npc_st: mut NpcState, name: string) -> void {
|
|||
}
|
||||
|
||||
# how many pairs share a name, the place's own names included
|
||||
export function npc_name_clashes(npc_st: mut NpcState) -> int {
|
||||
export function npc_name_clashes(npc_st: NpcState) -> int {
|
||||
var dup = 0
|
||||
let all = npc_walkers(npc_st)
|
||||
for i in 0 .. len(all) {
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ export state NpcState {
|
|||
np_wx: float = 0.0
|
||||
np_wz: float = 0.0
|
||||
np_clock: float = 0.0
|
||||
np_recent: []string = null # the last few names that left
|
||||
np_walkers: []NpcPerson = null
|
||||
np_posts: []NpcPerson = null
|
||||
np_recent: []string = new []string # the last few names that left
|
||||
np_walkers: []NpcPerson = new []NpcPerson
|
||||
np_posts: []NpcPerson = new []NpcPerson
|
||||
np_max: int = 10 # walkers at most
|
||||
np_n: int = 0 # walkers about
|
||||
np_dice: Rng = null
|
||||
np_facts: Queue<NpcFact> = null
|
||||
np_dice: Rng = rng_new(20260925)
|
||||
np_facts: Queue<NpcFact> = np_facts__new()
|
||||
np_next_h: float = 0.0 # the hour the census is next looked at
|
||||
np_hold: bool = false # held where they stand (a shot of their poses)
|
||||
np_mirror: bool = false # a guest drawing a host's: no routine runs here
|
||||
|
|
@ -23,12 +23,11 @@ export state NpcState {
|
|||
const NP_PI: float = 3.1415927
|
||||
const NP_TAU: float = 6.2831853
|
||||
|
||||
export function npc_facts(npc_st: mut NpcState) -> Queue<NpcFact> {
|
||||
if npc_st.np_facts == null { npc_st.np_facts = queue_new("npc.facts") }
|
||||
export function npc_facts(npc_st: NpcState) -> Queue<NpcFact> {
|
||||
return npc_st.np_facts
|
||||
}
|
||||
|
||||
function np_fact(npc_st: mut NpcState, what: int, p: NpcPerson, player: int) -> NpcFact {
|
||||
function np_fact(npc_st: NpcState, what: int, p: NpcPerson, player: int) -> NpcFact {
|
||||
let f = new NpcFact
|
||||
f.what = what
|
||||
f.person = p.id
|
||||
|
|
@ -40,40 +39,37 @@ function np_fact(npc_st: mut NpcState, what: int, p: NpcPerson, player: int) ->
|
|||
return f
|
||||
}
|
||||
|
||||
function np_ensure(npc_st: mut NpcState) -> void {
|
||||
if npc_st.np_walkers == null { npc_st.np_walkers = new []NpcPerson }
|
||||
if npc_st.np_posts == null { npc_st.np_posts = new []NpcPerson }
|
||||
if npc_st.np_dice == null { npc_st.np_dice = rng_new(20260925) }
|
||||
function np_ensure() -> void {
|
||||
}
|
||||
|
||||
# how many walkers the place can hold at once
|
||||
export function npc_config(npc_st: mut NpcState, max: int) -> void { npc_st.np_max = max }
|
||||
|
||||
export function npc_seed(npc_st: mut NpcState, n: int) -> void {
|
||||
np_ensure(npc_st)
|
||||
export function npc_seed(npc_st: NpcState, n: int) -> void {
|
||||
np_ensure()
|
||||
rng_seed(npc_st.np_dice, n)
|
||||
}
|
||||
|
||||
# 0 .. 1, and whole seconds lo .. hi, off the package's dice
|
||||
export function npc_rnd(npc_st: mut NpcState) -> float {
|
||||
np_ensure(npc_st)
|
||||
export function npc_rnd(npc_st: NpcState) -> float {
|
||||
np_ensure()
|
||||
return rng_float(npc_st.np_dice)
|
||||
}
|
||||
|
||||
export function npc_between(npc_st: mut NpcState, lo: int, hi: int) -> int {
|
||||
np_ensure(npc_st)
|
||||
export function npc_between(npc_st: NpcState, lo: int, hi: int) -> int {
|
||||
np_ensure()
|
||||
return rng_between(npc_st.np_dice, lo, hi)
|
||||
}
|
||||
|
||||
export function npc_secs(npc_st: mut NpcState, lo: int, hi: int) -> float { return float(npc_between(npc_st, lo, np_hi(lo, hi))) }
|
||||
export function npc_secs(npc_st: NpcState, lo: int, hi: int) -> float { return float(npc_between(npc_st, lo, np_hi(lo, hi))) }
|
||||
|
||||
export function npc_walkers(npc_st: mut NpcState) -> []NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
export function npc_walkers(npc_st: NpcState) -> []NpcPerson {
|
||||
np_ensure()
|
||||
return npc_st.np_walkers
|
||||
}
|
||||
|
||||
export function npc_posts(npc_st: mut NpcState) -> []NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
export function npc_posts(npc_st: NpcState) -> []NpcPerson {
|
||||
np_ensure()
|
||||
return npc_st.np_posts
|
||||
}
|
||||
|
||||
|
|
@ -82,20 +78,20 @@ export function npc_count(npc_st: NpcState) -> int { return npc_st.np_n }
|
|||
export function npc_max(npc_st: NpcState) -> int { return npc_st.np_max }
|
||||
|
||||
# a walker's slot or a post, and anyone by id
|
||||
export function npc_at(npc_st: mut NpcState, slot: int) -> NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
export function npc_at(npc_st: NpcState, slot: int) -> NpcPerson {
|
||||
np_ensure()
|
||||
if slot < 0 or slot >= len(npc_st.np_walkers) { return null }
|
||||
return npc_st.np_walkers[slot]
|
||||
}
|
||||
|
||||
export function npc_post(npc_st: mut NpcState, i: int) -> NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
export function npc_post(npc_st: NpcState, i: int) -> NpcPerson {
|
||||
np_ensure()
|
||||
if i < 0 or i >= len(npc_st.np_posts) { return null }
|
||||
return npc_st.np_posts[i]
|
||||
}
|
||||
|
||||
export function npc_by_id(npc_st: mut NpcState, id: int) -> NpcPerson {
|
||||
np_ensure(npc_st)
|
||||
export function npc_by_id(npc_st: NpcState, id: int) -> NpcPerson {
|
||||
np_ensure()
|
||||
for i in 0 .. len(npc_st.np_walkers) { if npc_st.np_walkers[i].active and npc_st.np_walkers[i].id == id { return npc_st.np_walkers[i] } }
|
||||
for i in 0 .. len(npc_st.np_posts) { if npc_st.np_posts[i].active and npc_st.np_posts[i].id == id { return npc_st.np_posts[i] } }
|
||||
return null
|
||||
|
|
@ -118,3 +114,4 @@ function np_hi(lo: int, hi: int) -> int {
|
|||
if hi < lo { return lo }
|
||||
return hi
|
||||
}
|
||||
function np_facts__new() -> Queue<NpcFact> { return queue_new("npc.facts") }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# routine.ludic - going somewhere to do something, doing it here, and deciding what is next: the
|
||||
# kind's own plan first, then a weighted draw among its steps for this hour, falling through to the
|
||||
# next step whose spot can be found, and standing a while when none can
|
||||
export function npc_go(npc_st: mut NpcState, p: NpcPerson, x: float, z: float, act: int, dur: float) -> void {
|
||||
export function npc_go(npc_st: NpcState, p: NpcPerson, x: float, z: float, act: int, dur: float) -> void {
|
||||
p.tx = x
|
||||
p.tz = z
|
||||
p.next_act = act
|
||||
|
|
@ -76,7 +76,7 @@ export function npc_plan(npc_st: mut NpcState, p: NpcPerson) -> void {
|
|||
|
||||
# a weighted draw among the steps whose hours hold now; a step whose spot cannot be found
|
||||
# gives way to the next one in the table, round to the start
|
||||
export function npc_steps(npc_st: mut NpcState, p: NpcPerson, steps: []NpcStep) -> bool {
|
||||
export function npc_steps(npc_st: NpcState, p: NpcPerson, steps: []NpcStep) -> bool {
|
||||
let h = NpcWorld.hour()
|
||||
var total = 0
|
||||
for i in 0 .. len(steps) { if np_in_hours(steps[i], h) { total += np_pos(steps[i].weight) } }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ def NpcSpots shore_here { find: fn np_spot_shore_here }
|
|||
def NpcSpots wander { find: fn np_spot_wander }
|
||||
|
||||
# the step's act for the step's time, at (x, z)
|
||||
export function npc_step_go(npc_st: mut NpcState, p: NpcPerson, s: NpcStep, x: float, z: float) -> void {
|
||||
export function npc_step_go(npc_st: NpcState, p: NpcPerson, s: NpcStep, x: float, z: float) -> void {
|
||||
npc_go(npc_st, p, x, z, s.act, npc_secs(npc_st, s.lo, s.hi))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ function fk_player_at(npc_tests_fake_st: mut NpcTestsFakeState, x: float, z: flo
|
|||
# seconds of the place, in twentieths
|
||||
function fk_run(npc_st: mut NpcState, secs: float) -> void { for k in 0 .. int(secs * 20.0) { npc_tick(npc_st, 0.05) } }
|
||||
|
||||
function fk_count(npc_st: mut NpcState, what: int) -> int {
|
||||
function fk_count(npc_st: NpcState, what: int) -> int {
|
||||
let fs = q_drain(npc_facts(npc_st))
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# tick.ludic - a step of everyone, on the machine that runs the place: the census on the half hour,
|
||||
# the day's end (only ever out of every player's sight), the walk or the act, and who noticed whom
|
||||
export function npc_tick(npc_st: mut NpcState, dt: float) -> void {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
for i in 0 .. len(npc_st.np_posts) { if npc_st.np_posts[i].active { np_step_post(npc_st, npc_st.np_posts[i], dt) } }
|
||||
if npc_st.np_hold or npc_st.np_mirror { return }
|
||||
np_census(npc_st)
|
||||
|
|
@ -15,7 +15,7 @@ export function npc_tick(npc_st: mut NpcState, dt: float) -> void {
|
|||
|
||||
# the posts alone: a machine that does not run the place still turns its vendors to whoever comes
|
||||
export function npc_posts_tick(npc_st: mut NpcState, dt: float) -> void {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
for i in 0 .. len(npc_st.np_posts) { if npc_st.np_posts[i].active { np_step_post(npc_st, npc_st.np_posts[i], dt) } }
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ function np_census(npc_st: mut NpcState) -> void {
|
|||
|
||||
function np_is_night(h: float) -> bool { return h >= 21.0 or h < 5.0 }
|
||||
|
||||
function np_draw_kind(npc_st: mut NpcState, night: bool) -> int {
|
||||
function np_draw_kind(npc_st: NpcState, night: bool) -> int {
|
||||
var total = 0
|
||||
for k in 0 .. NPCK_COUNT { if np_drawn(k, night) { total += NpcKinds[k].weight } }
|
||||
if total <= 0 { return -1 }
|
||||
|
|
@ -82,7 +82,7 @@ export function npc_hold(npc_st: mut NpcState, on: bool) -> void { npc_st.np_hol
|
|||
|
||||
# everyone gone, as a new trip starts; the posts are the place's and stay
|
||||
export function npc_reset(npc_st: mut NpcState) -> void {
|
||||
np_ensure(npc_st)
|
||||
np_ensure()
|
||||
for i in 0 .. len(npc_st.np_walkers) { npc_retire(npc_st, npc_st.np_walkers[i]) }
|
||||
npc_st.np_n = 0
|
||||
npc_st.np_next_h = 0.0
|
||||
|
|
|
|||
|
|
@ -54,17 +54,16 @@ export state PhotoState {
|
|||
pht_pending_stars: bool = false
|
||||
pht_comp: []float = null # size, framing, light, moment of the last subject scored
|
||||
pht_comp_have: bool = false
|
||||
pht_fact_q: Queue<PhotoFact> = null
|
||||
pht_fact_q: Queue<PhotoFact> = pht_fact_q__new()
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function photo_facts(photo_st: mut PhotoState) -> Queue<PhotoFact> {
|
||||
if photo_st.pht_fact_q == null { photo_st.pht_fact_q = queue_new("photo.facts") }
|
||||
export function photo_facts(photo_st: PhotoState) -> Queue<PhotoFact> {
|
||||
return photo_st.pht_fact_q
|
||||
}
|
||||
|
||||
function pht_fact(photo_st: mut PhotoState, what: int, i: int) -> PhotoFact {
|
||||
function pht_fact(photo_st: PhotoState, what: int, i: int) -> PhotoFact {
|
||||
let f = new PhotoFact
|
||||
f.what = what
|
||||
f.index = i
|
||||
|
|
@ -100,3 +99,4 @@ function pht_blank(photo_st: mut PhotoState) -> void {
|
|||
photo_st.pht_comp = pht_floats(4)
|
||||
photo_st.pht_comp_have = false
|
||||
}
|
||||
function pht_fact_q__new() -> Queue<PhotoFact> { return queue_new("photo.facts") }
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ program PhotoTest {
|
|||
photo_test_st.sun_z = 0.0
|
||||
photo_test_st.behaviour = false
|
||||
}
|
||||
function facts(photo_st: mut PhotoState) -> []PhotoFact { return q_drain(photo_facts(photo_st)) }
|
||||
function facts(photo_st: PhotoState) -> []PhotoFact { return q_drain(photo_facts(photo_st)) }
|
||||
function count(fs: []PhotoFact, what: int) -> int {
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export state SessionState {
|
|||
session__max: int = 4
|
||||
session__open: bool = true
|
||||
session__near_i: int = 0
|
||||
session__facts: Queue<SessionFact> = null
|
||||
session__facts: Queue<SessionFact> = session__facts__new()
|
||||
session__vote_id: int = 0
|
||||
session__vote_kind: int = 0
|
||||
session__vote_param: int = 0
|
||||
|
|
@ -78,12 +78,11 @@ export state SessionState {
|
|||
session__vote_passed: int = -1 # the last vote: -1 none, 0 failed, 1 passed
|
||||
}
|
||||
|
||||
export function ses_facts(session_st: mut SessionState) -> Queue<SessionFact> {
|
||||
if session_st.session__facts == null { session_st.session__facts = queue_new("session.facts") }
|
||||
export function ses_facts(session_st: SessionState) -> Queue<SessionFact> {
|
||||
return session_st.session__facts
|
||||
}
|
||||
|
||||
function session__fact(session_st: mut SessionState, what: int, slot: int, pid: int) -> SessionFact {
|
||||
function session__fact(session_st: SessionState, what: int, slot: int, pid: int) -> SessionFact {
|
||||
let f = new SessionFact
|
||||
f.what = what
|
||||
f.slot = slot
|
||||
|
|
@ -99,3 +98,4 @@ function session__init(session_st: mut SessionState) -> void {
|
|||
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<SessionFact> { return queue_new("session.facts") }
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ program SessionTest {
|
|||
function fname() -> string { return "me" }
|
||||
bind SessionLocal { x: fn fx, y: fn fy, z: fn fz, name: fn fname }
|
||||
|
||||
function whats(session_st: mut SessionState) -> []int {
|
||||
function whats(session_st: SessionState) -> []int {
|
||||
let fs = q_drain(ses_facts(session_st))
|
||||
let out = new []int
|
||||
for i in 0 .. len(fs) { push(out, fs[i].what) }
|
||||
return out
|
||||
}
|
||||
|
||||
function last_of(session_st: mut SessionState, what: int) -> SessionFact {
|
||||
function last_of(session_st: SessionState, what: int) -> SessionFact {
|
||||
let fs = q_drain(ses_facts(session_st))
|
||||
var f: SessionFact = null
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { f = fs[i] } }
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ function session__vote_finish(session_st: mut SessionState) -> void {
|
|||
f.yes = passed
|
||||
}
|
||||
|
||||
function session__vote_fact(session_st: mut SessionState, what: int) -> SessionFact {
|
||||
function session__vote_fact(session_st: SessionState, what: int) -> SessionFact {
|
||||
let f = session__fact(session_st, what, -1, 0)
|
||||
f.id = session_st.session__vote_id
|
||||
f.kind = session_st.session__vote_kind
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export state SettingsState {
|
|||
sg_defs: []SettingDef = null
|
||||
sg_num: []float = null
|
||||
sg_text: []string = null
|
||||
sg_changes: Queue<SettingChanged> = null
|
||||
sg_changes: Queue<SettingChanged> = sg_changes__new()
|
||||
}
|
||||
|
||||
function sg_init(settings_st: mut SettingsState) -> void {
|
||||
|
|
@ -14,8 +14,7 @@ function sg_init(settings_st: mut SettingsState) -> void {
|
|||
settings_st.sg_text = new []string
|
||||
}
|
||||
|
||||
export function settings_changes(settings_st: mut SettingsState) -> Queue<SettingChanged> {
|
||||
if settings_st.sg_changes == null { settings_st.sg_changes = queue_new("settings.changes") }
|
||||
export function settings_changes(settings_st: SettingsState) -> Queue<SettingChanged> {
|
||||
return settings_st.sg_changes
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +54,7 @@ export function settings_get_int(settings_st: SettingsState, id: int) -> int { r
|
|||
export function settings_get_bool(settings_st: SettingsState, id: int) -> bool { return settings_st.sg_num[id] != 0.0 }
|
||||
export function settings_get_text(settings_st: SettingsState, id: int) -> string { return settings_st.sg_text[id] }
|
||||
|
||||
function sg_changed(settings_st: mut SettingsState, id: int) -> void {
|
||||
function sg_changed(settings_st: SettingsState, id: int) -> void {
|
||||
let c = new SettingChanged
|
||||
c.id = id
|
||||
c.key = settings_st.sg_defs[id].key
|
||||
|
|
@ -93,3 +92,4 @@ export function settings_held(settings_st: SettingsState, id: int, v: float) ->
|
|||
if d.hi >= d.lo and (x < d.lo or x > d.hi) { return d.num }
|
||||
return x
|
||||
}
|
||||
function sg_changes__new() -> Queue<SettingChanged> { return queue_new("settings.changes") }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ program SettingsTest {
|
|||
for i in 0 .. TOY_COUNT { settings_add(settings_st, Toy[i]) }
|
||||
}
|
||||
|
||||
function facts(settings_st: mut SettingsState) -> []SettingChanged { return q_drain(settings_changes(settings_st)) }
|
||||
function facts(settings_st: SettingsState) -> []SettingChanged { return q_drain(settings_changes(settings_st)) }
|
||||
|
||||
test "a registry declares the store, each at its default" (settings_st: mut SettingsState) {
|
||||
declare(settings_st)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export state ShopState {
|
|||
shop_buy_best: float = 0.92
|
||||
shop_sell_new: float = 0.62
|
||||
shop_sell_best: float = 0.85
|
||||
shop_trade_q: Queue<ShopTrade> = null
|
||||
shop_trade_q: Queue<ShopTrade> = shop_trade_q__new()
|
||||
}
|
||||
|
||||
# the curve: buying from `buy_new` of base at rep 0 down to `buy_best` at 100; selling the same way
|
||||
|
|
@ -106,7 +106,7 @@ export property ShopTrade {
|
|||
}
|
||||
|
||||
|
||||
export function shop_trades(shop_st: mut ShopState) -> Queue<ShopTrade> {
|
||||
if shop_st.shop_trade_q == null { shop_st.shop_trade_q = queue_new("shop.trades") }
|
||||
export function shop_trades(shop_st: ShopState) -> Queue<ShopTrade> {
|
||||
return shop_st.shop_trade_q
|
||||
}
|
||||
function shop_trade_q__new() -> Queue<ShopTrade> { return queue_new("shop.trades") }
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ program ShopTest {
|
|||
shop_reset(shop_st)
|
||||
}
|
||||
|
||||
function trades(shop_st: mut ShopState) -> []ShopTrade { return q_drain(shop_trades(shop_st)) }
|
||||
function trades(shop_st: ShopState) -> []ShopTrade { return q_drain(shop_trades(shop_st)) }
|
||||
|
||||
test "buying takes the price and puts one in the pack, and says so" (shop_st: mut ShopState, shop_test_st: mut ShopTestState) {
|
||||
fresh(shop_st, shop_test_st)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function shop_sellable(shop_st: ShopState, v: int) -> []int {
|
|||
return out
|
||||
}
|
||||
|
||||
function shop_trade_fact(shop_st: mut ShopState, what: int, it: int, n: int, price: int) -> void {
|
||||
function shop_trade_fact(shop_st: ShopState, what: int, it: int, n: int, price: int) -> void {
|
||||
let t = new ShopTrade
|
||||
t.what = what
|
||||
t.vendor = shop_st.shop_at
|
||||
|
|
@ -41,7 +41,7 @@ export function shop_can_buy(shop_st: ShopState, it: int) -> bool {
|
|||
}
|
||||
|
||||
# one, paid for and in the pack; false and nothing spent when it cannot be
|
||||
export function shop_buy(shop_st: mut ShopState, it: int) -> bool {
|
||||
export function shop_buy(shop_st: ShopState, it: int) -> bool {
|
||||
if not shop_can_buy(shop_st, it) { return false }
|
||||
let pr = shop_price_buy(shop_st, it)
|
||||
if not ShopPurse.spend(pr) { return false }
|
||||
|
|
|
|||
|
|
@ -56,15 +56,14 @@ export state StepsState {
|
|||
steps__need: []int = null
|
||||
steps__cur: int = 0
|
||||
steps__done: int = 0
|
||||
steps__facts: Queue<StepsFact> = null
|
||||
steps__facts: Queue<StepsFact> = steps__facts__new()
|
||||
}
|
||||
|
||||
export function steps_facts(steps_st: mut StepsState) -> Queue<StepsFact> {
|
||||
if steps_st.steps__facts == null { steps_st.steps__facts = queue_new("steps.facts") }
|
||||
export function steps_facts(steps_st: StepsState) -> Queue<StepsFact> {
|
||||
return steps_st.steps__facts
|
||||
}
|
||||
|
||||
function steps__fact(steps_st: mut StepsState, what: int, ch: int, i: int) -> void {
|
||||
function steps__fact(steps_st: StepsState, what: int, ch: int, i: int) -> void {
|
||||
let f = new StepsFact
|
||||
f.what = what
|
||||
f.chapter = ch
|
||||
|
|
@ -81,3 +80,4 @@ export function steps_popcount(m: int) -> int {
|
|||
}
|
||||
return n
|
||||
}
|
||||
function steps__facts__new() -> Queue<StepsFact> { return queue_new("steps.facts") }
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ program StepsTest {
|
|||
steps_add(steps_st, K_COMPASS, 0, 1)
|
||||
}
|
||||
|
||||
function facts_of(steps_st: mut StepsState, what: int) -> int {
|
||||
function facts_of(steps_st: StepsState, what: int) -> int {
|
||||
let fs = q_drain(steps_facts(steps_st))
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
# ports.ludic - the config, and what the ports answer when the game leaves them unbound
|
||||
export function telemetry_config(telemetry_st: mut TelemetryState, c: TelemetryConfig) -> void { telemetry_st.telemetry__cfg = c }
|
||||
|
||||
function telemetry__conf(telemetry_st: mut TelemetryState) -> TelemetryConfig {
|
||||
if telemetry_st.telemetry__cfg == null { telemetry_st.telemetry__cfg = new TelemetryConfig }
|
||||
function telemetry__conf(telemetry_st: TelemetryState) -> TelemetryConfig {
|
||||
return telemetry_st.telemetry__cfg
|
||||
}
|
||||
|
||||
|
|
@ -10,7 +9,7 @@ function telemetry__yes() -> bool { return true }
|
|||
function telemetry__wall_ms(telemetry_st: TelemetryState) -> int { return (Time.now() - telemetry_st.telemetry__t0) * 1000 }
|
||||
function telemetry__wall_stamp() -> string { return DateTime.format(Time.now(), "YYYY-MM-DDTHH:mm:ssZ") }
|
||||
|
||||
function telemetry__can_send(telemetry_st: mut TelemetryState) -> bool {
|
||||
function telemetry__can_send(telemetry_st: TelemetryState) -> bool {
|
||||
let c = telemetry__conf(telemetry_st)
|
||||
if len(c.host) == 0 or len(c.key) == 0 { return false }
|
||||
return TelemetryWorld.can_send()
|
||||
|
|
@ -40,7 +39,7 @@ function telemetry__http_poll(h: int) -> int {
|
|||
|
||||
function telemetry__http_drop(h: int) -> void { Http.free(h) }
|
||||
|
||||
function telemetry__send(telemetry_st: mut TelemetryState, body: string) -> int { return TelemetryTransport.send(telemetry__conf(telemetry_st).host + telemetry__conf(telemetry_st).path, body) }
|
||||
function telemetry__send(telemetry_st: TelemetryState, body: string) -> int { return TelemetryTransport.send(telemetry__conf(telemetry_st).host + telemetry__conf(telemetry_st).path, body) }
|
||||
function telemetry__poll(h: int) -> int { return TelemetryTransport.poll(h) }
|
||||
|
||||
# a request abandoned (the player said no)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
export function telemetry_id(telemetry_st: TelemetryState) -> string { return telemetry_st.telemetry__id }
|
||||
export function telemetry_session(telemetry_st: TelemetryState) -> string { return telemetry_st.telemetry__session }
|
||||
export function telemetry_ready(telemetry_st: TelemetryState) -> bool { return telemetry_st.telemetry__ready }
|
||||
export function telemetry_get_config(telemetry_st: mut TelemetryState) -> TelemetryConfig { return telemetry__conf(telemetry_st) }
|
||||
export function telemetry_get_config(telemetry_st: TelemetryState) -> TelemetryConfig { return telemetry__conf(telemetry_st) }
|
||||
export function telemetry_fails(telemetry_st: TelemetryState) -> int { return telemetry_st.telemetry__fails }
|
||||
export function telemetry_next_ms(telemetry_st: TelemetryState) -> int { return telemetry_st.telemetry__next_ms }
|
||||
export function telemetry_in_flight(telemetry_st: TelemetryState) -> bool { return telemetry_st.telemetry__h >= 0 }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export function telemetry_start(telemetry_st: mut TelemetryState) -> void {
|
|||
}
|
||||
|
||||
# may an event be kept right now?
|
||||
export function telemetry_on(telemetry_st: mut TelemetryState) -> bool { return telemetry_st.telemetry__ready and telemetry__enabled() and telemetry__can_send(telemetry_st) }
|
||||
export function telemetry_on(telemetry_st: TelemetryState) -> bool { return telemetry_st.telemetry__ready and telemetry__enabled() and telemetry__can_send(telemetry_st) }
|
||||
|
||||
# an event: the properties (null for none) with the session and the library added, and the player
|
||||
# as a mark put in when the batch goes, so an event queued before the id is known is not misfiled
|
||||
|
|
@ -77,7 +77,7 @@ function telemetry__queue_drop(telemetry_st: mut TelemetryState, n: int) -> void
|
|||
}
|
||||
|
||||
# the batch: the first n lines joined, with the player id put in - no parsing
|
||||
export function telemetry_batch_body(telemetry_st: mut TelemetryState, n: int) -> string {
|
||||
export function telemetry_batch_body(telemetry_st: TelemetryState, n: int) -> string {
|
||||
let part = new []string
|
||||
for i in 0 .. n { push(part, telemetry_st.telemetry__q[i]) }
|
||||
let head = Value.object()
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export state TelemetryState {
|
|||
telemetry__proc_t0: int = 0
|
||||
telemetry__rand_n: int = 0
|
||||
telemetry__clock_on: bool = false
|
||||
telemetry__cfg: TelemetryConfig = null
|
||||
telemetry__cfg: TelemetryConfig = new TelemetryConfig
|
||||
telemetry__ready: bool = false
|
||||
telemetry__id: string = ""
|
||||
telemetry__session: string = ""
|
||||
|
|
@ -64,15 +64,14 @@ export state TelemetryState {
|
|||
telemetry__saved_ms: int = 0 # when the queue was last put on disk
|
||||
telemetry__fails: int = 0 # sends failed in a row
|
||||
telemetry__t0: int = 0 # the default clock's zero, wall seconds
|
||||
telemetry__facts: Queue<TelemetryFact> = null
|
||||
telemetry__facts: Queue<TelemetryFact> = telemetry__facts__new()
|
||||
}
|
||||
|
||||
export function telemetry_facts(telemetry_st: mut TelemetryState) -> Queue<TelemetryFact> {
|
||||
if telemetry_st.telemetry__facts == null { telemetry_st.telemetry__facts = queue_new("telemetry.facts") }
|
||||
export function telemetry_facts(telemetry_st: TelemetryState) -> Queue<TelemetryFact> {
|
||||
return telemetry_st.telemetry__facts
|
||||
}
|
||||
|
||||
function telemetry__fact(telemetry_st: mut TelemetryState, what: int, count: int, status: int, retry: int) -> void {
|
||||
function telemetry__fact(telemetry_st: TelemetryState, what: int, count: int, status: int, retry: int) -> void {
|
||||
let f = new TelemetryFact
|
||||
f.what = what
|
||||
f.count = count
|
||||
|
|
@ -80,3 +79,4 @@ function telemetry__fact(telemetry_st: mut TelemetryState, what: int, count: int
|
|||
f.retry_ms = retry
|
||||
q_push(telemetry_facts(telemetry_st), f)
|
||||
}
|
||||
function telemetry__facts__new() -> Queue<TelemetryFact> { return queue_new("telemetry.facts") }
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ program TelemetryTest {
|
|||
telemetry_tick(telemetry_st)
|
||||
}
|
||||
|
||||
function facts_of(telemetry_st: mut TelemetryState, what: int) -> int {
|
||||
function facts_of(telemetry_st: TelemetryState, what: int) -> int {
|
||||
let fs = q_drain(telemetry_facts(telemetry_st))
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export function thing_prompt(t: Thing) -> string {
|
|||
}
|
||||
|
||||
# the kind does what using it does; the use is a fact whatever the kind made of it
|
||||
export function thing_use(things_st: mut ThingsState, t: Thing) -> void {
|
||||
export function thing_use(things_st: ThingsState, t: Thing) -> void {
|
||||
if t == null or not thing_kind_ok(t.kind) { return }
|
||||
let k = ThingKinds[t.kind]
|
||||
th_fact(things_st, THING_USED, t)
|
||||
|
|
@ -46,7 +46,7 @@ export function thing_is_personal(t: Thing) -> bool { return thing_kind_ok(t.kin
|
|||
export function thing_is_put_down(t: Thing) -> bool { return ThingsWorld.put_down(t) }
|
||||
|
||||
# every active Thing whose kind ticks, `hours` of the world's clock on
|
||||
export function things_tick(things_st: mut ThingsState, hours: float) -> void {
|
||||
export function things_tick(things_st: ThingsState, hours: float) -> void {
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) {
|
||||
let t = all[i]
|
||||
|
|
@ -58,7 +58,7 @@ export function things_tick(things_st: mut ThingsState, hours: float) -> void {
|
|||
|
||||
# a restock: every Thing the world grew is back, and loses its `used` unless its kind keeps it;
|
||||
# what was put down is left as it is
|
||||
export function things_restock(things_st: mut ThingsState) -> void {
|
||||
export function things_restock(things_st: ThingsState) -> void {
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) {
|
||||
let t = all[i]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
function th_of(t: Thing, kind: int) -> bool { return kind < 0 or t.kind == kind }
|
||||
|
||||
# the first active one of a kind (and of that id, unless id < 0), in the order placed
|
||||
export function thing_find(things_st: mut ThingsState, kind: int, id: int) -> Thing {
|
||||
export function thing_find(things_st: ThingsState, kind: int, id: int) -> Thing {
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) {
|
||||
let t = all[i]
|
||||
|
|
@ -12,14 +12,14 @@ export function thing_find(things_st: mut ThingsState, kind: int, id: int) -> Th
|
|||
return null
|
||||
}
|
||||
|
||||
export function thing_by_uid(things_st: mut ThingsState, uid: int) -> Thing {
|
||||
export function thing_by_uid(things_st: ThingsState, uid: int) -> Thing {
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) { if all[i].uid == uid { return all[i] } }
|
||||
return null
|
||||
}
|
||||
|
||||
# the nearest active one of a kind to (x, z), or null
|
||||
export function thing_nearest(things_st: mut ThingsState, kind: int, x: float, z: float) -> Thing {
|
||||
export function thing_nearest(things_st: ThingsState, kind: int, x: float, z: float) -> Thing {
|
||||
var best: Thing = null
|
||||
var bd = 0.0
|
||||
let all = things_all(things_st)
|
||||
|
|
@ -43,7 +43,7 @@ export function thing_dist2(t: Thing, x: float, z: float) -> float {
|
|||
}
|
||||
|
||||
# every active one within r of (x, z), nearest first
|
||||
export function things_within(things_st: mut ThingsState, x: float, z: float, r: float) -> []Thing {
|
||||
export function things_within(things_st: ThingsState, x: float, z: float, r: float) -> []Thing {
|
||||
let out = new []Thing
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) {
|
||||
|
|
@ -64,7 +64,7 @@ function th_insert(out: []Thing, t: Thing, x: float, z: float) -> void {
|
|||
}
|
||||
|
||||
# every active one of a kind, in the order placed
|
||||
export function things_each(things_st: mut ThingsState, kind: int) -> []Thing {
|
||||
export function things_each(things_st: ThingsState, kind: int) -> []Thing {
|
||||
let out = new []Thing
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) { if all[i].active and th_of(all[i], kind) { push(out, all[i]) } }
|
||||
|
|
@ -72,7 +72,7 @@ export function things_each(things_st: mut ThingsState, kind: int) -> []Thing {
|
|||
}
|
||||
|
||||
# every one of a kind, active or not
|
||||
export function things_each_all(things_st: mut ThingsState, kind: int) -> []Thing {
|
||||
export function things_each_all(things_st: ThingsState, kind: int) -> []Thing {
|
||||
let out = new []Thing
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) { if th_of(all[i], kind) { push(out, all[i]) } }
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
# store.ludic - the Things, and the only verbs that make, remove, move, show and hide one; each
|
||||
# placing and removing is a fact, and the port is told at once so the game can draw it
|
||||
export state ThingsState {
|
||||
th_list: []Thing = null
|
||||
th_list: []Thing = new []Thing
|
||||
th_uid: int = 0
|
||||
th_facts: Queue<ThingFact> = null
|
||||
th_facts: Queue<ThingFact> = th_facts__new()
|
||||
th_marked: int = -1
|
||||
}
|
||||
|
||||
export function things_facts(things_st: mut ThingsState) -> Queue<ThingFact> {
|
||||
if things_st.th_facts == null { things_st.th_facts = queue_new("things.facts") }
|
||||
export function things_facts(things_st: ThingsState) -> Queue<ThingFact> {
|
||||
return things_st.th_facts
|
||||
}
|
||||
|
||||
function th_fact(things_st: mut ThingsState, what: int, t: Thing) -> void {
|
||||
function th_fact(things_st: ThingsState, what: int, t: Thing) -> void {
|
||||
let f = new ThingFact
|
||||
f.what = what
|
||||
f.uid = t.uid
|
||||
|
|
@ -28,12 +27,11 @@ function th_fact(things_st: mut ThingsState, what: int, t: Thing) -> void {
|
|||
export function things_ready(things_st: ThingsState) -> bool { return things_st.th_list != null }
|
||||
|
||||
# every Thing, in the order placed; the list is the package's, never to be pushed to
|
||||
export function things_all(things_st: mut ThingsState) -> []Thing {
|
||||
if things_st.th_list == null { things_st.th_list = new []Thing }
|
||||
export function things_all(things_st: ThingsState) -> []Thing {
|
||||
return things_st.th_list
|
||||
}
|
||||
|
||||
export function things_count(things_st: mut ThingsState) -> int { return len(things_all(things_st)) }
|
||||
export function things_count(things_st: ThingsState) -> int { return len(things_all(things_st)) }
|
||||
|
||||
# a new world: every Thing forgotten, quietly (the game has already dropped its drawings)
|
||||
export function things_clear(things_st: mut ThingsState) -> void { things_st.th_list = new []Thing }
|
||||
|
|
@ -110,3 +108,4 @@ export function thing_set_active(t: Thing, on: bool) -> void {
|
|||
}
|
||||
export function thing_hide(t: Thing) -> void { thing_set_active(t, false) }
|
||||
export function thing_show(t: Thing) -> void { thing_set_active(t, true) }
|
||||
function th_facts__new() -> Queue<ThingFact> { return queue_new("things.facts") }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# system.ludic - the things as a system: its save section carries every active Thing the port
|
||||
# keeps, by its kind's KEY (so the game may reorder its kinds), and a load puts each back
|
||||
export function things_save(things_st: mut ThingsState) -> Val {
|
||||
export function things_save(things_st: ThingsState) -> Val {
|
||||
let l = Value.list()
|
||||
let all = things_all(things_st)
|
||||
for i in 0 .. len(all) {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ program ThingsTest {
|
|||
bind ThingsWorld { ground: fn hill, placed: fn on_placed, removed: fn on_removed, shown: fn on_shown, restored: fn on_restored }
|
||||
|
||||
function put(things_st: mut ThingsState, kind: int, x: float, z: float) -> Thing { return thing_spawn(things_st, kind, "m", x, 0.0, z, 0.0, 0) }
|
||||
function facts(things_st: mut ThingsState) -> []ThingFact { return q_drain(things_facts(things_st)) }
|
||||
function facts(things_st: ThingsState) -> []ThingFact { return q_drain(things_facts(things_st)) }
|
||||
|
||||
test "a spawn is drawn, numbered and said" (things_st: mut ThingsState, things_test_st: ThingsTestState) {
|
||||
things_clear(things_st)
|
||||
|
|
|
|||
|
|
@ -59,12 +59,12 @@ export state TracksState {
|
|||
tk_read_n: int = 0 # signs read for the first time, of every source
|
||||
tk_yaw: float = 0.0 # the heading of the last sign read
|
||||
tk_has_yaw: bool = false
|
||||
tk_reads: Queue<TrackRead> = null
|
||||
tk_reads: Queue<TrackRead> = tk_reads__new()
|
||||
}
|
||||
|
||||
|
||||
# the facts: every sign read, oldest first
|
||||
export function tracks_reads(tracks_st: mut TracksState) -> Queue<TrackRead> {
|
||||
if tracks_st.tk_reads == null { tracks_st.tk_reads = queue_new("tracks.reads") }
|
||||
export function tracks_reads(tracks_st: TracksState) -> Queue<TrackRead> {
|
||||
return tracks_st.tk_reads
|
||||
}
|
||||
function tk_reads__new() -> Queue<TrackRead> { return queue_new("tracks.reads") }
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ program TracksTest {
|
|||
tracks_reset(tracks_st)
|
||||
}
|
||||
|
||||
function reads(tracks_st: mut TracksState) -> []TrackRead { return q_drain(tracks_reads(tracks_st)) }
|
||||
function reads(tracks_st: TracksState) -> []TrackRead { return q_drain(tracks_reads(tracks_st)) }
|
||||
|
||||
test "a print goes into its kind's ring and is drawn" (tracks_st: mut TracksState, tracks_test_st: mut TracksTestState) {
|
||||
fresh(tracks_st, tracks_test_st)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export state UiState {
|
|||
ca_bare: bool = false
|
||||
cs_pass: int = 0
|
||||
ua_sh: UiSheet = null
|
||||
uc_list: []UiClass = null # filled by the compiler's registrations, before the program's globals
|
||||
uc_list: []UiClass = new []UiClass # filled by the compiler's registrations, before the program's globals
|
||||
cl_alpha: float = 1.0
|
||||
ct_capture: string = ""
|
||||
ct_capture_at: int = -1 # the frame listening began, whose own key started it
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ export property UiClass {
|
|||
seen_lss: string = ""
|
||||
}
|
||||
export function ui_register(ui_st: mut UiState, k: UiClass) -> int {
|
||||
if ui_st.uc_list == null { ui_st.uc_list = new []UiClass }
|
||||
push(ui_st.uc_list, k)
|
||||
return len(ui_st.uc_list)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@ export function update_plan_version(update_st: UpdateState, i: int) -> string {
|
|||
export function update_target(update_st: UpdateState) -> string { return update_st.update__target }
|
||||
export function update_total_bytes(update_st: UpdateState) -> int { return update_st.update__total_bytes }
|
||||
|
||||
function update__path(update_st: mut UpdateState, i: int) -> string { return update_packages(update_st) + update__sep() + update_st.update__files[i] }
|
||||
function update__path(update_st: UpdateState, i: int) -> string { return update_packages(update_st) + update__sep() + update_st.update__files[i] }
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ function update__up(p: string) -> string {
|
|||
# the executable's directory
|
||||
export function update_dir() -> string { return update__up(UpdateWorld.exe()) }
|
||||
|
||||
export function update_root(update_st: mut UpdateState) -> string {
|
||||
export function update_root(update_st: UpdateState) -> string {
|
||||
let c = update__conf(update_st)
|
||||
if len(c.root) > 0 { return c.root }
|
||||
if update__mac() { return update__up(update__up(update_dir())) }
|
||||
|
|
@ -52,7 +52,7 @@ export function update_root(update_st: mut UpdateState) -> string {
|
|||
}
|
||||
|
||||
# where the packages live: never inside a macOS bundle, which is read-only and which apply replaces
|
||||
export function update_packages(update_st: mut UpdateState) -> string {
|
||||
export function update_packages(update_st: UpdateState) -> string {
|
||||
let c = update__conf(update_st)
|
||||
if len(c.packages) > 0 { return c.packages }
|
||||
if update__mac() and len(c.mac_packages) > 0 { return c.mac_packages }
|
||||
|
|
@ -64,7 +64,7 @@ function update__feed_file() -> string {
|
|||
return "releases.win.json"
|
||||
}
|
||||
|
||||
function update__updater(update_st: mut UpdateState) -> string {
|
||||
function update__updater(update_st: UpdateState) -> string {
|
||||
if update__mac() { return update_root(update_st) + "/Contents/MacOS/UpdateMac" }
|
||||
return update_root(update_st) + update__sep() + "Update.exe"
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ export function update_translocated() -> bool {
|
|||
}
|
||||
|
||||
# can this copy update itself? A copy Velopack did not install downloads the game again instead.
|
||||
export function update_installed(update_st: mut UpdateState) -> bool {
|
||||
export function update_installed(update_st: UpdateState) -> bool {
|
||||
if len(update__conf(update_st).root) > 0 { return true }
|
||||
if update_translocated() { return false }
|
||||
if update__mac() { return Fs.exists(update_dir() + "/UpdateMac") }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ property UpdateAsset {
|
|||
}
|
||||
|
||||
# this app's packages in the feed ({"Assets": [{PackageId, Version, Type, FileName, SHA256, Size}]})
|
||||
function update__assets(update_st: mut UpdateState, feed: Val) -> []UpdateAsset {
|
||||
function update__assets(update_st: UpdateState, feed: Val) -> []UpdateAsset {
|
||||
let out = new []UpdateAsset
|
||||
if feed == null or Value.kind(feed) != 6 or Value.has(feed, "Assets") == 0 { return out }
|
||||
let all = Value.get(feed, "Assets")
|
||||
|
|
@ -31,7 +31,7 @@ function update__assets(update_st: mut UpdateState, feed: Val) -> []UpdateAsset
|
|||
# What the feed calls the FULL package of version v. Never built here: Velopack puts the channel in
|
||||
# a macOS name (App-0.3.4-osx-full.nupkg) and not a Windows one, and it is both the name a patch
|
||||
# writes and the name the next update looks for as its base.
|
||||
function update__full_name(update_st: mut UpdateState, as: []UpdateAsset, v: string) -> string {
|
||||
function update__full_name(update_st: UpdateState, as: []UpdateAsset, v: string) -> string {
|
||||
for i in 0 .. len(as) { if not as[i].delta and as[i].ver == v { return as[i].file } }
|
||||
return update__conf(update_st).app_id + "-" + v + "-full.nupkg"
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ function update__newest_full(as: []UpdateAsset) -> int {
|
|||
}
|
||||
|
||||
# the deltas above this version up to the newest, oldest first
|
||||
function update__chain(update_st: mut UpdateState, as: []UpdateAsset, newest: string) -> []UpdateAsset {
|
||||
function update__chain(update_st: UpdateState, as: []UpdateAsset, newest: string) -> []UpdateAsset {
|
||||
let out = new []UpdateAsset
|
||||
let mine = update__conf(update_st).version
|
||||
for i in 0 .. len(as) {
|
||||
|
|
@ -65,7 +65,7 @@ function update__chain(update_st: mut UpdateState, as: []UpdateAsset, newest: st
|
|||
return out
|
||||
}
|
||||
|
||||
function update__fulls_after(update_st: mut UpdateState, as: []UpdateAsset) -> int {
|
||||
function update__fulls_after(update_st: UpdateState, as: []UpdateAsset) -> int {
|
||||
var n = 0
|
||||
for i in 0 .. len(as) { if not as[i].delta and update_newer(as[i].ver, update__conf(update_st).version) { n += 1 } }
|
||||
return n
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export state UpdateState {
|
|||
update__ask_h: int = -1
|
||||
update__latest: string = ""
|
||||
update__notes: Val = null
|
||||
update__cfg: UpdateConfig = null
|
||||
update__cfg: UpdateConfig = new UpdateConfig
|
||||
update__state: int = 0
|
||||
update__err: int = 0
|
||||
update__h: int = -1 # the request
|
||||
|
|
@ -77,22 +77,20 @@ export state UpdateState {
|
|||
update__rate: int = 0 # bytes a second, eased
|
||||
update__rate_t: int = -1
|
||||
update__rate_bytes: int = 0
|
||||
update__facts: Queue<UpdateFact> = null
|
||||
update__facts: Queue<UpdateFact> = update__facts__new()
|
||||
}
|
||||
|
||||
export function update_config(update_st: mut UpdateState, c: UpdateConfig) -> void { update_st.update__cfg = c }
|
||||
|
||||
function update__conf(update_st: mut UpdateState) -> UpdateConfig {
|
||||
if update_st.update__cfg == null { update_st.update__cfg = new UpdateConfig }
|
||||
function update__conf(update_st: UpdateState) -> UpdateConfig {
|
||||
return update_st.update__cfg
|
||||
}
|
||||
|
||||
export function update_facts(update_st: mut UpdateState) -> Queue<UpdateFact> {
|
||||
if update_st.update__facts == null { update_st.update__facts = queue_new("update.facts") }
|
||||
export function update_facts(update_st: UpdateState) -> Queue<UpdateFact> {
|
||||
return update_st.update__facts
|
||||
}
|
||||
|
||||
function update__fact(update_st: mut UpdateState, what: int) -> void {
|
||||
function update__fact(update_st: UpdateState, what: int) -> void {
|
||||
let f = new UpdateFact
|
||||
f.what = what
|
||||
f.error = update_st.update__err
|
||||
|
|
@ -101,3 +99,4 @@ function update__fact(update_st: mut UpdateState, what: int) -> void {
|
|||
f.bytes = update_st.update__total_bytes
|
||||
q_push(update_facts(update_st), f)
|
||||
}
|
||||
function update__facts__new() -> Queue<UpdateFact> { return queue_new("update.facts") }
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ function update__fetch(update_st: mut UpdateState, i: int) -> void {
|
|||
update_st.update__state = UPDATE_FETCH
|
||||
}
|
||||
|
||||
function update__hash_file(update_st: mut UpdateState) -> string {
|
||||
function update__hash_file(update_st: UpdateState) -> string {
|
||||
if len(update__conf(update_st).scratch) > 0 { return update__conf(update_st).scratch }
|
||||
return Os.temp_dir() + "/ludic-update-hash.txt"
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ function update__check(update_st: mut UpdateState, i: int) -> void {
|
|||
}
|
||||
|
||||
# the hash the child wrote: the first line with anything on it
|
||||
function update__hash_read(update_st: mut UpdateState) -> string {
|
||||
function update__hash_read(update_st: UpdateState) -> string {
|
||||
let s = Fs.read_text(update__hash_file(update_st))
|
||||
if s == null { return "" }
|
||||
let lines = Text.split(s, "\n")
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ program UpdateTest {
|
|||
function seed_base() -> void { Fs.write_text(pkgs() + "/Game-1.0.0-osx-full.nupkg", "base") }
|
||||
function plan_of(update_st: mut UpdateState, text: string) -> bool { return update_plan(update_st, Json.parse(text)) }
|
||||
|
||||
function facts_of(update_st: mut UpdateState, what: int) -> int {
|
||||
function facts_of(update_st: UpdateState, what: int) -> int {
|
||||
let fs = q_drain(update_facts(update_st))
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import "ludic.base"
|
|||
program WalletTest {
|
||||
numbers float
|
||||
|
||||
function changes(wallet_st: mut WalletState) -> []MoneyChanged { return q_drain(wallet_changes(wallet_st)) }
|
||||
function waiting(wallet_st: mut WalletState) -> int { return q_len(wallet_changes(wallet_st)) }
|
||||
function changes(wallet_st: WalletState) -> []MoneyChanged { return q_drain(wallet_changes(wallet_st)) }
|
||||
function waiting(wallet_st: WalletState) -> int { return q_len(wallet_changes(wallet_st)) }
|
||||
|
||||
test "earning and spending move the purse, and each says so" (wallet_st: mut WalletState) {
|
||||
wallet_reset(wallet_st)
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@ export property MoneyChanged {
|
|||
|
||||
export state WalletState {
|
||||
wl_money: int = 0
|
||||
wl_changes: Queue<MoneyChanged> = null
|
||||
wl_changes: Queue<MoneyChanged> = wl_changes__new()
|
||||
}
|
||||
|
||||
export function wallet_changes(wallet_st: mut WalletState) -> Queue<MoneyChanged> {
|
||||
if wallet_st.wl_changes == null { wallet_st.wl_changes = queue_new("wallet.changes") }
|
||||
export function wallet_changes(wallet_st: WalletState) -> Queue<MoneyChanged> {
|
||||
return wallet_st.wl_changes
|
||||
}
|
||||
|
||||
|
|
@ -62,3 +61,4 @@ export function wallet_system() -> System {
|
|||
s.load = fn wallet_load
|
||||
return s
|
||||
}
|
||||
function wl_changes__new() -> Queue<MoneyChanged> { return queue_new("wallet.changes") }
|
||||
|
|
|
|||
|
|
@ -74,19 +74,19 @@ export state WeatherState {
|
|||
wx_wet_today: bool = false
|
||||
wx_wet_yesterday: bool = false
|
||||
wx_dice: Rng = null
|
||||
wx_facts: Queue<WeatherFact> = null
|
||||
wx_facts: Queue<WeatherFact> = wx_facts__new()
|
||||
}
|
||||
|
||||
# the facts, oldest first; the game drains them into its notices and sounds
|
||||
export function weather_facts(weather_st: mut WeatherState) -> Queue<WeatherFact> {
|
||||
if weather_st.wx_facts == null { weather_st.wx_facts = queue_new("weather.facts") }
|
||||
export function weather_facts(weather_st: WeatherState) -> Queue<WeatherFact> {
|
||||
return weather_st.wx_facts
|
||||
}
|
||||
|
||||
function wx_fact(weather_st: mut WeatherState, what: int, kind: int, from: int) -> void {
|
||||
function wx_fact(weather_st: WeatherState, what: int, kind: int, from: int) -> void {
|
||||
let f = new WeatherFact
|
||||
f.what = what
|
||||
f.kind = kind
|
||||
f.from = from
|
||||
q_push(weather_facts(weather_st), f)
|
||||
}
|
||||
function wx_facts__new() -> Queue<WeatherFact> { return queue_new("weather.facts") }
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ program WeatherTest {
|
|||
weather_reset(weather_st)
|
||||
}
|
||||
|
||||
function facts(weather_st: mut WeatherState) -> []WeatherFact { return q_drain(weather_facts(weather_st)) }
|
||||
function facts(weather_st: WeatherState) -> []WeatherFact { return q_drain(weather_facts(weather_st)) }
|
||||
function step(weather_st: mut WeatherState, dt: float, gh: float, n: int) -> void { for i in 0 .. n { weather_run(weather_st, dt, gh) } }
|
||||
function count(fs: []WeatherFact, what: int) -> int {
|
||||
var n = 0
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ function wl_come_down(a: WildAnimal, x: float, z: float) -> void {
|
|||
}
|
||||
|
||||
# a circle about home, climbing to its height: the eagle wide and high, the jay low
|
||||
function wl_circle(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> void {
|
||||
function wl_circle(wildlife_st: WildlifeState, a: WildAnimal, dt: float) -> void {
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
a.fly_h = a.fly_h + (8.0 + s.home * 0.12 - a.fly_h) * Math.min(1.0, 0.4 * dt)
|
||||
let r = s.home * 0.5
|
||||
|
|
@ -57,13 +57,13 @@ function wl_circle(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) ->
|
|||
a.bank = 0.35
|
||||
}
|
||||
|
||||
function wl_take_off(wildlife_st: mut WildlifeState, a: WildAnimal, h: float) -> void {
|
||||
function wl_take_off(wildlife_st: WildlifeState, a: WildAnimal, h: float) -> void {
|
||||
a.state = WILD_FLY
|
||||
a.timer = 20.0 + wl_rnd(wildlife_st) * 40.0
|
||||
a.fly_h = Math.max(a.fly_h, h)
|
||||
}
|
||||
|
||||
function wl_land(wildlife_st: mut WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
function wl_land(wildlife_st: WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
a.fly_h = Math.max(0.0, a.fly_h - dt * 3.2)
|
||||
a.speed = s.walk * 0.8
|
||||
|
|
@ -84,7 +84,7 @@ function wl_land(wildlife_st: mut WildlifeState, a: WildAnimal, dh: float, dt: f
|
|||
}
|
||||
|
||||
# on the ground it pecks at seed or takes a drink at the water's edge; it leaves no droppings
|
||||
function wl_perch(wildlife_st: mut WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
function wl_perch(wildlife_st: WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
a.speed = 0.0
|
||||
a.y = WildlifeWorld.ground(a.x, a.z)
|
||||
a.bank = 0.0
|
||||
|
|
|
|||
|
|
@ -28,12 +28,11 @@ export property WildFact {
|
|||
}
|
||||
|
||||
|
||||
export function wildlife_facts(wildlife_st: mut WildlifeState) -> Queue<WildFact> {
|
||||
if wildlife_st.wl_facts == null { wildlife_st.wl_facts = queue_new("wildlife.facts") }
|
||||
export function wildlife_facts(wildlife_st: WildlifeState) -> Queue<WildFact> {
|
||||
return wildlife_st.wl_facts
|
||||
}
|
||||
|
||||
function wl_fact(wildlife_st: mut WildlifeState, what: int, a: WildAnimal) -> WildFact {
|
||||
function wl_fact(wildlife_st: WildlifeState, what: int, a: WildAnimal) -> WildFact {
|
||||
let f = new WildFact
|
||||
f.what = what
|
||||
f.key = a.key
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export function wildlife_tick_ground(wildlife_st: mut WildlifeState, a: WildAnim
|
|||
}
|
||||
|
||||
# a charger close enough comes at the nearest player; true while it is charging
|
||||
function wl_charge(wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dh: float, dt: float) -> bool {
|
||||
function wl_charge(wildlife_st: WildlifeState, a: WildAnimal, np: int, dh: float, dt: float) -> bool {
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
if s.charges and a.state != WILD_CHARGE and dh < WildlifeWorld.charge_reach() and not (a.calm > 0.0) {
|
||||
a.state = WILD_CHARGE
|
||||
|
|
@ -63,7 +63,7 @@ function wl_charge(wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dh: f
|
|||
|
||||
# Four postures read off the alert. Staring is a REACTION, not a condition: each times out and
|
||||
# hands the animal back to its business, and only a fresh rise above `seen` looks up again.
|
||||
function wl_posture(wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dt: float) -> void {
|
||||
function wl_posture(wildlife_st: WildlifeState, a: WildAnimal, np: int, dt: float) -> void {
|
||||
if wl_sp(wildlife_st, a.sp).tame or a.state == WILD_EAT { return }
|
||||
if a.alert > 95.0 {
|
||||
if a.state != WILD_FLEE {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
# lures.ludic - what an animal would walk to: food of its diet, a lure of its diet, a snare it is
|
||||
# small enough for (half the time: a curiosity), within 70 m - 175 m for food while feeding is taught
|
||||
|
||||
function wl_lure_scratch(wildlife_st: mut WildlifeState) -> void {
|
||||
if wildlife_st.wl_ask == null { wildlife_st.wl_ask = new WildLure }
|
||||
if wildlife_st.wl_best == null { wildlife_st.wl_best = new WildLure }
|
||||
function wl_lure_scratch() -> void {
|
||||
}
|
||||
|
||||
function wl_copy_lure(from: WildLure, to: WildLure) -> void {
|
||||
|
|
@ -16,15 +14,15 @@ function wl_copy_lure(from: WildLure, to: WildLure) -> void {
|
|||
to.owner = from.owner
|
||||
}
|
||||
|
||||
function wl_draws(wildlife_st: mut WildlifeState, a: WildAnimal, l: WildLure) -> bool {
|
||||
function wl_draws(wildlife_st: WildlifeState, a: WildAnimal, l: WildLure) -> bool {
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
if l.kind == WILD_SNARE { return s.size <= l.size and wl_rnd(wildlife_st) > 0.5 }
|
||||
return l.diet == s.diet and l.diet != WILD_SEED
|
||||
}
|
||||
|
||||
# the nearest thing set out that draws it, into `wl_best`; false when none does
|
||||
function wl_attraction(wildlife_st: mut WildlifeState, a: WildAnimal) -> bool {
|
||||
wl_lure_scratch(wildlife_st)
|
||||
function wl_attraction(wildlife_st: WildlifeState, a: WildAnimal) -> bool {
|
||||
wl_lure_scratch()
|
||||
var bd = 70.0
|
||||
var got = false
|
||||
let taught = WildlifeWorld.taught()
|
||||
|
|
@ -58,7 +56,7 @@ function wl_seed_scan(wildlife_st: mut WildlifeState, dt: float) -> void {
|
|||
if wildlife_st.wl_seed_t > 0.0 { return }
|
||||
wildlife_st.wl_seed_t = 1.0
|
||||
wildlife_st.wl_seed_any = false
|
||||
wl_lure_scratch(wildlife_st)
|
||||
wl_lure_scratch()
|
||||
for i in 0 .. WildlifeWorld.lures() {
|
||||
if WildlifeWorld.lure(i, wildlife_st.wl_ask) and wildlife_st.wl_ask.kind == WILD_FEED and wildlife_st.wl_ask.diet == WILD_SEED {
|
||||
wildlife_st.wl_seed_any = true
|
||||
|
|
@ -68,9 +66,9 @@ function wl_seed_scan(wildlife_st: mut WildlifeState, dt: float) -> void {
|
|||
}
|
||||
|
||||
# the nearest seed within 120 m, into `wl_best`: the one thing that brings an animal TO you
|
||||
function wl_bird_seed(wildlife_st: mut WildlifeState, a: WildAnimal) -> bool {
|
||||
function wl_bird_seed(wildlife_st: WildlifeState, a: WildAnimal) -> bool {
|
||||
if not wildlife_st.wl_seed_any { return false }
|
||||
wl_lure_scratch(wildlife_st)
|
||||
wl_lure_scratch()
|
||||
var bd = 120.0
|
||||
var got = false
|
||||
for i in 0 .. WildlifeWorld.lures() {
|
||||
|
|
@ -88,7 +86,7 @@ function wl_bird_seed(wildlife_st: mut WildlifeState, a: WildAnimal) -> bool {
|
|||
}
|
||||
|
||||
# it ate what was set out: calm for three game hours, and the game credits whoever left it
|
||||
function wl_ate(wildlife_st: mut WildlifeState, a: WildAnimal, uid: int, owner: int, diet: int) -> void {
|
||||
function wl_ate(wildlife_st: WildlifeState, a: WildAnimal, uid: int, owner: int, diet: int) -> void {
|
||||
a.calm = 180.0
|
||||
a.fed += 1
|
||||
let f = wl_fact(wildlife_st, WILD_FED, a)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# migrate.ludic - each morning the ranges slide toward where the season wants them, and the animals
|
||||
# that live in them are dragged along rather than teleported; an animal keeps inside its own
|
||||
export function wildlife_ranges_migrate(wildlife_st: mut WildlifeState) -> void {
|
||||
export function wildlife_ranges_migrate(wildlife_st: WildlifeState) -> void {
|
||||
let rs = wildlife_ranges(wildlife_st)
|
||||
let w = WildlifeWorld.winterness()
|
||||
for i in 0 .. len(rs) {
|
||||
|
|
@ -24,7 +24,7 @@ export function wildlife_ranges_migrate(wildlife_st: mut WildlifeState) -> void
|
|||
}
|
||||
|
||||
# its home kept inside its range
|
||||
function wl_clamp(wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
||||
function wl_clamp(wildlife_st: WildlifeState, a: WildAnimal) -> void {
|
||||
let r = wildlife_range(wildlife_st, a.rg)
|
||||
if r == null { return }
|
||||
let d = wildlife_range_dist(r, a.home_x, a.home_z)
|
||||
|
|
@ -34,7 +34,7 @@ function wl_clamp(wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
|||
}
|
||||
|
||||
# how many live in range `i`, legends apart
|
||||
export function wildlife_range_alive(wildlife_st: mut WildlifeState, i: int) -> int {
|
||||
export function wildlife_range_alive(wildlife_st: WildlifeState, i: int) -> int {
|
||||
var n = 0
|
||||
let all = wildlife_all(wildlife_st)
|
||||
for k in 0 .. len(all) { if all[k].alive and not all[k].legend and all[k].rg == i { n += 1 } }
|
||||
|
|
@ -42,7 +42,7 @@ export function wildlife_range_alive(wildlife_st: mut WildlifeState, i: int) ->
|
|||
}
|
||||
|
||||
# how many are alive in the whole valley, legends apart
|
||||
export function wildlife_total(wildlife_st: mut WildlifeState) -> int {
|
||||
export function wildlife_total(wildlife_st: WildlifeState) -> int {
|
||||
var n = 0
|
||||
let all = wildlife_all(wildlife_st)
|
||||
for k in 0 .. len(all) { if all[k].alive and not all[k].legend { n += 1 } }
|
||||
|
|
@ -50,7 +50,7 @@ export function wildlife_total(wildlife_st: mut WildlifeState) -> int {
|
|||
}
|
||||
|
||||
# the nearest range of `sp` a player has found, to (x, z), or -1
|
||||
export function wildlife_range_found_near(wildlife_st: mut WildlifeState, sp: int, x: float, z: float) -> int {
|
||||
export function wildlife_range_found_near(wildlife_st: WildlifeState, sp: int, x: float, z: float) -> int {
|
||||
var best = -1
|
||||
var bd = 99999.0
|
||||
let rs = wildlife_ranges(wildlife_st)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
# ranges.ludic - a species keeps to discs placed once, against the ground, 120-700 m out from where
|
||||
# the valley starts; each winters lower, toward the timber, as far down as it summered high
|
||||
|
||||
export function wildlife_ranges(wildlife_st: mut WildlifeState) -> []WildRange {
|
||||
if wildlife_st.wl_ranges == null { wildlife_st.wl_ranges = new []WildRange }
|
||||
export function wildlife_ranges(wildlife_st: WildlifeState) -> []WildRange {
|
||||
return wildlife_st.wl_ranges
|
||||
}
|
||||
|
||||
export function wildlife_range(wildlife_st: mut WildlifeState, i: int) -> WildRange {
|
||||
export function wildlife_range(wildlife_st: WildlifeState, i: int) -> WildRange {
|
||||
if i < 0 or i >= len(wildlife_ranges(wildlife_st)) { return null }
|
||||
return wildlife_ranges(wildlife_st)[i]
|
||||
}
|
||||
|
|
@ -17,7 +16,7 @@ export function wildlife_range_dist(r: WildRange, x: float, z: float) -> float {
|
|||
return Math.sqrt(dx * dx + dz * dz)
|
||||
}
|
||||
|
||||
function wl_range_clashes(wildlife_st: mut WildlifeState, sp: int, x: float, z: float) -> bool {
|
||||
function wl_range_clashes(wildlife_st: WildlifeState, sp: int, x: float, z: float) -> bool {
|
||||
let rs = wildlife_ranges(wildlife_st)
|
||||
for j in 0 .. len(rs) { if rs[j].sp == sp and wildlife_range_dist(rs[j], x, z) < wl_sp(wildlife_st, sp).range * 1.6 { return true } }
|
||||
return false
|
||||
|
|
@ -83,12 +82,12 @@ function wl_pick_winter(r: WildRange) -> void {
|
|||
}
|
||||
|
||||
# a player stood at (x, z): any range they are inside is found
|
||||
export function wildlife_ranges_visit(wildlife_st: mut WildlifeState, x: float, z: float) -> void {
|
||||
export function wildlife_ranges_visit(wildlife_st: WildlifeState, x: float, z: float) -> void {
|
||||
let rs = wildlife_ranges(wildlife_st)
|
||||
for i in 0 .. len(rs) { if not rs[i].found and wildlife_range_dist(rs[i], x, z) < rs[i].r { rs[i].found = true } }
|
||||
}
|
||||
|
||||
function wl_found_apply(wildlife_st: mut WildlifeState) -> void {
|
||||
function wl_found_apply(wildlife_st: WildlifeState) -> void {
|
||||
if wildlife_st.wl_found == null { return }
|
||||
let rs = wildlife_ranges(wildlife_st)
|
||||
for i in 0 .. len(rs) { if i < len(wildlife_st.wl_found) { rs[i].found = wildlife_st.wl_found[i] != 0 } }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# react.ludic - alert (it stops and looks: the window the camera wants), wary (it puts ground between
|
||||
# you without running) and fleeing; true when it is doing one of them, which is all it does this tick
|
||||
function wl_react(wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dt: float) -> bool {
|
||||
function wl_react(wildlife_st: WildlifeState, a: WildAnimal, np: int, dt: float) -> bool {
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
if a.state == WILD_ALERT {
|
||||
a.speed = 0.0
|
||||
|
|
@ -29,7 +29,7 @@ function wl_react(wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dt: fl
|
|||
}
|
||||
|
||||
# walking to (or reached) something set out; true while it is
|
||||
function wl_approach(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
function wl_approach(wildlife_st: WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
if (a.state == WILD_IDLE or a.state == WILD_WANDER) and wl_attraction(wildlife_st, a) { wl_take_lure(wildlife_st, a) }
|
||||
if a.state != WILD_APPROACH { return false }
|
||||
if a.lure == 0 or not WildlifeWorld.present(a.lure) {
|
||||
|
|
@ -52,7 +52,7 @@ function wl_approach(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -
|
|||
}
|
||||
|
||||
# at a snare it is held; at food it eats for 14 s; at a lure it stands curious for 9
|
||||
function wl_arrive(wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
||||
function wl_arrive(wildlife_st: WildlifeState, a: WildAnimal) -> void {
|
||||
a.state = WILD_EAT
|
||||
a.timer = 9.0
|
||||
if a.lure_kind == WILD_FEED { a.timer = 14.0 }
|
||||
|
|
@ -67,7 +67,7 @@ function wl_arrive(wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
|||
}
|
||||
|
||||
# eating what it came to; when it is done, food is credited and it wanders off
|
||||
function wl_eat(wildlife_st: mut WildlifeState, a: WildAnimal) -> bool {
|
||||
function wl_eat(wildlife_st: WildlifeState, a: WildAnimal) -> bool {
|
||||
if a.state != WILD_EAT { return false }
|
||||
a.speed = 0.0
|
||||
if a.timer < 0.0 {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ function wl_tick_one(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float, g
|
|||
}
|
||||
|
||||
# the gait advanced by a copy the game moves itself (a guest's copy of the host's animal)
|
||||
export function wildlife_stride(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> void {
|
||||
export function wildlife_stride(wildlife_st: WildlifeState, a: WildAnimal, dt: float) -> void {
|
||||
var stride = 1.2 * a.scale
|
||||
if wl_sp(wildlife_st, a.sp).flies { stride = 0.6 }
|
||||
a.phase = (a.phase + a.speed * dt / stride * WL_TAU) % WL_TAU
|
||||
|
|
@ -48,7 +48,7 @@ export function wildlife_release(a: WildAnimal) -> void {
|
|||
}
|
||||
|
||||
# the animal a snare holds, by the snare's uid
|
||||
export function wildlife_in_snare(wildlife_st: mut WildlifeState, uid: int) -> WildAnimal {
|
||||
export function wildlife_in_snare(wildlife_st: WildlifeState, uid: int) -> WildAnimal {
|
||||
let all = wildlife_all(wildlife_st)
|
||||
for i in 0 .. len(all) {
|
||||
let a = all[i]
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function wl_near_sq(d: float, reach: float) -> float {
|
|||
}
|
||||
|
||||
# alert points a second from player p at `dh` metres; 0 when nothing of them reaches it
|
||||
export function wildlife_alert_rate(wildlife_st: mut WildlifeState, a: WildAnimal, p: int, dh: float) -> float {
|
||||
export function wildlife_alert_rate(wildlife_st: WildlifeState, a: WildAnimal, p: int, dh: float) -> float {
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
if s.tame or a.calm > 0.0 { return 0.0 }
|
||||
if (a.state == WILD_APPROACH or a.state == WILD_EAT) and a.lure != 0 and a.lure_kind == WILD_FEED and dh > 5.0 and WildlifeWorld.taught() { return 0.0 }
|
||||
|
|
@ -65,7 +65,7 @@ export function wildlife_alert_rate(wildlife_st: mut WildlifeState, a: WildAnima
|
|||
}
|
||||
|
||||
# how fast it forgets player p: standing still buys it, sitting down buys more
|
||||
export function wildlife_alert_decay(wildlife_st: mut WildlifeState, a: WildAnimal, p: int) -> float {
|
||||
export function wildlife_alert_decay(wildlife_st: WildlifeState, a: WildAnimal, p: int) -> float {
|
||||
var d = wl_sp(wildlife_st, a.sp).forget
|
||||
let still = WildlifeWorld.stillness(p)
|
||||
if still == WILD_SITTING { d = d * 2.5 } else if still == WILD_STILL { d = d * 1.6 }
|
||||
|
|
@ -74,7 +74,7 @@ export function wildlife_alert_decay(wildlife_st: mut WildlifeState, a: WildAnim
|
|||
}
|
||||
|
||||
# the alert rises and falls with the player who nets it the most, and it watches them
|
||||
function wl_alert(wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dh: float, dt: float) -> void {
|
||||
function wl_alert(wildlife_st: WildlifeState, a: WildAnimal, np: int, dh: float, dt: float) -> void {
|
||||
var rise = wildlife_alert_rate(wildlife_st, a, np, dh)
|
||||
var fall = wildlife_alert_decay(wildlife_st, a, np)
|
||||
var who = np
|
||||
|
|
|
|||
|
|
@ -33,47 +33,47 @@ export property WildSpecies {
|
|||
}
|
||||
|
||||
export state WildlifeState {
|
||||
wl_facts: Queue<WildFact> = null
|
||||
wl_facts: Queue<WildFact> = wl_facts__new()
|
||||
wl_own: []WildAnimal = null
|
||||
wl_px: float = 0.0
|
||||
wl_pz: float = 0.0
|
||||
wl_ask: WildLure = null
|
||||
wl_best: WildLure = null
|
||||
wl_ask: WildLure = new WildLure
|
||||
wl_best: WildLure = new WildLure
|
||||
wl_seed_any: bool = false
|
||||
wl_seed_t: float = 0.0
|
||||
wl_ids: int = 0
|
||||
wl_ranges: []WildRange = null
|
||||
wl_ranges: []WildRange = new []WildRange
|
||||
wl_found: []int = null # found flags a load brought before the ranges were set out
|
||||
wl_seen: int = 0
|
||||
wl_fed: int = 0
|
||||
wl_fed_any: bool = false
|
||||
wl_near_i: int = 0
|
||||
wl_species: []WildSpecies = null
|
||||
wl_list: []WildAnimal = null
|
||||
wl_species: []WildSpecies = new []WildSpecies
|
||||
wl_list: []WildAnimal = new []WildAnimal
|
||||
wl_keys: int = 0
|
||||
wl_dice: Rng = null
|
||||
wl_dice: Rng = rng_new(97)
|
||||
wl_hold: bool = false # staged: nobody thinks, everybody keeps their speed
|
||||
wl_spot_ask: WildSpot = null
|
||||
wl_spot_ask: WildSpot = new WildSpot
|
||||
}
|
||||
|
||||
function wl_sp_all(wildlife_st: mut WildlifeState) -> []WildSpecies {
|
||||
if wildlife_st.wl_species == null { wildlife_st.wl_species = new []WildSpecies }
|
||||
function wl_sp_all(wildlife_st: WildlifeState) -> []WildSpecies {
|
||||
return wildlife_st.wl_species
|
||||
}
|
||||
|
||||
export function wildlife_species_clear(wildlife_st: mut WildlifeState) -> void { wildlife_st.wl_species = new []WildSpecies }
|
||||
|
||||
# the next species; returns its number
|
||||
export function wildlife_species_add(wildlife_st: mut WildlifeState, s: WildSpecies) -> int {
|
||||
export function wildlife_species_add(wildlife_st: WildlifeState, s: WildSpecies) -> int {
|
||||
push(wl_sp_all(wildlife_st), s)
|
||||
return len(wl_sp_all(wildlife_st)) - 1
|
||||
}
|
||||
|
||||
export function wildlife_species_count(wildlife_st: mut WildlifeState) -> int { return len(wl_sp_all(wildlife_st)) }
|
||||
export function wildlife_species_count(wildlife_st: WildlifeState) -> int { return len(wl_sp_all(wildlife_st)) }
|
||||
|
||||
export function wildlife_species(wildlife_st: mut WildlifeState, sp: int) -> WildSpecies {
|
||||
export function wildlife_species(wildlife_st: WildlifeState, sp: int) -> WildSpecies {
|
||||
if sp < 0 or sp >= len(wl_sp_all(wildlife_st)) { return null }
|
||||
return wl_sp_all(wildlife_st)[sp]
|
||||
}
|
||||
|
||||
function wl_sp(wildlife_st: mut WildlifeState, sp: int) -> WildSpecies { return wl_sp_all(wildlife_st)[sp] }
|
||||
function wl_sp(wildlife_st: WildlifeState, sp: int) -> WildSpecies { return wl_sp_all(wildlife_st)[sp] }
|
||||
function wl_facts__new() -> Queue<WildFact> { return queue_new("wildlife.facts") }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ function wl_face(a: WildAnimal, tx: float, tz: float, rate: float, dt: float) ->
|
|||
}
|
||||
|
||||
# true when it moved
|
||||
function wl_step(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
function wl_step(wildlife_st: WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
let d = a.speed * dt
|
||||
if d < 0.0001 { return false }
|
||||
let nx = a.x - Math.sin(a.yaw) * d
|
||||
|
|
@ -36,7 +36,7 @@ function wl_step(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bo
|
|||
return true
|
||||
}
|
||||
|
||||
function wl_pick_target(wildlife_st: mut WildlifeState, a: WildAnimal, radius: float) -> void {
|
||||
function wl_pick_target(wildlife_st: WildlifeState, a: WildAnimal, radius: float) -> void {
|
||||
let ang = wl_rnd(wildlife_st) * WL_TAU
|
||||
let d = wl_rnd(wildlife_st) * radius
|
||||
a.tx = a.home_x + Math.cos(ang) * d
|
||||
|
|
@ -50,14 +50,14 @@ function wl_at_target(a: WildAnimal, r: float) -> bool {
|
|||
}
|
||||
|
||||
# back to wandering about home after `t` seconds of whatever it was doing
|
||||
function wl_wander(wildlife_st: mut WildlifeState, a: WildAnimal, t: float) -> void {
|
||||
function wl_wander(wildlife_st: WildlifeState, a: WildAnimal, t: float) -> void {
|
||||
a.state = WILD_WANDER
|
||||
a.timer = t
|
||||
wl_pick_target(wildlife_st, a, wl_sp(wildlife_st, a.sp).home)
|
||||
}
|
||||
|
||||
# home where it stands now, kept inside its range
|
||||
function wl_rehome(wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
||||
function wl_rehome(wildlife_st: WildlifeState, a: WildAnimal) -> void {
|
||||
a.home_x = a.x
|
||||
a.home_z = a.z
|
||||
wl_clamp(wildlife_st, a)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,23 @@
|
|||
# store.ludic - the animals, their own dice, and the verbs that make and take one away
|
||||
const WL_TAU: float = 6.2831853
|
||||
|
||||
export function wildlife_all(wildlife_st: mut WildlifeState) -> []WildAnimal {
|
||||
if wildlife_st.wl_list == null { wildlife_st.wl_list = new []WildAnimal }
|
||||
export function wildlife_all(wildlife_st: WildlifeState) -> []WildAnimal {
|
||||
return wildlife_st.wl_list
|
||||
}
|
||||
|
||||
export function wildlife_count_all(wildlife_st: mut WildlifeState) -> int { return len(wildlife_all(wildlife_st)) }
|
||||
export function wildlife_count_all(wildlife_st: WildlifeState) -> int { return len(wildlife_all(wildlife_st)) }
|
||||
|
||||
# a new valley: every animal forgotten, quietly (the game has already let its drawings go)
|
||||
export function wildlife_clear(wildlife_st: mut WildlifeState) -> void { wildlife_st.wl_list = new []WildAnimal }
|
||||
|
||||
function wl_rng(wildlife_st: mut WildlifeState) -> Rng {
|
||||
if wildlife_st.wl_dice == null { wildlife_st.wl_dice = rng_new(97) }
|
||||
function wl_rng(wildlife_st: WildlifeState) -> Rng {
|
||||
return wildlife_st.wl_dice
|
||||
}
|
||||
|
||||
function wl_rnd(wildlife_st: mut WildlifeState) -> float { return rng_float(wl_rng(wildlife_st)) }
|
||||
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: mut WildlifeState, seed: int) -> void { rng_seed(wl_rng(wildlife_st), seed) }
|
||||
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 {
|
||||
|
|
@ -76,14 +74,14 @@ export function wildlife_remove(a: WildAnimal) -> void {
|
|||
# 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: mut WildlifeState, nid: int) -> WildAnimal {
|
||||
export function wildlife_by_nid(wildlife_st: WildlifeState, nid: int) -> WildAnimal {
|
||||
let all = wildlife_all(wildlife_st)
|
||||
for i in 0 .. len(all) { if all[i].nid == nid { return all[i] } }
|
||||
return null
|
||||
}
|
||||
|
||||
# how many of a species are alive, legends apart
|
||||
export function wildlife_count(wildlife_st: mut WildlifeState, sp: int) -> int {
|
||||
export function wildlife_count(wildlife_st: WildlifeState, sp: int) -> int {
|
||||
var n = 0
|
||||
let all = wildlife_all(wildlife_st)
|
||||
for i in 0 .. len(all) { if all[i].alive and all[i].sp == sp and not all[i].legend { n += 1 } }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export function wildlife_reset(wildlife_st: mut WildlifeState) -> void {
|
|||
q_clear(wildlife_facts(wildlife_st))
|
||||
}
|
||||
|
||||
export function wildlife_save(wildlife_st: mut WildlifeState) -> Val {
|
||||
export function wildlife_save(wildlife_st: WildlifeState) -> Val {
|
||||
let v = Value.object()
|
||||
sv_put_int(v, "seen", wildlife_st.wl_seen)
|
||||
sv_put_int(v, "fed", wildlife_st.wl_fed)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ function fk_setup(wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut Wi
|
|||
}
|
||||
|
||||
# 0 deer (meadow, tracks, medium), 1 bear (forest, charges), 2 hare (small), 3 jay (flies)
|
||||
function fk_species(wildlife_st: mut WildlifeState) -> void {
|
||||
function fk_species(wildlife_st: WildlifeState) -> void {
|
||||
let d = new WildSpecies
|
||||
d.key = "deer"
|
||||
d.walk = 1.1
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ program LuresTest {
|
|||
spot: fn fk_spot
|
||||
}
|
||||
|
||||
function facts(wildlife_st: mut WildlifeState) -> []WildFact { return q_drain(wildlife_facts(wildlife_st)) }
|
||||
function facts(wildlife_st: WildlifeState) -> []WildFact { return q_drain(wildlife_facts(wildlife_st)) }
|
||||
function set_out(wildlife_tests_fake_st: mut WildlifeTestsFakeState, uid: int, kind: int, diet: int, x: float, z: float, owner: int) -> WildLure {
|
||||
let l = new WildLure
|
||||
l.uid = uid
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue