mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
CardFactoryUtil: Miracle is a Trigger now, and make PlayAi a bit better to check if it can play it
This commit is contained in:
@@ -18,7 +18,6 @@
|
|||||||
package forge.ai;
|
package forge.ai;
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -974,40 +973,6 @@ public class AiController {
|
|||||||
return Boolean.parseBoolean(prop);
|
return Boolean.parseBoolean(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the spell ability which has already been played - use it for reference only */
|
|
||||||
public SpellAbility chooseAndPlaySa(boolean mandatory, boolean withoutPayingManaCost, final SpellAbility... list) {
|
|
||||||
return chooseAndPlaySa(Arrays.asList(list), mandatory, withoutPayingManaCost);
|
|
||||||
}
|
|
||||||
/** Returns the spell ability which has already been played - use it for reference only */
|
|
||||||
public SpellAbility chooseAndPlaySa(final List<SpellAbility> choices, boolean mandatory, boolean withoutPayingManaCost) {
|
|
||||||
for (final SpellAbility sa : choices) {
|
|
||||||
sa.setActivatingPlayer(player);
|
|
||||||
//Spells
|
|
||||||
if (sa instanceof Spell) {
|
|
||||||
if (AiPlayDecision.WillPlay != canPlayFromEffectAI((Spell) sa, mandatory, withoutPayingManaCost)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (AiPlayDecision.WillPlay == canPlaySa(sa)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (withoutPayingManaCost) {
|
|
||||||
ComputerUtil.playSpellAbilityWithoutPayingManaCost(player, sa, game);
|
|
||||||
}
|
|
||||||
else if (!ComputerUtilCost.canPayCost(sa, player)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ComputerUtil.playStack(sa, player, game);
|
|
||||||
}
|
|
||||||
return sa;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AiPlayDecision canPlayFromEffectAI(Spell spell, boolean mandatory, boolean withoutPayingManaCost) {
|
public AiPlayDecision canPlayFromEffectAI(Spell spell, boolean mandatory, boolean withoutPayingManaCost) {
|
||||||
final Card card = spell.getHostCard();
|
final Card card = spell.getHostCard();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
package forge.ai;
|
package forge.ai;
|
||||||
|
|
||||||
|
import java.security.InvalidParameterException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.esotericsoftware.minlog.Log;
|
import com.esotericsoftware.minlog.Log;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
@@ -44,17 +51,10 @@ import forge.game.trigger.WrappedAbility;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.collect.FCollection;
|
|
||||||
import forge.util.collect.FCollectionView;
|
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.collect.FCollection;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import forge.util.collect.FCollectionView;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +79,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
brains.setUseSimulation(value);
|
brains.setUseSimulation(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public SpellAbility getAbilityToPlay(Card hostCard, List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
|
public SpellAbility getAbilityToPlay(Card hostCard, List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
|
||||||
if (abilities.size() == 0) {
|
if (abilities.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -314,11 +315,6 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
ComputerUtil.playNoStack(player, effectSA, game);
|
ComputerUtil.playNoStack(player, effectSA, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playMiracle(SpellAbility miracle, Card card) {
|
|
||||||
getAi().chooseAndPlaySa(false, false, miracle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave) {
|
public CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave) {
|
||||||
return getAi().chooseCardsToDelve(genericAmount, grave);
|
return getAi().chooseCardsToDelve(genericAmount, grave);
|
||||||
@@ -436,6 +432,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
return brains.chooseNumber(sa, title, min, max);
|
return brains.chooseNumber(sa, title, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int chooseNumber(SpellAbility sa, String title, List<Integer> options, Player relatedPlayer) {
|
public int chooseNumber(SpellAbility sa, String title, List<Integer> options, Player relatedPlayer) {
|
||||||
return brains.chooseNumber(sa, title, options, relatedPlayer);
|
return brains.chooseNumber(sa, title, options, relatedPlayer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.ai.AiPlayDecision;
|
import forge.ai.AiPlayDecision;
|
||||||
|
import forge.ai.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilCost;
|
|
||||||
import forge.ai.PlayerControllerAi;
|
import forge.ai.PlayerControllerAi;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
|
import forge.game.Game;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -17,64 +21,38 @@ import forge.game.spellability.Spell;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.MyRandom;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class PlayAi extends SpellAbilityAi {
|
public class PlayAi extends SpellAbilityAi {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean checkApiLogic(final Player ai, final SpellAbility sa) {
|
||||||
final Cost abCost = sa.getPayCosts();
|
final Game game = ai.getGame();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
final Random r = MyRandom.getRandom();
|
|
||||||
|
|
||||||
if (abCost != null) {
|
|
||||||
// AI currently disabled for these costs
|
|
||||||
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't use this as a response
|
// don't use this as a response
|
||||||
if (!ai.getGame().getStack().isEmpty()) {
|
if (!game.getStack().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent run-away activations - first time will always return true
|
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||||
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getRestrictions().getNumberTurnActivations());
|
return false; // prevent infinite loop
|
||||||
|
}
|
||||||
|
|
||||||
List<Card> cards;
|
CardCollection cards;
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
ZoneType zone = tgt.getZone().get(0);
|
ZoneType zone = tgt.getZone().get(0);
|
||||||
cards = CardLists.getValidCards(ai.getGame().getCardsIn(zone), tgt.getValidTgts(), ai, source, sa);
|
cards = CardLists.getValidCards(game.getCardsIn(zone), tgt.getValidTgts(), ai, source, sa);
|
||||||
if (cards.isEmpty()) {
|
if (cards.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sa.getTargets().add(ComputerUtilCard.getBestAI(cards));
|
sa.getTargets().add(ComputerUtilCard.getBestAI(cards));
|
||||||
} else if (!sa.hasParam("Valid")) {
|
} else if (!sa.hasParam("Valid")) {
|
||||||
cards = new ArrayList<Card>(AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa));
|
cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
||||||
if (cards.isEmpty()) {
|
if (cards.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return chance;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,9 +68,7 @@ public class PlayAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||||
|
if (sa.usesTargeting()) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
|
||||||
if (tgt != null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +88,8 @@ public class PlayAi extends SpellAbilityAi {
|
|||||||
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
|
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
|
public Card chooseSingleCard(final Player ai, final SpellAbility sa, Iterable<Card> options, boolean isOptional,
|
||||||
|
Player targetedPlayer) {
|
||||||
List<Card> tgtCards = CardLists.filter(options, new Predicate<Card>() {
|
List<Card> tgtCards = CardLists.filter(options, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
@@ -122,6 +99,16 @@ public class PlayAi extends SpellAbilityAi {
|
|||||||
// timing restrictions still apply
|
// timing restrictions still apply
|
||||||
if (!s.getRestrictions().checkTimingRestrictions(c, s))
|
if (!s.getRestrictions().checkTimingRestrictions(c, s))
|
||||||
continue;
|
continue;
|
||||||
|
if (sa.hasParam("PlayCost")) {
|
||||||
|
Cost abCost;
|
||||||
|
if ("ManaCost".equals(sa.getParam("PlayCost"))) {
|
||||||
|
abCost = new Cost(c.getManaCost(), false);
|
||||||
|
} else {
|
||||||
|
abCost = new Cost(sa.getParam("PlayCost"), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
spell = (Spell) spell.copyWithDefinedCost(abCost);
|
||||||
|
}
|
||||||
if( AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlayFromEffectAI(spell, false, true)) {
|
if( AiPlayDecision.WillPlay == ((PlayerControllerAi)ai.getController()).getAi().canPlayFromEffectAI(spell, false, true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,15 +213,17 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
final boolean noManaCost = sa.hasParam("WithoutManaCost");
|
final boolean noManaCost = sa.hasParam("WithoutManaCost");
|
||||||
if (noManaCost) {
|
if (noManaCost) {
|
||||||
tgtSA = tgtSA.copyWithNoManaCost();
|
tgtSA = tgtSA.copyWithNoManaCost();
|
||||||
} else if (sa.hasParam("PlayMadness")) {
|
} else if (sa.hasParam("PlayCost")) {
|
||||||
Cost abCost;
|
Cost abCost;
|
||||||
if ("ManaCost".equals(sa.getParam("PlayMadness"))) {
|
if ("ManaCost".equals(sa.getParam("PlayCost"))) {
|
||||||
abCost = new Cost(source.getManaCost(), false);
|
abCost = new Cost(source.getManaCost(), false);
|
||||||
} else {
|
} else {
|
||||||
abCost = new Cost(sa.getParam("PlayMadness"), false);
|
abCost = new Cost(sa.getParam("PlayCost"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
tgtSA = tgtSA.copyWithDefinedCost(abCost);
|
tgtSA = tgtSA.copyWithDefinedCost(abCost);
|
||||||
|
}
|
||||||
|
if (sa.hasParam("Madness")) {
|
||||||
tgtSA.getHostCard().setMadness(true);
|
tgtSA.getHostCard().setMadness(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -211,7 +211,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private NavigableMap<Long, Player> tempControllers = Maps.newTreeMap();
|
private NavigableMap<Long, Player> tempControllers = Maps.newTreeMap();
|
||||||
|
|
||||||
private String originalText = "", text = "";
|
private String originalText = "", text = "";
|
||||||
private Cost miracleCost = null;
|
|
||||||
private String chosenType = "";
|
private String chosenType = "";
|
||||||
private List<String> chosenColors;
|
private List<String> chosenColors;
|
||||||
private String namedCard = "";
|
private String namedCard = "";
|
||||||
@@ -3471,13 +3470,6 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
unearthed = b;
|
unearthed = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Cost getMiracleCost() {
|
|
||||||
return miracleCost;
|
|
||||||
}
|
|
||||||
public final void setMiracleCost(final Cost cost) {
|
|
||||||
miracleCost = cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean hasSuspend() {
|
public final boolean hasSuspend() {
|
||||||
return suspend;
|
return suspend;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -901,7 +901,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (l[0].startsWith("CommanderCastFromCommandZone")) {
|
if (l[0].startsWith("CommanderCastFromCommandZone")) {
|
||||||
// TODO fix it for multiple commanders
|
// TODO fix it for multiple commanders
|
||||||
// Read SVar CommanderCostRaise from Commander Effect
|
// Read SVar CommanderCostRaise from Commander Effect
|
||||||
Card commeff = CardLists.filter(cc.getCardsIn(ZoneType.Command),
|
Card commeff = CardLists.filter(cc.getCardsIn(ZoneType.Command),
|
||||||
CardPredicates.nameEquals("Commander Effect")).get(0);
|
CardPredicates.nameEquals("Commander Effect")).get(0);
|
||||||
@@ -994,14 +994,14 @@ public class CardFactoryUtil {
|
|||||||
return doXMath(cc.getOpponentsGreatestLifeTotal(), m, c);
|
return doXMath(cc.getOpponentsGreatestLifeTotal(), m, c);
|
||||||
}
|
}
|
||||||
if (sq[0].contains("OppsAtLifeTotal")) {
|
if (sq[0].contains("OppsAtLifeTotal")) {
|
||||||
final int lifeTotal = xCount(c, sq[1]);
|
final int lifeTotal = xCount(c, sq[1]);
|
||||||
int number = 0;
|
int number = 0;
|
||||||
for (final Player opp : cc.getOpponents()) {
|
for (final Player opp : cc.getOpponents()) {
|
||||||
if (opp.getLife() == lifeTotal) {
|
if (opp.getLife() == lifeTotal) {
|
||||||
number++;
|
number++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return doXMath(number, m, c);
|
return doXMath(number, m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count$TargetedLifeTotal (targeted player's life total)
|
// Count$TargetedLifeTotal (targeted player's life total)
|
||||||
@@ -1157,13 +1157,13 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("ColorsCtrl")) {
|
if (sq[0].contains("ColorsCtrl")) {
|
||||||
final CardCollectionView list = cc.getCardsIn(ZoneType.Battlefield);
|
final CardCollectionView list = cc.getCardsIn(ZoneType.Battlefield);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (final byte col : MagicColor.WUBRG) {
|
for (final byte col : MagicColor.WUBRG) {
|
||||||
if (!CardLists.getColor(list, col).isEmpty()) {
|
if (!CardLists.getColor(list, col).isEmpty()) {
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return doXMath(n, m, c);
|
return doXMath(n, m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1473,7 +1473,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static CardCollectionView getCardListForXCount(final Card c, final Player cc, final String[] sq) {
|
private static CardCollectionView getCardListForXCount(final Card c, final Player cc, final String[] sq) {
|
||||||
final List<Player> opps = cc.getOpponents();
|
final List<Player> opps = cc.getOpponents();
|
||||||
CardCollection someCards = new CardCollection();
|
CardCollection someCards = new CardCollection();
|
||||||
final Game game = c.getGame();
|
final Game game = c.getGame();
|
||||||
|
|
||||||
@@ -1503,41 +1503,41 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("OppCtrl")) {
|
if (sq[0].contains("OppCtrl")) {
|
||||||
for (final Player p : opps) {
|
for (final Player p : opps) {
|
||||||
someCards.addAll(p.getZone(ZoneType.Battlefield).getCards());
|
someCards.addAll(p.getZone(ZoneType.Battlefield).getCards());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("InOppYard")) {
|
if (sq[0].contains("InOppYard")) {
|
||||||
for (final Player p : opps) {
|
for (final Player p : opps) {
|
||||||
someCards.addAll(p.getCardsIn(ZoneType.Graveyard));
|
someCards.addAll(p.getCardsIn(ZoneType.Graveyard));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("InOppHand")) {
|
if (sq[0].contains("InOppHand")) {
|
||||||
for (final Player p : opps) {
|
for (final Player p : opps) {
|
||||||
someCards.addAll(p.getCardsIn(ZoneType.Hand));
|
someCards.addAll(p.getCardsIn(ZoneType.Hand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("InChosenHand")) {
|
if (sq[0].contains("InChosenHand")) {
|
||||||
if (c.getChosenPlayer() != null) {
|
if (c.getChosenPlayer() != null) {
|
||||||
someCards.addAll(c.getChosenPlayer().getCardsIn(ZoneType.Hand));
|
someCards.addAll(c.getChosenPlayer().getCardsIn(ZoneType.Hand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("InChosenYard")) {
|
if (sq[0].contains("InChosenYard")) {
|
||||||
if (c.getChosenPlayer() != null) {
|
if (c.getChosenPlayer() != null) {
|
||||||
someCards.addAll(c.getChosenPlayer().getCardsIn(ZoneType.Graveyard));
|
someCards.addAll(c.getChosenPlayer().getCardsIn(ZoneType.Graveyard));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("OnBattlefield")) {
|
if (sq[0].contains("OnBattlefield")) {
|
||||||
someCards.addAll(game.getCardsIn(ZoneType.Battlefield));
|
someCards.addAll(game.getCardsIn(ZoneType.Battlefield));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("InAllYards")) {
|
if (sq[0].contains("InAllYards")) {
|
||||||
someCards.addAll(game.getCardsIn(ZoneType.Graveyard));
|
someCards.addAll(game.getCardsIn(ZoneType.Graveyard));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("SpellsOnStack")) {
|
if (sq[0].contains("SpellsOnStack")) {
|
||||||
@@ -1545,7 +1545,7 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sq[0].contains("InAllHands")) {
|
if (sq[0].contains("InAllHands")) {
|
||||||
someCards.addAll(game.getCardsIn(ZoneType.Hand));
|
someCards.addAll(game.getCardsIn(ZoneType.Hand));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count$InTargetedHand (targeted player's cards in hand)
|
// Count$InTargetedHand (targeted player's cards in hand)
|
||||||
@@ -2240,7 +2240,7 @@ public class CardFactoryUtil {
|
|||||||
addTriggerAbility(keyword, card, null);
|
addTriggerAbility(keyword, card, null);
|
||||||
}
|
}
|
||||||
else if (keyword.equals("Epic")) {
|
else if (keyword.equals("Epic")) {
|
||||||
addSpellAbility(keyword, card, null);
|
addSpellAbility(keyword, card, null);
|
||||||
}
|
}
|
||||||
else if (keyword.equals("Soulbond")) {
|
else if (keyword.equals("Soulbond")) {
|
||||||
// Setup ETB trigger for card with Soulbond keyword
|
// Setup ETB trigger for card with Soulbond keyword
|
||||||
@@ -2282,6 +2282,9 @@ public class CardFactoryUtil {
|
|||||||
else if (keyword.equals("Ingest")) {
|
else if (keyword.equals("Ingest")) {
|
||||||
addTriggerAbility(keyword, card, null);
|
addTriggerAbility(keyword, card, null);
|
||||||
}
|
}
|
||||||
|
else if (keyword.startsWith("Miracle")) {
|
||||||
|
addTriggerAbility(keyword, card, null);
|
||||||
|
}
|
||||||
else if (keyword.equals("Persist")) {
|
else if (keyword.equals("Persist")) {
|
||||||
addTriggerAbility(keyword, card, null);
|
addTriggerAbility(keyword, card, null);
|
||||||
}
|
}
|
||||||
@@ -2981,9 +2984,9 @@ public class CardFactoryUtil {
|
|||||||
"Execute$ " + trigPlay + " | Secondary$ True | TriggerDescription$ " +
|
"Execute$ " + trigPlay + " | Secondary$ True | TriggerDescription$ " +
|
||||||
"Play Madness " + ManaCostParser.parse(manacost) + " - " + card.getName();
|
"Play Madness " + ManaCostParser.parse(manacost) + " - " + card.getName();
|
||||||
|
|
||||||
final String playMadness = "AB$ Play | Cost$ 0 | Defined$ Self | PlayMadness$ " + manacost +
|
final String playMadness = "AB$ Play | Cost$ 0 | Defined$ Self | PlayCost$ " + manacost +
|
||||||
" | ConditionDefined$ Self | ConditionPresent$ Card.StrictlySelf+inZoneExile" +
|
" | ConditionDefined$ Self | ConditionPresent$ Card.StrictlySelf+inZoneExile" +
|
||||||
" | Optional$ True | SubAbility$ DBWasNotPlayMadness | RememberPlayed$ True";
|
" | Optional$ True | SubAbility$ DBWasNotPlayMadness | RememberPlayed$ True | Madness$ True";
|
||||||
final String moveToYard = "DB$ ChangeZone | Defined$ Self.StrictlySelf | Origin$ Exile | " +
|
final String moveToYard = "DB$ ChangeZone | Defined$ Self.StrictlySelf | Origin$ Exile | " +
|
||||||
"Destination$ Graveyard | ConditionDefined$ Remembered | ConditionPresent$" +
|
"Destination$ Graveyard | ConditionDefined$ Remembered | ConditionPresent$" +
|
||||||
" Card | ConditionCompare$ EQ0 | SubAbility$ DBMadnessCleanup";
|
" Card | ConditionCompare$ EQ0 | SubAbility$ DBMadnessCleanup";
|
||||||
@@ -3006,6 +3009,22 @@ public class CardFactoryUtil {
|
|||||||
card.setSVar("MeleePump", effect);
|
card.setSVar("MeleePump", effect);
|
||||||
card.setSVar("MeleeX", "TriggeredPlayersDefenders$Amount");
|
card.setSVar("MeleeX", "TriggeredPlayersDefenders$Amount");
|
||||||
final Trigger trigger = TriggerHandler.parseTrigger(trigStr.toString(), card, intrinsic);
|
final Trigger trigger = TriggerHandler.parseTrigger(trigStr.toString(), card, intrinsic);
|
||||||
|
final Trigger cardTrigger = card.addTrigger(trigger);
|
||||||
|
if (!intrinsic) {
|
||||||
|
kws.addTrigger(cardTrigger);
|
||||||
|
}
|
||||||
|
} else if (keyword.startsWith("Miracle")) {
|
||||||
|
final String[] k = keyword.split(":");
|
||||||
|
final String manacost = k[1];
|
||||||
|
final String abStr = "DB$ Play | Defined$ Self | PlayCost$ " + manacost;
|
||||||
|
|
||||||
|
final String trigStr = "Mode$ Drawn | ValidCard$ Card.Self | Miracle$ True | Secondary$ True "
|
||||||
|
+ "| Static$ True | TriggerDescription$ CARDNAME - Miracle";
|
||||||
|
|
||||||
|
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, card, intrinsic);
|
||||||
|
|
||||||
|
trigger.setOverridingAbility(AbilityFactory.getAbility(abStr, card));
|
||||||
|
|
||||||
final Trigger cardTrigger = card.addTrigger(trigger);
|
final Trigger cardTrigger = card.addTrigger(trigger);
|
||||||
if (!intrinsic) {
|
if (!intrinsic) {
|
||||||
kws.addTrigger(cardTrigger);
|
kws.addTrigger(cardTrigger);
|
||||||
@@ -4082,17 +4101,6 @@ public class CardFactoryUtil {
|
|||||||
addTriggerAbility(parse, card, null);
|
addTriggerAbility(parse, card, null);
|
||||||
} // madness
|
} // madness
|
||||||
|
|
||||||
if (hasKeyword(card, "Miracle") != -1) {
|
|
||||||
final int n = hasKeyword(card, "Miracle");
|
|
||||||
if (n != -1) {
|
|
||||||
final String parse = card.getKeywords().get(n).toString();
|
|
||||||
// card.removeIntrinsicKeyword(parse);
|
|
||||||
|
|
||||||
final String[] k = parse.split(":");
|
|
||||||
card.setMiracleCost(new Cost(k[1], false));
|
|
||||||
}
|
|
||||||
} // miracle
|
|
||||||
|
|
||||||
if (hasKeyword(card, "Devour") != -1) {
|
if (hasKeyword(card, "Devour") != -1) {
|
||||||
final int n = hasKeyword(card, "Devour");
|
final int n = hasKeyword(card, "Devour");
|
||||||
addReplacementEffect(card.getKeywords().get(n), card, null);
|
addReplacementEffect(card.getKeywords().get(n), card, null);
|
||||||
@@ -4129,22 +4137,22 @@ public class CardFactoryUtil {
|
|||||||
if (hasKeyword(card, "Recover") != -1) {
|
if (hasKeyword(card, "Recover") != -1) {
|
||||||
final String recoverCost = card.getKeywords().get(card.getKeywordPosition("Recover")).split(":")[1];
|
final String recoverCost = card.getKeywords().get(card.getKeywordPosition("Recover")).split(":")[1];
|
||||||
final String abStr = "AB$ ChangeZone | Cost$ 0 | Defined$ Self"
|
final String abStr = "AB$ ChangeZone | Cost$ 0 | Defined$ Self"
|
||||||
+ " | Origin$ Graveyard | Destination$ Hand | UnlessCost$ "
|
+ " | Origin$ Graveyard | Destination$ Hand | UnlessCost$ "
|
||||||
+ recoverCost + " | UnlessPayer$ You | UnlessSwitched$ True"
|
+ recoverCost + " | UnlessPayer$ You | UnlessSwitched$ True"
|
||||||
+ " | UnlessResolveSubs$ WhenNotPaid | SubAbility$ RecoverExile";
|
+ " | UnlessResolveSubs$ WhenNotPaid | SubAbility$ RecoverExile";
|
||||||
card.setSVar("RecoverTrig", abStr);
|
card.setSVar("RecoverTrig", abStr);
|
||||||
card.setSVar("RecoverExile", "DB$ ChangeZone | Defined$ Self"
|
card.setSVar("RecoverExile", "DB$ ChangeZone | Defined$ Self"
|
||||||
+ " | Origin$ Graveyard | Destination$ Exile");
|
+ " | Origin$ Graveyard | Destination$ Exile");
|
||||||
String trigObject = card.isCreature() ? "Creature.Other+YouOwn" : "Creature.YouOwn";
|
String trigObject = card.isCreature() ? "Creature.Other+YouOwn" : "Creature.YouOwn";
|
||||||
String trigArticle = card.isCreature() ? "another" : "a";
|
String trigArticle = card.isCreature() ? "another" : "a";
|
||||||
String trigStr = "Mode$ ChangesZone | ValidCard$ " + trigObject
|
String trigStr = "Mode$ ChangesZone | ValidCard$ " + trigObject
|
||||||
+ " | Origin$ Battlefield | Destination$ Graveyard | "
|
+ " | Origin$ Battlefield | Destination$ Graveyard | "
|
||||||
+ "TriggerZones$ Graveyard | Execute$ RecoverTrig | "
|
+ "TriggerZones$ Graveyard | Execute$ RecoverTrig | "
|
||||||
+ "TriggerDescription$ When " + trigArticle + " creature is "
|
+ "TriggerDescription$ When " + trigArticle + " creature is "
|
||||||
+ "put into your graveyard from the battlefield, you "
|
+ "put into your graveyard from the battlefield, you "
|
||||||
+ "may pay " + recoverCost + ". If you do, return "
|
+ "may pay " + recoverCost + ". If you do, return "
|
||||||
+ "CARDNAME from your graveyard to your hand. Otherwise,"
|
+ "CARDNAME from your graveyard to your hand. Otherwise,"
|
||||||
+ " exile CARDNAME. | Secondary$ True";
|
+ " exile CARDNAME. | Secondary$ True";
|
||||||
final Trigger myTrigger = TriggerHandler.parseTrigger(trigStr, card, true);
|
final Trigger myTrigger = TriggerHandler.parseTrigger(trigStr, card, true);
|
||||||
card.addTrigger(myTrigger);
|
card.addTrigger(myTrigger);
|
||||||
} // Recover
|
} // Recover
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.trigger;
|
package forge.game.trigger;
|
||||||
|
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.GameStage;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
@@ -64,6 +66,13 @@ public class TriggerDrawn extends Trigger {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mapParams.containsKey("Miracle")) {
|
||||||
|
final Game game = this.getHostCard().getGame();
|
||||||
|
if (number != 1 || game.getAge() == GameStage.Mulligan) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -268,11 +268,6 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
return chooseItems(validCards, min);
|
return chooseItems(validCards, min);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playMiracle(SpellAbility miracle, Card card) {
|
|
||||||
throw new IllegalStateException("Callers of this method currently assume that it performs extra functionality!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave) {
|
public CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave) {
|
||||||
return CardCollection.EMPTY;
|
return CardCollection.EMPTY;
|
||||||
|
|||||||
@@ -694,14 +694,6 @@ public class PlayerControllerHuman
|
|||||||
return new CardCollection(inp.getSelected());
|
return new CardCollection(inp.getSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playMiracle(final SpellAbility miracle, final Card card) {
|
|
||||||
final CardView view = CardView.get(card);
|
|
||||||
if (getGui().confirm(view, view + " - Drawn. Play for Miracle Cost?")) {
|
|
||||||
HumanPlay.playSpellAbility(this, player, miracle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollectionView chooseCardsToDelve(final int genericAmount, final CardCollection grave) {
|
public CardCollectionView chooseCardsToDelve(final int genericAmount, final CardCollection grave) {
|
||||||
final int cardsInGrave = Math.min(genericAmount, grave.size());
|
final int cardsInGrave = Math.min(genericAmount, grave.size());
|
||||||
|
|||||||
Reference in New Issue
Block a user