[Question]
  [
If you've ever played [Spacewar!](https://en.wikipedia.org/wiki/Spacewar_(video_game)), you know it was a fun game. If you haven't, know this: it was (and is) one of the very first and most important computer games. And it's still fun! The clone I grew up on is [this one](http://www.peterhirschberg.com/csw/index.htm), which is, apparently and unfortunately, Windows only. So I recreated it!
**The KotH is hosted here: [PPCG - Spacewar! King of the Hill](http://play.starmaninnovations.com/spacewar/).** I encourage you to play as a human against at least one other bot to get a feel for how the game works.
## The Game
* One frame is 30 milliseconds (thus, about 33 frames per second).
* The field is 800 pixels wide and 600 pixels tall.
* The field is toroidal, meaning that spaceships and missiles that move outside of the field reappear on the opposite side.
* There are two spaceships, red and blue.
	+ Red is positioned at x=50 and random y between 50, (field height - 50) pixels.
	+ Blue is positioned at x=(field width - 50) and random y between 50, (field height - 50) pixels.
	+ Both face x = (field width)/2.
* The available controls are:
	+ Turn left - 5 degrees per frame counterclockwise.
	+ Turn right - 5 degrees per frame clockwise.
	+ Fire missile - travels at an extra 10 pixels per frame in addition to the velocity of the ship, in the direction the ship was pointing.
	+ Fire engine - accelerates the spaceship at 0.30 pixels per frame in the direction the spaceship is pointing.
	+ Hyperspace jump - teleports to some random coordinates in the field, with a 25% chance of exploding. These random coordinates may be on top of the sun.
* The maximum speed for ships is 15 pixels per frame under engine power and 40 pixels per frame when gravity-boosted.
	+ When traveling faster than 15 pixels per frame, engine thrust may only change direction or slow down.
* Regarding missiles:
	+ Missiles travel in a straight line.
	+ Missiles may be fired at a maximum rate of 1 per 0.1 seconds.
	+ Missiles have a lifetime of 2.25 seconds.
	+ Ships have a maximum of 20 missiles each.
	+ Missiles are point particles internally.
* There is a sun in the very center that is extremely hazardous to your ship. The *slightest* contact is fatal. This sun also destroys missiles.
* The sun has gravity. The resultant acceleration is 5000/(distance^2) pixels/frame^2, where distance is in pixels. Spaceships and missiles are affected.
* Both ships have three strike zones: the nose, the left wing, and the right wing.
	+ A hit on the nose is instant death.
	+ A hit on either wing reduces the spaceship's turn rate and engine acceleration by half.
	+ If both wings are destroyed, the spaceship cannot be maneuvered and can only fire missiles.
* Ships may collide with each other.
	+ A nose-nose impact is fatal for both ships.
	+ A nose-wing impact destroys the wing.
	+ A wing-wing impact destroys both wings.
* Dead ships are solid and frozen until they explode 1 second later.
* After at least one ship has died, the field is reset 3 seconds later. Until then, the sun and any remaining missiles are still hazardous.
The original game also has deadly and indestructible asteroids, but I won't include those.
## The Rules
* Your bot must be written in JavaScript.
* Your bot should limit its decision to about 10 milliseconds. If I notice consistent lag *because of your bot*, I'll disqualify it and let you know so you can fix it.
* Bots will have access to the following:
	+ Field width and field height
	+ Sun position and radius
	+ The position, rotation, velocity, shape, missile stock, and in-hyperspace status of both ships
	+ The position and velocity of all missiles
* When prompted, your bot should return a list of strings.
	+ These strings should be one of the following: `turn left`, `turn right`, `fire engine`, `fire missile`, `hyperspace`. Any other string will be ignored.
	+ If there are any duplicates, only the first will be noted.
	+ `hyperspace` takes precedence over all others.
	+ `turn left` and `turn right` at the same time will have no effect.
	+ `fire engine` will have no effect if the ship only has the nose or is dead.
	+ `fire missile` will have no effect if a missile was fired too recently.
* In a change from the usual, **your bot is allowed to exploit the behavior of other bots.** I want to encourage a metagame.
	+ Bots **may not** emulate other bots. (I.e., no mind-reading.)
	+ Bots **may not** set any variables used by the game and physics code. (I.e., no cheating.)
## Bot Implementation Details
I will be storing your bot in its own JavaScript file that is automatically included, with the filename `bot_<name>.js`. So don't put any spaces or characters that would interfere with this or with naming a function in JavaScript. That's because you should define the following functions: `<name>_setup(team)` and `<name>_getActions(gameInfo, botVars)`. Further down the page, there exist textareas for the **userbot**, which you can edit to test your code.
### `<name>_setup(team)`
This function is for you to define any variables that you want to persist. `team` will be either `"red"` or `"blue"`. This function must return an object. Define variables like so:
```
var vars = {};
vars['example'] = "example";
return vars;
```
This `vars` object will be passed in to the other function:
### `<name>_getActions(gameInfo, botVars)`
`botVars` is the object returned by `<name>_setup(team)`. `gameInfo` is an object containing the following variables:
```
redScore
blueScore
timeLeft
fieldWidth
fieldHeight
sun_x
sun_y
sun_r //sun's radius
gravityStrength //acceleration in pixels/frame^2 at 1 pixel away from the sun's center
engineThrust    //acceleration in pixels/frame^2
speedLimit //maximum speed under engine power
maxSpeed   //maximum speed from gravity boosts
red_x
red_y
red_rot          //rotation in degrees
red_xv           //x velocity
red_yv           //y velocity
red_shape        //one of "full ship", "left wing", "right wing", "nose only"
red_missileStock //the number of missiles red has left
red_inHyperspace //true if red is in hyperspace
red_exploded     //until red explodes, it is still solid and hazardous
red_alive
// likewise for blue //
numMissiles
missiles //this is a list of objects, each with the following variables
  x
  y
  xv
  yv
```
Your bot has full access to these. I'm *pretty sure* that you can write to them and not affect the original variables, but don't do it anyway. **A note on rotations:** ships *point* in the +y direction, downwards, so anything that you want to align with the ship needs to be offset by 90 degrees. Also, positive rotation is clockwise.
This function must return a list of strings, representing your bot's actions. For example, `["turn right","thrust"]`. More details on this are in the **Rules** section.
## Additional Details
You may also make use of the following:
### `LineIntersection(L1, L2)`
L1 and L2 are two-element arrays of two-element arrays. That is, `L1 := [[x1,y1],[x2,y2]]` and `L2 := [[u1,v1],[u2,v2]]`. This function computes the intersection of two lines and returns this: `[[x,y], [a,b]]`. `[x,y]` are the coordinates of the intersection point and `[a,b]` is a pair of ratios that express how far along each line the intersection point is. As in, `a = 0.25` would mean that the intersection point is a quarter of the way from `[x1,y1]` to `[x2,y2]`, and likewise for `b`. **If there is no intersection, an empty array is returned.**
### `window["shipShapes"]`
```
var shipShapes = {
    'full ship': [[-8,16],[0,-8],[8,16]],
    'left wing': [[-8,16],[0,-8],[4,4],[0,8],[0,16]],
    'right wing':[[-4,4],[0,-8],[8,16],[0,16],[0,8]],
    'nose only': [[-4,4],[0,-8],[4,4],[0,8]]
};
```
These are the coordinates of the ships' polygons. To make getting the current coordinates easier, you may also use...
### `getShipCoords(<color>)`
`getShipCoords("red")` will return the current coordinates of the vertices of Red's ship, and likewise for `getShipCoords("blue")` and Blue. These coordinates are in a list like so: `[[x1,y1],[x2,y2],[x3,y3],...]`. Polygons are implicitly closed, so there is a line between the first and last coordinate pairs.
**You may not access or alter any other variables or functions in use by the game/website.** And definitely don't name your functions the same. I don't foresee that this will be a problem, but if your bot breaks the game code, that's one possibility. There is no logging or catching of exceptions.
## Winning
* Every pairing of bots shall be played at least 10 times, both ways. (So, at least 20 games total.)
* Aim to have the highest win/loss ratios *overall*. If your bot does super well against one other bot, but loses against the other three, that's not as good as winning against two and losing against two (as a general rule of thumb).
* For every bot, the ratios (wins+1)/(losses+1) will be calculated, then the mean and standard deviation of these ratios will be calculated. A higher mean will have priority, and in case means are within 1 unit of each other, the lower variance will have priority.
* Scoring will begin either in a week from today or after three days of no new submissions. This is so I don't have to repeat any pairing of bots.
**Above all, have fun!**
---
## Leaderboard (2016-01-08 05:15):
```
#   Name                       Mean      StdDev
1.  Helios                     13.625    6.852
2.  EdgeCase                    8.335    8.155
3.  OpponentDodger              8.415    8.186
4.  OrbitBot                    5.110    6.294
5.  SunAvoider                  5.276    6.772
6.  DangitBobby                 3.320    4.423
7.  SprayAndPray                3.118    4.642
8.  Engineer                    3.903    6.315
9.  RighthandedSpasms           1.805    2.477
10. AttackAndComeBack           2.521    2.921
11. PanicAttack                 2.622    3.102
12. FullSpeedAhead              2.058    3.295
13. UhhIDKWhatToCallThisBot     2.555    3.406
14. MissilesPlusScore           0.159    0.228
15. Hyper                       0.236    0.332
16. RandUmmm                    0.988    1.329
17. Kamikaze                    0.781    1.793
```
**Note:** This is subject to change as I run more games. Plus, the ordering of ranks 9-13 bothers me, so I may tweak the scoring method to better match one's intuition of how they should be ranked.
(Means and standard deviations were rounded to three decimal digits. Also, `Hyper` should be `HYPER` but that messes up the highlighting. :P)
  
[Answer]
# Helios
This bot is the center of the universe, or at least he thinks he is. The first thing he makes is to correct a grave error and place himself in the center of the coordinate system. Then he rotates anything around himself.
He doesn't like the other (fake) sun, therefore he tries to stay away from it. He also doesn't like other bots, therefore he shoots at them, if he is in a good shooting position.
```
function Helios_setup(team) {
    var botVars = {};
    botVars.myPrefix = team + "_";
    botVars.enemyPrefix = team == "red" ? "blue_" : "red_";
    return botVars;
}
function Helios_getActions(gameInfo, botVars) {
    var actions = [];
    var halfPi = Math.PI / 2;
    var engageAngle = Math.PI / 8;
    var field = {};
    field.width = gameInfo.fieldWidth;
    field.height = gameInfo.fieldHeight;
    field.halfWidth = field.width / 2;
    field.halfHeight = field.height / 2;
    field.posOffsetX = field.width * 3 / 2 - gameInfo[botVars.myPrefix + "x"];
    field.posOffsetY = field.height * 3 / 2 - gameInfo[botVars.myPrefix + "y"];
    field.posAngle = (450 - gameInfo[botVars.myPrefix + "rot"]) % 360 * Math.PI / 180;
    field.posSin = Math.sin(-field.posAngle);
    field.posCos = Math.cos(-field.posAngle);
    field.movOffsetXV = -gameInfo[botVars.myPrefix + "xv"];
    field.movOffsetYV = gameInfo[botVars.myPrefix + "yv"];
    field.movAngle = Math.atan2(-field.movOffsetYV, -field.movOffsetXV);
    field.movSin = Math.sin(-field.movAngle);
    field.movCos = Math.cos(-field.movAngle);
    function zeroIfUndefined(v) {
        return v === undefined ? 0 : v;
    }
    function sqr(x) {
        return x * x
    }
    function getEntity(source, prefix) {
        var tmpX = (field.posOffsetX + zeroIfUndefined(source[prefix + "x"])) % field.width - field.halfWidth;
        var tmpY = field.halfHeight - (field.posOffsetY + zeroIfUndefined(source[prefix + "y"])) % field.height;
        var tmpXV = zeroIfUndefined(source[prefix + "xv"]);
        var tmpYV = -zeroIfUndefined(source[prefix + "yv"]);
        var e = {};
        e.posX = tmpX * field.posCos - tmpY * field.posSin;
        e.posY = tmpX * field.posSin + tmpY * field.posCos;
        e.posR = Math.sqrt(sqr(e.posX) + sqr(e.posY));
        e.posPhi = Math.atan2(e.posY, e.posX);
        e.posXV = tmpXV * field.posCos - tmpYV * field.posSin;
        e.posYV = tmpXV * field.posSin + tmpYV * field.posCos;
        e.posV = Math.sqrt(sqr(e.posXV) + sqr(e.posYV));
        e.movX = tmpX * field.movCos - tmpY * field.movSin;
        e.movY = tmpX * field.movSin + tmpY * field.movCos;
        e.movR = Math.sqrt(sqr(e.movX) + sqr(e.movY));
        e.movPhi = Math.atan2(e.movY, e.movX);
        e.movXV = (tmpXV + field.movOffsetXV) * field.movCos - (tmpYV + field.movOffsetYV) * field.movSin;
        e.movYV = (tmpXV + field.movOffsetXV) * field.movSin + (tmpYV + field.movOffsetYV) * field.movCos;
        return e;
    }
    function getShip(prefix) {
        var ship = getEntity(gameInfo, prefix);
        ship.missileStock = gameInfo[prefix + "missileStock"];
        ship.inHyperspace = gameInfo[prefix + "inHyperspace"];
        ship.exploded = gameInfo[prefix + "exploded"];
        ship.alive = gameInfo[prefix + "alive"];
        return ship;
    }
    var myShip = getShip(botVars.myPrefix);
    myShip.movAngle = (field.posAngle - field.movAngle + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
    var enemyShip = getShip(botVars.enemyPrefix);
    var sun = getEntity(gameInfo, "sun_");
    enemyShip.intersectionLine = [[enemyShip.movX - enemyShip.movXV * 30, enemyShip.movY - enemyShip.movYV * 30],
            [enemyShip.movX + enemyShip.movXV * 30, enemyShip.movY + enemyShip.movYV * 30]];
    var intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle) * 10 * 30, Math.sin(myShip.movAngle) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersection = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle - 0.001) * 10 * 30, Math.sin(myShip.movAngle - 0.001) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersectionLeft = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle + 0.001) * 10 * 30, Math.sin(myShip.movAngle + 0.001) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersectionRight = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    function danger() {
        var tmp1 = sqr(sun.movXV) + sqr(sun.movYV);
        var tmp2 = tmp1 == 0 ? 0 : Math.max(0, Math.min(1, ((-sun.movX) * sun.movXV + (-sun.movY) * sun.movYV) / tmp1));
        var dis = Math.sqrt(sqr(sun.movX + tmp2 * sun.movXV) + sqr(sun.movY + tmp2 * sun.movYV));
        if (dis < 30) {
            return true;
        }
        var shipLine1 = [[-16, 8], [-16, -8]];
        var shipLine2 = [[-16, 8], [8, 0]];
        var shipLine3 = [[-16, -8], [8, 0]];
        if (gameInfo.missiles !== undefined) {
            for (var i = 0; i < gameInfo.missiles.length; i++) {
                var missile = getEntity(gameInfo.missiles[i], "");
                var missileLine = [[missile.movX + missile.movXV * 0.5, missile.movY + missile.movYV * 0.5],
                        [missile.movX + missile.movXV * 3, missile.movY + missile.movYV * 3]];
                if (LineIntersection(shipLine1, missileLine).length == 2 ||
                        LineIntersection(shipLine2, missileLine).length == 2 ||
                        LineIntersection(shipLine3, missileLine).length == 2) {
                  return true;
                }
            }
        }
        return false;
    }
    function fire() {
        return enemyShip.alive && !enemyShip.inHyperspace && myShip.intersection !== undefined &&
            myShip.intersection < 0.1 + myShip.missileStock / 200;
    }
    function evadeSun() {
        if ((sun.movPhi >= 0 && myShip.movAngle < 0) || (sun.movPhi <= 0 && myShip.movAngle > 0)) {
            actions.push("fire engine");
        }
        if (sun.movPhi > 0) {
            if (Math.abs(myShip.movAngle) < halfPi) {
                actions.push("turn right");
            } else {
                actions.push("turn left");
            }
        } else {
            if (Math.abs(myShip.movAngle) < halfPi) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
    }
    function aim() {
        if (myShip.intersection !== undefined && myShip.intersectionLeft !== undefined && myShip.intersectionLeft < myShip.intersection) {
            actions.push("turn left");
        } else if (myShip.intersection !== undefined && myShip.intersectionRight !== undefined && myShip.intersectionRight < myShip.intersection) {
            actions.push("turn right");
        } else {
            if (enemyShip.posPhi > 0) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
        if (myShip.posV < 2 || (enemyShip.alive && (enemyShip.movXV >= 0 || myShip.missileStock == 0))) {
            actions.push("fire engine");
        }
    }
    function brake() {
        if (myShip.movAngle > 0) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        }
        if (Math.abs(myShip.movAngle) > Math.PI * 3 / 4) {
            actions.push("fire engine");
        }
    }
    function engage() {
        if (enemyShip.missileStock > 0) {
            if ((enemyShip.posPhi > 0 && enemyShip.posPhi < engageAngle) || enemyShip.posPhi < -engageAngle) {
                actions.push("turn right");
            } else {
                actions.push("turn left");
            }
        } else {
            if (enemyShip.posPhi > 0) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
        actions.push("fire engine");
    }
    if (myShip.alive && !myShip.inHyperspace) {
        if (danger()) {
            actions.push("hyperspace");
        }
        if (fire()) {
            actions.push("fire missile");
        }
        if (enemyShip.exploded || enemyShip.inHyperspace || sun.movR < 150 || (sun.movR < 300 && Math.abs(sun.movPhi) < Math.PI)) {
            evadeSun();
        } else if (enemyShip.posR < 300 || myShip.intersection !== undefined) {
            aim();
        } else if (myShip.posV > 10) {
            brake();
        } else {
            engage();
        }
    }
    return actions;
}
```
[Answer]
## SunAvoider
This one just tries to stay away from the sun. It does so pretty well...until it gets one or both wings destroyed, then it's usually only a matter of time before it falls in.
```
function SunAvoider_setup(team) {
    var botVars = {};
    
    botVars["color"] = team;
    
    return botVars;
}
function SunAvoider_getActions(gameInfo, botVars) {
    var actions = [];
    
    if (gameInfo[botVars["color"]+"_alive"]) {
        var shipx = gameInfo[botVars["color"]+"_x"];
        var shipy = gameInfo[botVars["color"]+"_y"];
        var sunx = gameInfo["sun_x"];
        var suny = gameInfo["sun_y"];
        var dx = shipx - sunx;
        var dy = shipy - suny;
        var dis = Math.sqrt(dx*dx+dy*dy);
        var fireEngineChance = (dis-100)/(gameInfo["fieldHeight"]/2);
        
        if (Math.random() > fireEngineChance){ actions.push("fire engine") }
        
        var ang1 = gameInfo[botVars["color"]+"_rot"]+90;
        var ang2 = Math.degrees( Math.atan2(dy, dx) );
        var angDiff = ang2 - ang1;
        if (angDiff < -180) { //http://stackoverflow.com/a/7869457/1473772
            angDiff += 360;
        } else if (angDiff > 180) {
            angDiff -= 360;
        }
        
        if (angDiff >= 0) {
            actions.push("turn left");
        } else if (angDiff < 0) {
            actions.push("turn right");
        }
    }
    
    return actions;
}
```
[Answer]
# EdgeCase
Flies at full speed away from the sun towards the edge of the map! When it finds itself pointed towards the sun it will start shooting while turning itself away to get back to the edge. It also enters hyperspace when it's about to hit the sun.
```
function EdgeCase_setup(team) {
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}
function EdgeCase_getActions(gameInfo, botVars) {
  var actions = [];
  // 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");
  else {
    // Turn away from the sun
    if(rotationToSun > 90 && rotationToSun < 270) {
      actions.push("turn right");
    }
    else actions.push("turn left");
    // Fire engines if we're pointing away from the sun
    if(rotationToSun > 180) {
      actions.push("fire engine");
    }
    // If we shoot while our opponent's dead we can only kill ourself
    else if(opponentAlive) actions.push("fire missile");
  }
  return actions;
}
```
[Answer]
# OrbitBot
Currently has no targeting ~~or collision avoidance~~. It tries to orbit the sun.
**Edit: Now goes into hyperspace when impact is imminent.**
```
function OrbitBot_setup(team) {
  var botVars = {};
  botVars.color = team;
  return botVars;
}
function OrbitBot_getActions(gameInfo, botVars) {
  var actions = [];
  function getVar(name) {
    return gameInfo[botVars.color + "_" + name];
  }
  function getEnemyVar(name) {
    var eColor;
    if (botVars.color == 'blue') {
        eColor = 'red';
    } else {
        eColor = 'blue';
    }
    return gameInfo[eColor + "_" + name];
  }
  function distance(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  }
  function toroidDistance(x1, y1, x2, y2) {
    dx = Math.abs(x1 - x2);
        while (dx > gameInfo.fieldWidth) {
        dx -= gameInfo.fieldWidth;
    }
    dx = Math.min(dx, gameInfo.fieldWidth - dx);
    dy = Math.abs(y1 - y2);
        while (dx > gameInfo.fieldHeight) {
        dx -= gameInfo.fieldHeight;
    }
    dy = Math.min(dy, gameInfo.fieldHeight - dy);
    return Math.sqrt(dx*dx+dy*dy);
  }
  function angleDistance(theta1, theta2) {
    var d = theta1 - theta2;
    while (d < 0 || d > Math.PI) {
      if (d < 0) {
        d += Math.PI * 2;
      }
      if (d > Math.PI * 2) {
        d -= Math.PI * 2;
      } else if (d > Math.PI) {
        d = Math.PI * 2 - d;
      }
    }
    return d;
  }
  function toRad(degrees) {
    return degrees / 180 * Math.PI;
  }
  function cap(x, y, limit) {
    var r = x*x+y*y;
    if (r < limit * limit) {
        r = Math.sqrt(r);
        x = x * r / limit;
      y = y * r / limit;
    }
    return [x,y];
  }
  var shape = getVar('shape');
  if (shape != 'nose only') {
    var broken = shape != 'full ship';
    var sunX = gameInfo.sun_x,
      sunY = gameInfo.sun_y,
      sunG = gameInfo.gravityStrength;
    function desirability(x, y, vx, vy) {     //Borrowed from a useless bot.
      var lowest = distance(x, y, sunX, sunY) - 5;
      var missiles = gameInfo.missiles;
      for (var i = 0; i < missiles.length; i++) {
        var mx = missiles[i].x + missiles[i].xv / 2;
        var my = missiles[i].y + missiles[i].yv / 2;
        lowest = Math.min(lowest, toroidDistance(x, y, mx, my) - distance(0, 0, missiles[i].xv, missiles[i].yv));
      }
      return lowest - 16;
    }
    var x = getVar("x"),
      y = getVar("y"),
      vx = getVar("xv"),
      vy = getVar("yv");
    function desirabilityByAcceleration(ax, ay) {//Borrowed from a useless bot.
        var x1 = x,
            y1 = y,
          vx1 = vx,
          vy1 = vy;
      var speed = distance(0,0,vx1,vy1);
      var limit = Math.max(gameInfo.speedLimit, speed);
      vx1 += ax;
      vy1 += ay;
      var temp = cap(vx1, vy1, limit);
      vx1 = temp[0];
      vy1 = temp[1];
      var dx = x1 - sunX;
      var dy = y1 - sunY;
      var dis = Math.sqrt(dx*dx+dy*dy);
      if (dis > 5){
        var force = sunG / (dis * dis);
      } else {
        var force = sunG /5;
      }
      vx1 -= force*dx/dis;
      vy1 -= force*dy/dis;
      var temp = cap(vx1, vy1, 40);
      vx1 = temp[0];
      vy1 = temp[1];
      x1 += vx1;
      y1 += vy1;
      return desirability(x1, y1, vx1, vy1);
    }
    var r = distance(sunX, sunY, x, y);
    var theta = Math.atan((y - sunY) / (x - sunX));
    var sunA = sunG/r/r,
            sunAx = -Math.cos(theta) * sunA,
        sunAy = -Math.sin(theta) * sunA;
    var dv = Math.sqrt(sunG / r);
    var dvx = -dv * Math.sin(theta);
    var dvy = dv * Math.cos(theta);
    if (distance(-dvx, -dvy, vx, vy) < distance(dvx, dvy, vx, vy)) {
      dvx = -dvx;
      dvy = -dvy;
    }
    var dax = dvx - vx;
    var day = dvy - vy;
    var dAngle = Math.atan(day / dax);
    if (dax < 0) {
        dAngle += Math.PI;
    }
    var cAngle = toRad(getVar('rot') - 90);
    var dLeft = angleDistance(cAngle - toRad(broken ? 2.5 : 5), dAngle);
    var dRight = angleDistance(cAngle + toRad(broken ? 2.5 : 5), dAngle);
    var dNeither = angleDistance(cAngle, dAngle);
    if (dLeft < dRight && dLeft < dNeither) {
      actions.push('turn left');
    } else if (dRight < dLeft && dRight < dNeither) {
      actions.push('turn right');
    }
    var cax = Math.cos(cAngle) * (broken ? .15 : .3);
    var cay = Math.sin(cAngle) * (broken ? .15 : .3);
    var ax = 0;
    var ay = 0;
    if (distance(cax, cay, dax, day) < distance(0, 0, dax, day)) {
      actions.push('fire engine');
      ax = cax;
      ay = cay;
    }
    if (desirabilityByAcceleration(ax, ay) <= 16) {
        actions.push('hyperspace');
    }
  }
  return actions;
}
```
[Answer]
## RighthandedSpasms
The name is pretty descriptive. Chooses `turn right` with 0.5 probability, `fire engine` with 0.5 probability, and `fire missile` with 0.8 probability. Surprisingly difficult, mainly because it's really unpredictable.
```
function RighthandedSpasms_setup(team) {
    var botVars = {};
    
    botVars["color"] = team;
    
    return botVars;
}
function RighthandedSpasms_getActions(gameInfo, botVars) {
    var actions = [];
    
    if (gameInfo[botVars["color"]+"_alive"]) {
        if (Math.random() > 0.5) { actions.push("turn right") }
        if (Math.random() > 0.5) { actions.push("fire engine") }
        if (Math.random() > 0.8) { actions.push("fire missile") }
    }
    
    return actions;
}
```
[Answer]
# RandUmmm
This challenge needed a random bot. Bonus points for golfiness?
```
function RandUmmm_setup(t){
    function P(n,t,r,o,e,f,g){for(o=[e=1<<(f=n.length)];e;)for(t=e.toString(2),r=g=t.length,o[--e]=[];r;)~-t[--r]||o[e].push(n[r+f-g]);return o}var q=P(["fire missile","turn right","fire engine","turn left"]);q.pop();
    return {color:t,m:function(){return q[Math.random()*q.length|0]}};
}
function RandUmmm_getActions(g,b){
    return b.m();
}
```
[Answer]
# Engineer
Likes to use hyperspace when in danger. To see it's true power, open up your browser's console and type `overideHyperspace = 0;`. If you forget the semicolon, you'll get ASI for Christmas.
```
function Engineer_setup(t){
    return{c:t,C:"red0blue".split(0)[+(t=="red")]};
}
function Engineer_getActions(gameInfo,botVars){
    var actions = [];
    function d(x1,y1,x2,y2){return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))}
    function hS(g){return d(g.sun_x,g.sun_y,g[botVars.c+"_x"],g[botVars.c+"_y"])<50}
    function enemyDist(g){return d(g[botVars.c+"_x"],g[botVars.c+"_y"],g[botVars.C+"_x"],g[botVars.C+"_y"]);}
    function hSm(g){
        // get closest missile
        var r = (g.missiles||[{x:10000,y:10000}]).reduce(function(p,c){return Math.min(d(c.x,c.y,g[botVars.c+"_x"],g[botVars.c+"_y"]),p)},Infinity);
        return r<18;
    }
    function dF(g){
        var a = Math.degrees(Math.atan2(g[botVars.C+"_y"]-g[botVars.c+"_y"],g[botVars.C+"_x"]-g[botVars.c+"_x"]));
        var tP = (g[botVars.c+"_rot"]+360-a)%360;
        return [a,tP];
    }
    function lOr(g){
        var tP = dF(g)[1];
        return 90<tP&&tP<270?"turn left":"turn right";
    }
    function thrust(g){
        return Math.abs(dF(g)-g[botVars.c+"_rot"]);
    }
    // are we too close to the sun or a missile?
    if(hS(gameInfo)||hSm(gameInfo))actions.push("hyperspace");
    // should we fire?
    if(enemyDist(gameInfo)<200)actions.push("fire missile");
    // direction function
    actions.push(lOr(gameInfo,botVars));
    if(Math.random()<.7)actions.push("fire engine");
    return actions;
}
```
[Answer]
# SprayAndPray
```
function SprayAndPray_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}
function SprayAndPray_getActions(gameInfo, botVars) {
    var actions = [];
    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push("turn left");
        if (Math.random() > 0.5) { actions.push("fire engine")};
       actions.push("fire missile");
    }
    return actions;
}
```
Fires wildly in every direction. It's not very effective!
[Answer]
# Kamikaze
Not very competitive but I thought it would be fun! Just flies straight towards it's opponent while shooting.
```
function Kamikaze_setup(team) {
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}
function Kamikaze_getActions(gameInfo, botVars) {
  var actions = [];
  // Get our ship's position
  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;
  }
  // Turn towards our opponent's position
  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 left");
  }
  else actions.push("turn right");
  actions.push("fire missile", "fire engine");
  return actions;
}
```
[Answer]
# UhhIDKWhatToCallThisBot
Just random stuff.
```
function UhhIDKWhatToCallThisBot_setup(team) {
var botVars = {};
 botVars['t'] = 0;
botVars["color"] = team;
     return botVars;
}
function UhhIDKWhatToCallThisBot_getActions(gameInfo, botVars) {
    var actions = [];
    //when i need it: "turn left",
    //Use missiles sparingly!
    var WCID = [
    "fire engine",
     "turn right",
    "fire engine",
    "fire missile",
    "turn right",
    "fire engine"]
    if (gameInfo[botVars["color"]+"_alive"]) {
        botVars['t']++;
        actions.push(WCID[botVars[t]%(WCID.length)]);
    }
     return actions;
}
```
[Answer]
# OpponentDodger
GET AWAY FROM ME OPPONENT!!!
```
function OpponentDodger_setup(t){b={};b["c"]=t;b['o']=(t=="red")?"blue":"red";return b;}function OpponentDodger_getActions(g,b){a=[];o=b["c"];j={r:g[o+"_rot"],x:g[o+"_x"],y:g[o+"_y"]};o=b["o"];p={r:g[o+"_rot"],x:g[o+"_x"],y:g[o+"_y"]};l=Math.degrees(Math.atan2(p.y-j.y,p.x-j.x)),x=(j.r-l+360)%360;if(x > 90 && x < 270)a.push("turn right");else a.push("turn left");a.push("fire engine");return a;}  
```
Thanks to user81655 for some code!
[Answer]
# Spy
## The story
The prototype to this bot was a bot that had two modes: crazy mode and normal mode. When it was in crazy mode, it stayed there for a constant number of ticks. There was a contant probability of entering crazy mode. It also hyperspaced when it was close to the sun. In crazy mode, it aimed to the other bot and fired constantly. In normal mode, it flew away from the other bot, not firing.
I tweaked that prototype so that it would be in crazy mode if and only if the enemy was close enough. Then I had a crazy idea: what if it only stayed in crazy mode? After some experimentation (I added making the bot fire randomly when it was in normal mode) I found me new bot beat every bot but Helios. [This](https://gist.github.com/CrazyPython/16be557152f13c4fc6d4a99fd541d613) is my code at the end of this process, but before cleaning up.
I wrote my entire bot in the KotH textarea or the JS beautifier. (I did briefly use the Atom editor when cleaning up - but for like two lines of code)
## The bot
This bot contains a lot of code borrowed from other bots. It flips the code from Kamikaze to run away from the other bot instead of running to the other bot and it takes code from EdgeCase for hyperspacing when it's close to the sun.
It's arch nemesis is Helios. It being the odd one out and long chats with a martini. 
It runs away from the other bot with a 70% chance of firing a missile and hyperspaces when it's close to the sun. As simple as that. Yep.
Edit: I tested my bot with the new code and it fails for every other bot. I'm working on fixing it. I just confirmed this is only for my new bot.
## 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")
        }
    }
    return actions;
}
```
## The misc
Note: I might've broke something when cleaning up the code because I didn't test the bot after cleaning up the code.
It's also much much much better than all my other bots - it actually beat every other bot except for Helios **(edit)** , SetCourseFor30Degrees, and OrbitBot! It ties with SunAvoider.
Side note: I'm horrible at javascript, don't know why.
[Answer]
# AttackAndComeBack
Instead of swirling, it comes in at the top and exits at the bottom (returning at the top), firing very quickly. Generally avoids the sun.
```
function AttackAndComeBack_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}
function AttackAndComeBack_getActions(gameInfo, botVars) {
    var actions = [];
    actions.push("fire missile");
    if (Math.random()>0.4){actions.push("turn right");}
    else {actions.push("turn left");}
    actions.push("fire engine");
    return actions;
}
```
[Answer]
## FullSpeedAhead
Always fires both the engines and the missiles without turning ever. Sometimes lasts surprisingly long before hitting the sun.
```
function FullSpeedAhead_setup(team){
    return {color: team};
}
function FullSpeedAhead_getActions(gameInfo, botVars){
    var actions = [];
    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push("fire engine");
        actions.push("fire missile");
    }
    return actions;
}
```
[Answer]
# PanicAttack
Has a 50% chance of firing, and an 80% chance of turning left; but if it doesn't turn left, it'll turn right. After it runs out of missiles, time will eventually make it stop due to the sun.
**EDIT:** Added some logic to not fire when the enemy is alive because it could get killed by its own missiles.
```
function PanicAttack_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}
function PanicAttack_getActions(gameInfo, botVars) {
    var actions = [];
    actions.push("fire engine");
    if(botVars.color == "red") {
        var opponentAlive = gameInfo.blue_alive;
    }
    else if(botVars.color == "blue") {
        var opponentAlive = gameInfo.red_alive;
    }
    if ((Math.random()>0.5)&&opponentAlive) {
        actions.push("fire missile");
    }
    if (Math.random()>0.2) {
        actions.push("turn left");
    } else {
        actions.push("turn right");
    }
    return actions;
}
```
[Answer]
# DangitBobby
Bobby Hill doesn't care what others think about him- he's quite content to swing lazily around the field and patiently wait for his opponent to run out of steam before striking like a "husky" cobra.
```
function DangitBobby_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    if (team == 'red'){
        botVars['them'] = "blue";
    }
    else{
        botVars['them'] = 'red';
    }
    return botVars;
}
function DangitBobby_getActions(gameInfo, botVars) {
    var actions = [];
    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push('turn right');
        actions.push('fire engine');
        if (gameInfo[botVars['them']+'_missileStock'] == 0){
                actions.push('fire missile');
        }
    }
}
```
"THAT'S MY PURSE! I DON'T KNOW YOU!" 
[Answer]
# Sniper
I've been playing with prediction for a bit to create a sniper bot that snipes his enemies. My javascript is too large to fit in an answer so here is a link,
[bot\_Sniper](https://drive.google.com/file/d/0ByilzkL7-U2RUUg1RVRkcmxNSzg/view?usp=sharing).
[Answer]
## SmartArrow
Like Arrow, but smart
```
function SmartArrow_setup(team) {
    var botVars = {};
    botVars['mpref'] = team + '_';
    botVars['epref'] = team == 'red' ? 'blue_' : 'red_';
    botVars['ecolor'] = team == 'red' ? 'blue' : 'red';
    return botVars;
}
function SmartArrow_getActions(gameInfo, botVars) {
    var actions = [];
    var x = gameInfo[botVars['mpref'] + 'x'],
        y = gameInfo[botVars['mpref'] + 'y'],
        rot = gameInfo[botVars['mpref'] + 'rot']; // SmartArrow position and rotation
    var ex = gameInfo[botVars['epref'] + 'x'],
        ey = gameInfo[botVars['epref'] + 'y']; // Enemy position
    var sunx = gameInfo.sun_x,
        suny = gameInfo.sun_y; // Sun position
    var Dsunx = Math.abs(x - sunx),
        Dsuny = Math.abs(y - suny); // Sun position delta
    var dex = Math.abs(x - ex),
        dey = Math.abs(y - ey); // Enemy position delta
    var sangle = Math.degrees(Math.atan2(suny - y, sunx - x)),
        snrot = (rot - sangle + 360) % 360;
    if (Dsunx < 40 && Dsuny < 40) // If SmartArrow is too close from sun, hyperspace !
        return ['hyperspace'];
    var missiles = gameInfo.missiles;
    for (var i = 0; i < missiles.length; i++) { // Avoid all these silly missiles
        var dx = Math.abs(x - missiles[i].x),
            dy = Math.abs(y - missiles[i].y);
        if (dx < 10 && dy < 10)
            return ['hyperspace'];
    }
    if (gameInfo[botVars['epref'] + 'alive']) { // If his enemy is alive, SmartArrow try to kill him (logic)
        var angle = Math.degrees(Math.atan2(ey - y, ex - x)),
            nrot = (rot - angle + 360) % 360;
        if (nrot > 90 && nrot < 270)
            actions.push('turn left');
        else
            actions.push('turn right');
        if (nrot > 80 && nrot < 100
         && Math.random() > 0.5) actions.push('fire missile'); // If SmartArrow is in a good spot, shot this silly oponnent
        if (Math.random() > 0.5) actions.push('fire engine');
    }
    else { // Simply (try to) act like SunAvoider if his enemy is dead
        if (snrot > 90 && snrot < 270)
            actions.push('turn right');
        else
            actions.push('turn left');
        if (Dsunx < 300 && Dsuny < 300)
            actions.push('fire engine');
        if (dex < 40 && dey < 40)
            actions.push('hyperspace'); // Dying on the corpse of his opponent is dumb.
    }
    return actions;
}
```
[Answer]
# Kamikaze-
**Also not designed to be competitive.** Just for fun. It hyperspaces when close to the sun and chases the player without firing bullets. It's fun to watch this bot chase an unarmed version of Spy, but you can't have more than one userbot, unfortunately.
El'endia: ever considered adding more than one userbot ;)
```
function KamikazePlus_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}
function KamikazePlus_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 left");
        } else {
            actions.push("turn right");
        };
        actions.push("fire engine");
    }
    return actions;
}
```
Just took Kamikaze+'s code and got rid of the missile firing part.
[Answer]
# MissilesPlusScore
Some strange idea I came up with that takes that the absolute value of difference of the scores and uses a list of moves in a random based of the game way. It works well against bots with a strategy but fails against storms of missiles. Also my first [king-of-the-hill](/questions/tagged/king-of-the-hill "show questions tagged 'king-of-the-hill'").
```
function MissilesPlusScore__setup(team) {
var botVars = {};
botVars["color"] = team;
return botVars;
}
function MissilesPlusScore_getActions(gameInfo, botVars) {
var actions = [];
var moves=["fire missile","hyperspace","turn right","turn left","fire engine","fire missile","turn right","hyperspace","turn left","fire missile","hyperspace","turn right","turn left","hyperspace","fire engine","fire missile","turn right","turn left","hyperspace","fire missile","turn right","turn left","fire engine","hyperspace","fire missile","turn right","turn left","hyperspace"];
if(gameInfo[botVars["color"]+"_alive"]){
var num=gameInfo["redScore"]-gameInfo["blueScore"];
if(num<0){num=num*-1;}
if(num===0){actions.push(moves[Math.round(Math.random()*4)]);}
else{
actions.push(moves[num+gameInfo["numMissiles"]]);
}
}
    return actions;
}
```
# HYPER
HYPERSPACE IS COOL!!!!!!!!!!!!!!!!
```
function HYPER_setup(team){var botVars={};botVars["color"]=team;return botVars}function HYPER_getActions(gameInfo,botVars){var actions=[];if(gameInfo[botVars["color"]+"_alive"]){actions.push(["fire engine","fire missile","hyperspace"][Math.round(Math.random()*2)])};return actions}
```
# CoordinateInfluence
Based off the Coordinates, surprisingly effective:
```
function CoordinateInfluence_setup(team) {
var botVars = {};
botVars["color"] = team;
return botVars;
}
function CoordinateInfluence_getActions(gameInfo, botVars) {
var actions = [];
if (gameInfo[botVars["color"]+"_alive"]) {
if(gameInfo["blue_x"]>gameInfo["red_x"]){
if(gameInfo["blue_y"]<gameInfo["red_y"]){actions.push("turn right");}
else{actions.push("fire engine");}
}
else if(gameInfo["blue_y"]<gameInfo["red_y"]){
if(gameInfo["blue_x"]>gameInfo["red_x"]){actions.push("turn left");}
else{actions.push("fire missile");}
}
else{actions.push("hyperspace");}
}
return actions;
}
```
[Answer]
# SetCourseFor30Degrees
No idea why the captain is so insistent on setting the ship on a course of 30 degrees, but hey, as a lowly ensign, who are you to question? 
At least you have been given permission to avoid the sun! And you are allowed to fire the missiles... just not allowed to aim them...
```
function SetCourseFor30Degrees_setup(team) 
{
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}
function SetCourseFor30Degrees_getActions(gameInfo, botVars)
{
var actions = [];
var ang1 = gameInfo[botVars["color"]+"_rot"]+0;
var fireChance=0.95;
// sun avoidance
   var x = gameInfo[botVars["color"]+"_x"];
   var y = gameInfo[botVars["color"]+"_y"];
   var sunX = gameInfo["sun_x"]+0;
   var sunY = gameInfo["sun_y"]+0;
  var dx = sunX- x;
   var dy = sunY - y;
var shortRangeAvoidanceDistance = (dx * dx + dy * dy ) ;
 x = gameInfo[botVars["color"]+"_x"]+gameInfo[botVars["color"]+"_xv"]*10;
 y = gameInfo[botVars["color"]+"_y"]+gameInfo[botVars["color"]+"_yv"]*10;
 dx = sunX- x;
 dy = sunY - y;
var longRangeAvoidanceDistance = (dx * dx + dy * dy ) ;
var vel = Math.sqrt(gameInfo[botVars["color"]+"_xv"]*gameInfo[botVars["color"]+"_xv"]+
gameInfo[botVars["color"]+"_yv"]*gameInfo[botVars["color"]+"_yv"]);
var close=vel*1.5;
if (shortRangeAvoidanceDistance <= close* close)
{
  actions.push("hyperspace");
}
else
{
   if (longRangeAvoidanceDistance <= 200*200)
   {
     x = x+Math.cos((ang1-5)*Math.PI/180)*vel ;
     y = y+Math.sin((ang1-5)*Math.PI/180)*vel ;
     dx = sunX- x;
     dy = sunY - y;
     if (( dx * dx + dy * dy ) > longRangeAvoidanceDistance  )
     {
       actions.push("turn right")
     }
     else
     {
        actions.push("turn left")
     }
  }
  else
  {
    var course = botVars["color"]=="red"?30:-30;
    if (ang1>course ) {actions.push("turn left")}
    if (ang1<course ) {actions.push("turn right")}
  }
  if (Math.random() > fireChance){ actions.push("fire missile") }
  actions.push("fire engine")
}
return actions;
}
```
[Answer]
## Arrow
Simply chase his enemy, hyperspace when he is in danger and idle when his enemy is dead.
```
function Arrow_setup(team) {
    var botVars = {};
    botVars['mpref'] = team + '_';
    botVars['epref'] = team == 'red' ? 'blue_' : 'red_';
    return botVars;
}
function Arrow_getActions(gameInfo, botVars) {
    var actions = [];
    var x = gameInfo[botVars['mpref'] + 'x'],
        y = gameInfo[botVars['mpref'] + 'y'],
        rot = gameInfo[botVars['mpref'] + 'rot']; // My position and rotation
    var ex = gameInfo[botVars['epref'] + 'x'],
        ey = gameInfo[botVars['epref'] + 'y']; // Enemy position
    var Dsunx = Math.abs(x - gameInfo.sun_x);
    var Dsuny = Math.abs(y - gameInfo.sun_y);
    if (Dsunx < 30 && Dsuny < 30) // If Arrow is too close from sun, hyperspace !
        return ['hyperspace'];
    var missiles = gameInfo.missiles;
    for (var i = 0; i < missiles.length; i++) {
        var dx = Math.abs(x - missiles[i].x);
        var dy = Math.abs(y - missiles[i].y);
        if (dx < 10 && dy < 10)
            return ['hyperspace'];
    }
    if (gameInfo[botVars['epref'] + 'alive']) {
        var angle = Math.degrees(Math.atan2(ey - y, ex - x)),
            nrot = (rot - angle + 360) % 360;
        if (nrot > 90 && nrot < 270)
            actions.push('turn left');
        else
            actions.push('turn right');
        if (Math.random() > 0.5) actions.push('fire missile');
    }
    if (Math.random() > 0.5) actions.push('fire engine');
    return actions;
}
```
[Answer]
# Kamikaze+
**Not designed to be competitive.** Just for fun. Technically, it does the opposite of Spy: chase the player, hyperspace when close to the sun, fire missile 70% of the time. I sorta just want to see KamikazePlus chasing Spy and Spy running away like a madman.
```
function KamikazePlus_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}
function KamikazePlus_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 left");
        } else {
            actions.push("turn right");
        };
        actions.push("fire engine");
        if (Math.random() > 0.3) {
            actions.push("fire missile")
        }
    }
    return actions;
}
```
Basically just took Spy's code and flipped "left" and "right".
]