Repository navigation
[agent-loop: claude-opus-5-5] Minimum count on graveyard exile-X costs for Dragons of Tarkir - #4695
Merged
Merged
Conversation
…eft (DTK)
"Exile one or more creature cards from your graveyard" is ExileXFromGraveyard under the
ability's existing minimumXValue = 1. The no-{X} path now floors the selection at the
minimum, keeps prompting when candidates exactly meet it (X is bound by the pick), greys
the ability out / rejects it without enough matching cards, and rejects a smaller submitted
pile. AI: exile-X graveyard costs read as graveyard payoffs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review: an ActivateAbility carrying exiledCards but no xValue paid X = 0 and exiled
nothing (Corpseweft made a 0/0 for {1}{B}). Tests now reach that branch; doc wording
and stray KDoc fixed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
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.
Closes DTK gap G8 — minimum count on the variable graveyard exile-X cost ("Exile one or more creature cards from your graveyard"). Unlocks Corpseweft (G8's only card), shipped here.
What it does
No new SDK type. The cost is the existing
Costs.ExileXFromGraveyard(filter)under the activated ability's existingminimumXValue = 1(until now it was honoured only for X paid in{X}mana). With no{X}mana, where X is the size of the graveyard selection:ActivationChoicePauses):minSelectionsis floored atminimumXValue. It still prompts when the candidates exactly meet the floor, so X is bound by the pick and never paid silently as 0. Prompt: "Select 1 or more cards to exile…".ActivatedAbilityEnumeratormarks the ability unpayable (greyed out; omitted when the exile is the whole cost) while fewer matching cards are in the graveyard.ActivationValidator.checkExileXSelectionrejects it engine-direct too.ActivateAbilitywhoseexiledCardsdon't match itsxValueis rejected. Before,exiledCardswith noxValuepaid X = 0 and exiled nothing.CostEnumerationUtils.exileXCandidateCountis shared by the enumerator's floor and themaxAffordableXcap.Costs.ExileXFromGraveyard,minimumXValue) and theminimumXValueKDoc.Cards
{1}{B}, ExileXFromGraveyard(Creature),minimumXValue = 1, a tapped black Zombie Horror token sizedxValue * 2.CorpseweftScenarioTestcovers the 2-card case (4/4, tapped, creature cards only), an empty graveyard (greyed out and rejected), one candidate (still prompts, 2/2), and a pre-filled pile with no X (rejected).Tests
ExileXMinimumCountTest(engine) uses a floor of 2 to show the floor is general. It covers: not enumerated/rejected below the floor; selection floored with X = the count; prompts at exactly the floor; a pile below the floor rejected; a pre-filled pile with a mismatched X rejected, with or without a floor; floor 0 keeps the old any-number behaviour (Winter, Cursed Rider).ExileXGraveyardCostReadingAiTest(AI).AI
AI: reads 1/1 · pick 1.6 (DTK table) · intent Makes tokens, activated (+3.0 in play) · synergy feeds tokens/creatures enter/death, rewards graveyardGraveyardSynergydidn't readAbilityCost.ExileXFromGraveyardas a graveyard payoff (Corpseweft, Winter, Cursed Rider, Necropolis Fiend). It does now, pinned byExileXGraveyardCostReadingAiTest, with anai/changelog.d/loop-dtk-exile-x-min.mdentry.Gate
just loop-gate --reblesspassed on the first head. Only the DTK golden moved (Corpseweft added).AbandonReasonScenarioTest,CastFromCollectionAdditionalManaCostTest,SealedDeckGeneratorTest) and 3 AI assertion flakes (ChooseActionReadingAiTest,RepeatableProducerAiTest,ArenaHarnessTest). Each of these exceptSealedDeckGeneratorTestpassed when re-run alone withjust test-class;SealedDeckGeneratorTestwas a plain timeout and was not re-run. All 10 of this PR's new cases passed. CI runs the full suite.just assay-differential: unchanged, 8788 compared / 111 divergent. Assay declines Corpseweft's line, so a band for "exile one or more … from your graveyard" is new vocabulary forassay-report --rank tail.just check-card-printing "Corpseweft": canonical in DTK.Manual UI check
Headless Chromium against
just ui-dev:(Screenshots are hosted on the throwaway branch
loop-dtk-exile-x-min-screenshots.) The flow put the ability on the stack with X=2.Review (split mode, fresh-context: triage → engine + cards reviewers → weigh)
xValuepaid X = 0. The fix is thexValue == pile sizecheck, with tests that now reach it (the earlier "rejected" tests were caught by the older X-below-minimum check).hasPlayerChosenNonManaXand its KDoc, and the stray "Calculate max affordable X" KDoc is now oncalculateMaxAffordableX.CostHandler.findMatchingCardsUnified, the enumerator the new helper). Both use the same projected state, context and filter, and they agree today.Nothing was play-tested beyond the manual UI check above.
🤖 Generated with Claude Code