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
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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue