DEV Community

BrokenKeyboard
BrokenKeyboard

Posted on

Making a successful Battlesnake

What is battlesnake?

Battlesnake is a programming competition, and they have an amazing community. What you need to do is implement the battlesnake API in a webserver, and then let it play games!

Step 0

Follow the quick start guide here and get your snake up and running.

Step 1

For this series I'm going to be using javascript for the code examples, but you can use any language. The first thing to do is make sure that your snake is always online, you can use many methods of doing this (sorted from easiest to most difficult)

  1. uptimerobot
  2. use Heroku's always online (requires a credit card, but doesn't bill you). The always online allows your snake to participate in global arena 24/7.

Stopping collisions

The starter snake moves randomly, and will most of the time hit its own body. So lets fix that. The gameData variable sent to the api (JSON) has 2 major components, the board and you. you is just a battlesnake object that is your snake. This is extremely useful, as you will eventually need to know for sure what your snake's id is. But for now we'll be dealing with the board.snakes list.
board.snakes is just a list of battlesnake objects, so we'll be iterating through it, and adding all of the positions within the snakes' bodies ({x:xPos, y:yPos}) to a list to see which locations are invalid moves.
We'll then be checking to see if a certain move's outcome is within that list. If it is, then we wont be moving there. In javascript you need the lodash library to use the _.indexOf(objlist, obj) function, because direct object comparison doesnt work, and im lazy. You then can either randomly pick a move from either of those 2 or use some other heuristic (ie distance to food, or distance to snakes.

function to get the list of taken positions.

function getSnakeBodyList(gameData){
    let ret = [];
    for(let x = 0; x <gameData.snakes.length; x++){
        for(let y = 0; y < gameData.snakes[x].length; y++){
            ret.push(gameData.snakes[x].body[y]);
        }
    }
    return ret;
}
Enter fullscreen mode Exit fullscreen mode

Get list of valid moves:

function add(p1, p2){
    return {x: p1.x+p2.x, y: p1.y+p2.y};
}
function getValidMoves(gameData, nogoplaces){
    let l1 = [{x:0, y:1},{x:0, y:-1},{x:-1, y:0},{x:1, y:0}]; 
//Notice that the moves in l1 match up with the possibleMoves list. The y axis is inverted, so be careful.  
    var possibleMoves = ['up', 'down', 'left', 'right'];
    let ret = [];
    for(let x = 0; x < 4; x++){
        if(_.indexOf(nogoplaces, add(gameData.you.head, l1[x])) == -1){
            ret.push(possibleMoves[x]);
        }
    }
    return ret;
}
Enter fullscreen mode Exit fullscreen mode

One way to use these 2 functions is to just go
let validMoves = getValidmoves(gameData, getSnakeBodylist(gameData));
and then choose which move you wanna use.
Thanks, and look out for part 2 where I'll explain how to not crash into walls.

Top comments (0)