Die Ergebnisse sind da, der Wettbewerb ist vorbei.
Der Gewinner ist Arshajiis EvilBot mit 14 Siegen vor Neo-Bot mit 13 Siegen und CentreBot und LastStand mit jeweils 11 Siegen.
Scores vom letzten Lauf
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)
Dies ist eine echte Herausforderung. Das Ziel ist es, einen Bot zu schreiben, der mehr der anderen Bots schlägt als jeder andere.
Das Spiel
Die Bots werden in einer 10x10 Arena alle zu 2 gegeneinander ausgespielt, um die Energie des Gegners von 10 auf 0 zu reduzieren, bevor die eigene Energie auf 0 reduziert wird.
Jedes Match besteht aus 5 Kämpfen. Der Sieger des Spiels ist der Sieger der meisten Kämpfe. Die Gesamtzahl der Match- und Kampfsiege wird vom Steuerungsprogramm gespeichert und zur Ermittlung des Gesamtsiegers des Wettbewerbs verwendet. Der Gewinner erhält das große grüne Häkchen und die Bewunderung der Massen.
Jeder Kampf wird in mehreren Runden fortgesetzt. Zu Beginn jeder Runde wird jedem Bot der aktuelle Zustand der Arena mitgeteilt und der Bot antwortet mit einem Befehl, um zu bestimmen, was er als nächstes tun möchte. Sobald beide Befehle vom Steuerprogramm empfangen wurden, werden beide Befehle zur gleichen Zeit ausgeführt und die Energieniveaus der Arena und des Bots werden aktualisiert, um den neuen Zustand widerzuspiegeln. Haben beide Bots noch genug Energie, um das Spiel fortzusetzen, geht es in die nächste Runde. Es wird ein Limit von 1000 Runden pro Kampf geben, um sicherzustellen, dass kein Kampf für immer andauert. Wird dieses Limit erreicht, ist der Gewinner der Bot mit der größten Energie. Wenn beide Bots die gleiche Energie haben, ist der Kampf unentschieden und keiner der Bots bekommt einen Punkt für den Sieg (es wäre, als hätten sie beide verloren).
Die Waffen
Jeder Bot verfügt über eine Reihe von Waffen:
- Panzerbrechende Kugeln. Diese bewegen sich jeweils um 3 Felder und verursachen 1 Energiepunkt Schaden.
- Raketen. Diese bewegen sich auf jeweils 2 Feldern und verursachen am Aufprallpunkt 3 Energiepunkte Schaden und auf allen unmittelbar umliegenden Feldern 1 Punkt Schaden.
- Landminen. Diese fallen auf eines der Quadrate, die den Bot unmittelbar umgeben, und verursachen beim Betreten 2 Energiepunkte Schaden und 1 Energiepunkt Schaden an allem, was sich auf einem der unmittelbar umgebenden Quadrate befindet.
- Elektromagnetischer Puls. Bewirkt eine Fehlfunktion der Bewegungskreise beider Bots für zwei Umdrehungen, was bedeutet, dass sie sich nicht bewegen können. Sie können jedoch weiterhin Waffen einsetzen (ja, ich weiß, dass dies nicht realistisch ist, aber es ist ein Spiel. Es sollte nicht das wirkliche Leben sein). Bearbeiten: Jede EMP-Bereitstellung kostet einen Energiepunkt für den Bot, der sie verwendet.
Kugeln / Raketen können nur mit Bots oder Wänden zusammenschlagen. Sie treffen jeden Bot, der sich auf einem der Felder befindet, durch die sie fliegen. Sie verschwinden, sobald sie etwas getroffen haben.
In allen Fällen immediately surrounding squares
sind dies die 8 Felder, auf die sich der Bot bei seinem nächsten Zug bewegen könnte - das Moore-Viertel.
Die Befehle
0
nichts tun.N
,NE
,E
,SE
,S
,SW
,W
,NW
Sind alle Richtungsbefehle und bietet ein Quadrat in der gegebenen Richtung bewegen. Wenn sich der Bot nicht in diese Richtung bewegen kann, weil sich eine Wand oder ein anderer Bot auf dem Feld befindet, bleibt der Bot dort, wo er ist. Das Einfahren in ein Feld, das bereits eine Kugel oder eine Rakete enthält, ist sicher, da davon ausgegangen wird, dass sich die Kugel / die Rakete bereits auf dem Weg aus diesem Feld befindet.B
gefolgt von einem Leerzeichen und dann feuert einer der Richtungsbefehle eine Panzerungskugel in diese Richtung.M
gefolgt von einem Leerzeichen und dann feuert einer der Richtungsbefehle eine Rakete in diese Richtung ab.L
gefolgt von einem Leerzeichen und dann lässt einer der Richtungsbefehle eine Landmine auf dem Feld neben dem Bot fallen. Wenn das Feld bereits von einer Mauer oder einem Bot besetzt ist, wird der Befehl ignoriert. Wenn eine Landmine auf eine andere Landmine fällt, wird sie explodiert. Dies beschädigt den fallenden Bot und jeden anderen Bot in Reichweite der ursprünglichen Landmine.P
feuert die EMP.
Da pro Runde nur ein Befehl gegeben werden darf, kann ein Bot nur eine Waffe bewegen oder abfeuern / einsetzen, nicht beide gleichzeitig.
Befehlsreihenfolge
Die Bewegung eines Bots steht immer an erster Stelle, und alle Bewegungen werden zweimal ausgeführt, um zu erklären, dass ein anderer Bot im Weg ist, sich aber aus dem Weg bewegt.
Beispiel
- Bot1 versucht sich zu bewegen,
E
aber Bot2 befindet sich bereits auf diesem Feld - Steuerungsprogramm geht weiter zu Bot2.
- Bot2 versucht sich zu bewegen
S
und hat Erfolg, weil nichts im Wege steht. - Bot1 bekommt einen zweiten Versuch, seinen Zug zu machen. Diesmal ist es erfolgreich und Bot1 bewegt sich
E
.
Sobald die Bots die Bewegungen ausgeführt haben, die sie ausführen möchten, werden die Waffen abgefeuert und alle Projektile (neue und zuvor abgefeuerte) bewegen ihre vordefinierte Anzahl von Feldern.
Die Arena
Zu Beginn jeder Runde erhält der Bot den aktuellen Stand als einziges Kommandozeilenargument des Programms:
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
Die Arena besteht zunächst aus 10 Zeilen à 10 Zeichen. Es ist von nicht dargestellten Wänden umgeben. Die Bedeutungen der Zeichen lauten wie folgt:
.
steht für ein leeres QuadratY
repräsentiert deinen bot.X
repräsentiert den gegnerischen Bot.L
repräsentiert eine Landmine.B
repräsentiert eine Kugel im Flug.M
repräsentiert eine Rakete im Flug.
Darauf folgt die verbleibende Energie der Bots, ein Bot pro Zeile. Nur ein Leerzeichen trennt den Bot-Identifikator von seinem Energieniveau. Y
Repräsentiert wie in der Arena Ihren Bot und X
Ihren Gegner. Schließlich folgt eine Liste der Projektile und Landminen, deren Positionen und (gegebenenfalls) Überschriften, wiederum eine pro Linie.
Das Steuerungsprogramm
#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';
}
}
Das Steuerungsprogramm ruft Ihren Bot über die Befehlszeile auf. Aus diesem Grund werden Programme, die nicht über die Befehlszeile aufgerufen werden können, als ungültig betrachtet . Ich entschuldige mich bei denen, deren Sprache nicht so funktioniert, aber es wäre unpraktisch, jedes Match manuell durchzuführen.
intx13 hat freundlicherweise eine robustere Version des Steuerungsprogramms mit einigen Bugfixes geschrieben, die Sie hier finden können .
Verbesserungsvorschläge oder Fehlerbehebungen im Steuerungsprogramm sind willkommen.
Test Bots
Keiner der Test-Bots wird in die Wertungsläufe einbezogen. Sie dienen nur zu Testzwecken.
Dudley DoNowt (C)
int main(int argc, char *argv)
{
printf("0");
}
Tut nichts, unabhängig von der Situation. Nicht viel zu gewinnen erwartet.
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);
}
?>
Versucht, direkt neben den Gegner zu gelangen. Anfällig für Landminen, da sie nicht gesucht werden. Macht das Abfeuern von Raketen zu einer weniger effektiven Taktik für den Gegner, wenn er sein Ziel erreicht.
Die Ergebnisse
Der letzte Wertungslauf findet am 24. März 2014 nach 23:59 Uhr statt . Ich werde regelmäßig Testläufe durchführen, damit die Teilnehmer sehen können, wie sich ihre Bots gegen die aktuelle Opposition behaupten.
Einträge
Die Einträge sollten den Quellcode Ihres Bots und das Befehlszeilenargument enthalten, das ich verwenden muss, um ihn auszuführen. Sie können beliebig viele Einträge posten, aber jede Antwort sollte nur einen Bot enthalten.
Wichtig
Es scheint, dass einige Einträge auf die Festplatte schreiben möchten, um den Status zwischen den Durchläufen beizubehalten. Dies sind neue Regeln für das Schreiben auf die Festplatte.
- Sie können die Quelle Ihres eigenen Bots ändern. Das Ändern eines anderen Bots ist Betrug und führt zur Disqualifikation des betreffenden Bots.
- Sie können in eine Datei schreiben, die zum Speichern des Status erstellt wurde. Diese Datei muss in einem Unterverzeichnis des Verzeichnisses gespeichert werden, in dem sich Ihr Bot befindet. Das Unterverzeichnis wird benannt
state
. Das Schreiben in einen anderen Teil des Dateisystems (mit Ausnahme Ihrer eigenen Quelle) ist nicht zulässig.
quelle
Antworten:
EvilBot
Ein Bot, der versucht, so böse wie möglich zu sein
Nun, ich habe folgendes: einen Java-Bot, der versucht, einen kreisförmigen Streifen mit einem Radius von 2,5 um die Mitte der Arena so nah wie möglich an
den Gegnerheranzukommen und dann so viel Schaden wie möglich zu verursachen, wenn es möglich ist. Sein Bewegungsmuster basiert darauf, jedem seiner Nachbarfelder einen "Gefahren" -Wert zuzuweisen und sich auf der Grundlage dieser Werte und einer Tendenz, sich möglichst nahe an einem kreisförmigen Bereich mit einem Radius von 2,5 um den Mittelpunkt der Arena zu bewegen, zu entscheiden . Ich habe einige der Schrauben und Muttern aus @ Geobits 'Antwort verwendet (z. B. eine Zusammenfassung)BattleBot
Klasse und die Parsing-Technik), also danke! Ich werde wahrscheinlich ändern / erweitern, was ich bisher habe, obwohl es ganz gut läuft, wie es bei den anderen bisher geposteten Bots der Fall ist. Der Code ist unten. (Wenn jemand Java verwendet, können Sie gerne meine Abstract / Helper-Klassen verwenden.)(
EvilBot.java
)Verwendungszweck:
Anmerkungen:
Derzeit werden Landminen nicht genutzt, sondern nur ausgewichen. Ich werde das wahrscheinlich nicht ändern, da die Verwendung von Landminen nach einigen von mir durchgeführten Tests mehr Schaden als Nutzen (zumindest für EvilBot) zu haben scheint.
Derzeit wird EMP nicht verwendet. Ich habe die Strategie ausprobiert, mich auf den Gegner auszurichten und das EMP abzufeuern, gefolgt von Raketen, aber es gibt ein paar Gegenstrategien, die fast 100% der Zeit gewinnen würden, also habe ich beschlossen, diese Route aufzugeben. Ich werde später vielleicht die Verwendung des EMP auf verschiedene Arten untersuchen.
quelle
Rifter
Dieser Bot führt verschiedene Aktionen aus, je nachdem, gegen welchen Bot er kämpft. Um den Gegner zu bestimmen, dreht er seinen eigenen Zustand um und speist ihn in die anderen Bots ein, um zu sehen, was sie tun würden, und vergleicht dies mit dem, was sie tatsächlich tun. Sobald sie eine Schwelle von "richtigen" Zügen erreicht haben, werden die anderen nicht mehr getestet.
Sobald es weiß , was Bot es kämpft, ist es im Allgemeinen weiß , wo es auf der nächsten Runde sein wird, so ist es abfeuern kann dort anstelle ihrer aktuellen Position.
Natürlich gibt es einige Nachteile. Einer ist, dass Bots mit "zufälliger" Aktivität nicht so gut erkannt werden. Dies wird ausgeglichen, indem die Last Stand-Logik des Königs verwendet wird, wenn der Gegner nicht bekannt ist.
Wenn jedoch ein Bot rein deterministisch ist, hat dies keine Mühe , herauszufinden , wer es ist. Es kann dann einfach an die Situation angepasst werden, indem für jeden Gegner mehr Fälle in seine Logik aufgenommen werden. Wenn er zum Beispiel gegen Last Stand kämpft, wird er in die Enge getrieben, 2x1 entfernt stehen, so dass er sich nicht bewegen oder direkt schießen kann, und Raketen in die Wand dahinter schießen und sie mit Spritzschaden töten.
Wie meine anderen, erweitert es BattleBot.java:
quelle
ReadyAimShoot
ein R Bot
Dieser Bot versucht, sich in der gleichen Zeile oder Spalte wie das Ziel zu platzieren. Wenn er auf das Ziel ausgerichtet ist, feuert er das EMP ab. In der folgenden Runde schießt er eine Rakete auf das Ziel und dann eine Kugel. Es sollte sich auch der umliegenden Mine bewusst sein und sie meiden, aber es merkt nichts von Kugeln und Raketen. Wenn das Leben bereits bei 1 ist, wird die EMP übersprungen.
Um zu verfolgen, wann es den EMP auslöst, ändert es seinen Quellcode, indem es am Ende der Datei einen Kommentar hinzufügt (
#p_fired2
zuerst ändert es ihn#p_fired1
und löscht ihn dann). Ich hoffe, dass das Verfolgen, wann es die EMP auf diese Weise auslöst, nicht zu grenzwertig ist.Die Befehlszeile sollte
Rscript ReadyAimShoot.R
, gefolgt von dem Argument wie im Beispiel, zumindest auf UNIX-Systemen sein, aber wahrscheinlich auch auf Windows (das werde ich überprüfen, wenn ich es tatsächlich mit den anderen Bots teste).Edit : Da die R-Version Probleme beim Parsen der Eingabe zu haben scheint, funktioniert hier hoffentlich eine Python-Version desselben Bots. Wenn ein anderer R-Programmierer den Beitrag sieht und sieht, was mit diesem Bot nicht stimmt, kann er gerne debuggen!
quelle
King's Last Stand
Eine Erweiterung zu meinem
BattleBot
, dies ist entworfen, um EMP-Blaster zu bekämpfen. Der einzig sinnvolle Weg (IMO), EMP zu verwenden, besteht darin, es abzufeuern, während Sie sich auf derselben Achse wie der Gegner befinden, und dann Raketen / Waffen auf den feststeckenden Gegner zu schießen. Also, ich bleibe von der Achse weg :)Wenn Sie jemals ein Schachspiel gegen einen König + eine Königin haben, wissen Sie, dass eine Königin alleine kein Schachmatt erzielen kann. Sie müssen den König mit einbeziehen. Wenn Sie dies nicht tun, ist die Strategie des Einzelkönigs einfach: Versuchen Sie, außerhalb der Achse und in Richtung Zentrum zu bleiben, um die Mobilität zu maximieren. Wenn Sie nicht weiterkommen, versuchen Sie eine Pattsituation.
Natürlich gibt es hier keine großartige Möglichkeit, eine Pattsituation zu erzwingen, sodass Sie irgendwann an einer Seite oder in einer Ecke hängen bleiben, wenn die Dame auf einem beliebigen Kompetenzniveau spielt. Wenn sich dieser Bot jemals in dieser Situation befindet, schießt er. Angenommen, der Gegner geht zu EMP, ergibt dies einen Schadenvorteil von einer Runde. Daher sollte der letzte Kampf des Königs gut ausgehen, es sei denn, er hat bereits wenig Leben.
Oh, und wenn es sich bereits außerhalb der Achse befindet und vor Projektilen geschützt ist, schießt es einfach in die allgemeine Richtung des Feindes.
LastStand.java
Um run zu kompilieren, legen Sie es mit in einen Ordner
BattleBot.java
und führen es aus:quelle
EvadeBot
Dieser Bot legt großen Wert darauf, am Leben zu bleiben. Wenn es eingehende Kollisionen erkennt, versucht es, sich an einen sicheren Ort zu bewegen, indem es diesen Ort auf Kollisionen überprüft . Wenn es keine "sicheren" Stellen in der Umgebung gibt, bleibt es stehen und fährt mit dem nächsten Schritt fort.
Wenn es keine Kollisionen gab (oder sichere Stellen im Falle einer Kollision), wird eine Angriffsprüfung durchgeführt. Wenn der Gegner auf 8 Achsen ausgerichtet ist, feuert er 80% der Zeit. Wenn es nicht ausgerichtet ist, wird es 50% der Zeit in der nächsten Überschrift abgefeuert. Es wählt eine Waffe basierend auf der Entfernung. Wenn es nah ist, eine Landmine oder eine Kugel (abhängig von der genauen Entfernung und der relativen Gesundheit), Raketen aus der Ferne.
Wenn es sich entschied, nicht zu feuern, machte es einen zufälligen Spaziergang (erneut nach sicheren Stellen suchen).
Wenn keines der oben genannten Probleme gelöst wurde, bleibt es nur bis zur nächsten Runde dort.
EMP wird nicht verwendet, und ich habe ein schlechtes Gefühl, mich dagegen zu behaupten
ReadyAimShoot
, aber wir werden sehen, wie es geht.Der Code besteht aus zwei Teilen. Da ich mehr als einen Bot machen kann, habe ich eine abstrakte
BattleBot
Klasse erstellt. Es enthält Hilfsfunktionen wie das Lesen der Arena, Kollisionsprüfung, Steuerkursverwaltung usw. Es gibt auch eine Protokollfunktion, mit der Sie verfolgen können, was beim Debuggen vor sich geht. In diesem Falldebug==false
wird nur die tatsächliche Ausgabe gedruckt. Wenn jemand es verwenden / erweitern möchte, fühlen Sie sich frei. Es ist kein schöner Code, aber es ist besser als Boilerplate zu schreiben.BattleBot.java
Dieser besondere Bot ist
EvadeBot
. Zum Kompilieren / Ausführen legen Sie es in einen Ordner mitBattleBot.java
und führen Sie Folgendes aus:Wenn Sie das Argument weglassen oder es nicht korrekt analysieren können, wird standardmäßig
"0"
ausgegeben.EvadeBot.java
quelle
BattleBots.java
. Können Sie bitte meine Bots vor dem nächsten Lauf neu kompilieren?Spiral Bot Literate Haskell
In literate haskell sind Kommentare Standard, daher ist dieser gesamte Beitrag das Programm. Dieser Bot schießt Raketen in Spiralen um ihn herum und ignoriert dabei die Eingabe. Es speichert den Status in einer Datei (die hoffentlich nicht vom Competer podiert wird).
Zuerst listen wir die Raketenaktionen auf.
Als nächstes gehen wir direkt in die IO-Monade. Wenn "spiral.txt" nicht existiert, schreiben wir "0" darauf. Wir suchen auch nach dem Verzeichnis.
Dann lesen wir es und drucken die Aktion.
Und zum Schluss schreiben wir die Position now in die Datei.
quelle
state
, um versehentliche Konflikte mit anderen nicht-staatlichen Dateien zu vermeiden.LiterateHaskell.lhs:13:5: Not in scope: 'createDirectoryIfMissing'
undLiterateHaskell.lhs:14:5: Not in scope:
setCurrentDirectory'`, wenn ich versuche zu kompilieren.DodgingTurret
ein Python Bot
Hier ist ein weiterer Versuch. Da ReadyAimShoot eine Weile in der Werkstatt ist :) Ich dachte mir, ich werde in der Zwischenzeit etwas anderes ausprobieren und diesmal Python verwenden.
Ich habe schamlos die Zeile
sys.argv[1].splitlines()
von @Gareth gestohlen, aber diesmal bedeutet dies, dass ich kein Problem beim Parsen der Eingabe habe.Dieser Bot läuft zu Beginn des Kampfes in der Mitte, bleibt dort und schießt mit Raketen in Richtung des Gegners. Er versucht auch, Kugeln und Raketen in der Nähe auszuweichen, wenn sie sich auf dem Weg befinden, kehrt dann aber in die Mitte zurück, bevor er erneut schießt.
quelle
Straight Shooter
Dies ist ein weiterer einfacher Bot, den Sie zum Testen verwenden können. Wenn es eine direkte Sichtlinie zum Gegner hat, schießt es, ansonsten tritt es zufällig.
quelle
neo-bot
Kaffeeskript
Ein weiterer JavaScript-Bot, der dem Mix hinzugefügt werden soll. Dieser zielt auf Node.js ab und ist in CoffeeScript geschrieben. Die Architektur stammt aus der Java-Masse mit einer Basisklasse, die sich mit allgemeinen Problemen befasst, und einer weiteren Datei mit Spezialisierung für den jeweiligen Bot.
Die Hauptstrategie dieses Bots ist es, nicht von Ihren Projektilen getroffen zu werden. Wenn Sie keine unmittelbare Bedrohung darstellen, schießt der neo-bot einfach los.
Die Basisdatei
shared.coffee
Und
neo-bot.coffee
der Bot-Code.Ich würde wärmstens empfehlen, die Kaffeedateien vor dem Start mit Javascript zu kompilieren. es ist ziemlich viel schneller. Grundsätzlich möchten Sie dies tun:
quelle
CamperBot
Dieser Bot bleibt einfach da, wo er ist und schießt. Ich habe nur Kugeln eingesetzt, da die anderen Waffen dem Bot schaden würden. Bitte vergib mir meine schrecklichen C-Fähigkeiten;)
Nicht wirklich viel zu gewinnen erwartet.
quelle
Da es noch keine Einträge gibt, werde ich einen veröffentlichen, damit Sie etwas zu verprügeln haben. Ich gebe es dir:
Bergwerk! Bergwerk! Bergwerk!
Macht nichts besonders Schlaues. Lässt eine Mine fallen, wenn sich keine auf einem der umliegenden Felder befindet, wird sie ansonsten auf eines der sicheren umliegenden Felder verschoben. Kann den HuggyBot nur knapp schlagen.
Bitte entschuldigen Sie die naff Python-Codierung.
quelle
Zufälliger Bot
Dieser Bot führt bei jedem Zug eine zufällige Aktion aus. Der EMP wird nicht ausgelöst und die Karte wird überhaupt nicht angezeigt. Die halbe Zeit schießt es nur gegen die Wand!
Testen Sie es (gegen sich selbst) wie unten.
quelle
int main
stimmenvoid main
ist BS.Ärger und Strafe
Einige Ruby-Darstellungen im Kampf. Bewegt die zufällig zugewiesenen Wandabschussraketen an der gegenüberliegenden Wand auf und ab. Oben und unten leicht rissig.
quelle
Ein JavaScript-Kern
Ich dachte, ich wäre nett und würde dir meinen JS-Kernbot geben. Es verfügt über alle Funktionen, die zum Erstellen eines Bots erforderlich sind. Sie müssen lediglich einige Aktionen ausführen, die auf den Daten basieren, die Ihnen dadurch zur Verfügung stehen. Noch nicht fertig, da ich es nicht wirklich testen kann (kann den Arena-Code nicht kompilieren).
Fühlen Sie sich frei, dies zu nutzen, ich freue mich darauf, einige JS-Bots in der Mischung zu sehen.
Machen:
Füge Funktionen hinzu, um Waffenpositionen zu berechnen
Bitte beachten Sie, dass einige Dinge hier möglicherweise für ein anderes Betriebssystem geändert werden müssen (dies funktioniert nur unter Windows). Rhino-Version hier: http://pastebin.com/FHvmHCB8
quelle
Center-Bot
Ein JavaScript-Bot
Dieser Bot ist bestrebt, in die Mitte der Arena zu gelangen, bevor er in jeder Runde Kugeln oder Raketen auf sein Ziel schießt, je nachdem, wie nah es ist. Befindet sich der Feind in der Mitte, schießt er weiter in vage Richtung.
Ich erwarte nicht, dass es sehr gut funktioniert, aber es ist eher ein Test, und ich bin gespannt, wie gut es wirklich funktioniert.
als .js Datei speichern und mit ausführen
node centrebot.js
. Dies funktioniert mit Node.js, aber Sie müssen es möglicherweise für ein anderes Programm ändern, sorry!In meinen Tests:
Ich habe noch keinen der Top-Java-Bots getestet und bin mir auch nicht sicher ...
quelle
putstr(...)
statt Ihrer diestdo.writeLine(...)
und die Eingabe kommt vonscriptArgs[0]
. Nachdem ich das getan hatte, musste ich das to ändern\\n
,\n
um die Karte in Linien zu teilen. Wenn ich es starte bekomme ich eine Fehlermeldung weilFindFoe()
undfindCentre()
definiert aber nicht aufgerufen werden.E
hast, solltest du eine habenW
und wo immer du eineS
hast, solltest du eine habenN
. Wenn Sie die Beispieleingabe aus der Frage verwenden, können Sie sehen, dass die Ausgabe des ProgrammsSE
keine mögliche Richtung von der rechten unteren Ecke ist. Ich habe es für den nächsten Testlauf korrigiert.CunningPlanBot (Python 3.3)
Dies ist unter der eigentlichen Oberfläche völlig ungetestet ... Es funktioniert zumindest mit den Karten korrekt!
Es ist für Python 3.3 geschrieben
Was es macht:
Wenn in Phase 1 - Wenn sich Wand und Richtung in Wand oder in eine Landmine bewegen, ändern Sie nach dem Zufallsprinzip die Richtung in eine Richtung ohne Wand oder Landmine. - Bewegen Sie sich in die aktuelle Richtung. - Fahren Sie mit Phase 2 fort
Wenn Sie sich in Phase 2 befinden - Schießen Sie die Kugel in die Richtung, die dem Feind am nächsten liegt - Fahren Sie mit Phase 3 fort
Wenn in Phase 3 - Wenn keine Landmine vorhanden ist, lassen Sie die Landmine fallen - Fahren Sie mit Phase 1 fort
Muss noch herausfinden, ob man eine Rakete abschießt. Ich habe auch keine Ahnung, ob die Minenvermeidung funktioniert. Muss morgen Abend noch getestet werden.
quelle
sys.argv[1].splitlines()
zum Laufen zu bringen: Ich habe die Eingabe über die Befehlszeile abgerufen und dannline[x][y]
im folgenden Block verwendet.end=""
zu den Druckbefehlen hinzugefügt , um die Zeilenumbrüche zu beseitigen, die den Schreiber verwirren; änderte den Status, um in eine Datei innerhalb desstate
Verzeichnisses anstatt in sichstate
selbst zu schreiben .UltraBot
Ein Java-Bot, der die Gefahr für jedes Umfeld berechnet. Ist ein umliegendes Feld weniger gefährlich als das aktuelle, bewegt sich der Bot dorthin (oder in ein anderes, ebenso gefährliches Feld). Wenn es kein weniger gefährliches Feld gibt, schießt der Bot (Raketen, wenn der feindliche Bot weit entfernt ist, Kugeln, wenn der feindliche Bot in der Nähe ist). Ich habe Code aus dem BattleBot genommen (danke!).
Dieser Bot ist extrem schwer zu treffen, aber nicht sehr gut darin, den Feind zu erschießen. Ich erwarte immer noch, dass er besser ist als mein vorheriger CamperBot.
quelle
import
s fehlt ?UltraBot.java:...: x has private access in Point
NinjaPy
Eine Last-Minute-Einreichung in Python (ungetestet, wird aber hoffentlich funktionieren). Die Idee ist, dass es auf den Gegner zuläuft, während es in seinem blinden Winkel bleibt. Wenn es nah genug ist (3 Zellen entfernt), platziert es sich in der Diagonale des Gegners und schießt eine Rakete ab.
quelle