Add named Marks and cross-room NPC pathfinding

- Mark: a debug non-collidable named destination (pixel-art target icon),
  editor tool + name modal, globally-unique names, programmatic Room:addMark
- NPCs walk to Marks: each RGB copy is a per-room resident (like the player),
  running its own A* on its own colour layer, transferring rooms as it crosses
  seams; rendered and collided by the room it currently stands in
- Player copies are obstacles in NPC pathfinding
- A* is footprint-aware for multi-cell NPCs
- Editor: click an NPC to open a filterable destination picker
- Ink: Dialogue.open binds walk_to; Jorge can be sent to "end"/"begin"
- Fix: a blocked NPC now replans each tick and resumes instead of freezing
- [npc] move diagnostics under DEBUG (start/goal/route or block reason)
- Docs (adding-npcs) + CLAUDE.md LÖVE 11.x/float-colour corrections
- Fix test harness loadSprite stub; movement tests green (28)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-08-21 15:56:53 -04:00
parent ad405ed590
commit c348b81a93
17 changed files with 2755 additions and 43 deletions

888
rooms/room_16_17.sav Normal file
View file

@ -0,0 +1,888 @@
{
objects={
{
x=1,
class="static_wall",
y=1,
color="green"
},
{
x=1,
class="static_wall",
y=2,
color="green"
},
{
x=1,
class="static_wall",
y=3,
color="green"
},
{
x=1,
class="static_wall",
y=4,
color="green"
},
{
x=1,
class="static_wall",
y=1,
color="green"
},
{
x=2,
class="static_wall",
y=1,
color="green"
},
{
x=3,
class="static_wall",
y=1,
color="green"
},
{
x=4,
class="static_wall",
y=1,
color="green"
},
{
x=5,
class="static_wall",
y=1,
color="green"
},
{
x=6,
class="static_wall",
y=1,
color="green"
},
{
x=6,
class="static_wall",
y=1,
color="green"
},
{
x=7,
class="static_wall",
y=1,
color="green"
},
{
x=8,
class="static_wall",
y=1,
color="green"
},
{
x=9,
class="static_wall",
y=1,
color="green"
},
{
x=10,
class="static_wall",
y=1,
color="green"
},
{
x=11,
class="static_wall",
y=1,
color="green"
},
{
x=11,
class="static_wall",
y=2,
color="green"
},
{
x=11,
class="static_wall",
y=3,
color="green"
},
{
x=11,
class="static_wall",
y=4,
color="green"
},
{
x=11,
class="static_wall",
y=5,
color="green"
},
{
x=11,
class="static_wall",
y=4,
color="green"
},
{
x=11,
class="static_wall",
y=5,
color="green"
},
{
x=11,
class="static_wall",
y=6,
color="green"
},
{
x=11,
class="static_wall",
y=7,
color="green"
},
{
x=11,
class="static_wall",
y=8,
color="green"
},
{
x=11,
class="static_wall",
y=9,
color="green"
},
{
x=11,
class="static_wall",
y=10,
color="green"
},
{
x=11,
class="static_wall",
y=11,
color="green"
},
{
x=10,
class="static_wall",
y=11,
color="green"
},
{
x=9,
class="static_wall",
y=11,
color="green"
},
{
x=8,
class="static_wall",
y=11,
color="green"
},
{
x=7,
class="static_wall",
y=11,
color="green"
},
{
x=6,
class="static_wall",
y=11,
color="green"
},
{
x=5,
class="static_wall",
y=11,
color="green"
},
{
x=4,
class="static_wall",
y=11,
color="green"
},
{
x=1,
class="static_wall",
y=11,
color="green"
},
{
x=2,
class="static_wall",
y=11,
color="green"
},
{
x=3,
class="static_wall",
y=11,
color="green"
},
{
x=4,
class="static_wall",
y=11,
color="green"
},
{
x=6,
class="static_wall",
y=8,
color="green"
},
{
x=6,
class="static_wall",
y=7,
color="green"
},
{
x=6,
class="static_wall",
y=6,
color="green"
},
{
x=6,
class="static_wall",
y=5,
color="green"
},
{
x=6,
class="static_wall",
y=4,
color="green"
},
{
x=6,
class="static_wall",
y=4,
color="green"
},
{
x=7,
class="static_wall",
y=9,
color="green"
},
{
x=9,
class="static_wall",
y=7,
color="green"
},
{
x=10,
class="static_wall",
y=7,
color="green"
},
{
x=1,
class="static_wall",
y=1,
color="blue"
},
{
x=1,
class="static_wall",
y=2,
color="blue"
},
{
x=1,
class="static_wall",
y=3,
color="blue"
},
{
x=1,
class="static_wall",
y=4,
color="blue"
},
{
x=1,
class="static_wall",
y=1,
color="blue"
},
{
x=2,
class="static_wall",
y=1,
color="blue"
},
{
x=3,
class="static_wall",
y=1,
color="blue"
},
{
x=4,
class="static_wall",
y=1,
color="blue"
},
{
x=5,
class="static_wall",
y=1,
color="blue"
},
{
x=6,
class="static_wall",
y=1,
color="blue"
},
{
x=6,
class="static_wall",
y=1,
color="blue"
},
{
x=7,
class="static_wall",
y=1,
color="blue"
},
{
x=8,
class="static_wall",
y=1,
color="blue"
},
{
x=9,
class="static_wall",
y=1,
color="blue"
},
{
x=10,
class="static_wall",
y=1,
color="blue"
},
{
x=11,
class="static_wall",
y=1,
color="blue"
},
{
x=11,
class="static_wall",
y=2,
color="blue"
},
{
x=11,
class="static_wall",
y=3,
color="blue"
},
{
x=11,
class="static_wall",
y=4,
color="blue"
},
{
x=11,
class="static_wall",
y=5,
color="blue"
},
{
x=11,
class="static_wall",
y=4,
color="blue"
},
{
x=11,
class="static_wall",
y=5,
color="blue"
},
{
x=11,
class="static_wall",
y=6,
color="blue"
},
{
x=11,
class="static_wall",
y=7,
color="blue"
},
{
x=11,
class="static_wall",
y=8,
color="blue"
},
{
x=11,
class="static_wall",
y=9,
color="blue"
},
{
x=11,
class="static_wall",
y=10,
color="blue"
},
{
x=11,
class="static_wall",
y=11,
color="blue"
},
{
x=10,
class="static_wall",
y=11,
color="blue"
},
{
x=9,
class="static_wall",
y=11,
color="blue"
},
{
x=8,
class="static_wall",
y=11,
color="blue"
},
{
x=7,
class="static_wall",
y=11,
color="blue"
},
{
x=6,
class="static_wall",
y=11,
color="blue"
},
{
x=5,
class="static_wall",
y=11,
color="blue"
},
{
x=4,
class="static_wall",
y=11,
color="blue"
},
{
x=1,
class="static_wall",
y=11,
color="blue"
},
{
x=2,
class="static_wall",
y=11,
color="blue"
},
{
x=3,
class="static_wall",
y=11,
color="blue"
},
{
x=4,
class="static_wall",
y=11,
color="blue"
},
{
x=1,
class="static_wall",
y=8,
color="blue"
},
{
x=2,
class="static_wall",
y=8,
color="blue"
},
{
x=4,
class="static_wall",
y=7,
color="blue"
},
{
x=4,
class="static_wall",
y=6,
color="blue"
},
{
x=4,
class="static_wall",
y=6,
color="blue"
},
{
x=4,
class="static_wall",
y=5,
color="blue"
},
{
x=4,
class="static_wall",
y=4,
color="blue"
},
{
x=5,
class="static_wall",
y=8,
color="blue"
},
{
x=6,
class="static_wall",
y=8,
color="blue"
},
{
x=7,
class="static_wall",
y=8,
color="blue"
},
{
x=1,
class="static_wall",
y=1,
color="red"
},
{
x=1,
class="static_wall",
y=2,
color="red"
},
{
x=1,
class="static_wall",
y=1,
color="red"
},
{
x=1,
class="static_wall",
y=2,
color="red"
},
{
x=1,
class="static_wall",
y=3,
color="red"
},
{
x=1,
class="static_wall",
y=4,
color="red"
},
{
x=1,
class="static_wall",
y=1,
color="red"
},
{
x=2,
class="static_wall",
y=1,
color="red"
},
{
x=3,
class="static_wall",
y=1,
color="red"
},
{
x=4,
class="static_wall",
y=1,
color="red"
},
{
x=5,
class="static_wall",
y=1,
color="red"
},
{
x=6,
class="static_wall",
y=1,
color="red"
},
{
x=6,
class="static_wall",
y=1,
color="red"
},
{
x=7,
class="static_wall",
y=1,
color="red"
},
{
x=8,
class="static_wall",
y=1,
color="red"
},
{
x=9,
class="static_wall",
y=1,
color="red"
},
{
x=10,
class="static_wall",
y=1,
color="red"
},
{
x=11,
class="static_wall",
y=1,
color="red"
},
{
x=11,
class="static_wall",
y=2,
color="red"
},
{
x=11,
class="static_wall",
y=3,
color="red"
},
{
x=11,
class="static_wall",
y=4,
color="red"
},
{
x=11,
class="static_wall",
y=5,
color="red"
},
{
x=11,
class="static_wall",
y=4,
color="red"
},
{
x=11,
class="static_wall",
y=5,
color="red"
},
{
x=11,
class="static_wall",
y=6,
color="red"
},
{
x=11,
class="static_wall",
y=7,
color="red"
},
{
x=11,
class="static_wall",
y=8,
color="red"
},
{
x=11,
class="static_wall",
y=9,
color="red"
},
{
x=11,
class="static_wall",
y=10,
color="red"
},
{
x=11,
class="static_wall",
y=11,
color="red"
},
{
x=10,
class="static_wall",
y=11,
color="red"
},
{
x=9,
class="static_wall",
y=11,
color="red"
},
{
x=8,
class="static_wall",
y=11,
color="red"
},
{
x=7,
class="static_wall",
y=11,
color="red"
},
{
x=6,
class="static_wall",
y=11,
color="red"
},
{
x=5,
class="static_wall",
y=11,
color="red"
},
{
x=4,
class="static_wall",
y=11,
color="red"
},
{
x=1,
class="static_wall",
y=11,
color="red"
},
{
x=2,
class="static_wall",
y=11,
color="red"
},
{
x=3,
class="static_wall",
y=11,
color="red"
},
{
x=4,
class="static_wall",
y=11,
color="red"
},
{
x=4,
class="static_wall",
y=4,
color="red"
},
{
x=4,
class="static_wall",
y=5,
color="red"
},
{
x=5,
class="static_wall",
y=5,
color="red"
},
{
x=10,
class="static_wall",
y=10,
color="red"
},
{
x=9,
class="static_wall",
y=10,
color="red"
},
{
x=8,
class="static_wall",
y=9,
color="red"
},
{
x=7,
class="static_wall",
y=9,
color="red"
},
{
x=7,
class="static_wall",
y=8,
color="red"
},
{
x=7,
class="mark",
name="end",
y=6
}
},
wires={
}
}

