Los resultados están en, el concurso ha terminado.
El ganador es EvilBot de arshajii con 14 victorias por delante de Neo-Bot con 13 victorias y CentreBot y LastStand con 11 victorias cada una.
Puntajes de la carrera 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 es un desafío del rey de la colina . El objetivo es escribir un bot que supere a más bots que cualquier otro.
El juego
Todos los bots se enfrentarán entre sí 2 a la vez en una arena de 10x10 con la tarea de reducir la energía del oponente de 10 a 0 antes de que su propia energía se reduzca a 0.
Cada partido constará de 5 combates. El ganador del partido es el ganador de la mayoría de los combates. El programa de control almacenará el número total de victorias y combates y se utilizará para determinar el ganador general del concurso. El ganador recibe la gran marca verde y la adulación de las masas.
Cada combate continuará en una serie de rondas. Al comienzo de cada ronda, el estado actual de la arena se le dará a cada bot y el bot responderá con un comando para determinar qué quiere hacer a continuación. Una vez que el programa de control ha recibido ambos comandos, ambos comandos se ejecutan al mismo tiempo y los niveles de energía de arena y bot se actualizan para reflejar el nuevo estado. Si ambos bots aún tienen suficiente energía para continuar, el juego pasa a la siguiente ronda. Habrá un límite de 1000 rondas por combate para garantizar que ningún combate continúe para siempre, y en caso de que se alcance este límite, el ganador será el bot con más energía. Si ambos bots tienen la misma energía, el combate es un empate y ninguno de los dos obtendrá un punto por la victoria (sería como si ambos hubieran perdido).
Las armas
Cada bot tendrá a su disposición una serie de armas:
- Balas perforantes. Estos viajan 3 casillas a la vez y causan 1 punto de daño de energía.
- Misiles Estos viajan 2 casillas a la vez y causan 3 puntos de daño de energía en el punto de impacto, y 1 punto de daño en todas las casillas que rodean inmediatamente.
- Minas terrestres. Estos se dejan caer en una de las casillas que rodean al bot y causan 2 puntos de daño de energía cuando se pisa, y 1 punto de daño de energía a cualquier cosa que se encuentre en una de las casillas que rodean inmediatamente.
- Pulso electromagnetico. Hace que los circuitos de movimiento de ambos robots funcionen mal durante 2 turnos, lo que significa que no pueden moverse. Sin embargo, aún pueden desplegar armas (sí, sé que eso no es realista, pero es un juego. Se supone que no es la vida real). Editar: cada implementación de EMP costará un punto de energía para el bot que lo usa.
Las balas / misiles solo pueden impactar con bots o paredes. Golpearán cualquier bot que esté en cualquiera de los cuadrados por los que viajan. Desaparecen una vez que golpean algo.
En todos los casos, immediately surrounding squares
significa los 8 cuadrados a los que el bot podría moverse en su próximo movimiento: el vecindario de Moore.
Los comandos
0
hacer nada.N
,NE
,E
,SE
,S
,SW
,W
,NW
Son todos los comandos de dirección y mover el bot un cuadrado en la dirección dada. Si el bot no puede moverse en esa dirección porque hay una pared u otro bot en la casilla, el bot permanece donde está. Moverse a un cuadrado que ya contiene una bala o misil es seguro ya que se considerará que la bala / misil ya está saliendo de ese cuadrado.B
seguido de un espacio y luego uno de los comandos de dirección dispara una bala perforadora de armadura en esa dirección.M
seguido de un espacio y luego uno de los comandos de dirección dispara un misil en esa dirección.L
seguido de un espacio y luego uno de los comandos de dirección deja caer una mina terrestre en esa casilla al lado del bot. Si el cuadrado ya está ocupado por una pared o un bot, el comando se ignora. Si una mina terrestre se deja caer sobre otra mina terrestre, la detona. Esto dañará al bot que esté cayendo, y a cualquier otro bot dentro del alcance de la mina terrestre original.P
dispara el EMP.
Dado que solo se puede dar un comando por ronda, un bot solo puede mover o disparar / desplegar un arma, no hacer ambas cosas al mismo tiempo.
Orden de los comandos
El movimiento de cualquiera de los bots siempre vendrá primero, y todos los movimientos se intentarán dos veces para dar cuenta de que otro bot está en el camino pero se está apartando del camino.
Ejemplo
- Bot1 intenta moverse
E
pero Bot2 ya está en esa casilla - El programa de control pasa a Bot2.
- Bot2 intenta moverse
S
y tiene éxito porque no hay nada en el camino. - Bot1 consigue un segundo intento de hacer su movimiento. Esta vez tiene éxito y Bot1 se mueve
E
.
Una vez que los bots hayan hecho cualquier movimiento que quieran hacer, se dispararán las armas y todos los proyectiles (nuevos y disparados previamente) moverán su número predefinido de casillas.
La arena
Al comienzo de cada ronda, el bot recibirá el estado actual de juego como el único argumento de línea de comando del 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
La arena viene primero que consiste en 10 líneas de 10 personajes. Está rodeado de paredes que no se muestran. Los significados de los personajes son los siguientes:
.
representa un cuadrado vacíoY
representa a tu bot.X
representa al oponente bot.L
representa una mina terrestre.B
representa una bala en vuelo.M
representa un misil en vuelo.
Esto es seguido por la energía restante de los bots, un bot por línea. Solo un espacio separará el identificador de bot de su nivel de energía. Como en la arena, Y
representa a tu bot y X
representa a tu oponente. Finalmente viene una lista de los proyectiles y minas terrestres, sus posiciones y (si corresponde) encabezados, nuevamente uno por línea.
El programa de control
#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';
}
}
El programa de control llamará a su bot desde la línea de comandos. Por esta razón, los programas que no se pueden llamar desde la línea de comando se considerarán inválidos . Pido disculpas a aquellos cuyo lenguaje de elección no funciona de esa manera, pero hacer cada partido manualmente no sería práctico.
intx13 ha escrito amablemente una versión más robusta del programa de control con algunas correcciones de errores que puede encontrar aquí .
Las sugerencias de mejoras o correcciones de errores en el programa de control son bienvenidas.
Prueba de bots
Ninguno de los bots de prueba se incluirá en las carreras de puntuación. Son solo para fines de prueba.
Dudley DoNowt (C)
int main(int argc, char *argv)
{
printf("0");
}
No hace nada independientemente de la situación. No se espera ganar mucho.
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);
}
?>
Trata de estar justo al lado del oponente. Vulnerable a las minas terrestres ya que no las busca. Hace que disparar misiles sea una táctica menos efectiva para el oponente cuando logra su objetivo.
Los resultados
La carrera de puntuación final se realizará después de las 23:59 del 24 de marzo de 2014 . Realizaré pruebas de forma regular para que los participantes puedan ver cómo sus bots se están comparando con la oposición actual.
Entradas
Las entradas deben incluir la fuente de su bot y el argumento de la línea de comando que necesitaré para ejecutarlo. Puede publicar tantas entradas diferentes como desee, pero cada respuesta debe contener solo un bot.
Importante
Parece que algunas entradas desean escribir en el disco para conservar cierto estado entre ejecuciones. Estas son nuevas reglas con respecto a la escritura en el disco.
- Puede modificar la fuente de su propio bot. Modificar cualquier otro bot es hacer trampa y resultará en la descalificación del bot infractor.
- Puede escribir en un archivo creado con el propósito de almacenar el estado. Este archivo debe almacenarse en un subdirectorio del directorio donde se encuentra su bot. El subdirectorio será nombrado
state
. No se permite escribir en ninguna otra parte del sistema de archivos (que no sea su propia fuente).
fuente
Respuestas:
EvilBot
un bot que intenta ser lo más malvado posible
Bueno, esto es lo que tengo: un robot de Java que intenta acercarse lo más posible al
oponente auna franja circular de radio 2.5 alrededor del centro de la arena y luego hacer el mayor daño posible cuando pueda. Su patrón de movimiento se basa en asignar un valor de "peligro" a cada una de sus casillas vecinas, y en decidir moverse según estos valores y en una tendencia a estar tan cerca de una región circular de radio 2.5 alrededor del centro de la arena. Utilicé algunos de los detalles de la respuesta de @ Geobits (por ejemplo, tener un resumenBattleBot
clase y la técnica de análisis), ¡así que gracias! Probablemente voy a modificar / expandir lo que tengo hasta ahora, aunque le va bastante bien, al igual que con los otros bots publicados hasta ahora. El código está abajo. (si alguien más está usando Java, siéntase libre de usar mis clases abstractas / auxiliares).(
EvilBot.java
)Uso:
Notas:
Actualmente, las minas terrestres no se utilizan, solo se esquivan. Probablemente no voy a cambiar esto, ya que el uso de minas terrestres parece hacer más daño que bien (al menos para EvilBot) a juzgar por algunas pruebas que realicé.
Actualmente, EMP no se está utilizando. Intenté la estrategia de alinearme con el oponente y disparar el EMP seguido de misiles, pero hay algunas contraestrategias que ganarían casi el 100% del tiempo, así que decidí abandonar esa ruta. Podría explorar el uso del EMP de diferentes maneras más adelante.
fuente
Rifter
Este bot realiza diferentes acciones en función de qué bot está luchando. Para determinar al oponente, cambia su propio estado y lo alimenta a los otros bots para ver qué harían, y lo compara con lo que realmente hacen. Una vez que alcanzan un umbral de movimientos "correctos", deja de probar a los demás.
Una vez que sabe a qué bot está luchando, generalmente sabe dónde estará en el próximo turno, por lo que puede disparar allí en lugar de su posición actual.
Por supuesto, hay algunos inconvenientes. Una es que los bots que tienen actividad "aleatoria" no se detectan tan bien. Esto se equilibra mediante el uso de la lógica King's Last Stand cuando no se conoce al oponente.
Sin embargo, si un bot es puramente determinista, no tiene problemas para descubrir quién es. Luego se puede adaptar fácilmente a la situación agregando más casos en su lógica para cada oponente. Por ejemplo, al luchar contra Last Stand, lo arrinconará, se mantendrá 2x1 de distancia para que no pueda moverse o disparar directamente, y disparará misiles contra la pared detrás, matándolo con daños por salpicadura.
Como mis otros, extiende BattleBot.java:
fuente
ReadyAimShoot
a R Bot
Este bot intenta colocarse en la misma fila o columna que el objetivo, cuando está alineado con el objetivo dispara el EMP, luego, en el siguiente turno, dispara un misil hacia el objetivo y luego una bala. También debe ser consciente de la mina circundante y evitarlos, pero es completamente ajeno a las balas y los misiles. Si la vida ya está en 1, se salta el EMP.
Para realizar un seguimiento de cuándo activa el EMP, modifica su código fuente agregando un comentario al final del archivo (
#p_fired2
al principio, luego lo modifica#p_fired1
y luego lo borra). Espero que hacer un seguimiento de cuándo desencadena el EMP de esta manera no sea demasiado límite.La línea de comando debe ser
Rscript ReadyAimShoot.R
, seguida del argumento como en el ejemplo, al menos en sistemas UNIX pero probablemente también en Windows (lo comprobaré cuando lo pruebe en realidad con los otros bots).Editar : Dado que la versión R parece tener problemas para analizar la entrada, aquí hay una versión de Python del mismo bot con, espero, funciona. Si cualquier otro programador de R ve la publicación y ve qué le pasa a este bot, ¡no dude en depurar!
fuente
El último puesto del rey
Una extensión para mi
BattleBot
, esto está diseñado para combatir EMP-blasters. La única forma sensata (IMO) de usar EMP es disparándolo mientras estás en el mismo eje que el oponente, luego disparando misiles / armas hacia el oponente atascado. Entonces, me mantengo fuera del eje :)Si alguna vez has tenido un juego de ajedrez contra un rey contra un rey + reina, sabes que una reina sola no puede hacer jaque mate , debes involucrar al rey. Si no lo hace, la estrategia del rey solitario es fácil: trate de mantenerse fuera del eje y hacia el centro para maximizar la movilidad. Si te quedas atascado, ve a un punto muerto.
Por supuesto, no hay una gran manera de forzar un punto muerto aquí, así que eventualmente te quedas atascado en un lado o esquina si la reina está jugando en cualquier nivel de competencia. Si este bot alguna vez está en esa situación, dispara. Suponiendo que el oponente vaya a EMP, esto le da una ventaja de daño de un turno, por lo que la última posición del rey debería salir bien a menos que ya tenga poca vida.
Ah, y si ya está fuera del eje y a salvo de proyectiles, solo tomará un disparo en la dirección general del enemigo.
LastStand.java
Para compilar run, colóquelo en una carpeta con
BattleBot.java
y ejecute:fuente
EvadeBot
Este bot prioriza mantenerse con vida. Si detecta colisiones entrantes, se trata de moverse a un lugar seguro comprobando que la mancha de colisiones. Si no hay lugares "seguros" circundantes, se queda donde está y pasa al siguiente paso.
Si no hubo colisiones (o puntos seguros en caso de colisión), se realiza una comprobación de ataque. Si el oponente está alineado en 8 ejes, dispara el 80% del tiempo. Si no está alineado, se dispara el 50% del tiempo en el encabezado más cercano. Elige un arma basada en la distancia. Si está cerca, una mina terrestre o una bala (dependiendo de la distancia exacta y la salud relativa), misiles desde lejos.
Si decidió no disparar, realiza una caminata aleatoria (nuevamente buscando lugares seguros).
Si nada de lo anterior funcionó, simplemente se queda allí hasta el próximo turno.
No usa EMP, y tengo un mal presentimiento acerca de cómo enfrentarse
ReadyAimShoot
, pero veremos cómo funciona.El código está en dos piezas. Como puedo hacer más de un bot, creé una
BattleBot
clase abstracta . Incluye funciones auxiliares como leer la arena, verificación de colisiones, gestión de encabezados, etc. También hay una función de registro para ayudar a rastrear lo que está sucediendo durante la depuración. Sidebug==false
, solo imprimirá la salida real. Si alguien quiere usarlo / extenderlo, siéntase libre. No es un código bonito , pero supera la escritura repetitiva.BattleBot.java
Este bot en particular es
EvadeBot
. Para compilar / ejecutar, póngalo en una carpeta conBattleBot.java
y ejecute:Si omite el argumento o no puede analizarlo correctamente, el valor predeterminado es la
"0"
salida.EvadeBot.java
fuente
BattleBots.java
. ¿Puedes recompilar mis bots antes de la próxima ejecución?Espiral Bot Literate Haskell
En haskell alfabetizado, los comentarios son predeterminados, por lo que esta publicación completa es el programa. Este bot disparará misiles en espirales a su alrededor, ignorando la entrada. Almacena el estado en un archivo (que es de esperar que el competidor no lo incluya).
Primero enumeramos las acciones de misiles.
A continuación, vamos directamente a la mónada IO. Si "spiral.txt" no existe, le escribimos "0". También verificamos el directorio.
Luego lo leemos e imprimimos la acción.
Y finalmente escribimos en el archivo la posición actual.
fuente
state
para evitar conflictos accidentales con cualquier otro archivo no estatal.LiterateHaskell.lhs:13:5: Not in scope: 'createDirectoryIfMissing'
yLiterateHaskell.lhs:14:5: Not in scope:
configurandoCurrentDirectory '' cuando intento compilar.Torreta esquivada
un robot de Python
Aquí hay otro intento. Dado que ReadyAimShoot está en el taller de reparación por un tiempo :) pensé que mientras tanto intentaré otra cosa, esta vez usando Python.
sys.argv[1].splitlines()
Desvergonzadamente robé la línea de @Gareth, pero al menos esta vez eso significa que no tendré problemas para analizar la entrada.Este bot corre en el centro al comienzo del combate, luego se queda allí y dispara misiles en la dirección del oponente. También intenta esquivar balas y misiles cercanos si está en su camino, pero luego regresa al centro antes de comenzar a disparar nuevamente.
fuente
Tirador recto
Este es otro bot simple que puedes usar para probar. Si tiene una línea de visión directa con el oponente al que dispara, de lo contrario, da un paso al azar.
fuente
neo-bot
coffeescript
Otro bot de JavaScript para agregar a la mezcla. Éste apunta a Node.js y está escrito en CoffeeScript. La arquitectura se sigue de la multitud de Java con una clase base que maneja la bottinidad general y otro archivo con especialización para el bot en cuestión.
La estrategia principal de este bot es no ser golpeado por tus proyectiles. Si no eres una amenaza inmediata, neo-bot simplemente comenzará a disparar.
El archivo base
shared.coffee
Y
neo-bot.coffee
, el código bot.Recomiendo compilar los archivos de café a javascript antes de ejecutarlos; Es un poco más rápido. Básicamente quieres hacer esto:
fuente
CamperBot
Este bot solo se queda donde está y dispara. Solo implementé balas, ya que las otras armas dañarían al bot. Por favor, perdóname mis terribles habilidades C;)
Realmente no esperaba ganar mucho.
fuente
Como todavía no hay entradas, pondré una para que tengas algo que ganar. Te doy a ti:
¡Mía! ¡Mía! ¡Mía!
No hace nada particularmente inteligente. Deja caer una mina si no hay ninguno en ninguno de los cuadrados circundantes; de lo contrario, se mueve a uno de los cuadrados seguros circundantes. Apenas puede vencer al HuggyBot.
Por favor, disculpe la codificación Python naff.
fuente
Bot aleatorio
Este bot solo realiza una acción aleatoria en cada movimiento. No dispara el EMP y no mira el mapa en absoluto. ¡La mitad del tiempo solo está disparando contra la pared!
Pruébelo (contra sí mismo) como se muestra a continuación.
fuente
int main
bien?void main
es BS.Problemas y Strafe
Alguna representación de Ruby en la lucha. Mueve hacia arriba y hacia abajo los misiles de disparo de pared asignados al azar en la pared opuesta. Ligeramente irregular en la parte superior e inferior.
fuente
Un núcleo de JavaScript
Pensé que sería amable y te daría mi núcleo JS bot. Tiene todas las funciones necesarias para hacer un bot, todo lo que necesita es hacer algunas acciones en función de los datos que le proporciona. Todavía no ha terminado, ya que realmente no puedo probarlo (no puedo obtener el código de arena para compilar).
Siéntase libre de usar esto, estoy ansioso por ver algunos bots JS en la mezcla.
Que hacer:
Agregue funciones para calcular ubicaciones de armas
Tenga en cuenta que algunas cosas aquí pueden tener que modificarse para otro sistema operativo (esto solo funciona en Windows). Versión de Rhino aquí: http://pastebin.com/FHvmHCB8
fuente
Center-Bot
Un bot de JavaScript
Este bot tiene como objetivo llegar al medio de la arena, antes de disparar balas o misiles a su objetivo cada turno, dependiendo de qué tan cerca esté. Si el enemigo está en el medio, seguirá disparando balas en la dirección vaga.
No espero que le vaya muy bien, pero es más una prueba, y estoy interesado en ver qué tan bien lo hace realmente.
guardar como archivo .js y ejecutar con
node centrebot.js
. Esto funcionará con Node.js, pero es posible que deba modificarlo para otro programa, ¡lo siento!En mis pruebas:
No he probado ninguno de los mejores robots de Java, y tampoco estoy muy seguro ...
fuente
putstr(...)
en lugar de tustdo.writeLine(...)
y la entrada provienescriptArgs[0]
. Habiendo hecho de que tenía que cambiar el\\n
de\n
dividir el mapa en las líneas. Cuando lo ejecuto me sale un error porqueFindFoe()
yfindCentre()
se definen pero no se llaman.E
, debe tener unW
y donde sea que tenga unS
, debe tener unN
. Si usa la entrada de ejemplo de la pregunta, puede ver que la salida del programaSE
no es una dirección posible desde la esquina inferior derecha. Lo he corregido para la próxima prueba.CunningPlanBot (Python 3.3)
Esto no se ha probado completamente en la interfaz real ... ¡Funciona correctamente con los mapas al menos!
Está escrito para Python 3.3
Que hace:
Si está en la Fase 1 - Si en la pared y la dirección se mueve hacia la pared o hacia una mina terrestre, cambie aleatoriamente la dirección a una dirección que no sea de pared o mina - Muévase en la dirección actual - Vaya a la Fase 2
Si está en la Fase 2 - Dispara una bala en la dirección más cercana al enemigo - Pasa a la Fase 3
Si está en la Fase 3 - Si no hay mina terrestre, deje caer la mina terrestre - Pase a la fase 1
Todavía necesita averiguar si disparar un misil. Además, no tengo ni idea de si las cosas para evitar las minas terrestres funcionan. Necesita más pruebas mañana por la noche.
fuente
sys.argv[1].splitlines()
tomar la entrada de la línea de comandos y luego la usabaline[x][y]
en el siguiente bloque; agregadoend=""
a los comandos de impresión para deshacerse de la nueva línea que confunde al anotador; cambió el estado para escribir en un archivo dentro delstate
directorio en lugar de enstate
sí mismo.UltraBot
Un robot de Java que calcula el peligro para cada campo circundante. Si un campo circundante es menos peligroso que el actual, el bot se mueve allí (u otro campo igualmente peligroso). Si no hay un campo menos peligroso, el bot dispara (misiles si el bot enemigo está lejos, balas si el bot enemigo está cerca). Tomé un código del BattleBot (¡gracias!).
Este bot es extremadamente difícil de golpear, pero no es muy bueno para disparar al enemigo ... Todavía espero que sea mejor que mi CamperBot anterior.
fuente
import
s?UltraBot.java:...: x has private access in Point
NinjaPy
Un envío de última hora en python (no probado pero con suerte funcionará). La idea es que avance hacia el oponente mientras permanece en su punto ciego. Cuando está lo suficientemente cerca (a 3 celdas de distancia) se coloca en la diagonal del oponente y dispara un misil.
fuente