69
33
The results are in, the contest is over.
The winner is arshajii's EvilBot with 14 wins ahead of Neo-Bot with 13 wins and CentreBot and LastStand with 11 wins each.
Scores from the final run
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)
This is a king-of-the-hill challenge. The aim is to write a bot that will beat more of the other bots than any other.
The Game
The bots will all be pitted against each other 2 at a time in a 10x10 arena with the task of reducing the opponent's energy down from 10 to 0 before its own energy is reduced to 0.
Each match will consist of 5 bouts. The winner of the match is the winner of the most bouts. The total number of match wins and bout wins will be stored by the control program and will be used to determine the overall winner of the contest. The winner receives the big green tick and the adulation of the masses.
Each bout will proceed in a number of rounds. At the beginning of each round the current state of the arena will be given to each bot and the bot will then respond with a command to determine what it wants to do next. Once both commands have been received by the control program both commands are executed at the same time and the arena and bot energy levels are updated to reflect the new state. If both bots still have enough energy to continue the game goes onto the next round. There will be a limit of 1000 rounds per bout to ensure no bout goes on forever, and in the event that this limit is reached the winner will be the bot with the most energy. If both bots have equal energy the bout is a draw and neither bot will get a point for the win (it would be as if they had both lost).
The Weapons
Each bot will have at its disposal a number of weapons:
- Armour-piercing bullets. These travel 3 squares at a time and cause 1 energy point of damage.
- Missiles. These travel 2 squares at a time and cause 3 energy points of damage at the point of impact, and 1 point of damage in all the immediately surrounding squares.
- Landmines. These are dropped in one of the squares immediately surrounding the bot and cause 2 energy points of damage when stepped on, and 1 energy point of damage to anything standing in one of the immediately surrounding squares.
- Electro-magnetic pulse. Causes both bots' movement circuits to malfunction for 2 turns, meaning they cannot move. They can, however, still deploy weapons (yes I know that's not realistic, but it's a game. It's not supposed to be real life). Edit: Each EMP deployment will cost one energy point to the bot that uses it.
Bullets/missiles can only impact with bots, or walls. They will hit any bot that is in any of the squares that they travel through. They disappear once they have hit something.
In all cases immediately surrounding squares
means the 8 squares that the bot could move to on its next move - the Moore neighbourhood.
The commands
0
do nothing.N
,NE
,E
,SE
,S
,SW
,W
,NW
are all direction commands and move the bot one square in the given direction. If the bot is unable to move in that direction because there is a wall or another bot in the square, the bot remains where it is. Moving into a square that already contains a bullet or missile is safe since the bullet/missile will be considered to already be on its way out of that square.B
followed by a space and then one of the direction commands fires an armour piercing bullet in that direction.M
followed by a space and then one of the direction commands fires a missile in that direction.L
followed by a space and then one of the direction commands drops a land mine on that square next to the bot. If the square is already occupied by a wall or a bot, the command is ignored. If a landmine is dropped onto another landmine, it detonates it. This will damage the bot doing the dropping, and any other bot within range of the original landmine.P
fires the EMP.
Since only one command may be given per round, a bot can only move or fire/deploy a weapon, not do both at the same time.
Order of commands
The movement of either bot will always come first, and all movements will be attempted twice to account for another bot being in the way but moving out of the way.
Example
- Bot1 tries to move
E
but Bot2 is already in that square - Control program moves on to Bot2.
- Bot2 tries to move
S
and succeeds because nothing is in the way. - Bot1 gets a second attempt at doing its move. This time it succeeds and Bot1 moves
E
.
Once the bots have made any movements they want to make, the weapons will be fired and all projectiles (new and previously fired) will move their predefined number of squares.
The arena
At the beginning of each round the bot will receive the current state of play as the program's only command line argument:
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
The arena comes first consisting of 10 lines of 10 characters. It is surrounded with walls which are not shown. The characters' meanings are as follows:
.
represents an empty squareY
represents your bot.X
represents the opponent bot.L
represents a landmine.B
represents a bullet in flight.M
represents a missile in flight.
This is followed by the remaining energy of the bots, one bot per line. Only one space will separate the bot identifier from its energy level. As in the arena, Y
represents your bot and X
represents your opponent. Finally comes a list of the projectiles and landmines, their positions and (if appropriate) headings, again one per line.
The control program
#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';
}
}
The control program will call your bot from the command line. For this reason, programs which cannot be called from the command line will be considered invalid. I apologise to those whose language of choice doesn't work that way, but doing each match manually would be impractical.
intx13 has kindly written a more robust version of the control program with some bugfixes which you can find here.
Suggestions for improvements or bug-fixes to the control program are welcome.
Test bots
None of the test bots will be included in the scoring runs. They're just for testing purposes.
Dudley DoNowt (C)
int main(int argc, char *argv)
{
printf("0");
}
Does nothing regardless of the situation. Not expected to win much.
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);
}
?>
Tries to get right next to the opponent. Vulnerable to landmines since it doesn't look for them. Makes firing missiles a less effective tactic for the opponent when it achieves its goal.
The results
The final scoring run will be done after 23:59 on the 24th March 2014. I will run test runs regularly so that entrants can see how their bots are stacking up against the current opposition.
Entries
Entries should include your bot's source, and the command line argument I'll need to use to run it. You're welcome to post as many different entries as you like, but each answer should contain only one bot.
Important
It seems that some entries want to write to disk to retain some state between runs. These are new rules regarding writing to disk.
- You may modify the source of your own bot. Modifying any other bot is cheating and will result in the offending bot being disqualified.
- You may write to a file created for the purpose of storing state. This file must be stored in a subdirectory of the directory where your bot is located. The subdirectory will be named
state
. Writing to any other part of the filesystem (other than your own source) is disallowed.
1Sorry I didn't catch this in the Sandbox: is the supply of all weapons infinite? – Jonathan Van Matre – 2014-03-09T01:12:28.580
What should happen when a bullet or missile strikes with a bullet,missile or a landmine ? Also in the arena what do those numbers represent ? – Mukul Kumar – 2014-03-09T03:23:04.130
@JonathanVanMatre Yes, you have an infinite supply of all the weapons. – Gareth – 2014-03-09T09:02:56.810
@MukulKumar Bullets, missiles and landmines can all occupy the same square without hitting each other. So nothing happens, they just pass through each other. The lines after the arena are 1) your energy 2) your opponents energy 3) a list of weapons and their positions so
B 3 5 E
means there is a bullet at (3,5) and it's heading east. In the example I've given you'll see there are 2 bullets in the same square. – Gareth – 2014-03-09T09:08:28.683@Gareth please explain what do we do in
king of the hill
? – Mukul Kumar – 2014-03-09T12:56:39.340@MukulKumar The winner of a [king-of-the-hill] contest is the program that plays the game the best. I'll use the scorer program given in the question to set every bot against every other bot - the overall winner is the bot that beats the most opponents. – Gareth – 2014-03-09T13:14:51.257
How does one know how far a bullet or missile has traveled/will travel from it's current position? @Gareth – 11684 – 2014-03-09T14:36:59.333
Can one drop a mine under the opposing bot? What happens then? Will it immediately explode or will the opposing bot have a chance to evade it by moving away the next turn? – 11684 – 2014-03-09T14:45:55.937
@11684 The section 'The weapons' says how far the bullets and missiles move each turn, and the input sent to the bots describes where they are and which direction they're heading. – Gareth – 2014-03-09T14:47:32.700
1@11684 Interesting question that I hadn't considered. With the scorer program written as it is, a landmine dropped under a player will not explode. It only explodes if a) a bot moves onto it or b) it's dropped on top of another landmine. I don't see any reason to change this behaviour. – Gareth – 2014-03-09T14:49:37.220
@Gareth Oh, projectiles can move an unlimited amount of squares, the distance is per turn! Thank you for clarifying on this and the landmine behaviour. – 11684 – 2014-03-09T14:53:03.203
Would it be possible for the bots to receive their current W-L stats in a matchup at the beginning of each of the 5 bouts? – Jonathan Van Matre – 2014-03-09T16:32:37.790
@JonathanVanMatre I'm reluctant to change the input format now that the challenge has been posted. Do you have a reason for wanting that information? – Gareth – 2014-03-09T16:49:47.357
1It just opens up more strategic possibilities because you can change tactics based on your status. All good if you can't change it, though. – Jonathan Van Matre – 2014-03-09T17:04:36.853
What are your thoughts on the bot programs saving information from round to round? Would writing to a text file and reading it in at the end/start of rounds be acceptable? What about self modifying code which effectively does the same? If we can remember our opponents past moves that may help to predict future movements (depending on their control algorithm of course). – Kaya – 2014-03-09T17:05:30.637
@Kaya When the question was posted in the sandbox I suggested that I might give the history to the players and the only response I got was it would better without to avoid switching tactics for different opponents. I don't want bots writing to disk because I'll be running the scoring on my computer. – Gareth – 2014-03-09T17:17:38.000
Cool challenge! I would recommend running the bots in a VM though, for obvious reasons. – intx13 – 2014-03-10T03:04:09.980
As described, two bots cannot switch positions (ie. they both move 'through' each other). Is that intentional? – intx13 – 2014-03-10T10:57:32.727
@intx13 Yes. It came about as a happy coincidence as I was making the order of events clear in specification, but I've kept it that way intentionally. – Gareth – 2014-03-10T11:03:32.297
@Gareth, it says that "b" and "m" will represent the direction that a bullet/missile came from, but those symbols don't appear in the example map. Since that information is deducible from the information below the map, will those symbols still appear? – intx13 – 2014-03-10T13:03:09.537
@intx13 Sorry, that's from a previous version of the question. Ignore it and I'll remove it when I get back to my computer. – Gareth – 2014-03-10T13:06:38.640
@Gareth are you interested in patches to the control code? – intx13 – 2014-03-10T16:10:59.053
@intx13 Yes please, I'm currently looking into a bug I may have spotted. – Gareth – 2014-03-10T16:15:23.183
1
O man this totally reminds me of AI Wars - is this where you got the idea from?
– Claudiu – 2014-03-10T16:40:55.020@Claudiu I don't think I've seen that before. I wanted to do another [king-of-the-hill] challenge and I must have seen something similar to that in the past that popped back into my mind last week. – Gareth – 2014-03-10T17:00:33.297
1how can the bots know if the field is EMP'ed? would it be possible to add a line to the input as
P T
(being T the turns remaining) or the bots shall be oblivous and try to move and fail? – Einacio – 2014-03-10T17:42:33.713@Einacio I'm going to leave the bots oblivious in this case because I can think of a technique that would allow you to easily win nearly every time if you know that an EMP has been fired last turn. – Gareth – 2014-03-10T19:17:18.623
@Gareth I will have an updated control app for you shortly, with a number of minor bugs fixed and a ton of comments, etc. I'll just pastebin it when it's ready and you can copy-paste whatever you want from it. – intx13 – 2014-03-10T19:33:44.200
@Gareth Here it is. There are probably some bugs in it, I will test more tomorrow, but I fixed problems with strings not being null terminated, pointer casting errors/warnings, missiles only causing splash damage when hitting walls (not bots), some code speed issues due to array scanning, and some auto-casting issues with different least-significant index counts. Also, note that bot 2 has an advantage, so I randomized which bot is 1 and 2 in each bout.
– intx13 – 2014-03-10T22:05:05.840I'm also a bit of a comment nut so I added lots of those. Finally, I switched away from ANSI declarations to C99-style for scoping and readability, I hope that's not a problem. – intx13 – 2014-03-10T22:05:38.373
@intx13 Thanks. You can probably tell I don't use C very much. :-) I got it to work with just a few warnings, so figured that would be okay but since it's not working for Corwin I was obviously wrong there. – Gareth – 2014-03-10T22:06:41.050
Oh and also it takes bots on the command line now, so you don't have to recompile to test different bots. If you provide just one bot, it will play it against itself. – intx13 – 2014-03-10T22:06:58.363
@intx13 I may have to cut the comments for the version in the question, but add the link for the full commented code since I'm quite close to the character limit for the question and still need to have the results from scoring runs at the end. – Gareth – 2014-03-10T22:07:50.163
@Gareth You're welcome! Again, it's probably riddled with bugs, but hopefully they're easy to find now. I'll see how it goes when I actually write a bot. By all means, run it through a compressor or something to fit in SE. – intx13 – 2014-03-10T22:09:08.233
1I think a rule change is necessary. If a bot ever gets an energy advantage over the opponent, even by a single point, he should get out of range and fire the EMP every single turn until the bout timer expires. That will lead to very boring matches! Maybe only one EMP per bot per match? – intx13 – 2014-03-10T22:23:51.493
@intx13 I've got a better idea - each time you fire the EMP you use an energy point to power it. Fire it more than 9 times and you'll lose. I'll add it to the question now. I don't like changing the question after it's posted, but like you say it could be make for a dull competition. – Gareth – 2014-03-10T23:15:06.063
let us continue this discussion in chat
– Gareth – 2014-03-10T23:21:43.6632@intx13 Perhaps the bot corresponding to bot 1 and the one corresponding to bot 2 should not be random every bout, but rather randomly chosen only on the first bout and swapped at the beginning of each following bout. – arshajii – 2014-03-11T02:23:15.667
Forgive me for being dense, but I don't understand the scoring. What do "matches" and "bouts" represent? – Geobits – 2014-03-12T14:53:48.690
1@Geobits Each match is a contest between 2 particular bots. Each match is made up of 5 bouts. Most matches is the primary winning criteria, but in case of a draw (as is the case at the moment) bouts will be used as a tie-breaker. – Gareth – 2014-03-12T14:57:33.687
What do you mean by
storing state
? Can I store whatever I want or just some informations? – Vereos – 2014-03-12T15:00:23.7931@Vereos It's generally for storing history between runs - which way you fired last or which way you moved last or something like that. I don't think it would be much use for anything else. – Gareth – 2014-03-12T15:25:27.187
Can we assume
/state
to be persistent or will it be cleared before each test match/bout/run/round? I have an interesting idea, but only if it's kept around. – Geobits – 2014-03-12T20:07:18.447@Geobits
/state
will be constant through the entire contest. That doesn't mean that another bot won't trash your file though... – Gareth – 2014-03-12T20:10:31.2271
Moving into a square that already contains a bullet or missile is safe since the bullet/missile will be considered to already be on its way out of that square.
Wouldn't that mean that standing next to a bullet on one turn, bullet headed your way, and then stepping to the square the bullet was at would allow you to, so to say, dodge bullets? – Nit – 2014-03-13T12:56:58.5101@Nit Yes, there is a glitch in the matrix - but considering you'd be able dodge to the left or right anyway, it's not a major glitch. :-) – Gareth – 2014-03-13T13:58:43.050
I want to compete in this with my C# bot, just have a few questions: 1) can my bot be a compiled console exe or does it have to compile on the spot and 2) is the data sent as one long string with newline delimiters in it? And are they \r\n or \n only? – John Willemse – 2014-03-14T07:43:36.737
1@JohnWillemse No it needs to be source because a) it puts you at the same disadvantage as the others in having to show everyone your code and b) I'm running the tests on two different OSs (Linux and OS X). Yes it's one long string with
\n
newlines. – Gareth – 2014-03-14T09:09:40.747Okay great. Now I just need to write the bot, and find a way to compile and execute a .cs file from the console :P – John Willemse – 2014-03-14T09:29:39.460
2
I think I found a bug in @intx13's code. When both bots fire the EMP at the same time, I think both should lose energy. I haven't ran his code, but looking at it, this does not appear to be the case. See lines 295-304 https://github.com/gazrogers/CodegolfBattlebotsScorer/blob/master/scorernew.c
– Thomas Eding – 2014-03-14T23:51:40.3202Another potential bug. It looks like that bot energy can go below zero. This is okay, but if Bot1 has -1 energy and Bot2 has 0 energy, neither should score a win. – Thomas Eding – 2014-03-15T00:54:39.653
1Fixed and fixed, thanks @Thomas! – intx13 – 2014-03-15T02:37:11.487
Added a preliminary Haskell engine to github at https://github.com/thomaseding/battlebots Currently there are some IO and display discrepencies (easier to do basic testing in). More info listed in chat http://chat.stackexchange.com/rooms/13507/discussion-between-gareth-and-intx13
– Thomas Eding – 2014-03-17T06:12:46.897@Gareth: Perhaps one way to solve the JVM startup time is to allow bots to take input via stdin. That way you can keep the process open and slowly feed it more stdin as needed (a delimiter would be needed). In order to not break old bots, you could have a switch per bot via the engine's command line. – Thomas Eding – 2014-03-19T00:22:59.493
Wow my first bot performed way better than during the previous runs! My last one is quite a disappointment though :) – plannapus – 2014-03-26T10:51:41.390
2Thanks for this tournament, @Gareth. It was a nice challenge and inspired me to explore new areas of programming. Will challenge some of my friends I think. :) Grats to all the participants, good game! – Corwin – 2014-03-26T17:53:28.017