Les résultats sont là, le concours est terminé.
Le vainqueur est EvilBot d’ arshajii avec 14 victoires sur Neo-Bot avec 13 victoires et CentreBot et LastStand avec 11 victoires chacun.
Scores de la dernière manche
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)
C'est un défi roi . Le but est d’écrire un bot qui vaincra plus d’autres bots que d’autres.
Le jeu
Les robots seront tous opposés 2 à la fois dans une arène 10x10 avec la tâche de réduire l'énergie de l'adversaire de 10 à 0 avant que sa propre énergie ne soit réduite à 0.
Chaque match consistera en 5 combats. Le vainqueur du match est le vainqueur du plus grand nombre de combats. Le nombre total de victoires de match et de victoires de combat sera stocké par le programme de contrôle et sera utilisé pour déterminer le vainqueur final du concours. Le gagnant reçoit la grosse coche verte et l'adulation des masses.
Chaque combat se déroulera en plusieurs tours. Au début de chaque tour, l'état actuel de l'arène sera donné à chaque bot qui lui répondra ensuite avec une commande pour déterminer ce qu'il veut faire ensuite. Une fois que les deux commandes ont été reçues par le programme de contrôle, les deux commandes sont exécutées en même temps et les niveaux d’énergie de l’arène et du bot sont mis à jour pour refléter le nouvel état. Si les deux bots ont encore assez d’énergie pour continuer, le jeu passe au tour suivant. Il y aura une limite de 1000 rounds par combat pour éviter les combats, et si cette limite est atteinte, le vainqueur sera le bot le plus énergique. Si les deux bots ont la même énergie, le match est un match nul et aucun des deux ne marquera de victoire (ce serait comme s'il avait perdu tous les deux).
Les armes
Chaque bot aura à sa disposition un certain nombre d'armes:
- Des balles perforantes. Ceux-ci parcourent 3 cases à la fois et provoquent 1 point d'énergie de dommage.
- Missiles. Celles-ci parcourent 2 cases à la fois et provoquent 3 points de dégâts d'énergie au point d'impact et 1 point de dégâts dans toutes les cases environnantes.
- Mines terrestres. Celles-ci tombent dans l'une des cases entourant immédiatement le bot et causent 2 points de dégâts d'énergie en marchant dessus et 1 point de dégâts en énergie à tout ce qui se trouve dans l'une des cases environnantes.
- Pulsation éléctromagnétique. Provoque le dysfonctionnement des circuits de mouvement des deux robots pendant 2 tours, ce qui signifie qu'ils ne peuvent pas bouger. Ils peuvent cependant toujours utiliser des armes (oui, je sais que ce n’est pas réaliste, mais c’est un jeu. Ce n’est pas censé être la vraie vie). Edit: chaque déploiement EMP coûte un point d'énergie au bot qui l'utilise.
Les balles / missiles ne peuvent toucher que des robots ou des murs. Ils vont frapper n'importe quel bot qui se trouve dans l'une des cases par lesquelles ils passent. Ils disparaissent une fois qu'ils ont frappé quelque chose.
Dans tous les cas, immediately surrounding squares
désigne les 8 carrés vers lesquels le bot pourrait se déplacer lors de son prochain déplacement - le quartier de Moore.
Les commandes
0
ne fais rien.N
,NE
,E
,SE
,S
,SW
,W
,NW
Sont toutes les commandes de direction et déplacer le robot d' une case dans la direction donnée. Si le bot est incapable de se déplacer dans cette direction car il y a un mur ou un autre bot sur la case, le bot reste là où il se trouve. Il est prudent de se rendre dans une case contenant déjà une balle ou un missile, car on considérera que la balle / le missile est déjà en train de sortir de cette case.B
suivi d'un espace, puis l'une des commandes de direction tire une balle perforante dans cette direction.M
suivi d'un espace, puis l'une des commandes de direction tire un missile dans cette direction.L
suivi d'un espace, puis l'une des commandes de direction dépose une mine terrestre sur cette case à côté du bot. Si la case est déjà occupée par un mur ou un bot, la commande est ignorée. Si une mine terrestre tombe sur une autre, elle la fait exploser. Cela endommagerait le bot qui effectuait le largage et tout autre bot à portée de la mine d'origine.P
déclenche l'EMP.
Comme un seul commandement peut être donné par tour, un bot ne peut que déplacer ou tirer / déployer une arme, et non les deux à la fois.
Ordre des commandes
Le mouvement de l'un ou l'autre bot viendra toujours en premier, et tous les mouvements seront tentés deux fois pour tenir compte du fait qu'un autre bot se trouve sur le chemin, mais qu'il se déplace à l'écart.
Exemple
- Bot1 essaie de bouger
E
mais Bot2 est déjà dans cette case - Le programme de contrôle passe à Bot2.
- Bot2 essaie de bouger
S
et réussit car rien ne l' empêche . - Bot1 tente une seconde fois de jouer son coup. Cette fois, cela réussit et Bot1 se déplace
E
.
Une fois que les bots ont effectué les mouvements qu’ils souhaitent, les armes seront tirées et tous les projectiles (nouveaux et précédemment tirés) déplaceront le nombre de carrés prédéfini.
L'arène
Au début de chaque tour, le bot recevra l'état actuel du jeu comme seul argument de ligne de commande du programme:
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 première arène est composée de 10 lignes de 10 caractères. Il est entouré de murs non représentés. La signification des caractères est la suivante:
.
représente un carré videY
représente votre bot.X
représente le bot adverse.L
représente une mine terrestre.B
représente une balle en vol.M
représente un missile en vol.
Vient ensuite l’énergie restante des robots, un robot par ligne. Un seul espace séparera l'identifiant du bot de son niveau d'énergie. Comme dans l'arène, Y
représente votre bot et X
représente votre adversaire. Vient enfin une liste des projectiles et des mines antipersonnel, leurs positions et (le cas échéant) leurs en-têtes, encore une fois par ligne.
Le programme de contrôle
#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';
}
}
Le programme de contrôle appellera votre bot depuis la ligne de commande. Pour cette raison, les programmes qui ne peuvent pas être appelés à partir de la ligne de commande seront considérés comme non valides . Je m'excuse auprès de ceux dont le langage choisi ne fonctionne pas de cette façon, mais chaque match manuellement ne serait pas pratique.
intx13 a aimablement écrit une version plus robuste du programme de contrôle avec quelques corrections de bugs que vous pouvez trouver ici .
Les suggestions d’améliorations ou de corrections de bugs du programme de contrôle sont les bienvenues.
Bots de test
Aucun des robots de test ne sera inclus dans les analyses. Ils sont juste à des fins de test.
Dudley DoNowt (C)
int main(int argc, char *argv)
{
printf("0");
}
Ne fait rien quelle que soit la situation. Pas prévu de gagner beaucoup.
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);
}
?>
Essaie d'être juste à côté de l'adversaire. Vulnérable aux mines terrestres car il ne les cherche pas. Les tirs de missiles sont une tactique moins efficace pour l'adversaire lorsqu'il atteint son objectif.
Les resultats
Le pointage final sera fait après le 24 mars 2014 à 23h59 . Je ferai régulièrement des tests pour que les participants puissent voir comment leurs robots se rangent face à l’opposition actuelle.
Les entrées
Les entrées doivent inclure la source de votre bot et l'argument de ligne de commande que je devrai utiliser pour l'exécuter. Vous pouvez poster autant d’entrées que vous le souhaitez, mais chaque réponse ne doit contenir qu’un seul bot.
Important
Il semble que certaines entrées souhaitent écrire sur le disque pour conserver un certain état entre les exécutions. Ce sont de nouvelles règles concernant l'écriture sur le disque.
- Vous pouvez modifier la source de votre propre bot. Modifier un autre bot est une tricherie et entraînera la disqualification du bot incriminé.
- Vous pouvez écrire dans un fichier créé dans le but de stocker l’état. Ce fichier doit être stocké dans un sous-répertoire du répertoire où se trouve votre bot. Le sous-répertoire sera nommé
state
. L'écriture dans une autre partie du système de fichiers (autre que votre propre source) est interdite.
la source
Réponses:
EvilBot
un bot qui essaie d'être aussi méchant que possible
Eh bien, voici ce que j’ai: un robot Java qui essaie d’approcher
le plus possibleune bande circulaire de rayon 2,5 autour du centre de l’arène et de faire autant de dégâts que possible. Son modèle de mouvement est basé sur l’attribution d’une valeur de "danger" à chacune des cases voisines et sur la décision de se déplacer sur la base de ces valeurs et sur une tendance à se rapprocher d’une zone circulaire de rayon 2,5 autour du centre de la piste. J’ai utilisé certains éléments de base de la réponse de @ Geobits (par exemple, avoir un résuméBattleBot
classe et la technique d'analyse), alors merci! Je vais probablement modifier / développer ce que j'ai jusqu'à présent, même si cela se passe assez bien, comme c'est le cas pour les autres robots postés jusqu'à présent. Le code est ci-dessous. (Si quelqu'un d'autre utilise Java, n'hésitez pas à utiliser mes classes abstract / helper.)(
EvilBot.java
)Usage:
Remarques:
Actuellement, les mines terrestres ne sont pas utilisées, seulement évitées. Je ne vais probablement pas changer cela, car l'utilisation de mines antipersonnel semble faire plus de mal que de bien (du moins pour EvilBot) à en juger par quelques tests que j'ai effectués.
Actuellement, EMP n'est pas utilisé. J'ai essayé la stratégie d'alignement sur l'adversaire et le tir de l'EMP suivi de missiles, mais il existe quelques contre-stratégies qui gagneraient presque 100% du temps, alors j'ai décidé d'abandonner cette voie. Je pourrais explorer l’utilisation du PEM de différentes manières par la suite.
la source
Rifter
Ce bot prend différentes actions en fonction de quel bot il se bat. Pour déterminer l'adversaire, il retourne son propre état et le transmet aux autres robots pour voir ce qu'ils feraient, et le compare à ce qu'ils font réellement. Une fois qu'ils ont atteint un seuil de mouvements "corrects", les tests ne sont plus testés.
Une fois qu'il connaît le bot contre lequel il se bat, il sait généralement où il se trouvera lors du prochain tour, afin de pouvoir tirer là-bas au lieu de sa position actuelle.
Bien sûr, il y a des inconvénients. La première est que les bots qui ont une activité "aléatoire" ne sont pas aussi bien détectés. Ceci est contrebalancé en utilisant la logique du dernier combat du roi lorsque l'adversaire n'est pas connu.
Cependant, si un bot est purement déterministe, il n'a aucune difficulté à déterminer de qui il s'agit. Il peut ensuite être facilement adapté à la situation en ajoutant davantage de cas dans sa logique pour chaque adversaire. Par exemple, en luttant contre Last Stand, il le coincera, se tiendra 2x1 de sorte à ne pas pouvoir se déplacer ni tirer directement, et tirera des missiles contre le mur derrière, le tuant par des éclaboussures.
Comme mes autres, il étend BattleBot.java:
la source
ReadyAimShoot
un R Bot
Ce bot tente de se placer dans la même rangée ou colonne que la cible. Lorsqu'il est aligné sur la cible, il déclenche l'EMP, puis lors du tour suivant, il tire un missile en direction de la cible, puis une balle. Il devrait également être conscient de la mine environnante et les éviter, mais est complètement inconscient des balles et des missiles. Si la vie est déjà à 1, il saute l'EMP.
Pour garder une trace du moment où il déclenche l'EMP, il modifie son code source en ajoutant un commentaire à la fin du fichier (
#p_fired2
dans un premier temps, il le modifie ensuite pour#p_fired1
ensuite l'effacer). J'espère que le fait de savoir quand il déclenche le PEM de cette façon n'est pas trop marginal.La ligne de commande devrait être
Rscript ReadyAimShoot.R
, suivie de l'argument comme dans l'exemple, au moins sur les systèmes UNIX mais probablement aussi sur Windows (je vérifierai cela quand je le testerai réellement contre les autres bots).Edit : Puisque la version R semble rencontrer des problèmes d’analyse de l’entrée, voici une version python du même bot qui, je l’espère, fonctionne. Si un autre programmeur R voit la publication et voit ce qui ne va pas avec ce bot, n'hésitez pas à déboguer!
la source
Le dernier combat du roi
Une extension de mon
BattleBot
, cela est conçu pour lutter contre les blasters EMP. La seule manière sensée (IMO) d'utiliser EMP est de le tirer alors que vous êtes sur le même axe que l'adversaire, puis de tirer des missiles / armes vers l'adversaire coincé. Donc, je reste en dehors de l'axe :)Si vous avez déjà eu une partie d'échecs contre un roi contre une reine, vous savez qu'une reine à elle seule ne peut pas avoir de maté , vous devez impliquer le roi. Sinon, la stratégie du roi solitaire est simple: essayez de rester en dehors de l'axe et vers le centre pour maximiser la mobilité. Si vous êtes bloqué, optez pour une impasse.
Bien sûr, il n'y a pas grand moyen de forcer une impasse ici, donc finalement vous êtes coincé sur un côté ou un coin si la reine joue à tous les niveaux de compétence. Si ce bot est jamais dans cette situation, il tire. En supposant que l'adversaire se dirige vers EMP, cela donne un avantage de dégâts d'un tour. La dernière position du roi devrait donc se dérouler correctement, à moins qu'il n'ait déjà trop peu de vie.
Oh, et si c'est déjà hors axe et à l'abri des projectiles, il ne vous reste plus qu'à faire un saut dans la direction générale de l'ennemi.
LastStand.java
Pour compiler, placez dans un dossier
BattleBot.java
et exécutez:la source
EvadeBot
Ce bot a pour priorité de rester en vie. S'il détecte des collisions entrantes, il tente de se déplacer vers un endroit sûr en vérifiant si des collisions se produisent à cet endroit. S'il n'y a pas de zones "sûres" environnantes, il reste en place et passe à l'étape suivante.
S'il n'y a pas eu de collision (ou de zones de sécurité en cas de collision), le système effectue un contrôle d'attaque. Si l'adversaire est aligné sur 8 axes, il tire 80% du temps. S'il n'est pas aligné, il tire 50% du temps dans l'en-tête le plus proche. Il choisit une arme en fonction de la distance. Si c'est proche, une mine ou une balle (selon la distance exacte et la santé relative), des missiles de loin.
S'il décide de ne pas tirer, il effectue une marche au hasard (en vérifiant à nouveau les zones sûres).
Si rien de ce qui précède n'a fonctionné, il reste en place jusqu'au prochain tour.
Il n’utilise pas EMP, et j’ai un mauvais pressentiment
ReadyAimShoot
, mais nous verrons comment cela se passera.Le code est en deux morceaux. Puisqu'il est possible de créer plus d'un bot, j'ai créé une
BattleBot
classe abstraite . Il inclut des fonctions d'assistance telles que la lecture de l'arène, la vérification des collisions, la gestion des en-têtes, etc. Il existe également une fonction de journal permettant de suivre ce qui se passe pendant le débogage. Sidebug==false
, cela n'imprimera que la sortie réelle. Si quelqu'un veut l'utiliser / l'étendre, n'hésitez pas. Ce n'est pas joli code, mais il bat l'écriture passe-partout.BattleBot.java
Ce bot particulier est
EvadeBot
. Pour compiler / exécuter, placez-le dans un dossier avecBattleBot.java
et lancez:Si vous omettez l'argument ou s'il ne parvient pas à l'analyser correctement, la
"0"
sortie est affichée par défaut .EvadeBot.java
la source
BattleBots.java
. Pouvez-vous s'il vous plaît recompiler mes robots avant la prochaine exécution?Spiral Bot Alphabet Haskell
Dans un haskell alphabétisé, les commentaires sont par défaut, donc ce post est le programme. Ce bot va tirer des missiles en spirale autour de lui, ignorant les entrées. Il stocke l'état dans un fichier (qui, espérons-le, n'est pas défini par le compilateur.)
Nous énumérons d’abord les actions de missiles.
Ensuite, nous allons directement dans la monade IO. Si "spiral.txt" n'existe pas, on écrit "0". Nous vérifions également le répertoire.
Ensuite, nous le lisons et imprimons l’action.
Et finalement, nous écrivons dans le fichier la position actuelle.
la source
state
pour éviter tout conflit accidentel avec tout autre fichier non-étatique.LiterateHaskell.lhs:13:5: Not in scope: 'createDirectoryIfMissing'
etLiterateHaskell.lhs:14:5: Not in scope:
setCurrentDirectory'` quand je tente de compiler.Esquivant Tourelle
un bot en python
Voici une autre tentative. Puisque ReadyAimShoot est dans l’atelier de réparation depuis un certain temps :), j’ai pensé que j’essaierais quelque chose d’autre en attendant, en utilisant Python cette fois.
J'ai volé sans vergogne la ligne
sys.argv[1].splitlines()
de @Gareth mais au moins cette fois, cela signifie que je n'aurai pas de problème à analyser l'entrée.Ce bot court au centre au début du combat, puis y reste et tire des missiles dans la direction de l'adversaire. Il essaie également d'esquiver les balles et les missiles proches s'il est sur leur chemin, puis retourne au centre avant de recommencer à tirer.
la source
Bon tireur
Ceci est un autre bot simple que vous pouvez utiliser pour les tests. Si elle a une ligne de mire directe sur l'adversaire, elle tire, sinon elle avance au hasard.
la source
néo-bot
coffeescript
Un autre bot JavaScript à ajouter au mélange. Celui-ci cible Node.js et est écrit en CoffeeScript. L'architecture découle de la foule Java avec une classe de base gérant le bottiness général et un autre fichier avec une spécialisation pour le bot à portée de main.
La stratégie principale de ce bot est de ne pas être touché par vos projectiles. Si vous n'êtes pas une menace immédiate, neo-bot commencera à tirer.
Le fichier de base
shared.coffee
Et
neo-bot.coffee
le code du bot.Je recommande fortement de compiler les fichiers de café en javascript avant de lancer le programme; c'est un peu plus rapide. En gros, vous voulez faire ceci:
la source
CamperBot
Ce bot reste juste où il est et tire. J'ai seulement mis en place des balles, car les autres armes pourraient nuire au bot. S'il te plaît, pardonne-moi mes terribles compétences en C;)
Pas vraiment prévu de gagner beaucoup.
la source
Comme il n'y a pas encore d'entrées, je vais en publier une pour que vous ayez quelque chose à battre. Je te donne:
Mien! Mien! Mien!
Ne fait rien de particulièrement intelligent. Dépose une mine s'il n'y en a pas dans les carrés environnants, sinon passe dans l'une des cases sûres environnantes. Peut à peine battre le HuggyBot.
Veuillez excuser le codage Naff Python.
la source
Bot aléatoire
Ce bot fait juste une action aléatoire sur chaque mouvement. Il ne déclenche pas le PGE et ne regarde pas du tout la carte. La moitié du temps, c'est juste tirer dans le mur!
Testez-le (contre lui-même) comme ci-dessous.
la source
int main
vrai?void main
est BS.Trouble et Strafe
Quelques représentations de Ruby dans le combat. Se déplace de haut en bas dans le mur assigné au hasard des missiles tirant sur le mur opposé. Légèrement glitchy en haut et en bas.
la source
Un noyau JavaScript
Je pensais être gentil et vous donner mon bot JS de base. Il possède toutes les fonctions nécessaires à la création d'un bot. Tout ce dont vous avez besoin est constitué d'actions à effectuer en fonction des données que cela vous donne. Pas encore terminé, je ne peux pas vraiment le tester (impossible de compiler le code d'arène).
N'hésitez pas à utiliser cela, je suis impatient de voir quelques robots JS dans le mélange.
Faire:
Ajouter des fonctions pour calculer l'emplacement des armes
Veuillez noter que certaines choses ici peuvent devoir être modifiées pour un autre système d'exploitation (cela ne fonctionne que sous Windows). La version de Rhino ici: http://pastebin.com/FHvmHCB8
la source
Center-Bot
Un bot JavaScript
Ce bot a pour objectif de pénétrer au milieu de l’arène avant de tirer des balles ou des missiles sur sa cible à chaque tour, en fonction de sa proximité. Si l'ennemi est au milieu, il ne vous reste plus qu'à tirer des balles dans la direction vague.
Je ne m'attends pas à ce que tout se passe bien, mais c'est plutôt un test, et je suis curieux de voir à quel point cela fonctionne vraiment.
enregistrer en tant que fichier .js et exécuter avec
node centrebot.js
. Cela fonctionnera avec Node.js, mais vous devrez peut-être le modifier pour un autre programme, désolé!Dans mes tests:
Je n'ai testé aucun des meilleurs robots java, et je ne suis pas trop confiant non plus ...
la source
putstr(...)
à la place de yourstdo.writeLine(...)
et l'entrée provient descriptArgs[0]
. Après avoir fait que je devais changer\\n
de\n
diviser la carte en lignes. Quand je le lance, j'obtiens une erreur carFindFoe()
etfindCentre()
sont définis mais non appelés.E
vous devriez avoir unW
et où que vous ayez unS
vous devriez avoir unN
. Si vous utilisez l'exemple de saisie de la question, vous constaterez que la sortie du programme estSE
une direction impossible à partir du coin inférieur droit. Je l'ai corrigé pour le prochain test.CunningPlanBot (Python 3.3)
Ceci est complètement non testé sous l'interface actuelle ... Cela fonctionne au moins correctement avec les cartes!
C'est écrit pour Python 3.3
Ce qu'il fait:
Si en phase 1 - Si le mur et la direction se déplacent dans un mur ou dans une mine, changez de direction au hasard pour une direction autre que le mur ou la mine - Déplacez-vous dans la direction actuelle - Passez à la phase 2
Si vous êtes en phase 2 - Tirez la balle dans la direction la plus proche de l'ennemi - Passez à la phase 3
Si en phase 3 - Si aucune mine terrestre, lâchez la mine terrestre - Passez à la phase 1
Encore faut-il savoir s'il faut tirer avec un missile. De plus, je ne sais absolument pas si la mine antipersonnel fonctionne. A besoin de plus de tests demain soir.
la source
sys.argv[1].splitlines()
de saisir l'entrée de la ligne de commande, puis de l'utiliserline[x][y]
dans le bloc suivant; ajoutéend=""
aux commandes d'impression pour se débarrasser de la nouvelle ligne qui déroute le marqueur; changé l'état d'écrire dans un fichier dustate
répertoire plutôt questate
lui-même.UltraBot
Un bot Java qui calcule le danger pour chaque champ environnant. Si un champ environnant est moins dangereux que le champ actuel, le bot s'y déplace (ou un autre champ également dangereux). S'il n'y a pas de champ moins dangereux, le bot tire (missiles si le bot ennemi est loin, balles si le bot ennemi est proche). J'ai pris un code du BattleBot (merci!).
Ce bot est extrêmement difficile à toucher, mais pas très bon pour tirer sur l'ennemi… Je m'attends toujours à ce qu'il soit meilleur que mon précédent CamperBot.
la source
import
s?UltraBot.java:...: x has private access in Point
NinjaPy
Une soumission de dernière minute en python (non testée mais qui, espérons-le, fonctionnera). L'idée est qu'il avance vers l'adversaire tout en restant dans son angle mort. Quand il est assez proche (à 3 cellules de distance), il se place dans la diagonale de l'adversaire et tire un missile.
la source