// The strategic turn, as a catalog of named phases. // // The turn is not one function. It is three drivers running in a fixed order, and the // campaign has read all three out of the instruction stream: // // * `StrategyServer::ProcessTurn` -- 32 phases, the spine // * `ServerPlayer::ProcessTurn` -- 12 phases, run once per player from spine phase 13 // * `StrategyServer::OnAllCombatDone_Tail` -- 37 phases, a SEPARATE driver reached from a // different message after combat, and the one the autosave is written from // // This header is the roadmap and the ledger at once. Every phase of every driver appears // here whether or not it is implemented, so a run of the standalone prints the whole turn // and marks each phase with what we actually have. A phase that is not implemented is a // named no-op that shows up in the output; it is never silently skipped. // // Nothing in this file describes the original's memory layout. Phase indices are ordinals // in a published phase table, not offsets, and no address appears anywhere in src/app. #pragma once #include namespace sots::app { // Which driver a phase belongs to. enum class Driver : int { // The host steps that bracket the drivers: BeginProcessTurn before the spine, and the // save writer's own invariants after everything. Not part of the milestone's 44 -- they // are not phases of either turn driver -- but they are part of a turn and are listed so // the log is the whole sequence. Host = 0, Strategic = 1, // StrategyServer::ProcessTurn Player = 2, // ServerPlayer::ProcessTurn (once per player, from Strategic phase 13) Tail = 3, // StrategyServer::OnAllCombatDone_Tail (post-combat, pre-autosave) }; const char* DriverName(Driver d); // How much of a phase we have, and -- the load-bearing part -- whether the standalone is // allowed to COMMIT its result to the save. // // The distinction between `Blocked` and `Stub` is the whole point of this scaffold. A // blocked phase is one whose formula we hold and whose inputs we do not: running it and // writing the result would replace a leaf that currently happens to match with a leaf that // is confidently wrong. So a blocked phase is evaluated, its result is reported, and it is // not written unless the operator asks for it. That keeps the divergence count an honest // measure of what we know rather than a measure of how much code we ran. enum class PhaseStatus : int { Verified = 0, // implemented here AND compared against the live game by an earlier lane Implemented = 1, // implemented from an instruction-verified reading; committed Partial = 2, // part implemented and committed, part stubbed; the note says which Blocked = 3, // formula held, an input is not modelled -> evaluated, reported, NOT committed Stub = 4, // named no-op }; const char* StatusName(PhaseStatus s); // One-character glyph for the compact phase listing. char StatusGlyph(PhaseStatus s); struct PhaseDesc { Driver driver; int index; // ordinal in that driver's published phase table const char* id; // stable id, e.g. "S11" / "P07" / "T31" const char* name; // short identifier-shaped name PhaseStatus status; const char* note; // what it does, or what is missing -- printed next to the phase }; // The tables, in execution order. const PhaseDesc* HostPhases(std::size_t& count); const PhaseDesc* StrategicPhases(std::size_t& count); const PhaseDesc* PlayerPhases(std::size_t& count); const PhaseDesc* TailPhases(std::size_t& count); // The completion metric's denominator. The campaign's milestone counts the two turn-driver // tables -- 32 + 12 = 44 -- and tracks the tail's 37 separately, because the tail is a // second driver that has never been executed by anything we own. constexpr int kSpinePhaseCount = 44; struct PhaseTally { int total = 0, verified = 0, implemented = 0, partial = 0, blocked = 0, stub = 0; // "modelled" = anything we run at all, blocked included. "committed" = anything whose // result reaches the save. int modelled() const { return verified + implemented + partial + blocked; } int committed() const { return verified + implemented + partial; } }; PhaseTally TallySpine(); PhaseTally TallyTail(); } // namespace sots::app