Merge branch 'start_replacement_run_keys_refactor' into 'master'

Start replacement run keys refactor

See merge request core-developers/forge!2175
This commit is contained in:
swordshine
2019-10-06 06:22:54 +00:00
45 changed files with 382 additions and 370 deletions

View File

@@ -2079,8 +2079,7 @@ public class AiController {
return true; return true;
} }
public ReplacementEffect chooseSingleReplacementEffect(List<ReplacementEffect> list, public ReplacementEffect chooseSingleReplacementEffect(List<ReplacementEffect> list) {
Map<String, Object> runParams) {
// no need to choose anything // no need to choose anything
if (list.size() <= 1) { if (list.size() <= 1) {
return Iterables.getFirst(list, null); return Iterables.getFirst(list, null);

View File

@@ -29,6 +29,7 @@ import forge.card.MagicColor;
import forge.card.mana.ManaCostShard; import forge.card.mana.ManaCostShard;
import forge.game.*; import forge.game.*;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.ability.effects.CharmEffect; import forge.game.ability.effects.CharmEffect;
@@ -2849,10 +2850,9 @@ public class ComputerUtil {
} }
// Run any applicable replacement effects. // Run any applicable replacement effects.
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(player);
repParams.put("Affected", player); repParams.put(AbilityKey.LifeGained, 1);
repParams.put("LifeGained", 1); repParams.put(AbilityKey.Source, source);
repParams.put("Source", source);
List<ReplacementEffect> list = player.getGame().getReplacementHandler().getReplacementList( List<ReplacementEffect> list = player.getGame().getReplacementHandler().getReplacementList(
ReplacementType.GainLife, ReplacementType.GainLife,
@@ -2880,15 +2880,15 @@ public class ComputerUtil {
} }
// Run any applicable replacement effects. // Run any applicable replacement effects.
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(player);
repParams.put("Affected", player); repParams.put(AbilityKey.LifeGained, n);
repParams.put("LifeGained", n); repParams.put(AbilityKey.Source, source);
repParams.put("Source", source);
List<ReplacementEffect> list = player.getGame().getReplacementHandler().getReplacementList( List<ReplacementEffect> list = player.getGame().getReplacementHandler().getReplacementList(
ReplacementType.GainLife, ReplacementType.GainLife,
repParams, repParams,
ReplacementLayer.Other); ReplacementLayer.Other
);
if (Iterables.any(list, CardTraitPredicates.hasParam("AiLogic", "NoLife"))) { if (Iterables.any(list, CardTraitPredicates.hasParam("AiLogic", "NoLife"))) {
// no life gain is not negative // no life gain is not negative

View File

@@ -29,6 +29,7 @@ import forge.game.CardTraitBase;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.card.*; import forge.game.card.*;
@@ -2580,13 +2581,11 @@ public class ComputerUtilCombat {
final Game game = attacker.getGame(); final Game game = attacker.getGame();
// first try to replace the damage // first try to replace the damage
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(target);
repParams.put("Affected", target); repParams.put(AbilityKey.DamageSource, attacker);
repParams.put("DamageSource", attacker); repParams.put(AbilityKey.DamageAmount, damage);
repParams.put("DamageAmount", damage); repParams.put(AbilityKey.IsCombat, true);
repParams.put("IsCombat", true); repParams.put(AbilityKey.Prevention, true);
repParams.put("Prevention", true);
// repParams.put("PreventMap", preventMap);
List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList( List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList(
ReplacementType.DamageDone, repParams, ReplacementLayer.Other); ReplacementType.DamageDone, repParams, ReplacementLayer.Other);

View File

@@ -13,6 +13,7 @@ import forge.card.mana.ManaCostParser;
import forge.card.mana.ManaCostShard; import forge.card.mana.ManaCostShard;
import forge.game.Game; import forge.game.Game;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.card.*; import forge.game.card.*;
@@ -1408,11 +1409,11 @@ public class ComputerUtilMana {
AbilityManaPart mp = m.getManaPart(); AbilityManaPart mp = m.getManaPart();
// setup produce mana replacement effects // setup produce mana replacement effects
final Map<String, Object> repParams = new HashMap<>(); final Map<AbilityKey, Object> repParams = AbilityKey.newMap();
repParams.put("Mana", mp.getOrigProduced()); repParams.put(AbilityKey.Mana, mp.getOrigProduced());
repParams.put("Affected", sourceCard); repParams.put(AbilityKey.Affected, sourceCard);
repParams.put("Player", ai); repParams.put(AbilityKey.Player, ai);
repParams.put("AbilityMana", m); repParams.put(AbilityKey.AbilityMana, m);
for (final ReplacementEffect replacementEffect : replacementEffects) { for (final ReplacementEffect replacementEffect : replacementEffects) {
if (replacementEffect.canReplace(repParams)) { if (replacementEffect.canReplace(repParams)) {

View File

@@ -866,8 +866,8 @@ public class PlayerControllerAi extends PlayerController {
} }
@Override @Override
public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers, Map<String, Object> runParams) { public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers) {
return brains.chooseSingleReplacementEffect(possibleReplacers, runParams); return brains.chooseSingleReplacementEffect(possibleReplacers);
} }
@Override @Override

View File

@@ -10,6 +10,7 @@ import forge.card.MagicColor;
import forge.game.Game; import forge.game.Game;
import forge.game.GameObject; import forge.game.GameObject;
import forge.game.GlobalRuleChange; import forge.game.GlobalRuleChange;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
import forge.game.card.*; import forge.game.card.*;
@@ -1789,8 +1790,8 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
public boolean doReturnCommanderLogic(SpellAbility sa, Player aiPlayer) { public boolean doReturnCommanderLogic(SpellAbility sa, Player aiPlayer) {
Map<String, Object> originalParams = (Map<String, Object>)sa.getReplacingObject("OriginalParams"); Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>)sa.getReplacingObject(AbilityKey.OriginalParams);
SpellAbility causeSa = (SpellAbility)originalParams.get("Cause"); SpellAbility causeSa = (SpellAbility)originalParams.get(AbilityKey.Cause);
SpellAbility causeSub = null; SpellAbility causeSub = null;
// Squee, the Immortal: easier to recast it (the call below has to be "contains" since SA is an intrinsic effect) // Squee, the Immortal: easier to recast it (the call below has to be "contains" since SA is an intrinsic effect)
@@ -1813,7 +1814,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
// A blink effect implemented using a delayed trigger // A blink effect implemented using a delayed trigger
return !"Exile".equals(exec.getParam("Origin")) || !"Battlefield".equals(exec.getParam("Destination")); return !"Exile".equals(exec.getParam("Origin")) || !"Battlefield".equals(exec.getParam("Destination"));
} }
} else return causeSa.getHostCard() == null || !causeSa.getHostCard().equals(sa.getReplacingObject("Card")) } else return causeSa.getHostCard() == null || !causeSa.getHostCard().equals(sa.getReplacingObject(AbilityKey.Card))
|| !causeSa.getActivatingPlayer().equals(aiPlayer); || !causeSa.getActivatingPlayer().equals(aiPlayer);
} }

View File

@@ -2,12 +2,12 @@ package forge.ai.ability;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import forge.ai.ComputerUtil; import forge.ai.ComputerUtil;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilMana; import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView; import forge.game.card.CardCollectionView;
@@ -97,11 +97,10 @@ public class ManifestAi extends SpellAbilityAi {
topCopy.turnFaceDownNoUpdate(); topCopy.turnFaceDownNoUpdate();
topCopy.setManifested(true); topCopy.setManifested(true);
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(topCopy);
repParams.put("Affected", topCopy); repParams.put(AbilityKey.Origin, card.getZone().getZoneType());
repParams.put("Origin", card.getZone().getZoneType()); repParams.put(AbilityKey.Destination, ZoneType.Battlefield);
repParams.put("Destination", ZoneType.Battlefield); repParams.put(AbilityKey.Source, sa.getHostCard());
repParams.put("Source", sa.getHostCard());
List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList(ReplacementType.Moved, repParams, ReplacementLayer.Other); List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList(ReplacementType.Moved, repParams, ReplacementLayer.Other);
if (!list.isEmpty()) { if (!list.isEmpty()) {
return false; return false;

View File

@@ -55,8 +55,6 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.*; import java.util.*;
import static forge.util.EnumMapUtil.toStringMap;
/** /**
* Methods for common actions performed during a game. * Methods for common actions performed during a game.
* *
@@ -292,8 +290,7 @@ public class GameAction {
copied.getOwner().addInboundToken(copied); copied.getOwner().addInboundToken(copied);
} }
Map<AbilityKey, Object> repParams = AbilityKey.newMap(); Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(copied);
repParams.put(AbilityKey.Affected, copied);
repParams.put(AbilityKey.CardLKI, lastKnownInfo); repParams.put(AbilityKey.CardLKI, lastKnownInfo);
repParams.put(AbilityKey.Cause, cause); repParams.put(AbilityKey.Cause, cause);
repParams.put(AbilityKey.Origin, zoneFrom != null ? zoneFrom.getZoneType() : null); repParams.put(AbilityKey.Origin, zoneFrom != null ? zoneFrom.getZoneType() : null);
@@ -303,7 +300,7 @@ public class GameAction {
repParams.putAll(params); repParams.putAll(params);
} }
ReplacementResult repres = game.getReplacementHandler().run(ReplacementType.Moved, toStringMap(repParams)); ReplacementResult repres = game.getReplacementHandler().run(ReplacementType.Moved, repParams);
if (repres != ReplacementResult.NotReplaced) { if (repres != ReplacementResult.NotReplaced) {
// reset failed manifested Cards back to original // reset failed manifested Cards back to original
if (c.isManifested()) { if (c.isManifested()) {
@@ -1389,11 +1386,10 @@ public class GameAction {
} }
// Replacement effects // Replacement effects
final Map<String, Object> repRunParams = Maps.newHashMap(); final Map<AbilityKey, Object> repRunParams = AbilityKey.mapFromCard(c);
repRunParams.put("Source", sa); repRunParams.put(AbilityKey.Source, sa);
repRunParams.put("Card", c); repRunParams.put(AbilityKey.Affected, c);
repRunParams.put("Affected", c); repRunParams.put(AbilityKey.Regeneration, regenerate);
repRunParams.put("Regeneration", regenerate);
if (game.getReplacementHandler().run(ReplacementType.Destroy, repRunParams) != ReplacementResult.NotReplaced) { if (game.getReplacementHandler().run(ReplacementType.Destroy, repRunParams) != ReplacementResult.NotReplaced) {
return false; return false;

View File

@@ -115,25 +115,24 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
public int replaceDamage(final int damage, final Card source, final boolean isCombat, final boolean prevention, public int replaceDamage(final int damage, final Card source, final boolean isCombat, final boolean prevention,
final CardDamageMap damageMap, final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) { final CardDamageMap damageMap, final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) {
// Replacement effects // Replacement effects
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
repParams.put("Affected", this); repParams.put(AbilityKey.DamageSource, source);
repParams.put("DamageSource", source); repParams.put(AbilityKey.DamageAmount, damage);
repParams.put("DamageAmount", damage); repParams.put(AbilityKey.IsCombat, isCombat);
repParams.put("IsCombat", isCombat); repParams.put(AbilityKey.NoPreventDamage, !prevention);
repParams.put("NoPreventDamage", !prevention); repParams.put(AbilityKey.DamageMap, damageMap);
repParams.put("DamageMap", damageMap); repParams.put(AbilityKey.PreventMap, preventMap);
repParams.put("PreventMap", preventMap); repParams.put(AbilityKey.CounterTable, counterTable);
repParams.put("CounterTable", counterTable);
if (cause != null) { if (cause != null) {
repParams.put("Cause", cause); repParams.put(AbilityKey.Cause, cause);
} }
switch (getGame().getReplacementHandler().run(ReplacementType.DamageDone, repParams)) { switch (getGame().getReplacementHandler().run(ReplacementType.DamageDone, repParams)) {
case NotReplaced: case NotReplaced:
return damage; return damage;
case Updated: case Updated:
int newDamage = (int) repParams.get("DamageAmount"); int newDamage = (int) repParams.get(AbilityKey.DamageAmount);
GameEntity newTarget = (GameEntity) repParams.get("Affected"); GameEntity newTarget = (GameEntity) repParams.get(AbilityKey.Affected);
// check if this is still the affected card or player // check if this is still the affected card or player
if (this.equals(newTarget)) { if (this.equals(newTarget)) {
return newDamage; return newDamage;
@@ -169,15 +168,14 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
int restDamage = damage; int restDamage = damage;
// first try to replace the damage // first try to replace the damage
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
repParams.put("Affected", this); repParams.put(AbilityKey.DamageSource, source);
repParams.put("DamageSource", source); repParams.put(AbilityKey.DamageAmount, damage);
repParams.put("DamageAmount", damage); repParams.put(AbilityKey.IsCombat, isCombat);
repParams.put("IsCombat", isCombat); repParams.put(AbilityKey.Prevention, true);
repParams.put("Prevention", true); repParams.put(AbilityKey.PreventMap, preventMap);
repParams.put("PreventMap", preventMap);
if (cause != null) { if (cause != null) {
repParams.put("Cause", cause); repParams.put(AbilityKey.Cause, cause);
} }
switch (getGame().getReplacementHandler().run(ReplacementType.DamageDone, repParams)) { switch (getGame().getReplacementHandler().run(ReplacementType.DamageDone, repParams)) {
@@ -185,7 +183,7 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
restDamage = damage; restDamage = damage;
break; break;
case Updated: case Updated:
restDamage = (int) repParams.get("DamageAmount"); restDamage = (int) repParams.get(AbilityKey.DamageAmount);
break; break;
default: default:
restDamage = 0; restDamage = 0;

View File

@@ -3,6 +3,7 @@ package forge.game.ability;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
import forge.game.GameEntity;
import forge.game.card.Card; import forge.game.card.Card;
/** /**
@@ -37,12 +38,15 @@ public enum AbilityKey {
CostStack("CostStack"), CostStack("CostStack"),
CounterAmount("CounterAmount"), CounterAmount("CounterAmount"),
CounteredSA("CounteredSA"), CounteredSA("CounteredSA"),
CounterNum("CounterNum"),
CounterTable("CounterTable"),
CounterType("CounterType"), CounterType("CounterType"),
Crew("Crew"), Crew("Crew"),
CumulativeUpkeepPaid("CumulativeUpkeepPaid"), CumulativeUpkeepPaid("CumulativeUpkeepPaid"),
CurrentCastSpells("CurrentCastSpells"), CurrentCastSpells("CurrentCastSpells"),
CurrentStormCount("CurrentStormCount"), CurrentStormCount("CurrentStormCount"),
DamageAmount("DamageAmount"), DamageAmount("DamageAmount"),
DamageMap("DamageMap"),
DamageSource("DamageSource"), DamageSource("DamageSource"),
DamageSources("DamageSources"), DamageSources("DamageSources"),
DamageTarget("DamageTarget"), DamageTarget("DamageTarget"),
@@ -53,18 +57,23 @@ public enum AbilityKey {
Destination("Destination"), Destination("Destination"),
Devoured("Devoured"), Devoured("Devoured"),
EchoPaid("EchoPaid"), EchoPaid("EchoPaid"),
EffectOnly("EffectOnly"),
Exploited("Exploited"), Exploited("Exploited"),
Explorer("Explorer"), Explorer("Explorer"),
Event("Event"), Event("Event"),
Fighter("Fighter"), Fighter("Fighter"),
FirstTime("FirstTime"), FirstTime("FirstTime"),
Fizzle("Fizzle"), Fizzle("Fizzle"),
IsCombat("IsCombat"), // TODO confirm that this and IsCombatDamage can be merged
IsCombatDamage("IsCombatDamage"), IsCombatDamage("IsCombatDamage"),
IndividualCostPaymentInstance("IndividualCostPaymentInstance"), IndividualCostPaymentInstance("IndividualCostPaymentInstance"),
IsMadness("IsMadness"), IsMadness("IsMadness"),
LifeAmount("LifeAmount"), LifeAmount("LifeAmount"), //TODO confirm that this and LifeGained can be merged
LifeGained("LifeGained"),
Mana("Mana"),
MonstrosityAmount("MonstrosityAmount"), MonstrosityAmount("MonstrosityAmount"),
NewCounterAmount("NewCounterAmount"), NewCounterAmount("NewCounterAmount"),
NoPreventDamage("NoPreventDamage"),
Num("Num"), // TODO confirm that this and NumThisTurn can be merged Num("Num"), // TODO confirm that this and NumThisTurn can be merged
NumBlockers("NumBlockers"), NumBlockers("NumBlockers"),
NumThisTurn("NumThisTurn"), NumThisTurn("NumThisTurn"),
@@ -76,10 +85,15 @@ public enum AbilityKey {
Origin("Origin"), Origin("Origin"),
OriginalController("OriginalController"), OriginalController("OriginalController"),
OriginalDefender("OriginalDefender"), OriginalDefender("OriginalDefender"),
OriginalParams("OriginalParams"),
PayingMana("PayingMana"), PayingMana("PayingMana"),
Phase("Phase"), Phase("Phase"),
Player("Player"), Player("Player"),
PreventMap("PreventMap"),
Prevention("Prevention"),
Produced("Produced"), Produced("Produced"),
Regeneration("Regeneration"),
ReplacementResult("ReplacementResult"),
Result("Result"), Result("Result"),
Scheme("Scheme"), Scheme("Scheme"),
Source("Source"), Source("Source"),
@@ -91,8 +105,12 @@ public enum AbilityKey {
StackInstance("StackInstance"), StackInstance("StackInstance"),
StackSa("StackSa"), StackSa("StackSa"),
StackSi("StackSi"), StackSi("StackSi"),
SurveilNum("SurveilNum"),
Target("Target"), Target("Target"),
Targets("Targets"), Targets("Targets"),
TgtSA("TgtSA"),
Token("Token"),
TokenNum("TokenNum"),
Transformer("Transformer"), Transformer("Transformer"),
Vehicle("Vehicle"), Vehicle("Vehicle"),
Won("Won"); Won("Won");
@@ -141,4 +159,11 @@ public enum AbilityKey {
runParams.put(Card, card); runParams.put(Card, card);
return runParams; return runParams;
} }
public static Map<AbilityKey, Object> mapFromAffected(GameEntity gameEntity) {
final Map<AbilityKey, Object> runParams = newMap();
runParams.put(Affected, gameEntity);
return runParams;
}
} }

View File

@@ -48,7 +48,7 @@ public class AbilityUtils {
public static CounterType getCounterType(String name, SpellAbility sa) throws Exception { public static CounterType getCounterType(String name, SpellAbility sa) throws Exception {
CounterType counterType; CounterType counterType;
if ("ReplacedCounterType".equals(name)) { if ("ReplacedCounterType".equals(name)) {
name = (String) sa.getReplacingObject("CounterType"); name = (String) sa.getReplacingObject(AbilityKey.CounterType);
} }
try { try {
counterType = CounterType.getType(name); counterType = CounterType.getType(name);
@@ -157,7 +157,9 @@ 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)); AbilityKey type = AbilityKey.fromString(defined.substring(8));
final Object crd = root.getReplacingObject(type);
if (crd instanceof Card) { if (crd instanceof Card) {
c = game.getCardState((Card) crd); c = game.getCardState((Card) crd);
} else if (crd instanceof List<?>) { } else if (crd instanceof List<?>) {
@@ -712,7 +714,7 @@ public class AbilityUtils {
} }
else if (calcX[0].startsWith("Replaced")) { else if (calcX[0].startsWith("Replaced")) {
final SpellAbility root = sa.getRootAbility(); final SpellAbility root = sa.getRootAbility();
list = new CardCollection((Card) root.getReplacingObject(calcX[0].substring(8))); list = new CardCollection((Card) root.getReplacingObject(AbilityKey.fromString(calcX[0].substring(8))));
} }
else if (calcX[0].startsWith("ReplaceCount")) { else if (calcX[0].startsWith("ReplaceCount")) {
// ReplaceCount is similar to a regular Count, but just // ReplaceCount is similar to a regular Count, but just
@@ -720,7 +722,7 @@ public class AbilityUtils {
final SpellAbility root = sa.getRootAbility(); final SpellAbility root = sa.getRootAbility();
final String[] l = calcX[1].split("/"); final String[] l = calcX[1].split("/");
final String m = CardFactoryUtil.extractOperators(calcX[1]); final String m = CardFactoryUtil.extractOperators(calcX[1]);
final int count = (Integer) root.getReplacingObject(l[0]); final int count = (Integer) root.getReplacingObject(AbilityKey.fromString(l[0]));
return CardFactoryUtil.doXMath(count, m, card) * multiplier; return CardFactoryUtil.doXMath(count, m, card) * multiplier;
} }
@@ -1063,7 +1065,7 @@ public class AbilityUtils {
if (defined.endsWith("Controller")) { if (defined.endsWith("Controller")) {
String replacingType = defined.substring(8); String replacingType = defined.substring(8);
replacingType = replacingType.substring(0, replacingType.length() - 10); replacingType = replacingType.substring(0, replacingType.length() - 10);
final Object c = root.getReplacingObject(replacingType); final Object c = root.getReplacingObject(AbilityKey.fromString(replacingType));
if (c instanceof Card) { if (c instanceof Card) {
o = ((Card) c).getController(); o = ((Card) c).getController();
} }
@@ -1074,14 +1076,14 @@ public class AbilityUtils {
else if (defined.endsWith("Owner")) { else if (defined.endsWith("Owner")) {
String replacingType = defined.substring(8); String replacingType = defined.substring(8);
replacingType = replacingType.substring(0, replacingType.length() - 5); replacingType = replacingType.substring(0, replacingType.length() - 5);
final Object c = root.getReplacingObject(replacingType); final Object c = root.getReplacingObject(AbilityKey.fromString(replacingType));
if (c instanceof Card) { if (c instanceof Card) {
o = ((Card) c).getOwner(); o = ((Card) c).getOwner();
} }
} }
else { else {
final String replacingType = defined.substring(8); final String replacingType = defined.substring(8);
o = root.getReplacingObject(replacingType); o = root.getReplacingObject(AbilityKey.fromString(replacingType));
} }
if (o != null) { if (o != null) {
if (o instanceof Player) { if (o instanceof Player) {

View File

@@ -18,7 +18,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class CounterEffect extends SpellAbilityEffect { public class CounterEffect extends SpellAbilityEffect {
@Override @Override
@@ -155,10 +154,9 @@ public class CounterEffect extends SpellAbilityEffect {
final SpellAbility srcSA, final SpellAbilityStackInstance si) { final SpellAbility srcSA, final SpellAbilityStackInstance si) {
final Game game = tgtSA.getActivatingPlayer().getGame(); final Game game = tgtSA.getActivatingPlayer().getGame();
// Run any applicable replacement effects. // Run any applicable replacement effects.
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(tgtSA.getHostCard());
repParams.put("TgtSA", tgtSA); repParams.put(AbilityKey.TgtSA, tgtSA);
repParams.put("Affected", tgtSA.getHostCard()); repParams.put(AbilityKey.Cause, srcSA.getHostCard());
repParams.put("Cause", srcSA.getHostCard());
if (game.getReplacementHandler().run(ReplacementType.Counter, repParams) != ReplacementResult.NotReplaced) { if (game.getReplacementHandler().run(ReplacementType.Counter, repParams) != ReplacementResult.NotReplaced) {
return; return;
} }

View File

@@ -1,5 +1,6 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -11,6 +12,6 @@ import forge.game.spellability.SpellAbility;
public class ETBReplacementEffect extends SpellAbilityEffect { public class ETBReplacementEffect extends SpellAbilityEffect {
@Override @Override
public void resolve(SpellAbility sa) { public void resolve(SpellAbility sa) {
sa.getActivatingPlayer().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject("Card")), sa); sa.getActivatingPlayer().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject(AbilityKey.Card)), sa);
} }
} }

View File

@@ -2,10 +2,9 @@ package forge.game.ability.effects;
import java.util.Map; import java.util.Map;
import forge.game.ability.AbilityKey;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Maps;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
@@ -31,10 +30,10 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
String varValue = sa.getParamOrDefault("VarName", "1"); String varValue = sa.getParamOrDefault("VarName", "1");
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> originalParams = (Map<String, Object>) sa.getReplacingObject("OriginalParams"); Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
Map<String, Object> params = Maps.newHashMap(originalParams); Map<AbilityKey, Object> params = AbilityKey.newMap(originalParams);
Integer dmg = (Integer) sa.getReplacingObject("DamageAmount"); Integer dmg = (Integer) sa.getReplacingObject(AbilityKey.DamageAmount);
int prevent = AbilityUtils.calculateAmount(card, varValue, sa); int prevent = AbilityUtils.calculateAmount(card, varValue, sa);
@@ -54,10 +53,10 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
// no damage for original target anymore // no damage for original target anymore
if (dmg <= 0) { if (dmg <= 0) {
originalParams.put("ReplacementResult", ReplacementResult.Replaced); originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
return; return;
} }
params.put("DamageAmount", dmg); params.put(AbilityKey.DamageAmount, dmg);
//try to call replacementHandler with new Params //try to call replacementHandler with new Params
@@ -65,16 +64,16 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
switch (result) { switch (result) {
case NotReplaced: case NotReplaced:
case Updated: { case Updated: {
for (Map.Entry<String, Object> e : params.entrySet()) { for (Map.Entry<AbilityKey, Object> e : params.entrySet()) {
originalParams.put(e.getKey(), e.getValue()); originalParams.put(e.getKey(), e.getValue());
} }
// effect was updated // effect was updated
originalParams.put("ReplacementResult", ReplacementResult.Updated); originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
break; break;
} }
default: default:
// effect was replaced with something else // effect was replaced with something else
originalParams.put("ReplacementResult", result); originalParams.put(AbilityKey.ReplacementResult, result);
break; break;
} }
} }

View File

@@ -7,6 +7,7 @@ import com.google.common.collect.Maps;
import forge.game.Game; import forge.game.Game;
import forge.game.GameObject; import forge.game.GameObject;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
@@ -23,14 +24,14 @@ public class ReplaceEffect extends SpellAbilityEffect {
final Card card = sa.getHostCard(); final Card card = sa.getHostCard();
final Game game = card.getGame(); final Game game = card.getGame();
final String varName = sa.getParam("VarName"); final AbilityKey varName = AbilityKey.fromString(sa.getParam("VarName"));
final String varValue = sa.getParam("VarValue"); final String varValue = sa.getParam("VarValue");
final String type = sa.getParamOrDefault("VarType", "amount"); final String type = sa.getParamOrDefault("VarType", "amount");
final ReplacementType retype = sa.getReplacementEffect().getMode(); final ReplacementType retype = sa.getReplacementEffect().getMode();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> originalParams = (Map<String, Object>) sa.getReplacingObject("OriginalParams"); Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
Map<String, Object> params = Maps.newHashMap(originalParams); Map<AbilityKey, Object> params = Maps.newHashMap(originalParams);
if ("Card".equals(type)) { if ("Card".equals(type)) {
List<Card> list = AbilityUtils.getDefinedCards(card, varValue, sa); List<Card> list = AbilityUtils.getDefinedCards(card, varValue, sa);
@@ -56,8 +57,8 @@ public class ReplaceEffect extends SpellAbilityEffect {
params.put(varName, AbilityUtils.calculateAmount(card, varValue, sa)); params.put(varName, AbilityUtils.calculateAmount(card, varValue, sa));
} }
if (params.containsKey("EffectOnly")) { if (params.containsKey(AbilityKey.EffectOnly)) {
params.put("EffectOnly", true); params.put(AbilityKey.EffectOnly, true);
} }
//try to call replacementHandler with new Params //try to call replacementHandler with new Params
@@ -65,16 +66,16 @@ public class ReplaceEffect extends SpellAbilityEffect {
switch (result) { switch (result) {
case NotReplaced: case NotReplaced:
case Updated: { case Updated: {
for (Map.Entry<String, Object> e : params.entrySet()) { for (Map.Entry<AbilityKey, Object> e : params.entrySet()) {
originalParams.put(e.getKey(), e.getValue()); originalParams.put(e.getKey(), e.getValue());
} }
// effect was updated // effect was updated
originalParams.put("ReplacementResult", ReplacementResult.Updated); originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
break; break;
} }
default: default:
// effect was replaced with something else // effect was replaced with something else
originalParams.put("ReplacementResult", result); originalParams.put(AbilityKey.ReplacementResult, result);
break; break;
} }
} }

View File

@@ -3,10 +3,9 @@ package forge.game.ability.effects;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import forge.game.ability.AbilityKey;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Maps;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GameEntityCounterTable; import forge.game.GameEntityCounterTable;
@@ -36,10 +35,10 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
String varValue = sa.getParamOrDefault("VarName", "1"); String varValue = sa.getParamOrDefault("VarName", "1");
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> originalParams = (Map<String, Object>) sa.getReplacingObject("OriginalParams"); Map<AbilityKey, Object> originalParams = (Map<AbilityKey , Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
Map<String, Object> params = Maps.newHashMap(originalParams); Map<AbilityKey, Object> params = AbilityKey.newMap(originalParams);
Integer dmg = (Integer) sa.getReplacingObject("DamageAmount"); Integer dmg = (Integer) sa.getReplacingObject(AbilityKey.DamageAmount);
int prevent = AbilityUtils.calculateAmount(card, varValue, sa); int prevent = AbilityUtils.calculateAmount(card, varValue, sa);
@@ -57,15 +56,15 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
card.setSVar(varValue, "Number$" + prevent); card.setSVar(varValue, "Number$" + prevent);
} }
Card sourceLKI = (Card) sa.getReplacingObject("Source"); Card sourceLKI = (Card) sa.getReplacingObject(AbilityKey.Source);
CardDamageMap damageMap = (CardDamageMap) originalParams.get("DamageMap"); CardDamageMap damageMap = (CardDamageMap) originalParams.get(AbilityKey.DamageMap);
CardDamageMap preventMap = (CardDamageMap) originalParams.get("PreventMap"); CardDamageMap preventMap = (CardDamageMap) originalParams.get(AbilityKey.PreventMap);
GameEntityCounterTable counterTable = (GameEntityCounterTable) originalParams.get("CounterTable"); GameEntityCounterTable counterTable = (GameEntityCounterTable) originalParams.get(AbilityKey.CounterTable);
SpellAbility cause = (SpellAbility) originalParams.get("Cause"); SpellAbility cause = (SpellAbility) originalParams.get(AbilityKey.Cause);
boolean isCombat = (Boolean) originalParams.get("IsCombat"); boolean isCombat = (Boolean) originalParams.get(AbilityKey.IsCombat);
boolean noPrevention = (Boolean) originalParams.get("NoPreventDamage"); boolean noPrevention = (Boolean) originalParams.get(AbilityKey.NoPreventDamage);
GameEntity obj = (GameEntity) list.get(0); GameEntity obj = (GameEntity) list.get(0);
@@ -74,26 +73,26 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
// no damage for original target anymore // no damage for original target anymore
if (dmg <= 0) { if (dmg <= 0) {
originalParams.put("ReplacementResult", ReplacementResult.Replaced); originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
return; return;
} }
params.put("DamageAmount", dmg); params.put(AbilityKey.DamageAmount, dmg);
//try to call replacementHandler with new Params //try to call replacementHandler with new Params
ReplacementResult result = game.getReplacementHandler().run(event, params); ReplacementResult result = game.getReplacementHandler().run(event, params);
switch (result) { switch (result) {
case NotReplaced: case NotReplaced:
case Updated: { case Updated: {
for (Map.Entry<String, Object> e : params.entrySet()) { for (Map.Entry<AbilityKey, Object> e : params.entrySet()) {
originalParams.put(e.getKey(), e.getValue()); originalParams.put(e.getKey(), e.getValue());
} }
// effect was updated // effect was updated
originalParams.put("ReplacementResult", ReplacementResult.Updated); originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
break; break;
} }
default: default:
// effect was replaced with something else // effect was replaced with something else
originalParams.put("ReplacementResult", result); originalParams.put(AbilityKey.ReplacementResult, result);
break; break;
} }
} }

View File

@@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.game.ability.AbilityKey;
import forge.game.card.token.TokenInfo; import forge.game.card.token.TokenInfo;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -224,8 +225,11 @@ public class TokenEffect extends SpellAbilityEffect {
// Cause of the Token Effect, in general it should be this // Cause of the Token Effect, in general it should be this
// but if its a Replacement Effect, it might be something else or null // but if its a Replacement Effect, it might be something else or null
SpellAbility cause = sa; SpellAbility cause = sa;
if (root.isReplacementAbility() && root.hasReplacingObject("Cause")) { if (root.isReplacementAbility()) {
cause = (SpellAbility)root.getReplacingObject("Cause"); Object replacingObject = root.getReplacingObject(AbilityKey.Cause);
if (replacingObject != null) {
cause = (SpellAbility) replacingObject;
}
} }
final boolean remember = sa.hasParam("RememberTokens"); final boolean remember = sa.hasParam("RememberTokens");

View File

@@ -689,9 +689,7 @@ public class Card extends GameEntity implements Comparable<Card> {
if (result && runTriggers) { if (result && runTriggers) {
// Run replacement effects // Run replacement effects
Map<String, Object> repParams = Maps.newHashMap(); getGame().getReplacementHandler().run(ReplacementType.TurnFaceUp, AbilityKey.mapFromAffected(this));
repParams.put("Affected", this);
getGame().getReplacementHandler().run(ReplacementType.TurnFaceUp, repParams);
// Run triggers // Run triggers
getGame().getTriggerHandler().registerActiveTrigger(this, false); getGame().getTriggerHandler().registerActiveTrigger(this, false);
@@ -1241,18 +1239,17 @@ public class Card extends GameEntity implements Comparable<Card> {
addAmount = 0; // As per rule 107.1b addAmount = 0; // As per rule 107.1b
return 0; return 0;
} }
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
repParams.put("Affected", this); repParams.put(AbilityKey.Source, source);
repParams.put("Source", source); repParams.put(AbilityKey.CounterType, counterType);
repParams.put("CounterType", counterType); repParams.put(AbilityKey.CounterNum, addAmount);
repParams.put("CounterNum", addAmount); repParams.put(AbilityKey.EffectOnly, applyMultiplier);
repParams.put("EffectOnly", applyMultiplier);
switch (getGame().getReplacementHandler().run(ReplacementType.AddCounter, repParams)) { switch (getGame().getReplacementHandler().run(ReplacementType.AddCounter, repParams)) {
case NotReplaced: case NotReplaced:
break; break;
case Updated: { case Updated: {
addAmount = (int) repParams.get("CounterNum"); addAmount = (int) repParams.get(AbilityKey.CounterNum);
break; break;
} }
default: default:
@@ -3611,10 +3608,7 @@ public class Card extends GameEntity implements Comparable<Card> {
if (!tapped) { return; } if (!tapped) { return; }
// Run Replacement effects // Run Replacement effects
final Map<String, Object> repRunParams = Maps.newHashMap(); if (getGame().getReplacementHandler().run(ReplacementType.Untap, AbilityKey.mapFromAffected(this)) != ReplacementResult.NotReplaced) {
repRunParams.put("Affected", this);
if (getGame().getReplacementHandler().run(ReplacementType.Untap, repRunParams) != ReplacementResult.NotReplaced) {
return; return;
} }

View File

@@ -3,12 +3,12 @@ package forge.game.card.token;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import forge.ImageKeys; import forge.ImageKeys;
import forge.StaticData; import forge.StaticData;
import forge.card.CardType; import forge.card.CardType;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardFactory; import forge.game.card.CardFactory;
@@ -166,19 +166,18 @@ public class TokenInfo {
Player player = controller; Player player = controller;
Card proto = prototype; Card proto = prototype;
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(player);
repParams.put("Affected", player); repParams.put(AbilityKey.Token, prototype);
repParams.put("Token", prototype); repParams.put(AbilityKey.TokenNum, multiplier);
repParams.put("TokenNum", multiplier); repParams.put(AbilityKey.EffectOnly, applyMultiplier);
repParams.put("EffectOnly", applyMultiplier);
switch (game.getReplacementHandler().run(ReplacementType.CreateToken, repParams)) { switch (game.getReplacementHandler().run(ReplacementType.CreateToken, repParams)) {
case NotReplaced: case NotReplaced:
break; break;
case Updated: { case Updated: {
multiplier = (int) repParams.get("TokenNum"); multiplier = (int) repParams.get(AbilityKey.TokenNum);
player = (Player) repParams.get("Affected"); player = (Player) repParams.get(AbilityKey.Affected);
proto = (Card) repParams.get("Token"); proto = (Card) repParams.get(AbilityKey.Token);
break; break;
} }
default: default:

View File

@@ -235,10 +235,7 @@ public class Player extends GameEntity implements Comparable<Player> {
} }
// Replacement effects // Replacement effects
final Map<String, Object> repRunParams = Maps.newHashMap(); if (game.getReplacementHandler().run(ReplacementType.SetInMotion, AbilityKey.mapFromAffected(this)) != ReplacementResult.NotReplaced) {
repRunParams.put("Affected", this);
if (game.getReplacementHandler().run(ReplacementType.SetInMotion, repRunParams) != ReplacementResult.NotReplaced) {
return; return;
} }
@@ -403,10 +400,9 @@ public class Player extends GameEntity implements Comparable<Player> {
public final boolean gainLife(int lifeGain, final Card source, final SpellAbility sa) { public final boolean gainLife(int lifeGain, final Card source, final SpellAbility sa) {
// Run any applicable replacement effects. // Run any applicable replacement effects.
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
repParams.put("Affected", this); repParams.put(AbilityKey.LifeGained, lifeGain);
repParams.put("LifeGained", lifeGain); repParams.put(AbilityKey.Source, source);
repParams.put("Source", source);
if (!canGainLife()) { if (!canGainLife()) {
return false; return false;
@@ -417,8 +413,8 @@ public class Player extends GameEntity implements Comparable<Player> {
break; break;
case Updated: case Updated:
// check if this is still the affected player // check if this is still the affected player
if (this.equals(repParams.get("Affected"))) { if (this.equals(repParams.get(AbilityKey.Affected))) {
lifeGain = (int) repParams.get("LifeGained"); lifeGain = (int) repParams.get(AbilityKey.LifeGained);
// negative update means life loss // negative update means life loss
if (lifeGain < 0) { if (lifeGain < 0) {
this.loseLife(-lifeGain); this.loseLife(-lifeGain);
@@ -914,18 +910,17 @@ public class Player extends GameEntity implements Comparable<Player> {
return 0; return 0;
} }
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
repParams.put("Affected", this); repParams.put(AbilityKey.Source, source);
repParams.put("Source", source); repParams.put(AbilityKey.CounterType, counterType);
repParams.put("CounterType", counterType); repParams.put(AbilityKey.CounterNum, addAmount);
repParams.put("CounterNum", addAmount); repParams.put(AbilityKey.EffectOnly, applyMultiplier);
repParams.put("EffectOnly", applyMultiplier);
switch (getGame().getReplacementHandler().run(ReplacementType.AddCounter, repParams)) { switch (getGame().getReplacementHandler().run(ReplacementType.AddCounter, repParams)) {
case NotReplaced: case NotReplaced:
break; break;
case Updated: { case Updated: {
addAmount = (int) repParams.get("CounterNum"); addAmount = (int) repParams.get(AbilityKey.CounterNum);
break; break;
} }
default: default:
@@ -1276,16 +1271,15 @@ public class Player extends GameEntity implements Comparable<Player> {
public void surveil(int num, SpellAbility cause) { public void surveil(int num, SpellAbility cause) {
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
repParams.put("Affected", this); repParams.put(AbilityKey.Source, cause);
repParams.put("Source", cause); repParams.put(AbilityKey.SurveilNum, num);
repParams.put("SurveilNum", num);
switch (getGame().getReplacementHandler().run(ReplacementType.Surveil, repParams)) { switch (getGame().getReplacementHandler().run(ReplacementType.Surveil, repParams)) {
case NotReplaced: case NotReplaced:
break; break;
case Updated: { case Updated: {
num = (int) repParams.get("SurveilNum"); num = (int) repParams.get(AbilityKey.SurveilNum);
break; break;
} }
default: default:
@@ -1346,9 +1340,8 @@ public class Player extends GameEntity implements Comparable<Player> {
final CardCollection toReveal = new CardCollection(); final CardCollection toReveal = new CardCollection();
// Replacement effects // Replacement effects
final Map<String, Object> repRunParams = Maps.newHashMap(); final Map<AbilityKey, Object> repRunParams = AbilityKey.mapFromAffected(this);
repRunParams.put("Affected", this); repRunParams.put(AbilityKey.Number, n);
repRunParams.put("Number", n);
if (game.getReplacementHandler().run(ReplacementType.DrawCards, repRunParams) != ReplacementResult.NotReplaced) { if (game.getReplacementHandler().run(ReplacementType.DrawCards, repRunParams) != ReplacementResult.NotReplaced) {
return drawn; return drawn;
@@ -1378,10 +1371,7 @@ public class Player extends GameEntity implements Comparable<Player> {
final PlayerZone library = getZone(ZoneType.Library); final PlayerZone library = getZone(ZoneType.Library);
// Replacement effects // Replacement effects
final Map<String, Object> repRunParams = Maps.newHashMap(); if (game.getReplacementHandler().run(ReplacementType.Draw, AbilityKey.mapFromAffected(this)) != ReplacementResult.NotReplaced) {
repRunParams.put("Affected", this);
if (game.getReplacementHandler().run(ReplacementType.Draw, repRunParams) != ReplacementResult.NotReplaced) {
return drawn; return drawn;
} }
@@ -1556,10 +1546,9 @@ public class Player extends GameEntity implements Comparable<Player> {
// that should not trigger other Replacement again // that should not trigger other Replacement again
if (!discardToTopOfLibrary && !discardMadness) { if (!discardToTopOfLibrary && !discardMadness) {
// Replacement effects // Replacement effects
final Map<String, Object> repRunParams = Maps.newHashMap(); final Map<AbilityKey, Object> repRunParams = AbilityKey.mapFromCard(c);
repRunParams.put("Card", c); repRunParams.put(AbilityKey.Source, source);
repRunParams.put("Source", source); repRunParams.put(AbilityKey.Affected, this);
repRunParams.put("Affected", this);
if (game.getReplacementHandler().run(ReplacementType.Discard, repRunParams) != ReplacementResult.NotReplaced) { if (game.getReplacementHandler().run(ReplacementType.Discard, repRunParams) != ReplacementResult.NotReplaced) {
return null; return null;
@@ -1861,10 +1850,7 @@ public class Player extends GameEntity implements Comparable<Player> {
} }
// Replacement effects // Replacement effects
final Map<String, Object> runParams = Maps.newHashMap(); if (game.getReplacementHandler().run(ReplacementType.GameLoss, AbilityKey.mapFromAffected(this)) != ReplacementResult.NotReplaced) {
runParams.put("Affected", this);
if (game.getReplacementHandler().run(ReplacementType.GameLoss, runParams) != ReplacementResult.NotReplaced) {
return false; return false;
} }
} }

View File

@@ -211,7 +211,7 @@ public abstract class PlayerController {
Map<String, Object> params); Map<String, Object> params);
public abstract boolean confirmPayment(CostPart costPart, String string, SpellAbility sa); public abstract boolean confirmPayment(CostPart costPart, String string, SpellAbility sa);
public abstract ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers, Map<String, Object> runParams); public abstract ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers);
public abstract String chooseProtectionType(String string, SpellAbility sa, List<String> choices); public abstract String chooseProtectionType(String string, SpellAbility sa, List<String> choices);
// these 4 need some refining. // these 4 need some refining.

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CounterType; import forge.game.card.CounterType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -27,20 +28,20 @@ public class ReplaceAddCounter extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (((int) runParams.get("CounterNum")) <= 0) { if (((int) runParams.get(AbilityKey.CounterNum)) <= 0) {
return false; return false;
} }
if (hasParam("EffectOnly")) { if (hasParam("EffectOnly")) {
final Boolean effectOnly = (Boolean) runParams.get("EffectOnly"); final Boolean effectOnly = (Boolean) runParams.get(AbilityKey.EffectOnly);
if (!effectOnly) { if (!effectOnly) {
return false; return false;
} }
} }
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
Object o = runParams.get("Affected"); Object o = runParams.get(AbilityKey.Affected);
if (!(o instanceof Card)) { if (!(o instanceof Card)) {
return false; return false;
} }
@@ -48,7 +49,7 @@ public class ReplaceAddCounter extends ReplacementEffect {
return false; return false;
} }
} else if (hasParam("ValidPlayer")) { } else if (hasParam("ValidPlayer")) {
Object o = runParams.get("Affected"); Object o = runParams.get(AbilityKey.Affected);
if (!(o instanceof Player)) { if (!(o instanceof Player)) {
return false; return false;
} }
@@ -59,7 +60,7 @@ public class ReplaceAddCounter extends ReplacementEffect {
if (hasParam("ValidCounterType")) { if (hasParam("ValidCounterType")) {
String type = getParam("ValidCounterType"); String type = getParam("ValidCounterType");
if (CounterType.getType(type) != runParams.get("CounterType")) { if (CounterType.getType(type) != runParams.get(AbilityKey.CounterType)) {
return false; return false;
} }
} }
@@ -71,14 +72,14 @@ public class ReplaceAddCounter extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("CounterNum", runParams.get("CounterNum")); sa.setReplacingObject(AbilityKey.CounterNum, runParams.get(AbilityKey.CounterNum));
sa.setReplacingObject("CounterType", ((CounterType) runParams.get("CounterType")).getName()); sa.setReplacingObject(AbilityKey.CounterType, ((CounterType) runParams.get(AbilityKey.CounterType)).getName());
Object o = runParams.get("Affected"); Object o = runParams.get(AbilityKey.Affected);
if (o instanceof Card) { if (o instanceof Card) {
sa.setReplacingObject("Card", o); sa.setReplacingObject(AbilityKey.Card, o);
} else if (o instanceof Player) { } else if (o instanceof Player) {
sa.setReplacingObject("Player", o); sa.setReplacingObject(AbilityKey.Player, o);
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -42,15 +43,15 @@ public class ReplaceCounter extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
final SpellAbility spellAbility = (SpellAbility) runParams.get("TgtSA"); final SpellAbility spellAbility = (SpellAbility) runParams.get(AbilityKey.TgtSA);
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidCard").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidCard").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidCause")) { if (hasParam("ValidCause")) {
if (!matchesValid(runParams.get("Cause"), getParam("ValidCause").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Cause), getParam("ValidCause").split(","), this.getHostCard())) {
return false; return false;
} }
} }
@@ -67,8 +68,8 @@ public class ReplaceCounter extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardFactoryUtil; import forge.game.card.CardFactoryUtil;
@@ -46,49 +47,49 @@ public class ReplaceDamage extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (!(runParams.containsKey("Prevention") == (hasParam("PreventionEffect") || hasParam("Prevent")))) { if (!(runParams.containsKey(AbilityKey.Prevention) == (hasParam("PreventionEffect") || hasParam("Prevent")))) {
return false; return false;
} }
if (((Integer) runParams.get("DamageAmount")) == 0) { if (((Integer) runParams.get(AbilityKey.DamageAmount)) == 0) {
// If no actual damage is dealt, there is nothing to replace // If no actual damage is dealt, there is nothing to replace
return false; return false;
} }
if (hasParam("ValidSource")) { if (hasParam("ValidSource")) {
String validSource = getParam("ValidSource"); String validSource = getParam("ValidSource");
validSource = AbilityUtils.applyAbilityTextChangeEffects(validSource, this); validSource = AbilityUtils.applyAbilityTextChangeEffects(validSource, this);
if (!matchesValid(runParams.get("DamageSource"), validSource.split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.DamageSource), validSource.split(","), getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidTarget")) { if (hasParam("ValidTarget")) {
String validTarget = getParam("ValidTarget"); String validTarget = getParam("ValidTarget");
validTarget = AbilityUtils.applyAbilityTextChangeEffects(validTarget, this); validTarget = AbilityUtils.applyAbilityTextChangeEffects(validTarget, this);
if (!matchesValid(runParams.get("Affected"), validTarget.split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), validTarget.split(","), getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidCause")) { if (hasParam("ValidCause")) {
if (!runParams.containsKey("Cause")) { if (!runParams.containsKey(AbilityKey.Cause)) {
return false; return false;
} }
SpellAbility cause = (SpellAbility) runParams.get("Cause"); SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
String validCause = getParam("ValidCause"); String validCause = getParam("ValidCause");
validCause = AbilityUtils.applyAbilityTextChangeEffects(validCause, this); validCause = AbilityUtils.applyAbilityTextChangeEffects(validCause, this);
if (!matchesValid(cause, validCause.split(","), getHostCard())) { if (!matchesValid(cause, validCause.split(","), getHostCard())) {
return false; return false;
} }
if (hasParam("CauseIsSource")) { if (hasParam("CauseIsSource")) {
if (!cause.getHostCard().equals(runParams.get("DamageSource"))) { if (!cause.getHostCard().equals(runParams.get(AbilityKey.DamageSource))) {
return false; return false;
} }
} }
} }
if (hasParam("RelativeToSource")) { if (hasParam("RelativeToSource")) {
Card source = (Card) runParams.get("DamageSource"); Card source = (Card) runParams.get(AbilityKey.DamageSource);
String validRelative = getParam("RelativeToSource"); String validRelative = getParam("RelativeToSource");
validRelative = AbilityUtils.applyAbilityTextChangeEffects(validRelative, this); validRelative = AbilityUtils.applyAbilityTextChangeEffects(validRelative, this);
if (!matchesValid(runParams.get("DamageTarget"), validRelative.split(","), source)) { if (!matchesValid(runParams.get(AbilityKey.DamageTarget), validRelative.split(","), source)) {
return false; return false;
} }
} }
@@ -103,17 +104,17 @@ public class ReplaceDamage extends ReplacementEffect {
intoperand = CardFactoryUtil.xCount(getHostCard(), getHostCard().getSVar(operand)); intoperand = CardFactoryUtil.xCount(getHostCard(), getHostCard().getSVar(operand));
} }
if (!Expressions.compare((Integer) runParams.get("DamageAmount"), operator, intoperand)) { if (!Expressions.compare((Integer) runParams.get(AbilityKey.DamageAmount), operator, intoperand)) {
return false; return false;
} }
} }
if (hasParam("IsCombat")) { if (hasParam("IsCombat")) {
if (getParam("IsCombat").equals("True")) { if (getParam("IsCombat").equals("True")) {
if (!((Boolean) runParams.get("IsCombat"))) { if (!((Boolean) runParams.get(AbilityKey.IsCombat))) {
return false; return false;
} }
} else { } else {
if ((Boolean) runParams.get("IsCombat")) { if ((Boolean) runParams.get(AbilityKey.IsCombat)) {
return false; return false;
} }
} }
@@ -149,10 +150,10 @@ public class ReplaceDamage extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("DamageAmount", runParams.get("DamageAmount")); sa.setReplacingObject(AbilityKey.DamageAmount, runParams.get(AbilityKey.DamageAmount));
sa.setReplacingObject("Target", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Target, runParams.get(AbilityKey.Affected));
sa.setReplacingObject("Source", runParams.get("DamageSource")); sa.setReplacingObject(AbilityKey.Source, runParams.get(AbilityKey.DamageSource));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -42,23 +43,23 @@ public class ReplaceDestroy extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
Card card = (Card)runParams.get("Card"); Card card = (Card)runParams.get(AbilityKey.Card);
if (!matchesValid(card, getParam("ValidCard").split(","), getHostCard())) { if (!matchesValid(card, getParam("ValidCard").split(","), getHostCard())) {
return false; return false;
} }
// extra check for Regeneration // extra check for Regeneration
if (hasParam("Regeneration")) { if (hasParam("Regeneration")) {
if (!runParams.containsKey("Regeneration")) { if (!runParams.containsKey(AbilityKey.Regeneration)) {
return false; return false;
} }
if (!(Boolean)runParams.get("Regeneration")) { if (!(Boolean)runParams.get(AbilityKey.Regeneration)) {
return false; return false;
} }
if (!card.canBeShielded()) { if (!card.canBeShielded()) {
@@ -71,7 +72,7 @@ public class ReplaceDestroy extends ReplacementEffect {
} }
} }
if (hasParam("ValidSource")) { if (hasParam("ValidSource")) {
if (!matchesValid(runParams.get("Source"), getParam("ValidSource").split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Source), getParam("ValidSource").split(","), getHostCard())) {
return false; return false;
} }
} }
@@ -83,8 +84,8 @@ public class ReplaceDestroy extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Card")); sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Card));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -42,24 +43,24 @@ public class ReplaceDiscard extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
if (!matchesValid(runParams.get("Card"), getParam("ValidCard").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Card), getParam("ValidCard").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidSource")) { if (hasParam("ValidSource")) {
if (!matchesValid(runParams.get("Source"), getParam("ValidSource").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Source), getParam("ValidSource").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("DiscardFromEffect")) { if (hasParam("DiscardFromEffect")) {
if (null == runParams.get("Source")) { if (null == runParams.get(AbilityKey.Source)) {
return false; return false;
} }
} }
@@ -71,10 +72,10 @@ public class ReplaceDiscard extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Card")); sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Card));
sa.setReplacingObject("Player", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
sa.setReplacingObject("Source", runParams.get("Source")); sa.setReplacingObject(AbilityKey.Source, runParams.get(AbilityKey.Source));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -44,14 +45,14 @@ public class ReplaceDraw extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("NotFirstCardInDrawStep")) { if (hasParam("NotFirstCardInDrawStep")) {
final Player p = (Player)runParams.get("Affected"); final Player p = (Player)runParams.get(AbilityKey.Affected);
if (p.numDrawnThisDrawStep() == 0 if (p.numDrawnThisDrawStep() == 0
&& this.getHostCard().getGame().getPhaseHandler().is(PhaseType.DRAW) && this.getHostCard().getGame().getPhaseHandler().is(PhaseType.DRAW)
&& this.getHostCard().getGame().getPhaseHandler().isPlayerTurn(p)) { && this.getHostCard().getGame().getPhaseHandler().isPlayerTurn(p)) {
@@ -68,7 +69,7 @@ public class ReplaceDraw extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Player", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.util.Expressions; import forge.util.Expressions;
@@ -43,14 +44,14 @@ public class ReplaceDrawCards extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("Number")) { if (hasParam("Number")) {
final int n = (Integer)runParams.get("Number"); final int n = (Integer)runParams.get(AbilityKey.Number);
String comparator = getParam("Number"); String comparator = getParam("Number");
final String operator = comparator.substring(0, 2); final String operator = comparator.substring(0, 2);
final int operandValue = Integer.parseInt(comparator.substring(2)); final int operandValue = Integer.parseInt(comparator.substring(2));
@@ -68,7 +69,7 @@ public class ReplaceDrawCards extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Player", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -42,22 +43,22 @@ public class ReplaceGainLife extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (((int)runParams.get("LifeGained")) <= 0) { if (((int)runParams.get(AbilityKey.LifeGained)) <= 0) {
return false; return false;
} }
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidSource")) { if (hasParam("ValidSource")) {
if (!matchesValid(runParams.get("Source"), getParam("ValidSource").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Source), getParam("ValidSource").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if ("True".equals(getParam("SourceController"))) { if ("True".equals(getParam("SourceController"))) {
if (runParams.get("Source") == null || !runParams.get("Affected").equals(((Card)runParams.get("Source")).getController())) { if (runParams.get(AbilityKey.Source) == null || !runParams.get(AbilityKey.Affected).equals(((Card)runParams.get(AbilityKey.Source)).getController())) {
return false; return false;
} }
} }
@@ -69,9 +70,9 @@ public class ReplaceGainLife extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("LifeGained", runParams.get("LifeGained")); sa.setReplacingObject(AbilityKey.LifeGained, runParams.get(AbilityKey.LifeGained));
sa.setReplacingObject("Player", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import java.util.Map; import java.util.Map;
@@ -24,9 +25,9 @@ public class ReplaceGameLoss extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), this.getHostCard())) {
return false; return false;
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.player.Player; import forge.game.player.Player;
@@ -28,9 +29,9 @@ public class ReplaceMoved extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
final Player controller = getHostCard().getController(); final Player controller = getHostCard().getController();
final Card affected = (Card) runParams.get("Affected"); final Card affected = (Card) runParams.get(AbilityKey.Affected);
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
if (!matchesValid(affected, getParam("ValidCard").split(","), getHostCard())) { if (!matchesValid(affected, getParam("ValidCard").split(","), getHostCard())) {
@@ -39,27 +40,27 @@ public class ReplaceMoved extends ReplacementEffect {
} }
if (hasParam("ValidLKI")) { if (hasParam("ValidLKI")) {
if (!matchesValid(runParams.get("CardLKI"), getParam("ValidLKI").split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.CardLKI), getParam("ValidLKI").split(","), getHostCard())) {
return false; return false;
} }
} }
if (hasParam("Origin")) { if (hasParam("Origin")) {
ZoneType zt = (ZoneType) runParams.get("Origin"); ZoneType zt = (ZoneType) runParams.get(AbilityKey.Origin);
if (!ZoneType.listValueOf(getParam("Origin")).contains(zt)) { if (!ZoneType.listValueOf(getParam("Origin")).contains(zt)) {
return false; return false;
} }
} }
if (hasParam("Destination")) { if (hasParam("Destination")) {
ZoneType zt = (ZoneType) runParams.get("Destination"); ZoneType zt = (ZoneType) runParams.get(AbilityKey.Destination);
if (!ZoneType.listValueOf(getParam("Destination")).contains(zt)) { if (!ZoneType.listValueOf(getParam("Destination")).contains(zt)) {
return false; return false;
} }
} }
if (hasParam("ExcludeDestination")) { if (hasParam("ExcludeDestination")) {
ZoneType zt = (ZoneType) runParams.get("Destination"); ZoneType zt = (ZoneType) runParams.get(AbilityKey.Destination);
if (ZoneType.listValueOf(getParam("ExcludeDestination")).contains(zt)) { if (ZoneType.listValueOf(getParam("ExcludeDestination")).contains(zt)) {
return false; return false;
} }
@@ -67,29 +68,29 @@ public class ReplaceMoved extends ReplacementEffect {
if (hasParam("Fizzle")) { if (hasParam("Fizzle")) {
// if Replacement look for Fizzle // if Replacement look for Fizzle
if (!runParams.containsKey("Fizzle")) { if (!runParams.containsKey(AbilityKey.Fizzle)) {
return false; return false;
} }
Boolean val = (Boolean) runParams.get("Fizzle"); Boolean val = (Boolean) runParams.get(AbilityKey.Fizzle);
if ("True".equals(getParam("Fizzle")) != val) { if ("True".equals(getParam("Fizzle")) != val) {
return false; return false;
} }
} }
if (hasParam("ValidStackSa")) { if (hasParam("ValidStackSa")) {
if (!runParams.containsKey("StackSa")) { if (!runParams.containsKey(AbilityKey.StackSa)) {
return false; return false;
} }
if (!((SpellAbility)runParams.get("StackSa")).isValid(getParam("ValidStackSa").split(","), getHostCard().getController(), getHostCard(), null)) { if (!((SpellAbility)runParams.get(AbilityKey.StackSa)).isValid(getParam("ValidStackSa").split(","), getHostCard().getController(), getHostCard(), null)) {
return false; return false;
} }
} }
if (hasParam("Cause")) { if (hasParam("Cause")) {
if (!runParams.containsKey("Cause")) { if (!runParams.containsKey(AbilityKey.Cause)) {
return false; return false;
} }
SpellAbility cause = (SpellAbility) runParams.get("Cause"); SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
if (cause == null) { if (cause == null) {
return false; return false;
} }
@@ -99,8 +100,8 @@ public class ReplaceMoved extends ReplacementEffect {
} }
if (hasParam("NotCause")) { if (hasParam("NotCause")) {
if (runParams.containsKey("Cause")) { if (runParams.containsKey(AbilityKey.Cause)) {
SpellAbility cause = (SpellAbility) runParams.get("Cause"); SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
if (cause != null) { if (cause != null) {
if (cause.isValid(getParam("NotCause").split(","), controller, getHostCard(), null)) { if (cause.isValid(getParam("NotCause").split(","), controller, getHostCard(), null)) {
return false; return false;
@@ -116,10 +117,10 @@ public class ReplaceMoved extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Affected));
sa.setReplacingObject("CardLKI", runParams.get("CardLKI")); sa.setReplacingObject(AbilityKey.CardLKI, runParams.get(AbilityKey.CardLKI));
sa.setReplacingObject("Cause", runParams.get("Cause")); sa.setReplacingObject(AbilityKey.Cause, runParams.get(AbilityKey.Cause));
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardFactoryUtil; import forge.game.card.CardFactoryUtil;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -29,10 +30,10 @@ public class ReplaceProduceMana extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
//Check for tapping //Check for tapping
if (!hasParam("NoTapCheck")) { if (!hasParam("NoTapCheck")) {
final SpellAbility manaAbility = (SpellAbility) runParams.get("AbilityMana"); final SpellAbility manaAbility = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
if (manaAbility == null || manaAbility.getRootAbility().getPayCosts() == null || !manaAbility.getRootAbility().getPayCosts().hasTapCost()) { if (manaAbility == null || manaAbility.getRootAbility().getPayCosts() == null || !manaAbility.getRootAbility().getPayCosts().hasTapCost()) {
return false; return false;
} }
@@ -48,14 +49,14 @@ public class ReplaceProduceMana extends ReplacementEffect {
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
intoperand = CardFactoryUtil.xCount(getHostCard(), getHostCard().getSVar(operand)); intoperand = CardFactoryUtil.xCount(getHostCard(), getHostCard().getSVar(operand));
} }
int manaAmount = StringUtils.countMatches((String) runParams.get("Mana"), " ") + 1; int manaAmount = StringUtils.countMatches((String) runParams.get(AbilityKey.Mana), " ") + 1;
if (!Expressions.compare(manaAmount, operator, intoperand)) { if (!Expressions.compare(manaAmount, operator, intoperand)) {
return false; return false;
} }
} }
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidCard").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidCard").split(","), this.getHostCard())) {
return false; return false;
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import java.util.Map; import java.util.Map;
@@ -41,9 +42,9 @@ public class ReplaceSetInMotion extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), getHostCard())) {
return false; return false;
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -25,13 +26,13 @@ public class ReplaceSurveil extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.Map) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.Map)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (((int) runParams.get("SurveilNum")) <= 0) { if (((int) runParams.get(AbilityKey.SurveilNum)) <= 0) {
return false; return false;
} }
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), this.getHostCard())) {
return false; return false;
} }
} }
@@ -43,9 +44,9 @@ public class ReplaceSurveil extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.Map, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.Map, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Player", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
sa.setReplacingObject("SurveilNum", runParams.get("SurveilNum")); sa.setReplacingObject(AbilityKey.SurveilNum, runParams.get(AbilityKey.SurveilNum));
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -25,27 +26,27 @@ public class ReplaceToken extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.Map) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.Map)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (((int) runParams.get("TokenNum")) <= 0) { if (((int) runParams.get(AbilityKey.TokenNum)) <= 0) {
return false; return false;
} }
if (hasParam("EffectOnly")) { if (hasParam("EffectOnly")) {
final Boolean effectOnly = (Boolean) runParams.get("EffectOnly"); final Boolean effectOnly = (Boolean) runParams.get(AbilityKey.EffectOnly);
if (!effectOnly) { if (!effectOnly) {
return false; return false;
} }
} }
if (hasParam("ValidPlayer")) { if (hasParam("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidPlayer").split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), getHostCard())) {
return false; return false;
} }
} }
if (hasParam("ValidToken")) { if (hasParam("ValidToken")) {
if (runParams.containsKey("Token")) { if (runParams.containsKey(AbilityKey.Token)) {
if (!matchesValid(runParams.get("Token"), getParam("ValidToken").split(","), getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Token), getParam("ValidToken").split(","), getHostCard())) {
return false; return false;
} }
} else { } else {
@@ -61,9 +62,9 @@ public class ReplaceToken extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.Map, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.Map, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("TokenNum", runParams.get("TokenNum")); sa.setReplacingObject(AbilityKey.TokenNum, runParams.get(AbilityKey.TokenNum));
sa.setReplacingObject("Player", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -1,5 +1,6 @@
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -25,9 +26,9 @@ public class ReplaceTurnFaceUp extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidCard").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidCard").split(","), this.getHostCard())) {
return false; return false;
} }
} }
@@ -38,8 +39,8 @@ public class ReplaceTurnFaceUp extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -17,6 +17,7 @@
*/ */
package forge.game.replacement; package forge.game.replacement;
import forge.game.ability.AbilityKey;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -44,14 +45,14 @@ public class ReplaceUntap extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/ */
@Override @Override
public boolean canReplace(Map<String, Object> runParams) { public boolean canReplace(Map<AbilityKey, Object> runParams) {
if (hasParam("ValidCard")) { if (hasParam("ValidCard")) {
if (!matchesValid(runParams.get("Affected"), getParam("ValidCard").split(","), this.getHostCard())) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidCard").split(","), this.getHostCard())) {
return false; return false;
} }
} }
if (hasParam("UntapStep")) { if (hasParam("UntapStep")) {
final Object o = runParams.get("Affected"); final Object o = runParams.get(AbilityKey.Affected);
//normally should not happen, but protect from possible crash. //normally should not happen, but protect from possible crash.
if (!(o instanceof Card)) { if (!(o instanceof Card)) {
return false; return false;
@@ -72,8 +73,8 @@ public class ReplaceUntap extends ReplacementEffect {
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/ */
@Override @Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) { public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Affected")); sa.setReplacingObject(AbilityKey.Card, runParams.get(AbilityKey.Affected));
} }
} }

View File

@@ -19,6 +19,7 @@ package forge.game.replacement;
import forge.game.Game; import forge.game.Game;
import forge.game.TriggerReplacementBase; import forge.game.TriggerReplacementBase;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -121,7 +122,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
* the run params * the run params
* @return true, if successful * @return true, if successful
*/ */
public abstract boolean canReplace(final Map<String, Object> runParams); public abstract boolean canReplace (final Map<AbilityKey, Object> runParams);
/** /**
* <p> * <p>
@@ -198,13 +199,11 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
/** /**
* Sets the replacing objects. * Sets the replacing objects.
*
* @param runParams * @param runParams
* the run params * the run params
* @param spellAbility * @param spellAbility
* the SpellAbility
*/ */
public void setReplacingObjects(final Map<String, Object> runParams, final SpellAbility spellAbility) { public void setReplacingObjects(final Map<AbilityKey, Object> runParams, final SpellAbility spellAbility) {
// Should be overridden by replacers that need it. // Should be overridden by replacers that need it.
} }

View File

@@ -21,6 +21,7 @@ import forge.card.MagicColor;
import forge.game.Game; import forge.game.Game;
import forge.game.GameLogEntryType; import forge.game.GameLogEntryType;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
@@ -52,41 +53,17 @@ public class ReplacementHandler {
//private final List<ReplacementEffect> tmpEffects = new ArrayList<ReplacementEffect>(); //private final List<ReplacementEffect> tmpEffects = new ArrayList<ReplacementEffect>();
public ReplacementResult run(ReplacementType event, final Map<String, Object> runParams) { public List<ReplacementEffect> getReplacementList(final ReplacementType event, final Map<AbilityKey, Object> runParams, final ReplacementLayer layer) {
final Object affected = runParams.get("Affected");
Player decider = null;
// Figure out who decides which of multiple replacements to apply
// as well as whether or not to apply optional replacements.
if (affected instanceof Player) {
decider = (Player) affected;
} else {
decider = ((Card) affected).getController();
}
// try out all layer
for (ReplacementLayer layer : ReplacementLayer.values()) {
ReplacementResult res = run(event, runParams, layer, decider);
if (res != ReplacementResult.NotReplaced) {
return res;
}
}
return ReplacementResult.NotReplaced;
}
public List<ReplacementEffect> getReplacementList(final ReplacementType event, final Map<String, Object> runParams, final ReplacementLayer layer) {
final CardCollection preList = new CardCollection(); final CardCollection preList = new CardCollection();
boolean checkAgain = false; boolean checkAgain = false;
Card affectedLKI = null; Card affectedLKI = null;
Card affectedCard = null; Card affectedCard = null;
if (ReplacementType.Moved.equals(event) && ZoneType.Battlefield.equals(runParams.get("Destination"))) { if (ReplacementType.Moved.equals(event) && ZoneType.Battlefield.equals(runParams.get(AbilityKey.Destination))) {
// if it was caused by an replacement effect, use the already calculated RE list // if it was caused by an replacement effect, use the already calculated RE list
// otherwise the RIOT card would cause a StackError // otherwise the RIOT card would cause a StackError
SpellAbility cause = (SpellAbility) runParams.get("Cause"); SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
if (cause != null && cause.isReplacementAbility()) { if (cause != null && cause.isReplacementAbility()) {
final ReplacementEffect re = cause.getReplacementEffect(); final ReplacementEffect re = cause.getReplacementEffect();
// only return for same layer // only return for same layer
@@ -96,13 +73,13 @@ public class ReplacementHandler {
} }
// Rule 614.12 Enter the Battlefield Replacement Effects look at what the card would be on the battlefield // Rule 614.12 Enter the Battlefield Replacement Effects look at what the card would be on the battlefield
affectedCard = (Card) runParams.get("Affected"); affectedCard = (Card) runParams.get(AbilityKey.Affected);
affectedLKI = CardUtil.getLKICopy(affectedCard); affectedLKI = CardUtil.getLKICopy(affectedCard);
affectedLKI.setLastKnownZone(affectedCard.getController().getZone(ZoneType.Battlefield)); affectedLKI.setLastKnownZone(affectedCard.getController().getZone(ZoneType.Battlefield));
preList.add(affectedLKI); preList.add(affectedLKI);
game.getAction().checkStaticAbilities(false, Sets.newHashSet(affectedLKI), preList); game.getAction().checkStaticAbilities(false, Sets.newHashSet(affectedLKI), preList);
checkAgain = true; checkAgain = true;
runParams.put("Affected", affectedLKI); runParams.put(AbilityKey.Affected, affectedLKI);
} }
final List<ReplacementEffect> possibleReplacers = Lists.newArrayList(); final List<ReplacementEffect> possibleReplacers = Lists.newArrayList();
@@ -157,7 +134,7 @@ public class ReplacementHandler {
for (final ReplacementEffect re : affectedLKI.getReplacementEffects()) { for (final ReplacementEffect re : affectedLKI.getReplacementEffects()) {
re.setHostCard(affectedCard); re.setHostCard(affectedCard);
} }
runParams.put("Affected", affectedCard); runParams.put(AbilityKey.Affected, affectedCard);
} }
game.getAction().checkStaticAbilities(false); game.getAction().checkStaticAbilities(false);
} }
@@ -171,16 +148,40 @@ public class ReplacementHandler {
* *
* @param runParams * @param runParams
* the run params,same as for triggers. * the run params,same as for triggers.
* @return true if the event was replaced. * @return ReplacementResult, an enum that represents what happened to the replacement effect.
*/ */
public ReplacementResult run(final ReplacementType event, final Map<String, Object> runParams, final ReplacementLayer layer, final Player decider) { public ReplacementResult run(ReplacementType event, final Map<AbilityKey, Object> runParams) {
final Object affected = runParams.get(AbilityKey.Affected);
Player decider = null;
// Figure out who decides which of multiple replacements to apply
// as well as whether or not to apply optional replacements.
if (affected instanceof Player) {
decider = (Player) affected;
} else {
decider = ((Card) affected).getController();
}
// try out all layer
for (ReplacementLayer layer : ReplacementLayer.values()) {
ReplacementResult res = run(event, runParams, layer, decider);
if (res != ReplacementResult.NotReplaced) {
return res;
}
}
return ReplacementResult.NotReplaced;
}
private ReplacementResult run(final ReplacementType event, final Map<AbilityKey, Object> runParams, final ReplacementLayer layer, final Player decider) {
final List<ReplacementEffect> possibleReplacers = getReplacementList(event, runParams, layer); final List<ReplacementEffect> possibleReplacers = getReplacementList(event, runParams, layer);
if (possibleReplacers.isEmpty()) { if (possibleReplacers.isEmpty()) {
return ReplacementResult.NotReplaced; return ReplacementResult.NotReplaced;
} }
ReplacementEffect chosenRE = decider.getController().chooseSingleReplacementEffect("Choose a replacement effect to apply first.", possibleReplacers, runParams); ReplacementEffect chosenRE = decider.getController().chooseSingleReplacementEffect("Choose a replacement effect to apply first.", possibleReplacers);
possibleReplacers.remove(chosenRE); possibleReplacers.remove(chosenRE);
@@ -213,7 +214,7 @@ public class ReplacementHandler {
* @param replacementEffect * @param replacementEffect
* the replacement effect to run * the replacement effect to run
*/ */
private ReplacementResult executeReplacement(final Map<String, Object> runParams, private ReplacementResult executeReplacement(final Map<AbilityKey, Object> runParams,
final ReplacementEffect replacementEffect, final Player decider, final Game game) { final ReplacementEffect replacementEffect, final Player decider, final Game game) {
final Map<String, String> mapParams = replacementEffect.getMapParams(); final Map<String, String> mapParams = replacementEffect.getMapParams();
@@ -237,7 +238,7 @@ public class ReplacementHandler {
do { do {
replacementEffect.setReplacingObjects(runParams, tailend); replacementEffect.setReplacingObjects(runParams, tailend);
//set original Params to update them later //set original Params to update them later
tailend.setReplacingObject("OriginalParams", runParams); tailend.setReplacingObject(AbilityKey.OriginalParams, runParams);
tailend = tailend.getSubAbility(); tailend = tailend.getSubAbility();
} while(tailend != null); } while(tailend != null);
@@ -248,7 +249,7 @@ public class ReplacementHandler {
do { do {
replacementEffect.setReplacingObjects(runParams, tailend); replacementEffect.setReplacingObjects(runParams, tailend);
//set original Params to update them later //set original Params to update them later
tailend.setReplacingObject("OriginalParams", runParams); tailend.setReplacingObject(AbilityKey.OriginalParams, runParams);
tailend = tailend.getSubAbility(); tailend = tailend.getSubAbility();
} while(tailend != null); } while(tailend != null);
} }
@@ -275,7 +276,7 @@ public class ReplacementHandler {
Card cardForUi = host.getCardForUi(); Card cardForUi = host.getCardForUi();
String effectDesc = TextUtil.fastReplace(replacementEffect.toString(), "CARDNAME", cardForUi.getName()); String effectDesc = TextUtil.fastReplace(replacementEffect.toString(), "CARDNAME", cardForUi.getName());
final String question = replacementEffect instanceof ReplaceDiscard final String question = replacementEffect instanceof ReplaceDiscard
? TextUtil.concatWithSpace("Apply replacement effect of", cardForUi.toString(), "to", TextUtil.addSuffix(runParams.get("Card").toString(),"?\r\n"), TextUtil.enclosedParen(effectDesc)) ? TextUtil.concatWithSpace("Apply replacement effect of", cardForUi.toString(), "to", TextUtil.addSuffix(runParams.get(AbilityKey.Card).toString(),"?\r\n"), TextUtil.enclosedParen(effectDesc))
: TextUtil.concatWithSpace("Apply replacement effect of", TextUtil.addSuffix(cardForUi.toString(),"?\r\n"), TextUtil.enclosedParen(effectDesc)); : TextUtil.concatWithSpace("Apply replacement effect of", TextUtil.addSuffix(cardForUi.toString(),"?\r\n"), TextUtil.enclosedParen(effectDesc));
boolean confirmed = optDecider.getController().confirmReplacementEffect(replacementEffect, effectSA, question); boolean confirmed = optDecider.getController().confirmReplacementEffect(replacementEffect, effectSA, question);
if (!confirmed) { if (!confirmed) {
@@ -292,9 +293,9 @@ public class ReplacementHandler {
Player player = host.getController(); Player player = host.getController();
if (mapParams.containsKey("ManaReplacement")) { if (mapParams.containsKey("ManaReplacement")) {
final SpellAbility manaAb = (SpellAbility) runParams.get("AbilityMana"); final SpellAbility manaAb = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
final Player player1 = (Player) runParams.get("Player"); final Player player1 = (Player) runParams.get(AbilityKey.Player);
final String rep = (String) runParams.get("Mana"); final String rep = (String) runParams.get(AbilityKey.Mana);
// Replaced mana type // Replaced mana type
final Card repHost = host; final Card repHost = host;
String repType = repHost.getSVar(mapParams.get("ManaReplacement")); String repType = repHost.getSVar(mapParams.get("ManaReplacement"));
@@ -307,8 +308,8 @@ public class ReplacementHandler {
player.getController().playSpellAbilityNoStack(effectSA, true); player.getController().playSpellAbilityNoStack(effectSA, true);
// if the spellability is a replace effect then its some new logic // if the spellability is a replace effect then its some new logic
// if ReplacementResult is set in run params use that instead // if ReplacementResult is set in run params use that instead
if (runParams.containsKey("ReplacementResult")) { if (runParams.containsKey(AbilityKey.ReplacementResult)) {
return (ReplacementResult) runParams.get("ReplacementResult"); return (ReplacementResult) runParams.get(AbilityKey.ReplacementResult);
} }
} }

View File

@@ -128,11 +128,10 @@ public class AbilityManaPart implements java.io.Serializable {
final Card source = this.getSourceCard(); final Card source = this.getSourceCard();
final ManaPool manaPool = player.getManaPool(); final ManaPool manaPool = player.getManaPool();
String afterReplace = applyManaReplacement(sa, produced); String afterReplace = applyManaReplacement(sa, produced);
final Map<String, Object> repParams = Maps.newHashMap(); final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(source);
repParams.put("Mana", afterReplace); repParams.put(AbilityKey.Mana, afterReplace);
repParams.put("Affected", source); repParams.put(AbilityKey.Player, player);
repParams.put("Player", player); repParams.put(AbilityKey.AbilityMana, sa);
repParams.put("AbilityMana", sa);
if (player.getGame().getReplacementHandler().run(ReplacementType.ProduceMana, repParams) != ReplacementResult.NotReplaced) { if (player.getGame().getReplacementHandler().run(ReplacementType.ProduceMana, repParams) != ReplacementResult.NotReplaced) {
return; return;
} }

View File

@@ -143,7 +143,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
private EnumMap<AbilityKey, Object> triggeringObjects = AbilityKey.newMap(); private EnumMap<AbilityKey, Object> triggeringObjects = AbilityKey.newMap();
private HashMap<String, Object> replacingObjects = Maps.newHashMap(); private EnumMap<AbilityKey, Object> replacingObjects = AbilityKey.newMap();
private List<AbilitySub> chosenList = null; private List<AbilitySub> chosenList = null;
private CardCollection tappedForConvoke = new CardCollection(); private CardCollection tappedForConvoke = new CardCollection();
@@ -593,17 +593,15 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
triggerRemembered = Lists.newArrayList(); triggerRemembered = Lists.newArrayList();
} }
public HashMap<String, Object> getReplacingObjects() { public Map<AbilityKey, Object> getReplacingObjects() {
return replacingObjects; return replacingObjects;
} }
public boolean hasReplacingObject(final String type) { public Object getReplacingObject(final AbilityKey type) {
return replacingObjects.containsKey(type);
}
public Object getReplacingObject(final String type) {
final Object res = replacingObjects.get(type); final Object res = replacingObjects.get(type);
return res; return res;
} }
public void setReplacingObject(final String type, final Object o) {
public void setReplacingObject(final AbilityKey type, final Object o) {
replacingObjects.put(type, o); replacingObjects.put(type, o);
} }

View File

@@ -506,7 +506,7 @@ public class PlayerControllerForTests extends PlayerController {
} }
@Override @Override
public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers, Map<String, Object> runParams) { public ReplacementEffect chooseSingleReplacementEffect(String prompt, List<ReplacementEffect> possibleReplacers) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return Iterables.getFirst(possibleReplacers, null); return Iterables.getFirst(possibleReplacers, null);
} }

View File

@@ -19,6 +19,7 @@ Myrd
nefigah nefigah
OgreBattlecruiser OgreBattlecruiser
pfps pfps
Ryan1729
Seravy Seravy
Sirspud Sirspud
Sloth Sloth

View File

@@ -1,13 +1,10 @@
package forge.match.input; package forge.match.input;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import forge.GuiBase; import forge.GuiBase;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.ability.AbilityKey;
import forge.game.spellability.SpellAbilityView; import forge.game.spellability.SpellAbilityView;
import forge.util.TextUtil; import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -363,11 +360,11 @@ public abstract class InputPayMana extends InputSyncronizedBase {
final Card source = am.getHostCard(); final Card source = am.getHostCard();
final Player activator = am.getActivatingPlayer(); final Player activator = am.getActivatingPlayer();
final Game g = source.getGame(); final Game g = source.getGame();
final HashMap<String, Object> repParams = new HashMap<>(); final Map<AbilityKey, Object> repParams = AbilityKey.newMap();
repParams.put("Mana", m.getOrigProduced()); repParams.put(AbilityKey.Mana, m.getOrigProduced());
repParams.put("Affected", source); repParams.put(AbilityKey.Affected, source);
repParams.put("Player", activator); repParams.put(AbilityKey.Player, activator);
repParams.put("AbilityMana", am); repParams.put(AbilityKey.AbilityMana, am);
for (final Player p : g.getPlayers()) { for (final Player p : g.getPlayers()) {
for (final Card crd : p.getAllCards()) { for (final Card crd : p.getAllCards()) {

View File

@@ -1587,7 +1587,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public ReplacementEffect chooseSingleReplacementEffect(final String prompt, public ReplacementEffect chooseSingleReplacementEffect(final String prompt,
final List<ReplacementEffect> possibleReplacers, final Map<String, Object> runParams) { final List<ReplacementEffect> possibleReplacers) {
final ReplacementEffect first = possibleReplacers.get(0); final ReplacementEffect first = possibleReplacers.get(0);
if (possibleReplacers.size() == 1) { if (possibleReplacers.size() == 1) {
return first; return first;