From 45f37b7545dc4173d132e938c08bed5f0dfab183 Mon Sep 17 00:00:00 2001 From: "omegablast2002@yahoo.com" Date: Wed, 1 Sep 2010 21:31:27 +0000 Subject: [PATCH] fix windswept_heath.txt missing choice 1, added unearth support without workaround, tweaked alternative cost, added treason/sneak attack ability, added frozen. --- projects/mtg/bin/Res/test/windswept_heath.txt | 1 + projects/mtg/include/AllAbilities.h | 28 ++++- projects/mtg/include/MTGCardInstance.h | 5 +- projects/mtg/include/MTGDefinitions.h | 5 +- projects/mtg/include/MTGRules.h | 18 +++- projects/mtg/src/Damage.cpp | 7 ++ projects/mtg/src/DuelLayers.cpp | 2 + projects/mtg/src/GameObserver.cpp | 19 +++- projects/mtg/src/MTGAbility.cpp | 8 ++ projects/mtg/src/MTGCardInstance.cpp | 6 +- projects/mtg/src/MTGDefinitions.cpp | 3 + projects/mtg/src/MTGGameZones.cpp | 8 +- projects/mtg/src/MTGRules.cpp | 100 +++++++++++++++--- 13 files changed, 177 insertions(+), 33 deletions(-) diff --git a/projects/mtg/bin/Res/test/windswept_heath.txt b/projects/mtg/bin/Res/test/windswept_heath.txt index d09cdeed2..fa7684f98 100644 --- a/projects/mtg/bin/Res/test/windswept_heath.txt +++ b/projects/mtg/bin/Res/test/windswept_heath.txt @@ -11,6 +11,7 @@ library:Forest,Plains,Mountain,Swamp,Island [PLAYER2] [DO] Windswept Heath +choice 1 Plains [ASSERT] firstmain diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 192c9de6e..b2060b169 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -53,8 +53,6 @@ public: intValue = target->getManaCost()->getConvertedCost(); }else if (s == "lifetotal"){ intValue = target->controller()->life; - }else if (s == "sunburst"){ - intValue = target->costAmount; }else if (s == "odcount"){ intValue = target->controller()->opponent()->damageCount; }else if (s == "opponentlifetotal"){ @@ -2330,6 +2328,32 @@ class AAUntapper:public ActivatedAbility{ } }; +/* Can prevent a card from untapping next untap */ +class AAFrozen:public ActivatedAbility{ + public: + AAFrozen(int id, MTGCardInstance * card, MTGCardInstance * _target,ManaCost * _cost = NULL, int doTap = 0):ActivatedAbility(id,card, _cost,0,doTap){ + target = _target; + } + + int resolve(){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if (_target){ + while (_target->next) _target=_target->next; //This is for cards such as rampant growth + _target->frozen += 1; + } + return 1; + } + + const char * getMenuText(){ + return "Freeze"; + } + + AAFrozen * clone() const{ + AAFrozen * a = NEW AAFrozen(*this); + a->isClone = 1; + return a; + } +}; // Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase] //Ex : the rack, ivory tower... diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index e622f99df..4514da488 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -44,11 +44,10 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable { MTGGameZone * currentZone; Pos* view; int X; - int costAmount; + int frozen; int regenerateTokens; int isToken; int stillInUse(); - int getCostAmount(); Player * lastController; MTGGameZone * getCurrentZone(); MTGGameZone * previousZone; @@ -75,7 +74,7 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable { int removeType(int value, int removeAll = 0); //Combat - bool blocked; //Blocked this turn or not? + bool blocked; //Blocked this turn or not? MTGCardInstance * defenser; listblockers; int attacker; diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index 69679185a..bafe7297a 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -111,8 +111,11 @@ class Constants WILTING = 53, VIGOR = 54, CHANGELING = 55, + ABSORB = 56,//this need to be coded for players too "If a source would deal damage" + TREASON = 57, + UNEARTH = 58, - NB_BASIC_ABILITIES = 56, + NB_BASIC_ABILITIES = 59, RARITY_S = 'S', //Special Rarity diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index a5a523764..da09bf41f 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -64,6 +64,23 @@ class MTGPersistRule:public MTGAbility{ virtual MTGPersistRule * clone() const; }; +class MTGUnearthRule:public MTGAbility{ + public: + MTGUnearthRule(int _id); + int receiveEvent(WEvent * event); + virtual ostream& toString(ostream& out) const; + int testDestroy(); + virtual MTGUnearthRule * clone() const; +}; + +class MTGSneakAttackRule:public MTGAbility{ + public: + MTGSneakAttackRule(int _id); + int receiveEvent(WEvent * event); + virtual ostream& toString(ostream& out) const; + int testDestroy(); + virtual MTGSneakAttackRule * clone() const; +}; class MTGTokensCleanup:public MTGAbility{ public: @@ -146,7 +163,6 @@ class MTGDeathtouchRule:public MTGAbility{ virtual MTGDeathtouchRule * clone() const; }; - /* HUD Display */ class HUDString { diff --git a/projects/mtg/src/Damage.cpp b/projects/mtg/src/Damage.cpp index 7c543c2d8..c75aefde0 100644 --- a/projects/mtg/src/Damage.cpp +++ b/projects/mtg/src/Damage.cpp @@ -45,6 +45,10 @@ int Damage::resolve(){ target = ev->damage->target; if (!damage) return 0; +//asorbing effects for cards controller----------- + +//reserved for culmulitive absorb ability coding + //prevent next damage----------------------------- if((target)->preventable >= 1) { int preventing =(target)->preventable; @@ -71,6 +75,9 @@ int Damage::resolve(){ damage = 0; (_target)->counters->removeCounter(1,1); } + if ((_target)->has(Constants::ABSORB)) { + damage -= 1; + } if ((_target)->has(Constants::WILTING)) { for (int i = 0; i < damage; i++){ for (int i = damage; i > 0; i--){ diff --git a/projects/mtg/src/DuelLayers.cpp b/projects/mtg/src/DuelLayers.cpp index c343bf2a3..906cebc7e 100644 --- a/projects/mtg/src/DuelLayers.cpp +++ b/projects/mtg/src/DuelLayers.cpp @@ -25,6 +25,8 @@ void DuelLayers::init(){ action->Add(NEW MTGBlockRule(-1)); action->Add(NEW MTGLegendRule(-1)); action->Add(NEW MTGPersistRule(-1)); + action->Add(NEW MTGUnearthRule(-1)); + action->Add(NEW MTGSneakAttackRule(-1)); action->Add(NEW MTGLifelinkRule(-1)); action->Add(NEW MTGDeathtouchRule(-1)); action->Add(NEW OtherAbilitiesEventReceiver(-1)); diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index eac3bd6c3..37c69ba86 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -114,7 +114,21 @@ void GameObserver::nextGamePhase(){ for (int i = 0; i < 2; ++i) players[i]->getManaPool()->init(); - //After End of turn + // //End of turn--unearth clean up---leaving this as comment for code refference. origanal method i had for unearth now handled by sneakattackrule. + //if (currentGamePhase == Constants::MTG_PHASE_ENDOFTURN) { + // GameObserver *game = game->GetInstance(); + // Player * p = game->currentPlayer; + // MTGGameZone * z = p->game->inPlay; + // for (int i= 0; i < z->nb_cards; i++){ + // MTGCardInstance * card = z->cards[i]; + //if (card->has(Constants::UNEARTH)) { + // for(i = z->nb_cards; i > -1; i--){ + // card->controller()->game->putInExile(card); + //} + // } + // } + //} + if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT){ //Auto Hand cleaning, in case the player didn't do it himself while(currentPlayer->game->hand->nb_cards > 7) @@ -465,12 +479,11 @@ int GameObserver::untap(MTGCardInstance * card) { return 0; } if (card->has(Constants::DOESNOTUNTAP)) return 0; - + if (card->frozen > 0) return 0; card->attemptUntap(); return 1; } - TargetChooser * GameObserver::getCurrentTargetChooser(){ TargetChooser * _tc = mLayers->actionLayer()->getCurrentTargetChooser(); if (_tc) return _tc; diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 4c66aee4e..73d68ad7d 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1193,6 +1193,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG } } + //frozen, next untap this does not untap. + found = s.find("frozen"); + if (found != string::npos){ + MTGAbility * a = NEW AAFrozen(id,card,target); + a->oneShot = 1; + return a; + } + //Untapper (Ley Druid...) found = s.find("untap"); if (found != string::npos){ diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 31981f1e3..e6f9380a7 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -97,6 +97,7 @@ void MTGCardInstance::initMTGCI(){ belongs_to=NULL; tapped = 0; untapping = 0; + frozen = 0; summoningSickness = 1; preventable = 0; target = NULL; @@ -109,7 +110,6 @@ void MTGCardInstance::initMTGCI(){ next = NULL; lastController = NULL; regenerateTokens = 0; - costAmount = 0; blocked = false; currentZone = NULL; data = this; //an MTGCardInstance point to itself for data, allows to update it without killing the underlying database item @@ -297,10 +297,6 @@ int MTGCardInstance::hasSummoningSickness(){ return 1; } -int MTGCardInstance::getCostAmount(){ - return 1; -} - MTGCardInstance * MTGCardInstance::changeController(Player * newController){ Player * originalOwner = controller(); if (originalOwner == newController) return this; diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index bac096ef4..8553ffd09 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -64,6 +64,9 @@ const char* Constants::MTGBasicAbilities[] = { "wilting",//source takes damage in the form of -1/-1 counters. "vigor",//instead of taking damage the source gains +1/+1 counters "changeling",//this card is every creature type at all times +"absorb",//timeshifted sliver ability. if damage would be dealt to card, prevent 1 of that damage. +"treason", +"unearth", }; diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 22fc3ab30..41711dc7e 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -355,9 +355,11 @@ void MTGInPlay::untapAll(){ for (i = 0; i < nb_cards; i ++){ MTGCardInstance * card = cards[i]; card->setUntapping(); - if (!card->basicAbilities[Constants::DOESNOTUNTAP]){ - card->attemptUntap(); - } + if (!card->basicAbilities[Constants::DOESNOTUNTAP]){ + if(card->frozen < 1) {card->attemptUntap();} + if(card->frozen >= 1) {card->frozen = 0;} + + } } } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index e794d6c5d..87385a16f 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -40,9 +40,8 @@ int cardsinhand = game->players[0]->game->hand->nb_cards; return 1; } if (playerMana->canAfford(cost)){ - return 1; - } - + return 1; + } } return 0; } @@ -53,19 +52,10 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ ManaCost * alternative = card->getManaCost()->alternative; ManaCost * playerMana = player->getManaPool(); //this handles extra cost payments at the moment a card is played. - if (cost->isExtraPaymentSet()){ - if (!game->targetListIsSet(card)){ - return 0; - } - }else{ - cost->setExtraCostsAction(this, card); - game->waitForExtraPayment = cost->extraCosts; - return 0; - } - + //as long as you dont have enough mana to pay the real cost, and the alternative contains extra cost, add extras if(!playerMana->canAfford(cost) && playerMana->canAfford(alternative)){ - if (cost->alternative->isExtraPaymentSet()){ + if (cost->alternative->isExtraPaymentSet()){ if (!game->targetListIsSet(card)){ return 0; } @@ -76,6 +66,15 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ } } //------------------------------------------------------------------------ + if (cost->isExtraPaymentSet()){ + if (!game->targetListIsSet(card)){ + return 0; + } + }else{ + cost->setExtraCostsAction(this, card); + game->waitForExtraPayment = cost->extraCosts; + return 0; + } ManaCost * previousManaPool = NEW ManaCost(player->getManaPool()); int payResult = player->getManaPool()->pay(card->getManaCost()); @@ -550,8 +549,80 @@ HUDDisplay::~HUDDisplay(){ a->isClone = 1; return a; } +//unearth rule---------------------------------- +//if the card leaves play, exile it instead. + MTGUnearthRule::MTGUnearthRule(int _id):MTGAbility(_id,NULL){}; + int MTGUnearthRule::receiveEvent(WEvent * event){ + if (event->type == WEvent::CHANGE_ZONE){ + WEventZoneChange * e = (WEventZoneChange *) event; + MTGCardInstance * card = e->card->previous; + if (card && card->basicAbilities[Constants::UNEARTH]){ + int ok = 0; + for (int i = 0; i < 2 ; i++){ + Player * p = game->players[i]; + if (e->from == p->game->inPlay) ok = 1; + } + if (!ok) return 0; + for (int i = 0; i < 2 ; i++){ + Player * p = game->players[i]; + if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library){ + p->game->putInExile(e->card); + return 1; + } + } + } + } + return 0; + } + ostream& MTGUnearthRule::toString(ostream& out) const + { + out << "MTGUnearthRule ::: ("; + return MTGAbility::toString(out) << ")"; + } + int MTGUnearthRule::testDestroy(){return 0;} + MTGUnearthRule * MTGUnearthRule::clone() const{ + MTGUnearthRule * a = NEW MTGUnearthRule(*this); + a->isClone = 1; + return a; + } +//---------------------------------------------------------------------- +//sneakattack rule------------------------------------------------------ +//this rule also handles the exile of unearth cards at end of turn. + + MTGSneakAttackRule::MTGSneakAttackRule(int _id):MTGAbility(_id,NULL){}; + + int MTGSneakAttackRule::receiveEvent(WEvent *e){ + if (WEventPhaseChange* event = dynamic_cast(e)) { + if (Constants::MTG_PHASE_ENDOFTURN == event->from->id) { + for (int j = 0; j < 2 ; j++){ + Player * p = game->players[j]; + MTGGameZone * z = p->game->inPlay; + for (int i= 0; i < z->nb_cards; i++){ + MTGCardInstance * card = z->cards[i]; + if (card->has(Constants::TREASON)) {p->game->putInGraveyard(card);i--;} + if (card->has(Constants::UNEARTH)) {p->game->putInExile(card);i--;} + } + } + } + return 1; + } + return 1; + } + + ostream& MTGSneakAttackRule::toString(ostream& out) const + { + out << "MTGSneakAttackRule ::: ("; + return MTGAbility::toString(out) << ")"; + } + int MTGSneakAttackRule::testDestroy(){return 0;} + MTGSneakAttackRule * MTGSneakAttackRule::clone() const{ + MTGSneakAttackRule * a = NEW MTGSneakAttackRule(*this); + a->isClone = 1; + return a; + } + //------------------------------------------------------------------- MTGTokensCleanup::MTGTokensCleanup(int _id):MTGAbility(_id, NULL){} int MTGTokensCleanup::receiveEvent(WEvent * e){ @@ -684,4 +755,3 @@ HUDDisplay::~HUDDisplay(){ a->isClone = 1; return a; } -