remove extraneous whitespace
parent
cd385a4be8
commit
64368e1b9a
|
@ -12,7 +12,7 @@ import magic.ui.GameController;
|
|||
import java.io.File;
|
||||
|
||||
public class DeckStrCal {
|
||||
|
||||
|
||||
private static int games = 10;
|
||||
private static int repeat = 1;
|
||||
private static int str1 = 6;
|
||||
|
@ -95,14 +95,14 @@ public class DeckStrCal {
|
|||
validArgs = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (deck1.length() == 0) {
|
||||
System.err.println("Using player profile to generate deck 1");
|
||||
} else if (!(new File(deck1)).exists()) {
|
||||
System.err.println("Error: file " + deck1 + " does not exist");
|
||||
validArgs = false;
|
||||
}
|
||||
|
||||
|
||||
if (deck2.length() == 0) {
|
||||
System.err.println("Using player profile to generate deck 2");
|
||||
} else if (!(new File(deck2)).exists()) {
|
||||
|
@ -130,7 +130,7 @@ public class DeckStrCal {
|
|||
testDuel.initialize();
|
||||
testDuel.setDifficulty(0, str1);
|
||||
testDuel.setDifficulty(1, str2);
|
||||
|
||||
|
||||
// Set the AI
|
||||
testDuel.setAIs(new MagicAI[]{ai1.getAI(), ai2.getAI()});
|
||||
testDuel.getPlayer(0).setArtificial(true);
|
||||
|
@ -138,7 +138,7 @@ public class DeckStrCal {
|
|||
|
||||
// Set the deck.
|
||||
if (deck1.length() > 0) {
|
||||
DeckUtils.loadDeck(deck1, testDuel.getPlayer(0));
|
||||
DeckUtils.loadDeck(deck1, testDuel.getPlayer(0));
|
||||
}
|
||||
if (deck2.length() > 0) {
|
||||
DeckUtils.loadDeck(deck2, testDuel.getPlayer(1));
|
||||
|
@ -146,11 +146,11 @@ public class DeckStrCal {
|
|||
|
||||
return testDuel;
|
||||
}
|
||||
|
||||
|
||||
public static void main(final String[] args) {
|
||||
// setup the handler for any uncaught exception
|
||||
Thread.setDefaultUncaughtExceptionHandler(new magic.model.MagicGameReport());
|
||||
|
||||
|
||||
if (!parseArguments(args)) {
|
||||
System.err.println("Usage: java -cp <path to Magarena.jar/exe> magic.DeckStrCal --deck1 <.dec file> --deck2 <.dec file> [options]");
|
||||
System.err.println("Options:");
|
||||
|
@ -160,7 +160,7 @@ public class DeckStrCal {
|
|||
System.err.println("--games <1-*> (number of games to play, default 10)");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
// Load cards and cubes.
|
||||
MagicMain.initializeEngine();
|
||||
|
||||
|
@ -168,10 +168,10 @@ public class DeckStrCal {
|
|||
runDuel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void runDuel() {
|
||||
final MagicDuel testDuel = setupDuel();
|
||||
|
||||
|
||||
System.out.println(
|
||||
"#deck1" +
|
||||
"\tai1" +
|
||||
|
@ -181,15 +181,15 @@ public class DeckStrCal {
|
|||
"\tstr2" +
|
||||
"\tgames" +
|
||||
"\td1win"+
|
||||
"\td1lose"
|
||||
);
|
||||
"\td1lose"
|
||||
);
|
||||
|
||||
int played = 0;
|
||||
while (!testDuel.isFinished()) {
|
||||
final MagicGame game=testDuel.nextGame(false);
|
||||
game.setArtificial(true);
|
||||
final GameController controller=new GameController(game);
|
||||
|
||||
|
||||
//maximum duration of a game is 60 minutes
|
||||
controller.setMaxTestGameDuration(3600000);
|
||||
|
||||
|
@ -199,13 +199,13 @@ public class DeckStrCal {
|
|||
deck1 + "\t" +
|
||||
ai1 + "\t" +
|
||||
str1 + "\t" +
|
||||
deck2 + "\t" +
|
||||
deck2 + "\t" +
|
||||
ai2 + "\t" +
|
||||
str2 + "\t" +
|
||||
testDuel.getGamesTotal() + "\t" +
|
||||
testDuel.getGamesWon() + "\t" +
|
||||
(testDuel.getGamesPlayed() - testDuel.getGamesWon())
|
||||
);
|
||||
);
|
||||
played = testDuel.getGamesPlayed();
|
||||
}
|
||||
}
|
||||
|
@ -213,12 +213,12 @@ public class DeckStrCal {
|
|||
deck1 + "\t" +
|
||||
ai1 + "\t" +
|
||||
str1 + "\t" +
|
||||
deck2 + "\t" +
|
||||
deck2 + "\t" +
|
||||
ai2 + "\t" +
|
||||
str2 + "\t" +
|
||||
testDuel.getGamesTotal() + "\t" +
|
||||
testDuel.getGamesWon() + "\t" +
|
||||
(testDuel.getGamesPlayed() - testDuel.getGamesWon())
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,14 +43,14 @@ import java.awt.image.BufferedImage;
|
|||
|
||||
/**
|
||||
* <p><code>GraphicsUtilities</code> contains a set of tools to perform
|
||||
* common graphics operations easily.
|
||||
* common graphics operations easily.
|
||||
*
|
||||
* @author Romain Guy <romain.guy@mac.com>
|
||||
* @author rbair
|
||||
* @author Karl Schaefer
|
||||
*/
|
||||
public class GraphicsUtilities {
|
||||
|
||||
|
||||
public static BufferedImage scale(
|
||||
final BufferedImage img,
|
||||
final int targetWidth,
|
||||
|
@ -59,10 +59,10 @@ public class GraphicsUtilities {
|
|||
return img;
|
||||
} else {
|
||||
return scale(
|
||||
img,
|
||||
targetWidth,
|
||||
targetHeight,
|
||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR,
|
||||
img,
|
||||
targetWidth,
|
||||
targetHeight,
|
||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ public class GraphicsUtilities {
|
|||
w = targetWidth;
|
||||
h = targetHeight;
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
if (higherQuality && w > targetWidth) {
|
||||
w /= 2;
|
||||
|
|
|
@ -15,27 +15,27 @@ import javax.swing.UIManager.LookAndFeelInfo;
|
|||
import java.io.File;
|
||||
|
||||
public class MagicMain {
|
||||
|
||||
|
||||
private static final String GAME_FOLDER = "Magarena";
|
||||
private static final String MODS_PATH = "mods";
|
||||
private static final String SCRIPTS_PATH = "scripts";
|
||||
private static final String GAME_PATH =
|
||||
private static final String GAME_PATH =
|
||||
(System.getProperty("magarena.dir") != null ?
|
||||
System.getProperty("magarena.dir") :
|
||||
System.getProperty("user.dir")) +
|
||||
File.separatorChar +
|
||||
GAME_FOLDER;
|
||||
|
||||
|
||||
public static void main(final String[] args) {
|
||||
// setup the handler for any uncaught exception
|
||||
Thread.setDefaultUncaughtExceptionHandler(new magic.model.MagicGameReport());
|
||||
|
||||
|
||||
// setup the game log
|
||||
MagicGameLog.initialize();
|
||||
|
||||
|
||||
// show the data folder being used
|
||||
System.err.println("Data folder : "+GAME_PATH);
|
||||
|
||||
|
||||
// try to set the look and feel
|
||||
try {
|
||||
for (final LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
||||
|
@ -44,17 +44,17 @@ public class MagicMain {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// customize nimbus look
|
||||
UIManager.getLookAndFeelDefaults().put("Table.showGrid", true);
|
||||
// removes hardcoded border
|
||||
UIManager.getLookAndFeelDefaults().put("ScrollPane[Enabled].borderPainter", null);
|
||||
}
|
||||
UIManager.getLookAndFeelDefaults().put("ScrollPane[Enabled].borderPainter", null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println("Unable to set look and feel. Probably missing the latest version of Java 6.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
final long start_time = System.currentTimeMillis();
|
||||
initialize();
|
||||
final double duration = (double)(System.currentTimeMillis() - start_time) / 1000;
|
||||
|
@ -64,21 +64,21 @@ public class MagicMain {
|
|||
new MagicFrame();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static String getGamePath() {
|
||||
return GAME_PATH;
|
||||
}
|
||||
|
||||
|
||||
public static String getGameFolder() {
|
||||
return GAME_FOLDER;
|
||||
}
|
||||
|
||||
|
||||
public static String getModsPath() {
|
||||
return getGamePath()+File.separatorChar+MODS_PATH;
|
||||
}
|
||||
|
||||
|
||||
public static String getScriptsPath() {
|
||||
return getGamePath()+File.separatorChar+SCRIPTS_PATH;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ public class MagicMain {
|
|||
KeywordDefinitions.getInstance().loadKeywordDefinitions();
|
||||
DeckGenerators.getInstance().loadDeckGenerators();
|
||||
}
|
||||
|
||||
|
||||
private static void initialize() {
|
||||
final File gamePathFile = new File(getGamePath());
|
||||
if (!gamePathFile.exists() && !gamePathFile.mkdir()) {
|
||||
|
@ -101,7 +101,7 @@ public class MagicMain {
|
|||
if (!modsPathFile.exists() && !modsPathFile.mkdir()) {
|
||||
System.err.println("Unable to create directory " + getModsPath());
|
||||
}
|
||||
|
||||
|
||||
DeckUtils.createDeckFolder();
|
||||
History.createHistoryFolder();
|
||||
initializeEngine();
|
||||
|
|
|
@ -22,7 +22,7 @@ public class MagicTools {
|
|||
System.out.println(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void checkCards() {
|
||||
final String[] filenames = new File(MagicMain.getGamePath(),"cards").list();
|
||||
final Set<MagicCardDefinition> remaining = new HashSet<MagicCardDefinition>(CardDefinitions.getCards());
|
||||
|
@ -37,7 +37,7 @@ public class MagicTools {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(final String[] args) {
|
||||
MagicMain.initializeEngine();
|
||||
checkCards();
|
||||
|
|
|
@ -5,15 +5,15 @@ import java.io.DataOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
/**
|
||||
* <h3>MersenneTwister and MersenneTwisterFast</h3>
|
||||
* <p><b>Version 17</b>, based on version MT199937(99/10/29)
|
||||
* of the Mersenne Twister algorithm found at
|
||||
* of the Mersenne Twister algorithm found at
|
||||
* <a href="http://www.math.keio.ac.jp/matumoto/emt.html">
|
||||
* The Mersenne Twister Home Page</a>, with the initialization
|
||||
* improved using the new 2002/1/26 initialization algorithm
|
||||
* By Sean Luke, October 2004.
|
||||
*
|
||||
*
|
||||
* <p><b>MersenneTwister</b> is a drop-in subclass replacement
|
||||
* for java.util.Random. It is properly synchronized and
|
||||
* can be used in a multithreaded environment. On modern VMs such
|
||||
|
@ -57,9 +57,9 @@ import java.io.Serializable;
|
|||
* as it presently makes no difference in the speed, correctness, or results of the
|
||||
* algorithm.
|
||||
*
|
||||
* <p><b>Changes Since V13:</b> clone() method CloneNotSupportedException removed.
|
||||
* <p><b>Changes Since V13:</b> clone() method CloneNotSupportedException removed.
|
||||
*
|
||||
* <p><b>Changes Since V12:</b> clone() method added.
|
||||
* <p><b>Changes Since V12:</b> clone() method added.
|
||||
*
|
||||
* <p><b>Changes Since V11:</b> stateEquals(...) method added. MersenneTwisterFast
|
||||
* is equal to other MersenneTwisterFasts with identical state; likewise
|
||||
|
@ -91,7 +91,7 @@ import java.io.Serializable;
|
|||
* in speed to the point where it is faster than MersenneTwister but slower
|
||||
* than MersenneTwisterFast (which should be the case, as it's a less complex
|
||||
* algorithm but is synchronized).
|
||||
*
|
||||
*
|
||||
* <p><b>Changes Since V5:</b> New empty constructor made to work the same
|
||||
* as java.util.Random -- namely, it seeds based on the current time in
|
||||
* milliseconds.
|
||||
|
@ -100,17 +100,17 @@ import java.io.Serializable;
|
|||
* (see <a href="http://www.math.keio.ac.jp/matumoto/MT2002/emt19937ar.html"</a>
|
||||
* http://www.math.keio.ac.jp/matumoto/MT2002/emt19937ar.html</a>)
|
||||
*
|
||||
* <p>The MersenneTwister code is based on standard MT19937 C/C++
|
||||
* <p>The MersenneTwister code is based on standard MT19937 C/C++
|
||||
* code by Takuji Nishimura,
|
||||
* with suggestions from Topher Cooper and Marc Rieffel, July 1997.
|
||||
* The code was originally translated into Java by Michael Lecuyer,
|
||||
* January 1999, and the original code is Copyright (c) 1999 by Michael Lecuyer.
|
||||
*
|
||||
* <h3>Java notes</h3>
|
||||
*
|
||||
*
|
||||
* <p>This implementation implements the bug fixes made
|
||||
* in Java 1.2's version of Random, which means it can be used with
|
||||
* earlier versions of Java. See
|
||||
* earlier versions of Java. See
|
||||
* <a href="http://www.javasoft.com/products/jdk/1.2/docs/api/java/util/Random.html">
|
||||
* the JDK 1.2 java.util.Random documentation</a> for further documentation
|
||||
* on the random-number generation contracts made. Additionally, there's
|
||||
|
@ -122,7 +122,7 @@ import java.io.Serializable;
|
|||
* uses 48 bits. The Mersenne Twister instead uses 32 bits (int size).
|
||||
* So it's best if your seed does not exceed the int range.
|
||||
*
|
||||
* <p>MersenneTwister can be used reliably
|
||||
* <p>MersenneTwister can be used reliably
|
||||
* on JDK version 1.1.5 or above. Earlier Java versions have serious bugs in
|
||||
* java.util.Random; only MersenneTwisterFast (and not MersenneTwister nor
|
||||
* java.util.Random) should be used with them.
|
||||
|
@ -133,28 +133,28 @@ import java.io.Serializable;
|
|||
* Portions copyright (c) 1993 by Michael Lecuyer. <br>
|
||||
* All rights reserved. <br>
|
||||
*
|
||||
* <p>Redistribution and use in source and binary forms, with or without
|
||||
* <p>Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* <ul>
|
||||
* <li> Redistributions of source code must retain the above copyright notice,
|
||||
* <li> Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* <li> Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* <li> Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* <li> Neither the name of the copyright owners, their employers, nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* <li> Neither the name of the copyright owners, their employers, nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
* </ul>
|
||||
* <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* <p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
@version 17
|
||||
|
@ -170,7 +170,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
// Serialization
|
||||
private static final long serialVersionUID = -8219700664442619525L; // locked as of Version 15
|
||||
|
||||
|
||||
// Period parameters
|
||||
private static final int N = 624;
|
||||
private static final int M = 397;
|
||||
|
@ -182,17 +182,17 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
// Tempering parameters
|
||||
private static final int TEMPERING_MASK_B = 0x9d2c5680;
|
||||
private static final int TEMPERING_MASK_C = 0xefc60000;
|
||||
|
||||
|
||||
private int[] mt; // the array for the state vector
|
||||
private int mti; // mti==N+1 means mt[N] is not initialized
|
||||
private int[] mag01;
|
||||
|
||||
|
||||
// a good initial seed (of int size, though stored in a long)
|
||||
//private static final long GOOD_SEED = 4357;
|
||||
|
||||
private double __nextNextGaussian;
|
||||
private boolean __haveNextNextGaussian;
|
||||
|
||||
|
||||
/* We're overriding all internal data, to my knowledge, so this should be okay */
|
||||
public Object clone()
|
||||
{
|
||||
|
@ -205,7 +205,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
catch (CloneNotSupportedException e) { throw new InternalError(); } // should never happen
|
||||
}
|
||||
|
||||
|
||||
public boolean stateEquals(final Object o)
|
||||
{
|
||||
if (o==this) return true;
|
||||
|
@ -225,24 +225,24 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
int len = mt.length;
|
||||
for(int x=0;x<len;x++) mt[x] = stream.readInt();
|
||||
|
||||
|
||||
len = mag01.length;
|
||||
for(int x=0;x<len;x++) mag01[x] = stream.readInt();
|
||||
|
||||
|
||||
mti = stream.readInt();
|
||||
__nextNextGaussian = stream.readDouble();
|
||||
__haveNextNextGaussian = stream.readBoolean();
|
||||
}
|
||||
|
||||
|
||||
/** Writes the entire state of the MersenneTwister RNG to the stream */
|
||||
public void writeState(final DataOutputStream stream) throws IOException
|
||||
{
|
||||
int len = mt.length;
|
||||
for(int x=0;x<len;x++) stream.writeInt(mt[x]);
|
||||
|
||||
|
||||
len = mag01.length;
|
||||
for(int x=0;x<len;x++) stream.writeInt(mag01[x]);
|
||||
|
||||
|
||||
stream.writeInt(mti);
|
||||
stream.writeDouble(__nextNextGaussian);
|
||||
stream.writeBoolean(__haveNextNextGaussian);
|
||||
|
@ -255,7 +255,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
this(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a given seed. Though you pass this seed in
|
||||
* as a long, it's best to make sure it's actually an integer.
|
||||
|
@ -265,7 +265,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using an array of integers as seed.
|
||||
|
@ -282,7 +282,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
/**
|
||||
* Initalize the pseudo random number generator. Don't
|
||||
* pass in a long that's bigger than an int (Mersenne Twister
|
||||
* only uses the first 32 bits for its seed).
|
||||
* only uses the first 32 bits for its seed).
|
||||
*/
|
||||
|
||||
synchronized public void setSeed(final long seed)
|
||||
|
@ -292,16 +292,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
__haveNextNextGaussian = false;
|
||||
|
||||
mt = new int[N];
|
||||
|
||||
|
||||
mag01 = new int[2];
|
||||
mag01[0] = 0x0;
|
||||
mag01[1] = MATRIX_A;
|
||||
|
||||
mt[0]= (int)(seed & 0xffffffff);
|
||||
for (mti=1; mti<N; mti++)
|
||||
for (mti=1; mti<N; mti++)
|
||||
{
|
||||
mt[mti] =
|
||||
(1812433253 * (mt[mti-1] ^ (mt[mti-1] >>> 30)) + mti);
|
||||
mt[mti] =
|
||||
(1812433253 * (mt[mti-1] ^ (mt[mti-1] >>> 30)) + mti);
|
||||
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||
/* In the previous versions, MSBs of the seed affect */
|
||||
/* only MSBs of the array mt[]. */
|
||||
|
@ -327,7 +327,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
setSeed(19650218);
|
||||
i=1; j=0;
|
||||
k = (array.length < N ? N : array.length);
|
||||
for (; k!=0; k--)
|
||||
for (; k!=0; k--)
|
||||
{
|
||||
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * 1664525)) + array[j] + j; /* non linear */
|
||||
mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
|
||||
|
@ -336,30 +336,30 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (i>=N) { mt[0] = mt[N-1]; i=1; }
|
||||
if (j>=array.length) j=0;
|
||||
}
|
||||
for (k=N-1; k!=0; k--)
|
||||
for (k=N-1; k!=0; k--)
|
||||
{
|
||||
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >>> 30)) * 1566083941)) - i; /* non linear */
|
||||
mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */
|
||||
i++;
|
||||
if (i>=N)
|
||||
if (i>=N)
|
||||
{
|
||||
mt[0] = mt[N-1]; i=1;
|
||||
mt[0] = mt[N-1]; i=1;
|
||||
}
|
||||
}
|
||||
mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
|
||||
mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
|
||||
}
|
||||
|
||||
|
||||
public final int nextInt()
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -375,7 +375,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -390,13 +390,13 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
public final short nextShort()
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -412,7 +412,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -427,13 +427,13 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
public final char nextChar()
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -449,7 +449,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -463,13 +463,13 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
public final boolean nextBoolean()
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -485,7 +485,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -506,7 +506,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
public final boolean nextBoolean(final float probability)
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (probability < 0.0f || probability > 1.0f)
|
||||
throw new IllegalArgumentException ("probability must be between 0.0 and 1.0 inclusive.");
|
||||
if (probability==0.0f) return false; // fix half-open issues
|
||||
|
@ -514,9 +514,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -532,7 +532,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -559,9 +559,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -577,7 +577,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -587,9 +587,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -602,16 +602,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
z = mt[mti++];
|
||||
z ^= z >>> 11; // TEMPERING_SHIFT_U(z)
|
||||
z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z)
|
||||
z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z)
|
||||
z ^= (z >>> 18); // TEMPERING_SHIFT_L(z)
|
||||
|
||||
|
||||
/* derived from nextDouble documentation in jdk 1.2 docs, see top */
|
||||
return ((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53) < probability;
|
||||
}
|
||||
|
@ -620,13 +620,13 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
public final byte nextByte()
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -642,7 +642,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -656,15 +656,15 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
public final void nextBytes(final byte[] bytes)
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
for (int x=0;x<bytes.length;x++)
|
||||
{
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -677,10 +677,10 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -700,9 +700,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -718,7 +718,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -728,9 +728,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -743,16 +743,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
z = mt[mti++];
|
||||
z ^= z >>> 11; // TEMPERING_SHIFT_U(z)
|
||||
z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z)
|
||||
z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z)
|
||||
z ^= (z >>> 18); // TEMPERING_SHIFT_L(z)
|
||||
|
||||
|
||||
return (((long)y) << 32) + (long)z;
|
||||
}
|
||||
|
||||
|
@ -764,19 +764,19 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
if (n<=0)
|
||||
throw new IllegalArgumentException("n must be positive, got: " + n);
|
||||
|
||||
|
||||
long bits, val;
|
||||
do
|
||||
do
|
||||
{
|
||||
int y;
|
||||
int z;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -789,22 +789,22 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
|
||||
y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -817,16 +817,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
z = mt[mti++];
|
||||
z ^= z >>> 11; // TEMPERING_SHIFT_U(z)
|
||||
z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z)
|
||||
z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z)
|
||||
z ^= (z >>> 18); // TEMPERING_SHIFT_L(z)
|
||||
|
||||
|
||||
bits = (((((long)y) << 32) + (long)z) >>> 1);
|
||||
val = bits % n;
|
||||
} while (bits - val + (n-1) < 0);
|
||||
|
@ -843,9 +843,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -861,7 +861,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -871,9 +871,9 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -886,16 +886,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
z = mt[mti++];
|
||||
z ^= z >>> 11; // TEMPERING_SHIFT_U(z)
|
||||
z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z)
|
||||
z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z)
|
||||
z ^= (z >>> 18); // TEMPERING_SHIFT_L(z)
|
||||
|
||||
|
||||
/* derived from nextDouble documentation in jdk 1.2 docs, see top */
|
||||
return ((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53);
|
||||
}
|
||||
|
@ -911,7 +911,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
<tr><td>nextDouble(false, true)<td>(0.0, 1.0]
|
||||
<tr><td>nextDouble(true, true)<td>[0.0, 1.0]
|
||||
</table>
|
||||
|
||||
|
||||
<p>This version preserves all possible random values in the double range.
|
||||
*/
|
||||
public double nextDouble(final boolean includeZero, final boolean includeOne)
|
||||
|
@ -921,7 +921,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
d = nextDouble(); // grab a value, initially from half-open [0.0, 1.0)
|
||||
if (includeOne && nextBoolean()) d += 1.0; // if includeOne, with 1/2 probability, push to [1.0, 2.0)
|
||||
}
|
||||
}
|
||||
while ( (d > 1.0) || // everything above 1.0 is always invalid
|
||||
(!includeZero && d == 0.0)); // if we're not including zero, 0.0 is invalid
|
||||
return d;
|
||||
|
@ -935,23 +935,23 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
__haveNextNextGaussian = false;
|
||||
return __nextNextGaussian;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
double v1, v2, s;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
int y;
|
||||
int z;
|
||||
int a;
|
||||
int b;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -964,22 +964,22 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
|
||||
y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
z = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -992,22 +992,22 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
z = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (z >>> 1) ^ mag01[z & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
z = mt[mti++];
|
||||
z ^= z >>> 11; // TEMPERING_SHIFT_U(z)
|
||||
z ^= (z << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(z)
|
||||
z ^= (z << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(z)
|
||||
z ^= (z >>> 18); // TEMPERING_SHIFT_L(z)
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
a = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -1020,22 +1020,22 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
a = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (a >>> 1) ^ mag01[a & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
a = mt[mti++];
|
||||
a ^= a >>> 11; // TEMPERING_SHIFT_U(a)
|
||||
a ^= (a << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(a)
|
||||
a ^= (a << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(a)
|
||||
a ^= (a >>> 18); // TEMPERING_SHIFT_L(a)
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
b = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -1048,16 +1048,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
b = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (b >>> 1) ^ mag01[b & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
b = mt[mti++];
|
||||
b ^= b >>> 11; // TEMPERING_SHIFT_U(b)
|
||||
b ^= (b << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(b)
|
||||
b ^= (b << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(b)
|
||||
b ^= (b >>> 18); // TEMPERING_SHIFT_L(b)
|
||||
|
||||
|
||||
/* derived from nextDouble documentation in jdk 1.2 docs, see top */
|
||||
v1 = 2 *
|
||||
(((((long)(y >>> 6)) << 27) + (z >>> 5)) / (double)(1L << 53))
|
||||
|
@ -1072,23 +1072,23 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
return v1 * multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns a random float in the half-open range from [0.0f,1.0f). Thus 0.0f is a valid
|
||||
result but 1.0f is not. */
|
||||
public final float nextFloat()
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -1104,7 +1104,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
|
@ -1124,7 +1124,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
<tr><td>nextFloat(false, true)<td>(0.0f, 1.0f]
|
||||
<tr><td>nextFloat(true, true)<td>[0.0f, 1.0f]
|
||||
</table>
|
||||
|
||||
|
||||
<p>This version preserves all possible random values in the float range.
|
||||
*/
|
||||
public double nextFloat(final boolean includeZero, final boolean includeOne)
|
||||
|
@ -1134,7 +1134,7 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
d = nextFloat(); // grab a value, initially from half-open [0.0f, 1.0f)
|
||||
if (includeOne && nextBoolean()) d += 1.0f; // if includeOne, with 1/2 probability, push to [1.0f, 2.0f)
|
||||
}
|
||||
}
|
||||
while ( (d > 1.0f) || // everything above 1.0f is always invalid
|
||||
(!includeZero && d == 0.0f)); // if we're not including zero, 0.0f is invalid
|
||||
return d;
|
||||
|
@ -1148,17 +1148,17 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
{
|
||||
if (n<=0)
|
||||
throw new IllegalArgumentException("n must be positive, got: " + n);
|
||||
|
||||
|
||||
if ((n & -n) == n) // i.e., n is a power of 2
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -1171,30 +1171,30 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
|
||||
y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
|
||||
|
||||
|
||||
return (int)((n * (long) (y >>> 1) ) >> 31);
|
||||
}
|
||||
|
||||
|
||||
int bits, val;
|
||||
do
|
||||
do
|
||||
{
|
||||
int y;
|
||||
|
||||
|
||||
if (mti >= N) // generate N words at one time
|
||||
{
|
||||
int kk;
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
final int[] mt = this.mt; // locals are slightly faster
|
||||
final int[] mag01 = this.mag01; // locals are slightly faster
|
||||
|
||||
for (kk = 0; kk < N - M; kk++)
|
||||
{
|
||||
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
|
||||
|
@ -1207,16 +1207,16 @@ public strictfp class MersenneTwisterFast implements Serializable, Cloneable
|
|||
}
|
||||
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
|
||||
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= y >>> 11; // TEMPERING_SHIFT_U(y)
|
||||
y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
|
||||
y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
|
||||
y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
|
||||
|
||||
|
||||
bits = (y >>> 1);
|
||||
val = bits % n;
|
||||
} while(bits - val + (n-1) < 0);
|
||||
|
|
|
@ -27,11 +27,11 @@ package magic;
|
|||
* MurmurHash3 implementation in Java, based on Austin Appleby's <a href=
|
||||
* "https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp"
|
||||
* >original in C</a>
|
||||
*
|
||||
*
|
||||
* Only implementing x64 version, because this should always be faster on 64 bit
|
||||
* native processors, even 64 bit being ran with a 32 bit OS; this should also
|
||||
* be as fast or faster than the x86 version on some modern 32 bit processors.
|
||||
*
|
||||
*
|
||||
* @author Patrick McFarland
|
||||
* @see <a href="http://sites.google.com/site/murmurhash/">MurmurHash website</a>
|
||||
* @see <a href="http://en.wikipedia.org/wiki/MurmurHash">MurmurHash entry on Wikipedia</a>
|
||||
|
@ -96,7 +96,7 @@ public class MurmurHash3 {
|
|||
|
||||
/**
|
||||
* Hash a value using the x64 128 bit variant of MurmurHash3
|
||||
*
|
||||
*
|
||||
* @param key value to hash
|
||||
* @param seed random value
|
||||
* @return 128 bit hashed key, in an array containing two longs
|
||||
|
@ -159,7 +159,7 @@ public class MurmurHash3 {
|
|||
|
||||
/**
|
||||
* Hash a value using the x64 64 bit variant of MurmurHash3
|
||||
*
|
||||
*
|
||||
* @param key value to hash
|
||||
* @param seed random value
|
||||
* @return 64 bit hashed key
|
||||
|
@ -170,7 +170,7 @@ public class MurmurHash3 {
|
|||
|
||||
/**
|
||||
* Hash a value using the x64 32 bit variant of MurmurHash3
|
||||
*
|
||||
*
|
||||
* @param key value to hash
|
||||
* @param seed random value
|
||||
* @return 32 bit hashed key
|
||||
|
@ -181,7 +181,7 @@ public class MurmurHash3 {
|
|||
|
||||
/**
|
||||
* Hash a value using the x64 128 bit variant of MurmurHash3
|
||||
*
|
||||
*
|
||||
* @param key value to hash
|
||||
* @param seed random value
|
||||
* @return 128 bit hashed key, in an array containing two longs
|
||||
|
@ -225,7 +225,7 @@ public class MurmurHash3 {
|
|||
|
||||
/**
|
||||
* Hash a value using the x64 64 bit variant of MurmurHash3
|
||||
*
|
||||
*
|
||||
* @param key value to hash
|
||||
* @param seed random value
|
||||
* @return 64 bit hashed key
|
||||
|
@ -236,7 +236,7 @@ public class MurmurHash3 {
|
|||
|
||||
/**
|
||||
* Hash a value using the x64 32 bit variant of MurmurHash3
|
||||
*
|
||||
*
|
||||
* @param key value to hash
|
||||
* @param seed random value
|
||||
* @return 32 bit hashed key
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package magic.ai;
|
||||
|
||||
public class ArtificialChoiceResults {
|
||||
|
||||
|
||||
final Object[] choiceResults;
|
||||
ArtificialScore aiScore=ArtificialScore.INVALID_SCORE;
|
||||
int worker=-1;
|
||||
|
@ -10,7 +10,7 @@ public class ArtificialChoiceResults {
|
|||
ArtificialChoiceResults(final Object[] choiceResults) {
|
||||
this.choiceResults=choiceResults;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
final StringBuilder buffer=new StringBuilder();
|
||||
buffer.append("[").append(worker).append('/').append(gameCount).append('/').append(aiScore).append("]");
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
package magic.ai;
|
||||
|
||||
public class ArtificialMultiPruneScore implements ArtificialPruneScore {
|
||||
|
||||
|
||||
private final int maxBest;
|
||||
private final int minWorst;
|
||||
|
||||
|
||||
private ArtificialMultiPruneScore(final int maxBest,final int minWorst) {
|
||||
this.maxBest=maxBest;
|
||||
this.minWorst=minWorst;
|
||||
}
|
||||
|
||||
|
||||
ArtificialMultiPruneScore() {
|
||||
this(Integer.MIN_VALUE,Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getScore() {
|
||||
return maxBest; // Does matter for game id.
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean pruneScore(final int score,final boolean best) {
|
||||
return best?score>minWorst:score<maxBest;
|
||||
|
@ -32,7 +32,7 @@ public class ArtificialMultiPruneScore implements ArtificialPruneScore {
|
|||
return score<minWorst?new ArtificialMultiPruneScore(maxBest,score):this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return maxBest+" / "+minWorst;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package magic.ai;
|
||||
|
||||
public interface ArtificialPruneScore {
|
||||
|
||||
|
||||
int getScore();
|
||||
|
||||
|
||||
boolean pruneScore(final int score,final boolean best);
|
||||
|
||||
ArtificialPruneScore getPruneScore(final int score,final boolean best);
|
||||
|
||||
ArtificialPruneScore getPruneScore(final int score,final boolean best);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package magic.ai;
|
||||
|
||||
|
||||
class ArtificialPruneScoreRef {
|
||||
|
||||
private ArtificialPruneScore pruneScore;
|
||||
|
@ -7,11 +7,11 @@ class ArtificialPruneScoreRef {
|
|||
public ArtificialPruneScoreRef(final ArtificialPruneScore pScore) {
|
||||
pruneScore = pScore;
|
||||
}
|
||||
|
||||
|
||||
public void update(final int score) {
|
||||
pruneScore = pruneScore.getPruneScore(score,true);
|
||||
}
|
||||
|
||||
|
||||
public ArtificialPruneScore get() {
|
||||
return pruneScore;
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ public class ArtificialScore {
|
|||
static final ArtificialScore INVALID_SCORE=new ArtificialScore(0,0);
|
||||
static final int MAX = 99900000;
|
||||
static final int MIN = -MAX;
|
||||
|
||||
|
||||
private final int score;
|
||||
private final int depth;
|
||||
|
||||
|
||||
ArtificialScore(final int aScore,final int aDepth) {
|
||||
int boundedScore = Math.min(MAX,aScore);
|
||||
score = Math.max(MIN,boundedScore);
|
||||
|
@ -25,7 +25,7 @@ public class ArtificialScore {
|
|||
int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
boolean isBetter(final ArtificialScore other,final boolean max) {
|
||||
if (other==INVALID_SCORE) {
|
||||
return false;
|
||||
|
@ -44,11 +44,11 @@ public class ArtificialScore {
|
|||
return other.score < score;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this==INVALID_SCORE) {
|
||||
return "none";
|
||||
return "none";
|
||||
}
|
||||
final StringBuilder buffer=new StringBuilder();
|
||||
buffer.append(score).append(" at ").append(depth);
|
||||
|
|
|
@ -5,7 +5,7 @@ import magic.data.LRUCache;
|
|||
public class ArtificialScoreBoard {
|
||||
|
||||
private final LRUCache<Long,ArtificialScore> gameScoresMap;
|
||||
|
||||
|
||||
ArtificialScoreBoard() {
|
||||
gameScoresMap=new LRUCache<Long,ArtificialScore>(100000);
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ public class ArtificialScoreBoard {
|
|||
synchronized void setGameScore(final long gameId,final ArtificialScore aiScore) {
|
||||
gameScoresMap.put(gameId,aiScore);
|
||||
}
|
||||
|
||||
|
||||
synchronized ArtificialScore getGameScore(final long gameId) {
|
||||
return gameScoresMap.get(gameId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
synchronized void clear() {
|
||||
gameScoresMap.clear();
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@ public class ArtificialScoringSystem {
|
|||
public static final int ITEM_ON_STACK_SCORE=-1;
|
||||
public static final int UNEQUIP_SCORE=-100;
|
||||
public static final int UNNECESSARY_EQUIP_SCORE=-1000;
|
||||
|
||||
|
||||
private static final int[] LIFE_SCORES={
|
||||
0,1000,2000,3000,4000,
|
||||
4500,5000,5500,6000,6500,
|
||||
7000,7400,7800,8200,8600,
|
||||
9000,9200,9400,9600,9800,
|
||||
0,1000,2000,3000,4000,
|
||||
4500,5000,5500,6000,6500,
|
||||
7000,7400,7800,8200,8600,
|
||||
9000,9200,9400,9600,9800,
|
||||
10000
|
||||
};
|
||||
|
||||
|
||||
private static final int[] POISON_SCORES={
|
||||
5000,4700,4400,4100,3800,
|
||||
3400,3000,2500,2000,1000,
|
||||
|
@ -37,31 +37,31 @@ public class ArtificialScoringSystem {
|
|||
private static final int MAX_LIFE=LIFE_SCORES.length-1;
|
||||
|
||||
private static final int MAX_POISON=10;
|
||||
|
||||
|
||||
private static final int LIFE_ABOVE_MULTIPLIER=100;
|
||||
|
||||
|
||||
private static final int UNKNOWN_CARD_SCORE=300;
|
||||
|
||||
|
||||
private static final int PERMANENT_SCORE=300;
|
||||
|
||||
|
||||
public static int getTurnScore(final MagicGame game) {
|
||||
return Math.max(0,10-(game.getTurn()-1)>>1);
|
||||
}
|
||||
|
||||
|
||||
public static int getLoseGameScore(final MagicGame game) {
|
||||
// Lose score is lowered in function of the turn and phase when it occurs. Encourages AI to win as fast as possible.
|
||||
return LOSE_GAME_SCORE+game.getTurn()*2500+game.getPhase().getType().ordinal()*200;
|
||||
}
|
||||
|
||||
|
||||
public static int getCardDefinitionScore(final MagicCardDefinition cardDefinition) {
|
||||
return getCardDefinitionScore(cardDefinition, 1);
|
||||
}
|
||||
|
||||
|
||||
// score for a card that gets put into play without paying the mana cost
|
||||
public static int getFreeCardDefinitionScore(final MagicCardDefinition cardDefinition) {
|
||||
return getCardDefinitionScore(cardDefinition, 0);
|
||||
}
|
||||
|
||||
|
||||
private static int getCardDefinitionScore(final MagicCardDefinition cardDefinition, final int costFactor) {
|
||||
if (cardDefinition.isLand()) {
|
||||
int score=(int)(cardDefinition.getValue()*50);
|
||||
|
@ -77,11 +77,11 @@ public class ArtificialScoringSystem {
|
|||
return score+cardDefinition.getRemoval()*50+cardDefinition.getRarity()*30;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static int getCardScore(final MagicCard card) {
|
||||
return card.isKnown()?card.getCardDefinition().getScore():UNKNOWN_CARD_SCORE;
|
||||
}
|
||||
|
||||
|
||||
public static int getFreeCardScore(final MagicCard card) {
|
||||
return card.isKnown()?card.getCardDefinition().getFreeScore():UNKNOWN_CARD_SCORE;
|
||||
}
|
||||
|
@ -90,16 +90,16 @@ public class ArtificialScoringSystem {
|
|||
int score = permanent.getCardScore();
|
||||
if (permanent.isCreature()) {
|
||||
score+=permanent.getActivations().size()*50;
|
||||
score+=permanent.getManaActivations().size()*80;
|
||||
score+=permanent.getManaActivations().size()*80;
|
||||
} else {
|
||||
score+=PERMANENT_SCORE;
|
||||
if (permanent.isEquipment()) {
|
||||
score+=100;
|
||||
}
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public static int getVariablePermanentScore(final MagicPermanent permanent) {
|
||||
int score=permanent.getCounters(MagicCounterType.Charge)*30;
|
||||
if (!permanent.canTap()) {
|
||||
|
@ -111,14 +111,14 @@ public class ArtificialScoringSystem {
|
|||
final Set<MagicAbility> abilityFlags=permanent.getAbilityFlags();
|
||||
score+=pt.power()*300+pt.getPositiveToughness()*200+MagicAbility.getScore(abilityFlags)*(pt.getPositivePower()+1)/2;
|
||||
score+=permanent.getEquipmentPermanents().size()*50+permanent.getAuraPermanents().size()*100;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public static int getTappedScore(final MagicPermanent permanent) {
|
||||
return permanent.isCreature()?-10:-5;
|
||||
}
|
||||
|
||||
|
||||
public static int getLifeScore(final int life) {
|
||||
if (life>MAX_LIFE) {
|
||||
return LIFE_SCORES[MAX_LIFE]+(life-MAX_LIFE)*LIFE_ABOVE_MULTIPLIER;
|
||||
|
@ -128,42 +128,42 @@ public class ArtificialScoringSystem {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static int getPoisonScore(final int poison) {
|
||||
if (poison>MAX_POISON) {
|
||||
return POISON_SCORES[MAX_POISON];
|
||||
}
|
||||
return POISON_SCORES[poison];
|
||||
}
|
||||
|
||||
|
||||
public static int getManaScore(final int amount) {
|
||||
return -amount;
|
||||
}
|
||||
|
||||
|
||||
public static int getAttackerScore(final MagicCombatCreature attacker) {
|
||||
int score=attacker.power*5+attacker.lethalDamage*2-attacker.candidateBlockers.length;
|
||||
for (final MagicCombatCreature blocker : attacker.candidateBlockers) {
|
||||
score-=blocker.power;
|
||||
}
|
||||
// Dedicated attacker.
|
||||
if (attacker.hasAbility(MagicAbility.AttacksEachTurnIfAble) ||
|
||||
if (attacker.hasAbility(MagicAbility.AttacksEachTurnIfAble) ||
|
||||
attacker.hasAbility(MagicAbility.CannotBlock)) {
|
||||
score+=10;
|
||||
}
|
||||
// Abilities for attacking.
|
||||
if (attacker.hasAbility(MagicAbility.Trample) ||
|
||||
if (attacker.hasAbility(MagicAbility.Trample) ||
|
||||
attacker.hasAbility(MagicAbility.Vigilance)) {
|
||||
score+=8;
|
||||
}
|
||||
// Dangerous to block.
|
||||
if (!attacker.normalDamage ||
|
||||
attacker.hasAbility(MagicAbility.FirstStrike) ||
|
||||
if (!attacker.normalDamage ||
|
||||
attacker.hasAbility(MagicAbility.FirstStrike) ||
|
||||
attacker.hasAbility(MagicAbility.Indestructible)) {
|
||||
score+=7;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public static int getMillScore(final int amount) {
|
||||
return -amount;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Classical MCTS (UCT)
|
|||
- score = XX% (25000 matches against MMAB-1)
|
||||
|
||||
Enchancements to basic UCT
|
||||
- use ratio selection (v + 10)/(n + 10)
|
||||
- use ratio selection (v + 10)/(n + 10)
|
||||
- UCB1 with C = 1.0
|
||||
- UCB1 with C = 2.0
|
||||
- UCB1 with C = 3.0
|
||||
|
@ -46,7 +46,7 @@ Consistency Modifications for Automatically Tuned Monte-Carlo Tree Search
|
|||
using v_t threshold ensures consistency for case of reward in {0,1} using any score function
|
||||
v(s) < v_t (0.3), randomy pick a child, else pick child that maximize score
|
||||
|
||||
Monte-Carlo Tree Search in Lines of Action
|
||||
Monte-Carlo Tree Search in Lines of Action
|
||||
1-ply lookahread to detect direct win for player to move
|
||||
secure child formula for decision v + A/sqrt(n)
|
||||
evaluation cut-off: use score function to stop simulation early
|
||||
|
@ -55,7 +55,7 @@ Monte-Carlo Tree Search in Lines of Action
|
|||
mixed: start with corrective, rest of the moves use greedy
|
||||
*/
|
||||
public class MCTSAI implements MagicAI {
|
||||
|
||||
|
||||
private static int MIN_SCORE = Integer.MAX_VALUE;
|
||||
static int MIN_SIM = Integer.MAX_VALUE;
|
||||
private static final int MAX_ACTIONS = 10000;
|
||||
|
@ -72,12 +72,12 @@ public class MCTSAI implements MagicAI {
|
|||
MIN_SCORE = Integer.parseInt(System.getProperty("min_score"));
|
||||
System.err.println("MIN_SCORE = " + MIN_SCORE);
|
||||
}
|
||||
|
||||
|
||||
if (System.getProperty("ucb1_c") != null) {
|
||||
UCB1_C = Double.parseDouble(System.getProperty("ucb1_c"));
|
||||
System.err.println("UCB1_C = " + UCB1_C);
|
||||
}
|
||||
|
||||
|
||||
if (System.getProperty("ratio_k") != null) {
|
||||
RATIO_K = Double.parseDouble(System.getProperty("ratio_k"));
|
||||
System.err.println("RATIO_K = " + RATIO_K);
|
||||
|
@ -105,7 +105,7 @@ public class MCTSAI implements MagicAI {
|
|||
}
|
||||
|
||||
public Object[] findNextEventChoiceResults(
|
||||
final MagicGame startGame,
|
||||
final MagicGame startGame,
|
||||
final MagicPlayer scorePlayer) {
|
||||
|
||||
// Determine possible choices
|
||||
|
@ -115,21 +115,21 @@ public class MCTSAI implements MagicAI {
|
|||
choiceGame = null;
|
||||
|
||||
final int size = RCHOICES.size();
|
||||
|
||||
|
||||
// No choice
|
||||
assert size > 0 : "ERROR! No choice found at start of MCTS";
|
||||
|
||||
|
||||
// Single choice
|
||||
if (size == 1) {
|
||||
return startGame.map(RCHOICES.get(0));
|
||||
}
|
||||
|
||||
|
||||
//normal: max time is 1000 * level
|
||||
int MAX_TIME = 1000 * startGame.getArtificialLevel(scorePlayer.getIndex());
|
||||
int MAX_SIM = Integer.MAX_VALUE;
|
||||
|
||||
|
||||
final long START_TIME = System.currentTimeMillis();
|
||||
|
||||
|
||||
//root represents the start state
|
||||
final MCTSGameTree root = MCTSGameTree.getNode(CACHE, startGame, RCHOICES);
|
||||
|
||||
|
@ -139,29 +139,29 @@ public class MCTSAI implements MagicAI {
|
|||
int sims;
|
||||
for (sims = 0;
|
||||
System.currentTimeMillis() - START_TIME < MAX_TIME &&
|
||||
sims < MAX_SIM &&
|
||||
!root.isAIWin();
|
||||
sims < MAX_SIM &&
|
||||
!root.isAIWin();
|
||||
sims++) {
|
||||
|
||||
|
||||
//clone the MagicGame object for simulation
|
||||
final MagicGame rootGame = new MagicGame(startGame, scorePlayer);
|
||||
if (!CHEAT) {
|
||||
rootGame.hideHiddenCards();
|
||||
}
|
||||
|
||||
//pass in a clone of the state,
|
||||
|
||||
//pass in a clone of the state,
|
||||
//genNewTreeNode grows the tree by one node
|
||||
//and returns the path from the root to the new node
|
||||
final LinkedList<MCTSGameTree> path = growTree(root, rootGame);
|
||||
|
||||
|
||||
assert path.size() >= 2 : "ERROR! length of MCTS path is " + path.size();
|
||||
|
||||
// play a simulated game to get score
|
||||
// update all nodes along the path from root to new node
|
||||
// update all nodes along the path from root to new node
|
||||
final double score = randomPlay(path.getLast(), rootGame);
|
||||
|
||||
|
||||
// update score and game theoretic value along the chosen path
|
||||
MCTSGameTree child = null;
|
||||
MCTSGameTree child = null;
|
||||
MCTSGameTree parent = null;
|
||||
while (!path.isEmpty()) {
|
||||
child = parent;
|
||||
|
@ -179,8 +179,8 @@ public class MCTSAI implements MagicAI {
|
|||
parent.incLose(steps);
|
||||
} else if (parent.isOpp() && child.isAIWin()) {
|
||||
parent.incLose(steps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ public class MCTSAI implements MagicAI {
|
|||
for (final MCTSGameTree node : root) {
|
||||
final double D = node.getDecision();
|
||||
final int C = node.getChoice();
|
||||
if (D > maxD) {
|
||||
if (D > maxD) {
|
||||
maxD = D;
|
||||
bestC = C;
|
||||
}
|
||||
|
@ -203,22 +203,22 @@ public class MCTSAI implements MagicAI {
|
|||
|
||||
return startGame.map(RCHOICES.get(bestC));
|
||||
}
|
||||
|
||||
|
||||
private String outputChoice(
|
||||
final MagicPlayer scorePlayer,
|
||||
final MCTSGameTree root,
|
||||
final long START_TIME,
|
||||
final int bestC,
|
||||
final MCTSGameTree root,
|
||||
final long START_TIME,
|
||||
final int bestC,
|
||||
final int sims) {
|
||||
|
||||
|
||||
final StringBuilder out = new StringBuilder();
|
||||
final long duration = System.currentTimeMillis() - START_TIME;
|
||||
|
||||
out.append("MCTS" +
|
||||
" cheat=" + CHEAT +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" life=" + scorePlayer.getLife() +
|
||||
" time=" + duration +
|
||||
" time=" + duration +
|
||||
" sims=" + sims);
|
||||
out.append('\n');
|
||||
|
||||
|
@ -262,16 +262,16 @@ public class MCTSAI implements MagicAI {
|
|||
choices = getNextChoices(game, false)) {
|
||||
|
||||
assert choices.size() > 0 : "ERROR! No choice at start of genNewTreeNode";
|
||||
|
||||
assert !curr.hasDetails() || MCTSGameTree.checkNode(curr, choices) :
|
||||
|
||||
assert !curr.hasDetails() || MCTSGameTree.checkNode(curr, choices) :
|
||||
"ERROR! Inconsistent node found" + "\n" +
|
||||
game + " " +
|
||||
printPath(path) + " " +
|
||||
game + " " +
|
||||
printPath(path) + " " +
|
||||
MCTSGameTree.printNode(curr, choices);
|
||||
|
||||
|
||||
final MagicEvent event = game.getNextEvent();
|
||||
|
||||
//first time considering the choices available at this node,
|
||||
|
||||
//first time considering the choices available at this node,
|
||||
//fill in additional details for curr
|
||||
if (!curr.hasDetails()) {
|
||||
curr.setIsAI(game.getScorePlayer() == event.getPlayer());
|
||||
|
@ -292,17 +292,17 @@ public class MCTSAI implements MagicAI {
|
|||
final int idx = curr.size();
|
||||
final Object[] choice = choices.get(idx);
|
||||
game.executeNextEvent(choice);
|
||||
final MCTSGameTree child = new MCTSGameTree(curr, idx, game.getScore());
|
||||
final MCTSGameTree child = new MCTSGameTree(curr, idx, game.getScore());
|
||||
assert (child.desc = MCTSGameTree.obj2String(choice[0])).equals(child.desc);
|
||||
curr.addChild(child);
|
||||
path.add(child);
|
||||
return path;
|
||||
|
||||
|
||||
//all the children are in the tree, find the "best" child to explore
|
||||
} else {
|
||||
|
||||
assert curr.size() == choices.size() : "ERROR! Different number of choices in node and game" +
|
||||
printPath(path) + MCTSGameTree.printNode(curr, choices);
|
||||
assert curr.size() == choices.size() : "ERROR! Different number of choices in node and game" +
|
||||
printPath(path) + MCTSGameTree.printNode(curr, choices);
|
||||
|
||||
MCTSGameTree next = null;
|
||||
double bestS = Double.NEGATIVE_INFINITY ;
|
||||
|
@ -317,13 +317,13 @@ public class MCTSAI implements MagicAI {
|
|||
|
||||
//move down the tree
|
||||
curr = next;
|
||||
|
||||
|
||||
//update the game state and path
|
||||
game.executeNextEvent(choices.get(curr.getChoice()));
|
||||
path.add(curr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ public class MCTSAI implements MagicAI {
|
|||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!CHEAT) {
|
||||
game.showRandomizedHiddenCards();
|
||||
}
|
||||
|
@ -355,16 +355,16 @@ public class MCTSAI implements MagicAI {
|
|||
return 1.0 - actions/(2.0 * MAX_ACTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<Object[]> getNextChoices(final MagicGame game, final boolean sim) {
|
||||
|
||||
final int startActions = game.getNumActions();
|
||||
|
||||
//use fast choices during simulation
|
||||
game.setFastChoices(sim);
|
||||
|
||||
|
||||
// simulate game until it is finished or simulated MAX_ACTIONS actions
|
||||
while (!game.isFinished() &&
|
||||
while (!game.isFinished() &&
|
||||
(game.getNumActions() - startActions) < MAX_ACTIONS) {
|
||||
|
||||
//do not accumulate score down the tree when not in simulation
|
||||
|
@ -384,7 +384,7 @@ public class MCTSAI implements MagicAI {
|
|||
game.executeNextEvent();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//event has choice
|
||||
|
||||
if (sim) {
|
||||
|
@ -413,10 +413,10 @@ public class MCTSAI implements MagicAI {
|
|||
choices = event.getArtificialChoiceResults(game);
|
||||
}
|
||||
assert choices != null;
|
||||
|
||||
|
||||
final int size = choices.size();
|
||||
assert size > 0 : "ERROR! No choice found during MCTS getACR";
|
||||
|
||||
|
||||
if (size == 1) {
|
||||
//single choice
|
||||
game.executeNextEvent(choices.get(0));
|
||||
|
@ -426,11 +426,11 @@ public class MCTSAI implements MagicAI {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//game is finished or number of actions > MAX_ACTIONS
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
private static String CR2String(final Object[] choiceResults) {
|
||||
final StringBuilder buffer=new StringBuilder();
|
||||
if (choiceResults!=null) {
|
||||
|
@ -461,7 +461,7 @@ public class MCTSAI implements MagicAI {
|
|||
|
||||
//each tree node stores the choice from the parent that leads to this node
|
||||
class MCTSGameTree implements Iterable<MCTSGameTree> {
|
||||
|
||||
|
||||
private final MCTSGameTree parent;
|
||||
private final LinkedList<MCTSGameTree> children = new LinkedList<MCTSGameTree>();
|
||||
private final int choice;
|
||||
|
@ -476,21 +476,21 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
private double S;
|
||||
String desc;
|
||||
private String[] choicesStr;
|
||||
|
||||
|
||||
//min sim for using robust max
|
||||
private int maxChildSim = MCTSAI.MIN_SIM;
|
||||
|
||||
MCTSGameTree(final MCTSGameTree parent, final int choice, final int evalScore) {
|
||||
private int maxChildSim = MCTSAI.MIN_SIM;
|
||||
|
||||
MCTSGameTree(final MCTSGameTree parent, final int choice, final int evalScore) {
|
||||
this.evalScore = evalScore;
|
||||
this.choice = choice;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
|
||||
private static boolean log(final String message) {
|
||||
System.err.println(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static int obj2StringHash(final Object obj) {
|
||||
return obj2String(obj).hashCode();
|
||||
}
|
||||
|
@ -504,10 +504,10 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
return obj.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void addNode(
|
||||
final LRUCache<Long, MCTSGameTree> cache,
|
||||
final MagicGame game,
|
||||
final LRUCache<Long, MCTSGameTree> cache,
|
||||
final MagicGame game,
|
||||
final MCTSGameTree node) {
|
||||
if (node.isCached()) {
|
||||
return;
|
||||
|
@ -519,13 +519,13 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
}
|
||||
|
||||
static MCTSGameTree getNode(
|
||||
final LRUCache<Long, MCTSGameTree> cache,
|
||||
final MagicGame game,
|
||||
final LRUCache<Long, MCTSGameTree> cache,
|
||||
final MagicGame game,
|
||||
final List<Object[]> choices) {
|
||||
final long gid = game.getStateId();
|
||||
final MCTSGameTree candidate = cache.get(gid);
|
||||
|
||||
if (candidate != null) {
|
||||
|
||||
if (candidate != null) {
|
||||
assert log("CACHE HIT");
|
||||
assert log("HIT : " + game.getIdString());
|
||||
assert printNode(candidate, choices);
|
||||
|
@ -538,7 +538,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolean checkNode(final MCTSGameTree curr, final List<Object[]> choices) {
|
||||
if (curr.getMaxChildren() != choices.size()) {
|
||||
return false;
|
||||
|
@ -557,8 +557,8 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static boolean printNode(final MCTSGameTree curr, final List<Object[]> choices) {
|
||||
if (curr.choicesStr != null) {
|
||||
for (final String str : curr.choicesStr) {
|
||||
|
@ -600,7 +600,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
void setMaxChildren(final int mc) {
|
||||
maxChildren = mc;
|
||||
}
|
||||
|
||||
|
||||
private int getMaxChildren() {
|
||||
return maxChildren;
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
boolean isOpp() {
|
||||
return !isAI;
|
||||
}
|
||||
|
||||
|
||||
void setIsAI(final boolean ai) {
|
||||
this.isAI = ai;
|
||||
}
|
||||
|
@ -620,13 +620,13 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
boolean isSolved() {
|
||||
return evalScore == Integer.MAX_VALUE || evalScore == Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
|
||||
void updateScore(final MCTSGameTree child, final double delta) {
|
||||
final double oldMean = (numSim > 0) ? sum/numSim : 0;
|
||||
sum += delta;
|
||||
numSim += 1;
|
||||
final double newMean = sum/numSim;
|
||||
S += (delta - oldMean) * (delta - newMean);
|
||||
S += (delta - oldMean) * (delta - newMean);
|
||||
|
||||
//if child has sufficient simulations, backup using robust max instead of average
|
||||
if (child != null && child.getNumSim() > maxChildSim) {
|
||||
|
@ -635,11 +635,11 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
numSim = child.numSim;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double getUCT() {
|
||||
return getV() + MCTSAI.UCB1_C * Math.sqrt(Math.log(parent.getNumSim()) / getNumSim());
|
||||
}
|
||||
|
||||
|
||||
private double getRatio() {
|
||||
return (getSum() + MCTSAI.RATIO_K)/(getNumSim() + 2*MCTSAI.RATIO_K);
|
||||
}
|
||||
|
@ -647,7 +647,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
private double getNormal() {
|
||||
return Math.max(1.0, getV() + 2 * Math.sqrt(getVar()));
|
||||
}
|
||||
|
||||
|
||||
//decrease score of lose node, boost score of win nodes
|
||||
double modify(final double sc) {
|
||||
if ((!parent.isAI() && isAIWin()) || (parent.isAI() && isAILose())) {
|
||||
|
@ -655,8 +655,8 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
} else if ((parent.isAI() && isAIWin()) || (!parent.isAI() && isAILose())) {
|
||||
return sc + 2.0;
|
||||
} else {
|
||||
return sc;
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
|
||||
private double getVar() {
|
||||
|
@ -671,7 +671,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
boolean isAIWin() {
|
||||
return evalScore == Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
|
||||
boolean isAILose() {
|
||||
return evalScore == Integer.MIN_VALUE;
|
||||
}
|
||||
|
@ -691,7 +691,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
int getChoice() {
|
||||
return choice;
|
||||
}
|
||||
|
||||
|
||||
int getSteps() {
|
||||
return steps;
|
||||
}
|
||||
|
@ -709,9 +709,9 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
private int getEvalScore() {
|
||||
return evalScore;
|
||||
}
|
||||
|
||||
|
||||
double getDecision() {
|
||||
//boost decision score of win nodes by BOOST
|
||||
//boost decision score of win nodes by BOOST
|
||||
final int BOOST = 1000000;
|
||||
if (isAIWin()) {
|
||||
return BOOST + getNumSim();
|
||||
|
@ -721,16 +721,16 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
return getNumSim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int getNumSim() {
|
||||
return numSim;
|
||||
}
|
||||
|
||||
|
||||
private double getSum() {
|
||||
// AI is max player, other is min player
|
||||
return parent.isAI() ? sum : -sum;
|
||||
}
|
||||
|
||||
|
||||
public double getAvg() {
|
||||
return sum / numSim;
|
||||
}
|
||||
|
@ -738,7 +738,7 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
double getV() {
|
||||
return getSum() / numSim;
|
||||
}
|
||||
|
||||
|
||||
private double getSecureScore() {
|
||||
return getV() + 1.0/Math.sqrt(numSim);
|
||||
}
|
||||
|
@ -747,11 +747,11 @@ class MCTSGameTree implements Iterable<MCTSGameTree> {
|
|||
assert children.size() < maxChildren : "ERROR! Number of children nodes exceed maxChildren";
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
|
||||
MCTSGameTree first() {
|
||||
return children.get(0);
|
||||
}
|
||||
|
||||
|
||||
public Iterator<MCTSGameTree> iterator() {
|
||||
return children.iterator();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Classical MCTS (UCT)
|
|||
- score = XX% (25000 matches against MMAB-1)
|
||||
|
||||
Enchancements to basic UCT
|
||||
- use ratio selection (v + 10)/(n + 10)
|
||||
- use ratio selection (v + 10)/(n + 10)
|
||||
- UCB1 with C = 1.0
|
||||
- UCB1 with C = 2.0
|
||||
- UCB1 with C = 3.0
|
||||
|
@ -46,7 +46,7 @@ Consistency Modifications for Automatically Tuned Monte-Carlo Tree Search
|
|||
using v_t threshold ensures consistency for case of reward in {0,1} using any score function
|
||||
v(s) < v_t (0.3), randomy pick a child, else pick child that maximize score
|
||||
|
||||
Monte-Carlo Tree Search in Lines of Action
|
||||
Monte-Carlo Tree Search in Lines of Action
|
||||
1-ply lookahread to detect direct win for player to move
|
||||
secure child formula for decision v + A/sqrt(n)
|
||||
evaluation cut-off: use score function to stop simulation early
|
||||
|
@ -55,7 +55,7 @@ Monte-Carlo Tree Search in Lines of Action
|
|||
mixed: start with corrective, rest of the moves use greedy
|
||||
*/
|
||||
public class MCTSAI2 implements MagicAI {
|
||||
|
||||
|
||||
private static int MIN_SCORE = Integer.MAX_VALUE;
|
||||
static int MIN_SIM = Integer.MAX_VALUE;
|
||||
private static final int MAX_ACTIONS = 10000;
|
||||
|
@ -72,12 +72,12 @@ public class MCTSAI2 implements MagicAI {
|
|||
MIN_SCORE = Integer.parseInt(System.getProperty("min_score"));
|
||||
System.err.println("MIN_SCORE = " + MIN_SCORE);
|
||||
}
|
||||
|
||||
|
||||
if (System.getProperty("ucb1_c") != null) {
|
||||
UCB1_C = Double.parseDouble(System.getProperty("ucb1_c"));
|
||||
System.err.println("UCB1_C = " + UCB1_C);
|
||||
}
|
||||
|
||||
|
||||
if (System.getProperty("ratio_k") != null) {
|
||||
RATIO_K = Double.parseDouble(System.getProperty("ratio_k"));
|
||||
System.err.println("RATIO_K = " + RATIO_K);
|
||||
|
@ -105,7 +105,7 @@ public class MCTSAI2 implements MagicAI {
|
|||
}
|
||||
|
||||
public Object[] findNextEventChoiceResults(
|
||||
final MagicGame startGame,
|
||||
final MagicGame startGame,
|
||||
final MagicPlayer scorePlayer) {
|
||||
|
||||
// Determine possible choices
|
||||
|
@ -115,21 +115,21 @@ public class MCTSAI2 implements MagicAI {
|
|||
choiceGame = null;
|
||||
|
||||
final int size = RCHOICES.size();
|
||||
|
||||
|
||||
// No choice
|
||||
assert size > 0 : "ERROR! No choice found at start of MCTS";
|
||||
|
||||
|
||||
// Single choice
|
||||
if (size == 1) {
|
||||
return startGame.map(RCHOICES.get(0));
|
||||
}
|
||||
|
||||
|
||||
//normal: max time is 1000 * level
|
||||
int MAX_TIME = 1000 * startGame.getArtificialLevel(scorePlayer.getIndex());
|
||||
int MAX_SIM = Integer.MAX_VALUE;
|
||||
|
||||
|
||||
final long START_TIME = System.currentTimeMillis();
|
||||
|
||||
|
||||
//root represents the start state
|
||||
final MCTSGameTree root = MCTSGameTree.getNode(CACHE, startGame, RCHOICES);
|
||||
|
||||
|
@ -139,29 +139,29 @@ public class MCTSAI2 implements MagicAI {
|
|||
int sims;
|
||||
for (sims = 0;
|
||||
System.currentTimeMillis() - START_TIME < MAX_TIME &&
|
||||
sims < MAX_SIM &&
|
||||
!root.isAIWin();
|
||||
sims < MAX_SIM &&
|
||||
!root.isAIWin();
|
||||
sims++) {
|
||||
|
||||
|
||||
//clone the MagicGame object for simulation
|
||||
final MagicGame rootGame = new MagicGame(startGame, scorePlayer);
|
||||
if (!CHEAT) {
|
||||
rootGame.hideHiddenCards();
|
||||
}
|
||||
|
||||
//pass in a clone of the state,
|
||||
|
||||
//pass in a clone of the state,
|
||||
//genNewTreeNode grows the tree by one node
|
||||
//and returns the path from the root to the new node
|
||||
final LinkedList<MCTSGameTree> path = growTree(root, rootGame);
|
||||
|
||||
|
||||
assert path.size() >= 2 : "ERROR! length of MCTS path is " + path.size();
|
||||
|
||||
// play a simulated game to get score
|
||||
// update all nodes along the path from root to new node
|
||||
// update all nodes along the path from root to new node
|
||||
final double score = randomPlay(path.getLast(), rootGame);
|
||||
|
||||
|
||||
// update score and game theoretic value along the chosen path
|
||||
MCTSGameTree child = null;
|
||||
MCTSGameTree child = null;
|
||||
MCTSGameTree parent = null;
|
||||
while (!path.isEmpty()) {
|
||||
child = parent;
|
||||
|
@ -179,8 +179,8 @@ public class MCTSAI2 implements MagicAI {
|
|||
parent.incLose(steps);
|
||||
} else if (parent.isOpp() && child.isAIWin()) {
|
||||
parent.incLose(steps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ public class MCTSAI2 implements MagicAI {
|
|||
for (final MCTSGameTree node : root) {
|
||||
final double D = node.getDecision();
|
||||
final int C = node.getChoice();
|
||||
if (D > maxD) {
|
||||
if (D > maxD) {
|
||||
maxD = D;
|
||||
bestC = C;
|
||||
}
|
||||
|
@ -203,22 +203,22 @@ public class MCTSAI2 implements MagicAI {
|
|||
|
||||
return startGame.map(RCHOICES.get(bestC));
|
||||
}
|
||||
|
||||
|
||||
private String outputChoice(
|
||||
final MagicPlayer scorePlayer,
|
||||
final MCTSGameTree root,
|
||||
final long START_TIME,
|
||||
final int bestC,
|
||||
final MCTSGameTree root,
|
||||
final long START_TIME,
|
||||
final int bestC,
|
||||
final int sims) {
|
||||
|
||||
|
||||
final StringBuilder out = new StringBuilder();
|
||||
final long duration = System.currentTimeMillis() - START_TIME;
|
||||
|
||||
out.append("MCTS2" +
|
||||
" cheat=" + CHEAT +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" life=" + scorePlayer.getLife() +
|
||||
" time=" + duration +
|
||||
" time=" + duration +
|
||||
" sims=" + sims);
|
||||
out.append('\n');
|
||||
|
||||
|
@ -262,16 +262,16 @@ public class MCTSAI2 implements MagicAI {
|
|||
choices = getNextChoices(game, false)) {
|
||||
|
||||
assert choices.size() > 0 : "ERROR! No choice at start of genNewTreeNode";
|
||||
|
||||
assert !curr.hasDetails() || MCTSGameTree.checkNode(curr, choices) :
|
||||
|
||||
assert !curr.hasDetails() || MCTSGameTree.checkNode(curr, choices) :
|
||||
"ERROR! Inconsistent node found" + "\n" +
|
||||
game + " " +
|
||||
printPath(path) + " " +
|
||||
game + " " +
|
||||
printPath(path) + " " +
|
||||
MCTSGameTree.printNode(curr, choices);
|
||||
|
||||
|
||||
final MagicEvent event = game.getNextEvent();
|
||||
|
||||
//first time considering the choices available at this node,
|
||||
|
||||
//first time considering the choices available at this node,
|
||||
//fill in additional details for curr
|
||||
if (!curr.hasDetails()) {
|
||||
curr.setIsAI(game.getScorePlayer() == event.getPlayer());
|
||||
|
@ -292,23 +292,23 @@ public class MCTSAI2 implements MagicAI {
|
|||
final int idx = curr.size();
|
||||
final Object[] choice = choices.get(idx);
|
||||
game.executeNextEvent(choice);
|
||||
final MCTSGameTree child = new MCTSGameTree(curr, idx, game.getScore());
|
||||
final MCTSGameTree child = new MCTSGameTree(curr, idx, game.getScore());
|
||||
assert (child.desc = MCTSGameTree.obj2String(choice[0])).equals(child.desc);
|
||||
curr.addChild(child);
|
||||
path.add(child);
|
||||
return path;
|
||||
|
||||
|
||||
//all the children are in the tree, find the "best" child to explore
|
||||
} else {
|
||||
|
||||
assert curr.size() == choices.size() : "ERROR! Different number of choices in node and game" +
|
||||
printPath(path) + MCTSGameTree.printNode(curr, choices);
|
||||
assert curr.size() == choices.size() : "ERROR! Different number of choices in node and game" +
|
||||
printPath(path) + MCTSGameTree.printNode(curr, choices);
|
||||
|
||||
MCTSGameTree next = null;
|
||||
double bestS = Double.NEGATIVE_INFINITY ;
|
||||
for (final MCTSGameTree child : curr) {
|
||||
final double raw =
|
||||
child.getAvg() * (curr.isAI() ? 1 : -1) +
|
||||
final double raw =
|
||||
child.getAvg() * (curr.isAI() ? 1 : -1) +
|
||||
MCTSAI.UCB1_C * Math.sqrt(Math.log(curr.getNumSim()) / child.getNumSim());
|
||||
final double S = child.modify(raw);
|
||||
if (S > bestS) {
|
||||
|
@ -319,13 +319,13 @@ public class MCTSAI2 implements MagicAI {
|
|||
|
||||
//move down the tree
|
||||
curr = next;
|
||||
|
||||
|
||||
//update the game state and path
|
||||
game.executeNextEvent(choices.get(curr.getChoice()));
|
||||
path.add(curr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ public class MCTSAI2 implements MagicAI {
|
|||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!CHEAT) {
|
||||
game.showRandomizedHiddenCards();
|
||||
}
|
||||
|
@ -357,16 +357,16 @@ public class MCTSAI2 implements MagicAI {
|
|||
return 1.0 - actions/(2.0 * MAX_ACTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<Object[]> getNextChoices(final MagicGame game, final boolean sim) {
|
||||
|
||||
final int startActions = game.getNumActions();
|
||||
|
||||
//use fast choices during simulation
|
||||
game.setFastChoices(sim);
|
||||
|
||||
|
||||
// simulate game until it is finished or simulated MAX_ACTIONS actions
|
||||
while (!game.isFinished() &&
|
||||
while (!game.isFinished() &&
|
||||
(game.getNumActions() - startActions) < MAX_ACTIONS) {
|
||||
|
||||
//do not accumulate score down the tree when not in simulation
|
||||
|
@ -386,7 +386,7 @@ public class MCTSAI2 implements MagicAI {
|
|||
game.executeNextEvent();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//event has choice
|
||||
|
||||
if (sim) {
|
||||
|
@ -415,10 +415,10 @@ public class MCTSAI2 implements MagicAI {
|
|||
choices = event.getArtificialChoiceResults(game);
|
||||
}
|
||||
assert choices != null;
|
||||
|
||||
|
||||
final int size = choices.size();
|
||||
assert size > 0 : "ERROR! No choice found during MCTS getACR";
|
||||
|
||||
|
||||
if (size == 1) {
|
||||
//single choice
|
||||
game.executeNextEvent(choices.get(0));
|
||||
|
@ -428,11 +428,11 @@ public class MCTSAI2 implements MagicAI {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//game is finished or number of actions > MAX_ACTIONS
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
private static String CR2String(final Object[] choiceResults) {
|
||||
final StringBuilder buffer=new StringBuilder();
|
||||
if (choiceResults!=null) {
|
||||
|
|
|
@ -14,10 +14,10 @@ import magic.model.event.MagicEvent;
|
|||
import magic.model.phase.MagicPhase;
|
||||
|
||||
public class MMAB implements MagicAI {
|
||||
|
||||
|
||||
private static final long SEC_TO_NANO=1000000000L;
|
||||
private static final int THREADS = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
|
||||
private final boolean LOGGING = Boolean.getBoolean("debug");
|
||||
private final boolean CHEAT;
|
||||
private final boolean DECKSTR;
|
||||
|
@ -34,32 +34,32 @@ public class MMAB implements MagicAI {
|
|||
CHEAT = cheat;
|
||||
DECKSTR = deckStr;
|
||||
}
|
||||
|
||||
|
||||
private void log(final String message) {
|
||||
MagicGameLog.log(message);
|
||||
if (LOGGING) {
|
||||
System.err.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object[] findNextEventChoiceResults(final MagicGame sourceGame, final MagicPlayer scorePlayer) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
||||
// copying the game is necessary because for some choices game scores might be calculated,
|
||||
// copying the game is necessary because for some choices game scores might be calculated,
|
||||
// find all possible choice results.
|
||||
MagicGame choiceGame = new MagicGame(sourceGame,scorePlayer);
|
||||
final MagicEvent event = choiceGame.getNextEvent();
|
||||
final List<Object[]> choices = event.getArtificialChoiceResults(choiceGame);
|
||||
final int size = choices.size();
|
||||
choiceGame = null;
|
||||
|
||||
|
||||
assert size != 0 : "ERROR: no choices available for MMAB";
|
||||
|
||||
|
||||
// single choice result.
|
||||
if (size == 1) {
|
||||
return sourceGame.map(choices.get(0));
|
||||
}
|
||||
|
||||
|
||||
// submit jobs
|
||||
final ArtificialPruneScoreRef scoreRef = new ArtificialPruneScoreRef(new ArtificialMultiPruneScore());
|
||||
final ArtificialScoreBoard scoreBoard = new ArtificialScoreBoard();
|
||||
|
@ -103,14 +103,14 @@ public class MMAB implements MagicAI {
|
|||
// force termination of workers
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
|
||||
// select the best scoring choice result.
|
||||
ArtificialScore bestScore = ArtificialScore.INVALID_SCORE;
|
||||
ArtificialChoiceResults bestAchoice = achoices.get(0);
|
||||
for (final ArtificialChoiceResults achoice : achoices) {
|
||||
if (bestScore.isBetter(achoice.aiScore,true)) {
|
||||
bestScore = achoice.aiScore;
|
||||
bestAchoice = achoice;
|
||||
bestAchoice = achoice;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ public class MMAB implements MagicAI {
|
|||
" cheat=" + CHEAT +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" life=" + scorePlayer.getLife() +
|
||||
" phase=" + sourceGame.getPhase().getType() +
|
||||
" phase=" + sourceGame.getPhase().getType() +
|
||||
" slice=" + (slice/1000000) +
|
||||
" time=" + timeTaken
|
||||
);
|
||||
|
@ -139,21 +139,21 @@ class MMABWorker {
|
|||
private final ArtificialScoreBoard scoreBoard;
|
||||
|
||||
private int gameCount;
|
||||
|
||||
|
||||
MMABWorker(final int id,final MagicGame game,final ArtificialScoreBoard scoreBoard, final boolean CHEAT) {
|
||||
this.id=id;
|
||||
this.game=game;
|
||||
this.scoreBoard=scoreBoard;
|
||||
this.CHEAT=CHEAT;
|
||||
}
|
||||
|
||||
|
||||
private ArtificialScore runGame(final Object[] nextChoiceResults, final ArtificialPruneScore pruneScore, final int depth, final long maxTime) {
|
||||
game.startActions();
|
||||
|
||||
|
||||
if (nextChoiceResults!=null) {
|
||||
game.executeNextEvent(nextChoiceResults);
|
||||
}
|
||||
|
||||
|
||||
if (System.nanoTime() > maxTime || Thread.currentThread().isInterrupted()) {
|
||||
final ArtificialScore aiScore=new ArtificialScore(game.getScore(),depth);
|
||||
game.undoActions();
|
||||
|
@ -165,7 +165,7 @@ class MMABWorker {
|
|||
while (!game.isFinished()) {
|
||||
if (!game.hasNextEvent()) {
|
||||
game.executePhase();
|
||||
|
||||
|
||||
// Caching of best score for game situations.
|
||||
if (game.cacheState()) {
|
||||
final long gameId=game.getGameId(pruneScore.getScore());
|
||||
|
@ -181,7 +181,7 @@ class MMABWorker {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final MagicEvent event=game.getNextEvent();
|
||||
|
||||
if (!event.hasChoice()) {
|
||||
|
@ -203,14 +203,14 @@ class MMABWorker {
|
|||
*/
|
||||
|
||||
final int nrOfChoices=choiceResultsList.size();
|
||||
|
||||
|
||||
assert nrOfChoices > 0 : "nrOfChoices is 0";
|
||||
|
||||
|
||||
if (nrOfChoices==1) {
|
||||
game.executeNextEvent(choiceResultsList.get(0));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final boolean best=game.getScorePlayer()==event.getPlayer();
|
||||
ArtificialScore bestScore=ArtificialScore.INVALID_SCORE;
|
||||
ArtificialPruneScore newPruneScore=pruneScore;
|
||||
|
@ -241,7 +241,7 @@ class MMABWorker {
|
|||
|
||||
void evaluateGame(final ArtificialChoiceResults aiChoiceResults, final ArtificialPruneScore pruneScore, long maxTime) {
|
||||
gameCount = 0;
|
||||
|
||||
|
||||
aiChoiceResults.worker = id;
|
||||
aiChoiceResults.aiScore = runGame(game.map(aiChoiceResults.choiceResults),pruneScore,0,maxTime);
|
||||
aiChoiceResults.gameCount = gameCount;
|
||||
|
|
|
@ -14,10 +14,10 @@ import magic.model.event.MagicEvent;
|
|||
import magic.model.phase.MagicPhase;
|
||||
|
||||
public class MMAB2 implements MagicAI {
|
||||
|
||||
|
||||
private static final long SEC_TO_NANO=1000000000L;
|
||||
private static final int THREADS = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
|
||||
private final boolean LOGGING;
|
||||
private final boolean CHEAT;
|
||||
private ArtificialPruneScore pruneScore = new ArtificialMultiPruneScore();
|
||||
|
@ -26,37 +26,37 @@ public class MMAB2 implements MagicAI {
|
|||
//default: no logging, no cheats
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
|
||||
MMAB2(final boolean log, final boolean cheat) {
|
||||
LOGGING = log || Boolean.getBoolean("debug");
|
||||
CHEAT = cheat;
|
||||
}
|
||||
|
||||
|
||||
private void log(final String message) {
|
||||
MagicGameLog.log(message);
|
||||
if (LOGGING) {
|
||||
System.err.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object[] findNextEventChoiceResults(final MagicGame sourceGame, final MagicPlayer scorePlayer) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
||||
// copying the game is necessary because for some choices game scores might be calculated,
|
||||
// copying the game is necessary because for some choices game scores might be calculated,
|
||||
// find all possible choice results.
|
||||
MagicGame choiceGame = new MagicGame(sourceGame,scorePlayer);
|
||||
final MagicEvent event = choiceGame.getNextEvent();
|
||||
final List<Object[]> choices = event.getArtificialChoiceResults(choiceGame);
|
||||
final int size = choices.size();
|
||||
choiceGame = null;
|
||||
|
||||
|
||||
assert size != 0 : "ERROR: no choices available for MMAB2";
|
||||
|
||||
|
||||
// single choice result.
|
||||
if (size == 1) {
|
||||
return sourceGame.map(choices.get(0));
|
||||
}
|
||||
|
||||
|
||||
// submit jobs
|
||||
final ArtificialScoreBoard scoreBoard = new ArtificialScoreBoard();
|
||||
final ExecutorService executor = Executors.newFixedThreadPool(THREADS);
|
||||
|
@ -96,14 +96,14 @@ public class MMAB2 implements MagicAI {
|
|||
// force termination of workers
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
|
||||
// select the best scoring choice result.
|
||||
ArtificialScore bestScore = ArtificialScore.INVALID_SCORE;
|
||||
ArtificialChoiceResults bestAchoice = achoices.get(0);
|
||||
for (final ArtificialChoiceResults achoice : achoices) {
|
||||
if (bestScore.isBetter(achoice.aiScore,true)) {
|
||||
bestScore = achoice.aiScore;
|
||||
bestAchoice = achoice;
|
||||
bestAchoice = achoice;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ public class MMAB2 implements MagicAI {
|
|||
" cheat=" + CHEAT +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" life=" + scorePlayer.getLife() +
|
||||
" phase=" + sourceGame.getPhase().getType() +
|
||||
" phase=" + sourceGame.getPhase().getType() +
|
||||
" slice=" + (slice/1000000) +
|
||||
" time=" + timeTaken
|
||||
);
|
||||
|
@ -127,7 +127,7 @@ public class MMAB2 implements MagicAI {
|
|||
private void updatePruneScore(final int score) {
|
||||
pruneScore = pruneScore.getPruneScore(score,true);
|
||||
}
|
||||
|
||||
|
||||
private ArtificialPruneScore getPruneScore() {
|
||||
return pruneScore;
|
||||
}
|
||||
|
@ -140,21 +140,21 @@ class MMABWorker {
|
|||
private final ArtificialScoreBoard scoreBoard;
|
||||
|
||||
private int gameCount;
|
||||
|
||||
|
||||
MMABWorker(final int id,final MagicGame game,final ArtificialScoreBoard scoreBoard, final boolean CHEAT) {
|
||||
this.id=id;
|
||||
this.game=game;
|
||||
this.scoreBoard=scoreBoard;
|
||||
this.CHEAT=CHEAT;
|
||||
}
|
||||
|
||||
|
||||
private ArtificialScore runGame(final Object[] nextChoiceResults, final ArtificialPruneScore pruneScore, final int depth, final long maxTime) {
|
||||
game.startActions();
|
||||
|
||||
|
||||
if (nextChoiceResults!=null) {
|
||||
game.executeNextEvent(nextChoiceResults);
|
||||
}
|
||||
|
||||
|
||||
if (System.nanoTime() > maxTime || Thread.currentThread().isInterrupted()) {
|
||||
final ArtificialScore aiScore=new ArtificialScore(game.getScore(),depth);
|
||||
game.undoActions();
|
||||
|
@ -166,7 +166,7 @@ class MMABWorker {
|
|||
while (!game.isFinished()) {
|
||||
if (!game.hasNextEvent()) {
|
||||
game.executePhase();
|
||||
|
||||
|
||||
// Caching of best score for game situations.
|
||||
if (game.cacheState()) {
|
||||
final long gameId=game.getGameId(pruneScore.getScore());
|
||||
|
@ -182,7 +182,7 @@ class MMABWorker {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final MagicEvent event=game.getNextEvent();
|
||||
|
||||
if (!event.hasChoice()) {
|
||||
|
@ -204,14 +204,14 @@ class MMABWorker {
|
|||
*/
|
||||
|
||||
final int nrOfChoices=choiceResultsList.size();
|
||||
|
||||
|
||||
assert nrOfChoices > 0 : "nrOfChoices is 0";
|
||||
|
||||
|
||||
if (nrOfChoices==1) {
|
||||
game.executeNextEvent(choiceResultsList.get(0));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final boolean best=game.getScorePlayer()==event.getPlayer();
|
||||
ArtificialScore bestScore=ArtificialScore.INVALID_SCORE;
|
||||
ArtificialPruneScore newPruneScore=pruneScore;
|
||||
|
@ -242,7 +242,7 @@ class MMABWorker {
|
|||
|
||||
void evaluateGame(final ArtificialChoiceResults aiChoiceResults, final ArtificialPruneScore pruneScore, long maxTime) {
|
||||
gameCount = 0;
|
||||
|
||||
|
||||
aiChoiceResults.worker = id;
|
||||
aiChoiceResults.aiScore = runGame(game.map(aiChoiceResults.choiceResults),pruneScore,0,maxTime);
|
||||
aiChoiceResults.gameCount = gameCount;
|
||||
|
|
|
@ -5,5 +5,5 @@ import magic.model.MagicPlayer;
|
|||
|
||||
public interface MagicAI {
|
||||
int MAX_LEVEL = 8;
|
||||
Object[] findNextEventChoiceResults(final MagicGame game, final MagicPlayer player);
|
||||
Object[] findNextEventChoiceResults(final MagicGame game, final MagicPlayer player);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
package magic.ai;
|
||||
|
||||
public enum MagicAIImpl {
|
||||
MMAB("minimax", new MMAB(false)),
|
||||
MMABC("minimax (cheat)", new MMAB(true)),
|
||||
MMAB("minimax", new MMAB(false)),
|
||||
MMABC("minimax (cheat)", new MMAB(true)),
|
||||
MCTS("monte carlo tree search", new MCTSAI(false)),
|
||||
MCTSC("monte carlo tree search (cheat)", new MCTSAI(true)),
|
||||
VEGAS("vegas", new VegasAI(false)),
|
||||
VEGASC("vegas (cheat)", new VegasAI(true)),
|
||||
RND("random", new RandomAI()),
|
||||
MMABFast("minimax (deck strength)", magic.ai.MMAB.DeckStrAI()),
|
||||
|
||||
|
||||
MCTS2("monte carlo tree search", new MCTSAI2(false)),
|
||||
MCTSC2("monte carlo tree search (cheat)", new MCTSAI2(true)),
|
||||
;
|
||||
|
||||
|
||||
private static final MagicAIImpl[] SUPPORTED_AIS = {MMAB, MMABC, MCTS, MCTSC, VEGAS, VEGASC};
|
||||
|
||||
|
||||
private final String name;
|
||||
private final MagicAI ai;
|
||||
|
||||
|
@ -23,15 +23,15 @@ public enum MagicAIImpl {
|
|||
this.name=name;
|
||||
this.ai=ai;
|
||||
}
|
||||
|
||||
|
||||
private String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public MagicAI getAI() {
|
||||
return ai;
|
||||
return ai;
|
||||
}
|
||||
|
||||
|
||||
public static MagicAIImpl getAI(final String name) {
|
||||
for (final MagicAIImpl ai : values()) {
|
||||
if (ai.getName().equals(name)) {
|
||||
|
@ -40,7 +40,7 @@ public enum MagicAIImpl {
|
|||
}
|
||||
return MMAB;
|
||||
}
|
||||
|
||||
|
||||
public static String[] getNames() {
|
||||
final String[] names=new String[SUPPORTED_AIS.length];
|
||||
int index=0;
|
||||
|
|
|
@ -11,9 +11,9 @@ import java.util.List;
|
|||
|
||||
//AI that plays randomly
|
||||
public class RandomAI implements MagicAI {
|
||||
|
||||
|
||||
private final boolean LOGGING;
|
||||
|
||||
|
||||
public RandomAI() {
|
||||
this(false);
|
||||
}
|
||||
|
@ -21,24 +21,24 @@ public class RandomAI implements MagicAI {
|
|||
private RandomAI(final boolean log) {
|
||||
LOGGING = log || Boolean.getBoolean("debug");
|
||||
}
|
||||
|
||||
|
||||
private void log(final String message) {
|
||||
MagicGameLog.log(message);
|
||||
if (LOGGING) {
|
||||
System.err.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object[] findNextEventChoiceResults(final MagicGame game, final MagicPlayer scorePlayer) {
|
||||
//get a list of choices
|
||||
MagicGame choiceGame = new MagicGame(game, scorePlayer);
|
||||
final MagicEvent event=choiceGame.getNextEvent();
|
||||
final List<Object[]> choices=event.getArtificialChoiceResults(choiceGame);
|
||||
choiceGame = null;
|
||||
|
||||
|
||||
final int size = choices.size();
|
||||
final String info = "RandomAI " + scorePlayer.getIndex() + " (" + scorePlayer.getLife() + ")";
|
||||
|
||||
|
||||
if (size == 0) {
|
||||
throw new RuntimeException("No choice results");
|
||||
}
|
||||
|
@ -48,17 +48,17 @@ public class RandomAI implements MagicAI {
|
|||
for (final Object[] choice : choices) {
|
||||
achoices.add(new ArtificialChoiceResults(choice));
|
||||
}
|
||||
|
||||
|
||||
// Select a random artificial choice result
|
||||
final int idx = MagicRandom.nextInt(size);
|
||||
final ArtificialChoiceResults selected=achoices.get(idx);
|
||||
if (size >= 2) {
|
||||
log(info);
|
||||
log(info);
|
||||
for (final ArtificialChoiceResults achoice : achoices) {
|
||||
log((achoice==selected?"* ":" ")+achoice);
|
||||
}
|
||||
} else {
|
||||
//log(info + " " + selected);
|
||||
//log(info + " " + selected);
|
||||
}
|
||||
return game.map(selected.choiceResults);
|
||||
}
|
||||
|
|
|
@ -17,21 +17,21 @@ public class VegasAI implements MagicAI {
|
|||
|
||||
private static final long SEC_TO_NANO=1000000000L;
|
||||
private static final int THREADS=Runtime.getRuntime().availableProcessors();
|
||||
|
||||
|
||||
private final boolean LOGGING = Boolean.getBoolean("debug");
|
||||
private final boolean CHEAT;
|
||||
|
||||
|
||||
VegasAI(final boolean cheat) {
|
||||
CHEAT = cheat;
|
||||
}
|
||||
|
||||
|
||||
private void log(final String message) {
|
||||
MagicGameLog.log(message);
|
||||
if (LOGGING) {
|
||||
System.err.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object[] findNextEventChoiceResults(final MagicGame sourceGame,final MagicPlayer scorePlayer) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
@ -42,18 +42,18 @@ public class VegasAI implements MagicAI {
|
|||
}
|
||||
final MagicEvent event=choiceGame.getNextEvent();
|
||||
final List<Object[]> choiceResultsList=event.getArtificialChoiceResults(choiceGame);
|
||||
|
||||
|
||||
// No choices
|
||||
final int size=choiceResultsList.size();
|
||||
if (size==0) {
|
||||
throw new RuntimeException("No choice results");
|
||||
}
|
||||
|
||||
// Single choice
|
||||
}
|
||||
|
||||
// Single choice
|
||||
if (size==1) {
|
||||
return sourceGame.map(choiceResultsList.get(0));
|
||||
}
|
||||
|
||||
|
||||
// Multiple choices
|
||||
final ExecutorService executor = Executors.newFixedThreadPool(THREADS);
|
||||
final List<VegasScore> scores=new ArrayList<VegasScore>();
|
||||
|
@ -80,7 +80,7 @@ public class VegasAI implements MagicAI {
|
|||
// force termination of workers
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
|
||||
// Return best choice
|
||||
VegasScore bestScore=scores.get(0);
|
||||
for (final VegasScore score : scores) {
|
||||
|
@ -88,14 +88,14 @@ public class VegasAI implements MagicAI {
|
|||
bestScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Logging.
|
||||
final long timeTaken = System.currentTimeMillis() - startTime;
|
||||
log("VEGAS" +
|
||||
" cheat=" + CHEAT +
|
||||
" index=" + scorePlayer.getIndex() +
|
||||
" life=" + scorePlayer.getLife() +
|
||||
" phase=" + sourceGame.getPhase().getType() +
|
||||
" phase=" + sourceGame.getPhase().getType() +
|
||||
" slice=" + (slice/1000000) +
|
||||
" time=" + timeTaken
|
||||
);
|
||||
|
|
|
@ -5,11 +5,11 @@ public class VegasScore {
|
|||
private final Object[] choiceResults;
|
||||
private long totalScore;
|
||||
private int count;
|
||||
|
||||
|
||||
VegasScore(final Object[] choiceResults) {
|
||||
this.choiceResults=choiceResults;
|
||||
}
|
||||
|
||||
|
||||
void incrementScore(final int score) {
|
||||
totalScore+=score;
|
||||
count++;
|
||||
|
@ -18,7 +18,7 @@ public class VegasScore {
|
|||
Object[] getChoiceResults() {
|
||||
return choiceResults;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
final StringBuilder buffer=new StringBuilder();
|
||||
buffer.append("[").append(getScore()).append('/').append(count).append("]");
|
||||
|
@ -37,7 +37,7 @@ public class VegasScore {
|
|||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
int getScore() {
|
||||
return count>0?(int)(totalScore/count):ArtificialScoringSystem.LOSE_GAME_SCORE;
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ import java.util.Random;
|
|||
public class VegasWorker implements Runnable {
|
||||
|
||||
private static final int MAIN_PHASES=6;
|
||||
|
||||
|
||||
private final MagicGame sourceGame;
|
||||
private final VegasScore score;
|
||||
private final Object[] choiceResults;
|
||||
private final Random random;
|
||||
private final long slice;
|
||||
private final boolean CHEAT;
|
||||
|
||||
|
||||
VegasWorker(final boolean cheat, final MagicGame sourceGame, final VegasScore score,final Random random,final long slice) {
|
||||
this.CHEAT = cheat;
|
||||
this.sourceGame=sourceGame;
|
||||
|
@ -36,21 +36,21 @@ public class VegasWorker implements Runnable {
|
|||
}
|
||||
|
||||
final MagicEvent event=game.getNextEvent();
|
||||
|
||||
|
||||
if (!event.hasChoice()) {
|
||||
game.executeNextEvent();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final List<Object[]> choiceResultsList=event.getArtificialChoiceResults(game);
|
||||
final int nrOfChoices=choiceResultsList.size();
|
||||
|
||||
assert nrOfChoices != 0 : "ERROR: no choices available for VegasWorker";
|
||||
|
||||
|
||||
game.executeNextEvent(choiceResultsList.get(random.nextInt(nrOfChoices)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final long endTime = System.nanoTime() + slice;
|
||||
|
@ -64,5 +64,5 @@ public class VegasWorker implements Runnable {
|
|||
runGame(game);
|
||||
score.incrementScore(game.getScore());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@ import java.util.Vector;
|
|||
public class AvatarImages {
|
||||
|
||||
private static final AvatarImages INSTANCE = new AvatarImages();
|
||||
|
||||
|
||||
private final File avatarPath;
|
||||
private final Vector<String> names;
|
||||
private String current = "";
|
||||
private PlayerAvatar[] avatars;
|
||||
|
||||
|
||||
private AvatarImages() {
|
||||
avatarPath=new File(MagicMain.getGamePath(),"avatars");
|
||||
final File[] files=avatarPath.listFiles();
|
||||
|
@ -29,15 +29,15 @@ public class AvatarImages {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Vector<String> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
private static PlayerAvatar loadAvatar(final File file) {
|
||||
return new PlayerAvatar(FileIO.toImg(file, IconImages.MISSING));
|
||||
}
|
||||
|
||||
|
||||
private synchronized void loadAvatars() {
|
||||
final String avatar=GeneralConfig.getInstance().getAvatar();
|
||||
if (!avatar.equals(current)) {
|
||||
|
@ -48,7 +48,7 @@ public class AvatarImages {
|
|||
avatars=new PlayerAvatar[files.length];
|
||||
for (int index=0;index<files.length;index++) {
|
||||
avatars[index]=loadAvatar(files[index]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
avatars=new PlayerAvatar[2];
|
||||
avatars[0]=loadAvatar(new File(""));
|
||||
|
@ -56,7 +56,7 @@ public class AvatarImages {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public synchronized ImageIcon getAvatarIcon(int index,final int size) {
|
||||
loadAvatars();
|
||||
if (index < 0) {
|
||||
|
@ -66,7 +66,7 @@ public class AvatarImages {
|
|||
}
|
||||
return avatars[index].getIcon(size);
|
||||
}
|
||||
|
||||
|
||||
public synchronized int getNumberOfAvatars() {
|
||||
loadAvatars();
|
||||
return avatars.length;
|
||||
|
|
|
@ -35,7 +35,7 @@ public class CardDefinitions {
|
|||
public static final String TOKEN_IMAGE_FOLDER = "tokens";
|
||||
public static final String CARD_IMAGE_EXT = CardImagesProvider.IMAGE_EXTENSION;
|
||||
public static final String CARD_TEXT_EXT = ".txt";
|
||||
|
||||
|
||||
private static final List<MagicCardDefinition> cards = new ArrayList<MagicCardDefinition>();
|
||||
private static final List<MagicCardDefinition> landCards = new ArrayList<MagicCardDefinition>();
|
||||
private static final List<MagicCardDefinition> spellCards = new ArrayList<MagicCardDefinition>();
|
||||
|
@ -51,7 +51,7 @@ public class CardDefinitions {
|
|||
new ImportCustomizer().addStarImports(
|
||||
"java.util",
|
||||
"magic.data",
|
||||
"magic.model",
|
||||
"magic.model",
|
||||
"magic.model.action",
|
||||
"magic.model.choice",
|
||||
"magic.model.condition",
|
||||
|
@ -73,7 +73,7 @@ public class CardDefinitions {
|
|||
throw new RuntimeException("Unsupported card property: " + property);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void filterCards() {
|
||||
for (final MagicCardDefinition card : cards) {
|
||||
if (!card.isLand() && !card.isToken()) {
|
||||
|
@ -100,7 +100,7 @@ public class CardDefinitions {
|
|||
CubeDefinitions.getCubeDefinition("all").add(cardDefinition.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static MagicCardDefinition prop2carddef(final Properties content) {
|
||||
final MagicCardDefinition cardDefinition=new MagicCardDefinition();
|
||||
|
||||
|
@ -124,11 +124,11 @@ public class CardDefinitions {
|
|||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String getCanonicalName(String fullName) {
|
||||
return fullName.replaceAll("[^A-Za-z0-9]", "_");
|
||||
}
|
||||
|
||||
|
||||
private static void loadCardDefinition(final File file) {
|
||||
try {
|
||||
final MagicCardDefinition cdef = prop2carddef(FileIO.toProp(file));
|
||||
|
@ -141,7 +141,7 @@ public class CardDefinitions {
|
|||
throw new RuntimeException("Error loading " + file, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void loadCardDefinitions() {
|
||||
//load all files in card directory
|
||||
final File[] files = cardDir.listFiles(new FilenameFilter() {
|
||||
|
@ -152,24 +152,24 @@ public class CardDefinitions {
|
|||
for (final File file : files) {
|
||||
loadCardDefinition(file);
|
||||
}
|
||||
|
||||
|
||||
filterCards();
|
||||
printStatistics();
|
||||
|
||||
|
||||
addDefinition(MagicCardDefinition.UNKNOWN);
|
||||
|
||||
System.err.println(getNumberOfCards()+ " card definitions");
|
||||
MagicCardDefinition.printStatistics();
|
||||
}
|
||||
|
||||
|
||||
public static int getNumberOfCards() {
|
||||
return cards.size();
|
||||
}
|
||||
|
||||
|
||||
public static MagicCardDefinition getCard(final int cindex) {
|
||||
return cards.get(cindex);
|
||||
}
|
||||
|
||||
|
||||
public static MagicCardDefinition getCard(final String name) {
|
||||
final MagicCardDefinition cardDefinition=cardsMap.get(name);
|
||||
if (cardDefinition == null) {
|
||||
|
@ -177,7 +177,7 @@ public class CardDefinitions {
|
|||
}
|
||||
return cardDefinition;
|
||||
}
|
||||
|
||||
|
||||
public static void loadCardTexts() {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
|
@ -190,21 +190,21 @@ public class CardDefinitions {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static void loadCardText(final MagicCardDefinition card) {
|
||||
// try to load text from file
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(MagicMain.getGamePath());
|
||||
buffer.append(File.separator);
|
||||
buffer.append(CARD_TEXT_FOLDER);
|
||||
buffer.append(File.separator);
|
||||
buffer.append(File.separator);
|
||||
buffer.append(card.getCardTextName());
|
||||
buffer.append(CARD_TEXT_EXT);
|
||||
|
||||
|
||||
try {
|
||||
final String text = FileIO.toStr(new File(buffer.toString()));
|
||||
if (text != null) {
|
||||
card.setText(text);
|
||||
card.setText(text);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// text not downloaded or missing
|
||||
|
@ -229,15 +229,15 @@ public class CardDefinitions {
|
|||
public static List<MagicCardDefinition> getCards() {
|
||||
return cards;
|
||||
}
|
||||
|
||||
|
||||
public static List<MagicCardDefinition> getLandCards() {
|
||||
return landCards;
|
||||
}
|
||||
|
||||
|
||||
public static List<MagicCardDefinition> getSpellCards() {
|
||||
return spellCards;
|
||||
}
|
||||
|
||||
|
||||
private static void printStatistics() {
|
||||
final CardStatistics statistics=new CardStatistics(cards);
|
||||
statistics.printStatictics(System.err);
|
||||
|
|
|
@ -5,7 +5,7 @@ import magic.model.MagicCardDefinition;
|
|||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Interface for getting image of a card
|
||||
*/
|
||||
public interface CardImagesProvider {
|
||||
|
@ -15,7 +15,7 @@ public interface CardImagesProvider {
|
|||
//native resolution of images from magiccards.info
|
||||
int CARD_WIDTH=312;
|
||||
int CARD_HEIGHT=445;
|
||||
|
||||
|
||||
Dimension CARD_DIMENSION = new Dimension(CARD_WIDTH, CARD_HEIGHT);
|
||||
|
||||
BufferedImage getImage(
|
||||
|
|
|
@ -191,7 +191,7 @@ public enum CardProperty {
|
|||
}
|
||||
},
|
||||
;
|
||||
|
||||
|
||||
public void setProperty(final MagicCardDefinition card, final String value) {
|
||||
//do nothing
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public class CardStatistics {
|
|||
IconImages.COST_NINE
|
||||
));
|
||||
public static final int MANA_CURVE_SIZE=MANA_CURVE_TEXT.size();
|
||||
|
||||
|
||||
private static final List<String> TYPE_NAMES = Collections.unmodifiableList(Arrays.asList(
|
||||
"Land","Spell","Creature","Equipment","Aura","Enchantment","Artifact"));
|
||||
public static final List<ImageIcon> TYPE_ICONS = Collections.unmodifiableList(Arrays.asList(
|
||||
|
@ -37,22 +37,22 @@ public class CardStatistics {
|
|||
IconImages.SPELL,
|
||||
IconImages.CREATURE,
|
||||
IconImages.EQUIPMENT,
|
||||
IconImages.AURA,
|
||||
IconImages.AURA,
|
||||
IconImages.ENCHANTMENT,
|
||||
IconImages.ARTIFACT
|
||||
));
|
||||
public static final int NR_OF_TYPES=TYPE_NAMES.size();
|
||||
|
||||
|
||||
private final Collection<MagicCardDefinition> cards;
|
||||
|
||||
|
||||
private int totalCards;
|
||||
public final int[] totalTypes=new int[NR_OF_TYPES];
|
||||
|
||||
|
||||
private final int[] totalRarity=new int[MagicRarity.length];
|
||||
|
||||
|
||||
private double averageCost;
|
||||
private double averageValue;
|
||||
|
||||
|
||||
public final int[] colorCount=new int[MagicColor.NR_COLORS];
|
||||
public final int[] colorMono=new int[MagicColor.NR_COLORS];
|
||||
public final int[] colorLands=new int[MagicColor.NR_COLORS];
|
||||
|
@ -60,12 +60,12 @@ public class CardStatistics {
|
|||
public int monoColor;
|
||||
public int multiColor;
|
||||
public int colorless;
|
||||
|
||||
|
||||
public CardStatistics(final Collection<MagicCardDefinition> cards) {
|
||||
this.cards=cards;
|
||||
createStatistics();
|
||||
}
|
||||
|
||||
|
||||
private void createStatistics() {
|
||||
for (final MagicCardDefinition card : cards) {
|
||||
//ignore tokens
|
||||
|
@ -74,16 +74,16 @@ public class CardStatistics {
|
|||
}
|
||||
|
||||
totalCards++;
|
||||
|
||||
|
||||
totalRarity[card.getRarity()]++;
|
||||
|
||||
|
||||
if (card.isLand()) {
|
||||
totalTypes[0]++;
|
||||
for (final MagicColor color : MagicColor.values()) {
|
||||
if (card.getManaSource(color) > 0) {
|
||||
colorLands[color.ordinal()]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (card.hasX()) {
|
||||
manaCurve[0]++;
|
||||
|
@ -91,10 +91,10 @@ public class CardStatistics {
|
|||
final int convertedCost=card.getConvertedCost();
|
||||
manaCurve[convertedCost+1>=MANA_CURVE_SIZE?MANA_CURVE_SIZE-1:convertedCost+1]++;
|
||||
}
|
||||
|
||||
|
||||
averageCost+=card.getConvertedCost();
|
||||
averageValue+=card.getValue();
|
||||
|
||||
|
||||
if (card.isCreature()) {
|
||||
totalTypes[2]++;
|
||||
} else if (card.isEquipment()) {
|
||||
|
@ -108,11 +108,11 @@ public class CardStatistics {
|
|||
} else {
|
||||
totalTypes[1]++;
|
||||
}
|
||||
|
||||
|
||||
int count=0;
|
||||
int index=-1;
|
||||
for (final MagicColor color : MagicColor.values()) {
|
||||
|
||||
|
||||
if (color.hasColor(card.getColorFlags())) {
|
||||
index=color.ordinal();
|
||||
colorCount[index]++;
|
||||
|
@ -129,14 +129,14 @@ public class CardStatistics {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final int total=totalCards-totalTypes[0];
|
||||
if (total>0) {
|
||||
averageValue /= total;
|
||||
averageCost /= total;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printStatictics(final PrintStream stream) {
|
||||
|
||||
stream.print("Cards : "+totalCards);
|
||||
|
@ -144,9 +144,9 @@ public class CardStatistics {
|
|||
stream.print(" "+TYPE_NAMES.get(index)+" : "+totalTypes[index]);
|
||||
}
|
||||
stream.println();
|
||||
|
||||
|
||||
for (int index=0;index<MagicRarity.length;index++) {
|
||||
|
||||
|
||||
stream.print(MagicRarity.values()[index].getName() + " : " + totalRarity[index] + " ");
|
||||
}
|
||||
stream.println();
|
||||
|
@ -154,16 +154,16 @@ public class CardStatistics {
|
|||
stream.println("Monocolor : "+monoColor+" Multicolor : "+multiColor+" Colorless : "+colorless);
|
||||
|
||||
for (final MagicColor color : MagicColor.values()) {
|
||||
|
||||
|
||||
final int index=color.ordinal();
|
||||
stream.print("Color "+color.getName()+" : "+colorCount[index]);
|
||||
stream.print(" Mono : "+colorMono[index]);
|
||||
stream.print(" Lands : "+colorLands[index]);
|
||||
stream.println();
|
||||
}
|
||||
|
||||
stream.println();
|
||||
}
|
||||
|
||||
for (int index=0;index<MANA_CURVE_SIZE;index++) {
|
||||
|
||||
|
||||
stream.print(MANA_CURVE_TEXT.get(index)+" = "+manaCurve[index]+" ");
|
||||
}
|
||||
stream.println();
|
||||
|
|
|
@ -11,28 +11,28 @@ import java.util.List;
|
|||
import java.util.Scanner;
|
||||
|
||||
public class CubeDefinitions {
|
||||
|
||||
|
||||
private static final String[] INCLUDED_CUBES={"all"};
|
||||
private static final String CUBE_FILE_EXTENSION="_cube.txt";
|
||||
|
||||
|
||||
static final String DEFAULT_NAME=INCLUDED_CUBES[0];
|
||||
|
||||
|
||||
private static final FileFilter CUBE_FILE_FILTER=new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(final File file) {
|
||||
return file.isFile()&&file.getName().endsWith(CUBE_FILE_EXTENSION);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static final List<MagicCubeDefinition> cubeDefinitions;
|
||||
|
||||
|
||||
static {
|
||||
cubeDefinitions=new ArrayList<MagicCubeDefinition>();
|
||||
for (final String cubeName : INCLUDED_CUBES) {
|
||||
cubeDefinitions.add(new MagicCubeDefinition(cubeName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String[] getCubeNames() {
|
||||
final String[] names=new String[cubeDefinitions.size()];
|
||||
for (int index=0;index<names.length;index++) {
|
||||
|
@ -40,7 +40,7 @@ public class CubeDefinitions {
|
|||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
public static MagicCubeDefinition getCubeDefinition(final String name) {
|
||||
for (final MagicCubeDefinition cubeDefinition : cubeDefinitions) {
|
||||
if (cubeDefinition.getName().equals(name)) {
|
||||
|
@ -49,7 +49,7 @@ public class CubeDefinitions {
|
|||
}
|
||||
return cubeDefinitions.get(0);
|
||||
}
|
||||
|
||||
|
||||
private static void loadCubeDefinition(final String name,final File file) {
|
||||
String content = "";
|
||||
try { //load cube
|
||||
|
@ -70,7 +70,7 @@ public class CubeDefinitions {
|
|||
}
|
||||
cubeDefinitions.add(cubeDefinition);
|
||||
}
|
||||
|
||||
|
||||
public static void loadCubeDefinitions() {
|
||||
final File[] cubeFiles=new File(MagicMain.getModsPath()).listFiles(CUBE_FILE_FILTER);
|
||||
if (cubeFiles!=null) {
|
||||
|
@ -80,7 +80,7 @@ public class CubeDefinitions {
|
|||
loadCubeDefinition(name.substring(0,index),file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
System.err.println(cubeDefinitions.size()+" cube definitions");
|
||||
for (final MagicCubeDefinition cubeDefinition : cubeDefinitions) {
|
||||
System.err.println("Cube "+cubeDefinition.getName());
|
||||
|
|
|
@ -15,47 +15,47 @@ import java.util.TreeMap;
|
|||
public class DeckGenerators {
|
||||
|
||||
private static final DeckGenerators INSTANCE = new DeckGenerators();
|
||||
|
||||
|
||||
private static final String FILENAME = "deckgenerators.txt";
|
||||
|
||||
|
||||
private final Map<String, Class> generatorsMap;
|
||||
|
||||
|
||||
private DeckGenerators() {
|
||||
generatorsMap = new TreeMap<String, Class>();
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getGeneratorNames() {
|
||||
return generatorsMap.keySet();
|
||||
}
|
||||
|
||||
|
||||
private void addDeckGenerator(final String name, final Class c) {
|
||||
generatorsMap.put(name, c);
|
||||
}
|
||||
|
||||
|
||||
private void addDeckGenerator(final String name) {
|
||||
// find class
|
||||
final String cname = name.replaceAll("[^A-Za-z0-9]", "_");
|
||||
try { // reflection
|
||||
final Class c = Class.forName("magic.generator." + cname + "_DeckGenerator");
|
||||
|
||||
|
||||
addDeckGenerator(name, c);
|
||||
|
||||
|
||||
System.err.println("added deck generator " + name);
|
||||
} catch (final ClassNotFoundException ex) {
|
||||
// no class found
|
||||
} catch (final ClassCastException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public DefaultDeckGenerator getDeckGenerator(final String name) {
|
||||
return getDeckGenerator(generatorsMap.get(name));
|
||||
}
|
||||
|
||||
|
||||
private DefaultDeckGenerator getDeckGenerator(final Class c) {
|
||||
DefaultDeckGenerator gen = null;
|
||||
|
||||
|
||||
if(c != null) {
|
||||
try {
|
||||
gen = (DefaultDeckGenerator) c.newInstance();
|
||||
|
@ -67,10 +67,10 @@ public class DeckGenerators {
|
|||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return gen;
|
||||
}
|
||||
|
||||
|
||||
private void loadDeckGenerators(final String filename) {
|
||||
final InputStream stream = this.getClass().getResourceAsStream(filename);
|
||||
String content = null;
|
||||
|
@ -92,17 +92,17 @@ public class DeckGenerators {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void loadDeckGenerators() {
|
||||
loadDeckGenerators(FILENAME);
|
||||
|
||||
System.err.println(getNrGenerators()+ " deck generators loaded");
|
||||
}
|
||||
|
||||
|
||||
public int getNrGenerators() {
|
||||
return generatorsMap.size();
|
||||
}
|
||||
|
||||
|
||||
public static DeckGenerators getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.TreeMap;
|
|||
public class DeckUtils {
|
||||
|
||||
public static final String DECK_EXTENSION=".dec";
|
||||
|
||||
|
||||
public static final FileFilter DECK_FILEFILTER=new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(final File file) {
|
||||
|
@ -35,20 +35,20 @@ public class DeckUtils {
|
|||
return "Magarena deck";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static final String[] CARD_TYPES={"creatures","spells","lands"};
|
||||
|
||||
|
||||
public static String getDeckFolder() {
|
||||
return MagicMain.getGamePath()+File.separator+"decks";
|
||||
}
|
||||
|
||||
|
||||
public static void createDeckFolder() {
|
||||
final File deckFolderFile=new File(getDeckFolder());
|
||||
if (!deckFolderFile.exists() && !deckFolderFile.mkdir()) {
|
||||
System.err.println("WARNING. Unable to create " + getDeckFolder());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean saveDeck(final String filename,final MagicPlayerDefinition player) {
|
||||
final List<SortedMap<String,Integer>> cardMaps=new ArrayList<SortedMap<String,Integer>>();
|
||||
boolean isSuccessful = true;
|
||||
|
@ -56,7 +56,7 @@ public class DeckUtils {
|
|||
for (int count=3;count>0;count--) {
|
||||
cardMaps.add(new TreeMap<String, Integer>());
|
||||
}
|
||||
|
||||
|
||||
for (final MagicCardDefinition cardDefinition : player.getDeck()) {
|
||||
final String name=cardDefinition.getName();
|
||||
final int index;
|
||||
|
@ -71,9 +71,9 @@ public class DeckUtils {
|
|||
final Integer count=cardMap.get(name);
|
||||
cardMap.put(name,count==null?Integer.valueOf(1):Integer.valueOf(count+1));
|
||||
}
|
||||
|
||||
|
||||
BufferedWriter writer = null;
|
||||
try { //save deck
|
||||
try { //save deck
|
||||
writer = new BufferedWriter(new FileWriter(filename));
|
||||
for (int index=0;index<=2;index++) {
|
||||
final SortedMap<String,Integer> cardMap=cardMaps.get(index);
|
||||
|
@ -99,10 +99,10 @@ public class DeckUtils {
|
|||
} finally {
|
||||
magic.data.FileIO.close(writer);
|
||||
}
|
||||
|
||||
|
||||
return isSuccessful;
|
||||
}
|
||||
|
||||
|
||||
public static void loadDeck(final String filename,final MagicPlayerDefinition player) {
|
||||
String content = "";
|
||||
try { //load deck
|
||||
|
@ -118,7 +118,7 @@ public class DeckUtils {
|
|||
final int[] colorCount = new int[MagicColor.NR_COLORS];
|
||||
final MagicDeck deck = player.getDeck();
|
||||
final MagicDeck unsupported = new MagicDeck();
|
||||
|
||||
|
||||
deck.setName(new File(filename).getName());
|
||||
deck.clear(); // remove previous cards
|
||||
|
||||
|
@ -173,7 +173,7 @@ public class DeckUtils {
|
|||
profile.setPreConstructed();
|
||||
player.setProfile(profile);
|
||||
}
|
||||
|
||||
|
||||
public static void showUnsupportedCards(final MagicDeck unsupported) {
|
||||
if (unsupported.isEmpty()) {
|
||||
return;
|
||||
|
@ -182,7 +182,7 @@ public class DeckUtils {
|
|||
// show error message for unsupported cards
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("The loaded deck contained unsupported card(s): ");
|
||||
|
||||
|
||||
// generate list of unsupported cards
|
||||
for (int i = 0; i < unsupported.size(); i++) {
|
||||
if(i > 0) {
|
||||
|
@ -190,27 +190,27 @@ public class DeckUtils {
|
|||
}
|
||||
sb.append(unsupported.get(i).getName());
|
||||
}
|
||||
|
||||
// options panel doesn't have automatic text wrapping
|
||||
// because the method that provides max char limit isn't
|
||||
|
||||
// options panel doesn't have automatic text wrapping
|
||||
// because the method that provides max char limit isn't
|
||||
// coded, so override that method
|
||||
final JOptionPane cleanupPane = new JOptionPane(sb.toString(), JOptionPane.ERROR_MESSAGE) {
|
||||
private static final long serialVersionUID = 232L;
|
||||
|
||||
@Override
|
||||
public int getMaxCharactersPerLineCount() {
|
||||
return 70;
|
||||
}
|
||||
public int getMaxCharactersPerLineCount() {
|
||||
return 70;
|
||||
}
|
||||
};
|
||||
cleanupPane.createDialog(null, "Unsupported Cards").setVisible(true);
|
||||
|
||||
|
||||
unsupported.clear();
|
||||
}
|
||||
|
||||
|
||||
private static void retrieveDeckFiles(final File folder,final List<File> deckFiles) {
|
||||
final File[] files=folder.listFiles();
|
||||
for (final File file : files) {
|
||||
|
||||
|
||||
if (file.isDirectory()) {
|
||||
retrieveDeckFiles(file,deckFiles);
|
||||
} else if (file.getName().endsWith(DECK_EXTENSION)) {
|
||||
|
@ -218,11 +218,11 @@ public class DeckUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void loadRandomDeck(final MagicPlayerDefinition player) {
|
||||
final File deckFile=new File(getDeckFolder());
|
||||
final List<File> deckFiles=new ArrayList<File>();
|
||||
retrieveDeckFiles(deckFile,deckFiles);
|
||||
retrieveDeckFiles(deckFile,deckFiles);
|
||||
final int size=deckFiles.size();
|
||||
if (size==0) {
|
||||
// Creates a simple default deck.
|
||||
|
|
|
@ -9,19 +9,19 @@ import java.net.URL;
|
|||
public class DownloadCardTextFile extends WebDownloader {
|
||||
private static final String startPattern = "ctext\">";
|
||||
private static final String endPattern = "</p>";
|
||||
|
||||
|
||||
private final File file;
|
||||
private final URL url;
|
||||
|
||||
|
||||
DownloadCardTextFile(final File file, final URL url) {
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
|
||||
public String getFilename() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
@ -29,10 +29,10 @@ public class DownloadCardTextFile extends WebDownloader {
|
|||
public boolean exists() {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
|
||||
public void download(final Proxy proxy) {
|
||||
final String html = WebDownloader.getHTML(proxy, url);
|
||||
|
||||
|
||||
// find text in html
|
||||
int iStart = html.indexOf(startPattern);
|
||||
String foundText = null;
|
||||
|
@ -40,12 +40,12 @@ public class DownloadCardTextFile extends WebDownloader {
|
|||
iStart += startPattern.length();
|
||||
final int iEnd = html.indexOf(endPattern, iStart);
|
||||
foundText = html.substring(iStart, iEnd) + " ";
|
||||
|
||||
|
||||
foundText = foundText.replace((char) 195, 'A').replace((char) 8224, 'E');; // replace Æ character with AE
|
||||
foundText = foundText.replaceAll("\\<br\\>", " "); // replace newlines
|
||||
foundText = foundText.replaceAll("\\<[^\\>]*\\>", ""); // remove other html tags
|
||||
}
|
||||
|
||||
|
||||
// write text out to file
|
||||
// even if there's no text we want to create the file to ensure that we don't redownload it
|
||||
if(foundText != null) {
|
||||
|
@ -66,6 +66,6 @@ public class DownloadCardTextFile extends WebDownloader {
|
|||
}
|
||||
} else {
|
||||
System.err.println("ERROR! Unable to download card text for " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,17 +11,17 @@ public class DownloadImageFile extends WebDownloader {
|
|||
private final File file;
|
||||
private final URL url;
|
||||
private final MagicCardDefinition cdef;
|
||||
|
||||
|
||||
DownloadImageFile(final File file, final URL url) {
|
||||
this(file, url, MagicCardDefinition.UNKNOWN);
|
||||
}
|
||||
|
||||
|
||||
DownloadImageFile(final File file, final URL url, final MagicCardDefinition cdef) {
|
||||
this.file=file;
|
||||
this.url=url;
|
||||
this.cdef=cdef;
|
||||
}
|
||||
|
||||
|
||||
public String getFilename() {
|
||||
return file.getName();
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class DownloadImageFile extends WebDownloader {
|
|||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public void download(final Proxy proxy) {
|
||||
WebDownloader.downloadToFile(proxy, url, file);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import java.net.URL;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Download the necessary images and files from the WWW
|
||||
*/
|
||||
public class DownloadMissingFiles extends ArrayList<WebDownloader> {
|
||||
|
@ -21,11 +21,11 @@ public class DownloadMissingFiles extends ArrayList<WebDownloader> {
|
|||
|
||||
public DownloadMissingFiles(final String filename) {
|
||||
loadDownloadImageFiles(filename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void loadDownloadImageFiles(final String filename) {
|
||||
final InputStream stream;
|
||||
|
||||
|
||||
// download additional images
|
||||
if (filename.startsWith("file://")) {
|
||||
try { //create file input stream
|
||||
|
@ -73,27 +73,27 @@ public class DownloadMissingFiles extends ArrayList<WebDownloader> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// download card images and texts
|
||||
final File cardsPathFile=new File(gamePathFile, CardDefinitions.CARD_IMAGE_FOLDER);
|
||||
final File tokensPathFile = new File(gamePathFile, CardDefinitions.TOKEN_IMAGE_FOLDER);
|
||||
final File textPathFile = new File(gamePathFile, CardDefinitions.CARD_TEXT_FOLDER);
|
||||
|
||||
|
||||
if (!tokensPathFile.exists() && !tokensPathFile.mkdir()) {
|
||||
System.err.println("WARNING. Unable to create " + tokensPathFile);
|
||||
}
|
||||
if (!textPathFile.exists() && !textPathFile.mkdir()) {
|
||||
System.err.println("WARNING. Unable to create " + textPathFile);
|
||||
}
|
||||
|
||||
|
||||
for (final MagicCardDefinition cardDefinition : CardDefinitions.getCards()) {
|
||||
// card image
|
||||
final String imageURL = cardDefinition.getImageURL();
|
||||
if (imageURL != null) {
|
||||
final File imageFile = cardDefinition.isToken()?
|
||||
new File(tokensPathFile,
|
||||
final File imageFile = cardDefinition.isToken()?
|
||||
new File(tokensPathFile,
|
||||
cardDefinition.getImageName() + CardDefinitions.CARD_IMAGE_EXT) :
|
||||
new File(cardsPathFile,
|
||||
new File(cardsPathFile,
|
||||
cardDefinition.getImageName() + CardDefinitions.CARD_IMAGE_EXT);
|
||||
|
||||
try { //create URL
|
||||
|
@ -105,15 +105,15 @@ public class DownloadMissingFiles extends ArrayList<WebDownloader> {
|
|||
System.err.println("ERROR! URL malformed " + imageURL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// card text
|
||||
final String textUrl = cardDefinition.getCardInfoURL();
|
||||
if (textUrl != null && textUrl.length() > 0) {
|
||||
final File textFile = new File(textPathFile,
|
||||
final File textFile = new File(textPathFile,
|
||||
cardDefinition.getCardTextName() + CardDefinitions.CARD_TEXT_EXT);
|
||||
|
||||
|
||||
// download if the file does not exists OR it is zero length OR it is outdated
|
||||
if (!textFile.exists() ||
|
||||
if (!textFile.exists() ||
|
||||
textFile.length() == 0L ||
|
||||
cardDefinition.isIgnored(textFile.length())) {
|
||||
try { // create URL
|
||||
|
|
|
@ -18,7 +18,7 @@ public class DuelConfig {
|
|||
private static final String ANY_THREE="***";
|
||||
private static final String ANY_TWO="**";
|
||||
private static final String ANY_ONE="*";
|
||||
|
||||
|
||||
private static final String CONFIG_FILENAME="duel.cfg";
|
||||
private static final String AVATAR="avatar";
|
||||
private static final String NAME="name";
|
||||
|
@ -39,11 +39,11 @@ public class DuelConfig {
|
|||
private String opponentColors=ANY_THREE;
|
||||
private String cube=CubeDefinitions.DEFAULT_NAME;
|
||||
private String ai="minimax";
|
||||
|
||||
|
||||
public DuelConfig() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public DuelConfig(final DuelConfig duelConfig) {
|
||||
avatar=duelConfig.avatar;
|
||||
startLife=duelConfig.startLife;
|
||||
|
@ -53,7 +53,7 @@ public class DuelConfig {
|
|||
opponentColors=duelConfig.opponentColors;
|
||||
ai=duelConfig.ai;
|
||||
}
|
||||
|
||||
|
||||
public int getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
@ -61,11 +61,11 @@ public class DuelConfig {
|
|||
public void setAvatar(final int avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name=name;
|
||||
}
|
||||
|
@ -85,15 +85,15 @@ public class DuelConfig {
|
|||
public void setHandSize(final int handSize) {
|
||||
this.handSize = handSize;
|
||||
}
|
||||
|
||||
|
||||
public void setNrOfGames(final int aGames) {
|
||||
this.games = aGames;
|
||||
this.games = aGames;
|
||||
}
|
||||
|
||||
|
||||
public int getNrOfGames() {
|
||||
return games;
|
||||
}
|
||||
|
||||
|
||||
private static MagicPlayerProfile getProfile(final String colorText) {
|
||||
if (ANY_DECK.equals(colorText)) {
|
||||
return new MagicPlayerProfile("");
|
||||
|
@ -109,48 +109,48 @@ public class DuelConfig {
|
|||
}
|
||||
return new MagicPlayerProfile(colorText);
|
||||
}
|
||||
|
||||
|
||||
public String getPlayerColors() {
|
||||
return playerColors;
|
||||
}
|
||||
|
||||
|
||||
public void setPlayerColors(final String colors) {
|
||||
playerColors=colors;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerProfile getPlayerProfile() {
|
||||
return getProfile(playerColors);
|
||||
}
|
||||
|
||||
|
||||
public String getOpponentColors() {
|
||||
return opponentColors;
|
||||
}
|
||||
|
||||
|
||||
public void setOpponentColors(final String colors) {
|
||||
opponentColors=colors;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerProfile getOpponentProfile() {
|
||||
return getProfile(opponentColors);
|
||||
}
|
||||
|
||||
|
||||
public String getCube() {
|
||||
return cube;
|
||||
}
|
||||
|
||||
|
||||
public void setCube(final String cube) {
|
||||
this.cube=cube;
|
||||
}
|
||||
|
||||
|
||||
public MagicAI[] getPlayerAIs() {
|
||||
final MagicAI playerAI = MagicAIImpl.getAI(ai).getAI();
|
||||
return new MagicAI[]{playerAI, playerAI};
|
||||
}
|
||||
|
||||
|
||||
public String getAI() {
|
||||
return ai;
|
||||
}
|
||||
|
||||
|
||||
public void setAI(final String ai) {
|
||||
this.ai=ai;
|
||||
}
|
||||
|
@ -166,11 +166,11 @@ public class DuelConfig {
|
|||
cube=properties.getProperty(CUBE,cube);
|
||||
ai=properties.getProperty(AI,ai);
|
||||
}
|
||||
|
||||
|
||||
public void load() {
|
||||
load(FileIO.toProp(getConfigFile()));
|
||||
}
|
||||
|
||||
|
||||
public void save(final Properties properties) {
|
||||
properties.setProperty(AVATAR,Integer.toString(avatar));
|
||||
properties.setProperty(NAME,name);
|
||||
|
@ -182,22 +182,22 @@ public class DuelConfig {
|
|||
properties.setProperty(CUBE,cube);
|
||||
properties.setProperty(AI,ai);
|
||||
}
|
||||
|
||||
|
||||
public void save() {
|
||||
final Properties properties=new Properties();
|
||||
save(properties);
|
||||
try { //save config
|
||||
FileIO.toFile(getConfigFile(), properties, "Duel configuration");
|
||||
FileIO.toFile(getConfigFile(), properties, "Duel configuration");
|
||||
System.err.println("Saved duel config");
|
||||
} catch (final IOException ex) {
|
||||
System.err.println("ERROR! Unable to save duel config");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static File getConfigFile() {
|
||||
return new File(MagicMain.getGamePath(),CONFIG_FILENAME);
|
||||
}
|
||||
|
||||
|
||||
public static DuelConfig getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public class FileIO {
|
|||
close(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String toStr(final BufferedReader input) throws IOException {
|
||||
final StringBuilder contents = new StringBuilder();
|
||||
try {
|
||||
|
@ -55,7 +55,7 @@ public class FileIO {
|
|||
public static String toStr(final File aFile) throws IOException {
|
||||
return toStr(new FileInputStream(aFile));
|
||||
}
|
||||
|
||||
|
||||
static String toStr(final InputStream ins) throws IOException {
|
||||
return toStr(new BufferedReader(new InputStreamReader(ins)));
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ public class FileIO {
|
|||
properties = toProp(new FileInputStream(aFile));
|
||||
} catch (final IOException ex) {
|
||||
System.err.println("ERROR! Unable to load from " + aFile + ", " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
||||
public static Properties toProp(final InputStream ins) {
|
||||
final Properties properties = new Properties();
|
||||
try {
|
||||
|
@ -84,7 +84,7 @@ public class FileIO {
|
|||
|
||||
public static BufferedImage toImg(final File input, final BufferedImage def) {
|
||||
BufferedImage img = def;
|
||||
|
||||
|
||||
try {
|
||||
img = ImageIO.read(input);
|
||||
} catch (final IOException ex) {
|
||||
|
@ -92,16 +92,16 @@ public class FileIO {
|
|||
} catch (final IllegalArgumentException ex) {
|
||||
System.err.println("ERROR! Unable to read from null");
|
||||
}
|
||||
|
||||
|
||||
// no registered ImageReader able to read the file, likely file is corrupted
|
||||
if (img == null) {
|
||||
img = def;
|
||||
input.delete();
|
||||
}
|
||||
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
static BufferedImage toImg(final URL input, final BufferedImage def) {
|
||||
BufferedImage img = def;
|
||||
try {
|
||||
|
@ -113,7 +113,7 @@ public class FileIO {
|
|||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
public static BufferedImage toImg(final InputStream input, final BufferedImage def) {
|
||||
BufferedImage img = def;
|
||||
try {
|
||||
|
@ -127,7 +127,7 @@ public class FileIO {
|
|||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
public static void toFile(final File aFile, final String aContents, final boolean append) throws IOException {
|
||||
Writer output = null;
|
||||
try {
|
||||
|
@ -137,10 +137,10 @@ public class FileIO {
|
|||
close(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void toFile(
|
||||
final File aFile,
|
||||
final Properties properties,
|
||||
final File aFile,
|
||||
final Properties properties,
|
||||
final String name) throws IOException {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
|
@ -199,4 +199,4 @@ public class FileIO {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.util.Properties;
|
|||
public class GeneralConfig {
|
||||
|
||||
private static final GeneralConfig INSTANCE=new GeneralConfig();
|
||||
|
||||
|
||||
private static final String CONFIG_FILENAME="general.cfg";
|
||||
private static final String LEFT="left";
|
||||
private static final String TOP="top";
|
||||
|
@ -79,9 +79,9 @@ public class GeneralConfig {
|
|||
private boolean sound=DEFAULT_SOUND;
|
||||
private boolean confirmExit = DEFAULT_CONFIRM_EXIT;
|
||||
private boolean touchscreen = DEFAULT_TOUCHSCREEN;
|
||||
|
||||
|
||||
private GeneralConfig() {}
|
||||
|
||||
|
||||
public int getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
@ -121,51 +121,51 @@ public class GeneralConfig {
|
|||
public void setMaximized(final boolean maximized) {
|
||||
this.maximized=maximized;
|
||||
}
|
||||
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
|
||||
public void setTheme(final String theme) {
|
||||
this.theme=theme;
|
||||
}
|
||||
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
|
||||
public void setAvatar(final String avatar) {
|
||||
this.avatar=avatar;
|
||||
}
|
||||
|
||||
|
||||
public boolean isHighlightNone() {
|
||||
return "none".equals(highlight);
|
||||
}
|
||||
|
||||
|
||||
public boolean isHighlightOverlay() {
|
||||
return "overlay".equals(highlight);
|
||||
}
|
||||
|
||||
|
||||
public boolean isHighlightTheme() {
|
||||
return "theme".equals(highlight);
|
||||
}
|
||||
|
||||
|
||||
public String getHighlight() {
|
||||
return highlight;
|
||||
}
|
||||
|
||||
|
||||
public void setHighlight(final String highlight) {
|
||||
this.highlight = highlight;
|
||||
}
|
||||
|
||||
|
||||
public boolean getTextView() {
|
||||
return textView;
|
||||
}
|
||||
|
||||
|
||||
public void setTextView(final boolean textView) {
|
||||
this.textView=textView;
|
||||
}
|
||||
|
||||
|
||||
public boolean getSkipSingle() {
|
||||
return skipSingle;
|
||||
}
|
||||
|
@ -173,19 +173,19 @@ public class GeneralConfig {
|
|||
public void setSkipSingle(final boolean skipSingle) {
|
||||
this.skipSingle=skipSingle;
|
||||
}
|
||||
|
||||
|
||||
public boolean getAlwaysPass() {
|
||||
return alwaysPass;
|
||||
}
|
||||
|
||||
|
||||
public void setAlwaysPass(final boolean alwaysPass) {
|
||||
this.alwaysPass=alwaysPass;
|
||||
}
|
||||
|
||||
public boolean getSmartTarget() {
|
||||
|
||||
public boolean getSmartTarget() {
|
||||
return smartTarget;
|
||||
}
|
||||
|
||||
|
||||
public void setSmartTarget(final boolean smartTarget) {
|
||||
this.smartTarget=smartTarget;
|
||||
}
|
||||
|
@ -193,83 +193,83 @@ public class GeneralConfig {
|
|||
public int getDifficulty() {
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
|
||||
public void setDifficulty(final int difficulty) {
|
||||
this.difficulty=difficulty;
|
||||
}
|
||||
|
||||
|
||||
public int getExtraLife() {
|
||||
return extraLife;
|
||||
}
|
||||
|
||||
|
||||
public void setExtraLife(final int extraLife) {
|
||||
this.extraLife=extraLife;
|
||||
}
|
||||
|
||||
|
||||
public int getPopupDelay() {
|
||||
return popupDelay;
|
||||
}
|
||||
|
||||
|
||||
public void setPopupDelay(final int popupDelay) {
|
||||
this.popupDelay=popupDelay;
|
||||
}
|
||||
|
||||
|
||||
public int getMessageDelay() {
|
||||
return messageDelay;
|
||||
}
|
||||
|
||||
|
||||
public void setMessageDelay(final int messageDelay) {
|
||||
this.messageDelay = messageDelay;
|
||||
}
|
||||
|
||||
|
||||
public int getStrengthDifficulty() {
|
||||
return strengthDifficulty;
|
||||
}
|
||||
|
||||
|
||||
public void setStrengthDifficulty(final int strengthDifficulty) {
|
||||
this.strengthDifficulty=strengthDifficulty;
|
||||
}
|
||||
|
||||
|
||||
public int getStrengthGames() {
|
||||
return strengthGames;
|
||||
}
|
||||
|
||||
|
||||
public void setStrengthGames(final int strengthGames) {
|
||||
this.strengthGames=strengthGames;
|
||||
}
|
||||
|
||||
|
||||
public boolean isHighQuality() {
|
||||
return highQuality;
|
||||
}
|
||||
|
||||
|
||||
public void setHighQuality(final boolean highQuality) {
|
||||
this.highQuality=highQuality;
|
||||
}
|
||||
|
||||
|
||||
public boolean isSound() {
|
||||
return sound;
|
||||
}
|
||||
|
||||
|
||||
public void setSound(final boolean sound) {
|
||||
this.sound=sound;
|
||||
}
|
||||
|
||||
|
||||
public boolean isConfirmExit() {
|
||||
return confirmExit;
|
||||
}
|
||||
|
||||
public void setConfirmExit(final boolean confirmExit) {
|
||||
public void setConfirmExit(final boolean confirmExit) {
|
||||
this.confirmExit = confirmExit;
|
||||
}
|
||||
|
||||
|
||||
public boolean isTouchscreen() {
|
||||
return touchscreen;
|
||||
}
|
||||
|
||||
public void setTouchscreen(final boolean touchscreen) {
|
||||
public void setTouchscreen(final boolean touchscreen) {
|
||||
this.touchscreen = touchscreen;
|
||||
}
|
||||
|
||||
|
||||
private void load(final Properties properties) {
|
||||
left=Integer.parseInt(properties.getProperty(LEFT,""+DEFAULT_LEFT));
|
||||
top=Integer.parseInt(properties.getProperty(TOP,""+DEFAULT_TOP));
|
||||
|
@ -294,11 +294,11 @@ public class GeneralConfig {
|
|||
confirmExit = Boolean.parseBoolean(properties.getProperty(CONFIRM_EXIT,""+DEFAULT_CONFIRM_EXIT));
|
||||
touchscreen = Boolean.parseBoolean(properties.getProperty(TOUCHSCREEN,""+DEFAULT_TOUCHSCREEN));
|
||||
}
|
||||
|
||||
|
||||
public void load() {
|
||||
load(FileIO.toProp(getConfigFile()));
|
||||
}
|
||||
|
||||
|
||||
private void save(final Properties properties) {
|
||||
properties.setProperty(LEFT,String.valueOf(left));
|
||||
properties.setProperty(TOP,String.valueOf(top));
|
||||
|
@ -323,7 +323,7 @@ public class GeneralConfig {
|
|||
properties.setProperty(CONFIRM_EXIT,String.valueOf(confirmExit));
|
||||
properties.setProperty(TOUCHSCREEN,String.valueOf(touchscreen));
|
||||
}
|
||||
|
||||
|
||||
public void save() {
|
||||
final Properties properties=new Properties();
|
||||
save(properties);
|
||||
|
|
|
@ -12,17 +12,17 @@ import java.util.Map;
|
|||
* the cards directory
|
||||
*/
|
||||
public class HighQualityCardImagesProvider implements CardImagesProvider {
|
||||
|
||||
|
||||
private static final CardImagesProvider INSTANCE=new HighQualityCardImagesProvider();
|
||||
|
||||
private static final int MAX_IMAGES=100;
|
||||
private final Map<String,BufferedImage> scaledImages =
|
||||
private final Map<String,BufferedImage> scaledImages =
|
||||
new magic.data.LRUCache<String,BufferedImage>(MAX_IMAGES);
|
||||
private final Map<String,BufferedImage> origImages =
|
||||
private final Map<String,BufferedImage> origImages =
|
||||
new magic.data.LRUCache<String,BufferedImage>(MAX_IMAGES);
|
||||
|
||||
|
||||
private HighQualityCardImagesProvider() {}
|
||||
|
||||
|
||||
private static final String getFilename(
|
||||
final MagicCardDefinition cardDefinition,
|
||||
final int index) {
|
||||
|
@ -35,11 +35,11 @@ public class HighQualityCardImagesProvider implements CardImagesProvider {
|
|||
buffer.append(IMAGE_EXTENSION);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
private static BufferedImage loadCardImage(final String filename) {
|
||||
return FileIO.toImg(new File(filename), IconImages.MISSING_CARD);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage(
|
||||
final MagicCardDefinition cardDefinition,
|
||||
|
@ -56,10 +56,10 @@ public class HighQualityCardImagesProvider implements CardImagesProvider {
|
|||
}
|
||||
|
||||
if (!scaledImages.containsKey(filename)) {
|
||||
scaledImages.put(filename,
|
||||
scaledImages.put(filename,
|
||||
magic.GraphicsUtilities.scale(
|
||||
origImages.get(filename),
|
||||
CARD_WIDTH,
|
||||
origImages.get(filename),
|
||||
CARD_WIDTH,
|
||||
CARD_HEIGHT
|
||||
)
|
||||
);
|
||||
|
@ -67,12 +67,12 @@ public class HighQualityCardImagesProvider implements CardImagesProvider {
|
|||
|
||||
return orig ? origImages.get(filename) : scaledImages.get(filename);
|
||||
}
|
||||
|
||||
|
||||
public static CardImagesProvider getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
|
||||
public void clearCache() {
|
||||
origImages.clear();
|
||||
scaledImages.clear();
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@ import java.io.IOException;
|
|||
import java.util.Properties;
|
||||
|
||||
public class History {
|
||||
|
||||
|
||||
public static final String HISTORY_FOLDER = "history";
|
||||
private static final String HISTORY_EXTENSION = ".hist";
|
||||
|
||||
|
||||
private static final String GAMES_PLAYED = "gamesPlayed";
|
||||
private static final String GAMES_WON = "gamesWon";
|
||||
private static final String DUELS_PLAYED = "duelsPlayed";
|
||||
|
@ -28,7 +28,7 @@ public class History {
|
|||
private static final String COLOR_GREEN = "colorGreen";
|
||||
private static final String COLOR_RED = "colorRed";
|
||||
private static final String COLOR_WHITE = "colorWhite";
|
||||
|
||||
|
||||
private static int gamesPlayed;
|
||||
private static int gamesWon;
|
||||
private static int turnsPlayed;
|
||||
|
@ -41,25 +41,25 @@ public class History {
|
|||
private static int colorGreen;
|
||||
private static int colorRed;
|
||||
private static int colorWhite;
|
||||
|
||||
|
||||
private static String name = "";
|
||||
private final MagicDuel duel;
|
||||
|
||||
|
||||
public History(final MagicDuel duel) {
|
||||
this.duel = duel;
|
||||
}
|
||||
|
||||
|
||||
private static String getHistoryFolder() {
|
||||
return MagicMain.getGamePath() + File.separator + HISTORY_FOLDER;
|
||||
}
|
||||
|
||||
|
||||
public static void createHistoryFolder() {
|
||||
final File HistoryFolderFile = new File(getHistoryFolder());
|
||||
if (!HistoryFolderFile.exists() && !HistoryFolderFile.mkdir()) {
|
||||
System.err.println("WARNING. Unable to create " + getHistoryFolder());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update(final boolean won,final MagicGame game,final DuelConfig configuration) {
|
||||
gamesPlayed++;
|
||||
if (won) {
|
||||
|
@ -107,7 +107,7 @@ public class History {
|
|||
}
|
||||
saveHistory(name + HISTORY_EXTENSION);
|
||||
}
|
||||
|
||||
|
||||
private void load(final Properties properties) {
|
||||
gamesPlayed = Integer.parseInt(properties.getProperty(GAMES_PLAYED,"0"));
|
||||
gamesWon = Integer.parseInt(properties.getProperty(GAMES_WON,"0"));
|
||||
|
@ -122,13 +122,13 @@ public class History {
|
|||
colorRed = Integer.parseInt(properties.getProperty(COLOR_RED,"0"));
|
||||
colorWhite = Integer.parseInt(properties.getProperty(COLOR_WHITE,"0"));
|
||||
}
|
||||
|
||||
|
||||
public void loadHistory(final String name) {
|
||||
setName(name);
|
||||
load(FileIO.toProp(new File(getHistoryFolder() +
|
||||
File.separator + name + HISTORY_EXTENSION)));
|
||||
}
|
||||
|
||||
|
||||
private void save(final Properties properties) {
|
||||
properties.setProperty(GAMES_PLAYED,String.valueOf(gamesPlayed));
|
||||
properties.setProperty(GAMES_WON,String.valueOf(gamesWon));
|
||||
|
@ -143,7 +143,7 @@ public class History {
|
|||
properties.setProperty(COLOR_RED,String.valueOf(colorRed));
|
||||
properties.setProperty(COLOR_WHITE,String.valueOf(colorWhite));
|
||||
}
|
||||
|
||||
|
||||
private void saveHistory(final String filename) {
|
||||
final Properties properties = new Properties();
|
||||
save(properties);
|
||||
|
@ -160,11 +160,11 @@ public class History {
|
|||
private static void setName(final String aName) {
|
||||
History.name = aName;
|
||||
}
|
||||
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public static int getGamesPlayed() {
|
||||
return gamesPlayed;
|
||||
}
|
||||
|
@ -176,19 +176,19 @@ public class History {
|
|||
public static int getTurnsPlayed() {
|
||||
return turnsPlayed;
|
||||
}
|
||||
|
||||
|
||||
public static int getDuelsPlayed() {
|
||||
return duelsPlayed;
|
||||
}
|
||||
|
||||
|
||||
public static int getDuelsWon() {
|
||||
return duelsWon;
|
||||
}
|
||||
|
||||
|
||||
public static int getLifeLeftPlayer() {
|
||||
return lifeLeftPlayer;
|
||||
}
|
||||
|
||||
|
||||
public static int getLifeLeftAI() {
|
||||
return lifeLeftAI;
|
||||
}
|
||||
|
@ -196,19 +196,19 @@ public class History {
|
|||
public static int getColorBlack() {
|
||||
return colorBlack;
|
||||
}
|
||||
|
||||
|
||||
public static int getColorBlue() {
|
||||
return colorBlue;
|
||||
}
|
||||
|
||||
|
||||
public static int getColorGreen() {
|
||||
return colorGreen;
|
||||
}
|
||||
|
||||
|
||||
public static int getColorRed() {
|
||||
return colorRed;
|
||||
}
|
||||
|
||||
|
||||
public static int getColorWhite() {
|
||||
return colorWhite;
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@ public class IconImages {
|
|||
public static final BufferedImage MISSING2=loadImage("icons/missing2.png");
|
||||
public static final BufferedImage MISSING_CARD=loadImage("icons/missing_card.png");
|
||||
public static final ImageIcon MISSING_ICON=loadIcon("missing2.png");
|
||||
|
||||
|
||||
private static final BufferedImage MANA = loadImage("icons/Mana.png");
|
||||
public static final BufferedImage LOGO=loadImage("textures/logo.jpg");
|
||||
public static final BufferedImage WIZARD=loadImage("icons/wizard.png");
|
||||
public static final BufferedImage WOOD=loadImage("textures/wood.jpg");
|
||||
public static final BufferedImage MARBLE=loadImage("textures/marble.jpg");
|
||||
public static final BufferedImage GRANITE=loadImage("textures/granite.jpg");
|
||||
public static final BufferedImage GRANITE2=loadImage("textures/granite2.jpg");
|
||||
public static final BufferedImage GRANITE2=loadImage("textures/granite2.jpg");
|
||||
public static final BufferedImage OPAL=loadImage("textures/opal.jpg");
|
||||
public static final BufferedImage OPAL2=loadImage("textures/opal2.jpg");
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class IconImages {
|
|||
public static final ImageIcon DAMAGE=loadIcon("damage.gif");
|
||||
public static final ImageIcon COMBAT=loadIcon("combat.gif");
|
||||
public static final ImageIcon ATTACK=loadIcon("attack.gif");
|
||||
public static final ImageIcon BLOCK=loadIcon("block.gif");
|
||||
public static final ImageIcon BLOCK=loadIcon("block.gif");
|
||||
public static final ImageIcon BLOCKED=loadIcon("blocked.gif");
|
||||
public static final ImageIcon MESSAGE=loadIcon("message.png");
|
||||
public static final ImageIcon PROGRESS=loadIcon("progress.png");
|
||||
|
@ -97,7 +97,7 @@ public class IconImages {
|
|||
public static final ImageIcon DELAY=loadIcon("delay.png");
|
||||
public static final ImageIcon PICTURE=loadIcon("picture.png");
|
||||
public static final ImageIcon AVATAR=loadIcon("avatar.gif");
|
||||
|
||||
|
||||
public static final ImageIcon FLYING=loadIcon("flying.png");
|
||||
public static final ImageIcon TRAMPLE=loadIcon("trample.png");
|
||||
public static final ImageIcon STRIKE=loadIcon("strike.png");
|
||||
|
@ -110,12 +110,12 @@ public class IconImages {
|
|||
public static final ImageIcon BLUE=loadSymbolIcon(25, true);
|
||||
public static final ImageIcon BLACK=loadSymbolIcon(26, true);
|
||||
public static final ImageIcon RED=loadSymbolIcon(27, true);
|
||||
public static final ImageIcon GREEN=loadSymbolIcon(28, true);
|
||||
public static final ImageIcon GREEN=loadSymbolIcon(28, true);
|
||||
public static final ImageIcon COST_WHITE=loadSymbolIcon(24, false);
|
||||
public static final ImageIcon COST_BLUE=loadSymbolIcon(25, false);
|
||||
public static final ImageIcon COST_BLACK=loadSymbolIcon(26, false);
|
||||
public static final ImageIcon COST_RED=loadSymbolIcon(27, false);
|
||||
public static final ImageIcon COST_GREEN=loadSymbolIcon(28, false);
|
||||
public static final ImageIcon COST_GREEN=loadSymbolIcon(28, false);
|
||||
public static final ImageIcon COST_WHITE_BLUE=loadSymbolIcon(30, false);
|
||||
public static final ImageIcon COST_WHITE_BLACK=loadSymbolIcon(31, false);
|
||||
public static final ImageIcon COST_BLUE_BLACK=loadSymbolIcon(32, false);
|
||||
|
@ -145,11 +145,11 @@ public class IconImages {
|
|||
public static final ImageIcon COST_SIXTEEN=loadSymbolIcon(16, false);
|
||||
// public static final ImageIcon COST_NINE_OR_MORE=loadIcon("nineplus.gif");
|
||||
public static final ImageIcon COST_X=loadSymbolIcon(21, false);
|
||||
|
||||
|
||||
private static BufferedImage loadImage(final String name) {
|
||||
return FileIO.toImg(IconImages.class.getResource(name), MISSING2);
|
||||
}
|
||||
|
||||
|
||||
private static ImageIcon loadIcon(final String name) {
|
||||
final BufferedImage image=loadImage("icons/"+name);
|
||||
return new ImageIcon(image);
|
||||
|
@ -171,7 +171,7 @@ public class IconImages {
|
|||
return new ImageIcon(magic.GraphicsUtilities.scale(subimage,icoW,icoH));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static ImageIcon loadAnimatedIcon(final String name) {
|
||||
final byte[] data = new byte[1<<16];
|
||||
int size = 0;
|
||||
|
|
|
@ -10,13 +10,13 @@ public class KeywordDefinitions {
|
|||
private static final KeywordDefinitions INSTANCE=new KeywordDefinitions();
|
||||
|
||||
private static final String KEYWORDS_FILENAME="keywords.txt";
|
||||
|
||||
|
||||
private final List<KeywordDefinition> keywordDefinitions;
|
||||
|
||||
|
||||
private KeywordDefinitions() {
|
||||
keywordDefinitions=new ArrayList<KeywordDefinition>();
|
||||
}
|
||||
|
||||
|
||||
public void loadKeywordDefinitions() {
|
||||
keywordDefinitions.clear();
|
||||
String content = null;
|
||||
|
@ -44,15 +44,15 @@ public class KeywordDefinitions {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<KeywordDefinition> getKeywordDefinitions() {
|
||||
return keywordDefinitions;
|
||||
}
|
||||
|
||||
|
||||
public static KeywordDefinitions getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public static class KeywordDefinition {
|
||||
public String name;
|
||||
public String description="";
|
||||
|
|
|
@ -4,16 +4,16 @@ File: OSXAdapter.java
|
|||
|
||||
Abstract: Hooks existing preferences/about/quit functionality from an
|
||||
existing Java app into handlers for the Mac OS X application menu.
|
||||
Uses a Proxy object to dynamically implement the
|
||||
Uses a Proxy object to dynamically implement the
|
||||
com.apple.eawt.ApplicationListener interface and register it with the
|
||||
com.apple.eawt.Application object. This allows the complete project
|
||||
to be both built and run on any platform without any stubs or
|
||||
placeholders. Useful for developers looking to implement Mac OS X
|
||||
to be both built and run on any platform without any stubs or
|
||||
placeholders. Useful for developers looking to implement Mac OS X
|
||||
features while supporting multiple platforms with minimal impact.
|
||||
|
||||
|
||||
Version: 2.0
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by
|
||||
Apple Inc. ("Apple") in consideration of your agreement to the
|
||||
following terms, and your use, installation, modification or
|
||||
redistribution of this Apple software constitutes acceptance of these
|
||||
|
@ -27,8 +27,8 @@ license, under Apple's copyrights in this original Apple software (the
|
|||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc.
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc.
|
||||
may be used to endorse or promote products derived from the Apple
|
||||
Software without specific prior written permission from Apple. Except
|
||||
as expressly stated in this notice, no other rights or licenses, express
|
||||
|
@ -68,7 +68,7 @@ public class OSXAdapter implements InvocationHandler {
|
|||
protected Object targetObject;
|
||||
protected Method targetMethod;
|
||||
protected String proxySignature;
|
||||
|
||||
|
||||
static Object macOSXApplication;
|
||||
|
||||
// Pass this method an Object and Method equipped to perform application shutdown logic
|
||||
|
@ -76,7 +76,7 @@ public class OSXAdapter implements InvocationHandler {
|
|||
public static void setQuitHandler(final Object target, final Method quitHandler) {
|
||||
setHandler(new OSXAdapter("handleQuit", target, quitHandler));
|
||||
}
|
||||
|
||||
|
||||
// Pass this method an Object and Method equipped to display application info
|
||||
// They will be called when the About menu item is selected from the application menu
|
||||
public static void setAboutHandler(final Object target, final Method aboutHandler) {
|
||||
|
@ -94,7 +94,7 @@ public class OSXAdapter implements InvocationHandler {
|
|||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pass this method an Object and a Method equipped to display application options
|
||||
// They will be called when the Preferences menu item is selected from the application menu
|
||||
public static void setPreferencesHandler(final Object target, final Method prefsHandler) {
|
||||
|
@ -112,9 +112,9 @@ public class OSXAdapter implements InvocationHandler {
|
|||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pass this method an Object and a Method equipped to handle document events from the Finder
|
||||
// Documents are registered with the Finder via the CFBundleDocumentTypes dictionary in the
|
||||
// Documents are registered with the Finder via the CFBundleDocumentTypes dictionary in the
|
||||
// application bundle's Info.plist
|
||||
public static void setFileHandler(final Object target, final Method fileHandler) {
|
||||
setHandler(new OSXAdapter("handleOpenFile", target, fileHandler) {
|
||||
|
@ -127,14 +127,14 @@ public class OSXAdapter implements InvocationHandler {
|
|||
final String filename = (String) getFilenameMethod.invoke(appleEvent, (Object[])null);
|
||||
this.targetMethod.invoke(this.targetObject, filename);
|
||||
} catch (Exception ex) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// setHandler creates a Proxy object from the passed OSXAdapter and adds it as an ApplicationListener
|
||||
public static void setHandler(final OSXAdapter adapter) {
|
||||
try {
|
||||
|
@ -162,8 +162,8 @@ public class OSXAdapter implements InvocationHandler {
|
|||
this.targetObject = target;
|
||||
this.targetMethod = handler;
|
||||
}
|
||||
|
||||
// Override this method to perform any operations on the event
|
||||
|
||||
// Override this method to perform any operations on the event
|
||||
// that comes with the various callbacks
|
||||
// See setFileHandler above for an example
|
||||
public boolean callTarget(final Object appleEvent) throws InvocationTargetException, IllegalAccessException {
|
||||
|
@ -173,7 +173,7 @@ public class OSXAdapter implements InvocationHandler {
|
|||
}
|
||||
return Boolean.valueOf(result.toString()).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
// InvocationHandler implementation
|
||||
// This is the entry point for our proxy object; it is called every time an ApplicationListener method is invoked
|
||||
public Object invoke (final Object proxy, final Method method, final Object[] args) throws Throwable {
|
||||
|
@ -184,13 +184,13 @@ public class OSXAdapter implements InvocationHandler {
|
|||
// All of the ApplicationListener methods are void; return null regardless of what happens
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Compare the method that was called to the intended method when the OSXAdapter instance was created
|
||||
// (e.g. handleAbout, handleQuit, handleOpenFile, etc.)
|
||||
protected boolean isCorrectMethod(final Method method, final Object[] args) {
|
||||
return (targetMethod != null && proxySignature.equals(method.getName()) && args.length == 1);
|
||||
}
|
||||
|
||||
|
||||
// It is important to mark the ApplicationEvent as handled and cancel the default behavior
|
||||
// This method checks for a boolean result from the proxy method and sets the event accordingly
|
||||
protected void setApplicationEventHandled(final Object event, final boolean handled) {
|
||||
|
|
|
@ -20,12 +20,12 @@ public class SoundEffects implements LineListener {
|
|||
public static final String TURN_SOUND="turn.au";
|
||||
public static final String RESOLVE_SOUND="resolve.au";
|
||||
public static final String COMBAT_SOUND="combat.au";
|
||||
|
||||
|
||||
private static final File SOUNDS_PATH=new File(MagicMain.getGamePath(),"sounds");
|
||||
private static final SoundEffects INSTANCE=new SoundEffects();
|
||||
|
||||
|
||||
private SoundEffects() {}
|
||||
|
||||
|
||||
public static void playClip(final String name) {
|
||||
if (GeneralConfig.getInstance().isSound()) {
|
||||
Clip clip = null;
|
||||
|
@ -60,4 +60,4 @@ public class SoundEffects implements LineListener {
|
|||
event.getLine().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
public class TextImages {
|
||||
|
||||
|
||||
private static final Map<String,ImageIcon> TEXT_ICONS=new HashMap<String,ImageIcon>();
|
||||
|
||||
|
||||
static {
|
||||
TEXT_ICONS.put("{0}",IconImages.COST_ZERO);
|
||||
TEXT_ICONS.put("{1}",IconImages.COST_ONE);
|
||||
|
@ -27,7 +27,7 @@ public class TextImages {
|
|||
TEXT_ICONS.put("{15}",IconImages.COST_FIFTEEN);
|
||||
TEXT_ICONS.put("{16}",IconImages.COST_SIXTEEN);
|
||||
TEXT_ICONS.put("{X}",IconImages.COST_X);
|
||||
|
||||
|
||||
TEXT_ICONS.put("{B}",IconImages.COST_BLACK);
|
||||
TEXT_ICONS.put("{U}",IconImages.COST_BLUE);
|
||||
TEXT_ICONS.put("{G}",IconImages.COST_GREEN);
|
||||
|
@ -63,7 +63,7 @@ public class TextImages {
|
|||
TEXT_ICONS.put("{br}",IconImages.BRIBECOUNTER);
|
||||
TEXT_ICONS.put("{L}",IconImages.LOSE);
|
||||
}
|
||||
|
||||
|
||||
public static ImageIcon getIcon(final String text) {
|
||||
if (!TEXT_ICONS.containsKey(text)) {
|
||||
throw new RuntimeException("No corresponding icon for " + text);
|
||||
|
|
|
@ -13,7 +13,7 @@ public class TokenCardDefinitions {
|
|||
public static Collection<MagicCardDefinition> getAll() {
|
||||
return tokensMap.values();
|
||||
}
|
||||
|
||||
|
||||
public static MagicCardDefinition get(final String name) {
|
||||
if (tokensMap.containsKey(name)) {
|
||||
return tokensMap.get(name);
|
||||
|
@ -21,7 +21,7 @@ public class TokenCardDefinitions {
|
|||
throw new RuntimeException("token " + name + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void add(final MagicCardDefinition token) {
|
||||
tokensMap.put(token.getFullName(), token);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.net.URI;
|
|||
import java.net.URISyntaxException;
|
||||
|
||||
public class URLUtils {
|
||||
|
||||
|
||||
public static void openURL(final String url) {
|
||||
try {
|
||||
Desktop desktop = null;
|
||||
|
|
|
@ -11,15 +11,15 @@ import java.io.OutputStream;
|
|||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
|
||||
public abstract class WebDownloader {
|
||||
public abstract class WebDownloader {
|
||||
public abstract void download(final Proxy proxy);
|
||||
|
||||
|
||||
public abstract String getFilename();
|
||||
|
||||
|
||||
public abstract File getFile();
|
||||
|
||||
public abstract boolean exists();
|
||||
|
||||
|
||||
public static void downloadToFile(final Proxy proxy, final URL url, final File file) {
|
||||
OutputStream outputStream = null;
|
||||
InputStream inputStream = null;
|
||||
|
@ -47,17 +47,17 @@ public abstract class WebDownloader {
|
|||
magic.data.FileIO.close(outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getHTML(final Proxy proxy, final URL url) {
|
||||
InputStream inputStream = null;
|
||||
BufferedReader dataStream = null;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
|
||||
|
||||
try {
|
||||
inputStream = url.openConnection(proxy).getInputStream();
|
||||
dataStream = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
|
||||
while( (line = dataStream.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
|
@ -70,7 +70,7 @@ public abstract class WebDownloader {
|
|||
magic.data.FileIO.close(inputStream);
|
||||
magic.data.FileIO.close(dataStream);
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,23 +14,23 @@ import java.util.Random;
|
|||
public class Ability_Mono_DeckGenerator extends DefaultDeckGenerator {
|
||||
|
||||
private static final int MIN_NUM_CARDS_WITH_SUBTYPE = 30;
|
||||
|
||||
|
||||
private static final Random randGen = new Random();
|
||||
// all possible tribes - calculated once
|
||||
private static final ArrayList<MagicAbility> possibleAbilities = new ArrayList<MagicAbility>();
|
||||
private static final ArrayList<ArrayList<String>> possibleColors = new ArrayList<ArrayList<String>>();
|
||||
|
||||
|
||||
// random tribe from all possible for each instance
|
||||
private final MagicAbility ability;
|
||||
private final String colorText;
|
||||
|
||||
|
||||
public Ability_Mono_DeckGenerator() {
|
||||
super(null);
|
||||
|
||||
|
||||
if(!hasChoice()) {
|
||||
getPossibleTribes();
|
||||
}
|
||||
|
||||
|
||||
if(hasChoice()) {
|
||||
final int i = randGen.nextInt(possibleAbilities.size());
|
||||
ability = possibleAbilities.get(i);
|
||||
|
@ -39,14 +39,14 @@ public class Ability_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
ability = null;
|
||||
colorText = "";
|
||||
}
|
||||
|
||||
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
private boolean hasChoice() {
|
||||
return possibleAbilities.size() > 0 && possibleColors.size() == possibleAbilities.size();
|
||||
}
|
||||
|
||||
|
||||
private void getPossibleTribes() {
|
||||
for(final MagicAbility ab : MagicAbility.CORE) {
|
||||
final HashMap<MagicColor, Integer> countColors = new HashMap<MagicColor, Integer>();
|
||||
|
@ -55,7 +55,7 @@ public class Ability_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
countColors.put(MagicColor.Green, 0);
|
||||
countColors.put(MagicColor.Red, 0);
|
||||
countColors.put(MagicColor.Blue, 0);
|
||||
|
||||
|
||||
// count colors
|
||||
for(final MagicCardDefinition card : CardDefinitions.getCards()) {
|
||||
if (card.hasAbility(ab)) {
|
||||
|
@ -67,37 +67,37 @@ public class Ability_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final ArrayList<String> choiceColors = getPossibleColors(countColors);
|
||||
|
||||
|
||||
if(choiceColors.size() > 0) {
|
||||
possibleAbilities.add(ab);
|
||||
possibleColors.add(choiceColors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ArrayList<String> getPossibleColors(final HashMap<MagicColor, Integer> countColors) {
|
||||
// monocolor
|
||||
final ArrayList<String> a = new ArrayList<String>();
|
||||
|
||||
|
||||
for(final MagicColor c : countColors.keySet()) {
|
||||
if(countColors.get(c).intValue() > MIN_NUM_CARDS_WITH_SUBTYPE) {
|
||||
a.add("" + c.getSymbol());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
if(hasChoice()) {
|
||||
return !card.isCreature() || card.hasAbility(ability);
|
||||
|
@ -105,11 +105,11 @@ public class Ability_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxCost() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,16 +12,16 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public class DefaultDeckGenerator {
|
||||
|
||||
|
||||
private final List<MagicCardDefinition> spellCards = new ArrayList<MagicCardDefinition>();
|
||||
private final List<MagicCardDefinition> landCards = new ArrayList<MagicCardDefinition>();
|
||||
|
||||
|
||||
private MagicCubeDefinition cubeDefinition;
|
||||
|
||||
|
||||
public DefaultDeckGenerator(final MagicCubeDefinition cubeDefinition) {
|
||||
this.cubeDefinition = cubeDefinition;
|
||||
}
|
||||
|
||||
|
||||
public void setCubeDefinition(final MagicCubeDefinition cube) {
|
||||
cubeDefinition = cube;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class DefaultDeckGenerator {
|
|||
if(cubeDefinition == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
spellCards.clear();
|
||||
for (int rarity = getMinRarity(); rarity <= getMaxRarity(); rarity++) {
|
||||
for (final MagicCardDefinition card : CardDefinitions.getSpellCards()) {
|
||||
|
@ -42,15 +42,15 @@ public class DefaultDeckGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
public int getMaxRarity() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return true;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class DefaultDeckGenerator {
|
|||
if(cubeDefinition == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
landCards.clear();
|
||||
for (final MagicCardDefinition card : CardDefinitions.getLandCards()) {
|
||||
if (cubeDefinition.containsCard(card)) {
|
||||
|
@ -69,38 +69,38 @@ public class DefaultDeckGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleLandCard(final MagicCardDefinition card) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void generateDeck(final int size, final MagicPlayerProfile profile, final MagicDeck deck) {
|
||||
setColors(profile);
|
||||
|
||||
|
||||
final MagicCondensedDeck condensedDeck = new MagicCondensedDeck();
|
||||
|
||||
genSpells();
|
||||
genLands();
|
||||
|
||||
|
||||
final int spells = (size*3)/5;
|
||||
final int lands = profile.getNrOfNonBasicLands(size-spells);
|
||||
|
||||
final int lands = profile.getNrOfNonBasicLands(size-spells);
|
||||
|
||||
final int maxCreatures = (spells*2)/3;
|
||||
final int maxNonlandNoncreature = spells - maxCreatures;
|
||||
final int maxColorless = spells/6;
|
||||
final int maxHigh = spells/6;
|
||||
final int maxOther = (spells-maxHigh)/2;
|
||||
final int[] maxCost = {maxOther,maxOther+1,maxHigh};
|
||||
|
||||
|
||||
int countCreatures = 0;
|
||||
int countColorless = 0;
|
||||
int countNonlandNoncreature = 0;
|
||||
final int[] countCost = new int[3];
|
||||
|
||||
|
||||
addRequiredSpells(condensedDeck);
|
||||
|
||||
|
||||
// count required cards added
|
||||
for(final MagicCardDefinition card : condensedDeck.toMagicDeck()) {
|
||||
if(card.isCreature()) {
|
||||
|
@ -108,41 +108,41 @@ public class DefaultDeckGenerator {
|
|||
} else if(!card.isLand()) {
|
||||
countNonlandNoncreature++;
|
||||
}
|
||||
|
||||
|
||||
if(card.isColorless()) {
|
||||
countColorless++;
|
||||
}
|
||||
|
||||
|
||||
countCost[card.getCostBucket()]++;
|
||||
}
|
||||
|
||||
|
||||
// Add spells to deck.
|
||||
while (condensedDeck.getNumCards() < spells && spellCards.size() > 0) {
|
||||
final int index=MagicRandom.nextInt(spellCards.size());
|
||||
final MagicCardDefinition cardDefinition=spellCards.get(index);
|
||||
spellCards.remove(index);
|
||||
|
||||
|
||||
if (cardDefinition.isPlayable(profile)) {
|
||||
final boolean creature = cardDefinition.isCreature();
|
||||
|
||||
|
||||
if(creature && countCreatures >= maxCreatures) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!creature && countNonlandNoncreature >= maxNonlandNoncreature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final boolean colorless = cardDefinition.isColorless();
|
||||
if (!ignoreMaxColorless() && colorless && countColorless >= maxColorless) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final int bucket = cardDefinition.getCostBucket();
|
||||
if (!ignoreMaxCost() && countCost[bucket] >= maxCost[bucket]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if(condensedDeck.addCard(cardDefinition, false)) {
|
||||
countCost[bucket]++;
|
||||
if(creature) {
|
||||
|
@ -154,29 +154,29 @@ public class DefaultDeckGenerator {
|
|||
countColorless++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (spellCards.size() == 0) {
|
||||
genSpells();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add non basic lands to deck.
|
||||
addRequiredLands(condensedDeck);
|
||||
|
||||
|
||||
while (condensedDeck.getNumCards() < spells+lands && landCards.size() > 0) {
|
||||
final int index=MagicRandom.nextInt(landCards.size());
|
||||
final MagicCardDefinition cardDefinition=landCards.get(index);
|
||||
landCards.remove(index);
|
||||
|
||||
|
||||
if (cardDefinition.isPlayable(profile)) {
|
||||
condensedDeck.addCard(cardDefinition, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
deck.setContent(condensedDeck.toMagicDeck());
|
||||
}
|
||||
|
||||
|
||||
protected void addRequiredCards(final MagicCondensedDeck deck, final String[] cards) {
|
||||
for(final String name : cards) {
|
||||
final MagicCardDefinition cardDef = CardDefinitions.getCard(name);
|
||||
|
@ -187,17 +187,17 @@ public class DefaultDeckGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) { }
|
||||
|
||||
|
||||
public void addRequiredLands(final MagicCondensedDeck deck) { }
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) { }
|
||||
|
||||
|
||||
public boolean ignoreMaxColorless() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxCost() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -10,45 +10,45 @@ public class Elf_Horde_DeckGenerator extends DefaultDeckGenerator {
|
|||
|
||||
private static final String colorText = "g";
|
||||
private static final String[] cards = {
|
||||
"Joraga Warcaller",
|
||||
"Joraga Warcaller",
|
||||
"Elvish Champion",
|
||||
"Elvish Champion",
|
||||
"Imperious Perfect",
|
||||
"Imperious Perfect",
|
||||
"Imperious Perfect",
|
||||
"Imperious Perfect",
|
||||
"Ezuri, Renegade Leader",
|
||||
"Llanowar Elves",
|
||||
"Llanowar Elves",
|
||||
"Joraga Warcaller",
|
||||
"Joraga Warcaller",
|
||||
"Elvish Champion",
|
||||
"Elvish Champion",
|
||||
"Imperious Perfect",
|
||||
"Imperious Perfect",
|
||||
"Imperious Perfect",
|
||||
"Imperious Perfect",
|
||||
"Ezuri, Renegade Leader",
|
||||
"Llanowar Elves",
|
||||
"Llanowar Elves",
|
||||
"Llanowar Elves"
|
||||
};
|
||||
|
||||
|
||||
public Elf_Horde_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasSubType(MagicSubType.Elf);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, cards);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxCost() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class Fairy_Horde_DeckGenerator extends DefaultDeckGenerator {
|
|||
"Mistbind Clique",
|
||||
"Mistbind Clique"
|
||||
};
|
||||
|
||||
|
||||
private static final String[] lands = {
|
||||
"Mutavault",
|
||||
"Mutavault",
|
||||
|
@ -33,36 +33,36 @@ public class Fairy_Horde_DeckGenerator extends DefaultDeckGenerator {
|
|||
"Watery Grave",
|
||||
"Watery Grave"
|
||||
};
|
||||
|
||||
|
||||
public Fairy_Horde_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasSubType(MagicSubType.Faerie);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, spells);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredLands(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, lands);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxCost() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10,44 +10,44 @@ public class Human_Law_DeckGenerator extends DefaultDeckGenerator {
|
|||
|
||||
private static final String colorText = "w";
|
||||
private static final String[] cards = {
|
||||
"Champion of the Parish",
|
||||
"Champion of the Parish",
|
||||
"Champion of the Parish",
|
||||
"Elite Vanguard",
|
||||
"Gideon's Lawkeeper",
|
||||
"Hero of Bladehold",
|
||||
"Hero of Bladehold",
|
||||
"Hero of Bladehold",
|
||||
"Mirran Crusader",
|
||||
"Mirran Crusader",
|
||||
"Angelic Destiny",
|
||||
"Angelic Destiny",
|
||||
"Honor of the Pure",
|
||||
"Honor of the Pure",
|
||||
"Champion of the Parish",
|
||||
"Champion of the Parish",
|
||||
"Champion of the Parish",
|
||||
"Elite Vanguard",
|
||||
"Gideon's Lawkeeper",
|
||||
"Hero of Bladehold",
|
||||
"Hero of Bladehold",
|
||||
"Hero of Bladehold",
|
||||
"Mirran Crusader",
|
||||
"Mirran Crusader",
|
||||
"Angelic Destiny",
|
||||
"Angelic Destiny",
|
||||
"Honor of the Pure",
|
||||
"Honor of the Pure",
|
||||
"Day of Judgment"
|
||||
};
|
||||
|
||||
|
||||
public Human_Law_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasSubType(MagicSubType.Human);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, cards);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class Saint___Hero_DeckGenerator extends DefaultDeckGenerator {
|
|||
"Oblivion Ring",
|
||||
"Sword of Feast and Famine"
|
||||
};
|
||||
|
||||
|
||||
private static final String[] lands = {
|
||||
"Glacial Fortress",
|
||||
"Glacial Fortress",
|
||||
|
@ -34,28 +34,28 @@ public class Saint___Hero_DeckGenerator extends DefaultDeckGenerator {
|
|||
"Seachrome Coast",
|
||||
"Seachrome Coast"
|
||||
};
|
||||
|
||||
|
||||
public Saint___Hero_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, spells);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredLands(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, lands);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
|
|
@ -40,32 +40,32 @@ public class Token_Madness_DeckGenerator extends DefaultDeckGenerator {
|
|||
"Sunpetal Grove",
|
||||
"Sunpetal Grove"
|
||||
};
|
||||
|
||||
|
||||
public Token_Madness_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasText("token");
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, spells);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredLands(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, lands);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
|
|
@ -14,23 +14,23 @@ import java.util.Random;
|
|||
public class Tribal_Mono_DeckGenerator extends DefaultDeckGenerator {
|
||||
|
||||
private static final int MIN_NUM_CARDS_WITH_SUBTYPE = 30;
|
||||
|
||||
|
||||
private static final Random randGen = new Random();
|
||||
// all possible tribes - calculated once
|
||||
private static final ArrayList<MagicSubType> possibleTribes = new ArrayList<MagicSubType>();
|
||||
private static final ArrayList<ArrayList<String>> possibleColors = new ArrayList<ArrayList<String>>();
|
||||
|
||||
|
||||
// random tribe from all possible for each instance
|
||||
private final MagicSubType tribe;
|
||||
private final String colorText;
|
||||
|
||||
|
||||
public Tribal_Mono_DeckGenerator() {
|
||||
super(null);
|
||||
|
||||
|
||||
if(!hasChoice()) {
|
||||
getPossibleTribes();
|
||||
}
|
||||
|
||||
|
||||
if(hasChoice()) {
|
||||
final int i = randGen.nextInt(possibleTribes.size());
|
||||
tribe = possibleTribes.get(i);
|
||||
|
@ -39,14 +39,14 @@ public class Tribal_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
tribe = null;
|
||||
colorText = "";
|
||||
}
|
||||
|
||||
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
private boolean hasChoice() {
|
||||
return possibleTribes.size() > 0 && possibleColors.size() == possibleTribes.size();
|
||||
}
|
||||
|
||||
|
||||
private void getPossibleTribes() {
|
||||
for(final MagicSubType s : MagicSubType.ALL_CREATURES) {
|
||||
final HashMap<MagicColor, Integer> countColors = new HashMap<MagicColor, Integer>();
|
||||
|
@ -55,12 +55,12 @@ public class Tribal_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
countColors.put(MagicColor.Green, new Integer(0));
|
||||
countColors.put(MagicColor.Red, new Integer(0));
|
||||
countColors.put(MagicColor.Blue, new Integer(0));
|
||||
|
||||
|
||||
// count colors
|
||||
for(final MagicCardDefinition card : CardDefinitions.getCards()) {
|
||||
if(card.hasSubType(s)) {
|
||||
final int colorFlags = card.getColorFlags();
|
||||
|
||||
|
||||
for(final MagicColor c : countColors.keySet()) {
|
||||
if (c.hasColor(colorFlags)) {
|
||||
countColors.put(c, new Integer(countColors.get(c).intValue() + 1));
|
||||
|
@ -68,37 +68,37 @@ public class Tribal_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final ArrayList<String> choiceColors = getPossibleColors(countColors);
|
||||
|
||||
|
||||
if(choiceColors.size() > 0) {
|
||||
possibleTribes.add(s);
|
||||
possibleColors.add(choiceColors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ArrayList<String> getPossibleColors(final HashMap<MagicColor, Integer> countColors) {
|
||||
// monocolor
|
||||
final ArrayList<String> a = new ArrayList<String>();
|
||||
|
||||
|
||||
for(final MagicColor c : countColors.keySet()) {
|
||||
if(countColors.get(c).intValue() > MIN_NUM_CARDS_WITH_SUBTYPE) {
|
||||
a.add("" + c.getSymbol());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
if(hasChoice()) {
|
||||
return !card.isCreature() || card.hasSubType(tribe);
|
||||
|
@ -106,11 +106,11 @@ public class Tribal_Mono_DeckGenerator extends DefaultDeckGenerator {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxCost() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -10,61 +10,61 @@ public class Vampire_Rage_DeckGenerator extends DefaultDeckGenerator {
|
|||
|
||||
private static final String colorText = "br";
|
||||
private static final String[] spells = {
|
||||
"Falkenrath Marauders",
|
||||
"Falkenrath Noble",
|
||||
"Markov Patrician",
|
||||
"Markov Patrician",
|
||||
"Rakish Heir",
|
||||
"Rakish Heir",
|
||||
"Rakish Heir",
|
||||
"Stromkirk Noble",
|
||||
"Stromkirk Noble",
|
||||
"Stromkirk Noble",
|
||||
"Doom Blade",
|
||||
"Go for the Throat",
|
||||
"Go for the Throat",
|
||||
"Falkenrath Marauders",
|
||||
"Falkenrath Noble",
|
||||
"Markov Patrician",
|
||||
"Markov Patrician",
|
||||
"Rakish Heir",
|
||||
"Rakish Heir",
|
||||
"Rakish Heir",
|
||||
"Stromkirk Noble",
|
||||
"Stromkirk Noble",
|
||||
"Stromkirk Noble",
|
||||
"Doom Blade",
|
||||
"Go for the Throat",
|
||||
"Go for the Throat",
|
||||
"Mask of Avacyn"
|
||||
};
|
||||
|
||||
|
||||
private static final String[] lands = {
|
||||
"Blackcleave Cliffs",
|
||||
"Blackcleave Cliffs",
|
||||
"Blackcleave Cliffs",
|
||||
"Blackcleave Cliffs",
|
||||
"Blood Crypt",
|
||||
"Blood Crypt",
|
||||
"Blood Crypt",
|
||||
"Dragonskull Summit",
|
||||
"Dragonskull Summit",
|
||||
"Dragonskull Summit",
|
||||
"Blackcleave Cliffs",
|
||||
"Blackcleave Cliffs",
|
||||
"Blackcleave Cliffs",
|
||||
"Blackcleave Cliffs",
|
||||
"Blood Crypt",
|
||||
"Blood Crypt",
|
||||
"Blood Crypt",
|
||||
"Dragonskull Summit",
|
||||
"Dragonskull Summit",
|
||||
"Dragonskull Summit",
|
||||
"Dragonskull Summit"
|
||||
};
|
||||
|
||||
|
||||
public Vampire_Rage_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasSubType(MagicSubType.Vampire);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, spells);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredLands(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, lands);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
|
|
@ -10,47 +10,47 @@ public class White_Knights_DeckGenerator extends DefaultDeckGenerator {
|
|||
|
||||
private static final String colorText = "w";
|
||||
private static final String[] cards = {
|
||||
"Knight Exemplar",
|
||||
"Knight Exemplar",
|
||||
"Knight Exemplar",
|
||||
"Knight Exemplar",
|
||||
"Day of Judgment",
|
||||
"Student of Warfare",
|
||||
"Student of Warfare",
|
||||
"Sun Titan",
|
||||
"Kinsbaile Cavalier",
|
||||
"Honor of the Pure",
|
||||
"Honor of the Pure",
|
||||
"Honor of the Pure",
|
||||
"Hero of Bladehold",
|
||||
"Knight Exemplar",
|
||||
"Knight Exemplar",
|
||||
"Knight Exemplar",
|
||||
"Knight Exemplar",
|
||||
"Day of Judgment",
|
||||
"Student of Warfare",
|
||||
"Student of Warfare",
|
||||
"Sun Titan",
|
||||
"Kinsbaile Cavalier",
|
||||
"Honor of the Pure",
|
||||
"Honor of the Pure",
|
||||
"Honor of the Pure",
|
||||
"Hero of Bladehold",
|
||||
"Hero of Bladehold"
|
||||
};
|
||||
|
||||
|
||||
public White_Knights_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasSubType(MagicSubType.Knight);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, cards);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxCost() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,11 @@ public class White_Metal_DeckGenerator extends DefaultDeckGenerator {
|
|||
"Mox Opal",
|
||||
"Leonin Relic-Warder"
|
||||
};
|
||||
|
||||
|
||||
private static final String[] lands = {
|
||||
"Inkmoth Nexus",
|
||||
"Inkmoth Nexus",
|
||||
"Inkmoth Nexus",
|
||||
"Inkmoth Nexus",
|
||||
"Inkmoth Nexus",
|
||||
"Inkmoth Nexus",
|
||||
"Inkmoth Nexus"
|
||||
};
|
||||
|
||||
|
@ -41,31 +41,31 @@ public class White_Metal_DeckGenerator extends DefaultDeckGenerator {
|
|||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.isArtifact();
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, spells);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredLands(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, lands);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
||||
|
||||
public boolean ignoreMaxColorless() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10,43 +10,43 @@ public class Zombie_Madness_DeckGenerator extends DefaultDeckGenerator {
|
|||
|
||||
private static final String colorText = "b";
|
||||
private static final String[] cards = {
|
||||
"Cemetery Reaper",
|
||||
"Cemetery Reaper",
|
||||
"Cemetery Reaper",
|
||||
"Cemetery Reaper",
|
||||
"Death Baron",
|
||||
"Death Baron",
|
||||
"Festering Goblin",
|
||||
"Festering Goblin",
|
||||
"Lord of the Undead",
|
||||
"Lord of the Undead",
|
||||
"Lord of the Undead",
|
||||
"Call to the Grave",
|
||||
"Call to the Grave",
|
||||
"Cemetery Reaper",
|
||||
"Cemetery Reaper",
|
||||
"Cemetery Reaper",
|
||||
"Cemetery Reaper",
|
||||
"Death Baron",
|
||||
"Death Baron",
|
||||
"Festering Goblin",
|
||||
"Festering Goblin",
|
||||
"Lord of the Undead",
|
||||
"Lord of the Undead",
|
||||
"Lord of the Undead",
|
||||
"Call to the Grave",
|
||||
"Call to the Grave",
|
||||
"Severed Legion"
|
||||
};
|
||||
|
||||
|
||||
public Zombie_Madness_DeckGenerator() {
|
||||
super(null);
|
||||
setCubeDefinition(CubeDefinitions.getCubeDefinition(getColorText()));
|
||||
}
|
||||
|
||||
|
||||
public String getColorText() {
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public int getMinRarity() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
public boolean acceptPossibleSpellCard(final MagicCardDefinition card) {
|
||||
return !card.isCreature() || card.hasSubType(MagicSubType.Zombie);
|
||||
}
|
||||
|
||||
|
||||
public void addRequiredSpells(final MagicCondensedDeck deck) {
|
||||
addRequiredCards(deck, cards);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final MagicPlayerProfile profile) {
|
||||
profile.setColors(getColorText());
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,10 +24,10 @@ class MagicSyntaxTree extends magic.grammar.SemanticsBase {
|
|||
|
||||
if (numRule == 0 ||
|
||||
lhs().rule().startsWith("Select") ||
|
||||
lhs().rule().endsWith("Number") ||
|
||||
lhs().rule().endsWith("Count") ||
|
||||
lhs().rule().endsWith("Duration") ||
|
||||
lhs().rule().endsWith("Keyword") ||
|
||||
lhs().rule().endsWith("Number") ||
|
||||
lhs().rule().endsWith("Count") ||
|
||||
lhs().rule().endsWith("Duration") ||
|
||||
lhs().rule().endsWith("Keyword") ||
|
||||
lhs().rule().equals("ManaCost")) {
|
||||
node.clear();
|
||||
node.text = lhs().text();
|
||||
|
|
|
@ -20,7 +20,7 @@ public class Node {
|
|||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public void show() {
|
||||
show(0);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public enum MagicAbility {
|
|||
CannotBeBlockedByFlying("can't be blocked by creatures with flying",20),
|
||||
CannotBeBlockedExceptWithFlying("can't be blocked except by creatures with flying",30),
|
||||
CannotBeBlockedExceptWithFlyingOrReach("can't be blocked except by creatures with flying or reach",25),
|
||||
CannotBeBlockedExceptBySliver("can't be blocked except by Slivers", 90),
|
||||
CannotBeBlockedExceptBySliver("can't be blocked except by Slivers", 90),
|
||||
CannotBeBlockedByHumans("can't be blocked by humans",10),
|
||||
CannotBeBlockedByBlack("can't be blocked by black creatures",10),
|
||||
CannotBeBlockedByBlue("can't be blocked by blue creatures",10),
|
||||
|
@ -142,7 +142,7 @@ public enum MagicAbility {
|
|||
Infect("infect",35),
|
||||
Soulbond("soulbond",30),
|
||||
CantActivateAbilities("can't activate abilities",-20),
|
||||
|
||||
|
||||
Undying("undying",60) {
|
||||
public void addAbilityImpl(final MagicCardDefinition card, final String arg) {
|
||||
assert arg.isEmpty() : this + " does not accept arg = " + arg;
|
||||
|
@ -171,7 +171,7 @@ public enum MagicAbility {
|
|||
|
||||
// 63 core abilities that are tracked in MagicPermanent's abilityFlags
|
||||
// see MagicAbility.CORE
|
||||
|
||||
|
||||
Changeling("changeling",10) {
|
||||
public void addAbilityImpl(final MagicCardDefinition card, final String arg) {
|
||||
assert arg.isEmpty() : this + " does not accept arg = " + arg;
|
||||
|
@ -759,7 +759,7 @@ public enum MagicAbility {
|
|||
}
|
||||
},
|
||||
None("",0);
|
||||
|
||||
|
||||
public static final Set<MagicAbility> CORE = EnumSet.range(AttacksEachTurnIfAble, Flanking);
|
||||
|
||||
public static final Set<MagicAbility> PROTECTION_FLAGS = EnumSet.of(
|
||||
|
@ -777,7 +777,7 @@ public enum MagicAbility {
|
|||
ProtectionFromWerewolves,
|
||||
ProtectionFromZombies
|
||||
);
|
||||
|
||||
|
||||
public static final Set<MagicAbility> LANDWALK_FLAGS = EnumSet.of(
|
||||
Forestwalk,
|
||||
Islandwalk,
|
||||
|
@ -785,17 +785,17 @@ public enum MagicAbility {
|
|||
PlainsWalk,
|
||||
Swampwalk
|
||||
);
|
||||
|
||||
|
||||
//public static final long EXCLUDE_MASK = Long.MAX_VALUE-Flash.getMask()-CannotBeCountered.getMask()-TotemArmor.getMask();
|
||||
|
||||
|
||||
private final String name;
|
||||
private final int score;
|
||||
|
||||
|
||||
private MagicAbility(final String aName,final int aScore) {
|
||||
name = aName;
|
||||
score = aScore;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ public enum MagicAbility {
|
|||
public void addAbilityImpl(final MagicCardDefinition card, final String arg) {
|
||||
assert arg.isEmpty() : this + " does not accept arg = " + arg;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
@ -812,7 +812,7 @@ public enum MagicAbility {
|
|||
private int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public static int getScore(final Set<MagicAbility> flags) {
|
||||
int score=0;
|
||||
for (final MagicAbility ability : flags) {
|
||||
|
@ -820,7 +820,7 @@ public enum MagicAbility {
|
|||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public static MagicAbility getAbility(final String name) {
|
||||
MagicAbility match = None;
|
||||
for (final MagicAbility ability : values()) {
|
||||
|
@ -834,7 +834,7 @@ public enum MagicAbility {
|
|||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Set<MagicAbility> getAbilities(final String[] names) {
|
||||
Set<MagicAbility> flags = EnumSet.noneOf(MagicAbility.class);
|
||||
for (final String name : names) {
|
||||
|
@ -846,7 +846,7 @@ public enum MagicAbility {
|
|||
public static Set<MagicAbility> of(final MagicAbility first, MagicAbility... rest) {
|
||||
return EnumSet.of(first, rest);
|
||||
}
|
||||
|
||||
|
||||
public static Set<MagicAbility> noneOf() {
|
||||
return EnumSet.noneOf(MagicAbility.class);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ package magic.model;
|
|||
import java.util.ArrayList;
|
||||
|
||||
public class MagicBoosterPack extends ArrayList<MagicCardDefinition> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
};
|
||||
|
||||
private static final int TOKEN_ID=-1;
|
||||
|
||||
|
||||
private final MagicCardDefinition cardDefinition;
|
||||
private final MagicPlayer owner;
|
||||
private final long id;
|
||||
private final int imageIndex;
|
||||
private boolean token;
|
||||
private boolean known=true;
|
||||
|
||||
|
||||
public MagicCard(final MagicCardDefinition aCardDefinition,final MagicPlayer aOwner,final long aId) {
|
||||
aCardDefinition.loadScript();
|
||||
cardDefinition = aCardDefinition;
|
||||
|
@ -41,7 +41,7 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
|
||||
private MagicCard(final MagicCopyMap copyMap, final MagicCard sourceCard) {
|
||||
copyMap.put(sourceCard, this);
|
||||
|
||||
|
||||
cardDefinition = sourceCard.cardDefinition;
|
||||
owner = copyMap.copy(sourceCard.owner);
|
||||
id = sourceCard.id;
|
||||
|
@ -49,12 +49,12 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
token = sourceCard.token;
|
||||
known = sourceCard.known;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicCard copy(final MagicCopyMap copyMap) {
|
||||
return new MagicCard(copyMap, this);
|
||||
return new MagicCard(copyMap, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicCard map(final MagicGame game) {
|
||||
final MagicPlayer mappedOwner=owner.map(game);
|
||||
|
@ -76,15 +76,15 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public long getStateId() {
|
||||
return getCardDefinition().getIndex();
|
||||
}
|
||||
|
||||
|
||||
public int getImageIndex() {
|
||||
return imageIndex;
|
||||
}
|
||||
|
@ -92,27 +92,27 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
public MagicCardDefinition getCardDefinition() {
|
||||
return known ? cardDefinition : MagicCardDefinition.UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayer getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
||||
private void setToken() {
|
||||
token = true;
|
||||
}
|
||||
|
||||
|
||||
public boolean isToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
public int getPower() {
|
||||
return genPowerToughness().power();
|
||||
}
|
||||
|
||||
|
||||
public int getToughness() {
|
||||
return genPowerToughness().toughness();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public MagicPowerToughness genPowerToughness() {
|
||||
return genPowerToughness(MagicPermanent.NONE);
|
||||
}
|
||||
|
@ -120,24 +120,24 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
public MagicPowerToughness genPowerToughness(final MagicPermanent perm) {
|
||||
final MagicPowerToughness pt = getCardDefinition().genPowerToughness();
|
||||
getCardDefinition().applyCDAPowerToughness(
|
||||
getGame(),
|
||||
getGame(),
|
||||
perm.isValid() ? perm.getController() : getOwner(),
|
||||
perm,
|
||||
pt
|
||||
);
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
||||
public MagicManaCost getCost() {
|
||||
return getCardDefinition().getCost();
|
||||
}
|
||||
|
||||
|
||||
public MagicEvent[] getCostEvent() {
|
||||
return getCardDefinition().getCostEvent(this);
|
||||
}
|
||||
|
||||
|
||||
public static MagicCard createTokenCard(final MagicCardDefinition cardDefinition,final MagicPlayer owner) {
|
||||
final MagicCard card=new MagicCard(cardDefinition,owner,MagicCard.TOKEN_ID);
|
||||
final MagicCard card=new MagicCard(cardDefinition,owner,MagicCard.TOKEN_ID);
|
||||
card.setToken();
|
||||
return card;
|
||||
}
|
||||
|
@ -149,16 +149,16 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
void setKnown(final boolean known) {
|
||||
this.known=known;
|
||||
}
|
||||
|
||||
|
||||
public boolean isKnown() {
|
||||
return known;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getCardDefinition().getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
|
@ -176,9 +176,9 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
|
||||
@Override
|
||||
public void setPreventDamage(final int amount) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isValidTarget(final MagicSource source) {
|
||||
return true;
|
||||
|
@ -188,12 +188,12 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
public boolean isPermanent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCreature() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPlaneswalker() {
|
||||
return false;
|
||||
|
@ -203,36 +203,36 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
public boolean isPlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSpell() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private int getColorFlags() {
|
||||
return getCardDefinition().getColorFlags();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasColor(final MagicColor color) {
|
||||
return color.hasColor(getColorFlags());
|
||||
return color.hasColor(getColorFlags());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasAbility(final MagicAbility ability) {
|
||||
return getCardDefinition().hasAbility(ability);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasType(final MagicType type) {
|
||||
return getCardDefinition().hasType(type);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasSubType(final MagicSubType subType) {
|
||||
return getCardDefinition().hasSubType(subType);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<MagicActivation> getActivations() {
|
||||
return getCardDefinition().getCardActivations();
|
||||
|
@ -247,32 +247,32 @@ public class MagicCard implements MagicSource,MagicTarget,Comparable<MagicCard>
|
|||
return Long.signum(id - card.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicGame getGame() {
|
||||
return owner.getGame();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isLegalTarget(final MagicPlayer player, final MagicTargetFilter<? extends MagicTarget> targetFilter) {
|
||||
// Card in graveyard
|
||||
if (targetFilter.acceptType(MagicTargetType.Graveyard) &&
|
||||
if (targetFilter.acceptType(MagicTargetType.Graveyard) &&
|
||||
player.getGraveyard().contains(this)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Card in opponent's graveyard
|
||||
if (targetFilter.acceptType(MagicTargetType.OpponentsGraveyard) &&
|
||||
if (targetFilter.acceptType(MagicTargetType.OpponentsGraveyard) &&
|
||||
player.getOpponent().getGraveyard().contains(this)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Card in hand
|
||||
if (targetFilter.acceptType(MagicTargetType.Hand) &&
|
||||
if (targetFilter.acceptType(MagicTargetType.Hand) &&
|
||||
player.getHand().contains(this)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,11 +108,11 @@ public class MagicCardDefinition {
|
|||
private boolean excludeManaOrCombat;
|
||||
|
||||
private String requiresGroovy;
|
||||
|
||||
|
||||
public MagicCardDefinition() {
|
||||
initialize();
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
protected void initialize() {}
|
||||
|
||||
|
||||
|
@ -126,7 +126,7 @@ public class MagicCardDefinition {
|
|||
requiresGroovy = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void printStatistics() {
|
||||
System.err.println(numTriggers + " triggers");
|
||||
System.err.println(numStatics + " statics");
|
||||
|
@ -135,7 +135,7 @@ public class MagicCardDefinition {
|
|||
System.err.println(numSpellEvent + " spell event");
|
||||
System.err.println(numCDAs + " CDAs");
|
||||
}
|
||||
|
||||
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
@ -151,15 +151,15 @@ public class MagicCardDefinition {
|
|||
public boolean isIgnored(final long size) {
|
||||
return ignore != null && ignore.contains(size);
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
@ -167,15 +167,15 @@ public class MagicCardDefinition {
|
|||
public void setFullName(final String name) {
|
||||
fullName = name;
|
||||
}
|
||||
|
||||
|
||||
public void setIndex(final int index) {
|
||||
this.index=index;
|
||||
}
|
||||
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
public String getImageName() {
|
||||
return fullName;
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ public class MagicCardDefinition {
|
|||
public void setImageCount(final int count) {
|
||||
this.imageCount = count;
|
||||
}
|
||||
|
||||
|
||||
public int getImageCount() {
|
||||
return imageCount;
|
||||
}
|
||||
|
@ -195,19 +195,19 @@ public class MagicCardDefinition {
|
|||
public String getImageURL() {
|
||||
return imageURL;
|
||||
}
|
||||
|
||||
|
||||
public void setCardInfoURL(final String url) {
|
||||
this.cardInfoUrl = url;
|
||||
}
|
||||
|
||||
|
||||
public String getCardInfoURL() {
|
||||
return this.cardInfoUrl;
|
||||
}
|
||||
|
||||
|
||||
public String getCardTextName() {
|
||||
return getImageName();
|
||||
}
|
||||
|
||||
|
||||
public void setValue(final double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
@ -215,33 +215,33 @@ public class MagicCardDefinition {
|
|||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
public void setRemoval(final int removal) {
|
||||
this.removal=removal;
|
||||
}
|
||||
|
||||
|
||||
public int getRemoval() {
|
||||
return removal;
|
||||
}
|
||||
|
||||
|
||||
public int getScore() {
|
||||
if (score<0) {
|
||||
score=ArtificialScoringSystem.getCardDefinitionScore(this);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public int getFreeScore() {
|
||||
if (score<0) {
|
||||
score=ArtificialScoringSystem.getFreeCardDefinitionScore(this);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public void setRarity(final char c) {
|
||||
this.rarity = MagicRarity.getRarity(c);
|
||||
}
|
||||
|
||||
|
||||
public boolean isRarity(final MagicRarity r) {
|
||||
return this.rarity == r;
|
||||
}
|
||||
|
@ -249,11 +249,11 @@ public class MagicCardDefinition {
|
|||
public int getRarity() {
|
||||
return rarity.ordinal();
|
||||
}
|
||||
|
||||
|
||||
public String getRarityString() {
|
||||
return rarity.getName();
|
||||
}
|
||||
|
||||
|
||||
public Color getRarityColor() {
|
||||
final Theme theme=ThemeFactory.getInstance().getCurrentTheme();
|
||||
switch (getRarity()) {
|
||||
|
@ -263,11 +263,11 @@ public class MagicCardDefinition {
|
|||
default: return theme.getColor(Theme.COLOR_COMMON_FOREGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setToken() {
|
||||
token=true;
|
||||
}
|
||||
|
||||
|
||||
public boolean isToken() {
|
||||
return token;
|
||||
}
|
||||
|
@ -275,67 +275,67 @@ public class MagicCardDefinition {
|
|||
int getTypeFlags() {
|
||||
return typeFlags;
|
||||
}
|
||||
|
||||
|
||||
public void addType(final MagicType type) {
|
||||
typeFlags|=type.getMask();
|
||||
}
|
||||
|
||||
|
||||
public boolean hasType(final MagicType type) {
|
||||
return (typeFlags&type.getMask())!=0;
|
||||
}
|
||||
|
||||
|
||||
public boolean isBasic() {
|
||||
return hasType(MagicType.Basic);
|
||||
}
|
||||
|
||||
|
||||
public boolean isLand() {
|
||||
return hasType(MagicType.Land);
|
||||
}
|
||||
|
||||
|
||||
public boolean isCreature() {
|
||||
return hasType(MagicType.Creature);
|
||||
}
|
||||
|
||||
|
||||
public boolean isArtifact() {
|
||||
return hasType(MagicType.Artifact);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEquipment() {
|
||||
return isArtifact() && hasSubType(MagicSubType.Equipment);
|
||||
}
|
||||
|
||||
|
||||
public boolean isPlaneswalker() {
|
||||
return hasType(MagicType.Planeswalker);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnchantment() {
|
||||
return hasType(MagicType.Enchantment);
|
||||
}
|
||||
|
||||
|
||||
public boolean isLegendary() {
|
||||
return hasType(MagicType.Legendary);
|
||||
}
|
||||
|
||||
|
||||
public boolean isTribal() {
|
||||
return hasType(MagicType.Tribal);
|
||||
}
|
||||
|
||||
|
||||
public boolean isAura() {
|
||||
return isEnchantment() && hasSubType(MagicSubType.Aura);
|
||||
}
|
||||
|
||||
|
||||
public boolean isInstant() {
|
||||
return hasType(MagicType.Instant);
|
||||
}
|
||||
|
||||
|
||||
public boolean isSorcery() {
|
||||
return hasType(MagicType.Sorcery);
|
||||
}
|
||||
|
||||
|
||||
public boolean isSpell() {
|
||||
return isInstant()||isSorcery();
|
||||
}
|
||||
|
||||
|
||||
public String getLongTypeString() {
|
||||
if (isBasic()) {
|
||||
return "Basic " + getTypeString();
|
||||
|
@ -343,56 +343,56 @@ public class MagicCardDefinition {
|
|||
if (isLegendary()) {
|
||||
return "Legendary " + getTypeString();
|
||||
}
|
||||
|
||||
|
||||
if (isTribal()) {
|
||||
return "Tribal " + getTypeString();
|
||||
}
|
||||
return getTypeString();
|
||||
return getTypeString();
|
||||
}
|
||||
|
||||
|
||||
public String getTypeString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (isLand()) {
|
||||
sb.append(MagicType.Land.toString());
|
||||
}
|
||||
}
|
||||
if (isArtifact()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(MagicType.Artifact.toString());
|
||||
}
|
||||
}
|
||||
if (isCreature()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(MagicType.Creature.toString());
|
||||
}
|
||||
}
|
||||
if (isEnchantment()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(MagicType.Enchantment.toString());
|
||||
}
|
||||
}
|
||||
if (isInstant()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(MagicType.Instant.toString());
|
||||
}
|
||||
}
|
||||
if (isSorcery()) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(MagicType.Sorcery.toString());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean usesStack() {
|
||||
return !isLand();
|
||||
}
|
||||
|
||||
|
||||
public void setSubTypes(final String[] subTypeNames) {
|
||||
subTypeFlags = MagicSubType.getSubTypes(subTypeNames);
|
||||
}
|
||||
|
@ -400,22 +400,22 @@ public class MagicCardDefinition {
|
|||
EnumSet<MagicSubType> genSubTypeFlags() {
|
||||
return subTypeFlags.clone();
|
||||
}
|
||||
|
||||
|
||||
EnumSet<MagicSubType> getSubTypeFlags() {
|
||||
final EnumSet<MagicSubType> subTypes = genSubTypeFlags();
|
||||
applyCDASubType(null, null, subTypes);
|
||||
return subTypes;
|
||||
}
|
||||
|
||||
|
||||
public void applyCDASubType(
|
||||
final MagicGame game,
|
||||
final MagicPlayer player,
|
||||
final MagicGame game,
|
||||
final MagicPlayer player,
|
||||
final Set<MagicSubType> flags) {
|
||||
for (final MagicCDA lv : CDAs) {
|
||||
lv.getSubTypeFlags(game, player, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getSubTypeString() {
|
||||
final String brackets = getSubTypeFlags().toString(); // [...,...]
|
||||
if (brackets.length() <= 2) {
|
||||
|
@ -423,15 +423,15 @@ public class MagicCardDefinition {
|
|||
}
|
||||
return brackets.substring(1, brackets.length() - 1);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasSubType(final MagicSubType subType) {
|
||||
return getSubTypeFlags().contains(subType);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final String colors) {
|
||||
colorFlags=MagicColor.getFlags(colors);
|
||||
colorFlags=MagicColor.getFlags(colors);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasColor(final MagicColor color) {
|
||||
return (colorFlags&color.getMask())!=0;
|
||||
}
|
||||
|
@ -439,19 +439,19 @@ public class MagicCardDefinition {
|
|||
public boolean isColorless() {
|
||||
return colorFlags == 0;
|
||||
}
|
||||
|
||||
|
||||
public int getColorFlags() {
|
||||
return colorFlags;
|
||||
}
|
||||
|
||||
|
||||
public int getConvertedCost() {
|
||||
return cost.getConvertedCost();
|
||||
}
|
||||
|
||||
|
||||
public boolean hasConvertedCost(final int c) {
|
||||
return getConvertedCost() == c;
|
||||
}
|
||||
|
||||
|
||||
public int getCostBucket() {
|
||||
switch (getConvertedCost()) {
|
||||
case 0:
|
||||
|
@ -461,11 +461,11 @@ public class MagicCardDefinition {
|
|||
case 3:
|
||||
case 4:
|
||||
return 1;
|
||||
default:
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean hasX() {
|
||||
return cost.hasX();
|
||||
}
|
||||
|
@ -477,14 +477,14 @@ public class MagicCardDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
//every card should have a timing hint
|
||||
public void validate() {
|
||||
//every card should have a timing hint
|
||||
if (!isToken() && getTiming() == MagicTiming.None) {
|
||||
throw new RuntimeException(
|
||||
getName() + " does not have a timing hint"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//check colorFlags is set
|
||||
if (colorFlags == -1) {
|
||||
throw new RuntimeException(name + "'s color is not set");
|
||||
|
@ -494,7 +494,7 @@ public class MagicCardDefinition {
|
|||
public MagicManaCost getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
public MagicEvent[] getCostEvent(final MagicCard source) {
|
||||
final List<MagicEvent> costEvent = new ArrayList<MagicEvent>();
|
||||
if (cost != MagicManaCost.ZERO) {
|
||||
|
@ -508,7 +508,7 @@ public class MagicCardDefinition {
|
|||
}
|
||||
return costEvent.toArray(new MagicEvent[0]);
|
||||
}
|
||||
|
||||
|
||||
public boolean isPlayable(final MagicPlayerProfile profile) {
|
||||
if (isLand()) {
|
||||
int source = 0;
|
||||
|
@ -520,11 +520,11 @@ public class MagicCardDefinition {
|
|||
return cost.getCostScore(profile) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setEquipCost(final MagicManaCost equipCost) {
|
||||
add(new MagicEquipActivation(equipCost));
|
||||
}
|
||||
|
||||
|
||||
public void setManaSourceText(final String sourceText) {
|
||||
manaSourceText=sourceText;
|
||||
for (int index=0;index<sourceText.length();index+=2) {
|
||||
|
@ -534,20 +534,20 @@ public class MagicCardDefinition {
|
|||
manaSource[color.ordinal()]=source;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getManaSource(final MagicColor color) {
|
||||
return manaSource[color.ordinal()];
|
||||
}
|
||||
|
||||
|
||||
public void setPowerToughness(final int aPower, final int aToughness) {
|
||||
power = aPower;
|
||||
toughness = aToughness;
|
||||
}
|
||||
|
||||
|
||||
public int getCardPower() {
|
||||
return power;
|
||||
}
|
||||
|
||||
|
||||
public int getCardToughness() {
|
||||
return toughness;
|
||||
}
|
||||
|
@ -555,21 +555,21 @@ public class MagicCardDefinition {
|
|||
public MagicPowerToughness genPowerToughness() {
|
||||
return new MagicPowerToughness(power, toughness);
|
||||
}
|
||||
|
||||
|
||||
public void applyCDAPowerToughness(
|
||||
final MagicGame game,
|
||||
final MagicPlayer player,
|
||||
final MagicGame game,
|
||||
final MagicPlayer player,
|
||||
final MagicPermanent perm,
|
||||
final MagicPowerToughness pt) {
|
||||
for (final MagicCDA lv : CDAs) {
|
||||
lv.modPowerToughness(game, player, perm, pt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addAbility(final MagicAbility ability) {
|
||||
addAbility(ability, "");
|
||||
}
|
||||
|
||||
|
||||
public void addAbility(final MagicAbility ability, final String arg) {
|
||||
ability.addAbilityImpl(this, arg);
|
||||
abilityFlags.add(ability);
|
||||
|
@ -578,31 +578,31 @@ public class MagicCardDefinition {
|
|||
public Set<MagicAbility> genAbilityFlags() {
|
||||
return abilityFlags.clone();
|
||||
}
|
||||
|
||||
|
||||
public boolean hasAbility(final MagicAbility ability) {
|
||||
return abilityFlags.contains(ability);
|
||||
}
|
||||
|
||||
|
||||
public void setText(final String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
|
||||
public void setStaticType(final MagicStaticType staticType) {
|
||||
this.staticType=staticType;
|
||||
}
|
||||
|
||||
|
||||
MagicStaticType getStaticType() {
|
||||
return staticType;
|
||||
}
|
||||
|
||||
|
||||
public void setTiming(final MagicTiming timing) {
|
||||
this.timing=timing;
|
||||
}
|
||||
|
||||
|
||||
public MagicTiming getTiming() {
|
||||
return timing;
|
||||
}
|
||||
|
@ -610,13 +610,13 @@ public class MagicCardDefinition {
|
|||
public void add(final MagicChangeCardDefinition mod) {
|
||||
mod.change(this);
|
||||
}
|
||||
|
||||
|
||||
public void setEvent(final MagicCardEvent aCardEvent) {
|
||||
assert cardEvent == MagicPlayCardEvent.create() : "Attempting to set two MagicCardEvents for " + this;
|
||||
cardEvent = aCardEvent;
|
||||
numSpellEvent++;
|
||||
}
|
||||
|
||||
|
||||
public MagicCardEvent getCardEvent() {
|
||||
return cardEvent;
|
||||
}
|
||||
|
@ -624,22 +624,22 @@ public class MagicCardDefinition {
|
|||
public MagicActivationHints getActivationHints() {
|
||||
return new MagicActivationHints(timing,true);
|
||||
}
|
||||
|
||||
|
||||
// cast card activation is the first element of cardActivations
|
||||
public MagicActivation getCastActivation() {
|
||||
assert cardActivations.size() >= 1 : this + " has no card activations";
|
||||
return cardActivations.getFirst();
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicActivation> getCardActivations() {
|
||||
return cardActivations;
|
||||
}
|
||||
|
||||
|
||||
public void addCDA(final MagicCDA cda) {
|
||||
CDAs.add(cda);
|
||||
numCDAs++;
|
||||
}
|
||||
|
||||
|
||||
public void addCostEvent(final MagicEventSource eventSource) {
|
||||
costEventSources.add(eventSource);
|
||||
}
|
||||
|
@ -667,78 +667,78 @@ public class MagicCardDefinition {
|
|||
drawnTriggers.add(trigger);
|
||||
numTriggers++;
|
||||
}
|
||||
|
||||
|
||||
public void addTrigger(final MagicTrigger<?> trigger) {
|
||||
triggers.add(trigger);
|
||||
numTriggers++;
|
||||
}
|
||||
|
||||
|
||||
public void addStatic(final MagicStatic mstatic) {
|
||||
statics.add(mstatic);
|
||||
numStatics++;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicTrigger<?>> getTriggers() {
|
||||
return triggers;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicStatic> getStatics() {
|
||||
return statics;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicWhenSpellIsCastTrigger> getSpellIsCastTriggers() {
|
||||
return spellIsCastTriggers;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicWhenComesIntoPlayTrigger> getComeIntoPlayTriggers() {
|
||||
return comeIntoPlayTriggers;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicWhenPutIntoGraveyardTrigger> getPutIntoGraveyardTriggers() {
|
||||
return putIntoGraveyardTriggers;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicWhenDrawnTrigger> getDrawnTriggers() {
|
||||
return drawnTriggers;
|
||||
}
|
||||
|
||||
|
||||
public void addAct(final MagicPermanentActivation activation) {
|
||||
activations.add(activation);
|
||||
numPermanentActivations++;
|
||||
}
|
||||
|
||||
|
||||
public void addCardAct(final MagicCardActivation activation) {
|
||||
cardActivations.add(activation);
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicActivation> getActivations() {
|
||||
return activations;
|
||||
}
|
||||
|
||||
|
||||
public void addManaAct(final MagicManaActivation activation) {
|
||||
manaActivations.add(activation);
|
||||
numManaActivations++;
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicManaActivation> getManaActivations() {
|
||||
return manaActivations;
|
||||
}
|
||||
|
||||
|
||||
public void setExcludeManaOrCombat() {
|
||||
excludeManaOrCombat=true;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasExcludeManaOrCombat() {
|
||||
return excludeManaOrCombat;
|
||||
}
|
||||
|
||||
|
||||
public ImageIcon getIcon() {
|
||||
if (isLand()) {
|
||||
return IconImages.LAND;
|
||||
return IconImages.LAND;
|
||||
} else if (isCreature()) {
|
||||
return IconImages.CREATURE;
|
||||
} else if (isEquipment()) {
|
||||
return IconImages.EQUIPMENT;
|
||||
return IconImages.EQUIPMENT;
|
||||
} else if (isAura()) {
|
||||
return IconImages.AURA;
|
||||
} else if (isEnchantment()) {
|
||||
|
@ -749,7 +749,7 @@ public class MagicCardDefinition {
|
|||
return IconImages.SPELL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean subTypeHasText(final String s) {
|
||||
final MagicSubType[] subTypeValues = MagicSubType.values();
|
||||
for (final MagicSubType subtype : subTypeValues) {
|
||||
|
@ -759,7 +759,7 @@ public class MagicCardDefinition {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean abilityHasText(final String s) {
|
||||
for (final MagicAbility ability : MagicAbility.CORE) {
|
||||
if(hasAbility(ability) && ability.getName().toLowerCase().contains(s)) {
|
||||
|
@ -768,7 +768,7 @@ public class MagicCardDefinition {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasText(String s) {
|
||||
s = s.toLowerCase();
|
||||
return (
|
||||
|
@ -779,7 +779,7 @@ public class MagicCardDefinition {
|
|||
getText().toLowerCase().contains(s)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
|
@ -798,7 +798,7 @@ public class MagicCardDefinition {
|
|||
return NAME_COMPARATOR_DESC.compare(cardDefinition2, cardDefinition1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final Comparator<MagicCardDefinition> CONVERTED_COMPARATOR_DESC=new Comparator<MagicCardDefinition>() {
|
||||
@Override
|
||||
public int compare(final MagicCardDefinition cardDefinition1,final MagicCardDefinition cardDefinition2) {
|
||||
|
@ -809,7 +809,7 @@ public class MagicCardDefinition {
|
|||
return cardDefinition1.getName().compareTo(cardDefinition2.getName());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final Comparator<MagicCardDefinition> CONVERTED_COMPARATOR_ASC=new Comparator<MagicCardDefinition>() {
|
||||
@Override
|
||||
public int compare(final MagicCardDefinition cardDefinition1,final MagicCardDefinition cardDefinition2) {
|
||||
|
@ -819,7 +819,7 @@ public class MagicCardDefinition {
|
|||
|
||||
public static final Comparator<MagicCardDefinition> TYPE_COMPARATOR_DESC=new Comparator<MagicCardDefinition>() {
|
||||
@Override
|
||||
public int compare(final MagicCardDefinition cardDefinition1,final MagicCardDefinition cardDefinition2) {
|
||||
public int compare(final MagicCardDefinition cardDefinition1,final MagicCardDefinition cardDefinition2) {
|
||||
final int c = cardDefinition1.getTypeString().compareTo(cardDefinition2.getTypeString());
|
||||
if(c == 0) {
|
||||
return cardDefinition1.getLongTypeString().compareTo(cardDefinition2.getLongTypeString());
|
||||
|
@ -854,7 +854,7 @@ public class MagicCardDefinition {
|
|||
public int compare(final MagicCardDefinition cardDefinition1,final MagicCardDefinition cardDefinition2) {
|
||||
final int p1 = cardDefinition1.isCreature() ? cardDefinition1.getCardPower() : -100;
|
||||
final int p2 = cardDefinition2.isCreature() ? cardDefinition2.getCardPower() : -100;
|
||||
|
||||
|
||||
if (p1 != p2) {
|
||||
return p1 - p2;
|
||||
} else {
|
||||
|
@ -875,7 +875,7 @@ public class MagicCardDefinition {
|
|||
public int compare(final MagicCardDefinition cardDefinition1,final MagicCardDefinition cardDefinition2) {
|
||||
final int t1 = cardDefinition1.isCreature() ? cardDefinition1.getCardToughness() : -100;
|
||||
final int t2 = cardDefinition2.isCreature() ? cardDefinition2.getCardToughness() : -100;
|
||||
|
||||
|
||||
if (t1 != t2) {
|
||||
return t1 - t2;
|
||||
} else {
|
||||
|
|
|
@ -5,21 +5,21 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
public class MagicCardList extends ArrayList<MagicCard> {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
public MagicCardList() {}
|
||||
|
||||
|
||||
public MagicCardList(final MagicCardList cardList) {
|
||||
super(cardList);
|
||||
}
|
||||
|
||||
|
||||
MagicCardList(final MagicCopyMap copyMap, final MagicCardList cardList) {
|
||||
for (final MagicCard card : cardList) {
|
||||
add(copyMap.copy(card));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public long getStateId() {
|
||||
final long[] keys = new long[size()];
|
||||
int idx = 0;
|
||||
|
@ -29,7 +29,7 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
}
|
||||
return magic.MurmurHash3.hash(keys);
|
||||
}
|
||||
|
||||
|
||||
public long getUnorderedStateId() {
|
||||
final long[] keys = new long[size()];
|
||||
int idx = 0;
|
||||
|
@ -40,33 +40,33 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
Arrays.sort(keys);
|
||||
return magic.MurmurHash3.hash(keys);
|
||||
}
|
||||
|
||||
|
||||
public void addToBottom(final MagicCard card) {
|
||||
add(0,card);
|
||||
}
|
||||
|
||||
|
||||
public void addToTop(final MagicCard card) {
|
||||
add(card);
|
||||
}
|
||||
|
||||
|
||||
public MagicCard getCardAtBottom() {
|
||||
return get(0);
|
||||
}
|
||||
|
||||
|
||||
public MagicCard getCardAtTop() {
|
||||
final int size = this.size();
|
||||
return size > 0 ?
|
||||
return size > 0 ?
|
||||
this.get(size()-1) :
|
||||
MagicCard.NONE;
|
||||
}
|
||||
|
||||
|
||||
public MagicCard removeCardAtTop() {
|
||||
final int index=size()-1;
|
||||
final MagicCard card=get(index);
|
||||
remove(index);
|
||||
return card;
|
||||
}
|
||||
|
||||
|
||||
public int removeCard(final MagicCard card) {
|
||||
final int index=indexOf(card);
|
||||
if (index >= 0) {
|
||||
|
@ -85,18 +85,18 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
}
|
||||
return MagicCard.NONE;
|
||||
}
|
||||
|
||||
|
||||
public void setCards(final MagicCardList cardList) {
|
||||
clear();
|
||||
addAll(cardList);
|
||||
}
|
||||
|
||||
|
||||
void setKnown(final boolean known) {
|
||||
for (final MagicCard card : this) {
|
||||
card.setKnown(known);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int getNrOfLands() {
|
||||
int lands=0;
|
||||
for (final MagicCard card : this) {
|
||||
|
@ -106,7 +106,7 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
}
|
||||
return lands;
|
||||
}
|
||||
|
||||
|
||||
private boolean useSmartShuffle() {
|
||||
final int lands = getNrOfLands();
|
||||
final int total = size();
|
||||
|
@ -125,7 +125,7 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
public void shuffle() {
|
||||
shuffle(getStateId());
|
||||
}
|
||||
|
||||
|
||||
public void shuffle(final long seed) {
|
||||
final magic.MersenneTwisterFast rng = new magic.MersenneTwisterFast(seed);
|
||||
final MagicCardList oldCards = new MagicCardList(this);
|
||||
|
@ -133,11 +133,11 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
for (int size = oldCards.size(); size > 0; size--) {
|
||||
final int index=rng.nextInt(size);
|
||||
final MagicCard card=oldCards.get(index);
|
||||
oldCards.remove(index);
|
||||
oldCards.remove(index);
|
||||
add(card);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void smartShuffle(final long seed) {
|
||||
final magic.MersenneTwisterFast rng = new magic.MersenneTwisterFast(seed);
|
||||
final int size=size();
|
||||
|
@ -155,7 +155,7 @@ public class MagicCardList extends ArrayList<MagicCard> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
clear();
|
||||
for (int blocks=size/5;blocks>0;blocks--) {
|
||||
int landCount=0;
|
||||
|
|
|
@ -15,40 +15,40 @@ public enum MagicColor {
|
|||
Green("green",'g'),
|
||||
Red("red",'r')
|
||||
;
|
||||
|
||||
|
||||
public static final int NR_COLORS=values().length;
|
||||
|
||||
|
||||
private final String name;
|
||||
private final char symbol;
|
||||
private final int mask;
|
||||
|
||||
|
||||
private MagicColor(final String name,final char symbol) {
|
||||
this.name=name;
|
||||
this.name=name;
|
||||
this.symbol=symbol;
|
||||
this.mask=1<<ordinal();
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public char getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
public int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasColor(final int flags) {
|
||||
return (flags&mask)!=0;
|
||||
}
|
||||
|
||||
|
||||
public MagicAbility getProtectionAbility() {
|
||||
switch (this) {
|
||||
case White: return MagicAbility.ProtectionFromWhite;
|
||||
|
@ -59,7 +59,7 @@ public enum MagicColor {
|
|||
}
|
||||
throw new RuntimeException("No protection ability for MagicColor " + this);
|
||||
}
|
||||
|
||||
|
||||
public MagicAbility getLandwalkAbility() {
|
||||
switch (this) {
|
||||
case White: return MagicAbility.PlainsWalk;
|
||||
|
@ -67,10 +67,10 @@ public enum MagicColor {
|
|||
case Black: return MagicAbility.Swampwalk;
|
||||
case Green: return MagicAbility.Forestwalk;
|
||||
case Red: return MagicAbility.Mountainwalk;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No landwalk ability for MagicColor " + this);
|
||||
}
|
||||
|
||||
|
||||
public MagicAbility getCannotBeBlockedByAbility() {
|
||||
switch (this) {
|
||||
case White: return MagicAbility.CannotBeBlockedByWhite;
|
||||
|
@ -78,13 +78,13 @@ public enum MagicColor {
|
|||
case Black: return MagicAbility.CannotBeBlockedByBlack;
|
||||
case Green: return MagicAbility.CannotBeBlockedByGreen;
|
||||
case Red: return MagicAbility.CannotBeBlockedByRed;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No CannotBeBlockedBy ability for MagicColor " + this);
|
||||
}
|
||||
|
||||
|
||||
public MagicSubType getLandSubType() {
|
||||
switch (this) {
|
||||
case White: return MagicSubType.Plains;
|
||||
case White: return MagicSubType.Plains;
|
||||
case Blue: return MagicSubType.Island;
|
||||
case Black: return MagicSubType.Swamp;
|
||||
case Green: return MagicSubType.Forest;
|
||||
|
@ -92,7 +92,7 @@ public enum MagicColor {
|
|||
}
|
||||
throw new RuntimeException("No land subtype for MagicColor " + this);
|
||||
}
|
||||
|
||||
|
||||
public MagicManaType getManaType() {
|
||||
switch (this) {
|
||||
case White: return MagicManaType.White;
|
||||
|
@ -103,7 +103,7 @@ public enum MagicColor {
|
|||
}
|
||||
return MagicManaType.Colorless;
|
||||
}
|
||||
|
||||
|
||||
public ImageIcon getIcon() {
|
||||
switch (this) {
|
||||
case White: return IconImages.WHITE;
|
||||
|
@ -124,7 +124,7 @@ public enum MagicColor {
|
|||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
public static MagicColor getColor(final char symbol) {
|
||||
final char usymbol=Character.toLowerCase(symbol);
|
||||
for (final MagicColor color : values()) {
|
||||
|
@ -133,14 +133,14 @@ public enum MagicColor {
|
|||
}
|
||||
}
|
||||
throw new RuntimeException("No corresponding MagicColor for " + symbol);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getRandomColors(final int count) {
|
||||
final List<MagicColor> colors = new ArrayList<MagicColor>(Arrays.asList(values()));
|
||||
final StringBuilder colorText=new StringBuilder();
|
||||
for (int c=count;c>0;c--) {
|
||||
final int index=MagicRandom.nextInt(colors.size());
|
||||
colorText.append(colors.remove(index).getSymbol());
|
||||
colorText.append(colors.remove(index).getSymbol());
|
||||
}
|
||||
return colorText.toString();
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ public enum MagicColor {
|
|||
}
|
||||
return numColors;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isColorless(final MagicSource source) {
|
||||
return numColors(source) == 0;
|
||||
}
|
||||
|
|
|
@ -6,33 +6,33 @@ import java.util.Comparator;
|
|||
public class MagicCondensedCardDefinition {
|
||||
private int copies;
|
||||
private final MagicCardDefinition card;
|
||||
|
||||
|
||||
public MagicCondensedCardDefinition(final MagicCardDefinition card) {
|
||||
this.card = card;
|
||||
copies = 1;
|
||||
}
|
||||
|
||||
|
||||
public MagicCardDefinition getCard() {
|
||||
return card;
|
||||
}
|
||||
|
||||
|
||||
public void incrementNumCopies() {
|
||||
copies++;
|
||||
}
|
||||
|
||||
|
||||
public void decrementNumCopies() {
|
||||
if (copies > 0) {
|
||||
copies--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setNumCopies(final int i) {
|
||||
copies = i;
|
||||
}
|
||||
|
||||
|
||||
public int getNumCopies() {
|
||||
return copies;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Comparator<MagicCondensedCardDefinition> NUM_COPIES_COMPARATOR_DESC=new Comparator<MagicCondensedCardDefinition>() {
|
||||
@Override
|
||||
|
@ -47,7 +47,7 @@ public class MagicCondensedCardDefinition {
|
|||
return MagicCondensedCardDefinition.NUM_COPIES_COMPARATOR_DESC.compare(cardDefinition2, cardDefinition1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final Comparator<MagicCondensedCardDefinition> NAME_COMPARATOR_DESC=new Comparator<MagicCondensedCardDefinition>() {
|
||||
@Override
|
||||
public int compare(final MagicCondensedCardDefinition cardDefinition1,final MagicCondensedCardDefinition cardDefinition2) {
|
||||
|
@ -61,14 +61,14 @@ public class MagicCondensedCardDefinition {
|
|||
return MagicCardDefinition.NAME_COMPARATOR_ASC.compare(cardDefinition1.getCard(), cardDefinition2.getCard());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final Comparator<MagicCondensedCardDefinition> CONVERTED_COMPARATOR_DESC=new Comparator<MagicCondensedCardDefinition>() {
|
||||
@Override
|
||||
public int compare(final MagicCondensedCardDefinition cardDefinition1,final MagicCondensedCardDefinition cardDefinition2) {
|
||||
return MagicCardDefinition.CONVERTED_COMPARATOR_DESC.compare(cardDefinition1.getCard(), cardDefinition2.getCard());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final Comparator<MagicCondensedCardDefinition> CONVERTED_COMPARATOR_ASC=new Comparator<MagicCondensedCardDefinition>() {
|
||||
@Override
|
||||
public int compare(final MagicCondensedCardDefinition cardDefinition1,final MagicCondensedCardDefinition cardDefinition2) {
|
||||
|
|
|
@ -7,9 +7,9 @@ import java.util.List;
|
|||
public class MagicCondensedDeck extends ArrayList<MagicCondensedCardDefinition> {
|
||||
|
||||
private static final long serialVersionUID = 143L;
|
||||
|
||||
|
||||
private String name = "Unsaved Deck";
|
||||
|
||||
|
||||
private final HashMap<String, MagicCondensedCardDefinition> map = new HashMap<String, MagicCondensedCardDefinition>();
|
||||
|
||||
public MagicCondensedDeck() {}
|
||||
|
@ -18,82 +18,82 @@ public class MagicCondensedDeck extends ArrayList<MagicCondensedCardDefinition>
|
|||
super(deck);
|
||||
name = deck.getName();
|
||||
}
|
||||
|
||||
|
||||
public MagicCondensedDeck(final MagicDeck list) {
|
||||
this((List<MagicCardDefinition>) list);
|
||||
|
||||
|
||||
name = list.getName();
|
||||
}
|
||||
|
||||
|
||||
public MagicCondensedDeck(final List<MagicCardDefinition> list) {
|
||||
super();
|
||||
|
||||
|
||||
for(final MagicCardDefinition card : list) {
|
||||
addCard(card, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getKey(final MagicCardDefinition card) {
|
||||
return card.getName();
|
||||
}
|
||||
|
||||
|
||||
public boolean addCard(final MagicCardDefinition card, final boolean ignoreCopiesLimit) {
|
||||
if(!map.containsKey(getKey(card))) {
|
||||
// add to end
|
||||
add(new MagicCondensedCardDefinition(card));
|
||||
map.put(getKey(card), get(size() - 1));
|
||||
|
||||
|
||||
return true;
|
||||
} else {
|
||||
final MagicCondensedCardDefinition existingCard = map.get(getKey(card));
|
||||
|
||||
|
||||
if(ignoreCopiesLimit || existingCard.getNumCopies() < MagicDeckConstructionRule.MAX_COPIES) {
|
||||
existingCard.incrementNumCopies();
|
||||
|
||||
|
||||
return true;
|
||||
} // otherwise card can't be added because of copies limit
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setContent(final MagicCondensedDeck deck) {
|
||||
clear();
|
||||
addAll(deck);
|
||||
|
||||
|
||||
name = deck.getName();
|
||||
|
||||
|
||||
map.clear();
|
||||
map.putAll(deck.getMap());
|
||||
}
|
||||
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public int getNumCards() {
|
||||
return toMagicDeck().size();
|
||||
}
|
||||
|
||||
|
||||
public HashMap<String, MagicCondensedCardDefinition> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
public MagicDeck toMagicDeck() {
|
||||
final MagicDeck deck = new MagicDeck();
|
||||
|
||||
|
||||
for(int i = 0; i < size(); i++) {
|
||||
final MagicCondensedCardDefinition card = get(i);
|
||||
|
||||
|
||||
for(int j = 0; j < card.getNumCopies(); j++) {
|
||||
deck.add(card.getCard());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return deck;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,17 +10,17 @@ public class MagicCopyMap extends HashMap<MagicCopyable,MagicCopyable> {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends MagicCopyable> E copy(final E source) {
|
||||
if (source == null) {
|
||||
if (source == null) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
E target=(E)get(source);
|
||||
if (target==null) {
|
||||
if (target==null) {
|
||||
target=(E)source.copy(this);
|
||||
put(source,target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
private Object copyObject(final Object source) {
|
||||
if (source != null && source instanceof MagicCopyable) {
|
||||
return copy((MagicCopyable)source);
|
||||
|
@ -28,7 +28,7 @@ public class MagicCopyMap extends HashMap<MagicCopyable,MagicCopyable> {
|
|||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E> E[] copyObjects(final E[] sources,final Class<E> clazz) {
|
||||
if (sources==null||sources.length==0) {
|
||||
|
@ -40,7 +40,7 @@ public class MagicCopyMap extends HashMap<MagicCopyable,MagicCopyable> {
|
|||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E> void copyCollection(final Collection<E> sourceCollection,final Collection<E> targetCollection) {
|
||||
for (final E object : sourceCollection) {
|
||||
|
|
|
@ -22,18 +22,18 @@ public enum MagicCostManaType {
|
|||
RedWhite("red/white","{R/W}",Arrays.asList(MagicManaType.Red,MagicManaType.White)),
|
||||
GreenWhite("green/white","{G/W}",Arrays.asList(MagicManaType.Green,MagicManaType.White)),
|
||||
GreenBlue("green/blue","{G/U}",Arrays.asList(MagicManaType.Green,MagicManaType.Blue)),
|
||||
White("white","{W}",Arrays.asList(MagicManaType.White)),
|
||||
White("white","{W}",Arrays.asList(MagicManaType.White)),
|
||||
Blue("blue","{U}",Arrays.asList(MagicManaType.Blue)),
|
||||
Black("black","{B}",Arrays.asList(MagicManaType.Black)),
|
||||
Red("red","{R}",Arrays.asList(MagicManaType.Red)),
|
||||
Green("green","{G}",Arrays.asList(MagicManaType.Green)),
|
||||
;
|
||||
|
||||
|
||||
public static final int NR_OF_TYPES=values().length;
|
||||
public static final EnumSet<MagicCostManaType> HYBRID = EnumSet.range(WhiteBlue, GreenBlue);
|
||||
public static final EnumSet<MagicCostManaType> MONO = EnumSet.range(White, Green);
|
||||
public static final EnumSet<MagicCostManaType> NON_MONO = EnumSet.range(Colorless, GreenBlue);
|
||||
|
||||
|
||||
private final String name;
|
||||
private final String text;
|
||||
private final List<MagicManaType> types;
|
||||
|
@ -43,7 +43,7 @@ public enum MagicCostManaType {
|
|||
this.text=text;
|
||||
this.types=types;
|
||||
}
|
||||
|
||||
|
||||
public MagicCostManaType next() {
|
||||
switch (this) {
|
||||
case White: return Blue;
|
||||
|
@ -54,7 +54,7 @@ public enum MagicCostManaType {
|
|||
default: throw new RuntimeException("No next mana cost type for " + this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MagicCostManaType prev() {
|
||||
switch (this) {
|
||||
case White: return Green;
|
||||
|
@ -65,19 +65,19 @@ public enum MagicCostManaType {
|
|||
default: throw new RuntimeException("No next mana cost type for " + this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public List<MagicManaType> getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
public MagicManaType[] getTypes(final MagicPlayerProfile profile) {
|
||||
int count=0;
|
||||
final MagicManaType[] profileTypes=new MagicManaType[types.size()];
|
||||
|
@ -88,7 +88,7 @@ public enum MagicCostManaType {
|
|||
}
|
||||
return Arrays.copyOf(profileTypes,count);
|
||||
}
|
||||
|
||||
|
||||
public ImageIcon getIcon() {
|
||||
return TextImages.getIcon(text);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package magic.model;
|
||||
|
||||
public enum MagicCounterType {
|
||||
|
||||
|
||||
PlusOne("+1/+1","{+}"),
|
||||
MinusOne("-1/-1","{-}"),
|
||||
Charge("charge","{C}"),
|
||||
|
@ -11,19 +11,19 @@ public enum MagicCounterType {
|
|||
;
|
||||
|
||||
public static final int NR_COUNTERS=MagicCounterType.values().length;
|
||||
|
||||
|
||||
private final String name;
|
||||
private final String text;
|
||||
|
||||
|
||||
private MagicCounterType(final String name,final String text) {
|
||||
this.name=name;
|
||||
this.text=text;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
|
|
@ -5,21 +5,21 @@ import java.util.HashSet;
|
|||
public class MagicCubeDefinition extends HashSet<String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
public MagicCubeDefinition(final String name) {
|
||||
this.name=name;
|
||||
}
|
||||
|
||||
|
||||
public boolean containsCard(final MagicCardDefinition cardDefinition) {
|
||||
return contains(cardDefinition.getName());
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name + " (" + size() + " cards)";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
|
|
@ -3,7 +3,7 @@ package magic.model;
|
|||
import magic.model.target.MagicTarget;
|
||||
|
||||
public class MagicDamage {
|
||||
|
||||
|
||||
private final MagicSource source;
|
||||
private MagicTarget target;
|
||||
private int amount;
|
||||
|
@ -18,7 +18,7 @@ public class MagicDamage {
|
|||
this.amount=amount;
|
||||
this.combat=combat;
|
||||
}
|
||||
|
||||
|
||||
public MagicDamage(final MagicSource source,final MagicTarget target,final int amount) {
|
||||
this(source, target, amount, false);
|
||||
}
|
||||
|
@ -26,23 +26,23 @@ public class MagicDamage {
|
|||
public static final MagicDamage Combat(final MagicSource source,final MagicTarget target,final int amount) {
|
||||
return new MagicDamage(source, target, amount, true);
|
||||
}
|
||||
|
||||
|
||||
public MagicSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
public void setTarget(final MagicTarget target) {
|
||||
this.target=target;
|
||||
}
|
||||
|
||||
|
||||
public MagicTarget getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayer getTargetPlayer() {
|
||||
return (MagicPlayer)target;
|
||||
}
|
||||
|
||||
|
||||
public void setAmount(final int amt) {
|
||||
amount = amt;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class MagicDamage {
|
|||
amount -= amt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
@ -60,27 +60,27 @@ public class MagicDamage {
|
|||
public void setDealtAmount(final int dealtAmount) {
|
||||
this.dealtAmount=dealtAmount;
|
||||
}
|
||||
|
||||
|
||||
public int getDealtAmount() {
|
||||
return dealtAmount;
|
||||
}
|
||||
|
||||
|
||||
public boolean isCombat() {
|
||||
return combat;
|
||||
}
|
||||
|
||||
|
||||
public void setUnpreventable() {
|
||||
unpreventable=true;
|
||||
}
|
||||
|
||||
|
||||
public boolean isUnpreventable() {
|
||||
return unpreventable;
|
||||
}
|
||||
|
||||
|
||||
public void setNoRegeneration() {
|
||||
noRegeneration=true;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasNoRegeneration() {
|
||||
return noRegeneration;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.util.ArrayList;
|
|||
public class MagicDeck extends ArrayList<MagicCardDefinition> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private String name="Unsaved Deck";
|
||||
private String description;
|
||||
|
||||
|
@ -21,11 +21,11 @@ public class MagicDeck extends ArrayList<MagicCardDefinition> {
|
|||
addAll(deck);
|
||||
name = deck.name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name=name;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -4,31 +4,31 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public enum MagicDeckConstructionRule {
|
||||
|
||||
|
||||
MinDeckSize("Decks must have a least 40 cards."),
|
||||
FourCopyLimit("With the exception of basic lands, a deck must have no more than 4 copies of a card.")
|
||||
;
|
||||
|
||||
public static final int MIN_DECK_SIZE = 40;
|
||||
|
||||
public static final int MIN_DECK_SIZE = 40;
|
||||
public static final int MAX_COPIES = 4;
|
||||
|
||||
|
||||
private final String text;
|
||||
|
||||
|
||||
private MagicDeckConstructionRule(final String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
private String getRuleText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public static List<MagicDeckConstructionRule> checkDeck(final MagicDeck deck) {
|
||||
final ArrayList<MagicDeckConstructionRule> brokenRules = new ArrayList<MagicDeckConstructionRule>();
|
||||
|
||||
|
||||
if(deck.size() < MIN_DECK_SIZE) {
|
||||
brokenRules.add(MinDeckSize);
|
||||
}
|
||||
|
||||
|
||||
final MagicCondensedDeck countedDeck = new MagicCondensedDeck(deck);
|
||||
for(final MagicCondensedCardDefinition countedCard : countedDeck) {
|
||||
if(countedCard.getNumCopies() > 4 && !countedCard.getCard().isBasic() && !"Relentless Rats".equals(countedCard.getCard().getName())) {
|
||||
|
@ -36,18 +36,18 @@ public enum MagicDeckConstructionRule {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return brokenRules;
|
||||
}
|
||||
|
||||
|
||||
public static String getRulesText(final List<MagicDeckConstructionRule> rules) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
||||
for(final MagicDeckConstructionRule rule : rules) {
|
||||
sb.append(rule.getRuleText());
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,14 +20,14 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
|
||||
public class MagicDuel {
|
||||
|
||||
|
||||
private static final String OPPONENT="opponent";
|
||||
private static final String GAME="game";
|
||||
private static final String PLAYED="played";
|
||||
private static final String WON="won";
|
||||
private static final String START="start";
|
||||
private static final String COMPUTER="Computer";
|
||||
|
||||
|
||||
private final DuelConfig configuration;
|
||||
private final History history;
|
||||
private MagicPlayerDefinition[] playerDefinitions;
|
||||
|
@ -38,27 +38,27 @@ public class MagicDuel {
|
|||
private int gamesWon;
|
||||
private int startPlayer;
|
||||
private final int[] difficulty = new int[2];
|
||||
|
||||
|
||||
public MagicDuel(final DuelConfig configuration) {
|
||||
this.configuration=configuration;
|
||||
history = new History(this);
|
||||
ais=configuration.getPlayerAIs();
|
||||
restart();
|
||||
}
|
||||
|
||||
|
||||
public MagicDuel() {
|
||||
this(new DuelConfig());
|
||||
}
|
||||
|
||||
|
||||
public MagicDuel(final DuelConfig configuration,final MagicDuel duel) {
|
||||
this(configuration);
|
||||
playerDefinitions=duel.playerDefinitions;
|
||||
}
|
||||
|
||||
|
||||
public DuelConfig getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
|
||||
private MagicPlayerDefinition getOpponent() {
|
||||
return playerDefinitions[opponentIndex];
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ public class MagicDuel {
|
|||
public int getGamesPlayed() {
|
||||
return gamesPlayed;
|
||||
}
|
||||
|
||||
|
||||
public int getGamesTotal() {
|
||||
return (playerDefinitions.length-1)*configuration.getNrOfGames();
|
||||
}
|
||||
|
@ -82,11 +82,11 @@ public class MagicDuel {
|
|||
private void determineStartPlayer() {
|
||||
startPlayer=MagicRandom.nextInt(2);
|
||||
}
|
||||
|
||||
|
||||
public void setStartPlayer(final int startPlayer) {
|
||||
this.startPlayer=startPlayer;
|
||||
}
|
||||
|
||||
|
||||
private int getStartPlayer() {
|
||||
return startPlayer;
|
||||
}
|
||||
|
@ -98,37 +98,37 @@ public class MagicDuel {
|
|||
public MagicAI[] getAIs() {
|
||||
return ais;
|
||||
}
|
||||
|
||||
|
||||
public void setDifficulty(final int diff) {
|
||||
setDifficulty(0,diff);
|
||||
setDifficulty(1,diff);
|
||||
}
|
||||
|
||||
|
||||
public void setDifficulty(final int idx, final int diff) {
|
||||
difficulty[idx] = diff;
|
||||
}
|
||||
|
||||
|
||||
int getDifficulty() {
|
||||
return getDifficulty(0);
|
||||
}
|
||||
|
||||
|
||||
int getDifficulty(final int idx) {
|
||||
return difficulty[idx];
|
||||
}
|
||||
|
||||
|
||||
public void updateDifficulty() {
|
||||
difficulty[0] = GeneralConfig.getInstance().getDifficulty();
|
||||
difficulty[1] = GeneralConfig.getInstance().getDifficulty();
|
||||
}
|
||||
|
||||
|
||||
public boolean isEditable() {
|
||||
return gameNr==1;
|
||||
}
|
||||
|
||||
|
||||
public boolean isFinished() {
|
||||
return getGamesPlayed()==getGamesTotal();
|
||||
}
|
||||
|
||||
|
||||
void advance(final boolean won, final MagicGame game) {
|
||||
gamesPlayed++;
|
||||
if (won) {
|
||||
|
@ -147,11 +147,11 @@ public class MagicDuel {
|
|||
history.update(won,game,configuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<Integer> getAvatarIndices(final int avatars) {
|
||||
final List<Integer> indices=new ArrayList<Integer>();
|
||||
for (int index=0;index<avatars;index++) {
|
||||
|
||||
|
||||
indices.add(index);
|
||||
}
|
||||
return indices;
|
||||
|
@ -167,19 +167,19 @@ public class MagicDuel {
|
|||
final MagicPlayerDefinition player=new MagicPlayerDefinition(configuration.getName(),false,configuration.getPlayerProfile(),playerFace);
|
||||
players[0]=player;
|
||||
avatars.remove(playerFace);
|
||||
|
||||
|
||||
final int findex=MagicRandom.nextInt(avatars.size());
|
||||
final Integer computerFace=avatars.get(findex);
|
||||
players[1]=new MagicPlayerDefinition(COMPUTER,true,configuration.getOpponentProfile(),computerFace);
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
|
||||
public MagicGame nextGame(final boolean sound) {
|
||||
//create players
|
||||
final MagicPlayer player = new MagicPlayer(configuration.getStartLife(),playerDefinitions[0],0);
|
||||
final MagicPlayer opponent = new MagicPlayer(configuration.getStartLife(),playerDefinitions[opponentIndex],1);
|
||||
|
||||
|
||||
//give the AI player extra life
|
||||
opponent.setLife(opponent.getLife() + GeneralConfig.getInstance().getExtraLife());
|
||||
|
||||
|
@ -199,23 +199,23 @@ public class MagicDuel {
|
|||
opponent.createHandAndLibrary(configuration.getHandSize());
|
||||
return game;
|
||||
}
|
||||
|
||||
|
||||
public int getNrOfPlayers() {
|
||||
return playerDefinitions.length;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerDefinition getPlayer(final int index) {
|
||||
return playerDefinitions[index];
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerDefinition[] getPlayers() {
|
||||
return playerDefinitions;
|
||||
}
|
||||
|
||||
|
||||
public void setPlayers(final MagicPlayerDefinition[] aPlayerDefinitions) {
|
||||
this.playerDefinitions=aPlayerDefinitions;
|
||||
}
|
||||
|
||||
|
||||
public void buildDeck(final MagicPlayerDefinition player) {
|
||||
final MagicCubeDefinition cubeDefinition = CubeDefinitions.getCubeDefinition(configuration.getCube());
|
||||
final DefaultDeckGenerator generator = new DefaultDeckGenerator(cubeDefinition);
|
||||
|
@ -225,7 +225,7 @@ public class MagicDuel {
|
|||
player.generateDeck(generator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void buildDecks() {
|
||||
final MagicCubeDefinition cubeDefinition=CubeDefinitions.getCubeDefinition(configuration.getCube());
|
||||
final DefaultDeckGenerator generator = new DefaultDeckGenerator(cubeDefinition);
|
||||
|
@ -237,55 +237,55 @@ public class MagicDuel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void initialize() {
|
||||
playerDefinitions=createPlayers();
|
||||
buildDecks();
|
||||
history.loadHistory(configuration.getName());
|
||||
}
|
||||
|
||||
|
||||
public static final File getDuelFile() {
|
||||
return new File(MagicMain.getGamePath(),"duel.txt");
|
||||
return new File(MagicMain.getGamePath(),"duel.txt");
|
||||
}
|
||||
|
||||
|
||||
private static String getPlayerPrefix(final int index) {
|
||||
return "p"+(index+1)+".";
|
||||
}
|
||||
|
||||
|
||||
private void save(final Properties properties) {
|
||||
configuration.save(properties);
|
||||
|
||||
|
||||
properties.setProperty(OPPONENT,Integer.toString(opponentIndex));
|
||||
properties.setProperty(GAME,Integer.toString(gameNr));
|
||||
properties.setProperty(PLAYED,Integer.toString(gamesPlayed));
|
||||
properties.setProperty(WON,Integer.toString(gamesWon));
|
||||
properties.setProperty(START,Integer.toString(startPlayer));
|
||||
|
||||
|
||||
for (int index=0;index<playerDefinitions.length;index++) {
|
||||
playerDefinitions[index].save(properties,getPlayerPrefix(index));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void save(final File file) {
|
||||
final Properties properties=new Properties();
|
||||
save(properties);
|
||||
try { //save to file
|
||||
try { //save to file
|
||||
magic.data.FileIO.toFile(file, properties, "Duel");
|
||||
System.err.println("Saved duel");
|
||||
} catch (final IOException ex) {
|
||||
System.err.println("ERROR! Unable save duel to " + file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void load(final Properties properties) {
|
||||
configuration.load(properties);
|
||||
|
||||
|
||||
opponentIndex=Integer.parseInt(properties.getProperty(OPPONENT,"1"));
|
||||
gameNr=Integer.parseInt(properties.getProperty(GAME,"1"));
|
||||
gamesPlayed=Integer.parseInt(properties.getProperty(PLAYED,"0"));
|
||||
gamesWon=Integer.parseInt(properties.getProperty(WON,"0"));
|
||||
startPlayer=Integer.parseInt(properties.getProperty(START,"0"));
|
||||
|
||||
|
||||
playerDefinitions=new MagicPlayerDefinition[2];
|
||||
for (int index=0;index<playerDefinitions.length;index++) {
|
||||
playerDefinitions[index]=new MagicPlayerDefinition();
|
||||
|
@ -293,11 +293,11 @@ public class MagicDuel {
|
|||
}
|
||||
history.loadHistory(configuration.getName());
|
||||
}
|
||||
|
||||
|
||||
public void load(final File file) {
|
||||
load(magic.data.FileIO.toProp(file));
|
||||
}
|
||||
|
||||
|
||||
public void restart() {
|
||||
opponentIndex=1;
|
||||
gameNr=1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,12 +10,12 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.Date;
|
||||
|
||||
public class MagicGameLog {
|
||||
|
||||
|
||||
private static final String gameLog = MagicMain.getGamePath() + File.separator + "game.log";
|
||||
private static PrintWriter writer;
|
||||
|
||||
|
||||
private MagicGameLog() {}
|
||||
|
||||
|
||||
public static void initialize() {
|
||||
try {
|
||||
writer = new PrintWriter(gameLog);
|
||||
|
@ -35,14 +35,14 @@ public class MagicGameLog {
|
|||
System.err.println("Unable to create game log");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void log(final String message) {
|
||||
if (writer != null) {
|
||||
writer.println(message);
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void close() {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
|
|
|
@ -14,7 +14,7 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.Date;
|
||||
|
||||
public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
|
||||
public void uncaughtException(final Thread th, final Throwable ex) {
|
||||
MagicGameReport.buildReport(MagicGame.getInstance(), th, ex);
|
||||
System.exit(1);
|
||||
|
@ -23,7 +23,7 @@ public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
|||
private static void buildCard(final MagicGame game,final String place,final MagicCard card,final StringBuilder report) {
|
||||
report.append(" - ").append(place).append(" : ").append(card.getName()).append("\n");
|
||||
}
|
||||
|
||||
|
||||
private static void buildPermanent(final MagicGame game,final MagicPermanent permanent,final StringBuilder report) {
|
||||
report.append(" - Permanent : ").append(permanent.getName());
|
||||
if (permanent.isCreature()) {
|
||||
|
@ -40,7 +40,7 @@ public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
|||
}
|
||||
report.append("\n");
|
||||
}
|
||||
|
||||
|
||||
private static void buildPlayer(final MagicGame game,final MagicPlayer player,final StringBuilder report) {
|
||||
report.append(player.getIndex()).append("] ");
|
||||
report.append("Player : ").append(player.getName());
|
||||
|
@ -55,12 +55,12 @@ public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
|||
for (final MagicCard card: player.getGraveyard()) {
|
||||
buildCard(game,"Graveyard",card,report);
|
||||
}
|
||||
|
||||
|
||||
for (final MagicPermanent permanent : player.getPermanents()) {
|
||||
buildPermanent(game,permanent,report);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void buildStack(final MagicGame game,final StringBuilder report) {
|
||||
report.append("Stack : ").append(game.getStack().size()).append('\n');
|
||||
for (final MagicItemOnStack itemOnStack : game.getStack()) {
|
||||
|
@ -85,7 +85,7 @@ public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
|||
}
|
||||
report.append("Score = ").append(totalScore).append("\n");
|
||||
}
|
||||
|
||||
|
||||
private static String buildReport(final MagicGame game) {
|
||||
final StringBuilder report=new StringBuilder();
|
||||
report.append("Turn : ").append(game.getTurn());
|
||||
|
@ -94,13 +94,13 @@ public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
|||
report.append(" Player : ").append(game.getTurnPlayer());
|
||||
report.append(" Score : ").append(game.getScore());
|
||||
report.append("\n");
|
||||
|
||||
|
||||
for (final MagicPlayer player : game.getPlayers()) {
|
||||
buildPlayer(game,player,report);
|
||||
}
|
||||
|
||||
buildStack(game,report);
|
||||
buildScore(game,report);
|
||||
buildScore(game,report);
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ public class MagicGameReport implements Thread.UncaughtExceptionHandler {
|
|||
//save a copy to a crash log file
|
||||
final File clog = new File(MagicMain.getGamePath(), "crash.log");
|
||||
try {
|
||||
FileIO.toFile(clog, sb.toString(), true);
|
||||
FileIO.toFile(clog, sb.toString(), true);
|
||||
} catch (final IOException ex3) {
|
||||
System.err.println("Unable to save crash log");
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ public enum MagicIdentifierType {
|
|||
Permanent,
|
||||
PermanentTrigger,
|
||||
ItemOnStack;
|
||||
|
||||
|
||||
public static final int NR_OF_IDENTIFIERS=values().length;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public class MagicLogBook extends ArrayList<MagicMessage> {
|
|||
}
|
||||
return super.add(msg);
|
||||
}
|
||||
|
||||
|
||||
/** Removes all messages from end to given index, inclusive. */
|
||||
public synchronized void removeTo(final int toIndex) {
|
||||
for (int index=size()-1;index>=toIndex;index--) {
|
||||
|
|
|
@ -4,12 +4,12 @@ public class MagicLogMessageBuilder {
|
|||
|
||||
private final MagicGame game;
|
||||
private final StringBuilder[] messageBuilders;
|
||||
|
||||
|
||||
MagicLogMessageBuilder(final MagicGame game) {
|
||||
this.game=game;
|
||||
messageBuilders=new StringBuilder[]{new StringBuilder(),new StringBuilder()};
|
||||
}
|
||||
|
||||
|
||||
void appendMessage(final MagicPlayer player,final String message) {
|
||||
final StringBuilder messageBuilder=messageBuilders[player.getIndex()];
|
||||
if (messageBuilder.length()>0) {
|
||||
|
@ -17,7 +17,7 @@ public class MagicLogMessageBuilder {
|
|||
}
|
||||
messageBuilder.append(message);
|
||||
}
|
||||
|
||||
|
||||
void logMessages() {
|
||||
for (final MagicPlayer player : game.getPlayers()) {
|
||||
final StringBuilder messageBuilder=messageBuilders[player.getIndex()];
|
||||
|
@ -27,7 +27,7 @@ public class MagicLogMessageBuilder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clearMessages() {
|
||||
messageBuilders[0].setLength(0);
|
||||
messageBuilders[1].setLength(0);
|
||||
|
|
|
@ -22,7 +22,7 @@ public class MagicManaCost {
|
|||
|
||||
private static final int[] SINGLE_PENALTY={0,1,1,3,6,9};
|
||||
private static final int[] DOUBLE_PENALTY={0,0,1,2,4,6};
|
||||
|
||||
|
||||
private static final ImageIcon[] COLORLESS_ICONS={
|
||||
IconImages.COST_ZERO,
|
||||
IconImages.COST_ONE,
|
||||
|
@ -42,7 +42,7 @@ public class MagicManaCost {
|
|||
IconImages.COST_FIFTEEN,
|
||||
IconImages.COST_SIXTEEN
|
||||
};
|
||||
|
||||
|
||||
public static final MagicManaCost ZERO=MagicManaCost.create("{0}");
|
||||
|
||||
private final String costText;
|
||||
|
@ -65,13 +65,13 @@ public class MagicManaCost {
|
|||
while (matcher.find()) {
|
||||
addType(matcher.group(), XCountArr, convertedArr);
|
||||
}
|
||||
|
||||
|
||||
XCount = XCountArr[0];
|
||||
converted = convertedArr[0];
|
||||
|
||||
//assert getCanonicalText().equals(costText) : "canonical: " + getCanonicalText() + " != cost: " + costText;
|
||||
}
|
||||
|
||||
|
||||
private void addType(final MagicCostManaType type,final int amount,final int[] convertedArr) {
|
||||
convertedArr[0] += amount;
|
||||
amounts[type.ordinal()] += amount;
|
||||
|
@ -79,7 +79,7 @@ public class MagicManaCost {
|
|||
order.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addType(final String typeText, final int[] XCountArr, final int[] convertedArr) {
|
||||
final String symbol = typeText.substring(1, typeText.length() - 1);
|
||||
if ("X".equals(symbol)) {
|
||||
|
@ -96,7 +96,7 @@ public class MagicManaCost {
|
|||
throw new RuntimeException("Invalid cost \"" + costText + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean isNumeric(final String str) {
|
||||
for (final char c : str.toCharArray()) {
|
||||
if (!Character.isDigit(c)) {
|
||||
|
@ -109,19 +109,19 @@ public class MagicManaCost {
|
|||
public String getText() {
|
||||
return costText;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return costText;
|
||||
}
|
||||
|
||||
|
||||
public int getXCount() {
|
||||
return XCount;
|
||||
}
|
||||
public boolean hasX() {
|
||||
return XCount > 0;
|
||||
}
|
||||
|
||||
|
||||
public List<MagicCostManaType> getCostManaTypes(final int x) {
|
||||
final List<MagicCostManaType> types=new ArrayList<MagicCostManaType>();
|
||||
int colorless=x;
|
||||
|
@ -136,14 +136,14 @@ public class MagicManaCost {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (;colorless>0;colorless--) {
|
||||
types.add(MagicCostManaType.Colorless);
|
||||
}
|
||||
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
public int getColorFlags() {
|
||||
int colorFlags = 0;
|
||||
for (final MagicCostManaType costType : order) {
|
||||
|
@ -155,7 +155,7 @@ public class MagicManaCost {
|
|||
}
|
||||
return colorFlags;
|
||||
}
|
||||
|
||||
|
||||
private String getCanonicalText() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
//add X
|
||||
|
@ -248,9 +248,9 @@ public class MagicManaCost {
|
|||
icons.add(icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<ImageIcon> getIcons() {
|
||||
if (icons == null) {
|
||||
icons=new ArrayList<ImageIcon>();
|
||||
|
@ -258,7 +258,7 @@ public class MagicManaCost {
|
|||
}
|
||||
return icons;
|
||||
}
|
||||
|
||||
|
||||
int getCostScore(final MagicPlayerProfile profile) {
|
||||
final int[] singleCounts=new int[MagicManaType.NR_OF_TYPES];
|
||||
int doubleCount=0;
|
||||
|
@ -284,11 +284,11 @@ public class MagicManaCost {
|
|||
}
|
||||
return 2*converted+3*(10-SINGLE_PENALTY[maxSingleCount]-DOUBLE_PENALTY[doubleCount]);
|
||||
}
|
||||
|
||||
|
||||
public int getConvertedCost() {
|
||||
return converted;
|
||||
}
|
||||
|
||||
|
||||
public MagicBuilderManaCost getBuilderCost() {
|
||||
if (builderCost == null) {
|
||||
builderCost=new MagicBuilderManaCost();
|
||||
|
@ -296,17 +296,17 @@ public class MagicManaCost {
|
|||
}
|
||||
return builderCost;
|
||||
}
|
||||
|
||||
|
||||
public void addTo(final MagicBuilderManaCost aBuilderCost) {
|
||||
for (final MagicCostManaType type : order) {
|
||||
aBuilderCost.addType(type,amounts[type.ordinal()]);
|
||||
}
|
||||
if (hasX()) {
|
||||
aBuilderCost.setXCount(XCount);
|
||||
}
|
||||
}
|
||||
aBuilderCost.compress();
|
||||
}
|
||||
|
||||
|
||||
public void addTo(final MagicBuilderManaCost aBuilderCost,final int x) {
|
||||
for (final MagicCostManaType type : order) {
|
||||
aBuilderCost.addType(type,amounts[type.ordinal()]);
|
||||
|
@ -314,7 +314,7 @@ public class MagicManaCost {
|
|||
aBuilderCost.addType(MagicCostManaType.Colorless,x);
|
||||
aBuilderCost.compress();
|
||||
}
|
||||
|
||||
|
||||
public MagicCondition getCondition() {
|
||||
MagicCondition cond = CONDS_MAP.get(costText);
|
||||
if (cond == null) {
|
||||
|
@ -323,7 +323,7 @@ public class MagicManaCost {
|
|||
}
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
public static MagicManaCost create(final String costText) {
|
||||
MagicManaCost cost = COSTS_MAP.get(costText);
|
||||
if (cost == null) {
|
||||
|
|
|
@ -17,17 +17,17 @@ public enum MagicManaType {
|
|||
White("white","{W}"),
|
||||
NONE("none","{N}"),
|
||||
;
|
||||
|
||||
|
||||
public static final List<MagicManaType> ALL_COLORS = Collections.unmodifiableList(Arrays.asList(
|
||||
Black,Blue,Green,Red,White));
|
||||
public static final List<MagicManaType> ALL_TYPES = Collections.unmodifiableList(Arrays.asList(
|
||||
Colorless,Black,Blue,Green,Red,White)); // Colorless must be in front.
|
||||
|
||||
|
||||
public static final int NR_OF_TYPES = ALL_TYPES.size();
|
||||
|
||||
|
||||
private final String name;
|
||||
private final String text;
|
||||
|
||||
|
||||
private MagicManaType(final String name, final String text) {
|
||||
this.name=name;
|
||||
this.text=text;
|
||||
|
@ -36,15 +36,15 @@ public enum MagicManaType {
|
|||
public boolean isValid() {
|
||||
return this != MagicManaType.NONE;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public static MagicManaType get(final String name) {
|
||||
for (final MagicManaType type : values()) {
|
||||
if (type.toString().equalsIgnoreCase(name)) {
|
||||
|
@ -53,7 +53,7 @@ public enum MagicManaType {
|
|||
}
|
||||
throw new RuntimeException("Unknown mana type " + name);
|
||||
}
|
||||
|
||||
|
||||
public static List<MagicManaType> getList(final String name) {
|
||||
if ("{1}".equals(name)) {
|
||||
return Arrays.asList(Colorless);
|
||||
|
@ -74,7 +74,7 @@ public enum MagicManaType {
|
|||
public String toString() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public MagicColor getColor() {
|
||||
switch (this) {
|
||||
case Black: return MagicColor.Black;
|
||||
|
@ -85,7 +85,7 @@ public enum MagicManaType {
|
|||
}
|
||||
throw new RuntimeException("No color available for MagicManaType " + this);
|
||||
}
|
||||
|
||||
|
||||
public ImageIcon getIcon(final boolean small) {
|
||||
switch (this) {
|
||||
case Colorless: return small?IconImages.COST_ONE:IconImages.ONE;
|
||||
|
|
|
@ -12,7 +12,7 @@ public class MagicMessage {
|
|||
private final int turn;
|
||||
private final MagicPhaseType phaseType;
|
||||
private final String text;
|
||||
|
||||
|
||||
MagicMessage(final MagicGame game,final MagicPlayer player,final String text) {
|
||||
this.player=player;
|
||||
this.life=player.getLife();
|
||||
|
@ -24,19 +24,19 @@ public class MagicMessage {
|
|||
public MagicPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
|
||||
public int getLife() {
|
||||
return life;
|
||||
}
|
||||
|
||||
|
||||
public int getTurn() {
|
||||
return turn;
|
||||
}
|
||||
|
||||
|
||||
public MagicPhaseType getPhaseType() {
|
||||
return phaseType;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class MagicMessage {
|
|||
final Iterator<String> iterator=names.iterator();
|
||||
do {
|
||||
final String name=iterator.next();
|
||||
next=iterator.hasNext();
|
||||
next=iterator.hasNext();
|
||||
if (first) {
|
||||
first=false;
|
||||
} else if (next) {
|
||||
|
@ -60,14 +60,14 @@ public class MagicMessage {
|
|||
} while (next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String replaceName(final String sourceText,final Object source, final Object player, final Object ref) {
|
||||
return sourceText
|
||||
.replaceAll("PN", player.toString())
|
||||
.replaceAll("SN", source.toString())
|
||||
.replaceAll("RN", ref.toString());
|
||||
}
|
||||
|
||||
|
||||
public static String replaceChoices(final String sourceText,final Object[] choices) {
|
||||
String result = sourceText;
|
||||
for (int idx = 0; result.indexOf('$') >= 0; idx++) {
|
||||
|
|
|
@ -8,49 +8,49 @@ import magic.model.MagicCopyable;
|
|||
public class MagicPayedCost implements MagicCopyable {
|
||||
|
||||
public static final MagicPayedCost NO_COST = new MagicPayedCost();
|
||||
|
||||
|
||||
private MagicTarget target;
|
||||
private int x;
|
||||
private int kicker;
|
||||
|
||||
|
||||
public MagicPayedCost() {
|
||||
target = MagicTargetNone.getInstance();
|
||||
x = 0;
|
||||
kicker = 0;
|
||||
}
|
||||
|
||||
|
||||
public MagicPayedCost(final MagicPayedCost payedCost) {
|
||||
target = payedCost.target;
|
||||
x = payedCost.x;
|
||||
kicker = payedCost.kicker;
|
||||
}
|
||||
|
||||
|
||||
public MagicPayedCost(final MagicCopyMap copyMap,final MagicPayedCost payedCost) {
|
||||
target = copyMap.copy(payedCost.target);
|
||||
x = payedCost.x;
|
||||
kicker = payedCost.kicker;
|
||||
}
|
||||
|
||||
|
||||
public MagicCopyable copy(final MagicCopyMap copyMap) {
|
||||
return new MagicPayedCost(copyMap, this);
|
||||
}
|
||||
|
||||
|
||||
private void setTarget(final MagicTarget target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
|
||||
public MagicTarget getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
private void setX(final int x) {
|
||||
this.x = x;
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void set(final Object choiceResult) {
|
||||
if (choiceResult instanceof MagicTarget) {
|
||||
setTarget((MagicTarget)choiceResult);
|
||||
|
@ -58,7 +58,7 @@ public class MagicPayedCost implements MagicCopyable {
|
|||
setX(((MagicPayManaCostResult)choiceResult).getX());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setKicker(final int aKicker) {
|
||||
kicker = aKicker;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public class MagicPayedCost implements MagicCopyable {
|
|||
public int getKicker() {
|
||||
return kicker;
|
||||
}
|
||||
|
||||
|
||||
public boolean isKicked() {
|
||||
return kicker > 0;
|
||||
}
|
||||
|
|
|
@ -36,22 +36,22 @@ import java.util.Collections;
|
|||
public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicPermanent> {
|
||||
|
||||
public static final int NO_COLOR_FLAGS=-1;
|
||||
|
||||
|
||||
private final long id;
|
||||
private final MagicCardDefinition cardDefinition;
|
||||
private final MagicCard card;
|
||||
private final MagicPlayer firstController;
|
||||
private MagicPermanent equippedCreature = MagicPermanent.NONE;
|
||||
private final MagicPermanentSet equipmentPermanents;
|
||||
private final MagicPermanentSet equipmentPermanents;
|
||||
private MagicPermanent enchantedCreature = MagicPermanent.NONE;
|
||||
private final MagicPermanentSet auraPermanents;
|
||||
private final MagicPermanentSet auraPermanents;
|
||||
private MagicPermanent blockedCreature = MagicPermanent.NONE;
|
||||
private final MagicPermanentList blockingCreatures;
|
||||
private final MagicPermanentList blockingCreatures;
|
||||
private MagicPermanent pairedCreature = MagicPermanent.NONE;
|
||||
private final MagicCardList exiledCards;
|
||||
private MagicTarget chosenTarget = MagicTargetNone.getInstance();
|
||||
private int[] counters=new int[MagicCounterType.NR_COUNTERS];
|
||||
private int stateFlags =
|
||||
private int stateFlags =
|
||||
MagicPermanentState.Summoned.getMask() |
|
||||
MagicPermanentState.MustPayEchoCost.getMask();
|
||||
private int abilityPlayedThisTurn;
|
||||
|
@ -78,7 +78,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
card = aCard;
|
||||
cardDefinition = card.getCardDefinition();
|
||||
firstController = aController;
|
||||
|
||||
|
||||
equipmentPermanents=new MagicPermanentSet();
|
||||
auraPermanents=new MagicPermanentSet();
|
||||
blockingCreatures=new MagicPermanentList();
|
||||
|
@ -88,9 +88,9 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
private MagicPermanent(final MagicCopyMap copyMap, final MagicPermanent sourcePermanent) {
|
||||
id = sourcePermanent.id;
|
||||
cardDefinition = sourcePermanent.cardDefinition;
|
||||
|
||||
|
||||
copyMap.put(sourcePermanent, this);
|
||||
|
||||
|
||||
card = copyMap.copy(sourcePermanent.card);
|
||||
firstController = copyMap.copy(sourcePermanent.firstController);
|
||||
stateFlags=sourcePermanent.stateFlags;
|
||||
|
@ -110,7 +110,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
fixedScore=sourcePermanent.fixedScore;
|
||||
score=sourcePermanent.score;
|
||||
stateId=sourcePermanent.stateId;
|
||||
|
||||
|
||||
cachedController = copyMap.copy(sourcePermanent.cachedController);
|
||||
cachedTypeFlags = sourcePermanent.cachedTypeFlags;
|
||||
cachedSubTypeFlags = sourcePermanent.cachedSubTypeFlags;
|
||||
|
@ -118,18 +118,18 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
cachedAbilityFlags = sourcePermanent.cachedAbilityFlags;
|
||||
cachedPowerToughness = sourcePermanent.cachedPowerToughness;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicPermanent copy(final MagicCopyMap copyMap) {
|
||||
return new MagicPermanent(copyMap, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicPermanent map(final MagicGame game) {
|
||||
final MagicPlayer mappedController=getController().map(game);
|
||||
return mappedController.getPermanents().getPermanent(id);
|
||||
}
|
||||
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -137,11 +137,11 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean isInvalid() {
|
||||
return !isValid();
|
||||
}
|
||||
|
||||
|
||||
public long getStateId() {
|
||||
stateId = stateId != 0 ? stateId : magic.MurmurHash3.hash(new long[] {
|
||||
cardDefinition.getIndex(),
|
||||
|
@ -170,39 +170,39 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
});
|
||||
return stateId;
|
||||
}
|
||||
|
||||
|
||||
/** Determines uniqueness of a mana permanent, e.g. for producing mana, all Mountains are equal. */
|
||||
public int getManaId() {
|
||||
// Creatures or lands that can be animated are unique by default.
|
||||
if (cardDefinition.hasExcludeManaOrCombat()) {
|
||||
return (int)id;
|
||||
}
|
||||
}
|
||||
// Uniqueness is determined by card definition and number of charge counters.
|
||||
return -((cardDefinition.getIndex()<<16)+getCounters(MagicCounterType.Charge));
|
||||
}
|
||||
|
||||
|
||||
public MagicCard getCard() {
|
||||
return card;
|
||||
}
|
||||
|
||||
|
||||
public boolean isToken() {
|
||||
return card.isToken();
|
||||
}
|
||||
|
||||
|
||||
public boolean isNonToken() {
|
||||
return !card.isToken();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicCardDefinition getCardDefinition() {
|
||||
return cardDefinition;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<MagicActivation> getActivations() {
|
||||
return cardDefinition.getActivations();
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicManaActivation> getManaActivations() {
|
||||
return cardDefinition.getManaActivations();
|
||||
}
|
||||
|
@ -210,11 +210,11 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public Collection<MagicStatic> getStatics() {
|
||||
return cardDefinition.getStatics();
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicTrigger<?>> getTriggers() {
|
||||
return cardDefinition.getTriggers();
|
||||
}
|
||||
|
||||
|
||||
public Collection<MagicWhenComesIntoPlayTrigger> getComeIntoPlayTriggers() {
|
||||
return cardDefinition.getComeIntoPlayTriggers();
|
||||
}
|
||||
|
@ -226,15 +226,15 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public boolean producesMana() {
|
||||
return !cardDefinition.getManaActivations().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public int countManaActivations() {
|
||||
return cardDefinition.getManaActivations().size();
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return card.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
|
@ -252,12 +252,12 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public MagicPlayer getFirstController() {
|
||||
return firstController;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayer getController() {
|
||||
assert cachedController != null : "cachedController is null in " + this;
|
||||
return cachedController;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayer getOpponent() {
|
||||
return getController().getOpponent();
|
||||
}
|
||||
|
@ -265,35 +265,35 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public boolean isFriend(final MagicObject other) {
|
||||
return getController() == other.getController();
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnemy(final MagicObject other) {
|
||||
return getController() != other.getController();
|
||||
}
|
||||
|
||||
|
||||
public boolean isController(final MagicTarget player) {
|
||||
return getController() == player;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOwner(final MagicTarget player) {
|
||||
return getOwner() == player;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOpponent(final MagicTarget player) {
|
||||
return getOpponent() == player;
|
||||
}
|
||||
|
||||
|
||||
public static void update(final MagicGame game) {
|
||||
MagicPermanent.updateProperties(game);
|
||||
MagicPermanent.updateScoreFixController(game);
|
||||
}
|
||||
|
||||
|
||||
public static void updateScoreFixController(final MagicGame game) {
|
||||
for (final MagicPlayer player : game.getPlayers()) {
|
||||
for (final MagicPermanent perm : player.getPermanents()) {
|
||||
final MagicPlayer curr = perm.getController();
|
||||
if (!curr.controlsPermanent(perm)) {
|
||||
game.addDelayedAction(new MagicChangeControlAction(curr, perm, perm.getScore()));
|
||||
}
|
||||
}
|
||||
perm.updateScore();
|
||||
}}
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void apply(final MagicLayer layer) {
|
||||
switch (layer) {
|
||||
case Card:
|
||||
|
@ -369,48 +369,48 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public void setState(final MagicPermanentState state) {
|
||||
stateFlags|=state.getMask();
|
||||
}
|
||||
|
||||
|
||||
public void clearState(final MagicPermanentState state) {
|
||||
stateFlags&=Integer.MAX_VALUE-state.getMask();
|
||||
}
|
||||
|
||||
|
||||
public boolean hasState(final MagicPermanentState state) {
|
||||
return state.hasState(stateFlags);
|
||||
}
|
||||
|
||||
|
||||
public int getStateFlags() {
|
||||
return stateFlags;
|
||||
}
|
||||
|
||||
|
||||
public void setStateFlags(final int flags) {
|
||||
stateFlags=flags;
|
||||
}
|
||||
|
||||
|
||||
public boolean isTapped() {
|
||||
return hasState(MagicPermanentState.Tapped);
|
||||
}
|
||||
|
||||
|
||||
public boolean isUntapped() {
|
||||
return !hasState(MagicPermanentState.Tapped);
|
||||
}
|
||||
|
||||
|
||||
private int getColorFlags() {
|
||||
return cachedColorFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasColor(final MagicColor color) {
|
||||
return color.hasColor(getColorFlags());
|
||||
return color.hasColor(getColorFlags());
|
||||
}
|
||||
|
||||
|
||||
public void changeCounters(final MagicCounterType counterType,final int amount) {
|
||||
counters[counterType.ordinal()]+=amount;
|
||||
}
|
||||
|
||||
|
||||
public int getCounters(final MagicCounterType counterType) {
|
||||
return counters[counterType.ordinal()];
|
||||
}
|
||||
|
||||
|
||||
public boolean hasCounters() {
|
||||
for (final int amount : counters) {
|
||||
if (amount>0) {
|
||||
|
@ -419,7 +419,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasSubType(final MagicSubType subType) {
|
||||
return cachedSubTypeFlags.contains(subType);
|
||||
}
|
||||
|
@ -431,15 +431,15 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public MagicPowerToughness getPowerToughness() {
|
||||
return cachedPowerToughness;
|
||||
}
|
||||
|
||||
|
||||
public int getPower() {
|
||||
return getPowerToughness().getPositivePower();
|
||||
}
|
||||
|
||||
|
||||
public int getToughness() {
|
||||
return getPowerToughness().getPositiveToughness();
|
||||
}
|
||||
|
||||
|
||||
public Set<MagicAbility> getAbilityFlags() {
|
||||
return cachedAbilityFlags;
|
||||
}
|
||||
|
@ -448,33 +448,33 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public boolean hasAbility(final MagicAbility ability) {
|
||||
return cachedAbilityFlags.contains(ability);
|
||||
}
|
||||
|
||||
|
||||
private void updateScore() {
|
||||
stateId = 0;
|
||||
fixedScore = ArtificialScoringSystem.getFixedPermanentScore(this);
|
||||
score = fixedScore + ArtificialScoringSystem.getVariablePermanentScore(this);
|
||||
}
|
||||
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public int getStaticScore() {
|
||||
return cardDefinition.getStaticType().getScore(this);
|
||||
}
|
||||
|
||||
|
||||
public int getCardScore() {
|
||||
return cardDefinition.getScore();
|
||||
}
|
||||
|
||||
|
||||
public int getDamage() {
|
||||
return damage;
|
||||
}
|
||||
|
||||
|
||||
public void setDamage(final int damage) {
|
||||
this.damage=damage;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPreventDamage() {
|
||||
return preventDamage;
|
||||
|
@ -488,49 +488,49 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public int getLethalDamage(final int toughness) {
|
||||
return toughness<=damage?0:toughness-damage;
|
||||
}
|
||||
|
||||
|
||||
// Tap symbol.
|
||||
public boolean canTap() {
|
||||
return !hasState(MagicPermanentState.Tapped) &&
|
||||
(!hasState(MagicPermanentState.Summoned) ||
|
||||
!isCreature() ||
|
||||
return !hasState(MagicPermanentState.Tapped) &&
|
||||
(!hasState(MagicPermanentState.Summoned) ||
|
||||
!isCreature() ||
|
||||
hasAbility(MagicAbility.Haste)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Untap symbol.
|
||||
public boolean canUntap() {
|
||||
return hasState(MagicPermanentState.Tapped) &&
|
||||
(!hasState(MagicPermanentState.Summoned) ||
|
||||
!isCreature() ||
|
||||
return hasState(MagicPermanentState.Tapped) &&
|
||||
(!hasState(MagicPermanentState.Summoned) ||
|
||||
!isCreature() ||
|
||||
hasAbility(MagicAbility.Haste)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public boolean canRegenerate() {
|
||||
return !hasState(MagicPermanentState.Regenerated)&&!hasState(MagicPermanentState.CannotBeRegenerated);
|
||||
}
|
||||
|
||||
|
||||
public boolean isRegenerated() {
|
||||
return hasState(MagicPermanentState.Regenerated)&&!hasState(MagicPermanentState.CannotBeRegenerated);
|
||||
}
|
||||
|
||||
|
||||
public boolean isAttacking() {
|
||||
return hasState(MagicPermanentState.Attacking);
|
||||
}
|
||||
|
||||
|
||||
public boolean isBlocked() {
|
||||
return hasState(MagicPermanentState.Blocked);
|
||||
}
|
||||
|
||||
|
||||
public boolean isBlocking() {
|
||||
return hasState(MagicPermanentState.Blocking);
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanent getBlockedCreature() {
|
||||
return blockedCreature;
|
||||
}
|
||||
|
||||
|
||||
public void setBlockedCreature(final MagicPermanent creature) {
|
||||
if (creature.isValid()) {
|
||||
blockedName = creature.getName() + creature.getId() + (100 + creature.numBlockingCreatures());
|
||||
|
@ -545,67 +545,67 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public MagicPermanentList getBlockingCreatures() {
|
||||
return blockingCreatures;
|
||||
}
|
||||
|
||||
|
||||
public int numBlockingCreatures() {
|
||||
return blockingCreatures.size();
|
||||
}
|
||||
|
||||
|
||||
public void setBlockingCreatures(final MagicPermanentList creatures) {
|
||||
blockingCreatures.clear();
|
||||
blockingCreatures.addAll(creatures);
|
||||
}
|
||||
|
||||
|
||||
public void addBlockingCreature(final MagicPermanent creature) {
|
||||
blockingCreatures.add(creature);
|
||||
}
|
||||
|
||||
|
||||
public void removeBlockingCreature(final MagicPermanent creature) {
|
||||
blockingCreatures.remove(creature);
|
||||
}
|
||||
|
||||
|
||||
public void removeBlockingCreatures() {
|
||||
blockingCreatures.clear();
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanent getPairedCreature() {
|
||||
return pairedCreature;
|
||||
}
|
||||
|
||||
|
||||
public void setPairedCreature(final MagicPermanent creature) {
|
||||
pairedCreature = creature;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPaired() {
|
||||
return pairedCreature != MagicPermanent.NONE;
|
||||
}
|
||||
|
||||
|
||||
public MagicCardList getExiledCards() {
|
||||
return exiledCards;
|
||||
}
|
||||
|
||||
|
||||
public void addExiledCard(final MagicCard card) {
|
||||
// only non tokens can be added
|
||||
if (!card.isToken()) {
|
||||
exiledCards.add(card);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeExiledCard(final MagicCard card) {
|
||||
exiledCards.remove(card);
|
||||
}
|
||||
|
||||
|
||||
public MagicTarget getChosenTarget() {
|
||||
return chosenTarget;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayer getChosenPlayer() {
|
||||
return (MagicPlayer)chosenTarget;
|
||||
}
|
||||
|
||||
|
||||
public void setChosenTarget(final MagicTarget target) {
|
||||
chosenTarget = target;
|
||||
}
|
||||
|
||||
|
||||
void generateStateBasedActions() {
|
||||
final MagicGame game = getGame();
|
||||
if (isCreature()) {
|
||||
|
@ -619,26 +619,26 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
} else if (toughness-damage<=0) {
|
||||
game.addDelayedAction(new MagicDestroyAction(this));
|
||||
}
|
||||
|
||||
|
||||
// Soulbond
|
||||
if (pairedCreature.isValid() &&
|
||||
!pairedCreature.isCreature()) {
|
||||
game.doAction(new MagicSoulbondAction(this,pairedCreature,false));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (isAura()) {
|
||||
final MagicPlayAuraEvent auraEvent = (MagicPlayAuraEvent)cardDefinition.getCardEvent();
|
||||
//not targeting since Aura is already attached
|
||||
final MagicTargetChoice tchoice = new MagicTargetChoice(auraEvent.getTargetChoice(), false);
|
||||
if (!enchantedCreature.isValid() ||
|
||||
if (!enchantedCreature.isValid() ||
|
||||
!game.isLegalTarget(getController(),this,tchoice,enchantedCreature) ||
|
||||
enchantedCreature.hasProtectionFrom(this)) {
|
||||
game.logAppendMessage(getController(),getName()+" is put into its owner's graveyard.");
|
||||
game.addDelayedAction(new MagicRemoveFromPlayAction(this,MagicLocationType.Graveyard));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (isEquipment() && equippedCreature.isValid()) {
|
||||
if (isCreature() || !equippedCreature.isCreature() || equippedCreature.hasProtectionFrom(this)) {
|
||||
game.addDelayedAction(new MagicAttachEquipmentAction(this,MagicPermanent.NONE));
|
||||
|
@ -650,7 +650,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
game.logAppendMessage(getController(),getName()+" is put into its owner's graveyard.");
|
||||
game.addDelayedAction(new MagicRemoveFromPlayAction(this,MagicLocationType.Graveyard));
|
||||
}
|
||||
|
||||
|
||||
// +1/+1 and -1/-1 counters cancel each other out.
|
||||
final int plusCounters=getCounters(MagicCounterType.PlusOne);
|
||||
if (plusCounters>0) {
|
||||
|
@ -662,7 +662,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean hasProtectionFrom(final MagicSource source) {
|
||||
// From a color.
|
||||
int numColors = 0;
|
||||
|
@ -675,7 +675,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// From monocolored.
|
||||
if (numColors == 1 &&
|
||||
hasAbility(MagicAbility.ProtectionFromMonoColored)) {
|
||||
|
@ -687,7 +687,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
|
||||
final MagicPermanent creature = (MagicPermanent)source;
|
||||
|
||||
|
||||
// From creatures.
|
||||
if (creature.hasType(MagicType.Creature) &&
|
||||
hasAbility(MagicAbility.ProtectionFromCreatures)) {
|
||||
|
@ -723,48 +723,48 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
hasAbility(MagicAbility.ProtectionFromZombies)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean canAttack() {
|
||||
if (!isCreature() ||
|
||||
!canTap() ||
|
||||
if (!isCreature() ||
|
||||
!canTap() ||
|
||||
hasState(MagicPermanentState.ExcludeFromCombat) ||
|
||||
hasState(MagicPermanentState.CannotAttack)) {
|
||||
return false;
|
||||
}
|
||||
return !hasAbility(MagicAbility.CannotAttackOrBlock) &&
|
||||
return !hasAbility(MagicAbility.CannotAttackOrBlock) &&
|
||||
!hasAbility(MagicAbility.Defender);
|
||||
}
|
||||
|
||||
|
||||
public boolean canBlock() {
|
||||
if (!isCreature() ||
|
||||
isTapped() ||
|
||||
if (!isCreature() ||
|
||||
isTapped() ||
|
||||
hasState(MagicPermanentState.ExcludeFromCombat)) {
|
||||
return false;
|
||||
}
|
||||
return !hasAbility(MagicAbility.CannotAttackOrBlock) &&
|
||||
!hasAbility(MagicAbility.CannotBlock);
|
||||
}
|
||||
|
||||
|
||||
public boolean canBeBlocked(final MagicPlayer defendingPlayer) {
|
||||
// Unblockable
|
||||
if (hasAbility(MagicAbility.Unblockable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Landwalk
|
||||
for (final MagicColor color : MagicColor.values()) {
|
||||
if (hasAbility(color.getLandwalkAbility()) &&
|
||||
if (hasAbility(color.getLandwalkAbility()) &&
|
||||
defendingPlayer.controlsPermanent(color.getLandSubType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean canBlock(final MagicPermanent attacker) {
|
||||
// Fear and Intimidate
|
||||
if (!isArtifact()) {
|
||||
|
@ -777,7 +777,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shadow
|
||||
if (attacker.hasAbility(MagicAbility.Shadow)) {
|
||||
if (!hasAbility(MagicAbility.Shadow) &&
|
||||
|
@ -787,18 +787,18 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
} else if (hasAbility(MagicAbility.Shadow)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Flying
|
||||
if (attacker.hasAbility(MagicAbility.CannotBeBlockedByFlying) &&
|
||||
hasAbility(MagicAbility.Flying)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (attacker.hasAbility(MagicAbility.CannotBeBlockedExceptWithFlying) &&
|
||||
!hasAbility(MagicAbility.Flying)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!attacker.hasAbility(MagicAbility.Flying) &&
|
||||
hasAbility(MagicAbility.CannotBlockWithoutFlying)) {
|
||||
return false;
|
||||
|
@ -809,20 +809,20 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
!hasAbility(MagicAbility.Flying) &&
|
||||
!hasAbility(MagicAbility.Reach)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attacker.hasAbility(MagicAbility.CannotBeBlockedExceptWithFlyingOrReach) &&
|
||||
!hasAbility(MagicAbility.Flying) &&
|
||||
!hasAbility(MagicAbility.Reach)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Subtype
|
||||
if (attacker.hasAbility(MagicAbility.CannotBeBlockedByHumans) &&
|
||||
hasSubType(MagicSubType.Human)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (attacker.hasAbility(MagicAbility.CannotBeBlockedExceptBySliver) &&
|
||||
!hasSubType(MagicSubType.Sliver)) {
|
||||
return false;
|
||||
|
@ -841,11 +841,11 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Protection
|
||||
return !attacker.hasProtectionFrom(this);
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanent getEquippedCreature() {
|
||||
return equippedCreature;
|
||||
}
|
||||
|
@ -853,23 +853,23 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public void setEquippedCreature(final MagicPermanent creature) {
|
||||
equippedCreature=creature;
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanentSet getEquipmentPermanents() {
|
||||
return equipmentPermanents;
|
||||
}
|
||||
|
||||
|
||||
public void addEquipment(final MagicPermanent equipment) {
|
||||
equipmentPermanents.add(equipment);
|
||||
}
|
||||
|
||||
|
||||
public void removeEquipment(final MagicPermanent equipment) {
|
||||
equipmentPermanents.remove(equipment);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEquipped() {
|
||||
return equipmentPermanents.size()>0;
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanent getEnchantedCreature() {
|
||||
return enchantedCreature;
|
||||
}
|
||||
|
@ -877,31 +877,31 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public void setEnchantedCreature(final MagicPermanent creature) {
|
||||
enchantedCreature=creature;
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanentSet getAuraPermanents() {
|
||||
return auraPermanents;
|
||||
}
|
||||
|
||||
|
||||
public void addAura(final MagicPermanent aura) {
|
||||
auraPermanents.add(aura);
|
||||
}
|
||||
|
||||
|
||||
public void removeAura(final MagicPermanent aura) {
|
||||
auraPermanents.remove(aura);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnchanted() {
|
||||
return auraPermanents.size()>0;
|
||||
}
|
||||
|
||||
|
||||
public int getAbilityPlayedThisTurn() {
|
||||
return abilityPlayedThisTurn;
|
||||
}
|
||||
|
||||
|
||||
public void setAbilityPlayedThisTurn(final int amount) {
|
||||
abilityPlayedThisTurn=amount;
|
||||
}
|
||||
|
||||
|
||||
public void incrementAbilityPlayedThisTurn() {
|
||||
abilityPlayedThisTurn++;
|
||||
}
|
||||
|
@ -909,47 +909,47 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public void decrementAbilityPlayedThisTurn() {
|
||||
abilityPlayedThisTurn--;
|
||||
}
|
||||
|
||||
|
||||
private int getTypeFlags() {
|
||||
return cachedTypeFlags;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasType(final MagicType type) {
|
||||
return type.hasType(getTypeFlags());
|
||||
}
|
||||
|
||||
|
||||
public boolean isBasic() {
|
||||
return hasType(MagicType.Basic);
|
||||
}
|
||||
|
||||
|
||||
public boolean isLand() {
|
||||
return hasType(MagicType.Land);
|
||||
}
|
||||
|
||||
|
||||
public boolean isCreature() {
|
||||
return hasType(MagicType.Creature);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEquipment() {
|
||||
return isArtifact() && hasSubType(MagicSubType.Equipment);
|
||||
}
|
||||
|
||||
|
||||
public boolean isArtifact() {
|
||||
return hasType(MagicType.Artifact);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnchantment() {
|
||||
return hasType(MagicType.Enchantment);
|
||||
}
|
||||
|
||||
|
||||
public boolean isAura() {
|
||||
return isEnchantment() && hasSubType(MagicSubType.Aura);
|
||||
}
|
||||
|
||||
|
||||
public boolean isPlaneswalker() {
|
||||
return hasType(MagicType.Planeswalker);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSpell() {
|
||||
return false;
|
||||
|
@ -959,12 +959,12 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
public boolean isPlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPermanent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidTarget(final MagicSource source) {
|
||||
// Can't be the target of spells or abilities.
|
||||
|
@ -981,7 +981,7 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
if (hasAbility(MagicAbility.CannotBeTheTarget0) && source.getController().getIndex() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Can't be the target of spells or abilities player 1 controls.
|
||||
if (hasAbility(MagicAbility.CannotBeTheTarget1) && source.getController().getIndex() == 1) {
|
||||
return false;
|
||||
|
@ -1023,11 +1023,11 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public ImageIcon getIcon() {
|
||||
if (isAttacking()) {
|
||||
return IconImages.ATTACK;
|
||||
}
|
||||
}
|
||||
if (isBlocking()) {
|
||||
return IconImages.BLOCK;
|
||||
}
|
||||
|
@ -1036,12 +1036,12 @@ public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicP
|
|||
}
|
||||
return cardDefinition.getIcon();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isLegalTarget(final MagicPlayer player, final MagicTargetFilter<? extends MagicTarget> targetFilter) {
|
||||
return getController().controlsPermanent(this);
|
||||
}
|
||||
|
||||
|
||||
public static final MagicPermanent NONE = new MagicPermanent(-1L, MagicCard.NONE, MagicPlayer.NONE) {
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
|
|
|
@ -7,11 +7,11 @@ public class MagicPermanentList extends ArrayList<MagicPermanent> implements Mag
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MagicPermanentList() {}
|
||||
|
||||
|
||||
public MagicPermanentList(final MagicPermanentList list) {
|
||||
addAll(list);
|
||||
}
|
||||
|
||||
|
||||
MagicPermanentList(final MagicCopyMap copyMap,final MagicPermanentList list) {
|
||||
for (final MagicPermanent permanent : list) {
|
||||
add(copyMap.copy(permanent));
|
||||
|
|
|
@ -7,13 +7,13 @@ public class MagicPermanentSet extends TreeSet<MagicPermanent> {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
MagicPermanentSet() {}
|
||||
|
||||
|
||||
MagicPermanentSet(final MagicCopyMap copyMap,final MagicPermanentSet source) {
|
||||
for (final MagicPermanent permanent : source) {
|
||||
add(copyMap.copy(permanent));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MagicPermanent getPermanent(final long id) {
|
||||
for (final MagicPermanent permanent : this) {
|
||||
if (permanent.getId() == id) {
|
||||
|
@ -21,8 +21,8 @@ public class MagicPermanentSet extends TreeSet<MagicPermanent> {
|
|||
}
|
||||
}
|
||||
return MagicPermanent.NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
long getStateId() {
|
||||
final long[] keys = new long[size()];
|
||||
int idx = 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package magic.model;
|
||||
|
||||
public enum MagicPermanentState {
|
||||
|
||||
|
||||
Tapped("tapped","{T}"),
|
||||
Summoned("summoned","{n}"),
|
||||
DoesNotUntapDuringNext("doesn't untap during its controller's next untap step","{s}"),
|
||||
|
@ -39,29 +39,29 @@ public enum MagicPermanentState {
|
|||
ExcludeFromCombat.getMask()|
|
||||
DestroyAtEndOfCombat.getMask()|
|
||||
MustPayEchoCost.getMask();
|
||||
|
||||
|
||||
private final String description;
|
||||
private final String text;
|
||||
private final int mask;
|
||||
|
||||
|
||||
private MagicPermanentState(final String description,final String text) {
|
||||
this.description=description;
|
||||
this.text=text;
|
||||
this.mask=1<<ordinal();
|
||||
}
|
||||
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasState(final int flags) {
|
||||
return (flags&mask)!=0;
|
||||
}
|
||||
|
|
|
@ -47,10 +47,10 @@ public class MagicPlayer implements MagicTarget {
|
|||
|
||||
private static final int LOSING_POISON=10;
|
||||
private static final long ID_FACTOR=31;
|
||||
|
||||
|
||||
private final MagicPlayerDefinition playerDefinition;
|
||||
private final int index;
|
||||
|
||||
|
||||
private int life;
|
||||
private int stateFlags;
|
||||
private int poison;
|
||||
|
@ -76,7 +76,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
playerDefinition = aPlayerDefinition;
|
||||
index = aIndex;
|
||||
life = aLife;
|
||||
|
||||
|
||||
hand=new MagicCardList();
|
||||
library=new MagicCardList();
|
||||
graveyard=new MagicCardList();
|
||||
|
@ -87,10 +87,10 @@ public class MagicPlayer implements MagicTarget {
|
|||
builderCost=new MagicBuilderManaCost();
|
||||
activationPriority=new MagicActivationPriority();
|
||||
}
|
||||
|
||||
|
||||
private MagicPlayer(final MagicCopyMap copyMap, final MagicPlayer sourcePlayer) {
|
||||
copyMap.put(sourcePlayer, this);
|
||||
|
||||
|
||||
playerDefinition = sourcePlayer.playerDefinition;
|
||||
index = sourcePlayer.index;
|
||||
life = sourcePlayer.life;
|
||||
|
@ -111,12 +111,12 @@ public class MagicPlayer implements MagicTarget {
|
|||
activationPriority=new MagicActivationPriority(sourcePlayer.activationPriority);
|
||||
cachedAbilityFlags=sourcePlayer.cachedAbilityFlags;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicPlayer copy(final MagicCopyMap copyMap) {
|
||||
return new MagicPlayer(copyMap, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicPlayer map(final MagicGame game) {
|
||||
return game.getPlayer(index);
|
||||
|
@ -129,7 +129,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
public MagicGame getGame() {
|
||||
return currGame;
|
||||
}
|
||||
|
||||
|
||||
public long getStateId() {
|
||||
keys = new long[] {
|
||||
life,
|
||||
|
@ -151,7 +151,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
};
|
||||
return magic.MurmurHash3.hash(keys);
|
||||
}
|
||||
|
||||
|
||||
String getIdString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(keys[0]);
|
||||
|
@ -161,7 +161,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
long getPlayerId(final long id) {
|
||||
// Exile is not used for id.
|
||||
long playerId=id;
|
||||
|
@ -173,20 +173,20 @@ public class MagicPlayer implements MagicTarget {
|
|||
playerId=playerId*ID_FACTOR+graveyard.getStateId();
|
||||
return playerId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return playerDefinition.getName();
|
||||
}
|
||||
|
||||
|
||||
public MagicActivationMap getActivationMap() {
|
||||
return activationMap;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerDefinition getPlayerDefinition() {
|
||||
return playerDefinition;
|
||||
}
|
||||
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
@ -194,63 +194,63 @@ public class MagicPlayer implements MagicTarget {
|
|||
public long getId() {
|
||||
return 1000000000L + index;
|
||||
}
|
||||
|
||||
|
||||
public void setState(final MagicPlayerState state) {
|
||||
stateFlags|=state.getMask();
|
||||
}
|
||||
|
||||
|
||||
public void clearState(final MagicPlayerState state) {
|
||||
stateFlags&=Integer.MAX_VALUE-state.getMask();
|
||||
}
|
||||
|
||||
|
||||
public boolean hasState(final MagicPlayerState state) {
|
||||
return state.hasState(stateFlags);
|
||||
}
|
||||
|
||||
|
||||
public int getStateFlags() {
|
||||
return stateFlags;
|
||||
}
|
||||
|
||||
|
||||
public void setStateFlags(final int flags) {
|
||||
stateFlags=flags;
|
||||
}
|
||||
|
||||
|
||||
public void setLife(final int life) {
|
||||
this.life=life;
|
||||
}
|
||||
|
||||
|
||||
public int getLife() {
|
||||
return life;
|
||||
}
|
||||
|
||||
|
||||
public void setPoison(final int poison) {
|
||||
this.poison=poison;
|
||||
}
|
||||
|
||||
|
||||
public int getPoison() {
|
||||
return poison;
|
||||
}
|
||||
|
||||
|
||||
public void changeExtraTurns(final int amount) {
|
||||
extraTurns+=amount;
|
||||
}
|
||||
|
||||
|
||||
public int getExtraTurns() {
|
||||
return extraTurns;
|
||||
}
|
||||
|
||||
|
||||
public int getHandSize() {
|
||||
return hand.size();
|
||||
}
|
||||
|
||||
|
||||
public int getNumExcessCards() {
|
||||
return Math.max(0, getHandSize() - maxHandSize);
|
||||
}
|
||||
|
||||
|
||||
public void noMaxHandSize() {
|
||||
maxHandSize = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
|
||||
public MagicCardList getHand() {
|
||||
return hand;
|
||||
}
|
||||
|
@ -259,17 +259,17 @@ public class MagicPlayer implements MagicTarget {
|
|||
hand.addToTop(card);
|
||||
activationMap.addActivations(card);
|
||||
}
|
||||
|
||||
|
||||
public void addCardToHand(final MagicCard card,final int aIndex) {
|
||||
hand.add(aIndex,card);
|
||||
activationMap.addActivations(card);
|
||||
}
|
||||
|
||||
|
||||
public int removeCardFromHand(final MagicCard card) {
|
||||
activationMap.removeActivations(card);
|
||||
return hand.removeCard(card);
|
||||
}
|
||||
|
||||
|
||||
void setHandToUnknown() {
|
||||
activationMap.removeActivations(hand);
|
||||
hand.setKnown(false);
|
||||
|
@ -292,7 +292,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
addCardToHand(library.removeCardAtTop());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void createHandAndLibrary(final int handSize) {
|
||||
for (final MagicCardDefinition cardDefinition : playerDefinition.getDeck()) {
|
||||
final long id = currGame.getUniqueId();
|
||||
|
@ -303,8 +303,8 @@ public class MagicPlayer implements MagicTarget {
|
|||
final long seed = magic.MurmurHash3.hash(new long[] {
|
||||
2 * index - 1,
|
||||
MagicGame.getCount(),
|
||||
(System.getProperty("rndSeed") != null) ?
|
||||
Long.parseLong(System.getProperty("rndSeed")) :
|
||||
(System.getProperty("rndSeed") != null) ?
|
||||
Long.parseLong(System.getProperty("rndSeed")) :
|
||||
System.currentTimeMillis()
|
||||
});
|
||||
|
||||
|
@ -318,15 +318,15 @@ public class MagicPlayer implements MagicTarget {
|
|||
public MagicCardList getLibrary() {
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
public MagicCardList getGraveyard() {
|
||||
return graveyard;
|
||||
}
|
||||
|
||||
|
||||
public MagicCardList getExile() {
|
||||
return exile;
|
||||
}
|
||||
|
||||
|
||||
public MagicPermanentSet getPermanents() {
|
||||
return permanents;
|
||||
}
|
||||
|
@ -348,15 +348,15 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
activationMap.removeActivations(permanent);
|
||||
}
|
||||
|
||||
|
||||
public List<MagicSourceManaActivation> getManaActivations(final MagicGame game) {
|
||||
final List<MagicSourceManaActivation> activations=new ArrayList<MagicSourceManaActivation>();
|
||||
for (final MagicPermanent permanent : manaPermanents) {
|
||||
|
||||
|
||||
if (game.isArtificial()&&permanent.hasState(MagicPermanentState.ExcludeManaSource)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final MagicSourceManaActivation sourceActivation=new MagicSourceManaActivation(game,permanent);
|
||||
if (sourceActivation.available) {
|
||||
activations.add(sourceActivation);
|
||||
|
@ -364,7 +364,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return activations;
|
||||
}
|
||||
|
||||
|
||||
private int getManaActivationsCount(final MagicGame game) {
|
||||
int count=0;
|
||||
for (final MagicPermanent permanent : manaPermanents) {
|
||||
|
@ -376,11 +376,11 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public void setBuilderCost(final MagicBuilderManaCost builderCost) {
|
||||
this.builderCost=builderCost;
|
||||
}
|
||||
|
||||
|
||||
public MagicBuilderManaCost getBuilderCost() {
|
||||
return builderCost;
|
||||
}
|
||||
|
@ -388,11 +388,11 @@ public class MagicPlayer implements MagicTarget {
|
|||
public void setActivationPriority(final MagicActivationPriority abilityPriority) {
|
||||
this.activationPriority=abilityPriority;
|
||||
}
|
||||
|
||||
|
||||
public MagicActivationPriority getActivationPriority() {
|
||||
return activationPriority;
|
||||
}
|
||||
|
||||
|
||||
public int getMaximumX(final MagicGame game,final MagicManaCost cost) {
|
||||
return (getManaActivationsCount(game) -
|
||||
builderCost.getMinimumAmount() -
|
||||
|
@ -409,7 +409,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public int getNrOfBlockers() {
|
||||
int count=0;
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
|
@ -419,7 +419,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public int getNrOfPermanentsWithType(final MagicType type) {
|
||||
int count=0;
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
|
@ -439,7 +439,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public int getNrOfPermanents(final MagicTargetFilter<MagicPermanent> filter) {
|
||||
int count = 0;
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
|
@ -449,8 +449,8 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean controlsPermanent(final MagicTargetFilter<MagicPermanent> filter) {
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
if (filter.accept(currGame, this, permanent)) {
|
||||
|
@ -459,11 +459,11 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean controlsPermanent(final MagicPermanent permanent) {
|
||||
return permanents.contains(permanent);
|
||||
}
|
||||
|
||||
|
||||
public boolean controlsPermanent(final MagicColor color) {
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
if (permanent.hasColor(color)) {
|
||||
|
@ -472,7 +472,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean controlsPermanent(final MagicType type) {
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
if (permanent.hasType(type)) {
|
||||
|
@ -481,40 +481,40 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean controlsPermanent(final MagicSubType subType) {
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
if (permanent.hasSubType(subType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean controlsPermanent(final MagicAbility ability) {
|
||||
for (final MagicPermanent permanent : permanents) {
|
||||
if (permanent.hasAbility(ability)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MagicCardDefinition getCardDefinition() {
|
||||
throw new RuntimeException("player has no card definition");
|
||||
throw new RuntimeException("player has no card definition");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return playerDefinition.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPermanent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCreature() {
|
||||
return false;
|
||||
|
@ -524,7 +524,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
public boolean isPlayer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPlaneswalker() {
|
||||
return false;
|
||||
|
@ -566,22 +566,22 @@ public class MagicPlayer implements MagicTarget {
|
|||
public boolean hasAbility(final MagicAbility ability) {
|
||||
return cachedAbilityFlags.contains(ability);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasType(final MagicType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasSubType(final MagicSubType subType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasColor(final MagicColor color) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isValidTarget(final MagicSource source) {
|
||||
// Can't be the target of spells or abilities your opponents controls.
|
||||
|
@ -590,7 +590,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isLegalTarget(final MagicPlayer player, final MagicTargetFilter<? extends MagicTarget> targetFilter) {
|
||||
return true;
|
||||
|
@ -599,7 +599,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
public void incDrawnCards() {
|
||||
drawnCards++;
|
||||
}
|
||||
|
||||
|
||||
public void decDrawnCards() {
|
||||
drawnCards--;
|
||||
}
|
||||
|
@ -620,7 +620,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
currGame.addDelayedAction(new MagicLoseGameAction(this,MagicLoseGameAction.POISON_REASON));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void apply(final MagicLayer layer) {
|
||||
switch (layer) {
|
||||
case Player:
|
||||
|
@ -632,7 +632,7 @@ public class MagicPlayer implements MagicTarget {
|
|||
throw new RuntimeException("No case for " + layer + " in MagicPlayer.apply");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void apply(final MagicPermanent source, final MagicStatic mstatic) {
|
||||
final MagicLayer layer = mstatic.getLayer();
|
||||
switch (layer) {
|
||||
|
|
|
@ -10,12 +10,12 @@ public class MagicPlayerDefinition {
|
|||
|
||||
private static final int DECK_SIZE=40;
|
||||
private static final int MIN_SOURCE=16;
|
||||
|
||||
|
||||
private static final String NAME="name";
|
||||
private static final String ARTIFICIAL="artificial";
|
||||
private static final String COLORS="colors";
|
||||
private static final String FACE="face";
|
||||
|
||||
|
||||
private String name;
|
||||
private boolean artificial;
|
||||
private MagicPlayerProfile profile;
|
||||
|
@ -23,14 +23,14 @@ public class MagicPlayerDefinition {
|
|||
private final MagicDeck deck = new MagicDeck();
|
||||
|
||||
MagicPlayerDefinition() {}
|
||||
|
||||
|
||||
public MagicPlayerDefinition(final String name,final boolean artificial,final MagicPlayerProfile profile,final int face) {
|
||||
this.name=name;
|
||||
this.artificial=artificial;
|
||||
this.profile=profile;
|
||||
this.face=face;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -38,23 +38,23 @@ public class MagicPlayerDefinition {
|
|||
public void setArtificial(final boolean art) {
|
||||
this.artificial=art;
|
||||
}
|
||||
|
||||
|
||||
public boolean isArtificial() {
|
||||
return artificial;
|
||||
}
|
||||
|
||||
|
||||
public void setProfile(final MagicPlayerProfile profile) {
|
||||
this.profile=profile;
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
||||
public int getFace() {
|
||||
return face;
|
||||
}
|
||||
|
||||
|
||||
private void addBasicLandsToDeck() {
|
||||
// Calculate statistics per color.
|
||||
final int[] colorCount=new int[MagicColor.NR_COLORS];
|
||||
|
@ -70,10 +70,10 @@ public class MagicPlayerDefinition {
|
|||
if (color.hasColor(colorFlags)) {
|
||||
colorCount[color.ordinal()]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add optimal basic lands to deck.
|
||||
while (deck.size()<DECK_SIZE) {
|
||||
MagicColor bestColor=null;
|
||||
|
@ -100,41 +100,41 @@ public class MagicPlayerDefinition {
|
|||
deck.add(landCard);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MagicDeck getDeck() {
|
||||
return deck;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setDeck(final MagicDeck aDeck) {
|
||||
deck.setContent(aDeck);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DefaultDeckGenerator getDeckGenerator() {
|
||||
final String name = getProfile().getDeckGeneratorName();
|
||||
|
||||
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return DeckGenerators.getInstance().getDeckGenerator(name);
|
||||
}
|
||||
|
||||
|
||||
void generateDeck(final DefaultDeckGenerator defaultGenerator) {
|
||||
final DefaultDeckGenerator customGenerator = getDeckGenerator();
|
||||
|
||||
|
||||
if(customGenerator == null) {
|
||||
defaultGenerator.generateDeck(DECK_SIZE, profile, deck);
|
||||
} else {
|
||||
customGenerator.generateDeck(DECK_SIZE, profile, deck);
|
||||
}
|
||||
|
||||
|
||||
addBasicLandsToDeck();
|
||||
}
|
||||
|
||||
|
||||
private static String getDeckPrefix(final String prefix,final int index) {
|
||||
return prefix+"deck"+index;
|
||||
}
|
||||
|
||||
|
||||
void load(final Properties properties,final String prefix) {
|
||||
name=properties.getProperty(prefix+NAME,"");
|
||||
artificial=Boolean.parseBoolean(properties.getProperty(prefix+ARTIFICIAL,"true"));
|
||||
|
@ -159,13 +159,13 @@ public class MagicPlayerDefinition {
|
|||
|
||||
magic.data.DeckUtils.showUnsupportedCards(unsupported);
|
||||
}
|
||||
|
||||
|
||||
void save(final Properties properties,final String prefix) {
|
||||
properties.setProperty(prefix+NAME,name);
|
||||
properties.setProperty(prefix+ARTIFICIAL,Boolean.toString(artificial));
|
||||
properties.setProperty(prefix+COLORS,getProfile().getColorText());
|
||||
properties.setProperty(prefix+FACE,Integer.toString(face));
|
||||
|
||||
|
||||
int index=1;
|
||||
for (final MagicCardDefinition cardDefinition : deck) {
|
||||
properties.setProperty(getDeckPrefix(prefix,index++),cardDefinition.getFullName());
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
package magic.model;
|
||||
|
||||
public class MagicPlayerProfile {
|
||||
|
||||
private String deckGeneratorName;
|
||||
|
||||
private String deckGeneratorName;
|
||||
private String colorText;
|
||||
private MagicColor[] colors;
|
||||
private boolean isPreConstructed;
|
||||
|
||||
|
||||
public MagicPlayerProfile(final String colorText) {
|
||||
this(colorText, null);
|
||||
}
|
||||
|
||||
|
||||
public MagicPlayerProfile(final String colorText, final String deckGeneratorName) {
|
||||
setColors(colorText);
|
||||
setDeckGeneratorName(deckGeneratorName);
|
||||
}
|
||||
|
||||
|
||||
public void setColors(final String colorText) {
|
||||
|
||||
this.colorText=colorText;
|
||||
colors=new MagicColor[colorText.length()];
|
||||
for (int i=0;i<colorText.length();i++) {
|
||||
|
||||
|
||||
colors[i]=MagicColor.getColor(colorText.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setDeckGeneratorName(final String name) {
|
||||
this.deckGeneratorName = name;
|
||||
}
|
||||
|
||||
|
||||
public String getDeckGeneratorName() {
|
||||
return deckGeneratorName;
|
||||
}
|
||||
|
||||
|
||||
String getColorText() {
|
||||
|
||||
|
||||
return colorText;
|
||||
}
|
||||
|
||||
|
||||
public MagicColor[] getColors() {
|
||||
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
|
||||
int getNrOfColors() {
|
||||
|
||||
|
||||
return colors.length;
|
||||
}
|
||||
|
||||
|
||||
public int getNrOfNonBasicLands(final int amount) {
|
||||
|
||||
|
||||
switch (colors.length) {
|
||||
case 3: return amount/2;
|
||||
case 2: return amount/4;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean allowsManaType(final MagicManaType manaType) {
|
||||
|
||||
|
||||
for (final MagicColor color : colors) {
|
||||
|
||||
|
||||
if (color.getManaType()==manaType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void setPreConstructed() {
|
||||
isPreConstructed = true;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPreConstructed() {
|
||||
return isPreConstructed;
|
||||
}
|
||||
|
|
|
@ -9,23 +9,23 @@ public enum MagicPlayerState {
|
|||
CantCastSpells("can't cast spells this turn"),
|
||||
CantActivateAbilities("can't activate abilities this turn"),
|
||||
;
|
||||
|
||||
|
||||
private final String description;
|
||||
private final int mask;
|
||||
|
||||
|
||||
private MagicPlayerState(final String description) {
|
||||
this.description=description;
|
||||
this.mask=1<<ordinal();
|
||||
}
|
||||
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
public int getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasState(final int flags) {
|
||||
return (flags&mask)!=0;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@ public class MagicPowerToughness {
|
|||
|
||||
private int power;
|
||||
private int toughness;
|
||||
|
||||
|
||||
public MagicPowerToughness(final int aPower,final int aToughness) {
|
||||
power = aPower;
|
||||
toughness = aToughness;
|
||||
}
|
||||
|
||||
|
||||
public int power() {
|
||||
return power;
|
||||
}
|
||||
|
@ -17,34 +17,34 @@ public class MagicPowerToughness {
|
|||
public int toughness() {
|
||||
return toughness;
|
||||
}
|
||||
|
||||
|
||||
public int getPositivePower() {
|
||||
return power>0?power:0;
|
||||
}
|
||||
|
||||
|
||||
public int getPositiveToughness() {
|
||||
return toughness>0?toughness:0;
|
||||
}
|
||||
|
||||
|
||||
public void add(final MagicPowerToughness pt) {
|
||||
power += pt.power;
|
||||
toughness += pt.toughness;
|
||||
}
|
||||
|
||||
|
||||
public void add(final int pAmount, final int tAmount) {
|
||||
power += pAmount;
|
||||
toughness += tAmount;
|
||||
}
|
||||
|
||||
|
||||
public void set(final int pAmount, final int tAmount) {
|
||||
power = pAmount;
|
||||
toughness = tAmount;
|
||||
}
|
||||
|
||||
|
||||
public void setPower(final int tAmount) {
|
||||
power = tAmount;
|
||||
}
|
||||
|
||||
|
||||
public void setToughness(final int tAmount) {
|
||||
toughness = tAmount;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import magic.MersenneTwisterFast;
|
|||
public class MagicRandom {
|
||||
|
||||
private static final MersenneTwisterFast RNG;
|
||||
|
||||
|
||||
static {
|
||||
final String seedStr = System.getProperty("rndSeed");
|
||||
if (seedStr != null) {
|
||||
|
@ -17,7 +17,7 @@ public class MagicRandom {
|
|||
}
|
||||
|
||||
private MagicRandom() {}
|
||||
|
||||
|
||||
public static int nextInt(final int n) {
|
||||
return RNG.nextInt(n);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ public enum MagicRarity {
|
|||
Mythic_Rare('M');
|
||||
|
||||
public static final int length = values().length;
|
||||
|
||||
|
||||
private final char c;
|
||||
|
||||
private MagicRarity(final char c) {
|
||||
|
@ -22,7 +22,7 @@ public enum MagicRarity {
|
|||
public String getName() {
|
||||
return toString().replace('_',' ');
|
||||
}
|
||||
|
||||
|
||||
public static MagicRarity getRarity(final char c) {
|
||||
for (final MagicRarity type : values()) {
|
||||
if (type.c == c) {
|
||||
|
|
|
@ -7,17 +7,17 @@ public enum MagicStaticType {
|
|||
Player("player"),
|
||||
Opponent("opponent")
|
||||
;
|
||||
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
private MagicStaticType(final String name) {
|
||||
this.name=name;
|
||||
}
|
||||
|
||||
|
||||
private String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public int getScore(final MagicPermanent scorePermanent) {
|
||||
if (this==None) {
|
||||
return 0;
|
||||
|
@ -41,7 +41,7 @@ public enum MagicStaticType {
|
|||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
public static MagicStaticType getStaticTypeFor(final String name) {
|
||||
for (final MagicStaticType type : values()) {
|
||||
if (type.getName().equalsIgnoreCase(name)) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue