mirror of
https://github.com/Relintai/mtg-forge-ios.git
synced 2024-12-21 07:16:52 +01:00
- 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:
parent
d3bfe5a0b2
commit
5e7442af9d
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 -->
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user