feat: add NPC schedules with sleep, meal, and work periods

Add ACTION_SLEEP with home-position targeting and energy restoration. Embed schedule periods (SLEEP/MEAL/WORK/DISCRETIONARY) in ActionSelectionSystem with TimeOfDay from SimulationClock. NPCs sleep at night when energy is low, eat during meal periods when hungry, and work/discretionary the rest of the cycle. Home position stored per NPC and serialized through NPCStateRecord with backward-compatible fallback. Cycle duration persisted through save/restore. Includes headless test for sleep period, work period, meal hunger, energy restoration, serialization round-trip, and home targeting without world adapter.
This commit is contained in:
2026-07-08 17:44:39 +02:00
parent 6fdb9ba50f
commit 4604dc6d5a
12 changed files with 311 additions and 9 deletions
+5
View File
@@ -26,6 +26,7 @@ static func capture(npc: SimNPC) -> NPCStateRecord:
"current_task": String(npc.current_task),
"task_state": String(npc.task_state),
"position": [npc.position.x, npc.position.y, npc.position.z],
"home_position": [npc.home_position.x, npc.home_position.y, npc.home_position.z],
"is_starving": npc.is_starving,
"starvation_ticks": npc.starvation_ticks,
"starvation_death_threshold": npc.starvation_death_threshold,
@@ -137,6 +138,10 @@ func restore(debug_logs: bool) -> SimNPC:
npc.position = Vector3(
float(saved_position[0]), float(saved_position[1]), float(saved_position[2])
)
var saved_home: Array = data.get("home_position", saved_position)
npc.home_position = Vector3(
float(saved_home[0]), float(saved_home[1]), float(saved_home[2])
)
npc.is_starving = bool(data["is_starving"])
npc.starvation_ticks = int(data["starvation_ticks"])
npc.starvation_death_threshold = int(data["starvation_death_threshold"])