mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
- Added AI logic to play a simple Illusions-Donate Trix deck.
- Added a quest opponent The Great and Powerful Trixie 4, a mono blue Trix combo deck with Illusions of Grandeur and Donate and a wide array of permission. It may be a little haphazard and not always very consistent, but it does beat many hard and very hard opponents with a decent chance.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -18987,6 +18987,7 @@ forge-gui/res/quest/duels/Terminator[!!-~]3.dck -text
|
||||
forge-gui/res/quest/duels/Thanos[!!-~]3.dck -text
|
||||
forge-gui/res/quest/duels/The[!!-~]Great[!!-~]Gatsby[!!-~]1.dck -text
|
||||
forge-gui/res/quest/duels/The[!!-~]Great[!!-~]Gazoo[!!-~]3.dck -text
|
||||
forge-gui/res/quest/duels/The[!!-~]Great[!!-~]and[!!-~]Powerful[!!-~]Trixie[!!-~]4.dck -text
|
||||
forge-gui/res/quest/duels/The[!!-~]Nac[!!-~]Mac[!!-~]Feegle[!!-~]3.dck -text
|
||||
forge-gui/res/quest/duels/The[!!-~]Shade[!!-~]3.dck -text
|
||||
forge-gui/res/quest/duels/The[!!-~]Spectre[!!-~]3.dck -text
|
||||
|
||||
@@ -19,6 +19,7 @@ import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class PermanentAi extends SpellAbilityAi {
|
||||
|
||||
@@ -150,6 +151,46 @@ public class PermanentAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for specific AI preferences
|
||||
if (card.hasSVar("AICastPreference")) {
|
||||
String pref = card.getSVar("AICastPreference");
|
||||
String[] groups = StringUtils.split(pref, "|");
|
||||
for (String group : groups) {
|
||||
String[] elems = StringUtils.split(group.trim(), '$');
|
||||
String param = elems[0].trim();
|
||||
String value = elems[1].trim();
|
||||
if (param.equals("MustHaveInHand")) {
|
||||
// Only cast if another card is present in hand (e.g. Illusions of Grandeur followed by Donate)
|
||||
boolean hasCard = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals(value)).size() > 0;
|
||||
if (!hasCard) {
|
||||
return false;
|
||||
}
|
||||
} else if (param.equals("MaxControlled")) {
|
||||
// Only cast unless there are X or more cards like this on the battlefield under AI control already
|
||||
int numControlled = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals(card.getName())).size();
|
||||
if (numControlled >= Integer.parseInt(value)) {
|
||||
return false;
|
||||
}
|
||||
} else if (elems[0].trim().equals("NumManaSources")) {
|
||||
// Only cast if there are X or more mana sources controlled by the AI
|
||||
CardCollection m = ComputerUtilMana.getAvailableMana(ai, true);
|
||||
if (m.size() < Integer.parseInt(value)) {
|
||||
return false;
|
||||
}
|
||||
} else if (elems[0].trim().equals("NumManaSourcesNextTurn")) {
|
||||
// Only cast if there are X or more mana sources controlled by the AI *or*
|
||||
// if there are X-1 mana sources in play but the AI has an extra land in hand
|
||||
CardCollection m = ComputerUtilMana.getAvailableMana(ai, true);
|
||||
int hasExtraLandInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS).size() > 0 ? 1 : 0;
|
||||
if (m.size() + hasExtraLandInHand < Integer.parseInt(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
@@ -93,6 +94,20 @@ public class PumpAi extends PumpAiBase {
|
||||
sa.getTargets().add(lowest);
|
||||
return true;
|
||||
}
|
||||
} else if (sa.hasParam("AILogic") && sa.getParam("AILogic").startsWith("Donate")) {
|
||||
// Donate currently supports only one special code path (Illusions of Grandeur)
|
||||
CardCollectionView aiList = ai.getCardsIn(ZoneType.Battlefield, "Illusions of Grandeur");
|
||||
if (aiList.size() > 0) {
|
||||
// Donate an Illusions of Grandeur, step 1 - target the opponent.
|
||||
if (sa.getParam("AILogic").equals("DonateTargetPlayer")) {
|
||||
sa.resetTargets();
|
||||
sa.getTargets().add(ai.getOpponents().get(0)); // TODO: expand this to donate to an opp who doesn't have Illusions yet
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// AI currently does not know how to handle Donate effectively otherwise
|
||||
// TODO: enhance this for other cases (e.g. Donating a card with bad drawback to the opponent)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
@@ -233,6 +248,13 @@ public class PumpAi extends PumpAiBase {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (sa.getParam("AILogic").equals("DonateTargetPerm")) {
|
||||
// Illusions of Grandeur + Donate, step 2 - target Illusions.
|
||||
CardCollectionView aiList = ai.getCardsIn(ZoneType.Battlefield, "Illusions of Grandeur");
|
||||
if (aiList.size() > 0) {
|
||||
sa.getTargets().add(aiList.get(0));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (isFight) {
|
||||
return FightAi.canFightAi(ai, sa, attack, defense);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Name:Donate
|
||||
ManaCost:2 U
|
||||
Types:Sorcery
|
||||
A:SP$ Pump | Cost$ 2 U | ValidTgts$ Player | TgtPrompt$ Select target player | SubAbility$ D1 | SpellDescription$ Target player gains control of target permanent you control. | StackDescription$ None
|
||||
A:SP$ Pump | Cost$ 2 U | ValidTgts$ Player | TgtPrompt$ Select target player | SubAbility$ D1 | AILogic$ DonateTargetPlayer | SpellDescription$ Target player gains control of target permanent you control. | StackDescription$ None
|
||||
SVar:D1:DB$ Pump | RememberObjects$ Targeted | Static$ True | SubAbility$ D2 | StackDescription$ None
|
||||
SVar:D2:DB$ Pump | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | SubAbility$ D3 | StackDescription$ None
|
||||
SVar:D2:DB$ Pump | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | SubAbility$ D3 | AILogic$ DonateTargetPerm | StackDescription$ None
|
||||
SVar:D3:DB$ GainControl | Defined$ Targeted | NewController$ Remembered | SubAbility$ D4
|
||||
SVar:D4:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:RemRandomDeck:True
|
||||
|
||||
@@ -6,6 +6,9 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S
|
||||
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:RemAIDeck:True
|
||||
SVar:AICastPreference:MustHaveInHand$ Donate | MaxControlled$ 1 | NumManaSourcesNextTurn$ 5
|
||||
SVar:RemRandomDeck:True
|
||||
SVar:DeckNeeds:Name$Donate
|
||||
SVar:PlayMain1: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,29 @@
|
||||
[duel]
|
||||
[metadata]
|
||||
Name=The Great and Powerful Trixie 4
|
||||
Title=The Great and Powerful Trixie
|
||||
Difficulty=very hard
|
||||
Description=Mono Blue Trix combo deck with Illusions of Grandeur and Donate
|
||||
Icon=Great and Powerful Trixie.jpg
|
||||
Deck Type=constructed
|
||||
[main]
|
||||
1 Ancestral Recall
|
||||
4 Arcane Denial
|
||||
4 Counterspell
|
||||
1 Dig Through Time
|
||||
2 Disdainful Stroke
|
||||
4 Donate
|
||||
2 Essence Scatter
|
||||
4 Illusions of Grandeur
|
||||
15 Island
|
||||
4 Mana Leak
|
||||
1 Mox Emerald
|
||||
1 Mox Jet
|
||||
1 Mox Pearl
|
||||
1 Mox Ruby
|
||||
1 Mox Sapphire
|
||||
4 Propaganda
|
||||
4 Sapphire Medallion
|
||||
1 Treasure Cruise
|
||||
3 Unsummon
|
||||
4 Vapor Snag
|
||||
Reference in New Issue
Block a user