diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-05-07 12:23:50 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-05-07 12:23:50 +0200 |
| commit | 9590420f5f7595021771c216f3129827a0591b37 (patch) | |
| tree | 3b92adcafce35d050fb7b39d5ae6690ed510a841 /integration_test.go | |
| parent | 20abde4dd780b51840e3498336bf907f0fd9164c (diff) | |
Fix unit stopping when destination is occupied by another unit
When a unit arrived exactly MOVE_SPEED away from its destination, it would
move there via moveToward rather than snapping. On the next tick, its own
cell appeared blocked in the moveMap, triggering a repath to an adjacent
cell — causing infinite oscillation. Fix by excluding the unit's own current
cell from the blocked check before repathing. Also adds repath-to-adjacent
logic so units that arrive while the destination is genuinely occupied by
someone else settle next to it instead of stopping mid-journey.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'integration_test.go')
| -rw-r--r-- | integration_test.go | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/integration_test.go b/integration_test.go index 23d106b..7d687fb 100644 --- a/integration_test.go +++ b/integration_test.go @@ -162,3 +162,40 @@ func TestTwoEntitiesMovingToSameCellDontOverlap(t *testing.T) { assert.NotEqual(t, game.Position[unitA], game.Position[unitB], "Entity A and B should NOT overlap: A at %s, B at %s", game.Position[unitA], game.Position[unitB]) } + +func TestUnitDoesNotStopWhenDestinationOccupied(t *testing.T) { + // Unit B is far away, unit A is close. Both ordered to the same cell. + // A arrives first and settles. B should repath to an adjacent free cell + // rather than stopping mid-journey. + game := &Game{} + game.CurrentAction = Selecting + unitImg := NewFilledCircleImage(100, color.White) + + target := physics.Point{X: 500, Y: 0} + + unitA := game.Append(NewEntityBuilder(). + WithPosition(physics.Point{X: 400, Y: 0}). + WithSolid(unitImg).WithSelectable("round", selection.Unit). + WithMove().WithOrder().Build()) + unitB := game.Append(NewEntityBuilder(). + WithPosition(physics.Point{X: 0, Y: 0}). + WithSolid(unitImg).WithSelectable("round", selection.Unit). + WithMove().WithOrder().Build()) + + game.UpdateSimulation(Input{EscapePressed: true}) + game.UpdateSimulation(Input{Cursor: physics.Point{X: 50, Y: -50}, LeftMouseDown: true}) + game.UpdateSimulation(Input{Cursor: physics.Point{X: 450, Y: 50}, LeftMouseUp: true}) + game.UpdateSimulation(Input{Cursor: target, RightMouseUp: true}) + + // Run long enough for both units to settle (B travels ~5 cells) + for range 100 { + game.UpdateSimulation(Input{}) + } + + assert.False(t, game.Move[unitA].IsActive, "unit A should have stopped") + assert.False(t, game.Move[unitB].IsActive, "unit B should have stopped near target, not mid-journey") + assert.NotEqual(t, game.Position[unitA], game.Position[unitB], "units should not overlap") + // B should be adjacent to target, not stuck far away + assert.LessOrEqual(t, physics.Distance(game.Position[unitB], target), 150.0, + "unit B should be adjacent to target, got %s", game.Position[unitB]) +} |
