Depuração e desempenho
Por que um tick está lento, por que um comando não teve efeito, por que o jogo não se mexe. Investigue pelo sintoma e confirme com os scripts de verificação em partidas reais que vêm no projeto.
Veja o recibo
O recibo de cada comando é a pista de primeira mão:
r = g.cast(hero, "blizzard", x=tx, y=ty)
if not r:
print(r.reason, r.verdict) # rejected(…) e o código de motivo
print(r.exec_us, r.engine_us) # microssegundos que este comando levou na thread do jogo / quanto disso foi a própria função de ordem do motor
Normalmente, um comando leva de alguns microssegundos a algumas centenas de microssegundos na thread do jogo. Ao fim de um bloco de lote, g.last_receipts contém o recibo de cada comando do lote.
Veja dentro do jogo
g.say(unit, "Recuar") # um balão de fala aparece sobre a unidade (não afeta o jogo)
g.message("Indo creepar") # uma linha na área de mensagens, no canto inferior esquerdo (só visível nesta máquina)
O que você imprime com print aparece no terminal onde o Bot está rodando. Imprimir as decisões-chave de cada tick, junto com os balões de fala, é muito mais rápido do que ler o código.
Um tick está lento
Veja primeiro se é um destes casos:
| Causa | Correção |
|---|---|
| Enviar comandos um a um, cada um esperando um frame | Envolva em with g.batch():; dezenas de comandos esperam uma vez só |
Chamar g.visible() / g.can_do() uma a uma (cada chamada passa pela via rápida e espera um frame) | Para visibilidade, use u.visible_to() do snapshot; para viabilidade, pergunte em lote com g.can_do_many([...]) |
sleep ou espera dentro de on_tick | Anote o tempo de jogo e verifique de novo no tick seguinte |
| Recalcular algo caro a cada tick (caminhos, varredura do mapa inteiro) | Guarde o resultado em cache e recalcule a cada poucos ticks. g.grid() já tem cache de 2 segundos, e os níveis de tecnologia de g.stats() são atualizados a cada 5 segundos |
O jogo não se mexe / o Bot não consegue entrar na partida
| Sintoma | Causa provável |
|---|---|
| Fica sempre “esperando a partida” | Número de instância errado; ou a janela do jogo está minimizada — minimizado, a simulação do jogo para (o relógio não anda) |
| O jogo roda, mas as ordens do Bot não têm efeito | Ordens para unidades de outro jogador (recibo not_owner); ou o Bot se conectou como observer (forbidden) |
O comando fica held | A unidade está presa por uma camada de prioridade maior (a camada reflexa do cérebro de referência, uma ordem manual do console) e o comando não foi enviado |
| Ainda dá para dar comandos com o jogo pausado | Normal: na pausa, o relógio do motor para, mas a distribuição de eventos continua e os comandos são executados normalmente |
Conecte e veja o status
python -m openwar3 status --inst 5
Mostra o estado da conexão: pid do jogo, período de publicação do mundo e tempo de cada coleta, contadores da via rápida, se há uma partida em andamento, número de unidades, relógio do jogo.
Scripts de verificação em partidas reais
Abra uma instância de teste e verifique, item por item, se os recursos do SDK funcionam na sua máquina:
python tools/sdk_live_check.py --inst 20 # tudo
python tools/sdk_live_check.py --inst 20 --only prod # só uma seção
Seções: lote, tempo, produção, comandos em fila, atributos de combate, caminhos, modo justo. Cada seção dá comandos numa partida real, lê o efeito de volta e imprime quantos itens passaram.
Os testes offline não precisam do jogo aberto:
python tools/run_tests.py
“Parece bug”, mas não é
- O recibo de construção foi aceito, mas a fundação nunca aparece: o motor aceita na hora até pontos dentro da floresta, e a falha só vem quando o trabalhador chega. Use
build_near, que acompanha a construção e põe o ponto que falhou numa lista negra por um tempo. - O recibo do feitiço foi aceito, mas nada foi lançado: ele foi interrompido ou faltou mana. No tick seguinte, veja se
g.cooldown()entrou em recarga. - A ordem de ataque foi aceita, mas as tropas atacam outro alvo: para atacar um alvo específico, use
g.attack(tropa, inimigo)(semântica do clique direito). A ordem de ataque crua só troca a ordem, sem registrar o alvo, e a unidade vai atacar outra coisa por perto. - A contagem de trabalhadores não bate: trabalhadores dentro da mina de ouro não estão no snapshot.
- Não dá para treinar o herói que morreu: o herói é único; use
g.revive(altar). Reviver exige comida, e só é possível cerca de 3 segundos de jogo depois da morte.