Support saving/restoring game state that has creature tokens.

This commit is contained in:
Myrd
2015-01-03 19:15:44 +00:00
parent 06801023b5
commit 2853af3a10
5 changed files with 153 additions and 33 deletions

View File

@@ -14,6 +14,7 @@ import forge.game.Game;
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;
import forge.game.card.CardFactory;
import forge.game.card.CounterType; import forge.game.card.CounterType;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -94,7 +95,11 @@ public abstract class GameState {
if (newText.length() > 0) { if (newText.length() > 0) {
newText.append(";"); newText.append(";");
} }
newText.append(c.getName()); if (c.isToken()) {
newText.append("t:" + new CardFactory.TokenInfo(c).toString());
} else {
newText.append(c.getName());
}
if (zoneType == ZoneType.Battlefield) { if (zoneType == ZoneType.Battlefield) {
if (c.isTapped()) { if (c.isTapped()) {
newText.append("|Tapped:True"); newText.append("|Tapped:True");
@@ -206,8 +211,17 @@ public abstract class GameState {
if (life > 0) p.setLife(life, null); if (life > 0) p.setLife(life, null);
for (Entry<ZoneType, CardCollectionView> kv : playerCards.entrySet()) { for (Entry<ZoneType, CardCollectionView> kv : playerCards.entrySet()) {
if (kv.getKey() == ZoneType.Battlefield) { if (kv.getKey() == ZoneType.Battlefield) {
p.getZone(kv.getKey()).setCards(new ArrayList<Card>()); ArrayList<Card> cards = new ArrayList<Card>();
for (final Card c : kv.getValue()) { for (final Card c : kv.getValue()) {
if (c.isToken()) {
cards.add(c);
}
}
p.getZone(kv.getKey()).setCards(cards);
for (final Card c : kv.getValue()) {
if (c.isToken()) {
continue;
}
boolean tapped = c.isTapped(); boolean tapped = c.isTapped();
boolean sickness = c.hasSickness(); boolean sickness = c.hasSickness();
p.getZone(ZoneType.Hand).add(c); p.getZone(ZoneType.Hand).add(c);
@@ -237,8 +251,15 @@ public abstract class GameState {
for (final String element : data) { for (final String element : data) {
final String[] cardinfo = element.trim().split("\\|"); final String[] cardinfo = element.trim().split("\\|");
//System.out.println("paper card " + cardinfo[0]); Card c;
final Card c = Card.fromPaperCard(getPaperCard(cardinfo[0]), player); 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);
} else {
c = Card.fromPaperCard(getPaperCard(cardinfo[0]), player);
}
boolean hasSetCurSet = false; boolean hasSetCurSet = false;
for (final String info : cardinfo) { for (final String info : cardinfo) {
@@ -259,7 +280,7 @@ public abstract class GameState {
} }
} }
if (!hasSetCurSet) { if (!hasSetCurSet && !c.isToken()) {
c.setSetCode(c.getMostRecentSet()); c.setSetCode(c.getMostRecentSet());
} }

View File

@@ -368,9 +368,10 @@ public class TokenAi extends SpellAbilityAi {
} }
} }
final String substitutedName = tokenName.equals("ChosenType") ? host.getChosenType() : tokenName; final String substitutedName = tokenName.equals("ChosenType") ? host.getChosenType() : tokenName;
final List<Card> tokens = CardFactory.makeToken(substitutedName, final String imageName = imageNames.get(MyRandom.getRandom().nextInt(imageNames.size()));
imageNames.get(MyRandom.getRandom().nextInt(imageNames.size())), final CardFactory.TokenInfo tokenInfo = new CardFactory.TokenInfo(substitutedName, imageName,
ai, cost, substitutedTypes, finalPower, finalToughness, tokenKeywords); cost, substitutedTypes, tokenKeywords, finalPower, finalToughness);
final List<Card> tokens = CardFactory.makeToken(tokenInfo, ai);
// Grant rule changes // Grant rule changes
if (tokenHiddenKeywords != null) { if (tokenHiddenKeywords != null) {

View File

@@ -87,6 +87,13 @@ public class ImageKeys {
return ImageKeys.TOKEN_PREFIX + tokenName; return ImageKeys.TOKEN_PREFIX + tokenName;
} }
public static String getTokenImageName(String tokenKey) {
if (!tokenKey.startsWith(ImageKeys.TOKEN_PREFIX)) {
return null;
}
return tokenKey.substring(ImageKeys.TOKEN_PREFIX.length());
}
public static File getImageFile(String key) { public static File getImageFile(String key) {
if (StringUtils.isEmpty(key)) { if (StringUtils.isEmpty(key)) {
return null; return null;

View File

@@ -226,10 +226,11 @@ public class TokenEffect extends SpellAbilityEffect {
final boolean imprint = sa.hasParam("ImprintTokens"); final boolean imprint = sa.hasParam("ImprintTokens");
for (final Player controller : AbilityUtils.getDefinedPlayers(host, this.tokenOwner, sa)) { for (final Player controller : AbilityUtils.getDefinedPlayers(host, this.tokenOwner, sa)) {
for (int i = 0; i < finalAmount; i++) { for (int i = 0; i < finalAmount; i++) {
final List<Card> tokens = CardFactory.makeToken(substitutedName, final String imageName = imageNames.get(MyRandom.getRandom().nextInt(imageNames.size()));
imageNames.get(MyRandom.getRandom().nextInt(imageNames.size())), final CardFactory.TokenInfo tokenInfo = new CardFactory.TokenInfo(substitutedName, imageName,
controller, cost, substitutedTypes, finalPower, finalToughness, this.tokenKeywords); cost, substitutedTypes, this.tokenKeywords, finalPower, finalToughness);
for(Card tok : tokens) { final List<Card> tokens = CardFactory.makeToken(tokenInfo, controller);
for (Card tok : tokens) {
if (this.tokenTapped) { if (this.tokenTapped) {
tok.setTapped(true); tok.setTapped(true);
} }

View File

@@ -22,6 +22,7 @@ import forge.card.CardStateName;
import forge.card.CardRules; import forge.card.CardRules;
import forge.card.CardSplitType; import forge.card.CardSplitType;
import forge.card.CardType; import forge.card.CardType;
import forge.card.CardType.CoreType;
import forge.card.ICardFace; import forge.card.ICardFace;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.Game; import forge.game.Game;
@@ -45,6 +46,9 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
/** /**
* <p> * <p>
* AbstractCardFactory class. * AbstractCardFactory class.
@@ -605,31 +609,116 @@ public class CardFactory {
} }
} }
public static List<Card> makeToken(final String name, final String imageName, final Player controller, public static class TokenInfo {
final String manaCost, final String[] types, final int basePower, final int baseToughness, final String name;
final String[] intrinsicKeywords) { final String imageName;
final List<Card> list = new ArrayList<Card>(); final String manaCost;
final Card c = new Card(controller.getGame().nextCardId(), controller.getGame()); final String[] types;
c.setName(name); final String[] intrinsicKeywords;
c.setImageKey(ImageKeys.getTokenKey(imageName)); final int basePower;
final int baseToughness;
// TODO - most tokens mana cost is 0, this needs to be fixed public TokenInfo(String name, String imageName, String manaCost, String[] types,
// c.setManaCost(manaCost); String[] intrinsicKeywords, int basePower, int baseToughness) {
c.addColor(manaCost); this.name = name;
c.setToken(true); this.imageName = imageName;
this.manaCost = manaCost;
for (final String t : types) { this.types = types;
c.addType(t); this.intrinsicKeywords = intrinsicKeywords;
this.basePower = basePower;
this.baseToughness = baseToughness;
} }
c.setBasePower(basePower); public TokenInfo(Card c) {
c.setBaseToughness(baseToughness); 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) {
ArrayList<String> relevantTypes = new ArrayList<String>();
for (CoreType t : c.getType().getCoreTypes()) {
relevantTypes.add(t.name());
}
Iterables.addAll(relevantTypes, c.getType().getSubtypes());
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.addColor(manaCost);
c.setToken(true);
for (final String t : types) {
c.addType(t);
}
c.setBasePower(basePower);
c.setBaseToughness(baseToughness);
return c;
}
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<Card> makeToken(final TokenInfo tokenInfo, final Player controller) {
final List<Card> list = new ArrayList<Card>();
final Card c = tokenInfo.toCard(controller.getGame());
final int multiplier = controller.getTokenDoublersMagnitude(); final int multiplier = controller.getTokenDoublersMagnitude();
for (int i = 0; i < multiplier; i++) { for (int i = 0; i < multiplier; i++) {
Card temp = copyStats(c, controller); Card temp = copyStats(c, controller);
for (final String kw : intrinsicKeywords) { for (final String kw : tokenInfo.intrinsicKeywords) {
temp.addIntrinsicKeyword(kw); temp.addIntrinsicKeyword(kw);
} }
temp.setOwner(controller); temp.setOwner(controller);
@@ -640,6 +729,7 @@ public class CardFactory {
} }
return list; return list;
} }
/** /**
* Copy triggered ability * Copy triggered ability
* *