diff --git a/Mage.Client/src/main/java/mage/client/components/MageTextArea.java b/Mage.Client/src/main/java/mage/client/components/MageTextArea.java index c589fe32cc2..d9b4bdd7051 100644 --- a/Mage.Client/src/main/java/mage/client/components/MageTextArea.java +++ b/Mage.Client/src/main/java/mage/client/components/MageTextArea.java @@ -40,7 +40,7 @@ public class MageTextArea extends JEditorPane { buffer.append("pt;margin:3px 3px 3px 3px;color: #FFFFFF'>
"); text = text.replaceAll("#([^#]+)#", "$1"); - text = text.replaceAll("\\s*//\\s*", "
"); + //text = text.replaceAll("\\s*//\\s*", "
"); text = text.replace("\r\n", "
"); //text += "
"; diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java index c12732d4065..56782810eae 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java @@ -117,11 +117,13 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane { buffer.append("pt;margin:0px 1px 0px 1px'>"); buffer.append(""); buffer.append("
"); - buffer.append(card.getName()); + buffer.append(card.getDisplayName()); buffer.append(""); - buffer.append(castingCost); + if (!card.isSplitCard()) { + buffer.append(castingCost); + } buffer.append("
"); buffer.append("
"); buffer.append(getTypes(card)); @@ -160,24 +162,49 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane { buffer.append("
"); } - String legal = ""; - if (rulings.size() > 0) { - legal = legal.replaceAll("#([^#]+)#", "$1"); - legal = legal.replaceAll("\\s*//\\s*", "
"); - legal = legal.replace("\r\n", "
"); - legal += "
"; - for (String ruling : rulings) { + StringBuilder rule = new StringBuilder("
"); + if (card.isSplitCard()) { + rule.append(""); + rule.append("
"); + rule.append(card.getLeftSplitName()); + rule.append(""); + rule.append(card.getLeftSplitCosts().getText()); + rule.append("
"); + for (String ruling : card.getLeftSplitRules()) { if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) { - legal += "

"; - legal += ruling; - legal += "

"; + rule.append("

").append(ruling).append("

"); + } + } + rule.append(""); + rule.append("
"); + rule.append(card.getRightSplitName()); + rule.append(""); + rule.append(card.getRightSplitCosts().getText()); + rule.append("
"); + for (String ruling : card.getRightSplitRules()) { + if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) { + rule.append("

").append(ruling).append("

"); } } } + if (rulings.size() > 0) { + for (String ruling : rulings) { + if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) { + rule.append("

").append(ruling).append("

"); + } + } + } - + String legal = rule.toString(); if (legal.length() > 0) { - //buffer.append("
"); +// this 2 replaces were only done with the empty string, is it any longer needed? (LevelX2) +// legal = legal.replaceAll("#([^#]+)#", "$1"); +// legal = legal.replaceAll("\\s*//\\s*", "
"); +// legal = legal.replace("\r\n", "
"); legal = legal.replaceAll("\\{this\\}", card.getName()); legal = legal.replaceAll("\\{source\\}", card.getName()); buffer.append(ManaSymbols.replaceSymbolsWithHTML(legal, ManaSymbols.Type.CARD)); diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index df7fd22d019..e1e7725e389 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -33,14 +33,11 @@ import mage.Constants.CardType; import mage.Constants.Rarity; import mage.MageObject; import mage.ObjectColor; -import mage.abilities.Mode; import mage.cards.Card; -import mage.counters.Counter; import mage.counters.CounterType; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; import mage.game.permanent.token.Token; -import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.target.Target; import mage.target.Targets; @@ -48,6 +45,11 @@ import mage.target.Targets; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.costs.mana.ManaCosts; +import mage.cards.SplitCard; +import mage.counters.Counter; +import mage.game.stack.Spell; /** * @author BetaSteward_at_googlemail.com @@ -57,6 +59,7 @@ public class CardView extends SimpleCardView { protected UUID parentId; protected String name; + protected String displayName; protected List rules; protected String power; protected String toughness; @@ -76,6 +79,14 @@ public class CardView extends SimpleCardView { protected CardView secondCardFace; protected boolean transformed; + protected boolean isSplitCard; + protected String leftSplitName; + protected ManaCosts leftSplitCosts; + protected List leftSplitRules; + protected String rightSplitName; + protected ManaCosts rightSplitCosts; + protected List rightSplitRules; + protected List targets; protected UUID pairedCard; @@ -95,9 +106,44 @@ public class CardView extends SimpleCardView { fillEmpty(); return; } + Card cardHalf = null; + SplitCard splitCard = null; + this.isSplitCard = card.isSplitCard(); + if (card instanceof Spell) { + if (((Spell) card).getSpellAbility().getSpellAbilityType().equals(Constants.SpellAbilityType.SPLIT_LEFT)) { + splitCard = (SplitCard) ((Spell) card).getCard(); + cardHalf = ((SplitCard) splitCard).getLeftHalfCard(); + } else if (((Spell) card).getSpellAbility().getSpellAbilityType().equals(Constants.SpellAbilityType.SPLIT_RIGHT)) { + splitCard = (SplitCard) ((Spell) card).getCard(); + cardHalf = ((SplitCard) splitCard).getRightHalfCard(); + } else if (((Spell) card).getSpellAbility().getSpellAbilityType().equals(Constants.SpellAbilityType.SPLIT_FUSED)) { + isSplitCard = true; + splitCard = (SplitCard) ((Spell) card).getCard(); + } + } else if (card.isSplitCard()) { + splitCard = (SplitCard) card; + } + if (this.isSplitCard && splitCard != null) { + leftSplitName = splitCard.getLeftHalfCard().getName(); + leftSplitCosts = splitCard.getLeftHalfCard().getManaCost(); + leftSplitRules = splitCard.getLeftHalfCard().getRules(); + rightSplitName = splitCard.getRightHalfCard().getName(); + rightSplitCosts = splitCard.getRightHalfCard().getManaCost(); + rightSplitRules = splitCard.getRightHalfCard().getRules(); + } this.name = card.getName(); - this.rules = card.getRules(); + if (cardHalf != null) { + this.displayName = cardHalf.getName(); + this.rules = cardHalf.getRules(); + this.manaCost = cardHalf.getManaCost().getSymbols(); + this.convertedManaCost = cardHalf.getManaCost().convertedManaCost(); + } else { + this.displayName = card.getName(); + this.rules = card.getRules(); + this.manaCost = card.getManaCost().getSymbols(); + this.convertedManaCost = card.getManaCost().convertedManaCost(); + } if (card instanceof Permanent) { Permanent permanent = (Permanent)card; this.power = Integer.toString(card.getPower().getValue()); @@ -113,9 +159,9 @@ public class CardView extends SimpleCardView { this.subTypes = card.getSubtype(); this.superTypes = card.getSupertype(); this.color = card.getColor(); - this.manaCost = card.getManaCost().getSymbols(); - this.convertedManaCost = card.getManaCost().convertedManaCost(); this.canTransform = card.canTransform(); + + if (card instanceof PermanentToken) { this.rarity = Rarity.COMMON; this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode(); @@ -152,7 +198,6 @@ public class CardView extends SimpleCardView { public CardView(MageObject card) { super(card.getId(), "", 0, false, false); - this.name = card.getName(); if (card instanceof Permanent) { this.power = Integer.toString(card.getPower().getValue()); @@ -256,6 +301,10 @@ public class CardView extends SimpleCardView { return name; } + public String getDisplayName() { + return displayName; + } + public List getRules() { return rules; } @@ -381,6 +430,34 @@ public class CardView extends SimpleCardView { return this.canTransform; } + public boolean isSplitCard() { + return this.isSplitCard; + } + + public String getLeftSplitName() { + return leftSplitName; + } + + public ManaCosts getLeftSplitCosts() { + return leftSplitCosts; + } + + public List getLeftSplitRules() { + return leftSplitRules; + } + + public String getRightSplitName() { + return rightSplitName; + } + + public ManaCosts getRightSplitCosts() { + return rightSplitCosts; + } + + public List getRightSplitRules() { + return rightSplitRules; + } + public CardView getSecondCardFace() { return this.secondCardFace; } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index ff9564aaedd..9651f5ceacb 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -80,6 +80,8 @@ import java.io.IOException; import java.io.Serializable; import java.util.*; import java.util.Map.Entry; +import static mage.Constants.SpellAbilityType.SPLIT; +import static mage.Constants.SpellAbilityType.SPLIT_FUSED; @@ -1204,6 +1206,26 @@ public class ComputerPlayer> extends PlayerImpl i return 0; } + @Override + public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) { + switch(ability.getSpellAbilityType()) { + case SPLIT: + case SPLIT_FUSED: + MageObject object = game.getObject(ability.getSourceId()); + if (object != null) { + LinkedHashMap useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game); + if (useableAbilities != null && useableAbilities.size() > 0) { + game.fireGetChoiceEvent(playerId, name, new ArrayList(useableAbilities.values())); + // TODO: Improve this + return (SpellAbility) useableAbilities.values().iterator().next(); + } + } + return null; + default: + return ability; + } + } + @Override public Mode chooseMode(Modes modes, Ability source, Game game) { log.debug("chooseMode"); diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index cb75b1e6139..aaa525e932a 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -32,6 +32,8 @@ import java.io.Serializable; import java.util.*; import mage.Constants.Outcome; import mage.Constants.RangeOfInfluence; +import static mage.Constants.SpellAbilityType.SPLIT; +import static mage.Constants.SpellAbilityType.SPLIT_FUSED; import mage.Constants.Zone; import mage.MageObject; import mage.abilities.*; @@ -741,6 +743,32 @@ public class HumanPlayer extends PlayerImpl { } } + @Override + public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) { + switch(ability.getSpellAbilityType()) { + case SPLIT: + case SPLIT_FUSED: + MageObject object = game.getObject(ability.getSourceId()); + if (object != null) { + LinkedHashMap useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game); + if (useableAbilities != null && useableAbilities.size() == 1) { + return (SpellAbility) useableAbilities.values().iterator().next(); + } else if (useableAbilities != null && useableAbilities.size() > 0) { + game.fireGetChoiceEvent(playerId, name, new ArrayList(useableAbilities.values())); + waitForResponse(); + if (response.getUUID() != null) { + if (useableAbilities.containsKey(response.getUUID())) { + return (SpellAbility) useableAbilities.get(response.getUUID()); + } + } + } + } + return null; + default: + return ability; + } + } + @Override public Mode chooseMode(Modes modes, Ability source, Game game) { updateGameStatePriority("chooseMode", game); diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index e2d6d55a666..b7677acdcd7 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -39,7 +39,7 @@ public class SystemUtil { public static void addCardsForTesting(Game game) { try { File f = new File(INIT_FILE_PATH); - Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)"); + Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\/\\-.!'\\d]*):([\\d]*)"); if (!f.exists()) { logger.warn("Couldn't find init file: " + INIT_FILE_PATH); return; diff --git a/Mage/src/mage/abilities/SpellAbility.java b/Mage/src/mage/abilities/SpellAbility.java index d0804b22302..4d76a87d8a1 100644 --- a/Mage/src/mage/abilities/SpellAbility.java +++ b/Mage/src/mage/abilities/SpellAbility.java @@ -33,9 +33,7 @@ import mage.Constants.AsThoughEffectType; import mage.Constants.CardType; import mage.Constants.Zone; import mage.MageObject; -import mage.abilities.costs.Cost; import mage.abilities.costs.mana.ManaCost; -import mage.abilities.effects.Effect; import mage.abilities.keyword.FlashAbility; import mage.game.Game; @@ -90,7 +88,9 @@ public class SpellAbility extends ActivatedAbilityImpl { object.getAbilities().containsKey(FlashAbility.getInstance().getId()) || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST, game) || game.canPlaySorcery(playerId))) { - + if (spellAbilityType.equals(SpellAbilityType.SPLIT)) { + return false; + } // fix for Gitaxian Probe and casting opponent's spells if (!controllerId.equals(playerId)) { return false; diff --git a/Mage/src/mage/cards/SplitCard.java b/Mage/src/mage/cards/SplitCard.java index a560e218659..d8fb81d4e90 100644 --- a/Mage/src/mage/cards/SplitCard.java +++ b/Mage/src/mage/cards/SplitCard.java @@ -38,8 +38,6 @@ import mage.abilities.Abilities; import mage.abilities.AbilitiesImpl; import mage.abilities.Ability; import mage.abilities.SpellAbility; -import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.costs.mana.ManaCostsImpl; import mage.watchers.Watcher; /** @@ -108,11 +106,10 @@ public abstract class SplitCard> extends CardImpl { @Override public List getRules() { List rules = new ArrayList(); - rules.addAll(leftHalfCard.getRules()); - rules.addAll(rightHalfCard.getRules()); +// rules.addAll(leftHalfCard.getRules()); +// rules.addAll(rightHalfCard.getRules()); if (getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) { - rules.add("--------------------------------------------------------------------------"); - rules.add("Fuse (You may cast one or both halves of this card from your hand.)"); + rules.add("--------------------------------------------------------------------------\nFuse (You may cast one or both halves of this card from your hand.)"); } return rules; } @@ -163,23 +160,24 @@ class LeftHalfCard extends CardImpl { return new LeftHalfCard(this); } - @Override - public List getRules() { - List rules = new ArrayList(); - // TODO: Move formatting to client CardInfoPaneImpl.java - StringBuilder buffer = new StringBuilder(); - buffer.append(""); - buffer.append("
"); - buffer.append(this.getName()); - buffer.append(""); - buffer.append(getSpellAbility().getManaCosts().getText()); - buffer.append("
"); - rules.add(buffer.toString()); - rules.addAll(super.getRules()); - return rules; - } +// @Override +// public List getRules() { +// List rules = new ArrayList(); +// // TODO: Move formatting to client CardInfoPaneImpl.java +// StringBuilder buffer = new StringBuilder(); +// buffer.append(""); +// buffer.append("
"); +// buffer.append(this.getName()); +// buffer.append(""); +// buffer.append(getSpellAbility().getManaCosts().getText()); +// buffer.append("
"); +// +// rules.add(buffer.toString()); +// rules.addAll(super.getRules()); +// return rules; +// } } @@ -202,21 +200,21 @@ class RightHalfCard extends CardImpl { return new RightHalfCard(this); } - @Override - public List getRules() { - List rules = new ArrayList(); - // TODO: Move formatting to client CardInfoPaneImpl.java - StringBuilder buffer = new StringBuilder(); - buffer.append(""); - buffer.append("
"); - buffer.append(this.getName()); - buffer.append(""); - buffer.append(getSpellAbility().getManaCosts().getText()); - buffer.append("
"); - rules.add(buffer.toString()); - rules.addAll(super.getRules()); - return rules; - } +// @Override +// public List getRules() { +// List rules = new ArrayList(); +// // TODO: Move formatting to client CardInfoPaneImpl.java +// StringBuilder buffer = new StringBuilder(); +// buffer.append(""); +// buffer.append("
"); +// buffer.append(this.getName()); +// buffer.append(""); +// buffer.append(getSpellAbility().getManaCosts().getText()); +// buffer.append("
"); +// rules.add(buffer.toString()); +// rules.addAll(super.getRules()); +// return rules; +// } } diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 72e27ea3447..1d5c16af560 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -591,4 +591,8 @@ public class Spell> implements StackObject, Card { @Override public void removeCounters(Counter counter, Game game) {} + + public Card getCard() { + return card; + } } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 644cca18b0d..1bdb51151ca 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -167,6 +167,7 @@ public interface Player extends MageItem, Copyable { int drawCards(int num, Game game); int drawCards(int num, Game game, ArrayList appliedEffects); boolean cast(SpellAbility ability, Game game, boolean noMana); + SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana); boolean putInHand(Card card, Game game); boolean removeFromHand(Card card, Game game); boolean removeFromBattlefield(Permanent permanent, Game game); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 81be3063d60..2ad0243667f 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -595,6 +595,9 @@ public abstract class PlayerImpl> implements Player, Ser @Override public boolean cast(SpellAbility ability, Game game, boolean noMana) { + if (!ability.getSpellAbilityType().equals(SpellAbilityType.BASE)) { + ability = chooseSpellAbilityForCast(ability, game, noMana); + } //20091005 - 601.2a Card card = game.getCard(ability.getSourceId()); if (card != null) { @@ -618,6 +621,11 @@ public abstract class PlayerImpl> implements Player, Ser return false; } + @Override + public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) { + return ability; + } + @Override public boolean playLand(Card card, Game game) { //20091005 - 305.1 @@ -775,6 +783,31 @@ public abstract class PlayerImpl> implements Player, Ser return false; } + protected LinkedHashMap getSpellAbilities(MageObject object, Zone zone, Game game) { + LinkedHashMap useable = new LinkedHashMap(); + for (Ability ability: object.getAbilities()) { + if (ability instanceof SpellAbility) { + if (((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) { + if (zone.equals(Zone.HAND)) { + // Fix so you don't need to choose Fuse twice + useable.clear(); + useable.put(ability.getId(), (SpellAbility) ability); + return useable; + } else { + // Fuse only allowed from hand + continue; + } + } + if (((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT)) { + continue; + } + useable.put(ability.getId(), (SpellAbility) ability); + } + } + return useable; + } + + protected LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, Game game) { LinkedHashMap useable = new LinkedHashMap(); for (ActivatedAbility ability: object.getAbilities().getActivatedAbilities(zone)) {