Battlesnake AI with Candle
The game is simple: a snake moves around an 11×11 board, eating food while avoiding walls, its own body, and other snakes. Your server receives the board state and responds with a move. That’s it.
The interesting part is how to decide which move to make. A naive approach works okay — always go toward the nearest food, avoid the nearest wall. But a naive approach dies fast against anything competitive. This tutorial is about building a snake that learns.
We’ll use two tools for this:
Candle is a Rust machine learning library from Hugging Face. It’s lightweight, no Python required, and runs on CPU or GPU. We’ll use it to build the neural network that takes the board state and outputs a move decision.
Battlesnake is the game — it’s a hosted competitive programming game where your server is a web endpoint that gets called every turn. The docs are at docs.battlesnake.com. You don’t need to understand the game deeply to start; we’ll cover the parts that matter.
The plan:
- Parts 1–3: The board as data, your first simple network, and what a neural net is actually doing in this context
- Parts 4–5: A heuristic baseline (rule-based snake) and imitation learning — use the heuristic to generate training data, then train the net to copy it
- Parts 6–7: Reinforcement learning — rewards, policy gradients, and self-play training loops
- Part 8: Deploying — wire the trained model to a web server that talks to the Battlesnake engine
- Part 9: Scaling up — GPU training, larger boards, better architectures
We touch on both imitation learning and reinforcement learning, but always grounded in the concrete problem rather than abstract ML theory. The heuristic from the early parts becomes the foundation for everything that follows.
Version note. This tutorial uses candle-core 0.6 and candle-nn 0.6. Candle is pre-1.0 and the API has changed significantly since 0.6 (the current version is 0.10). The concepts — tensor operations, gradient tracking, training loops, policy gradients — are the same across versions. The specific method names and module paths may differ. If you’re on a newer version, check docs.rs for the current API.
Prerequisites
- Rust (1.70+) — rustup.rs
- mdBook —
cargo install mdbook
What we’re building
The project is a Rust workspace with two crates:
battlesnake/ ← workspace root
├── Cargo.toml ← workspace definition
├── snake-ml/ ← ML library (encoding, network, training)
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── snake-server/ ← HTTP server (serves /move, runs the snake)
├── Cargo.toml
└── src/
└── main.rs
Every file is created in this tutorial. No external repositories.
Next: Part 1 — Your Snake’s First Move — We start with what Battlesnake sends you and what a move response looks like. No ML yet — enough to have a working web server that the game engine can call.