- Improved support for Illusions-Donate, added deck The Great and Powerful Trixie 2, changed the deck The Great and Powerful Trixie 3 to be a more standard Legacy-legal Trix.

git-svn-id: http://svn.slightlymagic.net/forge/trunk@35719 269b9781-a132-4a9b-9d4e-f004f1b56b58
This commit is contained in:
Agetian 2017-09-23 09:04:16 +00:00
parent d3bfe5a0b2
commit 5e7442af9d
13 changed files with 124 additions and 33 deletions

View File

@ -881,6 +881,9 @@ public class AiController {
}
if (prefCard == null) {
prefCard = ComputerUtil.getCardPreference(player, sourceCard, "DiscardCost", validCards);
if (prefCard != null && prefCard.hasSVar("DoNotDiscardIfAble")) {
prefCard = null;
}
}
if (prefCard != null) {
discardList.add(prefCard);
@ -917,13 +920,29 @@ public class AiController {
if (numLandsInHand > 0) {
numLandsAvailable++;
}
//Discard unplayable card
if (validCards.get(0).getCMC() > numLandsAvailable) {
discardList.add(validCards.get(0));
validCards.remove(validCards.get(0));
boolean discardedUnplayable = false;
for (int j = 0; j < validCards.size(); j++) {
if (validCards.get(j).getCMC() > numLandsAvailable && !validCards.get(j).hasSVar("DoNotDiscardIfAble")) {
discardList.add(validCards.get(j));
validCards.remove(validCards.get(j));
discardedUnplayable = true;
break;
} else if (validCards.get(j).getCMC() <= numLandsAvailable) {
// cut short to avoid looping over cards which are guaranteed not to fit the criteria
break;
}
}
else { //Discard worst card
if (!discardedUnplayable) {
// discard worst card
Card worst = ComputerUtilCard.getWorstAI(validCards);
if (worst == null) {
// there were only instants and sorceries, and maybe cards that are not good to discard, so look
// for more discard options
worst = ComputerUtilCard.getCheapestSpellAI(validCards);
}
discardList.add(worst);
validCards.remove(worst);
}

View File

@ -94,9 +94,10 @@ public enum AiProps { /** */
BOUNCE_ALL_TO_HAND_CREAT_EVAL_DIFF ("200"), /** */
BOUNCE_ALL_ELSEWHERE_CREAT_EVAL_DIFF ("200"), /** */
BOUNCE_ALL_TO_HAND_NONCREAT_EVAL_DIFF ("3"), /** */
BOUNCE_ALL_ELSEWHERE_NONCREAT_EVAL_DIFF ("3"), /** */
BOUNCE_ALL_ELSEWHERE_NONCREAT_EVAL_DIFF ("3"),
INTUITION_ALTERNATIVE_LOGIC ("false"); /** */
// Experimental features, must be removed after extensive testing and, ideally, defaulting
INTUITION_SPECIAL_LOGIC ("false"); /** */
// <-- There are no experimental options here -->
private final String strDefaultVal;

View File

@ -350,7 +350,12 @@ public class ComputerUtilCard {
}
if (hasEnchantmants || hasArtifacts) {
final List<Card> ae = CardLists.filter(list, Predicates.<Card>or(CardPredicates.Presets.ARTIFACTS, CardPredicates.Presets.ENCHANTMENTS));
final List<Card> ae = CardLists.filter(list, Predicates.and(Predicates.<Card>or(CardPredicates.Presets.ARTIFACTS, CardPredicates.Presets.ENCHANTMENTS), new Predicate<Card>() {
@Override
public boolean apply(Card card) {
return !card.hasSVar("DoNotDiscardIfAble");
}
}));
return getCheapestPermanentAI(ae, null, false);
}
@ -363,6 +368,28 @@ public class ComputerUtilCard {
return getCheapestPermanentAI(list, null, false);
}
public static final Card getCheapestSpellAI(final Iterable<Card> list) {
if (!Iterables.isEmpty(list)) {
CardCollection cc = CardLists.filter(new CardCollection(list),
Predicates.or(CardPredicates.isType("Instant"), CardPredicates.isType("Sorcery")));
Collections.sort(cc, CardLists.CmcComparatorInv);
Card cheapest = cc.getLast();
if (cheapest.hasSVar("DoNotDiscardIfAble")) {
for (int i = cc.size() - 1; i >= 0; i--) {
if (!cc.get(i).hasSVar("DoNotDiscardIfAble")) {
cheapest = cc.get(i);
break;
}
}
}
return cheapest;
}
return null;
}
public static final Comparator<Card> EvaluateCreatureComparator = new Comparator<Card>() {
@Override
public int compare(final Card a, final Card b) {

View File

@ -537,7 +537,7 @@ public class SpecialCardAi {
public static class Intuition {
public static CardCollection considerMultiple(final Player ai, final SpellAbility sa) {
if (ai.getController().isAI()) {
if (!((PlayerControllerAi) ai.getController()).getAi().getBooleanProperty(AiProps.INTUITION_SPECIAL_LOGIC)) {
if (!((PlayerControllerAi) ai.getController()).getAi().getBooleanProperty(AiProps.INTUITION_ALTERNATIVE_LOGIC)) {
return new CardCollection(); // fall back to standard ChangeZoneAi considerations
}
}
@ -556,14 +556,14 @@ public class SpecialCardAi {
cardAmount.add(c.getName());
}
// Trix: see if we can complete the combo (if it looks like we might win shortly)
// Trix: see if we can complete the combo (if it looks like we might win shortly or if we need to get a Donate stat)
boolean donateComboMightWin = false;
if (ai.getOpponentsSmallestLifeTotal() <= 20) {
int numIllusionsOTB = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Illusions of Grandeur")).size();
if (ai.getOpponentsSmallestLifeTotal() < 20 || numIllusionsOTB > 0) {
donateComboMightWin = true;
int numIllusionsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals("Illusions of Grandeur")).size();
int numDonateInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals("Donate")).size();
int numIllusionsInLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.nameEquals("Illusions of Grandeur")).size();
int numIllusionsOTB = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Illusions of Grandeur")).size();
int numDonateInLib = CardLists.filter(ai.getCardsIn(ZoneType.Library), CardPredicates.nameEquals("Donate")).size();
CardCollection comboList = new CardCollection();
if ((numIllusionsInHand > 0 || numIllusionsOTB > 0) && numDonateInHand == 0 && numDonateInLib >= 3) {

View File

@ -164,3 +164,9 @@ BOUNCE_ALL_ELSEWHERE_CREAT_EVAL_DIFF=200
# on both side of the battlefield
BOUNCE_ALL_TO_HAND_NONCREAT_EVAL_DIFF=3
BOUNCE_ALL_ELSEWHERE_NONCREAT_EVAL_DIFF=3
# If enabled, the AI will try to pair up cards to present to the opponent so that a specific card may be picked,
# it'll also try to grab Accumulated Knowledge and Take Inventory more actively, as well as interact with the Trix
# combo deck more appropriately. In Reanimator decks, this logic will make the AI pick the fattest threats in the
# library to put some into the graveyard.
INTUITION_ALTERNATIVE_LOGIC=true

View File

@ -165,3 +165,8 @@ BOUNCE_ALL_ELSEWHERE_CREAT_EVAL_DIFF=200
BOUNCE_ALL_TO_HAND_NONCREAT_EVAL_DIFF=3
BOUNCE_ALL_ELSEWHERE_NONCREAT_EVAL_DIFF=3
# If enabled, the AI will try to pair up cards to present to the opponent so that a specific card may be picked,
# it'll also try to grab Accumulated Knowledge and Take Inventory more actively, as well as interact with the Trix
# combo deck more appropriately. In Reanimator decks, this logic will make the AI pick the fattest threats in the
# library to put some into the graveyard.
INTUITION_ALTERNATIVE_LOGIC=true

View File

@ -165,11 +165,14 @@ BOUNCE_ALL_ELSEWHERE_CREAT_EVAL_DIFF=400
BOUNCE_ALL_TO_HAND_NONCREAT_EVAL_DIFF=5
BOUNCE_ALL_ELSEWHERE_NONCREAT_EVAL_DIFF=5
# If enabled, the AI will try to pair up cards to present to the opponent so that a specific card may be picked,
# it'll also try to grab Accumulated Knowledge and Take Inventory more actively, as well as interact with the Trix
# combo deck more appropriately. In Reanimator decks, this logic will make the AI pick the fattest threats in the
# library to put some into the graveyard.
INTUITION_ALTERNATIVE_LOGIC=true
# -- Experimental feature toggles which only exist until the testing procedure for the relevant --
# -- features is over. These toggles will be removed later, or may be reintroduced under a --
# -- different name if necessary --
# Experimental logic for Intuition that makes it work better in reanimator decks, combo decks like Trix,
# and generally tries to either grab cards that are also good to put in the graveyard or that are available
# in multiples in the deck.
INTUITION_SPECIAL_LOGIC=true
# <-- there are no options here at the moment -->

View File

@ -164,3 +164,9 @@ BOUNCE_ALL_ELSEWHERE_CREAT_EVAL_DIFF=200
# on both side of the battlefield
BOUNCE_ALL_TO_HAND_NONCREAT_EVAL_DIFF=3
BOUNCE_ALL_ELSEWHERE_NONCREAT_EVAL_DIFF=3
# If enabled, the AI will try to pair up cards to present to the opponent so that a specific card may be picked,
# it'll also try to grab Accumulated Knowledge and Take Inventory more actively, as well as interact with the Trix
# combo deck more appropriately. In Reanimator decks, this logic will make the AI pick the fattest threats in the
# library to put some into the graveyard.
INTUITION_ALTERNATIVE_LOGIC=true

View File

@ -7,5 +7,6 @@ SVar:D2:DB$ Pump | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target perma
SVar:D3:DB$ GainControl | Defined$ Targeted | NewController$ Remembered | SubAbility$ D4
SVar:D4:DB$ Cleanup | ClearRemembered$ True
SVar:RemRandomDeck:True
SVar:DoNotDiscardIfAble:TRUE
SVar:Picture:http://www.wizards.com/global/images/magic/general/donate.jpg
Oracle:Target player gains control of target permanent you control.

View File

@ -4,12 +4,13 @@ Types:Enchantment
K:Cumulative upkeep:2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 20 life.
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigLoseLife | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME leaves the battlefield, you lose 20 life.
SVar:TrigGainLife:AB$GainLife | Cost$ 0 | Defined$ TriggeredCardController | LifeAmount$ 20
SVar:TrigLoseLife:AB$LoseLife | Cost$ 0 | Defined$ TriggeredCardController | LifeAmount$ 20
SVar:TrigGainLife:DB$ GainLife | Defined$ TriggeredCardController | LifeAmount$ 20
SVar:TrigLoseLife:DB$ LoseLife | Defined$ TriggeredCardController | LifeAmount$ 20
SVar:AICastPreference:MustHaveInHand$ Donate | MaxControlled$ 1 | NumManaSourcesNextTurn$ 5 | AlwaysCastIfLifeBelow$ 4
SVar:RemRandomDeck:True
SVar:DeckNeeds:Name$Donate
SVar:DonateMe:5
SVar:PlayMain1:TRUE
SVar:DoNotDiscardIfAble:TRUE
SVar:Picture:http://www.wizards.com/global/images/magic/general/illusions_of_grandeur.jpg
Oracle:Cumulative upkeep {2} (At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it.)\nWhen Illusions of Grandeur enters the battlefield, you gain 20 life.\nWhen Illusions of Grandeur leaves the battlefield, you lose 20 life.

View File

@ -0,0 +1,27 @@
[duel]
[metadata]
Name=The Great and Powerful Trixie 2
Title=The Great and Powerful Trixie
Difficulty=hard
Description=U splash W Trix combo deck with Illusions of Grandeur and Donate
Icon=The Great and Powerful Trixie.jpg
Deck Type=constructed
Profile=Cautious
[main]
3 Arcane Denial
2 Cancel
3 Disdainful Stroke
4 Donate
1 Enlightened Tutor
3 Essence Scatter
4 Glacial Fortress
4 Illusions of Grandeur
14 Island
3 Mana Leak
1 Mystical Tutor
1 Plains
4 Sapphire Medallion
2 Seachrome Coast
3 Unsummon
4 Vapor Snag
4 Wrath of God

View File

@ -3,25 +3,19 @@
Name=The Great and Powerful Trixie 3
Title=The Great and Powerful Trixie
Difficulty=hard
Description=U splash W Trix combo deck with Illusions of Grandeur and Donate
Description=Mono U Trix combo deck with Illusions of Grandeur and Donate
Icon=The Great and Powerful Trixie.jpg
Deck Type=constructed
[main]
1 Ancestral Recall
4 Arcane Denial
1 Black Lotus
4 Counterspell
3 Disdainful Stroke
4 Accumulated Knowledge
4 Capsize
4 Donate
3 Essence Scatter
4 Glacial Fortress
4 Frantic Search
4 Helm of Awakening
2 Hoodwink
4 Illusions of Grandeur
10 Island
1 Mox Pearl
1 Mox Sapphire
4 Intuition
21 Island
1 Merchant Scroll
4 Sapphire Medallion
1 Timetwister
4 Tundra
3 Unsummon
4 Vapor Snag
4 Wrath of God
4 Stroke of Genius

View File

@ -6,6 +6,7 @@ Difficulty=very hard
Description=UB Necro-Donate Trix combo deck with Necropotence, Illusions of Grandeur and Donate
Icon=The Great and Powerful Trixie.jpg
Deck Type=constructed
Profile=Cautious
[main]
1 Ancestral Recall
3 Arcane Denial