Add session continuation prompt for next agent
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# Session Continuation Prompt
|
||||
|
||||
## A) Starting Position
|
||||
|
||||
The project had a working task system where dorfs would:
|
||||
1. Get assigned jobs (FellTree, HaulCargo)
|
||||
2. Walk to job locations
|
||||
3. Chop trees
|
||||
4. Haul logs
|
||||
|
||||
**Last Known Good Commit:** The user started from commit `3c74a68` (Refactor job queue: add JobState enum, improve pathfinding fallback). However, the system was NOT fully working - dorfs would freeze because:
|
||||
- The old provisional pathfinding used a node limit (4096) that would fail on distant jobs
|
||||
- Job assignment was using provisional pathfinding to check "reachability" which is incorrect
|
||||
- Jobs would stay `Unclaimed` forever because dorfs couldn't be assigned
|
||||
|
||||
## B) Changes Made This Session and WHY
|
||||
|
||||
### 1. New Traversal Distance Function (`src/entities/shared_systems/pathfinding.rs`)
|
||||
**WHAT:** Added `calculate_traversal_distance()` - uses full A* with 15,000 node limit (not provisional) to check if a path actually exists.
|
||||
|
||||
**WHY:** The old approach used `calculate_provisional_path()` which:
|
||||
- Returns partial paths that hit node limits
|
||||
- Was NOT designed for reachability checking
|
||||
- Would return "no path" on distant jobs even though paths exist
|
||||
|
||||
### 2. JobState Calculating (`src/entities/tasks/job_queue.rs`)
|
||||
**WHAT:** Added `Calculating(Vec<Entity>)` state to lock dorfs during pathfinding.
|
||||
|
||||
**WHY:** Prevents race conditions where two jobs try to assign the same dorf.
|
||||
|
||||
### 3. Candidate Filter Fix (`src/entities/tasks/job_pathfinding.rs`)
|
||||
**WHAT:** Changed filter from `!queue.is_empty() && !matches!(state, Active)` to allow Idle tasks.
|
||||
|
||||
```rust
|
||||
// BEFORE: Only dorfs with empty queues
|
||||
if !queue.is_empty() { return false; }
|
||||
|
||||
// AFTER: Dorfs that are idle (empty queue OR Idle task)
|
||||
let is_idle = queue.is_empty()
|
||||
|| current_task.map(|t| matches!(t, Task::Idle { .. })).unwrap_or(false);
|
||||
let is_busy = matches!(*state, TaskState::Active) && !is_idle;
|
||||
if is_busy { return false; }
|
||||
```
|
||||
|
||||
**WHY:** The `job_assignment_system` gives Idle tasks to dorfs, then `task_executor_system` promotes them to Active. All dorfs had Active+Idle state, so they were ALL filtered out.
|
||||
|
||||
### 4. Target Clearing Fix (`src/entities/tasks/job_pathfinding.rs`)
|
||||
**WHAT:** Removed `ambulatory.target = None` from job assignment.
|
||||
|
||||
**WHY:** The job_pathfinding_system was clearing `ambulatory.target` on assignment, but then the executor would set it, and the next frame job_pathfinding would clear it again. This oscillation prevented movement.
|
||||
|
||||
### 5. HaulCargo Target Fix (`src/entities/tasks/executor.rs`)
|
||||
**WHAT:** Added branch to set `ambulatory.target` when `approach.is_some()` and `target.is_none()`.
|
||||
|
||||
```rust
|
||||
} else if ambulatory.target.is_none() {
|
||||
if let Some(approach_tile) = *approach {
|
||||
ambulatory.target = Some(Vec3::new(...));
|
||||
ambulatory.current_path = None;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**WHY:** When `job_pathfinding_system` pre-computed the approach tile, the executor would skip the "find approach" block and never set the target. Dorfs had approach position but no path to walk there.
|
||||
|
||||
## C) Current Plan for Improvement
|
||||
|
||||
The architecture is correct:
|
||||
1. `job_pathfinding_system` (FixedUpdate) - Finds idle dorfs, calculates traversal distances, assigns jobs with approach targets
|
||||
2. `job_assignment_system` (FixedUpdate) - Gives Idle tasks to dorfs with empty queues
|
||||
3. `task_executor_system` (FixedUpdate) - Executes tasks, handles movement via pathfinding
|
||||
|
||||
**Planned improvements (NOT YET IMPLEMENTED):**
|
||||
- Throttling: Only process N jobs per tick to prevent CPU spikes
|
||||
- Expanding scope: Start with 5 nearest dorfs, expand to 20, then all if all fail
|
||||
- Async pathfinding: Move expensive pathfinding to background threads
|
||||
|
||||
## D) Current Issues and State
|
||||
|
||||
### Last Test Result (output5.log):
|
||||
- **Jobs ARE being assigned** - `[PATHFIND] SUCCESS` messages appeared
|
||||
- **ChopTree works** - Trees are being chopped (120 tick countdown completes)
|
||||
- **HaulCargo jobs created** - 8 HaulCargo jobs created after tree fell
|
||||
- **BUG: `target=None`** - HaulCargo tasks showed `target=None` meaning no movement path was set
|
||||
|
||||
### Last Fix Applied:
|
||||
The HaulCargo target fix (commit `8e3e8b8`) should resolve the `target=None` issue. This fix was NOT tested yet.
|
||||
|
||||
### Known Remaining Issues:
|
||||
1. **Approach tile z-level mismatch** - The BFS finds standable tiles at cargo's z-level, but the dorf might be on a different floor. The z coordinate in approach might not match the dorf's current z.
|
||||
|
||||
2. **Cargo position staleness** - If cargo moves after job is created, the job's `cargo_pos` is stale.
|
||||
|
||||
3. **No pathfinding failure recovery** - If pathfinding fails, there's no retry or fallback.
|
||||
|
||||
## E) Plan to Get to Working State
|
||||
|
||||
**DO NOT MAKE MORE FIXES WITHOUT TESTING FIRST.**
|
||||
|
||||
1. **Run the game with output logging** - Capture output6.log after the HaulCargo target fix.
|
||||
|
||||
2. **Verify the fix works** - Look for:
|
||||
- `[HAUL] {:?} setting target to approach {:?}` messages
|
||||
- `target=Some(...)` instead of `target=None`
|
||||
- Dorfs moving toward cargo (transform positions changing)
|
||||
- `[HAUL] {:?} arrived at approach {:?}, picking up cargo` messages
|
||||
- `[HAUL] {:?} picked up {:?} → hauling to {:?}` messages
|
||||
|
||||
3. **If still broken** - Use targeted debug logging:
|
||||
```rust
|
||||
info!("[DEBUG] approach={:?} target={:?} transform={:?}", approach, ambulatory.target, transform.translation);
|
||||
```
|
||||
Add this to `MovingToCargo` step in executor.rs to trace the exact state.
|
||||
|
||||
4. **Check z-level issues** - If dorfs aren't moving, check if the approach tile is reachable. The approach z might not match the dorf's z:
|
||||
- Dorf at (x, y, z=0) needs to reach cargo at (x, y, z=16)
|
||||
- Approach tile should be adjacent to cargo AND reachable from dorf's z-level
|
||||
|
||||
5. **Only after full working state** - Consider implementing:
|
||||
- Throttling (MAX_JOBS_PER_TICK)
|
||||
- Expanding scope for island scenarios
|
||||
- Async pathfinding
|
||||
|
||||
## Key Files to Focus On
|
||||
|
||||
```
|
||||
src/entities/tasks/job_pathfinding.rs - Job assignment, pathfinding trigger
|
||||
src/entities/tasks/executor.rs - Task execution, movement triggers
|
||||
src/entities/shared_systems/pathfinding.rs - calculate_traversal_distance()
|
||||
src/entities/tasks/job_queue.rs - JobState, job management
|
||||
```
|
||||
|
||||
## Debug Commands
|
||||
|
||||
```bash
|
||||
# Check compilation
|
||||
cargo check 2>&1 | tail -20
|
||||
|
||||
# Run with logging
|
||||
cargo run 2>&1 | tee output.log
|
||||
|
||||
# Search for specific log patterns
|
||||
grep -E "\[PATHFIND\] SUCCESS" output.log
|
||||
grep -E "\[HAUL\]" output.log | tail -50
|
||||
grep -E "target=None" output.log | head -10
|
||||
grep -E "setting target" output.log
|
||||
```
|
||||
|
||||
## Critical Context: The Z-Level Problem
|
||||
|
||||
The world has multiple Z-levels (not flat). A tree at position (32, 32, 16) has z=16. The trunk might be at surface level while nearby standable tiles could be at z=0, z=16, or z=32.
|
||||
|
||||
The `find_all_standable_adjacent` BFS (in executor.rs) searches for standable tiles at the cargo's z-level. This works for 2D but may fail for 3D if:
|
||||
1. Cargo is on z=16 surface
|
||||
2. Approach tile found at z=16
|
||||
3. But the dorf is at z=0 underground
|
||||
4. Pathfinding z=0 → z=16 might fail or not exist
|
||||
|
||||
**IF dorfs still freeze after the current fix, the z-level is the next place to investigate.**
|
||||
Reference in New Issue
Block a user