ludic.npc (17.7): a person's fallback is a fact
A step round what is in the way, a target planned again after twenty seconds without progress, and a target given up are each pushed as NPC_F_STUCK (how, x, z), so the game can see where the way failed a person. The lake test expects one when a walker turns back from the water; the way test expects none when the world gives the way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
61f802e9ad
commit
ab84a5f936
6 changed files with 30 additions and 4 deletions
|
|
@ -114,7 +114,7 @@ by a person's taste.
|
|||
| `npc_pick_name(body)`, `npc_name_used(n)`, `npc_name_clashes()` | names |
|
||||
| `npc_talk(p, player)`, `npc_line_for(p)`, `npc_words(p, line)`, `npc_said()`, `npc_choose(p, line, c, player)`, `npc_talked_today(p)`, `npc_greeting(p)` | talk |
|
||||
| `npc_mirror(on)`, `npc_mirroring()`, `npc_put(slot, id, kind, look, seed, name, hx, hz)`, `npc_heard(slot, x, y, z, yaw, speed, act, stalk)`, `npc_heard_lately(p)`, `npc_mirror_tick(dt)` | a guest's copy of the host's people |
|
||||
| `npc_facts() -> Queue<NpcFact>` | `NPC_F_GREETED` (`player`), `NPC_F_TALKED` (`player`, `line`, `choice`), `NPC_F_ARRIVED` (`act`) |
|
||||
| `npc_facts() -> Queue<NpcFact>` | `NPC_F_GREETED` (`player`), `NPC_F_TALKED` (`player`, `line`, `choice`), `NPC_F_ARRIVED` (`act`), `NPC_F_STUCK` (`how` - `NPC_STUCK_DETOUR`, `_RETRY`, `_GAVE_UP` - at `x`, `z`: the way failed it and it fell back) |
|
||||
| `npc_system() -> System` | `"npc"`, `PH_SIMULATE`, a reset and no tick; nothing saved |
|
||||
|
||||
## Tests
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ export open registry NpcNames of NpcName as NPCN
|
|||
export const NPC_F_GREETED: int = 0 # a player came within notice
|
||||
export const NPC_F_TALKED: int = 1 # a player talked (line, choice -1 or the choice taken)
|
||||
export const NPC_F_ARRIVED: int = 2 # got where it was walking, and began the act
|
||||
export const NPC_F_STUCK: int = 3 # the way failed it and it fell back (`how`, at `x`, `z`)
|
||||
|
||||
export property NpcFact {
|
||||
what: int = 0
|
||||
|
|
@ -141,4 +142,7 @@ export property NpcFact {
|
|||
line: int = -1
|
||||
choice: int = -1
|
||||
act: int = -1
|
||||
how: int = 0 # NPC_STUCK_*
|
||||
x: float = 0.0
|
||||
z: float = 0.0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ program NpcTest {
|
|||
expect_eq(p.act, NPCA_SIT)
|
||||
}
|
||||
|
||||
test "nobody walks into the lake" (npc_st: mut NpcState, npc_tests_fake_st: mut NpcTestsFakeState) {
|
||||
test "nobody walks into the lake, and turning back from it is told as a fallback" (npc_st: mut NpcState, npc_tests_fake_st: mut NpcTestsFakeState) {
|
||||
let p = one(npc_st, npc_tests_fake_st, NPCK_HIKER)
|
||||
npc_go(npc_st, p, -80.0, 0.0, NPCA_SIT, 30.0)
|
||||
var west = 0.0
|
||||
|
|
@ -123,6 +123,12 @@ program NpcTest {
|
|||
west = Math.min(west, p.x)
|
||||
}
|
||||
expect(west > -50.5)
|
||||
var fell = 0
|
||||
let fs = q_drain(npc_facts(npc_st))
|
||||
for i in 0 .. len(fs) {
|
||||
if fs[i].what == NPC_F_STUCK and fs[i].x > -52.0 { fell += 1 }
|
||||
}
|
||||
expect(fell >= 1)
|
||||
}
|
||||
|
||||
test "a step's spot is where its hours say: the shore by day, home by night" (npc_st: mut NpcState, npc_tests_fake_st: mut NpcTestsFakeState) {
|
||||
|
|
|
|||
|
|
@ -78,5 +78,7 @@ program NpcWayTest {
|
|||
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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export function npc_walk(npc_st: mut NpcState, p: NpcPerson, dt: float) -> void
|
|||
p.stall = p.stall + dt
|
||||
if p.stall > p.stall_max { p.stall_max = p.stall }
|
||||
if p.detours < 10 and np_detour(p, want) {
|
||||
np_stuck_fact(npc_st, p, NPC_STUCK_DETOUR)
|
||||
p.detours += 1
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
# way.ludic - where a person walks when the straight line will not do: the world's way (NpcWorld.way,
|
||||
# a navmesh by a person's taste in Maroon Lake), and without one a step round what is in the way,
|
||||
# and giving the target up after three tries
|
||||
# and giving the target up after three tries - each of those a NPC_F_STUCK fact, so the fallback is seen
|
||||
export const NPC_STUCK_DETOUR: int = 0 # a step round what was in front of it
|
||||
export const NPC_STUCK_RETRY: int = 1 # no closer for twenty seconds, or no step round: planned again
|
||||
export const NPC_STUCK_GAVE_UP: int = 2 # the third of those: the target given up
|
||||
function np_stuck_fact(npc_st: NpcState, p: NpcPerson, how: int) -> void {
|
||||
let f = np_fact(npc_st, NPC_F_STUCK, p, -1)
|
||||
f.how = how
|
||||
f.x = p.x
|
||||
f.z = p.z
|
||||
}
|
||||
|
||||
# the next corner toward the target, asked again every half second, on reaching it, or for a new target
|
||||
const NP_WAY_EVERY: float = 0.5
|
||||
|
|
@ -39,7 +48,11 @@ function np_stuck(npc_st: mut NpcState, p: NpcPerson) -> void {
|
|||
p.fails += 1
|
||||
p.via_on = false
|
||||
if p.fails >= 3 {
|
||||
np_stuck_fact(npc_st, p, NPC_STUCK_GAVE_UP)
|
||||
p.fails = 0
|
||||
npc_wander(npc_st, p)
|
||||
} else { npc_plan(npc_st, p) }
|
||||
} else {
|
||||
np_stuck_fact(npc_st, p, NPC_STUCK_RETRY)
|
||||
npc_plan(npc_st, p)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue