Stop the AI seeking a card its library cannot supply - #11448
Open
omraj21 wants to merge 2 commits into
Open
Conversation
Seek was mapped to AlwaysPlayAi, which accepts every activation without looking
at the board. SeekEffect builds a pool from the library filtered by the seek
type, and when that pool is empty it just skips the type:
if (pool.isEmpty()) {
...
continue; // can't find if nothing to seek
}
The cost has already been paid by then. Runecarved Obelisk taps and sacrifices
itself to seek a card whose mana value is at most the number of charge counters
on it, so with no counters on it the AI sacrificed the artifact and got nothing.
A test with the old mapping shows it going from one copy on the battlefield to
zero.
Add SeekAi, which mirrors how SeekEffect builds the pool and declines when no
seek type can find anything.
Types whose filter depends on what the cost sacrifices are deliberately left
alone. Spawning Pod seeks Creature.cmcEQX where X is Sacrificed$CardManaCost
plus one, which cannot be resolved before the cost is paid, so guessing there
would stop the AI using the card at all. Those are treated as findable, which
keeps the previous behaviour for them - verified by comparing Spawning Pod
activations with and without this change.
forge.ai.** test suite: 247 tests, 0 failures.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Agetian
approved these changes
Jul 31, 2026
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.
Seekis mapped toAlwaysPlayAi, whose entire logic isreturn WillPlay— it never looks at the board.SeekEffectbuilds a pool from the library filtered by the seek type, and when that pool is empty it simply skips the type:The cost has already been paid by that point. Runecarved Obelisk pays it with the card itself:
With no charge counters nothing in the library can match, so the AI sacrificed the artifact for nothing. The added test shows it going from one copy on the battlefield to zero under the old mapping.
The fix
SeekAimirrors howSeekEffectbuilds its pool (including theDefinedCardsvariant) and declines when no seek type can find anything.Cost-dependent types are deliberately left alone
Spawning Pod seeks
Creature.cmcEQXwhereSVar:X:Sacrificed$CardManaCost/Plus.1— the filter depends on which creature the cost sacrifices, so it cannot be resolved before the cost is paid. Guessing there would make the AI stop using the card entirely, which would be a worse bug than the one being fixed.So any type whose
X/Y/Zresolves to aSacrificed$SVar is treated as findable, preserving the old behaviour. I verified this by running Spawning Pod activations with and without the change and getting identical results.Verification
doesNotSacrificeItselfSeekingAnEmptyPool— the regression; fails withRunecarved Obelisk should not have been sacrificed expected:<1> but was:<0>without the fixseeksWhenTheLibraryCanAnswer— with 6 charge counters it still sacrifices and draws, so the guard does not over-declineforge.ai.**test suite: 247 tests, 0 failures. Fullmvn -U -B clean testacross all 12 modules passes.Written with the help of GitHub Copilot CLI; the commit carries a
Co-authored-bytrailer for it.