Skip to content

Internal state

The state/ layer is the drone's memory: what it knows about itself (level, inventory, food, position, orientation) and about its surroundings (the toroidal mental map). It is fed by the update callbacks and consulted by the strategy.

Module File Role
drone ai/src/state/drone.py DroneState: snapshot of the drone's state
inventory ai/src/state/inventory.py Inventory helpers
vision ai/src/state/vision.py Vision-cone geometry
world_map ai/src/state/world_map.py Toroidal mental map

DroneState — the drone's state

DroneState (ai/src/state/drone.py:28) is a @dataclass with a custom __init__ (ai/src/state/drone.py:59). On construction it:

  • sets level = 1, inventory = {}, food = 0;
  • places the position at the centre of the map: pos = (W // 2, H // 2);
  • faces the drone N;
  • builds its own WorldMap(W, H);
  • immediately sends Inventory then Look (ai/src/state/drone.py:76-86), each with its callback (update_inventory / update_vision).
self.pos = (world_map[0] // 2, world_map[1] // 2)   # centre of the map
self.direction = "N"
self.world_map = WorldMap(world_map[0], world_map[1])
...
client.send_command(inventory(), lambda line: update_inventory(self, client, line))
client.send_command(look(),      lambda line: update_vision(self, client, line))

Life methods

Method Definition Meaning
time_units_left() food * LIFE_PER_FOOD remaining life in TU (LIFE_PER_FOOD = 126, ai/src/config.py:18)
is_starving(threshold) time_units_left() < threshold imminent starvation below a TU threshold
is_dead() food <= 0 death by starvation

The position is estimated

The server never returns the drone's absolute position. pos starts from the assumed centre and is updated locally by the FSM on every move (optimistic local state, see Strategy (FSM)).

inventory — inventory helpers

inventory.py (ai/src/state/inventory.py) provides high-level access over an InventoryResult:

  • normalize_inventory(inv): a full dictionary food + the 6 stones (absent ones coerced to 0);
  • food_count(inv): the amount of food;
  • stones_count(inv): {stone: quantity for stone in STONES}always returns all 6 stones, an absent stone counting as 0.

vision — vision-cone geometry

At level n, the drone sees a cone of (n+1)² tiles. vision.py (ai/src/state/vision.py) gives the formulas:

  • tiles_count_for_level(level) = (level + 1) ** 2 (number of tiles seen);
  • row_width_for_distance(distance) = 2 * distance + 1 (width of one row).

tile_index_to_relative_coord is a dead stub

tile_index_to_relative_coord (ai/src/state/vision.py:20) raises NotImplementedError. The index → coordinate conversion geometry is in fact re-implemented inline in WorldMap.update_from_look; this stub is never called. See Known limitations.

WorldMap — toroidal mental map

WorldMap (ai/src/state/world_map.py) remembers the resources it has seen, always working in wrapped coordinates (the world is a torus).

  • wrap(x, y) = (x % width, y % height): toroidal wrap.
  • remember_tile, add_resource, remove_resource, get_resources_at: per-tile memory.
  • nearest_food(from_pos) / nearest_resource(resource, from_pos): nearest known tile by toroidal distance (toric_distance, ai/src/strategy/pathfinding.py).

update_from_look — projecting vision onto the map

update_from_look(drone_pos, drone_direction, look_tiles) (ai/src/state/world_map.py:97) is the heart of the memory: for each look tile, it derives the relative offset then rotates it according to the drone's orientation to obtain world coordinates, which it wraps and remembers:

for i, tile_objects in enumerate(look_tiles):
    level = int(math.sqrt(i))
    dx_rel = (i - level**2) - level
    dy_rel = level
    if drone_direction == "N":   real_dx, real_dy =  dx_rel, -dy_rel
    elif drone_direction == "E": real_dx, real_dy =  dy_rel,  dx_rel
    elif drone_direction == "S": real_dx, real_dy = -dx_rel,  dy_rel
    elif drone_direction == "W": real_dx, real_dy = -dy_rel, -dx_rel
    tile_pos = (drone_pos[0] + real_dx, drone_pos[1] + real_dy)
    self.remember_tile(tile_pos[0], tile_pos[1], tile_objects)

The look index i encodes the row (level = ⌊√i⌋) and the column; the N/E/S/W rotation maps the drone's “front/left-right” frame into world frame. display_map(pos) produces an ASCII debug grid.

The update_from_look above is called by the FSM states, which re-inject into the LookResult the position and orientation at the moment the Look was issued (not at the moment the response arrives). This idea of optimistic local state — updating pos/direction before the server confirms — is detailed in Strategy (FSM).

Going further