aboutsummaryrefslogtreecommitdiff
path: root/integration_test.go
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-05-07 12:23:50 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-05-07 12:23:50 +0200
commit9590420f5f7595021771c216f3129827a0591b37 (patch)
tree3b92adcafce35d050fb7b39d5ae6690ed510a841 /integration_test.go
parent20abde4dd780b51840e3498336bf907f0fd9164c (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.go37
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])
+}