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)) {