ludic.wildlife: pin every transition of the 15 WILD_* states and the dice each draws (phase 27.2a)
Sixteen test programs under tests/*_pins_test.ludic, on today's code, each one tick from a set state through the public step (wildlife_tick_ground / _bird / wildlife_tick, wildlife_release, wildlife_new): the state it goes to, its timer, and how many of the package's rolls it took and which (the next roll is read off a newborn's yaw, compared with a stream of the same seed). IDLE, WANDER, ALERT, WARY, FLEE, CHARGE, GO_DRINK, GO_FEED, DRINK, APPROACH, EAT, TRAPPED, FLY, LAND, PERCH; the droppings' roll before them; the newborn's seven (eight for a bird); what the step leaves alone. tests/pin/ holds the shared step, the dice reader and two species of its own (a tame horse, a crow that never lands on its own). Compiled, not run here: 27.2 holds to them unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d7adc28125
commit
67d477af77
19 changed files with 1521 additions and 0 deletions
83
packages/ludic.wildlife/tests/approach_pins_test.ludic
Normal file
83
packages/ludic.wildlife/tests/approach_pins_test.ludic
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# approach_pins_test.ludic - phase 27.2a: APPROACH as it stands. Its lure gone, IDLE 2 s; within
|
||||
# 1.3 m it EATs - 14 s at food, 9 at a lure - or a snare holds it (TRAPPED where the snare is, a
|
||||
# CAUGHT fact); no roll on any of it
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program ApproachPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function coming(wildlife_st: mut WildlifeState, kind: int, lure_x: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_APPROACH, 5.0)
|
||||
a.lure = 50
|
||||
a.lure_kind = kind
|
||||
a.lure_x = lure_x
|
||||
a.lure_z = 0.0
|
||||
a.lure_owner = 3
|
||||
wildlife_seed(wildlife_st, 13)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "APPROACH, its lure gone: IDLE 2 s, the lure let go" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
wildlife_tests_fake_st.fk_gone = 50
|
||||
let a = coming(wildlife_st, WILD_FEED, 20.0)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.timer, 2.0, 0.0001)
|
||||
expect_eq(a.lure, 0)
|
||||
expect_eq(pn_drew(wildlife_st, 13), 0)
|
||||
}
|
||||
|
||||
test "APPROACH on its way: walks at its walk, the timer untouched by arriving" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = coming(wildlife_st, WILD_FEED, 20.0)
|
||||
expect_eq(a.state, WILD_APPROACH)
|
||||
expect_near(a.speed, 1.0, 0.0001)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 13), 0)
|
||||
}
|
||||
|
||||
test "APPROACH within 1.3 m: EAT 14 s at food, 9 s at a lure" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = coming(wildlife_st, WILD_FEED, 1.0)
|
||||
expect_eq(a.state, WILD_EAT)
|
||||
expect_near(a.timer, 14.0, 0.0001)
|
||||
expect_near(a.speed, 0.0, 0.00001)
|
||||
let b = coming(wildlife_st, WILD_LURE, 1.0)
|
||||
expect_eq(b.state, WILD_EAT)
|
||||
expect_near(b.timer, 9.0, 0.0001)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_FED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 13), 0)
|
||||
}
|
||||
|
||||
test "APPROACH within 1.3 m of a snare: TRAPPED on the snare, CAUGHT with the snare and its owner" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = coming(wildlife_st, WILD_SNARE, 1.0)
|
||||
expect_eq(a.state, WILD_TRAPPED)
|
||||
expect_near(a.x, 1.0, 0.0001)
|
||||
expect_near(a.z, 0.0, 0.0001)
|
||||
expect_near(a.y, 10.0, 0.0001)
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_CAUGHT), 1)
|
||||
expect_eq(fs[0].lure, 50)
|
||||
expect_eq(fs[0].owner, 3)
|
||||
expect_eq(pn_drew(wildlife_st, 13), 0)
|
||||
}
|
||||
}
|
||||
83
packages/ludic.wildlife/tests/bird_pins_test.ludic
Normal file
83
packages/ludic.wildlife/tests/bird_pins_test.ludic
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# bird_pins_test.ludic - phase 27.2a: a bird aloft as it stands (the jay: comes down whenever it can;
|
||||
# the crow: never on its own). Its timer up with nobody within its land_shy it rolls a spot (x, z) and
|
||||
# its land_chance, and comes down (LAND, 30 s); else it moves its home by two rolls and circles 30 s
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program BirdPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function aloft(wildlife_st: mut WildlifeState, sp: int, timer: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, sp, 0.0, 0.0, WILD_FLY, timer)
|
||||
wildlife_seed(wildlife_st, 16)
|
||||
pn_fly(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "FLY before its time: circles on, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = aloft(wildlife_st, 3, 5.0)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 16), 0)
|
||||
}
|
||||
|
||||
test "FLY, its time up, nobody near: LAND at (x + 24 (r0 - 0.5), z + 24 (r1 - 0.5)) for 30 s, r2 its chance" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = aloft(wildlife_st, 3, 0.01)
|
||||
expect_eq(a.state, WILD_LAND)
|
||||
expect_near(a.timer, 30.0, 0.0001)
|
||||
expect_near(a.tx, a.x + (pn_roll(16, 0) - 0.5) * 24.0, 0.001)
|
||||
expect_near(a.tz, a.z + (pn_roll(16, 1) - 0.5) * 24.0, 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 16), 3)
|
||||
}
|
||||
|
||||
test "FLY, its time up, somebody within land_shy: no landing roll; home moves by 120 (r0 - 0.5), 30 s" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 0.0, 0.0)
|
||||
let a = aloft(wildlife_st, 3, 0.01)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_near(a.timer, 30.0, 0.0001)
|
||||
expect_near(a.home_x, (pn_roll(16, 0) - 0.5) * 120.0, 0.001)
|
||||
expect_near(a.home_z, (pn_roll(16, 1) - 0.5) * 120.0, 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 16), 2)
|
||||
}
|
||||
|
||||
test "FLY, its time up, the chance failed: five rolls - spot, spot, chance, then home by r3, r4" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = aloft(wildlife_st, 5, 0.01)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_near(a.timer, 30.0, 0.0001)
|
||||
expect_near(a.home_x, (pn_roll(16, 3) - 0.5) * 120.0, 0.001)
|
||||
expect_near(a.home_z, (pn_roll(16, 4) - 0.5) * 120.0, 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 16), 5)
|
||||
}
|
||||
|
||||
test "a bird made as given starts IDLE and circles on as IDLE" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = wildlife_make(wildlife_st, 3, 0.0, 0.0, false, 0.0, 0, 1.0, 1)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
a.timer = 5.0
|
||||
wildlife_seed(wildlife_st, 16)
|
||||
pn_fly(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect(a.fly_h > 0.0)
|
||||
expect_eq(pn_drew(wildlife_st, 16), 0)
|
||||
}
|
||||
}
|
||||
91
packages/ludic.wildlife/tests/born_pins_test.ludic
Normal file
91
packages/ludic.wildlife/tests/born_pins_test.ludic
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# born_pins_test.ludic - phase 27.2a: where an animal's day starts, and what gates its tick, as they
|
||||
# stand. A newborn walker is IDLE, a newborn bird FLY, off seven and eight rolls in a set order; the
|
||||
# step (wildlife_tick) leaves alone one lying up, gone, pinned, held, or 900 m from everyone
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program BornPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
test "a newborn walker: IDLE; yaw, coat, size, thirst, hunger, droppings, timer - seven rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
wildlife_seed(wildlife_st, 19)
|
||||
let a = wildlife_new(wildlife_st, 2, 0.0, 0.0, false)
|
||||
let r = rng_new(19)
|
||||
rng_next(r)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.yaw, pn_roll(19, 0) * 6.2831853, 0.00001)
|
||||
expect_eq(a.variant, rng_next(r) % 12)
|
||||
expect_near(a.scale, 0.88 + pn_roll(19, 2) * 0.24, 0.00001)
|
||||
expect_near(a.thirst, pn_roll(19, 3) * 50.0, 0.0001)
|
||||
expect_near(a.hunger, pn_roll(19, 4) * 50.0, 0.0001)
|
||||
expect_near(a.scat_t, 40.0 + pn_roll(19, 5) * 180.0, 0.001)
|
||||
expect_near(a.timer, pn_roll(19, 6) * 6.0, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 19), 7)
|
||||
}
|
||||
|
||||
test "a newborn bird: FLY, its height 10 + 20 r6 before the timer - eight rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
wildlife_seed(wildlife_st, 19)
|
||||
let a = wildlife_new(wildlife_st, 3, 0.0, 0.0, false)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_near(a.fly_h, 10.0 + 20.0 * pn_roll(19, 6), 0.0001)
|
||||
expect_near(a.timer, pn_roll(19, 7) * 6.0, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 19), 8)
|
||||
}
|
||||
|
||||
test "wildlife_tick within 900 m steps it (IDLE, time up: WANDER); beyond, nothing moves and nothing rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_IDLE, 0.0)
|
||||
wildlife_seed(wildlife_st, 20)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.05 / 60.0)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.timer, 0.0, 0.00001)
|
||||
pn_player(wildlife_tests_fake_st, 100.0, 0.0)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.05 / 60.0)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_eq(pn_drew(wildlife_st, 20), 3)
|
||||
}
|
||||
|
||||
test "lying up, pinned or held: its state and timer kept, no roll; gone: removed with a WENT fact" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 100.0, 0.0)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_IDLE, 0.0)
|
||||
a.speed = 3.0
|
||||
wildlife_seed(wildlife_st, 20)
|
||||
wildlife_tests_fake_st.fk_about = WILD_AWAY
|
||||
wildlife_tick(wildlife_st, 0.05, 0.05 / 60.0)
|
||||
expect(not a.shown)
|
||||
wildlife_tests_fake_st.fk_about = WILD_ABOUT
|
||||
wildlife_hold(wildlife_st, true)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.05 / 60.0)
|
||||
expect_near(a.speed, 3.0, 0.00001)
|
||||
wildlife_hold(wildlife_st, false)
|
||||
a.pinned = true
|
||||
wildlife_tick(wildlife_st, 0.05, 0.05 / 60.0)
|
||||
expect_near(a.speed, 0.0, 0.00001)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.timer, 0.0, 0.00001)
|
||||
wildlife_tests_fake_st.fk_about = WILD_GONE
|
||||
wildlife_tick(wildlife_st, 0.05, 0.05 / 60.0)
|
||||
expect(not a.alive)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_WENT), 1)
|
||||
expect_eq(pn_drew(wildlife_st, 20), 0)
|
||||
}
|
||||
}
|
||||
93
packages/ludic.wildlife/tests/charge_pins_test.ludic
Normal file
93
packages/ludic.wildlife/tests/charge_pins_test.ludic
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# charge_pins_test.ludic - phase 27.2a: CHARGE as it stands (the bear). Anyone within the charge
|
||||
# reach (9 m) of a charger that is not calm is charged from any state but TRAPPED, before the alert
|
||||
# is read; within 2.6 m it shoves and wanders off calm; its 2.5 s up it wanders and may charge again
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program ChargePins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function bear(wildlife_st: mut WildlifeState, state: int, timer: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 1, 0.0, 0.0, state, timer)
|
||||
wildlife_seed(wildlife_st, 4)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "IDLE, FLEE and EAT, somebody within 9 m: CHARGE for 2.5 s, a CHARGED fact, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 5.0, 0.0)
|
||||
let states = [WILD_IDLE, WILD_FLEE, WILD_EAT]
|
||||
for i in 0 .. 3 {
|
||||
let a = bear(wildlife_st, states[i], 5.0)
|
||||
expect_eq(a.state, WILD_CHARGE)
|
||||
expect_near(a.timer, 2.5, 0.0001)
|
||||
expect_near(a.speed, 6.0, 0.0001)
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_CHARGED), 1)
|
||||
expect_eq(fs[0].player, 0)
|
||||
expect_eq(pn_drew(wildlife_st, 4), 0)
|
||||
}
|
||||
}
|
||||
|
||||
test "CHARGE within 2.6 m: SHOVED, WANDER 8 s toward (r0, r1), calm 30 min" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 2.0, 0.0)
|
||||
let a = bear(wildlife_st, WILD_CHARGE, 2.0)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 8.0, 0.0001)
|
||||
expect_near(a.calm, 30.0, 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, 4, 0, 60.0), 0.001)
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_SHOVED), 1)
|
||||
expect_eq(pn_count(fs, WILD_CHARGED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 4), 2)
|
||||
}
|
||||
|
||||
test "CHARGE, its 2.5 s up short of anyone: WANDER 6 s, two rolls, not calm - and the next tick charges again" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 5.0, 0.0)
|
||||
let a = bear(wildlife_st, WILD_CHARGE, 0.01)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 6.0, 0.0001)
|
||||
expect_near(a.calm, 0.0, 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, 4, 0, 60.0), 0.001)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_CHARGE)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_CHARGED), 1)
|
||||
expect_eq(pn_drew(wildlife_st, 4), 2)
|
||||
}
|
||||
|
||||
test "no charge from a calm bear, from beyond 9 m, or out of a snare; no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 5.0, 0.0)
|
||||
let a = pn_at(wildlife_st, 1, 0.0, 0.0, WILD_IDLE, 5.0)
|
||||
a.calm = 30.0
|
||||
wildlife_seed(wildlife_st, 4)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
let t = bear(wildlife_st, WILD_TRAPPED, 5.0)
|
||||
expect_eq(t.state, WILD_TRAPPED)
|
||||
pn_player(wildlife_tests_fake_st, 9.5, 0.0)
|
||||
let b = bear(wildlife_st, WILD_IDLE, 5.0)
|
||||
expect_eq(b.state, WILD_IDLE)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_CHARGED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 4), 0)
|
||||
}
|
||||
}
|
||||
80
packages/ludic.wildlife/tests/drink_pins_test.ludic
Normal file
80
packages/ludic.wildlife/tests/drink_pins_test.ludic
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# drink_pins_test.ludic - phase 27.2a: DRINK as it stands. It drinks (a water spot) or grazes at
|
||||
# 600 a game hour, its timer run down twice a tick; its time up - or EITHER need under 1, not only
|
||||
# the one it is meeting - it takes home where it stands and wanders 6 s toward (r0, r1)
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program DrinkPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function drinking(wildlife_st: mut WildlifeState, water: bool, thirst: float, hunger: float, timer: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 2, 3.0, 0.0, WILD_DRINK, timer)
|
||||
a.spot = 900
|
||||
a.spot_water = water
|
||||
a.thirst = thirst
|
||||
a.hunger = hunger
|
||||
wildlife_seed(wildlife_st, 10)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "DRINK at water: thirst down 600 a game hour, the timer 2 dt a tick, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = drinking(wildlife_st, true, 50.0, 50.0, 5.0)
|
||||
expect_eq(a.state, WILD_DRINK)
|
||||
expect_near(a.timer, 4.9, 0.0001)
|
||||
expect_near(a.speed, 0.0, 0.00001)
|
||||
expect_near(a.thirst, 50.0 + 12.0 * 0.05 / 60.0 - 0.5, 0.0001)
|
||||
expect_near(a.hunger, 50.0 + 5.0 * 0.05 / 60.0, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 10), 0)
|
||||
}
|
||||
|
||||
test "DRINK at forage grazes hunger down instead" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = drinking(wildlife_st, false, 50.0, 50.0, 5.0)
|
||||
expect_near(a.hunger, 50.0 + 5.0 * 0.05 / 60.0 - 0.5, 0.0001)
|
||||
expect_near(a.thirst, 50.0 + 12.0 * 0.05 / 60.0, 0.0001)
|
||||
}
|
||||
|
||||
test "DRINK, its time up: home where it stands, WANDER 6 s toward (r0, r1), two rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let b = pn_at(wildlife_st, 2, 3.0, 0.0, WILD_DRINK, 0.05)
|
||||
b.spot = 900
|
||||
b.spot_water = true
|
||||
b.home_x = 50.0
|
||||
b.thirst = 50.0
|
||||
b.hunger = 50.0
|
||||
wildlife_seed(wildlife_st, 10)
|
||||
pn_step(wildlife_st, b)
|
||||
expect_eq(b.state, WILD_WANDER)
|
||||
expect_near(b.timer, 6.0, 0.0001)
|
||||
expect_near(b.home_x, 3.0, 0.0001)
|
||||
expect_near(b.tx, pn_tx(b, 10, 0, 60.0), 0.001)
|
||||
expect_near(b.tz, pn_tz(b, 10, 0, 60.0), 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 10), 2)
|
||||
}
|
||||
|
||||
test "DRINK at water with hunger under 1: it leaves thirsty, WANDER 6 s, two rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = drinking(wildlife_st, true, 80.0, 0.0, 5.0)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect(a.thirst > 79.0)
|
||||
expect_eq(pn_drew(wildlife_st, 10), 2)
|
||||
}
|
||||
}
|
||||
94
packages/ludic.wildlife/tests/eat_pins_test.ludic
Normal file
94
packages/ludic.wildlife/tests/eat_pins_test.ludic
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# eat_pins_test.ludic - phase 27.2a: EAT and TRAPPED as they stand. Eating done, food still there is
|
||||
# credited (FED, calm 180 game minutes) and it wanders 4 s toward (r0, r1); a snare holds it through
|
||||
# anything the tick asks, and only a release lets it go - FLEE 4 s, holding nothing against anyone
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program EatPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function eating(wildlife_st: mut WildlifeState, kind: int, timer: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_EAT, timer)
|
||||
a.lure = 50
|
||||
a.lure_kind = kind
|
||||
a.lure_owner = 3
|
||||
wildlife_seed(wildlife_st, 14)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "EAT at food, its time up: FED with the food and its owner, calm 180, WANDER 4 s, two rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = eating(wildlife_st, WILD_FEED, 0.01)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 4.0, 0.0001)
|
||||
expect_near(a.calm, 180.0, 0.0001)
|
||||
expect_eq(a.fed, 1)
|
||||
expect_eq(a.lure, 0)
|
||||
expect_near(a.tx, pn_tx(a, 14, 0, 60.0), 0.001)
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_FED), 1)
|
||||
expect_eq(fs[0].lure, 50)
|
||||
expect_eq(fs[0].owner, 3)
|
||||
expect_eq(fs[0].diet, WILD_PLANTS)
|
||||
expect_eq(pn_drew(wildlife_st, 14), 2)
|
||||
}
|
||||
|
||||
test "EAT done at a lure, or the food gone: WANDER 4 s, nothing credited" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = eating(wildlife_st, WILD_LURE, 0.01)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.calm, 0.0, 0.0001)
|
||||
wildlife_tests_fake_st.fk_gone = 50
|
||||
let b = eating(wildlife_st, WILD_FEED, 0.01)
|
||||
expect_eq(b.state, WILD_WANDER)
|
||||
expect_eq(b.fed, 0)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_FED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 14), 2)
|
||||
}
|
||||
|
||||
test "EAT before its time: stands eating, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = eating(wildlife_st, WILD_FEED, 5.0)
|
||||
expect_eq(a.state, WILD_EAT)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 14), 0)
|
||||
}
|
||||
|
||||
test "TRAPPED holds through an alert over 95 and a thirst over 60; a release: FLEE 4 s, calm 0, lure 0" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_TRAPPED, 0.01)
|
||||
a.lure = 60
|
||||
a.alert = 97.0
|
||||
a.thirst = 90.0
|
||||
a.calm = 10.0
|
||||
a.speed = 2.0
|
||||
wildlife_seed(wildlife_st, 14)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_TRAPPED)
|
||||
expect_near(a.speed, 0.0, 0.00001)
|
||||
expect(wildlife_in_snare(wildlife_st, 60) == a)
|
||||
expect_eq(pn_drew(wildlife_st, 14), 0)
|
||||
wildlife_release(a)
|
||||
expect_eq(a.state, WILD_FLEE)
|
||||
expect_near(a.timer, 4.0, 0.0001)
|
||||
expect_near(a.calm, 0.0, 0.0001)
|
||||
expect_eq(a.lure, 0)
|
||||
}
|
||||
}
|
||||
85
packages/ludic.wildlife/tests/flee_pins_test.ludic
Normal file
85
packages/ludic.wildlife/tests/flee_pins_test.ludic
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# flee_pins_test.ludic - phase 27.2a: FLEE as it stands. Over 95 it bolts (3 + 3 r0 s, spooked for
|
||||
# 120 + 180 r1 game minutes, the alert dropped to 70, a FLED fact); fleeing it is not re-entered; its
|
||||
# time up it takes home where it stands and wanders 5 s; a fresh rise over 25 looks up mid-flight
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program FleePins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
test "IDLE, alert over 95: FLEE, then the spook; two rolls in that order" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_IDLE, 5.0)
|
||||
a.alert = 97.0
|
||||
wildlife_seed(wildlife_st, 5)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_FLEE)
|
||||
expect_near(a.timer, 3.0 + 3.0 * pn_roll(5, 0), 0.0001)
|
||||
expect_near(a.spook, 120.0 + 180.0 * pn_roll(5, 1), 0.001)
|
||||
expect_near(a.alert, 70.0, 0.0001)
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_FLED), 1)
|
||||
expect_eq(fs[0].player, 0)
|
||||
expect_eq(pn_drew(wildlife_st, 5), 2)
|
||||
}
|
||||
|
||||
test "FLEE, alert still over 95: no second flight, no fact, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_FLEE, 5.0)
|
||||
a.alert = 97.0
|
||||
wildlife_seed(wildlife_st, 5)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_FLEE)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect(a.alert > 95.0)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_FLED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 5), 0)
|
||||
}
|
||||
|
||||
test "FLEE, its time up: home where it stands, WANDER 5 s toward (r0, r1) about it" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_FLEE, 0.01)
|
||||
wildlife_seed(wildlife_st, 5)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 5.0, 0.0001)
|
||||
expect_near(a.home_x, a.x, 0.0001)
|
||||
expect_near(a.home_z, a.z, 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, 5, 0, 60.0), 0.001)
|
||||
expect_near(a.tz, pn_tz(a, 5, 0, 60.0), 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 5), 2)
|
||||
}
|
||||
|
||||
test "FLEE, a fresh alert between 25 and 60: ALERT mid-flight, one roll (WARY never interrupts it)" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_FLEE, 5.0)
|
||||
a.alert = 40.0
|
||||
wildlife_seed(wildlife_st, 5)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_ALERT)
|
||||
expect_near(a.timer, 1.5 + 2.5 * pn_roll(5, 0), 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 5), 1)
|
||||
let b = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_FLEE, 5.0)
|
||||
b.alert = 70.0
|
||||
wildlife_seed(wildlife_st, 5)
|
||||
pn_step(wildlife_st, b)
|
||||
expect_eq(b.state, WILD_FLEE)
|
||||
expect_eq(pn_drew(wildlife_st, 5), 0)
|
||||
}
|
||||
}
|
||||
89
packages/ludic.wildlife/tests/go_pins_test.ludic
Normal file
89
packages/ludic.wildlife/tests/go_pins_test.ludic
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# go_pins_test.ludic - phase 27.2a: GO_DRINK / GO_FEED as they stand. Within 2 m of the spot it
|
||||
# DRINKs for 6 + 10 r0 s; the spot gone, IDLE 2 s; its timer runs down twice a tick and gives up at
|
||||
# -600 (IDLE 3 s); a hungry one turns to food of its diet nearer - unless a nearer snare wins the roll
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program GoPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function going(wildlife_st: mut WildlifeState, state: int, spot_x: float, timer: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, state, timer)
|
||||
a.spot = 900
|
||||
a.spot_x = spot_x
|
||||
a.spot_water = state == WILD_GO_DRINK
|
||||
wildlife_seed(wildlife_st, 8)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "GO_DRINK within 2 m: DRINK for 6 + 10 r0 s, less one more tick taken at once" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = going(wildlife_st, WILD_GO_DRINK, 1.0, 120.0)
|
||||
expect_eq(a.state, WILD_DRINK)
|
||||
expect_near(a.timer, 6.0 + 10.0 * pn_roll(8, 0) - 0.05, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 8), 1)
|
||||
}
|
||||
|
||||
test "on the way: the timer runs down 2 dt a tick; the spot gone: IDLE 2 s; past -600: IDLE 3 s" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = going(wildlife_st, WILD_GO_DRINK, 30.0, 10.0)
|
||||
expect_eq(a.state, WILD_GO_DRINK)
|
||||
expect_near(a.timer, 9.9, 0.0001)
|
||||
let b = going(wildlife_st, WILD_GO_FEED, 30.0, -599.95)
|
||||
expect_eq(b.state, WILD_IDLE)
|
||||
expect_near(b.timer, 3.0, 0.0001)
|
||||
wildlife_tests_fake_st.fk_gone = 900
|
||||
let c = going(wildlife_st, WILD_GO_DRINK, 30.0, 10.0)
|
||||
expect_eq(c.state, WILD_IDLE)
|
||||
expect_near(c.timer, 2.0, 0.0001)
|
||||
expect_eq(c.spot, 0)
|
||||
expect_eq(pn_drew(wildlife_st, 8), 0)
|
||||
}
|
||||
|
||||
test "GO_FEED, food of its diet nearer: APPROACH it (the spot kept); GO_DRINK does not turn" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 50, WILD_FEED, WILD_PLANTS, 5.0, 0.0)
|
||||
let a = going(wildlife_st, WILD_GO_FEED, 30.0, 100.0)
|
||||
expect_eq(a.state, WILD_APPROACH)
|
||||
expect_eq(a.lure, 50)
|
||||
expect_eq(a.lure_kind, WILD_FEED)
|
||||
expect_eq(a.lure_owner, 3)
|
||||
expect_eq(a.spot, 900)
|
||||
let b = going(wildlife_st, WILD_GO_DRINK, 30.0, 100.0)
|
||||
expect_eq(b.state, WILD_GO_DRINK)
|
||||
expect_eq(b.lure, 0)
|
||||
expect_eq(pn_drew(wildlife_st, 8), 0)
|
||||
}
|
||||
|
||||
test "GO_FEED, a snare nearer than the food: r0 > 0.5 draws it to the snare, which masks the food" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 60, WILD_SNARE, 0, 3.0, 0.0)
|
||||
pn_lure(wildlife_tests_fake_st, 50, WILD_FEED, WILD_PLANTS, 5.0, 0.0)
|
||||
for seed in 1 .. 17 {
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_GO_FEED, 100.0)
|
||||
a.spot = 900
|
||||
a.spot_x = 30.0
|
||||
wildlife_seed(wildlife_st, seed)
|
||||
pn_step(wildlife_st, a)
|
||||
if pn_roll(seed, 0) > 0.5 { expect_eq(a.state, WILD_GO_FEED) } else { expect_eq(a.lure, 50) }
|
||||
expect_eq(pn_drew(wildlife_st, seed), 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
80
packages/ludic.wildlife/tests/guard_pins_test.ludic
Normal file
80
packages/ludic.wildlife/tests/guard_pins_test.ludic
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# guard_pins_test.ludic - phase 27.2a: which states the alert reaches as it stands. EATING and a
|
||||
# tame kind ignore it; going to water, drinking and walking to food do not - they bolt with the spot
|
||||
# or the lure still held
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program GuardPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function spooked(wildlife_st: mut WildlifeState, sp: int, state: int, alert: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, sp, 10.0, 0.0, state, 5.0)
|
||||
a.alert = alert
|
||||
a.spot = 900
|
||||
a.spot_x = 40.0
|
||||
a.spot_water = true
|
||||
a.lure = 50
|
||||
a.lure_kind = WILD_FEED
|
||||
a.lure_x = 30.0
|
||||
a.thirst = 50.0
|
||||
a.hunger = 50.0
|
||||
wildlife_seed(wildlife_st, 2)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "EAT, alert over 95: still eating, no fact, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = spooked(wildlife_st, 2, WILD_EAT, 97.0)
|
||||
expect_eq(a.state, WILD_EAT)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_FLED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 2), 0)
|
||||
}
|
||||
|
||||
test "a tame kind, alert over 95: IDLE still, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = spooked(wildlife_st, 4, WILD_IDLE, 97.0)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_eq(pn_drew(wildlife_st, 2), 0)
|
||||
}
|
||||
|
||||
test "DRINK, APPROACH, GO_DRINK and GO_FEED, alert over 95: FLEE, two rolls, the spot and the lure kept" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let states = [WILD_DRINK, WILD_APPROACH, WILD_GO_DRINK, WILD_GO_FEED]
|
||||
for i in 0 .. 4 {
|
||||
let a = spooked(wildlife_st, 2, states[i], 97.0)
|
||||
expect_eq(a.state, WILD_FLEE)
|
||||
expect_near(a.timer, 3.0 + 3.0 * pn_roll(2, 0), 0.0001)
|
||||
expect_eq(a.spot, 900)
|
||||
expect_eq(a.lure, 50)
|
||||
expect_eq(pn_drew(wildlife_st, 2), 2)
|
||||
}
|
||||
}
|
||||
|
||||
test "GO_DRINK and DRINK, a fresh alert over 25: ALERT, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = spooked(wildlife_st, 2, WILD_GO_DRINK, 40.0)
|
||||
expect_eq(a.state, WILD_ALERT)
|
||||
expect_eq(pn_drew(wildlife_st, 2), 1)
|
||||
let b = spooked(wildlife_st, 2, WILD_DRINK, 40.0)
|
||||
expect_eq(b.state, WILD_ALERT)
|
||||
expect_eq(pn_drew(wildlife_st, 2), 1)
|
||||
}
|
||||
}
|
||||
94
packages/ludic.wildlife/tests/idle_pins_test.ludic
Normal file
94
packages/ludic.wildlife/tests/idle_pins_test.ludic
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# idle_pins_test.ludic - phase 27.2a: IDLE's way out as it stands. Its time up it goes WANDER for
|
||||
# 6 + 10 r s toward a spot about home (an angle, a distance): a tracked walker first rolls for a bed
|
||||
# when the sit was short, and the droppings' roll comes before all of them
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program IdlePins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
test "IDLE, its time up: WANDER for 6 + 10 r0 s toward home at (r1, r2); a walker leaving no sign rolls three" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_IDLE, 0.0)
|
||||
wildlife_seed(wildlife_st, 11)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 6.0 + 10.0 * pn_roll(11, 0), 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, 11, 1, 60.0), 0.001)
|
||||
expect_near(a.tz, pn_tz(a, 11, 1, 60.0), 0.001)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_BED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 11), 3)
|
||||
}
|
||||
|
||||
test "a tracked walker after a short sit rolls r0 for a bed (under 0.06 leaves one), then the same three" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let seeds = [25, 11]
|
||||
for i in 0 .. 2 {
|
||||
let a = pn_at(wildlife_st, 0, 0.0, 0.0, WILD_IDLE, 0.0)
|
||||
wildlife_seed(wildlife_st, seeds[i])
|
||||
pn_step(wildlife_st, a)
|
||||
var bed = 0
|
||||
if pn_roll(seeds[i], 0) < 0.06 { bed = 1 }
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_BED), bed)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 6.0 + 10.0 * pn_roll(seeds[i], 1), 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, seeds[i], 2, 60.0), 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, seeds[i]), 4)
|
||||
}
|
||||
}
|
||||
|
||||
test "a sit of 6 s or more rolls no bed: the three alone" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 0, 0.0, 0.0, WILD_IDLE, -10.0)
|
||||
wildlife_seed(wildlife_st, 25)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 6.0 + 10.0 * pn_roll(25, 0), 0.0001)
|
||||
expect_eq(pn_count(pn_drain(wildlife_st), WILD_BED), 0)
|
||||
expect_eq(pn_drew(wildlife_st, 25), 3)
|
||||
}
|
||||
|
||||
test "droppings due roll first (scat_t = 120 + 300 r0, a fact within 500 m), then bed, time, target" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_player(wildlife_tests_fake_st, 100.0, 0.0)
|
||||
let a = pn_at(wildlife_st, 0, 0.0, 0.0, WILD_IDLE, 0.0)
|
||||
a.scat_t = 0.0
|
||||
wildlife_seed(wildlife_st, 15)
|
||||
pn_step(wildlife_st, a)
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_SCAT), 1)
|
||||
expect_near(a.scat_t, 120.0 + 300.0 * pn_roll(15, 0), 0.001)
|
||||
var bed = 0
|
||||
if pn_roll(15, 1) < 0.06 { bed = 1 }
|
||||
expect_eq(pn_count(fs, WILD_BED), bed)
|
||||
expect_near(a.timer, 6.0 + 10.0 * pn_roll(15, 2), 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, 15, 3, 60.0), 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 15), 5)
|
||||
}
|
||||
|
||||
test "IDLE before its time stays, and rolls nothing" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_IDLE, 5.0)
|
||||
wildlife_seed(wildlife_st, 11)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 11), 0)
|
||||
}
|
||||
}
|
||||
81
packages/ludic.wildlife/tests/lure_pins_test.ludic
Normal file
81
packages/ludic.wildlife/tests/lure_pins_test.ludic
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# lure_pins_test.ludic - phase 27.2a: IDLE and WANDER drawn to what is set out, as they stand. The
|
||||
# nearest within 70 m (food at 0.4 of its distance while feeding is taught) of its diet, or a snare
|
||||
# it fits, which rolls r > 0.5 each tick it is looked at: APPROACH, whatever its timer
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program LurePins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function drawn(wildlife_st: mut WildlifeState, sp: int, state: int) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, sp, 0.0, 0.0, state, 5.0)
|
||||
wildlife_seed(wildlife_st, 12)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "IDLE and WANDER, food of its diet within 70 m: APPROACH it, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 50, WILD_FEED, WILD_PLANTS, 20.0, 0.0)
|
||||
let a = drawn(wildlife_st, 2, WILD_IDLE)
|
||||
expect_eq(a.state, WILD_APPROACH)
|
||||
expect_eq(a.lure, 50)
|
||||
expect_eq(a.lure_kind, WILD_FEED)
|
||||
expect_eq(a.lure_owner, 3)
|
||||
expect_near(a.lure_x, 20.0, 0.0001)
|
||||
let b = drawn(wildlife_st, 2, WILD_WANDER)
|
||||
expect_eq(b.state, WILD_APPROACH)
|
||||
expect_eq(pn_drew(wildlife_st, 12), 0)
|
||||
}
|
||||
|
||||
test "food of another diet, or 80 m off, is left alone; taught, 80 m is near enough" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState, wild_pin_st: mut WildPinState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 51, WILD_FEED, WILD_FISH, 20.0, 0.0)
|
||||
pn_lure(wildlife_tests_fake_st, 50, WILD_FEED, WILD_PLANTS, 80.0, 0.0)
|
||||
let a = drawn(wildlife_st, 2, WILD_IDLE)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_eq(a.lure, 0)
|
||||
expect_eq(pn_drew(wildlife_st, 12), 0)
|
||||
wild_pin_st.pn_taught = true
|
||||
let b = drawn(wildlife_st, 2, WILD_IDLE)
|
||||
expect_eq(b.state, WILD_APPROACH)
|
||||
expect_eq(b.lure, 50)
|
||||
}
|
||||
|
||||
test "a snare it fits: one roll, over 0.5 and it APPROACHes the snare" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 60, WILD_SNARE, 0, 10.0, 0.0)
|
||||
for seed in 1 .. 17 {
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_IDLE, 5.0)
|
||||
wildlife_seed(wildlife_st, seed)
|
||||
pn_step(wildlife_st, a)
|
||||
if pn_roll(seed, 0) > 0.5 { expect_eq(a.state, WILD_APPROACH) } else { expect_eq(a.state, WILD_IDLE) }
|
||||
if pn_roll(seed, 0) > 0.5 { expect_eq(a.lure_kind, WILD_SNARE) }
|
||||
expect_eq(pn_drew(wildlife_st, seed), 1)
|
||||
}
|
||||
}
|
||||
|
||||
test "a snare too small for it (a deer, size 1): no roll, left alone" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 60, WILD_SNARE, 0, 10.0, 0.0)
|
||||
let a = drawn(wildlife_st, 0, WILD_IDLE)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_eq(pn_drew(wildlife_st, 12), 0)
|
||||
}
|
||||
}
|
||||
82
packages/ludic.wildlife/tests/perch_pins_test.ludic
Normal file
82
packages/ludic.wildlife/tests/perch_pins_test.ludic
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# perch_pins_test.ludic - phase 27.2a: a bird coming down and on the ground as it stands. Gliding in,
|
||||
# down and within 2 m it PERCHes for 8 + 16 r0 s; anyone within its flee, or 20 s over its time,
|
||||
# lifts it (FLY, 20 + 40 r0 s); on the ground its time up or anyone within its flee lifts it too
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program PerchPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function bird(wildlife_st: mut WildlifeState, state: int, timer: float, fly_h: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 3, 0.0, 0.0, state, timer)
|
||||
a.fly_h = fly_h
|
||||
wildlife_seed(wildlife_st, 17)
|
||||
pn_fly(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "LAND, down and at its spot: PERCH for 8 + 16 r0 s, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = bird(wildlife_st, WILD_LAND, 20.0, 0.1)
|
||||
expect_eq(a.state, WILD_PERCH)
|
||||
expect_near(a.timer, 8.0 + 16.0 * pn_roll(17, 0), 0.0001)
|
||||
expect_near(a.fly_h, 0.0, 0.00001)
|
||||
expect_eq(pn_drew(wildlife_st, 17), 1)
|
||||
}
|
||||
|
||||
test "LAND still high: gliding on, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = bird(wildlife_st, WILD_LAND, 20.0, 5.0)
|
||||
expect_eq(a.state, WILD_LAND)
|
||||
expect_near(a.fly_h, 5.0 - 0.05 * 3.2, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 17), 0)
|
||||
}
|
||||
|
||||
test "LAND with somebody within its flee, or 20 s past its time: FLY for 20 + 40 r0 s at the height it had" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let b = bird(wildlife_st, WILD_LAND, -19.99, 5.0)
|
||||
expect_eq(b.state, WILD_FLY)
|
||||
expect_near(b.fly_h, 5.0 - 0.05 * 3.2, 0.0001)
|
||||
pn_player(wildlife_tests_fake_st, 5.0, 0.0)
|
||||
let a = bird(wildlife_st, WILD_LAND, 20.0, 5.0)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_near(a.timer, 20.0 + 40.0 * pn_roll(17, 0), 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 17), 1)
|
||||
}
|
||||
|
||||
test "PERCH, its time up or somebody within its flee: FLY for 20 + 40 r0 s, 0.5 m up" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = bird(wildlife_st, WILD_PERCH, 0.01, 0.0)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_near(a.timer, 20.0 + 40.0 * pn_roll(17, 0), 0.0001)
|
||||
expect_near(a.fly_h, 0.5, 0.0001)
|
||||
pn_player(wildlife_tests_fake_st, 5.0, 0.0)
|
||||
let b = bird(wildlife_st, WILD_PERCH, 5.0, 0.0)
|
||||
expect_eq(b.state, WILD_FLY)
|
||||
expect_eq(pn_drew(wildlife_st, 17), 1)
|
||||
}
|
||||
|
||||
test "PERCH before its time, nobody near: stays, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = bird(wildlife_st, WILD_PERCH, 5.0, 0.0)
|
||||
expect_eq(a.state, WILD_PERCH)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 17), 0)
|
||||
}
|
||||
}
|
||||
46
packages/ludic.wildlife/tests/pin/dice.ludic
Normal file
46
packages/ludic.wildlife/tests/pin/dice.ludic
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# dice.ludic - what the package's dice drew since a seed, read off a newborn's yaw (the first draw
|
||||
# a newborn takes), and the facts and lures the pins count and set out
|
||||
numbers float
|
||||
const PN_TAU: float = 6.2831853
|
||||
|
||||
# the k-th draw (from 0) of a stream seeded as wildlife_seed(seed) seeds the package's
|
||||
function pn_roll(seed: int, k: int) -> float {
|
||||
let r = rng_new(seed)
|
||||
for i in 0 .. k { rng_next(r) }
|
||||
return rng_float(r)
|
||||
}
|
||||
|
||||
# how many draws the package has taken since wildlife_seed(seed): the next one is a newborn's yaw;
|
||||
# -1 when it is none of the first 64
|
||||
function pn_drew(wildlife_st: mut WildlifeState, seed: int) -> int {
|
||||
let yaw = wildlife_new(wildlife_st, 2, 9000.0, 9000.0, false).yaw
|
||||
let r = rng_new(seed)
|
||||
for k in 0 .. 64 {
|
||||
if Math.abs(rng_float(r) * PN_TAU - yaw) < 0.00001 { return k }
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
# a wander's target from draws k (the angle) and k + 1 (the distance) about home, radius `home`
|
||||
function pn_tx(a: WildAnimal, seed: int, k: int, home: float) -> float { return a.home_x + Math.cos(pn_roll(seed, k) * PN_TAU) * pn_roll(seed, k + 1) * home }
|
||||
function pn_tz(a: WildAnimal, seed: int, k: int, home: float) -> float { return a.home_z + Math.sin(pn_roll(seed, k) * PN_TAU) * pn_roll(seed, k + 1) * home }
|
||||
|
||||
# the facts waiting, drained, and how many of them are of a kind
|
||||
function pn_drain(wildlife_st: WildlifeState) -> []WildFact { return q_drain(wildlife_facts(wildlife_st)) }
|
||||
function pn_count(fs: []WildFact, what: int) -> int {
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
return n
|
||||
}
|
||||
|
||||
function pn_lure(wildlife_tests_fake_st: mut WildlifeTestsFakeState, uid: int, kind: int, diet: int, x: float, z: float) -> WildLure {
|
||||
let l = new WildLure
|
||||
l.uid = uid
|
||||
l.kind = kind
|
||||
l.diet = diet
|
||||
l.x = x
|
||||
l.z = z
|
||||
l.owner = 3
|
||||
push(wildlife_tests_fake_st.fk_lures, l)
|
||||
return l
|
||||
}
|
||||
60
packages/ludic.wildlife/tests/pin/index.ludic
Normal file
60
packages/ludic.wildlife/tests/pin/index.ludic
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# pin - what the transition pins share (phase 27.2a): one step at a fixed rate, an animal set in a
|
||||
# state, a spot and a teaching switch of the test's own, and two species the fake has not
|
||||
numbers float
|
||||
import "dice.ludic"
|
||||
export state WildPinState {
|
||||
pn_no_spot: bool = false # the world offers no water or forage
|
||||
pn_taught: bool = false # feeding is being taught
|
||||
}
|
||||
|
||||
function pn_spot(wild_pin_st: WildPinState, a: WildAnimal, water: bool, s: WildSpot) -> bool {
|
||||
if wild_pin_st.pn_no_spot { return false }
|
||||
s.uid = 900
|
||||
s.x = a.x + 30.0
|
||||
s.z = a.z
|
||||
s.water = water
|
||||
return true
|
||||
}
|
||||
|
||||
function pn_taught(wild_pin_st: WildPinState) -> bool { return wild_pin_st.pn_taught }
|
||||
|
||||
# after fk_setup: 4 a horse (tame), 5 a crow (flies, never comes down on its own)
|
||||
function pn_species(wildlife_st: WildlifeState) -> void {
|
||||
let h = new WildSpecies
|
||||
h.key = "horse"
|
||||
h.tame = true
|
||||
h.size = 2
|
||||
h.diet = WILD_HAY
|
||||
wildlife_species_add(wildlife_st, h)
|
||||
let c = new WildSpecies
|
||||
c.key = "crow"
|
||||
c.flies = true
|
||||
c.walk = 4.0
|
||||
c.flee = 8.0
|
||||
c.land_shy = 0.0
|
||||
c.land_chance = 0.0
|
||||
wildlife_species_add(wildlife_st, c)
|
||||
}
|
||||
|
||||
# one of species sp at (x, z), in `state` with `timer` left; no droppings due for a long while
|
||||
function pn_at(wildlife_st: mut WildlifeState, sp: int, x: float, z: float, state: int, timer: float) -> WildAnimal {
|
||||
let a = wildlife_make(wildlife_st, sp, x, z, false, 0.0, 0, 1.0, 1)
|
||||
a.state = state
|
||||
a.timer = timer
|
||||
a.scat_t = 100000.0
|
||||
return a
|
||||
}
|
||||
|
||||
# one tick of 50 ms, a walker's and a bird's
|
||||
function pn_step(wildlife_st: mut WildlifeState, a: WildAnimal) -> void { wildlife_tick_ground(wildlife_st, a, 0.05, 0.05 / 60.0) }
|
||||
function pn_fly(wildlife_st: mut WildlifeState, a: WildAnimal) -> void { wildlife_tick_bird(wildlife_st, a, 0.05) }
|
||||
|
||||
function pn_setup(wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) -> void {
|
||||
fk_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_species(wildlife_st)
|
||||
}
|
||||
|
||||
function pn_player(wildlife_tests_fake_st: mut WildlifeTestsFakeState, x: float, z: float) -> void {
|
||||
wildlife_tests_fake_st.fk_px[0] = x
|
||||
wildlife_tests_fake_st.fk_pz[0] = z
|
||||
}
|
||||
77
packages/ludic.wildlife/tests/posture_pins_test.ludic
Normal file
77
packages/ludic.wildlife/tests/posture_pins_test.ludic
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# posture_pins_test.ludic - phase 27.2a: the alert's postures as they stand. Over 25 and above what
|
||||
# it has already reacted to (`seen`) it looks up (ALERT, 1.5 + 2.5 r s); over 60, WARY (2 + 2 r s);
|
||||
# ALERT gives way to WARY, never WARY to ALERT; a level at or under `seen` does nothing
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program PosturePins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function hare(wildlife_st: mut WildlifeState, state: int, alert: float, seen: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, state, 5.0)
|
||||
a.alert = alert
|
||||
a.seen = seen
|
||||
wildlife_seed(wildlife_st, 3)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "IDLE, alert over 25 and fresh: ALERT for 1.5 + 2.5 r0 s, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = hare(wildlife_st, WILD_IDLE, 40.0, 0.0)
|
||||
expect_eq(a.state, WILD_ALERT)
|
||||
expect_near(a.timer, 1.5 + 2.5 * pn_roll(3, 0), 0.0001)
|
||||
expect_near(a.speed, 0.0, 0.00001)
|
||||
expect_eq(pn_drew(wildlife_st, 3), 1)
|
||||
}
|
||||
|
||||
test "IDLE, alert over 60 and fresh: WARY for 2 + 2 r0 s, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = hare(wildlife_st, WILD_IDLE, 70.0, 0.0)
|
||||
expect_eq(a.state, WILD_WARY)
|
||||
expect_near(a.timer, 2.0 + 2.0 * pn_roll(3, 0), 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 3), 1)
|
||||
}
|
||||
|
||||
test "ALERT, alert rising over 60: WARY, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = hare(wildlife_st, WILD_ALERT, 70.0, 0.0)
|
||||
expect_eq(a.state, WILD_WARY)
|
||||
expect_near(a.timer, 2.0 + 2.0 * pn_roll(3, 0), 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 3), 1)
|
||||
}
|
||||
|
||||
test "WARY, a fresh alert between 25 and 60: still WARY, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = hare(wildlife_st, WILD_WARY, 40.0, 0.0)
|
||||
expect_eq(a.state, WILD_WARY)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 3), 0)
|
||||
}
|
||||
|
||||
test "an alert no higher than what it has seen: nothing, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = hare(wildlife_st, WILD_IDLE, 70.0, 80.0)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
let b = hare(wildlife_st, WILD_IDLE, 40.0, 50.0)
|
||||
expect_eq(b.state, WILD_IDLE)
|
||||
expect_near(b.alert, 40.0 - 2.5 * 0.05, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 3), 0)
|
||||
}
|
||||
}
|
||||
71
packages/ludic.wildlife/tests/react_pins_test.ludic
Normal file
71
packages/ludic.wildlife/tests/react_pins_test.ludic
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# react_pins_test.ludic - phase 27.2a: the ends of ALERT and WARY as they stand. Either one, its time
|
||||
# up, wanders for 3 + 4 r0 s toward (r1, r2) about the home it had: three rolls, the time first
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program ReactPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
test "ALERT, its time up: WANDER 3 + 4 r0 s toward (r1, r2) about home, three rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_ALERT, 0.01)
|
||||
wildlife_seed(wildlife_st, 9)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 3.0 + 4.0 * pn_roll(9, 0), 0.0001)
|
||||
expect_near(a.home_x, 10.0, 0.0001)
|
||||
expect_near(a.tx, pn_tx(a, 9, 1, 60.0), 0.001)
|
||||
expect_near(a.tz, pn_tz(a, 9, 1, 60.0), 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 9), 3)
|
||||
}
|
||||
|
||||
test "ALERT before its time: stands still, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_ALERT, 5.0)
|
||||
a.speed = 3.0
|
||||
wildlife_seed(wildlife_st, 9)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_ALERT)
|
||||
expect_near(a.speed, 0.0, 0.00001)
|
||||
expect_eq(pn_drew(wildlife_st, 9), 0)
|
||||
}
|
||||
|
||||
test "WARY, its time up: the step away first, then WANDER 3 + 4 r0 s about the old home, three rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_WARY, 0.01)
|
||||
wildlife_seed(wildlife_st, 9)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 3.0 + 4.0 * pn_roll(9, 0), 0.0001)
|
||||
expect_near(a.home_x, 10.0, 0.0001)
|
||||
expect(Math.abs(a.x - 10.0) + Math.abs(a.z) > 0.001)
|
||||
expect_near(a.tx, pn_tx(a, 9, 1, 60.0), 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 9), 3)
|
||||
}
|
||||
|
||||
test "WARY before its time: backs off at 0.8 of its walk, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 10.0, 0.0, WILD_WARY, 5.0)
|
||||
wildlife_seed(wildlife_st, 9)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WARY)
|
||||
expect_near(a.speed, 0.8, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 9), 0)
|
||||
}
|
||||
}
|
||||
74
packages/ludic.wildlife/tests/seed_pins_test.ludic
Normal file
74
packages/ludic.wildlife/tests/seed_pins_test.ludic
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# seed_pins_test.ludic - phase 27.2a: seed set out, as it stands (the world is scanned for any once a
|
||||
# second, in wildlife_tick). A bird aloft with seed within 120 m and nobody within 0.7 of its flee
|
||||
# comes down 1 + 2 r0 m off it at the angle r1; perched at it, it rolls r < 0.12 dt to be FED
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program SeedPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
test "FLY, seed within 120 m: LAND (30 s) at 1 + 2 r0 m from the seed, angle r1: two rolls" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 77, WILD_FEED, WILD_SEED, 0.0, 0.0)
|
||||
pn_player(wildlife_tests_fake_st, 500.0, 0.0)
|
||||
let a = pn_at(wildlife_st, 3, 0.0, 0.0, WILD_FLY, 5.0)
|
||||
wildlife_seed(wildlife_st, 18)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.0)
|
||||
expect_eq(a.state, WILD_LAND)
|
||||
expect_near(a.timer, 30.0, 0.0001)
|
||||
let off = 1.0 + 2.0 * pn_roll(18, 0)
|
||||
let oa = pn_roll(18, 1) * 6.2831853
|
||||
expect_near(a.tx, Math.sin(oa) * off, 0.001)
|
||||
expect_near(a.tz, Math.cos(oa) * off, 0.001)
|
||||
expect_eq(pn_drew(wildlife_st, 18), 2)
|
||||
}
|
||||
|
||||
test "FLY, seed down but somebody within 0.7 of its flee: no coming down, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 77, WILD_FEED, WILD_SEED, 0.0, 0.0)
|
||||
pn_player(wildlife_tests_fake_st, 3.0, 0.0)
|
||||
let a = pn_at(wildlife_st, 3, 0.0, 0.0, WILD_FLY, 5.0)
|
||||
wildlife_seed(wildlife_st, 18)
|
||||
wildlife_tick(wildlife_st, 0.05, 0.0)
|
||||
expect_eq(a.state, WILD_FLY)
|
||||
expect_eq(pn_drew(wildlife_st, 18), 0)
|
||||
}
|
||||
|
||||
test "PERCH within 3 m of seed: one roll a tick, under 0.12 dt it is FED (calm 180); it stays" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 77, WILD_FEED, WILD_SEED, 1.0, 0.0)
|
||||
pn_player(wildlife_tests_fake_st, 500.0, 0.0)
|
||||
let seeds = [25, 11]
|
||||
for i in 0 .. 2 {
|
||||
let a = pn_at(wildlife_st, 3, 0.0, 0.0, WILD_PERCH, 5.0)
|
||||
a.hunger = 50.0
|
||||
wildlife_seed(wildlife_st, seeds[i])
|
||||
wildlife_tick(wildlife_st, 0.05, 0.0)
|
||||
expect_eq(a.state, WILD_PERCH)
|
||||
expect_near(a.hunger, 50.0 - 30.0 * 0.05, 0.0001)
|
||||
var fed = 0
|
||||
if pn_roll(seeds[i], 0) < 0.12 * 0.05 { fed = 1 }
|
||||
let fs = pn_drain(wildlife_st)
|
||||
expect_eq(pn_count(fs, WILD_FED), fed)
|
||||
if fed == 1 { expect_near(a.calm, 180.0, 0.0001) }
|
||||
expect_eq(pn_drew(wildlife_st, seeds[i]), 1)
|
||||
wildlife_remove(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
81
packages/ludic.wildlife/tests/seek_pins_test.ludic
Normal file
81
packages/ludic.wildlife/tests/seek_pins_test.ludic
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# seek_pins_test.ludic - phase 27.2a: IDLE and WANDER going to water or forage as they stand. Thirst
|
||||
# or hunger over 60 asks the world for a spot - water when thirst is the greater, forage on a tie -
|
||||
# and sets off (GO_DRINK / GO_FEED, 120 s) whatever its timer; no spot, no change; no roll either way
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program SeekPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
function needy(wildlife_st: mut WildlifeState, state: int, thirst: float, hunger: float) -> WildAnimal {
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, state, 5.0)
|
||||
a.thirst = thirst
|
||||
a.hunger = hunger
|
||||
wildlife_seed(wildlife_st, 6)
|
||||
pn_step(wildlife_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
test "IDLE, thirst over 60 and over hunger: GO_DRINK to the world's water, 120 s, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = needy(wildlife_st, WILD_IDLE, 70.0, 10.0)
|
||||
expect_eq(a.state, WILD_GO_DRINK)
|
||||
expect_eq(a.spot, 900)
|
||||
expect(a.spot_water)
|
||||
expect_near(a.spot_x, 30.0, 0.0001)
|
||||
expect_near(a.timer, 120.0, 0.0001)
|
||||
expect_near(a.way_t, 0.0, 0.00001)
|
||||
expect_eq(pn_drew(wildlife_st, 6), 0)
|
||||
}
|
||||
|
||||
test "IDLE, hunger over 60 and over thirst - or the two level: GO_FEED to forage" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = needy(wildlife_st, WILD_IDLE, 10.0, 70.0)
|
||||
expect_eq(a.state, WILD_GO_FEED)
|
||||
expect(not a.spot_water)
|
||||
let b = needy(wildlife_st, WILD_IDLE, 70.0, 70.0)
|
||||
expect_eq(b.state, WILD_GO_FEED)
|
||||
expect_eq(pn_drew(wildlife_st, 6), 0)
|
||||
}
|
||||
|
||||
test "WANDER sets off the same way" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = needy(wildlife_st, WILD_WANDER, 70.0, 10.0)
|
||||
expect_eq(a.state, WILD_GO_DRINK)
|
||||
expect_near(a.timer, 120.0, 0.0001)
|
||||
}
|
||||
|
||||
test "no spot answered: IDLE stays, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState, wild_pin_st: mut WildPinState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
wild_pin_st.pn_no_spot = true
|
||||
let a = needy(wildlife_st, WILD_IDLE, 70.0, 10.0)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_eq(a.spot, 0)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 6), 0)
|
||||
}
|
||||
|
||||
test "thirst beats food set out: water first, the lure not taken" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
pn_lure(wildlife_tests_fake_st, 50, WILD_FEED, WILD_PLANTS, 5.0, 0.0)
|
||||
let a = needy(wildlife_st, WILD_IDLE, 70.0, 10.0)
|
||||
expect_eq(a.state, WILD_GO_DRINK)
|
||||
expect_eq(a.lure, 0)
|
||||
}
|
||||
}
|
||||
77
packages/ludic.wildlife/tests/wander_pins_test.ludic
Normal file
77
packages/ludic.wildlife/tests/wander_pins_test.ludic
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# wander_pins_test.ludic - phase 27.2a: WANDER's way out as it stands. At its target (1.5 m) or its
|
||||
# time up it goes IDLE for 3 + 8 r s; a refused step (water, a climb, a push) rolls nothing, turns
|
||||
# it 75 degrees and zeroes its timer (the next step that goes ends the wander)
|
||||
import "ludic.wildlife"
|
||||
import "ludic.base"
|
||||
import "fake"
|
||||
import "pin"
|
||||
program WanderPins {
|
||||
numbers float
|
||||
bind WildlifeWorld {
|
||||
ground: fn fk_ground
|
||||
water: fn fk_water
|
||||
players: fn fk_players
|
||||
player_on: fn fk_player_on
|
||||
player_x: fn fk_x
|
||||
player_y: fn fk_y
|
||||
player_z: fn fk_z
|
||||
about: fn fk_about_of
|
||||
lures: fn fk_count
|
||||
lure: fn fk_lure
|
||||
present: fn fk_present
|
||||
spot: fn pn_spot
|
||||
taught: fn pn_taught
|
||||
}
|
||||
|
||||
test "WANDER at its target: IDLE for 3 + 8 r0 s, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_WANDER, 10.0)
|
||||
a.tx = 0.5
|
||||
a.tz = 0.0
|
||||
wildlife_seed(wildlife_st, 7)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.timer, 3.0 + 8.0 * pn_roll(7, 0), 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 7), 1)
|
||||
}
|
||||
|
||||
test "WANDER, its time up short of the target: IDLE for 3 + 8 r0 s, one roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_WANDER, 0.01)
|
||||
a.tx = 50.0
|
||||
a.tz = 0.0
|
||||
wildlife_seed(wildlife_st, 7)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_IDLE)
|
||||
expect_near(a.timer, 3.0 + 8.0 * pn_roll(7, 0), 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 7), 1)
|
||||
}
|
||||
|
||||
test "WANDER on its way stays, and rolls nothing" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, 0.0, 0.0, WILD_WANDER, 5.0)
|
||||
a.tx = 50.0
|
||||
a.tz = 0.0
|
||||
wildlife_seed(wildlife_st, 7)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 4.95, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 7), 0)
|
||||
}
|
||||
|
||||
test "a step into the water is refused: turned 75 degrees, timer 0, still WANDER, no roll" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||
pn_setup(wildlife_st, wildlife_tests_fake_st)
|
||||
let a = pn_at(wildlife_st, 2, -299.99, 0.0, WILD_WANDER, 5.0)
|
||||
a.yaw = 1.5707964
|
||||
a.tx = -400.0
|
||||
a.tz = 0.0
|
||||
let wet = wildlife_turned_wet(wildlife_st)
|
||||
wildlife_seed(wildlife_st, 7)
|
||||
pn_step(wildlife_st, a)
|
||||
expect_eq(a.state, WILD_WANDER)
|
||||
expect_near(a.timer, 0.0, 0.00001)
|
||||
expect_eq(wildlife_turned_wet(wildlife_st), wet + 1)
|
||||
expect_near(a.x, -299.99, 0.0001)
|
||||
expect_eq(pn_drew(wildlife_st, 7), 0)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue