mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Merge branch 'master' of https://git.cardforge.org/core-developers/forge.git
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-ai</artifactId>
|
<artifactId>forge-ai</artifactId>
|
||||||
|
|||||||
@@ -1778,7 +1778,7 @@ public class AiController {
|
|||||||
+ MyRandom.getRandom().nextInt(3);
|
+ MyRandom.getRandom().nextInt(3);
|
||||||
return Math.max(remaining, min) / 2;
|
return Math.max(remaining, min) / 2;
|
||||||
} else if ("LowestLoseLife".equals(logic)) {
|
} else if ("LowestLoseLife".equals(logic)) {
|
||||||
return MyRandom.getRandom().nextInt(Math.min(player.getLife() / 3, ComputerUtil.getOpponentFor(player).getLife())) + 1;
|
return MyRandom.getRandom().nextInt(Math.min(player.getLife() / 3, player.getWeakestOpponent().getLife())) + 1;
|
||||||
} else if ("HighestGetCounter".equals(logic)) {
|
} else if ("HighestGetCounter".equals(logic)) {
|
||||||
return MyRandom.getRandom().nextInt(3);
|
return MyRandom.getRandom().nextInt(3);
|
||||||
} else if (source.hasSVar("EnergyToPay")) {
|
} else if (source.hasSVar("EnergyToPay")) {
|
||||||
|
|||||||
@@ -521,7 +521,7 @@ public class ComputerUtilCard {
|
|||||||
*/
|
*/
|
||||||
public static CardCollectionView getLikelyBlockers(final Player ai, final CardCollectionView blockers) {
|
public static CardCollectionView getLikelyBlockers(final Player ai, final CardCollectionView blockers) {
|
||||||
AiBlockController aiBlk = new AiBlockController(ai);
|
AiBlockController aiBlk = new AiBlockController(ai);
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
Combat combat = new Combat(opp);
|
Combat combat = new Combat(opp);
|
||||||
//Use actual attackers if available, else consider all possible attackers
|
//Use actual attackers if available, else consider all possible attackers
|
||||||
Combat currentCombat = ai.getGame().getCombat();
|
Combat currentCombat = ai.getGame().getCombat();
|
||||||
@@ -884,7 +884,7 @@ public class ComputerUtilCard {
|
|||||||
List<String> chosen = new ArrayList<String>();
|
List<String> chosen = new ArrayList<String>();
|
||||||
Player ai = sa.getActivatingPlayer();
|
Player ai = sa.getActivatingPlayer();
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
if (sa.hasParam("AILogic")) {
|
if (sa.hasParam("AILogic")) {
|
||||||
final String logic = sa.getParam("AILogic");
|
final String logic = sa.getParam("AILogic");
|
||||||
|
|
||||||
@@ -974,7 +974,7 @@ public class ComputerUtilCard {
|
|||||||
public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) {
|
public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) {
|
||||||
final Player ai = sa.getActivatingPlayer();
|
final Player ai = sa.getActivatingPlayer();
|
||||||
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
final PhaseHandler ph = game.getPhaseHandler();
|
final PhaseHandler ph = game.getPhaseHandler();
|
||||||
final PhaseType phaseType = ph.getPhase();
|
final PhaseType phaseType = ph.getPhase();
|
||||||
@@ -1269,7 +1269,7 @@ public class ComputerUtilCard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
Card pumped = getPumpedCreature(ai, sa, c, toughness, power, keywords);
|
Card pumped = getPumpedCreature(ai, sa, c, toughness, power, keywords);
|
||||||
List<Card> oppCreatures = opp.getCreaturesInPlay();
|
List<Card> oppCreatures = opp.getCreaturesInPlay();
|
||||||
float chance = 0;
|
float chance = 0;
|
||||||
@@ -1842,17 +1842,45 @@ public class ComputerUtilCard {
|
|||||||
String needsToPlayName = isRightSplit ? "SplitNeedsToPlay" : "NeedsToPlay";
|
String needsToPlayName = isRightSplit ? "SplitNeedsToPlay" : "NeedsToPlay";
|
||||||
String needsToPlayVarName = isRightSplit ? "SplitNeedsToPlayVar" : "NeedsToPlayVar";
|
String needsToPlayVarName = isRightSplit ? "SplitNeedsToPlayVar" : "NeedsToPlayVar";
|
||||||
|
|
||||||
if (sa != null && sa.isEvoke()) {
|
// TODO: if there are ever split cards with Evoke or Kicker, factor in the right split option above
|
||||||
if (card.hasSVar("NeedsToPlayEvoked")) {
|
if (sa != null) {
|
||||||
needsToPlayName = "NeedsToPlayEvoked";
|
if (sa.isEvoke()) {
|
||||||
}
|
// if the spell is evoked, will use NeedsToPlayEvoked if available (otherwise falls back to NeedsToPlay)
|
||||||
if (card.hasSVar("NeedsToPlayEvokedVar")) {
|
if (card.hasSVar("NeedsToPlayEvoked")) {
|
||||||
needsToPlayVarName = "NeedsToPlayEvokedVar";
|
needsToPlayName = "NeedsToPlayEvoked";
|
||||||
|
}
|
||||||
|
if (card.hasSVar("NeedsToPlayEvokedVar")) {
|
||||||
|
needsToPlayVarName = "NeedsToPlayEvokedVar";
|
||||||
|
}
|
||||||
|
} else if (sa.isKicked()) {
|
||||||
|
// if the spell is kicked, uses NeedsToPlayKicked if able and locks out the regular NeedsToPlay check
|
||||||
|
// for unkicked spells, uses NeedsToPlay
|
||||||
|
if (card.hasSVar("NeedsToPlayKicked")) {
|
||||||
|
needsToPlayName = "NeedsToPlayKicked";
|
||||||
|
} else {
|
||||||
|
needsToPlayName = "UNUSED";
|
||||||
|
}
|
||||||
|
if (card.hasSVar("NeedsToPlayKickedVar")) {
|
||||||
|
needsToPlayVarName = "NeedsToPlayKickedVar";
|
||||||
|
} else {
|
||||||
|
needsToPlayVarName = "UNUSED";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card.hasSVar(needsToPlayName)) {
|
if (card.hasSVar(needsToPlayName)) {
|
||||||
final String needsToPlay = card.getSVar(needsToPlayName);
|
final String needsToPlay = card.getSVar(needsToPlayName);
|
||||||
|
|
||||||
|
// A special case which checks that this creature will attack if it's the AI's turn
|
||||||
|
if (needsToPlay.equalsIgnoreCase("WillAttack")) {
|
||||||
|
if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
|
||||||
|
return ComputerUtilCard.doesSpecifiedCreatureAttackAI(sa.getActivatingPlayer(), card) ?
|
||||||
|
AiPlayDecision.WillPlay : AiPlayDecision.BadEtbEffects;
|
||||||
|
} else {
|
||||||
|
return AiPlayDecision.WillPlay; // not our turn, skip this check for the possible Flash use etc.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CardCollectionView list = game.getCardsIn(ZoneType.Battlefield);
|
CardCollectionView list = game.getCardsIn(ZoneType.Battlefield);
|
||||||
|
|
||||||
list = CardLists.getValidCards(list, needsToPlay.split(","), card.getController(), card, null);
|
list = CardLists.getValidCards(list, needsToPlay.split(","), card.getController(), card, null);
|
||||||
|
|||||||
@@ -635,7 +635,7 @@ public class ComputerUtilCost {
|
|||||||
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
|
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
|
||||||
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
|
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
|
||||||
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
|
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
|
||||||
&& (!source.getName().equals("Chain of Vapor") || (ComputerUtil.getOpponentFor(payer).getCreaturesInPlay().size() > 0 && payer.getLandsInPlay().size() > 3));
|
&& (!source.getName().equals("Chain of Vapor") || (payer.getWeakestOpponent().getCreaturesInPlay().size() > 0 && payer.getLandsInPlay().size() > 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> getAvailableManaColors(Player ai, Card additionalLand) {
|
public static Set<String> getAvailableManaColors(Player ai, Card additionalLand) {
|
||||||
|
|||||||
@@ -1105,7 +1105,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
public String chooseCardName(SpellAbility sa, Predicate<ICardFace> cpp, String valid, String message) {
|
public String chooseCardName(SpellAbility sa, Predicate<ICardFace> cpp, String valid, String message) {
|
||||||
if (sa.hasParam("AILogic")) {
|
if (sa.hasParam("AILogic")) {
|
||||||
CardCollectionView aiLibrary = player.getCardsIn(ZoneType.Library);
|
CardCollectionView aiLibrary = player.getCardsIn(ZoneType.Library);
|
||||||
CardCollectionView oppLibrary = ComputerUtil.getOpponentFor(player).getCardsIn(ZoneType.Library);
|
CardCollectionView oppLibrary = player.getWeakestOpponent().getCardsIn(ZoneType.Library);
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final String logic = sa.getParam("AILogic");
|
final String logic = sa.getParam("AILogic");
|
||||||
|
|
||||||
@@ -1227,6 +1227,18 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
// Choose the optional cost if it can be paid (to be improved later, check for playability and other conditions perhaps)
|
// Choose the optional cost if it can be paid (to be improved later, check for playability and other conditions perhaps)
|
||||||
Cost fullCost = opt.getCost().copy().add(costSoFar);
|
Cost fullCost = opt.getCost().copy().add(costSoFar);
|
||||||
SpellAbility fullCostSa = chosen.copyWithDefinedCost(fullCost);
|
SpellAbility fullCostSa = chosen.copyWithDefinedCost(fullCost);
|
||||||
|
|
||||||
|
// Playability check for Kicker
|
||||||
|
if (opt.getType() == OptionalCost.Kicker1 || opt.getType() == OptionalCost.Kicker2) {
|
||||||
|
SpellAbility kickedSaCopy = fullCostSa.copy();
|
||||||
|
kickedSaCopy.addOptionalCost(opt.getType());
|
||||||
|
Card copy = CardUtil.getLKICopy(chosen.getHostCard());
|
||||||
|
copy.addOptionalCostPaid(opt.getType());
|
||||||
|
if (ComputerUtilCard.checkNeedsToPlayReqs(copy, kickedSaCopy) != AiPlayDecision.WillPlay) {
|
||||||
|
continue; // don't choose kickers we don't want to play
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ComputerUtilCost.canPayCost(fullCostSa, player)) {
|
if (ComputerUtilCost.canPayCost(fullCostSa, player)) {
|
||||||
chosenOptCosts.add(opt);
|
chosenOptCosts.add(opt);
|
||||||
costSoFar.add(opt.getCost());
|
costSoFar.add(opt.getCost());
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -22,7 +21,7 @@ public class ActivateAbilityAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
||||||
|
|
||||||
List<Card> list = CardLists.getType(opp.getCardsIn(ZoneType.Battlefield), sa.getParamOrDefault("Type", "Card"));
|
List<Card> list = CardLists.getType(opp.getCardsIn(ZoneType.Battlefield), sa.getParamOrDefault("Type", "Card"));
|
||||||
@@ -46,7 +45,7 @@ public class ActivateAbilityAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
@@ -87,7 +86,7 @@ public class ActivateAbilityAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
sa.getTargets().add(ComputerUtil.getOpponentFor(ai));
|
sa.getTargets().add(ai.getWeakestOpponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomReturn;
|
return randomReturn;
|
||||||
|
|||||||
@@ -78,13 +78,13 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
num = (num == null) ? "1" : num;
|
num = (num == null) ? "1" : num;
|
||||||
final int nToSac = AbilityUtils.calculateAmount(topStack.getHostCard(), num, topStack);
|
final int nToSac = AbilityUtils.calculateAmount(topStack.getHostCard(), num, topStack);
|
||||||
CardCollection list = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","),
|
CardCollection list = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","),
|
||||||
ComputerUtil.getOpponentFor(ai), topStack.getHostCard(), topStack);
|
ai.getWeakestOpponent(), topStack.getHostCard(), topStack);
|
||||||
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
||||||
ComputerUtilCard.sortByEvaluateCreature(list);
|
ComputerUtilCard.sortByEvaluateCreature(list);
|
||||||
if (!list.isEmpty() && list.size() == nToSac && ComputerUtilCost.canPayCost(sa, ai)) {
|
if (!list.isEmpty() && list.size() == nToSac && ComputerUtilCost.canPayCost(sa, ai)) {
|
||||||
Card animatedCopy = becomeAnimated(source, sa);
|
Card animatedCopy = becomeAnimated(source, sa);
|
||||||
list.add(animatedCopy);
|
list.add(animatedCopy);
|
||||||
list = CardLists.getValidCards(list, valid.split(","), ComputerUtil.getOpponentFor(ai), topStack.getHostCard(),
|
list = CardLists.getValidCards(list, valid.split(","), ai.getWeakestOpponent(), topStack.getHostCard(),
|
||||||
topStack);
|
topStack);
|
||||||
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
||||||
if (ComputerUtilCard.evaluateCreature(animatedCopy) < ComputerUtilCard.evaluateCreature(list.get(0))
|
if (ComputerUtilCard.evaluateCreature(animatedCopy) < ComputerUtilCard.evaluateCreature(list.get(0))
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -17,7 +16,7 @@ public class BalanceAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
int diff = 0;
|
int diff = 0;
|
||||||
// TODO Add support for multiplayer logic
|
// TODO Add support for multiplayer logic
|
||||||
final Player opp = ComputerUtil.getOpponentFor(aiPlayer);
|
final Player opp = aiPlayer.getWeakestOpponent();
|
||||||
final CardCollectionView humPerms = opp.getCardsIn(ZoneType.Battlefield);
|
final CardCollectionView humPerms = opp.getCardsIn(ZoneType.Battlefield);
|
||||||
final CardCollectionView compPerms = aiPlayer.getCardsIn(ZoneType.Battlefield);
|
final CardCollectionView compPerms = aiPlayer.getCardsIn(ZoneType.Battlefield);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package forge.ai.ability;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
@@ -25,7 +24,7 @@ public class BidLifeAi extends SpellAbilityAi {
|
|||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (tgt.canTgtCreature()) {
|
if (tgt.canTgtCreature()) {
|
||||||
List<Card> list = CardLists.getTargetableCards(ComputerUtil.getOpponentFor(aiPlayer).getCardsIn(ZoneType.Battlefield), sa);
|
List<Card> list = CardLists.getTargetableCards(aiPlayer.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), sa);
|
||||||
list = CardLists.getValidCards(list, tgt.getValidTgts(), source.getController(), source, sa);
|
list = CardLists.getValidCards(list, tgt.getValidTgts(), source.getController(), source, sa);
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
|
final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
|
||||||
ZoneType origin = null;
|
ZoneType origin = null;
|
||||||
final Player opponent = ComputerUtil.getOpponentFor(ai);
|
final Player opponent = ai.getWeakestOpponent();
|
||||||
boolean activateForCost = ComputerUtil.activateForCost(sa, ai);
|
boolean activateForCost = ComputerUtil.activateForCost(sa, ai);
|
||||||
|
|
||||||
if (sa.hasParam("Origin")) {
|
if (sa.hasParam("Origin")) {
|
||||||
@@ -439,7 +439,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
// if putting cards from hand to library and parent is drawing cards
|
// if putting cards from hand to library and parent is drawing cards
|
||||||
// make sure this will actually do something:
|
// make sure this will actually do something:
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(aiPlayer);
|
final Player opp = aiPlayer.getWeakestOpponent();
|
||||||
if (tgt != null && tgt.canTgtPlayer()) {
|
if (tgt != null && tgt.canTgtPlayer()) {
|
||||||
boolean isCurse = sa.isCurse();
|
boolean isCurse = sa.isCurse();
|
||||||
if (isCurse && sa.canTarget(opp)) {
|
if (isCurse && sa.canTarget(opp)) {
|
||||||
@@ -500,7 +500,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
Iterable<Player> pDefined;
|
Iterable<Player> pDefined;
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if ((tgt != null) && tgt.canTgtPlayer()) {
|
if ((tgt != null) && tgt.canTgtPlayer()) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
if (sa.isCurse()) {
|
if (sa.isCurse()) {
|
||||||
if (sa.canTarget(opp)) {
|
if (sa.canTarget(opp)) {
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(opp);
|
||||||
@@ -619,7 +619,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
private static Card chooseCreature(final Player ai, CardCollection list) {
|
private static Card chooseCreature(final Player ai, CardCollection list) {
|
||||||
// Creating a new combat for testing purposes.
|
// Creating a new combat for testing purposes.
|
||||||
final Player opponent = ComputerUtil.getOpponentFor(ai);
|
final Player opponent = ai.getWeakestOpponent();
|
||||||
Combat combat = new Combat(opponent);
|
Combat combat = new Combat(opponent);
|
||||||
for (Card att : opponent.getCreaturesInPlay()) {
|
for (Card att : opponent.getCreaturesInPlay()) {
|
||||||
combat.addAttacker(att, ai);
|
combat.addAttacker(att, ai);
|
||||||
@@ -935,7 +935,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
&& !currCombat.getBlockers(attacker).isEmpty()) {
|
&& !currCombat.getBlockers(attacker).isEmpty()) {
|
||||||
ComputerUtilCard.sortByEvaluateCreature(blockers);
|
ComputerUtilCard.sortByEvaluateCreature(blockers);
|
||||||
Combat combat = new Combat(ai);
|
Combat combat = new Combat(ai);
|
||||||
combat.addAttacker(attacker, ComputerUtil.getOpponentFor(ai));
|
combat.addAttacker(attacker, ai.getWeakestOpponent());
|
||||||
for (Card blocker : blockers) {
|
for (Card blocker : blockers) {
|
||||||
combat.addBlocker(attacker, blocker);
|
combat.addBlocker(attacker, blocker);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.google.common.base.Predicates;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilAbility;
|
import forge.ai.ComputerUtilAbility;
|
||||||
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
@@ -127,7 +126,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
} else if (aiLogic.equals("Duneblast")) {
|
} else if (aiLogic.equals("Duneblast")) {
|
||||||
CardCollection aiCreatures = ai.getCreaturesInPlay();
|
CardCollection aiCreatures = ai.getCreaturesInPlay();
|
||||||
CardCollection oppCreatures = ComputerUtil.getOpponentFor(ai).getCreaturesInPlay();
|
CardCollection oppCreatures = ai.getWeakestOpponent().getCreaturesInPlay();
|
||||||
aiCreatures = CardLists.getNotKeyword(aiCreatures, Keyword.INDESTRUCTIBLE);
|
aiCreatures = CardLists.getNotKeyword(aiCreatures, Keyword.INDESTRUCTIBLE);
|
||||||
oppCreatures = CardLists.getNotKeyword(oppCreatures, Keyword.INDESTRUCTIBLE);
|
oppCreatures = CardLists.getNotKeyword(oppCreatures, Keyword.INDESTRUCTIBLE);
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class ChooseCardNameAi extends SpellAbilityAi {
|
|||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (tgt.canOnlyTgtOpponent()) {
|
if (tgt.canOnlyTgtOpponent()) {
|
||||||
sa.getTargets().add(ComputerUtil.getOpponentFor(ai));
|
sa.getTargets().add(ai.getWeakestOpponent());
|
||||||
} else {
|
} else {
|
||||||
sa.getTargets().add(ai);
|
sa.getTargets().add(ai);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class ChooseColorAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("Addle".equals(sourceName)) {
|
if ("Addle".equals(sourceName)) {
|
||||||
if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) || ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Hand).isEmpty()) {
|
if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) || ai.getWeakestOpponent().getCardsIn(ZoneType.Hand).isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -61,7 +61,7 @@ public class ChooseColorAi extends SpellAbilityAi {
|
|||||||
if (logic.equals("MostExcessOpponentControls")) {
|
if (logic.equals("MostExcessOpponentControls")) {
|
||||||
for (byte color : MagicColor.WUBRG) {
|
for (byte color : MagicColor.WUBRG) {
|
||||||
CardCollectionView ailist = ai.getCardsIn(ZoneType.Battlefield);
|
CardCollectionView ailist = ai.getCardsIn(ZoneType.Battlefield);
|
||||||
CardCollectionView opplist = ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Battlefield);
|
CardCollectionView opplist = ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield);
|
||||||
|
|
||||||
ailist = CardLists.filter(ailist, CardPredicates.isColor(color));
|
ailist = CardLists.filter(ailist, CardPredicates.isColor(color));
|
||||||
opplist = CardLists.filter(opplist, CardPredicates.isColor(color));
|
opplist = CardLists.filter(opplist, CardPredicates.isColor(color));
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -17,7 +16,7 @@ public class ChooseNumberAi extends SpellAbilityAi {
|
|||||||
TargetRestrictions tgt = sa.getTargetRestrictions();
|
TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
Player opp = ComputerUtil.getOpponentFor(aiPlayer);
|
Player opp = aiPlayer.getWeakestOpponent();
|
||||||
if (sa.canTarget(opp)) {
|
if (sa.canTarget(opp)) {
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(opp);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import com.google.common.base.Predicates;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilCombat;
|
import forge.ai.ComputerUtilCombat;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
@@ -68,7 +67,7 @@ public class ChooseSourceAi extends SpellAbilityAi {
|
|||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
if (sa.canTarget(opp)) {
|
if (sa.canTarget(opp)) {
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(opp);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package forge.ai.ability;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
@@ -30,7 +29,7 @@ public class ControlExchangeAi extends SpellAbilityAi {
|
|||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
CardCollection list =
|
CardCollection list =
|
||||||
CardLists.getValidCards(ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa);
|
CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa);
|
||||||
// AI won't try to grab cards that are filtered out of AI decks on
|
// AI won't try to grab cards that are filtered out of AI decks on
|
||||||
// purpose
|
// purpose
|
||||||
list = CardLists.filter(list, new Predicate<Card>() {
|
list = CardLists.filter(list, new Predicate<Card>() {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package forge.ai.ability;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
@@ -39,7 +38,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
|||||||
final boolean curse = sa.isCurse();
|
final boolean curse = sa.isCurse();
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
|
|
||||||
hList = CardLists.getValidCards(ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
hList = CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||||
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
cList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||||
|
|
||||||
if (abCost != null) {
|
if (abCost != null) {
|
||||||
@@ -68,7 +67,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
Player pl = curse ? ComputerUtil.getOpponentFor(ai) : ai;
|
Player pl = curse ? ai.getWeakestOpponent() : ai;
|
||||||
sa.getTargets().add(pl);
|
sa.getTargets().add(pl);
|
||||||
|
|
||||||
hList = CardLists.filterControlledBy(hList, pl);
|
hList = CardLists.filterControlledBy(hList, pl);
|
||||||
@@ -149,7 +148,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||||
return player.getCreaturesInPlay().size() >= ComputerUtil.getOpponentFor(player).getCreaturesInPlay().size();
|
return player.getCreaturesInPlay().size() >= player.getWeakestOpponent().getCreaturesInPlay().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCombat;
|
import forge.ai.ComputerUtilCombat;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
@@ -20,7 +19,7 @@ import forge.util.MyRandom;
|
|||||||
|
|
||||||
public abstract class DamageAiBase extends SpellAbilityAi {
|
public abstract class DamageAiBase extends SpellAbilityAi {
|
||||||
protected boolean avoidTargetP(final Player comp, final SpellAbility sa) {
|
protected boolean avoidTargetP(final Player comp, final SpellAbility sa) {
|
||||||
Player enemy = ComputerUtil.getOpponentFor(comp);
|
Player enemy = comp.getWeakestOpponent();
|
||||||
// Logic for cards that damage owner, like Fireslinger
|
// Logic for cards that damage owner, like Fireslinger
|
||||||
// Do not target a player if they aren't below 75% of our health.
|
// Do not target a player if they aren't below 75% of our health.
|
||||||
// Unless Lifelink will cancel the damage to us
|
// Unless Lifelink will cancel the damage to us
|
||||||
@@ -54,7 +53,7 @@ public abstract class DamageAiBase extends SpellAbilityAi {
|
|||||||
protected boolean shouldTgtP(final Player comp, final SpellAbility sa, final int d, final boolean noPrevention, final boolean noPlaneswalkerRedirection) {
|
protected boolean shouldTgtP(final Player comp, final SpellAbility sa, final int d, final boolean noPrevention, final boolean noPlaneswalkerRedirection) {
|
||||||
int restDamage = d;
|
int restDamage = d;
|
||||||
final Game game = comp.getGame();
|
final Game game = comp.getGame();
|
||||||
Player enemy = ComputerUtil.getOpponentFor(comp);
|
Player enemy = comp.getWeakestOpponent();
|
||||||
boolean dmgByCardsInHand = false;
|
boolean dmgByCardsInHand = false;
|
||||||
|
|
||||||
if ("X".equals(sa.getParam("NumDmg")) && sa.getHostCard() != null && sa.hasSVar(sa.getParam("NumDmg")) &&
|
if ("X".equals(sa.getParam("NumDmg")) && sa.getHostCard() != null && sa.hasSVar(sa.getParam("NumDmg")) &&
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ public class DamageAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate creatures getting killed
|
// Evaluate creatures getting killed
|
||||||
Player enemy = ComputerUtil.getOpponentFor(ai);
|
Player enemy = ai.getWeakestOpponent();
|
||||||
final CardCollection humanList = getKillableCreatures(sa, enemy, dmg);
|
final CardCollection humanList = getKillableCreatures(sa, enemy, dmg);
|
||||||
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
|
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
@@ -294,7 +294,7 @@ public class DamageAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate creatures getting killed
|
// Evaluate creatures getting killed
|
||||||
Player enemy = ComputerUtil.getOpponentFor(ai);
|
Player enemy = ai.getWeakestOpponent();
|
||||||
final CardCollection humanList = getKillableCreatures(sa, enemy, dmg);
|
final CardCollection humanList = getKillableCreatures(sa, enemy, dmg);
|
||||||
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
|
CardCollection computerList = getKillableCreatures(sa, ai, dmg);
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
final boolean oppTargetsChoice = sa.hasParam("TargetingPlayer");
|
final boolean oppTargetsChoice = sa.hasParam("TargetingPlayer");
|
||||||
final String logic = sa.getParamOrDefault("AILogic", "");
|
final String logic = sa.getParamOrDefault("AILogic", "");
|
||||||
|
|
||||||
Player enemy = ComputerUtil.getOpponentFor(ai);
|
Player enemy = ai.getWeakestOpponent();
|
||||||
|
|
||||||
if ("PowerDmg".equals(logic)) {
|
if ("PowerDmg".equals(logic)) {
|
||||||
// check if it is better to target the player instead, the original target is already set in PumpAi.pumpTgtAI()
|
// check if it is better to target the player instead, the original target is already set in PumpAi.pumpTgtAI()
|
||||||
@@ -876,7 +876,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
// this is for Triggered targets that are mandatory
|
// this is for Triggered targets that are mandatory
|
||||||
final boolean noPrevention = sa.hasParam("NoPrevention");
|
final boolean noPrevention = sa.hasParam("NoPrevention");
|
||||||
final boolean divided = sa.hasParam("DividedAsYouChoose");
|
final boolean divided = sa.hasParam("DividedAsYouChoose");
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
while (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
while (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
||||||
if (tgt.canTgtPlaneswalker()) {
|
if (tgt.canTgtPlaneswalker()) {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import com.google.common.base.Predicate;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
@@ -177,7 +176,7 @@ public class DebuffAi extends SpellAbilityAi {
|
|||||||
* @return a CardCollection.
|
* @return a CardCollection.
|
||||||
*/
|
*/
|
||||||
private CardCollection getCurseCreatures(final Player ai, final SpellAbility sa, final List<String> kws) {
|
private CardCollection getCurseCreatures(final Player ai, final SpellAbility sa, final List<String> kws) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
CardCollection list = CardLists.getTargetableCards(opp.getCreaturesInPlay(), sa);
|
CardCollection list = CardLists.getTargetableCards(opp.getCreaturesInPlay(), sa);
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
list = CardLists.filter(list, new Predicate<Card>() {
|
list = CardLists.filter(list, new Predicate<Card>() {
|
||||||
@@ -217,7 +216,7 @@ public class DebuffAi extends SpellAbilityAi {
|
|||||||
list.remove(c);
|
list.remove(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardCollection pref = CardLists.filterControlledBy(list, ComputerUtil.getOpponentFor(ai));
|
final CardCollection pref = CardLists.filterControlledBy(list, ai.getWeakestOpponent());
|
||||||
final CardCollection forced = CardLists.filterControlledBy(list, ai);
|
final CardCollection forced = CardLists.filterControlledBy(list, ai);
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ public class DestroyAi extends SpellAbilityAi {
|
|||||||
} else if (sa.hasParam("Defined")) {
|
} else if (sa.hasParam("Defined")) {
|
||||||
list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
||||||
if ("WillSkipTurn".equals(logic) && (sa.getHostCard().getController().equals(ai)
|
if ("WillSkipTurn".equals(logic) && (sa.getHostCard().getController().equals(ai)
|
||||||
|| ai.getCreaturesInPlay().size() < ComputerUtil.getOpponentFor(ai).getCreaturesInPlay().size()
|
|| ai.getCreaturesInPlay().size() < ai.getWeakestOpponent().getCreaturesInPlay().size()
|
||||||
|| !source.getGame().getPhaseHandler().isPlayerTurn(ai)
|
|| !source.getGame().getPhaseHandler().isPlayerTurn(ai)
|
||||||
|| ai.getLife() <= 5)) {
|
|| ai.getLife() <= 5)) {
|
||||||
// Basic ai logic for Lethal Vapors
|
// Basic ai logic for Lethal Vapors
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class DestroyAllAi extends SpellAbilityAi {
|
|||||||
public boolean doMassRemovalLogic(Player ai, SpellAbility sa) {
|
public boolean doMassRemovalLogic(Player ai, SpellAbility sa) {
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final String logic = sa.getParamOrDefault("AILogic", "");
|
final String logic = sa.getParamOrDefault("AILogic", "");
|
||||||
Player opponent = ComputerUtil.getOpponentFor(ai); // TODO: how should this AI logic work for multiplayer and getOpponents()?
|
Player opponent = ai.getWeakestOpponent(); // TODO: how should this AI logic work for multiplayer and getOpponents()?
|
||||||
|
|
||||||
final int CREATURE_EVAL_THRESHOLD = 200;
|
final int CREATURE_EVAL_THRESHOLD = 200;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class DigAi extends SpellAbilityAi {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
final Card host = sa.getHostCard();
|
final Card host = sa.getHostCard();
|
||||||
Player libraryOwner = ai;
|
Player libraryOwner = ai;
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ public class DigAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (mandatory && sa.canTarget(opp)) {
|
if (mandatory && sa.canTarget(opp)) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -36,7 +35,7 @@ public class DigUntilAi extends SpellAbilityAi {
|
|||||||
final boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
|
final boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
|
||||||
|
|
||||||
Player libraryOwner = ai;
|
Player libraryOwner = ai;
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
if ("DontMillSelf".equals(logic)) {
|
if ("DontMillSelf".equals(logic)) {
|
||||||
// A card that digs for specific things and puts everything revealed before it into graveyard
|
// A card that digs for specific things and puts everything revealed before it into graveyard
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class DiscardAi extends SpellAbilityAi {
|
|||||||
return SpecialCardAi.VolrathsShapeshifter.consider(ai, sa);
|
return SpecialCardAi.VolrathsShapeshifter.consider(ai, sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean humanHasHand = ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Hand).size() > 0;
|
final boolean humanHasHand = ai.getWeakestOpponent().getCardsIn(ZoneType.Hand).size() > 0;
|
||||||
|
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
if (!discardTargetAI(ai, sa)) {
|
if (!discardTargetAI(ai, sa)) {
|
||||||
@@ -87,7 +87,7 @@ public class DiscardAi extends SpellAbilityAi {
|
|||||||
if (sa.hasParam("NumCards")) {
|
if (sa.hasParam("NumCards")) {
|
||||||
if (sa.getParam("NumCards").equals("X") && source.getSVar("X").equals("Count$xPaid")) {
|
if (sa.getParam("NumCards").equals("X") && source.getSVar("X").equals("Count$xPaid")) {
|
||||||
// Set PayX here to maximum value.
|
// Set PayX here to maximum value.
|
||||||
final int cardsToDiscard = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), ComputerUtil.getOpponentFor(ai)
|
final int cardsToDiscard = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), ai.getWeakestOpponent()
|
||||||
.getCardsIn(ZoneType.Hand).size());
|
.getCardsIn(ZoneType.Hand).size());
|
||||||
if (cardsToDiscard < 1) {
|
if (cardsToDiscard < 1) {
|
||||||
return false;
|
return false;
|
||||||
@@ -172,7 +172,7 @@ public class DiscardAi extends SpellAbilityAi {
|
|||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
if (!discardTargetAI(ai, sa)) {
|
if (!discardTargetAI(ai, sa)) {
|
||||||
if (mandatory && sa.canTarget(opp)) {
|
if (mandatory && sa.canTarget(opp)) {
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(opp);
|
||||||
@@ -193,7 +193,7 @@ public class DiscardAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
if ("X".equals(sa.getParam("RevealNumber")) && sa.getHostCard().getSVar("X").equals("Count$xPaid")) {
|
if ("X".equals(sa.getParam("RevealNumber")) && sa.getHostCard().getSVar("X").equals("Count$xPaid")) {
|
||||||
// Set PayX here to maximum value.
|
// Set PayX here to maximum value.
|
||||||
final int cardsToDiscard = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), ComputerUtil.getOpponentFor(ai)
|
final int cardsToDiscard = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), ai.getWeakestOpponent()
|
||||||
.getCardsIn(ZoneType.Hand).size());
|
.getCardsIn(ZoneType.Hand).size());
|
||||||
sa.getHostCard().setSVar("PayX", Integer.toString(cardsToDiscard));
|
sa.getHostCard().setSVar("PayX", Integer.toString(cardsToDiscard));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -19,7 +18,7 @@ public class DrainManaAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
boolean randomReturn = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
||||||
|
|
||||||
if (tgt == null) {
|
if (tgt == null) {
|
||||||
@@ -41,7 +40,7 @@ public class DrainManaAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
@@ -82,7 +81,7 @@ public class DrainManaAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
sa.getTargets().add(ComputerUtil.getOpponentFor(ai));
|
sa.getTargets().add(ai.getWeakestOpponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomReturn;
|
return randomReturn;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class FogAi extends SpellAbilityAi {
|
|||||||
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
|
||||||
final Game game = aiPlayer.getGame();
|
final Game game = aiPlayer.getGame();
|
||||||
boolean chance;
|
boolean chance;
|
||||||
if (game.getPhaseHandler().isPlayerTurn(ComputerUtil.getOpponentFor(sa.getActivatingPlayer()))) {
|
if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer().getWeakestOpponent())) {
|
||||||
chance = game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE);
|
chance = game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_FIRST_STRIKE_DAMAGE);
|
||||||
} else {
|
} else {
|
||||||
chance = game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DAMAGE);
|
chance = game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DAMAGE);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -9,7 +8,7 @@ import forge.game.spellability.TargetRestrictions;
|
|||||||
public class GameLossAi extends SpellAbilityAi {
|
public class GameLossAi extends SpellAbilityAi {
|
||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
if (opp.cantLose()) {
|
if (opp.cantLose()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -34,15 +33,16 @@ public class GameLossAi extends SpellAbilityAi {
|
|||||||
// Phage the Untouchable
|
// Phage the Untouchable
|
||||||
// (Final Fortune would need to attach it's delayed trigger to a
|
// (Final Fortune would need to attach it's delayed trigger to a
|
||||||
// specific turn, which can't be done yet)
|
// specific turn, which can't be done yet)
|
||||||
|
Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
if (!mandatory && ComputerUtil.getOpponentFor(ai).cantLose()) {
|
if (!mandatory && opp.cantLose()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
sa.getTargets().add(ComputerUtil.getOpponentFor(ai));
|
sa.getTargets().add(opp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -20,7 +19,7 @@ public class LifeExchangeAi extends SpellAbilityAi {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||||
final int myLife = aiPlayer.getLife();
|
final int myLife = aiPlayer.getLife();
|
||||||
Player opponent = ComputerUtil.getOpponentFor(aiPlayer);
|
Player opponent = aiPlayer.getWeakestOpponent();
|
||||||
final int hLife = opponent.getLife();
|
final int hLife = opponent.getLife();
|
||||||
|
|
||||||
if (!aiPlayer.canGainLife()) {
|
if (!aiPlayer.canGainLife()) {
|
||||||
@@ -76,7 +75,7 @@ public class LifeExchangeAi extends SpellAbilityAi {
|
|||||||
final boolean mandatory) {
|
final boolean mandatory) {
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (sa.canTarget(opp) && (mandatory || ai.getLife() < opp.getLife())) {
|
if (sa.canTarget(opp) && (mandatory || ai.getLife() < opp.getLife())) {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public class LifeExchangeVariantAi extends SpellAbilityAi {
|
|||||||
final boolean mandatory) {
|
final boolean mandatory) {
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (sa.canTarget(opp) && (mandatory || ai.getLife() < opp.getLife())) {
|
if (sa.canTarget(opp) && (mandatory || ai.getLife() < opp.getLife())) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilAbility;
|
import forge.ai.ComputerUtilAbility;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
@@ -20,7 +19,7 @@ public class LifeSetAi extends SpellAbilityAi {
|
|||||||
// Ability_Cost abCost = sa.getPayCosts();
|
// Ability_Cost abCost = sa.getPayCosts();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final int myLife = ai.getLife();
|
final int myLife = ai.getLife();
|
||||||
final Player opponent = ComputerUtil.getOpponentFor(ai);
|
final Player opponent = ai.getWeakestOpponent();
|
||||||
final int hlife = opponent.getLife();
|
final int hlife = opponent.getLife();
|
||||||
final String amountStr = sa.getParam("LifeAmount");
|
final String amountStr = sa.getParam("LifeAmount");
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ public class LifeSetAi extends SpellAbilityAi {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
final int myLife = ai.getLife();
|
final int myLife = ai.getLife();
|
||||||
final Player opponent = ComputerUtil.getOpponentFor(ai);
|
final Player opponent = ai.getWeakestOpponent();
|
||||||
final int hlife = opponent.getLife();
|
final int hlife = opponent.getLife();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
|
final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa);
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class MustBlockAi extends SpellAbilityAi {
|
|||||||
boolean chance = false;
|
boolean chance = false;
|
||||||
|
|
||||||
if (abTgt != null) {
|
if (abTgt != null) {
|
||||||
final List<Card> list = determineGoodBlockers(definedAttacker, ai, ComputerUtil.getOpponentFor(ai), sa, true,true);
|
final List<Card> list = determineGoodBlockers(definedAttacker, ai, ai.getWeakestOpponent(), sa, true,true);
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package forge.ai.ability;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
@@ -31,7 +30,7 @@ public class PowerExchangeAi extends SpellAbilityAi {
|
|||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
List<Card> list =
|
List<Card> list =
|
||||||
CardLists.getValidCards(ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa);
|
CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa);
|
||||||
// AI won't try to grab cards that are filtered out of AI decks on
|
// AI won't try to grab cards that are filtered out of AI decks on
|
||||||
// purpose
|
// purpose
|
||||||
list = CardLists.filter(list, new Predicate<Card>() {
|
list = CardLists.filter(list, new Predicate<Card>() {
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ public class ProtectAi extends SpellAbilityAi {
|
|||||||
if (s==null) {
|
if (s==null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
Player opponent = ComputerUtil.getOpponentFor(ai);
|
Player opponent = ai.getWeakestOpponent();
|
||||||
Combat combat = ai.getGame().getCombat();
|
Combat combat = ai.getGame().getCombat();
|
||||||
int dmg = ComputerUtilCombat.damageIfUnblocked(c, opponent, combat, true);
|
int dmg = ComputerUtilCombat.damageIfUnblocked(c, opponent, combat, true);
|
||||||
float ratio = 1.0f * dmg / opponent.getLife();
|
float ratio = 1.0f * dmg / opponent.getLife();
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
final Combat combat = game.getCombat();
|
final Combat combat = game.getCombat();
|
||||||
final PhaseHandler ph = game.getPhaseHandler();
|
final PhaseHandler ph = game.getPhaseHandler();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
final int newPower = card.getNetCombatDamage() + attack;
|
final int newPower = card.getNetCombatDamage() + attack;
|
||||||
//int defense = getNumDefense(sa);
|
//int defense = getNumDefense(sa);
|
||||||
if (!CardUtil.isStackingKeyword(keyword) && card.hasKeyword(keyword)) {
|
if (!CardUtil.isStackingKeyword(keyword) && card.hasKeyword(keyword)) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class PumpAllAi extends PumpAiBase {
|
|||||||
valid = sa.getParam("ValidCards");
|
valid = sa.getParam("ValidCards");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
CardCollection comp = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
CardCollection comp = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||||
CardCollection human = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
CardCollection human = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid, source.getController(), source);
|
||||||
|
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ public class RearrangeTopOfLibraryAi extends SpellAbilityAi {
|
|||||||
// ability is targeted
|
// ability is targeted
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
Player opp = ComputerUtil.getOpponentFor(aiPlayer);
|
Player opp = aiPlayer.getWeakestOpponent();
|
||||||
final boolean canTgtAI = sa.canTarget(aiPlayer);
|
final boolean canTgtAI = sa.canTarget(aiPlayer);
|
||||||
final boolean canTgtHuman = sa.canTarget(opp);
|
final boolean canTgtHuman = sa.canTarget(opp);
|
||||||
|
|
||||||
if (canTgtHuman && canTgtAI) {
|
if (canTgtHuman && canTgtAI) {
|
||||||
// TODO: maybe some other consideration rather than random?
|
// TODO: maybe some other consideration rather than random?
|
||||||
Player preferredTarget = MyRandom.percentTrue(50) ? aiPlayer : opp;
|
Player preferredTarget = MyRandom.percentTrue(50) ? aiPlayer : opp;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class RepeatAi extends SpellAbilityAi {
|
|||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
if (!opp.canBeTargetedBy(sa)) {
|
if (!opp.canBeTargetedBy(sa)) {
|
||||||
@@ -49,7 +49,7 @@ public class RepeatAi extends SpellAbilityAi {
|
|||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
|
|
||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
if (sa.canTarget(opp)) {
|
if (sa.canTarget(opp)) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(opp);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
@@ -63,7 +62,7 @@ public class SacrificeAi extends SpellAbilityAi {
|
|||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final boolean destroy = sa.hasParam("Destroy");
|
final boolean destroy = sa.hasParam("Destroy");
|
||||||
|
|
||||||
Player opp = ComputerUtil.getOpponentFor(ai);
|
Player opp = ai.getWeakestOpponent();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (!opp.canBeTargetedBy(sa)) {
|
if (!opp.canBeTargetedBy(sa)) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
@@ -37,7 +36,7 @@ public class SacrificeAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CardCollection humanlist =
|
CardCollection humanlist =
|
||||||
CardLists.getValidCards(ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source, sa);
|
CardLists.getValidCards(ai.getWeakestOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source, sa);
|
||||||
CardCollection computerlist =
|
CardCollection computerlist =
|
||||||
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source, sa);
|
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), source.getController(), source, sa);
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
* @return a boolean.
|
* @return a boolean.
|
||||||
*/
|
*/
|
||||||
protected boolean tapPrefTargeting(final Player ai, final Card source, final TargetRestrictions tgt, final SpellAbility sa, final boolean mandatory) {
|
protected boolean tapPrefTargeting(final Player ai, final Card source, final TargetRestrictions tgt, final SpellAbility sa, final boolean mandatory) {
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
CardCollection tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
|
CardCollection tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents());
|
||||||
tapList = CardLists.getValidCards(tapList, tgt.getValidTgts(), source.getController(), source, sa);
|
tapList = CardLists.getValidCards(tapList, tgt.getValidTgts(), source.getController(), source, sa);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package forge.ai.ability;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCombat;
|
import forge.ai.ComputerUtilCombat;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
@@ -30,7 +29,7 @@ public class TapAllAi extends SpellAbilityAi {
|
|||||||
// or during upkeep/begin combat?
|
// or during upkeep/begin combat?
|
||||||
|
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
|
|
||||||
if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_BEGIN)) {
|
if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_BEGIN)) {
|
||||||
@@ -125,8 +124,9 @@ public class TapAllAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
sa.getTargets().add(ComputerUtil.getOpponentFor(ai));
|
Player opp = ai.getWeakestOpponent();
|
||||||
validTappables = ComputerUtil.getOpponentFor(ai).getCardsIn(ZoneType.Battlefield);
|
sa.getTargets().add(opp);
|
||||||
|
validTappables = opp.getCardsIn(ZoneType.Battlefield);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mandatory) {
|
if (mandatory) {
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final Game game = ai.getGame();
|
final Game game = ai.getGame();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||||
return false; // prevent infinite tokens?
|
return false; // prevent infinite tokens?
|
||||||
@@ -261,13 +261,13 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
num = (num == null) ? "1" : num;
|
num = (num == null) ? "1" : num;
|
||||||
final int nToSac = AbilityUtils.calculateAmount(topStack.getHostCard(), num, topStack);
|
final int nToSac = AbilityUtils.calculateAmount(topStack.getHostCard(), num, topStack);
|
||||||
CardCollection list = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","),
|
CardCollection list = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","),
|
||||||
ComputerUtil.getOpponentFor(ai), topStack.getHostCard(), sa);
|
ai.getWeakestOpponent(), topStack.getHostCard(), sa);
|
||||||
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
||||||
// only care about saving single creature for now
|
// only care about saving single creature for now
|
||||||
if (!list.isEmpty() && nTokens > 0 && list.size() == nToSac) {
|
if (!list.isEmpty() && nTokens > 0 && list.size() == nToSac) {
|
||||||
ComputerUtilCard.sortByEvaluateCreature(list);
|
ComputerUtilCard.sortByEvaluateCreature(list);
|
||||||
list.add(token);
|
list.add(token);
|
||||||
list = CardLists.getValidCards(list, valid.split(","), ComputerUtil.getOpponentFor(ai), topStack.getHostCard(), sa);
|
list = CardLists.getValidCards(list, valid.split(","), ai.getWeakestOpponent(), topStack.getHostCard(), sa);
|
||||||
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(topStack));
|
||||||
if (ComputerUtilCard.evaluateCreature(token) < ComputerUtilCard.evaluateCreature(list.get(0))
|
if (ComputerUtilCard.evaluateCreature(token) < ComputerUtilCard.evaluateCreature(list.get(0))
|
||||||
&& list.contains(token)) {
|
&& list.contains(token)) {
|
||||||
@@ -285,7 +285,7 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
if (tgt.canOnlyTgtOpponent()) {
|
if (tgt.canOnlyTgtOpponent()) {
|
||||||
sa.getTargets().add(ComputerUtil.getOpponentFor(ai));
|
sa.getTargets().add(ai.getWeakestOpponent());
|
||||||
} else {
|
} else {
|
||||||
sa.getTargets().add(ai);
|
sa.getTargets().add(ai);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package forge.ai.ability;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -29,7 +28,7 @@ public class TwoPilesAi extends SpellAbilityAi {
|
|||||||
valid = sa.getParam("ValidCards");
|
valid = sa.getParam("ValidCards");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
if (tgt != null) {
|
if (tgt != null) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import forge.ai.ComputerUtil;
|
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
@@ -65,7 +64,7 @@ public class UnattachAllAi extends SpellAbilityAi {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
final Card card = sa.getHostCard();
|
final Card card = sa.getHostCard();
|
||||||
final Player opp = ComputerUtil.getOpponentFor(ai);
|
final Player opp = ai.getWeakestOpponent();
|
||||||
// Check if there are any valid targets
|
// Check if there are any valid targets
|
||||||
List<GameObject> targets = new ArrayList<GameObject>();
|
List<GameObject> targets = new ArrayList<GameObject>();
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
Player targetController = ai;
|
Player targetController = ai;
|
||||||
|
|
||||||
if (sa.isCurse()) {
|
if (sa.isCurse()) {
|
||||||
targetController = ComputerUtil.getOpponentFor(ai);
|
targetController = ai.getWeakestOpponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa);
|
CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa);
|
||||||
|
|||||||
@@ -1,24 +1,13 @@
|
|||||||
package forge.ai.simulation;
|
package forge.ai.simulation;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.ai.LobbyPlayerAi;
|
import forge.ai.LobbyPlayerAi;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.game.Game;
|
import forge.game.*;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameObject;
|
|
||||||
import forge.game.GameObjectMap;
|
|
||||||
import forge.game.GameRules;
|
|
||||||
import forge.game.Match;
|
|
||||||
import forge.game.StaticEffect;
|
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.token.TokenInfo;
|
import forge.game.card.token.TokenInfo;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
@@ -28,13 +17,16 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.RegisteredPlayer;
|
import forge.game.player.RegisteredPlayer;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityRestriction;
|
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.PlayerZoneBattlefield;
|
import forge.game.zone.PlayerZoneBattlefield;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class GameCopier {
|
public class GameCopier {
|
||||||
private static final ZoneType[] ZONES = new ZoneType[] {
|
private static final ZoneType[] ZONES = new ZoneType[] {
|
||||||
ZoneType.Battlefield,
|
ZoneType.Battlefield,
|
||||||
@@ -323,7 +315,6 @@ public class GameCopier {
|
|||||||
}
|
}
|
||||||
if (c.isPlaneswalker()) {
|
if (c.isPlaneswalker()) {
|
||||||
for (SpellAbility sa : c.getAllSpellAbilities()) {
|
for (SpellAbility sa : c.getAllSpellAbilities()) {
|
||||||
SpellAbilityRestriction restrict = sa.getRestrictions();
|
|
||||||
int active = sa.getActivationsThisTurn();
|
int active = sa.getActivationsThisTurn();
|
||||||
if (sa.isPwAbility() && active > 0) {
|
if (sa.isPwAbility() && active > 0) {
|
||||||
SpellAbility newSa = findSAInCard(sa, newCard);
|
SpellAbility newSa = findSAInCard(sa, newCard);
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ public class GameSimulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiple opponents.
|
// TODO: Support multiple opponents.
|
||||||
Player opponent = ComputerUtil.getOpponentFor(aiPlayer);
|
Player opponent = aiPlayer.getWeakestOpponent();
|
||||||
resolveStack(simGame, opponent);
|
resolveStack(simGame, opponent);
|
||||||
|
|
||||||
// TODO: If this is during combat, before blockers are declared,
|
// TODO: If this is during combat, before blockers are declared,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-core</artifactId>
|
<artifactId>forge-core</artifactId>
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import forge.card.CardRules;
|
|||||||
import forge.card.CardSplitType;
|
import forge.card.CardSplitType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
public class ImageUtil {
|
public class ImageUtil {
|
||||||
public static float getNearestHQSize(float baseSize, float actualSize) {
|
public static float getNearestHQSize(float baseSize, float actualSize) {
|
||||||
//get nearest power of actualSize to baseSize so that the image renders good
|
//get nearest power of actualSize to baseSize so that the image renders good
|
||||||
@@ -46,9 +44,7 @@ public class ImageUtil {
|
|||||||
cntPictures = db.getPrintCount(card.getName(), edition);
|
cntPictures = db.getPrintCount(card.getName(), edition);
|
||||||
hasManyPictures = cntPictures > 1;
|
hasManyPictures = cntPictures > 1;
|
||||||
} else {
|
} else {
|
||||||
// without set number of pictures equals number of urls provided in Svar:Picture
|
cntPictures = 1;
|
||||||
String urls = card.getPictureUrl(backFace);
|
|
||||||
cntPictures = StringUtils.countMatches(urls, "\\") + 1;
|
|
||||||
|
|
||||||
// raise the art index limit to the maximum of the sets this card was printed in
|
// raise the art index limit to the maximum of the sets this card was printed in
|
||||||
int maxCntPictures = db.getMaxPrintCount(card.getName());
|
int maxCntPictures = db.getMaxPrintCount(card.getName());
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-game</artifactId>
|
<artifactId>forge-game</artifactId>
|
||||||
|
|||||||
@@ -17,18 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.card;
|
package forge.game.card;
|
||||||
|
|
||||||
import java.util.List;
|
import com.google.common.collect.*;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.common.collect.Table;
|
|
||||||
|
|
||||||
import io.sentry.Sentry;
|
|
||||||
import io.sentry.event.BreadcrumbBuilder;
|
|
||||||
|
|
||||||
import forge.ImageKeys;
|
import forge.ImageKeys;
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
@@ -40,14 +29,16 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.AbilityManaPart;
|
import forge.game.spellability.*;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.TargetRestrictions;
|
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
import forge.util.collect.FCollection;
|
import forge.util.collect.FCollection;
|
||||||
|
import io.sentry.Sentry;
|
||||||
|
import io.sentry.event.BreadcrumbBuilder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public final class CardUtil {
|
public final class CardUtil {
|
||||||
// disable instantiation
|
// disable instantiation
|
||||||
@@ -308,6 +299,15 @@ public final class CardUtil {
|
|||||||
newCopy.updateKeywordsCache(newCopy.getState(s));
|
newCopy.updateKeywordsCache(newCopy.getState(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newCopy.setKickerMagnitude(in.getKickerMagnitude());
|
||||||
|
|
||||||
|
for (OptionalCost ocost : in.getOptionalCostsPaid()) {
|
||||||
|
newCopy.addOptionalCostPaid(ocost);
|
||||||
|
}
|
||||||
|
|
||||||
|
newCopy.setCastSA(in.getCastSA());
|
||||||
|
newCopy.setCastFrom(in.getCastFrom());
|
||||||
|
|
||||||
return newCopy;
|
return newCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<packaging.type>jar</packaging.type>
|
<packaging.type>jar</packaging.type>
|
||||||
<build.min.memory>-Xms1024m</build.min.memory>
|
<build.min.memory>-Xms1024m</build.min.memory>
|
||||||
<build.max.memory>-Xmx1536m</build.max.memory>
|
<build.max.memory>-Xmx1536m</build.max.memory>
|
||||||
<alpha-version>1.6.25.001</alpha-version>
|
<alpha-version>1.6.26.001</alpha-version>
|
||||||
<sign.keystore>keystore</sign.keystore>
|
<sign.keystore>keystore</sign.keystore>
|
||||||
<sign.alias>alias</sign.alias>
|
<sign.alias>alias</sign.alias>
|
||||||
<sign.storepass>storepass</sign.storepass>
|
<sign.storepass>storepass</sign.storepass>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-android</artifactId>
|
<artifactId>forge-gui-android</artifactId>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-desktop</artifactId>
|
<artifactId>forge-gui-desktop</artifactId>
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ public enum FControl implements KeyEventDispatcher {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.getID() == KeyEvent.KEY_PRESSED && e.getModifiers() == InputEvent.ALT_MASK) {
|
else if (e.getID() == KeyEvent.KEY_PRESSED && e.getModifiersEx() == InputEvent.ALT_DOWN_MASK) {
|
||||||
altKeyLastDown = true;
|
altKeyLastDown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package forge.gui;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRules;
|
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
@@ -295,30 +294,10 @@ public class ImportSourceAnalyzer {
|
|||||||
// character mangling on some system locales, but we want to replicate the old code here exactly
|
// character mangling on some system locales, but we want to replicate the old code here exactly
|
||||||
return out.toString().toLowerCase();
|
return out.toString().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private void addDefaultPicNames(final PaperCard c, final boolean backFace) {
|
private void addDefaultPicNames(final PaperCard c, final boolean backFace) {
|
||||||
final CardRules card = c.getRules();
|
return;
|
||||||
final String urls = card.getPictureUrl(backFace);
|
|
||||||
if (StringUtils.isEmpty(urls)) { return; }
|
|
||||||
|
|
||||||
final int numPics = 1 + StringUtils.countMatches(urls, "\\");
|
|
||||||
if (c.getArtIndex() > numPics) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String filenameBase = ImageUtil.getImageKey(c, backFace, false);
|
|
||||||
final String filename = filenameBase + ".jpg";
|
|
||||||
final boolean alreadyHadIt = null != defaultPicNames.put(filename, filename);
|
|
||||||
if ( alreadyHadIt ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do you shift artIndex by one here?
|
|
||||||
final String newLastSymbol = 0 == c.getArtIndex() ? "" : String.valueOf(c.getArtIndex() /* + 1 */);
|
|
||||||
final String oldFilename = oldCleanString(filenameBase.replaceAll("[0-9]?(\\.full)?$", "")) + newLastSymbol + ".jpg";
|
|
||||||
//if ( numPics > 1 )
|
|
||||||
//System.out.printf("Will move %s -> %s%n", oldFilename, filename);
|
|
||||||
defaultPicOldNameToCurrentName.put(oldFilename, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class TextSearchFilter<T extends InventoryItem> extends ItemFilter<T> {
|
|||||||
itemManager.focus();
|
itemManager.focus();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.VK_ENTER:
|
case KeyEvent.VK_ENTER:
|
||||||
if (e.getModifiers() == 0) {
|
if (e.getModifiersEx() == 0) {
|
||||||
if (changeTimer.isRunning()) {
|
if (changeTimer.isRunning()) {
|
||||||
applyChange(); //apply change now if currently delayed
|
applyChange(); //apply change now if currently delayed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ public abstract class ItemView<T extends InventoryItem> {
|
|||||||
private boolean popupShowing = false;
|
private boolean popupShowing = false;
|
||||||
private Popup popup;
|
private Popup popup;
|
||||||
private Timer popupTimer;
|
private Timer popupTimer;
|
||||||
private static final int okModifiers = InputEvent.SHIFT_MASK | InputEvent.ALT_GRAPH_MASK;
|
private static final int okModifiers = InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK;
|
||||||
|
|
||||||
public IncrementalSearch() {
|
public IncrementalSearch() {
|
||||||
}
|
}
|
||||||
@@ -481,7 +481,7 @@ public abstract class ItemView<T extends InventoryItem> {
|
|||||||
//$FALL-THROUGH$
|
//$FALL-THROUGH$
|
||||||
default:
|
default:
|
||||||
// shift and/or alt-graph down is ok. anything else is a hotkey (e.g. ctrl-f)
|
// shift and/or alt-graph down is ok. anything else is a hotkey (e.g. ctrl-f)
|
||||||
if (okModifiers != (e.getModifiers() | okModifiers)
|
if (okModifiers != (e.getModifiersEx() | okModifiers)
|
||||||
|| !CharUtils.isAsciiPrintable(e.getKeyChar())) { // escape sneaks in here on Windows
|
|| !CharUtils.isAsciiPrintable(e.getKeyChar())) { // escape sneaks in here on Windows
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -585,7 +585,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addMoveItems(final String verb, final String dest) {
|
public void addMoveItems(final String verb, final String dest) {
|
||||||
addItems(verb, dest, false, 0, InputEvent.SHIFT_DOWN_MASK, InputEvent.ALT_MASK);
|
addItems(verb, dest, false, 0, InputEvent.SHIFT_DOWN_MASK, InputEvent.ALT_DOWN_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMoveAlternateItems(final String verb, final String dest) {
|
public void addMoveAlternateItems(final String verb, final String dest) {
|
||||||
@@ -596,7 +596,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
|||||||
addItems(verb, dest, true, InputEvent.CTRL_DOWN_MASK,
|
addItems(verb, dest, true, InputEvent.CTRL_DOWN_MASK,
|
||||||
//getMenuShortcutKeyMask() instead of CTRL_DOWN_MASK since on OSX, ctrl-shift-space brings up the window manager
|
//getMenuShortcutKeyMask() instead of CTRL_DOWN_MASK since on OSX, ctrl-shift-space brings up the window manager
|
||||||
InputEvent.SHIFT_DOWN_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(),
|
InputEvent.SHIFT_DOWN_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(),
|
||||||
InputEvent.ALT_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
|
InputEvent.ALT_DOWN_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public enum VCardScript implements IVDoc<CCardScript> {
|
|||||||
txtScript.setDocument(doc);
|
txtScript.setDocument(doc);
|
||||||
error = doc.addStyle("error", null);
|
error = doc.addStyle("error", null);
|
||||||
error.addAttribute(StyleConstants.Background, Color.red);
|
error.addAttribute(StyleConstants.Background, Color.red);
|
||||||
error.addAttribute(StyleConstants.Bold, new Boolean(true));
|
error.addAttribute(StyleConstants.Bold, Boolean.valueOf(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public JTextPane getTxtScript() {
|
public JTextPane getTxtScript() {
|
||||||
|
|||||||
@@ -200,8 +200,8 @@ public class FUndoManager extends UndoManager implements DocumentListener {
|
|||||||
public UndoAction() {
|
public UndoAction() {
|
||||||
putValue(Action.NAME, "Undo");
|
putValue(Action.NAME, "Undo");
|
||||||
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
|
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
|
||||||
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_U));
|
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_U));
|
||||||
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK));
|
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +229,8 @@ public class FUndoManager extends UndoManager implements DocumentListener {
|
|||||||
public RedoAction() {
|
public RedoAction() {
|
||||||
putValue(Action.NAME, "Redo");
|
putValue(Action.NAME, "Redo");
|
||||||
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
|
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
|
||||||
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_R));
|
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_R));
|
||||||
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK));
|
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK));
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1849,7 +1849,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
|
|
||||||
Card simSpark = (Card)sim.getGameCopier().find(sparkDouble);
|
Card simSpark = (Card)sim.getGameCopier().find(sparkDouble);
|
||||||
|
|
||||||
assertTrue(simSpark != null);
|
assertNotNull(simSpark);
|
||||||
assertTrue(simSpark.getZone().is(ZoneType.Battlefield));
|
assertTrue(simSpark.getZone().is(ZoneType.Battlefield));
|
||||||
assertTrue(simSpark.getCounters(CounterType.P1P1) == 1);
|
assertTrue(simSpark.getCounters(CounterType.P1P1) == 1);
|
||||||
assertTrue(simSpark.getCounters(CounterType.LOYALTY) == 5);
|
assertTrue(simSpark.getCounters(CounterType.LOYALTY) == 5);
|
||||||
@@ -1882,13 +1882,59 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
|
|
||||||
Card awakened = findCardWithName(sim.getSimulatedGameState(), "Vitu-Ghazi");
|
Card awakened = findCardWithName(sim.getSimulatedGameState(), "Vitu-Ghazi");
|
||||||
|
|
||||||
assertTrue(awakened != null);
|
assertNotNull(awakened);
|
||||||
assertTrue(awakened.getName().equals("Vitu-Ghazi"));
|
assertTrue(awakened.getName().equals("Vitu-Ghazi"));
|
||||||
assertTrue(awakened.getCounters(CounterType.P1P1) == 9);
|
assertTrue(awakened.getCounters(CounterType.P1P1) == 9);
|
||||||
assertTrue(awakened.hasKeyword(Keyword.HASTE));
|
assertTrue(awakened.hasKeyword(Keyword.HASTE));
|
||||||
assertTrue(awakened.getType().hasSubtype("Goblin"));
|
assertTrue(awakened.getType().hasSubtype("Goblin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNecroticOozeActivateOnce() {
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
|
||||||
|
for (int i=0; i<7; i++) { addCardToZone("Swamp", p, ZoneType.Battlefield); }
|
||||||
|
for (int i=0; i<7; i++) { addCardToZone("Forest", p, ZoneType.Battlefield); }
|
||||||
|
|
||||||
|
addCardToZone("Basking Rootwalla", p, ZoneType.Graveyard);
|
||||||
|
Card ooze = addCardToZone("Necrotic Ooze", p, ZoneType.Hand);
|
||||||
|
|
||||||
|
SpellAbility oozeSA = ooze.getFirstSpellAbility();
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
sim.simulateSpellAbility(oozeSA);
|
||||||
|
|
||||||
|
Card oozeOTB = findCardWithName(sim.getSimulatedGameState(), "Necrotic Ooze");
|
||||||
|
|
||||||
|
assertNotNull(oozeOTB);
|
||||||
|
|
||||||
|
SpellAbility copiedSA = findSAWithPrefix(oozeOTB, "{1}{G}:");
|
||||||
|
assertNotNull(copiedSA);
|
||||||
|
assertTrue(copiedSA.getRestrictions().getLimitToCheck().equals("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testEpochrasite() {
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||||
|
|
||||||
|
for (int i=0; i<7; i++) { addCardToZone("Swamp", p, ZoneType.Battlefield); }
|
||||||
|
|
||||||
|
Card epo = addCardToZone("Epochrasite", p, ZoneType.Graveyard);
|
||||||
|
Card animate = addCardToZone("Animate Dead", p, ZoneType.Hand);
|
||||||
|
|
||||||
|
SpellAbility saAnimate = animate.getFirstSpellAbility();
|
||||||
|
saAnimate.getTargets().add(epo);
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
sim.simulateSpellAbility(saAnimate);
|
||||||
|
|
||||||
|
Card epoOTB = findCardWithName(sim.getSimulatedGameState(), "Epochrasite");
|
||||||
|
|
||||||
|
assertNotNull(epoOTB);
|
||||||
|
assertTrue(epoOTB.getCounters(CounterType.P1P1) == 3);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void broken_testCloneDimir() {
|
public void broken_testCloneDimir() {
|
||||||
Game game = initAndCreateGame();
|
Game game = initAndCreateGame();
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
<packaging.type>jar</packaging.type>
|
<packaging.type>jar</packaging.type>
|
||||||
<build.min.memory>-Xms128m</build.min.memory>
|
<build.min.memory>-Xms128m</build.min.memory>
|
||||||
<build.max.memory>-Xmx2048m</build.max.memory>
|
<build.max.memory>-Xmx2048m</build.max.memory>
|
||||||
<alpha-version>1.6.25.001</alpha-version>
|
<alpha-version>1.6.26.001</alpha-version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-ios</artifactId>
|
<artifactId>forge-gui-ios</artifactId>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-mobile-dev</artifactId>
|
<artifactId>forge-gui-mobile-dev</artifactId>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui-mobile</artifactId>
|
<artifactId>forge-gui-mobile</artifactId>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import java.util.List;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
public class Forge implements ApplicationListener {
|
public class Forge implements ApplicationListener {
|
||||||
public static final String CURRENT_VERSION = "1.6.25.001";
|
public static final String CURRENT_VERSION = "1.6.26.001";
|
||||||
|
|
||||||
private static final ApplicationListener app = new Forge();
|
private static final ApplicationListener app = new Forge();
|
||||||
private static Clipboard clipboard;
|
private static Clipboard clipboard;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>forge</artifactId>
|
<artifactId>forge</artifactId>
|
||||||
<groupId>forge</groupId>
|
<groupId>forge</groupId>
|
||||||
<version>1.6.26-SNAPSHOT</version>
|
<version>1.6.27-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>forge-gui</artifactId>
|
<artifactId>forge-gui</artifactId>
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
- New Net Deck Category -
|
|
||||||
The Genetic Algorithm AI Decks category has been added to net decks. This contains decks generated using a genetic algorithm to try to find decks that the AI plays best in each format.
|
|
||||||
|
|
||||||
- Bug fixes -
|
- Bug fixes -
|
||||||
As always, this release of Forge features an assortment of bug fixes and improvements based on user feedback during the previous release run.
|
As always, this release of Forge features an assortment of bug fixes and improvements based on user feedback during the previous release run.
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ Name:Ajani's Pridemate
|
|||||||
ManaCost:1 W
|
ManaCost:1 W
|
||||||
Types:Creature Cat Soldier
|
Types:Creature Cat Soldier
|
||||||
PT:2/2
|
PT:2/2
|
||||||
T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | OptionalDecider$ You | TriggerDescription$ Whenever you gain life, you may put a +1/+1 counter on CARDNAME.
|
T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever you gain life, put a +1/+1 counter on CARDNAME.
|
||||||
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
SVar:TrigPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/ajanis_pridemate.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/ajanis_pridemate.jpg
|
||||||
DeckHints:Ability$LifeGain
|
DeckHints:Ability$LifeGain
|
||||||
DeckHas:Ability$Counters
|
DeckHas:Ability$Counters
|
||||||
Oracle:Whenever you gain life, you may put a +1/+1 counter on Ajani's Pridemate.
|
Oracle:Whenever you gain life, put a +1/+1 counter on Ajani's Pridemate.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:6 W
|
|||||||
Types:Sorcery
|
Types:Sorcery
|
||||||
T:Mode$ SpellCast | ValidCard$ Card.Self | Static$ True | Execute$ ApproachingSuns
|
T:Mode$ SpellCast | ValidCard$ Card.Self | Static$ True | Execute$ ApproachingSuns
|
||||||
SVar:ApproachingSuns:DB$ Effect | Name$ ApproachingSuns | Duration$ Permanent
|
SVar:ApproachingSuns:DB$ Effect | Name$ ApproachingSuns | Duration$ Permanent
|
||||||
A:SP$ Branch | Cost$ 6 W | References$ X,Y,Z | BranchConditionSVar$ X | BranchConditionSVarCompare$ EQ3 | TrueSubAbility$ WinGame | FalseSubAbility$ GainLife | SpellDescription$ If CARDNAME was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. Otherwise, put CARDNAME into its owner's library seventh from the top and you gain 7 life.
|
A:SP$ Branch | Cost$ 6 W | References$ X,Y,Z | BranchConditionSVar$ X | BranchConditionSVarCompare$ EQ3 | TrueSubAbility$ WinGame | FalseSubAbility$ GainLife | SpellDescription$ If this spell was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. Otherwise, put CARDNAME into its owner's library seventh from the top and you gain 7 life.
|
||||||
SVar:WinGame:DB$ WinsGame | Defined$ You
|
SVar:WinGame:DB$ WinsGame | Defined$ You
|
||||||
SVar:GainLife:DB$ GainLife | LifeAmount$ 7 | Defined$ You | SubAbility$ Reapproach
|
SVar:GainLife:DB$ GainLife | LifeAmount$ 7 | Defined$ You | SubAbility$ Reapproach
|
||||||
SVar:Reapproach:DB$ ChangeZone | Origin$ Stack | Destination$ Library | LibraryPosition$ 6 | Defined$ Self
|
SVar:Reapproach:DB$ ChangeZone | Origin$ Stack | Destination$ Library | LibraryPosition$ 6 | Defined$ Self
|
||||||
@@ -11,4 +11,4 @@ SVar:Y:Count$ValidCommand Effect.YouCtrl+namedApproachingSuns/LimitMax.2
|
|||||||
SVar:Z:Count$ValidStack Card.wasCastFromHand+Self/LimitMax.1
|
SVar:Z:Count$ValidStack Card.wasCastFromHand+Self/LimitMax.1
|
||||||
SVar:X:SVar$Y/Plus.Z
|
SVar:X:SVar$Y/Plus.Z
|
||||||
DeckNeeds:Name$Approach of the Second Sun
|
DeckNeeds:Name$Approach of the Second Sun
|
||||||
Oracle:If Approach of the Second Sun was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. Otherwise, put Approach of the Second Sun into its owner's library seventh from the top and you gain 7 life.
|
Oracle:If this spell was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. Otherwise, put Approach of the Second Sun into its owner's library seventh from the top and you gain 7 life.
|
||||||
@@ -2,7 +2,7 @@ Name:Artisan of Forms
|
|||||||
ManaCost:1 U
|
ManaCost:1 U
|
||||||
Types:Creature Human Wizard
|
Types:Creature Human Wizard
|
||||||
PT:1/1
|
PT:1/1
|
||||||
T:Mode$ SpellCast | ValidActivatingPlayer$ You | TargetsValid$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigArtisanCopy | TriggerDescription$ Heroic — Whenever you cast a spell that targets CARDNAME, you may have CARDNAME become a copy of target creature and gain this ability.
|
T:Mode$ SpellCast | ValidActivatingPlayer$ You | TargetsValid$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigArtisanCopy | TriggerDescription$ Heroic — Whenever you cast a spell that targets CARDNAME, you may have CARDNAME become a copy of target creature, except it has this ability.
|
||||||
SVar:TrigArtisanCopy:DB$ Clone | ValidTgts$ Creature | TgtPrompt$ Select target creature to copy | Optional$ True | GainThisAbility$ True | AddSVars$ TrigArtisanCopy | AILogic$ CloneBestCreature
|
SVar:TrigArtisanCopy:DB$ Clone | ValidTgts$ Creature | TgtPrompt$ Select target creature to copy | Optional$ True | GainThisAbility$ True | AddSVars$ TrigArtisanCopy | AILogic$ CloneBestCreature
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/artisan_of_forms.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/artisan_of_forms.jpg
|
||||||
Oracle:Heroic — Whenever you cast a spell that targets Artisan of Forms, you may have Artisan of Forms become a copy of target creature and gain this ability.
|
Oracle:Heroic — Whenever you cast a spell that targets Artisan of Forms, you may have Artisan of Forms become a copy of target creature, except it has this ability.
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ K:Kicker:1 G
|
|||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+kicked | Execute$ TrigKicker | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, destroy target land.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+kicked | Execute$ TrigKicker | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, destroy target land.
|
||||||
SVar:TrigKicker:DB$Destroy | ValidTgts$ Land | TgtPrompt$ Select target land
|
SVar:TrigKicker:DB$Destroy | ValidTgts$ Land | TgtPrompt$ Select target land
|
||||||
DeckHints:Color$Green
|
DeckHints:Color$Green
|
||||||
|
SVar:NeedsToPlayKicked:Land.OppCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/benalish_emissary.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/benalish_emissary.jpg
|
||||||
Oracle:Kicker {1}{G} (You may pay an additional {1}{G} as you cast this spell.)\nWhen Benalish Emissary enters the battlefield, if it was kicked, destroy target land.
|
Oracle:Kicker {1}{G} (You may pay an additional {1}{G} as you cast this spell.)\nWhen Benalish Emissary enters the battlefield, if it was kicked, destroy target land.
|
||||||
|
|||||||
@@ -4,5 +4,8 @@ Types:Sorcery
|
|||||||
K:Kicker:Sac<2/Land>
|
K:Kicker:Sac<2/Land>
|
||||||
A:SP$ Discard | Cost$ 2 B | ValidTgts$ Player | TgtPrompt$ Choose a player | NumCards$ WasKicked | References$ WasKicked | Mode$ TgtChoose | SpellDescription$ Target player discards two cards. If CARDNAME was kicked, that player discards three cards instead.
|
A:SP$ Discard | Cost$ 2 B | ValidTgts$ Player | TgtPrompt$ Choose a player | NumCards$ WasKicked | References$ WasKicked | Mode$ TgtChoose | SpellDescription$ Target player discards two cards. If CARDNAME was kicked, that player discards three cards instead.
|
||||||
SVar:WasKicked:Count$Kicked.3.2
|
SVar:WasKicked:Count$Kicked.3.2
|
||||||
|
SVar:NeedsToPlayKickedVar:Z GE3
|
||||||
|
SVar:Z:Count$ValidHand Card.OppCtrl
|
||||||
|
SVar:AIPreference:SacCost$Land.basic+YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/bog_down.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/bog_down.jpg
|
||||||
Oracle:Kicker—Sacrifice two lands. (You may sacrifice two lands in addition to any other costs as you cast this spell.)\nTarget player discards two cards. If this spell was kicked, that player discards three cards instead.
|
Oracle:Kicker—Sacrifice two lands. (You may sacrifice two lands in addition to any other costs as you cast this spell.)\nTarget player discards two cards. If this spell was kicked, that player discards three cards instead.
|
||||||
|
|||||||
@@ -5,4 +5,6 @@ PT:1/3
|
|||||||
K:Kicker:3 B
|
K:Kicker:3 B
|
||||||
T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked | Origin$ Any | Destination$ Battlefield | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, each opponent discards two cards.
|
T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked | Origin$ Any | Destination$ Battlefield | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, each opponent discards two cards.
|
||||||
SVar:TrigDiscard:DB$ Discard | Defined$ Player.Opponent | NumCards$ 2 | Mode$ TgtChoose
|
SVar:TrigDiscard:DB$ Discard | Defined$ Player.Opponent | NumCards$ 2 | Mode$ TgtChoose
|
||||||
|
SVar:NeedsToPlayKickedVar:Z GE1
|
||||||
|
SVar:Z:Count$ValidHand Card.OppCtrl
|
||||||
Oracle:Kicker {3}{B} (You may pay an additional {3}{B} as you cast this spell.)\nWhen Caligo Skin-Witch enters the battlefield, if it was kicked, each opponent discards two cards.
|
Oracle:Kicker {3}{B} (You may pay an additional {3}{B} as you cast this spell.)\nWhen Caligo Skin-Witch enters the battlefield, if it was kicked, each opponent discards two cards.
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ ManaCost:1 UB UB
|
|||||||
Types:Creature Shapeshifter
|
Types:Creature Shapeshifter
|
||||||
PT:1/2
|
PT:1/2
|
||||||
# Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone
|
# Make Svars for granting abilities and triggers on clones distinct to avoid SVars getting overwritten when cloning a clone
|
||||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature | TriggerZones$ Battlefield | Execute$ CemeteryPucaCopy | TriggerDescription$ Whenever a creature dies, you may pay {1}. If you do, CARDNAME becomes a copy of that creature and gains this ability.
|
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature | TriggerZones$ Battlefield | Execute$ CemeteryPucaCopy | TriggerDescription$ Whenever a creature dies, you may pay {1}. If you do, CARDNAME becomes a copy of that creature, except it has this ability.
|
||||||
SVar:CemeteryPucaCopy:AB$ Clone | Cost$ 1 | Defined$ TriggeredCardLKICopy | GainThisAbility$ True
|
SVar:CemeteryPucaCopy:AB$ Clone | Cost$ 1 | Defined$ TriggeredCardLKICopy | GainThisAbility$ True
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/cemetery_puca.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/cemetery_puca.jpg
|
||||||
Oracle:Whenever a creature dies, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability.
|
Oracle:Whenever a creature dies, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature, except it has this ability.
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ ManaCost:2 W
|
|||||||
Types:Creature Human Soldier
|
Types:Creature Human Soldier
|
||||||
PT:1/2
|
PT:1/2
|
||||||
K:Protection from black
|
K:Protection from black
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ All | AddKeyword$ Alternative Cost:0 | CheckSVar$ X | CheckSecondSVar$ Y | Description$ If an opponent controls a Swamp and you control a Plains, you may cast CARDNAME without paying its mana cost.
|
S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ All | AddKeyword$ Alternative Cost:0 | CheckSVar$ X | CheckSecondSVar$ Y | Description$ If an opponent controls a Swamp and you control a Plains, you may cast this spell without paying its mana cost.
|
||||||
SVar:X:Count$Valid Swamp.OppCtrl
|
SVar:X:Count$Valid Swamp.OppCtrl
|
||||||
SVar:Y:Count$Valid Plains.YouCtrl
|
SVar:Y:Count$Valid Plains.YouCtrl
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/cho_arrim_legate.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/cho_arrim_legate.jpg
|
||||||
Oracle:Protection from black\nIf an opponent controls a Swamp and you control a Plains, you may cast Cho-Arrim Legate without paying its mana cost.
|
Oracle:Protection from black\nIf an opponent controls a Swamp and you control a Plains, you may cast this spell without paying its mana cost.
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user