Commit 4fe15595 authored by swordshine's avatar swordshine

Merge branch 'push_down_toStringMap_part_1' into 'master'

Push down toStringMap part 1

See merge request !2127
parents 158b1d0f 8a160c88
......@@ -54,6 +54,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.*;
import static forge.util.EnumMapUtil.toStringMap;
/**
* Methods for common actions performed during a game.
*
......@@ -297,7 +299,7 @@ public class GameAction {
repParams.putAll(params);
}
ReplacementResult repres = game.getReplacementHandler().run(EnumMapUtil.toStringMap(repParams));
ReplacementResult repres = game.getReplacementHandler().run(toStringMap(repParams));
if (repres != ReplacementResult.NotReplaced) {
// reset failed manifested Cards back to original
if (c.isManifested()) {
......
......@@ -10,8 +10,9 @@ public enum AbilityKey {
AbilityMana("AbilityMana"),
Activator("Activator"),
Affected("Affected"),
Attach("Attach"),
AllVotes("AllVotes"),
Amount("Amount"),
Attach("Attach"),
AttachSource("AttachSource"),
AttachTarget("AttachTarget"),
Attacked("Attacked"),
......@@ -51,14 +52,12 @@ public enum AbilityKey {
Devoured("Devoured"),
EchoPaid("EchoPaid"),
Exploited("Exploited"),
Explorer("Explorer"),
Event("Event"),
Fighter("Fighter"),
FirstTime("FirstTime"),
Fizzle("Fizzle"),
IsCombatDamage("IsCombatDamage"),
PayingMana("PayingMana"),
Phase("Phase"),
Player("Player"),
IndividualCostPaymentInstance("IndividualCostPaymentInstance"),
IsMadness("IsMadness"),
LifeAmount("LifeAmount"),
......@@ -71,14 +70,23 @@ public enum AbilityKey {
Object("Object"),
Objects("Objects"),
OtherAttackers("OtherAttackers"),
OtherVoters("OtherVoters"),
Origin("Origin"),
OriginalController("OriginalController"),
OriginalDefender("OriginalDefender"),
PayingMana("PayingMana"),
Phase("Phase"),
Player("Player"),
Produced("Produced"),
Result("Result"),
Scheme("Scheme"),
Source("Source"),
Sources("Sources"),
SourceSA("SourceSA"),
SpellAbility("SpellAbility"),
SpellAbilityStackInstance("SpellAbilityStackInstance"),
SpellAbilityTargetingCards("SpellAbilityTargetingCards"),
StackInstance("StackInstance"),
StackSa("StackSa"),
StackSi("StackSi"),
Target("Target"),
......@@ -99,10 +107,204 @@ public enum AbilityKey {
return key;
}
/**
* @param s A string that would be output from toString
* @return the corresponding key if there is one or null otherwise
*/
public static AbilityKey fromString(String s) {
switch (s) {
case "AbilityMana":
return AbilityMana;
case "Activator":
return Activator;
case "Affected":
return Affected;
case "AllVotes":
return AllVotes;
case "Amount":
return Amount;
case "Attach":
return Attach;
case "AttachSource":
return AttachSource;
case "AttachTarget":
return AttachTarget;
case "Attacked":
return Attacked;
case "Attacker":
return Attacker;
case "Attackers":
return Attackers;
case "AttackingPlayer":
return AttackingPlayer;
case "AttackedTarget":
return AttackedTarget;
case "Blocker":
return Blocker;
case "Blockers":
return Blockers;
case "CastSA":
return CastSA;
case "CastSACMC":
return CastSACMC;
case "Card":
return Card;
case "Cards":
return Cards;
case "CardLKI":
return CardLKI;
case "Cause":
return Cause;
case "Causer":
return Causer;
case "Championed":
return Championed;
case "CopySA":
return CopySA;
case "Cost":
return Cost;
case "CostStack":
return CostStack;
case "CounterAmount":
return CounterAmount;
case "CounteredSA":
return CounteredSA;
case "CounterType":
return CounterType;
case "Crew":
return Crew;
case "CumulativeUpkeepPaid":
return CumulativeUpkeepPaid;
case "CurrentCastSpells":
return CurrentCastSpells;
case "CurrentStormCount":
return CurrentStormCount;
case "DamageAmount":
return DamageAmount;
case "DamageSource":
return DamageSource;
case "DamageSources":
return DamageSources;
case "DamageTarget":
return DamageTarget;
case "DamageTargets":
return DamageTargets;
case "Defender":
return Defender;
case "Defenders":
return Defenders;
case "DefendingPlayer":
return DefendingPlayer;
case "Destination":
return Destination;
case "Devoured":
return Devoured;
case "EchoPaid":
return EchoPaid;
case "Exploited":
return Exploited;
case "Explorer":
return Explorer;
case "Event":
return Event;
case "Fighter":
return Fighter;
case "FirstTime":
return FirstTime;
case "Fizzle":
return Fizzle;
case "IsCombatDamage":
return IsCombatDamage;
case "IndividualCostPaymentInstance":
return IndividualCostPaymentInstance;
case "IsMadness":
return IsMadness;
case "LifeAmount":
return LifeAmount;
case "MonstrosityAmount":
return MonstrosityAmount;
case "NewCounterAmount":
return NewCounterAmount;
case "Num":
return Num;
case "NumBlockers":
return NumBlockers;
case "NumThisTurn":
return NumThisTurn;
case "Number":
return Number;
case "Object":
return Object;
case "Objects":
return Objects;
case "OtherAttackers":
return OtherAttackers;
case "OtherVoters":
return OtherVoters;
case "Origin":
return Origin;
case "OriginalController":
return OriginalController;
case "OriginalDefender":
return OriginalDefender;
case "PayingMana":
return PayingMana;
case "Phase":
return Phase;
case "Player":
return Player;
case "Produced":
return Produced;
case "Result":
return Result;
case "Scheme":
return Scheme;
case "Source":
return Source;
case "Sources":
return Sources;
case "SourceSA":
return SourceSA;
case "SpellAbility":
return SpellAbility;
case "SpellAbilityStackInstance":
return SpellAbilityStackInstance;
case "SpellAbilityTargetingCards":
return SpellAbilityTargetingCards;
case "StackInstance":
return StackInstance;
case "StackSa":
return StackSa;
case "StackSi":
return StackSi;
case "Target":
return Target;
case "Targets":
return Targets;
case "Transformer":
return Transformer;
case "Vehicle":
return Vehicle;
case "Won":
return Won;
default:
return null;
}
}
public static <V> EnumMap<AbilityKey, V> newMap() {
return new EnumMap<>(AbilityKey.class);
}
public static <V> EnumMap<AbilityKey, V> newMap(Map<AbilityKey, V> map) {
// The EnumMap constructor throws IllegalArgumentException if the map is empty.
if (map.isEmpty()) {
return newMap();
}
return new EnumMap<>(map);
}
public static Map<AbilityKey, Object> mapFromCard(forge.game.card.Card card) {
final Map<AbilityKey, Object> runParams = newMap();
......
......@@ -139,13 +139,15 @@ public class AbilityUtils {
final SpellAbility root = sa.getRootAbility();
if (defined.contains("LKICopy")) { //Triggered*LKICopy
int lkiPosition = defined.indexOf("LKICopy");
final Object crd = root.getTriggeringObject(defined.substring(9, lkiPosition));
AbilityKey type = AbilityKey.fromString(defined.substring(9, lkiPosition));
final Object crd = root.getTriggeringObject(type);
if (crd instanceof Card) {
c = (Card) crd;
}
}
else {
final Object crd = root.getTriggeringObject(defined.substring(9));
AbilityKey type = AbilityKey.fromString(defined.substring(9));
final Object crd = root.getTriggeringObject(type);
if (crd instanceof Card) {
c = game.getCardState((Card) crd);
} else if (crd instanceof Iterable) {
......@@ -641,12 +643,12 @@ public class AbilityUtils {
}
if (calcX[0].startsWith("TriggeredPlayer") || calcX[0].startsWith("TriggeredTarget")) {
final SpellAbility root = sa.getRootAbility();
Object o = root.getTriggeringObject(calcX[0].substring(9));
Object o = root.getTriggeringObject(AbilityKey.fromString(calcX[0].substring(9)));
return o instanceof Player ? CardFactoryUtil.playerXProperty((Player) o, calcX[1], card) * multiplier : 0;
}
if (calcX[0].equals("TriggeredSpellAbility")) {
final SpellAbility root = sa.getRootAbility();
SpellAbility sat = (SpellAbility) root.getTriggeringObject("SpellAbility");
SpellAbility sat = (SpellAbility) root.getTriggeringObject(AbilityKey.SpellAbility);
return calculateAmount(sat.getHostCard(), calcX[1], sat);
}
// Added on 9/30/12 (ArsenalNut) - Ended up not using but might be useful in future
......@@ -695,11 +697,11 @@ public class AbilityUtils {
}
else if (calcX[0].startsWith("TriggerObjects")) {
final SpellAbility root = sa.getRootAbility();
list = (CardCollection) root.getTriggeringObject(calcX[0].substring(14));
list = (CardCollection) root.getTriggeringObject(AbilityKey.fromString(calcX[0].substring(14)));
}
else if (calcX[0].startsWith("Triggered")) {
final SpellAbility root = sa.getRootAbility();
list = new CardCollection((Card) root.getTriggeringObject(calcX[0].substring(9)));
list = new CardCollection((Card) root.getTriggeringObject(AbilityKey.fromString(calcX[0].substring(9))));
}
else if (calcX[0].startsWith("TriggerCount")) {
// TriggerCount is similar to a regular Count, but just
......@@ -707,7 +709,7 @@ public class AbilityUtils {
final SpellAbility root = sa.getRootAbility();
final String[] l = calcX[1].split("/");
final String m = CardFactoryUtil.extractOperators(calcX[1]);
final int count = (Integer) root.getTriggeringObject(l[0]);
final int count = (Integer) root.getTriggeringObject(AbilityKey.fromString(l[0]));
return CardFactoryUtil.doXMath(count, m, card) * multiplier;
}
......@@ -777,19 +779,19 @@ public class AbilityUtils {
final Object o;
if (type.startsWith("Triggered")) {
if (type.contains("Card")) {
o = sa.getTriggeringObject("Card");
o = sa.getTriggeringObject(AbilityKey.Card);
}
else if (type.contains("Object")) {
o = sa.getTriggeringObject("Object");
o = sa.getTriggeringObject(AbilityKey.Object);
}
else if (type.contains("Attacker")) {
o = sa.getTriggeringObject("Attacker");
o = sa.getTriggeringObject(AbilityKey.Attacker);
}
else if (type.contains("Blocker")) {
o = sa.getTriggeringObject("Blocker");
o = sa.getTriggeringObject(AbilityKey.Blocker);
}
else {
o = sa.getTriggeringObject("Card");
o = sa.getTriggeringObject(AbilityKey.Card);
}
if (!(o instanceof Card)) {
......@@ -1004,7 +1006,7 @@ public class AbilityUtils {
if (defParsed.endsWith("Controller")) {
String triggeringType = defParsed.substring(9);
triggeringType = triggeringType.substring(0, triggeringType.length() - 10);
final Object c = root.getTriggeringObject(triggeringType);
final Object c = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
if (c instanceof Card) {
o = ((Card) c).getController();
}
......@@ -1015,7 +1017,7 @@ public class AbilityUtils {
else if (defParsed.endsWith("Opponent")) {
String triggeringType = defParsed.substring(9);
triggeringType = triggeringType.substring(0, triggeringType.length() - 8);
final Object c = root.getTriggeringObject(triggeringType);
final Object c = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
if (c instanceof Card) {
o = ((Card) c).getController().getOpponents();
}
......@@ -1026,14 +1028,14 @@ public class AbilityUtils {
else if (defParsed.endsWith("Owner")) {
String triggeringType = defParsed.substring(9);
triggeringType = triggeringType.substring(0, triggeringType.length() - 5);
final Object c = root.getTriggeringObject(triggeringType);
final Object c = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
if (c instanceof Card) {
o = ((Card) c).getOwner();
}
}
else {
final String triggeringType = defParsed.substring(9);
o = root.getTriggeringObject(triggeringType);
o = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
}
if (o != null) {
if (o instanceof Player) {
......@@ -1252,13 +1254,13 @@ public class AbilityUtils {
final SpellAbility root = sa.getRootAbility();
final String triggeringType = defined.substring(9);
final Object o = root.getTriggeringObject(triggeringType);
final Object o = root.getTriggeringObject(AbilityKey.fromString(triggeringType));
if (o instanceof SpellAbility) {
s = (SpellAbility) o;
// if there is no target information in SA but targets are listed in SpellAbilityTargeting cards, copy that
// information so it's not lost if the calling code is interested in targets of the triggered SA.
if (triggeringType.equals("SpellAbility")) {
final CardCollectionView tgtList = (CardCollectionView)root.getTriggeringObject("SpellAbilityTargetingCards");
final CardCollectionView tgtList = (CardCollectionView)root.getTriggeringObject(AbilityKey.SpellAbilityTargetingCards);
if (s.getTargets() != null && s.getTargets().getNumTargeted() == 0) {
if (tgtList != null && tgtList.size() > 0) {
TargetChoices tc = new TargetChoices();
......@@ -1390,7 +1392,7 @@ public class AbilityUtils {
cost = new Cost(source.getManaCost(), true);
}
else if (unlessCost.equals("TriggeredSpellManaCost")) {
SpellAbility triggered = (SpellAbility) sa.getRootAbility().getTriggeringObject("SpellAbility");
SpellAbility triggered = (SpellAbility) sa.getRootAbility().getTriggeringObject(AbilityKey.SpellAbility);
Card triggeredCard = triggered.getHostCard();
if (triggeredCard.getManaCost() == null) {
cost = new Cost(ManaCost.ZERO, true);
......@@ -1608,7 +1610,7 @@ public class AbilityUtils {
// Count$TriggeredPayingMana.<Color1>.<Color2>
if (sq[0].startsWith("TriggeredPayingMana")) {
final SpellAbility root = sa.getRootAbility();
String mana = (String) root.getTriggeringObject("PayingMana");
String mana = (String) root.getTriggeringObject(AbilityKey.PayingMana);
int count = 0;
Matcher mat = Pattern.compile(StringUtils.join(sq, "|", 1, sq.length)).matcher(mana);
while (mat.find()) {
......
......@@ -2,6 +2,7 @@ package forge.game.ability.effects;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.combat.AttackingBand;
......@@ -54,12 +55,12 @@ public class ChangeCombatantsEffect extends SpellAbilityEffect {
// retarget triggers to the new defender (e.g. Ulamog, Ceaseless Hunger + Portal Mage)
for (SpellAbilityStackInstance si : game.getStack()) {
if (si.isTrigger() && c.equals(si.getSourceCard())
&& si.getTriggeringObject("Attacker") != null) {
si.addTriggeringObject("OriginalDefender", originalDefender);
&& si.getTriggeringObject(AbilityKey.Attacker) != null) {
si.addTriggeringObject(AbilityKey.OriginalDefender, originalDefender);
if (defender instanceof Player) {
si.updateTriggeringObject("DefendingPlayer", defender);
si.updateTriggeringObject(AbilityKey.DefendingPlayer, defender);
} else if (defender instanceof Card) {
si.updateTriggeringObject("DefendingPlayer", ((Card)defender).getController());
si.updateTriggeringObject(AbilityKey.DefendingPlayer, ((Card)defender).getController());
}
}
}
......
......@@ -1048,7 +1048,7 @@ public class Card extends GameEntity implements Comparable<Card> {
}
}
public final Object getTriggeringObject(final String typeIn) {
public final Object getTriggeringObject(final AbilityKey typeIn) {
Object triggered = null;
if (!currentState.getTriggers().isEmpty()) {
for (final Trigger t : currentState.getTriggers()) {
......
......@@ -35,6 +35,7 @@ import forge.game.GameEntity;
import forge.game.GameEntityCounterTable;
import forge.game.GameLogEntryType;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.CardPredicates.Presets;
......@@ -948,7 +949,7 @@ public class CardFactoryUtil {
// TriggeringObjects
if (sq[0].startsWith("Triggered")) {
return doXMath(xCount((Card) c.getTriggeringObject("Card"), sq[0].substring(9)), m, c);
return doXMath(xCount((Card) c.getTriggeringObject(AbilityKey.Card), sq[0].substring(9)), m, c);
}
if (sq[0].contains("YourStartingLife")) {
......
......@@ -6,6 +6,7 @@ import forge.card.MagicColor;
import forge.game.Direction;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.card.CardPredicates.Presets;
import forge.game.combat.AttackingBand;
......@@ -874,7 +875,7 @@ public class CardProperty {
}
return false;
case "TriggeredCard":
final Object triggeringObject = source.getTriggeringObject(restriction.substring("Triggered".length()));
final Object triggeringObject = source.getTriggeringObject(AbilityKey.fromString(restriction.substring("Triggered".length())));
if (!(triggeringObject instanceof Card)) {
return false;
}
......@@ -957,7 +958,7 @@ public class CardProperty {
if (spellAbility == null) {
System.out.println("Looking at TriggeredCard but no SA?");
} else {
Card triggeredCard = ((Card)spellAbility.getTriggeringObject("Card"));
Card triggeredCard = ((Card) spellAbility.getTriggeringObject(AbilityKey.Card));
if (triggeredCard != null && card.sharesNameWith(triggeredCard)) {
return true;
}
......
......@@ -25,6 +25,7 @@ import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.GameObject;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.player.Player;
......@@ -412,7 +413,7 @@ public final class CardUtil {
}
} else if (reflectProperty.equals("Produced")) {
// Why is this name so similar to the one below?
final String producedColors = abMana instanceof AbilitySub ? (String) abMana.getRootAbility().getTriggeringObject("Produced") : (String) abMana.getTriggeringObject("Produced");
final String producedColors = abMana instanceof AbilitySub ? (String) abMana.getRootAbility().getTriggeringObject(AbilityKey.Produced) : (String) abMana.getTriggeringObject(AbilityKey.Produced);
for (final String col : MagicColor.Constant.ONLY_COLORS) {
final String s = MagicColor.toShortString(col);
if (producedColors.contains(s)) {
......
......@@ -546,13 +546,13 @@ public class Combat {
Game game = c.getGame();
for (SpellAbilityStackInstance si : game.getStack()) {
if (si.isTrigger() && c.equals(si.getSourceCard())) {
GameEntity origDefender = (GameEntity)si.getTriggeringObject("OriginalDefender");
GameEntity origDefender = (GameEntity)si.getTriggeringObject(AbilityKey.OriginalDefender);
if (origDefender != null) {
si.updateTriggeringObject("Defender", origDefender);
si.updateTriggeringObject(AbilityKey.Defender, origDefender);
if (origDefender instanceof Player) {
si.updateTriggeringObject("DefendingPlayer", origDefender);
si.updateTriggeringObject(AbilityKey.DefendingPlayer, origDefender);
} else if (origDefender instanceof Card) {
si.updateTriggeringObject("DefendingPlayer", ((Card)origDefender).getController());
si.updateTriggeringObject(AbilityKey.DefendingPlayer, ((Card)origDefender).getController());
}
}
}
......
......@@ -24,6 +24,7 @@ import com.google.common.collect.Maps;
import forge.card.mana.ManaCost;
import forge.game.*;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.Card;
......@@ -138,7 +139,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
private HashMap<String, CardCollection> paidLists = Maps.newHashMap();
private Map<String, Object> triggeringObjects = Maps.newHashMap();
private EnumMap<AbilityKey, Object> triggeringObjects = AbilityKey.newMap();
private HashMap<String, Object> replacingObjects = Maps.newHashMap();
......@@ -552,23 +553,23 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
return sa;
}
public Map<String, Object> getTriggeringObjects() {
public Map<AbilityKey, Object> getTriggeringObjects() {
return triggeringObjects;
}
public void setTriggeringObjects(final Map<String, Object> triggeredObjects) {
triggeringObjects = Maps.newHashMap(triggeredObjects);
public void setTriggeringObjects(final Map<AbilityKey, Object> triggeredObjects) {
triggeringObjects = AbilityKey.newMap(triggeredObjects);
}
public Object getTriggeringObject(final String type) {
public Object getTriggeringObject(final AbilityKey type) {
return triggeringObjects.get(type);
}
public void setTriggeringObject(final String type, final Object o) {
public void setTriggeringObject(final AbilityKey type, final Object o) {
triggeringObjects.put(type, o);
}
public boolean hasTriggeringObject(final String type) {
public boolean hasTriggeringObject(final AbilityKey type) {
return triggeringObjects.containsKey(type);
}
public void resetTriggeringObjects() {
triggeringObjects = Maps.newHashMap();
triggeringObjects = AbilityKey.newMap();
}
public List<Object> getTriggerRemembered() {
......@@ -877,7 +878,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
clone.originalMapParams = Maps.newHashMap(this.originalMapParams);
clone.mapParams = Maps.newHashMap(this.mapParams);
clone.triggeringObjects = Maps.newHashMap(this.triggeringObjects);
clone.triggeringObjects = AbilityKey.newMap(this.triggeringObjects);
if (getPayCosts() != null) {
clone.setPayCosts(getPayCosts().copy());
......
......@@ -92,7 +92,7 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
// is Kicked, is Buyback
// Triggers
private final Map<String, Object> triggeringObjects;
private final Map<AbilityKey, Object> triggeringObjects;
private final List<Object> triggerRemembered;
private final Map<String, String> storedSVars = Maps.newHashMap();
......@@ -364,7 +364,7 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
}
}
public boolean addTriggeringObject(String trigObj, Object value) {
public boolean addTriggeringObject(AbilityKey trigObj, Object value) {
if (!triggeringObjects.containsKey(trigObj)) {
triggeringObjects.put(trigObj, value);
return true;
......@@ -372,7 +372,7 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
return false;
}
public boolean updateTriggeringObject(String trigObj, Object value) {
public boolean updateTriggeringObject(AbilityKey trigObj, Object value) {
if (triggeringObjects.containsKey(trigObj)) {
triggeringObjects.replace(trigObj, value);
return true;
......@@ -380,7 +380,7 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView {
return false;
}
public Object getTriggeringObject(String trigObj) {
public Object getTriggeringObject(AbilityKey trigObj) {
if (triggeringObjects.containsKey(trigObj)) {
return triggeringObjects.get(trigObj);
}
......
......@@ -21,6 +21,7 @@ import forge.game.Game;
import forge.game.GameEntity;
import forge.game.TriggerReplacementBase;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.ApiType;
import forge.game.ability.effects.CharmEffect;
import forge.game.card.Card;
......@@ -36,7 +37,6 @@ import forge.game.zone.ZoneType;
import java.util.*;
import com.google.common.collect.Lists;
import com.g