Fix stranded-terminal recovery on a half-solved field - #88
Merged
Conversation
Two bugs in the same recovery path, found while investigating why big-list blueprint 227 stops planning under Factorio 2.1 terminal offsets. 1. The recovery ran on a mutated clone. GetBestSolution swaps context.CenterToTerminals for a per-strategy clone and mutates it, and does not put the originals back when a strategy fails. SelectBestSolution then called EliminateStrandedTerminals on whatever was left, so the recovery reasoned about a half-solved field rather than the real one. Measured on blueprint 227: the recovery saw 47 terminal locations where the field actually has 82. Two pumpjacks looked unreachable purely because the failed attempt had already pruned their terminals, and eliminating what looked like a pocket stranded them. Restoring the originals first makes the recovery see all 82, split them into components of 76, 3 and 3, and find all 23 pumpjacks in the largest. Blueprint 227 plans again. The 82 is not just an internal number agreeing with itself. An independent flood fill over the raw pumpjack geometry counted 82 free terminal cells, which is what says the restored view is the true one. 2. EliminateStrandedTerminals kept the wrong component. It walked one component and, if that component did not cover every pumpjack, assumed it was a stranded pocket and eliminated it. That only holds when the component it happened to walk first is the minority. On blueprint 227 the first walk reached 43 of 47 terminals covering 21 of 23 pumpjacks, and the old code eliminated all 43 - throwing away the main network to keep a two-pumpjack pocket, stranding 19 pumpjacks in one step. Now it enumerates every component and keeps the one serving the most pumpjacks, which makes the choice independent of where the walk started. What each change costs, measured separately rather than assumed: - The component fix changes nothing. The branch that got it wrong fires zero times across all 1147 big-list blueprints, and on its own it leaves every Verify snapshot untouched. - The restore fix changes two snapshots, both in AllowsBlueprintWithNonBlockingIsolatedArea, which is the test that exercises this path by name. Both selected plans get better: CC-DT goes from 114 to 116 beacon effects, and CC-FLUTE drops 4 pipes at equal effects and beacons. An ablation confirms the split: the restore fix alone makes blueprint 227 pass, so the component fix is defensive rather than load-bearing. It is included because it is wrong on its own terms and free to correct. Full suite passes 4299 of 4299. src/lua regenerated; tools/check-lua.sh passes both the Lua 5.2.4 syntax check and the sample run. Builds clean under /p:UseLuaSettings=true. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P9FADuTnjE7SFEQWnpNhfc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two bugs in the same recovery path, found while investigating why big-list blueprint 227 stops planning under the Factorio 2.1 terminal offsets (#81).
1. The recovery ran on a mutated clone
GetBestSolutionswapscontext.CenterToTerminalsfor a per-strategy clone and mutates it, and does not put the originals back when a strategy fails.SelectBestSolutionthen calledEliminateStrandedTerminalson whatever was left, so the recovery reasoned about a half-solved field rather than the real one.Measured on blueprint 227:
Two pumpjacks looked unreachable purely because the failed attempt had already pruned their terminals.
That 82 is not an internal number agreeing with itself. An independent flood fill over the raw pumpjack geometry counted 82 free terminal cells, which is what says the restored view is the true one.
2. EliminateStrandedTerminals kept the wrong component
It walked one component and, if that component did not cover every pumpjack, assumed it was a stranded pocket and eliminated it. That only holds when the component it happened to walk first is the minority one.
On blueprint 227 the first walk reached 43 of 47 terminals covering 21 of 23 pumpjacks, and the old code eliminated all 43 - throwing away the main network to keep a two-pumpjack pocket, stranding 19 pumpjacks in a single step.
It now enumerates every component and keeps the one serving the most pumpjacks, which makes the choice independent of where the walk started.
What each change costs, measured separately
AllowsBlueprintWithNonBlockingIsolatedArea- the test that exercises this path by name.Both selected plans in those two snapshots get better:
Selection ranks on effects, then fewest beacons, then fewest pipes. CC-DT wins on the primary criterion; CC-FLUTE ties and drops 4 pipes.
Score.HasExpectedScoreis unchanged.An ablation, so the two are not conflated
The restore fix alone makes blueprint 227 pass. So the component fix is defensive rather than load-bearing. It is included because it is wrong on its own terms and free to correct, not because 227 needs it.
Checks
dotnet test: 4299 passed, 0 failed.dotnet build /p:UseLuaSettings=true: clean.src/luaregenerated and committed;tools/check-lua.shpasses both the Lua 5.2.4 syntax check and thesample.luarun.Relationship to the other work
This is the second of two latent planner bugs that the 2.1 terminal offsets expose. The first is the
Group.Locationcentroid collision in #87. Both are prerequisites for landing #81, and both are separated out so a subtle logic fix does not land inside a 2743-file snapshot diff.🤖 Generated with Claude Code
https://claude.ai/code/session_01P9FADuTnjE7SFEQWnpNhfc