Erwan
-fix for issue 604 (Land play limitation should not apply in all cases) -- this adds a "castMehod" variable to MTGCardInstance. IF this variable is 0, the card was not "cast" (or for lands, "put into play" as part of the lands rule), but "added" to the battlefield with some other effect. On the other hand, if this variable is set, it means the card was cast -- as we discussed, I did not touch the "alternateCostPaid" variable, as I'm still not really sure these two concepts are actually the same
This commit is contained in:
@@ -392,6 +392,7 @@ Mimics#2.txt
|
|||||||
mirri_the_cursed.txt
|
mirri_the_cursed.txt
|
||||||
mirri_the_cursed2_i284.txt
|
mirri_the_cursed2_i284.txt
|
||||||
misc01.txt
|
misc01.txt
|
||||||
|
misty_rainforest_i604.txt
|
||||||
moat.txt
|
moat.txt
|
||||||
mobile_fort.txt
|
mobile_fort.txt
|
||||||
Morph#1.txt
|
Morph#1.txt
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#Bug: Misty Rainforst triggers the "one land per turn" limit
|
||||||
|
# see http://code.google.com/p/wagic/issues/detail?id=604
|
||||||
|
[INIT]
|
||||||
|
FIRSTMAIN
|
||||||
|
[PLAYER1]
|
||||||
|
inplay:misty rainforest
|
||||||
|
library:island
|
||||||
|
hand:forest
|
||||||
|
[PLAYER2]
|
||||||
|
[DO]
|
||||||
|
misty rainforest
|
||||||
|
island
|
||||||
|
forest
|
||||||
|
[ASSERT]
|
||||||
|
FIRSTMAIN
|
||||||
|
[PLAYER1]
|
||||||
|
life:19
|
||||||
|
graveyard:misty rainforest
|
||||||
|
inplay:island,forest
|
||||||
|
[PLAYER2]
|
||||||
|
[END]
|
||||||
@@ -4746,7 +4746,7 @@ public:
|
|||||||
{
|
{
|
||||||
|
|
||||||
counter = NEW TypeTargetChooser("land");
|
counter = NEW TypeTargetChooser("land");
|
||||||
landsPlayedThisTurn = source->controller()->game->inPlay->seenThisTurn(counter);
|
landsPlayedThisTurn = source->controller()->game->inPlay->seenThisTurn(counter, Constants::CAST_ALL);
|
||||||
PlayRestrictions * restrictions = source->controller()->game->playRestrictions;
|
PlayRestrictions * restrictions = source->controller()->game->playRestrictions;
|
||||||
landsRestriction = restrictions->getMaxPerTurnRestrictionByTargetChooser(counter);
|
landsRestriction = restrictions->getMaxPerTurnRestrictionByTargetChooser(counter);
|
||||||
restrictions->removeRestriction(landsRestriction);
|
restrictions->removeRestriction(landsRestriction);
|
||||||
@@ -4764,7 +4764,7 @@ public:
|
|||||||
|
|
||||||
int trigger()
|
int trigger()
|
||||||
{
|
{
|
||||||
int landsPlayedThisTurnUpdated = source->controller()->game->inPlay->seenThisTurn(counter);
|
int landsPlayedThisTurnUpdated = source->controller()->game->inPlay->seenThisTurn(counter, Constants::CAST_ALL);
|
||||||
if (landsPlayedThisTurnUpdated > 1 && landsPlayedThisTurnUpdated > landsPlayedThisTurn)
|
if (landsPlayedThisTurnUpdated > 1 && landsPlayedThisTurnUpdated > landsPlayedThisTurn)
|
||||||
{
|
{
|
||||||
landsPlayedThisTurn = landsPlayedThisTurnUpdated;
|
landsPlayedThisTurn = landsPlayedThisTurnUpdated;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
|||||||
int XX;
|
int XX;
|
||||||
int alternateCostPaid[ManaCost::MANA_PAID_WITH_RETRACE + 1];
|
int alternateCostPaid[ManaCost::MANA_PAID_WITH_RETRACE + 1];
|
||||||
int paymenttype;
|
int paymenttype;
|
||||||
|
int castMethod; /* Tells if the card reached its current zone by being cast or not (brought into the zone by an effect). non 0 == cast, 0 == not cast */
|
||||||
int frozen;
|
int frozen;
|
||||||
int sunburst;
|
int sunburst;
|
||||||
int equipment;
|
int equipment;
|
||||||
@@ -94,6 +95,9 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable {
|
|||||||
MTGCardInstance * next;
|
MTGCardInstance * next;
|
||||||
int doDamageTest;
|
int doDamageTest;
|
||||||
int summoningSickness;
|
int summoningSickness;
|
||||||
|
|
||||||
|
bool matchesCastFilter(int castMethod);
|
||||||
|
|
||||||
// The recommended method to test for summoning Sickness !
|
// The recommended method to test for summoning Sickness !
|
||||||
int hasSummoningSickness();
|
int hasSummoningSickness();
|
||||||
MTGCardInstance * changeController(Player * newcontroller);
|
MTGCardInstance * changeController(Player * newcontroller);
|
||||||
|
|||||||
@@ -228,6 +228,23 @@ SNOWSWAMPWALK = 90,
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum{
|
||||||
|
NOT_CAST = 0,
|
||||||
|
CAST_NORMALLY = 1,
|
||||||
|
CAST_WITH_KICKER = 2,
|
||||||
|
CAST_WITH_ALTERNATIVE = 3,
|
||||||
|
CAST_WITH_BUYBACK = 4,
|
||||||
|
CAST_WITH_FLASHBACK = 5,
|
||||||
|
CAST_WITH_RETRACE = 6,
|
||||||
|
CAST_WITH_MORPH = 7,
|
||||||
|
CAST_WITH_SUSPEND = 8,
|
||||||
|
|
||||||
|
CAST_ALTERNATE = -1, //matches all alternate costs, including itself
|
||||||
|
CAST_ALL = -2, // matches everything except NOT_CAST
|
||||||
|
CAST_DONT_CARE = -3 //matches everything
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
static char MTGColorChars[];
|
static char MTGColorChars[];
|
||||||
static const char* MTGColorStrings[];
|
static const char* MTGColorStrings[];
|
||||||
static int _r[], _g[], _b[];
|
static int _r[], _g[], _b[];
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ class MTGGameZone {
|
|||||||
int hasX();
|
int hasX();
|
||||||
|
|
||||||
//How many cards matching a TargetChooser have been put in this zone during the turn
|
//How many cards matching a TargetChooser have been put in this zone during the turn
|
||||||
int seenThisTurn(TargetChooser * tc);
|
int seenThisTurn(TargetChooser * tc, int castFilter = Constants::CAST_DONT_CARE);
|
||||||
int seenThisTurn(string s);
|
int seenThisTurn(string s, int castFilter = Constants::CAST_DONT_CARE);
|
||||||
|
|
||||||
void setOwner(Player * player);
|
void setOwner(Player * player);
|
||||||
MTGCardInstance * lastCardDrawn;
|
MTGCardInstance * lastCardDrawn;
|
||||||
|
|||||||
@@ -201,11 +201,14 @@ Interruptible(0)
|
|||||||
cost = NEW ManaCost();
|
cost = NEW ManaCost();
|
||||||
tc = NULL;
|
tc = NULL;
|
||||||
from = _source->getCurrentZone();
|
from = _source->getCurrentZone();
|
||||||
|
payResult = ManaCost::MANA_UNPAID;
|
||||||
|
source->castMethod = Constants::NOT_CAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost, int payResult) :
|
Spell::Spell(int id, MTGCardInstance * _source, TargetChooser * tc, ManaCost * _cost, int payResult) :
|
||||||
Interruptible(id), tc(tc), cost(_cost), payResult(payResult)
|
Interruptible(id), tc(tc), cost(_cost), payResult(payResult)
|
||||||
{
|
{
|
||||||
|
if (!cost) cost = NEW ManaCost();
|
||||||
source = _source;
|
source = _source;
|
||||||
mHeight = 40;
|
mHeight = 40;
|
||||||
type = ACTION_SPELL;
|
type = ACTION_SPELL;
|
||||||
@@ -215,6 +218,20 @@ Interruptible(id), tc(tc), cost(_cost), payResult(payResult)
|
|||||||
if(tc && tc->targets[i] != NULL)
|
if(tc && tc->targets[i] != NULL)
|
||||||
_source->backupTargets[i] = tc->targets[i];
|
_source->backupTargets[i] = tc->targets[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill information on how the card came into this zone. Right now the quickest way is to do it here, based on how the mana was paid...
|
||||||
|
switch(payResult) {
|
||||||
|
case ManaCost::MANA_UNPAID:
|
||||||
|
source->castMethod = Constants::NOT_CAST;
|
||||||
|
break;
|
||||||
|
case ManaCost::MANA_PAID:
|
||||||
|
case ManaCost::MANA_PAID_WITH_KICKER:
|
||||||
|
source->castMethod = Constants::CAST_NORMALLY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
source->castMethod = Constants::CAST_ALTERNATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Spell::computeX(MTGCardInstance * card)
|
int Spell::computeX(MTGCardInstance * card)
|
||||||
@@ -275,7 +292,13 @@ int Spell::resolve()
|
|||||||
if (!source->hasType("instant") && !source->hasType("sorcery"))
|
if (!source->hasType("instant") && !source->hasType("sorcery"))
|
||||||
{
|
{
|
||||||
Player * p = source->controller();
|
Player * p = source->controller();
|
||||||
|
int castMethod = source->castMethod;
|
||||||
source = p->game->putInZone(source, from, p->game->battlefield);
|
source = p->game->putInZone(source, from, p->game->battlefield);
|
||||||
|
|
||||||
|
// We need to get the information about the cast method on both the card in the stack AND the card in play,
|
||||||
|
//so we copy it from the previous card (in the stack) to the new one (in play).
|
||||||
|
source->castMethod = castMethod;
|
||||||
|
|
||||||
from = p->game->battlefield;
|
from = p->game->battlefield;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ int MTGAbility::allowedToCast(MTGCardInstance * card,Player * player)
|
|||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case CASTED_A_SPELL:
|
case CASTED_A_SPELL:
|
||||||
if(player->game->stack->seenThisTurn("*") < 1)
|
if(player->game->stack->seenThisTurn("*", Constants::CAST_ALL) < 1)
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case ONE_OF_AKIND:
|
case ONE_OF_AKIND:
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ MTGCardInstance::MTGCardInstance(MTGCard * card, MTGPlayerCards * arg_belongs_to
|
|||||||
life = toughness;
|
life = toughness;
|
||||||
preventable = 0;
|
preventable = 0;
|
||||||
flanked = 0;
|
flanked = 0;
|
||||||
|
castMethod = Constants::NOT_CAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MTGCardInstance::copy(MTGCardInstance * card)
|
void MTGCardInstance::copy(MTGCardInstance * card)
|
||||||
@@ -146,6 +147,8 @@ void MTGCardInstance::initMTGCI()
|
|||||||
damageToController = false;
|
damageToController = false;
|
||||||
wasDealtDamage = false;
|
wasDealtDamage = false;
|
||||||
suspended = false;
|
suspended = false;
|
||||||
|
castMethod = Constants::NOT_CAST;
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < ManaCost::MANA_PAID_WITH_RETRACE +1; i++)
|
for (int i = 0; i < ManaCost::MANA_PAID_WITH_RETRACE +1; i++)
|
||||||
alternateCostPaid[i] = 0;
|
alternateCostPaid[i] = 0;
|
||||||
@@ -883,7 +886,7 @@ int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent)
|
|||||||
{
|
{
|
||||||
if(opponent->view != NULL)
|
if(opponent->view != NULL)
|
||||||
{
|
{
|
||||||
//todo: qoute wololo "change this into a cool blinking effects when opposing creature has cursor focus."
|
//todo: quote wololo "change this into a cool blinking effects when opposing creature has cursor focus."
|
||||||
opponent->view->actZ += .8f;
|
opponent->view->actZ += .8f;
|
||||||
opponent->view->actT -= .2f;
|
opponent->view->actT -= .2f;
|
||||||
}
|
}
|
||||||
@@ -896,6 +899,16 @@ int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MTGCardInstance::matchesCastFilter(int castFilter) {
|
||||||
|
if(castFilter == Constants::CAST_DONT_CARE)
|
||||||
|
return true; //everything
|
||||||
|
if(castFilter == Constants::CAST_ALL)
|
||||||
|
return (castMethod != Constants::NOT_CAST); //everything except "not cast"
|
||||||
|
if (castFilter == Constants::CAST_ALTERNATE && castMethod > Constants::CAST_NORMALLY)
|
||||||
|
return true; //all alternate casts
|
||||||
|
return (castFilter == castMethod);
|
||||||
|
};
|
||||||
|
|
||||||
int MTGCardInstance::addProtection(TargetChooser * tc)
|
int MTGCardInstance::addProtection(TargetChooser * tc)
|
||||||
{
|
{
|
||||||
tc->targetter = NULL;
|
tc->targetter = NULL;
|
||||||
|
|||||||
@@ -608,7 +608,7 @@ int MTGGameZone::hasAbility(int ability)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGGameZone::seenThisTurn(TargetChooser * tc)
|
int MTGGameZone::seenThisTurn(TargetChooser * tc, int castMethod)
|
||||||
{
|
{
|
||||||
//The following 2 lines modify the passed TargetChooser. Call this function with care :/
|
//The following 2 lines modify the passed TargetChooser. Call this function with care :/
|
||||||
tc->setAllZones(); // This is to allow targetting cards without caring about the actual zone
|
tc->setAllZones(); // This is to allow targetting cards without caring about the actual zone
|
||||||
@@ -617,17 +617,18 @@ int MTGGameZone::seenThisTurn(TargetChooser * tc)
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
for (vector<MTGCardInstance *>::iterator iter = cardsSeenThisTurn.begin(); iter != cardsSeenThisTurn.end(); ++iter)
|
for (vector<MTGCardInstance *>::iterator iter = cardsSeenThisTurn.begin(); iter != cardsSeenThisTurn.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (tc->canTarget(*iter))
|
MTGCardInstance * c = (*iter);
|
||||||
|
if (c->matchesCastFilter(castMethod) && tc->canTarget(c))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGGameZone::seenThisTurn(string targetChooserDefinition)
|
int MTGGameZone::seenThisTurn(string targetChooserDefinition, int castMethod)
|
||||||
{
|
{
|
||||||
TargetChooserFactory tcf;
|
TargetChooserFactory tcf;
|
||||||
TargetChooser *tc = tcf.createTargetChooser(targetChooserDefinition, NULL);
|
TargetChooser *tc = tcf.createTargetChooser(targetChooserDefinition, NULL);
|
||||||
int result = seenThisTurn(tc);
|
int result = seenThisTurn(tc, castMethod);
|
||||||
delete(tc);
|
delete(tc);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
|||||||
if (card->hasType("land"))
|
if (card->hasType("land"))
|
||||||
{
|
{
|
||||||
MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp);
|
MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp);
|
||||||
Spell * spell = NEW Spell(copy);
|
Spell * spell = NEW Spell(0,copy,NULL,NULL, payResult);
|
||||||
spell->resolve();
|
spell->resolve();
|
||||||
delete spellCost;
|
delete spellCost;
|
||||||
delete spell;
|
delete spell;
|
||||||
@@ -151,7 +151,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
|||||||
|
|
||||||
if (card->has(Constants::STORM))
|
if (card->has(Constants::STORM))
|
||||||
{
|
{
|
||||||
int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*");
|
int storm = player->game->stack->seenThisTurn("*", Constants::CAST_ALL) + player->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
|
||||||
ManaCost * spellCost = player->getManaPool();
|
ManaCost * spellCost = player->getManaPool();
|
||||||
for (int i = storm; i > 1; i--)
|
for (int i = storm; i > 1; i--)
|
||||||
{
|
{
|
||||||
@@ -298,7 +298,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
|
|||||||
if (card->hasType("land"))
|
if (card->hasType("land"))
|
||||||
{
|
{
|
||||||
MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp);
|
MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp);
|
||||||
Spell * spell = NEW Spell(copy);
|
Spell * spell = NEW Spell(0,copy,NULL,NULL, alternateCostType);
|
||||||
copy->alternateCostPaid[alternateCostType] = 1;
|
copy->alternateCostPaid[alternateCostType] = 1;
|
||||||
spell->resolve();
|
spell->resolve();
|
||||||
SAFE_DELETE(spell);
|
SAFE_DELETE(spell);
|
||||||
@@ -316,7 +316,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
|
|||||||
|
|
||||||
if (card->has(Constants::STORM))
|
if (card->has(Constants::STORM))
|
||||||
{
|
{
|
||||||
int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*");
|
int storm = player->game->stack->seenThisTurn("*", Constants::CAST_ALL) + player->opponent()->game->stack->seenThisTurn("*", Constants::CAST_ALL);
|
||||||
for (int i = storm; i > 1; i--)
|
for (int i = storm; i > 1; i--)
|
||||||
{
|
{
|
||||||
game->mLayers->stackLayer()->addSpell(copy, NULL, playerMana, alternateCostType, 1);
|
game->mLayers->stackLayer()->addSpell(copy, NULL, playerMana, alternateCostType, 1);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone *
|
|||||||
|
|
||||||
if (maxPerTurn == NO_MAX) return PlayRestriction::CAN_PLAY;
|
if (maxPerTurn == NO_MAX) return PlayRestriction::CAN_PLAY;
|
||||||
|
|
||||||
if (zone->seenThisTurn(tc) >= maxPerTurn)
|
if (zone->seenThisTurn(tc, Constants::CAST_ALL) >= maxPerTurn)
|
||||||
return PlayRestriction::CANT_PLAY;
|
return PlayRestriction::CANT_PLAY;
|
||||||
|
|
||||||
return PlayRestriction::CAN_PLAY;
|
return PlayRestriction::CAN_PLAY;
|
||||||
|
|||||||
Reference in New Issue
Block a user