Optimize the logic around for attaching cards to other cards/players

This commit is contained in:
drdev
2014-10-06 15:12:02 +00:00
parent 5bfd8462b9
commit 44664bd30e
40 changed files with 438 additions and 617 deletions

View File

@@ -715,21 +715,19 @@ public class ComputerUtil {
} }
Card c; Card c;
if (CardLists.getNotType(remaining, "Creature").size() == 0) { if (CardLists.getNotType(remaining, "Creature").size() == 0) {
c = ComputerUtilCard.getWorstCreatureAI(remaining); c = ComputerUtilCard.getWorstCreatureAI(remaining);
} else if (CardLists.getNotType(remaining, "Land").size() == 0) { }
else if (CardLists.getNotType(remaining, "Land").size() == 0) {
c = ComputerUtilCard.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS)); c = ComputerUtilCard.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS));
} else { }
else {
c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false); c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false);
} }
final ArrayList<Card> auras = c.getEnchantedBy(); if (c.isEnchanted()) {
if (auras.size() > 0) {
// TODO: choose "worst" controlled enchanting Aura // TODO: choose "worst" controlled enchanting Aura
for (int j = 0; j < auras.size(); j++) { for (Card aura : c.getEnchantedBy(false)) {
final Card aura = auras.get(j);
if (aura.getController().equals(c.getController()) && remaining.contains(aura)) { if (aura.getController().equals(c.getController()) && remaining.contains(aura)) {
return aura; return aura;
} }

View File

@@ -716,8 +716,10 @@ public class ComputerUtilCard {
int curCMC = card.getCMC(); int curCMC = card.getCMC();
// Add all cost of all auras with the same controller // Add all cost of all auras with the same controller
final List<Card> auras = CardLists.filterControlledBy(card.getEnchantedBy(), card.getController()); if (card.isEnchanted()) {
curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size(); final List<Card> auras = CardLists.filterControlledBy(card.getEnchantedBy(false), card.getController());
curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size();
}
if (curCMC >= bigCMC) { if (curCMC >= bigCMC) {
bigCMC = curCMC; bigCMC = curCMC;
@@ -1040,7 +1042,7 @@ public class ComputerUtilCard {
} }
if (c.isEnchanted()) { if (c.isEnchanted()) {
boolean myEnchants = false; boolean myEnchants = false;
for (Card enc : c.getEnchantedBy()) { for (Card enc : c.getEnchantedBy(false)) {
if (enc.getOwner().equals(ai)) { if (enc.getOwner().equals(ai)) {
myEnchants = true; myEnchants = true;
break; break;

View File

@@ -419,10 +419,12 @@ public class ComputerUtilCombat {
public static int totalDamageOfBlockers(final Card attacker, final List<Card> defenders) { public static int totalDamageOfBlockers(final Card attacker, final List<Card> defenders) {
int damage = 0; int damage = 0;
for (Card equipment : attacker.getEquippedBy()) { if (attacker.isEquipped()) {
if (equipment.getName().equals("Godsend") && !defenders.isEmpty()) { for (Card equipment : attacker.getEquippedBy(false)) {
defenders.remove(0); if (equipment.getName().equals("Godsend") && !defenders.isEmpty()) {
} defenders.remove(0);
}
}
} }
for (final Card defender : defenders) { for (final Card defender : defenders) {
@@ -439,7 +441,7 @@ public class ComputerUtilCombat {
public static int totalFirstStrikeDamageOfBlockers(final Card attacker, final List<Card> defenders) { public static int totalFirstStrikeDamageOfBlockers(final Card attacker, final List<Card> defenders) {
int damage = 0; int damage = 0;
for (Card equipment : attacker.getEquippedBy()) { for (Card equipment : attacker.getEquippedBy(false)) {
if (equipment.getName().equals("Godsend") && !defenders.isEmpty()) { if (equipment.getName().equals("Godsend") && !defenders.isEmpty()) {
defenders.remove(0); defenders.remove(0);
} }
@@ -1567,10 +1569,12 @@ public class ComputerUtilCombat {
return false; return false;
} }
for (Card equipment : defender.getEquippedBy()) { if (defender.isEquipped()) {
if (equipment.getName().equals("Godsend")) { for (Card equipment : defender.getEquippedBy(false)) {
return true; if (equipment.getName().equals("Godsend")) {
} return true;
}
}
} }
int flankingMagnitude = 0; int flankingMagnitude = 0;
@@ -1599,10 +1603,12 @@ public class ComputerUtilCombat {
return true; return true;
} }
for (Card equipment : attacker.getEquippedBy()) { if (attacker.isEquipped()) {
if (equipment.getName().equals("Godsend")) { for (Card equipment : attacker.getEquippedBy(false)) {
return false; if (equipment.getName().equals("Godsend")) {
} return false;
}
}
} }
if (attacker.hasKeyword("PreventAllDamageBy Creature.blockingSource")) { if (attacker.hasKeyword("PreventAllDamageBy Creature.blockingSource")) {
@@ -1729,10 +1735,12 @@ public class ComputerUtilCombat {
final boolean withoutAbilities) { final boolean withoutAbilities) {
final Game game = ai.getGame(); final Game game = ai.getGame();
for (Card equipment : attacker.getEquippedBy()) { if (attacker.isEquipped()) {
if (equipment.getName().equals("Godsend")) { for (Card equipment : attacker.getEquippedBy(false)) {
return true; if (equipment.getName().equals("Godsend")) {
} return true;
}
}
} }
int flankingMagnitude = 0; int flankingMagnitude = 0;
@@ -1761,10 +1769,12 @@ public class ComputerUtilCombat {
return true; return true;
} }
for (Card equipment : defender.getEquippedBy()) { if (defender.isEquipped()) {
if (equipment.getName().equals("Godsend")) { for (Card equipment : defender.getEquippedBy(false)) {
return false; if (equipment.getName().equals("Godsend")) {
} return false;
}
}
} }
int defenderDamage = defender.getNetAttack() int defenderDamage = defender.getNetAttack()

View File

@@ -16,7 +16,6 @@ import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@@ -249,8 +248,7 @@ public class ComputerUtilCost {
if (!important) { if (!important) {
return false; return false;
} }
List<Card> auras = new ArrayList<Card>(source.getEnchantedBy()); if (!CardLists.filterControlledBy(source.getEnchantedBy(false), source.getController()).isEmpty()) {
if (!CardLists.filterControlledBy(auras, source.getController()).isEmpty()) {
return false; return false;
} }
continue; continue;

View File

@@ -1118,7 +1118,7 @@ public class ComputerUtilMana {
&& replacementEffect.zonesCheck(game.getZoneOf(crd))) { && replacementEffect.zonesCheck(game.getZoneOf(crd))) {
String repType = crd.getSVar(replacementEffect.getMapParams().get("ManaReplacement")); String repType = crd.getSVar(replacementEffect.getMapParams().get("ManaReplacement"));
if (repType.contains("Chosen")) { if (repType.contains("Chosen")) {
repType = repType.replace("Chosen", MagicColor.toShortString(crd.getChosenColors().get(0))); repType = repType.replace("Chosen", MagicColor.toShortString(crd.getChosenColor()));
} }
mp.setManaReplaceType(repType); mp.setManaReplaceType(repType);
} }

View File

@@ -325,9 +325,9 @@ public class AnimateAi extends SpellAbilityAi {
if (sa.hasParam("Colors")) { if (sa.hasParam("Colors")) {
final String colors = sa.getParam("Colors"); final String colors = sa.getParam("Colors");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(source.getChosenColors()); tmpDesc = CardUtil.getShortColorsString(source.getChosenColors());
} else { }
else {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(",")))); tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(","))));
} }
} }

View File

@@ -211,7 +211,7 @@ public class AttachAi extends SpellAbilityAi {
return true; return true;
} }
final ArrayList<Card> auras = c.getEnchantedBy(); final Iterable<Card> auras = c.getEnchantedBy(false);
final Iterator<Card> itr = auras.iterator(); final Iterator<Card> itr = auras.iterator();
while (itr.hasNext()) { while (itr.hasNext()) {
final Card aura = itr.next(); final Card aura = itr.next();
@@ -626,9 +626,10 @@ public class AttachAi extends SpellAbilityAi {
prefList = CardLists.filter(prefList, new Predicate<Card>() { prefList = CardLists.filter(prefList, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
for (Card aura : c.getEnchantedBy()) { for (Card aura : c.getEnchantedBy(false)) {
if (aura.getName().equals(attachSource.getName())) if (aura.getName().equals(attachSource.getName())) {
return false; return false;
}
} }
return true; return true;
} }
@@ -684,9 +685,10 @@ public class AttachAi extends SpellAbilityAi {
} }
// don't equip creatures that don't gain anything // don't equip creatures that don't gain anything
if (card.hasSVar("NonStackingAttachEffect")) { if (card.hasSVar("NonStackingAttachEffect")) {
for (Card equipment : newTarget.getEquippedBy()) { for (Card equipment : newTarget.getEquippedBy(false)) {
if (equipment.getName().equals(card.getName())) if (equipment.getName().equals(card.getName())) {
return false; return false;
}
} }
} }
} }
@@ -907,13 +909,19 @@ public class AttachAi extends SpellAbilityAi {
prefList = CardLists.filter(prefList, new Predicate<Card>() { prefList = CardLists.filter(prefList, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
for (Card equipment : c.getEquippedBy()) { if (c.isEquipped()) {
if (equipment.getName().equals(attachSource.getName())) for (Card equipment : c.getEquippedBy(false)) {
return false; if (equipment.getName().equals(attachSource.getName())) {
return false;
}
}
} }
for (Card aura : c.getEnchantedBy()) { if (c.isEnchanted()) {
if (aura.getName().equals(attachSource.getName())) for (Card aura : c.getEnchantedBy(false)) {
return false; if (aura.getName().equals(attachSource.getName())) {
return false;
}
}
} }
return true; return true;
} }

View File

@@ -811,7 +811,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
list = CardLists.filter(list, new Predicate<Card>() { list = CardLists.filter(list, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
for (Card aura : c.getEnchantedBy()) { for (Card aura : c.getEnchantedBy(false)) {
if (aura.getController().isOpponentOf(ai)) { if (aura.getController().isOpponentOf(ai)) {
return true; return true;
} else { } else {
@@ -885,7 +885,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
list = CardLists.filter(list, new Predicate<Card>() { list = CardLists.filter(list, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
for (Card aura : c.getEnchantedBy()) { for (Card aura : c.getEnchantedBy(false)) {
if (c.getOwner().isOpponentOf(ai) && aura.getController().equals(ai)) { if (c.getOwner().isOpponentOf(ai) && aura.getController().equals(ai)) {
return false; return false;
} }

View File

@@ -78,7 +78,7 @@ public class CountersPutAi extends SpellAbilityAi {
if (sa.hasParam("LevelUp")) { if (sa.hasParam("LevelUp")) {
// creatures enchanted by curse auras have low priority // creatures enchanted by curse auras have low priority
if (source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) { if (source.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)) {
for (Card aura : source.getEnchantedBy()) { for (Card aura : source.getEnchantedBy(false)) {
if (aura.getController().isOpponentOf(ai)) { if (aura.getController().isOpponentOf(ai)) {
return false; return false;
} }

View File

@@ -175,7 +175,7 @@ public class DestroyAi extends SpellAbilityAi {
} else { } else {
// Don't destroy stolen permanents when the stealing aura can be destroyed // Don't destroy stolen permanents when the stealing aura can be destroyed
if (choice.getOwner() == ai) { if (choice.getOwner() == ai) {
for (Card aura : choice.getEnchantedBy()) { for (Card aura : choice.getEnchantedBy(false)) {
SpellAbility sp = aura.getFirstSpellAbility(); SpellAbility sp = aura.getFirstSpellAbility();
if (sp != null && "GainControl".equals(sp.getParam("AILogic")) if (sp != null && "GainControl".equals(sp.getParam("AILogic"))
&& aura.getController() != ai && sa.canTarget(aura)) { && aura.getController() != ai && sa.canTarget(aura)) {

View File

@@ -296,7 +296,7 @@ public class TokenAi extends SpellAbilityAi {
for (int i = 0; i < substitutedColors.length; i++) { for (int i = 0; i < substitutedColors.length; i++) {
if (substitutedColors[i].equals("ChosenColor")) { if (substitutedColors[i].equals("ChosenColor")) {
// this currently only supports 1 chosen color // this currently only supports 1 chosen color
substitutedColors[i] = host.getChosenColors().get(0); substitutedColors[i] = host.getChosenColor();
} }
} }
String colorDesc = ""; String colorDesc = "";

View File

@@ -336,8 +336,7 @@ public class GameAction {
private void unattachCardLeavingBattlefield(Card copied) { private void unattachCardLeavingBattlefield(Card copied) {
// Handle unequipping creatures // Handle unequipping creatures
if (copied.isEquipped()) { if (copied.isEquipped()) {
final List<Card> equipments = new ArrayList<Card>(copied.getEquippedBy()); for (final Card equipment : copied.getEquippedBy(true)) {
for (final Card equipment : equipments) {
if (equipment.isInPlay()) { if (equipment.isInPlay()) {
equipment.unEquipCard(copied); equipment.unEquipCard(copied);
} }
@@ -345,8 +344,7 @@ public class GameAction {
} }
// Handle unfortifying lands // Handle unfortifying lands
if (copied.isFortified()) { if (copied.isFortified()) {
final List<Card> fortifications = new ArrayList<Card>(copied.getFortifiedBy()); for (final Card f : copied.getFortifiedBy(true)) {
for (final Card f : fortifications) {
if (f.isInPlay()) { if (f.isInPlay()) {
f.unFortifyCard(copied); f.unFortifyCard(copied);
} }
@@ -368,8 +366,7 @@ public class GameAction {
} }
// remove enchantments from creatures // remove enchantments from creatures
if (copied.isEnchanted()) { if (copied.isEnchanted()) {
final List<Card> auras = new ArrayList<Card>(copied.getEnchantedBy()); for (final Card aura : copied.getEnchantedBy(true)) {
for (final Card aura : auras) {
aura.unEnchantEntity(copied); aura.unEnchantEntity(copied);
} }
} }
@@ -1012,16 +1009,10 @@ public class GameAction {
return checkAgain; return checkAgain;
} }
/**
* TODO: Write javadoc for this method.
* @param c
* @return
*/
private boolean stateBasedAction704_5p(Card c) { private boolean stateBasedAction704_5p(Card c) {
boolean checkAgain = false; boolean checkAgain = false;
if (c.isEquipped()) { if (c.isEquipped()) {
final List<Card> equipments = new ArrayList<Card>(c.getEquippedBy()); for (final Card equipment : c.getEquippedBy(true)) {
for (final Card equipment : equipments) {
if (!equipment.isInPlay()) { if (!equipment.isInPlay()) {
equipment.unEquipCard(c); equipment.unEquipCard(c);
checkAgain = true; checkAgain = true;
@@ -1030,8 +1021,7 @@ public class GameAction {
} // if isEquipped() } // if isEquipped()
if (c.isFortified()) { if (c.isFortified()) {
final List<Card> fortifications = new ArrayList<Card>(c.getFortifiedBy()); for (final Card f : c.getFortifiedBy(true)) {
for (final Card f : fortifications) {
if (!f.isInPlay()) { if (!f.isInPlay()) {
f.unFortifyCard(c); f.unFortifyCard(c);
checkAgain = true; checkAgain = true;
@@ -1363,7 +1353,7 @@ public class GameAction {
} }
if (c.isEnchanted()) { if (c.isEnchanted()) {
for (Card e : c.getEnchantedBy()) { for (Card e : c.getEnchantedBy(false)) {
CardFactoryUtil.refreshTotemArmor(e); CardFactoryUtil.refreshTotemArmor(e);
} }
} }

View File

@@ -21,420 +21,186 @@ import forge.game.card.Card;
import forge.game.event.GameEventCardAttachment; import forge.game.event.GameEventCardAttachment;
import forge.game.event.GameEventCardAttachment.AttachMethod; import forge.game.event.GameEventCardAttachment.AttachMethod;
import java.util.ArrayList; import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
/**
* <p>
* Abstract Player class.
* </p>
*
* @author Forge
* @version $Id: Player.java 10091 2011-08-30 16:11:21Z Sloth $
*/
public abstract class GameEntity extends GameObject { public abstract class GameEntity extends GameObject {
private String name = ""; private String name = "";
private int preventNextDamage = 0; private int preventNextDamage = 0;
private LinkedHashSet<Card> enchantedBy;
private TreeMap<Card, Map<String, String>> preventionShieldsWithEffects = new TreeMap<Card, Map<String, String>>(); private TreeMap<Card, Map<String, String>> preventionShieldsWithEffects = new TreeMap<Card, Map<String, String>>();
/** The enchanted by. */
private ArrayList<Card> enchantedBy = new ArrayList<Card>();
/**
* <p>
* Getter for the field <code>name</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public String getName() { public String getName() {
return this.name; return name;
} }
/**
* <p>
* Setter for the field <code>name</code>.
* </p>
*
* @param s
* a {@link java.lang.String} object.
*/
public void setName(final String s) { public void setName(final String s) {
this.name = s; name = s;
} }
// ////////////////////////
//
// methods for handling damage
//
// ////////////////////////
/**
* <p>
* addDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @return whether or not damage was dealt
*/
public boolean addDamage(final int damage, final Card source) { public boolean addDamage(final int damage, final Card source) {
int damageToDo = damage; int damageToDo = damage;
damageToDo = this.replaceDamage(damageToDo, source, false); damageToDo = replaceDamage(damageToDo, source, false);
damageToDo = this.preventDamage(damageToDo, source, false); damageToDo = preventDamage(damageToDo, source, false);
return this.addDamageAfterPrevention(damageToDo, source, false); return addDamageAfterPrevention(damageToDo, source, false);
} }
/**
* <p>
* addDamageWithoutPrevention.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @return whether or not damage was dealt
*/
public boolean addDamageWithoutPrevention(final int damage, final Card source) { public boolean addDamageWithoutPrevention(final int damage, final Card source) {
int damageToDo = damage; int damageToDo = replaceDamage(damage, source, false);
return addDamageAfterPrevention(damageToDo, source, false);
damageToDo = this.replaceDamage(damageToDo, source, false);
return this.addDamageAfterPrevention(damageToDo, source, false);
} }
// This function handles damage after replacement and prevention effects are // This function handles damage after replacement and prevention effects are applied
// applied
/**
* <p>
* addDamageAfterPrevention.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @param isCombat
* a boolean.
* @return whether or not damage was dealt
*/
public abstract boolean addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat); public abstract boolean addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat);
// This should be also usable by the AI to forecast an effect (so it must // This should be also usable by the AI to forecast an effect (so it must
// not change the game state) // not change the game state)
/**
* <p>
* staticDamagePrevention.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat, final boolean isTest) { public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat, final boolean isTest) {
return 0; return 0;
} }
// This should be also usable by the AI to forecast an effect (so it must // This should be also usable by the AI to forecast an effect (so it must
// not change the game state) // not change the game state)
/**
* <p>
* staticReplaceDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public int staticReplaceDamage(final int damage, final Card source, final boolean isCombat) { public int staticReplaceDamage(final int damage, final Card source, final boolean isCombat) {
return 0; return 0;
} }
/**
* <p>
* replaceDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public abstract int replaceDamage(final int damage, final Card source, final boolean isCombat); public abstract int replaceDamage(final int damage, final Card source, final boolean isCombat);
/**
* <p>
* preventDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.game.card.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public abstract int preventDamage(final int damage, final Card source, final boolean isCombat); public abstract int preventDamage(final int damage, final Card source, final boolean isCombat);
// ////////////////////////
//
// methods for handling Damage Prevention
//
// ////////////////////////
// PreventNextDamage
/**
* <p>
* Setter for the field <code>preventNextDamage</code>.
* </p>
*
* @param n
* a int.
*/
public void setPreventNextDamage(final int n) {
this.preventNextDamage = n;
}
/**
* <p>
* Getter for the field <code>preventNextDamage</code>.
* </p>
*
* @return a int.
*/
public int getPreventNextDamage() { public int getPreventNextDamage() {
return this.preventNextDamage; return preventNextDamage;
}
public void setPreventNextDamage(final int n) {
preventNextDamage = n;
} }
/**
* <p>
* addPreventNextDamage.
* </p>
*
* @param n
* a int.
*/
public void addPreventNextDamage(final int n) { public void addPreventNextDamage(final int n) {
this.preventNextDamage += n; preventNextDamage += n;
} }
/**
* <p>
* subtractPreventNextDamage.
* </p>
*
* @param n
* a int.
*/
public void subtractPreventNextDamage(final int n) { public void subtractPreventNextDamage(final int n) {
this.preventNextDamage -= n; preventNextDamage -= n;
} }
/**
* <p>
* resetPreventNextDamage.
* </p>
*/
public void resetPreventNextDamage() { public void resetPreventNextDamage() {
this.preventNextDamage = 0; preventNextDamage = 0;
} }
// PreventNextDamageWithEffect // PreventNextDamageWithEffect
/**
* <p>
* Gets the map of damage prevention shields with effects.
* </p>
*
* @return the map of damage prevention shields with effects.
*/
public TreeMap<Card, Map<String, String>> getPreventNextDamageWithEffect() { public TreeMap<Card, Map<String, String>> getPreventNextDamageWithEffect() {
return this.preventionShieldsWithEffects; return preventionShieldsWithEffects;
} }
/**
* <p>
* Adds a damage prevention shield with an effect that happens at time of prevention.
* </p>
*
* @param shieldSource The source card which generated the shield
* @param effectMap A map of the effect occurring with the damage prevention
*/
public void addPreventNextDamageWithEffect(final Card shieldSource, TreeMap<String, String> effectMap) {
if (this.preventionShieldsWithEffects.containsKey(shieldSource)) {
int currentShields = Integer.valueOf(this.preventionShieldsWithEffects.get(shieldSource).get("ShieldAmount"));
currentShields += Integer.valueOf(effectMap.get("ShieldAmount"));
effectMap.put("ShieldAmount", Integer.toString(currentShields));
this.preventionShieldsWithEffects.put(shieldSource, effectMap);
} else {
this.preventionShieldsWithEffects.put(shieldSource, effectMap);
}
}
/**
* <p>
* subtractPreventNextDamageWithEffect.
* </p>
*
* @param shieldSource The source card which generated the shield
* @param n The number of shields to remove originating from shieldSource
*/
public void subtractPreventNextDamageWithEffect(final Card shieldSource, final int n) {
int currentShields = Integer.valueOf(this.preventionShieldsWithEffects.get(shieldSource).get("ShieldAmount"));
if (currentShields > n) {
this.preventionShieldsWithEffects.get(shieldSource).put("ShieldAmount", String.valueOf(currentShields - n));
} else {
this.preventionShieldsWithEffects.remove(shieldSource);
}
}
/**
* <p>
* resetPreventNextDamageWithEffect.
* </p>
*/
public void resetPreventNextDamageWithEffect() {
this.preventionShieldsWithEffects = new TreeMap<Card, Map<String, String>>();
}
/**
* <p>
* Gets the total amount of damage prevention shields.
* </p>
*
* @return the number of damage prevention shields with and without effects.
*/
public int getPreventNextDamageTotalShields() { public int getPreventNextDamageTotalShields() {
int shields = this.preventNextDamage; int shields = preventNextDamage;
for (final Map<String, String> value : this.preventionShieldsWithEffects.values()) { for (final Map<String, String> value : preventionShieldsWithEffects.values()) {
shields += Integer.valueOf(value.get("ShieldAmount")); shields += Integer.valueOf(value.get("ShieldAmount"));
} }
return shields; return shields;
} }
/** /**
* Checks for keyword. * Adds a damage prevention shield with an effect that happens at time of prevention.
* * @param shieldSource - The source card which generated the shield
* @param keyword * @param effectMap - A map of the effect occurring with the damage prevention
* the keyword
* @return true, if successful
*/ */
public void addPreventNextDamageWithEffect(final Card shieldSource, TreeMap<String, String> effectMap) {
if (preventionShieldsWithEffects.containsKey(shieldSource)) {
int currentShields = Integer.valueOf(preventionShieldsWithEffects.get(shieldSource).get("ShieldAmount"));
currentShields += Integer.valueOf(effectMap.get("ShieldAmount"));
effectMap.put("ShieldAmount", Integer.toString(currentShields));
preventionShieldsWithEffects.put(shieldSource, effectMap);
} else {
preventionShieldsWithEffects.put(shieldSource, effectMap);
}
}
public void subtractPreventNextDamageWithEffect(final Card shieldSource, final int n) {
int currentShields = Integer.valueOf(preventionShieldsWithEffects.get(shieldSource).get("ShieldAmount"));
if (currentShields > n) {
preventionShieldsWithEffects.get(shieldSource).put("ShieldAmount", String.valueOf(currentShields - n));
} else {
preventionShieldsWithEffects.remove(shieldSource);
}
}
public void resetPreventNextDamageWithEffect() {
preventionShieldsWithEffects = new TreeMap<Card, Map<String, String>>();
}
public boolean hasKeyword(final String keyword) { public boolean hasKeyword(final String keyword) {
return false; return false;
} }
// GameEntities can now be Enchanted // GameEntities can now be Enchanted
/** public final Iterable<Card> getEnchantedBy(boolean allowModify) {
* <p> if (enchantedBy == null) {
* Getter for the field <code>enchantedBy</code>. return new LinkedHashSet<Card>();
* </p> }
* if (allowModify) { //create copy to allow modifying original set while iterating
* @return a {@link java.util.ArrayList} object. return new LinkedHashSet<Card>(enchantedBy);
*/ }
public final ArrayList<Card> getEnchantedBy() { return enchantedBy;
return this.enchantedBy;
} }
public final void setEnchantedBy(final LinkedHashSet<Card> list) {
/** enchantedBy = list;
* <p> getView().updateEnchantedBy(this);
* Setter for the field <code>enchantedBy</code>. }
* </p> public final void setEnchantedBy(final Iterable<Card> list) {
* if (list == null) {
* @param list enchantedBy = null;
* a {@link java.util.ArrayList} object. }
*/ else {
public final void setEnchantedBy(final ArrayList<Card> list) { enchantedBy = new LinkedHashSet<Card>();
this.enchantedBy = list; for (Card c : list) {
enchantedBy.add(c);
}
}
getView().updateEnchantedBy(this);
} }
/**
* <p>
* isEnchanted.
* </p>
*
* @return a boolean.
*/
public final boolean isEnchanted() { public final boolean isEnchanted() {
return this.enchantedBy.size() != 0; return enchantedBy != null && !enchantedBy.isEmpty();
}
public final boolean isEnchantedBy(Card c) {
return enchantedBy != null && enchantedBy.contains(c);
}
public final boolean isEnchantedBy(final String cardName) {
for (final Card aura : getEnchantedBy(false)) {
if (aura.getName().equals(cardName)) {
return true;
}
}
return false;
} }
/**
* <p>
* addEnchantedBy.
* </p>
*
* @param c
* a {@link forge.game.card.Card} object.
*/
public final void addEnchantedBy(final Card c) { public final void addEnchantedBy(final Card c) {
this.enchantedBy.add(c); if (enchantedBy == null) {
enchantedBy = new LinkedHashSet<Card>();
}
enchantedBy.add(c);
getView().updateEnchantedBy(this);
getGame().fireEvent(new GameEventCardAttachment(c, null, this, AttachMethod.Enchant)); getGame().fireEvent(new GameEventCardAttachment(c, null, this, AttachMethod.Enchant));
} }
/**
* <p>
* removeEnchantedBy.
* </p>
*
* @param c
* a {@link forge.game.card.Card} object.
*/
public final void removeEnchantedBy(final Card c) { public final void removeEnchantedBy(final Card c) {
this.enchantedBy.remove(c); if (enchantedBy == null) { return; }
getGame().fireEvent(new GameEventCardAttachment(c, this, null, AttachMethod.Enchant));
}
/** if (enchantedBy.remove(c)) {
* <p> getView().updateEnchantedBy(this);
* unEnchantAllCards. getGame().fireEvent(new GameEventCardAttachment(c, this, null, AttachMethod.Enchant));
* </p> }
*/ }
public final void unEnchantAllCards() { public final void unEnchantAllCards() {
for (int i = 0; i < this.enchantedBy.size(); i++) { if (isEnchanted()) {
this.enchantedBy.get(i).unEnchantEntity(this); for (Card c : getEnchantedBy(true)) {
c.unEnchantEntity(this);
}
} }
} }
/**
*
* hasProtectionFrom.
*
* @param source
* Card
* @return boolean
*/
public boolean hasProtectionFrom(final Card source) { public boolean hasProtectionFrom(final Card source) {
return false; return false;
} }
// //////////////////////////////
//
// generic Object overrides
//
// ///////////////////////////////
/** {@inheritDoc} */
@Override @Override
public String toString() { public String toString() {
return this.name; return name;
} }
public abstract Game getGame(); public abstract Game getGame();

View File

@@ -1,5 +1,6 @@
package forge.game; package forge.game;
import forge.game.card.CardView;
import forge.trackable.TrackableObject; import forge.trackable.TrackableObject;
public abstract class GameEntityView<E extends Enum<E>> extends TrackableObject<E> { public abstract class GameEntityView<E extends Enum<E>> extends TrackableObject<E> {
@@ -19,4 +20,21 @@ public abstract class GameEntityView<E extends Enum<E>> extends TrackableObject<
void updatePreventNextDamage(GameEntity e) { void updatePreventNextDamage(GameEntity e) {
set(preventNextDamageProp(), e.getPreventNextDamageTotalShields()); set(preventNextDamageProp(), e.getPreventNextDamageTotalShields());
} }
protected abstract E enchantedByProp();
public Iterable<CardView> getEnchantedBy() {
return get(enchantedByProp());
}
void updateEnchantedBy(GameEntity e) {
if (e.isEnchanted()) {
set(enchantedByProp(), CardView.getCollection(e.getEnchantedBy(false)));
}
else {
set(enchantedByProp(), null);
}
}
public boolean isEnchanted() {
return getEnchantedBy() != null;
}
} }

View File

@@ -30,10 +30,7 @@ import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/**
* TODO: Write javadoc for this type.
*
*/
public class AbilityUtils { public class AbilityUtils {
public static CounterType getCounterType(String name, SpellAbility sa) throws Exception { public static CounterType getCounterType(String name, SpellAbility sa) throws Exception {
@@ -241,7 +238,7 @@ public class AbilityUtils {
} }
} }
else if (defined.equals("ChosenCard")) { else if (defined.equals("ChosenCard")) {
for (final Card chosen : hostCard.getChosenCard()) { for (final Card chosen : hostCard.getChosenCards()) {
cards.add(game.getCardState(chosen)); cards.add(game.getCardState(chosen));
} }
} }
@@ -1280,10 +1277,11 @@ public class AbilityUtils {
} }
} }
else if (unlessCost.equals("ChosenManaCost")) { else if (unlessCost.equals("ChosenManaCost")) {
if (source.getChosenCard().isEmpty()) { if (!source.hasChosenCard()) {
cost = new Cost(ManaCost.ZERO, true); cost = new Cost(ManaCost.ZERO, true);
} else { }
cost = new Cost(source.getChosenCard().get(0).getManaCost(), true); else {
cost = new Cost(Iterables.getFirst(source.getChosenCards(), null).getManaCost(), true);
} }
} }
else if (unlessCost.equals("RememberedCostMinus2")) { else if (unlessCost.equals("RememberedCostMinus2")) {

View File

@@ -96,7 +96,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
} }
} }
} }
host.setChosenCard(chosen); host.setChosenCards(chosen);
if (sa.hasParam("RememberChosen")) { if (sa.hasParam("RememberChosen")) {
for (final Card rem : chosen) { for (final Card rem : chosen) {
host.addRemembered(rem); host.addRemembered(rem);

View File

@@ -145,7 +145,7 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
chosen.add(o); chosen.add(o);
sourcesToChooseFrom.remove(o); sourcesToChooseFrom.remove(o);
} }
host.setChosenCard(chosen); host.setChosenCards(chosen);
if (sa.hasParam("RememberChosen")) { if (sa.hasParam("RememberChosen")) {
for (final Card rem : chosen) { for (final Card rem : chosen) {
host.addRemembered(rem); host.addRemembered(rem);

View File

@@ -39,8 +39,7 @@ public class CleanUpEffect extends SpellAbilityEffect {
source.clearFlipResult(); source.clearFlipResult();
} }
if (sa.hasParam("ClearChosenCard")) { if (sa.hasParam("ClearChosenCard")) {
source.getChosenCard().clear(); source.setChosenCards(null);
} }
} }
} }

View File

@@ -11,6 +11,8 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import com.google.common.collect.Iterables;
public class DestroyEffect extends SpellAbilityEffect { public class DestroyEffect extends SpellAbilityEffect {
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility) * @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
@@ -97,9 +99,9 @@ public class DestroyEffect extends SpellAbilityEffect {
boolean destroyed = false; boolean destroyed = false;
final Card lki = CardUtil.getLKICopy(tgtC); final Card lki = CardUtil.getLKICopy(tgtC);
if (remAttached) { if (remAttached) {
card.getRemembered().addAll(tgtC.getEnchantedBy()); Iterables.addAll(card.getRemembered(), tgtC.getEnchantedBy(false));
card.getRemembered().addAll(tgtC.getEquippedBy()); Iterables.addAll(card.getRemembered(), tgtC.getEquippedBy(false));
card.getRemembered().addAll(tgtC.getFortifiedBy()); Iterables.addAll(card.getRemembered(), tgtC.getFortifiedBy(false));
} }
if (sac) { if (sac) {
destroyed = game.getAction().sacrifice(tgtC, sa) != null; destroyed = game.getAction().sacrifice(tgtC, sa) != null;

View File

@@ -19,6 +19,8 @@ import forge.game.zone.ZoneType;
import java.util.List; import java.util.List;
import com.google.common.collect.Lists;
public class EffectEffect extends SpellAbilityEffect { public class EffectEffect extends SpellAbilityEffect {
@Override @Override
@@ -189,8 +191,8 @@ public class EffectEffect extends SpellAbilityEffect {
} }
// Set Chosen Color(s) // Set Chosen Color(s)
if (!hostCard.getChosenColors().isEmpty()) { if (hostCard.hasChosenColor()) {
eff.setChosenColors(hostCard.getChosenColors()); eff.setChosenColors(Lists.newArrayList(hostCard.getChosenColors()));
} }
// Set Chosen name // Set Chosen name

View File

@@ -170,7 +170,7 @@ public class TokenEffect extends SpellAbilityEffect {
for (int i = 0; i < substitutedColors.length; i++) { for (int i = 0; i < substitutedColors.length; i++) {
if (substitutedColors[i].equals("ChosenColor")) { if (substitutedColors[i].equals("ChosenColor")) {
// this currently only supports 1 chosen color // this currently only supports 1 chosen color
substitutedColors[i] = host.getChosenColors().get(0); substitutedColors[i] = host.getChosenColor();
} }
} }
String colorDesc = ""; String colorDesc = "";

View File

@@ -16,24 +16,23 @@ import java.util.List;
public class UnattachAllEffect extends SpellAbilityEffect { public class UnattachAllEffect extends SpellAbilityEffect {
private void handleUnattachment(final GameEntity o, final Card cardToUnattach) { private void handleUnattachment(final GameEntity o, final Card cardToUnattach) {
if (o instanceof Card) { if (o instanceof Card) {
final Card c = (Card) o; final Card c = (Card) o;
if (cardToUnattach.isAura()) { if (cardToUnattach.isAura()) {
//final boolean gainControl = "GainControl".equals(af.parseParams().get("AILogic")); //final boolean gainControl = "GainControl".equals(af.parseParams().get("AILogic"));
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl); //AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
} else if (cardToUnattach.isEquipment()) { } else if (cardToUnattach.isEquipment()) {
if (cardToUnattach.isEquipping() && c.getEquippedBy().contains(cardToUnattach)) { if (cardToUnattach.isEquipping() && c.isEquippedBy(cardToUnattach)) {
cardToUnattach.unEquipCard(cardToUnattach.getEquipping()); cardToUnattach.unEquipCard(cardToUnattach.getEquipping());
} }
} else if (cardToUnattach.isFortification()) { } else if (cardToUnattach.isFortification()) {
if (cardToUnattach.isFortifying() && c.getFortifiedBy().contains(cardToUnattach)) { if (cardToUnattach.isFortifying() && c.isFortifiedBy(cardToUnattach)) {
cardToUnattach.unFortifyCard(cardToUnattach.getFortifying()); cardToUnattach.unFortifyCard(cardToUnattach.getFortifying());
} }
} }
} else if (o instanceof Player) { } else if (o instanceof Player) {
final Player p = (Player) o; final Player p = (Player) o;
if (cardToUnattach.isAura() && p.getEnchantedBy().contains(cardToUnattach)) { if (cardToUnattach.isAura() && p.isEnchantedBy(cardToUnattach)) {
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false); //AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false);
} }
} }

View File

@@ -101,12 +101,12 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
private final CopyOnWriteArrayList<String> hiddenExtrinsicKeyword = new CopyOnWriteArrayList<String>(); private final CopyOnWriteArrayList<String> hiddenExtrinsicKeyword = new CopyOnWriteArrayList<String>();
// which equipment cards are equipping this card? // which equipment cards are equipping this card?
private ArrayList<Card> equippedBy = new ArrayList<Card>(); private LinkedHashSet<Card> equippedBy;
// if this card is of the type equipment, what card is it currently equipping? // if this card is of the type equipment, what card is it currently equipping?
private Card equipping = null; private Card equipping = null;
// which fortification cards are fortifying this card? // which fortification cards are fortifying this card?
private ArrayList<Card> fortifiedBy = new ArrayList<Card>(); private LinkedHashSet<Card> fortifiedBy;
// if this card is of the type fortification, what card is it currently fortifying? // if this card is of the type fortification, what card is it currently fortifying?
private Card fortifying = null; private Card fortifying = null;
@@ -213,11 +213,11 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
private String echoCost = ""; private String echoCost = "";
private Cost miracleCost = null; private Cost miracleCost = null;
private String chosenType = ""; private String chosenType = "";
private List<String> chosenColors = new ArrayList<String>(); private List<String> chosenColors;
private String namedCard = ""; private String namedCard = "";
private int chosenNumber; private int chosenNumber;
private Player chosenPlayer; private Player chosenPlayer;
private List<Card> chosenCard = new ArrayList<Card>(); private List<Card> chosenCards;
private Direction chosenDirection = null; private Direction chosenDirection = null;
private Card cloneOrigin = null; private Card cloneOrigin = null;
@@ -871,9 +871,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
int newValue = oldValue == null ? 0 : Math.max(oldValue.intValue() - n, 0); int newValue = oldValue == null ? 0 : Math.max(oldValue.intValue() - n, 0);
final int delta = (oldValue == null ? 0 : oldValue.intValue()) - newValue; final int delta = (oldValue == null ? 0 : oldValue.intValue()) - newValue;
if (delta == 0) { if (delta == 0) { return; }
return;
}
int powerBonusBefore = getPowerBonusFromCounters(); int powerBonusBefore = getPowerBonusFromCounters();
int toughnessBonusBefore = getToughnessBonusFromCounters(); int toughnessBonusBefore = getToughnessBonusFromCounters();
@@ -1016,7 +1014,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
getCharacteristics().setCardColor(colors); getCharacteristics().setCardColor(colors);
} }
public final List<CardColor> getColor() { public final Iterable<CardColor> getColor() {
return getCharacteristics().getCardColor(); return getCharacteristics().getCardColor();
} }
@@ -1031,15 +1029,15 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
public final Player getChosenPlayer() { public final Player getChosenPlayer() {
return chosenPlayer; return chosenPlayer;
} }
public final void setChosenPlayer(final Player p) { public final void setChosenPlayer(final Player p) {
if (chosenPlayer == p) { return; }
chosenPlayer = p; chosenPlayer = p;
view.updateChosenPlayer(this);
} }
public final int getChosenNumber() { public final int getChosenNumber() {
return chosenNumber; return chosenNumber;
} }
public final void setChosenNumber(final int i) { public final void setChosenNumber(final int i) {
chosenNumber = i; chosenNumber = i;
} }
@@ -1048,31 +1046,59 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
public final String getChosenType() { public final String getChosenType() {
return chosenType; return chosenType;
} }
public final void setChosenType(final String s) { public final void setChosenType(final String s) {
chosenType = s; chosenType = s;
view.updateChosenType(this);
} }
public final List<String> getChosenColors() { public final String getChosenColor() {
if (hasChosenColor()) {
return chosenColors.get(0);
}
return "";
}
public final Iterable<String> getChosenColors() {
if (chosenColors == null) {
return new ArrayList<String>();
}
return chosenColors; return chosenColors;
} }
public final void setChosenColors(final List<String> s) { public final void setChosenColors(final List<String> s) {
chosenColors = s; chosenColors = s;
view.updateChosenColors(this);
}
public boolean hasChosenColor() {
return chosenColors != null && !chosenColors.isEmpty();
}
public boolean hasChosenColor(String s) {
return chosenColors != null && chosenColors.contains(s);
} }
public final List<Card> getChosenCard() { public final Card getChosenCard() {
return chosenCard; if (hasChosenCard()) {
return chosenCards.get(0);
}
return null;
} }
public final Iterable<Card> getChosenCards() {
public final void setChosenCard(final List<Card> c) { if (chosenCards == null) {
chosenCard = c; return new ArrayList<Card>();
}
return chosenCards;
}
public final void setChosenCards(final List<Card> c) {
chosenCards = c;
}
public boolean hasChosenCard() {
return chosenCards != null && !chosenCards.isEmpty();
}
public boolean hasChosenCard(Card c) {
return chosenCards != null && chosenCards.contains(c);
} }
public Direction getChosenDirection() { public Direction getChosenDirection() {
return chosenDirection; return chosenDirection;
} }
public void setChosenDirection(Direction chosenDirection0) { public void setChosenDirection(Direction chosenDirection0) {
chosenDirection = chosenDirection0; chosenDirection = chosenDirection0;
} }
@@ -1081,47 +1107,24 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
public final String getNamedCard() { public final String getNamedCard() {
return namedCard; return namedCard;
} }
public final void setNamedCard(final String s) { public final void setNamedCard(final String s) {
namedCard = s; namedCard = s;
} view.updateNamedCard(this);
public final void setDrawnThisTurn(final boolean b) {
drawnThisTurn = b;
} }
public final boolean getDrawnThisTurn() { public final boolean getDrawnThisTurn() {
return drawnThisTurn; return drawnThisTurn;
} }
public final void setDrawnThisTurn(final boolean b) {
/** drawnThisTurn = b;
* get a list of Cards this card has gained control of.
* <p/>
* used primarily with AbilityFactory_GainControl
*
* @return a list of cards this card has gained control of
*/
public final List<Card> getGainControlTargets() {
return gainControlTargets;
} }
/** public final List<Card> getGainControlTargets() { //used primarily with AbilityFactory_GainControl
* add a Card to the list of Cards this card has gained control of. return gainControlTargets;
* <p/> }
* used primarily with AbilityFactory_GainControl
*
* @param c
* a {@link forge.game.card.Card} object.
*/
public final void addGainControlTarget(final Card c) { public final void addGainControlTarget(final Card c) {
gainControlTargets.add(c); gainControlTargets.add(c);
} }
/**
* clear the list of Cards this card has gained control of.
* <p/>
* used primarily with AbilityFactory_GainControl
*/
public final void removeGainControlTargets(final Card c) { public final void removeGainControlTargets(final Card c) {
gainControlTargets.remove(c); gainControlTargets.remove(c);
} }
@@ -1229,13 +1232,6 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
// get the text that does not belong to a cards abilities (and is not really // get the text that does not belong to a cards abilities (and is not really
// there rules-wise) // there rules-wise)
/**
* <p>
* getNonAbilityText.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public final String getNonAbilityText() { public final String getNonAbilityText() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final ArrayList<String> keyword = getHiddenExtrinsicKeyword(); final ArrayList<String> keyword = getHiddenExtrinsicKeyword();
@@ -1246,15 +1242,6 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
// convert a keyword list to the String that should be displayed ingame // convert a keyword list to the String that should be displayed ingame
/**
* <p>
* keywordsToText.
* </p>
*
* @param keywords
* a {@link java.util.ArrayList} object.
* @return a {@link java.lang.String} object.
*/
public final String keywordsToText(final ArrayList<String> keywords) { public final String keywordsToText(final ArrayList<String> keywords) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final StringBuilder sbLong = new StringBuilder(); final StringBuilder sbLong = new StringBuilder();
@@ -2223,31 +2210,77 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
} }
public final boolean isEquipped() { public final Iterable<Card> getEquippedBy(boolean allowModify) {
return !equippedBy.isEmpty(); if (equippedBy == null) {
} return new LinkedHashSet<Card>();
public final ArrayList<Card> getEquippedBy() { }
if (allowModify) { //create copy to allow modifying original set while iterating
return new LinkedHashSet<Card>(equippedBy);
}
return equippedBy; return equippedBy;
} }
public final void setEquippedBy(final ArrayList<Card> list) { public final void setEquippedBy(final LinkedHashSet<Card> list) {
equippedBy = list; equippedBy = list;
view.updateEquippedBy(this);
}
public final void setEquippedBy(final Iterable<Card> list) {
if (list == null) {
equippedBy = null;
}
else {
equippedBy = new LinkedHashSet<Card>();
for (Card c : list) {
equippedBy.add(c);
}
}
getView().updateEquippedBy(this);
}
public final boolean isEquipped() {
return equippedBy != null && !equippedBy.isEmpty();
}
public final boolean isEquippedBy(Card c) {
return equippedBy != null && equippedBy.contains(c);
} }
public final boolean isFortified() { public final Iterable<Card> getFortifiedBy(boolean allowModify) {
return !fortifiedBy.isEmpty(); if (fortifiedBy == null) {
} return new LinkedHashSet<Card>();
public final ArrayList<Card> getFortifiedBy() { }
if (allowModify) { //create copy to allow modifying original set while iterating
return new LinkedHashSet<Card>(fortifiedBy);
}
return fortifiedBy; return fortifiedBy;
} }
public final void setFortifiedBy(final ArrayList<Card> list) { public final void setFortifiedBy(final LinkedHashSet<Card> list) {
fortifiedBy = list; fortifiedBy = list;
view.updateFortifiedBy(this);
}
public final void setFortifiedBy(final Iterable<Card> list) {
if (list == null) {
fortifiedBy = null;
}
else {
fortifiedBy = new LinkedHashSet<Card>();
for (Card c : list) {
fortifiedBy.add(c);
}
}
getView().updateFortifiedBy(this);
}
public final boolean isFortified() {
return fortifiedBy != null && !fortifiedBy.isEmpty();
}
public final boolean isFortifiedBy(Card c) {
return fortifiedBy != null && fortifiedBy.contains(c);
} }
public final Card getEquipping() { public final Card getEquipping() {
return equipping; return equipping;
} }
public final void setEquipping(final Card card) { public final void setEquipping(final Card card) {
if (equipping == card) { return; }
equipping = card; equipping = card;
view.updateEquipping(this);
} }
public final boolean isEquipping() { public final boolean isEquipping() {
return equipping != null; return equipping != null;
@@ -2257,7 +2290,9 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
return fortifying; return fortifying;
} }
public final void setFortifying(final Card card) { public final void setFortifying(final Card card) {
if (fortifying == card) { return; }
fortifying = card; fortifying = card;
view.updateFortifying(this);
} }
public final boolean isFortifying() { public final boolean isFortifying() {
return fortifying != null; return fortifying != null;
@@ -2286,9 +2321,13 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
// They use double links... it's doubtful // They use double links... it's doubtful
equipping = c; setEquipping(c);
setTimestamp(getGame().getNextTimestamp()); setTimestamp(getGame().getNextTimestamp());
if (c.equippedBy == null) {
c.equippedBy = new LinkedHashSet<Card>();
}
c.equippedBy.add(this); c.equippedBy.add(this);
view.updateEquippedBy(this);
// Play the Equip sound // Play the Equip sound
getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Equip)); getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Equip));
@@ -2307,9 +2346,13 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
unFortifyCard(oldTarget); unFortifyCard(oldTarget);
} }
fortifying = c; setFortifying(c);
setTimestamp(getGame().getNextTimestamp()); setTimestamp(getGame().getNextTimestamp());
if (c.fortifiedBy == null) {
c.fortifiedBy = new LinkedHashSet<Card>();
}
c.fortifiedBy.add(this); c.fortifiedBy.add(this);
view.updateFortifiedBy(this);
// Play the Equip sound // Play the Equip sound
getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Fortify)); getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, c, AttachMethod.Fortify));
@@ -2322,9 +2365,11 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
public final void unEquipCard(final Card c) { // equipment.unEquipCard(equippedCard); public final void unEquipCard(final Card c) { // equipment.unEquipCard(equippedCard);
if (equipping == c) { if (equipping == c) {
equipping = null; setEquipping(null);
}
if (c.equippedBy != null && c.equippedBy.remove(this)) {
view.updateEquippedBy(this);
} }
c.equippedBy.remove(this);
getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Equip)); getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Equip));
@@ -2337,75 +2382,55 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
public final void unFortifyCard(final Card c) { // fortification.unEquipCard(fortifiedCard); public final void unFortifyCard(final Card c) { // fortification.unEquipCard(fortifiedCard);
if (fortifying == c) { if (fortifying == c) {
fortifying = null; setFortifying(null);
}
if (c.fortifiedBy != null && c.fortifiedBy.remove(this)) {
view.updateFortifiedBy(this);
} }
c.fortifiedBy.remove(this);
getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Fortify)); getGame().fireEvent(new GameEventCardAttachment(this, c, null, AttachMethod.Fortify));
} }
public final void unEquipAllCards() { public final void unEquipAllCards() {
// while there exists equipment, unequip the first one if (isEquipped()) {
while (equippedBy.size() > 0) { for (Card c : getEquippedBy(true)) {
equippedBy.get(0).unEquipCard(this); c.unEquipCard(this);
}
} }
} }
public final GameEntity getEnchanting() { public final GameEntity getEnchanting() {
return enchanting; return enchanting;
} }
public final void setEnchanting(final GameEntity e) {
if (enchanting == e) { return; }
enchanting = e;
view.updateEnchanting(this);
}
public final Card getEnchantingCard() { public final Card getEnchantingCard() {
if (enchanting instanceof Card) { if (enchanting instanceof Card) {
return (Card) enchanting; return (Card) enchanting;
} }
return null; return null;
} }
public final Player getEnchantingPlayer() { public final Player getEnchantingPlayer() {
if (enchanting instanceof Player) { if (enchanting instanceof Player) {
return (Player) enchanting; return (Player) enchanting;
} }
return null; return null;
} }
public final void setEnchanting(final GameEntity e) {
enchanting = e;
}
public final boolean isEnchanting() { public final boolean isEnchanting() {
return enchanting != null; return enchanting != null;
} }
public final boolean isEnchantingCard() { public final boolean isEnchantingCard() {
return getEnchantingCard() != null; return getEnchantingCard() != null;
} }
public final boolean isEnchantingPlayer() { public final boolean isEnchantingPlayer() {
return getEnchantingPlayer() != null; return getEnchantingPlayer() != null;
} }
/**
* checks to see if this card is enchanted by an aura with a given name.
*
* @param cardName
* the name of the aura
* @return true if this card is enchanted by an aura with the given name,
* false otherwise
*/
public final boolean isEnchantedBy(final String cardName) {
final ArrayList<Card> allAuras = getEnchantedBy();
for (final Card aura : allAuras) {
if (aura.getName().equals(cardName)) {
return true;
}
}
return false;
}
public final void removeEnchanting(final GameEntity e) { public final void removeEnchanting(final GameEntity e) {
if (enchanting.equals(e)) { if (enchanting == e) {
enchanting = null; setEnchanting(null);
} }
} }
@@ -2416,7 +2441,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
+ " but it can't be enchanted."); + " but it can't be enchanted.");
return; return;
} }
enchanting = entity; setEnchanting(entity);
setTimestamp(getGame().getNextTimestamp()); setTimestamp(getGame().getNextTimestamp());
entity.addEnchantedBy(this); entity.addEnchantedBy(this);
@@ -2430,10 +2455,11 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
public final void unEnchantEntity(final GameEntity entity) { public final void unEnchantEntity(final GameEntity entity) {
if (enchanting == null || !enchanting.equals(entity)) if (enchanting == null || !enchanting.equals(entity)) {
return; return;
}
enchanting = null; setEnchanting(null);
entity.removeEnchantedBy(this); entity.removeEnchantedBy(this);
if (isBestowed()) { if (isBestowed()) {
unanimateBestow(); unanimateBestow();
@@ -3294,21 +3320,25 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
setDirectlyPhasedOut(direct); setDirectlyPhasedOut(direct);
} }
for (final Card eq : getEquippedBy()) { if (isEquipped()) {
if (eq.isPhasedOut() == phasingIn) { for (final Card eq : getEquippedBy(false)) {
eq.phase(false); if (eq.isPhasedOut() == phasingIn) {
eq.phase(false);
}
} }
} }
if (isFortified()) {
for (final Card f : getFortifiedBy()) { for (final Card f : getFortifiedBy(false)) {
if (f.isPhasedOut() == phasingIn) { if (f.isPhasedOut() == phasingIn) {
f.phase(false); f.phase(false);
}
} }
} }
if (isEnchanted()) {
for (final Card aura : getEnchantedBy()) { for (final Card aura : getEnchantedBy(false)) {
if (aura.isPhasedOut() == phasingIn) { if (aura.isPhasedOut() == phasingIn) {
aura.phase(false); aura.phase(false);
}
} }
} }
@@ -3574,11 +3604,11 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
return false; return false;
} }
} else if (property.equals("ChosenCard")) { } else if (property.equals("ChosenCard")) {
if (!source.getChosenCard().contains(this)) { if (!source.hasChosenCard(this)) {
return false; return false;
} }
} else if (property.equals("nonChosenCard")) { } else if (property.equals("nonChosenCard")) {
if (source.getChosenCard().contains(this)) { if (source.hasChosenCard(this)) {
return false; return false;
} }
} }
@@ -3601,15 +3631,15 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
if (property.startsWith("non") == CardUtil.getColors(this).isMonoColor()) return false; if (property.startsWith("non") == CardUtil.getColors(this).isMonoColor()) return false;
} else if (property.equals("ChosenColor")) { } else if (property.equals("ChosenColor")) {
if (source.getChosenColors().isEmpty() || !CardUtil.getColors(this).hasAnyColor(MagicColor.fromName(source.getChosenColors().get(0)))) if (!source.hasChosenColor() || !CardUtil.getColors(this).hasAnyColor(MagicColor.fromName(source.getChosenColor())))
return false; return false;
} else if (property.equals("AllChosenColors")) { } else if (property.equals("AllChosenColors")) {
if (source.getChosenColors().isEmpty() || !CardUtil.getColors(this).hasAllColors(ColorSet.fromNames(source.getChosenColors()).getColor())) if (!source.hasChosenColor() || !CardUtil.getColors(this).hasAllColors(ColorSet.fromNames(source.getChosenColors()).getColor()))
return false; return false;
} else if (property.equals("AnyChosenColor")) { } else if (property.equals("AnyChosenColor")) {
if (source.getChosenColors().isEmpty() || !CardUtil.getColors(this).hasAnyColor(ColorSet.fromNames(source.getChosenColors()).getColor())) if (!source.hasChosenColor() || !CardUtil.getColors(this).hasAnyColor(ColorSet.fromNames(source.getChosenColors()).getColor()))
return false; return false;
} else if (property.equals("DoubleFaced")) { } else if (property.equals("DoubleFaced")) {
@@ -3801,7 +3831,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
return false; return false;
} }
} else if (property.startsWith("AttachedBy")) { } else if (property.startsWith("AttachedBy")) {
if (!equippedBy.contains(source) && !getEnchantedBy().contains(source) && !getFortifiedBy().contains(source)) { if (!isEquippedBy(source) && !isEnchantedBy(source) && !isFortifiedBy(source)) {
return false; return false;
} }
} else if (property.equals("Attached")) { } else if (property.equals("Attached")) {
@@ -3844,9 +3874,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
if (enchantedPlayer == null) { if (enchantedPlayer == null) {
return false; return false;
} }
for (Card c : enchantedPlayer.getEnchantedBy(false)) {
List<Card> enchanting = enchantedPlayer.getEnchantedBy();
for (Card c : enchanting) {
if (getName().equals(c.getName())) { if (getName().equals(c.getName())) {
return false; return false;
} }
@@ -3857,14 +3885,14 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
} else if (property.startsWith("EnchantedBy")) { } else if (property.startsWith("EnchantedBy")) {
if (property.equals("EnchantedBy")) { if (property.equals("EnchantedBy")) {
if (!getEnchantedBy().contains(source) && !equals(source.getEnchanting())) { if (!isEnchantedBy(source) && !equals(source.getEnchanting())) {
return false; return false;
} }
} else { } else {
final String restriction = property.split("EnchantedBy ")[1]; final String restriction = property.split("EnchantedBy ")[1];
if (restriction.equals("Imprinted")) { if (restriction.equals("Imprinted")) {
for (final Card card : source.getImprinted()) { for (final Card card : source.getImprinted()) {
if (!getEnchantedBy().contains(card) && !equals(card.getEnchanting())) { if (!isEnchantedBy(card) && !equals(card.getEnchanting())) {
return false; return false;
} }
} }
@@ -3873,14 +3901,14 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
final SpellAbility saTargeting = sa.getSATargetingCard(); final SpellAbility saTargeting = sa.getSATargetingCard();
if (saTargeting != null) { if (saTargeting != null) {
for (final Card c : saTargeting.getTargets().getTargetCards()) { for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (!getEnchantedBy().contains(c) && !equals(c.getEnchanting())) { if (!isEnchantedBy(c) && !equals(c.getEnchanting())) {
return false; return false;
} }
} }
} }
} }
} else { // EnchantedBy Aura.Other } else { // EnchantedBy Aura.Other
for (final Card aura : getEnchantedBy()){ for (final Card aura : getEnchantedBy(false)){
if (aura.isValid(restriction, sourceController, source)) { if (aura.isValid(restriction, sourceController, source)) {
return true; return true;
} }
@@ -3894,14 +3922,14 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
final SpellAbility saTargeting = sa.getSATargetingCard(); final SpellAbility saTargeting = sa.getSATargetingCard();
if (saTargeting != null) { if (saTargeting != null) {
for (final Card c : saTargeting.getTargets().getTargetCards()) { for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (getEnchantedBy().contains(c)) { if (isEnchantedBy(c)) {
return false; return false;
} }
} }
} }
} }
} else { } else {
if (getEnchantedBy().contains(source)) { if (isEnchantedBy(source)) {
return false; return false;
} }
} }
@@ -3951,7 +3979,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
final SpellAbility saTargeting = sa.getSATargetingCard(); final SpellAbility saTargeting = sa.getSATargetingCard();
if (saTargeting != null) { if (saTargeting != null) {
for (final Card c : saTargeting.getTargets().getTargetCards()) { for (final Card c : saTargeting.getTargets().getTargetCards()) {
if (!equippedBy.contains(c)) { if (!isEquippedBy(c)) {
return false; return false;
} }
} }
@@ -3959,16 +3987,16 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
} else if (property.substring(10).equals("Enchanted")) { } else if (property.substring(10).equals("Enchanted")) {
if (source.getEnchantingCard() == null || if (source.getEnchantingCard() == null ||
!equippedBy.contains(source.getEnchantingCard())) { !isEquippedBy(source.getEnchantingCard())) {
return false; return false;
} }
} else { } else {
if (!equippedBy.contains(source)) { if (!isEquippedBy(source)) {
return false; return false;
} }
} }
} else if (property.startsWith("FortifiedBy")) { } else if (property.startsWith("FortifiedBy")) {
if (!fortifiedBy.contains(source)) { if (!isFortifiedBy(source)) {
return false; return false;
} }
} else if (property.startsWith("CanBeEquippedBy")) { } else if (property.startsWith("CanBeEquippedBy")) {
@@ -6081,7 +6109,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
} }
if (hasProtectionFrom(aura, checkSBA) if (hasProtectionFrom(aura, checkSBA)
|| (hasKeyword("CARDNAME can't be enchanted in the future.") && !getEnchantedBy().contains(aura)) || (hasKeyword("CARDNAME can't be enchanted in the future.") && !isEnchantedBy(aura))
|| (hasKeyword("CARDNAME can't be enchanted.") && !aura.getName().equals("Anti-Magic Aura") || (hasKeyword("CARDNAME can't be enchanted.") && !aura.getName().equals("Anti-Magic Aura")
&& !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield))) && !(aura.getName().equals("Consecrate Land") && aura.isInZone(ZoneType.Battlefield)))
|| ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura))) { || ((tgt != null) && !isValid(tgt.getValidTgts(), aura.getController(), aura))) {

View File

@@ -94,10 +94,10 @@ public class CardFactory {
// I'm not sure if we really should be copying enchant/equip stuff over. // I'm not sure if we really should be copying enchant/equip stuff over.
out.setEquipping(in.getEquipping()); out.setEquipping(in.getEquipping());
out.setEquippedBy(in.getEquippedBy()); out.setEquippedBy(in.getEquippedBy(false));
out.setFortifying(in.getFortifying()); out.setFortifying(in.getFortifying());
out.setFortifiedBy(in.getFortifiedBy()); out.setFortifiedBy(in.getFortifiedBy(false));
out.setEnchantedBy(in.getEnchantedBy()); out.setEnchantedBy(in.getEnchantedBy(false));
out.setEnchanting(in.getEnchanting()); out.setEnchanting(in.getEnchanting());
out.setClones(in.getClones()); out.setClones(in.getClones());
out.setZone(in.getZone()); out.setZone(in.getZone());

View File

@@ -1159,7 +1159,7 @@ public class CardFactoryUtil {
ZoneType sourceZone = sq[0].contains("ChromaInGrave") ? ZoneType.Graveyard : ZoneType.Battlefield; ZoneType sourceZone = sq[0].contains("ChromaInGrave") ? ZoneType.Graveyard : ZoneType.Battlefield;
String colorName = sq[1]; String colorName = sq[1];
if (colorName.contains("Chosen")) { if (colorName.contains("Chosen")) {
colorName = MagicColor.toShortString(c.getChosenColors().get(0)); colorName = MagicColor.toShortString(c.getChosenColor());
} }
final List<Card> cards; final List<Card> cards;
if (sq[0].contains("ChromaSource")) { // Runs Chroma for passed in Source card if (sq[0].contains("ChromaSource")) { // Runs Chroma for passed in Source card

View File

@@ -243,11 +243,11 @@ public final class CardUtil {
newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn()); newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn());
newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn()); newCopy.getDamageHistory().setCreatureGotBlockedThisTurn(in.getDamageHistory().getCreatureGotBlockedThisTurn());
newCopy.setEnchanting(in.getEnchanting()); newCopy.setEnchanting(in.getEnchanting());
newCopy.setEnchantedBy(new ArrayList<Card> (in.getEnchantedBy())); newCopy.setEnchantedBy(in.getEnchantedBy(false));
newCopy.setEquipping(in.getEquipping()); newCopy.setEquipping(in.getEquipping());
newCopy.setEquippedBy(new ArrayList<Card> (in.getEquippedBy())); newCopy.setEquippedBy(in.getEquippedBy(false));
newCopy.setFortifying(in.getFortifying()); newCopy.setFortifying(in.getFortifying());
newCopy.setFortifiedBy(new ArrayList<Card> (in.getFortifiedBy())); newCopy.setFortifiedBy(in.getFortifiedBy(false));
newCopy.setClones(in.getClones()); newCopy.setClones(in.getClones());
newCopy.setHaunting(in.getHaunting()); newCopy.setHaunting(in.getHaunting());
for (final Card haunter : in.getHauntedBy()) { for (final Card haunter : in.getHauntedBy()) {

View File

@@ -222,7 +222,7 @@ public class CardView extends GameEntityView<CardProp> {
return get(CardProp.EquippedBy); return get(CardProp.EquippedBy);
} }
void updateEquippedBy(Card c) { void updateEquippedBy(Card c) {
set(CardProp.EquippedBy, CardView.getCollection(c.getEquippedBy())); set(CardProp.EquippedBy, CardView.getCollection(c.getEquippedBy(false)));
} }
public boolean isEquipped() { public boolean isEquipped() {
@@ -251,17 +251,6 @@ public class CardView extends GameEntityView<CardProp> {
return null; return null;
} }
public Iterable<CardView> getEnchantedBy() {
return get(CardProp.EnchantedBy);
}
void updateEnchantedBy(Card c) {
set(CardProp.EnchantedBy, CardView.getCollection(c.getEnchantedBy()));
}
public boolean isEnchanted() {
return getEnchantedBy() != null;
}
public CardView getFortifying() { public CardView getFortifying() {
return get(CardProp.Fortifying); return get(CardProp.Fortifying);
} }
@@ -273,7 +262,7 @@ public class CardView extends GameEntityView<CardProp> {
return get(CardProp.FortifiedBy); return get(CardProp.FortifiedBy);
} }
void updateFortifiedBy(Card c) { void updateFortifiedBy(Card c) {
set(CardProp.FortifiedBy, CardView.getCollection(c.getFortifiedBy())); set(CardProp.FortifiedBy, CardView.getCollection(c.getFortifiedBy(false)));
} }
public boolean isFortified() { public boolean isFortified() {
@@ -624,4 +613,9 @@ public class CardView extends GameEntityView<CardProp> {
protected CardProp preventNextDamageProp() { protected CardProp preventNextDamageProp() {
return CardProp.PreventNextDamage; return CardProp.PreventNextDamage;
} }
@Override
protected CardProp enchantedByProp() {
return CardProp.EnchantedBy;
}
} }

View File

@@ -77,8 +77,7 @@ public class CostUnattach extends CostPartWithList {
return true; return true;
} }
} else { } else {
List<Card> equipped = source.getEquippedBy(); if (CardLists.getValidCards(source.getEquippedBy(false), type, activator, source).size() > 0) {
if (CardLists.getValidCards(equipped, type, activator, source).size() > 0) {
return true; return true;
} }
} }
@@ -97,7 +96,7 @@ public class CostUnattach extends CostPartWithList {
return originalEquipment; return originalEquipment;
} }
} else { } else {
List<Card> attachees = CardLists.getValidCards(source.getEquippedBy(), this.getType(), activator, source); List<Card> attachees = CardLists.getValidCards(source.getEquippedBy(false), this.getType(), activator, source);
if (attachees.size() > 0) { if (attachees.size() > 0) {
// Just pick the first one, although maybe give a dialog // Just pick the first one, although maybe give a dialog
return attachees.get(0); return attachees.get(0);

View File

@@ -2074,7 +2074,7 @@ public class Player extends GameEntity implements Comparable<Player>, IIdentifia
return false; return false;
} }
} else if (property.startsWith("EnchantedBy")) { } else if (property.startsWith("EnchantedBy")) {
if (!getEnchantedBy().contains(source)) { if (!isEnchantedBy(source)) {
return false; return false;
} }
} else if (property.startsWith("Chosen")) { } else if (property.startsWith("Chosen")) {

View File

@@ -204,4 +204,9 @@ public class PlayerView extends GameEntityView<PlayerProp> {
protected PlayerProp preventNextDamageProp() { protected PlayerProp preventNextDamageProp() {
return PlayerProp.PreventNextDamage; return PlayerProp.PreventNextDamage;
} }
@Override
protected PlayerProp enchantedByProp() {
return PlayerProp.EnchantedBy;
}
} }

View File

@@ -233,8 +233,8 @@ public class ReplacementHandler implements IGameStateObject {
// Replaced mana type // Replaced mana type
final Card repHost = replacementEffect.getHostCard(); final Card repHost = replacementEffect.getHostCard();
String repType = repHost.getSVar(mapParams.get("ManaReplacement")); String repType = repHost.getSVar(mapParams.get("ManaReplacement"));
if (repType.contains("Chosen") && !repHost.getChosenColors().isEmpty()) { if (repType.contains("Chosen") && repHost.hasChosenColor()) {
repType = repType.replace("Chosen", MagicColor.toShortString(repHost.getChosenColors().get(0))); repType = repType.replace("Chosen", MagicColor.toShortString(repHost.getChosenColor()));
} }
manaAb.getManaPart().setManaReplaceType(repType); manaAb.getManaPart().setManaReplaceType(repType);
manaAb.getManaPart().produceMana(rep, player1, manaAb); manaAb.getManaPart().produceMana(rep, player1, manaAb);

View File

@@ -29,11 +29,11 @@ import forge.game.replacement.ReplacementHandler;
import forge.game.replacement.ReplacementLayer; import forge.game.replacement.ReplacementLayer;
import forge.game.replacement.ReplacementResult; import forge.game.replacement.ReplacementResult;
import forge.game.trigger.TriggerType; import forge.game.trigger.TriggerType;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -341,9 +341,8 @@ public class AbilityManaPart implements java.io.Serializable {
*/ */
public final String mana() { public final String mana() {
if (this.getOrigProduced().contains("Chosen")) { if (this.getOrigProduced().contains("Chosen")) {
if (this.getSourceCard() != null && !this.getSourceCard().getChosenColors().isEmpty()) { if (this.getSourceCard() != null && this.getSourceCard().hasChosenColor()) {
return MagicColor.toShortString(this.getSourceCard() return MagicColor.toShortString(this.getSourceCard().getChosenColor());
.getChosenColors().get(0));
} }
} }
return this.getOrigProduced(); return this.getOrigProduced();
@@ -473,8 +472,7 @@ public class AbilityManaPart implements java.io.Serializable {
} }
if (this.getOrigProduced().contains("Chosen") && sourceCard != null ) { if (this.getOrigProduced().contains("Chosen") && sourceCard != null ) {
List<String> chosenCol = this.getSourceCard().getChosenColors(); if (this.getSourceCard().hasChosenColor() && MagicColor.toShortString(this.getSourceCard().getChosenColor()).contains(s)) {
if ( !chosenCol.isEmpty() && MagicColor.toShortString(chosenCol.get(0)).contains(s)) {
return true; return true;
} }
} }

View File

@@ -275,7 +275,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
} }
if (this.getColorToCheck() != null) { if (this.getColorToCheck() != null) {
if (!sa.getHostCard().getChosenColors().contains(this.getColorToCheck())) { if (!sa.getHostCard().hasChosenColor(this.getColorToCheck())) {
return false; return false;
} }
} }

View File

@@ -302,7 +302,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
} }
if (this.getColorToCheck() != null) { if (this.getColorToCheck() != null) {
if (!sa.getHostCard().getChosenColors().contains(this.getColorToCheck())) { if (!sa.getHostCard().hasChosenColor(this.getColorToCheck())) {
return false; return false;
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.staticability; package forge.game.staticability;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.GameCommand; import forge.GameCommand;
@@ -159,7 +160,7 @@ public class StaticAbilityContinuous {
if (params.containsKey("AddKeyword")) { if (params.containsKey("AddKeyword")) {
addKeywords = params.get("AddKeyword").split(" & "); addKeywords = params.get("AddKeyword").split(" & ");
final List<String> chosencolors = hostCard.getChosenColors(); final Iterable<String> chosencolors = hostCard.getChosenColors();
for (final String color : chosencolors) { for (final String color : chosencolors) {
for (int w = 0; w < addKeywords.length; w++) { for (int w = 0; w < addKeywords.length; w++) {
addKeywords[w] = addKeywords[w].replaceAll("ChosenColor", color.substring(0, 1).toUpperCase().concat(color.substring(1, color.length()))); addKeywords[w] = addKeywords[w].replaceAll("ChosenColor", color.substring(0, 1).toUpperCase().concat(color.substring(1, color.length())));
@@ -381,8 +382,8 @@ public class StaticAbilityContinuous {
if (changeColorWordsTo != null) { if (changeColorWordsTo != null) {
final byte color; final byte color;
if (changeColorWordsTo.equals("ChosenColor")) { if (changeColorWordsTo.equals("ChosenColor")) {
if (hostCard.getChosenColors().size() > 0) { if (hostCard.hasChosenColor()) {
color = MagicColor.fromName(hostCard.getChosenColors().get(0)); color = MagicColor.fromName(Iterables.getFirst(hostCard.getChosenColors(), null));
} else { } else {
color = 0; color = 0;
} }

View File

@@ -22,8 +22,6 @@ import forge.game.card.Card;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import java.util.List;
/** /**
* <p> * <p>
* Trigger_TapsForMana class. * Trigger_TapsForMana class.
@@ -93,8 +91,7 @@ public class TriggerTapsForMana extends Trigger {
} }
String produced = (String) prod; String produced = (String) prod;
if ("ChosenColor".equals(mapParams.get("Produced"))) { if ("ChosenColor".equals(mapParams.get("Produced"))) {
List<String> colors = this.getHostCard().getChosenColors(); if (!this.getHostCard().hasChosenColor() || !produced.contains(MagicColor.toShortString(this.getHostCard().getChosenColor()))) {
if (colors.isEmpty() || !produced.contains(MagicColor.toShortString(colors.get(0)))) {
return false; return false;
} }
} }

View File

@@ -45,4 +45,12 @@ public abstract class TrackableObject<E extends Enum<E>> implements IIdentifiabl
protected void flagAsChanged(E key) { protected void flagAsChanged(E key) {
changedProps.add(key); changedProps.add(key);
} }
public void serialize() {
//TODO
}
public void deserialize() {
//TODO
}
} }

View File

@@ -74,6 +74,7 @@ public class TrackableProperty {
HasUnlimitedHandSize, HasUnlimitedHandSize,
NumDrawnThisTurn, NumDrawnThisTurn,
PreventNextDamage, PreventNextDamage,
EnchantedBy,
Keywords, Keywords,
CommanderInfo, CommanderInfo,
Ante, Ante,

View File

@@ -478,11 +478,11 @@ public abstract class LocalGameView implements IGameView {
view.setBlocking(combat != null && combat.isBlocking(c)); view.setBlocking(combat != null && combat.isBlocking(c));
view.setChosenPlayer(getPlayerView(c.getChosenPlayer(), false)); view.setChosenPlayer(getPlayerView(c.getChosenPlayer(), false));
view.setEquipping(getCardView(c.getEquipping(), false)); view.setEquipping(getCardView(c.getEquipping(), false));
view.setEquippedBy(getCardViews(c.getEquippedBy(), false)); view.setEquippedBy(getCardViews(c.getEquippedBy(false), false));
view.setEnchantingCard(getCardView(c.getEnchantingCard(), false)); view.setEnchantingCard(getCardView(c.getEnchantingCard(), false));
view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer(), false)); view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer(), false));
view.setEnchantedBy(getCardViews(c.getEnchantedBy(), false)); view.setEnchantedBy(getCardViews(c.getEnchantedBy(false), false));
view.setFortifiedBy(getCardViews(c.getFortifiedBy(), false)); view.setFortifiedBy(getCardViews(c.getFortifiedBy(false), false));
view.setGainControlTargets(getCardViews(c.getGainControlTargets(), false)); view.setGainControlTargets(getCardViews(c.getGainControlTargets(), false));
view.setCloneOrigin(getCardView(c.getCloneOrigin(), false)); view.setCloneOrigin(getCardView(c.getCloneOrigin(), false));
view.setImprinted(getCardViews(c.getImprinted(), false)); view.setImprinted(getCardViews(c.getImprinted(), false));

View File

@@ -55,7 +55,7 @@ public final class ViewUtil {
view.setRegenerationShields(c.getShieldCount()); view.setRegenerationShields(c.getShieldCount());
view.setPreventNextDamage(c.getPreventNextDamageTotalShields()); view.setPreventNextDamage(c.getPreventNextDamageTotalShields());
view.setChosenType(c.getChosenType()); view.setChosenType(c.getChosenType());
view.setChosenColors(c.getChosenColors()); view.setChosenColors(Lists.newArrayList(c.getChosenColors()));
view.setNamedCard(c.getNamedCard()); view.setNamedCard(c.getNamedCard());
if (c.isSplitCard()) { if (c.isSplitCard()) {