feat(base): 0.R4 - a queue keeps its own count, so every package verb takes only its own state; ludic migrate state --prune
ludic.base's Queue<T> carries a QueueTag (its name and pending count): queue_new(name), q_push(q, v), q_drain(q), q_clear(q) take no BaseState, and core_undrained(tags) names the given queues still holding facts. A reducer on a package's state can now call that package's verbs (wallet_earn(wallet_st, n)). ludic migrate state --prune (ludicc --migrate-prune) takes out each state parameter a function no longer uses, nor anything it calls, and the argument that fills it - including an argument for a parameter the callee has dropped, which is taken out before the call is checked, so a generic's T is told by the argument that says it. A reducer keeps its state. --dry-run now counts the edits it would make. Every package was moved with it: 608 base_st parameters and their arguments, 1889 edits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
8cf4b3fed6
commit
71735b10a2
151 changed files with 58668 additions and 54719 deletions
|
|
@ -1,14 +1,14 @@
|
|||
# birds.ludic - a bird circles its home at its own height, comes down now and then (for seed from
|
||||
# further off than for nothing), glides in rather than dropping, pecks and drinks, and lifts off
|
||||
export function wildlife_tick_bird(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> void {
|
||||
export function wildlife_tick_bird(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> void {
|
||||
a.timer = a.timer - dt
|
||||
let dh = wl_near(wildlife_st, a.x, a.z)
|
||||
if a.state == WILD_LAND {
|
||||
wl_land(base_st, wildlife_st, a, dh, dt)
|
||||
wl_land(wildlife_st, a, dh, dt)
|
||||
return
|
||||
}
|
||||
if a.state == WILD_PERCH {
|
||||
wl_perch(base_st, wildlife_st, a, dh, dt)
|
||||
wl_perch(wildlife_st, a, dh, dt)
|
||||
return
|
||||
}
|
||||
wl_circle(wildlife_st, a, dt)
|
||||
|
|
@ -63,12 +63,12 @@ function wl_take_off(wildlife_st: mut WildlifeState, a: WildAnimal, h: float) ->
|
|||
a.fly_h = Math.max(a.fly_h, h)
|
||||
}
|
||||
|
||||
function wl_land(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
function wl_land(wildlife_st: mut 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
|
||||
wl_face(a, a.tx, a.tz, 2.4, dt)
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
a.y = WildlifeWorld.ground(a.x, a.z) + a.fly_h
|
||||
a.bank = 0.2 * Math.clamp(a.fly_h / 4.0, 0.0, 1.0)
|
||||
if dh < s.flee or a.timer < -20.0 {
|
||||
|
|
@ -84,14 +84,14 @@ function wl_land(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wild
|
|||
}
|
||||
|
||||
# on the ground it pecks at seed or takes a drink at the water's edge; it leaves no droppings
|
||||
function wl_perch(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
function wl_perch(wildlife_st: mut WildlifeState, a: WildAnimal, dh: float, dt: float) -> void {
|
||||
a.speed = 0.0
|
||||
a.y = WildlifeWorld.ground(a.x, a.z)
|
||||
a.bank = 0.0
|
||||
if wl_bird_seed(wildlife_st, a) and Math.sqrt((wildlife_st.wl_best.x - a.x) * (wildlife_st.wl_best.x - a.x) + (wildlife_st.wl_best.z - a.z) * (wildlife_st.wl_best.z - a.z)) < 3.0 {
|
||||
a.hunger = Math.max(a.hunger - 30.0 * dt, 0.0)
|
||||
a.timer = Math.max(a.timer, 1.0)
|
||||
if wl_rnd(wildlife_st) < 0.12 * dt and WildlifeWorld.present(wildlife_st.wl_best.uid) { wl_ate(base_st, wildlife_st, a, wildlife_st.wl_best.uid, wildlife_st.wl_best.owner, WILD_SEED) }
|
||||
if wl_rnd(wildlife_st) < 0.12 * dt and WildlifeWorld.present(wildlife_st.wl_best.uid) { wl_ate(wildlife_st, a, wildlife_st.wl_best.uid, wildlife_st.wl_best.owner, WILD_SEED) }
|
||||
} else if wl_wet(a.x - Math.sin(a.yaw) * 2.0, a.z - Math.cos(a.yaw) * 2.0, 0.05) {
|
||||
a.thirst = Math.max(a.thirst - 30.0 * dt, 0.0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ export property WildFact {
|
|||
}
|
||||
|
||||
|
||||
export function wildlife_facts(base_st: mut BaseState, wildlife_st: mut WildlifeState) -> Queue<WildFact> {
|
||||
if wildlife_st.wl_facts == null { wildlife_st.wl_facts = queue_new(base_st, "wildlife.facts") }
|
||||
export function wildlife_facts(wildlife_st: mut WildlifeState) -> Queue<WildFact> {
|
||||
if wildlife_st.wl_facts == null { wildlife_st.wl_facts = queue_new("wildlife.facts") }
|
||||
return wildlife_st.wl_facts
|
||||
}
|
||||
|
||||
function wl_fact(base_st: mut BaseState, wildlife_st: mut WildlifeState, what: int, a: WildAnimal) -> WildFact {
|
||||
function wl_fact(wildlife_st: mut WildlifeState, what: int, a: WildAnimal) -> WildFact {
|
||||
let f = new WildFact
|
||||
f.what = what
|
||||
f.key = a.key
|
||||
|
|
@ -44,6 +44,6 @@ function wl_fact(base_st: mut BaseState, wildlife_st: mut WildlifeState, what: i
|
|||
f.z = a.z
|
||||
f.yaw = a.yaw
|
||||
f.scale = a.scale
|
||||
q_push(base_st, wildlife_facts(base_st, wildlife_st), f)
|
||||
q_push(wildlife_facts(wildlife_st), f)
|
||||
return f
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# ground.ludic - a walker's tick: its needs, the alert, then the first of charging, reacting, going
|
||||
# to its spot, walking to something set out, eating, idling and wandering that has it this tick
|
||||
export function wildlife_tick_ground(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dt: float, gh: float) -> void {
|
||||
wl_needs(base_st, wildlife_st, a, gh)
|
||||
export function wildlife_tick_ground(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float, gh: float) -> void {
|
||||
wl_needs(wildlife_st, a, gh)
|
||||
let dh = wl_near(wildlife_st, a.x, a.z)
|
||||
let np = wildlife_st.wl_near_i
|
||||
a.timer = a.timer - dt
|
||||
|
|
@ -12,18 +12,18 @@ export function wildlife_tick_ground(base_st: mut BaseState, wildlife_st: mut Wi
|
|||
a.speed = 0.0
|
||||
return
|
||||
}
|
||||
if wl_charge(base_st, wildlife_st, a, np, dh, dt) { return }
|
||||
wl_posture(base_st, wildlife_st, a, np, dt)
|
||||
if wl_react(base_st, wildlife_st, a, np, dt) { return }
|
||||
if wl_seek(base_st, wildlife_st, a, dt) { return }
|
||||
if wl_charge(wildlife_st, a, np, dh, dt) { return }
|
||||
wl_posture(wildlife_st, a, np, dt)
|
||||
if wl_react(wildlife_st, a, np, dt) { return }
|
||||
if wl_seek(wildlife_st, a, dt) { return }
|
||||
if wl_drink(wildlife_st, a, dt, gh) { return }
|
||||
if wl_approach(base_st, wildlife_st, a, dt) { return }
|
||||
if wl_eat(base_st, wildlife_st, a) { return }
|
||||
if wl_approach(wildlife_st, a, dt) { return }
|
||||
if wl_eat(wildlife_st, a) { return }
|
||||
let s = wl_sp(wildlife_st, a.sp)
|
||||
if a.state == WILD_IDLE {
|
||||
a.speed = 0.0
|
||||
if a.timer < 0.0 {
|
||||
if a.timer > -6.0 and s.tracks and wl_rnd(wildlife_st) < 0.06 { wl_fact(base_st, wildlife_st, WILD_BED, a) } # a long sit leaves crushed grass
|
||||
if a.timer > -6.0 and s.tracks and wl_rnd(wildlife_st) < 0.06 { wl_fact(wildlife_st, WILD_BED, a) } # a long sit leaves crushed grass
|
||||
a.state = WILD_WANDER
|
||||
a.timer = 6.0 + wl_rnd(wildlife_st) * 10.0
|
||||
wl_clamp(wildlife_st, a)
|
||||
|
|
@ -33,7 +33,7 @@ export function wildlife_tick_ground(base_st: mut BaseState, wildlife_st: mut Wi
|
|||
}
|
||||
wl_face(a, a.tx, a.tz, 2.0, dt)
|
||||
a.speed = s.walk
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
if wl_at_target(a, 1.5) or a.timer < 0.0 {
|
||||
a.state = WILD_IDLE
|
||||
a.timer = 3.0 + wl_rnd(wildlife_st) * 8.0
|
||||
|
|
@ -41,19 +41,19 @@ export function wildlife_tick_ground(base_st: mut BaseState, wildlife_st: mut Wi
|
|||
}
|
||||
|
||||
# a charger close enough comes at the nearest player; true while it is charging
|
||||
function wl_charge(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dh: float, dt: float) -> bool {
|
||||
function wl_charge(wildlife_st: mut 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
|
||||
a.timer = 2.5
|
||||
wl_fact(base_st, wildlife_st, WILD_CHARGED, a).player = np
|
||||
wl_fact(wildlife_st, WILD_CHARGED, a).player = np
|
||||
}
|
||||
if a.state != WILD_CHARGE { return false }
|
||||
wl_face(a, WildlifeWorld.player_x(np), WildlifeWorld.player_z(np), 4.0, dt)
|
||||
a.speed = s.run
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
if dh < 2.6 {
|
||||
wl_fact(base_st, wildlife_st, WILD_SHOVED, a).player = np
|
||||
wl_fact(wildlife_st, WILD_SHOVED, a).player = np
|
||||
wl_wander(wildlife_st, a, 8.0)
|
||||
a.calm = 30.0
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ function wl_charge(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wi
|
|||
|
||||
# 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(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dt: float) -> void {
|
||||
function wl_posture(wildlife_st: mut 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 {
|
||||
|
|
@ -71,7 +71,7 @@ function wl_posture(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: W
|
|||
a.timer = 3.0 + wl_rnd(wildlife_st) * 3.0
|
||||
a.spook = 120.0 + wl_rnd(wildlife_st) * 180.0
|
||||
a.alert = 70.0
|
||||
wl_fact(base_st, wildlife_st, WILD_FLED, a).player = np
|
||||
wl_fact(wildlife_st, WILD_FLED, a).player = np
|
||||
}
|
||||
} else if a.alert > 60.0 {
|
||||
if a.state != WILD_WARY and a.state != WILD_FLEE and a.alert > a.seen {
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ 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(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, uid: int, owner: int, diet: int) -> void {
|
||||
function wl_ate(wildlife_st: mut WildlifeState, a: WildAnimal, uid: int, owner: int, diet: int) -> void {
|
||||
a.calm = 180.0
|
||||
a.fed += 1
|
||||
let f = wl_fact(base_st, wildlife_st, WILD_FED, a)
|
||||
let f = wl_fact(wildlife_st, WILD_FED, a)
|
||||
f.lure = uid
|
||||
f.owner = owner
|
||||
f.diet = diet
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# needs.ludic - thirst and hunger climb with the game hours (midday is thirsty work, a run costs more
|
||||
# than a graze, dawn and dusk are when they go down to drink), and a walker leaves droppings
|
||||
function wl_needs(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, gh: float) -> void {
|
||||
function wl_needs(wildlife_st: mut WildlifeState, a: WildAnimal, gh: float) -> void {
|
||||
let h = WildlifeWorld.hour()
|
||||
var thirst = 8.0
|
||||
var hunger = 5.0
|
||||
|
|
@ -18,5 +18,5 @@ function wl_needs(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wil
|
|||
a.scat_t = 120.0 + wl_rnd(wildlife_st) * 300.0
|
||||
wl_near(wildlife_st, a.x, a.z)
|
||||
if wl_pdist(wildlife_st.wl_near_i, a) > 500.0 { return } # further than 500 m from everyone: nobody would find it
|
||||
wl_fact(base_st, wildlife_st, WILD_SCAT, a)
|
||||
wl_fact(wildlife_st, WILD_SCAT, a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, np: int, dt: float) -> bool {
|
||||
function wl_react(wildlife_st: mut 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
|
||||
|
|
@ -11,14 +11,14 @@ function wl_react(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wil
|
|||
if a.state == WILD_WARY {
|
||||
wl_face(a, a.x + (a.x - a.sus_x), a.z + (a.z - a.sus_z), 2.6, dt)
|
||||
a.speed = s.walk * 0.8
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
if a.timer < 0.0 { wl_wander(wildlife_st, a, 3.0 + wl_rnd(wildlife_st) * 4.0) }
|
||||
return true
|
||||
}
|
||||
if a.state == WILD_FLEE {
|
||||
wl_face(a, a.x + (a.x - WildlifeWorld.player_x(np)), a.z + (a.z - WildlifeWorld.player_z(np)), 5.0, dt)
|
||||
a.speed = s.run
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
if a.timer < 0.0 {
|
||||
wl_rehome(wildlife_st, a)
|
||||
wl_wander(wildlife_st, a, 5.0)
|
||||
|
|
@ -29,7 +29,7 @@ function wl_react(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wil
|
|||
}
|
||||
|
||||
# walking to (or reached) something set out; true while it is
|
||||
function wl_approach(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
function wl_approach(wildlife_st: mut 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) {
|
||||
|
|
@ -44,15 +44,15 @@ function wl_approach(base_st: mut BaseState, wildlife_st: mut WildlifeState, a:
|
|||
let dz = a.lure_z - a.z
|
||||
if Math.sqrt(dx * dx + dz * dz) < 1.3 {
|
||||
a.speed = 0.0
|
||||
wl_arrive(base_st, wildlife_st, a)
|
||||
wl_arrive(wildlife_st, a)
|
||||
return true
|
||||
}
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
return true
|
||||
}
|
||||
|
||||
# at a snare it is held; at food it eats for 14 s; at a lure it stands curious for 9
|
||||
function wl_arrive(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
||||
function wl_arrive(wildlife_st: mut WildlifeState, a: WildAnimal) -> void {
|
||||
a.state = WILD_EAT
|
||||
a.timer = 9.0
|
||||
if a.lure_kind == WILD_FEED { a.timer = 14.0 }
|
||||
|
|
@ -61,17 +61,17 @@ function wl_arrive(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wi
|
|||
a.x = a.lure_x
|
||||
a.z = a.lure_z
|
||||
a.y = WildlifeWorld.ground(a.x, a.z)
|
||||
let f = wl_fact(base_st, wildlife_st, WILD_CAUGHT, a)
|
||||
let f = wl_fact(wildlife_st, WILD_CAUGHT, a)
|
||||
f.lure = a.lure
|
||||
f.owner = a.lure_owner
|
||||
}
|
||||
|
||||
# eating what it came to; when it is done, food is credited and it wanders off
|
||||
function wl_eat(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal) -> bool {
|
||||
function wl_eat(wildlife_st: mut WildlifeState, a: WildAnimal) -> bool {
|
||||
if a.state != WILD_EAT { return false }
|
||||
a.speed = 0.0
|
||||
if a.timer < 0.0 {
|
||||
if a.lure != 0 and a.lure_kind == WILD_FEED and WildlifeWorld.present(a.lure) { wl_ate(base_st, wildlife_st, a, a.lure, a.lure_owner, wl_sp(wildlife_st, a.sp).diet) }
|
||||
if a.lure != 0 and a.lure_kind == WILD_FEED and WildlifeWorld.present(a.lure) { wl_ate(wildlife_st, a, a.lure, a.lure_owner, wl_sp(wildlife_st, a.sp).diet) }
|
||||
a.lure = 0
|
||||
wl_wander(wildlife_st, a, 4.0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# run.ludic - one step of every animal: the port says whether it is about at this hour; anything
|
||||
# within 900 m of a player thinks; the gait follows the ground covered; player 0 sees what is near
|
||||
export function wildlife_tick(base_st: mut BaseState, wildlife_st: mut WildlifeState, dt: float, gh: float) -> void {
|
||||
export function wildlife_tick(wildlife_st: mut WildlifeState, dt: float, gh: float) -> void {
|
||||
wl_seed_scan(wildlife_st, dt)
|
||||
let all = wildlife_all(wildlife_st)
|
||||
for i in 0 .. len(all) { wl_tick_one(base_st, wildlife_st, all[i], dt, gh) }
|
||||
for i in 0 .. len(all) { wl_tick_one(wildlife_st, all[i], dt, gh) }
|
||||
}
|
||||
|
||||
function wl_tick_one(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dt: float, gh: float) -> void {
|
||||
function wl_tick_one(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float, gh: float) -> void {
|
||||
if not a.alive { return }
|
||||
let about = WildlifeWorld.about(a)
|
||||
if about == WILD_AWAY {
|
||||
|
|
@ -15,7 +15,7 @@ function wl_tick_one(base_st: mut BaseState, wildlife_st: mut WildlifeState, a:
|
|||
}
|
||||
if about == WILD_GONE {
|
||||
wildlife_remove(a)
|
||||
wl_fact(base_st, wildlife_st, WILD_WENT, a)
|
||||
wl_fact(wildlife_st, WILD_WENT, a)
|
||||
return
|
||||
}
|
||||
a.shown = true
|
||||
|
|
@ -24,11 +24,11 @@ function wl_tick_one(base_st: mut BaseState, wildlife_st: mut WildlifeState, a:
|
|||
let s = wl_sp(wildlife_st, a.sp)
|
||||
if wildlife_st.wl_hold { }
|
||||
else if a.pinned { a.speed = 0.0 }
|
||||
else if s.flies { wildlife_tick_bird(base_st, wildlife_st, a, dt) } else { wildlife_tick_ground(base_st, wildlife_st, a, dt, gh) }
|
||||
else if s.flies { wildlife_tick_bird(wildlife_st, a, dt) } else { wildlife_tick_ground(wildlife_st, a, dt, gh) }
|
||||
var stride = 1.2 * a.scale
|
||||
if s.flies { stride = 0.6 }
|
||||
a.phase = (a.phase + a.speed * dt / stride * WL_TAU) % WL_TAU
|
||||
if WildlifeWorld.player_on(0) and wl_pdist(0, a) < 60.0 and wildlife_saw(wildlife_st, a.sp) { wl_fact(base_st, wildlife_st, WILD_SPOTTED, a) }
|
||||
if WildlifeWorld.player_on(0) and wl_pdist(0, a) < 60.0 and wildlife_saw(wildlife_st, a.sp) { wl_fact(wildlife_st, WILD_SPOTTED, a) }
|
||||
}
|
||||
|
||||
# the gait advanced by a copy the game moves itself (a guest's copy of the host's animal)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ function wl_face(a: WildAnimal, tx: float, tz: float, rate: float, dt: float) ->
|
|||
}
|
||||
|
||||
# true when it moved
|
||||
function wl_step(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
function wl_step(wildlife_st: mut 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
|
||||
|
|
@ -31,7 +31,7 @@ function wl_step(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wild
|
|||
a.track_d = a.track_d + d
|
||||
if wl_sp(wildlife_st, a.sp).tracks and a.track_d > 2.8 {
|
||||
a.track_d = 0.0
|
||||
wl_fact(base_st, wildlife_st, WILD_PRINT, a)
|
||||
wl_fact(wildlife_st, WILD_PRINT, a)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# system.ludic - the wildlife as a system: its save section is this player's record (the species
|
||||
# seen and fed) and which ranges they have found; the animals themselves are respawned with the
|
||||
# valley, so a reset forgets the record and nothing else
|
||||
export function wildlife_reset(base_st: mut BaseState, wildlife_st: mut WildlifeState) -> void {
|
||||
export function wildlife_reset(wildlife_st: mut WildlifeState) -> void {
|
||||
wl_record_reset(wildlife_st)
|
||||
wildlife_st.wl_found = null
|
||||
let rs = wildlife_ranges(wildlife_st)
|
||||
for i in 0 .. len(rs) { rs[i].found = false }
|
||||
q_clear(base_st, wildlife_facts(base_st, wildlife_st))
|
||||
q_clear(wildlife_facts(wildlife_st))
|
||||
}
|
||||
|
||||
export function wildlife_save(wildlife_st: mut WildlifeState) -> Val {
|
||||
|
|
@ -25,8 +25,8 @@ export function wildlife_save(wildlife_st: mut WildlifeState) -> Val {
|
|||
return v
|
||||
}
|
||||
|
||||
export function wildlife_load(base_st: mut BaseState, wildlife_st: mut WildlifeState, v: Val, version: int) -> void {
|
||||
wildlife_reset(base_st, wildlife_st)
|
||||
export function wildlife_load(wildlife_st: mut WildlifeState, v: Val, version: int) -> void {
|
||||
wildlife_reset(wildlife_st)
|
||||
wildlife_st.wl_seen = sv_int(v, "seen", 0)
|
||||
wildlife_st.wl_fed = sv_int(v, "fed", 0)
|
||||
wildlife_st.wl_fed_any = sv_bool(v, "fed_any", false)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ program LuresTest {
|
|||
spot: fn fk_spot
|
||||
}
|
||||
|
||||
function facts(base_st: mut BaseState, wildlife_st: mut WildlifeState) -> []WildFact { return q_drain(base_st, wildlife_facts(base_st, wildlife_st)) }
|
||||
function facts(wildlife_st: mut 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
|
||||
|
|
@ -36,16 +36,16 @@ program LuresTest {
|
|||
a.timer = 30.0
|
||||
return a
|
||||
}
|
||||
function go(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, secs: float) -> void {
|
||||
for k in 0 .. int(secs * 20.0) { wildlife_tick_ground(base_st, wildlife_st, a, 0.05, 0.05 / 60.0) }
|
||||
function go(wildlife_st: mut WildlifeState, a: WildAnimal, secs: float) -> void {
|
||||
for k in 0 .. int(secs * 20.0) { wildlife_tick_ground(wildlife_st, a, 0.05, 0.05 / 60.0) }
|
||||
}
|
||||
|
||||
test "food of its diet draws it in, it eats, and the fact names what and whose" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "food of its diet draws it in, it eats, and the fact names what and whose" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
set_out(wildlife_tests_fake_st, 41, WILD_FEED, WILD_PLANTS, 20.0, 0.0, 3)
|
||||
let a = idle(wildlife_st, 0, 0.0, 0.0)
|
||||
go(base_st, wildlife_st, a, 40.0)
|
||||
let fs = facts(base_st, wildlife_st)
|
||||
go(wildlife_st, a, 40.0)
|
||||
let fs = facts(wildlife_st)
|
||||
var fed = 0
|
||||
for i in 0 .. len(fs) {
|
||||
if fs[i].what == WILD_FED {
|
||||
|
|
@ -58,38 +58,38 @@ program LuresTest {
|
|||
expect(a.calm > 0.0)
|
||||
}
|
||||
|
||||
test "food of another diet is left alone" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "food of another diet is left alone" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
set_out(wildlife_tests_fake_st, 41, WILD_FEED, WILD_FISH, 20.0, 0.0, -1)
|
||||
let a = idle(wildlife_st, 0, 0.0, 0.0)
|
||||
go(base_st, wildlife_st, a, 5.0)
|
||||
go(wildlife_st, a, 5.0)
|
||||
expect(a.state != WILD_APPROACH)
|
||||
expect_eq(a.lure, 0)
|
||||
}
|
||||
|
||||
test "food taken away while it walks is given up" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "food taken away while it walks is given up" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
set_out(wildlife_tests_fake_st, 41, WILD_FEED, WILD_PLANTS, 50.0, 0.0, -1)
|
||||
let a = idle(wildlife_st, 0, 0.0, 0.0)
|
||||
go(base_st, wildlife_st, a, 1.0)
|
||||
go(wildlife_st, a, 1.0)
|
||||
expect_eq(a.state, WILD_APPROACH)
|
||||
wildlife_tests_fake_st.fk_gone = 41
|
||||
go(base_st, wildlife_st, a, 0.2)
|
||||
go(wildlife_st, a, 0.2)
|
||||
expect(a.state != WILD_APPROACH)
|
||||
}
|
||||
|
||||
test "a snare holds a small animal, the port can find it, and a release lets it go" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "a snare holds a small animal, the port can find it, and a release lets it go" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let l = set_out(wildlife_tests_fake_st, 55, WILD_SNARE, 0, 10.0, 0.0, -1)
|
||||
l.size = 0
|
||||
let h = idle(wildlife_st, 2, 0.0, 0.0)
|
||||
for k in 0 .. 40 {
|
||||
if h.state == WILD_TRAPPED { break }
|
||||
go(base_st, wildlife_st, h, 2.0)
|
||||
go(wildlife_st, h, 2.0)
|
||||
}
|
||||
expect_eq(h.state, WILD_TRAPPED)
|
||||
expect(wildlife_in_snare(wildlife_st, 55) == h)
|
||||
let fs = facts(base_st, wildlife_st)
|
||||
let fs = facts(wildlife_st)
|
||||
var held = false
|
||||
for i in 0 .. len(fs) { if fs[i].what == WILD_CAUGHT and fs[i].lure == 55 { held = true } }
|
||||
expect(held)
|
||||
|
|
@ -98,19 +98,19 @@ program LuresTest {
|
|||
expect(wildlife_in_snare(wildlife_st, 55) == null)
|
||||
}
|
||||
|
||||
test "a thirsty animal walks to the water the port offers, and drinks it down" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "a thirsty animal walks to the water the port offers, and drinks it down" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = idle(wildlife_st, 0, 0.0, 0.0)
|
||||
a.thirst = 90.0
|
||||
a.state = WILD_WANDER
|
||||
go(base_st, wildlife_st, a, 0.1)
|
||||
go(wildlife_st, a, 0.1)
|
||||
expect_eq(a.state, WILD_GO_DRINK)
|
||||
expect_eq(a.spot, 900)
|
||||
go(base_st, wildlife_st, a, 40.0)
|
||||
go(wildlife_st, a, 40.0)
|
||||
expect(a.thirst < 60.0)
|
||||
}
|
||||
|
||||
test "seed down brings a bird out of the sky and it takes it" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "seed down brings a bird out of the sky and it takes it" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
set_out(wildlife_tests_fake_st, 77, WILD_FEED, WILD_SEED, 30.0, 0.0, -1)
|
||||
let j = wildlife_new(wildlife_st, 3, 0.0, 0.0, false)
|
||||
|
|
@ -119,9 +119,9 @@ program LuresTest {
|
|||
var landed = false
|
||||
var ate = false
|
||||
for k in 0 .. 4000 {
|
||||
wildlife_tick(base_st, wildlife_st, 0.05, 0.0)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.0)
|
||||
if j.state == WILD_PERCH { landed = true }
|
||||
let fs = facts(base_st, wildlife_st)
|
||||
let fs = facts(wildlife_st)
|
||||
for i in 0 .. len(fs) { if fs[i].what == WILD_FED and fs[i].diet == WILD_SEED { ate = true } }
|
||||
if ate { break }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ program WildlifeTest {
|
|||
spot: fn fk_spot
|
||||
}
|
||||
|
||||
function facts(base_st: mut BaseState, wildlife_st: mut WildlifeState) -> []WildFact { return q_drain(base_st, wildlife_facts(base_st, wildlife_st)) }
|
||||
function facts(wildlife_st: mut WildlifeState) -> []WildFact { return q_drain(wildlife_facts(wildlife_st)) }
|
||||
function count(fs: []WildFact, what: int) -> int {
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
|
|
@ -47,8 +47,8 @@ program WildlifeTest {
|
|||
wildlife_tests_fake_st.fk_px[0] = x
|
||||
wildlife_tests_fake_st.fk_pz[0] = z
|
||||
}
|
||||
function go(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, secs: float) -> void {
|
||||
for k in 0 .. int(secs * 20.0) { wildlife_tick_ground(base_st, wildlife_st, a, 0.05, 0.05 / 60.0) }
|
||||
function go(wildlife_st: mut WildlifeState, a: WildAnimal, secs: float) -> void {
|
||||
for k in 0 .. int(secs * 20.0) { wildlife_tick_ground(wildlife_st, a, 0.05, 0.05 / 60.0) }
|
||||
}
|
||||
|
||||
test "the table handed in numbers the species, and a new animal is born through the port" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
|
|
@ -79,24 +79,24 @@ program WildlifeTest {
|
|||
expect_eq(wildlife_count_all(wildlife_st), wildlife_count(wildlife_st, 0) + wildlife_count(wildlife_st, 1) + wildlife_count(wildlife_st, 2) + wildlife_count(wildlife_st, 3))
|
||||
}
|
||||
|
||||
test "a player far off makes no difference that lasts: the alert settles under the unaware line" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "a player far off makes no difference that lasts: the alert settles under the unaware line" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = deer_at(wildlife_st, 0.0, 0.0)
|
||||
player_at(wildlife_tests_fake_st, 55.0, 0.0)
|
||||
wildlife_tests_fake_st.fk_noise = 0.3
|
||||
go(base_st, wildlife_st, a, 60.0)
|
||||
go(wildlife_st, a, 60.0)
|
||||
expect(a.alert < 25.0)
|
||||
expect(a.state != WILD_FLEE)
|
||||
}
|
||||
|
||||
test "close and in the open it is flushed, runs, and says so" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "close and in the open it is flushed, runs, and says so" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = deer_at(wildlife_st, 0.0, 0.0)
|
||||
player_at(wildlife_tests_fake_st, 8.0, 0.0)
|
||||
wildlife_tests_fake_st.fk_noise = 0.8
|
||||
go(base_st, wildlife_st, a, 10.0)
|
||||
go(wildlife_st, a, 10.0)
|
||||
expect(a.spook > 0.0)
|
||||
let fs = facts(base_st, wildlife_st)
|
||||
let fs = facts(wildlife_st)
|
||||
expect(count(fs, WILD_FLED) >= 1)
|
||||
expect(a.x < 0.0)
|
||||
}
|
||||
|
|
@ -135,33 +135,33 @@ program WildlifeTest {
|
|||
expect_near(wildlife_alert_rate(wildlife_st, a, 0, 60.0), 0.0, 0.0001)
|
||||
}
|
||||
|
||||
test "a charger comes at a player inside its reach, and a shove is a fact for the game" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "a charger comes at a player inside its reach, and a shove is a fact for the game" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let b = wildlife_make(wildlife_st, 1, 0.0, 0.0, false, 0.0, 0, 1.0, 2)
|
||||
player_at(wildlife_tests_fake_st, 6.0, 0.0)
|
||||
wildlife_tick_ground(base_st, wildlife_st, b, 0.05, 0.001)
|
||||
wildlife_tick_ground(wildlife_st, b, 0.05, 0.001)
|
||||
expect_eq(b.state, WILD_CHARGE)
|
||||
go(base_st, wildlife_st, b, 2.0)
|
||||
let fs = facts(base_st, wildlife_st)
|
||||
go(wildlife_st, b, 2.0)
|
||||
let fs = facts(wildlife_st)
|
||||
expect_eq(count(fs, WILD_CHARGED), 1)
|
||||
expect_eq(count(fs, WILD_SHOVED), 1)
|
||||
expect(b.calm > 0.0)
|
||||
}
|
||||
|
||||
test "away is hidden and skipped, gone is removed and said" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "away is hidden and skipped, gone is removed and said" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = deer_at(wildlife_st, 0.0, 0.0)
|
||||
player_at(wildlife_tests_fake_st, 10.0, 0.0)
|
||||
wildlife_tests_fake_st.fk_about = WILD_AWAY
|
||||
wildlife_tick(base_st, wildlife_st, 0.05, 0.001)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.001)
|
||||
expect(not a.shown and a.alive)
|
||||
wildlife_tests_fake_st.fk_about = WILD_GONE
|
||||
wildlife_tick(base_st, wildlife_st, 0.05, 0.001)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.001)
|
||||
expect(not a.alive)
|
||||
expect_eq(count(facts(base_st, wildlife_st), WILD_WENT), 1)
|
||||
expect_eq(count(facts(wildlife_st), WILD_WENT), 1)
|
||||
}
|
||||
|
||||
test "a walker leaves a print every 2.8 m, and player 0 spots a species once" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "a walker leaves a print every 2.8 m, and player 0 spots a species once" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = deer_at(wildlife_st, 0.0, 0.0)
|
||||
player_at(wildlife_tests_fake_st, 40.0, 0.0)
|
||||
|
|
@ -170,14 +170,14 @@ program WildlifeTest {
|
|||
a.tx = 0.0
|
||||
a.tz = -100.0
|
||||
a.timer = 100.0
|
||||
for k in 0 .. 200 { wildlife_tick(base_st, wildlife_st, 0.05, 0.0) }
|
||||
let fs = facts(base_st, wildlife_st)
|
||||
for k in 0 .. 200 { wildlife_tick(wildlife_st, 0.05, 0.0) }
|
||||
let fs = facts(wildlife_st)
|
||||
expect(count(fs, WILD_PRINT) >= 3)
|
||||
expect_eq(count(fs, WILD_SPOTTED), 1)
|
||||
expect(wildlife_seen(wildlife_st, 0))
|
||||
}
|
||||
|
||||
test "the record and the found ranges come back from the save section" (base_st: mut BaseState, wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
test "the record and the found ranges come back from the save section" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
wildlife_spawn(wildlife_st, 0.0, 0.0)
|
||||
wildlife_mark_fed(wildlife_st, 2)
|
||||
|
|
@ -185,9 +185,9 @@ program WildlifeTest {
|
|||
let r = wildlife_ranges(wildlife_st)[0]
|
||||
wildlife_ranges_visit(wildlife_st, r.x, r.z)
|
||||
let v = wildlife_save(wildlife_st)
|
||||
wildlife_reset(base_st, wildlife_st)
|
||||
wildlife_reset(wildlife_st)
|
||||
expect(not wildlife_fed_any(wildlife_st) and not wildlife_ranges(wildlife_st)[0].found)
|
||||
wildlife_load(base_st, wildlife_st, v, 1)
|
||||
wildlife_load(wildlife_st, v, 1)
|
||||
expect(wildlife_fed_any(wildlife_st))
|
||||
expect_eq(wildlife_fed_mask(wildlife_st), 4)
|
||||
expect(wildlife_seen(wildlife_st, 0))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# want.ludic - thirst and hunger over sixty send it to the water or the forage the game offers for
|
||||
# it (a hungry one on its way turns to food put down nearer); it drinks or grazes there
|
||||
|
||||
function wl_seek(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
function wl_seek(wildlife_st: mut WildlifeState, a: WildAnimal, dt: float) -> bool {
|
||||
if a.state == WILD_GO_FEED and wl_attraction(wildlife_st, a) and wildlife_st.wl_best.kind == WILD_FEED { wl_take_lure(wildlife_st, a) }
|
||||
if a.state != WILD_GO_DRINK and a.state != WILD_GO_FEED { return false }
|
||||
if a.spot == 0 or not WildlifeWorld.present(a.spot) {
|
||||
|
|
@ -14,7 +14,7 @@ function wl_seek(base_st: mut BaseState, wildlife_st: mut WildlifeState, a: Wild
|
|||
a.speed = wl_sp(wildlife_st, a.sp).walk
|
||||
a.tx = a.spot_x
|
||||
a.tz = a.spot_z
|
||||
wl_step(base_st, wildlife_st, a, dt)
|
||||
wl_step(wildlife_st, a, dt)
|
||||
if wl_at_target(a, 2.0) {
|
||||
a.state = WILD_DRINK
|
||||
a.timer = 6.0 + wl_rnd(wildlife_st) * 10.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue