# Seu primeiro Bot

> Comece com um Bot mínimo de 10 linhas, depois adicione treino de camponeses, construções para comida, exército, heróis e ataques — e, por fim, aprenda a ler os recibos.

Fonte: https://war3ai.com/pt/docs/first-bot/

Um Bot é uma classe que herda de `openwar3.Bot`. Você só sobrescreve os hooks de que precisa; `g` (`Game`) cuida de "observar" e de "agir".

## O Bot mínimo

```python title="my_bot.py"
from openwar3 import Bot

class MyBot(Bot):
    def on_start(self, g):          # chamado uma vez depois que a partida começa
        g.message("Cheguei")

    def on_tick(self, g):           # cerca de 5 vezes por segundo
        for w in g.idle_workers():
            g.gather(w, g.nearest(g.gold_mines(), w))
```

```bash
python tools/play.py --bot my_bot.py
```

Os camponeses ociosos vão para a mina de ouro mais próxima. Os quatro hooks:

| Hook | Quando é chamado |
|---|---|
| `on_start(g)` | Uma vez depois que a partida começa, antes do primeiro tick |
| `on_tick(g)` | A cada tick (5 vezes por segundo por padrão). Se um tick passar do tempo, o próximo é adiado automaticamente — eles nunca se acumulam |
| `on_event(g, ev)` | Antes de cada `on_tick`; entrega a você, um por um, todos os eventos desde o último tick |
| `on_end(g, reason)` | Uma vez quando a partida termina (o processo do jogo sumiu / não temos mais unidades / parada manual) |

> **Dica**
>
> Uma exceção no `on_tick` não encerra a partida: o executor imprime o stack trace e segue para o próximo tick; ele só para depois de **20 ticks seguidos com erro**.

## Adicionando economia: treinar camponeses, construir para ter comida

```python
from openwar3 import Bot

class Economy(Bot):
    def on_tick(self, g):
        res = g.resources()                       # None se não der para ler, não 0
        halls = g.my_buildings({"htow", "hkee", "hcas"})
        if res is None or not halls:
            return
        home = halls[0]

        # 1. Camponeses ociosos vão minerar ouro
        for w in g.idle_workers():
            mine = g.nearest(g.gold_mines(), w)
            if mine:
                g.gather(w, mine)

        # 2. Treinar camponeses: só 1 na fila por vez (fila cheia prende o ouro nela)
        if len(g.my_workers()) < 15 and not g.queue(home):
            g.train(home, "hpea")

        # 3. Comida quase no limite: ache um camponês que não esteja construindo e faça uma Fazenda perto da sede
        if res["food_cap"] - res["food_used"] <= 6:
            builder = next((w for w in g.my_workers() if not g.is_constructing(w)), None)
            if builder:
                g.build_near(builder, "hhou", home.x, home.y)
```

Três detalhes que valem atenção:

- **Só treine quando `g.queue(home)` estiver vazia.** Dar ordem de treino a cada tick enche a fila de 7 espaços e prende seu ouro (medido: a sede enfileirou 4 camponeses, com 300 de ouro presos na fila, e a abertura ficou muito mais lenta).
- **`build_near` em vez de coordenadas fixas.** Ele procura, do mais perto para o mais longe, um lugar que caiba e acompanha o resultado ao longo dos ticks; não faz nada quando falta dinheiro. Coordenadas fixas podem muito bem cair no meio de uma floresta.
- **Não escolha camponeses que já estão construindo.** Uma Fazenda humana leva 35 segundos para ficar pronta; se você tirar o trabalhador no meio, a obra para.

A versão completa, que funciona para as quatro raças, é `brains/examples/hello_bot.py`: 5 por mina, os trabalhadores extras cortam árvores quando a mina está cheia, e ele retoma obras paradas.

## Adicionando Quartel, herói e ataques

```python
from openwar3 import Bot

WAVE = 8

class Rush(Bot):
    def on_start(self, g):
        self.attacking = False

    def on_tick(self, g):
        halls = g.my_buildings({"htow", "hkee", "hcas"})
        if not halls:
            return
        home = halls[0]

        # Herói: tem altar mas não tem herói -> reviva primeiro, só treine se não der para reviver (heróis são únicos; treinar de novo depois da morte é rejeitado)
        altars = g.my_buildings({"halt"})
        if altars and not g.my_heroes():
            if not g.revive(altars[0]):
                g.train(altars[0], "Hpal")
        for h in g.my_heroes():
            info = g.hero_info(h)
            if info and info["skill_points"]:
                g.learn(h, "AHhb")                # Luz Sagrada

        # O Quartel produz Soldados sem parar (só 1 na fila por vez)
        for b in g.my_buildings({"hbar"}):
            if not g.queue(b):
                g.train(b, "hfoo")

        # Ataca quando uma leva estiver pronta; volta para casa depois de perdas pesadas
        army = g.my_army()
        if len(army) >= WAVE:
            self.attacking = True
        elif len(army) < WAVE // 2:
            self.attacking = False
        if self.attacking:
            target = g.nearest([e for e in g.enemies() if g.is_building(e)], home)
            if target:
                idle = [u for u in army if not g.order_of(u)]      # só dá ordens às unidades ociosas
                g.attack_move(idle, target.x, target.y)
```

Para a versão completa, veja `brains/examples/rush_bot.py` (ele herda de `hello_bot` e constrói o Quartel / altar se não existirem).

## Lendo os recibos

Todo comando retorna um recibo. `if r:` significa "o engine aceitou"; quando não foi aceito, `r.reason` diz o motivo:

```python
r = g.train(barracks, "hfoo")
if not r:
    print(r.reason)        # rejected（人口不够）  (= falta comida)
    print(r.verdict)       # 3
```

Códigos de motivo comuns: `3` falta comida, `8` falta ouro, `9` falta madeira, `32` fila cheia, `183` falta pré-requisito, `221` item inexistente / em construção / você já tem este herói, `1001` alvo não visível. Para a tabela completa, veja [Recibos e códigos de motivo](https://war3ai.com/pt/docs/reason-codes/).

> **Aceito ≠ feito**
>
> O recibo só diz que "o engine aceitou este comando". O engine também aceita na hora um ponto de construção dentro de uma floresta, e o trabalhador só falha quando chega lá; magias podem ser interrompidas. Para ver o efeito real, olhe os snapshots e os eventos: para construções, use `build_near` (ele acompanha se a fundação aparece), e para magias, veja se `g.cooldown()` mostra a recarga.

## Próximos passos

  - [Modelo mental](https://war3ai.com/pt/docs/concepts/): Snapshots, comandos, eventos, ticks, lotes — por que foi projetado assim.
  - [Receitas de jogadas profissionais](https://war3ai.com/pt/docs/cookbook/): 21 receitas: mineração saturada, nunca travar por comida, focar fogo, recuar unidades feridas, creepar à noite…
