# Bot for Spacewar PPCG KotH

I wrote a bot for a Programming Puzzles & Code Gold King of the Hill type of challenge called "Spacewar!". The challenge was written by @El'endiaStarman. The bot is called "Spy".

The controller is hosted here, so take a look for the feel. The API is a bit long, so here's a link.

The bot's logic:

It runs away from the other bot with a 70% chance of firing a missile and hyperspaces when it's close to the sun.

It's not online yet at a seperate bot; so you can copy-paste the code here into the KotH controller's text area at the bottom to test it out.

I sorta just monkey-patched this bot together without an IDE, so the code isn't that great. Seriously, there's even an extra function I didn't use.

## The code

function Spy_setup(team) {
// Typical setup. Nothing to see here. ;)
var botVars = {};
botVars["color"] = team;
return botVars;
}

function Spy_getActions(gameInfo, botVars) {
var actions = [];
var us, them, red = {
rotation: gameInfo.red_rot,
x: gameInfo.red_x,
y: gameInfo.red_y,
alive: gameInfo.blue_alive
},
blue = {
rotation: gameInfo.blue_rot,
x: gameInfo.blue_x,
y: gameInfo.blue_y,
alive: gameInfo.blue_alive
};
if (botVars.color == "red") {
us = red;
them = blue;
} else if (botVars.color == "blue") {
us = blue;
them = red;
}

function distance(x1, y1, x2, y2) {
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

// Get our ship's position
var rotation, x, y, opponentAlive;
if (botVars.color == "red") {
rotation = gameInfo.red_rot;
x = gameInfo.red_x;
y = gameInfo.red_y;
opponentAlive = gameInfo.blue_alive;
} else if (botVars.color == "blue") {
rotation = gameInfo.blue_rot;
x = gameInfo.blue_x;
y = gameInfo.blue_y;
opponentAlive = gameInfo.red_alive;
}

// Calculate our rotation compared to the sun in degrees
var sunX = gameInfo.sun_x,
sunY = gameInfo.sun_y,
angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
rotationToSun = (rotation - angle + 360) % 360;

// Check if we need to hyperspace to avoid the sun
var rX = x - sunX,
rY = y - sunY,
distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
if (distanceFromSun < 30) {
actions.push("hyperspace");
console.log("Command Module is Hyperspacing.")
}
if (gameInfo[botVars["color"] + "_alive"]) {
var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
rotationToOpponent = (us.rotation - angle + 360) % 360;
if (rotationToOpponent > 90 && rotationToOpponent < 270) {
actions.push("turn right");
} else {
actions.push("turn left");
};
actions.push("fire engine");
if (Math.random() > 0.3) {
actions.push("fire missile")
}
}
}


## Bugs

var us, them, red = {
rotation: gameInfo.red_rot,
x: gameInfo.red_x,
y: gameInfo.red_y,
alive: gameInfo.blue_alive
},
blue = {
rotation: gameInfo.blue_rot,
x: gameInfo.blue_x,
y: gameInfo.blue_y,
alive: gameInfo.blue_alive
};


Red and blue are using the same alive variable.

Also...

if (distanceFromSun < 30) {
actions.push("hyperspace");
console.log("Command Module is Hyperspacing.")
}
if (gameInfo[botVars["color"] + "_alive"]) {


I don't think dead ships are supposed to hyperspace.

## Licensing

When you use code from StackExchange, like from this answer to the PPCG challenge, you should at the very least add a comment referencing the original source.

## Duplication

Without looking at the code in detail, I spot this bit of duplication:

var rotation, x, y, opponentAlive;
if (botVars.color == "red") {
rotation = gameInfo.red_rot;
x = gameInfo.red_x;
y = gameInfo.red_y;
opponentAlive = gameInfo.blue_alive;
} else if (botVars.color == "blue") {
rotation = gameInfo.blue_rot;
x = gameInfo.blue_x;
y = gameInfo.blue_y;
opponentAlive = gameInfo.red_alive;
}

if (gameInfo[botVars["color"] + "_alive"]) {


You should pick one style and stick with it. I think you could get rid of a lot of the duplication by using the second style:

var rotation, x, y, opponentAlive;
rotation = gameInfo[botVars.color + "_rot"];
x = gameInfo[botVars.color + "_x"];
y = gameInfo[botVars.color + "_y"];


Leaves us with the opponentAlive variable, though.

For that, I'd just go with a function getOppositeColor:

function getOppositeColor(ownColor){
return ownColor === "blue" ? "red" : "blue";
}


And then we can get opponentAlive via

opponentAlive = gameInfo[getOppositeColor(botVars.color) + "_alive"];


Other weird things in your code are that you explicitly declare a distance function... and then you don't use it. You make objects for red and blue, but you don't use them and then extract values from gameInfo a second time...

You should get the variables once. Then use them. Make a single flow like that.

var actions = [];
var us, them, red = {
rotation: gameInfo.red_rot,
x: gameInfo.red_x,
y: gameInfo.red_y,
alive: gameInfo.red_alive
},
blue = {
rotation: gameInfo.blue_rot,
x: gameInfo.blue_x,
y: gameInfo.blue_y,
alive: gameInfo.blue_alive
};
if (botVars.color == "red") {
us = red;
them = blue;
} else if (botVars.color == "blue") {
us = blue;
them = red;
}


This part, in that regard, is perfectly fine.

var rotation, x, y, opponentAlive;
if (botVars.color == "red") {
rotation = gameInfo.red_rot;
x = gameInfo.red_x;
y = gameInfo.red_y;
opponentAlive = gameInfo.blue_alive;
} else if (botVars.color == "blue") {
rotation = gameInfo.blue_rot;
x = gameInfo.blue_x;
y = gameInfo.blue_y;
opponentAlive = gameInfo.red_alive;
}


This entire part can go. It's not needed. You already have all of these variables as us.rotation, us.x, us.y, and them.alive.

    if (rotationToOpponent > 90 && rotationToOpponent < 270) {
actions.push("turn right");
} else {
actions.push("turn left");
};


Also, you don't need a semicolon to end this if-statement here.

• I'm really bad at JS, thanks for the tips. Some of the code I copied from other bots. I put some of the stuff there to be compatible with other bot's code. – noɥʇʎԀʎzɐɹƆ Jul 18 '16 at 15:03
• Also, in my answer I cited the two other bots I took code from. – noɥʇʎԀʎzɐɹƆ Jul 18 '16 at 15:09
• You don't have a link to the answer anywhere in this question. – Pimgd Jul 18 '16 at 16:26