Os resultados estão chegando, o concurso acabou.
O vencedor é o EvilBot de arshajii, com 14 vitórias à frente do Neo-Bot, com 13 vitórias, e CentreBot e LastStand, com 11 vitórias cada.
Pontuações da corrida final
Results:
java Rifter: 9 match wins (45 total bout wins)
java EvadeBot: 10 match wins (44 total bout wins)
java EvilBot: 14 match wins (59 total bout wins)
java LastStand: 11 match wins (43 total bout wins)
java UltraBot: 9 match wins (40 total bout wins)
python ReadyAimShoot.py: 8 match wins (36 total bout wins)
./SpiralBot: 0 match wins (1 total bout wins)
python DodgingTurret.py: 8 match wins (43 total bout wins)
ruby1.9 TroubleAndStrafe.rb: 8 match wins (41 total bout wins)
./RandomBot: 1 match wins (6 total bout wins)
python StraightShooter.py: 8 match wins (41 total bout wins)
python mineminemine.py: 3 match wins (14 total bout wins)
./CamperBot: 5 match wins (20 total bout wins)
python3.3 CunningPlanBot.py: 3 match wins (15 total bout wins)
node CentreBot.js: 11 match wins (44 total bout wins)
node Neo-Bot.js: 13 match wins (59 total bout wins)
python NinjaPy.py: 3 match wins (19 total bout wins)
Este é um desafio do tipo rei da colina . O objetivo é escrever um bot que derrote mais dos outros bots do que qualquer outro.
O jogo
Os bots serão todos colocados uns contra os outros 2 de cada vez em uma arena de 10x10, com a tarefa de reduzir a energia do oponente de 10 para 0 antes que sua própria energia seja reduzida para 0.
Cada partida será composta por 5 lutas. O vencedor da partida é o vencedor de mais lutas. O número total de vitórias e lutas será armazenado pelo programa de controle e será usado para determinar o vencedor geral do concurso. O vencedor recebe o grande carrapato verde e a adulação das massas.
Cada luta prosseguirá em várias rodadas. No início de cada rodada, o estado atual da arena será dado a cada bot e o bot responderá com um comando para determinar o que deseja fazer a seguir. Depois que os dois comandos são recebidos pelo programa de controle, os dois comandos são executados ao mesmo tempo e os níveis de energia da arena e do bot são atualizados para refletir o novo estado. Se os dois robôs ainda tiverem energia suficiente para continuar, o jogo passa para a próxima rodada. Haverá um limite de 1000 rodadas por turno para garantir que não haja uma eternidade, e caso esse limite seja atingido, o vencedor será o bot com mais energia. Se ambos os bots tiverem energia igual, o ataque será um empate e nenhum bot ganhará um ponto pela vitória (seria como se os dois tivessem perdido).
As armas
Cada bot terá à sua disposição um número de armas:
- Balas perfurantes. Eles viajam 3 quadrados por vez e causam 1 ponto de energia de dano.
- Mísseis. Eles viajam 2 quadrados por vez e causam 3 pontos de dano de energia no ponto de impacto e 1 ponto de dano em todos os quadrados imediatamente ao redor.
- Minas terrestres. Eles são jogados em um dos quadrados imediatamente ao redor do bot e causam 2 pontos de dano de energia quando pisados, e 1 ponto de dano de energia a qualquer coisa que esteja em um dos quadrados imediatamente ao redor.
- Pulso eletromagnetico. Faz com que os circuitos de movimento dos dois robôs funcionem mal por 2 turnos, o que significa que eles não podem se mover. No entanto, eles ainda podem usar armas (sim, eu sei que isso não é realista, mas é um jogo. Não deveria ser a vida real). Edit: Cada implantação de EMP custará um ponto de energia para o bot que o usa.
Balas / mísseis só podem impactar com bots ou paredes. Eles atingem qualquer bot que esteja em qualquer um dos quadrados pelos quais viajam. Eles desaparecem quando atingem algo.
Em todos os casos, immediately surrounding squares
significa os 8 quadrados para os quais o bot poderia passar no próximo passo - o bairro de Moore.
Os comandos
0
fazer nada.N
,NE
,E
,SE
,S
,SW
,W
,NW
São todos os comandos de direcção e deslocar o bot um quadrado na direcção dada. Se o bot não puder se mover nessa direção porque há uma parede ou outro bot no quadrado, o bot permanecerá onde está. Mover-se para um quadrado que já contém uma bala ou míssil é seguro, uma vez que o projétil / míssil será considerado já saindo da praça.B
seguido por um espaço e, em seguida, um dos comandos de direção dispara uma bala perfurante de armadura nessa direção.M
seguido por um espaço e, em seguida, um dos comandos de direção dispara um míssil nessa direção.L
seguido por um espaço e, em seguida, um dos comandos de direção solta uma mina terrestre naquele quadrado ao lado do bot. Se o quadrado já estiver ocupado por uma parede ou um bot, o comando será ignorado. Se uma mina terrestre é lançada em outra mina terrestre, ela a detona. Isso danificará o bot que está caindo e qualquer outro bot ao alcance da mina terrestre original.P
aciona o EMP.
Como apenas um comando pode ser dado por rodada, um bot pode apenas mover ou disparar / implantar uma arma, e não as duas ao mesmo tempo.
Ordem dos comandos
O movimento de um ou outro bot sempre será o primeiro e todos os movimentos serão tentados duas vezes para explicar que outro bot está no caminho, mas está se afastando.
Exemplo
- Bot1 tenta se mover,
E
mas Bot2 já está naquele quadrado - O programa de controle passa para o Bot2.
- O Bot2 tenta se mover
S
e consegue, porque nada está no caminho. - Bot1 recebe uma segunda tentativa de fazer sua jogada. Desta vez, obtém sucesso e o Bot1 se move
E
.
Depois que os robôs fizerem os movimentos que quiserem, as armas serão disparadas e todos os projéteis (novos e disparados anteriormente) moverão seu número predefinido de quadrados.
A Arena
No início de cada rodada, o bot receberá o estado atual de jogo como o único argumento de linha de comando do programa:
X.....LLL.
..........
..........
..........
M.........
..........
..........
..........
..........
...B.....Y
Y 10
X 7
B 3 9 W
M 0 4 S
L 6 0
B 3 9 S
L 7 0
L 8 0
A arena vem primeiro, consistindo de 10 linhas de 10 caracteres. É cercado por paredes que não são mostradas. Os significados dos personagens são os seguintes:
.
representa um quadrado vazioY
representa seu bot.X
representa o bot oponente.L
representa uma mina terrestre.B
representa uma bala em voo.M
representa um míssil em vôo.
Isto é seguido pela energia restante dos bots, um bot por linha. Apenas um espaço separará o identificador de bot do seu nível de energia. Como na arena, Y
representa seu bot e X
seu oponente. Finalmente, é apresentada uma lista dos projéteis e minas terrestres, suas posições e (se for o caso) os títulos, novamente um por linha.
O programa de controle
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define NUMBOTS 2
#define BOUTSPERMATCH 5
#define ROUNDSPERBOUT 1000
#define MAXFILENAMESIZE 100
#define MAXWEAPONS 100
#define DISPLAYBOUTS true
typedef struct
{
int x, y, energy;
char cmd[5];
} Bot;
int getxmove(char cmd[5]);
int getymove(char cmd[5]);
int newposinbounds(int oldx, int oldy, int dx, int dy);
int directhit(Bot bot, int landmine[2]);
int landminecollision(int landmine1[2], int landmine2[2]);
int inshrapnelrange(Bot bot, int landmine[2]);
int directiontoint(char direction[5], char directions[8][3]);
void deployweapons(Bot *bot, Bot *enemy, int bullets[MAXWEAPONS][3], int missiles[MAXWEAPONS][3], int landmines[MAXWEAPONS][2], char directions[8][3]);
void cleararena(char arena[10][11]);
int main()
{
FILE *fp;
Bot b1, b2;
int bot1, bot2, bot1bouts, bot2bouts;
int bout, round, loop, totalprojectiles, dx, dy;
char bots[NUMBOTS][MAXFILENAMESIZE]=
{
"./donowt ",
"php -f huggybot.php "
};
char directions[8][3]={"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
char openstring[5000], argumentstring[4000], bot1string[6], bot2string[6];
int matcheswon[NUMBOTS],boutswon[NUMBOTS];
int missiles[MAXWEAPONS][3];
int bullets[MAXWEAPONS][3];
int landmines[MAXWEAPONS][2];
int paralyzedturnsremaining=0;
bool bot1moved;
char arena[10][11];
char projectiles[300][10];
for(loop=0;loop<NUMBOTS;loop++)
{
matcheswon[loop]=0;
boutswon[loop]=0;
}
srand(time(NULL));
for(bot1=0;bot1<NUMBOTS-1;bot1++)
{
for(bot2=bot1+1;bot2<NUMBOTS;bot2++)
{
bot1bouts=bot2bouts=0;
printf("%s vs %s ",bots[bot1],bots[bot2]);
for(bout=0;bout<BOUTSPERMATCH;bout++)
{
printf("%d ",bout);
//setup the arena for the bout
b1.x=1;b1.y=1;
b2.x=9;
//b1.y=rand()%10;
b2.y=rand()%10;
b1.energy=b2.energy=10;
//clear the previous stuff
memset(missiles, -1, sizeof(missiles));
memset(bullets, -1, sizeof(bullets));
memset(landmines, -1, sizeof(landmines));
for(round=0;round<ROUNDSPERBOUT;round++)
{
//draw the arena based on current state
cleararena(arena);
totalprojectiles=0;
for(loop=0;loop<MAXWEAPONS;loop++)
{
if(bullets[loop][0]!= -1)
{
arena[bullets[loop][1]][bullets[loop][0]]='B';
sprintf(projectiles[totalprojectiles], "%c %d %d %s\n", 'B', bullets[loop][0], bullets[loop][1], directions[bullets[loop][2]]);
totalprojectiles+=1;
}
if(missiles[loop][0]!= -1)
{
arena[missiles[loop][1]][missiles[loop][0]]='M';
sprintf(projectiles[totalprojectiles], "%c %d %d %s\n", 'M', missiles[loop][0], missiles[loop][1], directions[missiles[loop][2]]);
totalprojectiles+=1;
}
if(landmines[loop][0]!= -1)
{
arena[landmines[loop][1]][landmines[loop][0]]='L';
sprintf(projectiles[totalprojectiles], "%c %d %d\n", 'L', landmines[loop][0], landmines[loop][1]);
totalprojectiles+=1;
}
}
//send the arena to both bots to get the commands
// create bot1's input
arena[b1.y][b1.x]='Y';
arena[b2.y][b2.x]='X';
sprintf(bot1string, "Y %d\n", b1.energy);
sprintf(bot2string, "X %d\n", b2.energy);
strcpy(argumentstring, "'");
strncat(argumentstring, *arena, 10*11);
strcat(argumentstring, bot1string);
strcat(argumentstring, bot2string);
for(loop=0;loop<totalprojectiles;loop++)
{
strcat(argumentstring, projectiles[loop]);
}
strcat(argumentstring, "'");
sprintf(openstring, "%s %s", bots[bot1], argumentstring);
// send it and get the command back
fp=popen(openstring, "r");
fgets(b1.cmd, 5, fp);
fflush(NULL);
pclose(fp);
// create bot2's input
arena[b2.y][b2.x]='Y';
arena[b1.y][b1.x]='X';
sprintf(bot2string, "Y %d\n", b2.energy);
sprintf(bot1string, "X %d\n", b1.energy);
strcpy(argumentstring, "'");
strncat(argumentstring, *arena, 10*11);
strcat(argumentstring, bot2string);
strcat(argumentstring, bot1string);
for(loop=0;loop<totalprojectiles;loop++)
{
strcat(argumentstring, projectiles[loop]);
}
strcat(argumentstring, "'");
sprintf(openstring, "%s %s", bots[bot2], argumentstring);
// send it and get the command back
fp=popen(openstring, "r");
fgets(b2.cmd, 5, fp);
fflush(NULL);
pclose(fp);
if(DISPLAYBOUTS)
{
arena[b1.y][b1.x]='A';
arena[b2.y][b2.x]='B';
printf("\033c");
printf("Round: %d\n", round);
printf("%s", arena);
sprintf(bot1string, "A %d\n", b1.energy);
sprintf(bot2string, "B %d\n", b2.energy);
printf("%s%s", bot1string, bot2string);
}
//do bot movement phase
if(paralyzedturnsremaining==0)
{
// move bot 1 first
bot1moved=false;
dx=dy=0;
dx=getxmove(b1.cmd);
dy=getymove(b1.cmd);
if(newposinbounds(b1.x, b1.y, dx, dy))
{
if(!(b1.x+dx==b2.x) || !(b1.y+dy==b2.y))
{
bot1moved=true;
b1.x=b1.x+dx;
b1.y=b1.y+dy;
}
}
// move bot 2 next
dx=dy=0;
dx=getxmove(b2.cmd);
dy=getymove(b2.cmd);
if(newposinbounds(b2.x, b2.y, dx, dy))
{
if(!(b2.x+dx==b1.x) || !(b2.y+dy==b1.y))
{
b2.x=b2.x+dx;
b2.y=b2.y+dy;
}
}
if(!bot1moved) // if bot2 was in the way first time, try again
{
dx=dy=0;
dx=getxmove(b1.cmd);
dy=getymove(b1.cmd);
if(newposinbounds(b1.x, b1.y, dx, dy))
{
if(!(b1.x+dx==b2.x) || !(b1.y+dy==b2.y))
{
b1.x=b1.x+dx;
b1.y=b1.y+dy;
}
}
}
//check for landmine hits
for(loop=0;loop<MAXWEAPONS;loop++)
{
if(landmines[loop][0]!= -1)
{
if(directhit(b1, landmines[loop]))
{
b1.energy-=2;
if(inshrapnelrange(b2, landmines[loop]))
{
b2.energy-=1;
}
landmines[loop][0]= -1;
landmines[loop][1]= -1;
}
if(directhit(b2, landmines[loop]))
{
b2.energy-=2;
if(inshrapnelrange(b1, landmines[loop]))
{
b1.energy-=1;
}
landmines[loop][0]= -1;
landmines[loop][1]= -1;
}
}
}
}
else
{
paralyzedturnsremaining-=1;
}
//do weapons firing phase
if(strcmp(b1.cmd, "P")==0)
{
paralyzedturnsremaining=2;
b1.energy--;
}
else if(strcmp(b2.cmd, "P")==0)
{
paralyzedturnsremaining=2;
b2.energy--;
}
deployweapons(&b1, &b2, bullets, missiles, landmines, directions);
deployweapons(&b2, &b1, bullets, missiles, landmines, directions);
//do weapons movement phase
int moves;
for(loop=0;loop<MAXWEAPONS;loop++)
{
dx=dy=0;
if(bullets[loop][0]!= -1)
{
dx=getxmove(directions[bullets[loop][2]]);
dy=getymove(directions[bullets[loop][2]]);
for(moves=0;moves<3;moves++)
{
if(newposinbounds(bullets[loop][0], bullets[loop][1], dx, dy))
{
bullets[loop][0]+=dx;
bullets[loop][1]+=dy;
if(directhit(b1, bullets[loop]))
{
b1.energy-=1;
bullets[loop][0]= -1;
bullets[loop][1]= -1;
bullets[loop][2]= -1;
}
if(directhit(b2, bullets[loop]))
{
b2.energy-=1;
bullets[loop][0]= -1;
bullets[loop][1]= -1;
bullets[loop][2]= -1;
}
}
else
{
bullets[loop][0]= -1;
bullets[loop][1]= -1;
bullets[loop][2]= -1;
dx=dy=0;
}
}
}
};
for(loop=0;loop<MAXWEAPONS;loop++)
{
dx=dy=0;
if(missiles[loop][0]!= -1)
{
dx=getxmove(directions[missiles[loop][2]]);
dy=getymove(directions[missiles[loop][2]]);
for(moves=0;moves<2;moves++)
{
if(newposinbounds(missiles[loop][0], missiles[loop][1], dx, dy))
{
missiles[loop][0]+=dx;
missiles[loop][1]+=dy;
if(directhit(b1, missiles[loop]))
{
b1.energy-=3;
if(inshrapnelrange(b2, missiles[loop]))
{
b2.energy-=1;
}
missiles[loop][0]= -1;
missiles[loop][1]= -1;
missiles[loop][2]= -1;
}
if(directhit(b2, missiles[loop]))
{
b2.energy-=3;
if(inshrapnelrange(b1, missiles[loop]))
{
b1.energy-=1;
}
missiles[loop][0]= -1;
missiles[loop][1]= -1;
missiles[loop][2]= -1;
}
}
else
{
if(inshrapnelrange(b1, missiles[loop]))
{
b1.energy-=1;
}
if(inshrapnelrange(b2, missiles[loop]))
{
b2.energy-=1;
}
missiles[loop][0]= -1;
missiles[loop][1]= -1;
missiles[loop][2]= -1;
dx=dy=0;
}
}
}
}
//check if there's a winner
if(b1.energy<1 || b2.energy<1)
{
round=ROUNDSPERBOUT;
}
}
// who has won the bout
if(b1.energy<b2.energy)
{
bot2bouts+=1;
boutswon[bot2]+=1;
}
else if(b2.energy<b1.energy)
{
bot1bouts+=1;
boutswon[bot1]+=1;
}
}
if(bot1bouts>bot2bouts)
{
matcheswon[bot1]+=1;
}
else if(bot2bouts>bot1bouts)
{
matcheswon[bot2]+=1;
}
printf("\n");
}
}
// output final scores
printf("\nResults:\n");
printf("Bot\t\t\tMatches\tBouts\n");
for(loop=0;loop<NUMBOTS;loop++)
{
printf("%s\t%d\t%d\n", bots[loop], matcheswon[loop], boutswon[loop]);
}
}
int getxmove(char cmd[5])
{
int dx=0;
if(strcmp(cmd, "NE")==0)
dx= 1;
else if(strcmp(cmd, "E")==0)
dx= 1;
else if(strcmp(cmd, "SE")==0)
dx= 1;
else if(strcmp(cmd, "SW")==0)
dx= -1;
else if(strcmp(cmd, "W")==0)
dx= -1;
else if(strcmp(cmd, "NW")==0)
dx= -1;
return dx;
}
int getymove(char cmd[5])
{
int dy=0;
if(strcmp(cmd, "N")==0)
dy= -1;
else if(strcmp(cmd, "NE")==0)
dy= -1;
else if(strcmp(cmd, "SE")==0)
dy= 1;
else if(strcmp(cmd, "S")==0)
dy= 1;
else if(strcmp(cmd, "SW")==0)
dy= 1;
else if(strcmp(cmd, "NW")==0)
dy= -1;
return dy;
}
int newposinbounds(int oldx, int oldy, int dx, int dy)
{
return (oldx+dx>=0 && oldx+dx<10 && oldy+dy>=0 && oldy+dy<10);
}
int directhit(Bot bot, int landmine[2])
{
return (bot.x==landmine[0] && bot.y==landmine[1]);
}
int landminecollision(int landmine1[2], int landmine2[2])
{
return ((landmine1[1]==landmine2[1]) && abs(landmine1[0]==landmine2[0]));
}
int inshrapnelrange(Bot bot, int landmine[2])
{
return (abs(bot.x-landmine[0])<2 && abs(bot.y-landmine[1])<2);
}
int directiontoint(char direction[5], char directions[8][3])
{
int loop,returnval=8;
for(loop=0;loop<8;loop++)
{
if(strcmp(directions[loop], direction)==0)
returnval=loop;
}
return returnval;
}
void deployweapons(Bot *bot, Bot *enemy, int bullets[MAXWEAPONS][3], int missiles[MAXWEAPONS][3], int landmines[MAXWEAPONS][2], char directions[8][3])
{
int loop;
if(strlen(bot->cmd)>2)
{
if(bot->cmd[0]=='B')
{
int weaponslot=0;
while(bullets[weaponslot][0]!= -1)
weaponslot+=1;
bullets[weaponslot][0]=bot->x;
bullets[weaponslot][1]=bot->y;
bullets[weaponslot][2]=directiontoint(bot->cmd+2, directions);
if(bullets[weaponslot][2]>7)
{
// direction wasn't recognized so clear the weapon
bullets[weaponslot][0]= -1;
bullets[weaponslot][1]= -1;
bullets[weaponslot][2]= -1;
}
}
if(bot->cmd[0]=='M')
{
int weaponslot=0;
while(missiles[weaponslot][0]!= -1)
weaponslot+=1;
missiles[weaponslot][0]=bot->x;
missiles[weaponslot][1]=bot->y;
missiles[weaponslot][2]=directiontoint(bot->cmd+2, directions);
if(missiles[weaponslot][2]>7)
{
// direction wasn't recognized so clear the weapon
missiles[weaponslot][0]= -1;
missiles[weaponslot][1]= -1;
missiles[weaponslot][2]= -1;
}
}
if(bot->cmd[0]=='L')
{
int weaponslot=0;
while(landmines[weaponslot][0]!= -1)
weaponslot+=1;
if(newposinbounds(bot->x, bot->y, getxmove(bot->cmd+2), getymove(bot->cmd+2)))
{
landmines[weaponslot][0]=bot->x+getxmove(bot->cmd+2);
landmines[weaponslot][1]=bot->y+getymove(bot->cmd+2);
//check for landmine hits
for(loop=0;loop<MAXWEAPONS;loop++)
{
if(landmines[loop][0]!= -1)
{
if(landminecollision(landmines[weaponslot], landmines[loop]) && weaponslot!=loop)
{
if(inshrapnelrange(*bot, landmines[loop]))
{
bot->energy-=1;
}
if(inshrapnelrange(*enemy, landmines[loop]))
{
enemy->energy-=1;
}
landmines[loop][0]= -1;
landmines[loop][1]= -1;
landmines[weaponslot][0]= -1;
landmines[weaponslot][1]= -1;
}
}
}
}
}
}
}
void cleararena(char arena[10][11])
{
int loop;
memset(arena, '.', 110);
for(loop=0;loop<10;loop++)
{
arena[loop][10]='\n';
}
}
O programa de controle chama seu bot a partir da linha de comando. Por esse motivo, os programas que não puderem ser chamados a partir da linha de comando serão considerados inválidos . Peço desculpas àqueles cuja linguagem de escolha não funciona dessa maneira, mas fazer cada partida manualmente seria impraticável.
O intx13 escreveu uma versão mais robusta do programa de controle com algumas correções que você pode encontrar aqui .
Sugestões para melhorias ou correções no programa de controle são bem-vindas.
Bots de teste
Nenhum dos robôs de teste será incluído nas execuções de pontuação. Eles são apenas para fins de teste.
Dudley DoNowt (C)
int main(int argc, char *argv)
{
printf("0");
}
Não faz nada, independentemente da situação. Não se espera que ganhe muito.
HuggyBot (PHP)
<?php
$arena=$argv[1];
list($meX, $meY)=findMe($arena);
list($oppX, $oppY)=findOpp($arena);
if($meY<$oppY)
{
if($meX<$oppX)
echo "SE";
elseif($meX==$oppX)
echo "S";
else
echo "SW";
}
elseif($meY==$oppY)
{
if($meX<$oppX)
echo "E";
else
echo "W";
}
else
{
if($meX<$oppX)
echo "NE";
elseif($meX==$oppX)
echo "N";
else
echo "NW";
}
function findMe($arena)
{
return find("Y", explode("\n", $arena));
}
function findOpp($arena)
{
return find("X", explode("\n", $arena));
}
function find($char, $array)
{
$x=0;
$y=0;
for($loop=0;$loop<10;$loop++)
{
if(strpos($array[$loop], $char)!==FALSE)
{
$x=strpos($array[$loop], $char);
$y=$loop;
}
}
return array($x, $y);
}
?>
Tenta ficar ao lado do oponente. Vulnerável a minas terrestres, uma vez que não as procura. Torna o lançamento de mísseis uma tática menos eficaz para o oponente quando ele atinge seu objetivo.
Os resultados
A corrida final de pontuação será realizada após as 23h59 do dia 24 de março de 2014 . Realizarei testes regularmente para que os participantes possam ver como seus bots estão se saindo contra a oposição atual.
Entradas
As entradas devem incluir a fonte do seu bot e o argumento da linha de comando que precisarei usar para executá-lo. Você pode publicar quantas entradas diferentes quiser, mas cada resposta deve conter apenas um bot.
Importante
Parece que algumas entradas desejam gravar no disco para manter algum estado entre as execuções. Estas são novas regras relacionadas à gravação em disco.
- Você pode modificar a fonte do seu próprio bot. Modificar qualquer outro bot está trapaceando e resultará na desqualificação do bot ofensivo.
- Você pode gravar em um arquivo criado com o objetivo de armazenar o estado. Este arquivo deve ser armazenado em um subdiretório do diretório em que seu bot está localizado. O subdiretório será nomeado
state
. A gravação em qualquer outra parte do sistema de arquivos (que não seja sua própria fonte) não é permitida.
fonte
Respostas:
EvilBot
um bot que tenta ser o mais mal possível
Bem, eis o que eu tenho: um bot Java que tenta chegar o mais próximo possível
do oponente deuma faixa circular de raio 2,5 em torno do centro da arena e, em seguida, causar o máximo de dano possível. Seu padrão de movimento é baseado na atribuição de um valor de "perigo" a cada um dos quadrados vizinhos e na decisão de se mover com base nesses valores e com base na tendência de estar o mais próximo possível de uma região circular de raio 2,5 sobre o centro da arena. Usei algumas das porcas e parafusos da resposta do @ Geobits (por exemplo, ter um resumoBattleBot
classe e a técnica de análise), então obrigado! Provavelmente vou modificar / expandir o que tenho até agora, embora ele se saia muito bem como está com os outros bots publicados até agora. O código está abaixo. (se alguém estiver usando Java, sinta-se à vontade para usar minhas classes abstract / helper.)(
EvilBot.java
)Uso:
Notas:
Atualmente, as minas terrestres não estão sendo usadas, apenas esquivadas. Provavelmente não vou mudar isso, pois o uso de minas terrestres parece causar mais mal do que bem (pelo menos para o EvilBot), a julgar pelos poucos testes que fiz.
Atualmente, o EMP não está sendo usado. Tentei a estratégia de alinhar com o oponente e disparar o EMP seguido de mísseis, mas existem algumas contra-estratégias que ganhariam quase 100% das vezes, então decidi abandonar esse caminho. Eu poderia explorar o uso do EMP de maneiras diferentes posteriormente.
fonte
Rifter
Este bot executa ações diferentes com base no que está lutando. Para determinar o oponente, ele vira seu próprio estado e o alimenta nos outros bots para ver o que eles fariam, e compara isso ao que eles realmente fazem. Quando atingem um limiar de movimentos 'corretos', ele para de testar os outros.
Uma vez que ele sabe qual bot está lutando, geralmente sabe onde estará no próximo turno, para que possa disparar lá em vez da posição atual.
Claro, existem algumas desvantagens. Uma é que os bots com atividade "aleatória" não são tão bem detectados. Isso é equilibrado usando a lógica Last King Stand quando o oponente não é conhecido.
No entanto, se um bot é puramente determinístico, não há problemas para descobrir quem é. Ele pode ser facilmente adaptado à situação adicionando mais casos à sua lógica para cada oponente. Por exemplo, combater Last Stand, ele irá encurralá-lo, ficar 2x1 de distância para que ele não possa se mover ou disparar diretamente, e atirar mísseis contra a parede atrás, matando-a com dano de respingo.
Como meus outros, estende o BattleBot.java:
fonte
ReadyAimShoot
a R Bot
Esse bot tenta se colocar na mesma linha ou coluna que o alvo, quando está alinhado com o alvo, dispara o EMP; em seguida, no turno seguinte, dispara um míssil em direção ao alvo e, em seguida, uma bala. Também deve estar ciente da mina ao redor e evitá-la, mas é completamente alheio a balas e mísseis. Se a vida já estiver em 1, pula o EMP.
Para acompanhar quando ele aciona o EMP, modifica seu código-fonte adicionando um comentário no final do arquivo (
#p_fired2
no início, modifica-o#p_fired1
e depois apaga-o). Espero que acompanhar quando ele desencadeia o EMP dessa maneira não seja muito limitado.A linha de comando deve ser
Rscript ReadyAimShoot.R
, seguida pelo argumento, como no exemplo, pelo menos nos sistemas UNIX, mas provavelmente também no Windows (vou verificar isso quando realmente testá-lo nos outros bots).Edit : Como a versão R parece ter problemas ao analisar a entrada, aqui está uma versão python do mesmo bot que, espero, funciona. Se qualquer outro programador R vir a publicação e ver o que há de errado com esse bot, fique à vontade para depurar!
fonte
Última posição do rei
Uma extensão para o meu
BattleBot
, isso é projetado para combater EMP-blasters. A única maneira sensata (IMO) de usar o EMP é disparando-o enquanto você está no mesmo eixo do oponente e, em seguida, disparando mísseis / armas em direção ao oponente preso. Então, eu fico fora do eixo :)Se você já teve um jogo de xadrez disputando um rei contra uma rainha + rei, você sabe que uma rainha sozinha não pode fazer xeque-mate , você deve envolver o rei. Caso contrário, a estratégia do rei solitário é fácil: tente ficar fora do eixo e em direção ao centro para maximizar a mobilidade. Se você ficar preso, vá para um impasse.
É claro que não há uma maneira excelente de forçar um impasse aqui, então, eventualmente, você ficará preso em um lado ou canto se a rainha estiver jogando em qualquer nível de competência. Se esse bot estiver nessa situação, ele dispara. Supondo que o oponente vá ao EMP, isso oferece uma vantagem de dano de uma volta, então a última posição do rei deve ficar boa, a menos que ele já esteja com pouca vida.
Ah, e se já estiver fora do eixo e a salvo de projéteis, será necessário um tiro certeiro na direção geral do inimigo.
LastStand.java
Para compilar a execução, coloque em uma pasta
BattleBot.java
e execute:fonte
EvadeBot
Este bot prioriza permanecer vivo. Se ele detecta colisões recebidas, tenta se mover para um local seguro, verificando se há colisões nesse local. Se não houver pontos "seguros" ao redor, ele permanece colocado e passa para a próxima etapa.
Se não houve colisões (ou pontos seguros em caso de colisão), ele faz uma verificação de ataque. Se o oponente estiver alinhado em 8 eixos, ele dispara 80% do tempo. Se não estiver alinhado, ele dispara 50% do tempo no cabeçalho mais próximo. Ele escolhe uma arma com base na distância. Se estiver perto, uma mina terrestre ou uma bala (dependendo da distância exata e da saúde relativa), mísseis de longe.
Se ele decidir não disparar, ele fará uma caminhada aleatória (novamente procurando pontos seguros).
Se nenhuma das opções acima der certo, ela fica lá até a próxima curva.
Ele não usa EMP, e eu tenho um mau pressentimento sobre lutar contra
ReadyAimShoot
, mas vamos ver como vai.O código está dividido em duas partes. Como posso criar mais de um bot, criei uma
BattleBot
classe abstrata . Inclui funções auxiliares, como a leitura da arena, verificação de colisão, gerenciamento de rumo, etc. Há também uma função de registro para ajudar a rastrear o que está acontecendo durante a depuração. Sedebug==false
, apenas imprimirá a saída real. Se alguém quiser usá-lo / ampliá-lo, fique à vontade. Não é um código bonito , mas é melhor do que escrever clichê.BattleBot.java
Este bot em particular é
EvadeBot
. Para compilar / executar, coloque-o em uma pastaBattleBot.java
e execute:Se você omitir o argumento ou ele não puder ser analisado corretamente, o padrão será o
"0"
resultado.EvadeBot.java
fonte
BattleBots.java
. Você pode recompilar meus bots antes da próxima execução?Spiral Bot Literate Haskell
No haskell alfabetizado, os comentários são padrão, portanto, todo este post é o programa. Este bot dispara mísseis em espirais ao seu redor, ignorando a entrada. Ele armazena o estado em um arquivo (que, esperançosamente, não está sendo posicionado pelo compilador).
Primeiro, listamos as ações dos mísseis.
Em seguida, vamos direto para a mônada de IO. Se "spiral.txt" não existir, escrevemos "0" para ele. Também verificamos o diretório.
Em seguida, lemos e imprimimos a ação.
E, finalmente, escrevemos no arquivo a posição agora.
fonte
state
para evitar conflitos acidentais com outros arquivos não estatais.LiterateHaskell.lhs:13:5: Not in scope: 'createDirectoryIfMissing'
eLiterateHaskell.lhs:14:5: Not in scope:
setCurrentDirectory '' quando tento compilar.DodgeTurret
um Python Bot
Aqui está outra tentativa. Como o ReadyAimShoot está na oficina por um tempo :) imaginei que tentaria outra coisa nesse meio tempo, usando o Python dessa vez.
Eu descaradamente roubei a linha
sys.argv[1].splitlines()
do @Gareth, mas pelo menos dessa vez isso significa que não terei problemas ao analisar a entrada.Este bot corre no centro no início da luta, fica lá e atira mísseis na direção do oponente. Ele também tenta desviar de balas e mísseis próximos, se estiver a caminho, mas depois volta ao centro antes de começar a atirar novamente.
fonte
Atirador reto
Este é outro bot simples que você pode usar para testar. Se ele tem uma linha de visão direta para o oponente, ele dispara, caso contrário, ele pisa aleatoriamente.
fonte
neo-bot
coffeescript
Outro bot JavaScript para adicionar à mistura. Este é direcionado ao Node.js e está escrito em CoffeeScript. A arquitetura segue a multidão Java com uma classe base manipulando o engarrafamento geral e outro arquivo com especialização para o bot disponível.
A principal estratégia deste bot é não ser atingido por seus projéteis. Se você não é uma ameaça imediata, o neo-bot começará a atirar.
O arquivo base
shared.coffee
E
neo-bot.coffee
, o código bot.Eu recomendo compilar os arquivos de café em javascript antes de executar; é um pouco mais rápido. Basicamente, você deseja fazer isso:
fonte
CamperBot
Este bot fica onde está e atira. Eu apenas implantei balas, pois as outras armas prejudicariam o bot. Por favor, perdoe minhas terríveis habilidades em C;)
Não é realmente esperado ganhar muito.
fonte
Como ainda não existem inscrições, colocarei uma por aí, para que você tenha algo a perder. Eu te dou:
Meu! Meu! Meu!
Não faz nada particularmente inteligente. Larga uma mina se não houver nenhum dos quadrados circundantes, caso contrário, ele se moverá para um dos quadrados circundantes seguros. Mal consegue vencer o HuggyBot.
Por favor, desculpe a codificação naff Python.
fonte
Bot aleatório
Este bot apenas faz uma ação aleatória em cada movimento. Ele não aciona o EMP e nem sequer olha para o mapa. Metade do tempo está apenas disparando contra a parede!
Teste (contra si mesmo) como abaixo.
fonte
int main
certo?void main
é BS.Problemas e Strafe
Alguma representação do Ruby na luta. Move para cima e para baixo os mísseis de disparo de parede designados aleatoriamente na parede oposta. Ligeiramente defeituoso na parte superior e inferior.
fonte
Um núcleo JavaScript
Eu pensei que seria gentil e lhe daria o meu bot principal do JS. Possui todas as funções necessárias para criar um bot. Tudo o que você precisa é de algumas ações a serem realizadas com base nos dados que isso fornece. Ainda não terminei, pois não posso testá-lo (não é possível obter o código da arena para compilar).
Sinta-se livre para usar isso, estou ansioso para ver alguns bots JS no mix.
Façam:
Adicione funções para calcular os locais das armas
Observe que algumas coisas aqui podem precisar ser modificadas para outro sistema operacional (isso funciona apenas no Windows). Versão do Rhino aqui: http://pastebin.com/FHvmHCB8
fonte
Center-Bot
Um JavaScript Bot
Este bot tem como objetivo entrar no meio da arena, antes de disparar balas ou mísseis contra o alvo a cada turno, dependendo de quão perto estiver. Se o inimigo estiver no meio, ele continuará disparando balas na direção vaga.
Não espero que funcione muito bem, mas é mais um teste, e estou interessado em ver como realmente se sai.
salve como arquivo .js e execute com
node centrebot.js
. Isso funcionará com o Node.js, mas talvez seja necessário modificá-lo para outro programa, desculpe!Nos meus testes:
Ainda não testei nenhum dos principais bots java, e também não estou muito confiante ...
fonte
putstr(...)
em vez do seustdo.writeLine(...)
e a entrada é provenientescriptArgs[0]
. Tendo feito o que eu precisava para mudar a\\n
para\n
dividir o mapa em linhas. Quando o executo, recebo um erro porqueFindFoe()
efindCentre()
são definidos, mas não são chamados.E
você deve ter umW
e onde quer que você tenha um,S
você deve ter umN
. Se você usar a entrada de exemplo da pergunta, poderá ver que a saída do programaSE
não é uma direção possível no canto inferior direito. Eu o corrigi para a próxima execução de teste.CunningPlanBot (Python 3.3)
Isso é completamente não testado na interface real ... Funciona corretamente com os mapas pelo menos!
Está escrito para Python 3.3
O que faz:
Se na Fase 1 - Se a parede e a direção se moverem para a parede ou se mudarem para uma mina terrestre, mude aleatoriamente a direção para uma direção que não seja parede ou mina terrestre - Mova-se na direção atual - Vá para a Fase 2
Se na Fase 2 - Atire a bala na direção mais próxima do inimigo - Vá para a Fase 3
Se na Fase 3 - Se não houver minas terrestres, largue as minas terrestres - Vá para a Fase 1
Ainda precisa descobrir se dispara um míssil. Também não tenho idéia alguma sobre se as coisas que evitam as minas terrestres funcionam. Precisa de mais testes amanhã à noite.
fonte
sys.argv[1].splitlines()
pegar a entrada da linha de comando e, em seguida, usavaline[x][y]
no seguinte bloco; adicionadoend=""
aos comandos de impressão para se livrar da nova linha que confunde o apontador; alterou o estado para gravar em um arquivo dentro dostate
diretório e nãostate
ele próprio.UltraBot
Um bot Java que calcula o perigo para cada campo circundante. Se um campo circundante é menos perigoso que o atual, o bot se move para lá (ou outro campo igualmente perigoso). Se não houver campo menos perigoso, o bot atira (mísseis se o bot inimigo estiver longe, balas se o bot inimigo estiver próximo). Peguei um código do BattleBot (obrigado!).
Esse bot é extremamente difícil de acertar, mas não é muito bom em atirar no inimigo ... Eu ainda espero que seja melhor que o meu CamperBot anterior.
fonte
import
s?UltraBot.java:...: x has private access in Point
NinjaPy
Um envio de última hora em python (não testado, mas espero que funcione). A idéia é que ele avance em direção ao oponente enquanto permanece em seu ponto cego. Quando está perto o suficiente (3 células), ele se coloca na diagonal do oponente e dispara um míssil.
fonte