A Python-based chess training environment where Google's Gemini AI learns to play chess by competing against Stockfish.
Arena (also known as "Cyberchess") is an experimental platform that creates a learning environment for AI models. The system pits Google's Gemini AI against the Stockfish chess engine, collecting gameplay data for future model fine-tuning. This project explores AI learning through gameplay, feedback loops, and iterative improvement.
- ๐ค AI vs Engine Gameplay: Gemini (Black) learns by playing against Stockfish (White)
- ๐ Feedback Loop: In-context learning with illegal move correction
- ๐ Data Collection: Automatic export to PGN format for training datasets
- โก Fast Iteration: Quick games with configurable difficulty levels
- ๐ Educational: Transparent code for learning AI/ML concepts
- Python 3.8+ installed on your system
- Stockfish Chess Engine - Download from stockfishchess.org
- Google Gemini API Key - Get one from Google AI Studio
# Clone the repository
git clone https://github.com/GizzZmo/Arena.git
cd Arena
# Install required Python packages
pip install python-chess google-generativeaiEdit cyberchess.py and update the configuration section:
# Path to your Stockfish executable
STOCKFISH_PATH = "/path/to/stockfish" # e.g., "C:/stockfish/stockfish.exe" on Windows
# Your Gemini API key
GOOGLE_API_KEY = "your_api_key_here"python cyberchess.pyWatch as Gemini and Stockfish battle it out! The game will be displayed in your terminal, and results will be saved to training_data.pgn.
- ROADMAP.md - Project roadmap and future plans
- Code Documentation - Comprehensive docstrings in
cyberchess.py - API References - See inline comments for detailed explanations
- Arena Setup (Phase 1): Stockfish and Gemini are initialized with the chess board
- Gameplay (Phase 2):
- Stockfish (White) plays as the "teacher" at skill level 5
- Gemini (Black) plays as the "student" learning from experience
- If Gemini makes an illegal move, it receives feedback and retries
- Data Collection: Each completed game is saved to
training_data.pgn - Fine-tuning (Phase 3 - Future): Accumulated games will be used to fine-tune Gemini
--- CYBERCHESS: Stockfish (White) vs Gemini (Black) ---
Move 1
r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B N R
Stockfish is thinking...
Stockfish played: e2e4
Gemini is thinking...
Gemini played: e7e5
...
For overnight data collection, modify the main block to loop:
if __name__ == "__main__":
while True:
finished_board = play_game()
save_game_data(finished_board)This will continuously generate games for your training dataset.
- โ Phase 1: Arena setup and gameplay mechanics - Complete
- โ Phase 2: Data collection and feedback loop - Complete
- ๐ฏ Phase 3: Model fine-tuning with Vertex AI - Next Up
- ๐ Phase 4: Continuous improvement loop - Planned
- ๐ Phase 5: Advanced features and optimization - Future
See ROADMAP.md for detailed plans.
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ Stockfish โ โโโโโโโบ โ Chess Board โ
โ (Teacher) โ โ (State) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โฒ
โ
โผ
โโโโโโโโโโโโโโโโ
โ Gemini โ
โ (Student) โ
โโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโ
โ PGN Export โ
โ (Training โ
โ Data) โ
โโโโโโโโโโโโโโโโ
- python-chess: Chess game logic and board management
- google-generativeai: Gemini API interface
- Stockfish: External chess engine binary
get_gemini_move(): AI move generation with retry logicplay_game(): Game orchestration and executionsave_game_data(): PGN export for training data
Contributions are welcome! Here's how you can help:
- ๐ Report bugs and issues
- ๐ก Suggest new features or improvements
- ๐ Improve documentation
- ๐ฎ Run games and share training data
- ๐ป Submit pull requests
See ROADMAP.md for areas where contributions are needed.
This project is licensed under the MIT License - see the LICENSE file for details.
- Stockfish Team - For the powerful open-source chess engine
- Google Gemini - For the AI model capabilities
- python-chess - For the excellent chess library
- Community Contributors - Everyone who helps improve this project
- Author: Jon Arve Ovesen (GizzZmo)
- GitHub: GizzZmo/Arena
- Issues: Report a bug or request a feature
This is the "Arena" prototype. This script sets up the environment where Stockfish (The Teacher) plays against Gemini (The Student).
It includes a feedback loop: if Gemini tries to make an illegal move, the script catches it, tells Gemini why it was illegal, and asks it to try again (In-context correction).
Before running the code, you need three things:
- Python Libraries: Run this in your terminal:
pip install python-chess google-generativeai
- Stockfish Engine: Download the Stockfish executable for your OS (Windows/Mac/Linux) from stockfishchess.org. Note the path to where you save it.
- Gemini API Key: Get one from Google AI Studio.
- Environment variables: Configure once so you do not edit code:
export STOCKFISH_PATH="/full/path/to/stockfish" export GOOGLE_API_KEY="your_gemini_key" # optional: how many games to run per session and where to store PGNs export ARENA_GAMES=5 export ARENA_OUTPUT_DIR="data"
Create a file named cyberchess.py and paste this code in. Make sure to set STOCKFISH_PATH and GOOGLE_API_KEY (env vars recommended).
import chess
import chess.engine
import chess.pgn
import google.generativeai as genai
import time
import datetime
# --- CONFIGURATION ---
# REPLACE THIS with the path to your downloaded stockfish file
# Windows example: "C:/Users/Jon/Downloads/stockfish/stockfish-windows-x86-64.exe"
# Mac example: "/opt/homebrew/bin/stockfish"
STOCKFISH_PATH = "YOUR_STOCKFISH_PATH_HERE"
# REPLACE THIS with your Google Gemini API Key
GOOGLE_API_KEY = "YOUR_GEMINI_API_KEY_HERE"
# Setup Gemini
genai.configure(api_key=GOOGLE_API_KEY)
model = genai.GenerativeModel('gemini-1.5-flash') # Using Flash for speed
def get_gemini_move(board, retries=3):
"""
Sends the board state to Gemini and asks for a move.
Includes a retry loop for illegal moves.
"""
legal_moves = [move.uci() for move in board.legal_moves]
# We provide the FEN (Board State) and the list of legal moves to help Gemini
# ground its reasoning and avoid hallucinations.
prompt = f"""
You are playing a game of Chess against Stockfish. You are playing Black.
Current Board Position (FEN): {board.fen()}
Here is the list of legally possible moves you can make:
{', '.join(legal_moves)}
Your goal is to survive and learn. Analyze the board.
Pick the best move from the legal list above.
IMPORTANT: Reply ONLY with the move in UCI format (e.g., e7e5). Do not write any other text.
"""
for attempt in range(retries):
try:
response = model.generate_content(prompt)
move_str = response.text.strip().replace("\n", "").replace(" ", "")
# clean up common formatting issues if Gemini adds markdown
move_str = move_str.replace("`", "")
move = chess.Move.from_uci(move_str)
if move in board.legal_moves:
return move
else:
print(f" > Gemini tried illegal move: {move_str}. Retrying...")
# Add feedback to the next prompt (In-Context Learning)
prompt += f"\n\nERROR: {move_str} is not a legal move. Please choose strictly from the provided list."
except Exception as e:
print(f" > Error parsing Gemini response: {e}")
prompt += f"\n\nERROR: Invalid format. Please reply ONLY with the move string (e.g., e7e5)."
# If Gemini fails 3 times, we make a random move to keep the game going (fallback)
print(" > Gemini failed to produce a legal move. Making random move.")
import random
return random.choice(list(board.legal_moves))
def play_game():
# Initialize Board and Stockfish
board = chess.Board()
engine = chess.engine.SimpleEngine.popen_uci(STOCKFISH_PATH)
# Set Stockfish skill level (Lower it initially so Gemini has a chance)
# Skill level 0 is weak, 20 is Grandmaster. Let's start at 5.
engine.configure({"Skill Level": 5})
print("--- CYBERCHESS: Stockfish (White) vs Gemini (Black) ---")
game_moves = []
while not board.is_game_over():
print(f"\nMove {board.fullmove_number}")
print(board)
if board.turn == chess.WHITE:
# --- STOCKFISH TURN ---
print("Stockfish is thinking...")
# Limit Stockfish to 0.1 seconds so it plays fast
result = engine.play(board, chess.engine.Limit(time=0.1))
board.push(result.move)
print(f"Stockfish played: {result.move.uci()}")
game_moves.append(result.move)
else:
# --- GEMINI TURN ---
print("Gemini is thinking...")
move = get_gemini_move(board)
board.push(move)
print(f"Gemini played: {move.uci()}")
game_moves.append(move)
# --- GAME OVER ---
print("\n--- GAME OVER ---")
print(f"Result: {board.result()}")
engine.quit()
return board
def save_game_data(board):
"""
Saves the game to a PGN file.
This is the dataset we will use later to FINE TUNE Gemini.
"""
pgn_game = chess.pgn.Game.from_board(board)
pgn_game.headers["Event"] = "Cyberchess Dojo"
pgn_game.headers["White"] = "Stockfish Level 5"
pgn_game.headers["Black"] = "Gemini 1.5 Flash"
pgn_game.headers["Date"] = datetime.datetime.now().strftime("%Y.%m.%d")
with open("training_data.pgn", "a") as f:
f.write(str(pgn_game) + "\n\n")
print("Game saved to 'training_data.pgn'")
if __name__ == "__main__":
# In a real app, you would loop this: while True: play_game()
finished_board = play_game()
save_game_data(finished_board)The repository version of
cyberchess.pyincludes a session runner that honorsARENA_GAMES/ARENA_OUTPUT_DIR, validates configuration, and writes timestamped PGNs automaticallyโuse the shipped file when in doubt.
The script above handles Phase 1 (The Arena) and Phase 2 (Data Collection).
Here is how you handle the learning part:
- Run automated sessions:
ARENA_GAMES=10 ARENA_OUTPUT_DIR=data python cyberchess.pywill run 10 games back-to-back and drop per-game PGNs plus an aggregatedtraining_data.pgnin the chosen directory. Leave it running overnight for growth. - Accumulate Data: Each game is timestamped and annotated with ply count, duration, and termination reason so you can filter later.
- The Analysis: Gemini will lose almost every game at first. But occasionally, it will survive 20 or 30 moves.
- Fine Tuning (The Next Step): Once you have 1,000 games in that PGN file, you can upload that file to Google Vertex AI to create a Fine-Tuned Model. You then update the script to use
model = genai.GenerativeModel('your-finetuned-model-name').
Do you have the Stockfish binary downloaded, or do you need help finding the right version for your computer?
The GitHub Wiki tracks practical details that should stay short and easy to scan:
- Setup & Configuration: Stockfish install paths, engine skill presets, and how to set
GOOGLE_API_KEY. - Running Arena Sessions: Example commands, troubleshooting illegal-move retries, and saving PGN outputs.
- Data Management: How to rotate or archive
training_data.pgnand tips for fine-tuning inputs. - FAQ: Common errors (engine not found, API auth) and quick fixes.
Best practices for pages:
- Lead with a 3โ7 step checklist and copy/paste commands.
- Keep configuration values in one place; reference
.envkeys instead of repeating secrets. - Add a short โLast verified on (date) with version (x.y)โ note for commands that can drift.
- Prefer links to upstream docs instead of duplicating long explanations.
- Phase 1 โ Arena Loop (Completed): Stockfish vs. Gemini with illegal-move feedback and PGN logging. โ Definition of done: stable loop with reproducible setup docs.
- Phase 2 โ Data Growth (In progress): Automated long-running sessions, basic telemetry (move counts, termination reason), and improved PGN metadata. Definition of done: nightly runs produce timestamped PGNs with minimal manual babysitting.
- Phase 3 โ Fine-Tuning: Export
training_data.pgnto Vertex AI, swap in the fine-tuned model name, and validate against a fixed test suite of positions. โ Definition of done: baseline ELO/position tests recorded before and after swap. - Phase 4 โ UX & Sharing: Provide a CLI flag for headless runs, optional web viewer for games, and wiki guides for contributors. โ Definition of done: one-command start and a contributor page with expectations.