Commit Graph
6 Commits
Author SHA1 Message Date
popertots 1d78c211ad fix: cargo standability and clear old task target
- Make is_standable return true for cargo tiles (logs, rocks can be stood on)
- Clear ambulatory.target when assigning new task to prevent old targets persisting

These fixes address the 'Lost Signal' bug where dorfs would freeze:
1. Cargo tiles were incorrectly flagged as non-standable, blocking pathfinding
2. Old Idle task targets persisted when new jobs assigned, causing dorfs to path to wrong locations
2026-04-06 00:23:09 +01:00
popertots ec1ec6b7d4 Fix bug: prevent multiple job assignments to same dorf in one frame
- Add assigned_this_frame HashSet to track dorfs receiving jobs
- Filter out already-assigned dorfs from subsequent job assignments
- Add debug logging for spawn position (z-level)
- Add debug logging for is_standable failures
- Add debug logging for falling/snapping movement behavior

This fixes the critical bug where one dorf could be assigned multiple
jobs in the same frame, causing earlier assignments to be lost due to
queue.clear(). Each dorf now receives at most one job per frame.
2026-04-05 18:09:37 +01:00
popertots 022e21d484 Fix: Don't clear ambulatory.target during job assignment
The target oscillation was caused by job_pathfinding_system
clearing ambulatory.target = None on assignment, then the executor
setting it to approach, then job_pathfinding clearing it again
the next frame.

By not clearing ambulatory.target, the executor sets it once
and it persists until the task completes.
2026-04-04 12:02:15 +01:00
popertots 7cf1b83427 Fix: Allow dorfs running Idle task to be job candidates
The bug: We excluded ALL Active state dorfs, but Idle tasks get
immediately promoted from Pending to Active by task_executor_system.
So by the time job_pathfinding runs, all dorfs are Active with Idle.

The fix: Check if dorf is 'busy' = Active AND non-Idle task.
Dorfs with Idle tasks (even in Active state) can be interrupted
for real jobs.
2026-04-04 11:53:29 +01:00
popertots 196ff9cec4 Fix job pathfinding: allow idle dorfs to be candidates + add debug logging
KEY FIX: Changed candidate filter to allow dorfs with Idle tasks:
- Before: Only dorfs with empty queues were candidates
- After: Dorfs with empty queue OR Idle task are candidates
- This fixes deadlock where all dorfs had Idle tasks and were excluded

Debug logging added:
- job_pathfinding.rs: Log job processing, candidate counts, path results
- queue_debug.rs: Show job state (Unclaimed/Calculating/Claimed/Suspended), retry count, and dorf idle status

The bug was that job_pathfinding_system filtered out ALL dorfs because:
1. job_assignment_system gave Idle tasks to dorfs with empty queues
2. task_executor_system promoted them to Active
3. job_pathfinding_system then excluded Active dorfs AND non-empty queues
2026-04-04 11:50:10 +01:00
popertots 053fe415bf Implement async job pathfinding system
- Add calculate_traversal_distance() - full A* that returns actual distance
- Add batch_calculate_traversals() for efficient batch processing
- Add Calculating state to JobState enum for dorf locking
- Add approach_target and retry_count to job Entry
- Add helper methods: is_dorf_locked, get_locked_dorfs, get_scope_for_job
- Add job_assignment config section with max_dorfs_per_job
- Create job_pathfinding.rs with main pathfinding system:
  - Throttled to MAX_JOBS_PER_TICK (5) per frame
  - Expanding scope: 5 -> 20 -> 200 dorfs based on retry count
  - Uses full pathfinding, not provisional
  - Pre-computes approach_target for assigned dorfs
- Simplify job_assignment.rs to only handle idle fallback
- Update has_fell_tree to check state (Unclaimed, Calculating, Claimed)
2026-03-29 13:13:53 +01:00