# Bombahead Python SDK

Welcome to the `bombahead-py` documentation. This SDK is designed for developers who wish to build autonomous agents (bots) for the Bombahead competition. 

As software engineers, our goal is to abstract away the underlying networking protocols, serialization formats, and game loop timing. The SDK handles all of these infrastructural concerns, allowing you to focus purely on the algorithmic design of your bot: state evaluation, pathfinding, and decision-making.

---

## 1. Getting Started

The SDK requires Python 3.10 or higher. You can install it directly via pip:

```bash
pip install bombahead-py
```

---

## 2. Core Architecture

The architecture of the SDK is built around a simple reactive event loop. Your bot operates as an asynchronous callback invoked upon receiving a state update from the server.

To implement a bot, you must define a class that satisfies the `Bot` protocol. This requires implementing a single method: `get_next_move(self, state: GameState, helpers: GameHelpers) -> Action`.

### Example: A Minimal Bot

```python
from bombahead import Action, Bot, GameHelpers, GameState, run

class MyBot(Bot):
    def get_next_move(self, state: GameState, helpers: GameHelpers) -> Action:
        # A trivial policy: always do nothing.
        return Action.DO_NOTHING

if __name__ == "__main__":
    # `run` blocks the main thread, handling the event loop and network I/O
    run(MyBot())
```

---

## 3. State Representation (`GameState`)

The `GameState` object provides a complete snapshot of the game environment at the current tick.

### 3.1 Properties of `GameState`
- **`current_tick: int`**: The discrete time step of the current simulation frame.
- **`me: Player | None`**: Your bot's entity. It may be `None` if the game has not fully initialized or if your bot has been eliminated.
- **`opponents: list[Player]`**: A list of active adversary entities.
- **`field: Field`**: The 2D grid representing the arena.
- **`bombs: list[Bomb]`**: Active bombs currently placed on the field.
- **`explosions: list[Position]`**: Positions currently covered by active blast waves.

### 3.2 Key Models

**`Player`**
- `id: str`: The unique identifier.
- `pos: Position`: The entity's coordinate.
- `health: int`: Current hit points.
- `score: int`: Current accumulated score.

**`Position`**
A simple immutable 2D vector `(x, y)`. Provides a utility method `distance_to(other: Position) -> int` to compute the Manhattan distance (L1 norm) between two points.

**`Bomb`**
- `pos: Position`: Where the bomb is placed.
- `fuse: int`: Ticks remaining until detonation. A fuse of `1` means it detonates on the next tick.

**`Field`**
Represents the discrete matrix of the game.
- `width: int`, `height: int`: The dimensions of the map.
- `cell_at(pos: Position) -> CellType`: Safely returns the material of a given coordinate. Out-of-bounds coordinates implicitly return `CellType.WALL`.

**`CellType` Enum**
- `AIR`: Traversable space.
- `WALL`: Indestructible boundary or obstacle.
- `BOX`: Destructible obstacle that may yield points or clear paths.

---

## 4. The Decision Space (`Action`)

Your algorithmic policy must evaluate the state and return one of the following deterministic actions defined in the `Action` enum:

- `Action.MOVE_UP`
- `Action.MOVE_DOWN`
- `Action.MOVE_LEFT`
- `Action.MOVE_RIGHT`
- `Action.PLACE_BOMB`
- `Action.DO_NOTHING`

---

## 5. Algorithmic Helpers (`GameHelpers`)

To accelerate development and prevent the reinvention of standard algorithms, the SDK provides the `GameHelpers` class. This is instantiated automatically per tick and provides optimized implementations for common spatial queries.

### Navigation and Traversal
- **`is_walkable(pos: Position) -> bool`**
  Checks if a position is strictly within bounds, not a wall, not a box, and not currently occupied by a bomb.
  
- **`get_adjacent_walkable_positions(pos: Position) -> list[Position]`**
  Returns a list of orthogonally adjacent coordinates that are currently walkable.
  
- **`get_next_action_towards(start: Position, target: Position) -> Action`**
  Computes the shortest path from `start` to `target` using Breadth-First Search (BFS). Returns the immediate `Action` required to step along that path. If no path exists, returns `Action.DO_NOTHING`.

### Hazard Analysis
- **`is_safe(pos: Position) -> bool`**
  A critical heuristic. Evaluates whether a given position is currently free of bombs, active explosions, and *imminent* blast radii (i.e., it simulates bomb blast patterns across the grid).

- **`get_nearest_safe_position(start: Position) -> Position`**
  Uses BFS to locate the closest coordinate that satisfies `is_safe() == True`. Crucial for evasion routines. If the current position is already safe, it returns `start`.

### Tactical Queries
- **`find_nearest_box(start: Position) -> tuple[Position, bool]`**
  Locates the closest destructible `BOX` using BFS. Returns a tuple `(Position, bool)`. The boolean indicates whether a box was successfully found.

---

## 6. Design Philosophy & Advice

As you design your bot, treat the `get_next_move` function as a pure functional mapping from State to Action. Avoid relying heavily on external mutable state across ticks unless you are implementing advanced predictive models or tracking specific adversary behaviors.

**A Recommended Architecture:**
1. **Survival Prioritization:** Always check if your current `Position` is safe (`helpers.is_safe()`). If not, immediately defer to `helpers.get_next_action_towards()` targeting `helpers.get_nearest_safe_position()`.
2. **Offensive Strategy:** If safe, locate targets (boxes or opponents) and evaluate if placing a bomb will yield a strategic advantage without trapping your own bot.
3. **Traversal:** Use the pathfinding helpers to close the distance to targets.

Good luck, and build algorithms that are both robust and theoretically sound.
