Wyniki się skończyły, konkurs się zakończył.
Zwycięzcą jest EvilBot arshajii z 14 zwycięstwami przed Neo-Botem z 13 wygranymi oraz CentreBot i LastStand z 11 wygranymi każda.
Wyniki z ostatniego biegu
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)
To wyzwanie dla króla wzgórza . Celem jest napisanie bota, który pokona więcej botów niż jakikolwiek inny.
Gra
Wszystkie boty będą stawiane naprzeciwko siebie 2 na arenie 10x10 z zadaniem zmniejszenia energii przeciwnika z 10 do 0, zanim jego własna energia zostanie zmniejszona do 0.
Każdy mecz będzie się składał z 5 pojedynków. Zwycięzca meczu wygrywa najwięcej pojedynków. Całkowita liczba zwycięstw w meczu i zwycięstw w walce zostanie zapisana przez program kontrolny i zostanie wykorzystana do ustalenia ogólnego zwycięzcy konkursu. Zwycięzca otrzymuje wielki zielony tyk i uwielbienie mas.
Każda walka będzie przebiegać w kilku rundach. Na początku każdej rundy każdemu botowi zostanie podany aktualny stan areny, a następnie bot odpowie poleceniem, aby ustalić, co chce dalej zrobić. Po otrzymaniu obu poleceń przez program sterujący oba polecenia są wykonywane jednocześnie, a poziomy energii areny i bota są aktualizowane w celu odzwierciedlenia nowego stanu. Jeśli oba boty nadal mają dość energii, aby kontynuować, gra przechodzi do następnej rundy. Będzie limit 1000 rund na walkę, aby zapewnić, że żadna walka nie będzie trwała wiecznie, a jeśli ten limit zostanie osiągnięty, zwycięzcą zostanie bot o największej energii. Jeśli oba boty mają taką samą energię, walka jest remisem i żaden bot nie dostanie punktu za wygraną (byłoby tak, jakby obaj przegrali).
Bronie
Każdy bot będzie miał do dyspozycji szereg broni:
- Pociski przeciwpancerne. Podróżują one 3 pola na raz i powodują 1 punkt energii obrażeń.
- Pociski Przemieszczają się one o 2 pola na raz i powodują 3 punkty energii obrażeń w punkcie uderzenia oraz 1 punkt obrażeń na wszystkich bezpośrednio otaczających polach.
- Miny Są one upuszczane na jeden z kwadratów bezpośrednio otaczających bota i powodują 2 punkty energii obrażeń po nadepnięciu oraz 1 punkt energii obrażeń dla wszystkiego, co stoi na jednym z bezpośrednio otaczających pól.
- Puls elektromagnetyczny. Powoduje nieprawidłowe działanie obwodów ruchu obu botów przez 2 tury, co oznacza, że nie mogą się poruszać. Mogą jednak nadal rozmieszczać broń (tak, wiem, że to nie jest realistyczne, ale to gra. To nie powinno być prawdziwe życie). Edycja: Każde wdrożenie EMP będzie kosztowało jeden punkt energii dla bota, który go używa.
Pociski / pociski mogą uderzać tylko robotami lub ścianami. Trafią każdego bota, który znajduje się na dowolnym kwadracie, przez który przechodzą. Znikają, gdy coś uderzą.
We wszystkich przypadkach immediately surrounding squares
oznacza 8 kwadratów, do których bot może przejść w następnym ruchu - sąsiedztwie Moore.
Polecenia
0
nic nie robić.N
,NE
,E
,SE
,S
,SW
,W
,NW
Są wszystkie polecenia kierunek i przesunąć bot jeden kwadrat w danym kierunku. Jeśli bot nie może się ruszyć w tym kierunku, ponieważ na placu znajduje się ściana lub inny bot, bot pozostaje tam, gdzie jest. Poruszanie się na placu, który już zawiera pocisk lub pocisk, jest bezpieczne, ponieważ pocisk / pocisk zostanie uznany za znajdujący się już w drodze z tego kwadratu.B
następnie spacja, a następnie jedno z poleceń kierunku wystrzeliwuje pocisk przebijający pancerz w tym kierunku.M
następnie spacja, a następnie jedno z poleceń kierunku wystrzeliwuje pocisk w tym kierunku.L
po którym następuje spacja, a następnie jedno z poleceń kierunkowych upuszcza minę lądową na ten kwadrat obok bota. Jeśli kwadrat jest już zajęty przez ścianę lub bota, polecenie jest ignorowane. Jeśli mina zostanie zrzucona na inną minę, detonuje ją. Spowoduje to uszkodzenie robota upuszczającego i każdego innego bota w zasięgu oryginalnej miny.P
odpala EMP.
Ponieważ na jedną rundę można wydać tylko jedno polecenie, bot może jedynie poruszać się, strzelać / rozmieszczać broń, a nie robić obu jednocześnie.
Kolejność poleceń
Ruch jednego z botów zawsze będzie na pierwszym miejscu, a wszystkie ruchy będą podejmowane dwukrotnie, aby uwzględnić, że inny bot stoi na drodze, ale znika z drogi.
Przykład
- Bot1 próbuje się poruszyć,
E
ale Bot2 jest już na tym polu - Program sterujący przechodzi do Bot2.
- Bot2 próbuje się poruszać
S
i odnosi sukces, ponieważ nic nie stoi na przeszkodzie. - Bot1 otrzymuje drugą próbę wykonania swojego ruchu. Tym razem się to udaje i Bot1 porusza się
E
.
Gdy boty wykonają dowolne ruchy, które chcą wykonać, broń zostanie wystrzelona, a wszystkie pociski (nowe i poprzednio wystrzelone) przesuną określoną liczbę pól.
Arena
Na początku każdej rundy bot otrzyma bieżący stan gry jako jedyny argument wiersza poleceń programu:
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
Najpierw arena składa się z 10 linii po 10 znaków. Jest otoczony ścianami, których nie pokazano. Znaczenie znaków jest następujące:
.
reprezentuje pusty kwadratY
reprezentuje twojego bota.X
reprezentuje bota przeciwnika.L
reprezentuje minę lądową.B
przedstawia pocisk w locie.M
reprezentuje pocisk w locie.
Następnie pozostała energia botów, jeden bot na linię. Tylko jedna spacja oddzieli identyfikator bota od jego poziomu energii. Podobnie jak na arenie, Y
reprezentuje twojego bota i X
reprezentuje przeciwnika. Wreszcie pojawia się lista pocisków i min, ich pozycji i (w razie potrzeby) nagłówków, ponownie po jednym w wierszu.
Program sterujący
#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';
}
}
Program sterujący wywoła twojego bota z linii poleceń. Z tego powodu programy, których nie można wywołać z wiersza poleceń, zostaną uznane za nieprawidłowe . Przepraszam tych, których język nie działa w ten sposób, ale ręczne wykonanie każdego meczu byłoby niepraktyczne.
intx13 uprzejmie napisał solidniejszą wersję programu sterującego z kilkoma poprawkami błędów, które można znaleźć tutaj .
Sugestie dotyczące ulepszeń lub poprawek błędów w programie sterującym są mile widziane.
Boty testowe
Żaden z botów testowych nie zostanie uwzględniony w przebiegach punktacji. Są tylko do celów testowych.
Dudley DoNowt (C)
int main(int argc, char *argv)
{
printf("0");
}
Nic nie robi bez względu na sytuację. Nie oczekuje się, że wygra dużo.
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);
}
?>
Próbuje dostać się tuż obok przeciwnika. Wrażliwe na miny, ponieważ ich nie szuka. Sprawia, że strzelanie pociskami jest mniej skuteczną taktyką dla przeciwnika, gdy osiągnie swój cel.
Wyniki
Ostateczny przebieg punktacji nastąpi po 23:59 24 marca 2014 r . Będę regularnie przeprowadzał testy, aby uczestnicy mogli zobaczyć, w jaki sposób ich boty układają się przeciwko obecnemu przeciwnikowi.
Wpisy
Wpisy powinny zawierać źródło twojego bota oraz argument wiersza poleceń, którego będę musiał użyć, aby go uruchomić. Możesz opublikować tyle wpisów, ile chcesz, ale każda odpowiedź powinna zawierać tylko jednego bota.
Ważny
Wygląda na to, że niektóre wpisy chcą zapisać na dysku, aby zachować pewien stan między uruchomieniami. Są to nowe zasady dotyczące zapisu na dysk.
- Możesz zmodyfikować źródło swojego bota. Modyfikacja dowolnego innego bota jest oszustwem i spowoduje dyskwalifikację robota, który go popełnił.
- Możesz pisać do pliku utworzonego w celu przechowywania stanu. Ten plik musi być przechowywany w podkatalogu katalogu, w którym znajduje się bot. Podkatalog zostanie nazwany
state
. Zapisywanie w jakiejkolwiek innej części systemu plików (innej niż twoje własne źródło) jest zabronione.
źródło
Odpowiedzi:
EvilBot
bot, który stara się być tak zły, jak to możliwe
Oto, co mam: bot Java, który próbuje zbliżyć się jak najbliżej
przeciwnikado okrągłego paska o promieniu 2,5 wokół środka areny, a następnie zadać jak najwięcej obrażeń, kiedy tylko może. Jego wzór ruchu opiera się na przypisywaniu wartości „niebezpieczeństwa” każdemu sąsiedniemu kwadratowi i decydowaniu o ruchu w oparciu o te wartości oraz na podstawie tendencji do zbliżania się do okrągłego obszaru o promieniu 2,5 wokół środka areny. Użyłem niektórych nakrętek i śrub z odpowiedzi @ Geobits (np. Mając streszczenieBattleBot
klasa i technika analizy), więc dzięki! Prawdopodobnie zamierzam zmodyfikować / rozwinąć to, co do tej pory mam, chociaż radzi sobie całkiem dobrze, podobnie jak inne boty wysłane do tej pory. Kod znajduje się poniżej. (jeśli ktoś korzysta z Javy, możesz swobodnie korzystać z moich klas abstrakcyjnych / pomocniczych).(
EvilBot.java
)Stosowanie:
Uwagi:
Obecnie miny lądowe nie są używane, a jedynie unikane. Prawdopodobnie nie zamierzam tego zmieniać, ponieważ używanie min przeciwpiechotnych wydaje się wyrządzać więcej szkody niż pożytku (przynajmniej dla EvilBota), sądząc po kilku testach, które przeprowadziłem.
Obecnie EMP nie jest używany. Wypróbowałem strategię wyrównania z przeciwnikiem i odpalenia EMP, a następnie pocisków, ale istnieje kilka przeciw-strategii, które wygrałyby prawie w 100% przypadków, więc postanowiłem porzucić tę trasę. Mogę później zbadać użycie EMP na różne sposoby.
źródło
Strzelec
Ten bot wykonuje różne działania w zależności od tego, z kim walczy. Aby określić przeciwnika, odwraca swój stan i karmi go innymi botami, aby zobaczyć, co zrobią, i porównuje to z tym, co faktycznie robią. Gdy osiągną próg „prawidłowych” ruchów, przestaje testować inne.
Kiedy już wie, z jakim botem walczy, na ogół wie, gdzie będzie w następnej turze, więc może strzelać tam zamiast ich obecnej pozycji.
Oczywiście istnieją pewne wady. Jednym z nich jest to, że boty, które mają „losową” aktywność, nie są tak dobrze wykrywane. Jest to równoważone przez użycie logiki King's Last Stand, gdy przeciwnik nie jest znany.
Jeśli jednak bot ma charakter wyłącznie deterministyczny, nie ma problemu z ustaleniem, kto to jest. Można go łatwo dostosować do sytuacji, dodając więcej logiki dla każdego przeciwnika. Na przykład, walcząc z Ostatnią Podstawą, zaatakuje go, odstawi 2x1, aby nie mógł się poruszyć ani strzelać bezpośrednio, i wystrzeliwuje pociski w ścianę za sobą, zabijając ją obrażeniami obszarowymi.
Podobnie jak inne, rozszerza BattleBot.java:
źródło
ReadyAimShoot
R Bot
Ten bot próbuje ustawić się w tym samym rzędzie lub kolumnie, co cel, gdy jest wyrównany z celem, strzela EMP, a następnie w następnej turze strzela pociskiem w kierunku celu, a następnie kulą. Powinien także zdawać sobie sprawę z otaczającej kopalni i unikać ich, ale jest całkowicie nieświadomy kul i pocisków. Jeśli życie jest już na poziomie 1, pomija EMP.
Aby śledzić, kiedy uruchamia EMP, modyfikuje kod źródłowy, dodając komentarz na końcu pliku (
#p_fired2
najpierw modyfikuje go,#p_fired1
a następnie usuwa). Mam nadzieję, że śledzenie, kiedy wyzwala EMP w ten sposób, nie jest zbyt graniczne.Wiersz poleceń powinien być
Rscript ReadyAimShoot.R
poprzedzony argumentem jak w przykładzie, przynajmniej w systemach UNIX, ale prawdopodobnie również w systemie Windows (sprawdzę to, kiedy faktycznie przetestuję to na innych botach).Edycja : Ponieważ wydaje się, że wersja R ma problem z analizowaniem danych wejściowych, oto wersja Pythona tego samego bota z, mam nadzieję, że działa. Jeśli jakikolwiek inny programista R zobaczy post i zobaczy, co jest nie tak z tym botem, możesz debugować!
źródło
King's Last Stand
Rozszerzenie do mojego
BattleBot
, jest przeznaczone do zwalczania blasterów EMP. Jedynym rozsądnym sposobem (IMO) na użycie EMP jest strzelanie, gdy jesteś na tej samej osi co przeciwnik, a następnie strzelanie pociskami / bronią w kierunku utkniętego przeciwnika. Pozostaję poza osią :)Jeśli kiedykolwiek grałeś w szachy z królem przeciwko królowi i królowej, wiesz, że sama królowa nie może matować , musisz zaangażować króla. Jeśli tego nie zrobisz, strategia samotnego króla jest łatwa: staraj się pozostać poza osią i w kierunku centrum, aby zmaksymalizować mobilność. Jeśli utkniesz, idź na impas.
Oczywiście nie ma świetnego sposobu na wymuszenie impasu, więc w końcu utkniesz na boku lub rogu, jeśli królowa gra na dowolnym poziomie kompetencji. Jeśli ten bot kiedykolwiek znajdzie się w takiej sytuacji, strzela. Zakładając, że przeciwnik przejdzie do EMP, daje to przewagę w obrażeniach o jedną turę, więc ostatnia walka króla powinna się udać, chyba że ma już mało życia.
Aha, a jeśli jest już poza osią i bezpieczny od pocisków, po prostu weźmie celny strzał w ogólny kierunek wroga.
LastStand.java
Aby skompilować uruchomienie, umieść w folderze
BattleBot.java
i uruchom:źródło
EvadeBot
Ten bot priorytetem jest pozostanie przy życiu. Jeśli wykryje nadchodzące kolizje, próbuje przejść do bezpiecznego miejsca, sprawdzając, czy nie ma kolizji. Jeśli nie ma otaczających „bezpiecznych” miejsc, pozostaje na miejscu i przechodzi do następnego kroku.
Jeśli nie było kolizji (lub bezpiecznych miejsc w przypadku kolizji), sprawdza atak. Jeśli przeciwnik jest ustawiony w osi 8, strzela w 80% przypadków. Jeśli nie jest wyrównany, strzela w 50% przypadków w najbliższy nagłówek. Wybiera broń na podstawie odległości. Jeśli jest blisko, minę lub pocisk (w zależności od dokładnej odległości i względnego stanu zdrowia), pociski z daleka.
Jeśli zdecyduje się nie strzelać, bierze losowy spacer (ponownie sprawdza bezpieczne miejsca).
Jeśli żadne z powyższych nie zadziałało, po prostu siedzi tam do następnej tury.
Nie używa EMP i mam złe przeczucie, że mogę się z nim równać
ReadyAimShoot
, ale zobaczymy, jak to będzie.Kod składa się z dwóch części. Ponieważ mogę zrobić więcej niż jednego bota, stworzyłem
BattleBot
klasę abstrakcyjną . Obejmuje funkcje pomocnicze, takie jak czytanie areny, sprawdzanie kolizji, zarządzanie kursami itp. Istnieje również funkcja dziennika, która pomaga śledzić, co dzieje się podczas debugowania. Jeślidebug==false
wydrukuje tylko rzeczywiste wyjście. Jeśli ktoś chce go użyć / rozszerzyć, nie krępuj się. To nie jest ładny kod, ale bije pisanie bojlerów.BattleBot.java
Ten konkretny bot jest
EvadeBot
. Aby skompilować / uruchomić, umieść go w folderzeBattleBot.java
i uruchom:Jeśli pominiesz argument lub nie będzie mógł go poprawnie przeanalizować, domyślnie zostanie
"0"
wyświetlony wynik.EvadeBot.java
źródło
BattleBots.java
. Czy możesz ponownie skompilować moje boty przed następnym uruchomieniem?Spiral Bot Literate Haskell
W literackim haskell komentarze są domyślne, więc cały ten post jest programem. Ten bot będzie strzelał w spirale wokół niego, ignorując dane wejściowe. Przechowuje stan w pliku (który, mam nadzieję, nie jest pozycjonowany przez konkurenta).
Najpierw wymieniamy działania rakietowe.
Następnie przechodzimy prosto do monady IO. Jeśli „spiral.txt” nie istnieje, zapisujemy do niego „0”. Sprawdzamy również katalog.
Następnie czytamy i drukujemy akcję.
I na koniec zapisujemy do pliku pozycję teraz.
źródło
state
aby uniknąć przypadkowych kolizji z innymi plikami niepaństwowymi.LiterateHaskell.lhs:13:5: Not in scope: 'createDirectoryIfMissing'
iLiterateHaskell.lhs:14:5: Not in scope:
ustawiam bieżący katalog '', gdy próbuję skompilować.DodgingTurret
Python Bot
Oto kolejna próba. Ponieważ ReadyAimShoot jest przez chwilę w warsztacie :) Pomyślałem, że w międzyczasie spróbuję czegoś innego, tym razem używając Pythona.
Bezwstydnie ukradłem linię
sys.argv[1].splitlines()
z @Gareth, ale przynajmniej tym razem oznacza to, że nie będę miał problemu z analizą danych wejściowych.Ten bot działa na środku na początku walki, a następnie zostaje tam i strzela pociskami w kierunku przeciwnika. Próbuje również unikać pobliskich pocisków i pocisków, jeśli są one na ich drodze, ale następnie wraca na środek, zanim ponownie rozpocznie strzelanie.
źródło
Prosta strzelanka
To kolejny prosty bot, którego możesz użyć do testowania. Jeśli ma bezpośredni widok na przeciwnika, który strzela, w przeciwnym razie kroczy losowo.
źródło
neobot
coffeescript
Kolejny bot JavaScript do dodania do miksu. Ten celuje w Node.js i jest napisany w CoffeeScript. Architektura ta wywodzi się z tłumu Java z klasą bazową obsługującą ogólną pustkę i innym plikiem ze specjalizacją dla bota pod ręką.
Główną strategią tego bota jest uniknięcie trafienia pociskami. Jeśli nie jesteś bezpośrednim zagrożeniem, neobot zacznie strzelać.
Plik podstawowy
shared.coffee
I
neo-bot.coffee
kod bota.Przed uruchomieniem zdecydowanie polecam skompilowanie plików kawy do javascript; jest nieco szybszy. Zasadniczo chcesz to zrobić:
źródło
CamperBot
Ten bot po prostu zostaje tam, gdzie jest i strzela. Zaimplementowałem tylko pociski, ponieważ inna broń zaszkodziłaby botowi. Proszę wybacz mi moje okropne umiejętności C;)
Nie spodziewałem się, że wiele wygra.
źródło
Ponieważ nie ma jeszcze żadnych wpisów, opublikuję jeden, abyś miał coś do pobicia. Daję ci:
Moje! Moje! Moje!
Nie robi nic szczególnie sprytnego. Zrzuca minę, jeśli nie ma jej na żadnym z otaczających pól, w przeciwnym razie przenosi się na jeden z bezpiecznych otaczających pól. Potrafi ledwo pokonać HuggyBota.
Proszę wybaczyć kodowanie Python naff.
źródło
Losowy bot
Ten bot wykonuje losową akcję przy każdym ruchu. Nie uruchamia EMP i wcale nie patrzy na mapę. Połowa czasu po prostu strzela w ścianę!
Przetestuj (przeciwko sobie) jak poniżej.
źródło
int main
prawda?void main
jest BS.Trouble and Strafe
Pewna reprezentacja Ruby w walce. Porusza się w górę iw dół losowo przydzielonych pocisków strzelających do ściany na przeciwległej ścianie. Lekko glitchy u góry iu dołu.
źródło
Rdzeń JavaScript
Myślałem, że będę miły i dam ci mojego głównego bota JS. Ma wszystkie funkcje niezbędne do stworzenia bota, wystarczy wykonać kilka czynności w oparciu o dane, które to daje. Jeszcze nie skończyłem, ponieważ tak naprawdę nie mogę go przetestować (nie mogę skompilować kodu areny).
Zapraszam do korzystania z tego, nie mogę się doczekać, aby zobaczyć kilka botów JS w miksie.
Do zrobienia:
Dodaj funkcje do obliczania lokalizacji broni
Pamiętaj, że niektóre rzeczy tutaj mogą wymagać modyfikacji w innym systemie operacyjnym (działa tylko w systemie Windows). Wersja Rhino tutaj: http://pastebin.com/FHvmHCB8
źródło
Center-Bot
Bot JavaScript
Ten bot próbuje dostać się na środek areny, zanim w każdej turze strzela pociskami lub pociskami w cel, w zależności od tego, jak blisko jest. Jeśli wróg jest na środku, będzie po prostu strzelał pociskami w niejasnym kierunku.
Nie spodziewam się, że wypadnie to bardzo dobrze, ale jest to bardziej testowanie i jestem zainteresowany, aby zobaczyć, jak dobrze to działa.
zapisz jako plik .js i uruchom za pomocą
node centrebot.js
. Będzie to działać z Node.js, ale może być konieczne zmodyfikowanie go dla innego programu, przepraszam!W moich testach:
Nie testowałem żadnego z najlepszych botów Java i nie jestem też zbyt pewny ...
źródło
putstr(...)
do zamiast ciebiestdo.writeLine(...)
i dane wejściowe pochodząscriptArgs[0]
. Zrobiwszy, że muszę zmienić\\n
aby\n
podzielić mapę na linie. Po uruchomieniu pojawia się błąd, ponieważFindFoe()
ifindCentre()
są zdefiniowane, ale nie są wywoływane.E
, powinieneś miećW
i gdziekolwiek maszS
, powinieneś miećN
. Jeśli użyjesz przykładowego wejścia z pytania, zobaczysz, że wyjście z programuSE
nie jest możliwym kierunkiem z prawego dolnego rogu. Poprawiłem to do następnego uruchomienia testowego.CunningPlanBot (Python 3.3)
Jest to całkowicie niesprawdzone w rzeczywistym interfejsie ... Działa to poprawnie przynajmniej z mapami!
Jest napisany dla Python 3.3
Co to robi:
Jeśli w fazie 1 - Jeśli przy ścianie i kierunku przesuwa się w ścianę lub porusza się do miny, losowo zmień kierunek na kierunek bez ściany lub miny - Przejdź w bieżącym kierunku - Przejdź do fazy 2
W fazie 2 - Wystrzel kulę w kierunku najbliższym wrogowi - Przejdź do fazy 3
Jeśli w fazie 3 - Jeśli nie ma miny, zrzuć minę - Przejdź do fazy 1
Nadal musi ustalić, czy wystrzelić pocisk. Nie mam też pojęcia, czy mina unika tego. Potrzebuje więcej testów jutro wieczorem.
źródło
sys.argv[1].splitlines()
pobierałem dane z wiersza poleceń, a następnie użyłemline[x][y]
w następnym bloku; dodanoend=""
do poleceń drukowania, aby pozbyć się nowej linii, która dezorientuje sekretarza; zmienił stan, aby zapisać do pliku wstate
katalogu zamiast w nimstate
samym.UltraBot
Bot Java, który oblicza niebezpieczeństwo dla każdego otaczającego pola. Jeśli otaczające pole jest mniej niebezpieczne niż bieżące, bot się tam przenosi (lub inne równie niebezpieczne pole). Jeśli nie ma mniej niebezpiecznego pola, bot strzela (pociski, jeśli bot wroga jest daleko, pociski, jeśli bot wroga jest blisko). Wziąłem trochę kodu z BattleBota (dzięki!).
Ten bot jest niezwykle trudny do trafienia, ale niezbyt dobry w strzelaniu do wroga… Nadal oczekuję, że będzie lepszy niż mój poprzedni CamperBot.
źródło
import
s?UltraBot.java:...: x has private access in Point
NinjaPy
Przesyłanie w ostatniej chwili w pythonie (nieprzetestowane, ale mam nadzieję, że zadziała). Chodzi o to, że zbliża się do przeciwnika, pozostając w martwym polu. Gdy jest wystarczająco blisko (3 komórki dalej), umieszcza się na przekątnej przeciwnika i strzela pociskiem.
źródło