Kaggle / Kaggle/kaggle-environments

Bug: OOB check destroys fleets before collision detection runs

Open Beginner friendly
#1,017 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
452
Forks
190
Avg merge
31m
Merged PRs (30d)
2

Description

Fast fleets near the board edge get destroyed instead of captured. The engine checks out-of-bounds before checking if the fleet's path passed through a planet.

## Reproduction

Seed 62, 2 players. Player 0 accumulates ~1000 ships on planet 8 (static, at (95.4, 63.7)) and sends them at planet 0 (at (98.6, 98.6), radius 1.0 — 0.42 units from the top board edge).

At 1000 ships the fleet travels at speed 6. On the final step it starts 2.28 units from the target center, overshoots 6 units, and lands at y≈102.2 — outside the board.

The fleet's path segment passes within 0.0001 units of the planet center. `point_to_segment_distance` would return a hit. But the OOB check at line 586 destroys the fleet before the collision check at line 598 runs.

Attached: HTML replay showing the fleet vanish at step 206.

[oob_bug_replay.html](https://github.com/user-attachments/files/27088482/oob_bug_replay.html)

## The problem

In `orbit_wars.py`, fleet processing (line 575–601) runs checks in this order:

```python
for fleet in obs0.fleets:
# ... move fleet ...
old_pos = (fleet[2], fleet[3])
fleet[2] += math.cos(angle) * speed
fleet[3] += math.sin(angle) * speed
new_pos = (fleet[2], fleet[3])

# 1. OOB check — destroys fleet immediately
if not (0 <= fleet[2] <= BOARD_SIZE and 0 <= fleet[3] <= BOARD_SIZE):
fleets_to_remove.append(fleet)
continue # <-- skips collision check

# 2. Sun check
if point_to_segment_distance((CENTER, CENTER), old_pos, new_pos) < SUN_RADIUS:
fleets_to_remove.append(fleet)
continue

# 3. Planet collision (continuous — checks full path segment)
for planet in obs0.planets:
planet_pos = (planet[2], planet[3])
if point_to_segment_distance(planet_pos, old_pos, new_pos) < planet[4]:
combat_lists[planet[0]].append(fleet)
fleets_to_remove.append(fleet)
break
```

The `continue` at line 588 skips step 3 entirely.

## Proposed fix

Move the planet collision check before the OOB check. Use `for...else` so OOB only triggers when no planet captured the fleet:

```python
for fleet in obs0.fleets:
# ... move fleet ...

# 1. Sun check (always fatal)
if point_to_segment_distance((CENTER, CENTER), old_pos, new_pos) < SUN_RADIUS:
fleets_to_remove.append(fleet)
continue

# 2. Planet collision (continuous — checks full path segment)
for planet in obs0.planets:
planet_pos = (planet[2], planet[3])
if point_to_segment_distance(planet_pos, old_pos, new_pos) < planet[4]:
combat_lists[planet[0]].append(fleet)
fleets_to_remove.append(fleet)
break
else:
# 3. OOB check — only if no planet was hit
if not (0 <= fleet[2] <= BOARD_SIZE and 0 <= fleet[3] <= BOARD_SIZE):
fleets_to_remove.append(fleet)
```

This preserves all existing behavior except the edge case: a fleet whose path passes through a planet but whose endpoint lands OOB now gets captured instead of destroyed.

Contributor guide

Open the contributing guide

Research direction

Start in orbit_wars.py around lines 575–601 and reproduce the issue with seed 62 using the attached HTML replay as a reference. Trace the fleet movement, sun, planet-collision, and out-of-bounds checks. Done means a fleet whose path crosses a planet but ends outside the board is captured rather than destroyed, while existing behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
game-dev
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.