AI: fetch the land colour it is actually short of - #11504
Open
liamiak wants to merge 2 commits into
Open
Conversation
Land searches picked by list order. basicManaFixing chose the basic type the player
had fewest of, then took list.get(0) from whatever survived that filter, and
getBestLandAI ended in Aggregates.random. Neither asked which colours were actually
blocking anything.
Every fetchland comes through here - areAllBasics("Plains,Island") is true - and a
"Plains" search matches every dual carrying the Plains type. Measured over 12 seeded
AI-vs-AI games (deck 260613, three seeds), basicManaFixing fires 46 times, 44 of them
with a real choice, once over 31 candidates. One observed decision offered Tundra,
Underground Sea, Volcanic Island, Tropical Island, Raffine's Tower and Ketria Triome
among others - all carrying Island, all different beside it - and it took Tundra
because Tundra was first.
getColorFixingNeed counts how many cards go from unpayable to payable if that player
had this land, across their hand and the activatable abilities on their permanents.
It reuses ComputerUtilCost.getAvailableManaColors, which already takes an "if I also
had this land" argument, and canBePaidWithAvailable.
Ordering turned out to matter more than the metric. Colour need is asked before the
basic-type count, because that count cannot tell a colour that is missing from one
that is merely uncommon: with three Islands and a hand wanting black it concluded it
needed Plains, having none, and fetched a Plains-Island. Asking first also means the
whole candidate list is still in front of it rather than the remains of a filter.
Where a measure cannot separate the candidates it returns null and the caller keeps
what it was already doing, so nothing decides while blind - evaluateLand is never
asked to rank a utility land against a basic, and the existing fallbacks stand.
Of the 44 real decisions, colour need has signal in 33 and changes the pick in 25.
Also fixes what the comment above the old call site suspected: basicManaFixing read
the decider's board while searching someone else's library. It now works from the
owner's side, and inverts every layer when an opponent is the one choosing. That
inversion is covered by a unit test but never ran in the measured games - deck 260613
has no Chooser$ cards - so it is the least exercised part of this.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Covers the decision directly and through a real Flooded Strand activation, which is how it is reached in a game: two duals both carrying the searched-for type, only one of which unblocks the hand. Also pins the two ways it declines to act - an opponent choosing gives the least useful land, and identical candidates leave the caller's own ordering alone. The fetchland case fails without the fix. Drop this commit if you would rather not carry the tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Land searches picked by list order.
basicManaFixingchose the basic type the player had fewestof, then took
list.get(0)from whatever survived that filter;getBestLandAIended inAggregates.random. Neither asked which colours were actually blocking anything.Every fetchland comes through here —
areAllBasics("Plains,Island")is true — and a "Plains" searchmatches every dual carrying the Plains type. Measured over 12 seeded AI-vs-AI games (deck 260613,
three seeds),
basicManaFixingfires 46 times, 44 with a real choice, once over 31 candidates.One observed decision,
minType=Island, offered:All carry Island; all differ beside it. It took Tundra because Tundra was first.
The metric.
getColorFixingNeedcounts how many cards go from unpayable to payable if thatplayer had this land, across their hand and the activatable abilities on their permanents. It reuses
ComputerUtilCost.getAvailableManaColors, which already takes an "if I also had this land"argument, and
canBePaidWithAvailable.Ordering turned out to matter more than the metric. Colour need is asked before the basic-type
count, because that count cannot tell a colour that is missing from one that is merely uncommon:
with three Islands and a hand wanting black, it concluded it needed Plains — having none — and
fetched a Plains-Island. Asking first also means the whole candidate list is still in front of it
rather than the remains of a filter. That is the case the fetchland test pins.
Where a measure cannot separate the candidates it returns null and the caller keeps what it was
already doing, so nothing decides while blind:
evaluateLandis never asked to rank a utility landagainst a basic (Maze of Ith scores 53, below a Forest at 106), and the existing fallbacks stand.
Result: of the 44 real decisions, colour need has signal in 33 and changes the pick in 25.
This also fixes what the comment above the old call site suspected —
basicManaFixingread thedecider's board while searching someone else's library. It now works from the owner's side and
inverts every layer when an opponent is the one choosing. To be straight about it: that inversion is
covered by a unit test but never ran in the measured games, since deck 260613 has no
Chooser$cards, so it is the least exercised part of this.
getBestAI's all-lands branch has no player in scope, so it passes null, skips the colour layer andfalls to land value — better than random, but not colour-aware. That is the Vesuva path.
Full desktop suite: 357 tests, 0 failures. The regression tests are a separate commit and can be
dropped on their own.
Written with Claude Opus 5 (also recorded in the commit co-authors).