New shim module `ai_rng`: a bracket on StrategyClient::OnResumePlaying over the per-client generator at +0x134, with two independent measurements per bracket (an observer on the existing seven draw-site detours, and `left` read straight off the object) plus AI-call-site attribution through the cl_* facades and an optional seed pin. Measured on VM140/VM145, six runs, five fresh processes, unpinned autosaves byte-identical to the published oracle: turn2->turn3 human 0, AI 32 -> 3 words, AI 496 -> 0, AI 512 -> 0 turn1->turn2 human 0, AI 32 -> 7 words, AI 496 -> 0, AI 512 -> 1 word ... or 3 The last row is the answer: 512 makes ONE cl_RandRange call (the research-target tie-break at 0x006a8495, phase 18) and that one call cost 1 word in one process and 3 in another, because RNG_NextInt is an unbounded rejection loop. The count is not fixed across clients, across turns, or across processes with the path held fixed. Also found: cl_RandFloat 0x00579c70, a third cl_* RNG facade that reaches RNG_NextFloat by a TAIL JUMP and so leaves no rel32 edge for a call-graph sweep -- which is why ai-turn-logic.md 5's "zero NextFloat calls from the AI module" reads as true when it is not. The instrument caught its own defect: RNG_Chance calls RNG_NextFloat and both are detoured, so a drawn word was reported twice. left_delta was never affected, which is the point of having two measurements. Gates run separately on a fresh build directory: clean_room_check OK, host ctest 55/55, CT111 shim cross-build OK. |
||
|---|---|---|
| cmake | ||
| docs | ||
| include/generated | ||
| src | ||
| tests | ||
| third_party | ||
| tools | ||
| .gitignore | ||
| CMakeLists.txt | ||
| CMakePresets.json | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| README.md | ||
sots-engine
A from-scratch, functional reimplementation of the engine behind Sword of the Stars (2006). Not a byte-for-byte decompilation: behavior-equivalent code, built up one verified piece at a time (OpenRCT2-style) until the tree can build the whole application on its own.
Bring your own game. This repository contains engine code only. Game data, assets, saves, and
the original binaries are never included; tests and tools read an owner-supplied copy via
$SOTS_DATA_DIR. See CONTRIBUTING.md for the clean-room rules.
Status
Phase 2. M0 done — the shim frontend (src/shim/, a proxy binkw32.dll the original game
loads) builds, deploys, hooks, and logs from a real game launch. Engine code accrues under
src/mars/ and src/game/; each module is oracle-verified against the owner's game data before merge:
mars/parse— brace-block +.effectreaders (1,531/1,531 files agree with the reference)mars/text— flat key/value tables, id manifests, CSV (64/64 files agree)game/sim— strategic formulas (economy, research, colonies, movement) as pure functions; 356 hand-computed checksmars/vfs—.gob(ZIP) archive reader + loose-file override; entry counts and bytes verified againstunzipmars/stream— the game's self-describing save/serialization format (reader, writer, typed shapes) + gzip; three real saves round-trip byte-identicalmars/rng— MT19937 with save-state load/store; layout confirmed against real saves, draw mappings read off the binary (docs/mars-rng.md)game/data— typed catalogs (weapons, ship sections, turrets, id registries, tech tree, strings) with cross-reference checks; 229k values agree with the referencegame/design— ship-design assembly/fit/tech-gating rules and derived stats; validates all 127 stock designs from real savesapp— the standalone:sots_turnloads a save, runs one strategic turn over the published phase order of all three turn drivers, and writes a save. 14 of the 44 turn-driver phases are modelled; every phase that is not appears in the run log as a named no-op. How far it is from the byte-match, and what stands in the way, is indocs/S-standalone.md
Build: cmake --preset host && cmake --build --preset host && ctest --preset host (Linux);
tools/sync-build.sh cross-builds the shim on the lab box and stages it for deployment.
Layout (grows with the work)
src/shim/— binkw32 proxy + hooks + old-vs-new compare harness (frontend #1)src/mars/,src/game/— the engine and game reimplementation (accruing)src/app/— the standalone turn driver (frontend #2): load a save, run a turn, write a saveinclude/generated/sots_addresses.h— binary facts (RVAs/prototypes), generated from the RE repotests/— host tests; real-data tests skip unless$SOTS_DATA_DIRis settools/— build (MinGW i686 cross) and deploy scripts
Planning, findings, and verification evidence are tracked in the private RE repo (sots-re).