Merge branch 'master' into cmake
This commit is contained in:
278
projects/mtg/Android/src/net/wagic/utils/DeckImporter.java
Normal file
278
projects/mtg/Android/src/net/wagic/utils/DeckImporter.java
Normal file
@@ -0,0 +1,278 @@
|
||||
package net.wagic.utils;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class DeckImporter
|
||||
{
|
||||
|
||||
public static String importDeck( File f, String mypath, String activePath )
|
||||
{
|
||||
String message = "";
|
||||
String deck = "";
|
||||
String deckname = "";
|
||||
if(f.exists() && !f.isDirectory())
|
||||
{
|
||||
deckname = f.getName();
|
||||
int pos = deckname.lastIndexOf(".");
|
||||
if (pos > 0)
|
||||
{
|
||||
deckname = deckname.substring(0, pos);
|
||||
}
|
||||
deck += "#NAME:"+deckname+"\n";
|
||||
try
|
||||
{
|
||||
Scanner scanner = new Scanner(new File(mypath));
|
||||
if (scanner.hasNext())
|
||||
{
|
||||
while (scanner.hasNext())
|
||||
{
|
||||
String line = scanner.nextLine();
|
||||
String[] slines = line.split("\\s+");
|
||||
String arranged = "";
|
||||
for(int idx = 1; idx < slines.length; idx++)
|
||||
{
|
||||
arranged += slines[idx] + " ";
|
||||
}
|
||||
if (isNumeric(slines[0]) && arranged != null)
|
||||
{
|
||||
if (slines[1] != null && slines[1].startsWith("["))
|
||||
{
|
||||
arranged = arranged.substring(5);
|
||||
slines[1] = slines[1].replaceAll("\\[", "").replaceAll("\\]","");
|
||||
deck += arranged + " (" + renameSet(slines[1]) + ") * " + slines[0] + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
deck += arranged + "(*) * " + slines[0] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
File profile = new File(activePath+"/Res/settings/options.txt");
|
||||
if(profile.exists() && !profile.isDirectory())
|
||||
{
|
||||
String profileName = getActiveProfile(profile);
|
||||
if(profileName != "Missing!")
|
||||
{
|
||||
File rootProfiles = new File(activePath+"/Res/profiles/"+profileName);
|
||||
if(rootProfiles.exists() && rootProfiles.isDirectory())
|
||||
{
|
||||
//save deck
|
||||
int countdeck = 1;
|
||||
File[] files = rootProfiles.listFiles();
|
||||
for (int i = 0; i < files.length; i++)
|
||||
{//check if there is available deck...
|
||||
if(files[i].getName().startsWith("deck"))
|
||||
countdeck++;
|
||||
}
|
||||
File toSave = new File(rootProfiles+"/deck"+countdeck+".txt");
|
||||
try
|
||||
{
|
||||
FileOutputStream fop = new FileOutputStream(toSave);
|
||||
|
||||
// if file doesn't exists, then create it
|
||||
if (!toSave.exists()) {
|
||||
toSave.createNewFile();
|
||||
}
|
||||
|
||||
// get the content in bytes
|
||||
byte[] contentInBytes = deck.getBytes();
|
||||
|
||||
fop.write(contentInBytes);
|
||||
fop.flush();
|
||||
fop.close();
|
||||
|
||||
message = "Import Deck Success!\n\n"+deck;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
message = e.getMessage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "Missing Folder!";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "Invalid Profile!";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "No errors, and file EMPTY";
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
message = e.getMessage();
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private static boolean isNumeric(String input)
|
||||
{
|
||||
try
|
||||
{
|
||||
Integer.parseInt(input);
|
||||
}
|
||||
catch(NumberFormatException ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getActiveProfile(File mypath)
|
||||
{
|
||||
String name = "";
|
||||
try
|
||||
{
|
||||
Scanner scanner = new Scanner(new File(mypath.toString()));
|
||||
if (scanner.hasNext())
|
||||
{
|
||||
String line = scanner.nextLine();
|
||||
name = line.substring(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Missing!";
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
return "Missing!";
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private static String renameSet(String set)
|
||||
{
|
||||
if (set == "")
|
||||
return "*";
|
||||
if (set == "AL")
|
||||
return "ALL";
|
||||
if (set == "AQ")
|
||||
return "ATQ";
|
||||
if (set == "AP")
|
||||
return "APC";
|
||||
if (set == "AN")
|
||||
return "ARN";
|
||||
if (set == "AE")
|
||||
return "ARC";
|
||||
if (set == "BR")
|
||||
return "BRB";
|
||||
if (set == "BD")
|
||||
return "BTD";
|
||||
if (set == "CH")
|
||||
return "CHR";
|
||||
if (set == "6E")
|
||||
return "6ED";
|
||||
if (set == "CS")
|
||||
return "CSP";
|
||||
if (set == "DS")
|
||||
return "DST";
|
||||
if (set == "D2")
|
||||
return "DD2";
|
||||
if (set == "8E")
|
||||
return "8ED";
|
||||
if (set == "EX")
|
||||
return "EXO";
|
||||
if (set == "FE")
|
||||
return "FEM";
|
||||
if (set == "FD")
|
||||
return "5DN";
|
||||
if (set == "5E")
|
||||
return "5ED";
|
||||
if (set == "4E")
|
||||
return "4ED";
|
||||
if (set == "GP")
|
||||
return "GPT";
|
||||
if (set == "HL")
|
||||
return "HML";
|
||||
if (set == "IA")
|
||||
return "ICE";
|
||||
if (set == "IN")
|
||||
return "INV";
|
||||
if (set == "JU")
|
||||
return "JUD";
|
||||
if (set == "LG")
|
||||
return "LEG";
|
||||
if (set == "LE")
|
||||
return "LGN";
|
||||
if (set == "A")
|
||||
return "LEA";
|
||||
if (set == "B")
|
||||
return "LEB";
|
||||
if (set == "MM")
|
||||
return "MMQ";
|
||||
if (set == "MI")
|
||||
return "MIR";
|
||||
if (set == "MR")
|
||||
return "MRD";
|
||||
if (set == "NE")
|
||||
return "NEM";
|
||||
if (set == "9E")
|
||||
return "9ED";
|
||||
if (set == "OD")
|
||||
return "ODY";
|
||||
if (set == "ON")
|
||||
return "ONS";
|
||||
if (set == "PS")
|
||||
return "PLS";
|
||||
if (set == "PT")
|
||||
return "POR";
|
||||
if (set == "P2")
|
||||
return "P02";
|
||||
if (set == "P3")
|
||||
return "PTK";
|
||||
if (set == "PR")
|
||||
return "PPR";
|
||||
if (set == "PY")
|
||||
return "PCY";
|
||||
if (set == "R")
|
||||
return "RV";
|
||||
if (set == "SC")
|
||||
return "SCG";
|
||||
if (set == "7E")
|
||||
return "7ED";
|
||||
if (set == "ST")
|
||||
return "S99";
|
||||
if (set == "ST2K")
|
||||
return "S00";
|
||||
if (set == "SH")
|
||||
return "STH";
|
||||
if (set == "TE")
|
||||
return "TMP";
|
||||
if (set == "DK")
|
||||
return "DRK";
|
||||
if (set == "TO")
|
||||
return "TOR";
|
||||
if (set == "UG")
|
||||
return "UGL";
|
||||
if (set == "U")
|
||||
return "2ED";
|
||||
if (set == "UD")
|
||||
return "UDS";
|
||||
if (set == "UL")
|
||||
return "ULG";
|
||||
if (set == "US")
|
||||
return "USG";
|
||||
if (set == "VI")
|
||||
return "VIS";
|
||||
if (set == "WL")
|
||||
return "WTH";
|
||||
else
|
||||
return set;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,10 @@ import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import android.os.Build;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -21,8 +25,10 @@ public class StorageOptions
|
||||
public static void determineStorageOptions()
|
||||
{
|
||||
initializeMountPoints();
|
||||
readMountsFileTest();
|
||||
readMountsFile();
|
||||
readVoldFile();
|
||||
removeDuplicates(mMounts);
|
||||
compareMountsWithVold();
|
||||
testAndCleanMountsList();
|
||||
setProperties();
|
||||
@@ -40,6 +46,42 @@ public class StorageOptions
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMountsFileTest()
|
||||
{
|
||||
/*
|
||||
* Test mountpoints storage -kevlahnota
|
||||
*/
|
||||
|
||||
try
|
||||
{
|
||||
Scanner scanner = new Scanner(new File("/proc/mounts"));
|
||||
while (scanner.hasNext())
|
||||
{
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith("/"))
|
||||
{
|
||||
String[] lineElements = line.split("\\s+");
|
||||
if ("vfat".equals(lineElements[2]) || "fuse".equals(lineElements[2]) || "sdcardfs".equals(lineElements[2]))
|
||||
{
|
||||
File mountPoint = new File(lineElements[1]);
|
||||
if (!lineElements[1].equals(defaultMountPoint))
|
||||
if (mountPoint.isDirectory() && mountPoint.canRead())
|
||||
mMounts.add(lineElements[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException fnfex)
|
||||
{
|
||||
// if proc/mount doesn't exist we just use
|
||||
Log.i(StorageOptions.class.getCanonicalName(), fnfex.getMessage() + ": assuming " + defaultMountPoint + " is the only mount point");
|
||||
mMounts.add(defaultMountPoint);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Log.e(StorageOptions.class.getCanonicalName(), e.getMessage() + ": unknown exception while reading mounts file");
|
||||
mMounts.add(defaultMountPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMountsFile()
|
||||
{
|
||||
/*
|
||||
@@ -106,6 +148,23 @@ public class StorageOptions
|
||||
mMounts.add(defaultMountPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayList<String> removeDuplicates(ArrayList<String> list)
|
||||
{
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
|
||||
HashSet<String> set = new HashSet<String>();
|
||||
|
||||
for (String item : list)
|
||||
{
|
||||
if (!set.contains(item))
|
||||
{
|
||||
result.add(item);
|
||||
set.add(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void compareMountsWithVold()
|
||||
{
|
||||
@@ -132,14 +191,54 @@ public class StorageOptions
|
||||
/*
|
||||
* Now that we have a cleaned list of mount paths Test each one to make sure it's a valid and available path. If it is not, remove it from the list.
|
||||
*/
|
||||
|
||||
int t = 0;
|
||||
for (int i = 0; i < mMounts.size(); i++)
|
||||
{
|
||||
t++;
|
||||
String mount = mMounts.get(i);
|
||||
File root = new File(mount);
|
||||
if (!root.exists() || !root.isDirectory() || !root.canWrite())
|
||||
mMounts.remove(i--);
|
||||
}
|
||||
|
||||
if (t == 0 && Build.VERSION.SDK_INT >= 16)
|
||||
{//if none is found lets force it for Jellybean and above...
|
||||
if (System.getenv("EXTERNAL_STORAGE") != null)
|
||||
{
|
||||
File root = new File(System.getenv("EXTERNAL_STORAGE"));
|
||||
if (root.exists() && root.isDirectory() && root.canWrite())
|
||||
{
|
||||
if(!isRooted())
|
||||
{
|
||||
File folder = new File(System.getenv("EXTERNAL_STORAGE")+"/Android/data/net.wagic.app/files");
|
||||
folder.mkdirs();
|
||||
mMounts.add(folder.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
mMounts.add(System.getenv("EXTERNAL_STORAGE"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (System.getenv("SECONDARY_STORAGE") != null)
|
||||
{
|
||||
File root = new File(System.getenv("SECONDARY_STORAGE"));
|
||||
if (root.exists() && root.isDirectory() && root.canWrite())
|
||||
{
|
||||
if(!isRooted())
|
||||
{
|
||||
File folder = new File(System.getenv("SECONDARY_STORAGE")+"/Android/data/net.wagic.app/files");
|
||||
folder.mkdirs();
|
||||
mMounts.add(folder.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
mMounts.add(System.getenv("SECONDARY_STORAGE"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setProperties()
|
||||
@@ -153,10 +252,12 @@ public class StorageOptions
|
||||
int i = 1;
|
||||
for (String path : mMounts)
|
||||
{ // TODO: /mnt/sdcard is assumed to always mean internal storage. Use this comparison until there is a better way to do this
|
||||
if ("/mnt/sdcard".equalsIgnoreCase(path))
|
||||
mLabels.add("Built-in Storage");
|
||||
if ("/mnt/sdcard".equalsIgnoreCase(path) || "/storage/sdcard0".equalsIgnoreCase(path))
|
||||
mLabels.add("Internal SD " + "[" + path + "]");
|
||||
else if (path.contains("emulated"))
|
||||
mLabels.add("Emulated SD " + " [" + path + "]");
|
||||
else
|
||||
mLabels.add("External SD Card " + i++);
|
||||
mLabels.add("External SD " + " [" + path + "]");
|
||||
}
|
||||
|
||||
labels = new String[mLabels.size()];
|
||||
@@ -171,4 +272,90 @@ public class StorageOptions
|
||||
// use and to prepare it for the next time it's needed.
|
||||
mMounts.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isExternalStorageReadOnly() {
|
||||
String extStorageState = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isExternalStorageAvailable() {
|
||||
String extStorageState = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the device is rooted.
|
||||
*
|
||||
* @return <code>true</code> if the device is rooted, <code>false</code> otherwise.
|
||||
*/
|
||||
public static boolean isRooted() {
|
||||
|
||||
// get from build info
|
||||
String buildTags = android.os.Build.TAGS;
|
||||
if (buildTags != null && buildTags.contains("test-keys")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if /system/app/Superuser.apk is present
|
||||
try {
|
||||
File file = new File("/system/app/Superuser.apk");
|
||||
if (file.exists()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e1) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
File file = new File("/system/app/Superuser/Superuser.apk");
|
||||
if (file.exists()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e1) {
|
||||
// ignore
|
||||
}
|
||||
//SuperSU
|
||||
try {
|
||||
File file = new File("/system/app/SuperSU.apk");
|
||||
if (file.exists()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e1) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
File file = new File("/system/app/SuperSU/SuperSU.apk");
|
||||
if (file.exists()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e1) {
|
||||
// ignore
|
||||
}
|
||||
// try executing commands
|
||||
return canExecuteCommand("/system/xbin/which su")
|
||||
|| canExecuteCommand("/system/bin/which su") || canExecuteCommand("which su");
|
||||
}
|
||||
|
||||
// executes a command on the system
|
||||
private static boolean canExecuteCommand(String command) {
|
||||
boolean executedSuccesfully;
|
||||
try {
|
||||
Runtime.getRuntime().exec(command);
|
||||
executedSuccesfully = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
executedSuccesfully = false;
|
||||
}
|
||||
|
||||
return executedSuccesfully;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
package org.libsdl.app;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
@@ -16,6 +24,7 @@ import javax.microedition.khronos.egl.EGLSurface;
|
||||
|
||||
import net.wagic.app.R;
|
||||
import net.wagic.utils.StorageOptions;
|
||||
import net.wagic.utils.DeckImporter;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@@ -59,7 +68,10 @@ import android.widget.FrameLayout.LayoutParams;
|
||||
*/
|
||||
public class SDLActivity extends Activity implements OnKeyListener
|
||||
{
|
||||
|
||||
//import deck globals
|
||||
public ArrayList<String> myresult = new ArrayList<String>();
|
||||
public String myclickedItem = "";
|
||||
|
||||
// TAG used for debugging in DDMS
|
||||
public static String TAG = Activity.class.getCanonicalName();
|
||||
|
||||
@@ -200,7 +212,60 @@ public class SDLActivity extends Activity implements OnKeyListener
|
||||
|
||||
setStorage.create().show();
|
||||
}
|
||||
|
||||
private void importDeckOptions()
|
||||
{
|
||||
AlertDialog.Builder importDeck = new AlertDialog.Builder(this);
|
||||
importDeck.setTitle("Choose Deck to Import:");
|
||||
File root = new File(System.getenv("EXTERNAL_STORAGE")+"/Download");
|
||||
File[] files = root.listFiles();
|
||||
for( File f : files)
|
||||
{
|
||||
if( !myresult.contains(f.toString()) && (f.toString().contains(".txt")||f.toString().contains(".dec")))
|
||||
myresult.add(f.toString());
|
||||
}
|
||||
|
||||
//get first item?
|
||||
if(!myresult.isEmpty())
|
||||
myclickedItem = myresult.get(0).toString();
|
||||
|
||||
importDeck.setSingleChoiceItems(myresult.toArray(new String[myresult.size()]), 0, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int item)
|
||||
{
|
||||
myclickedItem = myresult.get(item).toString();
|
||||
}
|
||||
});
|
||||
|
||||
importDeck.setPositiveButton("Import Deck", new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
processSelectedDeck( myclickedItem );
|
||||
if (mSurface == null)
|
||||
mSingleton.initializeGame();
|
||||
}
|
||||
});
|
||||
|
||||
importDeck.create().show();
|
||||
}
|
||||
|
||||
private void processSelectedDeck(String mypath)
|
||||
{
|
||||
AlertDialog.Builder infoDialog = new AlertDialog.Builder(this);
|
||||
infoDialog.setTitle("Imported Deck:");
|
||||
String activePath = sdcardPath;
|
||||
if(activePath == ""){
|
||||
activePath = internalPath;
|
||||
}
|
||||
|
||||
File f = new File(mypath);
|
||||
//Call the deck importer....
|
||||
String state = DeckImporter.importDeck(f, mypath, activePath);
|
||||
infoDialog.setMessage(state);
|
||||
infoDialog.show();
|
||||
}
|
||||
|
||||
private void checkStorageLocationPreference()
|
||||
{
|
||||
SharedPreferences settings = getSharedPreferences(kWagicSharedPreferencesKey, MODE_PRIVATE);
|
||||
@@ -334,7 +399,8 @@ public class SDLActivity extends Activity implements OnKeyListener
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
SubMenu settingsMenu = menu.addSubMenu(Menu.NONE, 1, 1, "Settings");
|
||||
menu.add(Menu.NONE, 2, 2, "About");
|
||||
menu.add(Menu.NONE, 2, 2, "Import");
|
||||
menu.add(Menu.NONE, 3, 3, "About");
|
||||
settingsMenu.add(kStorageDataOptionsMenuId, kStorageDataOptionsMenuId, Menu.NONE, "Storage Data Options");
|
||||
// buildStorageOptionsMenu(settingsMenu);
|
||||
|
||||
@@ -350,6 +416,9 @@ public class SDLActivity extends Activity implements OnKeyListener
|
||||
{
|
||||
displayStorageOptions();
|
||||
} else if (itemId == 2)
|
||||
{
|
||||
importDeckOptions();
|
||||
} else if (itemId == 3)
|
||||
{
|
||||
// display some info about the app
|
||||
AlertDialog.Builder infoDialog = new AlertDialog.Builder(this);
|
||||
|
||||
@@ -16,7 +16,9 @@ auto=morphrule
|
||||
auto=payzerorule
|
||||
auto=overloadrule
|
||||
auto=attackrule
|
||||
auto=attackcostrule
|
||||
auto=blockrule
|
||||
auto=blockcostrule
|
||||
auto=combattriggerrule
|
||||
auto=legendrule
|
||||
auto=planeswalkerrule
|
||||
|
||||
@@ -15,7 +15,9 @@ auto=morphrule
|
||||
auto=payzerorule
|
||||
auto=overloadrule
|
||||
auto=attackrule
|
||||
auto=attackcostrule
|
||||
auto=blockrule
|
||||
auto=blockcostrule
|
||||
auto=combattriggerrule
|
||||
auto=legendrule
|
||||
auto=planeswalkerrule
|
||||
|
||||
@@ -19,7 +19,9 @@ auto=morphrule
|
||||
auto=payzerorule
|
||||
auto=overloadrule
|
||||
auto=attackrule
|
||||
auto=attackcostrule
|
||||
auto=blockrule
|
||||
auto=blockcostrule
|
||||
auto=combattriggerrule
|
||||
auto=legendrule
|
||||
auto=planeswalkerrule
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
grade=borderline
|
||||
[card]
|
||||
name=Arrogant Wurm
|
||||
abilities=trample,madness
|
||||
autoexile=restriction{discarded} pay({2}{G}) name(pay 2G to cast) activate name(pay 2G to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
text=Trample -- Madness {2}{G} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={3}{G}{G}
|
||||
type=Creature
|
||||
subtype=Wurm
|
||||
power=4
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Autumn Willow
|
||||
abilities=opponentshroud,shroud
|
||||
auto={G}:-shroud
|
||||
@@ -35,40 +24,6 @@ power=2
|
||||
toughness=2
|
||||
[/card]
|
||||
[card]
|
||||
name=Basking Rootwalla
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({0}) name(pay 0 to cast) activate name(pay 0 to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto={1}{G}:2/2 limit:1
|
||||
text={1}{G}: Basking Rootwalla gets +2/+2 until end of turn. Activate this ability only once each turn. -- Madness {0} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={G}
|
||||
type=Creature
|
||||
subtype=Lizard
|
||||
power=1
|
||||
toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Big Game Hunter
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}) name(pay B to cast) activate name(pay B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=bury target(creature[power>=4])
|
||||
text=When Big Game Hunter enters the battlefield, destroy target creature with power 4 or greater. It can't be regenerated. -- Madness {B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{B}{B}
|
||||
type=Creature
|
||||
subtype=Human Rebel Assassin
|
||||
power=1
|
||||
toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Call to the Netherworld
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({0}) name(pay 0 to cast) activate name(pay 0 to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature[black]|myGraveyard
|
||||
auto=moveTo(myHand)
|
||||
text=Return target black creature card from your graveyard to your hand. -- Madness {0} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={B}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Cemetery Puca
|
||||
text=Whenever a creature is put into a graveyard from the battlefield, you may pay {1}. If you do, Cemetery Puca becomes a copy of that creature and gains this ability.
|
||||
auto=@movedto(creature|graveyard) from(battlefield):all(trigger[from]) pay[[{1}]] copy
|
||||
@@ -109,16 +64,6 @@ power=2
|
||||
toughness=2
|
||||
[/card]
|
||||
[card]
|
||||
name=Dark Withering
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}) name(pay B to cast) activate name(pay B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature[-black]
|
||||
auto=destroy
|
||||
text=Destroy target nonblack creature. -- Madness {B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={4}{B}{B}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Dimir Doppelganger
|
||||
auto={1}{U}{B}:target(creature|graveyard) moveto(exile) and!(copy)!
|
||||
text={1}{U}{B}: Exile target creature card from a graveyard. Dimir Doppelganger becomes a copy of that card and gains this ability.
|
||||
@@ -164,26 +109,6 @@ auto={3}:counter(1/1)
|
||||
#Not all player can use ability
|
||||
[/card]
|
||||
[card]
|
||||
name=Fiery Temper
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({R}) name(pay R to cast) activate name(pay R to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature,player
|
||||
auto=damage:3
|
||||
text=Fiery Temper deals 3 damage to target creature or player. -- Madness {R} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{R}{R}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Frantic Purification
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({W}) name(pay W to cast) activate name(pay W to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=enchantment
|
||||
auto=destroy
|
||||
text=Destroy target enchantment. -- Madness {W} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{W}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Ghastly Remains
|
||||
auto=foreach(zombie|myhand) counter(1/1,1)
|
||||
autograveyard={B}{B}{B}:moveTo(myhand) myUpkeepOnly
|
||||
@@ -205,18 +130,6 @@ power=4
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Gorgon Recluse
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}{B}) name(pay BB to cast) activate name(pay BB to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=@combat(blocked,blocking) source(this) from(creature):all(trigger[from]) phaseaction[combatends once] destroy
|
||||
text=Whenever Gorgon Recluse blocks or becomes blocked by a nonblack creature, destroy that creature at end of combat. -- Madness {B}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={3}{B}{B}
|
||||
type=Creature
|
||||
subtype=Gorgon
|
||||
power=2
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Govern the Guildless
|
||||
target=creature[-multicolor]
|
||||
auto=moveto(mybattlefield)
|
||||
@@ -226,17 +139,6 @@ mana={5}{U}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Ichor Slick
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({3}{B}) name(pay 3B to cast) activate name(pay 3B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature
|
||||
auto=-3/-3
|
||||
autohand=__CYCLING__({2})
|
||||
text=Target creature gets -3/-3 until end of turn. -- Cycling {2} ({2}, Discard this card: Draw a card.) -- Madness {3}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{B}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Ivy Seer
|
||||
auto={2}{G}{T}:foreach(*[green]|myhand) 1/1 target(creature)
|
||||
text={2}{G}, {T}: Reveal any number of green cards in your hand. Target creature gets +X/+X until end of turn, where X is the number of cards revealed this way.
|
||||
@@ -308,15 +210,6 @@ type=Sorcery
|
||||
text=Put a 1/1 white Kor Soldier creature token onto the battlefield for each creature you control. Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
|
||||
[/card]
|
||||
[card]
|
||||
name=Obsessive Search
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({U}) name(pay U to cast) activate name(pay U to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=draw:1 controller
|
||||
text=Draw a card. -- Madness {U} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={U}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Ogre Marauder
|
||||
text=Whenever Ogre Marauder attacks, it gains "Ogre Marauder can't be blocked" until end of turn unless defending player sacrifices a creature.
|
||||
auto=@combat(attacking) source(this):ability$!name(choose one) if type(creature|mybattlefield)~morethan~0 then choice sacrifice notatarget(creature|mybattlefield) _ choice all(mystored) unblockable ueot!$ opponent
|
||||
@@ -336,15 +229,6 @@ type=Instant
|
||||
text=Target creature gets +2/+2 until end of turn. Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
|
||||
[/card]
|
||||
[card]
|
||||
name=Psychotic Haze
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({1}{B}) name(pay 1B to cast) activate name(pay 1B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=damage:1 all(creature,player)
|
||||
text=Psychotic Haze deals 1 damage to each creature and each player. -- Madness {1}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{B}{B}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Rakdos Augermage
|
||||
abilities=first strike
|
||||
auto={T}:name(target opponent) target(opponent) donothing && all(this) transforms((,newability[ability$!name(discard) reject notatarget(*|opponenthand)!$ targetedplayer && ability$!name(discard) reject notatarget(*|opponenthand)!$ controller])) assorcery
|
||||
@@ -364,17 +248,6 @@ mana={X}{X}{U}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Reckless Wurm
|
||||
abilities=trample,madness
|
||||
autoexile=restriction{discarded} pay({2}{R}) name(pay 2R to cast) activate name(pay 2R to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
text=Trample -- Madness {2}{R} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={3}{R}{R}
|
||||
type=Creature
|
||||
subtype=Wurm
|
||||
power=4
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Recurring Insight
|
||||
target=opponent
|
||||
auto=draw:type:*:targetedpersonshand controller
|
||||
@@ -451,30 +324,6 @@ type=Instant
|
||||
text=Staggershock deals 2 damage to target creature or player. Rebound (If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)
|
||||
[/card]
|
||||
[card]
|
||||
name=Strength of Isolation
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({W}) name(pay W to cast) activate name(pay W to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature
|
||||
auto=1/2
|
||||
auto=protection from black
|
||||
text=Enchant creature -- Enchanted creature gets +1/+2 and has protection from black. -- Madness {W} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{W}
|
||||
type=Enchantment
|
||||
subtype=Aura
|
||||
[/card]
|
||||
[card]
|
||||
name=Strength of Lunacy
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}) name(pay B to cast) activate name(pay B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature
|
||||
auto=2/1
|
||||
auto=protection from white
|
||||
text=Enchant creature -- Enchanted creature gets +2/+1 and has protection from white. -- Madness {B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{B}
|
||||
type=Enchantment
|
||||
subtype=Aura
|
||||
[/card]
|
||||
[card]
|
||||
name=Surreal Memoir
|
||||
auto=moverandom(instant) from(mygraveyard) to(myhand)
|
||||
auto=if rebound then transforms((,newability[moveto(exile)],newability[phaseaction[my upkeep once checkex] activate may activate castcard(restricted)]))
|
||||
|
||||
@@ -3075,6 +3075,18 @@ power=4
|
||||
toughness=6
|
||||
[/card]
|
||||
[card]
|
||||
name=Angel of Jubilation
|
||||
abilities=flying,cantpaylife
|
||||
auto=lord(other creature[-black]|mybattlefield) 1/1
|
||||
auto=lord(creature) cantbesacrified
|
||||
text=Flying -- Other nonblack creatures you control get +1/+1. -- Players can't pay life or sacrifice creatures to cast spells or activate abilities.
|
||||
mana={1}{W}{W}{W}
|
||||
type=Creature
|
||||
subtype=Angel
|
||||
power=3
|
||||
toughness=3
|
||||
[/card]
|
||||
[card]
|
||||
name=Angel of Light
|
||||
abilities=flying,vigilance
|
||||
text=Flying, vigilance
|
||||
@@ -4278,6 +4290,18 @@ power=5
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Archangel of Tithes
|
||||
abilities=flying
|
||||
auto=this(untapped) lord(creature|opponentbattlefield) transforms((,newability[attackpwcost:1]))
|
||||
auto=this(attacking) lord(creature|opponentbattlefield) transforms((,newability[blockcost:1]))
|
||||
text=Flying -- As long as Archangel of Tithes is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures. -- As long as Archangel of Tithes is attacking, creatures can't block unless their controller pays {1} for each of those creatures.
|
||||
mana={1}{W}{W}{W}
|
||||
type=Creature
|
||||
subtype=Angel
|
||||
power=3
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Archangel of Thune
|
||||
abilities=flying,lifelink
|
||||
auto=@lifeof(player):all(creature|mybattlefield) counter(1/1,1)
|
||||
@@ -4289,18 +4313,6 @@ power=3
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Archangel of Tithes
|
||||
abilities=flying
|
||||
auto=this(untapped) lord(creature|opponentbattlefield) transforms((,newability[@each mycombatbegins:pay[[{1}]] name(pay 1 mana) donothing?cantattack all(this)]))
|
||||
auto=@combat(attacking) source(this):all(creature|opponentbattlefield) transforms((,newability[pay[[{1}]] name(pay 1 mana) donothing?cantblock all(this)]))
|
||||
text=Flying -- As long as Archangel of Tithes is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures. -- As long as Archangel of Tithes is attacking, creatures can't block unless their controller pays {1} for each of those creatures.
|
||||
mana={1}{W}{W}{W}
|
||||
type=Creature
|
||||
subtype=Angel
|
||||
power=3
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Archangel's Light
|
||||
auto=life:twicetype:*:mygraveyard
|
||||
auto=moveto(myLibrary) all(*|myGraveyard) && shuffle
|
||||
@@ -5122,6 +5134,17 @@ power=4
|
||||
toughness=3
|
||||
[/card]
|
||||
[card]
|
||||
name=Arrogant Wurm
|
||||
abilities=trample,madness
|
||||
autoexile=restriction{discarded} pay({2}{G}) name(pay 2G to cast) activate name(pay 2G to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
text=Trample -- Madness {2}{G} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={3}{G}{G}
|
||||
type=Creature
|
||||
subtype=Wurm
|
||||
power=4
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Arrows of Justice
|
||||
target=creature[attacking;blocking]
|
||||
auto=damage:4
|
||||
@@ -5541,6 +5564,15 @@ mana={4}{B}{B}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Assault Formation
|
||||
auto=lord(creature|mybattlefield) combattoughness
|
||||
auto={G}:target(creature[defender]) canattack
|
||||
auto={2}{G}:lord(creature|myBattlefield) 0/1 ueot
|
||||
text=Each creature you control assigns combat damage equal to its toughness rather than its power. -- {G}: Target creature with defender can attack this turn as though it didn't have defender. -- {2}{G}: Creatures you control get +0/+1 until end of turn.
|
||||
mana={1}{G}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Assault Griffin
|
||||
abilities=flying
|
||||
text=Flying
|
||||
@@ -7900,6 +7932,18 @@ type=Artifact
|
||||
subtype=Equipment
|
||||
[/card]
|
||||
[card]
|
||||
name=Basking Rootwalla
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({0}) name(pay 0 to cast) activate name(pay 0 to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto={1}{G}:2/2 limit:1
|
||||
text={1}{G}: Basking Rootwalla gets +2/+2 until end of turn. Activate this ability only once each turn. -- Madness {0} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={G}
|
||||
type=Creature
|
||||
subtype=Lizard
|
||||
power=1
|
||||
toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Bassara Tower Archer
|
||||
abilities=opponentshroud,reach
|
||||
text=Hexproof, reach
|
||||
@@ -9002,6 +9046,18 @@ mana={3}{G}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Big Game Hunter
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}) name(pay B to cast) activate name(pay B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=bury target(creature[power>=4])
|
||||
text=When Big Game Hunter enters the battlefield, destroy target creature with power 4 or greater. It can't be regenerated. -- Madness {B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{B}{B}
|
||||
type=Creature
|
||||
subtype=Human Rebel Assassin
|
||||
power=1
|
||||
toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Bile Blight
|
||||
target=creature
|
||||
auto=transforms((,newability[all(*[share!name!]) -3/-3])) ueot
|
||||
@@ -14037,6 +14093,16 @@ subtype=Human
|
||||
power=*
|
||||
toughness=*
|
||||
[/card]
|
||||
[card]
|
||||
name=Call to the Netherworld
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({0}) name(pay 0 to cast) activate name(pay 0 to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature[black]|myGraveyard
|
||||
auto=moveTo(myHand)
|
||||
text=Return target black creature card from your graveyard to your hand. -- Madness {0} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={B}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
###The 2 cards below should stay together (Flip Card)###
|
||||
[card]
|
||||
name=Callow Jushi
|
||||
@@ -16746,6 +16812,18 @@ mana={1}
|
||||
type=Artifact
|
||||
[/card]
|
||||
[card]
|
||||
name=Chrome Mox
|
||||
auto=may imprint notatarget(*[-land;-artifact]|myhand)
|
||||
auto=this(variable{evictg}>0) {t}:add{g}
|
||||
auto=this(variable{evictu}>0) {t}:add{u}
|
||||
auto=this(variable{evictr}>0) {t}:add{r}
|
||||
auto=this(variable{evictb}>0) {t}:add{b}
|
||||
auto=this(variable{evictw}>0) {t}:add{w}
|
||||
text=Imprint - When Chrome Mox enters the battlefield, you may exile a nonartifact, nonland card from your hand. -- {T}: Add one mana of any of the exiled card's colors to your mana pool.
|
||||
mana={0}
|
||||
type=Artifact
|
||||
[/card]
|
||||
[card]
|
||||
name=Chrome Steed
|
||||
auto=aslongas(artifact|mybattlefield) 2/2 >2
|
||||
text=Metalcraft - Chrome Steed gets +2/+2 as long as you control three or more artifacts.
|
||||
@@ -17025,6 +17103,16 @@ mana={3}{W}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Circular Logic
|
||||
abilities=madness
|
||||
target=*|stack
|
||||
auto=if cantargetcard(*|opponentstack) then transforms((,newability[pay[[{value:type:*:opponentgraveyard}]] name(pay {value} mana) donothing?fizzle])) forever else transforms((,newability[pay[[{value:type:*:mygraveyard}]] name(pay {value} mana) donothing?fizzle])) forever
|
||||
autoexile=restriction{discarded} pay({U}) name(pay U to cast) activate name(pay U to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
text=Counter target spell unless its controller pays {1} for each card in your graveyard. -- Madness {U} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{U}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Citadel Castellan
|
||||
abilities=vigilance
|
||||
auto=this(cantargetcard(*[-renown]) transforms((,newability[@combatdamaged(player) from(this):counter(1/1.2) && becomes(renown) forever]))
|
||||
@@ -18283,6 +18371,17 @@ mana={3}{G}{G}{W}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Collective Restraint
|
||||
auto=aslongas(forest|mybattlefield) lord(creature|opponentbattlefield) transforms((,newability[attackcost:1]))
|
||||
auto=aslongas(island|mybattlefield) lord(creature|opponentbattlefield) transforms((,newability[attackcost:1]))
|
||||
auto=aslongas(mountain|mybattlefield) lord(creature|opponentbattlefield) transforms((,newability[attackcost:1]))
|
||||
auto=aslongas(swamp|mybattlefield) lord(creature|opponentbattlefield) transforms((,newability[attackcost:1]))
|
||||
auto=aslongas(plains|mybattlefield) lord(creature|opponentbattlefield) transforms((,newability[attackcost:1]))
|
||||
text=Domain — Creatures can't attack you unless their controller pays {X} for each creature he or she controls that's attacking you, where X is the number of basic land types among lands you control.
|
||||
mana={3}{U}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Collective Unconscious
|
||||
auto=foreach(creature|myBattlefield)draw:1
|
||||
text=Draw a card for each creature you control.
|
||||
@@ -21908,6 +22007,16 @@ mana={2}{R}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Dark Withering
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}) name(pay B to cast) activate name(pay B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature[-black]
|
||||
auto=destroy
|
||||
text=Destroy target nonblack creature. -- Madness {B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={4}{B}{B}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Darkest Hour
|
||||
auto=lord(creature) transforms((,black))
|
||||
text=All creatures are black.
|
||||
@@ -25949,6 +26058,16 @@ power=0
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Doran, the Siege Tower
|
||||
auto=lord(creature) combattoughness
|
||||
text=Each creature assigns combat damage equal to its toughness rather than its power.
|
||||
mana={W}{B}{G}
|
||||
type=Legendary Creature
|
||||
subtype=Treefolk Shaman
|
||||
power=0
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Dormant Sliver
|
||||
auto=lord(sliver) defender
|
||||
auto=@movedTo(sliver|myBattlefield):draw:1 controller
|
||||
@@ -29222,7 +29341,7 @@ type=Instant
|
||||
name=Elephant Grass
|
||||
auto=cumulativeupcost[{1}] sacrifice
|
||||
auto=lord(creature[black]|opponentbattlefield) cantattack
|
||||
auto=lord(creature[-black]|opponentbattlefield) transforms((,newability[@each mycombatbegins:pay[[{2}]] name(pay 2 mana) donothing?cantattack all(this)]))
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[attackcost:2]))
|
||||
text=Cumulative upkeep {1} (At the beginning of your upkeep, put an age counter on this permanent, then sacrifice it unless you pay its upkeep cost for each age counter on it.) -- Black creatures can't attack you. -- Nonblack creatures can't attack you unless their controller pays {2} for each creature he or she controls that's attacking you.
|
||||
mana={G}
|
||||
type=Enchantment
|
||||
@@ -34020,6 +34139,16 @@ type=Enchantment
|
||||
subtype=Aura
|
||||
[/card]
|
||||
[card]
|
||||
name=Fiery Temper
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({R}) name(pay R to cast) activate name(pay R to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature,player
|
||||
auto=damage:3
|
||||
text=Fiery Temper deals 3 damage to target creature or player. -- Madness {R} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{R}{R}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Fight to the Death
|
||||
auto=destroy all(creature[blocking;blocked])
|
||||
text=Destroy all blocking creatures and all blocked creatures.
|
||||
@@ -36577,6 +36706,16 @@ mana={2}{GW}{GW}{GW}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Frantic Purification
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({W}) name(pay W to cast) activate name(pay W to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=enchantment
|
||||
auto=destroy
|
||||
text=Destroy target enchantment. -- Madness {W} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{W}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Frantic Salvage
|
||||
target=<anyamount>artifact|mygraveyard
|
||||
auto=moveTo(mylibrary)
|
||||
@@ -37277,7 +37416,7 @@ subtype=Aura
|
||||
[card]
|
||||
name=Fury Charm
|
||||
auto=may destroy target(artifact)
|
||||
auto=may 1/1 && trample target(creature)
|
||||
auto=may name(1/1 & trample) target(creature) transforms((,newability[1/1],newability[trample])) ueot
|
||||
auto=may counter(0/0,-2,Time) target(*)
|
||||
text=Choose one - Destroy target artifact; or target creature gets +1/+1 and gains trample until end of turn; or remove two time counters from target permanent or suspended card.
|
||||
mana={1}{R}
|
||||
@@ -38754,7 +38893,7 @@ subtype=Aura
|
||||
[/card]
|
||||
[card]
|
||||
name=Ghostly Prison
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[@each mycombatbegins:pay[[{2}]] name(pay 2 mana) donothing?cantattack all(this)]))
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[attackcost:2]))
|
||||
text=Creatures can't attack you unless their controller pays {2} for each creature he or she controls that's attacking you.
|
||||
mana={2}{W}
|
||||
type=Enchantment
|
||||
@@ -41111,6 +41250,17 @@ mana={1}{B}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Goham Djinn
|
||||
auto={1}{B}:regenerate
|
||||
auto=this(variable{commonblack}>0) -2/-2
|
||||
text={1}{B}: Regenerate Goham Djinn. -- Goham Djinn gets -2/-2 as long as black is the most common color among all permanents or is tied for most common.
|
||||
mana={5}{B}
|
||||
type=Creature
|
||||
subtype=Djinn
|
||||
power=5
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Gold Myr
|
||||
auto={T}:Add{W}
|
||||
text={T}: Add {W} to your mana pool.
|
||||
@@ -41496,6 +41646,18 @@ type=Artifact
|
||||
subtype=Equipment
|
||||
[/card]
|
||||
[card]
|
||||
name=Gorgon Recluse
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}{B}) name(pay BB to cast) activate name(pay BB to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=@combat(blocked,blocking) source(this) from(creature):all(trigger[from]) phaseaction[combatends once] destroy
|
||||
text=Whenever Gorgon Recluse blocks or becomes blocked by a nonblack creature, destroy that creature at end of combat. -- Madness {B}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={3}{B}{B}
|
||||
type=Creature
|
||||
subtype=Gorgon
|
||||
power=2
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Gorilla Chieftain
|
||||
auto={1}{G}:regenerate
|
||||
text={1}{G}: Regenerate Gorilla Chieftain.
|
||||
@@ -43785,6 +43947,17 @@ mana={6}
|
||||
type=Artifact
|
||||
[/card]
|
||||
[card]
|
||||
name=Halam Djinn
|
||||
abilities=haste
|
||||
auto=this(variable{commonred}>0) -2/-2
|
||||
text=Haste -- Halam Djinn gets -2/-2 as long as red is the most common color among all permanents or is tied for most common.
|
||||
mana={5}{R}
|
||||
type=Creature
|
||||
subtype=Djinn
|
||||
power=6
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Halberdier
|
||||
abilities=first strike
|
||||
text=First strike
|
||||
@@ -48054,6 +48227,17 @@ power=2
|
||||
toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Ichor Slick
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({3}{B}) name(pay 3B to cast) activate name(pay 3B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature
|
||||
auto=-3/-3
|
||||
autohand=__CYCLING__({2})
|
||||
text=Target creature gets -3/-3 until end of turn. -- Cycling {2} ({2}, Discard this card: Draw a card.) -- Madness {3}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{B}
|
||||
type=Sorcery
|
||||
[/card]
|
||||
[card]
|
||||
name=Ichor Wellspring
|
||||
auto=draw:1
|
||||
auto=@movedTo(this|graveyard) from(battlefield):draw:1 controller
|
||||
@@ -54354,6 +54538,15 @@ power=3
|
||||
toughness=3
|
||||
[/card]
|
||||
[card]
|
||||
name=Koskun Falls
|
||||
auto=upcost[{T(creature|mybattlefield)}] sacrifice
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[attackcost:2]))
|
||||
auto=@movedTo(enchantment[world]|battlefield):sacrifice all(this)
|
||||
text=At the beginning of your upkeep, sacrifice Koskun Falls unless you tap an untapped creature you control. -- Creatures can't attack you unless their controller pays {2} for each creature he or she controls that's attacking you.
|
||||
mana={2}{B}{B}
|
||||
type=World Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Koskun Keep
|
||||
auto={T}:Add{1}
|
||||
auto={1}{T}:Add{R}
|
||||
@@ -65596,6 +65789,17 @@ power=2
|
||||
toughness=2
|
||||
[/card]
|
||||
[card]
|
||||
name=Mycosynth Golem
|
||||
abilities=affinityartifacts
|
||||
auto=lord(creature[artifact]|myhand,mylibrary,mygraveyard,myexile) affinityartifacts forcedalive
|
||||
text=Affinity for artifacts (This spell costs {1} less to cast for each artifact you control.) -- Artifact creature spells you cast have affinity for artifacts. (They cost {1} less to cast for each artifact you control.)
|
||||
mana={11}
|
||||
type=Artifact Creature
|
||||
subtype=Golem
|
||||
power=4
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Mycosynth Wellspring
|
||||
auto=may moveTo(myhand) notatarget(land[basic]|mylibrary)
|
||||
auto=@movedTo(this|graveyard) from(battlefield):may moveTo(myhand) notatarget(land[basic]|mylibrary)
|
||||
@@ -68955,6 +69159,15 @@ text={T}: Add {U} to your mana pool. -- {1}: Return Oboro, Palace in the Clouds
|
||||
type=Legendary Land
|
||||
[/card]
|
||||
[card]
|
||||
name=Obsessive Search
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({U}) name(pay U to cast) activate name(pay U to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=draw:1 controller
|
||||
text=Draw a card. -- Madness {U} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={U}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Obsianus Golem
|
||||
mana={6}
|
||||
type=Artifact Creature
|
||||
@@ -75460,7 +75673,7 @@ toughness=1
|
||||
[/card]
|
||||
[card]
|
||||
name=Propaganda
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[@each mycombatbegins:pay[[{2}]] name(pay 2 mana) donothing?cantattack all(this)]))
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[attackcost:2]))
|
||||
text=Creatures can't attack you unless their controller pays {2} for each creature he or she controls that's attacking you.
|
||||
mana={2}{U}
|
||||
type=Enchantment
|
||||
@@ -75746,6 +75959,15 @@ mana={1}{R}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Psychotic Haze
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({1}{B}) name(pay 1B to cast) activate name(pay 1B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
auto=damage:1 all(creature,player)
|
||||
text=Psychotic Haze deals 1 damage to each creature and each player. -- Madness {1}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={2}{B}{B}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=Psychotrope Thallid
|
||||
text=At the beginning of your upkeep, put a spore counter on Psychotrope Thallid. -- Remove three spore counters from Psychotrope Thallid: Put a 1/1 green Saproling creature token onto the battlefield. -- {1}, Sacrifice a Saproling: Draw a card.
|
||||
mana={2}{G}
|
||||
@@ -78865,6 +79087,17 @@ toughness=2
|
||||
[/card]
|
||||
###The 2 cards above should stay together (Flip Card)###
|
||||
[card]
|
||||
name=Reckless Wurm
|
||||
abilities=trample,madness
|
||||
autoexile=restriction{discarded} pay({2}{R}) name(pay 2R to cast) activate name(pay 2R to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
text=Trample -- Madness {2}{R} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={3}{R}{R}
|
||||
type=Creature
|
||||
subtype=Wurm
|
||||
power=4
|
||||
toughness=4
|
||||
[/card]
|
||||
[card]
|
||||
name=Reclaim
|
||||
target=*|mygraveyard
|
||||
auto=moveTo(myLibrary)
|
||||
@@ -79099,6 +79332,7 @@ auto=this(variable{plandu}>0) {t}:add{u}
|
||||
auto=this(variable{plandr}>0) {t}:add{r}
|
||||
auto=this(variable{plandb}>0) {t}:add{b}
|
||||
auto=this(variable{plandw}>0) {t}:add{w}
|
||||
auto=this(variable{plandc}>0) {t}:add{1}
|
||||
text={T}: Add to your mana pool one mana of any type that a land you control could produce.
|
||||
type=Land
|
||||
[/card]
|
||||
@@ -82405,6 +82639,17 @@ text=Ruins of Trokair enters the battlefield tapped. -- {T}: Add {W} to your man
|
||||
type=Land
|
||||
[/card]
|
||||
[card]
|
||||
name=Ruham Djinn
|
||||
abilities=first strike
|
||||
auto=this(variable{commonwhite}>0) -2/-2
|
||||
text=First strike -- -- Ruham Djinn gets -2/-2 as long as white is the most common color among all permanents or is tied for most common.
|
||||
mana={5}{W}
|
||||
type=Creature
|
||||
subtype=Djinn
|
||||
power=5
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Ruhan of the Fomori
|
||||
abilities=mustattack
|
||||
text=At the beginning of combat on your turn, choose an opponent at random. Ruhan of the Fomori attacks that player this combat if able.
|
||||
@@ -86536,7 +86781,7 @@ type=Artifact
|
||||
[/card]
|
||||
[card]
|
||||
name=Selesnya Charm
|
||||
auto=choice target(creature) 2/2 && trample ueot
|
||||
auto=choice name(2/2 & trample) target(creature) transforms((,newability[2/2],newability[trample])) ueot
|
||||
auto=choice moveTo(exile) target(creature[power>=5])
|
||||
auto=choice token(Knight,Creature Knight,2/2,white,vigilance)
|
||||
text=Choose one — Target creature gets +2/+2 and gains trample until end of turn; or exile target creature with power 5 or greater; or put a 2/2 white Knight creature token with vigilance onto the battlefield.
|
||||
@@ -97406,6 +97651,30 @@ type=Instant
|
||||
subtype=Arcane
|
||||
[/card]
|
||||
[card]
|
||||
name=Strength of Isolation
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({W}) name(pay W to cast) activate name(pay W to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature
|
||||
auto=1/2
|
||||
auto=protection from black
|
||||
text=Enchant creature -- Enchanted creature gets +1/+2 and has protection from black. -- Madness {W} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{W}
|
||||
type=Enchantment
|
||||
subtype=Aura
|
||||
[/card]
|
||||
[card]
|
||||
name=Strength of Lunacy
|
||||
abilities=madness
|
||||
autoexile=restriction{discarded} pay({B}) name(pay B to cast) activate name(pay B to cast) castcard(normal)?name(put in graveyard) moveto(ownergraveyard)
|
||||
target=creature
|
||||
auto=2/1
|
||||
auto=protection from white
|
||||
text=Enchant creature -- Enchanted creature gets +2/+1 and has protection from white. -- Madness {B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)
|
||||
mana={1}{B}
|
||||
type=Enchantment
|
||||
subtype=Aura
|
||||
[/card]
|
||||
[card]
|
||||
name=Strength of Night
|
||||
kicker={B}
|
||||
auto=all(creature|myBattlefield) 1/1 ueot
|
||||
@@ -97923,6 +98192,17 @@ mana={3}{B}{R}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Sulam Djinn
|
||||
abilities=trample
|
||||
auto=this(variable{commongreen}>0) -2/-2
|
||||
text=Trample -- Sulam Djinn gets -2/-2 as long as green is the most common color among all permanents or is tied for most common.
|
||||
mana={5}{G}
|
||||
type=Creature
|
||||
subtype=Djinn
|
||||
power=6
|
||||
toughness=6
|
||||
[/card]
|
||||
[card]
|
||||
name=Suleiman's Legacy
|
||||
auto=lord(djinn) sacrifice
|
||||
auto=lord(efreet) sacrifice
|
||||
@@ -110151,7 +110431,7 @@ toughness=1
|
||||
[card]
|
||||
name=Vitality Charm
|
||||
auto=choice token(Insect,creature insect, 1/1,green)
|
||||
auto=aslongas(creature|battlefield) choice 1/1 && trample target(creature)
|
||||
auto=aslongas(creature|battlefield) choice name(1/1 & trample) target(creature) transforms((,newability[1/1],newability[trample])) ueot
|
||||
auto=aslongas(beast|battlefield) choice regenerate target(beast)
|
||||
text=Choose one - Put a 1/1 green Insect creature token onto the battlefield; or target creature gets +1/+1 and gains trample until end of turn; or regenerate target Beast.
|
||||
mana={G}
|
||||
@@ -112045,11 +112325,10 @@ power=3
|
||||
toughness=6
|
||||
[/card]
|
||||
[card]
|
||||
name=War Dance
|
||||
auto=@each my upkeep:may counter(0/0,1,Verse)
|
||||
auto={S}:thisforeach(counter{0/0.1.Verse}) 1/1 target(creature)
|
||||
text=At the beginning of your upkeep, you may put a verse counter on War Dance. -- Sacrifice War Dance: Target creature gets +X/+X until end of turn, where X is the number of verse counters on War Dance.
|
||||
mana={G}
|
||||
name=War Cadence
|
||||
auto={X}{U}:name(Block X Cost) thisforeach(X) all(creature) transforms((,newability[blockcost:1])) ueot
|
||||
text={X}{R}: This turn, creatures can't block unless their controller pays {X} for each blocking creature he or she controls.
|
||||
mana={2}{R}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
@@ -112060,6 +112339,14 @@ mana={3}
|
||||
type=Artifact
|
||||
[/card]
|
||||
[card]
|
||||
name=War Dance
|
||||
auto=@each my upkeep:may counter(0/0,1,Verse)
|
||||
auto={S}:thisforeach(counter{0/0.1.Verse}) 1/1 target(creature)
|
||||
text=At the beginning of your upkeep, you may put a verse counter on War Dance. -- Sacrifice War Dance: Target creature gets +X/+X until end of turn, where X is the number of verse counters on War Dance.
|
||||
mana={G}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=War Elemental
|
||||
auto=this(opponentdamagecount < 1) aslongas(War Elemental|mybattlefield) sacrifice oneshot
|
||||
auto=@damagefoeof(player):may all(trigger[to]) dynamicability<!myfoe thatmuchcountersoneone tosrc!>
|
||||
@@ -112136,6 +112423,13 @@ mana={3}{W}
|
||||
type=Instant
|
||||
[/card]
|
||||
[card]
|
||||
name=War Tax
|
||||
auto={X}{U}:name(Attack X Cost) thisforeach(X) all(creature) transforms((,newability[attackcost:1])) ueot
|
||||
text={X}{U}: This turn, creatures can't attack unless their controller pays {X} for each attacking creature he or she controls.
|
||||
mana={2}{U}
|
||||
type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=War-Name Aspirant
|
||||
auto=if raid then counter(1/1,1)
|
||||
auto=cantbeblockedby(creature[power<=1])
|
||||
@@ -114046,7 +114340,7 @@ subtype=Aura
|
||||
[card]
|
||||
name=Windborn Muse
|
||||
abilities=flying
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[@each mycombatbegins:pay[[{2}]] name(pay 2 mana) donothing?cantattack all(this)]))
|
||||
auto=lord(creature|opponentbattlefield) transforms((,newability[attackcost:2]))
|
||||
text=Flying (This creature can't be blocked except by creatures with flying or reach.) -- Creatures can't attack you unless their controller pays {2} for each creature he or she controls that's attacking you.
|
||||
mana={3}{W}
|
||||
type=Creature
|
||||
@@ -115485,7 +115779,7 @@ toughness=5
|
||||
[card]
|
||||
name=Wrench Mind
|
||||
target=player
|
||||
auto=ability$!choice name(discard 2 cards) target(<2>*|myhand) reject _ choice name(discard artifact) target(artifact|myhand) reject !$ targetedplayer
|
||||
auto=ability$! name(discard 2 cards) choice name(discard 2 cards) target(<2>*|myhand) reject _ if type(artifact|myhand)~morethan~0 then name(discard artifact) choice name(discard artifact) target(artifact|myhand) reject !$ targetedplayer
|
||||
text=Target player discards two cards unless he or she discards an artifact card.
|
||||
mana={B}{B}
|
||||
type=Sorcery
|
||||
@@ -116241,6 +116535,17 @@ power=5
|
||||
toughness=5
|
||||
[/card]
|
||||
[card]
|
||||
name=Zanam Djinn
|
||||
abilities=flying
|
||||
auto=this(variable{commonblue}>0) -2/-2
|
||||
text=Flying -- Zanam Djinn gets -2/-2 as long as blue is the most common color among all permanents or is tied for most common.
|
||||
mana={5}{U}
|
||||
type=Creature
|
||||
subtype=Djinn
|
||||
power=5
|
||||
toughness=6
|
||||
[/card]
|
||||
[card]
|
||||
name=Zanikev Locust
|
||||
autograveyard={2}{B}{B}{E}:name(scavenge) counter(1/1,storedpower) target(creature) asSorcery
|
||||
abilities=flying
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
48
projects/mtg/bin/Res/test/Doran.txt
Normal file
48
projects/mtg/bin/Res/test/Doran.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
#Testing Doran, The Siege Tower
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
life:20
|
||||
inplay:140201, True Conviction
|
||||
manapool:{3}{U}
|
||||
[PLAYER2]
|
||||
life:30
|
||||
[DO]
|
||||
next
|
||||
#begin
|
||||
next
|
||||
#attackers
|
||||
140201
|
||||
next
|
||||
#blockers
|
||||
next
|
||||
#damage
|
||||
next
|
||||
eot
|
||||
eot
|
||||
#untap
|
||||
next
|
||||
#upkeep
|
||||
next
|
||||
#draw
|
||||
next
|
||||
#main1
|
||||
next
|
||||
#combat begin
|
||||
next
|
||||
#attackers
|
||||
140201
|
||||
next
|
||||
#blockers
|
||||
next
|
||||
#damage
|
||||
next
|
||||
next
|
||||
[ASSERT]
|
||||
COMBATEND
|
||||
[PLAYER1]
|
||||
inplay:140201, True Conviction
|
||||
life:40
|
||||
[PLAYER2]
|
||||
life:10
|
||||
[END]
|
||||
37
projects/mtg/bin/Res/test/Replenish.txt
Normal file
37
projects/mtg/bin/Res/test/Replenish.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
#Put in play Fists of Ironwood via Replenish
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
life:20
|
||||
hand:Replenish, 4683, Replenish
|
||||
graveyard:83672, Mass Hysteria
|
||||
inplay:Swamp, Forest, Island, Mountain, Plains
|
||||
manapool:{3}{W}
|
||||
[PLAYER2]
|
||||
life:20
|
||||
[DO]
|
||||
Replenish
|
||||
#Fists of Ironwood remains on graveyard since there are no valid targets
|
||||
Swamp
|
||||
4683
|
||||
Forest
|
||||
Island
|
||||
Plains
|
||||
Mountain
|
||||
Replenish
|
||||
#Fists of Ironwood attach on Zombie Token created by Sarcomancy, Then produces 2 Saproling Tokens
|
||||
-4683
|
||||
next
|
||||
next
|
||||
-83672
|
||||
-4683
|
||||
eot
|
||||
[ASSERT]
|
||||
UNTAP
|
||||
[PLAYER1]
|
||||
graveyard:Replenish, Replenish
|
||||
inplay:Sarcomancy, Mass Hysteria, Swamp, Forest, Island, Mountain, Plains, -4683, -83672, -83672, 83672
|
||||
life:20
|
||||
[PLAYER2]
|
||||
life:17
|
||||
[END]
|
||||
23
projects/mtg/bin/Res/test/Show_and_Tell.txt
Normal file
23
projects/mtg/bin/Res/test/Show_and_Tell.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
#Put in play Fists of Ironwood via Show and Tell
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
life:20
|
||||
hand:Show and Tell, Fists of Ironwood
|
||||
manapool:{2}{U}
|
||||
[PLAYER2]
|
||||
life:20
|
||||
[DO]
|
||||
Show and Tell
|
||||
choice 0
|
||||
Fists of Ironwood
|
||||
eot
|
||||
[ASSERT]
|
||||
UNTAP
|
||||
[PLAYER1]
|
||||
graveyard:Show and Tell
|
||||
hand:Fists of Ironwood
|
||||
life:20
|
||||
[PLAYER2]
|
||||
life:20
|
||||
[END]
|
||||
@@ -223,6 +223,7 @@ civic_wayfinder.txt
|
||||
clone.txt
|
||||
clone2.txt
|
||||
clone3.txt
|
||||
clone4.txt
|
||||
cockatrice.txt
|
||||
cockatrice_i228.txt
|
||||
colossus_of_sardia1.txt
|
||||
@@ -275,6 +276,7 @@ dingus_staff_i153.txt
|
||||
Distorting_Wake.txt
|
||||
Distorting_Wake2.txt
|
||||
divergent_growth.txt
|
||||
Doran.txt
|
||||
doomed_necromancer.txt
|
||||
double_strike_i145.txt
|
||||
double_strike2_i145.txt
|
||||
@@ -575,6 +577,7 @@ regal_force.txt
|
||||
reinforcements_1.txt
|
||||
Rending_Vines.txt
|
||||
Rending_Vines2.txt
|
||||
Replenish.txt
|
||||
resounding_roar.txt
|
||||
resurrection.txt
|
||||
resuscitate_i210.txt
|
||||
@@ -621,6 +624,7 @@ shimmer_myr_FORCEDALIVE.txt
|
||||
shivan_hellkite.txt
|
||||
shock.txt
|
||||
shock2.txt
|
||||
Show_and_Tell.txt
|
||||
siege_gang_commander.txt
|
||||
simic_initiate.txt
|
||||
slate_of_ancestry.txt
|
||||
|
||||
52
projects/mtg/bin/Res/test/clone4.txt
Normal file
52
projects/mtg/bin/Res/test/clone4.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
#Testing Clone with Thistledown Liege Fix issue #448
|
||||
#we have p/t layers
|
||||
[INIT]
|
||||
FIRSTMAIN
|
||||
[PLAYER1]
|
||||
hand:129501
|
||||
inplay:Thistledown Liege
|
||||
manapool:{3}{U}
|
||||
[PLAYER2]
|
||||
life:20
|
||||
[DO]
|
||||
129501
|
||||
choice 0
|
||||
Thistledown Liege
|
||||
next
|
||||
#begin
|
||||
next
|
||||
#attackers
|
||||
Thistledown Liege
|
||||
129501
|
||||
next
|
||||
#blockers
|
||||
next
|
||||
#damage
|
||||
next
|
||||
eot
|
||||
eot
|
||||
#untap
|
||||
next
|
||||
#upkeep
|
||||
next
|
||||
#draw
|
||||
next
|
||||
#main1
|
||||
next
|
||||
#combat begin
|
||||
next
|
||||
#attackers
|
||||
129501
|
||||
next
|
||||
#blockers
|
||||
next
|
||||
#damage
|
||||
next
|
||||
#combat end
|
||||
[ASSERT]
|
||||
COMBATEND
|
||||
[PLAYER1]
|
||||
inplay:Thistledown Liege, 129501
|
||||
[PLAYER2]
|
||||
life:14
|
||||
[END]
|
||||
@@ -202,203 +202,43 @@ private:
|
||||
}
|
||||
else if (s == "azorius")//devotion blue white
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 2);
|
||||
intValue += zone->countDevotion(dtc, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_WHITE);
|
||||
}
|
||||
else if (s == "boros")//devotion red white
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 3);
|
||||
intValue += zone->countDevotion(dtc, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_WHITE,Constants::MTG_COLOR_RED);
|
||||
}
|
||||
else if (s == "dimir")//devotion blue black
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 2);
|
||||
intValue += zone->countDevotion(dtc, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_BLUE);
|
||||
}
|
||||
else if (s == "golgari")//devotion to green black
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 1);
|
||||
intValue += zone->countDevotion(dtc, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_GREEN);
|
||||
}
|
||||
else if (s == "gruul")//devotion to green red
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 1);
|
||||
intValue += zone->countDevotion(dtc, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_RED);
|
||||
}
|
||||
else if (s == "izzet")//devotion to red blue
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 2);
|
||||
intValue += zone->countDevotion(dtc, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_RED);
|
||||
}
|
||||
else if (s == "orzhov")//devotion to white black
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 4);
|
||||
intValue += zone->countDevotion(dtc, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_WHITE);
|
||||
}
|
||||
else if (s == "rakdos")//devotion to red black
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 3);
|
||||
intValue += zone->countDevotion(dtc, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_RED);
|
||||
}
|
||||
else if (s == "selesnya")//devotion to green white
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 1);
|
||||
intValue += zone->countDevotion(dtc, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_WHITE);
|
||||
}
|
||||
else if (s == "simic")//devotion to green blue
|
||||
{
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * dp = card->getObserver()->players[i];
|
||||
MTGGameZone * dzones[] = { dp->game->inPlay, dp->game->graveyard, dp->game->hand, dp->game->library, dp->game->exile };
|
||||
for (int k = 0; k < 5; k++)
|
||||
{
|
||||
MTGGameZone * zone = dzones[k];
|
||||
if (dtc->targetsZone(zone, card)&&dp == card->controller())
|
||||
{
|
||||
intValue += zone->countDevotion(dtc, 1);
|
||||
intValue += zone->countDevotion(dtc, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN);
|
||||
}
|
||||
else if (s.find("type:") != string::npos)
|
||||
{
|
||||
@@ -565,6 +405,46 @@ private:
|
||||
intValue +=1;
|
||||
}
|
||||
}
|
||||
else if (s == "evictg")
|
||||
{
|
||||
intValue = card->imprintG;
|
||||
}
|
||||
else if (s == "evictu")
|
||||
{
|
||||
intValue = card->imprintU;
|
||||
}
|
||||
else if (s == "evictr")
|
||||
{
|
||||
intValue = card->imprintR;
|
||||
}
|
||||
else if (s == "evictb")
|
||||
{
|
||||
intValue = card->imprintB;
|
||||
}
|
||||
else if (s == "evictw")
|
||||
{
|
||||
intValue = card->imprintW;
|
||||
}
|
||||
else if (s == "commongreen")
|
||||
{
|
||||
intValue = mostCommonColor(Constants::MTG_COLOR_GREEN, card);
|
||||
}
|
||||
else if (s == "commonblue")
|
||||
{
|
||||
intValue = mostCommonColor(Constants::MTG_COLOR_BLUE, card);
|
||||
}
|
||||
else if (s == "commonred")
|
||||
{
|
||||
intValue = mostCommonColor(Constants::MTG_COLOR_RED, card);
|
||||
}
|
||||
else if (s == "commonblack")
|
||||
{
|
||||
intValue = mostCommonColor(Constants::MTG_COLOR_BLACK, card);
|
||||
}
|
||||
else if (s == "commonwhite")
|
||||
{
|
||||
intValue = mostCommonColor(Constants::MTG_COLOR_WHITE, card);
|
||||
}
|
||||
else if (s == "targetedcurses")
|
||||
{
|
||||
if(card->playerTarget)
|
||||
@@ -686,153 +566,65 @@ private:
|
||||
}
|
||||
else if (s == "olandg")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller()->opponent() && amp->output->hasColor(1))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller()->opponent());
|
||||
}
|
||||
else if (s == "olandu")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller()->opponent() && amp->output->hasColor(2))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller()->opponent());
|
||||
}
|
||||
else if (s == "olandr")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller()->opponent() && amp->output->hasColor(3))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller()->opponent());
|
||||
}
|
||||
else if (s == "olandb")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller()->opponent() && amp->output->hasColor(4))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller()->opponent());
|
||||
}
|
||||
else if (s == "olandw")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller()->opponent() && amp->output->hasColor(5))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller()->opponent());
|
||||
}
|
||||
else if (s == "olandc")
|
||||
{
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()->opponent()) +
|
||||
countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller()->opponent());
|
||||
}
|
||||
else if (s == "plandg")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller() && amp->output->hasColor(1))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller());
|
||||
}
|
||||
else if (s == "plandu")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller() && amp->output->hasColor(2))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller());
|
||||
}
|
||||
else if (s == "plandr")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller() && amp->output->hasColor(3))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller());
|
||||
}
|
||||
else if (s == "plandb")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller() && amp->output->hasColor(4))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller());
|
||||
}
|
||||
else if (s == "plandw")
|
||||
{
|
||||
intValue = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{//start
|
||||
MTGAbility * a = ((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i]);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
|
||||
if (amp && amp->source->isLand() && amp->source->controller() == target->controller() && amp->output->hasColor(5))
|
||||
intValue = 1;
|
||||
}//end
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller());
|
||||
}
|
||||
else if (s == "plandc")
|
||||
{
|
||||
intValue = countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()) +
|
||||
countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller());
|
||||
}
|
||||
else if (s == "cantargetmycre")// can target my creature
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("creature") && !card->controller()->game->battlefield->cards[j]->protectedAgainst(card))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
intValue = countCanTargetby("creature", card, card->controller());
|
||||
}
|
||||
else if (s == "cantargetoppocre")// can target opponent creature
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->opponent()->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->opponent()->game->battlefield->cards[j]->hasType("creature") && !card->controller()->opponent()->game->battlefield->cards[j]->protectedAgainst(card))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
intValue = countCanTargetby("creature", card, card->controller()->opponent());
|
||||
}
|
||||
else if (s == "cantargetcre")// can target any creature
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->opponent()->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->opponent()->game->battlefield->cards[j]->hasType("creature") && !card->controller()->opponent()->game->battlefield->cards[j]->protectedAgainst(card))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
for (int k = card->controller()->game->battlefield->nb_cards - 1; k >= 0; --k)
|
||||
{
|
||||
if (card->controller()->game->battlefield->cards[k]->hasType("creature") && !card->controller()->game->battlefield->cards[k]->protectedAgainst(card))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
intValue = countCanTargetby("creature", card, card->controller()) + countCanTargetby("creature", card, card->controller()->opponent());
|
||||
}
|
||||
else if (s == "controllerturn")//intvalue = 1 if its your turn this(variable{controllerturn})
|
||||
{
|
||||
@@ -872,107 +664,43 @@ private:
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE) && card->controller()->game->inPlay->cards[j] != card)
|
||||
{
|
||||
intValue += card->controller()->game->inPlay->cards[j]->getManaCost()->getConvertedCost();
|
||||
}
|
||||
}
|
||||
intValue += card->controller()->game->inPlay->cards[j]->getManaCost()->getConvertedCost();
|
||||
}
|
||||
else if (s == "pdauntless")//Dauntless Dourbark
|
||||
{
|
||||
intValue = 0;
|
||||
for (int j = card->controller()->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("forest"))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("treefolk"))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
MTGGameZone * checkZone = card->controller()->inPlay();
|
||||
intValue =
|
||||
countCardTypeinZone("forest",checkZone) +
|
||||
countCardTypeinZone("treefolk",checkZone);
|
||||
}
|
||||
else if (s == "pbasiclandtypes")//Basic Land types
|
||||
{
|
||||
intValue = 0;
|
||||
int forest = 0, plains = 0, swamp = 0, island = 0, mountain = 0;
|
||||
for (int j = card->controller()->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("forest"))
|
||||
{
|
||||
forest = 1;
|
||||
}
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("plains"))
|
||||
{
|
||||
plains = 1;
|
||||
}
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("swamp"))
|
||||
{
|
||||
swamp = 1;
|
||||
}
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("island"))
|
||||
{
|
||||
island = 1;
|
||||
}
|
||||
if (card->controller()->game->battlefield->cards[j]->hasType("mountain"))
|
||||
{
|
||||
mountain = 1;
|
||||
}
|
||||
}
|
||||
intValue = mountain + island + forest + swamp + plains;
|
||||
MTGGameZone * checkZone = card->controller()->inPlay();
|
||||
intValue =
|
||||
cardHasTypeinZone("forest",checkZone) +
|
||||
cardHasTypeinZone("plains",checkZone) +
|
||||
cardHasTypeinZone("swamp",checkZone) +
|
||||
cardHasTypeinZone("island",checkZone) +
|
||||
cardHasTypeinZone("mountain",checkZone);
|
||||
}
|
||||
else if (s == "myname")//Name of the card you control
|
||||
{
|
||||
intValue = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * p = card->getObserver()->players[i];
|
||||
for (int j = p->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (p->game->battlefield->cards[j]->name == card->name && p == card->controller())
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
intValue = countCardNameinZone(card->name,card->controller()->inPlay());
|
||||
}
|
||||
else if (s == "allmyname")//Plague Rats and others
|
||||
{
|
||||
intValue = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * p = card->getObserver()->players[i];
|
||||
for (int j = p->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (p->game->battlefield->cards[j]->name == card->name)
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
intValue += countCardNameinZone(card->name,card->getObserver()->players[i]->game->battlefield);
|
||||
}
|
||||
else if (s == "pgbzombie")//Soulless One
|
||||
{
|
||||
intValue = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * p = card->getObserver()->players[i];
|
||||
for (int j = p->game->graveyard->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (p->game->graveyard->cards[j]->hasType("zombie"))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
for (int j = p->game->inPlay->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (p->game->inPlay->cards[j]->hasType("zombie"))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->graveyard);
|
||||
intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->battlefield);
|
||||
}
|
||||
}
|
||||
else if (s == "pginstantsorcery")//Spellheart Chimera
|
||||
@@ -982,51 +710,31 @@ private:
|
||||
{
|
||||
if (card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_INSTANT)
|
||||
||card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_SORCERY))
|
||||
{
|
||||
intValue += 1;
|
||||
}
|
||||
intValue += 1;
|
||||
}
|
||||
}
|
||||
else if (s == "gravecardtypes")//Tarmogoyf
|
||||
{
|
||||
intValue = 0;
|
||||
int art = 0, cre = 0, enc = 0, ins = 0, lnd = 0, sor = 0, trb = 0, pwk = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Player * p = card->getObserver()->players[i];
|
||||
if(p->game->graveyard->hasType("planeswalker"))
|
||||
pwk = 1;
|
||||
if(p->game->graveyard->hasType("tribal"))
|
||||
trb = 1;
|
||||
if(p->game->graveyard->hasType("sorcery"))
|
||||
sor = 1;
|
||||
if(p->game->graveyard->hasType("land"))
|
||||
lnd = 1;
|
||||
if(p->game->graveyard->hasType("instant"))
|
||||
ins = 1;
|
||||
if(p->game->graveyard->hasType("enchantment"))
|
||||
enc = 1;
|
||||
if(p->game->graveyard->hasType("creature"))
|
||||
cre = 1;
|
||||
if(p->game->graveyard->hasType("artifact"))
|
||||
art = 1;
|
||||
MTGGameZone * checkZone = card->getObserver()->players[i]->game->graveyard;
|
||||
intValue =
|
||||
cardHasTypeinZone("planeswalker",checkZone) +
|
||||
cardHasTypeinZone("tribal",checkZone) +
|
||||
cardHasTypeinZone("sorcery",checkZone) +
|
||||
cardHasTypeinZone("land",checkZone) +
|
||||
cardHasTypeinZone("instant",checkZone) +
|
||||
cardHasTypeinZone("enchantment",checkZone) +
|
||||
cardHasTypeinZone("creature",checkZone) +
|
||||
cardHasTypeinZone("artifact",checkZone);
|
||||
}
|
||||
intValue = art + cre + enc + ins + lnd + sor + trb + pwk;
|
||||
}
|
||||
else if (s == "morethanfourcards")
|
||||
{
|
||||
if(card->playerTarget)
|
||||
{//blackvise
|
||||
intValue = 0;
|
||||
if ((card->playerTarget->game->hand->nb_cards - 4)>0)
|
||||
intValue = (card->playerTarget->game->hand->nb_cards - 4);
|
||||
}
|
||||
else
|
||||
{//viseling
|
||||
intValue = 0;
|
||||
if ((card->controller()->opponent()->game->hand->nb_cards - 4)>0)
|
||||
intValue = (card->controller()->opponent()->game->hand->nb_cards - 4);
|
||||
}
|
||||
intValue = 0;
|
||||
int damage = card->playerTarget ? card->playerTarget->game->hand->nb_cards - 4 : card->controller()->opponent()->game->hand->nb_cards - 4;
|
||||
if ( damage > 0 )
|
||||
intValue = damage;
|
||||
}
|
||||
else if (s == "powertotalinplay")//Count Total Power of Creatures you control... Formidable
|
||||
{
|
||||
@@ -1034,9 +742,7 @@ private:
|
||||
for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE))
|
||||
{
|
||||
intValue += card->controller()->game->inPlay->cards[j]->power;
|
||||
}
|
||||
intValue += card->controller()->game->inPlay->cards[j]->power;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1077,6 +783,100 @@ private:
|
||||
}
|
||||
public:
|
||||
|
||||
int countDevotionTo(MTGCardInstance * card, MTGGameZone * zone, int color1, int color2)
|
||||
{
|
||||
int counthybrid = 0;
|
||||
TargetChooserFactory dtf(card->getObserver());
|
||||
TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
|
||||
if (dtc->targetsZone(zone, card))
|
||||
{
|
||||
counthybrid += zone->countDevotion(dtc, color1, color2);
|
||||
}
|
||||
SAFE_DELETE(dtc);
|
||||
return counthybrid;
|
||||
}
|
||||
|
||||
int countCardNameinZone(string name, MTGGameZone * zone)
|
||||
{
|
||||
int count = 0;
|
||||
for( int i= 0; i < zone->nb_cards; i ++)
|
||||
if(zone->cards[i]->name == name)
|
||||
count += 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
int countCardsInPlaybyColor(int color, GameObserver * observer)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for( int j= 0; j < observer->players[i]->inPlay()->nb_cards; j++)
|
||||
if(observer->players[i]->inPlay()->cards[j]->hasColor(color))
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int mostCommonColor(int color, MTGCardInstance * card)
|
||||
{
|
||||
int maxColor = 0;
|
||||
vector<int> colors;
|
||||
|
||||
for(int i = 1; i < 6; i++)
|
||||
colors.push_back( countCardsInPlaybyColor(i, card->getObserver()) );
|
||||
|
||||
for(int j = 0; j < 5; j++)
|
||||
if ( colors[j] > maxColor )
|
||||
maxColor = colors[j];
|
||||
|
||||
if (countCardsInPlaybyColor(color, card->getObserver()) >= maxColor && maxColor > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int countCardTypeinZone(string type, MTGGameZone * zone)
|
||||
{
|
||||
int count = 0;
|
||||
for( int i= 0; i < zone->nb_cards; i ++)
|
||||
if(zone->cards[i]->hasType(type))
|
||||
count += 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
int cardHasTypeinZone(const char * type, MTGGameZone * zone)
|
||||
{
|
||||
int count = 0;
|
||||
if(zone->hasType(type))
|
||||
count = 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
int countCanTargetby(string type, MTGCardInstance * card, Player * player)
|
||||
{
|
||||
int count = 0;
|
||||
for (int j = player->game->battlefield->nb_cards - 1; j >= 0; --j)
|
||||
{
|
||||
if (player->game->battlefield->cards[j]->hasType(type) && !player->game->battlefield->cards[j]->protectedAgainst(card))
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int countManaProducedby(int color, MTGCardInstance * target, Player * player)
|
||||
{
|
||||
int count = 0;
|
||||
for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
|
||||
{
|
||||
if (dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])) &&
|
||||
(dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])))->source->isLand() &&
|
||||
(dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])))->source->controller() == player &&
|
||||
(dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])))->output->hasColor(color))
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
WParsedInt(int value = 0)
|
||||
{
|
||||
intValue = value;
|
||||
@@ -1925,7 +1725,7 @@ public:
|
||||
const string getMenuText();
|
||||
AACopier * clone() const;
|
||||
};
|
||||
//imprint
|
||||
//phaseout
|
||||
class AAPhaseOut: public ActivatedAbility
|
||||
{
|
||||
public:
|
||||
@@ -1934,6 +1734,15 @@ public:
|
||||
const string getMenuText();
|
||||
AAPhaseOut * clone() const;
|
||||
};
|
||||
//AAImprint
|
||||
class AAImprint: public ActivatedAbility
|
||||
{
|
||||
public:
|
||||
AAImprint(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
|
||||
int resolve();
|
||||
const string getMenuText();
|
||||
AAImprint * clone() const;
|
||||
};
|
||||
//cloning...this makes a token thats a copy of the target.
|
||||
class AACloner: public ActivatedAbility
|
||||
{
|
||||
@@ -5122,6 +4931,33 @@ public:
|
||||
|
||||
};
|
||||
|
||||
//AAttackSetCost
|
||||
class AAttackSetCost: public MTGAbility
|
||||
{
|
||||
public:
|
||||
string number;
|
||||
bool pw;
|
||||
AAttackSetCost(GameObserver* observer, int _id, MTGCardInstance * _source, string number, bool pw = false);
|
||||
void Update(float dt);
|
||||
int addToGame();
|
||||
int destroy();
|
||||
const string getMenuText();
|
||||
AAttackSetCost * clone() const;
|
||||
};
|
||||
|
||||
//ABlockSetCost
|
||||
class ABlockSetCost: public MTGAbility
|
||||
{
|
||||
public:
|
||||
string number;
|
||||
ABlockSetCost(GameObserver* observer, int _id, MTGCardInstance * _source, string number);
|
||||
void Update(float dt);
|
||||
int addToGame();
|
||||
int destroy();
|
||||
const string getMenuText();
|
||||
ABlockSetCost * clone() const;
|
||||
};
|
||||
|
||||
//ABlink
|
||||
class ABlink: public MTGAbility
|
||||
{
|
||||
|
||||
@@ -76,6 +76,7 @@ class SacrificeCost : public ExtraCost
|
||||
{
|
||||
public:
|
||||
SacrificeCost(TargetChooser *_tc = NULL);
|
||||
virtual int canPay();
|
||||
virtual int doPay();
|
||||
virtual SacrificeCost * clone() const;
|
||||
};
|
||||
|
||||
@@ -216,6 +216,8 @@ public:
|
||||
PAYZERO_COST = 33,
|
||||
OVERLOAD_COST = 34,
|
||||
BESTOW_COST = 35,
|
||||
ATTACK_COST = 36,
|
||||
BLOCK_COST = 37,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -257,6 +257,20 @@ public:
|
||||
int myconvertedcost;
|
||||
ManaCost * computeNewCost(MTGCardInstance * card,ManaCost * oldCost, ManaCost * refCost,bool noTrinisphere = false);
|
||||
int countTrini;
|
||||
vector<MTGCardInstance*>imprintedCards;
|
||||
int attackCost;
|
||||
int attackCostBackup;
|
||||
int attackPlaneswalkerCost;
|
||||
int attackPlaneswalkerCostBackup;
|
||||
int blockCost;
|
||||
int blockCostBackup;
|
||||
int imprintG;
|
||||
int imprintU;
|
||||
int imprintR;
|
||||
int imprintB;
|
||||
int imprintW;
|
||||
string currentimprintName;
|
||||
vector<string>imprintedNames;
|
||||
|
||||
void eventattacked();
|
||||
void eventattackedAlone();
|
||||
|
||||
@@ -243,7 +243,10 @@ class Constants
|
||||
LIBRARYEATER = 122,
|
||||
DEVOID = 123,
|
||||
CANTCHANGELIFE = 124,
|
||||
NB_BASIC_ABILITIES = 125,
|
||||
COMBATTOUGHNESS = 125,
|
||||
CANTPAYLIFE = 126,
|
||||
CANTBESACRIFIED = 127,
|
||||
NB_BASIC_ABILITIES = 128,
|
||||
|
||||
|
||||
RARITY_S = 'S', //Special Rarity
|
||||
|
||||
@@ -98,7 +98,7 @@ class MTGGameZone {
|
||||
unsigned int countByType(const string &value);
|
||||
unsigned int countByCanTarget(TargetChooser * tc);
|
||||
unsigned int countTotalManaSymbols(TargetChooser * tc, int color);
|
||||
unsigned int countDevotion(TargetChooser * tc, int color); //devotion for gods
|
||||
unsigned int countDevotion(TargetChooser * tc, int color1, int color2); //devotion for gods
|
||||
MTGCardInstance * findByName(string name);
|
||||
|
||||
//returns true if one of the cards in the zone has the ability
|
||||
|
||||
@@ -219,6 +219,18 @@ public:
|
||||
virtual MTGSuspendRule * clone() const;
|
||||
};
|
||||
|
||||
class MTGAttackCostRule: public PermanentAbility
|
||||
{
|
||||
public:
|
||||
string scost;
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||
int reactToClick(MTGCardInstance * card);
|
||||
virtual ostream& toString(ostream& out) const;
|
||||
MTGAttackCostRule(GameObserver* observer, int _id);
|
||||
const string getMenuText();
|
||||
virtual MTGAttackCostRule * clone() const;
|
||||
};
|
||||
|
||||
class MTGAttackRule: public PermanentAbility, public Limitor
|
||||
{
|
||||
public:
|
||||
@@ -274,6 +286,18 @@ public:
|
||||
virtual MTGCombatTriggersRule * clone() const;
|
||||
};
|
||||
|
||||
class MTGBlockCostRule: public PermanentAbility
|
||||
{
|
||||
public:
|
||||
string scost;
|
||||
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
|
||||
int reactToClick(MTGCardInstance * card);
|
||||
virtual ostream& toString(ostream& out) const;
|
||||
MTGBlockCostRule(GameObserver* observer, int _id);
|
||||
const string getMenuText();
|
||||
virtual MTGBlockCostRule * clone() const;
|
||||
};
|
||||
|
||||
class MTGBlockRule: public PermanentAbility
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
int getCost(int color);
|
||||
int getManaSymbols(int color);
|
||||
int getManaSymbolsHybridMerged(int color);
|
||||
int countHybridsNoPhyrexian();
|
||||
|
||||
//Returns NULL if i is greater than nbhybrids
|
||||
ManaCostHybrid * getHybridCost(unsigned int i);
|
||||
|
||||
@@ -482,6 +482,7 @@ int AACopier::resolve()
|
||||
source->copiedID = _target->getMTGId();
|
||||
source->modifiedbAbi = _target->modifiedbAbi;
|
||||
source->origbasicAbilities = _target->origbasicAbilities;
|
||||
source->basicAbilities = _target->basicAbilities;
|
||||
if(_target->isMorphed)
|
||||
{
|
||||
source->power = 2;
|
||||
@@ -510,7 +511,7 @@ AACopier * AACopier::clone() const
|
||||
return NEW AACopier(*this);
|
||||
}
|
||||
|
||||
//phaser
|
||||
//phaseout
|
||||
AAPhaseOut::AAPhaseOut(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost) :
|
||||
ActivatedAbility(observer, _id, _source, _cost, 0)
|
||||
{
|
||||
@@ -543,6 +544,60 @@ AAPhaseOut * AAPhaseOut::clone() const
|
||||
return NEW AAPhaseOut(*this);
|
||||
}
|
||||
|
||||
//AAImprint
|
||||
AAImprint::AAImprint(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost) :
|
||||
ActivatedAbility(observer, _id, _source, _cost, 0)
|
||||
{
|
||||
target = _target;
|
||||
}
|
||||
|
||||
int AAImprint::resolve()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if (_target)
|
||||
{
|
||||
Player * p = _target->controller();
|
||||
if(p)
|
||||
p->game->putInExile(_target);
|
||||
|
||||
while(_target->next)
|
||||
_target = _target->next;
|
||||
|
||||
source->imprintedCards.push_back(_target);
|
||||
|
||||
if (source->imprintedCards.size())
|
||||
{
|
||||
if (source->imprintedCards.back()->hasColor(Constants::MTG_COLOR_GREEN))
|
||||
source->imprintG += 1;
|
||||
if (source->imprintedCards.back()->hasColor(Constants::MTG_COLOR_BLUE))
|
||||
source->imprintU += 1;
|
||||
if (source->imprintedCards.back()->hasColor(Constants::MTG_COLOR_RED))
|
||||
source->imprintR += 1;
|
||||
if (source->imprintedCards.back()->hasColor(Constants::MTG_COLOR_BLACK))
|
||||
source->imprintB += 1;
|
||||
if (source->imprintedCards.back()->hasColor(Constants::MTG_COLOR_WHITE))
|
||||
source->imprintW += 1;
|
||||
if (source->imprintedCards.back()->getName().size())
|
||||
{
|
||||
source->currentimprintName = source->imprintedCards.back()->getName();
|
||||
source->imprintedNames.push_back(source->imprintedCards.back()->getName());
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const string AAImprint::getMenuText()
|
||||
{
|
||||
return "Imprint";
|
||||
}
|
||||
|
||||
AAImprint * AAImprint::clone() const
|
||||
{
|
||||
return NEW AAImprint(*this);
|
||||
}
|
||||
|
||||
//Counters
|
||||
AACounter::AACounter(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target,string counterstring, const char * _name, int power, int toughness,
|
||||
int nb,int maxNb, ManaCost * cost) :
|
||||
@@ -1312,6 +1367,16 @@ int GenericPaidAbility::resolve()
|
||||
optionalCost->extraCosts->costs[i]->setSource(((MTGCardInstance *)target));
|
||||
}
|
||||
}
|
||||
if (source && source->previous && source->basicAbilities[(int)Constants::MADNESS])
|
||||
{
|
||||
must = true;
|
||||
optionalCost = source->computeNewCost(source->previous,optionalCost,optionalCost);
|
||||
if(optionalCost->extraCosts)
|
||||
{
|
||||
for(unsigned int i = 0; i < optionalCost->extraCosts->costs.size();i++)
|
||||
optionalCost->extraCosts->costs[i]->setSource(source);
|
||||
}
|
||||
}
|
||||
if(asAlternate && nomenu && optionalCost->getConvertedCost() < 1)
|
||||
nomenuAbility->resolve();
|
||||
else
|
||||
@@ -2945,7 +3010,7 @@ int AAMover::resolve()
|
||||
//inplay is a special zone !
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (destZone == game->players[i]->game->inPlay && fromZone != game->players[i]->game->inPlay && fromZone
|
||||
if (!_target->hasSubtype(Subtypes::TYPE_AURA) && destZone == game->players[i]->game->inPlay && fromZone != game->players[i]->game->inPlay && fromZone
|
||||
!= game->players[i]->opponent()->game->inPlay)
|
||||
{
|
||||
MTGCardInstance * copy = game->players[i]->game->putInZone(_target, fromZone, game->players[i]->game->temp);
|
||||
@@ -2973,21 +3038,45 @@ int AAMover::resolve()
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p->game->putInZone(_target, fromZone, destZone);
|
||||
while(_target->next)
|
||||
_target = _target->next;
|
||||
if(andAbility)
|
||||
{
|
||||
MTGAbility * andAbilityClone = andAbility->clone();
|
||||
andAbilityClone->target = _target;
|
||||
if(andAbility->oneShot)
|
||||
{
|
||||
andAbilityClone->resolve();
|
||||
SAFE_DELETE(andAbilityClone);
|
||||
if(_target->hasSubtype(Subtypes::TYPE_AURA) && (destZone == game->players[0]->game->inPlay || destZone == game->players[1]->game->inPlay))
|
||||
{//put into play aura if there is no valid targets then it will be in its current zone
|
||||
MTGAbility *a = NEW AACastCard(game, game->mLayers->actionLayer()->getMaxId(), _target, _target,false,false,false,"","Put in play",false,true);
|
||||
a->oneShot = false;
|
||||
a->canBeInterrupted = false;
|
||||
a->addToGame();
|
||||
if(andAbility && _target->next)
|
||||
{//if successful target->next should be valid
|
||||
MTGAbility * andAbilityClone = andAbility->clone();
|
||||
andAbilityClone->target = _target->next;
|
||||
if(andAbility->oneShot)
|
||||
{
|
||||
andAbilityClone->resolve();
|
||||
SAFE_DELETE(andAbilityClone);
|
||||
}
|
||||
else
|
||||
{
|
||||
andAbilityClone->addToGame();
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
p->game->putInZone(_target, fromZone, destZone);
|
||||
while(_target->next)
|
||||
_target = _target->next;
|
||||
if(andAbility)
|
||||
{
|
||||
andAbilityClone->addToGame();
|
||||
MTGAbility * andAbilityClone = andAbility->clone();
|
||||
andAbilityClone->target = _target;
|
||||
if(andAbility->oneShot)
|
||||
{
|
||||
andAbilityClone->resolve();
|
||||
SAFE_DELETE(andAbilityClone);
|
||||
}
|
||||
else
|
||||
{
|
||||
andAbilityClone->addToGame();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@@ -5356,6 +5445,106 @@ APhaseActionGeneric::~APhaseActionGeneric()
|
||||
SAFE_DELETE(ability);
|
||||
}
|
||||
|
||||
//AAttackSetCost
|
||||
AAttackSetCost::AAttackSetCost(GameObserver* observer, int _id, MTGCardInstance * _source, string number, bool pw) :
|
||||
MTGAbility(observer, _id, _source), number(number), pw(pw)
|
||||
{
|
||||
}
|
||||
|
||||
void AAttackSetCost::Update(float dt)
|
||||
{
|
||||
if(game->getCurrentGamePhase() != MTG_PHASE_COMBATATTACKERS)
|
||||
{
|
||||
source->attackCost = source->attackCostBackup;
|
||||
if(pw)
|
||||
source->attackPlaneswalkerCost = source->attackPlaneswalkerCostBackup;
|
||||
MTGAbility::Update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
int AAttackSetCost::addToGame()
|
||||
{
|
||||
WParsedInt attackcost(number, NULL, source);
|
||||
source->attackCost += attackcost.getValue();
|
||||
source->attackCostBackup += attackcost.getValue();
|
||||
if(pw)
|
||||
{
|
||||
source->attackPlaneswalkerCost += attackcost.getValue();
|
||||
source->attackPlaneswalkerCostBackup += attackcost.getValue();
|
||||
}
|
||||
|
||||
return MTGAbility::addToGame();
|
||||
}
|
||||
|
||||
int AAttackSetCost::destroy()
|
||||
{
|
||||
|
||||
WParsedInt attackcost(number, NULL, source);
|
||||
source->attackCost -= attackcost.getValue();
|
||||
source->attackCostBackup -= attackcost.getValue();
|
||||
if(pw)
|
||||
{
|
||||
source->attackPlaneswalkerCost -= attackcost.getValue();
|
||||
source->attackPlaneswalkerCostBackup -= attackcost.getValue();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const string AAttackSetCost::getMenuText()
|
||||
{
|
||||
return "Attack Cost";
|
||||
}
|
||||
|
||||
AAttackSetCost * AAttackSetCost::clone() const
|
||||
{
|
||||
return NEW AAttackSetCost(*this);
|
||||
}
|
||||
|
||||
//ABlockSetCost
|
||||
ABlockSetCost::ABlockSetCost(GameObserver* observer, int _id, MTGCardInstance * _source, string number) :
|
||||
MTGAbility(observer, _id, _source), number(number)
|
||||
{
|
||||
}
|
||||
|
||||
void ABlockSetCost::Update(float dt)
|
||||
{
|
||||
if(game->getCurrentGamePhase() != MTG_PHASE_COMBATBLOCKERS)
|
||||
{
|
||||
source->blockCost = source->blockCostBackup;
|
||||
MTGAbility::Update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
int ABlockSetCost::addToGame()
|
||||
{
|
||||
WParsedInt blockCost(number, NULL, source);
|
||||
source->blockCost += blockCost.getValue();
|
||||
source->blockCostBackup += blockCost.getValue();
|
||||
|
||||
return MTGAbility::addToGame();
|
||||
}
|
||||
|
||||
int ABlockSetCost::destroy()
|
||||
{
|
||||
|
||||
WParsedInt blockCost(number, NULL, source);
|
||||
source->blockCost -= blockCost.getValue();
|
||||
source->blockCostBackup -= blockCost.getValue();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const string ABlockSetCost::getMenuText()
|
||||
{
|
||||
return "Block Cost";
|
||||
}
|
||||
|
||||
ABlockSetCost * ABlockSetCost::clone() const
|
||||
{
|
||||
return NEW ABlockSetCost(*this);
|
||||
}
|
||||
|
||||
//a blink
|
||||
ABlink::ABlink(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target, bool blinkueot, bool blinkForSource, bool blinkhand, MTGAbility * stored) :
|
||||
MTGAbility(observer, _id, card),blinkueot(blinkueot),blinkForSource(blinkForSource),blinkhand(blinkhand),stored(stored)
|
||||
|
||||
@@ -248,7 +248,9 @@ LifeCost::LifeCost(TargetChooser *_tc)
|
||||
int LifeCost::canPay()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if(_target->controller()->life <= 0 || _target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE))
|
||||
if (_target->controller()->life <= 0 || _target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE) ||
|
||||
_target->controller()->opponent()->game->battlefield->hasAbility(Constants::CANTPAYLIFE) ||
|
||||
_target->controller()->game->battlefield->hasAbility(Constants::CANTPAYLIFE))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -286,7 +288,9 @@ SpecificLifeCost::SpecificLifeCost(TargetChooser *_tc, int slc)
|
||||
int SpecificLifeCost::canPay()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if(_target->controller()->life >= slc && !_target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE))
|
||||
if(_target->controller()->life >= slc && !_target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE) &&
|
||||
!_target->controller()->opponent()->game->battlefield->hasAbility(Constants::CANTPAYLIFE) &&
|
||||
!_target->controller()->game->battlefield->hasAbility(Constants::CANTPAYLIFE))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -334,7 +338,16 @@ LifeorManaCost::LifeorManaCost(TargetChooser *_tc, string manaType)
|
||||
int LifeorManaCost::canPay()
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if (_target->controller()->getManaPool()->canAfford(getManaCost()) || _target->controller()->life > 1)
|
||||
if ( _target->controller()->life <= 1 || _target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE) ||
|
||||
_target->controller()->opponent()->game->battlefield->hasAbility(Constants::CANTPAYLIFE) ||
|
||||
_target->controller()->game->battlefield->hasAbility(Constants::CANTPAYLIFE))
|
||||
{
|
||||
return _target->controller()->getManaPool()->canAfford(getManaCost());
|
||||
}
|
||||
else if((_target->controller()->life > 1 || _target->controller()->getManaPool()->canAfford(getManaCost())) &&
|
||||
(!_target->controller()->inPlay()->hasAbility(Constants::CANTCHANGELIFE) &&
|
||||
!_target->controller()->opponent()->game->battlefield->hasAbility(Constants::CANTPAYLIFE) &&
|
||||
!_target->controller()->game->battlefield->hasAbility(Constants::CANTPAYLIFE)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -926,6 +939,9 @@ ExtraCost("Select creature to offer", _tc)
|
||||
|
||||
int Offering::canPay()
|
||||
{
|
||||
if (target && target->has(Constants::CANTBESACRIFIED))
|
||||
return 0;
|
||||
|
||||
if (target && (!source->controller()->getManaPool()->canAfford(source->getManaCost()->Diff(target->getManaCost()))))
|
||||
{
|
||||
tc->removeTarget(target);
|
||||
@@ -983,6 +999,13 @@ SacrificeCost::SacrificeCost(TargetChooser *_tc)
|
||||
{
|
||||
}
|
||||
|
||||
int SacrificeCost::canPay()
|
||||
{
|
||||
if (target && target->has(Constants::CANTBESACRIFIED))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SacrificeCost::doPay()
|
||||
{
|
||||
if (target)
|
||||
|
||||
@@ -687,6 +687,24 @@ void GameObserver::gameStateBasedEffects()
|
||||
card->myPair->myPair = NULL;
|
||||
card->myPair = NULL;
|
||||
}
|
||||
///clear imprints
|
||||
if(isInPlay(card) && card->imprintedCards.size())
|
||||
{
|
||||
for(size_t ic = 0; ic < card->imprintedCards.size(); ic++)
|
||||
{
|
||||
if(!isInExile(card->imprintedCards[ic]))
|
||||
{
|
||||
card->imprintG = 0;
|
||||
card->imprintU = 0;
|
||||
card->imprintR = 0;
|
||||
card->imprintB = 0;
|
||||
card->imprintW = 0;
|
||||
card->currentimprintName = "";
|
||||
card->imprintedNames.clear();
|
||||
card->imprintedCards.erase(card->imprintedCards.begin() + ic);
|
||||
}
|
||||
}
|
||||
}
|
||||
card->bypassTC = false; //turn off bypass
|
||||
////////////////////////////////////////////////////
|
||||
//Unattach Equipments that dont have valid targets//
|
||||
|
||||
@@ -1179,6 +1179,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
observer->addObserver(NEW MTGAttackRule(observer, -1));
|
||||
return NULL;
|
||||
}
|
||||
//this rule handles attacking cost ability during attacker phase
|
||||
found = s.find("attackcostrule");
|
||||
if(found != string::npos)
|
||||
{
|
||||
observer->addObserver(NEW MTGAttackCostRule(observer, -1));
|
||||
return NULL;
|
||||
}
|
||||
//this rule handles blocking ability during blocker phase
|
||||
found = s.find("blockrule");
|
||||
if(found != string::npos)
|
||||
@@ -1186,6 +1193,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
observer->addObserver(NEW MTGBlockRule(observer, -1));
|
||||
return NULL;
|
||||
}
|
||||
//this rule handles blocking cost ability during blocker phase
|
||||
found = s.find("blockcostrule");
|
||||
if(found != string::npos)
|
||||
{
|
||||
observer->addObserver(NEW MTGBlockCostRule(observer, -1));
|
||||
return NULL;
|
||||
}
|
||||
//this rule handles cards that have soulbond
|
||||
found = s.find("soulbondrule");
|
||||
if(found != string::npos)
|
||||
@@ -2361,6 +2375,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
}
|
||||
|
||||
//imprint
|
||||
found = s.find("imprint");
|
||||
if (found != string::npos)
|
||||
{
|
||||
MTGAbility * a = NEW AAImprint(observer, id, card, target);
|
||||
a->oneShot = 1;
|
||||
return a;
|
||||
}
|
||||
|
||||
//phaseout
|
||||
found = s.find("phaseout");
|
||||
if (found != string::npos)
|
||||
{
|
||||
@@ -2820,6 +2843,24 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
return NEW AReduceToAbility(observer, id, card,s.substr(9));
|
||||
}
|
||||
|
||||
//attack cost
|
||||
if (s.find("attackcost:") != string::npos)
|
||||
{
|
||||
return NEW AAttackSetCost(observer, id, card, s.substr(11));
|
||||
}
|
||||
|
||||
//attack cost + planeswalker
|
||||
if (s.find("attackpwcost:") != string::npos)
|
||||
{
|
||||
return NEW AAttackSetCost(observer, id, card, s.substr(13),true);
|
||||
}
|
||||
|
||||
//block cost
|
||||
if (s.find("blockcost:") != string::npos)
|
||||
{
|
||||
return NEW ABlockSetCost(observer, id, card, s.substr(10));
|
||||
}
|
||||
|
||||
//flanking
|
||||
if (s.find("flanker") != string::npos)
|
||||
{
|
||||
|
||||
@@ -100,8 +100,10 @@ void MTGCardInstance::copy(MTGCardInstance * card)
|
||||
setText(""); //The text is retrieved from the data anyways
|
||||
setName(data->name);
|
||||
|
||||
power = data->power;
|
||||
toughness = data->toughness;
|
||||
power = data->power;//layer 7a
|
||||
toughness = data->toughness;//layer 7a
|
||||
power += pbonus;//layer 7b
|
||||
toughness += tbonus;//layer 7b
|
||||
life = toughness;
|
||||
lifeOrig = life;
|
||||
magicText = data->magicText;
|
||||
@@ -206,6 +208,20 @@ void MTGCardInstance::initMTGCI()
|
||||
myPair = NULL;
|
||||
miracle = false;
|
||||
countTrini = 0;
|
||||
imprintedCards.clear();
|
||||
attackCost = 0;
|
||||
attackCostBackup = 0;
|
||||
attackPlaneswalkerCost = 0;
|
||||
attackPlaneswalkerCostBackup = 0;
|
||||
blockCost = 0;
|
||||
blockCostBackup = 0;
|
||||
imprintG = 0;
|
||||
imprintU = 0;
|
||||
imprintR = 0;
|
||||
imprintB = 0;
|
||||
imprintW = 0;
|
||||
currentimprintName = "";
|
||||
imprintedNames.clear();
|
||||
|
||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_SUSPEND +1; i++)
|
||||
alternateCostPaid[i] = 0;
|
||||
@@ -1525,12 +1541,13 @@ const string& MTGCardInstance::getSample()
|
||||
|
||||
int MTGCardInstance::stepPower(CombatStep step)
|
||||
{
|
||||
int damage = has(Constants::COMBATTOUGHNESS) ? toughness : power;
|
||||
switch (step)
|
||||
{
|
||||
case FIRST_STRIKE:
|
||||
case END_FIRST_STRIKE:
|
||||
if (has(Constants::FIRSTSTRIKE) || has(Constants::DOUBLESTRIKE))
|
||||
return MAX(0, power);
|
||||
return MAX(0, damage);
|
||||
else
|
||||
return 0;
|
||||
case DAMAGE:
|
||||
@@ -1539,7 +1556,7 @@ int MTGCardInstance::stepPower(CombatStep step)
|
||||
if (has(Constants::FIRSTSTRIKE) && !has(Constants::DOUBLESTRIKE))
|
||||
return 0;
|
||||
else
|
||||
return MAX(0, power);
|
||||
return MAX(0, damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,10 @@ const char* Constants::MTGBasicAbilities[] = {
|
||||
"canplayfromexile",
|
||||
"libraryeater",
|
||||
"devoid",
|
||||
"cantchangelife"
|
||||
"cantchangelife",
|
||||
"combattoughness",
|
||||
"cantpaylife",
|
||||
"cantbesacrified"
|
||||
};
|
||||
|
||||
map<string,int> Constants::MTGBasicAbilitiesMap;
|
||||
|
||||
@@ -642,7 +642,7 @@ unsigned int MTGGameZone::countTotalManaSymbols(TargetChooser * tc, int color)
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int MTGGameZone::countDevotion(TargetChooser * tc, int color)
|
||||
unsigned int MTGGameZone::countDevotion(TargetChooser * tc, int color1, int color2)
|
||||
{
|
||||
if (!tc) {
|
||||
return 0;
|
||||
@@ -654,8 +654,13 @@ unsigned int MTGGameZone::countDevotion(TargetChooser * tc, int color)
|
||||
{
|
||||
if (tc->canTarget(cards[i], withoutProtections))
|
||||
{
|
||||
result += cards[i]->getManaCost()->getManaSymbolsHybridMerged(color);
|
||||
result += cards[i]->getManaCost()->getManaSymbolsHybridMerged(color1);
|
||||
}
|
||||
if (tc->canTarget(cards[i], withoutProtections))
|
||||
{
|
||||
result += cards[i]->getManaCost()->getManaSymbolsHybridMerged(color2);
|
||||
}
|
||||
result -= cards[i]->getManaCost()->countHybridsNoPhyrexian();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1348,12 +1348,154 @@ MTGOverloadRule * MTGOverloadRule::clone() const
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//ATTACK COST
|
||||
MTGAttackCostRule::MTGAttackCostRule(GameObserver* observer, int _id) :
|
||||
PermanentAbility(observer, _id)
|
||||
{
|
||||
aType = MTGAbility::ATTACK_COST;
|
||||
scost = "Pay to attack";
|
||||
}
|
||||
|
||||
int MTGAttackCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
|
||||
{
|
||||
|
||||
if (currentPhase == MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && card->controller() == game->currentlyActing())//on my turn and when I am the acting player.
|
||||
{
|
||||
if(card->isPhased)
|
||||
return 0;
|
||||
if(card->attackCost < 1)
|
||||
return 0;
|
||||
ManaCost * playerMana = card->controller()->getManaPool();
|
||||
ManaCost * attackcost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL));
|
||||
attackcost->add(0,card->attackCostBackup);
|
||||
if(attackcost->extraCosts)
|
||||
for(unsigned int i = 0; i < attackcost->extraCosts->costs.size();i++)
|
||||
{
|
||||
attackcost->extraCosts->costs[i]->setSource(card);
|
||||
}
|
||||
scost = attackcost->getConvertedCost();
|
||||
if (playerMana->canAfford(attackcost))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGAttackCostRule::reactToClick(MTGCardInstance * card)
|
||||
{
|
||||
if (!isReactingToClick(card))
|
||||
return 0;
|
||||
Player * player = game->currentlyActing();
|
||||
ManaCost * attackcost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL));
|
||||
attackcost->add(0,card->attackCostBackup);
|
||||
ManaCost * playerMana = player->getManaPool();
|
||||
playerMana->pay(attackcost);//I think you can't pay partial cost to attack cost so you pay full (508.1i)
|
||||
card->attackCost = 0;
|
||||
card->attackPlaneswalkerCost = 0;
|
||||
return 1;
|
||||
/*
|
||||
508.1g: If any of the chosen creatures require paying costs to attack, the active player determines the total cost to attack.
|
||||
Costs may include paying mana, tapping permanents, sacrificing permanents, discarding cards, and so on. Once the total cost is determined, it becomes “locked in.”
|
||||
If effects would change the total cost after this time, ignore this change.
|
||||
508.1h: If any of the costs require mana, the active player then has a chance to activate mana abilities (see rule 605, “Mana Abilities”).
|
||||
508.1i: Once the player has enough mana in his or her mana pool, he or she pays all costs in any order. Partial payments are not allowed.
|
||||
*/
|
||||
}
|
||||
|
||||
ostream& MTGAttackCostRule::toString(ostream& out) const
|
||||
{
|
||||
out << "MTGAttackCostRule ::: (";
|
||||
return MTGAbility::toString(out) << ")";
|
||||
}
|
||||
|
||||
const string MTGAttackCostRule::getMenuText()
|
||||
{
|
||||
sprintf(menuText, "Pay to attack");
|
||||
return menuText;
|
||||
}
|
||||
|
||||
MTGAttackCostRule * MTGAttackCostRule::clone() const
|
||||
{
|
||||
return NEW MTGAttackCostRule(*this);
|
||||
}
|
||||
|
||||
//BLOCK COST
|
||||
MTGBlockCostRule::MTGBlockCostRule(GameObserver* observer, int _id) :
|
||||
PermanentAbility(observer, _id)
|
||||
{
|
||||
aType = MTGAbility::BLOCK_COST;
|
||||
scost = "Pay to block";
|
||||
}
|
||||
|
||||
int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
|
||||
{
|
||||
if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting
|
||||
&& card->controller() != game->currentPlayer
|
||||
)
|
||||
{
|
||||
if(card->isPhased)
|
||||
return 0;
|
||||
if(card->blockCost < 1)
|
||||
return 0;
|
||||
|
||||
ManaCost * playerMana = card->controller()->getManaPool();
|
||||
ManaCost * blockcost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL));
|
||||
blockcost->add(0,card->blockCostBackup);
|
||||
if(blockcost->extraCosts)
|
||||
for(unsigned int i = 0; i < blockcost->extraCosts->costs.size();i++)
|
||||
{
|
||||
blockcost->extraCosts->costs[i]->setSource(card);
|
||||
}
|
||||
scost = blockcost->getConvertedCost();
|
||||
if (playerMana->canAfford(blockcost))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MTGBlockCostRule::reactToClick(MTGCardInstance * card)
|
||||
{
|
||||
if (!isReactingToClick(card))
|
||||
return 0;
|
||||
Player * player = game->currentlyActing();
|
||||
ManaCost * blockcost = NEW ManaCost(ManaCost::parseManaCost("{0}",NULL,NULL));
|
||||
blockcost->add(0,card->blockCostBackup);
|
||||
ManaCost * playerMana = player->getManaPool();
|
||||
playerMana->pay(blockcost);//I think you can't pay partial cost to block cost so you pay full (509.1f)
|
||||
card->blockCost = 0;
|
||||
return 1;
|
||||
/*
|
||||
509.1d: If any of the chosen creatures require paying costs to block, the defending player determines the total cost to block.
|
||||
Costs may include paying mana, tapping permanents, sacrificing permanents, discarding cards, and so on.
|
||||
Once the total cost is determined, it becomes “locked in.” If effects would change the total cost after this time, ignore this change.
|
||||
509.1e: If any of the costs require mana, the defending player then has a chance to activate mana abilities (see rule 605, “Mana Abilities”).
|
||||
509.1f: Once the player has enough mana in his or her mana pool, he or she pays all costs in any order. Partial payments are not allowed.
|
||||
*/
|
||||
}
|
||||
|
||||
ostream& MTGBlockCostRule::toString(ostream& out) const
|
||||
{
|
||||
out << "MTGBlockCostRule ::: (";
|
||||
return MTGAbility::toString(out) << ")";
|
||||
}
|
||||
|
||||
const string MTGBlockCostRule::getMenuText()
|
||||
{
|
||||
sprintf(menuText, "Pay to block");
|
||||
return menuText;
|
||||
}
|
||||
|
||||
MTGBlockCostRule * MTGBlockCostRule::clone() const
|
||||
{
|
||||
return NEW MTGBlockCostRule(*this);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool MTGAttackRule::select(Target* t)
|
||||
{
|
||||
if (CardView* c = dynamic_cast<CardView*>(t))
|
||||
{
|
||||
MTGCardInstance * card = c->getCard();
|
||||
if (card->canAttack() && !card->isPhased)
|
||||
if (card->canAttack() && !card->isPhased && card->attackCost < 1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1377,7 +1519,7 @@ int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
|
||||
return 0;
|
||||
if (card->isAttacker())
|
||||
return 1;
|
||||
if (card->canAttack())
|
||||
if (card->canAttack() && card->attackCost < 1)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1453,7 +1595,7 @@ int MTGPlaneswalkerAttackRule::isReactingToClick(MTGCardInstance * card, ManaCos
|
||||
return 0;
|
||||
if (card->isAttacker())
|
||||
return 1;
|
||||
if (card->canAttack())
|
||||
if (card->canAttack() && card->attackPlaneswalkerCost < 1)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1718,7 +1860,7 @@ int MTGBlockRule::receiveEvent(WEvent *e)
|
||||
{
|
||||
MTGCardInstance * card = z->cards[i];
|
||||
if ((card->defenser && !card->defenser->has(Constants::LURE))||!card->defenser)
|
||||
if(card->canBlock(lurer))
|
||||
if(card->canBlock(lurer) && card->blockCost < 1)
|
||||
card->setDefenser(lurer);
|
||||
//force a block on a lurer, the player has a chance to set his own choice on multiple lures
|
||||
//but this action can not be ignored.
|
||||
@@ -1736,7 +1878,7 @@ int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost *)
|
||||
&& card->controller() != game->currentPlayer
|
||||
)
|
||||
{
|
||||
if (card->canBlock() && !card->isPhased)
|
||||
if (card->canBlock() && !card->isPhased && card->blockCost < 1)
|
||||
{
|
||||
if(card->isDefenser())
|
||||
blockmenu = "Remove Blocker";
|
||||
|
||||
@@ -667,7 +667,7 @@ int ManaCost::getManaSymbolsHybridMerged(int color)
|
||||
int result = cost[color];
|
||||
for (size_t i = 0; i < hybrids.size(); ++i)
|
||||
{
|
||||
result = hybrids[i].getManaSymbolsHybridMerged(color);//removed +
|
||||
result += hybrids[i].getManaSymbolsHybridMerged(color);
|
||||
}
|
||||
if (extraCosts && extraCosts->costs.size())
|
||||
{
|
||||
@@ -683,6 +683,14 @@ int ManaCost::getManaSymbolsHybridMerged(int color)
|
||||
return result;
|
||||
}
|
||||
|
||||
int ManaCost::countHybridsNoPhyrexian()
|
||||
{
|
||||
int result = 0;
|
||||
for (size_t i = 0; i < hybrids.size(); i++)
|
||||
result ++;
|
||||
return result;
|
||||
}
|
||||
|
||||
int ManaCost::parseManaSymbol(char symbol)
|
||||
{
|
||||
switch (symbol)
|
||||
|
||||
@@ -253,7 +253,9 @@ bool Player::hasPossibleAttackers()
|
||||
for (int j = 0; j < nbcards; ++j)
|
||||
{
|
||||
MTGCardInstance * c = z->cards[j];
|
||||
if (c->canAttack())
|
||||
if (!c->isTapped() &&
|
||||
!c->hasSummoningSickness() &&
|
||||
c->isCreature())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user