app/game_analyzer.h

post-game engine analysis of a GameRecord (review-docs

PLAN.md §5).

THE BOARD ANALYZES ITS OWN GAMES. The engine is a C++ binary and the Pi is idle the moment a game ends, so analysis runs here, on a background thread, and the web app renders the finished artifact. No engine in a Worker.

Two invariants the rest of the system depends on:

  • Scores are WHITE-relative. The search reports side-to-move-relative scores; AnalysisLine normalizes that away once, in LinkedEngine::analyze. An eval graph plotted from side-to-move scores is a sawtooth of lies.

  • The analyzer owns a PRIVATE engine. analyze() clobbers search state, so it must never borrow the engine playing a game.

Analysis is at a fixed NODE budget and forced full strength, whatever personality the game was played at: a game played on Easy still earns a Hard review. Nodes rather than time keeps the artifact reproducible across machines, which is what lets two boards in a networked game produce the identical result.

namespace kirin
class GameAnalyzer
#include <game_analyzer.h>

Public Types

using ProgressCallback = std::function<void(int, int)>

Public Functions

explicit GameAnalyzer(IEngine &engine, long nodesPerMove = kDefaultNodes)
GameAnalysis analyze(const GameRecord &record, const ProgressCallback &onProgress = nullptr, const std::atomic<bool> *cancel = nullptr)

Public Static Attributes

static constexpr long kDefaultNodes = 200000

Private Members

IEngine &engine_
long nodesPerMove_