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.
34 lines
1.4 KiB
CMake
34 lines
1.4 KiB
CMake
# Strategic-layer formulas as pure functions (no game state, no I/O).
|
|
# Not yet wired into the root CMakeLists; add_subdirectory(src/game/sim) when the
|
|
# host build grows a game target. tests/game_sim/build_and_run.sh builds the same
|
|
# sources with plain g++ in the meantime.
|
|
add_library(sots_game_sim STATIC
|
|
economy.cpp
|
|
construction.cpp
|
|
research.cpp
|
|
colony.cpp
|
|
movement.cpp
|
|
visibility.cpp
|
|
observed.cpp
|
|
scriptobjects.cpp
|
|
techgraph.cpp
|
|
player_turn.cpp)
|
|
target_include_directories(sots_game_sim PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
|
target_compile_features(sots_game_sim PUBLIC cxx_std_17)
|
|
if(NOT MSVC)
|
|
target_compile_options(sots_game_sim PRIVATE -Wall -Wextra)
|
|
endif()
|
|
|
|
option(SOTS_GAME_SIM_TESTS "Build the game/sim unit tests" OFF)
|
|
if(SOTS_GAME_SIM_TESTS)
|
|
enable_testing()
|
|
set(_sim_tests economy research colony movement techgraph visibility observed construction player_turn scriptobjects)
|
|
foreach(_t IN LISTS _sim_tests)
|
|
add_executable(game_sim_test_${_t} ${CMAKE_CURRENT_SOURCE_DIR}/../../../tests/game_sim/test_${_t}.cpp)
|
|
target_link_libraries(game_sim_test_${_t} PRIVATE sots_game_sim)
|
|
add_test(NAME game_sim_${_t} COMMAND game_sim_test_${_t})
|
|
endforeach()
|
|
add_executable(game_sim_smoke_save ${CMAKE_CURRENT_SOURCE_DIR}/../../../tests/game_sim/smoke_real_save.cpp)
|
|
target_link_libraries(game_sim_smoke_save PRIVATE sots_game_sim)
|
|
add_test(NAME game_sim_smoke_save COMMAND game_sim_smoke_save)
|
|
endif()
|