362 lines
9.5 KiB
C++
362 lines
9.5 KiB
C++
#include "PrecompiledHeader.h"
|
|
|
|
#include "CardDescriptor.h"
|
|
#include "Subtypes.h"
|
|
#include "Counters.h"
|
|
|
|
CardDescriptor::CardDescriptor()
|
|
: MTGCardInstance(), mColorExclusions(0)
|
|
{
|
|
init();
|
|
counterName = "";
|
|
counterPower = 0;
|
|
counterToughness = 0;
|
|
counterNB = 0;
|
|
mode = CD_AND;
|
|
powerComparisonMode = COMPARISON_NONE;
|
|
toughnessComparisonMode = COMPARISON_NONE;
|
|
manacostComparisonMode = COMPARISON_NONE;
|
|
counterComparisonMode = COMPARISON_NONE;
|
|
convertedManacost = -1;
|
|
compareName ="";
|
|
nameComparisonMode = COMPARISON_NONE;
|
|
colorComparisonMode = COMPARISON_NONE;
|
|
CDopponentDamaged = 0;
|
|
CDcontrollerDamaged = 0;
|
|
}
|
|
|
|
int CardDescriptor::init()
|
|
{
|
|
int result = MTGCardInstance::init();
|
|
attacker = 0;
|
|
defenser = NULL;
|
|
banding = NULL;
|
|
anyCounter = 0;
|
|
//Remove unnecessary pointers
|
|
SAFE_DELETE(counters);
|
|
SAFE_DELETE(previous);
|
|
return result;
|
|
}
|
|
|
|
void CardDescriptor::unsecureSetTapped(int i)
|
|
{
|
|
tapped = i;
|
|
}
|
|
|
|
void CardDescriptor::unsecuresetfresh(int k)
|
|
{
|
|
fresh = k;
|
|
}
|
|
|
|
void CardDescriptor::setisMultiColored(int w)
|
|
{
|
|
isMultiColored = w;
|
|
}
|
|
|
|
void CardDescriptor::setNegativeSubtype(string value)
|
|
{
|
|
int id = MTGAllCards::findType(value);
|
|
addType(-id);
|
|
}
|
|
|
|
// Very generic function to compare a value to a criterion.
|
|
// Should be easily transferable to a more generic class if desired.
|
|
bool CardDescriptor::valueInRange(int comparisonMode, int value, int criterion)
|
|
{
|
|
switch (comparisonMode)
|
|
{
|
|
case COMPARISON_AT_MOST:
|
|
return (value <= criterion);
|
|
case COMPARISON_AT_LEAST:
|
|
return (value >= criterion);
|
|
case COMPARISON_EQUAL:
|
|
return (value == criterion);
|
|
case COMPARISON_GREATER:
|
|
return (value > criterion);
|
|
case COMPARISON_LESS:
|
|
return (value < criterion);
|
|
case COMPARISON_UNEQUAL:
|
|
return (value != criterion);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card)
|
|
{
|
|
int found = 1;
|
|
for (size_t i = 0; i < types.size(); i++)
|
|
{
|
|
found = 0;
|
|
if (types[i] >= 0)
|
|
{
|
|
|
|
if (card->hasSubtype(types[i]) || (MTGAllCards::findType(card->getLCName(), false) == types[i]))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!card->hasSubtype(-types[i]) && (MTGAllCards::findType(card->getLCName(), false) != -types[i]))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
return NULL;
|
|
|
|
if (colors)
|
|
{
|
|
found = (colors & card->colors);
|
|
if (!found)
|
|
return NULL;
|
|
}
|
|
|
|
if (mColorExclusions)
|
|
{
|
|
found = mColorExclusions & card->colors;
|
|
if (found)
|
|
return NULL;
|
|
}
|
|
|
|
// Quantified restrictions are always AND-ed:
|
|
if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power))
|
|
return NULL;
|
|
if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness))
|
|
return NULL;
|
|
if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost))
|
|
return NULL;
|
|
if (nameComparisonMode && compareName != card->name)
|
|
return NULL;
|
|
return card;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card)
|
|
{
|
|
MTGCardInstance * match = card;
|
|
for (size_t i = 0; i < types.size(); i++)
|
|
{
|
|
if (types[i] >= 0)
|
|
{
|
|
if (!card->hasSubtype(types[i]) && !(MTGAllCards::findType(card->getLCName(), false) == types[i]))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (card->hasSubtype(-types[i]) || (MTGAllCards::findType(card->getLCName(), false) == -types[i]))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
}
|
|
if ((colors & card->colors) != colors)
|
|
match = NULL;
|
|
|
|
if (mColorExclusions)
|
|
{
|
|
// if any of forbidden colors intersect with card colors
|
|
if ((mColorExclusions & card->colors) != 0)
|
|
match = NULL;
|
|
}
|
|
|
|
if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power))
|
|
match = NULL;
|
|
if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness))
|
|
match = NULL;
|
|
if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost))
|
|
match = NULL;
|
|
if(nameComparisonMode && compareName != card->name)
|
|
match = NULL;
|
|
|
|
return match;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
|
|
{
|
|
|
|
MTGCardInstance * match = card;
|
|
if (mode == CD_AND)
|
|
{
|
|
match = match_and(card);
|
|
}
|
|
else if (mode == CD_OR)
|
|
{
|
|
match = match_or(card);
|
|
}
|
|
|
|
//Abilities
|
|
BasicAbilitiesSet set = basicAbilities & card->basicAbilities;
|
|
if (set != basicAbilities)
|
|
return NULL;
|
|
|
|
BasicAbilitiesSet excludedSet = mAbilityExclusions & card->basicAbilities;
|
|
if (excludedSet.any())
|
|
return NULL;
|
|
|
|
|
|
if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped()))
|
|
{
|
|
match = NULL;
|
|
}
|
|
|
|
if ((fresh == -1 && card->fresh) || (fresh == 1 && !card->fresh))
|
|
{
|
|
match = NULL;
|
|
}
|
|
|
|
if ((isMultiColored == -1 && card->isMultiColored) || (isMultiColored == 1 && !card->isMultiColored))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isLeveler == -1 && card->isLeveler) || (isLeveler == 1 && !card->isLeveler))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((CDenchanted == -1 && card->enchanted) || (CDenchanted == 1 && !card->enchanted))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((CDdamaged == -1 && card->wasDealtDamage) || (CDdamaged == 1 && !card->wasDealtDamage))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if(CDopponentDamaged == -1 || CDopponentDamaged == 1)
|
|
{
|
|
Player * p = card->controller()->opponent();//controller()->opponent();
|
|
if ((CDopponentDamaged == -1 && card->damageToOpponent && card->controller() == p) || (CDopponentDamaged == 1 && !card->damageToOpponent && card->controller() == p)
|
|
|| (CDopponentDamaged == -1 && card->damageToController && card->controller() == p->opponent()) || (CDopponentDamaged == 1 && !card->damageToController && card->controller() == p->opponent()))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((CDcontrollerDamaged == -1 && card->damageToController && card->controller() == p) || (CDcontrollerDamaged == 1 && !card->damageToController && card->controller() == p)
|
|
|| (CDcontrollerDamaged == -1 && card->damageToOpponent && card->controller() == p->opponent()) || (CDcontrollerDamaged == 1 && !card->damageToOpponent && card->controller() == p->opponent()))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
if ((isToken == -1 && card->isToken) || (isToken == 1 && !card->isToken))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if (attacker == 1)
|
|
{
|
|
if (defenser == &AnyCard)
|
|
{
|
|
if (!card->attacker && !card->defenser)
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (!card->attacker)
|
|
match = NULL;
|
|
}
|
|
}
|
|
else if (attacker == -1)
|
|
{
|
|
if (defenser == &NoCard)
|
|
{
|
|
if (card->attacker || card->defenser)
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (card->attacker)
|
|
match = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (defenser == &NoCard)
|
|
{
|
|
if (card->defenser)
|
|
match = NULL;
|
|
}
|
|
else if (defenser == &AnyCard)
|
|
{
|
|
if (!card->defenser)
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
// we don't care about the attack/blocker state
|
|
}
|
|
}
|
|
|
|
//Counters
|
|
if (anyCounter)
|
|
{
|
|
if (!(card->counters->mCount))
|
|
{
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
int hasCounter = 0;
|
|
for (int i = 0; i < card->counters->mCount; i++)
|
|
{
|
|
if (card->counters->counters[i]->nb > 0)
|
|
hasCounter = 1;
|
|
}
|
|
if (!hasCounter)
|
|
match = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (counterComparisonMode)
|
|
{
|
|
Counter * targetCounter = card->counters->hasCounter(counterName.c_str(), counterPower, counterToughness);
|
|
if (targetCounter)
|
|
{
|
|
if (!valueInRange(counterComparisonMode, targetCounter->nb, counterNB))
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (counterComparisonMode != COMPARISON_LESS && counterComparisonMode != COMPARISON_AT_MOST)
|
|
match = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return match;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match(MTGGameZone * zone)
|
|
{
|
|
return (nextmatch(zone, NULL));
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::nextmatch(MTGGameZone * zone, MTGCardInstance * previous)
|
|
{
|
|
int found = 0;
|
|
if (NULL == previous)
|
|
found = 1;
|
|
for (int i = 0; i < zone->nb_cards; i++)
|
|
{
|
|
if (found && match(zone->cards[i]))
|
|
{
|
|
return zone->cards[i];
|
|
}
|
|
if (zone->cards[i] == previous)
|
|
{
|
|
found = 1;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CardDescriptor::SetExclusionColor(int _color, int removeAllOthers)
|
|
{
|
|
if (removeAllOthers)
|
|
mColorExclusions = 0;
|
|
|
|
mColorExclusions |= ConvertColorToBitMask(_color);
|
|
}
|