AI checkers game played by a UR robot arm. Minimax AI with alpha-beta pruning, urkit for robot control, YOLO for piece detection.
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python server.pyOpen http://localhost:8765 in your browser. The setup wizard runs on first start.
server.py # HTTP server + game loop (Python http.server, no FastAPI)
game.py # Game engine + minimax AI
robot.py # Robot control (urkit wrapper, UR5e + Robotiq 2F-140)
vision.py # YOLO piece detection + board state tracking
calibration.py # Force-based board calibration (contact detection)
wizard.py # Setup wizard state machine
config.yaml # Server, robot, vision, calibration config
calibration.yaml # Persisted calibration data (auto-generated)
points.db # Named robot positions (auto-generated)
static/ # Frontend (vanilla HTML/CSS/JS, EN/DE)
models/ # YOLO weights (best.pt)
First server start launches a multi-step wizard:
- Connect to Robot — Connects using IP from
config.yaml(edit config and restart if wrong) - Board Calibration — Use existing
calibration.yamlor run new force-based calibration - Camera Selection — Auto-detect all cameras, pick one with live preview
Wizard state is in-memory only. Server restart = wizard runs again.
Skip the wizard during development: set debug.skip_wizard: True in config.yaml.
All settings in config.yaml:
debug:
skip_wizard: True # Skip wizard (dev only)
# Robot (urkit from_config keys)
robot_ip: "172.31.0.200" # Robot IP address
points_path: "points.db" # Named positions DB
gripper: 2f-140 # Robotiq gripper model
ik_reference: fixed_home # IK reference point (prevents wrist flipping)
default_vel: 0.3 # m/s
default_acc: 0.5 # m/s²
speed:
debug_vel: 1.5 # m/s (debug mode)
debug_acc: 5.0 # m/s² (debug mode)
vision:
model_path: "models/best.pt"
confidence_threshold: 0.75
calibration:
force_threshold: 2.0 # Newtons
server:
host: "0.0.0.0"
port: 8765Fails hard if required fields are missing — no silent defaults.
- Set static IP on robot and PC (same subnet)
- Enable Remote Control on robot pendant
- Enable RTDE in Security → Services
- Install Robotiq URCap (if using Robotiq 2F-140 gripper)
Robot IP is configured via config.yaml or the setup wizard.
- Place YOLO model at
models/best.pt - Mount camera above board, facing down
- Select camera in the setup wizard (live preview available)
The YOLO model detects: pieces (P1/P2 men and kings), hands, and board markers. Human moves are detected by placing pieces directly on the board — no UI input needed. Stability check requires 3 consecutive identical frames before accepting a move.
Force-based automatic calibration using urkit contact detection:
- Move to home position and activate gripper
- Find Z contact (board surface) by moving down
- Find X contact (left edge) by moving left
- Find Y contacts (front/back edges) by moving forward/backward
- Calculate board corners, save to
calibration.yamlandpoints.db
All robot positions are saved as named points in points.db. Calibration data persists across restarts.
Fails hard if calibration fails — no default coordinates, no fallback.
- Human plays physically on the board (places pieces, vision detects moves)
- Choose to play as P1 (Green, robot side) or P2 (Orange)
- AI plays the opposing side with robot arm execution
- Both sides controlled by AI, robot arm executes all moves
- Each AI can have independent difficulty settings
Negamax with alpha-beta pruning and advanced optimizations:
- Iterative deepening with time control — predictable move time, never exceeds limit
- Transposition table with Zobrist hashing — avoids re-searching identical positions
- Quiescence search — searches captures at leaf nodes (no horizon effect)
- Killer moves + history heuristic — better move ordering → more pruning → deeper search
- Piece-square tables — positional understanding (advancement, center control)
| Difficulty | Depth | Time limit | Strength |
|---|---|---|---|
| easy | 2 | 0.5s | Casual, beatable |
| medium | 4 | 1.0s | Solid, requires strategy (default) |
| hard | 8 | 2.0s | Very strong |
| random | 0 | — | Random legal moves |
8×8 board, 12 pieces per side. Configurable rules via start parameters:
- men_capture_backward (
true/false) — Men capture in all 4 directions or forward only - flying_kings (
true/false) — Kings move any distance or 1 square only - Mandatory capture — Always enforced, longest chain wins (majority rule)
- Multi-jump chains — Supported, promotion only when chain ends on back row
- Draw detection — Game ends after 25 moves without capture
Defaults: men_capture_backward=true, flying_kings=true (International/German rules).
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/status |
Full game state (board, player, wizard, forced moves) |
| POST | /api/start?mode=...&difficulty=... |
Start game |
| POST | /api/pause |
Pause/resume game |
| POST | /api/reset |
Stop game (graceful, finishes current move) |
| Parameter | Values | Default |
|---|---|---|
| mode | ai_vs_human, ai_vs_ai |
ai_vs_human |
| difficulty | easy, medium, hard, random |
medium |
| difficulty_p2 | same as difficulty | same as difficulty |
| ai_type | smart, bad (plays to lose) |
smart |
| human_color | p1, p2 |
p2 |
| men_capture_backward | true, false |
true |
| flying_kings | true, false |
true |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/wizard/state |
Current wizard state |
| POST | /api/wizard/connect |
Connect to robot (uses config.yaml IP) |
| POST | /api/wizard/use_calibration?use=true|false |
Use existing calibration |
| POST | /api/wizard/run_calibration |
Run force-based calibration |
| GET | /api/wizard/cameras |
Detect available cameras |
| POST | /api/wizard/camera?index=N |
Select camera |
| GET | /api/wizard/camera_feed/N |
Live camera preview |
| POST | /api/wizard/board_calibrate |
Calibrate board grid from camera |
| GET | /api/wizard/board_preview |
Board detection preview |
| GET | /api/wizard/board_state |
Detected board state |
| POST | /api/wizard/reset |
Reset wizard |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/debug/vision |
Vision debug (expected vs detected board) |
| GET | /debug |
Debug page |
| Path | Description |
|---|---|
/ |
Wizard (if incomplete) or main menu (if complete) |
/wizard |
Setup wizard |
Frontend polls /api/status every 0.5 seconds. No WebSockets, no Socket.IO.
- Board display with coordinate labels and last-move highlighting
- Move history navigation (prev/next/jump to current)
- Forced move highlighting — legal moves shown when human must capture
- Pre-game board verification — checks physical board before starting
- i18n — English and German language support
- Reconfigure button to re-run the setup wizard
source venv/bin/activate
pytestGame logic tests run without robot or camera. Integration tests require full hardware setup.
See requirements.txt:
- urkit (≥0.3.21) — Robot control (urkit + ur_rtde + pyyaml)
- ultralytics (≥8.0) — YOLO inference (numpy + opencv-python + torch + pyyaml)
Only two direct dependencies — everything else is pulled in transitively.