added new auto keys, this and thisforeach, functionallity similair to aslongas and foreach, but for properties of the card as opposed to cards on the field. More details in first comment.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "../include/CardGui.h"
|
||||
#include "../include/MTGDeck.h"
|
||||
#include "../include/Translate.h"
|
||||
#include "../include/ThisDescriptor.h"
|
||||
|
||||
|
||||
int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option){
|
||||
@@ -38,8 +39,8 @@ int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option){
|
||||
Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target) {
|
||||
int nb = 1;
|
||||
string name = "";
|
||||
size_t start = s.find("(") + 1;
|
||||
size_t end = s.find(")", start);
|
||||
size_t start = 0;
|
||||
size_t end = s.length();
|
||||
size_t separator = s.find(",", start);
|
||||
if (separator == string::npos) separator = s.find(".", start);
|
||||
if (separator != string::npos){
|
||||
@@ -362,11 +363,79 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
multi->oneShot=1;
|
||||
return multi;
|
||||
}
|
||||
|
||||
//Lord, foreach, aslongas
|
||||
string lords[] = {"lord(","foreach(", "aslongas(", "all("};
|
||||
|
||||
//rather dirty way to stop thises and lords from conflicting with each other.
|
||||
string prelords[] = {"foreach(","lord(","aslongas(", "all("};
|
||||
size_t lord = string::npos;
|
||||
for (int j = 0; j < 4; ++j){
|
||||
size_t found2 = s.find(prelords[j]);
|
||||
if (found2!=string::npos && ((found == string::npos) || found2 < found)){
|
||||
lord = found2;
|
||||
}
|
||||
}
|
||||
|
||||
//This, ThisForEach;
|
||||
string thises[] = {"this(","thisforeach("};
|
||||
found = string::npos;
|
||||
int i = -1;
|
||||
for (int j = 0; j < 2; ++j){
|
||||
size_t found2 = s.find(thises[j]);
|
||||
if (found2!=string::npos && ((found == string::npos) || found2 < found)){
|
||||
found = found2;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
if (found != string::npos && found < lord) {
|
||||
size_t header = thises[i].size();
|
||||
size_t end = s.find(")", found+header);
|
||||
string s1;
|
||||
if (found == 0 || end != s.size()-1){
|
||||
s1 = s.substr(end+1);
|
||||
}else{
|
||||
s1 = s.substr(0, found);
|
||||
}
|
||||
if (end != string::npos){
|
||||
string thisDescriptorString = s.substr(found+header,end-found-header);
|
||||
ThisDescriptorFactory tdf;
|
||||
ThisDescriptor * td = tdf.createThisDescriptor(thisDescriptorString);
|
||||
|
||||
if (!td){
|
||||
OutputDebugString("MTGABILITY: Parsing Error:");
|
||||
OutputDebugString(s.c_str());
|
||||
OutputDebugString("\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MTGAbility * a = parseMagicLine(s1,id,spell, card,0,activated);
|
||||
if (!a){
|
||||
SAFE_DELETE(td);
|
||||
return NULL;
|
||||
}
|
||||
MTGAbility * result = NULL;
|
||||
int oneShot = 0;
|
||||
if (activated) oneShot = 1;
|
||||
if (card->hasType("sorcery") || card->hasType("instant")) oneShot = 1;
|
||||
if (a->oneShot) oneShot = 1;
|
||||
Damageable * _target = NULL;
|
||||
if (spell) _target = spell->getNextDamageableTarget();
|
||||
if (!_target) _target = target;
|
||||
|
||||
switch(i){
|
||||
case 0: result = NEW AThis(id, card, _target, td, a); break;
|
||||
case 1: result = NEW AThisForEach(id, card, _target, td, a); break;
|
||||
default: result = NULL;
|
||||
}
|
||||
if (result) result->oneShot = oneShot;
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//Lord, foreach, aslongas
|
||||
string lords[] = {"lord(","foreach(","aslongas(", "all("};
|
||||
found = string::npos;
|
||||
i = -1;
|
||||
for (int j = 0; j < 4; ++j){
|
||||
size_t found2 = s.find(lords[j]);
|
||||
if (found2!=string::npos && ((found == string::npos) || found2 < found)){
|
||||
@@ -451,6 +520,8 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
|
||||
SAFE_DELETE(tc);
|
||||
|
||||
|
||||
|
||||
//Cycling
|
||||
found = s.find("cycling");
|
||||
if (found != string::npos){
|
||||
@@ -730,7 +801,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
if (found != string::npos){
|
||||
size_t start = s.find("(");
|
||||
size_t end = s.find(")");
|
||||
string counterString = s.substr(start,end-start+1);
|
||||
string counterString = s.substr(start+1,end-start-1);
|
||||
Counter * counter = parseCounter(counterString,target);
|
||||
if (counter){
|
||||
MTGAbility * a = NEW AACounter(id,card,target,counter->name.c_str(),counter->power,counter->toughness,counter->nb);
|
||||
|
||||
@@ -71,7 +71,7 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan
|
||||
size_t counter_start = value.find("(");
|
||||
size_t counter_end = value.find(")", counter_start);
|
||||
AbilityFactory * abf = NEW AbilityFactory();
|
||||
string counterString = value.substr(counter_start,counter_end-counter_start);
|
||||
string counterString = value.substr(counter_start+1,counter_end-counter_start-1);
|
||||
Counter * counter = abf->parseCounter(counterString,c);
|
||||
size_t separator = value.find(",",counter_start);
|
||||
size_t separator2 = string::npos;
|
||||
|
||||
@@ -204,9 +204,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
|
||||
}else{
|
||||
size_t start = attribute.find("{");
|
||||
size_t end = attribute.find("}");
|
||||
string counterString = attribute.substr(start,end-start+1);
|
||||
counterString.replace(0,1,"(");
|
||||
counterString.replace(counterString.length() - 1,1,")");
|
||||
string counterString = attribute.substr(start+1,end-start-1);
|
||||
AbilityFactory * abf = NEW AbilityFactory();
|
||||
Counter * counter = abf->parseCounter(counterString,card);
|
||||
if (counter) {
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
#include "../include/config.h"
|
||||
#include "../include/ThisDescriptor.h"
|
||||
#include "../include/Counters.h"
|
||||
#include "../include/MTGCardInstance.h"
|
||||
#include "../include/CardDescriptor.h"
|
||||
|
||||
|
||||
//Returns the amount by which a value passes the comparison.
|
||||
int ThisDescriptor::matchValue(int value){
|
||||
switch (comparisonMode){
|
||||
case COMPARISON_AT_MOST:
|
||||
return (comparisonCriterion - value + 1);
|
||||
case COMPARISON_AT_LEAST:
|
||||
return (value - comparisonCriterion + 1);
|
||||
case COMPARISON_EQUAL:
|
||||
return (comparisonCriterion == value);
|
||||
case COMPARISON_GREATER:
|
||||
return (value - comparisonCriterion);
|
||||
case COMPARISON_LESS:
|
||||
return (comparisonCriterion - value);
|
||||
case COMPARISON_UNEQUAL:
|
||||
return (comparisonCriterion != value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThisDescriptor * ThisDescriptorFactory::createThisDescriptor(string s){
|
||||
size_t found;
|
||||
|
||||
string whitespaces (" \t\f\v\n\r");
|
||||
|
||||
found=s.find_last_not_of(whitespaces);
|
||||
if (found!=string::npos)
|
||||
s.erase(found+1);
|
||||
else return NULL;
|
||||
|
||||
found=s.find_first_not_of(whitespaces);
|
||||
if (found!=string::npos)
|
||||
s.erase(0,found);
|
||||
else return NULL;
|
||||
|
||||
//set comparison mode
|
||||
//equal, greater, and less must remain above the others, otherwise the others may never be used.
|
||||
int mode = 0;
|
||||
size_t found2 = string::npos;
|
||||
int opLength = 0;
|
||||
|
||||
found = s.find("=");
|
||||
if (found != string::npos){
|
||||
mode = COMPARISON_EQUAL;
|
||||
found2 = found + 1;
|
||||
opLength = 1;
|
||||
}
|
||||
found = s.find(">");
|
||||
if (found != string::npos){
|
||||
mode = COMPARISON_GREATER;
|
||||
found2 = found + 1;
|
||||
opLength = 1;
|
||||
}
|
||||
found = s.find("<");
|
||||
if (found != string::npos){
|
||||
mode = COMPARISON_LESS;
|
||||
found2 = found + 1;
|
||||
opLength = 1;
|
||||
}
|
||||
found = s.find("<=");
|
||||
if (found != string::npos){
|
||||
mode = COMPARISON_AT_MOST;
|
||||
found2 = found + 2;
|
||||
opLength = 2;
|
||||
}
|
||||
found = s.find(">=");
|
||||
if (found != string::npos){
|
||||
mode = COMPARISON_AT_LEAST;
|
||||
found2 = found + 2;
|
||||
opLength = 2;
|
||||
}
|
||||
found = s.find("!=");
|
||||
if (found != string::npos){
|
||||
mode = COMPARISON_UNEQUAL;
|
||||
found2 = found + 2;
|
||||
opLength = 2;
|
||||
}
|
||||
if (!mode) mode = COMPARISON_AT_LEAST;
|
||||
|
||||
//get comparison criterion
|
||||
int criterionFound = 0;
|
||||
int criterion = 1;
|
||||
if ((found2 != string::npos) && (found2 < s.length())){
|
||||
criterion = atoi(s.substr(found2).c_str());
|
||||
criterionFound = 1;
|
||||
}
|
||||
if (found2 != string::npos) s.erase(found2 - opLength);
|
||||
|
||||
//counters
|
||||
found = s.find("counter{");
|
||||
if (found != string::npos) {
|
||||
size_t start = s.find("{");
|
||||
size_t end = s.find("}");
|
||||
string counterString = s.substr(start+1,end-start-1);
|
||||
AbilityFactory * abf = NEW AbilityFactory();
|
||||
Counter * counter = abf->parseCounter(counterString,NULL);
|
||||
if (counter) {
|
||||
if (criterionFound) counter->nb = criterion;
|
||||
ThisCounter * td = NEW ThisCounter(counter);
|
||||
if (td) {
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//any counter
|
||||
found = s.find("counters");
|
||||
if (found != string::npos) {
|
||||
ThisCounterAny * td = NEW ThisCounterAny(criterion);
|
||||
if (td) {
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//power
|
||||
found = s.find("power");
|
||||
if (found != string::npos) {
|
||||
ThisPower * td = NEW ThisPower(criterion);
|
||||
if (td) {
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//toughness
|
||||
found = s.find("toughness");
|
||||
if (found != string::npos) {
|
||||
ThisToughness * td = NEW ThisToughness(criterion);
|
||||
if (td) {
|
||||
td->comparisonMode = mode;
|
||||
return td;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ThisCounter::ThisCounter(Counter * _counter){
|
||||
counter = _counter;
|
||||
comparisonCriterion = counter->nb;
|
||||
}
|
||||
|
||||
ThisCounter::ThisCounter(int power, int toughness, int nb, const char * name){
|
||||
counter = NEW Counter(NULL,name,power,toughness);
|
||||
comparisonCriterion = nb;
|
||||
}
|
||||
|
||||
int ThisCounter::match(MTGCardInstance * card){
|
||||
Counter * targetCounter = card->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness);
|
||||
if (targetCounter){
|
||||
return matchValue(targetCounter->nb);
|
||||
}else{
|
||||
switch (comparisonMode) {
|
||||
case COMPARISON_LESS:
|
||||
return comparisonCriterion;
|
||||
case COMPARISON_AT_MOST:
|
||||
return comparisonCriterion + 1;
|
||||
case COMPARISON_UNEQUAL:
|
||||
if (comparisonCriterion) return 1;
|
||||
else return 0;
|
||||
case COMPARISON_EQUAL:
|
||||
if (comparisonCriterion) return 0;
|
||||
else return 1;
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThisCounter::~ThisCounter() {
|
||||
SAFE_DELETE(counter);
|
||||
}
|
||||
|
||||
ThisPower::ThisPower(int power){
|
||||
comparisonCriterion = power;
|
||||
}
|
||||
|
||||
int ThisPower::match(MTGCardInstance * card){
|
||||
return matchValue(card->power);
|
||||
}
|
||||
|
||||
ThisToughness::ThisToughness(int toughness){
|
||||
comparisonCriterion = toughness;
|
||||
}
|
||||
|
||||
int ThisToughness::match(MTGCardInstance * card){
|
||||
return matchValue(card->toughness);
|
||||
}
|
||||
|
||||
ThisCounterAny::ThisCounterAny(int nb){
|
||||
comparisonCriterion = nb;
|
||||
}
|
||||
|
||||
int ThisCounterAny::match(MTGCardInstance * card){
|
||||
int result = 0;
|
||||
for (int i = 0; i < card->counters->mCount; i++) {
|
||||
result += card->counters->counters[i]->nb;
|
||||
}
|
||||
return matchValue(result);
|
||||
}
|
||||
Reference in New Issue
Block a user