merge latest trunk

This commit is contained in:
myk
2013-03-08 03:13:43 +00:00
79 changed files with 1019 additions and 504 deletions

View File

@@ -1631,6 +1631,7 @@ public class Card extends GameEntity implements Comparable<Card> {
public final ManaCost getManaCost() {
return this.getCharacteristics().getManaCost();
}
/**
* <p>
@@ -9194,7 +9195,7 @@ public class Card extends GameEntity implements Comparable<Card> {
System.out.println("Trying to sacrifice immutables: " + this);
return false;
}
if (source != null && !getController().isOpponentOf(source.getActivatingPlayer())
if (source != null && getController().isOpponentOf(source.getActivatingPlayer())
&& getController().hasKeyword("Spells and abilities your opponents control can't cause you to sacrifice permanents.")) {
return false;
}

View File

@@ -7,7 +7,7 @@ import forge.card.ability.effects.ChangeZoneAllEffect;
import forge.card.ability.effects.ChangeZoneEffect;
import forge.card.ability.effects.ManaEffect;
import forge.card.ability.effects.ManaReflectedEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cardfactory.CardFactory;
import forge.card.cost.Cost;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityManaPart;
@@ -50,7 +50,7 @@ public class AbilityApiBased extends AbilityActivated {
public AbilityActivated getCopy() {
Target tgt = getTarget() == null ? null : new Target(getTarget());
AbilityActivated res = new AbilityApiBased(api, getSourceCard(), getPayCosts(), tgt, params);
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
return res;
}

View File

@@ -4,6 +4,7 @@ import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
@@ -21,42 +22,8 @@ public class SacrificeAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(AIPlayer ai, SpellAbility sa) {
boolean chance = sacrificeTgtAI(ai, sa);
// Some additional checks based on what is being sacrificed, and who is
// sacrificing
final Target tgt = sa.getTarget();
if (tgt != null) {
final String valid = sa.getParam("SacValid");
String num = sa.getParam("Amount");
num = (num == null) ? "1" : num;
final int amount = AbilityUtils.calculateAmount(sa.getSourceCard(), num, sa);
List<Card> list =
CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard());
if (list.size() == 0) {
return false;
}
final Card source = sa.getSourceCard();
if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
// Set PayX here to maximum value.
final int xPay = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount);
source.setSVar("PayX", Integer.toString(xPay));
}
final int half = (amount / 2) + (amount % 2); // Half of amount
// rounded up
// If the Human has at least half rounded up of the amount to be
// sacrificed, cast the spell
if (list.size() < half) {
return false;
}
}
return chance;
return sacrificeTgtAI(ai, sa);
}
@Override
@@ -83,16 +50,49 @@ public class SacrificeAi extends SpellAbilityAi {
private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa) {
final Card card = sa.getSourceCard();
final Card source = sa.getSourceCard();
final Target tgt = sa.getTarget();
final boolean destroy = sa.hasParam("Destroy");
Player opp = ai.getOpponent();
if (tgt != null) {
tgt.resetTargets();
if (opp.canBeTargetedBy(sa)) {
tgt.addTarget(opp);
return true;
if (!opp.canBeTargetedBy(sa)) {
return false;
}
tgt.addTarget(opp);
final String valid = sa.getParam("SacValid");
String num = sa.getParam("Amount");
num = (num == null) ? "1" : num;
final int amount = AbilityUtils.calculateAmount(sa.getSourceCard(), num, sa);
List<Card> list =
CardLists.getValidCards(ai.getOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard());
if (!destroy) {
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(sa));
} else {
if (!CardLists.getKeyword(list, "Indestructible").isEmpty()) {
// human can choose to destroy indestructibles
return false;
}
}
if (list.size() == 0) {
return false;
}
if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
// Set PayX here to maximum value.
final int xPay = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount);
source.setSVar("PayX", Integer.toString(xPay));
}
final int half = (amount / 2) + (amount % 2); // Half of amount
// rounded up
// If the Human has at least half rounded up of the amount to be
// sacrificed, cast the spell
if (!sa.isTrigger() && list.size() < half) {
return false;
}
}
@@ -109,9 +109,8 @@ public class SacrificeAi extends SpellAbilityAi {
// TODO: Cast if the type is favorable: my "worst" valid is
// worse than his "worst" valid
final String num = sa.hasParam("Amount") ? sa.getParam("Amount") : "1";
int amount = AbilityUtils.calculateAmount(card, num, sa);
int amount = AbilityUtils.calculateAmount(source, num, sa);
final Card source = sa.getSourceCard();
if (num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
// Set PayX here to maximum value.
amount = Math.min(ComputerUtilMana.determineLeftoverMana(sa, ai), amount);

View File

@@ -1,18 +1,31 @@
package forge.card.ability.ai;
import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.Singletons;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
import forge.game.player.AIPlayer;
import forge.game.zone.ZoneType;
public class UntapAllAi extends SpellAbilityAi {
@Override
protected boolean canPlayAI(AIPlayer aiPlayer, SpellAbility sa) {
// check SubAbilities DoTrigger?
final Card source = sa.getSourceCard();
final AbilitySub abSub = sa.getSubAbility();
if (abSub != null) {
return true;
String valid = "";
List<Card> list = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
if (sa.hasParam("ValidCards")) {
valid = sa.getParam("ValidCards");
}
list = CardLists.getValidCards(list, valid.split(","), source.getController(), source);
return !list.isEmpty();
}
return false;
}

View File

@@ -12,6 +12,7 @@ import forge.Command;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
@@ -122,7 +123,7 @@ public class CloneEffect extends SpellAbilityEffect {
stateToCopy = cardToCopy.getCurState();
}
CardFactoryUtil.copyState(cardToCopy, stateToCopy, tgtCard);
CardFactory.copyState(cardToCopy, stateToCopy, tgtCard);
// must call this before addAbilityFactoryAbilities so cloned added abilities are handled correctly
addExtraCharacteristics(tgtCard, sa, origSVars);
CardFactoryUtil.addAbilityFactoryAbilities(tgtCard);
@@ -140,7 +141,7 @@ public class CloneEffect extends SpellAbilityEffect {
tgtCard.addAlternateState(CardCharacteristicName.Flipped);
tgtCard.setState(CardCharacteristicName.Flipped);
}
CardFactoryUtil.copyState(cardToCopy, CardCharacteristicName.Flipped, tgtCard);
CardFactory.copyState(cardToCopy, CardCharacteristicName.Flipped, tgtCard);
addExtraCharacteristics(tgtCard, sa, origSVars);
CardFactoryUtil.addAbilityFactoryAbilities(tgtCard);
for (int i = 0; i < tgtCard.getStaticAbilityStrings().size(); i++) {

View File

@@ -12,6 +12,7 @@ import forge.Command;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.mana.ManaCost;
import forge.card.spellability.Ability;
@@ -82,7 +83,7 @@ public class CopyPermanentEffect extends SpellAbilityEffect {
if (!c.isToken() || c.isCopiedToken()) {
// copy creature and put it onto the battlefield
copy = Singletons.getModel().getCardFactory().getCard(CardDb.getCard(c), sa.getActivatingPlayer());
copy = CardFactory.getCard(CardDb.getCard(c), sa.getActivatingPlayer());
// when copying something stolen:
copy.addController(controller);
@@ -90,7 +91,7 @@ public class CopyPermanentEffect extends SpellAbilityEffect {
copy.setToken(true);
copy.setCopiedToken(true);
} else { // isToken()
copy = CardFactoryUtil.copyStats(c);
copy = CardFactory.copyStats(c);
copy.setName(c.getName());
copy.setImageFilename(c.getImageFilename());

View File

@@ -5,9 +5,9 @@ import java.util.Iterator;
import java.util.List;
import forge.Card;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactory;
import forge.card.spellability.SpellAbility;
import forge.game.player.Player;
import forge.gui.GuiChoose;
@@ -99,7 +99,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
for (final SpellAbility chosenSAcopy : chosenSAs) {
chosenSAcopy.setActivatingPlayer(controller);
for (int i = 0; i < amount; i++) {
Singletons.getModel().getCardFactory().copySpellontoStack(card, chosenSAcopy.getSourceCard(), chosenSAcopy, true);
CardFactory.copySpellontoStack(card, chosenSAcopy.getSourceCard(), chosenSAcopy, true);
}
}
}
@@ -115,7 +115,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect {
chosenSA.setActivatingPlayer(controller);
for (int i = 0; i < amount; i++) {
Singletons.getModel().getCardFactory().copySpellontoStack(card, chosenSA.getSourceCard(), chosenSA, true);
CardFactory.copySpellontoStack(card, chosenSA.getSourceCard(), chosenSA, true);
}
}
} // end resolve

View File

@@ -150,7 +150,7 @@ public class PlayEffect extends SpellAbilityEffect {
source.clearRemembered();
}
if (sa.hasParam("CopyCard")) {
tgtCard = Singletons.getModel().getCardFactory().getCard(CardDb.getCard(tgtCard), sa.getActivatingPlayer());
tgtCard = CardDb.getCard(tgtCard).toForgeCard(sa.getActivatingPlayer());
// when copying something stolen:
tgtCard.addController(sa.getActivatingPlayer());

View File

@@ -3,6 +3,8 @@ package forge.card.ability.effects;
import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
@@ -51,6 +53,9 @@ public class SacrificeEffect extends SpellAbilityEffect {
for (final Player p : tgts) {
List<Card> battlefield = p.getCardsIn(ZoneType.Battlefield);
List<Card> validTargets = AbilityUtils.filterListByType(battlefield, valid, sa);
if (!destroy) {
validTargets = CardLists.filter(validTargets, CardPredicates.canBeSacrificedBy(sa));
}
if (sa.hasParam("Random")) {
choosenToSacrifice = Aggregates.random(validTargets, Math.min(amount, validTargets.size()));

View File

@@ -27,6 +27,7 @@ import forge.CardCharacteristicName;
import forge.CardColor;
import forge.CardUtil;
import forge.Color;
import forge.card.CardCharacteristics;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.card.ICardFace;
@@ -39,12 +40,9 @@ import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellPermanent;
import forge.card.spellability.Target;
import forge.card.trigger.TriggerHandler;
import forge.error.BugReporter;
import forge.game.player.Player;
import forge.gui.GuiUtils;
import forge.item.CardDb;
import forge.item.IPaperCard;
import forge.properties.NewConstants;
/**
* <p>
@@ -65,33 +63,6 @@ import forge.properties.NewConstants;
* @version $Id$
*/
public class CardFactory {
/**
* <p>
* Constructor for CardFactory.
* </p>
*
* @param file
* a {@link java.io.File} object.
*/
private final CardStorageReader reader;
public CardFactory() {
GuiUtils.checkEDT("CardFactory$constructor", false);
reader = new CardStorageReader(NewConstants.CARD_DATA_DIR.defaultLoc, true);
try {
// this fills in our map of card names to Card instances.
final List<CardRules> listCardRules = reader.loadCards();
CardDb.setup(listCardRules.iterator());
} catch (final Exception ex) {
BugReporter.reportException(ex);
}
} // constructor
/**
* <p>
* copyCard.
@@ -101,15 +72,15 @@ public class CardFactory {
* a {@link forge.Card} object.
* @return a {@link forge.Card} object.
*/
public final Card copyCard(final Card in) {
public final static Card copyCard(final Card in) {
final CardCharacteristicName curState = in.getCurState();
if (in.isInAlternateState()) {
in.setState(CardCharacteristicName.Original);
}
final Card out = this.getCard(CardDb.getCard(in), in.getOwner());
final Card out = getCard(CardDb.getCard(in), in.getOwner());
out.setUniqueNumber(in.getUniqueNumber());
CardFactoryUtil.copyCharacteristics(in, out);
CardFactory.copyCharacteristics(in, out);
if (in.hasAlternateState()) {
for (final CardCharacteristicName state : in.getStates()) {
in.setState(state);
@@ -117,7 +88,7 @@ public class CardFactory {
out.addAlternateState(state);
}
out.setState(state);
CardFactoryUtil.copyCharacteristics(in, out);
CardFactory.copyCharacteristics(in, out);
}
in.setState(curState);
out.setState(curState);
@@ -154,7 +125,7 @@ public class CardFactory {
* @param bCopyDetails
* a boolean.
*/
public final void copySpellontoStack(final Card source, final Card original, final SpellAbility sa,
public final static void copySpellontoStack(final Card source, final Card original, final SpellAbility sa,
final boolean bCopyDetails) {
//Player originalController = original.getController();
Player controller = sa.getActivatingPlayer();
@@ -240,7 +211,7 @@ public class CardFactory {
* @return a {@link forge.Card} instance, owned by owner; or the special
* blankCard
*/
public final Card getCard(final IPaperCard cp, final Player owner) {
public final static Card getCard(final IPaperCard cp, final Player owner) {
//System.out.println(cardName);
CardRules cardRules = cp.getRules();
@@ -435,4 +406,110 @@ public class CardFactory {
}
}
/**
* <p>
* Copies stats like power, toughness, etc.
* </p>
*
* @param sim
* a {@link java.lang.Object} object.
* @return a {@link forge.Card} object.
*/
public static Card copyStats(final Card sim) {
final Card c = new Card();
c.setFlipCard(sim.isFlipCard());
c.setDoubleFaced(sim.isDoubleFaced());
c.setCurSetCode(sim.getCurSetCode());
final CardCharacteristicName origState = sim.getCurState();
for (final CardCharacteristicName state : sim.getStates()) {
c.addAlternateState(state);
c.setState(state);
sim.setState(state);
CardFactory.copyCharacteristics(sim, c);
}
sim.setState(origState);
c.setState(origState);
c.setRules(sim.getRules());
return c;
} // copyStats()
/**
* Copy characteristics.
*
* @param from
* the from
* @param to
* the to
*/
private static void copyCharacteristics(final Card from, final Card to) {
to.setBaseAttack(from.getBaseAttack());
to.setBaseDefense(from.getBaseDefense());
to.setBaseLoyalty(from.getBaseLoyalty());
to.setBaseAttackString(from.getBaseAttackString());
to.setBaseDefenseString(from.getBaseDefenseString());
to.setIntrinsicKeyword(from.getIntrinsicKeyword());
to.setName(from.getName());
to.setType(from.getCharacteristics().getType());
to.setText(from.getSpellText());
to.setManaCost(from.getManaCost());
to.setColor(from.getColor());
to.setSVars(from.getSVars());
to.setIntrinsicAbilities(from.getIntrinsicAbilities());
to.setImageFilename(from.getImageFilename());
to.setTriggers(from.getTriggers());
to.setReplacementEffects(from.getReplacementEffects());
to.setStaticAbilityStrings(from.getStaticAbilityStrings());
}
/**
* Copy characteristics.
*
* @param from
* the from
* @param stateToCopy
* the state to copy
* @param to
* the to
*/
public static void copyState(final Card from, final CardCharacteristicName stateToCopy, final Card to) {
// copy characteristics not associated with a state
to.setBaseLoyalty(from.getBaseLoyalty());
to.setBaseAttackString(from.getBaseAttackString());
to.setBaseDefenseString(from.getBaseDefenseString());
to.setText(from.getSpellText());
// get CardCharacteristics for desired state
CardCharacteristics characteristics = from.getState(stateToCopy);
to.getCharacteristics().copy(characteristics);
// handle triggers and replacement effect through Card class interface
to.setTriggers(characteristics.getTriggers());
to.setReplacementEffects(characteristics.getReplacementEffects());
}
public static void copySpellAbility(SpellAbility from, SpellAbility to) {
to.setDescription(from.getDescription());
to.setStackDescription(from.getDescription());
if (from.getSubAbility() != null) {
to.setSubAbility(from.getSubAbility().getCopy());
}
if (from.getRestrictions() != null) {
to.setRestrictions(from.getRestrictions());
}
if (from.getConditions() != null) {
to.setConditions(from.getConditions());
}
for (String sVar : from.getSVars()) {
to.setSVar(sVar, from.getSVar(sVar));
}
}
} // end class AbstractCardFactory

View File

@@ -48,7 +48,7 @@ class CardFactoryArtifacts {
public AbilityActivated getCopy() {
AbilityActivated res = new AbilityGrindstone(getSourceCard(),
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
return res;
}
@@ -118,7 +118,7 @@ class CardFactoryArtifacts {
public AbilityActivated getCopy() {
AbilityActivated res = new AbilityScrollRack(getSourceCard(),
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
return res;
}
@@ -261,7 +261,7 @@ class CardFactoryArtifacts {
public AbilityActivated getCopy() {
AbilityActivated res = new AbilityTemporalAperture(getSourceCard(),
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
return res;
}

View File

@@ -40,7 +40,6 @@ import forge.Constant;
import forge.CounterType;
import forge.GameEntity;
import forge.Singletons;
import forge.card.CardCharacteristics;
import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType;
@@ -146,7 +145,7 @@ public class CardFactoryUtil {
public AbilityActivated getCopy() {
AbilityActivated res = new AbilityUnearth(getSourceCard(),
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
final SpellAbilityRestriction restrict = new SpellAbilityRestriction();
restrict.setZone(ZoneType.Graveyard);
restrict.setSorcerySpeed(true);
@@ -359,7 +358,7 @@ public class CardFactoryUtil {
public AbilityActivated getCopy() {
AbilityActivated res = new AbilityTransmute(getSourceCard(),
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
res.getRestrictions().setZone(ZoneType.Hand);
return res;
}
@@ -2488,7 +2487,7 @@ public class CardFactoryUtil {
final int multiplier = controller.getTokenDoublersMagnitude();
for (int i = 0; i < multiplier; i++) {
Card temp = CardFactoryUtil.copyStats(c);
Card temp = CardFactory.copyStats(c);
for (final String kw : intrinsicKeywords) {
temp.addIntrinsicKeyword(kw);
@@ -2669,112 +2668,6 @@ public class CardFactoryUtil {
|| (c == CounterType.TIME);
}
/**
* <p>
* Copies stats like power, toughness, etc.
* </p>
*
* @param sim
* a {@link java.lang.Object} object.
* @return a {@link forge.Card} object.
*/
public static Card copyStats(final Card sim) {
final Card c = new Card();
c.setFlipCard(sim.isFlipCard());
c.setDoubleFaced(sim.isDoubleFaced());
c.setCurSetCode(sim.getCurSetCode());
final CardCharacteristicName origState = sim.getCurState();
for (final CardCharacteristicName state : sim.getStates()) {
c.addAlternateState(state);
c.setState(state);
sim.setState(state);
CardFactoryUtil.copyCharacteristics(sim, c);
}
sim.setState(origState);
c.setState(origState);
c.setRules(sim.getRules());
return c;
} // copyStats()
/**
* Copy characteristics.
*
* @param from
* the from
* @param to
* the to
*/
public static void copyCharacteristics(final Card from, final Card to) {
to.setBaseAttack(from.getBaseAttack());
to.setBaseDefense(from.getBaseDefense());
to.setBaseLoyalty(from.getBaseLoyalty());
to.setBaseAttackString(from.getBaseAttackString());
to.setBaseDefenseString(from.getBaseDefenseString());
to.setIntrinsicKeyword(from.getIntrinsicKeyword());
to.setName(from.getName());
to.setType(from.getCharacteristics().getType());
to.setText(from.getSpellText());
to.setManaCost(from.getManaCost());
to.setColor(from.getColor());
to.setSVars(from.getSVars());
to.setIntrinsicAbilities(from.getIntrinsicAbilities());
to.setImageFilename(from.getImageFilename());
to.setTriggers(from.getTriggers());
to.setReplacementEffects(from.getReplacementEffects());
to.setStaticAbilityStrings(from.getStaticAbilityStrings());
}
/**
* Copy characteristics.
*
* @param from
* the from
* @param stateToCopy
* the state to copy
* @param to
* the to
*/
public static void copyState(final Card from, final CardCharacteristicName stateToCopy, final Card to) {
// copy characteristics not associated with a state
to.setBaseLoyalty(from.getBaseLoyalty());
to.setBaseAttackString(from.getBaseAttackString());
to.setBaseDefenseString(from.getBaseDefenseString());
to.setText(from.getSpellText());
// get CardCharacteristics for desired state
CardCharacteristics characteristics = from.getState(stateToCopy);
to.getCharacteristics().copy(characteristics);
// handle triggers and replacement effect through Card class interface
to.setTriggers(characteristics.getTriggers());
to.setReplacementEffects(characteristics.getReplacementEffects());
}
public static void copySpellAbility(SpellAbility from, SpellAbility to) {
to.setDescription(from.getDescription());
to.setStackDescription(from.getDescription());
if (from.getSubAbility() != null) {
to.setSubAbility(from.getSubAbility().getCopy());
}
if (from.getRestrictions() != null) {
to.setRestrictions(from.getRestrictions());
}
if (from.getConditions() != null) {
to.setConditions(from.getConditions());
}
for (String sVar : from.getSVars()) {
to.setSVar(sVar, from.getSVar(sVar));
}
}
public static void correctAbilityChainSourceCard(final SpellAbility sa, final Card card) {
sa.setSourceCard(card);

View File

@@ -28,7 +28,7 @@ import forge.card.ability.effects.ChangeZoneAllEffect;
import forge.card.ability.effects.ChangeZoneEffect;
import forge.card.ability.effects.ManaEffect;
import forge.card.ability.effects.ManaReflectedEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cardfactory.CardFactory;
import forge.game.player.AIPlayer;
/**
@@ -109,7 +109,7 @@ public final class AbilitySub extends SpellAbility implements java.io.Serializab
public AbilitySub getCopy() {
Target t = getTarget() == null ? null : new Target(getTarget());
AbilitySub res = new AbilitySub(api, getSourceCard(), t, params);
CardFactoryUtil.copySpellAbility(this, res);
CardFactory.copySpellAbility(this, res);
return res;
}

View File

@@ -148,6 +148,9 @@ public class InputControl extends MyObservable implements java.io.Serializable {
* @return a {@link forge.control.input.Input} object.
*/
public final Input getActualInput() {
if ( !game.hasMulliganned() )
return new InputMulligan();
final PhaseHandler handler = game.getPhaseHandler();
final PhaseType phase = handler.getPhase();
final Player playerTurn = handler.getPlayerTurn();

View File

@@ -174,7 +174,6 @@ public class InputMulligan extends Input {
}
ga.checkStateEffects();
Singletons.getModel().getMatch().getInput().clearInput();
Player next = game.getPhaseHandler().getPlayerTurn();
@@ -187,7 +186,9 @@ public class InputMulligan extends Input {
VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(next);
SDisplayUtil.showTab(nextField);
game.getPhaseHandler().nextPhase();
game.setMulliganned(true);
Singletons.getModel().getMatch().getInput().clearInput();
Singletons.getModel().getMatch().getInput().resetInput();
}
@Override

View File

@@ -19,6 +19,8 @@ import forge.Singletons;
import forge.deck.generate.Generate2ColorDeck;
import forge.deck.generate.Generate3ColorDeck;
import forge.deck.generate.Generate5ColorDeck;
import forge.deck.generate.GenerateColoredDeckBase;
import forge.deck.generate.GenerateMonoColorDeck;
import forge.deck.generate.GenerateThemeDeck;
import forge.game.player.PlayerType;
import forge.item.CardDb;
@@ -67,7 +69,7 @@ public class DeckgenUtil {
* @return {@link forge.deck.Deck}
*/
public static Deck buildColorDeck(final String[] selection, PlayerType pt) {
ItemPoolView<CardPrinted> cards = null;
final Deck deck;
// Replace "random" with "AI" for deck generation code
@@ -75,22 +77,20 @@ public class DeckgenUtil {
selection[i] = COLOR_VALS.get(selection[i]);
}
// 2, 3, and 5 colors.
if (selection.length == 2) {
final Generate2ColorDeck gen = new Generate2ColorDeck(
selection[0], selection[1]);
cards = gen.get2ColorDeck(60, pt);
GenerateColoredDeckBase gen = null;
if (selection.length == 1) {
gen = new GenerateMonoColorDeck(selection[0]);
} else if (selection.length == 2) {
gen = new Generate2ColorDeck(selection[0], selection[1]);
} else if (selection.length == 3) {
gen = new Generate3ColorDeck(selection[0], selection[1], selection[2]);
} else {
gen = new Generate5ColorDeck();
}
else if (selection.length == 3) {
final Generate3ColorDeck gen = new Generate3ColorDeck(
selection[0], selection[1], selection[2]);
cards = gen.get3ColorDeck(60, pt);
}
else {
final Generate5ColorDeck gen = new Generate5ColorDeck();
cards = gen.get5ColorDeck(60, pt);
}
ItemPoolView<CardPrinted> cards = gen == null ? null : gen.getDeck(60, pt);
// After generating card lists, build deck.
deck = new Deck();
deck.getMain().addAll(cards);
@@ -132,8 +132,8 @@ public class DeckgenUtil {
/** @return {@link forge.deck.Deck} */
public static Deck getRandomColorDeck(PlayerType pt) {
final int[] colorCount = new int[] {2, 3, 5};
final int count = colorCount[(int) (Math.round(Math.random() * 2))];
final int[] colorCount = new int[] {1, 2, 3, 5};
final int count = colorCount[MyRandom.getRandom().nextInt(colorCount.length)];
final String[] selection = new String[count];
// A simulated selection of "random 1" will trigger the AI selection process.
@@ -288,14 +288,7 @@ public class DeckgenUtil {
public static boolean colorCheck(final String[] colors0) {
boolean result = true;
if (colors0.length == 1) {
JOptionPane.showMessageDialog(null,
"Sorry, single color generated decks aren't supported yet."
+ "\n\rPlease choose at least one more color for this deck.",
"Generate deck: 1 color", JOptionPane.ERROR_MESSAGE);
result = false;
}
else if (colors0.length == 4) {
if (colors0.length == 4) {
JOptionPane.showMessageDialog(null,
"Sorry, four color generated decks aren't supported yet."
+ "\n\rPlease use 2, 3, or 5 colors for this deck.",

View File

@@ -76,7 +76,7 @@ public class Generate2ColorDeck extends GenerateColoredDeckBase {
}
public final ItemPoolView<CardPrinted> get2ColorDeck(final int size, final PlayerType pt) {
public final ItemPoolView<CardPrinted> getDeck(final int size, final PlayerType pt) {
addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt);
// Add lands

View File

@@ -75,7 +75,7 @@ public class Generate3ColorDeck extends GenerateColoredDeckBase {
* the pt
* @return a {@link forge.CardList} object.
*/
public final ItemPoolView<CardPrinted> get3ColorDeck(final int size, final PlayerType pt) {
public final ItemPoolView<CardPrinted> getDeck(final int size, final PlayerType pt) {
addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt);
// Add lands

View File

@@ -65,7 +65,7 @@ public class Generate5ColorDeck extends GenerateColoredDeckBase {
* a PlayerType
* @return a {@link forge.CardList} object.
*/
public final ItemPoolView<CardPrinted> get5ColorDeck(final int size, final PlayerType pt) {
public final ItemPoolView<CardPrinted> getDeck(final int size, final PlayerType pt) {
addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt);
// Add lands

View File

@@ -40,6 +40,7 @@ import forge.game.player.PlayerType;
import forge.item.CardDb;
import forge.item.CardPrinted;
import forge.item.ItemPool;
import forge.item.ItemPoolView;
import forge.properties.ForgePreferences.FPref;
import forge.util.Aggregates;
import forge.util.MyRandom;
@@ -88,6 +89,9 @@ public abstract class GenerateColoredDeckBase {
addCmcAdjusted(spells, spellCnt, cmcLevels, cmcAmounts);
}
public ItemPoolView<CardPrinted> getDeck(final int size, final PlayerType pt) {
return null; // all but theme deck do override this method
}
protected void addSome(int cnt, List<CardPrinted> source) {
for (int i = 0; i < cnt; i++) {

View File

@@ -0,0 +1,94 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.Arrays;
import java.util.List;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.game.player.PlayerType;
import forge.item.CardPrinted;
import forge.item.ItemPoolView;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id: Generate2ColorDeck.java 19765 2013-02-20 03:01:37Z myk $
*/
public class GenerateMonoColorDeck extends GenerateColoredDeckBase {
@Override protected final float getLandsPercentage() { return 0.39f; }
@Override protected final float getCreatPercentage() { return 0.36f; }
@Override protected final float getSpellPercentage() { return 0.25f; }
final List<FilterCMC> cmcLevels = Arrays.asList(
new GenerateDeckUtil.FilterCMC(0, 2),
new GenerateDeckUtil.FilterCMC(3, 4),
new GenerateDeckUtil.FilterCMC(5, 6),
new GenerateDeckUtil.FilterCMC(7, 20));
final int[] cmcAmounts = {10, 8, 5, 3};
// mana curve of the card pool
// 20x 0 - 2
// 16x 3 - 4
// 12x 5 - 6
// 4x 7 - 20
// = 52x - card pool (before further random filtering)
/**
* <p>
* Constructor for Generate2ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
*/
public GenerateMonoColorDeck(final String clr1) {
if (clr1.equals("AI")) {
int color1 = r.nextInt(5);
colors = ColorSet.fromMask(MagicColor.WHITE << color1);
} else {
colors = ColorSet.fromNames(clr1);
}
}
public final ItemPoolView<CardPrinted> getDeck(final int size, final PlayerType pt) {
addCreaturesAndSpells(size, cmcLevels, cmcAmounts, pt);
// Add lands
int numLands = (int) (getLandsPercentage() * size);
tmpDeck.append("numLands:").append(numLands).append("\n");
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
adjustDeckSize(size);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -38,6 +38,7 @@ import forge.GameEntity;
import forge.card.CardSplitType;
import forge.card.CardType;
import forge.card.ability.effects.AttachEffect;
import forge.card.cardfactory.CardFactory;
import forge.card.cost.Cost;
import forge.card.mana.ManaCost;
import forge.card.replacement.ReplacementEffect;
@@ -159,7 +160,7 @@ public class GameAction {
if (zoneFrom.is(ZoneType.Battlefield)) {
c.setFlipStaus(false);
}
copied = forge.Singletons.getModel().getCardFactory().copyCard(c);
copied = CardFactory.copyCard(c);
copied.setUnearthed(c.isUnearthed());
copied.setTapped(false);
for (final Trigger trigger : copied.getTriggers()) {
@@ -671,7 +672,7 @@ public class GameAction {
if (p != null && p.is(ZoneType.Battlefield)) {
lastKnownInfo = CardUtil.getLKICopy(c);
c.clearCounters(); // remove all counters
library.add(forge.Singletons.getModel().getCardFactory().copyCard(c), libPosition);
library.add(CardFactory.copyCard(c), libPosition);
} else {
c.clearCounters(); // remove all counters
library.add(c, libPosition);

View File

@@ -73,6 +73,9 @@ public class GameActionPlay {
* a {@link forge.card.spellability.SpellAbility} object.
*/
public final void playSpellAbilityForFree(final SpellAbility sa) {
final Card source = sa.getSourceCard();
setSplitCardState(source, sa); // Split card support
if (sa.getPayCosts() != null) {
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
CharmEffect.makeChoices(sa);
@@ -180,23 +183,20 @@ public class GameActionPlay {
List<Card> untappedCreats = CardLists.filter(spell.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED);
if (untappedCreats.size() != 0) {
if (!untappedCreats.isEmpty()) {
final List<Card> choices = new ArrayList<Card>();
for (final Card c : untappedCreats) {
choices.add(c);
}
choices.addAll(untappedCreats);
ArrayList<String> usableColors = new ArrayList<String>();
ManaCostBeingPaid newCost = new ManaCostBeingPaid(originalCost.toString());
Card tapForConvoke = null;
if (sa.getActivatingPlayer().isHuman()) {
tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(),
choices);
tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(), choices);
} else {
// TODO: AI to choose a creature to tap would go here
// Probably along with deciding how many creatures to
// tap
}
while (tapForConvoke != null && untappedCreats.size() != 0) {
while (tapForConvoke != null && !untappedCreats.isEmpty()) {
final Card workingCard = (Card) tapForConvoke;
usableColors = GameActionPlay.getConvokableColors(workingCard, newCost);
@@ -223,7 +223,7 @@ public class GameActionPlay {
sa.addTappedForConvoke(workingCard);
choices.remove(workingCard);
untappedCreats.remove(workingCard);
if ((choices.size() < 2) || (newCost.getConvertedManaCost() == 0)) {
if (choices.isEmpty() || (newCost.getConvertedManaCost() == 0)) {
break;
}
} else {
@@ -239,7 +239,7 @@ public class GameActionPlay {
}
// will only be null if user cancelled.
if (tapForConvoke != null) {
if (!sa.getTappedForConvoke().isEmpty()) {
// Convoked creats are tapped here with triggers
// suppressed,
// Then again when payment is done(In

View File

@@ -23,16 +23,12 @@ import forge.CardUtil;
import forge.Singletons;
import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType;
import forge.control.input.Input;
import forge.control.input.InputControl;
import forge.control.input.InputMulligan;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.error.BugReporter;
import forge.game.event.FlipCoinEvent;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.AIPlayer;
import forge.game.player.LobbyPlayer;
import forge.game.player.Player;
@@ -195,8 +191,6 @@ public class GameNew {
removedAnteCards.put(player, myRemovedAnteCards);
}
if (rAICards.size() > 0) {
String message = buildFourColumnList("AI deck contains the following cards that it can't play or may be buggy:", rAICards);
if (GameType.Quest == game.getType()) {
@@ -215,7 +209,116 @@ public class GameNew {
JOptionPane.showMessageDialog(null, ante.toString(), "", JOptionPane.INFORMATION_MESSAGE);
}
GameNew.actuateGame(match, game, false);
// Deciding which cards go to ante
if (preferences.getPrefBoolean(FPref.UI_ANTE)) {
final String nl = System.getProperty("line.separator");
final StringBuilder msg = new StringBuilder();
for (final Player p : game.getPlayers()) {
final List<Card> lib = p.getCardsIn(ZoneType.Library);
Predicate<Card> goodForAnte = Predicates.not(CardPredicates.Presets.BASIC_LANDS);
Card ante = Aggregates.random(Iterables.filter(lib, goodForAnte));
if (ante == null) {
throw new RuntimeException(p + " library is empty.");
}
game.getGameLog().add("Ante", p + " anted " + ante, 0);
VAntes.SINGLETON_INSTANCE.addAnteCard(p, ante);
game.getAction().moveTo(ZoneType.Ante, ante);
msg.append(p.getName()).append(" ante: ").append(ante).append(nl);
}
JOptionPane.showMessageDialog(null, msg, "Ante", JOptionPane.INFORMATION_MESSAGE);
}
determineFirstTurnPlayer(match.getLastGameOutcome(), game);
// Draw <handsize> cards
for (final Player p1 : game.getPlayers()) {
p1.drawCards(p1.getMaxHandSize());
}
Thread thGame = new GameInputUpdatesThread(match, game);
thGame.setName("Game input updater");
thGame.start();
}
// ultimate of Karn the Liberated
public static void restartGame(final MatchController match, final GameState game, final Player startingTurn, Map<Player, List<Card>> playerLibraries) {
Map<LobbyPlayer, PlayerStartConditions> players = match.getPlayers();
Map<Player, PlayerStartConditions> playersConditions = new HashMap<Player, PlayerStartConditions>();
for (Player p : game.getPlayers()) {
playersConditions.put(p, players.get(p.getLobbyPlayer()));
}
game.setMulliganned(false);
match.getInput().clearInput();
//Card.resetUniqueNumber();
// need this code here, otherwise observables fail
forge.card.trigger.Trigger.resetIDs();
TriggerHandler trigHandler = game.getTriggerHandler();
trigHandler.clearTriggerSettings();
trigHandler.clearDelayedTrigger();
trigHandler.cleanUpTemporaryTriggers();
trigHandler.suppressMode(TriggerType.ChangesZone);
game.getStack().reset();
GameAction action = game.getAction();
for (Entry<Player, PlayerStartConditions> p : playersConditions.entrySet()) {
final Player player = p.getKey();
player.setStartingLife(p.getValue().getStartingLife());
player.setNumLandsPlayed(0);
putCardsOnBattlefield(player, p.getValue().getCardsOnBattlefield(player));
PlayerZone library = player.getZone(ZoneType.Library);
List<Card> newLibrary = playerLibraries.get(player);
for (Card c : newLibrary) {
action.moveTo(library, c);
}
player.shuffle();
player.getZone(ZoneType.Battlefield).updateObservers();
player.updateObservers();
player.getZone(ZoneType.Hand).updateObservers();
}
trigHandler.clearSuppression(TriggerType.ChangesZone);
PhaseHandler phaseHandler = game.getPhaseHandler();
phaseHandler.setPlayerTurn(startingTurn);
// Draw <handsize> cards
for (final Player p : game.getPlayers()) {
p.drawCards(p.getMaxHandSize());
}
}
/**
* TODO: Write javadoc for this method.
* @param match
* @param game
*/
private static void determineFirstTurnPlayer(final GameOutcome lastGameOutcome, final GameState game) {
// Only cut/coin toss if it's the first game of the match
Player goesFirst;
Player humanPlayer = Singletons.getControl().getPlayer();
boolean isFirstGame = lastGameOutcome == null;
if (isFirstGame) {
goesFirst = GameNew.seeWhoPlaysFirstDice(game);
} else {
goesFirst = lastGameOutcome.isWinner(humanPlayer.getLobbyPlayer()) ? humanPlayer.getOpponent() : humanPlayer;
}
String message = goesFirst + ( isFirstGame ? " has won the coin toss." : " lost the last game.");
boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message);
if ( goesFirst != humanPlayer ) {
JOptionPane.showMessageDialog(null, message + "\nComputer Going First", "You are drawing", JOptionPane.INFORMATION_MESSAGE);
}
goesFirst = willPlay ? goesFirst : goesFirst.getOpponent();
game.getPhaseHandler().setPlayerTurn(goesFirst);
}
private static void initVariantsZones(final Player player, final PlayerStartConditions psc) {
@@ -283,128 +386,6 @@ public class GameNew {
}
// ultimate of Karn the Liberated
public static void restartGame(final MatchController match, final GameState game, final Player startingTurn, Map<Player, List<Card>> playerLibraries) {
Map<LobbyPlayer, PlayerStartConditions> players = match.getPlayers();
Map<Player, PlayerStartConditions> playersConditions = new HashMap<Player, PlayerStartConditions>();
for (Player p : game.getPlayers()) {
playersConditions.put(p, players.get(p.getLobbyPlayer()));
}
match.getInput().clearInput();
//Card.resetUniqueNumber();
// need this code here, otherwise observables fail
forge.card.trigger.Trigger.resetIDs();
TriggerHandler trigHandler = game.getTriggerHandler();
trigHandler.clearTriggerSettings();
trigHandler.clearDelayedTrigger();
trigHandler.cleanUpTemporaryTriggers();
trigHandler.suppressMode(TriggerType.ChangesZone);
game.getStack().reset();
GameAction action = game.getAction();
for (Entry<Player, PlayerStartConditions> p : playersConditions.entrySet()) {
final Player player = p.getKey();
player.setStartingLife(p.getValue().getStartingLife());
player.setNumLandsPlayed(0);
putCardsOnBattlefield(player, p.getValue().getCardsOnBattlefield(player));
PlayerZone library = player.getZone(ZoneType.Library);
List<Card> newLibrary = playerLibraries.get(player);
for (Card c : newLibrary) {
action.moveTo(library, c);
}
player.shuffle();
player.getZone(ZoneType.Battlefield).updateObservers();
player.updateObservers();
player.getZone(ZoneType.Hand).updateObservers();
}
trigHandler.clearSuppression(TriggerType.ChangesZone);
PhaseHandler phaseHandler = game.getPhaseHandler();
phaseHandler.setPlayerTurn(startingTurn);
GameNew.actuateGame(match, game, true);
}
/**
* This must be separated from the newGame method since life totals and
* player details could be adjusted before the game is started.
*
* That process (also cleanup and observer updates) should be done in
* newGame, then when all is ready, call this function.
* @param isRestartedGame Whether the actuated game is the first start or a restart
*/
private static void actuateGame(final MatchController match, final GameState game, boolean isRestartedGame) {
if (!isRestartedGame) {
// Deciding which cards go to ante
if (preferences.getPrefBoolean(FPref.UI_ANTE)) {
final String nl = System.getProperty("line.separator");
final StringBuilder msg = new StringBuilder();
for (final Player p : game.getPlayers()) {
final List<Card> lib = p.getCardsIn(ZoneType.Library);
Predicate<Card> goodForAnte = Predicates.not(CardPredicates.Presets.BASIC_LANDS);
Card ante = Aggregates.random(Iterables.filter(lib, goodForAnte));
if (ante == null) {
throw new RuntimeException(p + " library is empty.");
}
game.getGameLog().add("Ante", p + " anted " + ante, 0);
VAntes.SINGLETON_INSTANCE.addAnteCard(p, ante);
game.getAction().moveTo(ZoneType.Ante, ante);
msg.append(p.getName()).append(" ante: ").append(ante).append(nl);
}
JOptionPane.showMessageDialog(null, msg, "Ante", JOptionPane.INFORMATION_MESSAGE);
}
GameOutcome lastGameOutcome = match.getLastGameOutcome();
// Only cut/coin toss if it's the first game of the match
Player goesFirst;
Player humanPlayer = Singletons.getControl().getPlayer();
boolean isFirstGame = lastGameOutcome == null;
if (isFirstGame) {
goesFirst = GameNew.seeWhoPlaysFirstDice(game);
} else {
goesFirst = lastGameOutcome.isWinner(humanPlayer.getLobbyPlayer()) ? humanPlayer.getOpponent() : humanPlayer;
}
String message = goesFirst + ( isFirstGame ? " has won the coin toss." : " lost the last game.");
boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message);
if ( goesFirst != humanPlayer ) {
JOptionPane.showMessageDialog(null, message + "\nComputer Going First", "You are drawing", JOptionPane.INFORMATION_MESSAGE);
}
goesFirst = willPlay ? goesFirst : goesFirst.getOpponent();
game.getPhaseHandler().setPlayerTurn(goesFirst);
}
// Draw <handsize> cards
for (final Player p : game.getPlayers()) {
p.drawCards(p.getMaxHandSize());
}
game.getPhaseHandler().setPhaseState(PhaseType.MULLIGAN);
InputControl control = match.getInput();
Input tmp = new InputMulligan();
control.setInput(tmp);
Thread thGame = new GameInputUpdatesThread(match, game);
match.getInput().getInput().showMessage();
thGame.setName("Game input updater");
thGame.start();
} // newGame()
private static String buildFourColumnList(String firstLine, Iterable<CardPrinted> cAnteRemoved) {
StringBuilder sb = new StringBuilder(firstLine);
int i = 0;

View File

@@ -666,4 +666,8 @@ public class GameState {
// TODO Auto-generated method stub
return actionPlay;
}
public boolean mulliganned = false;
public boolean hasMulliganned(){ return mulliganned; }
public void setMulliganned(boolean value) { mulliganned = value; }
}

View File

@@ -48,7 +48,6 @@ import forge.game.GameActionUtil;
import forge.game.GameState;
import forge.game.GlobalRuleChange;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilBlock;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost;
import forge.game.player.AIPlayer;
@@ -57,7 +56,6 @@ import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.gui.GuiDialog;
import forge.gui.GuiUtils;
import forge.gui.framework.EDocID;
import forge.gui.framework.SDisplayUtil;
import forge.gui.match.views.VCombat;
@@ -431,21 +429,8 @@ public class CombatUtil {
if (blockers.size() <= 1) {
continue;
}
List<Card> orderedBlockers = null;
if (player.isHuman()) {
GuiUtils.setPanelSelection(attacker);
List<Card> ordered = GuiChoose.order("Choose Blocking Order", "Damaged First", 0, blockers, null, attacker);
orderedBlockers = new ArrayList<Card>();
for (Object o : ordered) {
orderedBlockers.add((Card) o);
}
}
else {
orderedBlockers = ComputerUtilBlock.orderBlockers(attacker, blockers);
}
combat.setBlockerList(attacker, orderedBlockers);
List<Card> orderedBlockers = player.getController().orderBlockers(attacker, blockers);
combat.setBlockerList(attacker, orderedBlockers);
}
CombatUtil.showCombat();
// Refresh Combat Panel
@@ -459,19 +444,7 @@ public class CombatUtil {
continue;
}
List<Card> orderedAttacker = null;
if (blocker.getController().isHuman()) {
GuiUtils.setPanelSelection(blocker);
List<Card> ordered = GuiChoose.order("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker);
orderedAttacker = new ArrayList<Card>();
for (Object o : ordered) {
orderedAttacker.add((Card) o);
}
}
else {
orderedAttacker = ComputerUtilBlock.orderAttackers(blocker, attackers);
}
List<Card> orderedAttacker = blocker.getController().getController().orderAttackers(blocker, attackers);
combat.setAttackersBlockedByList(blocker, orderedAttacker);
}
CombatUtil.showCombat();

View File

@@ -52,9 +52,9 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
/** Constant <code>serialVersionUID=5207222278370963197L</code>. */
private static final long serialVersionUID = 5207222278370963197L;
private PhaseType phase = PhaseType.MULLIGAN;
private int turn = 0;
// Start turn at 0, so first untap step will turn it to 1
private PhaseType phase = PhaseType.UNTAP;
private int turn = 1;
// Start turn at 1, since first untap is where we start
private final transient Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>();
private final transient Map<PhaseType, Stack<PhaseType>> extraPhases = new HashMap<PhaseType, Stack<PhaseType>>();
@@ -262,7 +262,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
break;
case DRAW:
if (getTurn() == 1 || PhaseUtil.skipDraw(this.getPlayerTurn())) {
if (getTurn() == 1 || this.getPlayerTurn().isSkippingDraw()) {
this.setPlayersPriorityPermission(false);
} else {
this.getPlayerTurn().drawCards(1, true);

View File

@@ -9,8 +9,6 @@ import org.apache.commons.lang3.StringUtils;
public enum PhaseType {
MULLIGAN("Mulligan"),
// Note: Mulligan is not part of "All Phases" which are strictly ingame phases
UNTAP("Untap"),
UPKEEP("Upkeep"),
DRAW("Draw"),

View File

@@ -114,28 +114,7 @@ public class PhaseUtil {
game.getPhaseHandler().setPlayersPriorityPermission(false);
}
/**
* <p>
* skipDraw.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
* @return a boolean.
*/
public static boolean skipDraw(final Player player) {
if (player.hasKeyword("Skip your next draw step.")) {
player.removeKeyword("Skip your next draw step.");
return true;
}
if (player.hasKeyword("Skip your draw step.")) {
return true;
}
return false;
}
// ********* Declare Attackers ***********

View File

@@ -354,13 +354,14 @@ public class Upkeep extends Phase {
final Command paidCommand = Command.BLANK;
final Ability blankAbility = Upkeep.BlankAbility(c, upkeepCost);
blankAbility.setActivatingPlayer(controller);
final Ability upkeepAbility = new Ability(c, ManaCost.ZERO) {
@Override
public void resolve() {
if (controller.isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, blankAbility.getPayCosts(),
paidCommand, unpaidCommand, null, game);
paidCommand, unpaidCommand, this, game);
} else { // computer
if (ComputerUtilCost.shouldPayCost(controller, c, upkeepCost) && ComputerUtilCost.canPayCost(blankAbility, controller)) {
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game);

View File

@@ -3241,6 +3241,20 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
game.getStack().add(miracleTrigger);
}
public boolean isSkippingDraw() {
if (hasKeyword("Skip your next draw step.")) {
removeKeyword("Skip your next draw step.");
return true;
}
if (hasKeyword("Skip your draw step.")) {
return true;
}
return false;
}
/**
* TODO: Write javadoc for this type.
*

View File

@@ -97,4 +97,7 @@ public abstract class PlayerController {
public abstract boolean confirmAction(SpellAbility sa, String mode, String message);
public abstract boolean getWillPlayOnFirstTurn(String message);
public abstract boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message);
public abstract List<Card> orderBlockers(Card attacker, List<Card> blockers);
public abstract List<Card> orderAttackers(Card blocker, List<Card> attackers);
}

View File

@@ -15,6 +15,7 @@ import forge.game.ai.AiController;
import forge.game.ai.AiInputBlock;
import forge.game.ai.AiInputCommon;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilBlock;
import forge.game.ai.ComputerUtilCombat;
import forge.gui.GuiChoose;
@@ -208,4 +209,14 @@ public class PlayerControllerAi extends PlayerController {
return brains.confirmStaticApplication(hostCard, affected, logic, message);
}
@Override
public List<Card> orderBlockers(Card attacker, List<Card> blockers) {
return ComputerUtilBlock.orderBlockers(attacker, blockers);
}
@Override
public List<Card> orderAttackers(Card blocker, List<Card> attackers) {
return ComputerUtilBlock.orderAttackers(blocker, attackers);
}
}

View File

@@ -22,6 +22,7 @@ import forge.game.GameType;
import forge.game.phase.PhaseType;
import forge.gui.GuiChoose;
import forge.gui.GuiDialog;
import forge.gui.GuiUtils;
import forge.gui.match.CMatchUI;
import forge.item.CardPrinted;
@@ -260,4 +261,16 @@ public class PlayerControllerHuman extends PlayerController {
return !playDraw.equals(1);
}
@Override
public List<Card> orderBlockers(Card attacker, List<Card> blockers) {
GuiUtils.setPanelSelection(attacker);
return GuiChoose.order("Choose Blocking Order", "Damaged First", 0, blockers, null, attacker);
}
@Override
public List<Card> orderAttackers(Card blocker, List<Card> attackers) {
GuiUtils.setPanelSelection(blocker);
return GuiChoose.order("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker);
}
}

View File

@@ -32,6 +32,7 @@ import forge.CardPredicates.Presets;
import forge.Command;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostBeingPaid;
@@ -608,7 +609,7 @@ public class MagicStack extends MyObservable {
@Override
public void execute() {
for (int i = 0; i < sp.getSourceCard().getReplicateMagnitude(); i++) {
Singletons.getModel().getCardFactory().copySpellontoStack(sp.getSourceCard(), sp.getSourceCard(), sp, false);
CardFactory.copySpellontoStack(sp.getSourceCard(), sp.getSourceCard(), sp, false);
}
}
};

View File

@@ -36,10 +36,12 @@ import javax.swing.border.EtchedBorder;
import org.apache.commons.lang3.StringUtils;
import forge.Card;
import forge.CardCharacteristicName;
import forge.CounterType;
import forge.GameEntity;
import forge.Singletons;
import forge.card.CardEdition;
import forge.card.CardSplitType;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.toolbox.FLabel;
@@ -202,10 +204,14 @@ public class CardDetailPanel extends FPanel {
final boolean canShowThis = card.canBeShownTo(Singletons.getControl().getPlayer());
if (canShowThis) {
if (card.getManaCost().toString().equals("") || card.isLand()) {
if (card.getManaCost().isNoCost()) {
this.nameCostLabel.setText(card.getName());
} else {
this.nameCostLabel.setText(card.getName() + " - " + card.getManaCost());
String manaCost = card.getManaCost().toString();
if ( card.getRules() != null && card.getRules().getSplitType() == CardSplitType.Split && card.getCurState() == CardCharacteristicName.Original) {
manaCost = card.getRules().getMainPart().getManaCost().toString() + " // " + card.getRules().getOtherPart().getManaCost().toString();
}
this.nameCostLabel.setText(card.getName() + " - " + manaCost);
}
this.typeLabel.setText(GuiDisplayUtil.formatCardType(card));

View File

@@ -431,7 +431,7 @@ public final class GuiDisplayUtil {
for (final String element : data) {
final String[] cardinfo = element.trim().split("\\|");
final Card c = Singletons.getModel().getCardFactory().getCard(CardDb.instance().getCard(cardinfo[0]), player);
final Card c = CardDb.instance().getCard(cardinfo[0]).toForgeCard(player);
boolean hasSetCurSet = false;
for (final String info : cardinfo) {
@@ -596,7 +596,7 @@ public final class GuiDisplayUtil {
*/
public static void devModeCardToHand() {
final List<Player> players = Singletons.getModel().getGame().getPlayers();
final Player p = GuiChoose.oneOrNone("Put card in play for which player?", players);
final Player p = GuiChoose.oneOrNone("Put card in hand for which player?", players);
if (null == p) {
return;
}

View File

@@ -52,7 +52,7 @@ public class InputProxy extends MyObservable implements Observer {
* @param in
* a {@link forge.control.input.Input} object.
*/
public void setInput(final Input in) {
public final void setInput(final Input in) {
valid = true;
this.input = in;
this.input.showMessage(); // this call may invalidate the input by the time it returns

View File

@@ -106,15 +106,15 @@ public enum CDeckgen implements ICDoc {
switch (colorCount0) {
case 2:
genConstructed.getMain().addAll(
(new Generate2ColorDeck("AI", "AI")).get2ColorDeck(60, PlayerType.HUMAN));
(new Generate2ColorDeck("AI", "AI")).getDeck(60, PlayerType.HUMAN));
break;
case 3:
genConstructed.getMain().addAll(
(new Generate3ColorDeck("AI", "AI", "AI")).get3ColorDeck(60, PlayerType.HUMAN));
(new Generate3ColorDeck("AI", "AI", "AI")).getDeck(60, PlayerType.HUMAN));
break;
case 5:
genConstructed.getMain().addAll(
(new Generate5ColorDeck()).get5ColorDeck(60, PlayerType.HUMAN));
(new Generate5ColorDeck()).getDeck(60, PlayerType.HUMAN));
break;
default:
}

View File

@@ -24,6 +24,8 @@ import java.util.List;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.gui.toolbox.CardFaceSymbols;
@@ -34,7 +36,13 @@ import forge.gui.toolbox.CardFaceSymbols;
public class ManaCostRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1770527102334163549L;
private ManaCost value;
static final int elemtWidth = 13;
static final int elemtGap = 0;
static final int padding0 = 1;
static final int spaceBetweenSplitCosts = 3;
private ManaCost v1;
private ManaCost v2;
/*
* (non-Javadoc)
@@ -46,8 +54,10 @@ public class ManaCostRenderer extends DefaultTableCellRenderer {
@Override
public final Component getTableCellRendererComponent(final JTable table, final Object value,
final boolean isSelected, final boolean hasFocus, final int row, final int column) {
this.value = (ManaCost) value;
this.setToolTipText(this.value.toString());
CardRules v = value instanceof CardRules ? (CardRules) value : null;
this.v1 = v == null ? ManaCost.NO_COST : v.getMainPart().getManaCost();
this.v2 = v == null || v.getSplitType() != CardSplitType.Split ? null : v.getOtherPart().getManaCost();
this.setToolTipText(v2 == null ? v1.toString() : v1.toString() + " / " + v2.toString());
return super.getTableCellRendererComponent(table, "", isSelected, hasFocus, row, column);
}
@@ -60,18 +70,38 @@ public class ManaCostRenderer extends DefaultTableCellRenderer {
public final void paint(final Graphics g) {
super.paint(g);
final int elemtWidth = 13;
final int elemtGap = 0;
final int padding = 1;
float xpos = padding;
final int genericManaCost = this.value.getGenericCost();
final int xManaCosts = this.value.countX();
final boolean hasGeneric = (genericManaCost > 0) || this.value.isPureGeneric();
final List<ManaCostShard> shards = this.value.getShards();
final int cellWidth = this.getWidth();
if ( null == v2 )
drawCost(g, v1, padding0, cellWidth);
else
{
int shards1 = v1.isPureGeneric() || v1.getGenericCost() > 0 ? 1 : 0;
int shards2 = v2.isPureGeneric() || v2.getGenericCost() > 0 ? 1 : 0;
shards1 += v1.getShards().size();
shards2 += v2.getShards().size();
int perGlyph = (cellWidth - padding0 - spaceBetweenSplitCosts) / (shards1 + shards2);
perGlyph = Math.min(perGlyph, elemtWidth + elemtGap);
drawCost(g, v1, padding0, padding0 + perGlyph * shards1);
drawCost(g, v2, cellWidth - perGlyph * shards2, cellWidth );
}
}
/**
* TODO: Write javadoc for this method.
* @param g
* @param padding
* @param cellWidth
*/
private void drawCost(final Graphics g, ManaCost value, final int padding, final int cellWidth) {
float xpos = padding;
final int genericManaCost = value.getGenericCost();
final int xManaCosts = value.countX();
final boolean hasGeneric = (genericManaCost > 0) || this.v1.isPureGeneric();
final List<ManaCostShard> shards = value.getShards();
final int cntGlyphs = hasGeneric ? shards.size() + 1 : shards.size();
final float offsetIfNoSpace = cntGlyphs > 1 ? (cellWidth - padding - elemtWidth) / (cntGlyphs - 1f)
: elemtWidth + elemtGap;

View File

@@ -33,6 +33,7 @@ import forge.Singletons;
import forge.card.CardAiHints;
import forge.card.CardEdition;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.ColorSet;
import forge.card.mana.ManaCost;
import forge.deck.DeckBase;
@@ -318,11 +319,14 @@ public final class SColumnUtil {
private static final Pattern AE_FINDER = Pattern.compile("AE", Pattern.LITERAL);
private static ManaCost toManaCost(final InventoryItem i) {
return i instanceof CardPrinted ? ((IPaperCard) i).getRules().getManaCost() : ManaCost.NO_COST;
return i instanceof IPaperCard ? ((IPaperCard) i).getRules().getManaCost() : ManaCost.NO_COST;
}
private static CardRules toCardRules(final InventoryItem i) {
return i instanceof IPaperCard ? ((IPaperCard) i).getRules() : null;
}
private static ColorSet toColor(final InventoryItem i) {
return i instanceof CardPrinted ? ((IPaperCard) i).getRules().getColor() : ColorSet.getNullColor();
return i instanceof IPaperCard ? ((IPaperCard) i).getRules().getColor() : ColorSet.getNullColor();
}
private static int toPower(final InventoryItem i) {
@@ -430,7 +434,7 @@ public final class SColumnUtil {
private static final Function<Entry<InventoryItem, Integer>, Object> FN_COST_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toManaCost(from.getKey());
return SColumnUtil.toCardRules(from.getKey());
}
};

View File

@@ -61,7 +61,11 @@ public class GuiDownloadPicturesLQ extends GuiDownloader {
for (final IPaperCard c : CardDb.instance().getUniqueCards()) {
CardRules cardRules = c.getRules();
this.createDLObjects(cardRules.getPictureUrl(), cardRules.getMainPart().getName());
if (cardRules != null && cardRules.getSplitType() == CardSplitType.Split && cardRules.getOtherPart() != null) {
this.createDLObjects(cardRules.getPictureUrl(), String.format("%s%s", cardRules.getMainPart().getName(), cardRules.getOtherPart().getName()));
} else {
this.createDLObjects(cardRules.getPictureUrl(), cardRules.getMainPart().getName());
}
ICardCharacteristics secondSide = cardRules.getOtherPart();
if (secondSide != null && cardRules.getSplitType() == CardSplitType.Transform) {

View File

@@ -1,9 +1,12 @@
package forge.gui.home;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import forge.gui.toolbox.FSkin;
@@ -30,5 +33,17 @@ public class StartButton extends JButton {
setIcon(FSkin.getIcon(FSkin.ButtonImages.IMG_BTN_START_OVER));
}
});
addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setEnabled(false);
// ensure the click action can resolve before we allow the button to be clicked again
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() { setEnabled(true); }
});
}
});
}
}

View File

@@ -34,6 +34,7 @@ import forge.Command;
import forge.Constant;
import forge.Constant.Preferences;
import forge.Singletons;
import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
@@ -298,7 +299,7 @@ public class CField implements ICDoc {
faceDown.setName("Face Down");
choices2.add(faceDown);
} else {
final Card faceDown = Singletons.getModel().getCardFactory().copyCard(crd);
final Card faceDown = CardFactory.copyCard(crd);
faceDown.setState(CardCharacteristicName.Original);
choices2.add(faceDown);
}

View File

@@ -221,6 +221,7 @@ public class CardFaceSymbols {
g.drawImage(image, x, y, null);
}
/**
* <p>
* getWidth.
@@ -239,4 +240,8 @@ public class CardFaceSymbols {
//System.out.println(String.format("%d for %s", width, manaCost.toString()));
return width * 14;
}
public static int getHeight() {
return 14;
}
}

View File

@@ -20,7 +20,6 @@ package forge.item;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -80,7 +79,7 @@ public final class CardDb {
* @param list
* the new up
*/
public static void setup(final Iterator<CardRules> list) {
public static void setup(final Iterable<CardRules> list) {
if (CardDb.commonCards != null) {
throw new RuntimeException("CardDb has already been initialized, don't do it twice please");
}
@@ -425,9 +424,9 @@ public final class CardDb {
uniqueSpecialCards.put(cardName, lastAdded);
}
CardSorter(final Iterator<CardRules> parser) {
while (parser.hasNext()) {
this.addNewCard(parser.next());
CardSorter(final Iterable<CardRules> parser) {
for (CardRules cr : parser) {
this.addNewCard(cr);
}
}
}

View File

@@ -27,6 +27,7 @@ import forge.CardUtil;
import forge.Singletons;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.cardfactory.CardFactory;
import forge.game.player.Player;
@@ -295,7 +296,7 @@ public final class CardPrinted implements Comparable<IPaperCard>, InventoryItemF
*/
@Override
public Card toForgeCard(Player owner) {
final Card c = Singletons.getModel().getCardFactory().getCard(this, owner);
final Card c = CardFactory.getCard(this, owner);
return c;
}

View File

@@ -1,9 +1,9 @@
package forge.item;
import forge.Card;
import forge.Singletons;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.cardfactory.CardFactory;
import forge.game.player.Player;
public class CardToken implements InventoryItemFromSet, IPaperCard {
@@ -40,7 +40,7 @@ public class CardToken implements InventoryItemFromSet, IPaperCard {
@Override
public Card toForgeCard(Player owner) {
final Card c = Singletons.getModel().getCardFactory().getCard(this, owner);
final Card c = CardFactory.getCard(this, owner);
return c;
}

View File

@@ -32,8 +32,9 @@ import forge.card.CardBlock;
import forge.card.EditionCollection;
import forge.card.FatPackData;
import forge.card.FormatCollection;
import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardStorageReader;
import forge.deck.CardCollections;
import forge.error.BugReporter;
import forge.error.ExceptionHandler;
import forge.game.GameState;
import forge.game.GameType;
@@ -41,8 +42,11 @@ import forge.game.MatchController;
import forge.game.limited.GauntletMini;
import forge.game.player.LobbyPlayer;
import forge.gauntlet.GauntletData;
import forge.gui.GuiUtils;
import forge.item.CardDb;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
import forge.properties.NewConstants;
import forge.quest.QuestController;
import forge.quest.QuestWorld;
import forge.quest.data.QuestPreferences;
@@ -74,7 +78,6 @@ public enum FModel {
private GauntletData gauntletData;
private GauntletMini gauntlet;
private final CardFactory cardFactory;
private final QuestController quest;
private final CardCollections decks;
@@ -144,7 +147,16 @@ public enum FModel {
this.loadDynamicGamedata();
// Loads all cards (using progress bar).
this.cardFactory = new CardFactory();
GuiUtils.checkEDT("CardFactory$constructor", false);
final CardStorageReader reader = new CardStorageReader(NewConstants.CARD_DATA_DIR.defaultLoc, true);
try {
// this fills in our map of card names to Card instances.
CardDb.setup(reader.loadCards());
} catch (final Exception ex) {
BugReporter.reportException(ex);
}
this.decks = new CardCollections();
this.quest = new QuestController();
}
@@ -380,14 +392,6 @@ public enum FModel {
return gameState;
}
/**
* TODO: Write javadoc for this method.
* @return
*/
public CardFactory getCardFactory() {
return cardFactory;
}
public GauntletMini getGauntletMini() {
if (gauntlet == null) {

View File

@@ -46,6 +46,7 @@ import forge.util.storage.IStorageView;
*
*/
public class QuestUtilUnlockSets {
private static int UNLOCK_COST = 4000;
/**
* Consider unlocking a new expansion in limited quest format.
@@ -66,10 +67,10 @@ public class QuestUtilUnlockSets {
final List<ImmutablePair<CardEdition, Integer>> setPrices = new ArrayList<ImmutablePair<CardEdition, Integer>>();
for (CardEdition ed : getUnlockableEditions(qData)) {
int price = 7500;
int price = UNLOCK_COST;
if (mapPrices.containsKey(ed.getName() + " Booster Pack")) {
price = Math.max(new Double(60 * Math.pow(Math.sqrt(mapPrices.get(ed.getName()
+ " Booster Pack")), 1.65)).intValue(), 7500);
+ " Booster Pack")), 1.65)).intValue(), UNLOCK_COST);
}
setPrices.add(ImmutablePair.of(ed, price));
}

View File

@@ -36,10 +36,13 @@ import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import forge.Card;
import forge.CardCharacteristicName;
import forge.CounterType;
import forge.ImageCache;
import forge.Singletons;
import forge.card.CardEdition;
import forge.card.CardSplitType;
import forge.card.mana.ManaCost;
import forge.gui.CardContainer;
import forge.gui.toolbox.CardFaceSymbols;
import forge.properties.ForgePreferences.FPref;
@@ -351,6 +354,17 @@ public class CardPanel extends JPanel implements CardContainer {
}
}
/**
* TODO: Write javadoc for this method.
* @param g
* @param manaCost
*/
private void drawManaCost(final Graphics g, ManaCost cost, int deltaY ) {
int width = CardFaceSymbols.getWidth(cost);
int height = CardFaceSymbols.getHeight();
CardFaceSymbols.draw(g, cost, (this.cardXOffset + (this.cardWidth / 2)) - (width / 2), deltaY + this.cardYOffset + (this.cardHeight / 2) - height/2);
}
/** {@inheritDoc} */
@Override
protected final void paintChildren(final Graphics g) {
@@ -361,10 +375,16 @@ public class CardPanel extends JPanel implements CardContainer {
}
if (this.showCastingCost) {
int width = CardFaceSymbols.getWidth(this.getGameCard().getManaCost());
if (this.cardWidth < 200) {
CardFaceSymbols.draw(g, this.getGameCard().getManaCost(), (this.cardXOffset + (this.cardWidth / 2))
- (width / 2), this.cardYOffset + (this.cardHeight / 2));
Card gameCard = this.getGameCard();
boolean showSplitMana = gameCard.getRules() != null && gameCard.getRules().getSplitType() == CardSplitType.Split && gameCard.getCurState() == CardCharacteristicName.Original;
if ( !showSplitMana ) {
drawManaCost(g, gameCard.getManaCost(), 0);
} else {
drawManaCost(g, gameCard.getRules().getMainPart().getManaCost(), +12);
drawManaCost(g, gameCard.getRules().getOtherPart().getManaCost(), -12);
}
}
}