Let the AI pay for converge and sunburst when X is the colour knob - #11485
Closed
liamiak wants to merge 1 commit into
Closed
Let the AI pay for converge and sunburst when X is the colour knob#11485liamiak wants to merge 1 commit into
liamiak wants to merge 1 commit into
Conversation
On a card whose colour count lives in a second SVar, X has one job: buy colours. The AI was not announcing it, so those cards were cast for the minimum. ComputerUtilCost.setMaxXValue ends by setting X on the ability, so it leaves X at the maximum. PermanentAi then measured its converge baseline there, which is already the best colour count available - so the first step of its walk always compared worse and X collapsed to 0. TokenAi missed differently: its X block is guarded by "X".equals(tokenAmount), so a card counting colours in Y never reached any X handling at all. Both want the same thing, so name it once as ComputerUtilMana.setXForBestConverge; PermanentAi loses ten lines to it. Effect on every card in the pool whose cost has X and where Card.hasConverge() is true, with five differently coloured lands: Engineered Explosives X=0 -> 5 (0 charge counters -> 5) Chamber Sentry X=0 -> 5 (entered as a 0/0 and died) Skyrider Elf X=0 -> 3 (entered as a 0/0 and died) Sweep the Skies none -> 4 (converge 1 -> 5) Only Engineered Explosives was flagged; the other three are in AI decks today. It is unflagged here, since casting it for X=0 was the only thing wrong with it - DestroyAllAi already matched Wrath of God's decision on every board tried. Prismatic Ending is the fifth and stays flagged. Announcing X takes its converge to 5 and it still declines: its condition reads Count$Converge, which returns the colours actually paid and so is 0 before the spell is cast. Predicting that in the condition path is separate work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tool4ever
reviewed
Aug 2, 2026
| SVar:X:Count$xPaid | ||
| SVar:Y:Count$CardCounters.CHARGE | ||
| SVar:NonStackingEffect:True | ||
| AI:RemoveDeck:All |
Contributor
There was a problem hiding this comment.
I don't think the reasoning for this was zero X since that's another regression and more like AI unable to coordinate which one is actually a smart choice
Contributor
Author
|
You're right — closing into #11486. Engineered Explosives needs board-aware counter selection rather than most-colours: its counters |
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.
On a converge or sunburst card whose colour count lives in a second SVar,
Xhas one job: buy colours. The AI was not announcing it, so those cards were cast for the minimum.ComputerUtilCost.setMaxXValueends withsa.setXManaCostPaid(x), leaving X at the maximum.PermanentAithen measured its converge baseline there:The baseline is already the best colour count available, so the first step of the walk always compared worse and X collapsed to 0.
TokenAihad a different miss: its X block is guarded by"X".equals(tokenAmount), so a card counting colours inYnever reached any X handling at all.Both want the same thing, so it is now named once -
ComputerUtilMana.setXForBestConverge- andPermanentAishrinks by 10 lines calling it.Effect
All five cards in the pool whose cost has X and for which
Card.hasConverge()is true, with five differently coloured lands untapped:Only Engineered Explosives is flagged. The other three that this fixes are in AI decks today - two of them entering as 0/0s and dying.
Edge cases behave: five Wastes gives X=0, and Plains/Plains/Island gives X=2 rather than paying for a colour already covered.
Engineered Explosives unflagged
Casting it for X=0 was the only thing wrong with it. The activated half needs nothing:
DestroyAllroutes it through the sameDestroyAllAi.doMassRemovalLogicas Wrath of God, and it matched Wrath's decision on every board I tried. Two charge counters, everything at cmc 2 so both cards hit the same permanents:It does wipe at a cost to itself when the swing justifies it, on the shared
CREATURE_EVAL_THRESHOLD- not only when it risks nothing.The flag was also self-fulfilling:
AiController.getSpellAbilityToPlayImplstrips every ability of a flagged card before evaluating anything, so "the AI never plays it" held regardless of whether its AI worked.Prismatic Ending, not fixed
Announcing X takes its converge from 1 to 5 and it still declines, so X is necessary but not sufficient there. Its condition is
ConditionPresent$ Permanent.nonLand+cmcLEY, andCount$Convergereads the colours actually paid:Before the spell is cast
getCastSA()is null, so Y is 0 andcmcLEYmatches nothing above a 0-drop. The AI'sgetConvergeCountpredicts converge by simulating payment, but the condition path uses the rules-side count; bridging the two is a separate piece of work and I have left the card flagged.DamageAllAi:30andDestroyAllAi:64have the sameX-only assumption, but no card in the pool currently reaches them through it.Testing
Two tests. Engineered Explosives plays a real turn and lands with five charge counters - that one has to go through the full
AiControllerpath, since it is the unflagging that needs proving. Sweep the Skies asserts the announced X instead, becauseTokenAigates token spells behind a random roll and a played-turn assertion on it is flaky; both assertions were run repeatedly each way.Each test fails without its own half of the change. 337 tests, 0 failures, checkstyle clean.
🤖 Implemented with the assistance of Claude Code (Opus 5).