diff --git a/.gitattributes b/.gitattributes index 8da9aa56e1c..41e99041d3b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -507,6 +507,7 @@ forge-game/src/main/java/forge/game/card/CardView.java -text forge-game/src/main/java/forge/game/card/CounterType.java svneol=native#text/plain forge-game/src/main/java/forge/game/card/IHasCardView.java -text forge-game/src/main/java/forge/game/card/package-info.java -text +forge-game/src/main/java/forge/game/card/token/TokenInfo.java -text forge-game/src/main/java/forge/game/combat/AttackConstraints.java -text forge-game/src/main/java/forge/game/combat/AttackRequirement.java -text forge-game/src/main/java/forge/game/combat/AttackRestriction.java -text diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index d97820916af..8016894d533 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -29,6 +29,7 @@ import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; import forge.game.card.CardFactory; import forge.game.card.CounterType; +import forge.game.card.token.TokenInfo; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.event.GameEventAttackersDeclared; @@ -217,7 +218,7 @@ public abstract class GameState { newText.append(";"); } if (c.isToken()) { - newText.append("t:" + new CardFactory.TokenInfo(c).toString()); + newText.append("t:" + new TokenInfo(c).toString()); } else { if (c.getPaperCard() == null) { return; @@ -944,8 +945,9 @@ public abstract class GameState { Card c; boolean hasSetCurSet = false; if (cardinfo[0].startsWith("t:")) { + // TODO Make sure Game State conversion works with new tokens String tokenStr = cardinfo[0].substring(2); - c = CardFactory.makeOneToken(CardFactory.TokenInfo.fromString(tokenStr), player); + c = new TokenInfo(tokenStr).makeOneToken(player); } else { PaperCard pc = StaticData.instance().getCommonCards().getCard(cardinfo[0], setCode); if (pc == null) { 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 754242a039e..cfe7282c8f8 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -9,6 +9,7 @@ import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.card.*; +import forge.game.card.token.TokenInfo; import forge.game.combat.Combat; import forge.game.cost.CostPart; import forge.game.cost.CostPutCounter; @@ -450,9 +451,9 @@ public class TokenAi extends SpellAbilityAi { } final String substitutedName = tokenName.equals("ChosenType") ? host.getChosenType() : tokenName; final String imageName = imageNames.get(MyRandom.getRandom().nextInt(imageNames.size())); - final CardFactory.TokenInfo tokenInfo = new CardFactory.TokenInfo(substitutedName, imageName, + final TokenInfo tokenInfo = new TokenInfo(substitutedName, imageName, cost, substitutedTypes, tokenKeywords, finalPower, finalToughness); - Card token = CardFactory.makeOneToken(tokenInfo, ai); + Card token = tokenInfo.makeOneToken(ai); if (token == null) { return null; 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 37096760fe4..105895037cb 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -22,6 +22,7 @@ import forge.game.card.Card; import forge.game.card.CardFactory; import forge.game.card.CardFactoryUtil; import forge.game.card.CounterType; +import forge.game.card.token.TokenInfo; import forge.game.combat.Combat; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; @@ -236,8 +237,7 @@ public class GameCopier { private static final boolean USE_FROM_PAPER_CARD = true; private Card createCardCopy(Game newGame, Player newOwner, Card c) { if (c.isToken() && !c.isEmblem()) { - String tokenStr = new CardFactory.TokenInfo(c).toString(); - Card result = CardFactory.makeOneToken(CardFactory.TokenInfo.fromString(tokenStr), newOwner); + Card result = new TokenInfo(c).makeOneToken(newOwner); CardFactory.copyCopiableCharacteristics(c, result); CardFactory.copyCopiableAbilities(c, result); return result; diff --git a/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java b/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java index b8a2d892077..85d8cb915b0 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/TokenEffect.java @@ -20,6 +20,7 @@ package forge.game.ability.effects; import java.util.Arrays; import java.util.List; +import forge.game.card.token.TokenInfo; import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -273,9 +274,9 @@ public class TokenEffect extends SpellAbilityEffect { final Game game = controller.getGame(); for (int i = 0; i < finalAmount; i++) { final String imageName = imageNames.get(MyRandom.getRandom().nextInt(imageNames.size())); - final CardFactory.TokenInfo tokenInfo = new CardFactory.TokenInfo(substitutedName, imageName, + final TokenInfo tokenInfo = new TokenInfo(substitutedName, imageName, cost, substitutedTypes, this.tokenKeywords, finalPower, finalToughness); - final List tokens = CardFactory.makeToken(tokenInfo, controller, cause != null); + final List tokens = tokenInfo.makeTokenWithMultiplier(controller, cause != null); // Grant rule changes if (this.tokenHiddenKeywords != null) { 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 c90164860f2..e329d61ff1f 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -685,166 +685,6 @@ public class CardFactory { } to.changeText(); } - - public static class TokenInfo { - final String name; - final String imageName; - final String manaCost; - final String[] types; - final String[] intrinsicKeywords; - final int basePower; - final int baseToughness; - - public TokenInfo(String name, String imageName, String manaCost, String[] types, - String[] intrinsicKeywords, int basePower, int baseToughness) { - this.name = name; - this.imageName = imageName; - this.manaCost = manaCost; - this.types = types; - this.intrinsicKeywords = intrinsicKeywords; - this.basePower = basePower; - this.baseToughness = baseToughness; - } - - public TokenInfo(Card c) { - this.name = c.getName(); - this.imageName = ImageKeys.getTokenImageName(c.getImageKey()); - this.manaCost = c.getManaCost().toString(); - this.types = getCardTypes(c); - this.intrinsicKeywords = c.getKeywords().toArray(new String[0]); - this.basePower = c.getBasePower(); - this.baseToughness = c.getBaseToughness(); - } - - private static String[] getCardTypes(Card c) { - List relevantTypes = Lists.newArrayList(); - for (CoreType t : c.getType().getCoreTypes()) { - relevantTypes.add(t.name()); - } - Iterables.addAll(relevantTypes, c.getType().getSubtypes()); - if (c.getType().isLegendary()) { - relevantTypes.add("Legendary"); - } - return relevantTypes.toArray(new String[relevantTypes.size()]); - } - - private Card toCard(Game game) { - final Card c = new Card(game.nextCardId(), game); - c.setName(name); - c.setImageKey(ImageKeys.getTokenKey(imageName)); - - // TODO - most tokens mana cost is 0, this needs to be fixed - // c.setManaCost(manaCost); - c.setColor(manaCost); - c.setToken(true); - - for (final String t : types) { - c.addType(t); - } - - c.setBasePower(basePower); - c.setBaseToughness(baseToughness); - return c; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(name).append(','); - sb.append("P:").append(basePower).append(','); - sb.append("T:").append(baseToughness).append(','); - sb.append("Cost:").append(manaCost).append(','); - sb.append("Types:").append(Joiner.on('-').join(types)).append(','); - sb.append("Keywords:").append(Joiner.on('-').join(intrinsicKeywords)).append(','); - sb.append("Image:").append(imageName); - return sb.toString(); - } - - public static TokenInfo fromString(String str) { - final String[] tokenInfo = str.split(","); - int power = 0; - int toughness = 0; - String manaCost = "0"; - String[] types = null; - String[] keywords = null; - String imageName = null; - for (String info : tokenInfo) { - int index = info.indexOf(':'); - if (index == -1) { - continue; - } - String remainder = info.substring(index + 1); - if (info.startsWith("P:")) { - power = Integer.parseInt(remainder); - } else if (info.startsWith("T:")) { - toughness = Integer.parseInt(remainder); - } else if (info.startsWith("Cost:")) { - manaCost = remainder; - } else if (info.startsWith("Types:")) { - types = remainder.split("-"); - } else if (info.startsWith("Keywords:")) { - keywords = remainder.split("-"); - } else if (info.startsWith("Image:")) { - imageName = remainder; - } - } - return new TokenInfo(tokenInfo[0], imageName, manaCost, types, keywords, power, toughness); - } - } - - public static List makeToken(final TokenInfo tokenInfo, final Player controller, final boolean applyMultiplier) { - final List list = Lists.newArrayList(); - final Game game = controller.getGame(); - - 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 = tokenInfo.toCard(game); - - for (final String kw : tokenInfo.intrinsicKeywords) { - temp.addIntrinsicKeyword(kw); - } - temp.setOwner(controller); - temp.setToken(true); - CardFactoryUtil.parseKeywords(temp, temp.getName()); - CardFactoryUtil.setupKeywordedAbilities(temp); - list.add(temp); - } - 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/card/token/TokenInfo.java b/forge-game/src/main/java/forge/game/card/token/TokenInfo.java new file mode 100644 index 00000000000..5a5aadc5d23 --- /dev/null +++ b/forge-game/src/main/java/forge/game/card/token/TokenInfo.java @@ -0,0 +1,181 @@ +package forge.game.card.token; + +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.card.CardType; +import forge.game.Game; +import forge.game.card.Card; +import forge.game.card.CardFactoryUtil; +import forge.game.player.Player; + +import java.util.List; +import java.util.Map; + +public class TokenInfo { + final String name; + final String imageName; + final String manaCost; + final String[] types; + final String[] intrinsicKeywords; + final int basePower; + final int baseToughness; + + public TokenInfo(String name, String imageName, String manaCost, String[] types, + String[] intrinsicKeywords, int basePower, int baseToughness) { + this.name = name; + this.imageName = imageName; + this.manaCost = manaCost; + this.types = types; + this.intrinsicKeywords = intrinsicKeywords; + this.basePower = basePower; + this.baseToughness = baseToughness; + } + + public TokenInfo(Card c) { + this.name = c.getName(); + this.imageName = ImageKeys.getTokenImageName(c.getImageKey()); + this.manaCost = c.getManaCost().toString(); + this.types = getCardTypes(c); + this.intrinsicKeywords = c.getKeywords().toArray(new String[0]); + this.basePower = c.getBasePower(); + this.baseToughness = c.getBaseToughness(); + } + + public TokenInfo(String str) { + final String[] tokenInfo = str.split(","); + int power = 0; + int toughness = 0; + String manaCost = "0"; + String[] types = null; + String[] keywords = null; + String imageName = null; + for (String info : tokenInfo) { + int index = info.indexOf(':'); + if (index == -1) { + continue; + } + String remainder = info.substring(index + 1); + if (info.startsWith("P:")) { + power = Integer.parseInt(remainder); + } else if (info.startsWith("T:")) { + toughness = Integer.parseInt(remainder); + } else if (info.startsWith("Cost:")) { + manaCost = remainder; + } else if (info.startsWith("Types:")) { + types = remainder.split("-"); + } else if (info.startsWith("Keywords:")) { + keywords = remainder.split("-"); + } else if (info.startsWith("Image:")) { + imageName = remainder; + } + } + + this.name = tokenInfo[0]; + this.imageName = imageName; + this.manaCost = manaCost; + this.types = types; + this.intrinsicKeywords = keywords; + this.basePower = power; + this.baseToughness = toughness; + } + + private static String[] getCardTypes(Card c) { + List relevantTypes = Lists.newArrayList(); + for (CardType.CoreType t : c.getType().getCoreTypes()) { + relevantTypes.add(t.name()); + } + Iterables.addAll(relevantTypes, c.getType().getSubtypes()); + if (c.getType().isLegendary()) { + relevantTypes.add("Legendary"); + } + return relevantTypes.toArray(new String[relevantTypes.size()]); + } + + private Card toCard(Game game) { + final Card c = new Card(game.nextCardId(), game); + c.setName(name); + c.setImageKey(ImageKeys.getTokenKey(imageName)); + + // TODO - most tokens mana cost is 0, this needs to be fixed + // c.setManaCost(manaCost); + c.setColor(manaCost); + c.setToken(true); + + for (final String t : types) { + c.addType(t); + } + + c.setBasePower(basePower); + c.setBaseToughness(baseToughness); + return c; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(name).append(','); + sb.append("P:").append(basePower).append(','); + sb.append("T:").append(baseToughness).append(','); + sb.append("Cost:").append(manaCost).append(','); + sb.append("Types:").append(Joiner.on('-').join(types)).append(','); + sb.append("Keywords:").append(Joiner.on('-').join(intrinsicKeywords)).append(','); + sb.append("Image:").append(imageName); + return sb.toString(); + } + + public List makeTokenWithMultiplier(final Player controller, final boolean applyMultiplier) { + final List list = Lists.newArrayList(); + final Game game = controller.getGame(); + + 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 = toCard(game); + + for (final String kw : intrinsicKeywords) { + temp.addIntrinsicKeyword(kw); + } + temp.setOwner(controller); + temp.setToken(true); + CardFactoryUtil.parseKeywords(temp, temp.getName()); + CardFactoryUtil.setupKeywordedAbilities(temp); + list.add(temp); + } + return list; + } + + public Card makeOneToken(final Player controller) { + final Game game = controller.getGame(); + final Card c = toCard(game); + + for (final String kw : intrinsicKeywords) { + c.addIntrinsicKeyword(kw); + } + + c.setOwner(controller); + c.setToken(true); + CardFactoryUtil.parseKeywords(c, c.getName()); + CardFactoryUtil.setupKeywordedAbilities(c); + return c; + } +} \ No newline at end of file