Merge branch 'master' into cmake

This commit is contained in:
xawotihs
2016-06-19 11:39:56 +02:00
32 changed files with 2202 additions and 2950 deletions

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -16,7 +16,9 @@ auto=morphrule
auto=payzerorule
auto=overloadrule
auto=attackrule
auto=attackcostrule
auto=blockrule
auto=blockcostrule
auto=combattriggerrule
auto=legendrule
auto=planeswalkerrule

View File

@@ -15,7 +15,9 @@ auto=morphrule
auto=payzerorule
auto=overloadrule
auto=attackrule
auto=attackcostrule
auto=blockrule
auto=blockcostrule
auto=combattriggerrule
auto=legendrule
auto=planeswalkerrule

View File

@@ -19,7 +19,9 @@ auto=morphrule
auto=payzerorule
auto=overloadrule
auto=attackrule
auto=attackcostrule
auto=blockrule
auto=blockcostrule
auto=combattriggerrule
auto=legendrule
auto=planeswalkerrule

View File

@@ -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)]))

View File

@@ -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

View 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]

View 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]

View 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]

View File

@@ -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

View 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]

View File

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

View File

@@ -76,6 +76,7 @@ class SacrificeCost : public ExtraCost
{
public:
SacrificeCost(TargetChooser *_tc = NULL);
virtual int canPay();
virtual int doPay();
virtual SacrificeCost * clone() const;
};

View File

@@ -216,6 +216,8 @@ public:
PAYZERO_COST = 33,
OVERLOAD_COST = 34,
BESTOW_COST = 35,
ATTACK_COST = 36,
BLOCK_COST = 37,
};
};

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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);

View File

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

View File

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

View File

@@ -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//

View File

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

View File

@@ -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);
}
}

View File

@@ -154,7 +154,10 @@ const char* Constants::MTGBasicAbilities[] = {
"canplayfromexile",
"libraryeater",
"devoid",
"cantchangelife"
"cantchangelife",
"combattoughness",
"cantpaylife",
"cantbesacrified"
};
map<string,int> Constants::MTGBasicAbilitiesMap;

View File

@@ -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;
}

View File

@@ -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";

View File

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

View File

@@ -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;