Slither Bots is a series of scripts I created that automate playing the web-based game Slither.io in increasingly complicated ways.

Slither.io is a multiplayer version of the classic Worm game. You hit other snakes, you lose, they hit you, they lose. Once a worm dies, it drops a bunch of food that can be slurped up by the survivors (or anyone else) and can double or triple a player’s size in a second or two.

I started very simply, and added layers of complexity one after another, saving them each as a separate generation.

You can try any of these out on your own with a few easy steps:

Open Firefox (or Chrome for you heathens).

Go to http://slither.io

Tools -> Web Developer -> Web Console

Open a bot by clicking the name of the generation below

Copy the entire file, paste it into the JS console, hit enter, watch and be amazed.

No attempt was made at making it smart, just verifying that all the game hooks and controls work correctly.

The first step is to have our snake avoid enemy snakes. It seemed that debugging the tracking of other snakes would be easier if we were trying to deliberately lose, and steer straight at the nearest enemy snake, rather than trying to avoid them.

setInterval(function() { var closest_snake = null; var closest_distance = 5000; for (var ii = 0;ii<snakes.length;ii++) { var targetSnake = snakes[ii]; if (targetSnake.id != snake.id) { console.log('Enemy: ',targetSnake); var distance_x = Math.round(targetSnake.xx - snake.xx); var distance_y = Math.round(targetSnake.yy - snake.yy); var distance = Math.abs(distance_x)+Math.abs(distance_y); console.log(' Distance: ',distance,' - ',distance_x,distance_y) if (distance < closest_distance) { closest_distance = distance; closest_snake = targetSnake; } } } console.log("CLOSEST: ",closest_distance,closest_snake); set_direction(Math.round(closest_snake.xx - snake.xx),Math.round(closest_snake.yy - snake.yy)); update_high_scores(); },200);

The logical next step after getting the Kamikaze mode working was the opposite of that, to just blindly run away from any nearby snakes.

To verify food tracking worked, glutton mode simply eats whatever food is available, ignoring everything else.

This mode is really a combination of the Wuss and Glutton modes. It eats food, unless there is another snake nearby, then it runs away. If the other snake gets too close, the games boost function is used to move away faster. It also included new code to detect if it was trying to get the same piece of food for too long, which would happen when it starts winding around a piece without getting closer. It ignores that piece of food afterwards and keeps going to the next closest piece.

Every generation up to this very only took into account the proximity of things to the head of the snake. This generation only looks at things that are in the 45 degrees in front of the snake, taking it’s current travel direction into accoint.

// Ony look at food within the defined vision_angle var angle = get_angle(snake.xx,snake.yy,food.xx,food.yy); if (angle <= my_angle+vision_angle/2 && angle >= my_angle-vision_angle/2) {

This is the same as the last generation, but the pieces of food that are calculated as being in the snakes field of vision are highlighted to make debugging easier.

// Highlight the food in our vision field food.fi = per_color_imgs[2].pr_imgs[10];

To integrate food better into the bot, it should favor clusters of food rather than any random floating piece of food. Clusters appear when a snake dies and it can be very advantageous to eat these up before other players.

This mode detects clusters of food by downsampling the resolution of the grid of food and searching the grid for a close cluster, if it finds one it goes towards that.

// Downsample the food grid by 100 to make finding clusters easier var x = Math.round(food.xx/100); var y = Math.round(food.yy/100);

This is the furthest I have taken things so far. It’s the start of a basic genetic algorithm. Several parameters are broken out into variables that are randomly nudged after each death.

function apply_mutation() { var new_params = params[params.length-1]; for (var ii = 0; ii < new_params.length; ii++) { // Apply a random percentage change, capped at 25% change of any one attribute at one time. if (Math.random() > .5) { new_params[ii] = Math.round((new_params[ii] + (new_params[ii] * Math.random()) * .25)*10)/10; } else { new_params[ii] = Math.round((new_params[ii] - (new_params[ii] * Math.random()) * .25)*10)/10; } } params.push(new_params); }

Obviously without something overseeing multiple versions running at once, and modifying them in a more smart way according to which ones get the higher score. I assume something like that could be done using chrome headless or something similar. Feel free to give it a shot!

Potential Modifications

Prediction of where other bots are going to move

Actively try and kill other snakes

Use Machine Learning?

I probably won’t get around to these any time soon, but merge requests are highly encouraged!

Let me know if you try out the scripts and what your thoughts are!