diff --git a/.classpath b/.classpath
index 18d70f02cb8..c4a47895836 100644
--- a/.classpath
+++ b/.classpath
@@ -2,5 +2,13 @@
+
+
+
+
+
+
+
+
diff --git a/res/cards.txt b/res/cards.txt
index 179e7319e7d..ba3819a899b 100644
--- a/res/cards.txt
+++ b/res/cards.txt
@@ -1461,7 +1461,7 @@ no text
Timbermaw Larva
3 G
Creature Beast
-Whenever Timbermaw Larva attacks, it gets +1/+1 until end of turn for each Forest you control.
+Whenever Timbermaw Larva attacks, it gets +1/+1 until end of turn for each you control.
2/2
Ghastlord of Fugue
@@ -18007,4 +18007,37 @@ Warrior's Honor
Instant
Creatures you control get +1/+1 until end of turn.
+Stifle
+U
+Instant
+Counter target activated or triggered ability.
+
+Spell Pierce
+U
+Instant
+Counter target noncreature spell unless its controller pays 2.
+
+Mystical Tutor
+U
+Instant
+Search your library for an instant or sorcery card and reveal that card. Shuffle your library, then put the card on top of it.
+
+Rebuild
+2 U
+Instant
+no text
+Cycling:2
+
+Wasteland
+no cost
+Land
+no text
+tap: add 1
+
+Strip Mine
+no cost
+Land
+no text
+tap: add 1
+
End
\ No newline at end of file
diff --git a/res/main.properties b/res/main.properties
index 857b9db867f..2fdfc6cb19d 100644
--- a/res/main.properties
+++ b/res/main.properties
@@ -1,6 +1,6 @@
program/mail=mtgerror@yahoo.com
program/forum=http://www.slightlymagic.net/forum/viewforum.php?f=26
-program/version=Forge -- official beta: 10/01/17, SVN revision: 323
+program/version=Forge -- official beta: $Date$, SVN revision: $Revision$
tokens--file=AllTokens.txt
diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java
index 8ea211b3b33..1e5b0ed2a6d 100644
--- a/src/forge/CardFactory.java
+++ b/src/forge/CardFactory.java
@@ -8910,25 +8910,56 @@ public class CardFactory implements NewConstants {
//is spell?, did opponent play it?, is this a creature spell?
return sa.isSpell() &&
opponent.equals(sa.getSourceCard().getController()) &&
- sa.getSourceCard().getType().contains("Creature");
+ sa.getSourceCard().getType().contains("Creature") &&
+ CardFactoryUtil.isCounterable(sa.getSourceCard());
}//canPlay()
};
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
-
- //*************** START *********** START **************************
- else if(cardName.equals("Counterspell") || cardName.equals("Cancel") || cardName.equals("Last Word") || cardName.equals("Traumatic Visions"))
+ //*************** START *********** START **************************
+ else if(cardName.equals("Spell Pierce"))
{
SpellAbility spell = new Spell(card)
{
- private static final long serialVersionUID = -2489268054171391552L;
+ private static final long serialVersionUID = 4685055135070191326L;
public void resolve()
{
- SpellAbility sa = AllZone.Stack.pop();
- AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
+ String manaCost = "2";
+ Ability ability = new Ability(card, manaCost){
+ public void resolve()
+ {
+ ;
+ }
+ };
+
+ final Command unpaidCommand = new Command()
+ {
+ private static final long serialVersionUID = 8094833091127334678L;
+
+ public void execute()
+ {
+ SpellAbility sa = AllZone.Stack.pop();
+ AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
+ }
+ };
+
+ if (card.getController().equals(Constant.Player.Computer))
+ {
+ AllZone.InputControl.setInput(new Input_PayManaCost_Ability(card +"\r\n", ability.getManaCost(), Command.Blank, unpaidCommand));
+ }
+ else
+ {
+ if (ComputerUtil.canPayCost(ability))
+ ComputerUtil.playNoStack(ability);
+ else
+ {
+ SpellAbility sa = AllZone.Stack.pop();
+ AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
+ }
+ }
}
public boolean canPlay()
{
@@ -8939,6 +8970,43 @@ public class CardFactory implements NewConstants {
String opponent = AllZone.GameAction.getOpponent(card.getController());
SpellAbility sa = AllZone.Stack.peek();
+ //is spell?, did opponent play it?, is this a creature spell?
+ return sa.isSpell() &&
+ opponent.equals(sa.getSourceCard().getController()) &&
+ !sa.getSourceCard().getType().contains("Creature") &&
+ CardFactoryUtil.isCounterable(sa.getSourceCard());
+ }//canPlay()
+ };
+ card.clearSpellAbility();
+ card.addSpellAbility(spell);
+ }//*************** END ************ END **************************
+
+ //*************** START *********** START **************************
+ else if(cardName.equals("Counterspell") || cardName.equals("Cancel") || cardName.equals("Last Word") || cardName.equals("Traumatic Visions") || cardName.equals("Stifle"))
+ {
+ SpellAbility spell = new Spell(card)
+ {
+ private static final long serialVersionUID = -2489268054171391552L;
+
+ public void resolve()
+ {
+ SpellAbility sa = AllZone.Stack.pop();
+ if(!cardName.equals("Stifle"))
+ AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
+ }
+ public boolean canPlay()
+ {
+ if(AllZone.Stack.size() == 0)
+ return false;
+
+ //see if spell is on stack and that opponent played it
+ String opponent = AllZone.GameAction.getOpponent(card.getController());
+ SpellAbility sa = AllZone.Stack.peek();
+
+ if(cardName.equals("Stifle"))
+ return !sa.isSpell() && CardFactoryUtil.isCounterable(sa.getSourceCard());
+
+
return sa.isSpell() && opponent.equals(sa.getSourceCard().getController())
&& CardFactoryUtil.isCounterable(sa.getSourceCard());
}
@@ -8949,8 +9017,14 @@ public class CardFactory implements NewConstants {
{
desc = "Last Word can't be countered by spells or abilities.\r\n";
}
- spell.setDescription(desc + "Counter target spell.");
- spell.setStackDescription(card.getName() + " - Counters target spell.");
+ if(cardName.equals("Stifle")){
+ spell.setDescription(desc + "Counter target triggered or activated ability.");
+ spell.setStackDescription(card.getName() + " - Counters target triggered or activated ability.");
+ } else
+ {
+ spell.setDescription(desc + "Counter target spell.");
+ spell.setStackDescription(card.getName() + " - Counters target spell.");
+ }
card.addSpellAbility(spell);
}//*************** END ************ END **************************
@@ -9545,7 +9619,7 @@ public class CardFactory implements NewConstants {
//*************** START *********** START **************************
- else if(cardName.equals("Evacuation"))
+ else if(cardName.equals("Evacuation") || cardName.equals("Rebuild"))
{
SpellAbility spell = new Spell(card)
{
@@ -9556,7 +9630,10 @@ public class CardFactory implements NewConstants {
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
- all = all.getType("Creature");
+ if(cardName.equals("Rebuild"))
+ all = all.getType("Artifact");
+ else
+ all = all.getType("Creature");
for(int i = 0; i < all.size(); i++)
{
@@ -9577,6 +9654,11 @@ public class CardFactory implements NewConstants {
return AllZone.getZone(Constant.Zone.Hand, c.getOwner());
}
};
+ if(cardName.equals("Rebuild"))
+ {
+ spell.setDescription("Return all artifacts to their owners' hands.");
+ spell.setStackDescription(card.getName() + " - return all artifacts to their owners' hands.");
+ }
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
@@ -9915,6 +9997,83 @@ public class CardFactory implements NewConstants {
card.addSpellAbility(spell);
}//*************** END ************ END **************************
+ //*************** START *********** START **************************
+ else if(cardName.equals("Mystical Tutor"))
+ {
+ SpellAbility spell = new Spell(card)
+ {
+ private static final long serialVersionUID = 2281623056004772379L;
+ public boolean canPlayAI()
+ {
+ return 4 < AllZone.Phase.getTurn();
+ }
+
+ public void resolve()
+ {
+ String player = card.getController();
+ if(player.equals(Constant.Player.Human))
+ humanResolve();
+ else
+ computerResolve();
+ }
+ public void computerResolve()
+ {
+ CardList list = new CardList(AllZone.Computer_Library.getCards());
+ CardList instantsAndSorceries = new CardList();
+
+ for (int i=0;i 0 && AllZone.GameAction.isCardInPlay(card))
+ return true;
+ else
+ return false;
+
+ }//canPlay()
+ public void resolve()
+ {
+ if(card.getOwner().equals(Constant.Player.Human))
+ humanResolve();
+ //else
+ // computerResolve();
+ }
+
+ public void humanResolve()
+ {
+ Card target = getTargetCard();
+ if(target != null)
+ AllZone.GameAction.destroy(target);
+ }//resolve()
+ };//SpellAbility
+
+ Input runtime = new Input()
+ {
+
+ private static final long serialVersionUID = -7328086812286814833L;
+ boolean once = true;
+ public void showMessage()
+ {
+ //this is necessary in order not to have a StackOverflowException
+ //because this updates a card, it creates a circular loop of observers
+ if(once)
+ {
+ once = false;
+ String player = card.getController();
+
+ PlayerZone compBattlezone = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
+ PlayerZone playerBattlezone = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
+ CardList list = new CardList(compBattlezone.getCards());
+ list.addAll(playerBattlezone.getCards());
+
+ list = list.filter(new CardListFilter()
+ {
+ public boolean addCard(Card c)
+ {
+ if(card.getName().equals("Wasteland"))
+ return c.getType().contains("Land") && !c.getType().contains("Basic");
+ else
+ return c.getType().contains("Land");
+ }
+ });
+
+ Object o = AllZone.Display.getChoice("Choose a " + (card.getName().equals("Wasteland") ? "nonbasic" : "") + "land to destroy", list.toArray());
+ ability.setTargetCard((Card)o);
+
+ AllZone.GameAction.sacrifice(card);
+
+ //ability.setStackDescription(card.getController() +" - Destroy target " + (card.getName().equals("Wasteland") ? "nonbasic" : "") + "land.");
+
+ AllZone.Stack.add(ability);
+
+ stop();
+ }
+ }//showMessage()
+ };
+ card.addSpellAbility(ability);
+ ability.setDescription("Tap, Sacrifice " + card.getName() +": Destroy target " + (card.getName().equals("Wasteland") ? "nonbasic" : "") + "land.");
+ ability.setBeforePayMana(runtime);
+ }//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Arid Mesa") || cardName.equals("Marsh Flats") || cardName.equals("Misty Rainforest") ||
diff --git a/src/forge/ComputerAI_counterSpells2.java b/src/forge/ComputerAI_counterSpells2.java
index f9ece8591bb..0a82b58a129 100644
--- a/src/forge/ComputerAI_counterSpells2.java
+++ b/src/forge/ComputerAI_counterSpells2.java
@@ -37,6 +37,10 @@ public class ComputerAI_counterSpells2 {
""
};
+ final String[] nonCreatureUnlessPay2 = {
+ "Spell Pierce"
+ };
+
final String[] unlessPay1 = {
"Force Spike", "Daze", "Runeboggle", "Spell Snip"
};
@@ -86,6 +90,11 @@ public class ComputerAI_counterSpells2 {
return true;
}
+ else if (!sa.getSourceCard().isCreature() && usableManaSources < 2) {
+ if (checkArray(c, nonCreatureUnlessPay2))
+ return true;
+ }
+
if (checkArray(c, basic))
return true;
diff --git a/src/forge/GuiDisplay3.java b/src/forge/GuiDisplay3.java
index 5047d9a212e..2c00830e6cf 100644
--- a/src/forge/GuiDisplay3.java
+++ b/src/forge/GuiDisplay3.java
@@ -70,6 +70,7 @@ import com.google.common.collect.MapMaker;
//import org.omg.CORBA.portable.InputStream;
import arcane.ui.ScaledImagePanel;
+import arcane.ui.ScaledImagePanel.MultipassType;
import arcane.ui.ScaledImagePanel.ScalingType;
import forge.error.ErrorViewer;
@@ -662,9 +663,8 @@ public class GuiDisplay3 extends JFrame implements Display, NewConstants, NewCon
else {
InputStream stream;
try {
- //stream = new URL(GuiDisplayUtil.getURL(c)).openStream();
stream = GuiDisplayUtil.getURL(c).openStream();
- srcImage = ImageIO.read(stream);
+ srcImage = arcane.ui.util.ImageUtil.getImage(stream);
imageCache.put(imageName, srcImage);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
@@ -675,25 +675,9 @@ public class GuiDisplay3 extends JFrame implements Display, NewConstants, NewCon
}
}
- //BufferedImage srcImageBlurred = arcane.ui.util.ImageUtil.getBlurredImage(srcImage, 3, 1.0f); // get a blurred image
- cardImagePanel.setImage(srcImage, srcImage);
- cardImagePanel.repaint();
- /*
- BufferedInputStream stream = (BufferedInputStream) GuiDisplayUtil.getPictureStream(c);
- BufferedImage srcImage;
- try {
- srcImage = arcane.ui.util.ImageUtil.getImage(stream);
- BufferedImage srcImageBlurred = arcane.ui.util.ImageUtil.getBlurredImage(srcImage, 3, 1.0f); // get a blurred image
-
- cardImagePanel.setImage(srcImage, srcImageBlurred);
- cardImagePanel.repaint();
-
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } // only need stream
- */
+ cardImagePanel.setImage(srcImage, null);
+ cardImagePanel.repaint();
//System.out.println(picturePanel.getComponentCount());
}//updateCardDetail()
@@ -1274,9 +1258,10 @@ public class GuiDisplay3 extends JFrame implements Display, NewConstants, NewCon
pane.add(new ExternalPanel(picturePanel), "picture");
*/
- cardImagePanel.setScalingBlur(true); //use blured image if scaling down more than 50%
+ cardImagePanel.setScalingBlur(false); //use blured image if scaling down more than 50%
cardImagePanel.setScaleLarger(true); //upscale if needed true
cardImagePanel.setScalingType(ScalingType.bicubic); // type of scaling bicubic has good quality / speed ratio
+ cardImagePanel.setScalingMultiPassType(MultipassType.none);
cardImagePanel.setLayout(new BoxLayout(cardImagePanel, BoxLayout.Y_AXIS));
cardImagePanel.setBackground(c1);
diff --git a/src/forge/Gui_DownloadPictures.java b/src/forge/Gui_DownloadPictures.java
index 5f80b13362e..3615181e7ff 100644
--- a/src/forge/Gui_DownloadPictures.java
+++ b/src/forge/Gui_DownloadPictures.java
@@ -5,6 +5,7 @@ import static javax.swing.JOptionPane.*;
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
@@ -181,11 +182,20 @@ public class Gui_DownloadPictures extends DefaultBoundedRangeModel implements Ru
private void update(int card) {
this.card = card;
- fireStateChanged();
- bar.setString(String.format(ForgeProps.getLocalized(card == cards.length? BAR_CLOSE:BAR_WAIT), this.card,
- cards.length));
- System.out.println(card + "/" + cards.length);
-
+ final class Worker implements Runnable{
+ private int card;
+ Worker(int card){
+ this.card = card;
+ }
+
+ public void run() {
+ fireStateChanged();
+ bar.setString(String.format(ForgeProps.getLocalized(card == cards.length? BAR_CLOSE:BAR_WAIT), card,
+ cards.length));
+ System.out.println(card + "/" + cards.length);
+ }
+ };
+ EventQueue.invokeLater(new Worker(card));
}
public JDialog getDlg(JFrame frame) {
diff --git a/src/forge/Gui_DownloadPictures_LQ.java b/src/forge/Gui_DownloadPictures_LQ.java
index c1f5cb5db47..7bcaa9e718e 100644
--- a/src/forge/Gui_DownloadPictures_LQ.java
+++ b/src/forge/Gui_DownloadPictures_LQ.java
@@ -4,6 +4,7 @@ import static java.lang.Integer.*;
import static javax.swing.JOptionPane.*;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
@@ -146,10 +147,20 @@ public class Gui_DownloadPictures_LQ extends DefaultBoundedRangeModel implements
private void update(int card) {
this.card = card;
- fireStateChanged();
- bar.setString(String.format(ForgeProps.getLocalized(card == cards.length? BAR_CLOSE:BAR_WAIT), this.card,
- cards.length));
- System.out.println(card + "/" + cards.length);
+ final class Worker implements Runnable{
+ private int card;
+ Worker(int card){
+ this.card = card;
+ }
+
+ public void run() {
+ fireStateChanged();
+ bar.setString(String.format(ForgeProps.getLocalized(card == cards.length? BAR_CLOSE:BAR_WAIT), card,
+ cards.length));
+ System.out.println(card + "/" + cards.length);
+ }
+ };
+ EventQueue.invokeLater(new Worker(card));
}
public JDialog getDlg(JFrame frame) {