daniel156161 65c97b219b
Build and Push Docker Container / build-and-push (push) Successful in 8m20s
fix(deps): add httpx, remove unused gel dependency
- Add httpx>=0.28.0 (required by quart_common.web.wide_event)

- Remove gel>=3.1.0 (only lazy-imported in EdgeDB.py with try/except)

- Update uv.lock with resolved dependency changes
2026-08-01 16:33:37 +02:00
2026-04-04 10:23:12 +02:00
2025-05-15 09:56:01 +02:00
2022-01-24 15:30:05 +01:00

Battlesnake Python Starter Project

An official Battlesnake template written in Python. Get started at play.battlesnake.com.

Battlesnake Logo

This project is a great starting point for anyone wanting to program their first Battlesnake in Python. It can be run locally or easily deployed to a cloud provider of your choosing. See the Battlesnake API Docs for more detail.

Technologies Used

This project uses Python 3 and Flask. It also comes with an optional Dockerfile to help with deployment.

Run Your Battlesnake

Install dependencies using pip

pip install -r requirements.txt

Start your Battlesnake

python main.py

You should see the following output once it is running

Running your Battlesnake at http://0.0.0.0:8000
 * Serving Flask app 'My Battlesnake'
 * Debug mode: off

Open localhost:8000 in your browser and you should see

{"apiversion":"1","author":"","color":"#888888","head":"default","tail":"default"}

Play a Game Locally

Install the Battlesnake CLI

Command to run a local game

battlesnake play -W 11 -H 11 --name 'Python Starter Project' --url http://localhost:8000 -g solo --browser

Next Steps

Continue with the Battlesnake Quickstart Guide to customize and improve your Battlesnake's behavior.

Included Competitive Snake

This repo now includes snakes/BestBattleSnake.py, a stronger default snake that combines:

  • collision and head-to-head risk checks
  • flood-fill space evaluation to avoid traps
  • food routing that gets more aggressive as health drops
  • tail access checks for better long-term survival

Run it explicitly with:

SNAKE=BestBattleSnake python main.py

Optional duel tuning (when only 2 snakes are alive):

BATTLE_SNAKE_DUEL_STYLE=balanced python main.py

Allowed values: safe, balanced, aggressive.

PrismBattleSnake_GPT_5_6_Sol

PrismBattleSnake_GPT_5_6_Sol is a separate snake that keeps Apex's strategy while accelerating hot spatial operations with a Python-integer bitboard engine. Its filename, class, and registry key include the model name, while its public Battlesnake API name remains PrismBattleSnake.

Run it with:

SNAKE=PrismBattleSnake_GPT_5_6_Sol python main.py

Benchmark Apex and Prism against sampled positions from a gameplay database:

python scripts/benchmark_snakes_from_db.py \
  --database /path/to/gameplay.sqlite3 \
  --samples 100

The benchmark opens SQLite read-only and reports mean, median, p95, and maximum move latency. Increase --samples for a broader but slower comparison.

Compact gameplay database

New gameplay turns use normalized storage: the turn row stores food, hazards, move, and thinking data once; snake identity is stored once per game in game_snakes; and changing snake state/body data lives in snake_turns. Replay loading rebuilds the normal Battlesnake board payload.

Create and verify a separate compact copy of an existing SQLite database. By default, replay-heavy rows are retained for games rated medium or high by structural completeness, valid moves, thinking coverage, game length, move diversity, opponent data, and terminal outcome. All game-result rows remain stored, so historical win/loss rates stay persistent when low-quality replay data is removed.

python scripts/migrate_gameplay_database.py \
  --source /path/to/gameplay.sqlite3 \
  --destination /path/to/gameplay.compact.sqlite3 \
  --minimum-quality medium

After reviewing the compact copy, --replace renames the original to a timestamped backup and puts the verified compact database at the original path. Stop all writers before using it:

python scripts/migrate_gameplay_database.py \
  --source /path/to/gameplay.sqlite3 \
  --replace

The migration never modifies the source in place. It verifies row counts and runs SQLite's integrity_check before any replacement.

Record new games while cleanup runs

Point the running server at a temporary delta database while the old database is being compacted. After stopping the writer and flushing the delta database, merge it into the cleaned copy:

python scripts/merge_gameplay_databases.py \
  --base /path/to/gameplay.compact.sqlite3 \
  --delta /path/to/gameplay.delta.sqlite3 \
  --destination /path/to/gameplay.merged.sqlite3 \
  --minimum-quality medium

The merger keeps all game results, quality-rates delta games, regenerates numeric turn IDs, and verifies row counts, foreign keys, and database integrity. Identical game IDs are skipped; conflicting duplicates abort the merge. After reviewing the result, --replace-base backs up and replaces the cleaned base. Stop the delta writer before the final merge and file swap.

Export Training Dataset

Game saves now include a dataset section with labeled move samples.

Export all stored samples to JSONL:

python -m server.DatasetExporter --input data --output data/dataset/good_moves.jsonl

Or with just:

just export-dataset

Curate a high-quality training subset (single file):

python -m server.DatasetCurator --input good_moves-2026-04-03.jsonl --output data/dataset/best_moves.jsonl

Curate from multiple JSONL sources (repeat --input):

python -m server.DatasetCurator \
  --input good_moves-2026-04-03.jsonl \
  --input good_moves-2026-04-04.jsonl \
  --output data/dataset/best_moves.jsonl

Curate from folder or glob:

python -m server.DatasetCurator --input data/dataset --output data/dataset/best_moves.jsonl
python -m server.DatasetCurator --input "good_moves-*.jsonl" --output data/dataset/best_moves.jsonl

Append mode (keeps existing curated rows and deduplicates against them):

python -m server.DatasetCurator --input "good_moves-*.jsonl" --output data/dataset/best_moves.jsonl --append

Archive processed input files after curation:

python -m server.DatasetCurator --input "good_moves-*.jsonl" --output data/dataset/best_moves.jsonl --append --archive-input
python -m server.DatasetCurator --input "good_moves-*.jsonl" --output data/dataset/best_moves.jsonl --append --archive-input --archive-dir data/dataset/archive

Or with just:

just curate-dataset
just curate-dataset append=true
just curate-dataset append=true archive=true archive_dir=data/dataset/archive

Analyze dataset quality overall and by day (best game overall/day included):

python -m server.DatasetStats --input "good_moves-*.jsonl"
python -m server.DatasetStats --input data/dataset --output data/dataset/stats-report.json

The stats report now includes both:

  • best_game (survival/length focused)
  • best_pressure_game (high-pressure quality focused: fewer safe options + strong survival)

Or with just:

just analyze-dataset
just analyze-dataset input=data/dataset output=data/dataset/stats-report.json

To store compact dataset-only records (JSONL) and skip full per-game JSON files:

STORE_DATASET_ONLY=true DATASET_JSONL_PATH=data/dataset/good_moves.jsonl python main.py

Optional compact storage tuning:

  • DATASET_ROTATE_DAILY=true creates one JSONL file per day (default: true)
  • DATASET_JSONL_MAX_MB=50 rotates when file reaches max size in MB (default: 50)
  • DATASET_COMPRESS_ROTATED=true gzip-compresses rotated/old JSONL files (default: true)

Note: To play games on play.battlesnake.com you'll need to deploy your Battlesnake to a live web server OR use a port forwarding tool like ngrok to access your server locally.

S
Description
Languages
Python 88.7%
JavaScript 7.2%
CSS 1.7%
Just 1.1%
HTML 1.1%
Other 0.2%