From c83950a5d47e8f6d750a3fe15eae4f8f176f8ed3 Mon Sep 17 00:00:00 2001 From: "omegablast2002@yahoo.com" Date: Sat, 4 Sep 2010 00:16:20 +0000 Subject: [PATCH] storm,cantwin/lose,additionallands,cast restricting --- projects/mtg/include/ActionStack.h | 2 +- projects/mtg/include/AllAbilities.h | 137 ++++++++++++++++++++++++++ projects/mtg/include/MTGDefinitions.h | 12 ++- projects/mtg/include/MTGGameZones.h | 2 +- projects/mtg/include/Player.h | 7 ++ projects/mtg/src/AIPlayer.cpp | 23 ++++- projects/mtg/src/ActionStack.cpp | 3 +- projects/mtg/src/GameObserver.cpp | 23 ++++- projects/mtg/src/MTGAbility.cpp | 47 +++++++++ projects/mtg/src/MTGDefinitions.cpp | 10 ++ projects/mtg/src/MTGGameZones.cpp | 12 ++- projects/mtg/src/MTGRules.cpp | 88 +++++++++++++++-- projects/mtg/src/Player.cpp | 7 ++ 13 files changed, 356 insertions(+), 17 deletions(-) diff --git a/projects/mtg/include/ActionStack.h b/projects/mtg/include/ActionStack.h index fbdce2a53..e5676e836 100644 --- a/projects/mtg/include/ActionStack.h +++ b/projects/mtg/include/ActionStack.h @@ -163,7 +163,7 @@ class ActionStack :public GuiLayer{ Player * askIfWishesToInterrupt; int garbageCollect(); int addAction(Interruptible * interruptible); - Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana, int payResult); + Spell * addSpell(MTGCardInstance* card, TargetChooser * tc, ManaCost * mana, int payResult, int storm); int AddNextGamePhase(); int addPutInGraveyard(MTGCardInstance * card); int addDraw(Player * player, int nbcards = 1); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index d16865c8e..5e8f58d15 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -697,6 +697,45 @@ class AADrawer:public ActivatedAbilityTP{ }; +//lands, allows to play more land during a turn: + +class AAMoreLandPlz:public ActivatedAbilityTP{ + public: + WParsedInt *additional; + AAMoreLandPlz(int _id, MTGCardInstance * card,Targetable * _target,ManaCost * _cost, WParsedInt * _additional, int _tap = 0, int who=TargetChooser::UNSET):ActivatedAbilityTP(_id, card,_target,_cost,_tap,who),additional(_additional){ + } + + int resolve(){ + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + player->canPutLandsIntoPlay += additional->getValue(); + } + return 1; + } + + const char * getMenuText(){ + return "Additional Lands"; + } + + AAMoreLandPlz * clone() const{ + AAMoreLandPlz * a = NEW AAMoreLandPlz(*this); + a->additional = NEW WParsedInt(*(a->additional)); + a->isClone = 1; + return a; + } + + ~AAMoreLandPlz(){ + SAFE_DELETE(additional); + } + +}; + /*Gives life to target controller*/ class AALifer:public ActivatedAbilityTP{ public: @@ -744,7 +783,18 @@ class AAWinGame:public ActivatedAbilityTP{ if (_target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){ _target = ((MTGCardInstance *)_target)->controller(); } + int cantlosers = 0; + MTGGameZone * z = ((Player *)_target)->opponent()->game->inPlay; + int nbcards = z->nb_cards; + for (int i = 0; i < nbcards; ++i){ + MTGCardInstance * c = z->cards[i]; + if (c->has(Constants::CANTLOSE)){ + cantlosers++; + } + } + if(cantlosers < 1){ game->gameOver = ((Player *)_target)->opponent(); + } } return 1; } @@ -4259,6 +4309,93 @@ class AAShuffle:public ActivatedAbilityTP{ } }; +//only 1 spell +class AAOnlyOne:public ActivatedAbilityTP{ + public: + AAOnlyOne(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost=NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id,card, _target,_cost,_tap,who){ + } + int resolve(){ + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + player->onlyonecast = 1; + } + return 1; + } + + const char * getMenuText(){ + return "Only One Spell!"; + } + + AAOnlyOne * clone() const{ + AAOnlyOne * a = NEW AAOnlyOne(*this); + a->isClone = 1; + return a; + } +}; +//nospells +class AANoSpells:public ActivatedAbilityTP{ + public: + AANoSpells(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost=NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id,card, _target,_cost,_tap,who){ + } + int resolve(){ + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + player->castrestrictedspell = 1; + } + return 1; + } + + const char * getMenuText(){ + return "No Spells!"; + } + + AANoSpells * clone() const{ + AANoSpells * a = NEW AANoSpells(*this); + a->isClone = 1; + return a; + } +}; +//NoCreature +class AANoCreatures:public ActivatedAbilityTP{ + public: + AANoCreatures(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost=NULL, int _tap = 0, int who = TargetChooser::UNSET):ActivatedAbilityTP(_id,card, _target,_cost,_tap,who){ + } + int resolve(){ + Targetable * _target = getTarget(); + Player * player; + if (_target){ + if (_target->typeAsTarget() == TARGET_CARD){ + player = ((MTGCardInstance *)_target)->controller(); + }else{ + player = (Player *) _target; + } + player->castrestrictedcreature = 1; + } + return 1; + } + + const char * getMenuText(){ + return "No Creatures!"; + } + + AANoCreatures * clone() const{ + AANoCreatures * a = NEW AANoCreatures(*this); + a->isClone = 1; + return a; + } +}; //Random Discard class AARandomDiscarder:public ActivatedAbilityTP{ public: diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index bafe7297a..b3857faef 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -114,8 +114,18 @@ class Constants ABSORB = 56,//this need to be coded for players too "If a source would deal damage" TREASON = 57, UNEARTH = 58, + CANTLOSE = 59, + CANTLIFELOSE = 60, + CANTMILLLOSE = 61, + CANTCASTCREATURE = 62, + CANTCAST = 63, + CANTCASTINSTANTSORCERY = 64, + STORM = 65, + BOTHCANTCAST = 66, + BOTHNOCREATURE = 67, + BOTHONESPELL = 68, - NB_BASIC_ABILITIES = 59, + NB_BASIC_ABILITIES = 69, RARITY_S = 'S', //Special Rarity diff --git a/projects/mtg/include/MTGGameZones.h b/projects/mtg/include/MTGGameZones.h index e1ed53800..20992094d 100644 --- a/projects/mtg/include/MTGGameZones.h +++ b/projects/mtg/include/MTGGameZones.h @@ -158,7 +158,7 @@ class MTGPlayerCards { void drawFromLibrary(); void showHand(); void resetLibrary(); - void initDeck(MTGDeck * deck); + void initDeck(MTGDeck * deck); MTGCardInstance * putInGraveyard(MTGCardInstance * card); MTGCardInstance * putInExile(MTGCardInstance * card); MTGCardInstance * putInHand(MTGCardInstance * card); diff --git a/projects/mtg/include/Player.h b/projects/mtg/include/Player.h index 8e04a8c7a..8cf49b6eb 100644 --- a/projects/mtg/include/Player.h +++ b/projects/mtg/include/Player.h @@ -22,6 +22,13 @@ class Player: public Damageable{ JTexture * mAvatarTex; JQuad * mAvatar; int canPutLandsIntoPlay; + int castedspellsthisturn; + int onlyonecast; + int castrestrictedcreature; + int castrestrictedspell; + int cantcastspell; + int cantcastcreature; + int cantcastinso; MTGPlayerCards * game; int afterDamage(); int poisoned(); diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index a52e8b575..af8e3f243 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -621,6 +621,11 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty cd.setType(type); card = NULL; while((card = cd.nextmatch(game->hand, card))){ + if (card->hasType(Subtypes::TYPE_CREATURE) && this->castrestrictedcreature < 0 && this->castrestrictedspell < 0) continue; + if (card->hasType(Subtypes::TYPE_ENCHANTMENT) && this->castrestrictedspell < 0) continue; + if (card->hasType(Subtypes::TYPE_ARTIFACT) && this->castrestrictedspell < 0) continue; + if (card->hasType(Subtypes::TYPE_SORCERY) && this->castrestrictedspell < 0) continue; + if (card->hasType(Subtypes::TYPE_INSTANT) && this->castrestrictedspell < 0) continue; if (card->hasType(Subtypes::TYPE_LAND) && !this->canPutLandsIntoPlay) continue; if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name)) continue; int currentCost = card->getManaCost()->getConvertedCost(); @@ -709,12 +714,20 @@ int AIPlayerBaka::computeActions(){ nextCardToPlay = FindCardToPlay(currentMana, "land"); //look for the most expensive creature we can afford - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "creature"); + if(castrestrictedspell == 0 && cantcastspell == 0){ + if(onlyonecast == 0 || castedspellsthisturn < onlyonecast){ + if(castrestrictedcreature == 0 && cantcastcreature == 0){ + if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "creature"); + } //Let's Try an enchantment maybe ? - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "enchantment"); - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "artifact"); - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "sorcery"); - if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "instant"); + if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "enchantment"); + if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "artifact"); + if (cantcastinso == 0){ + if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "sorcery"); + if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "instant"); + } + } + } if (potential) delete(currentMana); if (nextCardToPlay){ if (potential){ diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 02a400200..a51e15dfa 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -389,12 +389,13 @@ int ActionStack::addAction(Interruptible * action){ return 1; } -Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana, int payResult){ +Spell * ActionStack::addSpell(MTGCardInstance * _source, TargetChooser * tc, ManaCost * mana, int payResult,int storm){ #if defined (WIN32) || defined (LINUX) char buf[4096], *p = buf; sprintf(buf, "ACTIONSTACK Add spell\n"); OutputDebugString(buf); #endif + if(storm > 0){ mana = NULL;} Spell * spell = NEW Spell(mCount,_source,tc, mana,payResult); addAction(spell); if (!game->players[0]->isAI() && diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 37c69ba86..74873948a 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -97,6 +97,13 @@ void GameObserver::nextGamePhase(){ if (currentGamePhase == Constants::MTG_PHASE_BEFORE_BEGIN){ cleanupPhase(); currentPlayer->canPutLandsIntoPlay = 1; + currentPlayer->castedspellsthisturn = 0; + currentPlayer->castrestrictedcreature = 0; + currentPlayer->castrestrictedspell = 0; + currentPlayer->cantcastcreature = 0; + currentPlayer->cantcastspell = 0; + currentPlayer->cantcastinso = 0; + currentPlayer->onlyonecast = 0; currentPlayer->damageCount = 0; currentPlayer->preventable = 0; mLayers->actionLayer()->cleanGarbage(); //clean abilities history for this turn; @@ -318,7 +325,21 @@ void GameObserver::stateEffects() } } for (int i =0; i < 2; i++) - if (players[i]->life <= 0) gameOver = players[i]; + if (players[i]->life <= 0){ + int cantlosers = 0; + MTGGameZone * z = players[i]->game->inPlay; + int nbcards = z->nb_cards; + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::CANTLOSE) || c->has(Constants::CANTLIFELOSE)){ + cantlosers++; + } + } + if(cantlosers < 1){ + gameOver = players[i]; + } + } + for (int i =0; i < 2; i++) if (players[i]->poisonCount >= 10) gameOver = players[i]; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 73d68ad7d..141b386ad 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -906,6 +906,24 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG a->oneShot = 1; return a; } + //additional lands per turn + found = s.find("land:"); + if (found != string::npos){ + size_t start = s.find(":",found); + size_t end = s.find(" ",start); + string additionalStr; + if (end != string::npos){ + additionalStr = s.substr(start+1,end-start-1); + }else{ + additionalStr = s.substr(start+1); + } + WParsedInt * additional = NEW WParsedInt(additionalStr,spell,card); + Targetable * t = NULL; + if (spell) t = spell->getNextTarget(); + MTGAbility * a = NEW AAMoreLandPlz(id,card,t,NULL,additional,0,who); + a->oneShot = 1; + return a; + } //Deplete found = s.find("deplete:"); @@ -935,6 +953,35 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG a->oneShot = 1; return a; } + + + //cantcastspells + found = s.find("onlyonespell"); + if (found != string::npos){ + Targetable * t = NULL; + if (spell) t = spell->getNextTarget(); + MTGAbility * a = NEW AAOnlyOne(id,card,t,NULL,0,who); + a->oneShot = 1; + return a; + } + //cantcastspells + found = s.find("nospells"); + if (found != string::npos){ + Targetable * t = NULL; + if (spell) t = spell->getNextTarget(); + MTGAbility * a = NEW AANoSpells(id,card,t,NULL,0,who); + a->oneShot = 1; + return a; + } + //cantcastcreature + found = s.find("nocreatures"); + if (found != string::npos){ + Targetable * t = NULL; + if (spell) t = spell->getNextTarget(); + MTGAbility * a = NEW AANoCreatures(id,card,t,NULL,0,who); + a->oneShot = 1; + return a; + } //Discard found = s.find("discard:"); diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index 8553ffd09..3f805d5dc 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -67,6 +67,16 @@ const char* Constants::MTGBasicAbilities[] = { "absorb",//timeshifted sliver ability. if damage would be dealt to card, prevent 1 of that damage. "treason", "unearth", +"cantlose", +"cantlifelose", +"cantmilllose", +"cantcastcreature", +"cantspellcast", +"cantcastinstantsorcery", +"storm", +"bothcantcast", +"bothnocreature", +"bothonecast", }; diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 41711dc7e..0cfd0b4fc 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -79,7 +79,17 @@ void MTGPlayerCards::initGame(int shuffle, int draw){ void MTGPlayerCards::drawFromLibrary(){ if (!library->nb_cards) { - GameObserver::GetInstance()->gameOver = library->owner; + int cantlosers = 0; + MTGGameZone * z = library->owner->game->inPlay; + int nbcards = z->nb_cards; + for (int i = 0; i < nbcards; ++i){ + MTGCardInstance * c = z->cards[i]; + if (c->has(Constants::CANTLOSE) || c->has(Constants::CANTMILLLOSE)){ + cantlosers++; + } + } + if(cantlosers < 1){ + GameObserver::GetInstance()->gameOver = library->owner;} return; } MTGCardInstance * toMove = library->cards[library->nb_cards-1]; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 87385a16f..7ad64e390 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -32,18 +32,81 @@ int cardsinhand = game->players[0]->game->hand->nb_cards; ManaCost * playerMana = player->getManaPool(); ManaCost * cost = card->getManaCost(); ManaCost * alternative = card->getManaCost()->alternative; + #ifdef WIN32 cost->Dump(); #endif +//cantcast restrictions--------- + int cantcreaturecasters = 0; + MTGGameZone * z = card->controller()->game->inPlay; + int nbcards = z->nb_cards; + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::CANTCASTCREATURE)){ + player->cantcastcreature = 1; + cantcreaturecasters++; + } + } + int cantcasters = 0; + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::CANTCAST)){ + player->cantcastspell = 1; + cantcasters++; + } + } + int cantinsocasters = 0; + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::CANTCASTINSTANTSORCERY)){ + player->cantcastinso = 1; + cantinsocasters++; + } + } +//restrict both players------- + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::BOTHCANTCAST)){ + player->cantcastspell = 1; + player->opponent()->cantcastspell = 1; + } + } + + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::BOTHNOCREATURE)){ + player->cantcastcreature = 1; + player->opponent()->cantcastcreature = 1; + } + } + + for (int j = 0; j < nbcards; ++j){ + MTGCardInstance * c = z->cards[j]; + if (c->has(Constants::BOTHONESPELL)){ + player->onlyonecast = 1; + player->opponent()->onlyonecast = 1; + + } + } + + if(player->castedspellsthisturn > 0 && player->onlyonecast > 0){return 0;} + if(player->castrestrictedspell > 0){return 0;} + if(player->castrestrictedcreature > 0 && card->hasType("creature")){return 0;} + if(cantcasters > 0 && !card->hasType("land")){ return 0;} + if(cantinsocasters > 0 && card->hasType("sorcery")){ return 0;} + if(cantinsocasters > 0 && card->hasType("instant")){ return 0;} + if(cantcreaturecasters > 0 && card->hasType("creature")){ return 0;}//---this ends the cant cast restriction. + + //cost of card. if(alternative && playerMana->canAfford(alternative)){ return 1; } if (playerMana->canAfford(cost)){ - return 1; + return 1;//play if you can afford too. } } - return 0; + return 0;//dont play if you cant afford it. } int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ if (!isReactingToClick(card)) return 0; @@ -101,13 +164,26 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card){ Spell * spell = NULL; MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->stack); if (game->targetChooser){ - spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult); + spell = game->mLayers->stackLayer()->addSpell(copy,game->targetChooser, spellCost,payResult,0); game->targetChooser = NULL; + player->castedspellsthisturn += 1; }else{ - spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult); - } - copy->X = spell->computeX(copy); + spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,0); + player->castedspellsthisturn += 1; + } + if(card->has(Constants::STORM)){ + int storm = player->castedspellsthisturn; + ManaCost * spellCost = player->getManaPool(); + for(int i = storm; i > 1; i--){ + spell = game->mLayers->stackLayer()->addSpell(copy,NULL, spellCost, payResult,1); + + } + }//end of storm + if(!card->has(Constants::STORM)){ + copy->X = spell->computeX(copy); } + } + return 1; } diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index 41fda0a4b..2f9434b6f 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -12,6 +12,13 @@ Player::Player(MTGPlayerCards * deck, string file, string fileSmall) : Damageabl game->setOwner(this); manaPool = NEW ManaPool(this); canPutLandsIntoPlay = 1; + castedspellsthisturn = 0; + castrestrictedspell = 0; + castrestrictedcreature = 0; + cantcastcreature = 0; + cantcastspell = 0; + cantcastinso = 0; + onlyonecast = 0; poisonCount = 0; damageCount = 0; preventable = 0;