Merge branch 'master' into iOS-build

This commit is contained in:
xawotihs
2015-09-04 00:04:59 +02:00
22 changed files with 2938 additions and 204 deletions
File diff suppressed because it is too large Load Diff
@@ -86,17 +86,6 @@ mana={5}{U}
type=Sorcery
[/card]
[card]
name=Gravecrawler
abilities=cantblock
autograveyard=aslongas(zombie|myBattlefield) {B}:name(cast from graveyard) activate name(cast from graveyard) castcard(normal) assorcery
text=Gravecrawler can't block. -- You may cast Gravecrawler from your graveyard as long as you control a Zombie.
mana={B}
type=Creature
subtype=Zombie
power=2
toughness=1
[/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.
File diff suppressed because it is too large Load Diff
@@ -4149,15 +4149,6 @@ mana={U}{U}
type=Sorcery
[/card]
[card]
name=Draining Whelk
text=Flash (You may cast this spell any time you could cast an instant.) -- Flying -- When Draining Whelk enters the battlefield, counter target spell. Put X +1/+1 counters on Draining Whelk, where X is that spell's converted mana cost.
mana={4}{U}{U}
type=Creature
subtype=Illusion
power=1
toughness=1
[/card]
[card]
name=Drake Umbra
mana={4}{U}
type=Enchantment
@@ -7676,12 +7667,6 @@ type=Instant
text=As an additional cost to cast Induce Despair, reveal a creature card from your hand. Target creature gets -X/-X until end of turn, where X is the revealed card's converted mana cost.
[/card]
[card]
name=Induce Paranoia
text=Counter target spell. If {B} was spent to cast Induce Paranoia, that spell's controller puts the top X cards of his or her library into his or her graveyard, where X is the spell's converted mana cost.
mana={2}{U}{U}
type=Instant
[/card]
[card]
name=Inescapable Brute
text=Wither (This deals damage to creatures in the form of -1/-1 counters.) -- Inescapable Brute must be blocked if able.
mana={5}{R}
@@ -12877,13 +12862,6 @@ mana={R}{R}
type=Enchantment
[/card]
[card]
name=Ral Zarek
text=+1: Tap target permanent, then untap another target permanent. -- -2: Ral Zarek deals 3 damage to target creature or player. -- -7: Flip five coins. Take an extra turn after this one for each coin that comes up heads.
mana={2}{U}{R}
type=Planeswalker
subtype=Ral
[/card]
[card]
name=Raiding Party
text=Raiding Party can't be the target of white spells or abilities from white sources. -- Sacrifice an Orc: Each player may tap any number of untapped white creatures he or she controls. For each creature tapped this way, that player chooses up to two Plains. Then destroy all Plains that weren't chosen this way by any player.
mana={2}{R}
@@ -14513,12 +14491,6 @@ mana={W}
type=Enchantment
[/card]
[card]
name=Serum Powder
text={T}: Add {1} to your mana pool. -- Any time you could mulligan and Serum Powder is in your hand, you may exile all the cards from your hand, then draw that many cards. (You can do this in addition to taking mulligans.)
mana={3}
type=Artifact
[/card]
[card]
name=Serum Visions
text=Draw a card. -- Scry 2. (To scry 2, look at the top two cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)
mana={U}
+29
View File
@@ -0,0 +1,29 @@
# BUG..cast tundra wolves with soul warden in play, kill soul warden with last gasp, you still get a life because the spell resolved
# first before Soul Warden goes to graveyard.
[INIT]
FIRSTMAIN
[PLAYER1]
hand:Tundra Wolves
manapool:{W}
inplay:Soul Warden
life:20
[PLAYER2]
manapool:{B}{B}
hand:Last Gasp
[DO]
Tundra Wolves
no
yes
Last Gasp
Soul Warden
endinterruption
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:Soul Warden
inplay:Tundra Wolves
life:20
[PLAYER2]
graveyard:Last Gasp
life:20
[END]
@@ -16,6 +16,9 @@ choice 0
choice 0
choice 0
180595
choice 0
180595
choice 1
eot
[ASSERT]
untap
+5
View File
@@ -313,6 +313,7 @@ executioners_swing.txt
executioners_swing2.txt
executioners_swing3.txt
explore.txt
exquisite_blood_i953.txt
Faceless_Butcher.txt
fading.txt
fangren_pathcutter.txt
@@ -530,6 +531,7 @@ protomatter_powder.txt
prowess_of_the_fair.txt
prowess_of_the_fair2.txt
prowess_of_the_fair3.txt
PTInstant.txt
pygmy_troll.txt
pyknite_i426.txt
pyroclasm.txt
@@ -655,6 +657,7 @@ thallid.txt
the_tabernacle_at_pendrell_vale.txt
thelon_of_havenwood.txt
threaten.txt
thraximundar.txt
throne_of_bone.txt
thunder-thrash_elder.txt
tidal_warrior_i646.txt
@@ -662,6 +665,8 @@ tidal_warrior_i649.txt
tidal_warrior_i652.txt
Timely_Reinforcements.txt
titanic_ultimatum.txt
tokenizer.txt
tokenizer2.txt
torture.txt
tranquil_domain.txt
turn_to_slag.txt
@@ -0,0 +1,20 @@
#Bug: thraximundar ability must resolve first... and survives
[INIT]
FIRSTMAIN
[PLAYER1]
inplay:thraximundar,bloodfire colossus
manapool:{R}
[PLAYER2]
[DO]
bloodfire colossus
choice 0
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:bloodfire colossus
inplay:thraximundar
manapool:{0}
life:14
[PLAYER2]
life:14
[END]
+29
View File
@@ -0,0 +1,29 @@
# Testing Tokenizer - Parallel Lives (ISD) 249662
# Dragon Fodder (ALA) 174936
# text=Put two 1/1 red Goblin creature tokens into play.
# Tokens must be 2.. since there are no tokenizer.
[INIT]
FIRSTMAIN
[PLAYER1]
hand:174936
manapool:{R}{1}
inplay:249662
[PLAYER2]
hand:Demystify
manapool:{W}
[DO]
174936
no
yes
Demystify
249662
endinterruption
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:249662,174936
inplay:-174936,-174936
[PLAYER2]
graveyard:Demystify
life:20
[END]
+27
View File
@@ -0,0 +1,27 @@
# Testing Tokenizer - Parallel Lives (ISD) 249662
# Dragon Fodder (ALA) 174936
# text=Put two 1/1 red Goblin creature tokens into play.
# Tokens must be 8.. since there are two tokenizer... original value
# is 2 with first tokenizer it will become 4, with the second tokenizer
# the value will be 8...
[INIT]
FIRSTMAIN
[PLAYER1]
hand:174936
manapool:{R}{1}
inplay:249662,249662
[PLAYER2]
inplay:plains
hand:Demystify
[DO]
174936
[ASSERT]
FIRSTMAIN
[PLAYER1]
graveyard:174936
inplay:249662,249662,-174936,-174936,-174936,-174936,-174936,-174936,-174936,-174936
[PLAYER2]
hand:Demystify
inplay:plains
life:20
[END]
+29 -1
View File
@@ -3140,7 +3140,7 @@ public:
SAFE_DELETE(NewPow);
SAFE_DELETE(NewTou);
}
for (int i = 0; i < multiplier->getValue(); ++i)
for (int i = 0; i < Tokenizer(); ++i)
{
//MTGCardInstance * myToken;
if (tokenId)
@@ -3199,6 +3199,23 @@ public:
return 1;
}
int Tokenizer()//tokenizer
{
int tokenize = 1;
if (source->controller()->game->battlefield->hasAbility(Constants::TOKENIZER))
{
int nbcards = source->controller()->game->battlefield->nb_cards;
for (int j = 0; j < nbcards; j++)
{
if (source->controller()->game->battlefield->cards[j]->has(Constants::TOKENIZER))
tokenize *= 2;
}
return multiplier->getValue()*tokenize;
}
else
return multiplier->getValue();
}
void setTokenOwner()
{
switch(who)
@@ -5540,6 +5557,17 @@ public:
AAShuffle * clone() const;
};
//Mulligan
class AAMulligan: public ActivatedAbilityTP
{
public:
AAMulligan(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int who =
TargetChooser::UNSET);
int resolve();
const string getMenuText();
AAMulligan * clone() const;
};
//Remove Mana From ManaPool
class AARemoveMana: public ActivatedAbilityTP
{
+1
View File
@@ -151,6 +151,7 @@ class GameObserver{
bool undo();
bool isLoading(){ return mLoading; };
void Mulligan(Player* player = NULL);
void serumMulligan(Player* player = NULL);
Player* getPlayer(size_t index) { return players[index];};
bool isStarted() { return (mLayers!=NULL);};
RandomGenerator* getRandomGenerator() { return &randomGenerator; };
+2 -1
View File
@@ -219,7 +219,8 @@ class Constants
LURE = 101,
NOLEGEND = 102,
CANPLAYFROMGRAVEYARD = 103,
NB_BASIC_ABILITIES = 104,
TOKENIZER = 104,
NB_BASIC_ABILITIES = 105,
RARITY_S = 'S', //Special Rarity
+2
View File
@@ -68,6 +68,8 @@ public:
MTGInPlay * inPlay();
ManaPool * getManaPool();
void takeMulligan();
void serumMulligan();
bool DeadLifeState();
ManaCost * doesntEmpty;
ManaCost * poolDoesntEmpty;
void cleanupPhase();
+74 -26
View File
@@ -1359,6 +1359,13 @@ int AAFizzler::resolve()
sCard = sTarget->source;
if (!sCard || !sTarget || sCard->has(Constants::NOFIZZLE))
return 0;
if (source->alias == 111057 && sTarget)//Draining Whelk
{
for (int j = sTarget->cost->getConvertedCost(); j > 0; j--)
{
source->counters->addCounter(1,1);
}
}
stack->Fizzle(sTarget, fizzleMode);
return 1;
}
@@ -2482,35 +2489,49 @@ int AACloner::resolve()
Player * targetPlayer = who == 1 ? source->controller()->opponent() : source->controller();
MTGCardInstance * myClone = NEW MTGCardInstance(clone, targetPlayer->game);
targetPlayer->game->temp->addCard(myClone);
int tokenize = 1;//tokenizer support for cloning
if (targetPlayer->game->battlefield->hasAbility(Constants::TOKENIZER))
{
int nbcards = targetPlayer->game->battlefield->nb_cards;
for (int j = 0; j < nbcards; j++)
{
if (targetPlayer->game->battlefield->cards[j]->has(Constants::TOKENIZER))
tokenize *= 2;
}
}
Spell * spell = NEW Spell(game, myClone);
spell->source->isToken = 1;
spell->resolve();
spell->source->fresh = 1;
spell->source->model = spell->source;
spell->source->model->data = spell->source;
if(_target->isToken)
for (int i = 0; i < tokenize; ++i)
{
spell->source->power = _target->origpower;
spell->source->toughness = _target->origtoughness;
spell->source->life = _target->origtoughness;
MTGCardInstance * myClone = NEW MTGCardInstance(clone, targetPlayer->game);
targetPlayer->game->temp->addCard(myClone);
Spell * spell = NEW Spell(game, myClone);
spell->source->isToken = 1;
spell->resolve();
spell->source->fresh = 1;
spell->source->model = spell->source;
spell->source->model->data = spell->source;
if(_target->isToken)
{
spell->source->power = _target->origpower;
spell->source->toughness = _target->origtoughness;
spell->source->life = _target->origtoughness;
}
list<int>::iterator it;
for (it = awith.begin(); it != awith.end(); it++)
{
spell->source->basicAbilities[*it] = 1;
}
for (it = colors.begin(); it != colors.end(); it++)
{
spell->source->setColor(*it);
}
for (it = typesToAdd.begin(); it != typesToAdd.end(); it++)
{
spell->source->addType(*it);
}
delete spell;
}
list<int>::iterator it;
for (it = awith.begin(); it != awith.end(); it++)
{
spell->source->basicAbilities[*it] = 1;
}
for (it = colors.begin(); it != colors.end(); it++)
{
spell->source->setColor(*it);
}
for (it = typesToAdd.begin(); it != typesToAdd.end(); it++)
{
spell->source->addType(*it);
}
delete spell;
return 1;
}
@@ -2941,6 +2962,32 @@ AAShuffle * AAShuffle::clone() const
return NEW AAShuffle(*this);
}
// Mulligan
AAMulligan::AAMulligan(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, int who) :
ActivatedAbilityTP(observer, _id, card, _target, _cost, who)
{
}
int AAMulligan::resolve()
{
Player * player = getPlayerFromTarget(getTarget());
if (player)
{
player->serumMulligan();
}
return 1;
}
const string AAMulligan::getMenuText()
{
return "Mulligan";
}
AAMulligan * AAMulligan::clone() const
{
return NEW AAMulligan(*this);
}
// Remove Mana From ManaPool
AARemoveMana::AARemoveMana(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, string manaDesc, int who) :
ActivatedAbilityTP(observer, _id, card, _target, NULL, who)
@@ -4316,6 +4363,7 @@ int PTInstant::resolve()
APowerToughnessModifier * a = ability->clone();
GenericInstantAbility * wrapper = NEW GenericInstantAbility(game, 1, source, (Damageable *) (this->target), a);
wrapper->addToGame();
((Damageable *) (this->target))->afterDamage();//additional check the negative pt after resolving..
return 1;
}
const string PTInstant::getMenuText()
+3
View File
@@ -1242,6 +1242,9 @@ bool CardGui::FilterCard(MTGCard * _card,string filter)
if (minus)
{
cd.setisMultiColored(-1);
cd.SetExclusionColor(0);//not multicolored is monocolored not colorless, use iscolorless attribute
cd.SetExclusionColor(6);//restriction... green, red, blue, black or white colored only
cd.mode = CardDescriptor::CD_OR;
}
else
{
+8 -28
View File
@@ -727,34 +727,7 @@ void GameObserver::gameStateBasedEffects()
///////////////////////////////////////////////////////////
//life checks/poison checks also checks cant win or lose.//
///////////////////////////////////////////////////////////
if (players[i]->life <= 0 || players[i]->poisonCount >= 10)
{
int cantlosers = 0;
MTGGameZone * z = players[i]->game->inPlay;
int nbcards = z->nb_cards;
for (int j = 0; j < nbcards; ++j)
{
MTGCardInstance * c = z->cards[j];
if (c->has(Constants::CANTLOSE) || (c->has(Constants::CANTLIFELOSE) && players[i]->poisonCount < 10))
{
cantlosers++;
}
}
MTGGameZone * k = players[i]->opponent()->game->inPlay;
int onbcards = k->nb_cards;
for (int m = 0; m < onbcards; ++m)
{
MTGCardInstance * e = k->cards[m];
if (e->has(Constants::CANTWIN))
{
cantlosers++;
}
}
if (cantlosers < 1)
{
setLoser(players[i]);
}
}
players[i]->DeadLifeState();//refactored
}
//////////////////////////////////////////////////////
//-------------card based states effects------------//
@@ -1839,6 +1812,13 @@ void GameObserver::Mulligan(Player* player)
player->takeMulligan();
}
void GameObserver::serumMulligan(Player* player)
{
if(!player) player = currentPlayer;
logAction(player, "mulligan serum powder");
player->serumMulligan();
}
Player* GameObserver::createPlayer(const string& playerMode
#ifdef TESTSUITE
, TestSuiteGame* testgame
+43
View File
@@ -2532,6 +2532,16 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
return a;
}
//Serum Powder
found = s.find("serumpowder");
if (found != string::npos)
{
Targetable * t = spell? spell->getNextTarget() : NULL;
MTGAbility * a = NEW AAMulligan(observer, id, card, t, NULL, who);
a->oneShot = 1;
return a;
}
//Remove Mana from ManaPool
vector<string> splitRemove = parseBetween(s, "removemana(", ")");
if (splitRemove.size())
@@ -4942,6 +4952,39 @@ int TriggeredAbility::receiveEvent(WEvent * e)
resolve();
return 1;
}
if(dynamic_cast<WEventCardSacrifice*>(e))
{
//sacrificed event
//thraximundar vs bloodfore collosus, thraximundar
//must be able to survive a sacrificed bloodfire collosus,
//same with mortician beetle vs phyrexian denouncer test
resolve();
return 1;
}
if(dynamic_cast<WEventLife*>(e))
{
//check life state on life triger
WEventLife * lifecheck = dynamic_cast<WEventLife*>(e);
if (lifecheck->player->DeadLifeState())
{
return 0;
}
fireAbility();
return 1;
}
if(dynamic_cast<WEventDamage*>(e))
{
//check life state on damage trigger
WEventDamage * lifecheck = dynamic_cast<WEventDamage*>(e);
if (lifecheck->damage->target->type_as_damageable == Damageable::DAMAGEABLE_PLAYER)
{
Player * triggerPlayer = (Player *) lifecheck->damage->target;
if(triggerPlayer->DeadLifeState())
return 0;
}
fireAbility();
return 1;
}
WEventZoneChange * stackCheck = dynamic_cast<WEventZoneChange*>(e);
if(stackCheck && (stackCheck->to == game->currentPlayer->game->stack||stackCheck->to == game->currentPlayer->opponent()->game->stack))
{
+2 -1
View File
@@ -132,7 +132,8 @@ const char* Constants::MTGBasicAbilities[] = {
"soulbond",
"lure",
"nolegend",
"canplayfromgraveyard"
"canplayfromgraveyard",
"tokenizer"//parallel lives
};
map<string,int> Constants::MTGBasicAbilitiesMap;
+50
View File
@@ -217,6 +217,56 @@ void Player::takeMulligan()
//Draw hand with 1 less card penalty //almhum
}
void Player::serumMulligan()
{
MTGPlayerCards * currentPlayerZones = game;
int cardsinhand = currentPlayerZones->hand->nb_cards;
for (int i = 0; i < cardsinhand; i++) //Exile
currentPlayerZones->putInZone(currentPlayerZones->hand->cards[0],
currentPlayerZones->hand,
currentPlayerZones->exile);
currentPlayerZones->library->shuffle(); //Shuffle
for (int i = 0; i < (cardsinhand); i++)
game->drawFromLibrary();
//Draw hand no penalty
}
bool Player::DeadLifeState()
{
if ((life <= 0)||(poisonCount >= 10))
{
int cantlosers = 0;
MTGGameZone * z = game->inPlay;
int nbcards = z->nb_cards;
for (int j = 0; j < nbcards; ++j)
{
MTGCardInstance * c = z->cards[j];
if (c->has(Constants::CANTLOSE) || (c->has(Constants::CANTLIFELOSE) && poisonCount < 10))
{
cantlosers++;
}
}
MTGGameZone * k = opponent()->game->inPlay;
int onbcards = k->nb_cards;
for (int m = 0; m < onbcards; ++m)
{
MTGCardInstance * e = k->cards[m];
if (e->has(Constants::CANTWIN))
{
cantlosers++;
}
}
if (cantlosers < 1)
{
getObserver()->setLoser(this);
return true;
}
}
return false;
}
//Cleanup phase at the end of a turn
void Player::cleanupPhase()
{
+3
View File
@@ -503,6 +503,9 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
if (minus)
{
cd->setisMultiColored(-1);
cd->SetExclusionColor(0);//not multicolored is monocolored not colorless, use iscolorless attribute
cd->SetExclusionColor(6);//restriction... green, red, blue, black or white colored only
cd->mode = CardDescriptor::CD_OR;
}
else
{