unlock recipes by one rule, whatever building runs them
isRecipeUnlocked only ever meant anything for miner and assembler recipes: the traversal inserted those two and nothing else. So every caller carried the same branch -- ask the unlock state for a miner or an assembler, ask something else otherwise -- in the blueprint gate, the selection dialog, and the item tooltip's producer list, three copies of one exception. Recipe unlocking moves out of the item traversal into a pass of its own, run once the item set has settled: a recipe is unlocked when it is not a gated assembler recipe still awaiting its group, and it has an output group it could actually yield. Smelter and reprocessing recipes are judged by that too, so the question is now meaningful for all of them and the three branches collapse to one call. The two conditions stay independent on purpose. Explicit gating is about permission and outlives a wanted output -- a drop-only recipe whose output is useful anyway stays locked until it is awarded. Reprocessing still takes no part in the item traversal (REQ-BLD-REPROCESSING): it is asked in the new pass whether it can yield anything, without its yields feeding what counts as unlocked. Judging a group whole rather than per item (REQ-LOCK-OUTPUT-POOL) is what keeps a group's locked companion item from letting the whole group through. Recorded replays from before this change will not reproduce: unlocked recipe ids feed the state checksum, and smelter and reprocessing ids now join them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
@@ -162,6 +162,46 @@ TEST_CASE("RecipeSchematic: normal implicit unlock is unaffected for untagged as
|
||||
REQUIRE(sim.isRecipeUnlocked("circuit_board"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Recipe unlocking, one rule for every building (REQ-LOCK-IMPLICIT step 4)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("RecipeSchematic: a smelter recipe is unlocked once its output is wanted",
|
||||
"[recipe_schematic]")
|
||||
{
|
||||
// Smelter recipes are judged like any other now: iron_ingot's output feeds the
|
||||
// circuit board every unlocked ship needs, so the recipe is one the player can run.
|
||||
const Simulation sim(loadTestConfig());
|
||||
REQUIRE(sim.isRecipeUnlocked("iron_ingot"));
|
||||
REQUIRE(sim.isRecipeUnlocked("copper_ingot"));
|
||||
}
|
||||
|
||||
TEST_CASE("RecipeSchematic: a reprocessing recipe is unlocked by one yieldable group",
|
||||
"[recipe_schematic]")
|
||||
{
|
||||
// reprocessing_cycle can yield iron_ingot, circuit_board or advanced_alloy. The
|
||||
// first two are wanted from the start, so the recipe is runnable even though
|
||||
// advanced_alloy is not -- one group it can yield is enough (REQ-LOCK-OUTPUT-POOL).
|
||||
const Simulation sim(loadTestConfig());
|
||||
REQUIRE(sim.isRecipeUnlocked("reprocessing_cycle"));
|
||||
|
||||
// Being obtainable from the plant is not what unlocks an item, so the group the
|
||||
// plant cannot usefully yield stays locked (REQ-BLD-REPROCESSING).
|
||||
REQUIRE_FALSE(sim.isItemUnlocked("advanced_alloy"));
|
||||
}
|
||||
|
||||
TEST_CASE("RecipeSchematic: explicit gating outlives a wanted output", "[recipe_schematic]")
|
||||
{
|
||||
// The two halves of the rule are independent. quick_circuit produces circuit_board,
|
||||
// which is unlocked from the start, so it passes the yield test outright -- and must
|
||||
// still be locked, because its unlock group has not been awarded (REQ-LOCK-EXPLICIT).
|
||||
// Were recipe unlocking decided by outputs alone, blueprints and dialogs would hand
|
||||
// the player every drop-only recipe whose output happens to be wanted anyway.
|
||||
const Simulation sim(loadTestConfig());
|
||||
REQUIRE(sim.isItemUnlocked("circuit_board"));
|
||||
REQUIRE_FALSE(sim.isRecipeUnlocked("quick_circuit"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Drop pool and station destruction (REQ-DEF-SCHEMATIC-DROP)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user