- fixed issue 595 (MaxCast not working). Root cause was the stupidest typo ever in the code (maxCost instead of maxCast...)
- fixed an issue with Storm mentioned by zethfox (was counting only spells played by current player)
- Moved "max lands per turn" rule outside of the code (yay!) Please be sure to update your Rules folder!
This commit is contained in:
wagic.the.homebrew@gmail.com
2011-02-15 14:17:34 +00:00
parent fa18c60a44
commit 8dd6856453
13 changed files with 260 additions and 108 deletions
+2 -2
View File
@@ -1484,14 +1484,14 @@ int ACastRestriction::addToGame()
//For now the only modifying rule is the one for lands, so this is hardcoded here.
//This means that a modifying rule for anything lands will actually modify the lands rule.
//In the future, we need a way to "identify" rules that modify an existing restriction, probably by doing a comparison of the TargetChoosers
existingRestriction = (MaxPerTurnRestriction *) (targetPlayer->game->playRestrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID));
existingRestriction = targetPlayer->game->playRestrictions->getMaxPerTurnRestrictionByTargetChooser(restrictionsScope);
if(existingRestriction && existingRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX)
existingRestriction->maxPerTurn += value->getValue();
}
else
{
TargetChooser * _tc = restrictionsScope->clone();
existingRestriction = NEW MaxPerTurnRestriction(PlayRestriction::UNDEF_ID, _tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer));
existingRestriction = NEW MaxPerTurnRestriction(_tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer));
targetPlayer->game->playRestrictions->addRestriction(existingRestriction);
}
+1 -1
View File
@@ -18,7 +18,7 @@ const size_t kLordKeywordsCount = 5;
const string kThisKeywords[] = { "this(", "thisforeach(" };
const size_t kThisKeywordsCount = 2;
const string kMaxCastKeywords[] = { "maxplay(", "maxcost("};
const string kMaxCastKeywords[] = { "maxplay(", "maxcast("};
const int kMaxCastZones[] = { MTGGameZone::BATTLEFIELD, MTGGameZone::STACK};
const size_t kMaxCastKeywordsCount = 2;
-3
View File
@@ -260,10 +260,7 @@ void MTGPlayerCards::init()
garbage = NEW MTGGameZone();
temp = NEW MTGGameZone();
//This is a Rule that should ideally be moved as an ability in the game...
playRestrictions = NEW PlayRestrictions();
TargetChooser * tc = NEW TypeTargetChooser("land");
playRestrictions->addRestriction(NEW MaxPerTurnRestriction(PlayRestriction::LANDS_RULE_ID, tc, 1, inPlay));
}
void MTGPlayerCards::showHand()
+3 -3
View File
@@ -149,7 +149,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
if (card->has(Constants::STORM))
{
int storm = player->game->stack->seenThisTurn("*");
int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*");
ManaCost * spellCost = player->getManaPool();
for (int i = storm; i > 1; i--)
{
@@ -314,8 +314,8 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
if (card->has(Constants::STORM))
{
int storm = player->game->stack->seenThisTurn("*");
for (int i = storm; i > 1; i--)
int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*");
for (int i = storm; i > 1; i--)
{
game->mLayers->stackLayer()->addSpell(copy, NULL, playerMana, alternateCostType, 1);
}
+13 -8
View File
@@ -5,7 +5,7 @@
#include "MTGCardInstance.h"
PlayRestriction::PlayRestriction(unsigned int id, TargetChooser * tc): id(id), tc(tc)
PlayRestriction::PlayRestriction(TargetChooser * tc): tc(tc)
{
tc->setAllZones(); // This is to allow targetting cards without caring about the actual zone
tc->targetter = NULL;
@@ -17,8 +17,8 @@ PlayRestriction::~PlayRestriction()
};
MaxPerTurnRestriction::MaxPerTurnRestriction(unsigned int id, TargetChooser * tc, int maxPerTurn, MTGGameZone * zone):
PlayRestriction(id, tc), maxPerTurn(maxPerTurn), zone(zone)
MaxPerTurnRestriction::MaxPerTurnRestriction(TargetChooser * tc, int maxPerTurn, MTGGameZone * zone):
PlayRestriction(tc), maxPerTurn(maxPerTurn), zone(zone)
{}
int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone)
@@ -38,17 +38,22 @@ int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone *
};
PlayRestriction * PlayRestrictions::getRestrictionById(unsigned int id)
MaxPerTurnRestriction * PlayRestrictions::getMaxPerTurnRestrictionByTargetChooser(TargetChooser * tc)
{
if (id == PlayRestriction::UNDEF_ID)
return NULL; // do not request Restrictions that don't have an id, there are several of them
TargetChooser * _tc = tc->clone();
_tc->setAllZones(); // we don't care about the actual zone for the "equals" check
for (vector<PlayRestriction *>::iterator iter = restrictions.begin(); iter != restrictions.end(); ++iter)
{
if ((*iter)->id == id)
return *iter;
MaxPerTurnRestriction * mptr = dynamic_cast<MaxPerTurnRestriction *> (*iter);
if (mptr && mptr->tc->equals(_tc))
{
delete _tc;
return mptr;
}
}
delete _tc;
return NULL;
}
+163 -39
View File
@@ -745,7 +745,7 @@ bool TargetChooser::canTarget(Targetable * target)
}
if(source && ((source->hasSubtype("aura") || source->hasSubtype("equipment")) && source->target && source->target == card && source->target->isPhased && targetter->target == card))
return true;
//this is kinda cheating but by defualt we let auras and equipments always contenue to target a phased creature.
//this is kinda cheating but by default we let auras and equipments always continue to target a phased creature.
else if(card->isPhased)
return false;
if (source && targetter && card->isInPlay())
@@ -830,6 +830,14 @@ bool TargetChooser::validTargetsExist()
return false;
}
bool TargetChooser::equals(TargetChooser * tc)
{
//This function always return 1 for now, since the default TargetChooser targets everything
//In the future we might need to check some of "targetter" settings to take protection into account...
return true;
}
/**
a specific Card
**/
@@ -860,6 +868,20 @@ CardTargetChooser * CardTargetChooser::clone() const
return a;
}
bool CardTargetChooser::equals(TargetChooser * tc)
{
CardTargetChooser * ctc = dynamic_cast<CardTargetChooser *> (tc);
if (!ctc)
return false;
if (validTarget != ctc->validTarget) //todo, check also previous cards, see "cantarget"...
return false;
return TargetZoneChooser::equals(tc);
}
/**
Choose anything that has a given list of types
**/
@@ -940,6 +962,34 @@ TypeTargetChooser * TypeTargetChooser::clone() const
return a;
}
bool TypeTargetChooser ::equals(TargetChooser * tc)
{
TypeTargetChooser * ttc = dynamic_cast<TypeTargetChooser *> (tc);
if (!ttc)
return false;
if (nbtypes != ttc->nbtypes)
return false;
map<int,int> counts;
for (int i = 0; i < nbtypes; ++i)
{
counts[types[i]] +=1;
counts[ttc->types[i]] -=1;
}
for (int i = 0; i < nbtypes; ++i)
{
if (counts[types[i]] || counts[ttc->types[i]])
return false;
}
return TargetZoneChooser::equals(tc);
}
/**
A Target Chooser associated to a Card Descriptor object, for fine tuning of targets description
**/
@@ -1001,46 +1051,16 @@ DescriptorTargetChooser * DescriptorTargetChooser::clone() const
return a;
}
/**
Choose a creature
**/
CreatureTargetChooser::CreatureTargetChooser(MTGCardInstance * card, int _maxtargets, bool other) :
TargetZoneChooser(card, _maxtargets, other)
bool DescriptorTargetChooser::equals(TargetChooser * tc)
{
int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD };
init(default_zones, 2);
}
CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other) :
TargetZoneChooser(card, _maxtargets, other)
{
if (nbzones == 0)
{
int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD };
init(default_zones, 2);
}
else
{
init(_zones, nbzones);
}
}
DescriptorTargetChooser * dtc = dynamic_cast<DescriptorTargetChooser *> (tc);
if (!dtc)
return false;
//TODO Descriptors need to have an "equals" method too -_-
bool CreatureTargetChooser::canTarget(Targetable * target)
{
if (!TargetZoneChooser::canTarget(target)) return false;
if (target->typeAsTarget() == TARGET_CARD)
{
MTGCardInstance * card = (MTGCardInstance *) target;
return card->isCreature();
}
return false;
}
CreatureTargetChooser * CreatureTargetChooser::clone() const
{
CreatureTargetChooser * a = NEW CreatureTargetChooser(*this);
return a;
return TargetZoneChooser::equals(tc);
}
/* TargetzoneChooser targets everything in a given zone */
@@ -1114,6 +1134,35 @@ TargetZoneChooser * TargetZoneChooser::clone() const
return a;
}
bool TargetZoneChooser::equals(TargetChooser * tc)
{
TargetZoneChooser * tzc = dynamic_cast<TargetZoneChooser *> (tc);
if (!tzc)
return false;
if (nbzones!= tzc->nbzones)
return false;
map<int,int> counts;
for (int i = 0; i < nbzones; ++i)
{
counts[zones[i]] +=1;
counts[tzc->zones[i]] -=1;
}
for (int i = 0; i < nbzones; ++i)
{
if (counts[zones[i]] || counts[tzc->zones[i]])
return false;
}
//TODO: ALL_ZONES should be equivalent to something actually targetting all zones...
return TargetChooser::equals(tc);
}
/* Player Target */
PlayerTargetChooser::PlayerTargetChooser(MTGCardInstance * card, int _maxtargets, Player *p) :
TargetChooser(card, _maxtargets), p(p)
@@ -1140,6 +1189,19 @@ PlayerTargetChooser* PlayerTargetChooser::clone() const
return a;
}
bool PlayerTargetChooser::equals(TargetChooser * tc)
{
PlayerTargetChooser * ptc = dynamic_cast<PlayerTargetChooser *> (tc);
if (!ptc)
return false;
if (p != ptc->p)
return false;
return TargetChooser::equals(tc);
}
/*Damageable Target */
bool DamageableTargetChooser::canTarget(Targetable * target)
{
@@ -1156,7 +1218,7 @@ bool DamageableTargetChooser::canTarget(Targetable * target)
{
return true;
}
return CreatureTargetChooser::canTarget(target);
return TypeTargetChooser::canTarget(target);
}
DamageableTargetChooser* DamageableTargetChooser::clone() const
@@ -1165,6 +1227,16 @@ DamageableTargetChooser* DamageableTargetChooser::clone() const
return a;
}
bool DamageableTargetChooser::equals(TargetChooser * tc)
{
DamageableTargetChooser * dtc = dynamic_cast<DamageableTargetChooser *> (tc);
if (!dtc)
return false;
return TypeTargetChooser::equals(tc);
}
/*Spell */
SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) :
@@ -1196,6 +1268,19 @@ SpellTargetChooser* SpellTargetChooser::clone() const
return a;
}
bool SpellTargetChooser::equals(TargetChooser * tc)
{
SpellTargetChooser * stc = dynamic_cast<SpellTargetChooser *> (tc);
if (!stc)
return false;
if (color != stc->color)
return false;
return TargetChooser::equals(tc);
}
/*Spell or Permanent */
SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) :
TargetZoneChooser(card, _maxtargets, other)
@@ -1232,6 +1317,19 @@ SpellOrPermanentTargetChooser* SpellOrPermanentTargetChooser::clone() const
return a;
}
bool SpellOrPermanentTargetChooser::equals(TargetChooser * tc)
{
SpellOrPermanentTargetChooser * sptc = dynamic_cast<SpellOrPermanentTargetChooser *> (tc);
if (!sptc)
return false;
if (color != sptc->color)
return false;
return TargetZoneChooser::equals(tc);
}
/*Damage */
DamageTargetChooser::DamageTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, int _state) :
TargetChooser(card, _maxtargets)
@@ -1262,6 +1360,19 @@ DamageTargetChooser* DamageTargetChooser::clone() const
return a;
}
bool DamageTargetChooser::equals(TargetChooser * tc)
{
DamageTargetChooser * dtc = dynamic_cast<DamageTargetChooser *> (tc);
if (!dtc)
return false;
if (color != dtc->color || state != dtc->state)
return false;
return TargetChooser::equals(tc);
}
TriggerTargetChooser::TriggerTargetChooser(int _triggerTarget)
{
triggerTarget = _triggerTarget;
@@ -1284,3 +1395,16 @@ TriggerTargetChooser * TriggerTargetChooser::clone() const
TriggerTargetChooser * a = NEW TriggerTargetChooser(*this);
return a;
}
bool TriggerTargetChooser::equals(TargetChooser * tc)
{
TriggerTargetChooser * ttc = dynamic_cast<TriggerTargetChooser *> (tc);
if (!ttc)
return false;
if (triggerTarget != ttc->triggerTarget)
return false;
return TargetChooser::equals(tc);
}