optimizations + leave game fix

This commit is contained in:
BetaSteward 2011-03-10 22:05:15 -05:00
parent 99735b368b
commit 42509dd4f8
21 changed files with 175 additions and 120 deletions

View file

@ -33,7 +33,7 @@ public class CardsStorage {
static {
for (ExpansionSet set : Sets.getInstance().values()) {
setCodes.add(set.getCode());
Set<Card> cards = set.createCards();
List<Card> cards = set.getCards();
allCards.addAll(cards);
for (Card card : cards) {
if (CardUtil.isLand(card) && !CardUtil.isBasicLand(card)) {

View file

@ -15,7 +15,7 @@ public class CardsStorage {
static {
for (ExpansionSet set: Sets.getInstance().values()) {
allCards.addAll(set.createCards());
allCards.addAll(set.getCards());
}
Set<String> names = new HashSet<String>();
for (Card card : allCards) {

View file

@ -84,6 +84,11 @@ public class TwoPlayerDuel extends GameImpl<TwoPlayerDuel> {
return opponents;
}
@Override
public void leave(UUID playerId) {
}
@Override
public TwoPlayerDuel copy() {
return new TwoPlayerDuel(this);

View file

@ -82,7 +82,7 @@ public class Sets extends HashMap<String, ExpansionSet> {
private void addSet(ExpansionSet set) {
this.put(set.getCode(), set);
for (Card card: set.createCards()) {
for (Card card: set.getCards()) {
names.add(card.getName());
}
}

View file

@ -43,7 +43,7 @@ import mage.game.Game;
public abstract class MageObjectImpl<T extends MageObjectImpl<T>> implements MageObject {
protected final UUID objectId;
protected UUID objectId;
protected String name;
protected ManaCosts<ManaCost> manaCost;

View file

@ -96,7 +96,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
this.choices = new Choices();
}
public AbilityImpl(AbilityImpl<T> ability) {
public AbilityImpl(final AbilityImpl<T> ability) {
this.id = ability.id;
this.originalId = ability.originalId;
this.abilityType = ability.abilityType;

View file

@ -29,11 +29,12 @@
package mage.abilities.costs.mana;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import mage.Constants.ColoredManaSymbol;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.VariableCost;
import mage.abilities.mana.ManaOptions;
import mage.game.Game;
@ -47,6 +48,8 @@ import mage.target.Targets;
*/
public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements ManaCosts<T> {
private static Map<String, ManaCosts> costs = new HashMap<String, ManaCosts>();
public ManaCostsImpl() {}
public ManaCostsImpl(String mana) {
@ -196,32 +199,41 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
@Override
public void load(String mana) {
this.clear();
if (mana == null || mana.length() == 0)
return;
String[] symbols = mana.split("^\\{|\\}\\{|\\}$");
for (String symbol: symbols) {
if (symbol.length() > 0) {
if (symbol.length() == 1 || isNumeric(symbol)) {
if (Character.isDigit(symbol.charAt(0))) {
this.add((T)new GenericManaCost(Integer.valueOf(symbol)));
if (costs.containsKey(mana)) {
ManaCosts<T> savedCosts = costs.get(mana);
for (ManaCost cost: savedCosts) {
this.add((T)cost.copy());
}
}
else {
if (mana == null || mana.length() == 0)
return;
String[] symbols = mana.split("^\\{|\\}\\{|\\}$");
for (String symbol: symbols) {
if (symbol.length() > 0) {
if (symbol.length() == 1 || isNumeric(symbol)) {
if (Character.isDigit(symbol.charAt(0))) {
this.add((T)new GenericManaCost(Integer.valueOf(symbol)));
}
else {
if (!symbol.equals("X"))
this.add((T)new ColoredManaCost(ColoredManaSymbol.lookup(symbol.charAt(0))));
else
this.add((T)new VariableManaCost());
//TODO: handle multiple {X} and/or {Y} symbols
}
}
else {
if (!symbol.equals("X"))
this.add((T)new ColoredManaCost(ColoredManaSymbol.lookup(symbol.charAt(0))));
else
this.add((T)new VariableManaCost());
//TODO: handle multiple {X} and/or {Y} symbols
}
}
else {
if (Character.isDigit(symbol.charAt(0))) {
this.add((T)new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2))));
}
else {
this.add((T)new HybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)), ColoredManaSymbol.lookup(symbol.charAt(2))));
if (Character.isDigit(symbol.charAt(0))) {
this.add((T)new MonoHybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(2))));
}
else {
this.add((T)new HybridManaCost(ColoredManaSymbol.lookup(symbol.charAt(0)), ColoredManaSymbol.lookup(symbol.charAt(2))));
}
}
}
}
costs.put(mana, this.copy());
}
}

View file

@ -57,6 +57,7 @@ public interface Card extends MageObject {
public String getExpansionSetCode();
public void setExpansionSetCode(String expansionSetCode);
public void assignNewId();
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag);
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game);
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId);

View file

@ -30,6 +30,7 @@ package mage.cards;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
@ -66,8 +67,7 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
this(ownerId, name);
this.rarity = rarity;
this.cardNumber = cardNumber;
for (CardType newCardType: cardTypes)
this.cardType.add(newCardType);
this.cardType.addAll(Arrays.asList(cardTypes));
this.manaCost.load(costs);
if (cardType.contains(CardType.LAND))
addAbility(new PlayLandAbility(name));
@ -95,6 +95,12 @@ public abstract class CardImpl<T extends CardImpl<T>> extends MageObjectImpl<T>
watchers = card.watchers.copy();
}
@Override
public void assignNewId() {
this.objectId = UUID.randomUUID();
this.abilities.setSourceId(objectId);
}
public static Card createCard(String name) {
try {
Class<?> theClass = Class.forName(name);

View file

@ -61,9 +61,9 @@ public abstract class ExpansionSet implements Serializable {
protected String symbolCode;
protected Date releaseDate;
protected ExpansionSet parentSet;
protected List<Class> cards;
protected List<Card> cards;
protected SetType setType;
protected Map<Rarity, List<Class>> rarities;
protected Map<Rarity, List<Card>> rarities;
protected String blockName;
protected boolean hasBoosters = false;
@ -83,7 +83,7 @@ public abstract class ExpansionSet implements Serializable {
this.rarities = getCardsByRarity();
}
public List<Class> getCards() {
public List<Card> getCards() {
return cards;
}
@ -107,7 +107,7 @@ public abstract class ExpansionSet implements Serializable {
return setType;
}
public Card createCard(Class clazz) {
private Card createCard(Class clazz) {
try {
Constructor<?> con = clazz.getConstructor(new Class[]{UUID.class});
return (Card) con.newInstance(new Object[]{null});
@ -118,49 +118,46 @@ public abstract class ExpansionSet implements Serializable {
}
}
public Set<Card> createCards() {
Set<Card> created = new HashSet<Card>();
for (Class clazz : cards) {
created.add(createCard(clazz));
}
return created;
}
@Override
public String toString() {
return name;
}
public Card findCard(String name) {
for (Card card : createCards()) {
if (name.equals(card.getName()))
return card;
for (Card card : cards) {
if (name.equals(card.getName())) {
Card newCard = card.copy();
newCard.assignNewId();
return newCard;
}
}
return null;
}
public Card findCard(String name, boolean random) {
List<Card> cards = new ArrayList<Card>();
for (Card card : createCards()) {
List<Card> foundCards = new ArrayList<Card>();
for (Card card : cards) {
if (name.equals(card.getName())) {
cards.add(card);
foundCards.add(card);
}
}
if (cards.size() > 0) {
return cards.get(rnd.nextInt(cards.size()));
if (foundCards.size() > 0) {
Card newCard = foundCards.get(rnd.nextInt(foundCards.size())).copy();
newCard.assignNewId();
return newCard;
}
return null;
}
public String findCard(int cardNum) {
for (Card card : createCards()) {
for (Card card : cards) {
if (card.getCardNumber() == cardNum)
return card.getClass().getCanonicalName();
}
return null;
}
private ArrayList<Class> getCardClassesForPackage(String packageName) {
private List<Card> getCardClassesForPackage(String packageName) {
ClassLoader classLoader = this.getClass().getClassLoader();
assert classLoader != null;
String path = packageName.replace('.', '/');
@ -187,7 +184,7 @@ public abstract class ExpansionSet implements Serializable {
e.printStackTrace();
}
}
ArrayList<Class> classes = new ArrayList<Class>();
List<Class> classes = new ArrayList<Class>();
if (isLoadingFromJar) {
if (jarPath.contains("!")) {
jarPath = jarPath.substring(0, jarPath.lastIndexOf('!'));
@ -214,7 +211,11 @@ public abstract class ExpansionSet implements Serializable {
}
}
}
return classes;
List<Card> newCards = new ArrayList<Card>();
for (Class clazz: classes) {
newCards.add(createCard(clazz));
}
return newCards;
}
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
@ -276,14 +277,13 @@ public abstract class ExpansionSet implements Serializable {
return classes;
}
private Map<Rarity, List<Class>> getCardsByRarity() {
Map<Rarity, List<Class>> cardsByRarity = new HashMap<Rarity, List<Class>>();
private Map<Rarity, List<Card>> getCardsByRarity() {
Map<Rarity, List<Card>> cardsByRarity = new HashMap<Rarity, List<Card>>();
for (Class clazz : cards) {
Card card = createCard(clazz);
for (Card card : cards) {
if (!cardsByRarity.containsKey(card.getRarity()))
cardsByRarity.put(card.getRarity(), new ArrayList<Class>());
cardsByRarity.get(card.getRarity()).add(clazz);
cardsByRarity.put(card.getRarity(), new ArrayList<Card>());
cardsByRarity.get(card.getRarity()).add(card);
}
return cardsByRarity;
@ -332,7 +332,7 @@ public abstract class ExpansionSet implements Serializable {
return null;
int size = rarities.get(rarity).size();
if (size > 0) {
return createCard(rarities.get(rarity).get(rnd.nextInt(size)));
return rarities.get(rarity).get(rnd.nextInt(size)).copy();
}
return null;
}

View file

@ -28,7 +28,6 @@
package mage.game;
import mage.Constants;
import mage.game.match.MatchType;
import mage.cards.Card;
import mage.game.stack.SpellStack;
@ -61,7 +60,6 @@ import mage.game.permanent.PermanentCard;
import mage.game.turn.Phase;
import mage.game.turn.Step;
import mage.game.turn.Turn;
import mage.players.Library;
import mage.players.Player;
import mage.players.PlayerList;
import mage.players.Players;
@ -97,6 +95,7 @@ public interface Game extends MageItem, Serializable {
public boolean canPlaySorcery(UUID playerId);
public UUID getActivePlayerId();
public UUID getPriorityPlayerId();
public void leave(UUID playerId);
public boolean isGameOver();
public Battlefield getBattlefield();
public SpellStack getStack();

View file

@ -53,7 +53,6 @@ import mage.game.stack.StackObject;
import mage.game.turn.Phase;
import mage.game.turn.Step;
import mage.game.turn.Turn;
import mage.players.Library;
import mage.players.Player;
import mage.players.PlayerList;
import mage.players.Players;
@ -114,9 +113,10 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
this.range = game.range;
this.attackOption = game.attackOption;
this.state = game.state.copy();
for (Map.Entry<UUID, Card> entry: game.gameCards.entrySet()) {
this.gameCards.put(entry.getKey(), entry.getValue().copy());
}
// for (Map.Entry<UUID, Card> entry: game.gameCards.entrySet()) {
// this.gameCards.put(entry.getKey(), entry.getValue().copy());
// }
this.gameCards = game.gameCards;
}
@Override
@ -457,7 +457,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
public synchronized void quit(UUID playerId) {
Player player = state.getPlayer(playerId);
if (player != null) {
player.leaveGame(this);
leave(playerId);
fireInformEvent(player.getName() + " has left the game.");
}
}
@ -869,6 +869,36 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
return getActivePlayerId().equals(playerId) && getStack().isEmpty() && isMainPhase();
}
@Override
public void leave(UUID playerId) {
Player player = getPlayer(playerId);
player.leave();
//20100423 - 800.4a
for (Iterator<Permanent> it = getBattlefield().getAllPermanents().iterator(); it.hasNext();) {
Permanent perm = it.next();
if (perm.getOwnerId().equals(playerId)) {
if (perm.getAttachedTo() != null) {
Permanent attachedTo = getPermanent(perm.getAttachedTo());
if (attachedTo != null)
attachedTo.removeAttachment(perm.getId(), this);
}
it.remove();
}
}
for (Iterator<StackObject> it = getStack().iterator(); it.hasNext();) {
StackObject object = it.next();
if (object.getControllerId().equals(playerId)) {
it.remove();
}
}
for (Iterator<Permanent> it = getBattlefield().getAllPermanents().iterator(); it.hasNext();) {
Permanent perm = it.next();
if (perm.getControllerId().equals(playerId)) {
perm.moveToExile(null, "", null, this);
}
}
}
@Override
public UUID getActivePlayerId() {
return state.getActivePlayerId();

View file

@ -34,6 +34,7 @@ import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import mage.Constants.CardType;
@ -54,8 +55,8 @@ public class Battlefield implements Serializable {
public Battlefield () {}
public Battlefield(final Battlefield battlefield) {
for (UUID permId: battlefield.field.keySet()) {
field.put(permId, battlefield.field.get(permId).copy());
for (Entry<UUID, Permanent> entry: battlefield.field.entrySet()) {
field.put(entry.getKey(), entry.getValue().copy());
}
}

View file

@ -83,20 +83,32 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
public void reset(Game game) {
// when the permanent is reset copy all original values from the card
// must copy card each reset so that the original values don't get modified
Card copy = game.getCard(objectId).copy();
copyFromCard(copy);
// Card copy = game.getCard(objectId).copy();
copyFromCard(game.getCard(objectId));
super.reset(game);
}
protected void copyFromCard(Card card) {
this.name = card.getName();
this.abilities = card.getAbilities();
this.abilities.setControllerId(this.controllerId);
this.cardType = card.getCardType();
this.color = card.getColor();
this.manaCost = card.getManaCost();
this.power = card.getPower();
this.toughness = card.getToughness();
this.manaCost = card.getManaCost().copy();
this.color = card.getColor().copy();
this.power = card.getPower().copy();
this.toughness = card.getToughness().copy();
this.loyalty = card.getLoyalty().copy();
this.abilities = card.getAbilities().copy();
this.abilities.setControllerId(controllerId);
this.cardType.clear();
for (CardType cType: card.getCardType()) {
this.cardType.add(cType);
}
this.subtype.clear();
for (String subType: card.getSubtype()) {
this.subtype.add(subType);
}
this.supertype.clear();
for (String superType: card.getSupertype()) {
this.supertype.add(superType);
}
if (card instanceof LevelerCard) {
LevelAbility level = ((LevelerCard)card).getLevel(this.getCounters().getCount("Level"));
if (level != null) {
@ -107,8 +119,6 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
}
}
}
this.subtype = card.getSubtype();
this.supertype = card.getSupertype();
this.art = card.getArt();
this.expansionSetCode = card.getExpansionSetCode();
this.rarity = card.getRarity();

View file

@ -55,6 +55,7 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
protected boolean tapped;
protected boolean flipped;
protected UUID originalControllerId;
protected UUID controllerId;
protected int damage;
protected boolean controlledFromStartOfTurn;
@ -72,12 +73,14 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
public PermanentImpl(UUID ownerId, UUID controllerId, String name) {
super(ownerId, name);
this.originalControllerId = controllerId;
this.controllerId = controllerId;
this.counters = new Counters();
}
public PermanentImpl(UUID id, UUID ownerId, UUID controllerId, String name) {
super(id, ownerId, name);
this.originalControllerId = controllerId;
this.controllerId = controllerId;
this.counters = new Counters();
}
@ -86,6 +89,7 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
super(permanent);
this.tapped = permanent.tapped;
this.flipped = permanent.flipped;
this.originalControllerId = permanent.originalControllerId;
this.controllerId = permanent.controllerId;
this.damage = permanent.damage;
this.controlledFromStartOfTurn = permanent.controlledFromStartOfTurn;
@ -111,7 +115,7 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
@Override
public void reset(Game game) {
// this.controllerId = ownerId;
this.controllerId = originalControllerId;
this.maxBlocks = 1;
}
@ -169,7 +173,6 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
for (Ability ability : this.abilities) {
ability.reset(game);
}
this.controllerId = this.ownerId;
}
@Override

View file

@ -30,6 +30,7 @@ package mage.game.permanent;
import mage.game.permanent.token.Token;
import java.util.UUID;
import mage.Constants.CardType;
import mage.Constants.Zone;
import mage.abilities.Ability;
import mage.game.Game;
@ -56,22 +57,25 @@ public class PermanentToken extends PermanentImpl<PermanentToken> {
@Override
public void reset(Game game) {
Token copy = token.copy();
copyFromToken(copy);
// Token copy = token.copy();
copyFromToken(token);
super.reset(game);
}
protected void copyFromToken(Token token) {
this.name = token.getName();
this.abilities.clear();
for (Ability ability: token.getAbilities()) {
this.addAbility(ability);
this.abilities = token.getAbilities().copy();
this.cardType.clear();
for (CardType cType: token.getCardType()) {
this.cardType.add(cType);
}
this.cardType = token.getCardType();
this.color = token.getColor();
this.power = token.getPower();
this.toughness = token.getToughness();
this.subtype = token.getSubtype();
this.subtype.clear();
for (String subType: token.getSubtype()) {
this.subtype.add(subType);
}
this.color = token.getColor().copy();
this.power = token.getPower().copy();
this.toughness = token.getToughness().copy();
}
@Override

View file

@ -330,8 +330,14 @@ public class Spell<T extends Spell<T>> implements StackObject, Card {
throw new UnsupportedOperationException("Unsupported operation");
}
@Override
public Ability getStackAbility() {
return this.ability;
}
@Override
public void assignNewId() {
throw new UnsupportedOperationException("Unsupported operation");
}
}

View file

@ -55,7 +55,6 @@ import mage.counters.Counters;
import mage.filter.FilterAbility;
import mage.game.events.GameEvent;
import mage.game.Game;
import mage.game.Table;
import mage.game.draft.Draft;
import mage.game.match.Match;
import mage.game.permanent.Permanent;
@ -126,7 +125,7 @@ public interface Player extends MageItem, Copyable<Player> {
public boolean discard(Card card, Ability source, Game game);
public void lost(Game game);
public void won(Game game);
public void leaveGame(Game game);
public void leave();
public void concede(Game game);
public void abort();

View file

@ -732,11 +732,13 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
@Override
public void concede(Game game) {
leaveGame(game);
this.loses = true;
this.abort();
game.leave(playerId);
}
@Override
public void leaveGame(Game game) {
public void leave() {
this.passed = true;
this.abort();
this.loses = true;
@ -745,29 +747,6 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
this.hand.clear();
this.graveyard.clear();
this.library.clear();
for (Iterator<Permanent> it = game.getBattlefield().getAllPermanents().iterator(); it.hasNext();) {
Permanent perm = it.next();
if (perm.getOwnerId().equals(playerId)) {
if (perm.getAttachedTo() != null) {
Permanent attachedTo = game.getPermanent(perm.getAttachedTo());
if (attachedTo != null)
attachedTo.removeAttachment(perm.getId(), game);
}
it.remove();
}
}
for (Iterator<StackObject> it = game.getStack().iterator(); it.hasNext();) {
StackObject object = it.next();
if (object.getControllerId().equals(playerId)) {
it.remove();
}
}
for (Iterator<Permanent> it = game.getBattlefield().getAllPermanents().iterator(); it.hasNext();) {
Permanent perm = it.next();
if (perm.getControllerId().equals(playerId)) {
perm.moveToExile(null, "", null, game);
}
}
}
@Override
@ -782,7 +761,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
//20100423 - 603.9
if (!this.wins)
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LOST, null, null, playerId));
leaveGame(game);
game.leave(playerId);
}
}