Table of Contents
If a snake leaves the last tile of the board, they will die.
Eating a food pellet will make snakes one segment longer. Snakes grow out of their tail: new tail segment will appear in the same square that the tail was in the previous turn.
Eating a food pellet will restore snakes' health-points to 100.
The amount of food can vary from game to game, but within the same game it will always stay the same. As soon as a piece of food is eaten, it will respawn at a random, unoccupied location on the next turn.
Every turn snakes will loose one health-point. Health-points serve like the snake's hunger bar, and if it reaches zero, the snake will starve and die. Eating food will restore snake's health to one-hundred points on the next turn.
If a snake collides with itself or any other snakes' tails, it dies.
Head-to-head collisions follow different rules than the previously mentioned tail collisions.
In head-on collisions, the longer snake will survive.
But if both snakes are the same size, they both die. Note that in the below scenario, the food remains (collisions are resolved before food is eaten).
If you have a game server running locally you can visit /test
, plug your
snake's URL in and a number of tests will be run against your server, checking
if it follows all the basic game rules.
All interactions with the game are implemented as HTTP POST webhooks. Once the
game has begun your server will receive a request to your /start
endpoint, and
then on each turn a request to the /move
endpoint.
URL | /start |
Method | POST |
request body JSON | object |
expected response JSON | object |
interface StartRequest {
game_id: string;
}
interface StartResponse {
/**
* What color your snake should be on the board.
* Accepts any valid CSS color.
* https://developer.mozilla.org/en-US/docs/Web/CSS/color
*/
color: string;
name: string;
/**
* URL of the image to display as your avatar.
*/
head_url: string;
taunt: string;
head_type: HeadType;
tail_type: TailType;
secondary_color: string;
}
String referring to what head image should be used for your snake.
Renders one of the matching images in this directory.
type HeadType =
| 'bendr'
| 'dead'
| 'fang'
| 'pixel'
| 'regular'
| 'safe'
| 'sand-worm'
| 'shades'
| 'smile'
| 'tongue';
String referring to what tail image should be used for your snake.
Renders one of the matching images in this directory.
type TailType =
| 'block-bum'
| 'curled'
| 'fat-rattle'
| 'freckled'
| 'pixel'
| 'regular'
| 'round-bum'
| 'skinny'
| 'small-rattle'
{
"game_id": "b1dadee8-a112-4e0e-afa2-2845cd1f21aa"
}
{
"color": "#FF0000",
"secondary_color": "#00FF00",
"head_url": "http://placecage.com/c/100/100",
"name": "Cage Snake",
"taunt": "OH GOD NOT THE BEES",
"head_type": "pixel",
"tail_type": "pixel"
}
A request including all the current game information will be issued to this endpoint on each turn. The game server expects a JSON response within 200ms.
URL | /move |
Method | POST |
request body JSON | object |
expected response JSON | object |
interface MoveResponse {
move: Move;
}
type Move = 'up' | 'down' | 'left' | 'right';
interface World {
object: 'world';
id: number;
you: Snake;
snakes: List<Snake>;
height: number;
width: number;
turn: number;
food: List<Point>;
}
interface Snake {
body: List<Point>;
health: number;
id: string;
length: number;
name: string;
object: 'snake';
taunt: string;
}
interface List<T> {
object: 'list';
data: T[];
}
interface Point {
object: 'point';
x: number;
y: number;
}
{
"food": {
"data": [
{
"object": "point",
"x": 0,
"y": 9
}
],
"object": "list"
},
"height": 20,
"id": 1,
"object": "world",
"snakes": {
"data": [
{
"body": {
"data": [
{
"object": "point",
"x": 13,
"y": 19
},
{
"object": "point",
"x": 13,
"y": 19
},
{
"object": "point",
"x": 13,
"y": 19
}
],
"object": "list"
},
"health": 100,
"id": "58a0142f-4cd7-4d35-9b17-815ec8ff8e70",
"length": 3,
"name": "Sonic Snake",
"object": "snake",
"taunt": "Gotta go fast"
},
{
"body": {
"data": [
{
"object": "point",
"x": 8,
"y": 15
},
{
"object": "point",
"x": 8,
"y": 15
},
{
"object": "point",
"x": 8,
"y": 15
}
],
"object": "list"
},
"health": 100,
"id": "48ca23a2-dde8-4d0f-b03a-61cc9780427e",
"length": 3,
"name": "Typescript Snake",
"object": "snake",
"taunt": ""
}
],
"object": "list"
},
"turn": 0,
"width": 20,
"you": {
"body": {
"data": [
{
"object": "point",
"x": 8,
"y": 15
},
{
"object": "point",
"x": 8,
"y": 15
},
{
"object": "point",
"x": 8,
"y": 15
}
],
"object": "list"
},
"health": 100,
"id": "48ca23a2-dde8-4d0f-b03a-61cc9780427e",
"length": 3,
"name": "Typescript Snake",
"object": "snake",
"taunt": ""
}
}
{
"move": "up"
}
docker pull battlesnake/battle_snake
docker run -it -p 3000:3000 battlesnake/battle_snake
You should be able to view the game server at http://localhost:3000.
If you are running your snake on localhost, you won't be able to reference it as
localhost
because the container runs on its own network. If you're running
Docker For Mac you can reference localhost:5678 with
http://docker.for.mac.localhost:5678/, otherwise use your full ip address on
your network to reference your localhost (192.168.1.xxx or whatever your subnet
is configured for, use ifconfig to find out).
MacOSX
brew update && brew install erlang elixir nodejs yarn
Linux
I suggest installing Erlang through evm and Elixir through kiex.
git clone [email protected]:battle-snake/battle_snake.git`
cd battle_snake
yarn install
mix do local.hex --force, local.rebar
mix do deps.get, deps.compile
mix do ecto.create, ecto.migrate
mix phx.server
yarn cypress:open
mix test
Spotted an inaccuracy in the document, think they suck, or have a suggestion on how to make it better? Open an issue, or even better submit a PR!
Copyright 2016-2018 Dylan Kendal
Licensed under the GNU Affero General Public License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/agpl-3.0.txt
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.