Read one worker level where hiring read harvest and the menu read build - #256
Read one worker level where hiring read harvest and the menu read build#256Giszmo wants to merge 1 commit into
Conversation
e5b1cf6 to
c2ca5c2
Compare
|
Not a review of the change itself yet — one thing that will bite on rebase, flagging it early since you'll be rebasing anyway. The format version this claims is now taken. master is at That matters beyond the constant: the gated reads in this PR would then be So on rebase this wants 97, and both the bump and every gate that references it need to move together. #232 is currently sitting on 97 as well, so whichever of the two lands second wants 98. Worth borrowing the pattern #232 ended up with: a named constant beside master's existing ones in Happy to review the substance — the one-worker-level unification — whenever you'd like, rebased or not. The design question in it (dropping the editor's Harvest box, normalising existing maps to the higher of the two levels) doesn't depend on the rebase. |
A worker has two schooling levels that mean the same thing. Only the school raises either, it raises both in one visit (upgradeInParallel), and nothing else in the game tells them apart: the harvest level gated which building tier a worker may work for and its chop speed, the build level gated which upgrades the menu offers (Team::maxBuildLevel) and its fill speed. So the hiring gate and the upgrade button read different numbers for the same question, and the map editor offered two boxes for one value. Set apart in the editor, a unit could be allowed to upgrade a building it was then refused by. Make it one value: - Unit::workerLevel() reads it; Unit::setWorkerLevel() sets both halves and their performance together. The hiring gate, Team::maxBuildLevel and the fetch ranking read through it. - A unit loaded from a save older than the change keeps the higher of the two, so maps edited before this keep working and cannot desync on it. - A non-parallel upgrade of build or harvest raises both. - The editor keeps the build box and drops the harvest box; the unit panel drops the Harvest row, which always showed the Build value. The save format and race tables are untouched; both abilities are still stored and still drive their own speeds. A real-engine harness (test/LevelGateHarness.cpp, target level-gate-test, run in CI) checks the gate against completed buildings and sites and that a level-2 site hires build 1 with harvest 0 and refuses the reverse. Simulation behaviour can change for maps with the two levels apart, so VERSION_MINOR goes to 98 and replays older than that are refused. The number lives beside master's other save-format gates as FILE_FORMAT_VERSION_ONE_WORKER_LEVEL in src/FileFormatVersions.h, and the load-time evening-out reads it, so the next time master moves there is one place to change and a grep that finds it. Opus 5 helped authoring this commit.
c2ca5c2 to
abb97f5
Compare
|
Rebased onto master and renumbered — thanks for flagging it before it bit. Two adjustments to your note, then what I did. It wants 98, not 97. #232 has landed (95c6a60), so master already holds 97 as The desync mechanism you describe doesn't apply to this PR. It adds no version-gated reads and no new fields to the save stream. The only serialization it touched was one ungated in-memory normalisation at the end of Took the named-constant point anyway, and gave it something to hold. //! Harvest and build became one worker level. Saves before this could hold the
//! two apart — the map editor offered a box for each — so the loader evens a
//! worker out to the higher of the two (UnitSerialization.cpp:90).
static constexpr int FILE_FORMAT_VERSION_ONE_WORKER_LEVEL = 98;and the load-time evening-out is now gated on it rather than running unconditionally: if (versionMinor < FILE_FORMAT_VERSION_ONE_WORKER_LEVEL
&& canLearn[BUILD] && level[HARVEST] != level[BUILD])
setWorkerLevel(std::max(level[HARVEST], level[BUILD]));That is safe because after this change nothing leaves the two apart in a save at 98 or later: every school tier has Also updated Verified locally on the rebased head before pushing: The substance is unreviewed and the design question you raised — dropping the editor's Harvest box, normalising existing maps to the higher of the two — is untouched by the rebase, so it is still open whenever you want to look. |
Marked as a bugfix on Leo's call; #255 (any worker stocks completed buildings) will sit on top of this.
Bug
A worker carries two schooling levels,
level[HARVEST]andlevel[BUILD], for one concept. Only the school raises either, and it raises both in the same visit (upgradeInParallel), so in play they are always equal. The code, however, reads them inconsistently:Building::canUnitWorkHere)Team::maxBuildLevel, upgrade button)bringResourcesLevel)The editor exposes both as separate boxes, and the unit panel shows two rows with the same number. A map with the two set apart can offer an upgrade the colony's workers are then refused for.
Real-engine run on master, one hiring pass, worker four tiles from a level-2 inn site carrying wood:
harvest=0 build=1→ refused (UnitTooLowLevel),harvest=1 build=0→ hired. The upgrade menu would say the opposite.Fix
Unit::workerLevel()is the one read;Unit::setWorkerLevel()sets both halves and their performance together.Team::maxBuildLeveland the fetch ranking read through it.VERSION_MINOR→ 96, replay floor with it.Verification
level-gate-testharness (new, run in CI): tier gate on completed inns and sites, plusbuild=1, harvest=0hired by a level-2 site andbuild=0, harvest=1refused.TestsRunner(187).🤖 Generated with Claude Code