mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
ChangeZoneAllAi: fixed problem with return from exile Effects
also upated the Code using PlayerPredicates, with getOpponents instead of just one
This commit is contained in:
@@ -1,10 +1,18 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.ai.AiPlayerPredicates;
|
||||||
import forge.ai.ComputerUtil;
|
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;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
|
import forge.game.Game;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -16,19 +24,18 @@ import forge.game.cost.Cost;
|
|||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
|
import forge.game.player.PlayerPredicates;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class ChangeZoneAllAi extends SpellAbilityAi {
|
public class ChangeZoneAllAi extends SpellAbilityAi {
|
||||||
@Override
|
@Override
|
||||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||||
// Change Zone All, can be any type moving from one zone to another
|
// Change Zone All, can be any type moving from one zone to another
|
||||||
final Cost abCost = sa.getPayCosts();
|
final Cost abCost = sa.getPayCosts();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
final Game game = ai.getGame();
|
||||||
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
||||||
final ZoneType origin = ZoneType.listValueOf(sa.getParam("Origin")).get(0);
|
final ZoneType origin = ZoneType.listValueOf(sa.getParam("Origin")).get(0);
|
||||||
|
|
||||||
@@ -54,11 +61,14 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
// ex. "Return all Auras attached to target"
|
// ex. "Return all Auras attached to target"
|
||||||
// ex. "Return all blocking/blocked by target creature"
|
// ex. "Return all blocking/blocked by target creature"
|
||||||
|
|
||||||
final Player opp = ai.getOpponent();
|
CardCollectionView oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents());
|
||||||
final CardCollectionView humanType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
|
oppType = AbilityUtils.filterListByType(oppType, sa.getParam("ChangeType"), sa);
|
||||||
|
|
||||||
|
// final CardCollectionView humanType =
|
||||||
|
// AbilityUtils.filterListByType(opp.getCardsIn(origin),
|
||||||
|
// sa.getParam("ChangeType"), sa);
|
||||||
CardCollectionView computerType = ai.getCardsIn(origin);
|
CardCollectionView computerType = ai.getCardsIn(origin);
|
||||||
computerType = AbilityUtils.filterListByType(computerType, sa.getParam("ChangeType"), sa);
|
computerType = AbilityUtils.filterListByType(computerType, sa.getParam("ChangeType"), sa);
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
|
||||||
|
|
||||||
// Ugin AI: always try to sweep before considering +1
|
// Ugin AI: always try to sweep before considering +1
|
||||||
if (source.getName().equals("Ugin, the Spirit Dragon")) {
|
if (source.getName().equals("Ugin, the Spirit Dragon")) {
|
||||||
@@ -67,7 +77,8 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
Card single = null;
|
Card single = null;
|
||||||
for (int i = 0; i < loyalty; i++) {
|
for (int i = 0; i < loyalty; i++) {
|
||||||
source.setSVar("ChosenX", "Number$" + i);
|
source.setSVar("ChosenX", "Number$" + i);
|
||||||
final CardCollectionView oppType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
|
oppType = CardLists.filterControlledBy(game.getCardsIn(origin), ai.getOpponents());
|
||||||
|
oppType = AbilityUtils.filterListByType(oppType, sa.getParam("ChangeType"), sa);
|
||||||
computerType = AbilityUtils.filterListByType(ai.getCardsIn(origin), sa.getParam("ChangeType"), sa);
|
computerType = AbilityUtils.filterListByType(ai.getCardsIn(origin), sa.getParam("ChangeType"), sa);
|
||||||
int net = ComputerUtilCard.evaluatePermanentList(oppType) - ComputerUtilCard.evaluatePermanentList(computerType) - i;
|
int net = ComputerUtilCard.evaluatePermanentList(oppType) - ComputerUtilCard.evaluatePermanentList(computerType) - i;
|
||||||
if (net > best) {
|
if (net > best) {
|
||||||
@@ -116,13 +127,18 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
// TODO improve restrictions on when the AI would want to use this
|
// TODO improve restrictions on when the AI would want to use this
|
||||||
// spBounceAll has some AI we can compare to.
|
// spBounceAll has some AI we can compare to.
|
||||||
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
||||||
if (tgt != null) {
|
// search targetable Opponents
|
||||||
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
final Iterable<Player> oppList = Iterables.filter(ai.getOpponents(), PlayerPredicates.isTargetableBy(sa));
|
||||||
|| !opp.canBeTargetedBy(sa)) {
|
|
||||||
return false;
|
// get the one with the most handsize
|
||||||
}
|
Player oppTarget = Collections.max(Lists.newArrayList(oppList), PlayerPredicates.compareByZoneSize(origin));
|
||||||
|
|
||||||
|
// set the target
|
||||||
|
if (oppTarget != null && !oppTarget.getCardsIn(ZoneType.Hand).isEmpty()) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
sa.getTargets().add(opp);
|
sa.getTargets().add(oppTarget);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Battlefield)) {
|
} else if (origin.equals(ZoneType.Battlefield)) {
|
||||||
// this statement is assuming the AI is trying to use this spell
|
// this statement is assuming the AI is trying to use this spell
|
||||||
@@ -131,39 +147,60 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
// occur
|
// occur
|
||||||
// if only creatures are affected evaluate both lists and pass only
|
// if only creatures are affected evaluate both lists and pass only
|
||||||
// if human creatures are more valuable
|
// if human creatures are more valuable
|
||||||
if (tgt != null) {
|
if (sa.usesTargeting()) {
|
||||||
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
// search targetable Opponents
|
||||||
|| !opp.canBeTargetedBy(sa)) {
|
final Iterable<Player> oppList = Iterables.filter(ai.getOpponents(),
|
||||||
|
PlayerPredicates.isTargetableBy(sa));
|
||||||
|
|
||||||
|
// get the one with the most in graveyard
|
||||||
|
// zone is visible so evaluate which would be hurt the most
|
||||||
|
Player oppTarget = Collections.max(Lists.newArrayList(oppList),
|
||||||
|
PlayerPredicates.compareByZoneSize(origin));
|
||||||
|
|
||||||
|
// set the target
|
||||||
|
if (oppTarget != null && !oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty()) {
|
||||||
|
sa.resetTargets();
|
||||||
|
sa.getTargets().add(oppTarget);
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sa.resetTargets();
|
|
||||||
sa.getTargets().add(opp);
|
|
||||||
computerType = new CardCollection();
|
computerType = new CardCollection();
|
||||||
}
|
}
|
||||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
if ((CardLists.getNotType(oppType, "Creature").size() == 0)
|
||||||
|
&& (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
if ((ComputerUtilCard.evaluateCreatureList(computerType) + 200) >= ComputerUtilCard
|
if ((ComputerUtilCard.evaluateCreatureList(computerType) + 200) >= ComputerUtilCard
|
||||||
.evaluateCreatureList(humanType)) {
|
.evaluateCreatureList(oppType)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // otherwise evaluate both lists by CMC and pass only if human
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
// permanents are more valuable
|
// permanents are more valuable
|
||||||
else if ((ComputerUtilCard.evaluatePermanentList(computerType) + 3) >= ComputerUtilCard
|
else if ((ComputerUtilCard.evaluatePermanentList(computerType) + 3) >= ComputerUtilCard
|
||||||
.evaluatePermanentList(humanType)) {
|
.evaluatePermanentList(oppType)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't cast during main1?
|
// Don't cast during main1?
|
||||||
if (ai.getGame().getPhaseHandler().is(PhaseType.MAIN1, ai)) {
|
if (game.getPhaseHandler().is(PhaseType.MAIN1, ai)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Graveyard)) {
|
} else if (origin.equals(ZoneType.Graveyard)) {
|
||||||
if (tgt != null) {
|
if (sa.usesTargeting()) {
|
||||||
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|
// search targetable Opponents
|
||||||
|| !opp.canBeTargetedBy(sa)) {
|
final Iterable<Player> oppList = Iterables.filter(ai.getOpponents(),
|
||||||
|
PlayerPredicates.isTargetableBy(sa));
|
||||||
|
|
||||||
|
// get the one with the most in graveyard
|
||||||
|
// zone is visible so evaluate which would be hurt the most
|
||||||
|
Player oppTarget = Collections.max(Lists.newArrayList(oppList),
|
||||||
|
AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa));
|
||||||
|
|
||||||
|
// set the target
|
||||||
|
if (oppTarget != null && !oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty()) {
|
||||||
|
sa.resetTargets();
|
||||||
|
sa.getTargets().add(oppTarget);
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sa.resetTargets();
|
|
||||||
sa.getTargets().add(opp);
|
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Exile)) {
|
} else if (origin.equals(ZoneType.Exile)) {
|
||||||
|
|
||||||
@@ -178,28 +215,30 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
if (destination.equals(ZoneType.Battlefield)) {
|
if (destination.equals(ZoneType.Battlefield)) {
|
||||||
if (sa.getParam("GainControl") != null) {
|
if (sa.getParam("GainControl") != null) {
|
||||||
// Check if the cards are valuable enough
|
// Check if the cards are valuable enough
|
||||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
if ((CardLists.getNotType(oppType, "Creature").size() == 0)
|
||||||
|
&& (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
if ((ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard
|
if ((ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard
|
||||||
.evaluateCreatureList(humanType)) < 400) {
|
.evaluateCreatureList(oppType)) < 400) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // otherwise evaluate both lists by CMC and pass only if human
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
// permanents are less valuable
|
// permanents are less valuable
|
||||||
else if ((ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard
|
else if ((ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard
|
||||||
.evaluatePermanentList(humanType)) < 6) {
|
.evaluatePermanentList(oppType)) < 6) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// don't activate if human gets more back than AI does
|
// don't activate if human gets more back than AI does
|
||||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
if ((CardLists.getNotType(oppType, "Creature").size() == 0)
|
||||||
|
&& (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
if (ComputerUtilCard.evaluateCreatureList(computerType) <= (ComputerUtilCard
|
if (ComputerUtilCard.evaluateCreatureList(computerType) <= (ComputerUtilCard
|
||||||
.evaluateCreatureList(humanType) + 100)) {
|
.evaluateCreatureList(oppType) + 100)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // otherwise evaluate both lists by CMC and pass only if human
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
// permanents are less valuable
|
// permanents are less valuable
|
||||||
else if (ComputerUtilCard.evaluatePermanentList(computerType) <= (ComputerUtilCard
|
else if (ComputerUtilCard.evaluatePermanentList(computerType) <= (ComputerUtilCard
|
||||||
.evaluatePermanentList(humanType) + 2)) {
|
.evaluatePermanentList(oppType) + 2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,28 +299,37 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
protected boolean doTriggerAINoCost(Player ai, final SpellAbility sa, boolean mandatory) {
|
||||||
// Change Zone All, can be any type moving from one zone to another
|
// Change Zone All, can be any type moving from one zone to another
|
||||||
|
|
||||||
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
||||||
final ZoneType origin = ZoneType.listValueOf(sa.getParam("Origin")).get(0);
|
final ZoneType origin = ZoneType.listValueOf(sa.getParam("Origin")).get(0);
|
||||||
|
|
||||||
final Player opp = ai.getOpponent();
|
CardCollectionView humanType = CardLists.filterControlledBy(ai.getGame().getCardsIn(origin), ai.getOpponents());
|
||||||
final CardCollectionView humanType = AbilityUtils.filterListByType(opp.getCardsIn(origin), sa.getParam("ChangeType"), sa);
|
humanType = AbilityUtils.filterListByType(humanType, sa.getParam("ChangeType"), sa);
|
||||||
|
|
||||||
CardCollectionView computerType = ai.getCardsIn(origin);
|
CardCollectionView computerType = ai.getCardsIn(origin);
|
||||||
computerType = AbilityUtils.filterListByType(computerType, sa.getParam("ChangeType"), sa);
|
computerType = AbilityUtils.filterListByType(computerType, sa.getParam("ChangeType"), sa);
|
||||||
|
|
||||||
// TODO improve restrictions on when the AI would want to use this
|
// TODO improve restrictions on when the AI would want to use this
|
||||||
// spBounceAll has some AI we can compare to.
|
// spBounceAll has some AI we can compare to.
|
||||||
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
if (sa.usesTargeting()) {
|
||||||
if (tgt != null) {
|
// search targetable Opponents
|
||||||
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
final Iterable<Player> oppList = Iterables.filter(ai.getOpponents(),
|
||||||
|| !opp.canBeTargetedBy(sa)) {
|
PlayerPredicates.isTargetableBy(sa));
|
||||||
|
|
||||||
|
// get the one with the most handsize
|
||||||
|
Player oppTarget = Collections.max(Lists.newArrayList(oppList),
|
||||||
|
PlayerPredicates.compareByZoneSize(origin));
|
||||||
|
|
||||||
|
// set the target
|
||||||
|
if (oppTarget != null && !oppTarget.getCardsIn(ZoneType.Hand).isEmpty()) {
|
||||||
|
sa.resetTargets();
|
||||||
|
sa.getTargets().add(oppTarget);
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sa.resetTargets();
|
|
||||||
sa.getTargets().add(opp);
|
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Battlefield)) {
|
} else if (origin.equals(ZoneType.Battlefield)) {
|
||||||
// this statement is assuming the AI is trying to use this spell offensively
|
// this statement is assuming the AI is trying to use this spell offensively
|
||||||
@@ -300,14 +348,23 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Graveyard)) {
|
} else if (origin.equals(ZoneType.Graveyard)) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
if (sa.usesTargeting()) {
|
||||||
if (tgt != null) {
|
// search targetable Opponents
|
||||||
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|
final Iterable<Player> oppList = Iterables.filter(ai.getOpponents(),
|
||||||
|| !opp.canBeTargetedBy(sa)) {
|
PlayerPredicates.isTargetableBy(sa));
|
||||||
|
|
||||||
|
// get the one with the most in graveyard
|
||||||
|
// zone is visible so evaluate which would be hurt the most
|
||||||
|
Player oppTarget = Collections.max(Lists.newArrayList(oppList),
|
||||||
|
AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa));
|
||||||
|
|
||||||
|
// set the target
|
||||||
|
if (oppTarget != null && !oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty()) {
|
||||||
|
sa.resetTargets();
|
||||||
|
sa.getTargets().add(oppTarget);
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sa.resetTargets();
|
|
||||||
sa.getTargets().add(opp);
|
|
||||||
}
|
}
|
||||||
} else if (origin.equals(ZoneType.Exile)) {
|
} else if (origin.equals(ZoneType.Exile)) {
|
||||||
|
|
||||||
@@ -320,6 +377,10 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (destination.equals(ZoneType.Battlefield)) {
|
if (destination.equals(ZoneType.Battlefield)) {
|
||||||
|
// if mandatory, no need to evaluate
|
||||||
|
if (mandatory) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (sa.getParam("GainControl") != null) {
|
if (sa.getParam("GainControl") != null) {
|
||||||
// Check if the cards are valuable enough
|
// Check if the cards are valuable enough
|
||||||
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user