Skip to content

AI: include ProduceMana in the performance-mode replacement zone skip#11327

Merged
Agetian merged 1 commit into
Card-Forge:masterfrom
liamiak:speed-up-mana-replacement-scan
Jul 24, 2026
Merged

AI: include ProduceMana in the performance-mode replacement zone skip#11327
Agetian merged 1 commit into
Card-Forge:masterfrom
liamiak:speed-up-mana-replacement-scan

Conversation

@liamiak

@liamiak liamiak commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

getReplacementList visits 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, which groupSourcesByManaColor checks per mana ability on top of the Tap checks.

Why ProduceMana qualifies

Survey of forge-gui/res/cardsfolder:

  • 25 Event$ ProduceMana replacement-effect lines
  • 23 declare ActiveZones — every one is Battlefield and/or Command
  • the 2 that don't (False Dawn, Quarum Trench Gnomes) are both SP$/AB$ Effect | ReplacementEffects$ ..., i.e. hosted on Effect cards, which live in the command zone

So 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:

before after
Tap scan 2788.6 µs 194.4 µs
ProduceMana scan 2749.2 µs 178.7 µs
RE-list rebuilds per scan 1681 34

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_MODE defaults to false, 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!

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
Hanmac requested a review from tool4ever July 23, 2026 05:17

@tool4ever tool4ever left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok as temporary workaround

@Agetian
Agetian merged commit 039324b into Card-Forge:master Jul 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants