ludic/packages/ludic.npc/tests/way_test.ludic
Orkuncakilkaya 7fdd6582be fix(ludic.npc): the facts' records and the queue's lists made at their size at the start (64), so a frame with a new peak of facts makes nothing
The fence found np_fact_record making a record in five frames of every scenario: the pool grew to
each new peak of facts held at once, and q_unheld's free list and the queue's two lists grew with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 15:46:11 +03:00

120 lines
4.2 KiB
Text

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