Docs Conceitos centrais

As quinze regras

Cada uma foi aprendida na prática, em partidas reais. Confira a lista ao escrever um Bot e você economiza a maior parte do tempo de investigação.

Entregue esta página ao LLM junto com o api.json, e o Bot que ele escrever vai tropeçar muito menos.

Ler o estado

1. Sem leitura é None, não 0

resources(), time_of_day(), production() e cooldown() podem retornar None (carregando, unidade sem detalhes, construção sem produzir…). Verifique antes de usar:

res = g.resources()
if res is None:
    return

2. Identifique unidades pelo handle, não pelo endereço

Endereços são reaproveitados por unidades novas: um endereço antigo pode apontar para uma unidade recém-criada. Para lembrar de uma unidade entre ticks, guarde u.handle e recupere com g.unit(handle).

3. O fluxo de eventos é global

production.done e unit.died incluem eventos do adversário e dos creeps. Filtre por ev.owner (ou pelo handle da construção):

if ev.kind == "production.done" and ev.owner == g.me():
    ...

4. Trabalhadores dentro da mina de ouro não estão no snapshot

No momento em que entra na mina, o trabalhador some do snapshot (unit.removed, ele não morreu). Para contar quantos há em cada mina, mantenha a sua própria contagem, não a recalcule pelo snapshot — senão você manda gente demais para uma mina cheia.

Dar comandos

5. Recibo “aceito” ≠ concluído

O motor aceita na hora até um ponto de construção dentro da floresta, e a falha só vem quando o trabalhador chega; habilidades podem ser interrompidas. Confira o efeito pelo snapshot e pelos eventos: para construir, use build_near (ele acompanha se a fundação aparece); para habilidades, veja se g.cooldown() entrou em recarga.

6. Não dá para atacar o que não se vê

Comandos com alvo em inimigos na névoa de guerra são rejeitados com o código de motivo 1001. Para perseguir um inimigo na névoa, use attack_move na última posição em que ele apareceu.

7. Só dê ordens a unidades ociosas

Repetir o mesmo comando para a mesma unidade a cada tick a interrompe: os soldados ficam tremendo no lugar e o ciclo de coleta dos camponeses volta a zero. Para saber se ela está “ociosa”, use g.order_of(u) (que inclui o que você acabou de mandar neste tick), não o u.order do snapshot (o snapshot ainda não se atualizou).

8. Shift só “insere logo depois da atual”

O motor não tem “adicionar ao final”: enviar B e C seguidos com queue='after' resulta em A, C, B. Para percorrer uma série de pontos em ordem, use g.path(units, lista_de_pontos); para um trabalhador construir várias em sequência, use g.build_queue(worker, plano) — eles inserem em ordem inversa e cuidam disso por você.

9. Os comandos de um tick saem em um lote

Enviar dezenas de comandos um a um significa esperar a thread do jogo dezenas de vezes; dentro de with g.batch():, a espera é uma só.

Economia e produção

10. No máximo 5 trabalhadores por mina

Mais que isso não aumenta a renda. A meta de trabalhadores acompanha o número de minas: 5 no ouro por mina, mais alguns na madeira.

11. Só 1 na fila de treino

Encher as 7 vagas prende o dinheiro na fila (nos testes, 4 camponeses na fila do edifício principal prenderam 300 de ouro, e o início ficou bem mais lento). Coloque o próximo quando g.queue(b) esvaziar.

12. Comida travada: olhe a tabela de produção

g.production(b).blocked = há algo na fila, mas não começou; quase sempre é falta de comida. Isso avisa um passo antes de “construir quando a comida estiver perto do limite”: você perde um monte de tropas numa luta, a fila trava na hora de repor, e você fica sabendo na hora.

13. O herói é único; com a fila do edifício principal ocupada, não dá para subir de tier

  • Se o herói morrer, só dá para usar g.revive(altar); treinar de novo é rejeitado (221); reviver também exige comida (o herói ocupa 5).
  • Com algo na fila do edifício principal, não dá para melhorá-lo (código de motivo 185, “construção ocupada”).

Tempo e espaço

14. Na velocidade 2×, não se guie pelo relógio de parede

Para esperar 3 segundos de jogo, veja g.clock() subir 3, não use sleep(1.5). Com o jogo acelerado, o relógio do motor anda mais rápido que o relógio de parede.

15. Em mapas de ilhas ou com florestas, não use distância em linha reta

Para escolher acampamentos de creeps e expansões, use g.path_distance(a, b) (A* por terra, contornando florestas, penhascos e construções); se não houver caminho, retorna None. O ponto mais próximo em linha reta pode estar do outro lado do mar.

Mais uma: escreva para o modo justo

Com --fair, você só vê unidades, itens, produção e eventos dentro da sua visão — essa é a regra da Arena. Escreva para o modo justo desde já e, quando for para a Arena, não vai precisar mudar nada. Veja Modo justo.