← Back to lobby

🐍 Snake Challenge

Student Guide β€” Game URL: https://snake.abc123xyz.info

1. How It Works

You build a small HTTP server (your bot). Every 500 ms the game calls your bot with the current game state and asks: "which direction?". Your bot replies. That's the whole job.

Game server ──POST /move──▢  YOUR BOT
            ◀── { direction } ──

The server handles walls, self-collisions, scoring, and rendering. You only need to decide strategy.

2. Request Your Bot Receives

The game sends a POST /move with this JSON body every tick:

{
  "snake": {
    "body": [{"x": 5, "y": 9}, {"x": 4, "y": 9}],
    "dir":   "RIGHT",
    "alive": true,
    "score": 2
  },
  "opponent": {
    "alive": true,
    "head":  {"x": 15, "y": 9},
    "body":  [{"x": 15, "y": 9}, {"x": 16, "y": 9}]
  },
  "foods": [{"x": 10, "y": 5}, {"x": 3, "y": 14}],
  "grid":  {"width": 20, "height": 20},
  "tick":  42,
  "safe_moves": ["UP", "RIGHT", "DOWN"],
  "rules": {"warMode": false}
}
FieldMeaning
snake.body[0]Your head position (x, y)
safe_movesMoves that won't immediately kill you β€” start here
foodsAll food positions on the board
opponent.headOpponent head position
opponent.bodyFull opponent body (in full-info mode)
rules.warModeIf true, hitting opponent body cuts and scores

3. What Your Bot Must Return

{"direction": "RIGHT"}

One of: "UP"  "DOWN"  "LEFT"  "RIGHT"

Timeout: 5 seconds per tick. If your bot doesn't respond in time the server picks the safest available move for you automatically.

4. Starter Bots

Pick any language. Copy, run, then improve.

Python

bot.py
from flask import Flask, request, jsonify
import random

app = Flask(__name__)

@app.route('/move', methods=['POST'])
def move():
    data = request.json
    safe = data.get('safe_moves', ['UP'])

    # ── your strategy here ──
    direction = random.choice(safe)

    return jsonify({'direction': direction})

if __name__ == '__main__':
    app.run(port=8000)
pip install flask
python bot.py

Node.js

bot.js
const express = require('express')
const app = express()
app.use(express.json())

app.post('/move', (req, res) => {
  const safe = req.body.safe_moves || ['UP']

  // ── your strategy here ──
  const direction = safe[Math.floor(Math.random() * safe.length)]

  res.json({ direction })
})

app.listen(8000, () => console.log('Bot ready on :8000'))
npm init -y && npm install express
node bot.js

Go

main.go
package main

import (
    "encoding/json"
    "math/rand"
    "net/http"
)

type Payload struct {
    SafeMoves []string `json:"safe_moves"`
}

func main() {
    http.HandleFunc("/move", func(w http.ResponseWriter, r *http.Request) {
        var p Payload
        json.NewDecoder(r.Body).Decode(&p)
        safe := p.SafeMoves
        if len(safe) == 0 { safe = []string{"UP"} }
        json.NewEncoder(w).Encode(map[string]string{
            "direction": safe[rand.Intn(len(safe))],
        })
    })
    http.ListenAndServe(":8000", nil)
}
go run main.go

5. Test Your Bot Locally

Run this curl command β€” your bot should reply with a direction:

curl -X POST http://localhost:8000/move \
  -H "Content-Type: application/json" \
  -d '{
    "snake":    {"body":[{"x":5,"y":9},{"x":4,"y":9}],"dir":"RIGHT","alive":true,"score":0},
    "opponent": {"alive":true,"head":{"x":15,"y":9}},
    "foods":    [{"x":10,"y":5}],
    "grid":     {"width":20,"height":20},
    "tick":     1,
    "safe_moves": ["UP","RIGHT","DOWN"],
    "rules":    {"warMode":false}
  }'

Expected: {"direction":"RIGHT"}

