The tail's phase 34 sweeps every player over every ship of every fleet and
records the design of each ship it can see. Three of the recorder's rules are
invisible from a save and every one of them changes the answer:
* the lookup key is the DESIGN ID ALONE, not the (design, owner) pair;
* a re-observation ERASES the record and PUSHES A COPY ON THE BACK rather than
updating in place, so the list ends in last-observation order and the record's
first-seen turn survives the move. This is why a turn's output is a
PERMUTATION of its input and not an append -- which is what made the group
look like 55 unrelated leaves;
* the list is CAPPED AT 20 RECORDS PER DESIGN OWNER, counted from the most
recent end, and the cap is applied after EVERY record call rather than once
per sweep. On an empire with more than twenty designs in service that thrashes
inside the one sweep: records are evicted and re-created, and a re-created
record's first-seen turn is reset.
A fourth rule is a guard on the DESIGN'S OWNER and not on the observer: a design
owned by an NPC that is not a rebel AI is never observed by anyone. Every
observation record in every corpus save agrees -- the NPC factions' 26 designs
appear in nobody's list -- and removing the guard costs 9 leaves on the canonical
pair while costing nothing on the rich turn, so the two pairs test different rules
and both were run.
TWO THINGS ARE NOT MODELLED AND BOTH ARE NAMED IN THE CATALOG TEXT. The gate is a
two-bit-per-player word on the ship that is NOT serialised; this phase stands it
in with ownership, which is the smallest rule correct on every state the corpus
holds, because on both reference pairs no player observes another player's ship.
That is a hypothesis with a cheap falsifier and it is labelled as one. And the
phase's tech and weapon arms are not implemented: the original feeds the design
through three set builders into the observed-tech and observed-weapon lists, and
those builders are not decoded.
Measured, closed and regressed never netted:
canonical pair turn2 -> turn3 62 -> 61 leaves 1 closed / 0 regressed
rich turn ad-turn27 -> pinB 1092 -> 1058 36 closed / 2 regressed
The 2 are two `otnF` words at positions whose `odid` also moves, i.e. positions
that now hold a different record; and the 21 design leaves that remain are the
shadow of ship construction, not of this phase -- two designs receive their first
ships during that turn and no phase here builds a ship. Fed the true post-turn
ship list, the same code leaves 1 leaf of 55.
Host build 255/255; host ctest 57/59 with the two pre-existing corpus-writer
failures unchanged (12 of 43 saves, the SpecialProjectNameGen `usp` item, not
this lane's); shim cross-build green; clean-room and shim-config checks green.
36 lines
1.3 KiB
CMake
36 lines
1.3 KiB
CMake
# src/app — the standalone: load a save, run one strategic turn, write a save.
|
|
# Included from the root CMakeLists.txt via add_subdirectory(src/app).
|
|
#
|
|
# The turn logic is a library so the test can drive it in process; `sots_turn` is the CLI.
|
|
|
|
add_library(sots_app STATIC
|
|
alliance.cpp
|
|
phase_catalog.cpp
|
|
trade_raid.cpp
|
|
treaty.cpp
|
|
turn_record.cpp
|
|
construction_phase.cpp
|
|
event_phase.cpp
|
|
growth_phase.cpp
|
|
observed_phase.cpp
|
|
script_phase.cpp
|
|
visibility_phase.cpp
|
|
command_replay.cpp
|
|
turn.cpp
|
|
report.cpp)
|
|
target_include_directories(sots_app PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
|
# game_design (and game_data under it) is here for one phase only: the tail's turn record
|
|
# needs a design's hull size and defence-platform flag, which are recomputed from the section
|
|
# catalog and are nowhere on the wire. No game data is embedded; the root is supplied at run
|
|
# time and its absence costs exactly six fields.
|
|
target_link_libraries(sots_app PUBLIC mars_stream mars_rng sots_game_sim sots_game_events sots_game_ai game_design)
|
|
target_compile_features(sots_app PUBLIC cxx_std_17)
|
|
if(NOT MSVC)
|
|
target_compile_options(sots_app PRIVATE -Wall -Wextra -Werror)
|
|
endif()
|
|
|
|
add_executable(sots_turn main.cpp)
|
|
target_link_libraries(sots_turn PRIVATE sots_app)
|
|
if(NOT MSVC)
|
|
target_compile_options(sots_turn PRIVATE -Wall -Wextra -Werror)
|
|
endif()
|