feat(npc, nav): 17.5 - a person walks by the world's way where it has one (NpcWorld.way: the next corner toward the target, asked every half second, on reaching it or for a new target; the errand begins only at the target itself; the step round and the give-up stay the fallback), way_test round a wall; and ludic.nav reads a mesh file into the shim's own memory and frees it once parsed, so loading a map leaves nothing in Ludic's never-freed heap
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4add35b4ca
commit
ee0768bf3e
12 changed files with 184 additions and 39 deletions
82
packages/ludic.npc/tests/way_test.ludic
Normal file
82
packages/ludic.npc/tests/way_test.ludic
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue