# way_test.ludic - a person walks by the world's way where the world has one: round a wall the # straight line runs into, by the corners NpcWorld.way gives, and arrives only where it was going - # never at a corner import "ludic.npc" import "ludic.base" import "fake" program NpcWayTest { numbers float bind NpcWorld { ground: fn fk_ground water: fn fk_water allowed: fn fk_allowed push: fn fk_push pushed_x: fn fk_pushed_x pushed_z: fn fk_pushed_z clear: fn fk_clear hour: fn fk_hour_now day: fn fk_day_now players: fn fk_players player_on: fn fk_player_on player_x: fn fk_x player_z: fn fk_z want: fn fk_wanted extra: fn fk_extra_kind taken: fn fk_taken born: fn fk_on_born gone: fn fk_on_gone way: fn wt_way way_x: fn wt_x way_z: fn wt_z } bind NpcTalk { say: fn tk_say, greeting: fn tk_greeting } def NpcActs sit { } def NpcActs fish { turns: false } def NpcKinds from "kinds.lres" def NpcNames from "names.lres" def NpcLines from "lines.lres" function tk_say(p: NpcPerson, line: int) -> string { return "" } function tk_greeting(p: NpcPerson) -> string { return "" } function tk_start(npc_st: mut NpcState, p: NpcPerson) -> void { npc_start_near(npc_st, p, 0.0, 0.0, 0.0, 10.0) } state WayTestState { wx: float = 0.0 wz: float = 0.0 asked: int = 0 } # a wall across x = 20 for |z| < 15 (a straight walk to (38, -25) meets it): the way goes round its # north end, then on to the target - which is clear of where the fake place forbids stopping function wt_way(way_test_st: mut WayTestState, p: NpcPerson, x: float, z: float) -> bool { way_test_st.asked += 1 way_test_st.wx = x way_test_st.wz = z if p.x < 19.0 and p.z < 16.0 { way_test_st.wx = 20.0 way_test_st.wz = 17.0 } return true } function wt_x(way_test_st: WayTestState) -> float { return way_test_st.wx } function wt_z(way_test_st: WayTestState) -> float { return way_test_st.wz } test "it walks round the wall by the corners it is given and begins only where it was going" (npc_st: mut NpcState, npc_tests_fake_st: mut NpcTestsFakeState, way_test_st: WayTestState) { fk_setup(npc_st, npc_tests_fake_st) npc_tests_fake_st.fk_want = 1 let p = npc_spawn(npc_st, NPCK_HIKER) npc_set_at(p, 0.0, 0.0) npc_go(npc_st, p, 38.0, -25.0, NPCA_SIT, 30.0) var north = -100.0 var k = 0 while p.act == NPCA_WALK and k < 2000 { npc_tick(npc_st, 0.05) if p.x > 19.0 and p.x < 21.0 { north = Math.max(north, p.z) } k += 1 } expect(north > 14.0) expect_eq(p.act, NPCA_SIT) expect(npc_d(p.x, p.z, 38.0, -25.0) < 1.3) expect(way_test_st.asked > 5) let fs = q_drain(npc_facts(npc_st)) for i in 0 .. len(fs) { expect(fs[i].what != NPC_F_STUCK) } } test "a crowd walker says where and how fast, is moved by hand to its target, and begins there" (npc_st: mut NpcState, npc_tests_fake_st: mut NpcTestsFakeState, way_test_st: WayTestState) { fk_setup(npc_st, npc_tests_fake_st) npc_tests_fake_st.fk_want = 1 let p = npc_spawn(npc_st, NPCK_HIKER) npc_set_at(p, 0.0, 0.0) npc_set_crowd(p, 0) npc_go(npc_st, p, 38.0, -25.0, NPCA_SIT, 30.0) for k in 0 .. 60 { npc_tick(npc_st, 0.05) } expect_eq(p.x, 0.0) expect_eq(p.z, 0.0) expect_eq(p.goal_x, 38.0) expect_eq(p.goal_z, -25.0) expect(p.goal_speed > 0.5) expect_eq(way_test_st.asked, 0) for k in 1 .. 101 { npc_moved(p, 0.38 * float(k), -0.25 * float(k), 1.0, -0.66) } npc_tick(npc_st, 0.05) expect_eq(p.act, NPCA_SIT) expect(p.phase > 100.0) } test "an arrival a turn, drained each turn, makes no fact record past the ones made at the start" (npc_st: mut NpcState, npc_tests_fake_st: mut NpcTestsFakeState, way_test_st: WayTestState) { fk_setup(npc_st, npc_tests_fake_st) npc_tests_fake_st.fk_want = 1 let p = npc_spawn(npc_st, NPCK_HIKER) var arrived = 0 for k in 0 .. 500 { npc_set_at(p, 0.0, 0.0) npc_go(npc_st, p, 0.5, 0.0, NPCA_SIT, 30.0) npc_tick(npc_st, 0.05) let fs = q_drain(npc_facts(npc_st)) for i in 0 .. len(fs) { if fs[i].what == NPC_F_ARRIVED { arrived += 1 } } } expect(arrived > 400) expect_eq(npc_fact_records(npc_st), 64) } }