Física do jogo

As regras do mundo

Quanto custa cada ação, quanto dano cada coisa causa e como o jogo entende direções. Quem conhece estes números escreve um robô melhor, e isso é aritmética simples.

A bússola da arena

Este é o ponto que mais confunde, então vale começar por ele. No PyRobocode, o ângulo 0 aponta para baixo, e não para cima nem para a direita, como a maioria das pessoas espera. E os ângulos crescem no sentido horário.

180° para cima 0° para baixo (o padrão) 90° esquerda 270° direita o ângulo cresce nesta direção
A bússola do PyRobocode. turn(90) partindo do zero deixa o robô olhando para a esquerda da tela.
E as coordenadas?

O canto superior esquerdo da arena é o ponto (0, 0). O x cresce para a direita, como você espera. Mas o y cresce para baixo: quanto maior o y, mais perto da parede de baixo o robô está. É a mesma lógica que faz o ângulo 0 apontar para baixo.

Atalho para não errar

Guarde as quatro direções como constantes no topo do arquivo e nunca mais pense nisso:

no topo do arquivo
BAIXO = 0
ESQUERDA = 90
CIMA = 180
DIREITA = 270

Como o tempo passa: quadros e a fila

A partida acontece em quadros, como um desenho animado. A cada quadro, o jogo executa um pedacinho do que cada robô mandou fazer.

Quando você escreve self.move(20), o robô não pula 20 pixels. O jogo divide esse comando em pedaços de 5 e executa um por quadro:

Quadro12345
move(20) +5 px+5 px+5 px+5 px fila vazia → run()

Vale igual para giros: turn(20) vira 5 graus por quadro, em 4 quadros. Por isso um move(400) deixa o robô ocupado por 80 quadros, uma eternidade em que ele não decide mais nada e vira alvo fácil.

GrandezaValor
Passo de movimento5 pixels por quadro
Passo de giro5 graus por quadro
Velocidade do tiro10 pixels por quadro, o dobro da velocidade do robô
Prefira múltiplos de 5

Como tudo é fatiado de 5 em 5, ângulos e distâncias que são múltiplos de 5 saem exatos. Valores quebrados negativos podem girar até 5 graus a mais do que você pediu. Não quebra nada, mas atrapalha a mira fina.

O relógio

A partida tem 180 segundos. Se o tempo acabar com vários robôs vivos, a colocação é decidida por vida, depois eliminações, depois menos punições por inatividade. Preservar vida é, literalmente, ganhar pontos.

Na velocidade padrão do jogo, cada quadro leva 36 milésimos de segundo, o que dá cerca de 5000 quadros por partida. Como cada comando anda 5 pixels por quadro, isso é o orçamento total de movimento do seu robô: aproximadamente 25 mil pixels, ou 35 voltas em torno de uma arena de 700 por 500.

Vida

RegraValor
Vida inicial100
Teto de vida100, e curar acima disso não acumula
Vida zeradao robô sai da arena; quem deu o último dano ganha uma eliminação

A vida de cada robô aparece embaixo do tanque na arena e na barra colorida do painel da direita. No seu código, use self.getHealth().

De onde vem o dano

SituaçãoEfeito
Bater numa parede −1 de vida, o robô é empurrado para trás e a fila de comandos é descartada
Bater num bloco da arena −1 de vida, mesmo prejuízo da parede, mas dispara onHitObstacle e não onHitWall. Veja a página da arena.
Trombar em outro robô −1 de vida nos dois, os dois são empurrados e as duas filas são descartadas
Levar um tiro −3 × potência de vida
Disparar −1 × potência de vida, na hora do disparo
Acertar um tiro +2 × potência de vida para quem atirou
Tiro absorvido por um bloco nenhum dano, mas a energia do disparo foi perdida. Dispara onBulletHitObstacle, e não onBulletMiss
Ficar parado tempo demais depois de 15 segundos parado, −2 de vida a cada 5 segundos, mais uma penalidade registrada no desempate

A matemática do tiro

Esta é a conta mais útil do jogo inteiro. Um disparo de potência P:

Ou seja, em relação à sua própria vida:

ResultadoSua vidaVida do adversárioSaldo da troca
Acertou −P +2P = +P −3P Excelente: você ganha vida e tira o dobro dela do outro
Errou −P nada Prejuízo puro

Números concretos

PotênciaCusto do disparoDano se acertarVida que você recuperaTiros para eliminar alguém com 100 de vida
1−13+234
2−26+417
3−39+612
5−515+107
10−1030+204
A conclusão prática

Tiro forte que acerta é o melhor negócio do jogo. Um fire(10) que acerta tira 30 do outro e te devolve 20, então você sai da troca com mais vida do que entrou.

Tiro forte que erra é o pior. Três fire(10) errados custam 30 de vida sua, quase um terço do total, sem encostar em ninguém.

Por isso a regra que os robôs bons seguem: potência alta quando o alvo está perto e parado, potência baixa quando está longe ou se mexendo. A potência aceita valores de 0.5 a 10.

Como o radar enxerga

O radar projeta um cone à frente dele. Quando o tanque de um adversário entra nesse cone, o jogo chama o onTargetSpotted() do seu robô, entregando a posição do inimigo. Fora do cone, o adversário é invisível, mesmo que esteja colado em você.

O cone gira junto com o radar. Se o radar estiver travado na arma (lockRadar("gun")), ele gira quando a arma gira; se estiver travado no corpo, gira quando o corpo gira; se estiver livre, só gira com radarTurn().

O cone não atravessa concreto

Se houver um bloco entre você e o adversário, o radar não enxerga ele, mesmo com o cone apontado na direção exata. Silêncio no radar não significa arena vazia: pode ser que o inimigo esteja perto, atrás de um bloco. Detalhes na página da arena.

Os quatro formatos disponíveis, e a troca entre alcance e abertura, estão na página de referência.

Ligue o radar visível enquanto testa

self.radarVisible(True) no init() desenha o cone na tela. Ver o cone varrendo a arena explica na hora por que o robô não está encontrando ninguém.