Inspiration

Othello engines are very strong, but they teach very little. Edax can tell you that your move lost six discs against perfect play. It cannot tell a beginner why: which square the move opened, and which reply now wins a corner. Large language models can explain things in plain words, but on a board game they often invent captures that are not legal. We wanted a coach that combines the two strengths: the engine decides what is true, and the language model explains it.

What it does

Nemothello is an Othello app for learning from your own games.

  • Play against Edax at three levels, with optional move hints and legal-move highlights. Your color and level stay fixed once the game is under way.
  • Review a finished game move by move. Every move is compared with the engine's recommendation, and the board can demonstrate the continuation step by step. When the actual game went a different way, the app says so.
  • Ask Nemotron about any move. It answers follow-up questions, and the board shows the line it is talking about.
  • Read a game summary: how many of your moves matched the recommendation, any pattern in your choices, and one lesson from the key move of the game.

How we built it

  • Web: Next.js. Backend: FastAPI, plus our own rules engine, which is the single source of truth for legal moves and flips.
  • Engine: Edax 4.6 compiled from source. The opponent searches at depth 1, 4 or 8, depending on the level.
  • Coach: NVIDIA Nemotron 3 Super (nvidia/nemotron-3-super-120b-a12b) through Nebius Token Factory's OpenAI-compatible API.

After a game, Edax scores every legal move in every position. For a played move $m$, the score loss is

$$ \Delta(m) = s(m^{*}) - s(m), $$

where $s$ is the engine's final disc margin and $m^{*}$ is the recommended move. A move with $\Delta = 0$ matches the recommendation. A move with $0 < \Delta < 4$ is only slightly worse, and we do not call it a mistake. A move with $\Delta \ge 4$ is worth reviewing.

For a key move, the rules engine looks for the concrete board mechanism that separates the played move from the recommended one: a capture line that one move opens and the other closes. For corners it proves a forced threat. The opponent has a move $a$ such that for every reply $d$, the corner $c$ is still a legal capture:

$$ \exists\, a \;\; \forall\, d : \; c \in \operatorname{Legal}(\text{board after } a, d). $$

Nemotron then works as a tool-calling agent. It calls play_line to play out a line on the rules engine and check_corner_threat to test a corner, then answers through submit_answer, citing the facts those tools returned. The backend checks every answer before the player sees it:

  • Numbers are written as placeholders and filled in from verified values, so the model never copies a count.
  • Text that cites unknown facts, names squares outside the evidence, or mentions engine scores goes back to the model with the specific problem.
  • Game summaries take two calls. Nemotron drafts the summary with thinking on, then a second call audits the draft against the evidence. A draft gets up to three tries.

The app is deployed on one Linux VM with Docker Compose. Caddy provides HTTPS, the backend image compiles Edax itself, and SQLite stores games and saved lessons, so reopening a lesson costs no model call.

Challenges I ran into

  • Grounding. Early explanations sounded right but described captures that were impossible on the actual board. The fix was structural: the engine produces the facts, the model only selects and explains them, and the text that states the board mechanism is generated from verified data.
  • Explaining "why", not just "what". "The recommended move is better" teaches nothing. Finding a short, true reason a beginner can see (this disc completes a line from a4, so the opponent can flip the whole row and then take a1) meant comparing the two candidate boards square by square.
  • Strict auditing. An auditor that is too strict rejects good summaries. With thinking on, our audit rejected supported text, so it now runs without thinking and separates factual issues from style notes.
  • Bilingual output. Chinese explanations needed plain beginner terms and consistent move numbering, which we enforce after generation.

What I learned

  • A language model is a strong explainer when something else is responsible for truth. Splitting those two jobs made the coach both readable and correct.
  • Tool calling on Token Factory let us switch between Nemotron sizes by changing one model ID, without hosting any GPU.
  • Good teaching text is short. Each round of cutting repetition and hedging made the lessons clearer.

What's next

  • Lessons on more board mechanisms beyond capture lines and corners, such as mobility and parity.
  • Practice positions generated from the player's own recurring mistakes.

Built With

Share this project:

Updates

Submission history