"""Starter bot for StrategyBot Conquest. Upload this file as it is, then make it better.

Your file needs one function, act(state), called once per tick. Return one action:

  "NORTH" / "EAST" / "SOUTH" / "WEST"   step one cell. Into your land: a move.
                                        Into neutral land: you claim it (1 more tick).
                                        Into enemy land: a battle with your attack army.
  "BUILD MINE" / "BUILD BARRACKS" / "BUILD POST"   build where you stand
  "ALLOCATE 0.5 0.35 0.15"              re-split your army into attack/defense/reserve
                                        (only on your capital)
  "GARRISON 100" / "WITHDRAW 100"       park reserve soldiers on this cell / take them back
  "BOMB 7 4"                            strike enemy cells you can see right now (never a
  "MISSILE 7 4"                         capital, never takes land). Each weapon has its own
  "MIRV 7 4 8 5 9 4"                    gold price, range, blast and cooldown: state["rules"]
  "HBOMB 7 4"                           ["weapons"]. MIRV hits up to 3 different cells for one
                                        price. A bare "MISSILE" lets the game pick the target.
  "RELOCATE"                            move your capital to the cell you stand on (your own
                                        joined-up cell, no building): 150 gold, locks you 3 ticks
  "WAIT"

Your robot must stay joined to its capital through your own land. If an enemy takes a cell
that breaks that path, your robot is out that same tick: keep your land thick, not a snake.
While you are claiming, fighting, building or relocating you are locked: anything you send is ignored.
New soldiers arrive in reserve, so to grow your attack army you have to go home and
ALLOCATE. Anything you print() shows up in your bot's log, not in the game.

state (coordinates are [x, y], x = column, y = row, [0, 0] top-left):
  turn, turns_remaining, width, height
  phase            "setup" on tick 0 when capitals are chosen (capital_mode "choose"), else "play"
  capital_choices  in setup: the cells you may put your capital on
  owner[y][x]      -1 neutral, a team id, or None if you have never seen that cell
  seen[y][x]       the tick you last saw that cell (== turn: you see it right now)
  walls, region    blocked cells; which quarter of the map each cell is in
  capitals         the capitals you know about: [{id, x, y}]
  buildings, garrisons   what you know of them
  self             id, position, capital, army {attack, defense, reserve, garrisoned,
                   in_battle}, gold, territory_count, score, income, busy, supplied,
                   weapons {bomb, missile, mirv, hydrogen_bomb: ready_in, cost, range...},
                   relocate_ready_in
  robots           enemy robots you can see right now
  battles          battles you are in
  rules            every number in the game
  legal_actions    what you may send right now (ALLOCATE, GARRISON, BOMB take numbers)

You see your own land and the cells next to it. Everything else is memory.

This bot claims the nearest neutral cell. With nothing left to claim it goes home to
put most of its army into attack, then walks into the nearest enemy cell. It builds a
mine when it can afford one.
"""
from collections import deque

DIRS = {"NORTH": (0, -1), "EAST": (1, 0), "SOUTH": (0, 1), "WEST": (-1, 0)}


def first_step(s, start, is_goal, can_cross):
    """Breadth-first search: the first move on a shortest path to a goal cell."""
    walls = {tuple(c) for c in s["walls"]}
    robots = {tuple(r["position"]) for r in s["robots"]}
    first = {start: None}
    todo = deque([start])
    while todo:
        c = todo.popleft()
        for name, (dx, dy) in DIRS.items():
            n = (c[0] + dx, c[1] + dy)
            if not (0 <= n[0] < s["width"] and 0 <= n[1] < s["height"]) or n in walls or n in robots or n in first:
                continue
            first[n] = first[c] or name
            if is_goal(n):
                return first[n]
            if can_cross(n):
                todo.append(n)
    return None


def act(state):
    me = state["self"]
    legal = state["legal_actions"]
    if state["phase"] == "setup":
        return "WAIT"  # keep the default capital; or e.g. "CAPITAL 2 3", any cell in capital_choices
    if me["busy"]:
        return "WAIT"  # claiming, fighting, building or relocating: you are locked in

    owner = lambda c: state["owner"][c[1]][c[0]]
    mine = lambda c: owner(c) == me["id"]
    enemy = lambda c: owner(c) not in (-1, None, me["id"])
    pos, capital = tuple(me["position"]), tuple(me["capital"])
    army = me["army"]

    # a mine pays for itself in about 20 ticks (not on the capital: keep it free)
    if "BUILD MINE" in legal and pos != capital and state["turns_remaining"] > 40:
        return "BUILD MINE"

    # claim the nearest neutral (or never-seen) cell, walking through your own land
    step = first_step(state, pos, lambda c: owner(c) in (-1, None), mine)
    if step in legal:
        return step

    # nothing left to claim: low on attack soldiers? go home and re-split
    if army["attack"] < 200 and army["reserve"] + army["defense"] > 400:
        if pos == capital:
            return "ALLOCATE 0.6 0.3 0.1"
        step = first_step(state, pos, lambda c: c == capital, mine)
        if step in legal:
            return step

    # Ideas to try (uncomment one):
    # rich and an enemy cell in sight? a missile hurts its soldiers and maybe a building
    # if "MISSILE" in legal and me["gold"] >= 200:
    #     return "MISSILE"          # or "MISSILE x y" to pick the cell yourself
    # land grown far from the capital? stand in the middle of it and move the capital there
    # if "RELOCATE" in legal and me["territory_count"] > 20 and abs(pos[0] - capital[0]) + abs(pos[1] - capital[1]) > 4:
    #     return "RELOCATE"

    # walk into an enemy cell next to you, or walk to the border
    if army["attack"] >= 200:
        for name, (dx, dy) in DIRS.items():
            c = (pos[0] + dx, pos[1] + dy)
            if 0 <= c[0] < state["width"] and 0 <= c[1] < state["height"] and enemy(c) and name in legal:
                return name
        border = lambda c: mine(c) and any(
            0 <= c[0] + dx < state["width"] and 0 <= c[1] + dy < state["height"]
            and enemy((c[0] + dx, c[1] + dy)) for dx, dy in DIRS.values())
        step = first_step(state, pos, border, mine)
        if step in legal:
            return step
    return "WAIT"
