Kit inicial
Cinco robôs para copiar
Estes robôs funcionam. Copie um, cole no seu arquivo dentro de Robots/,
troque o nome da classe pelo nome do seu time e rode. Depois comece a mexer.
Atalhos: 1. RoboMinimo · 2. RoboAndarilho · 3. RoboVigia · 4. RoboCacador · 5. RoboSombra
Os cinco robôs estão em ordem crescente de dificuldade e cada um acrescenta uma ideia ao anterior. Se você tem pouco tempo, pule direto para o RoboVigia: ele já anda, enxerga e atira, e é um adversário razoável. Se quer disputar o primeiro lugar, comece pelo RoboCacador e melhore a partir dele.
| Robô | Anda | Enxerga | Atira | Trata obstáculo | Ideia nova que ele traz |
|---|---|---|---|---|---|
| RoboMinimo | não | não | não | esqueleto vazio | O esqueleto obrigatório |
| RoboAndarilho | sim | não | não | sim | move, turn, stop e reagir à parede |
| RoboVigia | ao levar tiro | sim | sim | sim | Varredura de radar e disparo |
| RoboCacador | patrulha | sim | sim | rota se adapta | Máquina de estados e mira calculada |
| RoboSombra | sim | sim | sim | os três eventos | Reagir ao terreno e ler o silêncio do radar |
1. RoboMinimo esqueleto
Ele não faz nada, e esse é justamente o ponto. Tem os onze comandos que o jogo exige, todos vazios. É a base segura para começar: você preenche um de cada vez e testa.
O que ele ensina: a estrutura obrigatória de qualquer robô.
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
# ROBO 1 de 5 - O ESQUELETO
#
# Este robo nao faz nada: ele so entra na arena e fica parado.
# O valor dele e outro: ele tem TODOS os metodos que o jogo exige.
# Se algum deles faltar, o jogo fecha sozinho no meio da batalha.
#
# Use este arquivo como ponto de partida e va preenchendo os metodos.
from robot import Robot
class RoboMinimo(Robot):
def init(self):
"""Roda uma unica vez, quando o robo entra na arena."""
# Cores em RGB: (vermelho, verde, azul), de 0 a 255
self.setColor(66, 185, 193) # o corpo do tanque
self.setGunColor(255, 255, 255) # o cano da arma
self.setRadarColor(255, 204, 77) # o radar
self.setBulletsColor(66, 185, 193) # os tiros
# Deixa o campo de visao do radar visivel. Otimo para entender
# o que o robo enxerga enquanto voce testa.
self.radarVisible(True)
def run(self):
"""O cerebro do robo. Escreva aqui o que ele deve fazer."""
pass
def sensors(self):
"""Roda a cada quadro. Use para observar a arena."""
pass
def onHitWall(self):
"""Bati numa parede."""
pass
def onRobotHit(self, robotId, robotName):
"""EU bati em outro robo."""
pass
def onHitByRobot(self, robotId, robotName):
"""OUTRO robo bateu em mim."""
pass
def onHitByBullet(self, bulletBotId, bulletBotName, bulletPower):
"""Levei um tiro."""
pass
def onBulletHit(self, botId, bulletId):
"""Meu tiro acertou alguem."""
pass
def onBulletMiss(self, bulletId):
"""Meu tiro saiu da arena sem acertar ninguem."""
pass
def onTargetSpotted(self, botId, botName, botPos):
"""Meu radar viu um inimigo."""
pass
def onRobotDeath(self):
"""Minha vida chegou a zero."""
pass
# ------------------------------------------------------------------
# Daqui para baixo sao OPCIONAIS: o jogo so chama se voce escrever, e
# o robo funciona sem eles. Mas o primeiro e quase obrigatorio na
# pratica, porque a arena tem blocos no meio e bater neles NAO chama
# o onHitWall. Sem ele, o robo trava no bloco e morre sozinho.
# ------------------------------------------------------------------
def onHitObstacle(self, obstacleId, side):
"""Bati num bloco da arena. side: left, right, top, bottom."""
pass
def onBulletHitObstacle(self, bulletId, obstacleId):
"""Meu tiro foi absorvido por um bloco."""
pass
def onInactivityPenalty(self, damage, idleSeconds, penaltyCount):
"""Fiquei parado tempo demais e a arena me puniu."""
pass
O que mudar primeiro
- Troque
RoboMinimopelo nome do seu time (nas duas ocorrências: no nome do arquivo e depois declass). - Troque as cores em
setColore companhia. - Coloque
self.move(80)dentro dorun()e rode. Pronto: seu robô anda.
2. RoboAndarilho ele anda
Anda em quadrado pela arena e, quando bate numa parede, dá ré e vira. Ainda não atira:
a ideia aqui é entender como os comandos entram na fila e como o stop()
separa uma ação da outra.
O que ele ensina: move, turn, stop, reset e o evento onHitWall.
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
# ROBO 2 de 5 - ELE ANDA
#
# Anda em quadrado pela arena e recua quando bate numa parede.
# Nao atira ainda: o objetivo aqui e entender move, turn e stop.
from robot import Robot
# Constantes no topo do arquivo: fica facil de ajustar sem cacar no codigo.
PASSO = 40 # quantos pixels ele anda por vez
CURVA = 90 # quantos graus ele vira ao fim de cada trecho
RECUO = 80 # quanto ele da de re depois de bater
# Ao desviar de um bloco ele nunca vira sempre o mesmo tanto. Repetir o giro
# faz o robo refazer o mesmo caminho e bater no mesmo bloco de novo.
GIROS = [120, 155, 100, 170, 135]
class RoboAndarilho(Robot):
def init(self):
# Qual giro da lista GIROS eu uso no proximo desvio.
self.qual_giro = 0
self.setColor(110, 231, 160)
self.setGunColor(255, 255, 255)
self.setRadarColor(255, 204, 77)
self.setBulletsColor(110, 231, 160)
self.radarVisible(True)
def run(self):
# Bloco 1: anda para a frente.
self.move(PASSO)
self.stop()
# Bloco 2: so depois de terminar de andar, vira.
self.turn(CURVA)
self.stop()
# O stop() e o que separa um bloco do outro. Sem ele, o robo
# andaria e viraria AO MESMO TEMPO, fazendo uma curva aberta.
def sensors(self):
pass
def onHitWall(self):
# Bateu na parede: custou 1 de vida. Cancela o que estava fazendo,
# da re e vira, tudo no mesmo bloco.
self.reset()
self.move(-RECUO)
self.turn(CURVA)
def onHitObstacle(self, obstacleId, side):
# A arena tem blocos no meio, e bater neles NAO chama onHitWall.
# Sem este metodo o robo fica trombando no mesmo bloco ate morrer.
self.reset()
# Cada desvio usa um giro diferente. E isso que impede o robo de
# voltar pelo mesmo caminho e bater no mesmo bloco outra vez.
giro = GIROS[self.qual_giro % len(GIROS)]
self.qual_giro = self.qual_giro + 1
self.move(-PASSO)
self.turn(giro)
def onRobotHit(self, robotId, robotName):
self.rPrint("Bati no " + str(robotName))
def onHitByRobot(self, robotId, robotName):
self.rPrint("O " + str(robotName) + " bateu em mim")
def onHitByBullet(self, bulletBotId, bulletBotName, bulletPower):
self.rPrint("Levei tiro do " + str(bulletBotName))
def onBulletHit(self, botId, bulletId):
pass
def onBulletMiss(self, bulletId):
pass
def onTargetSpotted(self, botId, botName, botPos):
pass
def onRobotDeath(self):
self.rPrint("Fim de jogo para mim")
Repare no onHitWall
Ele chama self.reset() antes de qualquer coisa. Sem isso, o robô voltaria
a executar o plano antigo, que era justamente andar contra a parede. O
reset() joga o plano fora e permite decidir de novo.
Repare também que move(-PASSO) e turn(CURVA) estão no mesmo
bloco, sem stop() entre eles: o robô dá ré enquanto vira, o que é
mais rápido do que fazer uma coisa e depois a outra.
Como melhorar
- Mude
PASSOeCURVAlá no topo e veja o desenho que ele faz na arena. - Use
CURVA = 120para ele andar em triângulo em vez de quadrado, o que é mais difícil de prever. - Copie o
onTargetSpotteddo próximo robô e ele já começa a atirar.
3. RoboVigia ele atira
Fica varrendo a arena com o radar. Assim que enxerga alguém, atira. Se levar um tiro, sai do lugar, porque quem acertou você uma vez vai tentar de novo no mesmo ponto.
O que ele ensina: lockRadar, setRadarField, gunTurn, fire e os eventos onTargetSpotted e onHitByBullet.
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
# ROBO 3 de 5 - ELE ATIRA
#
# Fica varrendo a arena com o radar. Assim que ve alguem, atira.
# Se levar tiro, sai do lugar - ficar parado apanhando e o pior negocio.
from robot import Robot
VARREDURA = 10 # quantos graus o radar gira a cada rodada
POTENCIA = 3 # forca do tiro (de 0.5 ate 10)
FUGA = 100 # quantos pixels ele corre ao levar tiro
class RoboVigia(Robot):
def init(self):
self.setColor(255, 204, 77)
self.setGunColor(255, 255, 255)
self.setRadarColor(255, 122, 107)
self.setBulletsColor(255, 204, 77)
# O radar passa a acompanhar a arma. Assim, tudo que o radar
# enxerga ja esta na mira - nao precisa mirar depois.
self.lockRadar("gun")
# Radar estreito: enxerga longe, mas so bem na frente.
self.setRadarField("thin")
self.radarVisible(True)
def run(self):
# Gira a arma (e o radar junto) procurando alguem.
self.gunTurn(VARREDURA)
self.stop()
def sensors(self):
pass
def onTargetSpotted(self, botId, botName, botPos):
# O radar viu alguem bem na frente da arma. Atira.
self.rPrint("Vi o " + str(botName))
self.fire(POTENCIA)
def onHitByBullet(self, bulletBotId, bulletBotName, bulletPower):
# Alguem me acertou: sair do lugar dificulta o proximo tiro dele.
self.reset()
self.move(FUGA)
self.turn(45)
def onHitWall(self):
self.reset()
self.move(-FUGA)
def onHitObstacle(self, obstacleId, side):
# Bater num bloco do meio da arena nao chama onHitWall. Precisa
# deste metodo, senao o robo insiste no mesmo bloco e sangra.
self.reset()
self.move(-FUGA)
self.turn(90)
def onRobotHit(self, robotId, robotName):
pass
def onHitByRobot(self, robotId, robotName):
pass
def onBulletHit(self, botId, bulletId):
self.rPrint("Acertei!")
def onBulletMiss(self, bulletId):
pass
def onRobotDeath(self):
pass
O truque que faz ele funcionar
A linha self.lockRadar("gun") no init() faz o radar
apontar sempre para onde a arma aponta. Consequência: tudo que o radar
enxerga já está na mira. Por isso o onTargetSpotted deste robô
é uma linha só: não precisa calcular ângulo nenhum, é só atirar.
A outra peça é setRadarField("thin"): um cone estreito e comprido, que
enxerga do outro lado da arena. Combinado com a arma girando devagar, vira um
franco-atirador que varre o mapa inteiro.
Como melhorar
- Ajuste
POTENCIA. Valores altos matam rápido mas custam vida quando erram (veja a matemática do tiro). - Diminua
VARREDURApara ele varrer mais devagar e ter mais chance de enxergar quem passa. - Faça ele andar também: um alvo parado é um alvo fácil, e ficar parado ainda gera penalidade.
- Atire mais forte quando estiver com vida alta e mais fraco quando estiver quase morrendo, usando
self.getHealth().
4. RoboCacador competidor
Este já é um adversário de verdade. Ele patrulha as bordas da arena sem encostar nas paredes, varre o radar enquanto anda, calcula o ângulo exato até quem aparece e escolhe a potência do tiro conforme a distância.
O que ele ensina: máquina de estados, mira com trigonometria e escolha de potência.
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
# ROBO 4 de 5 - ELE CACA
#
# Patrulha as bordas da arena sem encostar nas paredes, varre o radar
# enquanto anda, mira com precisao em quem aparece e escolhe a forca do
# tiro pela distancia.
#
# Este e um bom adversario. Use como base e melhore.
import math
from robot import Robot
MARGEM = 90 # distancia inicial que ele mantem das paredes
MARGEM_MINIMA = 50 # o mais colado na parede que ele aceita andar
PASSO = 15 # quanto ele anda por rodada
VARREDURA = 8 # quantos graus o radar gira por rodada
ALCANCE = 450 # so atira em quem estiver mais perto que isso
# Lembre da bussola do jogo: 0 aponta para BAIXO e o angulo cresce
# no sentido horario.
BAIXO = 0
ESQUERDA = 90
CIMA = 180
DIREITA = 270
CIRCUITO = [BAIXO, ESQUERDA, CIMA, DIREITA]
class RoboCacador(Robot):
def init(self):
self.setColor(66, 185, 193)
self.setGunColor(255, 255, 255)
self.setRadarColor(255, 122, 107)
self.setBulletsColor(127, 214, 219)
self.arena = self.getMapSize()
self.lockRadar("gun")
self.setRadarField("thin")
self.radarVisible(True)
# Em qual trecho do circuito ele esta (indice da lista CIRCUITO).
self.trecho = 0
# A que distancia das paredes ele patrulha. Muda sozinha quando ele
# descobre que a rota atual passa por cima de um bloco.
self.margem = MARGEM
# ---------------------------------------------------------- ajudantes --
def chegou_no_fim_do_trecho(self):
"""Diz se ja esta perto demais da parede deste trecho."""
posicao = self.getPosition()
direcao = CIRCUITO[self.trecho]
if direcao == BAIXO:
return posicao.y() > self.arena.height() - self.margem
if direcao == CIMA:
return posicao.y() < self.margem
if direcao == ESQUERDA:
return posicao.x() < self.margem
return posicao.x() > self.arena.width() - self.margem
def menor_giro(self, de, para):
"""Menor giro (entre -180 e 180) para sair de um angulo e chegar noutro."""
erro = para - de
while erro < -180:
erro = erro + 360
while erro > 180:
erro = erro - 360
return erro
# ------------------------------------------------------------ cerebro --
def run(self):
if self.chegou_no_fim_do_trecho():
self.trecho = (self.trecho + 1) % len(CIRCUITO)
erro = self.menor_giro(self.getHeading() % 360, CIRCUITO[self.trecho])
if abs(erro) > 5:
self.turn(erro) # ainda torto: primeiro se alinha
else:
self.move(PASSO) # alinhado: anda
# A arma (e o radar junto com ela) varre enquanto o corpo anda.
self.gunTurn(VARREDURA)
self.stop()
def sensors(self):
pass
def onTargetSpotted(self, botId, botName, botPos):
eu = self.getPosition()
dx = botPos.x() - eu.x()
dy = botPos.y() - eu.y()
# Angulo ate o inimigo, ja convertido para a bussola do jogo.
angulo_do_inimigo = math.degrees(math.atan2(dy, dx)) - 90
erro = self.menor_giro(self.getGunHeading() % 360, angulo_do_inimigo)
self.gunTurn(erro)
self.stop()
distancia = math.sqrt(dx * dx + dy * dy)
if distancia < ALCANCE:
if distancia < 150:
potencia = 5 # perto: vale a pena o tiro caro
elif distancia < 300:
potencia = 3
else:
potencia = 1 # longe: tiro barato, chance maior de errar
self.fire(potencia)
def onHitWall(self):
# Encostou na parede: perdeu vida. Volta e pula para o proximo trecho.
self.reset()
self.trecho = (self.trecho + 1) % len(CIRCUITO)
self.move(-PASSO * 2)
def onHitObstacle(self, obstacleId, side):
# A arena tem blocos no meio do caminho, e eles NAO chamam onHitWall.
# Sem este metodo o robo trombava no mesmo bloco ate morrer sozinho.
self.reset()
# Bati porque a minha rota passa por cima de um bloco. Como os blocos
# ficam no miolo da arena, andar mais colado na parede resolve. Sem
# este ajuste ele volta na mesma rota e bate de novo, sem parar.
self.margem = max(MARGEM_MINIMA, self.margem - 25)
self.trecho = (self.trecho + 1) % len(CIRCUITO)
self.move(-PASSO * 2)
def onHitByBullet(self, bulletBotId, bulletBotName, bulletPower):
self.rPrint("Tomei " + str(3 * bulletPower) + " de dano do " + str(bulletBotName))
def onRobotHit(self, robotId, robotName):
self.reset()
self.move(-PASSO * 2)
def onHitByRobot(self, robotId, robotName):
pass
def onBulletHit(self, botId, bulletId):
pass
def onBulletMiss(self, bulletId):
pass
def onRobotDeath(self):
pass
As três ideias dentro dele
Patrulha por trechos
A variável self.trecho guarda em que lado da arena ele está andando.
Quando chega perto da parede, passa para o próximo trecho. Isso se chama
máquina de estados: em vez de um plano fixo, o robô tem uma
situação atual e regras para trocar de situação.
Mira calculada
Com a posição do inimigo e a sua, dá para descobrir o ângulo exato entre os dois.
É o que faz a linha com atan2. O menor_giro depois
garante que ele vire pelo caminho mais curto, em vez de dar a volta inteira.
Potência por distância
Perto, o tiro dificilmente erra: vale o disparo caro. Longe, a chance de errar é alta: melhor gastar pouco. É a aplicação direta da matemática do tiro.
A rota que aprende
Repare no onHitObstacle. Além de recuar, ele faz
self.margem = max(MARGEM_MINIMA, self.margem - 25): cada vez que bate
num bloco, a patrulha passa a andar 25 pixels mais perto da parede. Como os blocos
ficam no miolo da arena, em poucas batidas ele encontra uma volta limpa.
Não é detalhe. Medimos nos 16 mapas, com o robô sozinho e uma partida inteira de
duração: sem esse ajuste ele batia 382 vezes e morria no mapa classic;
com ele, bate 112 vezes, nunca encosta numa parede e termina no pior caso com 59 de
vida.
Como melhorar
- Mexa em
MARGEMeMARGEM_MINIMA: mais longe das paredes é mais espaço de manobra, mais perto é menos chance de achar um bloco. - Faça o circuito ser sorteado em vez de sempre no mesmo sentido, assim ninguém prevê para onde ele vai.
- Guarde a última posição de cada inimigo no
onTargetSpottede mire onde ele vai estar, não onde estava. - Use
self.getHealth()para mudar de comportamento: caçar com vida alta, fugir com vida baixa. - Use
len(self.getEnemiesLeft()) - 1para ficar mais agressivo quando sobrar só um adversário.
5. RoboSombra lê o terreno
Os quatro anteriores tratam obstáculo como estorvo. Este trata como informação. Ele usa os três eventos opcionais: desvia quando bate num bloco, muda de posição quando o tiro é absorvido, e percebe quando o radar ficou tempo demais em silêncio, o que quase sempre significa concreto na frente.
Talvez você espere um robô que se esconde atrás de um bloco de propósito. Não dá: nenhum comando do jogo informa onde os blocos estão. O robô só descobre o terreno batendo nele ou vendo o tiro sumir. Por isso o RoboSombra não planeja esconderijo, ele reage rápido ao que encontra. Saber essa limitação vale mais do que qualquer truque, porque evita você perder a tarde tentando o impossível.
O que ele ensina: os três eventos opcionais, e usar um contador de tempo como sensor indireto.
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
# ROBO 5 de 5 - ELE LE O TERRENO
#
# A arena tem blocos de concreto no meio. Eles param o robo, engolem os
# tiros e escondem os inimigos do radar. Este robo trata os tres casos.
#
# Uma coisa importante: NAO existe comando para perguntar onde estao os
# blocos. O robo so descobre o terreno batendo nele ou vendo o tiro sumir.
# Entao a ideia aqui nao e decorar o mapa, e sim reagir depressa ao que
# aparece pela frente.
import math
from robot import Robot
PASSO = 40 # quanto ele anda em cada trecho
CURVA = 90 # quanto ele vira ao fim de cada trecho
RECUO = 80 # quanto ele da de re depois de bater
VARREDURA = 12 # quanto a arma gira por trecho, procurando alguem
ALCANCE = 450 # so atira em quem estiver mais perto que isso
# Depois de tantos trechos sem ver ninguem, provavelmente tem concreto na
# frente. Ai vale mudar de area em vez de continuar girando o radar.
PACIENCIA = 25
# Ao desviar de um bloco ele nunca vira sempre o mesmo tanto. Repetir o giro
# faz o robo refazer o mesmo caminho e bater no mesmo bloco de novo.
GIROS = [120, 155, 100, 170, 135]
class RoboSombra(Robot):
def init(self):
self.setColor(140, 120, 200)
self.setGunColor(255, 255, 255)
self.setRadarColor(200, 160, 255)
self.setBulletsColor(180, 160, 230)
self.lockRadar("gun")
self.setRadarField("normal")
self.radarVisible(True)
# Ha quantos trechos eu nao vejo ninguem.
self.silencio = 0
# Qual giro da lista GIROS eu uso no proximo desvio.
self.qual_giro = 0
# Blocos que ja encontrei nesta arena.
self.blocos = []
# ---------------------------------------------------------- ajudantes --
def desviar(self):
"""Vira um tanto diferente a cada vez, para nao repetir o caminho."""
giro = GIROS[self.qual_giro % len(GIROS)]
self.qual_giro = self.qual_giro + 1
self.turn(giro)
def menor_giro(self, de, para):
"""Menor giro, entre -180 e 180, para sair de um angulo e chegar noutro."""
erro = para - de
while erro < -180:
erro = erro + 360
while erro > 180:
erro = erro - 360
return erro
# ------------------------------------------------------------ cerebro --
def run(self):
self.silencio = self.silencio + 1
self.move(PASSO)
self.gunTurn(VARREDURA)
self.stop()
if self.silencio > PACIENCIA:
# Radar calado por muito tempo quase sempre significa concreto na
# frente, e nao arena vazia. Mudar de area resolve, girar nao.
self.silencio = 0
self.desviar()
else:
self.turn(CURVA)
self.stop()
def sensors(self):
pass
# ------------------------------------------------------------- terreno --
def onHitObstacle(self, obstacleId, side):
"""Bati num bloco. Este evento NAO e o onHitWall."""
if obstacleId not in self.blocos:
self.blocos.append(obstacleId)
self.reset()
self.silencio = 0
self.move(-PASSO)
self.desviar()
def onBulletHitObstacle(self, bulletId, obstacleId):
"""Meu tiro morreu no concreto: tem bloco na minha linha de tiro."""
# Mirar melhor nao adianta, o problema e a posicao. Entao mudo de lugar.
self.reset()
self.move(PASSO)
self.desviar()
def onInactivityPenalty(self, damage, idleSeconds, penaltyCount):
"""Alarme: se cheguei aqui, alguma coisa travou na minha logica."""
self.rPrint("Fiquei parado. Punicao numero " + str(penaltyCount))
self.reset()
self.move(PASSO)
self.desviar()
def onHitWall(self):
self.reset()
self.move(-RECUO)
self.turn(CURVA)
# ------------------------------------------------------------- combate --
def onTargetSpotted(self, botId, botName, botPos):
self.silencio = 0
eu = self.getPosition()
dx = botPos.x() - eu.x()
dy = botPos.y() - eu.y()
angulo_do_inimigo = math.degrees(math.atan2(dy, dx)) - 90
erro = self.menor_giro(self.getGunHeading() % 360, angulo_do_inimigo)
self.gunTurn(erro)
self.stop()
distancia = math.sqrt(dx * dx + dy * dy)
if distancia < ALCANCE:
if distancia < 150:
self.fire(5)
elif distancia < 300:
self.fire(3)
else:
self.fire(1)
def onHitByBullet(self, bulletBotId, bulletBotName, bulletPower):
# Levei tiro, entao existe linha de visao limpa ate mim. Trocar de
# lugar e a unica forma de cortar essa linha.
self.reset()
self.move(PASSO)
self.desviar()
def onRobotHit(self, robotId, robotName):
self.reset()
self.move(-PASSO)
self.desviar()
def onHitByRobot(self, robotId, robotName):
pass
def onBulletHit(self, botId, bulletId):
pass
def onBulletMiss(self, bulletId):
pass
def onRobotDeath(self):
self.rPrint("Encontrei " + str(len(self.blocos)) + " blocos nesta arena")
As três ideias dentro dele
Sai pela perpendicular
No onHitObstacle ele usa o side para escolher o rumo:
se está à esquerda do bloco, vai para cima ou para baixo. É o caminho mais curto
para deixar de raspar nele.
Silêncio é informação
O contador self.silencio sobe a cada rodada e zera quando o radar vê
alguém. Passando de PACIENCIA, ele muda de lugar. Girar o radar não
resolve quando o problema é o concreto.
Tiro absorvido, anda de lado
No onBulletHitObstacle ele não corrige a mira, corrige a posição.
Se há um bloco na linha de tiro, mirar melhor continua acertando o bloco.
Como melhorar
- Ajuste
PACIENCIA: baixo demais e ele fica trocando de lugar sem parar, alto demais e ele demora a perceber que está bloqueado. - Ele guarda os nomes dos blocos em
self.blocosmas quase não usa. Guarde também a sua posição em cada batida e evite voltar para perto delas. - Combine com a patrulha do RoboCacador: rota organizada mais reação ao terreno.
- O arquivo está dentro de
Robots/e foi salvo? - O nome da classe é o nome que você quer ver na arena?
- Os onze comandos obrigatórios estão todos lá?
- Você rodou uma batalha inteira sem o jogo fechar sozinho?
- Ele se mexe o tempo todo, sem ficar parado?