917
rooms/testing_movement.sav Normal file
View file

@ -0,0 +1,917 @@
{
objects={
{
x=11,
class="static_wall",
y=7,
color="green"
},
{
x=11,
class="static_wall",
y=4,
color="green"
},
{
x=11,
class="static_wall",
y=3,
color="green"
},
{
x=11,
class="static_wall",
y=2,
color="green"
},
{
x=11,
class="static_wall",
y=1,
color="green"
},
{
x=10,
class="static_wall",
y=1,
color="green"
},
{
x=10,
class="static_wall",
y=1,
color="green"
},
{
x=9,
class="static_wall",
y=1,
color="green"
},
{
x=8,
class="static_wall",
y=1,
color="green"
},
{
x=7,
class="static_wall",
y=1,
color="green"
},
{
x=6,
class="static_wall",
y=1,
color="green"
},
{
x=5,
class="static_wall",
y=1,
color="green"
},
{
x=4,
class="static_wall",
y=1,
color="green"
},
{
x=4,
class="static_wall",
y=1,
color="green"
},
{
x=3,
class="static_wall",
y=1,
color="green"
},
{
x=2,
class="static_wall",
y=1,
color="green"
},
{
x=1,
class="static_wall",
y=1,
color="green"
},
{
x=1,
class="static_wall",
y=2,
color="green"
},
{
x=1,
class="static_wall",
y=3,
color="green"
},
{
x=1,
class="static_wall",
y=4,
color="green"
},
{
x=1,
class="static_wall",
y=5,
color="green"
},
{
x=1,
class="static_wall",
y=6,
color="green"
},
{
x=1,
class="static_wall",
y=7,
color="green"
},
{
x=1,
class="static_wall",
y=8,
color="green"
},
{
x=1,
class="static_wall",
y=9,
color="green"
},
{
x=1,
class="static_wall",
y=10,
color="green"
},
{
x=1,
class="static_wall",
y=11,
color="green"
},
{
x=2,
class="static_wall",
y=11,
color="green"
},
{
x=3,
class="static_wall",
y=11,
color="green"
},
{
x=4,
class="static_wall",
y=11,
color="green"
},
{
x=5,
class="static_wall",
y=11,
color="green"
},
{
x=6,
class="static_wall",
y=11,
color="green"
},
{
x=7,
class="static_wall",
y=11,
color="green"
},
{
x=8,
class="static_wall",
y=11,
color="green"
},
{
x=8,
class="static_wall",
y=11,
color="green"
},
{
x=9,
class="static_wall",
y=11,
color="green"
},
{
x=10,
class="static_wall",
y=11,
color="green"
},
{
x=11,
class="static_wall",
y=11,
color="green"
},
{
x=11,
class="static_wall",
y=10,
color="green"
},
{
x=11,
class="static_wall",
y=9,
color="green"
},
{
x=11,
class="static_wall",
y=8,
color="green"
},
{
x=11,
class="static_wall",
y=7,
color="green"
},
{
x=8,
class="static_wall",
y=2,
color="green"
},
{
x=8,
class="static_wall",
y=3,
color="green"
},
{
x=8,
class="static_wall",
y=4,
color="green"
},
{
x=8,
class="static_wall",
y=5,
color="green"
},
{
x=8,
class="static_wall",
y=8,
color="green"
},
{
x=8,
class="static_wall",
y=9,
color="green"
},
{
x=8,
class="static_wall",
y=10,
color="green"
},
{
x=8,
class="static_wall",
y=11,
color="green"
},
{
x=11,
class="static_wall",
y=7,
color="blue"
},
{
x=11,
class="static_wall",
y=4,
color="blue"
},
{
x=11,
class="static_wall",
y=3,
color="blue"
},
{
x=11,
class="static_wall",
y=2,
color="blue"
},
{
x=11,
class="static_wall",
y=1,
color="blue"
},
{
x=10,
class="static_wall",
y=1,
color="blue"
},
{
x=10,
class="static_wall",
y=1,
color="blue"
},
{
x=9,
class="static_wall",
y=1,
color="blue"
},
{
x=8,
class="static_wall",
y=1,
color="blue"
},
{
x=7,
class="static_wall",
y=1,
color="blue"
},
{
x=6,
class="static_wall",
y=1,
color="blue"
},
{
x=5,
class="static_wall",
y=1,
color="blue"
},
{
x=4,
class="static_wall",
y=1,
color="blue"
},
{
x=4,
class="static_wall",
y=1,
color="blue"
},
{
x=3,
class="static_wall",
y=1,
color="blue"
},
{
x=2,
class="static_wall",
y=1,
color="blue"
},
{
x=1,
class="static_wall",
y=1,
color="blue"
},
{
x=1,
class="static_wall",
y=2,
color="blue"
},
{
x=1,
class="static_wall",
y=3,
color="blue"
},
{
x=1,
class="static_wall",
y=4,
color="blue"
},
{
x=1,
class="static_wall",
y=5,
color="blue"
},
{
x=1,
class="static_wall",
y=6,
color="blue"
},
{
x=1,
class="static_wall",
y=7,
color="blue"
},
{
x=1,
class="static_wall",
y=8,
color="blue"
},
{
x=1,
class="static_wall",
y=9,
color="blue"
},
{
x=1,
class="static_wall",
y=10,
color="blue"
},
{
x=1,
class="static_wall",
y=11,
color="blue"
},
{
x=2,
class="static_wall",
y=11,
color="blue"
},
{
x=3,
class="static_wall",
y=11,
color="blue"
},
{
x=4,
class="static_wall",
y=11,
color="blue"
},
{
x=5,
class="static_wall",
y=11,
color="blue"
},
{
x=6,
class="static_wall",
y=11,
color="blue"
},
{
x=7,
class="static_wall",
y=11,
color="blue"
},
{
x=8,
class="static_wall",
y=11,
color="blue"
},
{
x=8,
class="static_wall",
y=11,
color="blue"
},
{
x=9,
class="static_wall",
y=11,
color="blue"
},
{
x=10,
class="static_wall",
y=11,
color="blue"
},
{
x=11,
class="static_wall",
y=11,
color="blue"
},
{
x=11,
class="static_wall",
y=10,
color="blue"
},
{
x=11,
class="static_wall",
y=9,
color="blue"
},
{
x=11,
class="static_wall",
y=8,
color="blue"
},
{
x=11,
class="static_wall",
y=7,
color="blue"
},
{
x=8,
class="static_wall",
y=2,
color="blue"
},
{
x=8,
class="static_wall",
y=3,
color="blue"
},
{
x=8,
class="static_wall",
y=4,
color="blue"
},
{
x=8,
class="static_wall",
y=5,
color="blue"
},
{
x=8,
class="static_wall",
y=8,
color="blue"
},
{
x=8,
class="static_wall",
y=9,
color="blue"
},
{
x=8,
class="static_wall",
y=10,
color="blue"
},
{
x=8,
class="static_wall",
y=11,
color="blue"
},
{
x=11,
class="static_wall",
y=7,
color="red"
},
{
x=11,
class="static_wall",
y=4,
color="red"
},
{
x=11,
class="static_wall",
y=3,
color="red"
},
{
x=11,
class="static_wall",
y=2,
color="red"
},
{
x=11,
class="static_wall",
y=1,
color="red"
},
{
x=10,
class="static_wall",
y=1,
color="red"
},
{
x=10,
class="static_wall",
y=1,
color="red"
},
{
x=9,
class="static_wall",
y=1,
color="red"
},
{
x=8,
class="static_wall",
y=1,
color="red"
},
{
x=7,
class="static_wall",
y=1,
color="red"
},
{
x=6,
class="static_wall",
y=1,
color="red"
},
{
x=5,
class="static_wall",
y=1,
color="red"
},
{
x=4,
class="static_wall",
y=1,
color="red"
},
{
x=4,
class="static_wall",
y=1,
color="red"
},
{
x=3,
class="static_wall",
y=1,
color="red"
},
{
x=2,
class="static_wall",
y=1,
color="red"
},
{
x=1,
class="static_wall",
y=1,
color="red"
},
{
x=1,
class="static_wall",
y=2,
color="red"
},
{
x=1,
class="static_wall",
y=3,
color="red"
},
{
x=1,
class="static_wall",
y=4,
color="red"
},
{
x=1,
class="static_wall",
y=5,
color="red"
},
{
x=1,
class="static_wall",
y=6,
color="red"
},
{
x=1,
class="static_wall",
y=7,
color="red"
},
{
x=1,
class="static_wall",
y=8,
color="red"
},
{
x=1,
class="static_wall",
y=9,
color="red"
},
{
x=1,
class="static_wall",
y=10,
color="red"
},
{
x=1,
class="static_wall",
y=11,
color="red"
},
{
x=2,
class="static_wall",
y=11,
color="red"
},
{
x=3,
class="static_wall",
y=11,
color="red"
},
{
x=4,
class="static_wall",
y=11,
color="red"
},
{
x=5,
class="static_wall",
y=11,
color="red"
},
{
x=6,
class="static_wall",
y=11,
color="red"
},
{
x=7,
class="static_wall",
y=11,
color="red"
},
{
x=8,
class="static_wall",
y=11,
color="red"
},
{
x=8,
class="static_wall",
y=11,
color="red"
},
{
x=9,
class="static_wall",
y=11,
color="red"
},
{
x=10,
class="static_wall",
y=11,
color="red"
},
{
x=11,
class="static_wall",
y=11,
color="red"
},
{
x=11,
class="static_wall",
y=10,
color="red"
},
{
x=11,
class="static_wall",
y=9,
color="red"
},
{
x=11,
class="static_wall",
y=8,
color="red"
},
{
x=11,
class="static_wall",
y=7,
color="red"
},
{
x=8,
class="static_wall",
y=2,
color="red"
},
{
x=8,
class="static_wall",
y=3,
color="red"
},
{
x=8,
class="static_wall",
y=4,
color="red"
},
{
x=8,
class="static_wall",
y=5,
color="red"
},
{
x=8,
class="static_wall",
y=8,
color="red"
},
{
x=8,
class="static_wall",
y=9,
color="red"
},
{
x=8,
class="static_wall",
y=10,
color="red"
},
{
x=8,
class="static_wall",
y=11,
color="red"
},
{
x=5,
class="jorge",
y=4
},
{
x=5,
class="mark",
name="begin",
y=4
}
},
wires={
}
}

View file

@ -1,6 +1,7 @@
{
width=18,
height=18,
lastRoom="blocker_test",
lastRoom="room_16_17",
rooms={
{
name="3",
@ -281,7 +282,16 @@ rooms={
name="white_ok",
x=11,
y=1
},
{
name="room_16_17",
x=16,
y=17
},
{
name="testing_movement",
x=15,
y=17
}
},
width=18
}
}