# wildlife_test.ludic - species as data, a valley spawned against its ground, the alert (where it # SETTLES, not only how it rises), cover, stillness and wind, the charge, the hours, prints and the save import "ludic.wildlife" import "ludic.base" import "fake" program WildlifeTest { numbers float bind WildlifeWorld { ground: fn fk_ground water: fn fk_water forest: fn fk_forest sight: fn fk_sight push: fn fk_push pushed_x: fn fk_pushed_x pushed_z: fn fk_pushed_z 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 hidden: fn fk_is_hidden noise: fn fk_noise_of scent: fn fk_scent_of stillness: fn fk_still_of wind: fn fk_wind_of wind_dir: fn fk_wind_to winterness: fn fk_winter_of about: fn fk_about_of per_range: fn fk_one lures: fn fk_count lure: fn fk_lure present: fn fk_present born: fn fk_on_born spot: fn fk_spot } function facts(wildlife_st: WildlifeState) -> []WildFact { return q_drain(wildlife_facts(wildlife_st)) } function count(fs: []WildFact, what: int) -> int { var n = 0 for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } } return n } function deer_at(wildlife_st: mut WildlifeState, x: float, z: float) -> WildAnimal { let a = wildlife_make(wildlife_st, 0, x, z, false, 0.0, 0, 1.0, 1) a.state = WILD_IDLE a.timer = 30.0 return a } function player_at(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 } function go(wildlife_st: mut WildlifeState, a: WildAnimal, secs: float) -> void { for k in 0 .. int(secs * 20.0) { wildlife_tick_ground(wildlife_st, a, 0.05, 0.05 / 60.0) } } test "the table handed in numbers the species, and a new animal is born through the port" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) expect_eq(wildlife_species_count(wildlife_st), 4) expect(wildlife_species(wildlife_st, 3).flies) let a = wildlife_new(wildlife_st, 0, 10.0, 20.0, false) expect_eq(wildlife_tests_fake_st.fk_born, 1) expect_near(a.y, 10.0, 0.001) expect(a.variant >= 0 and a.variant <= 11) expect(a.scale > 0.87 and a.scale < 1.13) let j = wildlife_new(wildlife_st, 3, 0.0, 0.0, false) expect_eq(j.state, WILD_FLY) expect(wildlife_new(wildlife_st, 9, 0.0, 0.0, false) == null) } test "a spawn sets ranges out on their own habitat, clear of the start, and fills them" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) wildlife_spawn(wildlife_st, 0.0, 0.0) let rs = wildlife_ranges(wildlife_st) expect(len(rs) >= 6) for i in 0 .. len(rs) { expect(wildlife_range_dist(rs[i], 0.0, 0.0) >= wildlife_species(wildlife_st, rs[i].sp).keep_away) if rs[i].sp == 1 { expect(rs[i].z > 400.0) } expect(rs[i].sx > -300.0) } expect(wildlife_count(wildlife_st, 0) >= 1) expect_eq(wildlife_count_all(wildlife_st), wildlife_count(wildlife_st, 0) + wildlife_count(wildlife_st, 1) + wildlife_count(wildlife_st, 2) + wildlife_count(wildlife_st, 3)) } test "a player far off makes no difference that lasts: the alert settles under the unaware line" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) player_at(wildlife_tests_fake_st, 55.0, 0.0) wildlife_tests_fake_st.fk_noise = 0.3 go(wildlife_st, a, 60.0) expect(a.alert < 25.0) expect(a.state != WILD_FLEE) } test "close and in the open it is flushed, runs, and says so" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) player_at(wildlife_tests_fake_st, 8.0, 0.0) wildlife_tests_fake_st.fk_noise = 0.8 go(wildlife_st, a, 10.0) expect(a.spook > 0.0) let fs = facts(wildlife_st) expect(count(fs, WILD_FLED) >= 1) expect(a.x < 0.0) } test "cover hides a player from sight, a hide from everything but the nose" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) let open = wildlife_alert_rate(wildlife_st, a, 0, 30.0) player_at(wildlife_tests_fake_st, 30.0, 0.0) let open2 = wildlife_alert_rate(wildlife_st, a, 0, 30.0) wildlife_tests_fake_st.fk_blocked = true let covered = wildlife_alert_rate(wildlife_st, a, 0, 30.0) wildlife_tests_fake_st.fk_blocked = false wildlife_tests_fake_st.fk_hidden = true let hidden = wildlife_alert_rate(wildlife_st, a, 0, 30.0) expect(open2 > 0.0) expect(open >= open2) expect_near(covered, 0.0, 0.0001) expect_near(hidden, 0.0, 0.0001) } test "sitting still makes it forget faster, and the wind carries scent only downwind" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) let moving = wildlife_alert_decay(wildlife_st, a, 0) wildlife_tests_fake_st.fk_still = WILD_SITTING expect(wildlife_alert_decay(wildlife_st, a, 0) > moving * 2.0) player_at(wildlife_tests_fake_st, 0.0, -60.0) wildlife_tests_fake_st.fk_blocked = true wildlife_tests_fake_st.fk_scent = 1.0 wildlife_tests_fake_st.fk_wind = 0.5 wildlife_tests_fake_st.fk_wind_dir = 3.1415927 # blowing toward +z: from the player to the deer expect(wildlife_downwind(a, 0) > 0.9) expect(wildlife_alert_rate(wildlife_st, a, 0, 60.0) > 0.0) wildlife_tests_fake_st.fk_wind_dir = 0.0 expect_near(wildlife_alert_rate(wildlife_st, a, 0, 60.0), 0.0, 0.0001) } test "a charger comes at a player inside its reach, and a shove is a fact for the game" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let b = wildlife_make(wildlife_st, 1, 0.0, 0.0, false, 0.0, 0, 1.0, 2) player_at(wildlife_tests_fake_st, 6.0, 0.0) wildlife_tick_ground(wildlife_st, b, 0.05, 0.001) expect_eq(b.state, WILD_CHARGE) go(wildlife_st, b, 2.0) let fs = facts(wildlife_st) expect_eq(count(fs, WILD_CHARGED), 1) expect_eq(count(fs, WILD_SHOVED), 1) expect(b.calm > 0.0) } test "away is hidden and skipped, gone is removed and said" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) player_at(wildlife_tests_fake_st, 10.0, 0.0) wildlife_tests_fake_st.fk_about = WILD_AWAY wildlife_tick(wildlife_st, 0.05, 0.001) expect(not a.shown and a.alive) wildlife_tests_fake_st.fk_about = WILD_GONE wildlife_tick(wildlife_st, 0.05, 0.001) expect(not a.alive) expect_eq(count(facts(wildlife_st), WILD_WENT), 1) } test "a walker leaves a print every 2.8 m, and player 0 spots a species once" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) player_at(wildlife_tests_fake_st, 40.0, 0.0) wildlife_tests_fake_st.fk_blocked = true a.state = WILD_WANDER a.tx = 0.0 a.tz = -100.0 a.timer = 100.0 for k in 0 .. 200 { wildlife_tick(wildlife_st, 0.05, 0.0) } let fs = facts(wildlife_st) expect(count(fs, WILD_PRINT) >= 3) expect_eq(count(fs, WILD_SPOTTED), 1) expect(wildlife_seen(wildlife_st, 0)) } test "a walker slides round a trunk rather than through it" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) let a = deer_at(wildlife_st, 0.0, 0.0) wildlife_tests_fake_st.fk_trunk = true player_at(wildlife_tests_fake_st, 60.0, 0.0) wildlife_tests_fake_st.fk_blocked = true a.state = WILD_WANDER a.tx = 0.0 a.tz = -100.0 a.timer = 100.0 var closest = 100.0 for k in 0 .. 800 { wildlife_tick(wildlife_st, 0.05, 0.0) closest = Math.min(closest, Math.sqrt((a.x - 0.3) * (a.x - 0.3) + (a.z + 20.0) * (a.z + 20.0))) } expect(closest > 1.35) expect(a.z < -25.0) } test "the record and the found ranges come back from the save section" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) wildlife_spawn(wildlife_st, 0.0, 0.0) wildlife_mark_fed(wildlife_st, 2) wildlife_saw(wildlife_st, 0) let r = wildlife_ranges(wildlife_st)[0] wildlife_ranges_visit(wildlife_st, r.x, r.z) let v = wildlife_save(wildlife_st) wildlife_reset(wildlife_st) expect(not wildlife_fed_any(wildlife_st) and not wildlife_ranges(wildlife_st)[0].found) wildlife_load(wildlife_st, v, 1) expect(wildlife_fed_any(wildlife_st)) expect_eq(wildlife_fed_mask(wildlife_st), 4) expect(wildlife_seen(wildlife_st, 0)) expect(wildlife_ranges(wildlife_st)[0].found) } test "a morning moves the ranges toward winter and brings one back to a range that lost its own" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) wildlife_spawn(wildlife_st, 0.0, 0.0) let r = wildlife_ranges(wildlife_st)[0] let x0 = r.x let all = wildlife_all(wildlife_st) for i in 0 .. len(all) { if all[i].rg == 0 { wildlife_remove(all[i]) } } wildlife_tests_fake_st.fk_winter = 1.0 let added = wildlife_morning(wildlife_st) expect(added >= 1) expect_eq(wildlife_range_alive(wildlife_st, 0), 1) expect_near(r.x, r.wx, 0.001) expect(r.x != x0 or r.wx == r.sx) } test "the table: a nid finds its animal, the living count by species, the nearest, and a refile" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) { fk_setup(wildlife_st, wildlife_tests_fake_st) wildlife_clear(wildlife_st) let a = wildlife_make(wildlife_st, 0, 10.0, 0.0, false, 0.0, 0, 1.0, 41) let b = wildlife_make(wildlife_st, 0, 90.0, 0.0, false, 0.0, 0, 1.0, 42) let c = wildlife_make(wildlife_st, 1, 30.0, 0.0, true, 0.0, 0, 1.0, 43) expect(wildlife_by_nid(wildlife_st, 42) == b) expect(wildlife_by_nid(wildlife_st, 7) == null) expect_eq(wildlife_count(wildlife_st, 0), 2) expect_eq(wildlife_count(wildlife_st, 1), 0) expect(wildlife_nearest(wildlife_st, -1, 0.0, 0.0, 0.0) == a) expect(wildlife_nearest(wildlife_st, 1, 0.0, 0.0, 0.0) == c) let near = new []WildAnimal expect_eq(wildlife_near(wildlife_st, 0.0, 0.0, 40.0, near), 2) expect_eq(wildlife_near_of(wildlife_st, 0, 0.0, 0.0, 200.0, near), 2) expect_eq(wildlife_alive_of(wildlife_st, 1), 1) wildlife_remove(a) expect_eq(wildlife_count(wildlife_st, 0), 1) expect(wildlife_nearest(wildlife_st, 0, 0.0, 0.0, 0.0) == b) b.x = -5.0 wildlife_refile(wildlife_st) expect(wildlife_nearest(wildlife_st, -1, 0.0, 0.0, 20.0) == b) expect_eq(wildlife_verify(wildlife_st), 0) expect_eq(wildlife_count_all(wildlife_st), 3) wildlife_clear(wildlife_st) expect_eq(wildlife_count_all(wildlife_st), 0) expect(wildlife_by_nid(wildlife_st, 42) == null) } }