Skip to content

Project overview

What this project is

This repository is a self-play and MCTS experiment system built around a 15x15 board. The board looks Go-like, but the rules are intentionally simplified so the project can focus on search, training, record keeping, and recovery instead of full referee complexity.

If you are completely new to projects like this, you can picture it as a loop:

  1. the program plays games against itself
  2. it saves what happened in those games
  3. it trains the model from those saved games
  4. it uses the updated model in later games

Why the project is built this way

Long-running training systems fail in predictable ways if their boundaries are vague:

  1. the rules become too complicated to validate
  2. the training loop runs for hours and still does not leave enough data behind to explain what happened

This project narrows the rules, then builds a clear path from self-play to training to checkpoints and metrics.

Core components

Simplified rules

What it is: a Go-like move and capture system with alternating turns, pass, suicide checks, captures, and repeated-position protection.

Why it is needed: MCTS and self-play need a stable state transition model. If the rules are inconsistent, the training data stops meaning one thing.

How it is used here: the rules live in the Rust engine only. Python does not implement another copy.

Inputs and outputs:

  • input: board state, side to move, candidate action
  • output: legality decision, next state, capture data, end reason, and scoring fields

How to judge a normal result:

  • illegal moves are rejected
  • two consecutive passes end the game
  • repeated in-game positions are rejected
  • captures and score-related fields appear in saved records

If pass is unfamiliar, it simply means skipping a move and giving the turn to the other side.

MCTS

What it is: Monte Carlo Tree Search used to allocate search effort and choose moves.

In plainer language, it means trying several possible continuations before committing to a move.

Why it is needed: the project is not a random playout generator. It needs a search process that can combine model guidance with board state exploration.

How it is used here: Rust handles node structure, selection, expansion, and backpropagation while Python provides model inference.

Inputs and outputs:

  • input: current state, legal actions, model policy/value outputs
  • output: search statistics and a selected action

How to judge a normal result:

  • search does not produce rule-breaking actions
  • visit counts and value statistics accumulate as the tree grows
  • self-play can reach legal terminal states

Training loop

What it is: a cycle where self-play data is fed back into model training, then reused in later self-play.

Why it is needed: without the training stage, the project would only generate games and never test whether the model improves from saved data.

How it is used here: Python reads stored game records, builds batches, updates the residual CNN, saves checkpoints, and feeds the next round.

Inputs and outputs:

  • input: game records, configuration, previous checkpoints, training device information
  • output: updated weights, checkpoints, metrics, and a model ready for later inference

How to judge a normal result:

  • checkpoints and metrics keep being written
  • interrupted runs can recover
  • hardware selection changes the device, not the model route

Here, metrics means the numeric trace of training and runtime behavior, such as step counts, loss values, or worker usage. Those numbers are what let you tell the difference between a healthy run and one that quietly drifted off course.

What the project is not trying to do

  • It is not a full Go referee.
  • It does not promise professional-strength play.
  • It does not trade away reusable data for demo convenience.
  • It does not keep separate rules implementations in Rust and Python.