mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
moved a method from ai to effect class (because the code being moved does not take decisions)
This commit is contained in:
@@ -2,7 +2,6 @@ package forge.ai.ability;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@@ -18,15 +17,12 @@ import forge.ai.ComputerUtilCombat;
|
|||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.card.CardCharacteristicName;
|
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.GlobalRuleChange;
|
import forge.game.GlobalRuleChange;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.AttachEffect;
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
@@ -41,9 +37,7 @@ import forge.game.player.PlayerActionConfirmMode;
|
|||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.trigger.TriggerType;
|
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
public class ChangeZoneAi extends SpellAbilityAi {
|
public class ChangeZoneAi extends SpellAbilityAi {
|
||||||
@@ -1088,172 +1082,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static Card chooseCardToHiddenOriginChangeZone(ZoneType destination, List<ZoneType> origin, SpellAbility sa, List<Card> fetchList, Player player, final Player decider) {
|
||||||
* <p>
|
|
||||||
* changeHiddenOriginResolveAI.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* a {@link forge.game.ability.AbilityFactory} object.
|
|
||||||
* @param sa
|
|
||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
|
||||||
* @param player
|
|
||||||
* a {@link forge.game.player.Player} object.
|
|
||||||
* @param changeNum2
|
|
||||||
* @param destination
|
|
||||||
* @param fetchList
|
|
||||||
* @param libraryPos2
|
|
||||||
* @param origin2
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static List<Card> hiddenOriginResolveAI(final Player decider, final SpellAbility sa, Player player, int changeNum, List<ZoneType> origin, ZoneType destination, List<Card> fetchList, int libraryPos) {
|
|
||||||
|
|
||||||
final Card source = sa.getSourceCard();
|
|
||||||
final boolean defined = sa.hasParam("Defined");
|
|
||||||
final Game game = decider.getGame();
|
|
||||||
|
|
||||||
final List<Card> movedCards = new ArrayList<Card>();
|
|
||||||
final boolean remember = sa.hasParam("RememberChanged");
|
|
||||||
final boolean forget = sa.hasParam("ForgetChanged");
|
|
||||||
final boolean champion = sa.hasParam("Champion");
|
|
||||||
final boolean imprint = sa.hasParam("Imprint");
|
|
||||||
final String totalcmc = sa.getParam("WithTotalCMC");
|
|
||||||
int totcmc = AbilityUtils.calculateAmount(source, totalcmc, sa);
|
|
||||||
|
|
||||||
for (int i = 0; i < changeNum; i++) {
|
|
||||||
if (sa.hasParam("DifferentNames")) {
|
|
||||||
for (Card c : movedCards) {
|
|
||||||
fetchList = CardLists.filter(fetchList, Predicates.not(CardPredicates.nameEquals(c.getName())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (totalcmc != null) {
|
|
||||||
if (totcmc >= 0) {
|
|
||||||
fetchList = CardLists.getValidCards(fetchList, "Card.cmcLE" + Integer.toString(totcmc), decider, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((fetchList.size() == 0) || (destination == null)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Improve the AI for fetching.
|
|
||||||
Card c = null;
|
|
||||||
if (sa.hasParam("AtRandom")) {
|
|
||||||
c = Aggregates.random(fetchList);
|
|
||||||
} else if (defined) {
|
|
||||||
c = fetchList.get(0);
|
|
||||||
} else {
|
|
||||||
c = chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
|
||||||
}
|
|
||||||
|
|
||||||
movedCards.add(c);
|
|
||||||
fetchList.remove(c);
|
|
||||||
if (totalcmc != null) {
|
|
||||||
totcmc -= c.getCMC();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Card c : movedCards) {
|
|
||||||
Card movedCard = null;
|
|
||||||
if (ZoneType.Library.equals(destination)) {
|
|
||||||
movedCard = game.getAction().moveToLibrary(c, libraryPos);
|
|
||||||
} else if (ZoneType.Battlefield.equals(destination)) {
|
|
||||||
if (sa.hasParam("Tapped")) {
|
|
||||||
c.setTapped(true);
|
|
||||||
}
|
|
||||||
if (sa.hasParam("GainControl")) {
|
|
||||||
Player newController = sa.getActivatingPlayer();
|
|
||||||
if (sa.hasParam("NewController")) {
|
|
||||||
newController = AbilityUtils.getDefinedPlayers(sa.getSourceCard(), sa.getParam("NewController"), sa).get(0);
|
|
||||||
}
|
|
||||||
c.setController(newController, game.getNextTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa.hasParam("AttachedTo")) {
|
|
||||||
List<Card> list = AbilityUtils.getDefinedCards(sa.getSourceCard(),
|
|
||||||
sa.getParam("AttachedTo"), sa);
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
list = game.getCardsIn(ZoneType.Battlefield);
|
|
||||||
list = CardLists.getValidCards(list, sa.getParam("AttachedTo"), c.getController(), c);
|
|
||||||
}
|
|
||||||
if (!list.isEmpty()) {
|
|
||||||
final Card attachedTo = ComputerUtilCard.getBestAI(list);
|
|
||||||
if (c.isEnchanting()) {
|
|
||||||
// If this Card is already Enchanting something, need
|
|
||||||
// to unenchant it, then clear out the commands
|
|
||||||
final GameEntity oldEnchanted = c.getEnchanting();
|
|
||||||
c.removeEnchanting(oldEnchanted);
|
|
||||||
}
|
|
||||||
c.enchantEntity(attachedTo);
|
|
||||||
} else { // When it should enter the battlefield attached to an illegal permanent it fails
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa.hasParam("Attacking")) {
|
|
||||||
final Combat combat = game.getCombat();
|
|
||||||
if ( null != combat ) {
|
|
||||||
final List<GameEntity> e = combat.getDefenders();
|
|
||||||
final GameEntity defender = player.getController().chooseSingleEntityForEffect(e, sa, "Declare " + c);
|
|
||||||
combat.addAttacker(c, defender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sa.hasParam("Blocking")) {
|
|
||||||
final Combat combat = game.getCombat();
|
|
||||||
if ( null != combat ) {
|
|
||||||
List<Card> attackers = AbilityUtils.getDefinedCards(source, sa.getParam("Blocking"), sa);
|
|
||||||
if (!attackers.isEmpty()) {
|
|
||||||
Card attacker = attackers.get(0);
|
|
||||||
if (combat.isAttacking(attacker)) {
|
|
||||||
combat.addBlocker(attacker, c);
|
|
||||||
combat.orderAttackersForDamageAssignment(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Auras without Candidates stay in their current location
|
|
||||||
if (c.isAura()) {
|
|
||||||
final SpellAbility saAura = AttachEffect.getAttachSpellAbility(c);
|
|
||||||
if (!saAura.getTargetRestrictions().hasCandidates(saAura, false)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
movedCard = game.getAction().moveTo(c.getController().getZone(destination), c);
|
|
||||||
if (sa.hasParam("Tapped")) {
|
|
||||||
movedCard.setTapped(true);
|
|
||||||
}
|
|
||||||
} else if (destination.equals(ZoneType.Exile)) {
|
|
||||||
movedCard = game.getAction().exile(c);
|
|
||||||
if (sa.hasParam("ExileFaceDown")) {
|
|
||||||
movedCard.setState(CardCharacteristicName.FaceDown);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
movedCard = game.getAction().moveTo(destination, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (champion) {
|
|
||||||
final HashMap<String, Object> runParams = new HashMap<String, Object>();
|
|
||||||
runParams.put("Card", source);
|
|
||||||
runParams.put("Championed", c);
|
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.Championed, runParams, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remember) {
|
|
||||||
source.addRemembered(movedCard);
|
|
||||||
}
|
|
||||||
if (forget) {
|
|
||||||
source.removeRemembered(movedCard);
|
|
||||||
}
|
|
||||||
// for imprinted since this doesn't use Target
|
|
||||||
if (imprint) {
|
|
||||||
source.addImprinted(movedCard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return movedCards;
|
|
||||||
} // end changeHiddenOriginResolveAI
|
|
||||||
|
|
||||||
private static Card chooseCardToHiddenOriginChangeZone(ZoneType destination, List<ZoneType> origin, SpellAbility sa, List<Card> fetchList, Player player, final Player decider) {
|
|
||||||
|
|
||||||
String type = sa.getParam("ChangeType");
|
String type = sa.getParam("ChangeType");
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ 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.ComputerUtilCard;
|
||||||
import forge.ai.ability.ChangeZoneAi;
|
import forge.ai.ability.ChangeZoneAi;
|
||||||
import forge.card.CardCharacteristicName;
|
import forge.card.CardCharacteristicName;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
@@ -714,7 +715,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
if (decider.isHuman()) {
|
if (decider.isHuman()) {
|
||||||
movedCards = changeHiddenOriginResolveHuman(decider, sa, player, changeNum, origin, destination, fetchList, libraryPos);
|
movedCards = changeHiddenOriginResolveHuman(decider, sa, player, changeNum, origin, destination, fetchList, libraryPos);
|
||||||
} else {
|
} else {
|
||||||
movedCards = ChangeZoneAi.hiddenOriginResolveAI(decider, sa, player, changeNum, origin, destination, fetchList, libraryPos);
|
movedCards = hiddenOriginResolveAI(decider, sa, player, changeNum, origin, destination, fetchList, libraryPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((!ZoneType.Battlefield.equals(destination) && changeType != null && !defined)
|
if (((!ZoneType.Battlefield.equals(destination) && changeType != null && !defined)
|
||||||
@@ -728,7 +729,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Card> changeHiddenOriginResolveHuman(final Player decider, final SpellAbility sa, Player player, int changeNum, List<ZoneType> origin, ZoneType destination, List<Card> fetchList, int libraryPos) {
|
private List<Card> changeHiddenOriginResolveHuman(final Player decider, final SpellAbility sa, Player player, int changeNum, List<ZoneType> origin, ZoneType destination, List<Card> fetchList, int libraryPos) {
|
||||||
final Card source = sa.getSourceCard();
|
final Card source = sa.getSourceCard();
|
||||||
final Game game = player.getGame();
|
final Game game = player.getGame();
|
||||||
|
|
||||||
@@ -915,6 +916,156 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
return movedCards;
|
return movedCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<Card> hiddenOriginResolveAI(final Player decider, final SpellAbility sa, Player player, int changeNum, List<ZoneType> origin, ZoneType destination, List<Card> fetchList, int libraryPos) {
|
||||||
|
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final boolean defined = sa.hasParam("Defined");
|
||||||
|
final Game game = decider.getGame();
|
||||||
|
|
||||||
|
final List<Card> movedCards = new ArrayList<Card>();
|
||||||
|
final boolean remember = sa.hasParam("RememberChanged");
|
||||||
|
final boolean forget = sa.hasParam("ForgetChanged");
|
||||||
|
final boolean champion = sa.hasParam("Champion");
|
||||||
|
final boolean imprint = sa.hasParam("Imprint");
|
||||||
|
final String totalcmc = sa.getParam("WithTotalCMC");
|
||||||
|
int totcmc = AbilityUtils.calculateAmount(source, totalcmc, sa);
|
||||||
|
|
||||||
|
for (int i = 0; i < changeNum; i++) {
|
||||||
|
if (sa.hasParam("DifferentNames")) {
|
||||||
|
for (Card c : movedCards) {
|
||||||
|
fetchList = CardLists.filter(fetchList, Predicates.not(CardPredicates.nameEquals(c.getName())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (totalcmc != null) {
|
||||||
|
if (totcmc >= 0) {
|
||||||
|
fetchList = CardLists.getValidCards(fetchList, "Card.cmcLE" + Integer.toString(totcmc), decider, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((fetchList.size() == 0) || (destination == null)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Improve the AI for fetching.
|
||||||
|
Card c = null;
|
||||||
|
if (sa.hasParam("AtRandom")) {
|
||||||
|
c = Aggregates.random(fetchList);
|
||||||
|
} else if (defined) {
|
||||||
|
c = fetchList.get(0);
|
||||||
|
} else {
|
||||||
|
c = ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
||||||
|
}
|
||||||
|
|
||||||
|
movedCards.add(c);
|
||||||
|
fetchList.remove(c);
|
||||||
|
if (totalcmc != null) {
|
||||||
|
totcmc -= c.getCMC();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Card c : movedCards) {
|
||||||
|
Card movedCard = null;
|
||||||
|
if (ZoneType.Library.equals(destination)) {
|
||||||
|
movedCard = game.getAction().moveToLibrary(c, libraryPos);
|
||||||
|
} else if (ZoneType.Battlefield.equals(destination)) {
|
||||||
|
if (sa.hasParam("Tapped")) {
|
||||||
|
c.setTapped(true);
|
||||||
|
}
|
||||||
|
if (sa.hasParam("GainControl")) {
|
||||||
|
Player newController = sa.getActivatingPlayer();
|
||||||
|
if (sa.hasParam("NewController")) {
|
||||||
|
newController = AbilityUtils.getDefinedPlayers(sa.getSourceCard(), sa.getParam("NewController"), sa).get(0);
|
||||||
|
}
|
||||||
|
c.setController(newController, game.getNextTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("AttachedTo")) {
|
||||||
|
List<Card> list = AbilityUtils.getDefinedCards(sa.getSourceCard(),
|
||||||
|
sa.getParam("AttachedTo"), sa);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
list = game.getCardsIn(ZoneType.Battlefield);
|
||||||
|
list = CardLists.getValidCards(list, sa.getParam("AttachedTo"), c.getController(), c);
|
||||||
|
}
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
final Card attachedTo = ComputerUtilCard.getBestAI(list);
|
||||||
|
if (c.isEnchanting()) {
|
||||||
|
// If this Card is already Enchanting something, need
|
||||||
|
// to unenchant it, then clear out the commands
|
||||||
|
final GameEntity oldEnchanted = c.getEnchanting();
|
||||||
|
c.removeEnchanting(oldEnchanted);
|
||||||
|
}
|
||||||
|
c.enchantEntity(attachedTo);
|
||||||
|
} else { // When it should enter the battlefield attached to an illegal permanent it fails
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("Attacking")) {
|
||||||
|
final Combat combat = game.getCombat();
|
||||||
|
if ( null != combat ) {
|
||||||
|
final List<GameEntity> e = combat.getDefenders();
|
||||||
|
final GameEntity defender = player.getController().chooseSingleEntityForEffect(e, sa, "Declare " + c);
|
||||||
|
combat.addAttacker(c, defender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sa.hasParam("Blocking")) {
|
||||||
|
final Combat combat = game.getCombat();
|
||||||
|
if ( null != combat ) {
|
||||||
|
List<Card> attackers = AbilityUtils.getDefinedCards(source, sa.getParam("Blocking"), sa);
|
||||||
|
if (!attackers.isEmpty()) {
|
||||||
|
Card attacker = attackers.get(0);
|
||||||
|
if (combat.isAttacking(attacker)) {
|
||||||
|
combat.addBlocker(attacker, c);
|
||||||
|
combat.orderAttackersForDamageAssignment(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Auras without Candidates stay in their current location
|
||||||
|
if (c.isAura()) {
|
||||||
|
final SpellAbility saAura = AttachEffect.getAttachSpellAbility(c);
|
||||||
|
if (!saAura.getTargetRestrictions().hasCandidates(saAura, false)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
movedCard = game.getAction().moveTo(c.getController().getZone(destination), c);
|
||||||
|
if (sa.hasParam("Tapped")) {
|
||||||
|
movedCard.setTapped(true);
|
||||||
|
}
|
||||||
|
} else if (destination.equals(ZoneType.Exile)) {
|
||||||
|
movedCard = game.getAction().exile(c);
|
||||||
|
if (sa.hasParam("ExileFaceDown")) {
|
||||||
|
movedCard.setState(CardCharacteristicName.FaceDown);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
movedCard = game.getAction().moveTo(destination, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (champion) {
|
||||||
|
final HashMap<String, Object> runParams = new HashMap<String, Object>();
|
||||||
|
runParams.put("Card", source);
|
||||||
|
runParams.put("Championed", c);
|
||||||
|
game.getTriggerHandler().runTrigger(TriggerType.Championed, runParams, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remember) {
|
||||||
|
source.addRemembered(movedCard);
|
||||||
|
}
|
||||||
|
if (forget) {
|
||||||
|
source.removeRemembered(movedCard);
|
||||||
|
}
|
||||||
|
// for imprinted since this doesn't use Target
|
||||||
|
if (imprint) {
|
||||||
|
source.addImprinted(movedCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return movedCards;
|
||||||
|
} // end changeHiddenOriginResolveAI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* removeFromStack.
|
* removeFromStack.
|
||||||
|
|||||||
Reference in New Issue
Block a user