# Receitas de jogadas profissionais

> A maior parte da vantagem de um jogador de alto nível vem de dezenas de pequenos hábitos. Esta página traduz, uma a uma, técnicas comuns dos profissionais em código do SDK — cada trecho pode ser colado direto no on_tick.

Fonte: https://war3ai.com/pt/docs/cookbook/

Convenções: `g` é o `Game`, `home` é a nossa base principal (`g.my_buildings({"htow", "hkee", "hcas"})[0]`), `now = g.clock()`. Para detalhes das APIs, veja a [referência da API](https://war3ai.com/pt/api/); exemplos completos e executáveis estão em [Bots de exemplo](https://war3ai.com/pt/docs/examples/).

> **Dica**
>
> Quando pedir a um LLM para adicionar uma técnica, cole para ele a receita correspondente junto com o código. Isso funciona muito melhor do que dizer "jogue mais como um profissional".

## I. Economia

### 1. Trabalhadores nunca ociosos, 5 por mina

```python
for w in g.idle_workers():                                   # só designa os ociosos (dar nova ordem a quem está ocupado interrompe a coleta)
    mine = g.nearest([m for m in g.gold_mines() if crew[m.addr] < 5], w)
    g.gather(w, mine) if mine else g.gather(w, g.trees(w.x, w.y, limit=1)[0])
```

Anote você mesmo quantos mandou para cada mina (`crew`): trabalhadores dentro de uma mina de ouro não aparecem no snapshot. Exemplo completo em `hello_bot.py`.

### 2. Só 1 na fila, sem travar o ouro

```python
for b in g.my_buildings({"hbar"}):
    if not g.queue(b):                                       # só enfileira o próximo quando a fila esvaziar
        g.train(b, "hfoo")
```

### 3. Nunca travar por comida

```python
stuck = any(p.blocked for _b, p in g.all_production("me"))  # na fila mas não começou = falta comida
res = g.resources()
if stuck or res["food_cap"] - res["food_used"] <= 6:
    g.build_near(builder, "hhou", home.x, home.y)
```

`blocked` avisa um passo antes de "quase cheio": quando você perde parte do exército numa luta e a fila trava na hora de repor, você fica sabendo na hora.

### 4. Ordem de construção + voltar à mina ao terminar (Shift para voltar a minerar)

```python
spot = g.build_near(w, "hbar", home.x, home.y)
if spot:
    g.gather(w, mine, queue="after")                         # volta a minerar ao terminar, sem precisar procurá-lo de novo no próximo tick
```

Um camponês construindo várias em sequência: `g.build_queue(w, [("hhou", x1, y1), ("hhou", x2, y2)])`. O ouro só é descontado quando a obra começa.

### 5. Momento de subir de tier, melhorias de ataque/armadura

```python
if not g.queue(hall) and g.can_do(hall, "hkee") in (0, 220):   # a sede só melhora com a fila vazia (senão 185)
    g.upgrade(hall, "hkee")
p = g.production(hall)                                          # progresso da subida de tier
if p and p.kind == "upgrade":
    print(f"Faltam {p.remaining:.0f} segundos para a sede")
for sm in g.my_buildings({"hbla"}):
    if not g.queue(sm):
        ok = [u for u, v in zip(UPS, g.can_do_many([(sm, u) for u in UPS])) if v in (0, 220)]
        if ok:
            g.research(sm, ok[0])
```

### 6. Abrindo expansão: escolha a mina mais próxima pela distância a pé

```python
mines = [m for m in g.gold_mines() if g.dist(m, home) > 1500 and not taken(m)]
best = min(mines, key=lambda m: g.path_distance(home, m) or 1e9)   # minas em ilhas retornam None -> ficam por último
```

## II. Reconhecimento e informação

### 7. Veja o que o adversário está fazendo

```python
for b, p in g.all_production("enemy"):          # o que as construções inimigas visíveis estão treinando / pesquisando / melhorando
    print(b.type, p.kind, p.queue, f"{p.progress:.0%}" if p.progress is not None else "travada")
```

Combine com eventos: `ev.kind == "production.done" and ev.owner != g.me()` — o que o adversário acabou de produzir.

### 8. Lembre do que você já viu (névoa de guerra)

```python
for u, t, age in g.last_seen(max_age=60):       # inimigos vistos nos últimos 60 segundos de jogo (última posição e vida)
    ...
hero_seen = [r for r in g.last_seen() if r[0].is_hero]   # onde o herói inimigo foi visto pela última vez
```

No modo justo, esta é a sua única fonte de informação sobre o adversário, igual para um jogador humano.

### 9. Onde o computador vai atacar (só para a IA do computador)

```python
plan = g.enemy_ai_plan(some_enemy_soldier)      # para onde o capitão do computador está indo
```

O computador define o ponto-alvo antes de sair de casa — leve seu exército para lá com antecedência.

## III. Creeping

### 10. Creepar à noite

```python
if g.is_night():                                 # 18h ~ 6h: os creeps dormem (você ataca primeiro sem ser cercado), a visão de todos diminui
    ...
wait = g.seconds_until(18)                       # segundos de jogo até anoitecer (um dia tem 480 segundos)
```

### 11. Só ataque acampamentos que você consegue vencer

```python
from openwar3 import combat
mine = [g.stats(u) for u in army]
def ttk(target): return combat.time_to_kill(mine, g.stats(target), target_hp=target.hp) or 1e9
camp = [c for c in g.creeps() if g.dist(c, center) < 600]
ours = max(ttk(c) for c in camp)                                 # quanto tempo para limpar este acampamento (estimativa grosseira)
theirs = g.time_to_kill(camp, weakest_of_mine) or 1e9            # quanto tempo para eles matarem nossa unidade mais fraca
if ours < theirs and g.reachable(center, camp[0]):
    g.attack_move(army, camp[0].x, camp[0].y)
```

Exemplo completo: `_maybe_creep` em `micro_bot.py`.

## IV. Micro

### 12. Focar fogo: ataque o que morre mais rápido, não o mais próximo

```python
target = min(visible_enemies, key=lambda e: g.time_to_kill(fighters, e) or 1e9)
g.attack([u for u in fighters if (g.current_target(u) or target).handle != target.handle], target)
```

Só dê ordem às unidades que ainda não estão atacando o alvo (`current_target`), para não interromper as que já estão.

### 13. Recuar unidades feridas

```python
for u in army:
    if u.hp < u.hp_max * 0.35:
        g.move(u, *toward(home, u, 500))       # recua 500 na direção de casa; não puxe a mesma unidade de novo em 3 segundos
```

Como detectar fogo focado: nos eventos `damage`, a mesma unidade levando golpes de várias origens num intervalo curto = ela está cercada.

### 14. Mantenha os heróis vivos, não entregue XP

```python
for h in g.my_heroes():
    if h.hp < h.hp_max * 0.4:
        g.move(h, home.x, home.y)
        g.use_item(h, slot_of(h, "phea"))       # poção de cura: ache o número do espaço com inventory(h)
```

### 15. Vantagens de tipo: a unidade certa no alvo certo

```python
s = g.stats(u)
best = max(enemies, key=lambda e: s.dps_vs(g.stats(e)))   # fuzileiros contra grifos (perfurante vs. armadura leve ×2), grifos contra soldados (mágico vs. armadura pesada ×2)
```

A tabela de vantagens vem dos dados do jogo: `combat.damage_multiplier("pierce", "small") == 2.0`.

### 16. Flanqueio e caminhos: contorne as torres

```python
route = g.walk_path(army_center, target)        # pontos de virada do menor caminho por terra
g.path(army, route, attack=True)                # atacar-mover passando por cada ponto em ordem
```

Para evitar torres, marque a área em volta de cada torre como intransitável na grade de pathing antes de calcular a rota:

```python
grid = g.grid().copy()
for t in towers:
    grid.block_area(t.x, t.y, 800)             # alcance da torre 700 + margem
route = grid.path((army_x, army_y), (target.x, target.y))
```

### 17. Envie os comandos de um tick em um lote

```python
with g.batch():
    g.attack(melee, target_a)
    g.attack(ranged, target_b)
    g.move(wounded, *home_xy)
    g.cast(hero, "thunderclap")
```

Dezenas de comandos esperam a thread do jogo uma única vez (medido: 8 movimentos caíram de 68 ms para 6.5 ms).

### 18. Cerco: artilharia ataca o chão

```python
g.attack_ground(mortars, tower.x, tower.y)       # morteiros / demolidores atiram numa área (atrás das árvores, unidades invisíveis)
```

## V. Heróis

### 19. Ordem de habilidades

```python
SKILLS = {"Hamg": ["AHwe", "AHbz", "AHwe", "AHbz", "AHwe", "AHmt"]}   # Elemental da Água, Nevasca… no nível 6 a suprema Teleporte em Massa
info = g.hero_info(h)
if info and info["skill_points"]:
    g.learn(h, SKILLS[h.type][learned_count])  # se for rejeitado (nível baixo demais para a suprema), espere o próximo nível
```

### 20. A magia saiu mesmo?

```python
r = g.cast(h, "thunderbolt", target=enemy_hero)
# no próximo tick:
if g.cooldown(h, "AHtb"):                         # em recarga = saiu de verdade; aceito ≠ lançado
    ...
```

### 21. Comprar poções, voltar para casa

```python
g.buy(shop, "phea")                               # o herói está parado ao lado da loja
g.use_item(hero, slot, x=home.x, y=home.y)        # Pergaminho de Portal da Cidade (uso de item em ponto)
```

## VI. Revisão pós-jogo

- Registre as decisões de cada tick no log (`print` vai para a janela de execução) e use `g.say(unidade, "Recuar")` para vê-las dentro do jogo;
- Os eventos `production.done` trazem "quantos segundos levou" — monte sua própria linha do tempo de construção (em que segundo saiu o primeiro herói, em que segundo você subiu de tier) e compare com a de jogadores de alto nível;
- Deixe o agente revisar o próprio jogo: veja o relatório de partida em [Iteração autônoma do agente](https://war3ai.com/pt/docs/agent-loop/).