6. Make Your Bot Public

The game server needs to reach your bot over the internet. No domain needed β€” pick the option that fits you:

⭐ Option A β€” Replit (recommended for beginners)

Everything in the browser. No installs. No account setup beyond signing up.

1
Go to replit.com β†’ sign up free β†’ Create Repl β†’ choose Python or Node.js
2
Paste the starter bot code from Section 4 into the editor
3
Click Run β€” Replit gives you a public URL like https://botname.username.repl.co
4
Your bot URL = https://botname.username.repl.co/move

⚑ Option B β€” localtunnel (one command, no account)

Run your bot locally and expose it instantly. Requires Node.js installed.

# Terminal 1 β€” start your bot
python bot.py        # or: node bot.js

# Terminal 2 β€” expose it (no account needed)
npx localtunnel --port 8000

You get a URL like https://loud-mango-42.loca.lt β€” use that as your bot URL with /move appended.

Note: localtunnel URLs change every time you restart. That's fine for a single match session.

🌐 Option C β€” Cloudflare Quick Tunnel (no account, stable)

More reliable than localtunnel. One command, no sign-up.

# Terminal 1 β€” start your bot
python bot.py        # or: node bot.js

# Terminal 2 β€” expose it
npx cloudflared tunnel --url http://localhost:8000

You get a URL like https://abc-def-123.trycloudflare.com β€” append /move as your bot URL.

Option D β€” ngrok

Free account required. Stable URLs on paid plan, random URL on free.

ngrok http 8000
# Copy the https://….ngrok-free.app URL β†’ add /move
OptionAccount needed?Runs where?Best for
⭐ ReplitFree signupCloud (browser)Beginners, no local setup
⚑ localtunnelNoneYour machineQuickest local tunnel
🌐 Cloudflare TunnelNoneYour machineReliable local tunnel
ngrokFree signupYour machineFamiliar tool

7. Join a Match

1
2
Player A β€” Create a match: enter your name + bot URL β†’ click Create Match β†’ share the Match ID with your opponent
3
Player B β€” Join: enter the Match ID + your name + your bot URL β†’ click Join Match
4
Either player clicks Start Game
5
Watch live β€” the Bot Context panel (bottom right) shows exactly what your bot sees each tick: head position, safe moves, food distances, opponent info, and what your bot replied

8. Strategy Ladder

LevelStrategy
🟒 BeginnerPick a random safe_move β€” you'll never die from walls or yourself
🟑 IntermediateAlways move toward the nearest food
🟠 AdvancedFlood-fill: avoid moves that trap you in small spaces
πŸ”΄ ExpertRace for food before opponent, cut opponent body in War mode
Key insight: safe_moves already removes wall and self-collision moves. You don't need to check those β€” just focus on which safe move is strategically best.

Food targeting (Python)

@app.route('/move', methods=['POST'])
def move():
    data   = request.json
    head   = data['snake']['body'][0]
    safe   = data.get('safe_moves', ['UP'])
    foods  = data.get('foods', [])

    if not foods:
        return jsonify({'direction': safe[0]})

    # nearest food by Manhattan distance
    target = min(foods, key=lambda f: abs(f['x']-head['x']) + abs(f['y']-head['y']))

    vectors = {'UP':(0,-1), 'DOWN':(0,1), 'LEFT':(-1,0), 'RIGHT':(1,0)}
    best = min(safe, key=lambda d: (
        abs((head['x'] + vectors[d][0]) - target['x']) +
        abs((head['y'] + vectors[d][1]) - target['y'])
    ))
    return jsonify({'direction': best})

9. War Mode

When the match creator enables War Mode:

10. Quick Reference

ItemValue
Game URLhttps://snake.abc123xyz.info
Bot endpointPOST /move on your server
Response{"direction": "UP|DOWN|LEFT|RIGHT"}
Timeout per tick5 seconds
Default grid20Γ—20
Default tick speed500 ms

Good luck! 🐍