sleep_provider deconflicts beds against other pawns' targets
L: SleepProvider.find_best_for filters bed candidates via the existing Job.is_target_taken_by_other mechanism that ConstructionProvider already uses. Sets j.target_node = best_bed on the proposed job so other pawns see the claim. Fixes the 2/3-pawns-floor-sleep symptom (memory.md 2026-05-11) caused by greedy nearest-neighbor convergence. The bed.claim() mechanism was already race-free; this just prevents simultaneous proposals on the same bed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cf43ef9a98
commit
2f76ae1639
1 changed files with 9 additions and 0 deletions
|
|
@ -52,6 +52,12 @@ func find_best_for(pawn) -> Job:
|
|||
for bed in World.beds:
|
||||
if not bed.is_available():
|
||||
continue
|
||||
# Skip beds already targeted by another pawn's active job. This is the
|
||||
# same deconfliction used by ConstructionProvider (Job.is_target_taken_by_other)
|
||||
# and prevents all simultaneously-tired pawns from converging on the same
|
||||
# nearest bed and then losing the race at claim time.
|
||||
if Job.is_target_taken_by_other(bed, pawn):
|
||||
continue
|
||||
var d: int = abs(bed.tile.x - pawn.tile.x) + abs(bed.tile.y - pawn.tile.y)
|
||||
if d < best_dist:
|
||||
best_dist = d
|
||||
|
|
@ -73,6 +79,9 @@ func find_best_for(pawn) -> Job:
|
|||
var j := Job.new()
|
||||
if best_bed != null:
|
||||
j.label = "Sleep at %s" % target_tile
|
||||
# Tag the job's target so other pawns see this bed as taken via
|
||||
# Job.is_target_taken_by_other() before it is physically claimed.
|
||||
j.target_node = best_bed
|
||||
else:
|
||||
j.label = "Sleep on the floor at %s" % target_tile
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue