Commit stage 1 of large game view refactoring

This commit is contained in:
drdev
2014-10-06 04:06:42 +00:00
parent e599aef134
commit afcad4e672
92 changed files with 3490 additions and 6023 deletions

11
.gitattributes vendored
View File

@@ -271,6 +271,7 @@ forge-game/src/main/java/forge/game/GameAction.java svneol=native#text/plain
forge-game/src/main/java/forge/game/GameActionUtil.java svneol=native#text/plain forge-game/src/main/java/forge/game/GameActionUtil.java svneol=native#text/plain
forge-game/src/main/java/forge/game/GameEndReason.java -text forge-game/src/main/java/forge/game/GameEndReason.java -text
forge-game/src/main/java/forge/game/GameEntity.java -text forge-game/src/main/java/forge/game/GameEntity.java -text
forge-game/src/main/java/forge/game/GameEntityView.java -text
forge-game/src/main/java/forge/game/GameFormat.java -text forge-game/src/main/java/forge/game/GameFormat.java -text
forge-game/src/main/java/forge/game/GameLog.java -text forge-game/src/main/java/forge/game/GameLog.java -text
forge-game/src/main/java/forge/game/GameLogEntry.java -text forge-game/src/main/java/forge/game/GameLogEntry.java -text
@@ -281,6 +282,7 @@ forge-game/src/main/java/forge/game/GameOutcome.java -text
forge-game/src/main/java/forge/game/GameRules.java -text forge-game/src/main/java/forge/game/GameRules.java -text
forge-game/src/main/java/forge/game/GameStage.java -text forge-game/src/main/java/forge/game/GameStage.java -text
forge-game/src/main/java/forge/game/GameType.java -text forge-game/src/main/java/forge/game/GameType.java -text
forge-game/src/main/java/forge/game/GameView.java -text
forge-game/src/main/java/forge/game/GlobalRuleChange.java -text forge-game/src/main/java/forge/game/GlobalRuleChange.java -text
forge-game/src/main/java/forge/game/IHasGameType.java -text forge-game/src/main/java/forge/game/IHasGameType.java -text
forge-game/src/main/java/forge/game/IIdentifiable.java -text forge-game/src/main/java/forge/game/IIdentifiable.java -text
@@ -441,12 +443,14 @@ forge-game/src/main/java/forge/game/card/CardPredicates.java svneol=native#text/
forge-game/src/main/java/forge/game/card/CardShields.java -text forge-game/src/main/java/forge/game/card/CardShields.java -text
forge-game/src/main/java/forge/game/card/CardType.java svneol=native#text/plain forge-game/src/main/java/forge/game/card/CardType.java svneol=native#text/plain
forge-game/src/main/java/forge/game/card/CardUtil.java svneol=native#text/plain forge-game/src/main/java/forge/game/card/CardUtil.java svneol=native#text/plain
forge-game/src/main/java/forge/game/card/CardView.java -text
forge-game/src/main/java/forge/game/card/CounterType.java svneol=native#text/plain forge-game/src/main/java/forge/game/card/CounterType.java svneol=native#text/plain
forge-game/src/main/java/forge/game/card/package-info.java -text forge-game/src/main/java/forge/game/card/package-info.java -text
forge-game/src/main/java/forge/game/combat/AttackingBand.java -text forge-game/src/main/java/forge/game/combat/AttackingBand.java -text
forge-game/src/main/java/forge/game/combat/Combat.java svneol=native#text/plain forge-game/src/main/java/forge/game/combat/Combat.java svneol=native#text/plain
forge-game/src/main/java/forge/game/combat/CombatLki.java -text forge-game/src/main/java/forge/game/combat/CombatLki.java -text
forge-game/src/main/java/forge/game/combat/CombatUtil.java svneol=native#text/plain forge-game/src/main/java/forge/game/combat/CombatUtil.java svneol=native#text/plain
forge-game/src/main/java/forge/game/combat/CombatView.java -text
forge-game/src/main/java/forge/game/cost/Cost.java svneol=native#text/plain forge-game/src/main/java/forge/game/cost/Cost.java svneol=native#text/plain
forge-game/src/main/java/forge/game/cost/CostAddMana.java -text forge-game/src/main/java/forge/game/cost/CostAddMana.java -text
forge-game/src/main/java/forge/game/cost/CostChooseCreatureType.java -text forge-game/src/main/java/forge/game/cost/CostChooseCreatureType.java -text
@@ -550,6 +554,7 @@ forge-game/src/main/java/forge/game/player/PlayerActionConfirmMode.java -text
forge-game/src/main/java/forge/game/player/PlayerController.java -text forge-game/src/main/java/forge/game/player/PlayerController.java -text
forge-game/src/main/java/forge/game/player/PlayerOutcome.java -text forge-game/src/main/java/forge/game/player/PlayerOutcome.java -text
forge-game/src/main/java/forge/game/player/PlayerStatistics.java -text forge-game/src/main/java/forge/game/player/PlayerStatistics.java -text
forge-game/src/main/java/forge/game/player/PlayerView.java -text
forge-game/src/main/java/forge/game/player/RegisteredPlayer.java -text forge-game/src/main/java/forge/game/player/RegisteredPlayer.java -text
forge-game/src/main/java/forge/game/player/package-info.java svneol=native#text/plain forge-game/src/main/java/forge/game/player/package-info.java svneol=native#text/plain
forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java -text forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java -text
@@ -585,7 +590,9 @@ forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java svne
forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java svneol=native#text/plain
forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java svneol=native#text/plain
forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java svneol=native#text/plain
forge-game/src/main/java/forge/game/spellability/SpellAbilityView.java -text
forge-game/src/main/java/forge/game/spellability/SpellPermanent.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/SpellPermanent.java svneol=native#text/plain
forge-game/src/main/java/forge/game/spellability/StackItemView.java -text
forge-game/src/main/java/forge/game/spellability/TargetChoices.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/TargetChoices.java svneol=native#text/plain
forge-game/src/main/java/forge/game/spellability/TargetRestrictions.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/TargetRestrictions.java svneol=native#text/plain
forge-game/src/main/java/forge/game/spellability/package-info.java svneol=native#text/plain forge-game/src/main/java/forge/game/spellability/package-info.java svneol=native#text/plain
@@ -663,6 +670,10 @@ forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java svneol=nativ
forge-game/src/main/java/forge/game/zone/Zone.java -text forge-game/src/main/java/forge/game/zone/Zone.java -text
forge-game/src/main/java/forge/game/zone/ZoneType.java -text forge-game/src/main/java/forge/game/zone/ZoneType.java -text
forge-game/src/main/java/forge/game/zone/package-info.java svneol=native#text/plain forge-game/src/main/java/forge/game/zone/package-info.java svneol=native#text/plain
forge-game/src/main/java/forge/trackable/TrackableCollection.java -text
forge-game/src/main/java/forge/trackable/TrackableIndex.java -text
forge-game/src/main/java/forge/trackable/TrackableObject.java -text
forge-game/src/main/java/forge/trackable/TrackableProperty.java -text
forge-game/src/main/java/forge/util/Expressions.java -text forge-game/src/main/java/forge/util/Expressions.java -text
forge-game/src/main/java/forge/util/MessageUtil.java -text forge-game/src/main/java/forge/util/MessageUtil.java -text
forge-gui-android/.classpath -text forge-gui-android/.classpath -text

View File

