AI: include ProduceMana in the performance-mode replacement zone skip#11327
Merged
Agetian merged 1 commit intoJul 24, 2026
Merged
Conversation
getReplacementList visits every card in the game. For the mana hot path that means rebuilding the replacement-effect list of ~1700 cards to find the handful that could ever apply, and it runs per mana source per AI cost check. The existing performance-mode skip already covers Tap/Untap on the grounds that those replacements are only active from the battlefield or the command zone. The same holds for ProduceMana: of the 25 ProduceMana replacement effects in cardsfolder, 23 declare ActiveZones and every one of those is Battlefield and/or Command. The two that do not declare zones (False Dawn, Quarum Trench Gnomes) are both hosted on Effect cards, which live in the command zone. Measured over 3 headless 4-player games (per-call, since game length varies between runs): Tap 2788.6 -> 194.4 us/scan ProduceMana 2749.2 -> 178.7 us/scan replacement-effect list rebuilds per scan: 1681 -> 34 Tap was already covered; ProduceMana is what this change adds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hanmac
approved these changes
Jul 23, 2026
tool4ever
approved these changes
Jul 23, 2026
tool4ever
left a comment
Contributor
There was a problem hiding this comment.
ok as temporary workaround
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.
getReplacementListvisits every card in the game. On the mana hot path that means rebuilding the replacement-effect list of ~1700 cards to find the handful that could ever apply — and it runs per mana source, per AI cost check.The performance-mode zone skip added in #11160 already covers Tap/Untap, on the grounds that those replacements are only active from the battlefield or the command zone. This extends the same skip to
ProduceMana, whichgroupSourcesByManaColorchecks per mana ability on top of the Tap checks.Why ProduceMana qualifies
Survey of
forge-gui/res/cardsfolder:Event$ ProduceManareplacement-effect linesActiveZones— every one isBattlefieldand/orCommandSP$/AB$ Effect | ReplacementEffects$ ..., i.e. hosted on Effect cards, which live in the command zoneSo no ProduceMana replacement effect in the card database is active outside battlefield/command — the same justification that licensed Tap/Untap.
Measurements
3 headless 4-player games, "Big 240531" mirror. Normalised per call, since sims aren't deterministic and game length varies between runs:
Tap was already covered by #11160; ProduceMana is what this change adds. The traversal itself is unchanged — this only avoids the per-card
getReplacementEffects()rebuild, which measured as ~78% of the scan cost.Note
While measuring this I found that the skip never fires by default:
PERFORMANCE_MODEdefaults tofalse, so #11160's optimisation is inert for most users and is not exercised by CI. That's a separate discussion and I'll open it separately rather than bundle it here.Edit/note from actual human: It seems claude (opus 4.8) is missing the note on identifying AI-generated code in this context window, so I'm adding it manually. We're both trying to find the right balance of small PRs vs optimization wins, and we're both having fun (for likely quite different values of fun) getting our head around the engine, and the norms desired by the forge community - hope this help, and happy to shift if this is too much of a pain/distraction from the eternal grind of new sets, but also thrilled to maybe be able to help with something that's brought me much joy!