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:
Orkun ÇAKILKAYA 2026-09-30 16:57:15 +03:00
parent d7adc28125
commit 67d477af77
19 changed files with 1521 additions and 0 deletions

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View 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
}

View 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
}

View 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)
}
}

View 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)
}
}

View 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)
}
}
}

View 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)
}
}

View 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)
}
}