@@ -27,7 +27,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@@ -1147,11 +1146,14 @@ public class AiController {
List<Card> list = player.getCardsIn(ZoneType.Battlefield); List<Card> list = player.getCardsIn(ZoneType.Battlefield);
list = CardLists.filter(list, CardPredicates.Presets.PLANEWALKERS); list = CardLists.filter(list, CardPredicates.Presets.PLANEWALKERS);
List<String> type = card.getType(); for (String type : card.getType()) { //determine planewalker subtype
final String subtype = type.get(type.size() - 1); if (!type.equals("Planeswalker")) {
final List<Card> cl = CardLists.getType(list, subtype); final List<Card> cl = CardLists.getType(list, type);
if (!cl.isEmpty()) { if (!cl.isEmpty()) {
return AiPlayDecision.WouldDestroyOtherPlaneswalker; return AiPlayDecision.WouldDestroyOtherPlaneswalker;
}
break;
}
} }
} }
if (card.isType("World")) { if (card.isType("World")) {

View File

@@ -172,7 +172,7 @@ public class AiCostDecision extends CostDecisionMakerBase implements ICostVisito
} }
List<SpellAbility> chosen = new ArrayList<SpellAbility>(); List<SpellAbility> chosen = new ArrayList<SpellAbility>();
for (SpellAbilityStackInstance si :source.getGame().getStack()) { for (SpellAbilityStackInstance si :source.getGame().getStack()) {
SpellAbility sp = si.getSpellAbility().getRootAbility(); SpellAbility sp = si.getSpellAbility(true).getRootAbility();
if (si.getSourceCard().isValid(cost.getType().split(";"), source.getController(), source)) { if (si.getSourceCard().isValid(cost.getType().split(";"), source.getController(), source)) {
chosen.add(sp); chosen.add(sp);
} }

View File

@@ -1196,7 +1196,7 @@ public class ComputerUtil {
for (StaticAbility stAb : c.getStaticAbilities()) { for (StaticAbility stAb : c.getStaticAbilities()) {
Map<String, String> params = stAb.getMapParams(); Map<String, String> params = stAb.getMapParams();
if ("Continuous".equals(params.get("Mode")) && params.containsKey("AddKeyword") if ("Continuous".equals(params.get("Mode")) && params.containsKey("AddKeyword")
&& params.get("AddKeyword").contains("Haste") && c.getEquippingCard() == null) { && params.get("AddKeyword").contains("Haste") && c.getEquipping() == null) {
return true; return true;
} }
} }
@@ -1376,7 +1376,7 @@ public class ComputerUtil {
} }
// already regenerated // already regenerated
if (!c.getShield().isEmpty()) { if (c.getShieldCount() > 0) {
continue; continue;
} }
@@ -1431,13 +1431,13 @@ public class ComputerUtil {
if (o instanceof Card) { if (o instanceof Card) {
final Card c = (Card) o; final Card c = (Card) o;
final boolean canRemove = (c.getNetDefense() <= dmg) final boolean canRemove = (c.getNetDefense() <= dmg)
|| (!c.hasKeyword("Indestructible") && c.getShield().isEmpty() && (dmg >= ComputerUtilCombat.getDamageToKill(c))); || (!c.hasKeyword("Indestructible") && c.getShieldCount() == 0 && (dmg >= ComputerUtilCombat.getDamageToKill(c)));
if (!canRemove) { if (!canRemove) {
continue; continue;
} }
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll ) { if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll ) {
final boolean cantSave = c.getNetDefense() + defense <= dmg final boolean cantSave = c.getNetDefense() + defense <= dmg
|| (!c.hasKeyword("Indestructible") && c.getShield().isEmpty() && !grantIndestructible || (!c.hasKeyword("Indestructible") && c.getShieldCount() == 0 && !grantIndestructible
&& (dmg >= defense + ComputerUtilCombat.getDamageToKill(c))); && (dmg >= defense + ComputerUtilCombat.getDamageToKill(c)));
if (cantSave && (tgt == null || !grantShroud)) { if (cantSave && (tgt == null || !grantShroud)) {
continue; continue;
@@ -1473,7 +1473,7 @@ public class ComputerUtil {
} }
// already regenerated // already regenerated
if (!c.getShield().isEmpty()) { if (c.getShieldCount() > 0) {
continue; continue;
} }

View File

@@ -784,9 +784,7 @@ public class ComputerUtilCard {
final Map<String, Integer> map = new HashMap<String, Integer>(); final Map<String, Integer> map = new HashMap<String, Integer>();
for (final Card c : list) { for (final Card c : list) {
final ArrayList<String> typeList = c.getType(); for (final String var : c.getType()) {
for (final String var : typeList) {
if (CardType.isACreatureType(var)) { if (CardType.isACreatureType(var)) {
if (!map.containsKey(var)) { if (!map.containsKey(var)) {
map.put(var, 1); map.put(var, 1);
@@ -987,7 +985,7 @@ public class ComputerUtilCard {
Combat currCombat = game.getCombat(); Combat currCombat = game.getCombat();
if (currCombat != null && !currCombat.getAllBlockers().isEmpty() && currCombat.getAllBlockers().contains(c)) { if (currCombat != null && !currCombat.getAllBlockers().isEmpty() && currCombat.getAllBlockers().contains(c)) {
for (Card attacker : currCombat.getAttackersBlockedBy(c)) { for (Card attacker : currCombat.getAttackersBlockedBy(c)) {
if (attacker.getShield().isEmpty() && ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, currCombat)) { if (attacker.getShieldCount() == 0 && ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, currCombat)) {
List<Card> blockers = currCombat.getBlockers(attacker); List<Card> blockers = currCombat.getBlockers(attacker);
ComputerUtilCard.sortByEvaluateCreature(blockers); ComputerUtilCard.sortByEvaluateCreature(blockers);
Combat combat = new Combat(ai); Combat combat = new Combat(ai);

View File

@@ -1978,7 +1978,7 @@ public class ComputerUtilCombat {
final boolean noPrevention) { final boolean noPrevention) {
final int killDamage = ComputerUtilCombat.getDamageToKill(c); final int killDamage = ComputerUtilCombat.getDamageToKill(c);
if (c.hasKeyword("Indestructible") || !c.getShield().isEmpty()) { if (c.hasKeyword("Indestructible") || c.getShieldCount() > 0) {
if (!(source.hasKeyword("Wither") || source.hasKeyword("Infect"))) { if (!(source.hasKeyword("Wither") || source.hasKeyword("Infect"))) {
return maxDamage + 1; return maxDamage + 1;
} }

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.getChosenColor().get(0))); repType = repType.replace("Chosen", MagicColor.toShortString(crd.getChosenColors().get(0)));
} }
mp.setManaReplaceType(repType); mp.setManaReplaceType(repType);
} }

View File

@@ -634,7 +634,7 @@ public class PlayerControllerAi extends PlayerController {
String choice = choices.get(0); String choice = choices.get(0);
if (game.stack.size() > 1) { if (game.stack.size() > 1) {
for (SpellAbilityStackInstance si : game.getStack()) { for (SpellAbilityStackInstance si : game.getStack()) {
SpellAbility spell = si.getSpellAbility(); SpellAbility spell = si.getSpellAbility(true);
if (sa != spell) { if (sa != spell) {
String s = ProtectAi.toProtectFrom(spell.getHostCard(), sa); String s = ProtectAi.toProtectFrom(spell.getHostCard(), sa);
if (s != null) { if (s != null) {
@@ -786,7 +786,7 @@ public class PlayerControllerAi extends PlayerController {
@Override @Override
public CardShields chooseRegenerationShield(Card c) { public CardShields chooseRegenerationShield(Card c) {
return Iterables.getFirst(c.getShield(), null); return Iterables.getFirst(c.getShields(), null);
} }
@Override @Override

View File

@@ -326,7 +326,7 @@ public class AnimateAi extends SpellAbilityAi {
final String colors = sa.getParam("Colors"); final String colors = sa.getParam("Colors");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(source.getChosenColor()); 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

@@ -678,7 +678,7 @@ public class AttachAi extends SpellAbilityAi {
//don't equip a worse creature //don't equip a worse creature
if (card.isEquipping()) { if (card.isEquipping()) {
Card oldTarget = card.getEquipping().get(0); Card oldTarget = card.getEquipping();
if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) { if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) {
return false; return false;
} }
@@ -990,7 +990,7 @@ public class AttachAi extends SpellAbilityAi {
return null; return null;
} }
// Don't fortify if already fortifying // Don't fortify if already fortifying
if (attachSource.getFortifyingCard() != null && attachSource.getFortifyingCard().getController() == aiPlayer) { if (attachSource.getFortifying() != null && attachSource.getFortifying().getController() == aiPlayer) {
return null; return null;
} }
@@ -1019,14 +1019,14 @@ public class AttachAi extends SpellAbilityAi {
AiController aic = ((PlayerControllerAi)aiPlayer.getController()).getAi(); AiController aic = ((PlayerControllerAi)aiPlayer.getController()).getAi();
if (c != null && attachSource.getType().contains("Equipment") if (c != null && attachSource.getType().contains("Equipment")
&& attachSource.getEquippingCard() != null && attachSource.isEquipping()
&& attachSource.getEquippingCard().getController() == aiPlayer) { && attachSource.getEquipping().getController() == aiPlayer) {
if (c.equals(attachSource.getEquippingCard())) { if (c.equals(attachSource.getEquipping())) {
// Do not equip if equipping the same card already // Do not equip if equipping the same card already
return null; return null;
} }
boolean uselessCreature = isUselessCreature(aiPlayer, attachSource.getEquippingCard()); boolean uselessCreature = isUselessCreature(aiPlayer, attachSource.getEquipping());
if (aic.getProperty(AiProps.MOVE_EQUIPMENT_TO_BETTER_CREATURES).equals("never")) { if (aic.getProperty(AiProps.MOVE_EQUIPMENT_TO_BETTER_CREATURES).equals("never")) {
// Do not equip other creatures if the AI profile does not allow moving equipment around // Do not equip other creatures if the AI profile does not allow moving equipment around
@@ -1330,9 +1330,7 @@ public class AttachAi extends SpellAbilityAi {
return true; return true;
} }
ArrayList<String> cardTypes = sa.getHostCard().getType(); if (sa.getHostCard().getType().contains("Equipment") && isUselessCreature(ai, c)) {
if (cardTypes.contains("Equipment") && isUselessCreature(ai, c)) {
// useless to equip a creature that can't attack or block. // useless to equip a creature that can't attack or block.
return false; return false;
} }

View File

@@ -736,7 +736,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
for (Card attacker : attackers) { for (Card attacker : attackers) {
List<Card> blockers = currCombat.getBlockers(attacker); List<Card> blockers = currCombat.getBlockers(attacker);
// Save my attacker by bouncing a blocker // Save my attacker by bouncing a blocker
if (attacker.getController().equals(ai) && attacker.getShield().isEmpty() if (attacker.getController().equals(ai) && attacker.getShieldCount() == 0
&& ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, currCombat) && ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, currCombat)
&& !currCombat.getBlockers(attacker).isEmpty()) { && !currCombat.getBlockers(attacker).isEmpty()) {
ComputerUtilCard.sortByEvaluateCreature(blockers); ComputerUtilCard.sortByEvaluateCreature(blockers);
@@ -799,7 +799,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
ComputerUtilCard.sortByEvaluateCreature(combatants); ComputerUtilCard.sortByEvaluateCreature(combatants);
for (final Card c : combatants) { for (final Card c : combatants) {
if (c.getShield().isEmpty() && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat) && c.getOwner() == ai && !c.isToken()) { if (c.getShieldCount() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat) && c.getOwner() == ai && !c.isToken()) {
sa.getTargets().add(c); sa.getTargets().add(c);
return true; return true;
} }

View File

@@ -157,7 +157,7 @@ public class ChooseSourceAi extends SpellAbilityAi {
private Card chooseCardOnStack(SpellAbility sa, Player ai, Game game) { private Card chooseCardOnStack(SpellAbility sa, Player ai, Game game) {
for (SpellAbilityStackInstance si : game.getStack()) { for (SpellAbilityStackInstance si : game.getStack()) {
final Card source = si.getSourceCard(); final Card source = si.getSourceCard();
final SpellAbility abilityOnStack = si.getSpellAbility(); final SpellAbility abilityOnStack = si.getSpellAbility(true);
if (sa.hasParam("Choices") && !abilityOnStack.getHostCard().isValid(sa.getParam("Choices"), ai, sa.getHostCard())) { if (sa.hasParam("Choices") && !abilityOnStack.getHostCard().isValid(sa.getParam("Choices"), ai, sa.getHostCard())) {
continue; continue;

View File

@@ -287,7 +287,7 @@ public class DamageDealAi extends DamageAiBase {
} }
final int assignedDamage = ComputerUtilCombat.getEnoughDamageToKill(humanCreature, dmg, source, false, noPrevention); final int assignedDamage = ComputerUtilCombat.getEnoughDamageToKill(humanCreature, dmg, source, false, noPrevention);
if (assignedDamage <= dmg if (assignedDamage <= dmg
&& humanCreature.getShield().isEmpty() && !ComputerUtil.canRegenerate(humanCreature.getController(), humanCreature)) { && humanCreature.getShieldCount() == 0 && !ComputerUtil.canRegenerate(humanCreature.getController(), humanCreature)) {
tcs.add(humanCreature); tcs.add(humanCreature);
tgt.addDividedAllocation(humanCreature, assignedDamage); tgt.addDividedAllocation(humanCreature, assignedDamage);
lastTgt = humanCreature; lastTgt = humanCreature;

View File

@@ -113,7 +113,7 @@ public class DestroyAi 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) {
return (c.getShield().isEmpty() && !ComputerUtil.canRegenerate(ai, c)); return (c.getShieldCount() == 0 && !ComputerUtil.canRegenerate(ai, c));
} }
}); });
} }
@@ -237,7 +237,7 @@ public class DestroyAi extends SpellAbilityAi {
preferred = CardLists.filter(preferred, new Predicate<Card>() { preferred = CardLists.filter(preferred, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
return c.getShield().isEmpty(); return c.getShieldCount() == 0;
} }
}); });
} }

View File

@@ -118,10 +118,11 @@ public class EffectAi extends SpellAbilityAi {
return false; return false;
} }
boolean threatened = false; boolean threatened = false;
for (final SpellAbilityStackInstance stackSA : game.getStack()) { for (final SpellAbilityStackInstance stackInst : game.getStack()) {
if (!stackSA.isSpell()) { continue; } if (!stackInst.isSpell()) { continue; }
if (stackSA.getSpellAbility().getApi() == ApiType.DealDamage) { SpellAbility stackSpellAbility = stackInst.getSpellAbility(true);
final SpellAbility saTargeting = stackSA.getSpellAbility().getSATargetingPlayer(); if (stackSpellAbility.getApi() == ApiType.DealDamage) {
final SpellAbility saTargeting = stackSpellAbility.getSATargetingPlayer();
if (saTargeting != null && Iterables.contains(saTargeting.getTargets().getTargetPlayers(), ai)) { if (saTargeting != null && Iterables.contains(saTargeting.getTargets().getTargetPlayers(), ai)) {
threatened = true; threatened = true;
} }

View File

@@ -153,7 +153,7 @@ public class FightAi extends SpellAbilityAi {
return true; return true;
} }
if (opponent.hasProtectionFrom(fighter) || !opponent.canBeDestroyed() if (opponent.hasProtectionFrom(fighter) || !opponent.canBeDestroyed()
|| !opponent.getShield().isEmpty() || ComputerUtil.canRegenerate(opponent.getController(), opponent)) { || opponent.getShieldCount() > 0 || ComputerUtil.canRegenerate(opponent.getController(), opponent)) {
return false; return false;
} }
if (fighter.hasKeyword("Deathtouch") || ComputerUtilCombat.getDamageToKill(opponent) <= fighter.getNetAttack() + pumpAttack) { if (fighter.hasKeyword("Deathtouch") || ComputerUtilCombat.getDamageToKill(opponent) <= fighter.getNetAttack() + pumpAttack) {

View File

@@ -138,7 +138,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
return false; return false;
} }
} else if (keyword.endsWith("CARDNAME can't be regenerated.")) { } else if (keyword.endsWith("CARDNAME can't be regenerated.")) {
if (!card.getShield().isEmpty()) { if (card.getShieldCount() > 0) {
return true; return true;
} }
if (card.hasKeyword("If CARDNAME would be destroyed, regenerate it.") && combat != null if (card.hasKeyword("If CARDNAME would be destroyed, regenerate it.") && combat != null

View File

@@ -99,7 +99,7 @@ public class RegenerateAi extends SpellAbilityAi {
boolean flag = false; boolean flag = false;
for (final Card c : list) { for (final Card c : list) {
if (c.getShield().isEmpty()) { if (c.getShieldCount() == 0) {
flag |= ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat); flag |= ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat);
} }
} }
@@ -128,7 +128,7 @@ public class RegenerateAi extends SpellAbilityAi {
final List<Card> threatenedTargets = new ArrayList<Card>(); final List<Card> threatenedTargets = new ArrayList<Card>();
for (final Card c : targetables) { for (final Card c : targetables) {
if (objects.contains(c) && c.getShield().isEmpty() && !ComputerUtil.canRegenerate(ai, c)) { if (objects.contains(c) && c.getShieldCount() == 0 && !ComputerUtil.canRegenerate(ai, c)) {
threatenedTargets.add(c); threatenedTargets.add(c);
} }
} }
@@ -144,7 +144,7 @@ public class RegenerateAi extends SpellAbilityAi {
ComputerUtilCard.sortByEvaluateCreature(combatants); ComputerUtilCard.sortByEvaluateCreature(combatants);
for (final Card c : combatants) { for (final Card c : combatants) {
if (c.getShield().isEmpty() && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) { if (c.getShieldCount() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) {
sa.getTargets().add(c); sa.getTargets().add(c);
chance = true; chance = true;
break; break;
@@ -200,7 +200,7 @@ public class RegenerateAi extends SpellAbilityAi {
if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
Combat combat = game.getCombat(); Combat combat = game.getCombat();
for (final Card c : combatants) { for (final Card c : combatants) {
if (c.getShield().isEmpty() && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) { if (c.getShieldCount() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) {
sa.getTargets().add(c); sa.getTargets().add(c);
return true; return true;
} }
@@ -213,7 +213,7 @@ public class RegenerateAi extends SpellAbilityAi {
// choose my best X without regen // choose my best X without regen
if (CardLists.getNotType(compTargetables, "Creature").isEmpty()) { if (CardLists.getNotType(compTargetables, "Creature").isEmpty()) {
for (final Card c : combatants) { for (final Card c : combatants) {
if (c.getShield().isEmpty()) { if (c.getShieldCount() == 0) {
sa.getTargets().add(c); sa.getTargets().add(c);
return true; return true;
} }
@@ -223,7 +223,7 @@ public class RegenerateAi extends SpellAbilityAi {
} else { } else {
CardLists.sortByCmcDesc(compTargetables); CardLists.sortByCmcDesc(compTargetables);
for (final Card c : compTargetables) { for (final Card c : compTargetables) {
if (c.getShield().isEmpty()) { if (c.getShieldCount() == 0) {
sa.getTargets().add(c); sa.getTargets().add(c);
return true; return true;
} }

View File

@@ -61,7 +61,7 @@ public class RegenerateAllAi extends SpellAbilityAi {
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa); final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa);
for (final Card c : list) { for (final Card c : list) {
if (objects.contains(c) && c.getShield().isEmpty()) { if (objects.contains(c) && c.getShieldCount() == 0) {
numSaved++; numSaved++;
} }
} }
@@ -70,7 +70,7 @@ public class RegenerateAllAi extends SpellAbilityAi {
final List<Card> combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES); final List<Card> combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES);
final Combat combat = game.getCombat(); final Combat combat = game.getCombat();
for (final Card c : combatants) { for (final Card c : combatants) {
if (c.getShield().isEmpty() && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) { if (c.getShieldCount() == 0 && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat)) {
numSaved++; numSaved++;
} }
} }

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.getChosenColor().get(0); substitutedColors[i] = host.getChosenColors().get(0);
} }
} }
String colorDesc = ""; String colorDesc = "";

View File

@@ -83,7 +83,7 @@ public class UnattachAllAi extends SpellAbilityAi {
//don't equip a worse creature //don't equip a worse creature
if (card.isEquipping()) { if (card.isEquipping()) {
Card oldTarget = card.getEquipping().get(0); Card oldTarget = card.getEquipping();
if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) { if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) {
return false; return false;
} }

View File

@@ -100,6 +100,8 @@ public class Game implements IGameStateObject {
private GameOutcome outcome; private GameOutcome outcome;
private boolean disableAutoYields; private boolean disableAutoYields;
private final GameView view = new GameView();
@Override @Override
public void loadState(GameStateDeserializer gsd) { public void loadState(GameStateDeserializer gsd) {
gsd.readObject(rules); gsd.readObject(rules);
@@ -202,6 +204,10 @@ public class Game implements IGameStateObject {
subscribeToEvents(gameLog.getEventVisitor()); subscribeToEvents(gameLog.getEventVisitor());
} }
public GameView getView() {
return view;
}
/** /**
* Gets the players who are still fighting to win, in turn order. * Gets the players who are still fighting to win, in turn order.
* *

View File

@@ -354,14 +354,14 @@ public class GameAction {
} }
// equipment moving off battlefield // equipment moving off battlefield
if (copied.isEquipping()) { if (copied.isEquipping()) {
final Card equippedCreature = copied.getEquipping().get(0); final Card equippedCreature = copied.getEquipping();
if (equippedCreature.isInPlay()) { if (equippedCreature.isInPlay()) {
copied.unEquipCard(equippedCreature); copied.unEquipCard(equippedCreature);
} }
} }
// fortifications moving off battlefield // fortifications moving off battlefield
if (copied.isFortifying()) { if (copied.isFortifying()) {
final Card fortifiedLand = copied.getFortifying().get(0); final Card fortifiedLand = copied.getFortifying();
if (fortifiedLand.isInPlay()) { if (fortifiedLand.isInPlay()) {
copied.unFortifyCard(fortifiedLand); copied.unFortifyCard(fortifiedLand);
} }
@@ -1040,7 +1040,7 @@ public class GameAction {
} // if isFortified() } // if isFortified()
if (c.isEquipping()) { if (c.isEquipping()) {
final Card equippedCreature = c.getEquipping().get(0); final Card equippedCreature = c.getEquipping();
if (!equippedCreature.isCreature() || !equippedCreature.isInPlay() if (!equippedCreature.isCreature() || !equippedCreature.isInPlay()
|| !equippedCreature.canBeEquippedBy(c) || !equippedCreature.canBeEquippedBy(c)
|| (equippedCreature.isPhasedOut() && !c.isPhasedOut()) || (equippedCreature.isPhasedOut() && !c.isPhasedOut())
@@ -1056,7 +1056,7 @@ public class GameAction {
} // if isEquipping() } // if isEquipping()
if (c.isFortifying()) { if (c.isFortifying()) {
final Card fortifiedLand = c.getFortifying().get(0); final Card fortifiedLand = c.getFortifying();
if (!fortifiedLand.isLand() || !fortifiedLand.isInPlay() if (!fortifiedLand.isLand() || !fortifiedLand.isInPlay()
|| (fortifiedLand.isPhasedOut() && !c.isPhasedOut())) { || (fortifiedLand.isPhasedOut() && !c.isPhasedOut())) {
c.unFortifyCard(fortifiedLand); c.unFortifyCard(fortifiedLand);
@@ -1071,11 +1071,6 @@ public class GameAction {
return checkAgain; return checkAgain;
} }
/**
* TODO: Write javadoc for this method.
* @param c
* @return
*/
private boolean stateBasedAction704_5r(Card c) { private boolean stateBasedAction704_5r(Card c) {
boolean checkAgain = false; boolean checkAgain = false;
int plusOneCounters = c.getCounters(CounterType.P1P1); int plusOneCounters = c.getCounters(CounterType.P1P1);
@@ -1334,7 +1329,7 @@ public class GameAction {
} }
if (c.canBeShielded() && (!c.isCreature() || c.getNetDefense() > 0) if (c.canBeShielded() && (!c.isCreature() || c.getNetDefense() > 0)
&& (!c.getShield().isEmpty() || c.hasKeyword("If CARDNAME would be destroyed, regenerate it."))) { && (c.getShieldCount() > 0 || c.hasKeyword("If CARDNAME would be destroyed, regenerate it."))) {
c.subtractShield(c.getController().getController().chooseRegenerationShield(c)); c.subtractShield(c.getController().getController().chooseRegenerationShield(c));
c.setDamage(0); c.setDamage(0);
c.tap(); c.tap();
@@ -1483,7 +1478,7 @@ public class GameAction {
final Card persistCard = newCard; final Card persistCard = newCard;
String effect = String.format("AB$ ChangeZone | Cost$ 0 | Defined$ CardUID_%d" + String effect = String.format("AB$ ChangeZone | Cost$ 0 | Defined$ CardUID_%d" +
" | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ M1M1_1", " | Origin$ Graveyard | Destination$ Battlefield | WithCounters$ M1M1_1",
persistCard.getUniqueNumber()); persistCard.getId());
SpellAbility persistAb = AbilityFactory.getAbility(effect, c); SpellAbility persistAb = AbilityFactory.getAbility(effect, c);
persistAb.setTrigger(true); persistAb.setTrigger(true);
persistAb.setStackDescription(newCard.getName() + " - Returning from Persist"); persistAb.setStackDescription(newCard.getName() + " - Returning from Persist");
@@ -1497,7 +1492,7 @@ public class GameAction {
final Card undyingCard = newCard; final Card undyingCard = newCard;
String effect = String.format("AB$ ChangeZone | Cost$ 0 | Defined$ CardUID_%d |" + String effect = String.format("AB$ ChangeZone | Cost$ 0 | Defined$ CardUID_%d |" +
" Origin$ Graveyard | Destination$ Battlefield | WithCounters$ P1P1_1", " Origin$ Graveyard | Destination$ Battlefield | WithCounters$ P1P1_1",
undyingCard.getUniqueNumber()); undyingCard.getId());
SpellAbility undyingAb = AbilityFactory.getAbility(effect, c); SpellAbility undyingAb = AbilityFactory.getAbility(effect, c);
undyingAb.setTrigger(true); undyingAb.setTrigger(true);
undyingAb.setStackDescription(newCard.getName() + " - Returning from Undying"); undyingAb.setStackDescription(newCard.getName() + " - Returning from Undying");

View File

@@ -438,4 +438,5 @@ public abstract class GameEntity extends GameObject {
} }
public abstract Game getGame(); public abstract Game getGame();
public abstract GameEntityView<?> getView();
} }

View File

@@ -0,0 +1,22 @@
package forge.game;
import forge.trackable.TrackableObject;
public abstract class GameEntityView<E extends Enum<E>> extends TrackableObject<E> {
public static GameEntityView<?> get(GameEntity e) {
return e == null ? null : e.getView();
}
protected GameEntityView(int id0, Class<E> propEnum0) {
super(id0, propEnum0);
}
protected abstract E preventNextDamageProp();
public int getPreventNextDamage() {
return get(preventNextDamageProp());
}
void updatePreventNextDamage(GameEntity e) {
set(preventNextDamageProp(), e.getPreventNextDamageTotalShields());
}
}

View File

@@ -0,0 +1,50 @@
package forge.game;
import java.util.List;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.combat.AttackingBand;
import forge.game.combat.Combat;
import forge.game.combat.CombatView;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbilityView;
import forge.game.spellability.StackItemView;
import forge.trackable.TrackableIndex;
public class GameView {
private final TrackableIndex<CardView> cards = new TrackableIndex<CardView>();
private final TrackableIndex<PlayerView> players = new TrackableIndex<PlayerView>();
private final TrackableIndex<SpellAbilityView> spellAbilities = new TrackableIndex<SpellAbilityView>();
private final TrackableIndex<StackItemView> stackItems = new TrackableIndex<StackItemView>();
private CombatView combatView;
public GameView() {
}
public CombatView getCombatView() {
return combatView;
}
public void refreshCombat(Game game) {
final Combat combat = game.getCombat();
if (combat == null) {
combatView = null;
return;
}
combatView = new CombatView();
for (final AttackingBand b : combat.getAttackingBands()) {
if (b == null) continue;
final GameEntity defender = combat.getDefenderByAttacker(b);
final List<Card> blockers = combat.getBlockers(b);
final boolean isBlocked = b.isBlocked() == Boolean.TRUE;
combatView.addAttackingBand(
CardView.getCollection(b.getAttackers()),
GameEntityView.get(defender),
isBlocked ? CardView.getCollection(blockers) : null,
CardView.getCollection(blockers));
}
}
}

View File

@@ -146,7 +146,7 @@ public class StaticEffects implements IGameStateObject {
if (params.containsKey("AddColor")) { if (params.containsKey("AddColor")) {
final String colors = params.get("AddColor"); final String colors = params.get("AddColor");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
addColors = CardUtil.getShortColorsString(se.getSource().getChosenColor()); addColors = CardUtil.getShortColorsString(se.getSource().getChosenColors());
} else { } else {
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & ")))); addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & "))));
} }
@@ -155,7 +155,7 @@ public class StaticEffects implements IGameStateObject {
if (params.containsKey("SetColor")) { if (params.containsKey("SetColor")) {
final String colors = params.get("SetColor"); final String colors = params.get("SetColor");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
addColors = CardUtil.getShortColorsString(se.getSource().getChosenColor()); addColors = CardUtil.getShortColorsString(se.getSource().getChosenColors());
} else { } else {
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & ")))); addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(" & "))));
} }

View File

@@ -89,19 +89,16 @@ public class AbilityUtils {
if (defined.equals("Self")) { if (defined.equals("Self")) {
c = hostCard; c = hostCard;
} }
else if (defined.equals("OriginalHost")) { else if (defined.equals("OriginalHost")) {
c = sa.getRootAbility().getOriginalHost(); c = sa.getRootAbility().getOriginalHost();
} }
else if (defined.equals("EffectSource")) { else if (defined.equals("EffectSource")) {
if (hostCard.isType("Effect")) { if (hostCard.isType("Effect")) {
c = AbilityUtils.findEffectRoot(hostCard); c = AbilityUtils.findEffectRoot(hostCard);
} }
} }
else if (defined.equals("Equipped")) { else if (defined.equals("Equipped")) {
c = hostCard.getEquippingCard(); c = hostCard.getEquipping();
} }
else if (defined.equals("Enchanted")) { else if (defined.equals("Enchanted")) {
@@ -112,7 +109,6 @@ public class AbilityUtils {
c = sa.getRootAbility().getPaidList("Sacrificed").get(0).getEnchantingCard(); c = sa.getRootAbility().getPaidList("Sacrificed").get(0).getEnchantingCard();
} }
} }
else if (defined.endsWith("OfLibrary")) { else if (defined.endsWith("OfLibrary")) {
final List<Card> lib = hostCard.getController().getCardsIn(ZoneType.Library); final List<Card> lib = hostCard.getController().getCardsIn(ZoneType.Library);
if (lib.size() > 0) { // TopOfLibrary or BottomOfLibrary if (lib.size() > 0) { // TopOfLibrary or BottomOfLibrary
@@ -121,22 +117,26 @@ public class AbilityUtils {
// we don't want this to fall through and return the "Self" // we don't want this to fall through and return the "Self"
return cards; return cards;
} }
} else if (defined.equals("Targeted")) { }
else if (defined.equals("Targeted")) {
final SpellAbility saTargeting = sa.getSATargetingCard(); final SpellAbility saTargeting = sa.getSATargetingCard();
if (saTargeting != null) { if (saTargeting != null) {
Iterables.addAll(cards, saTargeting.getTargets().getTargetCards()); Iterables.addAll(cards, saTargeting.getTargets().getTargetCards());
} }
} else if (defined.equals("ThisTargetedCard")) { // do not add parent targeted }
else if (defined.equals("ThisTargetedCard")) { // do not add parent targeted
if (sa != null && sa.getTargets() != null) { if (sa != null && sa.getTargets() != null) {
Iterables.addAll(cards, sa.getTargets().getTargetCards()); Iterables.addAll(cards, sa.getTargets().getTargetCards());
} }
} else if (defined.equals("ParentTarget")) { }
else if (defined.equals("ParentTarget")) {
final SpellAbility parent = sa.getParentTargetingCard(); final SpellAbility parent = sa.getParentTargetingCard();
if (parent != null) { if (parent != null) {
Iterables.addAll(cards, parent.getTargets().getTargetCards()); Iterables.addAll(cards, parent.getTargets().getTargetCards());
} }
} else if (defined.startsWith("Triggered") && (sa != null)) { }
else if (defined.startsWith("Triggered") && (sa != null)) {
final SpellAbility root = sa.getRootAbility(); final SpellAbility root = sa.getRootAbility();
if (defined.contains("LKICopy")) { //TriggeredCardLKICopy if (defined.contains("LKICopy")) { //TriggeredCardLKICopy
final Object crd = root.getTriggeringObject(defined.substring(9, 13)); final Object crd = root.getTriggeringObject(defined.substring(9, 13));
@@ -154,7 +154,8 @@ public class AbilityUtils {
} }
} }
} }
} else if (defined.startsWith("Replaced") && (sa != null)) { }
else if (defined.startsWith("Replaced") && (sa != null)) {
final SpellAbility root = sa.getRootAbility(); final SpellAbility root = sa.getRootAbility();
final Object crd = root.getReplacingObject(defined.substring(8)); final Object crd = root.getReplacingObject(defined.substring(8));
if (crd instanceof Card) { if (crd instanceof Card) {
@@ -164,7 +165,8 @@ public class AbilityUtils {
cards.add(cardItem); cards.add(cardItem);
} }
} }
} else if (defined.equals("Remembered")) { }
else if (defined.equals("Remembered")) {
if (hostCard.getRemembered().isEmpty()) { if (hostCard.getRemembered().isEmpty()) {
final Card newCard = game.getCardState(hostCard); final Card newCard = game.getCardState(hostCard);
for (final Object o : newCard.getRemembered()) { for (final Object o : newCard.getRemembered()) {
@@ -179,7 +181,8 @@ public class AbilityUtils {
cards.add(game.getCardState((Card) o)); cards.add(game.getCardState((Card) o));
} }
} }
} else if (defined.equals("DirectRemembered")) { }
else if (defined.equals("DirectRemembered")) {
if (hostCard.getRemembered().isEmpty()) { if (hostCard.getRemembered().isEmpty()) {
final Card newCard = game.getCardState(hostCard); final Card newCard = game.getCardState(hostCard);
for (final Object o : newCard.getRemembered()) { for (final Object o : newCard.getRemembered()) {
@@ -194,7 +197,8 @@ public class AbilityUtils {
cards.add((Card) o); cards.add((Card) o);
} }
} }
} else if (defined.equals("DelayTriggerRemembered")) { }
else if (defined.equals("DelayTriggerRemembered")) {
if (sa.getRootAbility().isTrigger()) { if (sa.getRootAbility().isTrigger()) {
for (Object o : sa.getRootAbility().getTriggerRemembered()) { for (Object o : sa.getRootAbility().getTriggerRemembered()) {
if (o instanceof Card) { if (o instanceof Card) {
@@ -202,20 +206,24 @@ public class AbilityUtils {
} }
} }
} }
} else if (defined.equals("FirstRemembered")) { }
else if (defined.equals("FirstRemembered")) {
Object o = Iterables.getFirst(hostCard.getRemembered(), null); Object o = Iterables.getFirst(hostCard.getRemembered(), null);
if (o != null && o instanceof Card) { if (o != null && o instanceof Card) {
cards.add(game.getCardState((Card) o)); cards.add(game.getCardState((Card) o));
} }
} else if (defined.equals("Clones")) { }
else if (defined.equals("Clones")) {
for (final Card clone : hostCard.getClones()) { for (final Card clone : hostCard.getClones()) {
cards.add(game.getCardState(clone)); cards.add(game.getCardState(clone));
} }
} else if (defined.equals("Imprinted")) { }
else if (defined.equals("Imprinted")) {
for (final Card imprint : hostCard.getImprinted()) { for (final Card imprint : hostCard.getImprinted()) {
cards.add(game.getCardState(imprint)); cards.add(game.getCardState(imprint));
} }
} else if (defined.startsWith("ThisTurnEntered")) { }
else if (defined.startsWith("ThisTurnEntered")) {
final String[] workingCopy = defined.split("_"); final String[] workingCopy = defined.split("_");
ZoneType destination, origin; ZoneType destination, origin;
String validFilter; String validFilter;
@@ -231,7 +239,8 @@ public class AbilityUtils {
for (final Card cl : CardUtil.getThisTurnEntered(destination, origin, validFilter, hostCard)) { for (final Card cl : CardUtil.getThisTurnEntered(destination, origin, validFilter, hostCard)) {
cards.add(game.getCardState(cl)); cards.add(game.getCardState(cl));
} }
} else if (defined.equals("ChosenCard")) { }
else if (defined.equals("ChosenCard")) {
for (final Card chosen : hostCard.getChosenCard()) { for (final Card chosen : hostCard.getChosenCard()) {
cards.add(game.getCardState(chosen)); cards.add(game.getCardState(chosen));
} }
@@ -239,11 +248,12 @@ public class AbilityUtils {
else if (defined.startsWith("CardUID_")) { else if (defined.startsWith("CardUID_")) {
String idString = defined.substring(8); String idString = defined.substring(8);
for (final Card cardByID : game.getCardsInGame()) { for (final Card cardByID : game.getCardsInGame()) {
if (cardByID.getUniqueNumber() == Integer.valueOf(idString)) { if (cardByID.getId() == Integer.valueOf(idString)) {
cards.add(game.getCardState(cardByID)); cards.add(game.getCardState(cardByID));
} }
} }
} else { }
else {
List<Card> list = null; List<Card> list = null;
if (defined.startsWith("SacrificedCards")) { if (defined.startsWith("SacrificedCards")) {
list = sa.getRootAbility().getPaidList("SacrificedCards"); list = sa.getRootAbility().getPaidList("SacrificedCards");
@@ -251,50 +261,42 @@ public class AbilityUtils {
else if (defined.startsWith("Sacrificed")) { else if (defined.startsWith("Sacrificed")) {
list = sa.getRootAbility().getPaidList("Sacrificed"); list = sa.getRootAbility().getPaidList("Sacrificed");
} }
else if (defined.startsWith("DiscardedCards")) { else if (defined.startsWith("DiscardedCards")) {
list = sa.getRootAbility().getPaidList("DiscardedCards"); list = sa.getRootAbility().getPaidList("DiscardedCards");
} }
else if (defined.startsWith("Discarded")) { else if (defined.startsWith("Discarded")) {
list = sa.getRootAbility().getPaidList("Discarded"); list = sa.getRootAbility().getPaidList("Discarded");
} }
else if (defined.startsWith("ExiledCards")) { else if (defined.startsWith("ExiledCards")) {
list = sa.getRootAbility().getPaidList("ExiledCards"); list = sa.getRootAbility().getPaidList("ExiledCards");
} }
else if (defined.startsWith("Exiled")) { else if (defined.startsWith("Exiled")) {
list = sa.getRootAbility().getPaidList("Exiled"); list = sa.getRootAbility().getPaidList("Exiled");
} }
else if (defined.startsWith("TappedCards")) { else if (defined.startsWith("TappedCards")) {
list = sa.getRootAbility().getPaidList("TappedCards"); list = sa.getRootAbility().getPaidList("TappedCards");
} }
else if (defined.startsWith("Tapped")) { else if (defined.startsWith("Tapped")) {
list = sa.getRootAbility().getPaidList("Tapped"); list = sa.getRootAbility().getPaidList("Tapped");
} }
else if (defined.startsWith("UntappedCards")) { else if (defined.startsWith("UntappedCards")) {
list = sa.getRootAbility().getPaidList("UntappedCards"); list = sa.getRootAbility().getPaidList("UntappedCards");
} }
else if (defined.startsWith("Untapped")) { else if (defined.startsWith("Untapped")) {
list = sa.getRootAbility().getPaidList("Untapped"); list = sa.getRootAbility().getPaidList("Untapped");
} }
else if (defined.startsWith("Valid ")) { else if (defined.startsWith("Valid ")) {
String validDefined = defined.substring("Valid ".length()); String validDefined = defined.substring("Valid ".length());
list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), validDefined.split(","), hostCard.getController(), hostCard); list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), validDefined.split(","), hostCard.getController(), hostCard);
} }
else if (defined.startsWith("ValidHand ")) { else if (defined.startsWith("ValidHand ")) {
String validDefined = defined.substring("ValidHand ".length()); String validDefined = defined.substring("ValidHand ".length());
list = CardLists.getValidCards(game.getCardsIn(ZoneType.Hand), validDefined.split(","), hostCard.getController(), hostCard); list = CardLists.getValidCards(game.getCardsIn(ZoneType.Hand), validDefined.split(","), hostCard.getController(), hostCard);
} }
else if (defined.startsWith("ValidAll ")) { else if (defined.startsWith("ValidAll ")) {
String validDefined = defined.substring("ValidAll ".length()); String validDefined = defined.substring("ValidAll ".length());
list = CardLists.getValidCards(game.getCardsInGame(), validDefined.split(","), hostCard.getController(), hostCard); list = CardLists.getValidCards(game.getCardsInGame(), validDefined.split(","), hostCard.getController(), hostCard);
} }
else { else {
return cards; return cards;
} }
@@ -307,7 +309,6 @@ public class AbilityUtils {
if (c != null) { if (c != null) {
cards.add(c); cards.add(c);
} }
return cards; return cards;
} }
@@ -1151,7 +1152,7 @@ public class AbilityUtils {
for (SpellAbility targetSpell : saTargeting.getTargets().getTargetSpells()) { for (SpellAbility targetSpell : saTargeting.getTargets().getTargetSpells()) {
SpellAbilityStackInstance stackInstance = game.getStack().getInstanceFromSpellAbility(targetSpell); SpellAbilityStackInstance stackInstance = game.getStack().getInstanceFromSpellAbility(targetSpell);
if (stackInstance != null) { if (stackInstance != null) {
SpellAbility instanceSA = stackInstance.getSpellAbility(); SpellAbility instanceSA = stackInstance.getSpellAbility(true);
if (instanceSA != null) { if (instanceSA != null) {
sas.add(instanceSA); sas.add(instanceSA);
} }

View File

@@ -89,7 +89,7 @@ public class AnimateAllEffect extends AnimateEffectBase {
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(host.getChosenColor()); tmpDesc = CardUtil.getShortColorsString(host.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

@@ -109,7 +109,7 @@ public class AnimateEffect extends AnimateEffectBase {
final String colors = sa.getParam("Colors"); final String colors = sa.getParam("Colors");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(source.getChosenColor()); 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

@@ -50,21 +50,21 @@ public class ChangeTargetsEffect extends SpellAbilityEffect {
// Redirect rules read 'you MAY choose new targets' ... okay! // Redirect rules read 'you MAY choose new targets' ... okay!
// TODO: Don't even ask to change targets, if the SA and subs don't actually have targets // TODO: Don't even ask to change targets, if the SA and subs don't actually have targets
boolean isOptional = sa.hasParam("Optional"); boolean isOptional = sa.hasParam("Optional");
if( isOptional && !chooser.getController().confirmAction(sa, null, "Do you want to change targets of " + tgtSA.getHostCard() + "?")) if (isOptional && !chooser.getController().confirmAction(sa, null, "Do you want to change targets of " + tgtSA.getHostCard() + "?")) {
continue; continue;
}
if( changesOneTarget ) { if (changesOneTarget) {
// 1. choose a target of target spell // 1. choose a target of target spell
List<Pair<SpellAbilityStackInstance, GameObject>> allTargets = new ArrayList<>(); List<Pair<SpellAbilityStackInstance, GameObject>> allTargets = new ArrayList<>();
while(changingTgtSI != null) { while(changingTgtSI != null) {
SpellAbility changedSa = changingTgtSI.getSpellAbility(); SpellAbility changedSa = changingTgtSI.getSpellAbility(true);
if(changedSa.usesTargeting()) { if (changedSa.usesTargeting()) {
for(GameObject it : changedSa.getTargets().getTargets()) for(GameObject it : changedSa.getTargets().getTargets())
allTargets.add(ImmutablePair.of(changingTgtSI, it)); allTargets.add(ImmutablePair.of(changingTgtSI, it));
} }
changingTgtSI = changingTgtSI.getSubInstance(); changingTgtSI = changingTgtSI.getSubInstance();
} }
if( allTargets.isEmpty() ) { if (allTargets.isEmpty()) {
// is it an error or not? // is it an error or not?
System.err.println("Player managed to target a spell without targets with Spellskite's ability."); System.err.println("Player managed to target a spell without targets with Spellskite's ability.");
return; return;
@@ -80,28 +80,33 @@ public class ChangeTargetsEffect extends SpellAbilityEffect {
replaceIn.updateTarget(newTargetBlock); replaceIn.updateTarget(newTargetBlock);
// 3. test if updated choices would be correct. // 3. test if updated choices would be correct.
GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa), null); GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa), null);
if(replaceIn.getSpellAbility().canTarget(newTarget)) { if (replaceIn.getSpellAbility(true).canTarget(newTarget)) {
newTargetBlock.add(newTarget); newTargetBlock.add(newTarget);
replaceIn.updateTarget(newTargetBlock); replaceIn.updateTarget(newTargetBlock);
} else }
else {
replaceIn.updateTarget(oldTargetBlock); replaceIn.updateTarget(oldTargetBlock);
} else { }
}
else {
while(changingTgtSI != null) { while(changingTgtSI != null) {
SpellAbility changingTgtSA = changingTgtSI.getSpellAbility(); SpellAbility changingTgtSA = changingTgtSI.getSpellAbility(true);
if (sa.hasParam("RandomTarget")){ if (sa.hasParam("RandomTarget")){
changingTgtSA.resetTargets(); changingTgtSA.resetTargets();
List<GameEntity> candidates = changingTgtSA.getTargetRestrictions().getAllCandidates(changingTgtSA, true); List<GameEntity> candidates = changingTgtSA.getTargetRestrictions().getAllCandidates(changingTgtSA, true);
GameEntity choice = Aggregates.random(candidates); GameEntity choice = Aggregates.random(candidates);
changingTgtSA.getTargets().add(choice); changingTgtSA.getTargets().add(choice);
changingTgtSI.updateTarget(changingTgtSA.getTargets()); changingTgtSI.updateTarget(changingTgtSA.getTargets());
} else if (sa.hasParam("DefinedMagnet")){ }
else if (sa.hasParam("DefinedMagnet")){
GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa, "DefinedMagnet"), null); GameObject newTarget = Iterables.getFirst(getDefinedCardsOrTargeted(sa, "DefinedMagnet"), null);
if(changingTgtSA.canTarget(newTarget)) { if (changingTgtSA.canTarget(newTarget)) {
changingTgtSA.resetTargets(); changingTgtSA.resetTargets();
changingTgtSA.getTargets().add(newTarget); changingTgtSA.getTargets().add(newTarget);
changingTgtSI.updateTarget(changingTgtSA.getTargets()); changingTgtSI.updateTarget(changingTgtSA.getTargets());
} }
} else { }
else {
// Update targets, with a potential new target // Update targets, with a potential new target
TargetChoices newTarget = sa.getActivatingPlayer().getController().chooseNewTargetsFor(changingTgtSA); TargetChoices newTarget = sa.getActivatingPlayer().getController().chooseNewTargetsFor(changingTgtSA);
if (null != newTarget) { if (null != newTarget) {

View File

@@ -471,14 +471,14 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
tgtC.enchantEntity(attachedTo); tgtC.enchantEntity(attachedTo);
} else if (tgtC.isEquipment()) { //Equipment } else if (tgtC.isEquipment()) { //Equipment
if (tgtC.isEquipping()) { if (tgtC.isEquipping()) {
final Card oldEquiped = tgtC.getEquippingCard(); final Card oldEquiped = tgtC.getEquipping();
if ( null != oldEquiped ) if ( null != oldEquiped )
tgtC.unEquipCard(oldEquiped); tgtC.unEquipCard(oldEquiped);
} }
tgtC.equipCard(attachedTo); tgtC.equipCard(attachedTo);
} else { // fortification } else { // fortification
if (tgtC.isFortifying()) { if (tgtC.isFortifying()) {
final Card oldFortified = tgtC.getFortifyingCard(); final Card oldFortified = tgtC.getFortifying();
if( oldFortified != null ) if( oldFortified != null )
tgtC.unFortifyCard(oldFortified); tgtC.unFortifyCard(oldFortified);
} }
@@ -856,7 +856,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
} }
else if (c.isEquipment()) { //Equipment else if (c.isEquipment()) { //Equipment
if (c.isEquipping()) { if (c.isEquipping()) {
final Card oldEquiped = c.getEquippingCard(); final Card oldEquiped = c.getEquipping();
if ( null != oldEquiped ) if ( null != oldEquiped )
c.unEquipCard(oldEquiped); c.unEquipCard(oldEquiped);
} }
@@ -864,7 +864,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
} }
else { else {
if (c.isFortifying()) { if (c.isFortifying()) {
final Card oldFortified = c.getFortifyingCard(); final Card oldFortified = c.getFortifying();
if ( null != oldFortified ) if ( null != oldFortified )
c.unFortifyCard(oldFortified); c.unFortifyCard(oldFortified);
} }

View File

@@ -68,7 +68,7 @@ public class ChooseColorEffect extends SpellAbilityEffect {
if (chosenColors.isEmpty()) { if (chosenColors.isEmpty()) {
return; return;
} }
card.setChosenColor(chosenColors); card.setChosenColors(chosenColors);
p.getGame().getAction().nofityOfValue(sa, card, p.getName() + " picked " + Lang.joinHomogenous(chosenColors), p); p.getGame().getAction().nofityOfValue(sa, card, p.getName() + " picked " + Lang.joinHomogenous(chosenColors), p);
} }
} }

View File

@@ -61,8 +61,9 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
stackSources.add(stackinst.getSourceCard()); stackSources.add(stackinst.getSourceCard());
} }
// Get the list of cards that are referenced by effects on the stack // Get the list of cards that are referenced by effects on the stack
if (null != stackinst.getSpellAbility().getTriggeringObjects()) { SpellAbility siSpellAbility = stackinst.getSpellAbility(true);
for (Object c : stackinst.getSpellAbility().getTriggeringObjects().values()) { if (siSpellAbility.getTriggeringObjects() != null) {
for (Object c : siSpellAbility.getTriggeringObjects().values()) {
if (c instanceof Card) { if (c instanceof Card) {
if (!stackSources.contains((Card) c)) { if (!stackSources.contains((Card) c)) {
referencedSources.add((Card) c); referencedSources.add((Card) c);
@@ -70,12 +71,12 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
} }
} }
} }
if (null != stackinst.getSpellAbility().getTargetCard()) { if (siSpellAbility.getTargetCard() != null) {
referencedSources.add(stackinst.getSpellAbility().getTargetCard()); referencedSources.add(siSpellAbility.getTargetCard());
} }
// TODO: is this necessary? // TODO: is this necessary?
if (null != stackinst.getSpellAbility().getReplacingObjects()) { if (siSpellAbility.getReplacingObjects() != null) {
for (Object c : stackinst.getSpellAbility().getReplacingObjects().values()) { for (Object c : siSpellAbility.getReplacingObjects().values()) {
if (c instanceof Card) { if (c instanceof Card) {
if (!stackSources.contains((Card) c)) { if (!stackSources.contains((Card) c)) {
referencedSources.add((Card) c); referencedSources.add((Card) c);
@@ -85,7 +86,6 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
} }
} }
if (sa.hasParam("Choices")) { if (sa.hasParam("Choices")) {
permanentSources = CardLists.getValidCards(permanentSources, sa.getParam("Choices"), host.getController(), host); permanentSources = CardLists.getValidCards(permanentSources, sa.getParam("Choices"), host.getController(), host);

View File

@@ -106,12 +106,12 @@ public class CloneEffect extends SpellAbilityEffect {
tgtCard.clearStates(CardCharacteristicName.Cloner); tgtCard.clearStates(CardCharacteristicName.Cloner);
} }
// add "Cloner" state to clone // add "Cloner" state to clone
tgtCard.addAlternateState(CardCharacteristicName.Cloner); tgtCard.addAlternateState(CardCharacteristicName.Cloner, false);
tgtCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner); tgtCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner);
tgtCard.setState(CardCharacteristicName.Original); tgtCard.setState(CardCharacteristicName.Original);
} else { } else {
//copy Original state to Cloned //copy Original state to Cloned
tgtCard.addAlternateState(CardCharacteristicName.Cloned); tgtCard.addAlternateState(CardCharacteristicName.Cloned, false);
tgtCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloned); tgtCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloned);
if (tgtCard.isFlipCard()) { if (tgtCard.isFlipCard()) {
tgtCard.setState(CardCharacteristicName.Original); tgtCard.setState(CardCharacteristicName.Original);
@@ -285,7 +285,7 @@ public class CloneEffect extends SpellAbilityEffect {
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")) {
shortColors = CardUtil.getShortColorsString(tgtCard.getChosenColor()); shortColors = CardUtil.getShortColorsString(tgtCard.getChosenColors());
} else { } else {
shortColors = CardUtil.getShortColorsString(Arrays.asList(colors.split(","))); shortColors = CardUtil.getShortColorsString(Arrays.asList(colors.split(",")));
} }

View File

@@ -37,7 +37,7 @@ public class ControlGainEffect extends SpellAbilityEffect {
for (final Card c : getDefinedCards(sa)) { for (final Card c : getDefinedCards(sa)) {
sb.append(" "); sb.append(" ");
if (c.isFaceDown()) { if (c.isFaceDown()) {
sb.append("Face-down creature (").append(c.getUniqueNumber()).append(')'); sb.append("Face-down creature (").append(c.getId()).append(')');
} else { } else {
sb.append(c); sb.append(c);
} }

View File

@@ -26,7 +26,7 @@ public class CounterEffect extends SpellAbilityEffect {
if (sa.hasParam("AllType")) { if (sa.hasParam("AllType")) {
sas = new ArrayList<SpellAbility>(); sas = new ArrayList<SpellAbility>();
for (SpellAbilityStackInstance si : game.getStack()) { for (SpellAbilityStackInstance si : game.getStack()) {
SpellAbility spell = si.getSpellAbility(); SpellAbility spell = si.getSpellAbility(true);
if (sa.getParam("AllType").equals("Spell") && !spell.isSpell()) { if (sa.getParam("AllType").equals("Spell") && !spell.isSpell()) {
continue; continue;
} }
@@ -71,7 +71,7 @@ public class CounterEffect extends SpellAbilityEffect {
if (sa.hasParam("AllType")) { if (sa.hasParam("AllType")) {
sas = new ArrayList<SpellAbility>(); sas = new ArrayList<SpellAbility>();
for (SpellAbilityStackInstance si : game.getStack()) { for (SpellAbilityStackInstance si : game.getStack()) {
SpellAbility spell = si.getSpellAbility(); SpellAbility spell = si.getSpellAbility(true);
if (sa.getParam("AllType").equals("Spell") && !spell.isSpell()) { if (sa.getParam("AllType").equals("Spell") && !spell.isSpell()) {
continue; continue;
} }

View File

@@ -104,7 +104,7 @@ public class DamagePreventEffect extends SpellAbilityEffect {
effTgts = AbilityUtils.getDefinedObjects(host, sa.getParam("ShieldEffectTarget"), sa); effTgts = AbilityUtils.getDefinedObjects(host, sa.getParam("ShieldEffectTarget"), sa);
for (final Object effTgt : effTgts) { for (final Object effTgt : effTgts) {
if (effTgt instanceof Card) { if (effTgt instanceof Card) {
effTgtString = String.valueOf(((Card) effTgt).getUniqueNumber()); effTgtString = String.valueOf(((Card) effTgt).getId());
effectMap.put("ShieldEffectTarget", "CardUID_" + effTgtString); effectMap.put("ShieldEffectTarget", "CardUID_" + effTgtString);
} else if (effTgt instanceof Player) { } else if (effTgt instanceof Player) {
effTgtString = ((Player) effTgt).getName(); effTgtString = ((Player) effTgt).getName();
@@ -131,7 +131,7 @@ public class DamagePreventEffect extends SpellAbilityEffect {
effTgts = AbilityUtils.getDefinedObjects(host, sa.getParam("ShieldEffectTarget"), sa); effTgts = AbilityUtils.getDefinedObjects(host, sa.getParam("ShieldEffectTarget"), sa);
for (final Object effTgt : effTgts) { for (final Object effTgt : effTgts) {
if (effTgt instanceof Card) { if (effTgt instanceof Card) {
effTgtString = String.valueOf(((Card) effTgt).getUniqueNumber()); effTgtString = String.valueOf(((Card) effTgt).getId());
effectMap.put("ShieldEffectTarget", "CardUID_" + effTgtString); effectMap.put("ShieldEffectTarget", "CardUID_" + effTgtString);
} else if (effTgt instanceof Player) { } else if (effTgt instanceof Player) {
effTgtString = ((Player) effTgt).getName(); effTgtString = ((Player) effTgt).getName();

View File

@@ -32,7 +32,7 @@ public class DestroyEffect extends SpellAbilityEffect {
while (it.hasNext()) { while (it.hasNext()) {
final Card tgtC = it.next(); final Card tgtC = it.next();
if (tgtC.isFaceDown()) { if (tgtC.isFaceDown()) {
sb.append("Morph ").append("(").append(tgtC.getUniqueNumber()).append(")"); sb.append("Morph ").append("(").append(tgtC.getId()).append(")");
} else { } else {
sb.append(tgtC); sb.append(tgtC);
} }

View File

@@ -189,8 +189,8 @@ public class EffectEffect extends SpellAbilityEffect {
} }
// Set Chosen Color(s) // Set Chosen Color(s)
if (!hostCard.getChosenColor().isEmpty()) { if (!hostCard.getChosenColors().isEmpty()) {
eff.setChosenColor(hostCard.getChosenColor()); eff.setChosenColors(hostCard.getChosenColors());
} }
// Set Chosen name // Set Chosen name

View File

@@ -75,7 +75,7 @@ public class PlayLandVariantEffect extends SpellAbilityEffect {
} }
String imageFileName = game.getRules().canCloneUseTargetsImage ? source.getImageKey() : random.getImageKey(); String imageFileName = game.getRules().canCloneUseTargetsImage ? source.getImageKey() : random.getImageKey();
source.addAlternateState(CardCharacteristicName.Cloner); source.addAlternateState(CardCharacteristicName.Cloner, false);
source.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner); source.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner);
source.setState(CardCharacteristicName.Original); source.setState(CardCharacteristicName.Original);
CardCharacteristicName stateToCopy = random.getCurState(); CardCharacteristicName stateToCopy = random.getCurState();

View File

@@ -56,7 +56,7 @@ public class ProtectAllEffect extends SpellAbilityEffect {
game.getAction().nofityOfValue(sa, choser, Lang.joinHomogenous(gains), choser); game.getAction().nofityOfValue(sa, choser, Lang.joinHomogenous(gains), choser);
} else { } else {
if (sa.getParam("Gains").equals("ChosenColor")) { if (sa.getParam("Gains").equals("ChosenColor")) {
for (final String color : host.getChosenColor()) { for (final String color : host.getChosenColors()) {
gains.add(color.toLowerCase()); gains.add(color.toLowerCase());
} }
} else if (sa.getParam("Gains").equals("TargetedCardColor")) { } else if (sa.getParam("Gains").equals("TargetedCardColor")) {

View File

@@ -114,7 +114,7 @@ public class ProtectEffect extends SpellAbilityEffect {
game.getAction().nofityOfValue(sa, choser, Lang.joinHomogenous(gains), choser); game.getAction().nofityOfValue(sa, choser, Lang.joinHomogenous(gains), choser);
} else { } else {
if (sa.getParam("Gains").equals("ChosenColor")) { if (sa.getParam("Gains").equals("ChosenColor")) {
for (final String color : host.getChosenColor()) { for (final String color : host.getChosenColors()) {
gains.add(color.toLowerCase()); gains.add(color.toLowerCase());
} }
} else { } else {

View File

@@ -209,7 +209,7 @@ public class PumpEffect extends SpellAbilityEffect {
if (defined.equals("ChosenType")) { if (defined.equals("ChosenType")) {
replaced = host.getChosenType(); replaced = host.getChosenType();
} else if (defined.equals("CardUIDSource")) { } else if (defined.equals("CardUIDSource")) {
replaced = "CardUID_" + String.valueOf(host.getUniqueNumber()); replaced = "CardUID_" + String.valueOf(host.getId());
} }
for (int i = 0; i < keywords.size(); i++) { for (int i = 0; i < keywords.size(); i++) {
keywords.set(i, keywords.get(i).replaceAll(defined, replaced)); keywords.set(i, keywords.get(i).replaceAll(defined, replaced));

View File

@@ -73,7 +73,7 @@ public class RegenerateEffect extends SpellAbilityEffect {
} else if (sa.hasParam("ReplaceCardUID")) { // Debt of Loyalty } else if (sa.hasParam("ReplaceCardUID")) { // Debt of Loyalty
String def = sa.getParam("ReplaceCardUID"); String def = sa.getParam("ReplaceCardUID");
List<Card> replaced = AbilityUtils.getDefinedCards(sourceCard, def, sa); List<Card> replaced = AbilityUtils.getDefinedCards(sourceCard, def, sa);
abString = abString.replace(def, replaced.isEmpty() ? "" : Integer.toString(replaced.get(0).getUniqueNumber())); abString = abString.replace(def, replaced.isEmpty() ? "" : Integer.toString(replaced.get(0).getId()));
} }
triggerSA = AbilityFactory.getAbility(abString, sourceCard); triggerSA = AbilityFactory.getAbility(abString, sourceCard);
triggerSA.setActivatingPlayer(sa.getActivatingPlayer()); triggerSA.setActivatingPlayer(sa.getActivatingPlayer());

View File

@@ -28,7 +28,7 @@ public class SetStateEffect extends SpellAbilityEffect {
while (it.hasNext()) { while (it.hasNext()) {
final Card tgtC = it.next(); final Card tgtC = it.next();
if (tgtC.isFaceDown()) { if (tgtC.isFaceDown()) {
sb.append("Morph ").append("(").append(tgtC.getUniqueNumber()).append(")"); sb.append("Morph ").append("(").append(tgtC.getId()).append(")");
} else { } else {
sb.append(tgtC); sb.append(tgtC);
} }

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.getChosenColor().get(0); substitutedColors[i] = host.getChosenColors().get(0);
} }
} }
String colorDesc = ""; String colorDesc = "";

View File

@@ -24,11 +24,11 @@ public class UnattachAllEffect extends SpellAbilityEffect {
//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.getEquippedBy().contains(cardToUnattach)) {
cardToUnattach.unEquipCard(cardToUnattach.getEquipping().get(0)); cardToUnattach.unEquipCard(cardToUnattach.getEquipping());
} }
} else if (cardToUnattach.isFortification()) { } else if (cardToUnattach.isFortification()) {
if (cardToUnattach.isFortifying() && c.getFortifiedBy().contains(cardToUnattach)) { if (cardToUnattach.isFortifying() && c.getFortifiedBy().contains(cardToUnattach)) {
cardToUnattach.unFortifyCard(cardToUnattach.getFortifying().get(0)); cardToUnattach.unFortifyCard(cardToUnattach.getFortifying());
} }
} }
} else if (o instanceof Player) { } else if (o instanceof Player) {

View File

@@ -33,11 +33,11 @@ public class UnattachEffect extends SpellAbilityEffect {
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl); //AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
} else if (cardToUnattach.isEquipment()) { } else if (cardToUnattach.isEquipment()) {
if (cardToUnattach.isEquipping()) { if (cardToUnattach.isEquipping()) {
cardToUnattach.unEquipCard(cardToUnattach.getEquipping().get(0)); cardToUnattach.unEquipCard(cardToUnattach.getEquipping());
} }
} else if (cardToUnattach.isFortification()) { } else if (cardToUnattach.isFortification()) {
if (cardToUnattach.isFortifying()) { if (cardToUnattach.isFortifying()) {
cardToUnattach.unFortifyCard(cardToUnattach.getFortifying().get(0)); cardToUnattach.unFortifyCard(cardToUnattach.getFortifying());
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -31,8 +31,10 @@ import forge.game.trigger.Trigger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
@@ -40,7 +42,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/ */
public class CardCharacteristics { public class CardCharacteristics {
private String name = ""; private String name = "";
private List<String> type = new CopyOnWriteArrayList<String>(); private Set<String> type = new CopyOnWriteArraySet<String>();
private ManaCost manaCost = ManaCost.NO_COST; private ManaCost manaCost = ManaCost.NO_COST;
private List<CardColor> cardColor = new ArrayList<CardColor>(); private List<CardColor> cardColor = new ArrayList<CardColor>();
private String oracleText = ""; private String oracleText = "";
@@ -84,7 +86,7 @@ public class CardCharacteristics {
* *
* @return the type * @return the type
*/ */
public final List<String> getType() { public final Set<String> getType() {
return this.type; return this.type;
} }
@@ -438,7 +440,7 @@ public class CardCharacteristics {
// String name : just copy reference // String name : just copy reference
this.name = source.getName(); this.name = source.getName();
// ArrayList<String> type : list of String objects so use copy constructor // ArrayList<String> type : list of String objects so use copy constructor
this.type = new CopyOnWriteArrayList<String>(source.getType()); this.type = new CopyOnWriteArraySet<String>(source.getType());
// CardManaCost manaCost : not sure if a deep copy is needed // CardManaCost manaCost : not sure if a deep copy is needed
this.manaCost = source.getManaCost(); this.manaCost = source.getManaCost();
// ArrayList<CardColor> cardColor : not sure if a deep copy is needed // ArrayList<CardColor> cardColor : not sure if a deep copy is needed

View File

@@ -75,9 +75,9 @@ public class CardFactory {
Card out; Card out;
if (!(in.isToken() || in.getCopiedPermanent() != null)) { if (!(in.isToken() || in.getCopiedPermanent() != null)) {
out = assignNewId ? getCard(in.getPaperCard(), in.getOwner()) out = assignNewId ? getCard(in.getPaperCard(), in.getOwner())
: getCard(in.getPaperCard(), in.getOwner(), in.getUniqueNumber()); : getCard(in.getPaperCard(), in.getOwner(), in.getId());
} else { // token } else { // token
out = assignNewId ? new Card(in.getGame().nextCardId(), in.getPaperCard()) : new Card(in.getUniqueNumber(), in.getPaperCard()); out = assignNewId ? new Card(in.getGame().nextCardId(), in.getPaperCard()) : new Card(in.getId(), in.getPaperCard());
out = CardFactory.copyStats(in, in.getController()); out = CardFactory.copyStats(in, in.getController());
out.setToken(true); out.setToken(true);
@@ -148,7 +148,7 @@ public class CardFactory {
String tmp = ""; String tmp = "";
final String newColor = sourceSA.getParam("CopyIsColor"); final String newColor = sourceSA.getParam("CopyIsColor");
if (newColor.equals("ChosenColor")) { if (newColor.equals("ChosenColor")) {
tmp = CardUtil.getShortColorsString(source.getChosenColor()); tmp = CardUtil.getShortColorsString(source.getChosenColors());
} else { } else {
tmp = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(newColor.split(",")))); tmp = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(newColor.split(","))));
} }
@@ -356,20 +356,19 @@ public class CardFactory {
} }
private static Card readCard(final CardRules rules, final IPaperCard paperCard, int cardId) { private static Card readCard(final CardRules rules, final IPaperCard paperCard, int cardId) {
final Card card = new Card(cardId, paperCard); final Card card = new Card(cardId, paperCard);
// 1. The states we may have: // 1. The states we may have:
CardSplitType st = rules.getSplitType(); CardSplitType st = rules.getSplitType();
if ( st == CardSplitType.Split) { if (st == CardSplitType.Split) {
card.addAlternateState(CardCharacteristicName.LeftSplit); card.addAlternateState(CardCharacteristicName.LeftSplit, false);
card.setState(CardCharacteristicName.LeftSplit); card.setState(CardCharacteristicName.LeftSplit);
} }
readCardFace(card, rules.getMainPart()); readCardFace(card, rules.getMainPart());
if ( st != CardSplitType.None) { if (st != CardSplitType.None) {
card.addAlternateState(st.getChangedStateName()); card.addAlternateState(st.getChangedStateName(), false);
card.setState(st.getChangedStateName()); card.setState(st.getChangedStateName());
readCardFace(card, rules.getOtherPart()); readCardFace(card, rules.getOtherPart());
} }
@@ -570,7 +569,7 @@ public class CardFactory {
// get CardCharacteristics for desired state // get CardCharacteristics for desired state
if (!to.getStates().contains(toState)) { if (!to.getStates().contains(toState)) {
to.addAlternateState(toState); to.addAlternateState(toState, true);
} }
final CardCharacteristics toCharacteristics = to.getState(toState), final CardCharacteristics toCharacteristics = to.getState(toState),
fromCharacteristics = from.getState(fromState); fromCharacteristics = from.getState(fromState);
@@ -590,7 +589,7 @@ public class CardFactory {
final CardCharacteristics fromCharacteristics = from.getState(fromState); final CardCharacteristics fromCharacteristics = from.getState(fromState);
final CardCharacteristicName oldToState = to.getCurState(); final CardCharacteristicName oldToState = to.getCurState();
if (!to.getStates().contains(toState)) { if (!to.getStates().contains(toState)) {
to.addAlternateState(toState); to.addAlternateState(toState, false);
} }
to.setState(toState); to.setState(toState);
@@ -688,7 +687,7 @@ public class CardFactory {
t.setTriggeringObjects(trig); t.setTriggeringObjects(trig);
trig.setTriggerRemembered(t.getTriggerRemembered()); trig.setTriggerRemembered(t.getTriggerRemembered());
if (t.getStoredTriggeredObjects() != null) { if (t.getStoredTriggeredObjects() != null) {
trig.setAllTriggeringObjects(t.getStoredTriggeredObjects()); trig.setTriggeringObjects(t.getStoredTriggeredObjects());
} }
trig.setActivatingPlayer(sa.getActivatingPlayer()); trig.setActivatingPlayer(sa.getActivatingPlayer());

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.getChosenColor().get(0)); colorName = MagicColor.toShortString(c.getChosenColors().get(0));
} }
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
@@ -1250,7 +1250,7 @@ public class CardFactoryUtil {
if (sq[0].contains("CardManaCost")) { if (sq[0].contains("CardManaCost")) {
Card ce; Card ce;
if (sq[0].contains("Equipped") && c.isEquipping()) { if (sq[0].contains("Equipped") && c.isEquipping()) {
ce = c.getEquipping().get(0); ce = c.getEquipping();
} }
else if (sq[0].contains("Remembered")) { else if (sq[0].contains("Remembered")) {
ce = (Card) c.getRemembered().get(0); ce = (Card) c.getRemembered().get(0);
@@ -2027,7 +2027,7 @@ public class CardFactoryUtil {
final int magnitude = Integer.parseInt(s); final int magnitude = Integer.parseInt(s);
String description = String.format("Bushido %d (When this blocks or becomes blocked, it gets +%d/+%d until end of turn).", magnitude, magnitude, magnitude); String description = String.format("Bushido %d (When this blocks or becomes blocked, it gets +%d/+%d until end of turn).", magnitude, magnitude, magnitude);
String regularPart = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ +%d | NumDef$ +%d | StackDescription$ %s", c.getUniqueNumber(), magnitude, magnitude, description); String regularPart = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ +%d | NumDef$ +%d | StackDescription$ %s", c.getId(), magnitude, magnitude, description);
SpellAbility ability = AbilityFactory.getAbility(regularPart, c); SpellAbility ability = AbilityFactory.getAbility(regularPart, c);
ability.setDescription(ability.getStackDescription()); ability.setDescription(ability.getStackDescription());

View File

@@ -213,14 +213,13 @@ public final class CardUtil {
* @return a copy of C with LastKnownInfo stuff retained. * @return a copy of C with LastKnownInfo stuff retained.
*/ */
public static Card getLKICopy(final Card in) { public static Card getLKICopy(final Card in) {
final Card newCopy = new Card(in.getId(), in.getPaperCard());
final Card newCopy = new Card(in.getUniqueNumber(), in.getPaperCard());
newCopy.setCurSetCode(in.getCurSetCode()); newCopy.setCurSetCode(in.getCurSetCode());
newCopy.setOwner(in.getOwner()); newCopy.setOwner(in.getOwner());
newCopy.setController(in.getController(), 0); newCopy.setController(in.getController(), 0);
newCopy.getCharacteristics().copyFrom(in.getState(in.getCurState())); newCopy.getCharacteristics().copyFrom(in.getState(in.getCurState()));
if (in.isCloned()) { if (in.isCloned()) {
newCopy.addAlternateState(CardCharacteristicName.Cloner); newCopy.addAlternateState(CardCharacteristicName.Cloner, false);
} }
newCopy.setType(new ArrayList<String>(in.getType())); newCopy.setType(new ArrayList<String>(in.getType()));
newCopy.setToken(in.isToken()); newCopy.setToken(in.isToken());
@@ -245,9 +244,9 @@ public final class CardUtil {
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(new ArrayList<Card> (in.getEnchantedBy()));
newCopy.setEquipping(new ArrayList<Card> (in.getEquipping())); newCopy.setEquipping(in.getEquipping());
newCopy.setEquippedBy(new ArrayList<Card> (in.getEquippedBy())); newCopy.setEquippedBy(new ArrayList<Card> (in.getEquippedBy()));
newCopy.setFortifying(new ArrayList<Card> (in.getFortifying())); newCopy.setFortifying(in.getFortifying());
newCopy.setFortifiedBy(new ArrayList<Card> (in.getFortifiedBy())); newCopy.setFortifiedBy(new ArrayList<Card> (in.getFortifiedBy()));
newCopy.setClones(in.getClones()); newCopy.setClones(in.getClones());
newCopy.setHaunting(in.getHaunting()); newCopy.setHaunting(in.getHaunting());

View File

@@ -0,0 +1,625 @@
package forge.game.card;
import java.util.Set;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import forge.card.CardCharacteristicName;
import forge.card.CardRarity;
import forge.card.CardType;
import forge.card.ColorSet;
import forge.card.mana.ManaCost;
import forge.game.GameEntityView;
import forge.game.player.PlayerView;
import forge.game.zone.ZoneType;
import forge.trackable.TrackableCollection;
import forge.trackable.TrackableObject;
import forge.trackable.TrackableProperty.CardProp;
import forge.trackable.TrackableProperty.CardStateProp;
public class CardView extends GameEntityView<CardProp> {
public static CardView get(Card c) {
return c == null ? null : c.getView();
}
public static TrackableCollection<CardView> getCollection(Iterable<Card> cards) {
if (cards == null) {
return null;
}
TrackableCollection<CardView> collection = new TrackableCollection<CardView>();
for (Card c : cards) {
collection.add(c.getView());
}
return collection;
}
public CardView(int id0) {
super(id0, CardProp.class);
set(CardProp.Original, new CardStateView(id0));
}
public PlayerView getOwner() {
return get(CardProp.Owner);
}
void updateOwner(Card c) {
set(CardProp.Owner, PlayerView.get(c.getOwner()));
}
public PlayerView getController() {
return get(CardProp.Controller);
}
void updateController(Card c) {
set(CardProp.Owner, PlayerView.get(c.getController()));
}
public ZoneType getZone() {
return get(CardProp.Zone);
}
void updateZone(Card c) {
set(CardProp.Zone, c.getZone() == null ? null : c.getZone().getZoneType());
}
public boolean isCloned() {
return get(CardProp.Cloned);
}
public boolean isFaceDown() {
return get(CardProp.FaceDown);
}
public boolean isFlipCard() {
return get(CardProp.FlipCard);
}
public boolean isFlipped() {
return get(CardProp.Flipped);
}
public boolean isSplitCard() {
return get(CardProp.SplitCard);
}
public boolean isTransformed() {
return get(CardProp.Transformed);
}
public String getSetCode() {
return get(CardProp.SetCode);
}
void updateSetCode(Card c) {
set(CardProp.SetCode, c.getCurSetCode());
}
public CardRarity getRarity() {
return get(CardProp.Rarity);
}
void updateRarity(Card c) {
set(CardProp.Rarity, c.getRarity());
}
public boolean isAttacking() {
return get(CardProp.Attacking);
}
void updateAttacking(Card c) {
set(CardProp.Attacking, c.getGame().getCombat().isAttacking(c));
}
public boolean isBlocking() {
return get(CardProp.Blocking);
}
void updateBlocking(Card c) {
set(CardProp.Blocking, c.getGame().getCombat().isBlocking(c));
}
public boolean isPhasedOut() {
return get(CardProp.PhasedOut);
}
void updatePhasedOut(Card c) {
set(CardProp.PhasedOut, c.isPhasedOut());
}
public boolean isFirstTurnControlled() {
return get(CardProp.Sickness);
}
public boolean hasSickness() {
return isFirstTurnControlled() && !getOriginal().hasHaste();
}
public boolean isSick() {
return getZone() == ZoneType.Battlefield && hasSickness();
}
void updateSickness(Card c) {
set(CardProp.Sickness, c.isInPlay() && c.isSick());
}
public boolean isTapped() {
return get(CardProp.Tapped);
}
void updateTapped(Card c) {
set(CardProp.Tapped, c.isTapped());
}
public boolean isToken() {
return get(CardProp.Token);
}
void updateToken(Card c) {
set(CardProp.Token, c.isToken());
}
public Map<CounterType, Integer> getCounters() {
return get(CardProp.Counters);
}
void updateCounters(Card c) {
set(CardProp.Counters, c.getCounters());
}
public int getDamage() {
return get(CardProp.Damage);
}
void updateDamage(Card c) {
set(CardProp.Damage, c.getDamage());
}
public int getAssignedDamage() {
return get(CardProp.AssignedDamage);
}
void updateAssignedDamage(Card c) {
set(CardProp.AssignedDamage, c.getTotalAssignedDamage());
}
public int getLethalDamage() {
return getOriginal().getToughness() - getDamage() - getAssignedDamage();
}
public int getShieldCount() {
return get(CardProp.ShieldCount);
}
void updateShieldCount(Card c) {
set(CardProp.ShieldCount, c.getShieldCount());
}
public String getChosenType() {
return get(CardProp.ChosenType);
}
void updateChosenType(Card c) {
set(CardProp.ChosenType, c.getChosenType());
}
public List<String> getChosenColors() {
return get(CardProp.ChosenColors);
}
void updateChosenColors(Card c) {
set(CardProp.ChosenColors, c.getChosenColors());
}
public PlayerView getChosenPlayer() {
return get(CardProp.ChosenPlayer);
}
void updateChosenPlayer(Card c) {
set(CardProp.ChosenPlayer, c.getChosenPlayer());
}
public String getNamedCard() {
return get(CardProp.NamedCard);
}
void updateNamedCard(Card c) {
set(CardProp.NamedCard, c.getNamedCard());
}
public CardView getEquipping() {
return get(CardProp.Equipping);
}
void updateEquipping(Card c) {
set(CardProp.Equipping, CardView.get(c.getEquipping()));
}
public Iterable<CardView> getEquippedBy() {
return get(CardProp.EquippedBy);
}
void updateEquippedBy(Card c) {
set(CardProp.EquippedBy, CardView.getCollection(c.getEquippedBy()));
}
public boolean isEquipped() {
return getEquippedBy() != null;
}
public GameEntityView<?> getEnchanting() {
return get(CardProp.Enchanting);
}
void updateEnchanting(Card c) {
set(CardProp.Owner, GameEntityView.get(c.getEnchanting()));
}
public CardView getEnchantingCard() {
GameEntityView<?> enchanting = getEnchanting();
if (enchanting instanceof CardView) {
return (CardView) enchanting;
}
return null;
}
public PlayerView getEnchantingPlayer() {
GameEntityView<?> enchanting = getEnchanting();
if (enchanting instanceof PlayerView) {
return (PlayerView) enchanting;
}
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() {
return get(CardProp.Fortifying);
}
void updateFortifying(Card c) {
set(CardProp.Fortifying, c.getFortifying());
}
public Iterable<CardView> getFortifiedBy() {
return get(CardProp.FortifiedBy);
}
void updateFortifiedBy(Card c) {
set(CardProp.FortifiedBy, CardView.getCollection(c.getFortifiedBy()));
}
public boolean isFortified() {
return getFortifiedBy() != null;
}
public Iterable<CardView> getGainControlTargets() {
return get(CardProp.GainControlTargets);
}
void updateGainControlTargets(Card c) {
set(CardProp.GainControlTargets, CardView.getCollection(c.getGainControlTargets()));
}
public CardView getCloneOrigin() {
return get(CardProp.CloneOrigin);
}
void updateCloneOrigin(Card c) {
set(CardProp.CloneOrigin, CardView.get(c.getCloneOrigin()));
}
public Iterable<CardView> getImprinted() {
return get(CardProp.Imprinted);
}
void updateImprinted(Card c) {
set(CardProp.Imprinted, CardView.getCollection(c.getImprinted()));
}
public Iterable<CardView> getHauntedBy() {
return get(CardProp.HauntedBy);
}
void updateHauntedBy(Card c) {
set(CardProp.HauntedBy, CardView.getCollection(c.getHauntedBy()));
}
public CardView getHaunting() {
return get(CardProp.Haunting);
}
void updateHaunting(Card c) {
set(CardProp.Haunting, CardView.get(c.getHaunting()));
}
public Iterable<CardView> getMustBlock() {
return get(CardProp.MustBlock);
}
void updateHaunting(CardView haunting) {
set(CardProp.MustBlock, haunting);
}
public CardView getPairedWith() {
return get(CardProp.PairedWith);
}
void updatePairedWith(Card c) {
set(CardProp.PairedWith, CardView.get(c.getPairedWith()));
}
public CardStateView getOriginal() {
return get(CardProp.Original);
}
public CardStateView getAlternate() {
return get(CardProp.Alternate);
}
public CardStateView getState(final boolean alternate0) {
return alternate0 ? getAlternate() : getOriginal();
}
void updateState(Card c, boolean fromCurStateChange) {
boolean isDoubleFaced = c.isDoubleFaced();
boolean isFaceDown = c.isFaceDown();
boolean isFlipCard = c.isFlipCard();
boolean isFlipped = c.getCurState() == CardCharacteristicName.Flipped;
boolean isSplitCard = c.isSplitCard();
boolean isTransformed = c.getCurState() == CardCharacteristicName.Transformed;
boolean hasAltState = isDoubleFaced || isFlipCard || isSplitCard || (isFaceDown/* && mayShowCardFace*/);
set(CardProp.Alternate, hasAltState ? new CardStateView(getId()) : null);
set(CardProp.Cloned, c.isCloned());
set(CardProp.FaceDown, isFaceDown);
set(CardProp.SplitCard, isSplitCard);
set(CardProp.FlipCard, isFlipCard);
if (fromCurStateChange) {
set(CardProp.Flipped, isFlipped);
set(CardProp.Transformed, isTransformed);
updateRarity(c); //rarity and set based on current state
updateSetCode(c);
}
if (isSplitCard) {
final CardCharacteristicName orig, alt;
if (c.getCurState() == CardCharacteristicName.RightSplit) {
// If right half on stack, place it first
orig = CardCharacteristicName.RightSplit;
alt = CardCharacteristicName.LeftSplit;
}
else {
orig = CardCharacteristicName.LeftSplit;
alt = CardCharacteristicName.RightSplit;
}
updateState(c, getOriginal(), orig);
updateState(c, getAlternate(), alt);
return;
}
final CardStateView origView = getOriginal();
origView.updateName(c);
origView.updateColors(c);
origView.updateImageKey(c);
origView.updateType(c);
origView.updateManaCost(c);
origView.updatePower(c);
origView.updateToughness(c);
origView.updateLoyalty(c);
origView.updateText(c);
origView.updateChangedColorWords(c);
origView.updateChangedTypes(c);
origView.updateManaCost(c);
origView.updateKeywords(c);
origView.updateFoilIndex(c);
if (hasAltState) {
if (isFlipCard && !isFlipped) {
updateState(c, getAlternate(), CardCharacteristicName.Flipped);
}
else if (isDoubleFaced && !isTransformed) {
updateState(c, getAlternate(), CardCharacteristicName.Transformed);
}
else {
updateState(c, getAlternate(), CardCharacteristicName.Original);
}
}
}
private void updateState(Card c, CardStateView view, CardCharacteristicName state) {
final CardCharacteristics chars = c.getState(state);
view.updateName(chars);
view.updateColors(chars);
view.updateImageKey(chars);
view.updateType(chars);
view.updateManaCost(chars);
view.updatePower(chars);
view.updateToughness(chars);
view.updateLoyalty(chars);
view.updateText(chars);
view.updateFoilIndex(chars);
}
@Override
public String toString() {
if (getId() <= 0) { //if fake card, just return name
return getOriginal().getName();
}
/*if (!mayBeShown) {
return "(Unknown card)";
}*/
if (StringUtils.isEmpty(getOriginal().getName())) {
CardStateView alternate = getAlternate();
if (alternate != null) {
return "Face-down card (" + getAlternate().getName() + ")";
}
return "(" + getId() + ")";
}
return getOriginal().getName() + " (" + getId() + ")";
}
public String determineName(final CardStateView state) {
if (state == getOriginal()) {
return toString();
}
return getAlternate().getName() + " (" + getId() + ")";
}
public class CardStateView extends TrackableObject<CardStateProp> {
public CardStateView(int id0) {
super(id0, CardStateProp.class);
}
@Override
public String toString() {
return getCard().determineName(this);
}
public CardView getCard() {
return CardView.this;
}
public String getName() {
return get(CardStateProp.Name);
}
void updateName(Card c) {
set(CardStateProp.Name, c.getName());
}
void updateName(CardCharacteristics c) {
set(CardStateProp.Name, c.getName());
}
public ColorSet getColors() {
return get(CardStateProp.Colors);
}
void updateColors(Card c) {
set(CardStateProp.Colors, c.determineColor());
}
void updateColors(CardCharacteristics c) {
set(CardStateProp.Colors, c.determineColor());
}
public String getImageKey() {
return get(CardStateProp.ImageKey);
}
void updateImageKey(Card c) {
set(CardStateProp.ImageKey, c.getImageKey());
}
void updateImageKey(CardCharacteristics c) {
set(CardStateProp.ImageKey, c.getImageKey());
}
public Set<String> getType() {
return get(CardStateProp.Type);
}
void updateType(Card c) {
set(CardStateProp.Type, c.getType());
}
void updateType(CardCharacteristics c) {
set(CardStateProp.Type, c.getType());
}
public ManaCost getManaCost() {
return get(CardStateProp.ManaCost);
}
void updateManaCost(Card c) {
set(CardStateProp.ManaCost, c.getManaCost());
}
void updateManaCost(CardCharacteristics c) {
set(CardStateProp.ManaCost, c.getManaCost());
}
public int getPower() {
return get(CardStateProp.Power);
}
void updatePower(Card c) {
set(CardStateProp.Power, c.getNetAttack());
}
void updatePower(CardCharacteristics c) {
set(CardStateProp.Power, c.getBaseAttack());
}
public int getToughness() {
return get(CardStateProp.Toughness);
}
void updateToughness(Card c) {
set(CardStateProp.Toughness, c.getNetDefense());
}
void updateToughness(CardCharacteristics c) {
set(CardStateProp.Toughness, c.getBaseDefense());
}
public int getLoyalty() {
return get(CardStateProp.Loyalty);
}
void updateLoyalty(Card c) {
set(CardStateProp.Loyalty, c.getCurrentLoyalty());
}
void updateLoyalty(CardCharacteristics c) {
set(CardStateProp.Loyalty, 0); // Q why is loyalty not a property of CardCharacteristic? A: because no alt states have a base loyalty (only candidate is Garruk Relentless).
}
public String getText() {
return get(CardStateProp.Text);
}
void updateText(Card c) {
set(CardStateProp.Text, c.getText());
}
void updateText(CardCharacteristics c) {
set(CardStateProp.Text, c.getOracleText());
}
public int getFoilIndex() {
return get(CardStateProp.FoilIndex);
}
void updateFoilIndex(Card c) {
set(CardStateProp.FoilIndex, c.getCharacteristics().getFoil());
}
void updateFoilIndex(CardCharacteristics c) {
set(CardStateProp.FoilIndex, c.getFoil());
}
public Map<String, String> getChangedColorWords() {
return get(CardStateProp.ChangedColorWords);
}
void updateChangedColorWords(Card c) {
set(CardStateProp.ChangedColorWords, c.getChangedTextColorWords());
}
public Map<String, String> getChangedTypes() {
return get(CardStateProp.ChangedTypes);
}
void updateChangedTypes(Card c) {
set(CardStateProp.ChangedTypes, c.getChangedTextTypeWords());
}
public boolean hasDeathtouch() {
return get(CardStateProp.HasDeathtouch);
}
public boolean hasHaste() {
return get(CardStateProp.HasHaste);
}
public boolean hasInfect() {
return get(CardStateProp.HasInfect);
}
public boolean hasStorm() {
return get(CardStateProp.HasStorm);
}
public boolean hasTrample() {
return get(CardStateProp.HasTrample);
}
void updateKeywords(Card c) {
set(CardStateProp.HasDeathtouch, c.hasKeyword("Deathtouch"));
set(CardStateProp.HasHaste, c.hasKeyword("Haste"));
set(CardStateProp.HasInfect, c.hasKeyword("Infect"));
set(CardStateProp.HasStorm, c.hasKeyword("Storm"));
set(CardStateProp.HasTrample, c.hasKeyword("Trample"));
}
public boolean isBasicLand() {
return isLand() && Iterables.any(getType(), Predicates.in(CardType.getBasicTypes()));
}
public boolean isCreature() {
return getType().contains("Creature");
}
public boolean isLand() {
return getType().contains("Land");
}
public boolean isPlane() {
return getType().contains("Plane");
}
public boolean isPhenomenon() {
return getType().contains("Phenomenon");
}
public boolean isPlaneswalker() {
return getType().contains("Planeswalker");
}
}
@Override
protected CardProp preventNextDamageProp() {
return CardProp.PreventNextDamage;
}
}

View File

@@ -278,9 +278,9 @@ public class Combat {
if (source.isAura()) { if (source.isAura()) {
attacker = source.getEnchantingCard(); attacker = source.getEnchantingCard();
} else if (source.isEquipment()) { } else if (source.isEquipment()) {
attacker = source.getEquippingCard(); attacker = source.getEquipping();
} else if (source.isFortification()) { } else if (source.isFortification()) {
attacker = source.getFortifyingCard(); attacker = source.getFortifying();
} }
// return the corresponding defender // return the corresponding defender

View File

@@ -634,7 +634,7 @@ public class CombatUtil {
final String parse = blocker.getKeyword().get(keywordPosition).toString(); final String parse = blocker.getKeyword().get(keywordPosition).toString();
if (parse.startsWith("CantBlockCardUID")) { if (parse.startsWith("CantBlockCardUID")) {
final String[] k = parse.split("_", 2); final String[] k = parse.split("_", 2);
if (attacker.getUniqueNumber() == Integer.parseInt(k[1])) { if (attacker.getId() == Integer.parseInt(k[1])) {
return false; return false;
} }
} else { } else {
@@ -999,7 +999,7 @@ public class CombatUtil {
// Rule 702.23b: If a creature has multiple instances of flanking, each triggers separately. // Rule 702.23b: If a creature has multiple instances of flanking, each triggers separately.
for( int i = 0; i < flankingMagnitude; i++ ) { for( int i = 0; i < flankingMagnitude; i++ ) {
String effect = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ -1 | NumDef$ -1 | ", blocker.getUniqueNumber()); String effect = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ -1 | NumDef$ -1 | ", blocker.getId());
String desc = String.format("StackDescription$ Flanking (The blocking %s gets -1/-1 until end of turn)", blocker.getName()); String desc = String.format("StackDescription$ Flanking (The blocking %s gets -1/-1 until end of turn)", blocker.getName());
SpellAbility ability = AbilityFactory.getAbility(effect + desc, attacker); SpellAbility ability = AbilityFactory.getAbility(effect + desc, attacker);
@@ -1031,7 +1031,7 @@ public class CombatUtil {
private static void executeRampageAbility(final Game game, final Card c, final int magnitude, final int numBlockers) { private static void executeRampageAbility(final Game game, final Card c, final int magnitude, final int numBlockers) {
// numBlockers starts with 1 since it is for every creature beyond the first // numBlockers starts with 1 since it is for every creature beyond the first
for (int i = 1; i < numBlockers; i++) { for (int i = 1; i < numBlockers; i++) {
String effect = "AB$ Pump | Cost$ 0 | " + c.getUniqueNumber() + " | NumAtt$ " + magnitude + " | NumDef$ " + magnitude + " | "; String effect = "AB$ Pump | Cost$ 0 | " + c.getId() + " | NumAtt$ " + magnitude + " | NumDef$ " + magnitude + " | ";
String desc = "StackDescription$ Rampage " + magnitude + " (Whenever CARDNAME becomes blocked, it gets +" + magnitude + "/+" String desc = "StackDescription$ Rampage " + magnitude + " (Whenever CARDNAME becomes blocked, it gets +" + magnitude + "/+"
+ magnitude + " until end of turn for each creature blocking it beyond the first.)"; + magnitude + " until end of turn for each creature blocking it beyond the first.)";

View File

@@ -0,0 +1,150 @@
package forge.game.combat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import forge.game.GameEntityView;
import forge.game.card.CardView;
import forge.trackable.TrackableObject;
import forge.trackable.TrackableProperty.CombatProp;
public class CombatView extends TrackableObject<CombatProp> {
public CombatView() {
super(-1, CombatProp.class); //ID not needed
}
private Map<CardView, GameEntityView<?>> getAttackersWithDefenders() {
return get(CombatProp.AttackersWithDefenders);
}
private Map<CardView, Iterable<CardView>> getAttackersWithBlockers() {
return get(CombatProp.AttackersWithBlockers);
}
private Map<Iterable<CardView>, GameEntityView<?>> getBandsWithDefenders() {
return get(CombatProp.BandsWithDefenders);
}
private Map<Iterable<CardView>, Iterable<CardView>> getBandsWithBlockers() {
return get(CombatProp.BandsWithBlockers);
}
private Map<CardView, Iterable<CardView>> getAttackersWithPlannedBlockers() {
return get(CombatProp.AttackersWithPlannedBlockers);
}
private Map<Iterable<CardView>, Iterable<CardView>> getBandsWithPlannedBlockers() {
return get(CombatProp.BandsWithPlannedBlockers);
}
public int getNumAttackers() {
return getAttackersWithDefenders().size();
}
public boolean isAttacking(final CardView card) {
return getAttackersWithDefenders().containsKey(card);
}
public Iterable<CardView> getAttackers() {
return getAttackersWithDefenders().keySet();
}
public Iterable<GameEntityView<?>> getDefenders() {
return Sets.newHashSet(getAttackersWithDefenders().values());
}
public GameEntityView<?> getDefender(final CardView attacker) {
return getAttackersWithDefenders().get(attacker);
}
public boolean isBlocking(final CardView card) {
for (final Iterable<CardView> blockers : getAttackersWithBlockers().values()) {
if (blockers == null) {
continue;
}
if (Iterables.contains(blockers, card)) {
return true;
}
}
return false;
}
/**
* @param attacker
* @return the blockers associated with an attacker, or {@code null} if the
* attacker is unblocked.
*/
public Iterable<CardView> getBlockers(final CardView attacker) {
return getAttackersWithBlockers().get(attacker);
}
/**
* @param attacker
* @return the blockers associated with an attacker, or {@code null} if the
* attacker is unblocked (planning stage, for targeting overlay).
*/
public Iterable<CardView> getPlannedBlockers(final CardView attacker) {
return getAttackersWithPlannedBlockers().get(attacker);
}
/**
* Get an {@link Iterable} of the blockers of the specified band, or
* {@code null} if that band is unblocked.
*
* @param attackingBand
* an {@link Iterable} representing an attacking band.
* @return an {@link Iterable} of {@link CardView} objects, or {@code null}.
*/
public Iterable<CardView> getBlockers(final Iterable<CardView> attackingBand) {
return getBandsWithBlockers().get(attackingBand);
}
/**
* Get an {@link Iterable} of the blockers of the specified band, or
* {@code null} if that band is unblocked (planning stage, for targeting overlay).
*
* @param attackingBand
* an {@link Iterable} representing an attacking band.
* @return an {@link Iterable} of {@link CardView} objects, or {@code null}.
*/
public Iterable<CardView> getPlannedBlockers(final Iterable<CardView> attackingBand) {
return getBandsWithPlannedBlockers().get(attackingBand);
}
public Iterable<CardView> getAttackersOf(final GameEntityView<?> defender) {
ArrayList<CardView> views = new ArrayList<CardView>();
for (Entry<CardView, GameEntityView<?>> entry : getAttackersWithDefenders().entrySet()) {
if (entry.getValue().equals(defender)) {
views.add(entry.getKey());
}
}
return views;
}
public Iterable<Iterable<CardView>> getAttackingBandsOf(final GameEntityView<?> defender) {
ArrayList<Iterable<CardView>> views = new ArrayList<Iterable<CardView>>();
for (Entry<Iterable<CardView>, GameEntityView<?>> entry : getBandsWithDefenders().entrySet()) {
if (entry.getValue().equals(defender)) {
views.add(entry.getKey());
}
}
return views;
}
public void addAttackingBand(final Iterable<CardView> attackingBand, final GameEntityView<?> defender, final Iterable<CardView> blockers, final Iterable<CardView> plannedBlockers) {
final List<CardView> attackingBandCopy = Lists.newArrayList(attackingBand),
blockersCopy, plannedBlockersCopy;
blockersCopy = blockers == null ? null : Lists.newArrayList(blockers);
plannedBlockersCopy = plannedBlockers == null ? null : Lists.newArrayList(plannedBlockers);
for (final CardView attacker : attackingBandCopy) {
this.getAttackersWithDefenders().put(attacker, defender);
this.getAttackersWithBlockers().put(attacker, blockersCopy);
this.getAttackersWithPlannedBlockers().put(attacker, plannedBlockersCopy);
}
this.getBandsWithDefenders().put(attackingBandCopy, defender);
this.getBandsWithBlockers().put(attackingBandCopy, blockersCopy);
this.getBandsWithPlannedBlockers().put(attackingBandCopy, plannedBlockersCopy);
}
}

View File

@@ -111,7 +111,7 @@ public class CostUnattach extends CostPartWithList {
*/ */
@Override @Override
protected Card doPayment(SpellAbility ability, Card targetCard) { protected Card doPayment(SpellAbility ability, Card targetCard) {
targetCard.unEquipCard(targetCard.getEquipping().get(0)); targetCard.unEquipCard(targetCard.getEquipping());
return targetCard; return targetCard;
} }

View File

@@ -58,7 +58,7 @@ public class GameStateSerializer {
public void write(Card card) { public void write(Card card) {
if (card == null) { return; } if (card == null) { return; }
int key = card.getUniqueNumber(); int key = card.getId();
cards.put(key, card); cards.put(key, card);
write(key); //only write info for each card once at end of file write(key); //only write info for each card once at end of file
} }

View File

@@ -518,7 +518,7 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
int exaltedMagnitude = card.getKeywordAmount("Exalted"); int exaltedMagnitude = card.getKeywordAmount("Exalted");
for (int i = 0; i < exaltedMagnitude; i++) { for (int i = 0; i < exaltedMagnitude; i++) {
String abScript = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ +1 | NumDef$ +1 | StackDescription$ Exalted for attacker {c:CardUID_%d} (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn).", attacker.getUniqueNumber(), attacker.getUniqueNumber()); String abScript = String.format("AB$ Pump | Cost$ 0 | Defined$ CardUID_%d | NumAtt$ +1 | NumDef$ +1 | StackDescription$ Exalted for attacker {c:CardUID_%d} (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn).", attacker.getId(), attacker.getId());
SpellAbility ability = AbilityFactory.getAbility(abScript, card); SpellAbility ability = AbilityFactory.getAbility(abScript, card);
ability.setActivatingPlayer(card.getController()); ability.setActivatingPlayer(card.getController());
ability.setDescription(ability.getStackDescription()); ability.setDescription(ability.getStackDescription());

View File

@@ -257,11 +257,11 @@ public class Untap extends Phase {
continue; continue;
} }
} else if (c.isEquipment() && c.isEquipping()) { } else if (c.isEquipment() && c.isEquipping()) {
if (list.contains(c.getEquippingCard())) { if (list.contains(c.getEquipping())) {
continue; continue;
} }
} else if (c.isFortification() && c.isFortifying()) { } else if (c.isFortification() && c.isFortifying()) {
if (list.contains(c.getFortifyingCard())) { if (list.contains(c.getFortifying())) {
continue; continue;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,207 @@
package forge.game.player;
import java.util.Map;
import com.google.common.collect.Maps;
import forge.LobbyPlayer;
import forge.card.MagicColor;
import forge.game.GameEntityView;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardView;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
import forge.trackable.TrackableCollection;
import forge.trackable.TrackableProperty.PlayerProp;
public class PlayerView extends GameEntityView<PlayerProp> {
public static PlayerView get(Player p) {
return p == null ? null : p.getView();
}
public static TrackableCollection<PlayerView> getCollection(Iterable<Player> players) {
if (players == null) {
return null;
}
TrackableCollection<PlayerView> collection = new TrackableCollection<PlayerView>();
for (Player p : players) {
collection.add(p.getView());
}
return collection;
}
public PlayerView(int id0) {
super(id0, PlayerProp.class);
set(PlayerProp.Mana, Maps.newHashMapWithExpectedSize(MagicColor.NUMBER_OR_COLORS + 1));
}
public LobbyPlayer getLobbyPlayer() {
return get(PlayerProp.LobbyPlayer);
}
void updateLobbyPlayer(Player p) {
set(PlayerProp.LobbyPlayer, p.getLobbyPlayer());
}
public Iterable<PlayerView> getOpponents() {
return get(PlayerProp.Opponents);
}
private TrackableCollection<PlayerView> getOpponentCollection() {
return get(PlayerProp.Opponents);
}
public boolean isOpponentOf(final PlayerView other) {
return getOpponentCollection().contains(other);
}
public String getName() {
return getLobbyPlayer().getName();
}
@Override
public String toString() {
return getName();
}
public int getLife() {
return get(PlayerProp.Life);
}
void updateLife(Player p) {
set(PlayerProp.Life, p.getLife());
}
public int getPoisonCounters() {
return get(PlayerProp.PoisonCounters);
}
void updatePoisonCounters(Player p) {
set(PlayerProp.PoisonCounters, p.getPoisonCounters());
}
public int getMaxHandSize() {
return get(PlayerProp.MaxHandSize);
}
void updateMaxHandSize(Player p) {
set(PlayerProp.MaxHandSize, p.getMaxHandSize());
}
public boolean hasUnlimitedHandSize() {
return get(PlayerProp.HasUnlimitedHandSize);
}
void updateUnlimitedHandSize(Player p) {
set(PlayerProp.HasUnlimitedHandSize, p.isUnlimitedHandSize());
}
public int getNumDrawnThisTurn() {
return get(PlayerProp.NumDrawnThisTurn);
}
void updateNumDrawnThisTurn(Player p) {
set(PlayerProp.NumDrawnThisTurn, p.getNumDrawnThisTurn());
}
public Iterable<String> getKeywords() {
return get(PlayerProp.Keywords);
}
void updateKeywords(Player p) {
set(PlayerProp.Keywords, p.getKeywords());
}
public String getCommanderInfo() {
return get(PlayerProp.CommanderInfo);
}
void updateCommanderInfo(Player p) {
set(PlayerProp.CommanderInfo, CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; "));
}
public Iterable<CardView> getAnte() {
return get(PlayerProp.Ante);
}
public Iterable<CardView> getBattlefield() {
return get(PlayerProp.Battlefield);
}
public Iterable<CardView> getCommand() {
return get(PlayerProp.Command);
}
public Iterable<CardView> getExile() {
return get(PlayerProp.Exile);
}
public Iterable<CardView> getFlashback() {
return get(PlayerProp.Flashback);
}
public Iterable<CardView> getGraveyard() {
return get(PlayerProp.Graveyard);
}
public Iterable<CardView> getHand() {
return get(PlayerProp.Hand);
}
public Iterable<CardView> getLibrary() {
return get(PlayerProp.Library);
}
public Iterable<CardView> getCards(final ZoneType zone) {
PlayerProp prop = getZoneProp(zone);
if (prop != null) {
return get(prop);
}
return null;
}
private PlayerProp getZoneProp(final ZoneType zone) {
switch (zone) {
case Ante:
return PlayerProp.Ante;
case Battlefield:
return PlayerProp.Battlefield;
case Command:
return PlayerProp.Command;
case Exile:
return PlayerProp.Exile;
case Graveyard:
return PlayerProp.Graveyard;
case Hand:
return PlayerProp.Hand;
case Library:
return PlayerProp.Library;
default:
return null; //other zones not represented
}
}
void updateZone(PlayerZone zone) {
PlayerProp prop = getZoneProp(zone.getZoneType());
if (prop == null) { return; }
set(prop, CardView.getCollection(zone.getCards()));
}
private Map<Byte, Integer> getMana() {
return get(PlayerProp.Mana);
}
void updateMana(Player p) {
boolean changed = false;
Map<Byte, Integer> mana = getMana();
for (byte b : MagicColor.WUBRGC) {
int value = p.getManaPool().getAmountOfColor(b);
if (mana.put(b, value) != value) {
changed = true;
}
}
if (changed) {
flagAsChanged(PlayerProp.Mana);
}
}
public int getMana(final byte color) {
Integer count = getMana().get(color);
return count != null ? count.intValue() : 0;
}
@Override
protected PlayerProp preventNextDamageProp() {
return PlayerProp.PreventNextDamage;
}
}

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.getChosenColor().isEmpty()) { if (repType.contains("Chosen") && !repHost.getChosenColors().isEmpty()) {
repType = repType.replace("Chosen", MagicColor.toShortString(repHost.getChosenColor().get(0))); repType = repType.replace("Chosen", MagicColor.toShortString(repHost.getChosenColors().get(0)));
} }
manaAb.getManaPart().setManaReplaceType(repType); manaAb.getManaPart().setManaReplaceType(repType);
manaAb.getManaPart().produceMana(rep, player1, manaAb); manaAb.getManaPart().produceMana(rep, player1, manaAb);

View File

@@ -341,9 +341,9 @@ 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().getChosenColor().isEmpty()) { if (this.getSourceCard() != null && !this.getSourceCard().getChosenColors().isEmpty()) {
return MagicColor.toShortString(this.getSourceCard() return MagicColor.toShortString(this.getSourceCard()
.getChosenColor().get(0)); .getChosenColors().get(0));
} }
} }
return this.getOrigProduced(); return this.getOrigProduced();
@@ -473,7 +473,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().getChosenColor(); List<String> chosenCol = this.getSourceCard().getChosenColors();
if ( !chosenCol.isEmpty() && MagicColor.toShortString(chosenCol.get(0)).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().getChosenColor().contains(this.getColorToCheck())) { if (!sa.getHostCard().getChosenColors().contains(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().getChosenColor().contains(this.getColorToCheck())) { if (!sa.getHostCard().getChosenColors().contains(this.getColorToCheck())) {
return false; return false;
} }
} }

View File

@@ -51,10 +51,10 @@ public class SpellAbilityStackInstance implements IIdentifiable {
// Coming off the Stack would work similarly, except it would just add the // Coming off the Stack would work similarly, except it would just add the
// full active SI instead of each of the parts // full active SI instead of each of the parts
private int id; private final int id;
private SpellAbility ability = null; private final SpellAbility ability;
private SpellAbilityStackInstance subInstance = null; private final SpellAbilityStackInstance subInstance;
private Player activator; private Player activator;
// When going to a SubAbility that SA has a Instance Choice object // When going to a SubAbility that SA has a Instance Choice object
@@ -73,67 +73,58 @@ public class SpellAbilityStackInstance implements IIdentifiable {
private int xManaPaid = 0; private int xManaPaid = 0;
// Other Paid things // Other Paid things
private HashMap<String, List<Card>> paidHash = new HashMap<String, List<Card>>(); private final HashMap<String, List<Card>> paidHash;
// Additional info // Additional info
// is Kicked, is Buyback // is Kicked, is Buyback
// Triggers // Triggers
private HashMap<String, Object> triggeringObjects = new HashMap<String, Object>(); private final HashMap<String, Object> triggeringObjects;
private List<Object> triggerRemembered = new ArrayList<Object>(); private final List<Object> triggerRemembered;
private final HashMap<String, String> storedSVars = new HashMap<String, String>(); private final HashMap<String, String> storedSVars = new HashMap<String, String>();
private final List<ZoneType> zonesToOpen; private final List<ZoneType> zonesToOpen;
private final Map<Player, Object> playersWithValidTargets; private final Map<Player, Object> playersWithValidTargets;
/** private final StackItemView view;
* <p>
* Constructor for SpellAbility_StackInstance.
* </p>
*
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
*/
public SpellAbilityStackInstance(final SpellAbility sa) { public SpellAbilityStackInstance(final SpellAbility sa) {
// Base SA info // Base SA info
this.id = nextId(); id = nextId();
this.ability = sa; ability = sa;
this.stackDescription = this.ability.getStackDescription(); stackDescription = sa.getStackDescription();
this.activator = sa.getActivatingPlayer(); activator = sa.getActivatingPlayer();
// Payment info // Payment info
this.paidHash = this.ability.getPaidHash(); paidHash = ability.getPaidHash();
this.ability.resetPaidHash(); ability.resetPaidHash();
this.splicedCards = sa.getSplicedCards(); splicedCards = sa.getSplicedCards();
// TODO getXManaCostPaid should be on the SA, not the Card // TODO getXManaCostPaid should be on the SA, not the Card
this.xManaPaid = sa.getHostCard().getXManaCostPaid(); xManaPaid = sa.getHostCard().getXManaCostPaid();
// Triggering info // Triggering info
this.triggeringObjects = sa.getTriggeringObjects(); triggeringObjects = sa.getTriggeringObjects();
this.triggerRemembered = sa.getTriggerRemembered(); triggerRemembered = sa.getTriggerRemembered();
final AbilitySub subAb = this.ability.getSubAbility(); subInstance = ability.getSubAbility() == null ? null : new SpellAbilityStackInstance(ability.getSubAbility());
if (subAb != null) {
this.subInstance = new SpellAbilityStackInstance(subAb);
}
// Targeting info -- 29/06/11 Moved to after taking care of SubAbilities // Targeting info -- 29/06/11 Moved to after taking care of SubAbilities
// because otherwise AF_DealDamage SubAbilities that use Defined$ // because otherwise AF_DealDamage SubAbilities that use Defined$
// Targeted breaks (since it's parents target is reset) // Targeted breaks (since it's parents target is reset)
if (sa.usesTargeting()) { if (sa.usesTargeting()) {
this.tc = ability.getTargets(); tc = ability.getTargets();
this.ability.resetTargets(); ability.resetTargets();
} }
final Card source = this.ability.getHostCard(); final Card source = ability.getHostCard();
// Store SVars and Clear // Store SVars and Clear
for (final String store : Card.getStorableSVars()) { for (final String store : Card.getStorableSVars()) {
final String value = source.getSVar(store); final String value = source.getSVar(store);
if (value.length() > 0) { if (value.length() > 0) {
this.storedSVars.put(store, value); storedSVars.put(store, value);
source.setSVar(store, ""); source.setSVar(store, "");
} }
} }
@@ -156,154 +147,107 @@ public class SpellAbilityStackInstance implements IIdentifiable {
} }
} }
} }
view = new StackItemView(this);
} }
@Override @Override
public int getId() { public int getId() {
return this.id; return id;
} }
/** //TODO: See if refresh actually needed for most places this is being called
* <p> // Perhaps lets move the refresh logic to a separate function called only when necessary
* getSpellAbility. public final SpellAbility getSpellAbility(boolean refresh) {
* </p> if (refresh) {
* ability.resetTargets();
* @return a {@link forge.game.spellability.SpellAbility} object. ability.setTargets(tc);
*/ ability.setActivatingPlayer(activator);
public final SpellAbility getSpellAbility() {
this.ability.resetTargets();
this.ability.setTargets(tc);
this.ability.setActivatingPlayer(activator);
// Saved sub-SA needs to be reset on the way out // Saved sub-SA needs to be reset on the way out
if (this.subInstance != null) { if (subInstance != null) {
this.ability.setSubAbility((AbilitySub) this.subInstance.getSpellAbility()); ability.setSubAbility((AbilitySub) subInstance.getSpellAbility(true));
} }
// Set Cost specific things here // Set Cost specific things here
this.ability.resetPaidHash(); ability.resetPaidHash();
this.ability.setPaidHash(this.paidHash); ability.setPaidHash(paidHash);
this.ability.setSplicedCards(splicedCards); ability.setSplicedCards(splicedCards);
this.ability.getHostCard().setXManaCostPaid(this.xManaPaid); ability.getHostCard().setXManaCostPaid(xManaPaid);
// Triggered // Triggered
this.ability.setAllTriggeringObjects(this.triggeringObjects); ability.setTriggeringObjects(triggeringObjects);
this.ability.setTriggerRemembered(this.triggerRemembered); ability.setTriggerRemembered(triggerRemembered);
// Add SVars back in // Add SVars back in
final Card source = this.ability.getHostCard(); final Card source = ability.getHostCard();
for (final String store : this.storedSVars.keySet()) { for (final String store : storedSVars.keySet()) {
final String value = this.storedSVars.get(store); final String value = storedSVars.get(store);
if (value.length() > 0) { if (value.length() > 0) {
source.setSVar(store, value); source.setSVar(store, value);
}
} }
} }
return ability;
return this.ability;
} }
// A bit of SA shared abilities to restrict conflicts // A bit of SA shared abilities to restrict conflicts
/**
* <p>
* Getter for the field <code>stackDescription</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public final String getStackDescription() { public final String getStackDescription() {
return this.stackDescription; return stackDescription;
} }
/**
* <p>
* getHostCard.
* </p>
*
* @return a {@link forge.game.card.Card} object.
*/
public final Card getSourceCard() { public final Card getSourceCard() {
return this.ability.getHostCard(); return ability.getHostCard();
} }
/**
* <p>
* isSpell.
* </p>
*
* @return a boolean.
*/
public final boolean isSpell() { public final boolean isSpell() {
return this.ability.isSpell(); return ability.isSpell();
} }
/**
* <p>
* isAbility.
* </p>
*
* @return a boolean.
*/
public final boolean isAbility() { public final boolean isAbility() {
return this.ability.isAbility(); return ability.isAbility();
} }
/**
* <p>
* isTrigger.
* </p>
*
* @return a boolean.
*/
public final boolean isTrigger() { public final boolean isTrigger() {
return this.ability.isTrigger(); return ability.isTrigger();
} }
/**
* <p>
* isStateTrigger.
* </p>
*
* @param id
* a int.
* @return a boolean.
*/
public final boolean isStateTrigger(final int id) { public final boolean isStateTrigger(final int id) {
return this.ability.getSourceTrigger() == id; return ability.getSourceTrigger() == id;
} }
/**
* Checks if is optional trigger.
*
* @return true, if is optional trigger
*/
public final boolean isOptionalTrigger() { public final boolean isOptionalTrigger() {
return this.ability.isOptionalTrigger(); return ability.isOptionalTrigger();
} }
public final SpellAbilityStackInstance getSubInstance() { public final SpellAbilityStackInstance getSubInstance() {
return this.subInstance; return subInstance;
} }
public final TargetChoices getTargetChoices() { public final TargetChoices getTargetChoices() {
return this.tc; return tc;
} }
public final List<ZoneType> getZonesToOpen() { public final List<ZoneType> getZonesToOpen() {
return this.zonesToOpen; return zonesToOpen;
} }
public final Map<Player, Object> getPlayersWithValidTargets() { public final Map<Player, Object> getPlayersWithValidTargets() {
return this.playersWithValidTargets; return playersWithValidTargets;
} }
public void updateTarget(TargetChoices target) { public void updateTarget(TargetChoices target) {
if (target != null) { if (target != null) {
this.tc = target; tc = target;
this.ability.setTargets(tc); ability.setTargets(tc);
this.stackDescription = this.ability.getStackDescription(); stackDescription = ability.getStackDescription();
view.updateTargetCards(this);
view.updateTargetPlayers(this);
view.updateText(this);
// Run BecomesTargetTrigger // Run BecomesTargetTrigger
HashMap<String, Object> runParams = new HashMap<String, Object>(); HashMap<String, Object> runParams = new HashMap<String, Object>();
runParams.put("SourceSA", this.ability); runParams.put("SourceSA", ability);
HashSet<Object> distinctObjects = new HashSet<Object>(); HashSet<Object> distinctObjects = new HashSet<Object>();
for (final Object tgt : target.getTargets()) { for (final Object tgt : target.getTargets()) {
if (distinctObjects.contains(tgt)) { if (distinctObjects.contains(tgt)) {
@@ -315,7 +259,7 @@ public class SpellAbilityStackInstance implements IIdentifiable {
((Card) tgt).setBecameTargetThisTurn(true); ((Card) tgt).setBecameTargetThisTurn(true);
} }
runParams.put("Target", tgt); runParams.put("Target", tgt);
this.getSourceCard().getGame().getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams, false); getSourceCard().getGame().getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams, false);
} }
} }
} }
@@ -347,12 +291,18 @@ public class SpellAbilityStackInstance implements IIdentifiable {
return activator; return activator;
} }
public void setActivator(Player activator) { public void setActivator(Player activator0) {
this.activator = activator; if (activator == activator0) { return; }
activator = activator0;
view.updateActivator(this);
} }
@Override @Override
public String toString() { public String toString() {
return String.format("%s->%s", getSourceCard(), stackDescription); return String.format("%s->%s", getSourceCard(), getStackDescription());
}
public StackItemView getView() {
return view;
} }
} }

View File

@@ -0,0 +1,49 @@
package forge.game.spellability;
import forge.game.card.CardView;
import forge.trackable.TrackableObject;
import forge.trackable.TrackableProperty.SpellAbilityProp;
public class SpellAbilityView extends TrackableObject<SpellAbilityProp> {
SpellAbilityView(SpellAbility sa) {
super(sa.getId(), SpellAbilityProp.class);
updateHostCard(sa);
updateDescription(sa);
updateCanPlay(sa);
updatePromptIfOnlyPossibleAbility(sa);
}
@Override
public String toString() {
return this.getDescription();
}
public CardView getHostCard() {
return get(SpellAbilityProp.HostCard);
}
void updateHostCard(SpellAbility sa) {
set(SpellAbilityProp.HostCard, CardView.get(sa.getHostCard()));
}
public String getDescription() {
return get(SpellAbilityProp.Description);
}
void updateDescription(SpellAbility sa) {
set(SpellAbilityProp.Description, sa.toUnsuppressedString());
}
public boolean canPlay() {
return get(SpellAbilityProp.CanPlay);
}
void updateCanPlay(SpellAbility sa) {
set(SpellAbilityProp.CanPlay, sa.canPlay());
}
public boolean promptIfOnlyPossibleAbility() {
return get(SpellAbilityProp.PromptIfOnlyPossibleAbility);
}
void updatePromptIfOnlyPossibleAbility(SpellAbility sa) {
set(SpellAbilityProp.PromptIfOnlyPossibleAbility, sa.promptIfOnlyPossibleAbility());
}
}

View File

@@ -0,0 +1,98 @@
package forge.game.spellability;
import forge.game.card.CardView;
import forge.game.player.PlayerView;
import forge.trackable.TrackableObject;
import forge.trackable.TrackableProperty.StackItemProp;
public class StackItemView extends TrackableObject<StackItemProp> {
public StackItemView(SpellAbilityStackInstance si) {
super(si.getId(), StackItemProp.class);
updateKey(si);
updateSourceTrigger(si);
updateText(si);
updateSourceCard(si);
updateActivator(si);
updateTargetCards(si);
updateTargetPlayers(si);
updateAbility(si);
updateOptionalTrigger(si);
updateSubInstance(si);
}
public String getKey() {
return get(StackItemProp.Key);
}
void updateKey(SpellAbilityStackInstance si) {
set(StackItemProp.Key, si.getSpellAbility(false).toUnsuppressedString());
}
public int getSourceTrigger() {
return get(StackItemProp.SourceTrigger);
}
void updateSourceTrigger(SpellAbilityStackInstance si) {
set(StackItemProp.SourceTrigger, si.getSpellAbility(false).getSourceTrigger());
}
public String getText() {
return get(StackItemProp.Text);
}
void updateText(SpellAbilityStackInstance si) {
set(StackItemProp.Text, si.getStackDescription());
}
public CardView getSourceCard() {
return get(StackItemProp.SourceCard);
}
void updateSourceCard(SpellAbilityStackInstance si) {
set(StackItemProp.SourceCard, si.getSourceCard());
}
public PlayerView getActivator() {
return get(StackItemProp.Activator);
}
void updateActivator(SpellAbilityStackInstance si) {
set(StackItemProp.Activator, PlayerView.get(si.getActivator()));
}
public Iterable<CardView> getTargetCards() {
return get(StackItemProp.TargetCards);
}
void updateTargetCards(SpellAbilityStackInstance si) {
set(StackItemProp.TargetCards, CardView.getCollection(si.getTargetChoices().getTargetCards()));
}
public Iterable<PlayerView> getTargetPlayers() {
return get(StackItemProp.TargetPlayers);
}
void updateTargetPlayers(SpellAbilityStackInstance si) {
set(StackItemProp.TargetPlayers, PlayerView.getCollection(si.getTargetChoices().getTargetPlayers()));
}
public boolean isAbility() {
return get(StackItemProp.Ability);
}
void updateAbility(SpellAbilityStackInstance si) {
set(StackItemProp.Ability, si.isAbility());
}
public boolean isOptionalTrigger() {
return get(StackItemProp.OptionalTrigger);
}
void updateOptionalTrigger(SpellAbilityStackInstance si) {
set(StackItemProp.OptionalTrigger, si.isOptionalTrigger());
}
public StackItemView getSubInstance() {
return get(StackItemProp.SubInstance);
}
void updateSubInstance(SpellAbilityStackInstance si) {
set(StackItemProp.SubInstance, si.getSubInstance() == null ? null : new StackItemView(si.getSubInstance()));
}
@Override
public String toString() {
return getText();
}
}

View File

@@ -159,7 +159,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.getChosenColor(); final List<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())));
@@ -170,7 +170,7 @@ public class StaticAbilityContinuous {
addKeywords[w] = addKeywords[w].replaceAll("ChosenType", chosenType); addKeywords[w] = addKeywords[w].replaceAll("ChosenType", chosenType);
} }
final String chosenName = hostCard.getNamedCard(); final String chosenName = hostCard.getNamedCard();
final String hostCardUID = Integer.toString(hostCard.getUniqueNumber()); // Protection with "doesn't remove" effect final String hostCardUID = Integer.toString(hostCard.getId()); // Protection with "doesn't remove" effect
for (int w = 0; w < addKeywords.length; w++) { for (int w = 0; w < addKeywords.length; w++) {
if (addKeywords[w].startsWith("Protection:")) { if (addKeywords[w].startsWith("Protection:")) {
addKeywords[w] = addKeywords[w].replaceAll("ChosenName", "Card.named" + chosenName).replace("HostCardUID", hostCardUID); addKeywords[w] = addKeywords[w].replaceAll("ChosenName", "Card.named" + chosenName).replace("HostCardUID", hostCardUID);
@@ -223,7 +223,7 @@ public class StaticAbilityContinuous {
addTypes[0] = chosenType; addTypes[0] = chosenType;
se.setChosenType(chosenType); se.setChosenType(chosenType);
} else if (addTypes[0].equals("ImprintedCreatureType")) { } else if (addTypes[0].equals("ImprintedCreatureType")) {
final ArrayList<String> imprint = hostCard.getImprinted().get(0).getType(); final Set<String> imprint = hostCard.getImprinted().get(0).getType();
ArrayList<String> imprinted = new ArrayList<String>(); ArrayList<String> imprinted = new ArrayList<String>();
for (String t : imprint) { for (String t : imprint) {
if (CardType.isACreatureType(t) || t.equals("AllCreatureTypes")) { if (CardType.isACreatureType(t) || t.equals("AllCreatureTypes")) {
@@ -262,7 +262,7 @@ public class StaticAbilityContinuous {
if (params.containsKey("AddColor")) { if (params.containsKey("AddColor")) {
final String colors = params.get("AddColor"); final String colors = params.get("AddColor");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
addColors = CardUtil.getShortColorsString(hostCard.getChosenColor()); addColors = CardUtil.getShortColorsString(hostCard.getChosenColors());
} else { } else {
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split( addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(
" & ")))); " & "))));
@@ -272,7 +272,7 @@ public class StaticAbilityContinuous {
if (params.containsKey("SetColor")) { if (params.containsKey("SetColor")) {
final String colors = params.get("SetColor"); final String colors = params.get("SetColor");
if (colors.equals("ChosenColor")) { if (colors.equals("ChosenColor")) {
addColors = CardUtil.getShortColorsString(hostCard.getChosenColor()); addColors = CardUtil.getShortColorsString(hostCard.getChosenColors());
} else { } else {
addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList( addColors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(
colors.split(" & ")))); colors.split(" & "))));
@@ -381,8 +381,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.getChosenColor().size() > 0) { if (hostCard.getChosenColors().size() > 0) {
color = MagicColor.fromName(hostCard.getChosenColor().get(0)); color = MagicColor.fromName(hostCard.getChosenColors().get(0));
} else { } else {
color = 0; color = 0;
} }
@@ -653,7 +653,7 @@ public class StaticAbilityContinuous {
} else if (params.get("Affected").contains("EnchantedBy")) { } else if (params.get("Affected").contains("EnchantedBy")) {
affectedCards = Lists.newArrayList(hostCard.getEnchantingCard()); affectedCards = Lists.newArrayList(hostCard.getEnchantingCard());
} else if (params.get("Affected").contains("EquippedBy")) { } else if (params.get("Affected").contains("EquippedBy")) {
affectedCards = Lists.newArrayList(hostCard.getEquippingCard()); affectedCards = Lists.newArrayList(hostCard.getEquipping());
} else if (params.get("Affected").equals("EffectSource")) { } else if (params.get("Affected").equals("EffectSource")) {
affectedCards = new ArrayList<Card>(AbilityUtils.getDefinedCards(hostCard, params.get("Affected"), null)); affectedCards = new ArrayList<Card>(AbilityUtils.getDefinedCards(hostCard, params.get("Affected"), null));
return affectedCards; return affectedCards;

View File

@@ -190,7 +190,7 @@ public class TriggerHandler implements IGameStateObject {
while(itr.hasNext()) { while(itr.hasNext()) {
t = (Trigger)itr.next(); t = (Trigger)itr.next();
if (c.getUniqueNumber() == t.getHostCard().getUniqueNumber() && t.isIntrinsic()) { if (c.getId() == t.getHostCard().getId() && t.isIntrinsic()) {
toBeRemoved.add(t); toBeRemoved.add(t);
} }
} }
@@ -420,7 +420,7 @@ public class TriggerHandler implements IGameStateObject {
Card host = regtrig.getHostCard(); Card host = regtrig.getHostCard();
Card trigCard = regtrig.getRunParams().containsKey("Card") ? (Card)regtrig.getRunParams().get("Card") : null; Card trigCard = regtrig.getRunParams().containsKey("Card") ? (Card)regtrig.getRunParams().get("Card") : null;
if (trigCard != null && (host.getUniqueNumber() == trigCard.getUniqueNumber())) { if (trigCard != null && (host.getId() == trigCard.getId())) {
host = trigCard; host = trigCard;
} else { } else {
host = game.getCardState(regtrig.getHostCard()); host = game.getCardState(regtrig.getHostCard());
@@ -445,7 +445,7 @@ public class TriggerHandler implements IGameStateObject {
regtrig.setTriggeringObjects(sa); regtrig.setTriggeringObjects(sa);
sa.setTriggerRemembered(regtrig.getTriggerRemembered()); sa.setTriggerRemembered(regtrig.getTriggerRemembered());
if (regtrig.getStoredTriggeredObjects() != null) { if (regtrig.getStoredTriggeredObjects() != null) {
sa.setAllTriggeringObjects(regtrig.getStoredTriggeredObjects()); sa.setTriggeringObjects(regtrig.getStoredTriggeredObjects());
} }
if (sa.getActivatingPlayer() == null) { // overriding delayed trigger should have set activator if (sa.getActivatingPlayer() == null) { // overriding delayed trigger should have set activator
sa.setActivatingPlayer(host.getController()); sa.setActivatingPlayer(host.getController());

View File

@@ -95,7 +95,7 @@ public class TriggerSpellAbilityCast extends Trigger {
} }
if (this.mapParams.containsKey("ValidActivatingPlayer")) { if (this.mapParams.containsKey("ValidActivatingPlayer")) {
if (si == null || !matchesValid(si.getSpellAbility().getActivatingPlayer(), this.mapParams.get("ValidActivatingPlayer") if (si == null || !matchesValid(si.getSpellAbility(true).getActivatingPlayer(), this.mapParams.get("ValidActivatingPlayer")
.split(","), this.getHostCard())) { .split(","), this.getHostCard())) {
return false; return false;
} }
@@ -103,7 +103,7 @@ public class TriggerSpellAbilityCast extends Trigger {
String compare = this.mapParams.get("ActivatorThisTurnCast"); String compare = this.mapParams.get("ActivatorThisTurnCast");
List<Card> thisTurnCast = CardUtil.getThisTurnCast(this.mapParams.containsKey("ValidCard") ? this.mapParams.get("ValidCard") : "Card", List<Card> thisTurnCast = CardUtil.getThisTurnCast(this.mapParams.containsKey("ValidCard") ? this.mapParams.get("ValidCard") : "Card",
this.getHostCard()); this.getHostCard());
thisTurnCast = CardLists.filterControlledBy(thisTurnCast, si.getSpellAbility().getActivatingPlayer()); thisTurnCast = CardLists.filterControlledBy(thisTurnCast, si.getSpellAbility(true).getActivatingPlayer());
int left = thisTurnCast.size(); int left = thisTurnCast.size();
int right = Integer.parseInt(compare.substring(2)); int right = Integer.parseInt(compare.substring(2));
if (!Expressions.compare(left, compare, right)) { if (!Expressions.compare(left, compare, right)) {
@@ -121,7 +121,7 @@ public class TriggerSpellAbilityCast extends Trigger {
if (this.mapParams.containsKey("TargetsValid")) { if (this.mapParams.containsKey("TargetsValid")) {
SpellAbility sa = spellAbility; SpellAbility sa = spellAbility;
if (si != null) { if (si != null) {
sa = si.getSpellAbility(); sa = si.getSpellAbility(true);
} }
boolean validTgtFound = false; boolean validTgtFound = false;
@@ -211,7 +211,7 @@ public class TriggerSpellAbilityCast extends Trigger {
final SpellAbilityStackInstance si = sa.getHostCard().getGame().getStack().getInstanceFromSpellAbility(castSA); final SpellAbilityStackInstance si = sa.getHostCard().getGame().getStack().getInstanceFromSpellAbility(castSA);
sa.setTriggeringObject("Card", castSA.getHostCard()); sa.setTriggeringObject("Card", castSA.getHostCard());
sa.setTriggeringObject("SpellAbility", castSA); sa.setTriggeringObject("SpellAbility", castSA);
sa.setTriggeringObject("SpellAbilityTargetingCards", (si != null ? si.getSpellAbility() : castSA).getTargets().getTargetCards()); sa.setTriggeringObject("SpellAbilityTargetingCards", (si != null ? si.getSpellAbility(true) : castSA).getTargets().getTargetCards());
sa.setTriggeringObject("Player", this.getRunParams().get("Player")); sa.setTriggeringObject("Player", this.getRunParams().get("Player"));
sa.setTriggeringObject("Activator", this.getRunParams().get("Activator")); sa.setTriggeringObject("Activator", this.getRunParams().get("Activator"));
sa.setTriggeringObject("CurrentStormCount", this.getRunParams().get("CurrentStormCount")); sa.setTriggeringObject("CurrentStormCount", this.getRunParams().get("CurrentStormCount"));

View File

@@ -93,7 +93,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().getChosenColor(); List<String> colors = this.getHostCard().getChosenColors();
if (colors.isEmpty() || !produced.contains(MagicColor.toShortString(colors.get(0)))) { if (colors.isEmpty() || !produced.contains(MagicColor.toShortString(colors.get(0)))) {
return false; return false;
} }

View File

@@ -31,7 +31,7 @@ public class WrappedAbility extends Ability implements ISpellAbility {
boolean mandatory = false; boolean mandatory = false;
public WrappedAbility(final Trigger regTrig, final SpellAbility sa0, final Player decider0) { public WrappedAbility(final Trigger regTrig, final SpellAbility sa0, final Player decider0) {
super(regTrig.getHostCard(), ManaCost.ZERO); super(sa0.getHostCard(), ManaCost.ZERO);
regtrig = regTrig; regtrig = regTrig;
sa = sa0; sa = sa0;
decider = decider0; decider = decider0;
@@ -41,7 +41,6 @@ public class WrappedAbility extends Ability implements ISpellAbility {
return sa; return sa;
} }
@Override @Override
public boolean isWrapper() { public boolean isWrapper() {
return true; return true;
@@ -109,8 +108,8 @@ public class WrappedAbility extends Ability implements ISpellAbility {
} }
@Override @Override
public void setAllTriggeringObjects(final HashMap<String, Object> triggeredObjects) { public void setTriggeringObjects(final HashMap<String, Object> triggeredObjects) {
sa.setAllTriggeringObjects(triggeredObjects); sa.setTriggeringObjects(triggeredObjects);
} }
@Override @Override
@@ -178,11 +177,6 @@ public class WrappedAbility extends Ability implements ISpellAbility {
return sa.getRestrictions(); return sa.getRestrictions();
} }
@Override
public Card getHostCard() {
return sa.getHostCard();
}
@Override @Override
public String getStackDescription() { public String getStackDescription() {
final StringBuilder sb = new StringBuilder(regtrig.toString()); final StringBuilder sb = new StringBuilder(regtrig.toString());

View File

@@ -191,7 +191,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
// Add all Frozen Abilities onto the stack // Add all Frozen Abilities onto the stack
while (!this.frozenStack.isEmpty()) { while (!this.frozenStack.isEmpty()) {
final SpellAbility sa = this.frozenStack.pop().getSpellAbility(); final SpellAbility sa = this.frozenStack.pop().getSpellAbility(true);
this.add(sa); this.add(sa);
} }
// Add all waiting triggers onto the stack // Add all waiting triggers onto the stack
@@ -427,15 +427,15 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
runParams.put("Cost", sp.getPayCosts()); runParams.put("Cost", sp.getPayCosts());
runParams.put("Player", sp.getHostCard().getController()); runParams.put("Player", sp.getHostCard().getController());
runParams.put("Activator", sp.getActivatingPlayer()); runParams.put("Activator", sp.getActivatingPlayer());
runParams.put("CastSA", si.getSpellAbility()); runParams.put("CastSA", si.getSpellAbility(true));
runParams.put("CastSACMC", si.getSpellAbility().getHostCard().getCMC()); runParams.put("CastSACMC", si.getSpellAbility(true).getHostCard().getCMC());
runParams.put("CurrentStormCount", game.getStack().getCardsCastThisTurn().size()); runParams.put("CurrentStormCount", game.getStack().getCardsCastThisTurn().size());
game.getTriggerHandler().runTrigger(TriggerType.SpellAbilityCast, runParams, true); game.getTriggerHandler().runTrigger(TriggerType.SpellAbilityCast, runParams, true);
// Run SpellCast triggers // Run SpellCast triggers
if (sp.isSpell()) { if (sp.isSpell()) {
game.getTriggerHandler().runTrigger(TriggerType.SpellCast, runParams, true); game.getTriggerHandler().runTrigger(TriggerType.SpellCast, runParams, true);
this.executeCastCommand(si.getSpellAbility().getHostCard()); this.executeCastCommand(si.getSpellAbility(true).getHostCard());
} }
// Run AbilityCast triggers // Run AbilityCast triggers
@@ -458,7 +458,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
runParams = new HashMap<String, Object>(); runParams = new HashMap<String, Object>();
SpellAbility s = sp; SpellAbility s = sp;
if (si != null) { if (si != null) {
s = si.getSpellAbility(); s = si.getSpellAbility(true);
} }
runParams.put("SourceSA", s); runParams.put("SourceSA", s);
HashSet<Object> distinctObjects = new HashSet<Object>(); HashSet<Object> distinctObjects = new HashSet<Object>();
@@ -780,13 +780,13 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
} }
public final SpellAbility peekAbility() { public final SpellAbility peekAbility() {
return this.stack.peekFirst().getSpellAbility(); return this.stack.peekFirst().getSpellAbility(true);
} }
public final void remove(final SpellAbilityStackInstance si) { public final void remove(final SpellAbilityStackInstance si) {
this.stack.remove(si); this.stack.remove(si);
this.frozenStack.remove(si); this.frozenStack.remove(si);
game.fireEvent(new GameEventSpellRemovedFromStack(si.getSpellAbility())); game.fireEvent(new GameEventSpellRemovedFromStack(si.getSpellAbility(true)));
} }
public final SpellAbilityStackInstance getInstanceFromSpellAbility(final SpellAbility sa) { public final SpellAbilityStackInstance getInstanceFromSpellAbility(final SpellAbility sa) {

View File

@@ -0,0 +1,21 @@
package forge.trackable;
import java.util.LinkedHashSet;
@SuppressWarnings("serial")
public class TrackableCollection<T extends TrackableObject<?>> extends LinkedHashSet<T> { //use linked hash set so order is maintained
public TrackableCollection() {
}
@Override
public boolean add(T item) {
//TODO: Track change
return super.add(item);
}
@Override
public boolean remove(Object item) {
//TODO: Track change
return super.remove(item);
}
}

View File

@@ -0,0 +1,9 @@
package forge.trackable;
import java.util.HashMap;
@SuppressWarnings("serial")
public class TrackableIndex<T extends TrackableObject<?>> extends HashMap<Integer, T> {
public TrackableIndex() {
}
}

View File

@@ -0,0 +1,48 @@
package forge.trackable;
import java.util.EnumMap;
import java.util.EnumSet;
import forge.game.IIdentifiable;
//base class for objects that can be tracked and synced between game server and GUI
public abstract class TrackableObject<E extends Enum<E>> implements IIdentifiable {
private final int id;
private final EnumMap<E, Object> props;
private final EnumSet<E> changedProps;
protected TrackableObject(int id0, Class<E> propEnum0) {
id = id0;
props = new EnumMap<E, Object>(propEnum0);
changedProps = EnumSet.noneOf(propEnum0);
}
public int getId() {
return id;
}
@Override
public int hashCode() {
return id;
}
@SuppressWarnings("unchecked")
protected <T> T get(E key) {
return (T)props.get(key);
}
protected <T> void set(E key, T value) {
if (value == null) {
if (props.remove(key) != null) {
changedProps.add(key);
}
}
else if (!value.equals(props.put(key, value))) {
changedProps.add(key);
}
}
//use when updating collection type properties with using set
protected void flagAsChanged(E key) {
changedProps.add(key);
}
}

View File

@@ -0,0 +1,118 @@
package forge.trackable;
public class TrackableProperty {
public enum CardProp {
Owner,
Controller,
Zone,
Cloned,
FaceDown,
FlipCard,
Flipped,
SplitCard,
Transformed,
SetCode,
Rarity,
Attacking,
Blocking,
PhasedOut,
Sickness,
Tapped,
Token,
Counters,
Damage,
AssignedDamage,
ShieldCount,
PreventNextDamage,
ChosenType,
ChosenColors,
ChosenPlayer,
NamedCard,
Equipping,
EquippedBy,
Enchanting,
EnchantedBy,
Fortifying,
FortifiedBy,
GainControlTargets,
CloneOrigin,
Imprinted,
HauntedBy,
Haunting,
MustBlock,
PairedWith,
Original,
Alternate
}
public enum CardStateProp {
Name,
Colors,
ImageKey,
Type,
ManaCost,
Power,
Toughness,
Loyalty,
Text,
ChangedColorWords,
ChangedTypes,
HasDeathtouch,
HasHaste,
HasInfect,
HasStorm,
HasTrample,
FoilIndex
}
public enum PlayerProp {
LobbyPlayer,
Opponents,
Life,
PoisonCounters,
MaxHandSize,
HasUnlimitedHandSize,
NumDrawnThisTurn,
PreventNextDamage,
Keywords,
CommanderInfo,
Ante,
Battlefield,
Command,
Exile,
Flashback,
Graveyard,
Hand,
Library,
Mana
}
public enum SpellAbilityProp {
HostCard,
Description,
CanPlay,
PromptIfOnlyPossibleAbility
}
public enum StackItemProp {
Key,
SourceTrigger,
Text,
SourceCard,
Activator,
TargetCards,
TargetPlayers,
SubInstance,
Ability,
OptionalTrigger
}
public enum CombatProp {
AttackersWithDefenders,
AttackersWithBlockers,
BandsWithDefenders,
BandsWithBlockers,
AttackersWithPlannedBlockers,
BandsWithPlannedBlockers
}
}

View File

@@ -575,7 +575,7 @@ public class PlayerControllerForTests extends PlayerController {
@Override @Override
public CardShields chooseRegenerationShield(Card c) { public CardShields chooseRegenerationShield(Card c) {
return Iterables.getFirst(c.getShield(), null); return Iterables.getFirst(c.getShields(), null);
} }
@Override @Override

View File

@@ -5,6 +5,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -167,7 +168,7 @@ public class CardDetailUtil {
} }
public static String formatCardType(final CardStateView card) { public static String formatCardType(final CardStateView card) {
final List<String> list = card.getType(); final Set<String> list = card.getType();
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final List<String> superTypes = new ArrayList<String>(); final List<String> superTypes = new ArrayList<String>();

View File

@@ -82,7 +82,7 @@ public class InputBlock extends InputSyncronizedBase {
showMessage("Select another attacker to declare blockers for."); showMessage("Select another attacker to declare blockers for.");
} }
else { else {
String attackerName = currentAttacker.isFaceDown() ? "Morph" : currentAttacker.getName() + " (" + currentAttacker.getUniqueNumber() + ")"; String attackerName = currentAttacker.isFaceDown() ? "Morph" : currentAttacker.getName() + " (" + currentAttacker.getId() + ")";
String message = "Select creatures to block " + attackerName + " or select another attacker to declare blockers for."; String message = "Select creatures to block " + attackerName + " or select another attacker to declare blockers for.";
showMessage(message); showMessage(message);
} }

View File

@@ -327,7 +327,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
for (SpellAbilityStackInstance si : game.getStack()) { for (SpellAbilityStackInstance si : game.getStack()) {
final Card stC = si.getSourceCard(); final Card stC = si.getSourceCard();
final SpellAbility stSA = si.getSpellAbility().getRootAbility(); final SpellAbility stSA = si.getSpellAbility(true).getRootAbility();
if (stC.isValid(cost.getType().split(";"), ability.getActivatingPlayer(), source) && stSA.isSpell()) { if (stC.isValid(cost.getType().split(";"), ability.getActivatingPlayer(), source) && stSA.isSpell()) {
saList.add(stSA); saList.add(stSA);
if (stC.isCopiedSpell()) { if (stC.isCopiedSpell()) {

View File

@@ -1275,10 +1275,14 @@ public class PlayerControllerHuman extends PlayerController {
@Override @Override
public CardShields chooseRegenerationShield(Card c) { public CardShields chooseRegenerationShield(Card c) {
if (c.getShield().size() < 2) { if (c.getShieldCount() < 2) {
return Iterables.getFirst(c.getShield(), null); return Iterables.getFirst(c.getShields(), null);
} }
return SGuiChoose.one(getGui(), "Choose a regeneration shield:", c.getShield()); ArrayList<CardShields> shields = new ArrayList<CardShields>();
for (CardShields shield : c.getShields()) {
shields.add(shield);
}
return SGuiChoose.one(getGui(), "Choose a regeneration shield:", shields);
} }
@Override @Override

View File

@@ -318,7 +318,7 @@ public class TargetSelection {
final Game game = ability.getActivatingPlayer().getGame(); final Game game = ability.getActivatingPlayer().getGame();
for (final SpellAbilityStackInstance si : game.getStack()) { for (final SpellAbilityStackInstance si : game.getStack()) {
SpellAbility abilityOnStack = si.getSpellAbility(); SpellAbility abilityOnStack = si.getSpellAbility(true);
if (ability.equals(abilityOnStack)) { if (ability.equals(abilityOnStack)) {
// By peeking at stack item, target is set to its SI state. So set it back before adding targets // By peeking at stack item, target is set to its SI state. So set it back before adding targets
ability.resetTargets(); ability.resetTargets();
@@ -346,7 +346,7 @@ public class TargetSelection {
return false; return false;
} }
if (madeChoice instanceof StackItemView) { if (madeChoice instanceof StackItemView) {
ability.getTargets().add(controller.getStackItem((StackItemView)madeChoice).getSpellAbility()); ability.getTargets().add(controller.getStackItem((StackItemView)madeChoice).getSpellAbility(true));
} else // 'FINISH TARGETING' chosen } else // 'FINISH TARGETING' chosen
bTargetingDone = true; bTargetingDone = true;
} }

View File

@@ -3,6 +3,7 @@ package forge.view;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -751,7 +752,7 @@ public class CardView extends GameEntityView {
private String name; private String name;
private ColorSet colors; private ColorSet colors;
private String imageKey; private String imageKey;
private List<String> type; private Set<String> type;
private ManaCost manaCost; private ManaCost manaCost;
private int power, toughness, loyalty; private int power, toughness, loyalty;
private String text; private String text;
@@ -768,7 +769,7 @@ public class CardView extends GameEntityView {
this.name = ""; this.name = "";
this.colors = ColorSet.getNullColor(); this.colors = ColorSet.getNullColor();
this.imageKey = ImageKeys.HIDDEN_CARD; this.imageKey = ImageKeys.HIDDEN_CARD;
this.type = Collections.emptyList(); this.type = Collections.emptySet();
this.manaCost = ManaCost.NO_COST; this.manaCost = ManaCost.NO_COST;
this.power = 0; this.power = 0;
this.toughness = 0; this.toughness = 0;
@@ -837,15 +838,15 @@ public class CardView extends GameEntityView {
/** /**
* @return the type * @return the type
*/ */
public List<String> getType() { public Set<String> getType() {
return type; return type;
} }
/** /**
* @param type the type to set * @param type the type to set
*/ */
public void setType(final List<String> type) { public void setType(final Set<String> type) {
this.type = Collections.unmodifiableList(type); this.type = type;
} }
/** /**

View File

@@ -484,7 +484,7 @@ public abstract class LocalGameView implements IGameView {
view.setAttacking(combat != null && combat.isAttacking(c)); view.setAttacking(combat != null && combat.isAttacking(c));
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(Iterables.getFirst(c.getEquipping(), null), false)); view.setEquipping(getCardView(c.getEquipping(), false));
view.setEquippedBy(getCardViews(c.getEquippedBy(), false)); view.setEquippedBy(getCardViews(c.getEquippedBy(), 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 File

@@ -27,8 +27,8 @@ public class StackItemView implements IIdentifiable {
public StackItemView(SpellAbilityStackInstance si, LocalGameView gameView) { public StackItemView(SpellAbilityStackInstance si, LocalGameView gameView) {
id = si.getId(); id = si.getId();
key = si.getSpellAbility().toUnsuppressedString(); key = si.getSpellAbility(false).toUnsuppressedString();
sourceTrigger = si.getSpellAbility().getSourceTrigger(); sourceTrigger = si.getSpellAbility(false).getSourceTrigger();
text = si.getStackDescription(); text = si.getStackDescription();
source = gameView.getCardView(si.getSourceCard(), true); source = gameView.getCardView(si.getSourceCard(), true);
activatingPlayer = gameView.getPlayerView(si.getActivator(), false); activatingPlayer = gameView.getPlayerView(si.getActivator(), false);

View File

@@ -1,6 +1,5 @@
package forge.view; package forge.view;
import java.util.Collections;
import java.util.List; import java.util.List;
import com.google.common.base.Function; import com.google.common.base.Function;
@@ -53,10 +52,10 @@ public final class ViewUtil {
view.setCounters(c.getCounters()); view.setCounters(c.getCounters());
view.setDamage(c.getDamage()); view.setDamage(c.getDamage());
view.setAssignedDamage(c.getTotalAssignedDamage()); view.setAssignedDamage(c.getTotalAssignedDamage());
view.setRegenerationShields(c.getShield().size()); view.setRegenerationShields(c.getShieldCount());
view.setPreventNextDamage(c.getPreventNextDamageTotalShields()); view.setPreventNextDamage(c.getPreventNextDamageTotalShields());
view.setChosenType(c.getChosenType()); view.setChosenType(c.getChosenType());
view.setChosenColors(c.getChosenColor()); view.setChosenColors(c.getChosenColors());
view.setNamedCard(c.getNamedCard()); view.setNamedCard(c.getNamedCard());
if (c.isSplitCard()) { if (c.isSplitCard()) {
@@ -78,7 +77,7 @@ public final class ViewUtil {
origView.setName(c.getName()); origView.setName(c.getName());
origView.setColors(c.determineColor()); origView.setColors(c.determineColor());
origView.setImageKey(c.getImageKey() ); origView.setImageKey(c.getImageKey() );
origView.setType(Collections.unmodifiableList(c.getType())); origView.setType(c.getType());
origView.setManaCost(c.getManaCost()); origView.setManaCost(c.getManaCost());
origView.setPower(c.getNetAttack()); origView.setPower(c.getNetAttack());
origView.setToughness(c.getNetDefense()); origView.setToughness(c.getNetDefense());
@@ -119,7 +118,7 @@ public final class ViewUtil {
view.setName(chars.getName()); view.setName(chars.getName());
view.setColors(chars.determineColor()); view.setColors(chars.determineColor());
view.setImageKey(chars.getImageKey()); view.setImageKey(chars.getImageKey());
view.setType(Collections.unmodifiableList(chars.getType())); view.setType(chars.getType());
view.setManaCost(chars.getManaCost()); view.setManaCost(chars.getManaCost());
view.setPower(chars.getBaseAttack()); view.setPower(chars.getBaseAttack());
view.setToughness(chars.getBaseDefense()); view.setToughness(chars.getBaseDefense());