From e2eb916d7299f1aa9ce9aa9263611f9131c60d4c Mon Sep 17 00:00:00 2001 From: Hanmac Date: Mon, 26 Dec 2016 16:57:28 +0000 Subject: [PATCH] make TokenDoubler use new Replacement Effect --- .../src/main/java/forge/ai/GameState.java | 5 +-- .../main/java/forge/ai/ability/TokenAi.java | 30 ++++++------- .../java/forge/ai/simulation/GameCopier.java | 4 +- .../ability/effects/CopyPermanentEffect.java | 38 +++++++++++----- .../java/forge/game/card/CardFactory.java | 45 ++++++++++++++++++- .../main/java/forge/game/player/Player.java | 5 --- 6 files changed, 89 insertions(+), 38 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index ae00f63fac7..e6dafdc2311 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -51,6 +51,7 @@ public abstract class GameState { public abstract IPaperCard getPaperCard(String cardName); + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(String.format("humanlife=%d\n", humanLife)); @@ -269,9 +270,7 @@ public abstract class GameState { Card c; if (cardinfo[0].startsWith("t:")) { String tokenStr = cardinfo[0].substring(2); - // TODO: Use a version of the API that doesn't return a list (i.e. these shouldn't be affected - // by doubling season, etc). - c = CardFactory.makeToken(CardFactory.TokenInfo.fromString(tokenStr), player).get(0); + c = CardFactory.makeOneToken(CardFactory.TokenInfo.fromString(tokenStr), player); } else { c = Card.fromPaperCard(getPaperCard(cardinfo[0]), player); } diff --git a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java index 764c83ef4d7..ae3ee0eeda2 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -438,16 +438,16 @@ public class TokenAi extends SpellAbilityAi { final String imageName = imageNames.get(MyRandom.getRandom().nextInt(imageNames.size())); final CardFactory.TokenInfo tokenInfo = new CardFactory.TokenInfo(substitutedName, imageName, cost, substitutedTypes, tokenKeywords, finalPower, finalToughness); - List tokens = CardFactory.makeToken(tokenInfo, ai); - if (tokens.isEmpty()) { + Card token = CardFactory.makeOneToken(tokenInfo, ai); + + if (token == null) { return null; } - final Card c = tokens.get(0); // Grant rule changes if (tokenHiddenKeywords != null) { for (final String s : tokenHiddenKeywords) { - c.addHiddenExtrinsicKeyword(s); + token.addHiddenExtrinsicKeyword(s); } } @@ -455,8 +455,8 @@ public class TokenAi extends SpellAbilityAi { if (tokenAbilities != null) { for (final String s : tokenAbilities) { final String actualAbility = host.getSVar(s); - final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, c); - c.addSpellAbility(grantedAbility); + final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, token); + token.addSpellAbility(grantedAbility); } } @@ -464,10 +464,10 @@ public class TokenAi extends SpellAbilityAi { if (tokenTriggers != null) { for (final String s : tokenTriggers) { final String actualTrigger = host.getSVar(s); - final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, c, true); + final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, token, true); final String ability = host.getSVar(parsedTrigger.getMapParams().get("Execute")); - parsedTrigger.setOverridingAbility(AbilityFactory.getAbility(ability, c)); - c.addTrigger(parsedTrigger); + parsedTrigger.setOverridingAbility(AbilityFactory.getAbility(ability, token)); + token.addTrigger(parsedTrigger); } } @@ -481,7 +481,7 @@ public class TokenAi extends SpellAbilityAi { name = actualSVar.split(":")[0]; actualSVar = actualSVar.split(":")[1]; } - c.setSVar(name, actualSVar); + token.setSVar(name, actualSVar); } } @@ -489,18 +489,18 @@ public class TokenAi extends SpellAbilityAi { if (tokenStaticAbilities != null) { for (final String s : tokenStaticAbilities) { final String actualAbility = host.getSVar(s); - c.addStaticAbilityString(actualAbility); - c.addStaticAbility(actualAbility); + token.addStaticAbilityString(actualAbility); + token.addStaticAbility(actualAbility); } } // Apply static abilities and prune dead tokens final Game game = ai.getGame(); - ComputerUtilCard.applyStaticContPT(game, c, null); - if (!notNull && c.getNetToughness() < 1) { + ComputerUtilCard.applyStaticContPT(game, token, null); + if (!notNull && token.getNetToughness() < 1) { return null; } else { - return c; + return token; } } } diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index fc7337f5e5f..07246f9641c 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -191,9 +191,7 @@ public class GameCopier { private Card createCardCopy(Game newGame, Player newOwner, Card c) { if (c.isToken() && !c.isEmblem()) { String tokenStr = new CardFactory.TokenInfo(c).toString(); - // TODO: Use a version of the API that doesn't return a list (i.e. these shouldn't be affected - // by doubling season, etc). - return CardFactory.makeToken(CardFactory.TokenInfo.fromString(tokenStr), newOwner).get(0); + return CardFactory.makeOneToken(CardFactory.TokenInfo.fromString(tokenStr), newOwner); } if (USE_FROM_PAPER_CARD && !c.isEmblem()) { return Card.fromPaperCard(c.getPaperCard(), newOwner); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java index 8b3878e7119..77860729432 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java @@ -4,6 +4,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import forge.StaticData; import forge.card.CardRulesPredicates; @@ -32,7 +33,6 @@ import forge.util.PredicateString.StringOp; import org.apache.commons.lang3.StringUtils; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -59,11 +59,11 @@ public class CopyPermanentEffect extends SpellAbilityEffect { public void resolve(final SpellAbility sa) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); - final List keywords = new ArrayList(); - final List types = new ArrayList(); - final List svars = new ArrayList(); - final List triggers = new ArrayList(); - final List pumpKeywords = new ArrayList(); + final List keywords = Lists.newArrayList(); + final List types = Lists.newArrayList(); + final List svars = Lists.newArrayList(); + final List triggers = Lists.newArrayList(); + final List pumpKeywords = Lists.newArrayList(); final long timestamp = game.getNextTimestamp(); @@ -119,8 +119,8 @@ public class CopyPermanentEffect extends SpellAbilityEffect { cards = Lists.newArrayList(Iterables.filter(cards, cpp)); } if (sa.hasParam("RandomCopied")) { - List copysource = new ArrayList(cards); - List choice = new ArrayList(); + List copysource = Lists.newArrayList(cards); + List choice = Lists.newArrayList(); final String num = sa.hasParam("RandomNum") ? sa.getParam("RandomNum") : "1"; int ncopied = AbilityUtils.calculateAmount(hostCard, num, sa); while(ncopied > 0) { @@ -156,8 +156,26 @@ public class CopyPermanentEffect extends SpellAbilityEffect { for (final Card c : tgtCards) { if ((tgt == null) || c.canBeTargetedBy(sa)) { - int multiplier = numCopies * hostCard.getController().getTokenDoublersMagnitude(); - final List crds = new ArrayList(multiplier); + int multiplier = numCopies; + + final Map repParams = Maps.newHashMap(); + repParams.put("Event", "CreateToken"); + repParams.put("Affected", controller); + repParams.put("TokenNum", multiplier); + repParams.put("EffectOnly", true); + + switch (game.getReplacementHandler().run(repParams)) { + case NotReplaced: + break; + case Updated: { + multiplier = (int) repParams.get("TokenNum"); + break; + } + default: + return ; + } + + final List crds = Lists.newArrayListWithCapacity(multiplier); for (int i = 0; i < multiplier; i++) { final Card copy = CardFactory.copyCopiableCharacteristics(c, sa.getActivatingPlayer()); diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 8551b8b6301..e6c1603d663 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -25,6 +25,7 @@ import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import forge.ImageKeys; import forge.StaticData; @@ -797,9 +798,33 @@ public class CardFactory { } public static List makeToken(final TokenInfo tokenInfo, final Player controller) { + return makeToken(tokenInfo, controller, true); + } + + public static List makeToken(final TokenInfo tokenInfo, final Player controller, final boolean applyMultiplier) { final List list = Lists.newArrayList(); - final Card c = tokenInfo.toCard(controller.getGame()); - final int multiplier = controller.getTokenDoublersMagnitude(); + final Game game = controller.getGame(); + final Card c = tokenInfo.toCard(game); + + int multiplier = 1; + + final Map repParams = Maps.newHashMap(); + repParams.put("Event", "CreateToken"); + repParams.put("Affected", controller); + repParams.put("TokenNum", multiplier); + repParams.put("EffectOnly", applyMultiplier); + + switch (game.getReplacementHandler().run(repParams)) { + case NotReplaced: + break; + case Updated: { + multiplier = (int) repParams.get("TokenNum"); + break; + } + default: + return list; + } + for (int i = 0; i < multiplier; i++) { Card temp = i == 0 ? c : copyStats(c, controller); @@ -814,6 +839,22 @@ public class CardFactory { } return list; } + + public static Card makeOneToken(final TokenInfo info, final Player controller) { + + final Game game = controller.getGame(); + final Card c = info.toCard(game); + + for (final String kw : info.intrinsicKeywords) { + c.addIntrinsicKeyword(kw); + } + + c.setOwner(controller); + c.setToken(true); + CardFactoryUtil.parseKeywords(c, c.getName()); + CardFactoryUtil.setupKeywordedAbilities(c); + return c; + } /** * Copy triggered ability diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index ba4fd01a5e9..510348ef0b7 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2563,11 +2563,6 @@ public class Player extends GameEntity implements Comparable { return CardLists.getColor(getCardsIn(ZoneType.Battlefield), color); } - public int getTokenDoublersMagnitude() { - int tokenDoublers = keywords.getAmount("TokenDoubler"); - return 1 << tokenDoublers; // pow(a,0) = 1; pow(a,1) = a - } - public final int getAmountOfKeyword(final String k) { return keywords.getAmount(k); }