From d52f06d98d44c0c0774b41856e5bb0eb2dd1c15e Mon Sep 17 00:00:00 2001 From: "wagic.the.homebrew@gmail.com" Date: Sat, 4 Jul 2009 04:15:05 +0000 Subject: [PATCH] Erwan - Magic 2010 - blockers ordering - Fixed a memory leak introduced in a previous revision (foreach) --- projects/mtg/bin/Res/test/_tests.txt | 1 + .../mtg/bin/Res/test/generic/m10_blockers.txt | 28 ++ projects/mtg/include/AIPlayer.h | 1 + projects/mtg/include/AllAbilities.h | 8 +- projects/mtg/include/Blocker.h | 24 +- projects/mtg/include/DamageResolverLayer.h | 17 +- projects/mtg/include/GameObserver.h | 3 +- projects/mtg/include/MTGCardInstance.h | 40 ++- projects/mtg/include/MTGGuiPlay.h | 6 +- projects/mtg/src/AIPlayer.cpp | 51 ++++ projects/mtg/src/Blocker.cpp | 38 +-- projects/mtg/src/CardGui.cpp | 3 +- projects/mtg/src/ConstraintResolver.cpp | 4 +- projects/mtg/src/DamageResolverLayer.cpp | 268 ++++++++++++------ projects/mtg/src/DamagerDamaged.cpp | 6 +- projects/mtg/src/GameObserver.cpp | 31 +- projects/mtg/src/MTGAbility.cpp | 115 ++++---- projects/mtg/src/MTGCardInstance.cpp | 49 +++- projects/mtg/src/MTGGameZones.cpp | 23 +- projects/mtg/src/MTGGuiPlay.cpp | 84 ++++-- projects/mtg/src/MTGRules.cpp | 7 +- projects/mtg/src/TestSuiteAI.cpp | 26 +- 22 files changed, 580 insertions(+), 253 deletions(-) create mode 100644 projects/mtg/bin/Res/test/generic/m10_blockers.txt diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 5027a4a83..1fd6bbda3 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -2,6 +2,7 @@ #Generic engine features ######################## generic/attacks_each_turn.txt +generic/m10_blockers.txt generic/first_strike.txt generic/first_strike2.txt generic/first_strike3.txt diff --git a/projects/mtg/bin/Res/test/generic/m10_blockers.txt b/projects/mtg/bin/Res/test/generic/m10_blockers.txt new file mode 100644 index 000000000..a4f183c2f --- /dev/null +++ b/projects/mtg/bin/Res/test/generic/m10_blockers.txt @@ -0,0 +1,28 @@ +#New blockers reordering rule +[INIT] +COMBATATTACKERS +[PLAYER1] +inplay:Puppeteer +[PLAYER2] +inplay:raging goblin,Drudge Skeletons +[DO] +Puppeteer +next +#blockers +raging goblin +Drudge Skeletons +next +#blockers order +Drudge Skeletons +next +#combat damage +next +#combat end +[ASSERT] +COMBATEND +[PLAYER1] +graveyard:Puppeteer +[PLAYER2] +graveyard:Drudge Skeletons +inplay:raging goblin +[END] \ No newline at end of file diff --git a/projects/mtg/include/AIPlayer.h b/projects/mtg/include/AIPlayer.h index 7605b8169..3c548f849 100644 --- a/projects/mtg/include/AIPlayer.h +++ b/projects/mtg/include/AIPlayer.h @@ -51,6 +51,7 @@ class AIPlayer: public Player{ ManaCost * potentialMana; queue clickstream; void tapLandsForMana(ManaCost * potentialMana, ManaCost * cost); + int orderBlockers(); int combatDamages(); int interruptIfICan(); int chooseAttackers(); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 44cf6c2f8..1203ea23f 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -931,17 +931,17 @@ class AInstantPowerToughnessModifierUntilEOT: public InstantAbility{ //Untap Blockers with simple Mana Mechanism -class AUntapManaBlocker: public Blocker{ +class AUntapManaBlocker: public UntapBlocker{ public: - AUntapManaBlocker(int id, MTGCardInstance * card, ManaCost * _cost):Blocker(id, card, _cost){ + AUntapManaBlocker(int id, MTGCardInstance * card, ManaCost * _cost):UntapBlocker(id, card, _cost){ } - AUntapManaBlocker(int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost):Blocker(id, card,_target, _cost){ + AUntapManaBlocker(int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost):UntapBlocker(id, card,_target, _cost){ } virtual ostream& toString(ostream& out) const { out << "AUntapManaBlocker ::: ("; - return Blocker::toString(out) << ")"; + return UntapBlocker::toString(out) << ")"; } }; diff --git a/projects/mtg/include/Blocker.h b/projects/mtg/include/Blocker.h index 504341a1c..96a29a942 100644 --- a/projects/mtg/include/Blocker.h +++ b/projects/mtg/include/Blocker.h @@ -12,7 +12,7 @@ class ManaCost; class GameObserver; class MTGAbility; -class Blocker : public MTGAbility { +class UntapBlocker : public MTGAbility { protected: ManaCost * manaCost; int currentPhase; @@ -20,28 +20,28 @@ class Blocker : public MTGAbility { public: virtual ManaCost * untapManaCost(){return manaCost;}; virtual int unblock(){return 1;}; - Blocker(int id, MTGCardInstance * card, ManaCost * _cost); - Blocker(int id, MTGCardInstance * card); - Blocker(int id, MTGCardInstance * card, MTGCardInstance *_target); - Blocker(int id, MTGCardInstance * card, MTGCardInstance *_target, ManaCost * _cost); - ~Blocker(); + UntapBlocker(int id, MTGCardInstance * card, ManaCost * _cost); + UntapBlocker(int id, MTGCardInstance * card); + UntapBlocker(int id, MTGCardInstance * card, MTGCardInstance *_target); + UntapBlocker(int id, MTGCardInstance * card, MTGCardInstance *_target, ManaCost * _cost); + ~UntapBlocker(); virtual void Update(float dt); virtual int destroy(); }; -class Blockers { +class UntapBlockers { protected: int cursor; int blockers[MAX_BLOCKERS]; GameObserver * game; public: - Blockers(); - ~Blockers(); - int Add (Blocker * ability); - int Remove (Blocker * ability); + UntapBlockers(); + ~UntapBlockers(); + int Add (UntapBlocker * ability); + int Remove (UntapBlocker * ability); int init(); - Blocker * next(); + UntapBlocker * next(); int rewind(); int isEmpty(); }; diff --git a/projects/mtg/include/DamageResolverLayer.h b/projects/mtg/include/DamageResolverLayer.h index 7d60eaba0..7fddce436 100644 --- a/projects/mtg/include/DamageResolverLayer.h +++ b/projects/mtg/include/DamageResolverLayer.h @@ -10,8 +10,11 @@ class DamageStack; class DamageResolverLayer:public PlayGuiObjectController{ protected: int trampleDamage(); + void updateAllCoordinates(); public: int buttonOk; + int orderingIsNeeded; + int currentPhase; int remainingDamageSteps; Player * currentChoosingPlayer; @@ -23,16 +26,26 @@ class DamageResolverLayer:public PlayGuiObjectController{ int initResolve(); Player * whoSelectsDamagesDealtBy(MTGCardInstance * card); int addAutoDamageToOpponents(MTGCardInstance * card); - int addIfNotExists(MTGCardInstance * card, Player * selecter); + DamagerDamaged * addIfNotExists(MTGCardInstance * card, Player * selecter); int addDamager(MTGCardInstance * card, Player * selecter); + int updateCoordinates(MTGCardInstance * card); DamagerDamaged * findByCard(MTGCardInstance * card); int canStopDealDamages(); int resolveDamages(); int isOpponent(DamagerDamaged * a, DamagerDamaged * b); - void nextPlayer(); + int nextPlayer(); virtual void Update(float dt); virtual bool CheckUserInput(u32 key); virtual void Render(); + int isDisplayed(){return mCount;}; + int autoOrderBlockers(); + bool blockersOrderingDone(); + + bool clickDamage(DamagerDamaged * current); + bool clickDamage(MTGCardInstance * c); + bool clickReorderBlocker(MTGCardInstance * blocker); + + bool checkUserInputOrderBlockers(u32 key); }; #endif diff --git a/projects/mtg/include/GameObserver.h b/projects/mtg/include/GameObserver.h index 55748c4a9..2c0718ff7 100644 --- a/projects/mtg/include/GameObserver.h +++ b/projects/mtg/include/GameObserver.h @@ -28,10 +28,11 @@ class GameObserver{ int nbPlayers; int currentPlayerId; int currentRound; - + int blockersAssigned; public: + int blockersSorted; int forceShuffleLibrary[2]; int turn; int forceShuffleLibraries(); diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 5a1205fd6..0cccdb161 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -17,11 +17,12 @@ class MTGAbility; class MTGCard; class TexturesCache; class ManaCost; -class Blockers; +class UntapBlockers; class CardDescriptor; class Counters; - +#include +using namespace std; class MTGCardInstance: public MTGCard, public Damageable { protected: @@ -31,9 +32,9 @@ class MTGCardInstance: public MTGCard, public Damageable { int tapped; int lifeOrig; - Blockers * blockers; + UntapBlockers * untapBlockers; MTGPlayerCards * belongs_to; - MTGAbility * UntapBlockers[10]; + MTGAbility * untapBlockerAbilities[10]; void unband(); MTGCardInstance * getNextPartner(); void initMTGCI(); @@ -51,38 +52,47 @@ class MTGCardInstance: public MTGCard, public Damageable { // The recommended method to test for summoning Sickness ! int hasSummoningSickness(); MTGCardInstance * changeController(Player * newcontroller); - MTGCardInstance * defenser; float changedZoneRecently; Player * owner; Counters * counters; int typeAsTarget(){return TARGET_CARD;} - int attacker; - MTGCardInstance * banding; // If belongs to a band when attacking MTGCardInstance * target; void addType(int type); + + //Combat + MTGCardInstance * defenser; + listblockers; + int attacker; + int toggleDefenser(MTGCardInstance * opponent); + int moveBlockerInRow(MTGCardInstance * blocker); + int toggleAttacker(); + MTGCardInstance * banding; // If belongs to a band when attacking int canBlock(); int canBlock(MTGCardInstance * opponent); int canAttack(); + int isAttacker(); + MTGCardInstance * isDefenser(); + int initAttackersDefensers(); + MTGCardInstance * getNextOpponent(MTGCardInstance * previous=NULL); + MTGCardInstance * getNextDefenser(MTGCardInstance * previous=NULL); + int nbOpponents(); + int afterDamage(); int has(int ability); int cleanup(); int reset(); - int isAttacker(); - MTGCardInstance * isDefenser(); - int toggleDefenser(MTGCardInstance * opponent); - int toggleAttacker(); + + MTGCard * model; MTGCardInstance(); MTGCardInstance(MTGCard * card, MTGPlayerCards * _belongs_to); - Blockers * getBlockers(); + UntapBlockers * getUntapBlockers(); int regenerate(); int triggerRegenerate(); Player * controller(); JQuad * getIcon(); - int initAttackersDefensers(); - MTGCardInstance * getNextOpponent(MTGCardInstance * previous=NULL); - int nbOpponents(); + ~MTGCardInstance(); int bury(); int destroy(); diff --git a/projects/mtg/include/MTGGuiPlay.h b/projects/mtg/include/MTGGuiPlay.h index 894a7d512..e96cb23c3 100644 --- a/projects/mtg/include/MTGGuiPlay.h +++ b/projects/mtg/include/MTGGuiPlay.h @@ -15,9 +15,9 @@ class MTGGuiPlay: public PlayGuiObjectController { int offset; Player * currentPlayer; MTGCardInstance * cardsGrid[SCREEN_WIDTH/5][SCREEN_HEIGHT/5]; - int nb_creatures; - int nb_spells; - int nb_lands; + int nb_creatures[2]; + int nb_spells[2]; + int nb_lands[2]; int cards_x_limit; JQuad * phaseIcons[24]; diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index 77526f6cb..682b24b54 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -474,10 +474,59 @@ int AIPlayer::chooseBlockers(){ return 1; } +int AIPlayer::orderBlockers(){ + GameObserver * g = GameObserver::GetInstance(); + DamageResolverLayer * drl = g->mLayers->combatLayer(); + if (drl->orderingIsNeeded && g->currentPlayer==this){ + drl->blockersOrderingDone(); //TODO clever rank of blockers + return 1; + } + return 0; +} + + + int AIPlayer::combatDamages(){ int result = 0; GameObserver * gameObs = GameObserver::GetInstance(); int currentGamePhase = gameObs->getCurrentGamePhase(); + + if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) return orderBlockers(); + + if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE) return 0; + DamageResolverLayer * drl = gameObs->mLayers->combatLayer(); + + if (drl->currentChoosingPlayer == this){ + for (int i = 0; i < drl->mCount; i++){ + DamagerDamaged * current = (DamagerDamaged *) drl->mObjects[i]; + if (current->damageSelecter == this){ + OutputDebugString("YEs, AI IS THE DAMAGE DEALER"); + MTGCardInstance * attacker = current->card; + MTGCardInstance * canardEmissaire = *(attacker->blockers.rbegin()); + + while (canardEmissaire && current->damageToDeal){ + drl->clickDamage(canardEmissaire); + } + result = 1; + + } + } + } + + + if (result) return drl->nextPlayer(); + return 0; + +} + +/* +int AIPlayer::combatDamages(){ + int result = 0; + GameObserver * gameObs = GameObserver::GetInstance(); + int currentGamePhase = gameObs->getCurrentGamePhase(); + + if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) return orderBlockers(); + if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE) return 0; DamageResolverLayer * drl = gameObs->mLayers->combatLayer(); #if defined (WIN32) || defined (LINUX) @@ -524,6 +573,7 @@ int AIPlayer::combatDamages(){ } } } + if (result){ drl->nextPlayer(); } @@ -531,6 +581,7 @@ int AIPlayer::combatDamages(){ return result; } +*/ AIStats * AIPlayer::getStats(){ if (!stats){ diff --git a/projects/mtg/src/Blocker.cpp b/projects/mtg/src/Blocker.cpp index b7f7b8f2b..13662a5dd 100644 --- a/projects/mtg/src/Blocker.cpp +++ b/projects/mtg/src/Blocker.cpp @@ -1,32 +1,32 @@ #include "../include/config.h" #include "../include/Blocker.h" -Blocker::Blocker(int id, MTGCardInstance * card):MTGAbility(id, card){ +UntapBlocker::UntapBlocker(int id, MTGCardInstance * card):MTGAbility(id, card){ init ( NEW ManaCost()); } -Blocker::Blocker(int id, MTGCardInstance * card, ManaCost * _cost):MTGAbility(id, card){ +UntapBlocker::UntapBlocker(int id, MTGCardInstance * card, ManaCost * _cost):MTGAbility(id, card){ init(_cost); } -Blocker::Blocker(int id, MTGCardInstance * card, MTGCardInstance *_target):MTGAbility(id, card,_target){ +UntapBlocker::UntapBlocker(int id, MTGCardInstance * card, MTGCardInstance *_target):MTGAbility(id, card,_target){ init ( NEW ManaCost()); } -Blocker::Blocker(int id, MTGCardInstance * card, MTGCardInstance *_target, ManaCost * _cost):MTGAbility(id, card,_target){ +UntapBlocker::UntapBlocker(int id, MTGCardInstance * card, MTGCardInstance *_target, ManaCost * _cost):MTGAbility(id, card,_target){ init(_cost); } -Blocker::~Blocker(){ +UntapBlocker::~UntapBlocker(){ SAFE_DELETE(manaCost); } -void Blocker::init(ManaCost * _cost){ +void UntapBlocker::init(ManaCost * _cost){ currentPhase = -1; manaCost = _cost; } //Default behaviour for blockers : they block the card they're attached to -void Blocker::Update(float dt){ +void UntapBlocker::Update(float dt){ game = GameObserver::GetInstance(); int newPhase = game->getCurrentGamePhase(); if (newPhase != currentPhase){ @@ -36,7 +36,7 @@ void Blocker::Update(float dt){ }else{ _target = source; } - _target->getBlockers()->Add(this); + _target->getUntapBlockers()->Add(this); #if defined (WIN32) || defined (LINUX) char buf[4096]; sprintf(buf, "Adding Blocker to %s \n", _target->model->getName()); @@ -46,24 +46,24 @@ void Blocker::Update(float dt){ currentPhase = newPhase; } -int Blocker::destroy(){ +int UntapBlocker::destroy(){ MTGCardInstance * _target; if (target){ _target = (MTGCardInstance *) target; }else{ _target = source; } - _target->getBlockers()->Remove(this); + _target->getUntapBlockers()->Remove(this); return 1; } -Blockers::Blockers(){ +UntapBlockers::UntapBlockers(){ init(); } -int Blockers::init(){ +int UntapBlockers::init(){ cursor = -1; for (int i=0; i< MAX_BLOCKERS ; i++){ @@ -73,25 +73,25 @@ int Blockers::init(){ return 1; } -int Blockers::Add (Blocker * ability){ +int UntapBlockers::Add (UntapBlocker * ability){ game = GameObserver::GetInstance(); int index = game->mLayers->actionLayer()->getIndexOf(ability); blockers[index] = 1; return index; } -int Blockers::Remove (Blocker * ability){ +int UntapBlockers::Remove (UntapBlocker * ability){ game = GameObserver::GetInstance(); int index = game->mLayers->actionLayer()->getIndexOf(ability); blockers[index] = 0; return index; } -int Blockers::rewind(){ +int UntapBlockers::rewind(){ cursor = -1; return 1; } -Blocker * Blockers::next(){ +UntapBlocker * UntapBlockers::next(){ cursor++; game = GameObserver::GetInstance(); while (blockers[cursor] == 0){ @@ -101,12 +101,12 @@ Blocker * Blockers::next(){ return NULL; } } - return (Blocker *) (game->mLayers->actionLayer()->getByIndex(cursor)); + return (UntapBlocker *) (game->mLayers->actionLayer()->getByIndex(cursor)); } -int Blockers::isEmpty(){ +int UntapBlockers::isEmpty(){ for (int i=0; i< MAX_BLOCKERS ; i++){ if (blockers[i]) return 0; @@ -114,6 +114,6 @@ int Blockers::isEmpty(){ return 1; } -Blockers::~Blockers(){ +UntapBlockers::~UntapBlockers(){ } diff --git a/projects/mtg/src/CardGui.cpp b/projects/mtg/src/CardGui.cpp index 21dc0aa3c..4e98b335f 100644 --- a/projects/mtg/src/CardGui.cpp +++ b/projects/mtg/src/CardGui.cpp @@ -233,7 +233,8 @@ void CardGui::Update(float dt){ } if (card->changedZoneRecently){ if (mParticleSys) mParticleSys->Update(dt); - card->changedZoneRecently-= (5 *dt); + card->changedZoneRecently-= (5 *dt); + if (card->changedZoneRecently == 0) card->changedZoneRecently-= dt;//must not become zero atm if (card->changedZoneRecently < 0){ if (mParticleSys) mParticleSys->Stop(); } diff --git a/projects/mtg/src/ConstraintResolver.cpp b/projects/mtg/src/ConstraintResolver.cpp index 6497e4960..7305cf107 100644 --- a/projects/mtg/src/ConstraintResolver.cpp +++ b/projects/mtg/src/ConstraintResolver.cpp @@ -8,8 +8,8 @@ int ConstraintResolver::untap(GameObserver * game, MTGCardInstance * card){ } int ok = 1; ManaCost * untapManaCost = NEW ManaCost(); - Blockers * blockers = card->getBlockers(); - Blocker * blocker; + UntapBlockers * blockers = card->getUntapBlockers(); + UntapBlocker * blocker; blockers->rewind(); Player * player = game->currentPlayer; while ((blocker = blockers->next())){ diff --git a/projects/mtg/src/DamageResolverLayer.cpp b/projects/mtg/src/DamageResolverLayer.cpp index 4318ac35b..b5f8fa902 100644 --- a/projects/mtg/src/DamageResolverLayer.cpp +++ b/projects/mtg/src/DamageResolverLayer.cpp @@ -12,17 +12,22 @@ DamageResolverLayer::DamageResolverLayer(int id, GameObserver * _game):PlayGuiOb currentSource = NULL; buttonOk = 0; currentChoosingPlayer = NULL; + orderingIsNeeded = 0; } void DamageResolverLayer::Update(float dt){ int newPhase = game->getCurrentGamePhase(); + if (newPhase == Constants::MTG_PHASE_UNTAP){ + orderingIsNeeded = 0; + game->blockersSorted = 0; + } if (newPhase == Constants::MTG_PHASE_COMBATDAMAGE){ if (!game->mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)){ - if (newPhase != currentPhase){ - init(); + init(); } if (remainingDamageSteps && empty()){ - initResolve(); + OutputDebugString("Combat Damage STEP\n"); + initResolve(); } } }else{ @@ -33,6 +38,26 @@ void DamageResolverLayer::Update(float dt){ } +int DamageResolverLayer::autoOrderBlockers(){ + resetObjects(); + MTGInPlay * attackers = game->currentPlayer->game->inPlay; + MTGCardInstance * attacker = attackers->getNextAttacker(NULL); + while (attacker != NULL){ + if (attacker->blockers.size() > 1){ + orderingIsNeeded = 1; + Player * p = attacker->controller(); + addIfNotExists(attacker, p); + list::iterator it; + for (it= attacker->blockers.begin(); it != attacker->blockers.end(); ++it){ + addIfNotExists(*it, p); + } + } + attacker = attackers->getNextAttacker(attacker); + } + game->blockersSorted = 1; + return 1 - orderingIsNeeded; +}; + Player * DamageResolverLayer::whoSelectsDamagesDealtBy(MTGCardInstance * card){ if (card->controller() == game->currentPlayer){ //Attacker MTGInPlay * defensers = game->opponent()->game->inPlay; @@ -75,41 +100,66 @@ int DamageResolverLayer::addAutoDamageToOpponents(MTGCardInstance * card){ } -int DamageResolverLayer::addIfNotExists(MTGCardInstance * card, Player * selecter){ +DamagerDamaged * DamageResolverLayer::addIfNotExists(MTGCardInstance * card, Player * selecter){ for (int i = 0; i < mCount; i++){ DamagerDamaged * item = (DamagerDamaged *)mObjects[i]; - if (item->card == card) return 0; + if (item->card == card) return item; } CardGui * cardg = game->mLayers->playLayer()->getByCard(card); DamagerDamaged * item = NEW DamagerDamaged(cardg, selecter, mCount == 0); Add(item); mCurr = 0; + return item; +} + +void DamageResolverLayer::updateAllCoordinates(){ + for (int i = 0; i < mCount; i++){ + DamagerDamaged * item = (DamagerDamaged *)mObjects[i]; + CardGui * cardg = game->mLayers->playLayer()->getByCard(item->card); + item->x = cardg->x; + item->y = cardg->y; + } +} + +int DamageResolverLayer::updateCoordinates(MTGCardInstance * card){ + DamagerDamaged * item; + for (int i = 0; i < mCount; i++){ + item = (DamagerDamaged *)mObjects[i]; + if (item->card != card) item = NULL ; + } + if (!item) return 0; + CardGui * cardg = game->mLayers->playLayer()->getByCard(card); + item->x = cardg->x; + item->y = cardg->y; return 1; } //Adds a card and all its opponents to the Damagers' list int DamageResolverLayer::addDamager(MTGCardInstance * card, Player * selecter){ - addIfNotExists(card, selecter); + DamagerDamaged * me = addIfNotExists(card, selecter); if (card->controller() == game->currentPlayer){ //Attacker MTGInPlay * defensers = game->opponent()->game->inPlay; MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card); while (defenser != NULL){ - addIfNotExists(defenser, whoSelectsDamagesDealtBy(defenser)); + DamagerDamaged * item = addIfNotExists(defenser, whoSelectsDamagesDealtBy(defenser)); + while (!item->hasLethalDamage() && me->dealOneDamage(item)){} //Add default damage to the card... defenser = defensers->getNextDefenser(defenser, card); } }else{ //Defenser MTGInPlay * attackers = game->currentPlayer->game->inPlay; MTGCardInstance * attacker = card->isDefenser(); - addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker)); + DamagerDamaged * item = addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker)); + while (!item->hasLethalDamage() && me->dealOneDamage(item)){} //Add default damage to the card... MTGCardInstance * banding = attacker->banding; if (banding){ attacker = attackers->getNextAttacker(NULL); while (attacker != NULL){ - if (attacker->banding == banding){ - addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker)); - } - attacker = attackers->getNextAttacker(attacker); + if (attacker->banding == banding){ + item = addIfNotExists(attacker,whoSelectsDamagesDealtBy(attacker)); + while (!item->hasLethalDamage() && me->dealOneDamage(item)){} //Add default damage to the card... + } + attacker = attackers->getNextAttacker(attacker); } } } @@ -139,27 +189,23 @@ int DamageResolverLayer::initResolve(){ MTGCardInstance * attacker = attackers->getNextAttacker(NULL); while (attacker != NULL){ -#if defined (WIN32) || defined (LINUX) - sprintf(buf, "attacker : %s \n", attacker->getName()); - OutputDebugString(buf); -#endif - if ((!strike && !attacker->has(Constants::FIRSTSTRIKE)) || (strike && attacker->has(Constants::FIRSTSTRIKE)) || attacker->has(Constants::DOUBLESTRIKE)){ - Player * selecter = whoSelectsDamagesDealtBy(attacker); - if (!selecter){ - addAutoDamageToOpponents(attacker); + if ((!strike && !attacker->has(Constants::FIRSTSTRIKE)) || (strike && attacker->has(Constants::FIRSTSTRIKE)) || attacker->has(Constants::DOUBLESTRIKE)){ + OutputDebugString("Attacker Damaging!\n"); + if (Player * selecter = whoSelectsDamagesDealtBy(attacker)){ + addDamager(attacker, selecter); }else{ - addDamager(attacker, selecter); + addAutoDamageToOpponents(attacker); } } MTGCardInstance * defenser = defensers->getNextDefenser(NULL, attacker); while (defenser != NULL){ - if ((!strike && !defenser->has(Constants::FIRSTSTRIKE)) || (strike && defenser->has(Constants::FIRSTSTRIKE)) || defenser->has(Constants::DOUBLESTRIKE)){ - Player * selecterb = whoSelectsDamagesDealtBy(defenser); - if (!selecterb){ - addAutoDamageToOpponents(defenser); - }else{ - addDamager(defenser, selecterb); - } + if ((!strike && !defenser->has(Constants::FIRSTSTRIKE)) || (strike && defenser->has(Constants::FIRSTSTRIKE)) || defenser->has(Constants::DOUBLESTRIKE)){ + OutputDebugString("Blocker Damaging!\n"); + if (Player * selecterb = whoSelectsDamagesDealtBy(defenser)){ + addDamager(defenser, selecterb); + }else{ + addAutoDamageToOpponents(defenser); + } } defenser = defensers->getNextDefenser(defenser, attacker); } @@ -177,7 +223,7 @@ int DamageResolverLayer::initResolve(){ damageStack = NULL; modal = remainingDamageSteps; }else{ - if (canStopDealDamages()) currentChoosingPlayer = game->opponent(); + //nextPlayer(); } return 1; } @@ -199,22 +245,35 @@ DamagerDamaged * DamageResolverLayer::findByCard(MTGCardInstance * card){ int DamageResolverLayer::canStopDealDamages(){ for (int i = 0; i < mCount ; i ++){ DamagerDamaged * current = (DamagerDamaged *) mObjects[i]; - if (current->damageSelecter==currentChoosingPlayer && current->damageToDeal > 0){ - MTGCardInstance * card = current->card; + MTGCardInstance * card = current->card; + if (current->damageSelecter==currentChoosingPlayer){ + if (current->damageToDeal > 0){ + if (card->controller() == game->currentPlayer){ //Attacker + if (card->has(Constants::TRAMPLE)){ + MTGInPlay * defensers = game->opponent()->game->inPlay; + MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card); + while (defenser != NULL){ + DamagerDamaged * _defenser = findByCard(defenser); + if (!_defenser->hasLethalDamage()) return 0; + defenser = defensers->getNextDefenser(defenser, card); + } + }else{ + return 0; + } + }else{ //Defenser + return 0; + } + } if (card->controller() == game->currentPlayer){ //Attacker - if (card->has(Constants::TRAMPLE)){ - MTGInPlay * defensers = game->opponent()->game->inPlay; - MTGCardInstance * defenser = defensers->getNextDefenser(NULL, card); - while (defenser != NULL){ - DamagerDamaged * _defenser = findByCard(defenser); - if (!_defenser->hasLethalDamage()) return 0; - defenser = defensers->getNextDefenser(defenser, card); - } - }else{ - return 0; - } - }else{ //Defenser - return 0; + //check that blockers have lethal damage + list::iterator it; + int found_non_lethal = 0; + for (it= card->blockers.begin(); it != card->blockers.end(); ++it){ + MTGCardInstance * c = *it; + DamagerDamaged * defenser = findByCard(c); + if (found_non_lethal && defenser->sumDamages()) return 0; + if (!defenser->hasLethalDamage()) found_non_lethal = 1; + } } } } @@ -274,44 +333,95 @@ int DamageResolverLayer::isOpponent(DamagerDamaged * a, DamagerDamaged * b){ return 0; } -void DamageResolverLayer::nextPlayer(){ +int DamageResolverLayer::nextPlayer(){ + if (!canStopDealDamages()) return 0; if (currentChoosingPlayer == game->currentPlayer){ currentChoosingPlayer = game->opponent(); - if (canStopDealDamages()) resolveDamages(); - }else{ - resolveDamages(); } + resolveDamages(); + return 1; + } + +bool DamageResolverLayer::blockersOrderingDone(){ + orderingIsNeeded = 0; + game->blockersSorted = 1; + resetObjects(); + return true; +} + +bool DamageResolverLayer::clickReorderBlocker(MTGCardInstance * blocker){ + if (!blocker->defenser) return false; + MTGCardInstance * attacker = blocker->defenser; + attacker->moveBlockerInRow(blocker); + list::iterator it; + return true; +} + +bool DamageResolverLayer::checkUserInputOrderBlockers(u32 key){ + if (PSP_CTRL_CIRCLE == key) { + if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){ + DamagerDamaged * current = (DamagerDamaged *) mObjects[mCurr]; + MTGCardInstance * blocker = current->card; + return clickReorderBlocker(blocker); + } + return false; + }else if (PSP_CTRL_SQUARE == key){ + return blockersOrderingDone(); + }else{ + return PlayGuiObjectController::CheckUserInput(key); + } +} + +bool DamageResolverLayer::clickDamage(MTGCardInstance *c){ + DamagerDamaged * current = findByCard(c); + return clickDamage(current); +} + +bool DamageResolverLayer::clickDamage(DamagerDamaged * current){ + if (!current) return false; + if (!currentSource || !isOpponent(current,currentSource)){ + for (int i = 0; i < mCount; i++){ + DamagerDamaged * _current = (DamagerDamaged *) mObjects[i]; + if (isOpponent(current,_current)){ + currentSource = _current; + break; + } + } + } + if (currentSource){ + if (currentSource->damageSelecter == currentChoosingPlayer){ + if (isOpponent(current,currentSource)){ + MTGCardInstance * card = currentSource->card; + list::iterator it = card->blockers.begin(); + while (it!= card->blockers.end() && *it!=current->card){ + DamagerDamaged * item = findByCard(*it); + while (!item->hasLethalDamage() && currentSource->dealOneDamage(item)){} //Add default damage to the card... + it++; + } + if (!currentSource->dealOneDamage(current)){ + currentSource->removeDamagesTo(current); + } + } + } + }else{ + if (current->damageSelecter == currentChoosingPlayer){ + currentSource = current; + } + } + return true; +} + bool DamageResolverLayer::CheckUserInput(u32 key){ if (!mCount) return false; + if (orderingIsNeeded) return checkUserInputOrderBlockers(key); if (PSP_CTRL_CIRCLE == key){ if (mObjects[mCurr] && mObjects[mCurr]->ButtonPressed()){ DamagerDamaged * current = (DamagerDamaged *) mObjects[mCurr]; - if (!currentSource || !isOpponent(current,currentSource)){ - for (int i = 0; i < mCount; i++){ - DamagerDamaged * _current = (DamagerDamaged *) mObjects[i]; - if (isOpponent(current,_current)){ - currentSource = _current; - break; - } - } - } - if (currentSource){ - if (currentSource->damageSelecter == currentChoosingPlayer){ - if (isOpponent(current,currentSource)){ - if (!currentSource->dealOneDamage(current)){ - currentSource->removeDamagesTo(current); - } - } - } - }else{ - if (current->damageSelecter == currentChoosingPlayer){ - currentSource = current; - } - } - buttonOk = 0; - if (canStopDealDamages()) buttonOk = 1; + return clickDamage(current); + //buttonOk = 0; + //if (canStopDealDamages()) buttonOk = 1; } return true; }else if (PSP_CTRL_CROSS == key){ @@ -323,11 +433,7 @@ bool DamageResolverLayer::CheckUserInput(u32 key){ return true; } }else if (PSP_CTRL_SQUARE == key){ - if (canStopDealDamages()){ - nextPlayer(); - //switch to next player or end of selection - } - return true; + return nextPlayer(); }else{ return PlayGuiObjectController::CheckUserInput(key); } @@ -336,15 +442,16 @@ bool DamageResolverLayer::CheckUserInput(u32 key){ void DamageResolverLayer::Render(){ if (!mCount) return; + updateAllCoordinates(); //this is dirty :( JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT); mFont->SetBase(0); JRenderer * renderer = JRenderer::GetInstance(); renderer->FillRect(0 ,0 , SCREEN_WIDTH , SCREEN_HEIGHT , ARGB(200,0,0,0)); if (currentChoosingPlayer == game->currentPlayer){ - mFont->DrawString("Player 1", 0,0); + mFont->DrawString("Attacking Player", 0,0); }else{ - mFont->DrawString("Player 2", 0,0); + mFont->DrawString("Blocking Player", 0,0); } if (currentSource){ currentSource->RenderBig(10, 20); @@ -358,7 +465,8 @@ void DamageResolverLayer::Render(){ } - if (buttonOk){ + if (currentPhase == Constants::MTG_PHASE_COMBATDAMAGE && canStopDealDamages()){ mFont->DrawString("Damages Assigned, Click Square to Continue", 250, 5); } + if (orderingIsNeeded) mFont->DrawString("Order blockers, then Click Square to Continue", 200, 5); } diff --git a/projects/mtg/src/DamagerDamaged.cpp b/projects/mtg/src/DamagerDamaged.cpp index 882aba76c..d3e16c6a5 100644 --- a/projects/mtg/src/DamagerDamaged.cpp +++ b/projects/mtg/src/DamagerDamaged.cpp @@ -1,7 +1,9 @@ #include "../include/config.h" #include "../include/DamagerDamaged.h" - +/* +Temporary objects that store the damages dealt to/from creatures during the combat phase +*/ DamagerDamaged::DamagerDamaged(CardGui * cardg, Player * _damageSelecter, bool _hasFocus):CardGui(0, cardg->card,cardg->defaultHeight,cardg->x,cardg->y, _hasFocus){ @@ -26,7 +28,7 @@ int DamagerDamaged::sumDamages(){ } int DamagerDamaged::hasLethalDamage(){ - if (sumDamages() >= card->toughness) return 1; + if (sumDamages() >= card->life) return 1; return 0; } diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 347a64230..76a753c3c 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -52,6 +52,8 @@ GameObserver::GameObserver(Player * _players[], int _nb_players){ gameOver = NULL; phaseRing = NEW PhaseRing(_players,_nb_players); replacementEffects = NEW ReplacementEffects(); + blockersSorted = false; + blockersAssigned = 0; } void GameObserver::setGamePhaseManager(MTGGamePhase * _phases){ @@ -78,10 +80,20 @@ void GameObserver::nextPlayer(){ currentPlayerId = (currentPlayerId+1)%nbPlayers; currentPlayer = players[currentPlayerId]; currentActionPlayer = currentPlayer; + blockersSorted = false; + blockersAssigned = 0; } void GameObserver::nextGamePhase(){ Phase * cPhaseOld = phaseRing->getCurrentPhase(); + if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){ + blockersAssigned = 1; + if (!mLayers->combatLayer()->autoOrderBlockers()){ + OutputDebugString("Player has To choose ordering!"); + return; + } + } + phaseRing->forward(); Phase * cPhase = phaseRing->getCurrentPhase(); @@ -140,11 +152,22 @@ int GameObserver::cancelCurrentAction(){ } void GameObserver::userRequestNextGamePhase(){ + OutputDebugString("requesting Next Phase\n"); if (mLayers->stackLayer()->getNext(NULL,0,NOT_RESOLVED)) return; if (getCurrentTargetChooser()) return; - if (mLayers->combatLayer()->remainingDamageSteps) return; - //TODO CHECK POSSIBILITY - if (opponent()->isAI() || GameOptions::GetInstance()->values[GameOptions::phaseInterrupts[currentGamePhase]].getIntValue()){ + if (mLayers->combatLayer()->isDisplayed()) return; + Phase * cPhaseOld = phaseRing->getCurrentPhase(); + if (!blockersSorted && cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS){ + blockersAssigned = 1; + if (!mLayers->combatLayer()->autoOrderBlockers()){ + OutputDebugString("Player has To choose ordering!"); + return; + } + } + OutputDebugString("Next Phase Accepted\n"); + if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS || + opponent()->isAI() || + GameOptions::GetInstance()->values[GameOptions::phaseInterrupts[currentGamePhase]].getIntValue()){ mLayers->stackLayer()->AddNextGamePhase(); }else{ nextGamePhase(); @@ -237,7 +260,7 @@ GameObserver::~GameObserver(){ void GameObserver::Update(float dt){ Player * player = currentPlayer; - if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS){ + if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS && !blockersSorted){ player = opponent(); }else if (currentGamePhase == Constants::MTG_PHASE_COMBATDAMAGE){ DamageResolverLayer * drl = mLayers->combatLayer(); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 8197a9add..416913060 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -932,29 +932,29 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ //TODO } }else{ - if(tc){ - game->addObserver(NEW ATargetterPowerToughnessModifierUntilEOT(id, card,power,toughness, cost, tc,doTap)); - }else{ - if (lordType == PARSER_FOREACH){ - game->addObserver(NEW AForeach(id,card,target,lordTargets,lordIncludeSelf,power,toughness)); - }else if (lordType == PARSER_ASLONGAS){ - game->addObserver(NEW AKirdApe(id,card,lordTargets,lordIncludeSelf,power,toughness)); + if(tc){ + game->addObserver(NEW ATargetterPowerToughnessModifierUntilEOT(id, card,power,toughness, cost, tc,doTap)); + }else{ + if (lordType == PARSER_FOREACH){ + game->addObserver(NEW AForeach(id,card,target,lordTargets,lordIncludeSelf,power,toughness)); + }else if (lordType == PARSER_ASLONGAS){ + game->addObserver(NEW AKirdApe(id,card,lordTargets,lordIncludeSelf,power,toughness)); + }else{ + if (!cost){ + if(card->hasType("enchantment")){ + game->addObserver(NEW APowerToughnessModifier(id, card, target,power,toughness)); }else{ - if (!cost){ - if(card->hasType("enchantment")){ - game->addObserver(NEW APowerToughnessModifier(id, card, target,power,toughness)); - }else{ - game->addObserver(NEW AInstantPowerToughnessModifierUntilEOT(id, card, target,power,toughness)); - } - }else{ - game->addObserver(NEW APowerToughnessModifierUntilEndOfTurn(id, card, target,power,toughness, cost, limit)); - } + game->addObserver(NEW AInstantPowerToughnessModifierUntilEOT(id, card, target,power,toughness)); } - } + }else{ + game->addObserver(NEW APowerToughnessModifierUntilEndOfTurn(id, card, target,power,toughness, cost, limit)); + } } - result++; - continue; } + } + result++; + continue; + } //Mana Producer found = s.find("add"); @@ -970,43 +970,44 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){ if (input->isNull()){ SAFE_DELETE(input); } - MTGAbility * a = NEW AManaProducer(id, target, output, input,doTap); - ManaCost * FinalOutput = NEW ManaCost(); - if (lordType == PARSER_FOREACH){ - int multiplier = countCards(lordTargets); - for (int i = 0; i < Constants::MTG_NB_COLORS; i++){ - if (output->hasColor(i)){ - FinalOutput->add(i,multiplier); - } - } - game->addObserver (NEW AManaProducer(id, target,FinalOutput, input,doTap)); - }else{ - if (multi){ - multi->Add(a); - }else{ - game->addObserver(a); - } - } - }else{ + MTGAbility * a = NEW AManaProducer(id, target, output, input,doTap); + + if (lordType == PARSER_FOREACH){ + ManaCost * FinalOutput = NEW ManaCost(); + int multiplier = countCards(lordTargets); + for (int i = 0; i < Constants::MTG_NB_COLORS; i++){ + if (output->hasColor(i)){ + FinalOutput->add(i,multiplier); + } + } + game->addObserver (NEW AManaProducer(id, target,FinalOutput, input,doTap)); + }else{ + if (multi){ + multi->Add(a); + }else{ + game->addObserver(a); + } + } + }else{ OutputDebugString ("uh oh\n"); - if (lordType == PARSER_FOREACH){ - ManaCost * FinalOutput = NEW ManaCost(); - int multiplier = countCards(lordTargets); - for (int i = 0; i < Constants::MTG_NB_COLORS; i++){ - if (output->hasColor(i)){ - FinalOutput->add(i,multiplier); - } - } - card->controller()->getManaPool()->add(FinalOutput); - delete FinalOutput; - }else{ - card->controller()->getManaPool()->add(output); - delete output; - } - } - result++; - continue; - } + if (lordType == PARSER_FOREACH){ + ManaCost * FinalOutput = NEW ManaCost(); + int multiplier = countCards(lordTargets); + for (int i = 0; i < Constants::MTG_NB_COLORS; i++){ + if (output->hasColor(i)){ + FinalOutput->add(i,multiplier); + } + } + card->controller()->getManaPool()->add(FinalOutput); + delete FinalOutput; + }else{ + card->controller()->getManaPool()->add(output); + delete output; + } + } + result++; + continue; + } //Gain/loose Ability for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ @@ -2105,7 +2106,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ case 129521: //Dehydratation // Don't understand why but target automatically untap when cast... { - game->addObserver(NEW Blocker(_id,card,card->target)); + game->addObserver(NEW UntapBlocker(_id,card,card->target)); break; } @@ -2245,7 +2246,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell){ } if (card->basicAbilities[Constants::DOESNOTUNTAP]){ - game->addObserver(NEW Blocker(_id, card)); + game->addObserver(NEW UntapBlocker(_id, card)); } // Tested works the first r10 did not function because of the mistake in the array of the definition diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 04fc3cbef..b6d411e50 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -9,6 +9,8 @@ #include "../include/CardDescriptor.h" #include "../include/Counters.h" #include "../include/Subtypes.h" +#include +using namespace std; MTGCardInstance::MTGCardInstance(): MTGCard(), Damageable(0){ LOG("==Creating MTGCardInstance=="); @@ -75,7 +77,7 @@ void MTGCardInstance::copy(MTGCardInstance * card){ MTGCardInstance::~MTGCardInstance(){ LOG("==Deleting MTGCardInstance=="); - SAFE_DELETE(blockers); + SAFE_DELETE(untapBlockers); SAFE_DELETE(counters); SAFE_DELETE(previous); LOG("==Deleting MTGCardInstance Succesfull=="); @@ -88,7 +90,7 @@ void MTGCardInstance::initMTGCI(){ doDamageTest = 1; belongs_to=NULL; tapped = 0; - blockers = NULL; + untapBlockers = NULL; untapping = 0; summoningSickness = 0; target = NULL; @@ -111,9 +113,9 @@ void MTGCardInstance::addType(int type){ nb_types++; } -Blockers * MTGCardInstance::getBlockers(){ - if (!blockers) blockers = NEW Blockers(); - return blockers; +UntapBlockers * MTGCardInstance::getUntapBlockers(){ + if (!untapBlockers) untapBlockers = NEW UntapBlockers(); + return untapBlockers; } int MTGCardInstance::isInPlay(){ @@ -238,6 +240,7 @@ int MTGCardInstance::initAttackersDefensers(){ attacker = 0; defenser = NULL; banding = NULL; + blockers.clear(); return 1; } @@ -437,6 +440,37 @@ int MTGCardInstance::nbOpponents(){ } return result; } + +MTGCardInstance * MTGCardInstance::getNextDefenser(MTGCardInstance * previous){ + int found_previous = 0; + if (!previous) found_previous = 1; + list::iterator it; + for (it= blockers.begin(); it != blockers.end(); ++it){ + MTGCardInstance * c = *it; + if (found_previous && c->isInPlay()) return c; + if (c == previous) found_previous = 1; + } + return NULL; +} + +int MTGCardInstance::moveBlockerInRow(MTGCardInstance * blocker){ + list::iterator it1 = find(blockers.begin(), blockers.end(), blocker); + list::iterator it2 = it1; + if (it2 != blockers.end()) it2++; + if (it2 == blockers.end()) it2 = blockers.begin(); + + blockers.splice( it2, blockers, it1 ); // move a before b, invalidates a + char buffer[512]; + OutputDebugString("===Outputing blockers\n"); + for (it1 = blockers.begin(); it1 != blockers.end(); it1++){ + MTGCardInstance * c = *it1; + sprintf(buffer, "%p-", c); + OutputDebugString(buffer); + } + OutputDebugString("\n===End Outputing blockers\n"); + return 1; +} + //Returns opponents to this card for this turn. This * should * take into account banding MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous){ GameObserver * game = GameObserver::GetInstance(); @@ -474,7 +508,12 @@ MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous){ int MTGCardInstance::toggleDefenser(MTGCardInstance * opponent){ if (canBlock()){ if (canBlock(opponent)){ + if (defenser) defenser->blockers.remove(this); defenser = opponent; + if (defenser){ + defenser->blockers.push_back(this); + } + GameObserver::GetInstance()->blockersSorted = false; return 1; } } diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 345f3cbe3..be1f65acb 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -149,10 +149,11 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone } } + MTGCardInstance * ret = copy; if (card->isToken){ if (to != g->players[0]->game->inPlay && to != g->players[1]->game->inPlay){ - garbage->addCard(copy); - return NULL; + to = garbage; + ret = NULL; } } @@ -162,7 +163,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone WEvent * e = NEW WEventZoneChange(copy, from, to); g->receiveEvent(e); delete e; - return copy; + return ret; } return card; //Error } @@ -331,19 +332,7 @@ int MTGInPlay::nbPartners(MTGCardInstance * attacker){ } MTGCardInstance * MTGInPlay::getNextDefenser(MTGCardInstance * previous, MTGCardInstance * attacker){ - int foundprevious = 0; - if (previous == NULL){ - foundprevious = 1; - } - for (int i = 0; i < nb_cards; i ++){ - MTGCardInstance * current = cards[i]; - if (current == previous){ - foundprevious = 1; - }else if (foundprevious && current->isDefenser() == attacker){ - return current; - } - } - return NULL; + return attacker->getNextDefenser(previous); } MTGCardInstance * MTGInPlay::getNextAttacker(MTGCardInstance * previous){ @@ -366,7 +355,7 @@ void MTGInPlay::untapAll(){ int i; for (i = 0; i < nb_cards; i ++){ cards[i]->setUntapping(); - if (cards[i]->getBlockers()->isEmpty()){ + if (cards[i]->getUntapBlockers()->isEmpty()){ #if defined (WIN32) || defined (LINUX) char buf[4096]; sprintf(buf, "Can untap %s\n", cards[i]->getName()); diff --git a/projects/mtg/src/MTGGuiPlay.cpp b/projects/mtg/src/MTGGuiPlay.cpp index c9933b637..5abfd0727 100644 --- a/projects/mtg/src/MTGGuiPlay.cpp +++ b/projects/mtg/src/MTGGuiPlay.cpp @@ -91,9 +91,17 @@ void MTGGuiPlay::initCardsDisplay(){ } } cards_x_limit = 12; - nb_creatures = 0; - nb_lands = 0; - nb_spells = 0; + for (int i = 0; i < 2; i++){ + nb_creatures[i] = 0; + nb_lands[i] = 0; + nb_spells[i] = 0; + } + + for (int i = 6; i < mCount; i++){ + CardGui * cardg = (CardGui *)mObjects[i]; + cardg->x = 0; + cardg->y = 0; + } } @@ -111,43 +119,64 @@ void MTGGuiPlay::adjustCardPosition(CardGui * cardg){ } void MTGGuiPlay::setCardPosition(CardGui * cardg, int player, int playerTurn, int spellMode){ + GameObserver * g = GameObserver::GetInstance(); MTGCardInstance * card = cardg->card; + if (!(cardg->x ==0 && cardg->y ==0)) return ; if (card->target) return; if (spellMode && (card->isACreature() || card->hasType("land"))) return; if (!spellMode && !card->isACreature() && !card->hasType("land")) return; if (card->isACreature()){ - int x_offset = nb_creatures % cards_x_limit; - int y_offset = nb_creatures / cards_x_limit; + int x_offset = nb_creatures[player] % cards_x_limit; + int y_offset = nb_creatures[player] / cards_x_limit; cardg->x= ZX_MAIN + (Z_CARDWIDTH * x_offset); cardg->y=ZY_MAIN + ZH_CREATURES + (Z_CARDHEIGHT * y_offset) + 100 * (1-player); - nb_creatures++; + nb_creatures[player]++; if (playerTurn){ if (card->isAttacker()){ - cardg->y=122 + 30 * (1-player); + cardg->y=122 + 30 * (1-player); + //Sets position of opponents as well + if (player == 1){ + for (list::iterator it= card->blockers.begin(); it !=card->blockers.end() ; ++it){ + CardGui * c = getByCard(*it); + if (c) { + setCardPosition(c,1-player,1-playerTurn,spellMode); + adjustCardPosition(c); + } + } + }else{ + for (list::reverse_iterator it= card->blockers.rbegin(); it !=card->blockers.rend() ; ++it){ + CardGui * c = getByCard(*it); + if (c) { + setCardPosition(c,1-player,1-playerTurn,spellMode); + adjustCardPosition(c); + } + } + } + } }else{ if (card->isDefenser()){ - CardGui * targetg = getByCard(card->isDefenser()); - if (targetg) cardg->x = targetg->x; - cardg->y=122 + 30 * (1-player); + CardGui * targetg = getByCard(card->isDefenser()); + if (targetg) cardg->x = targetg->x; + cardg->y=122 + 30 * (1-player); } } }else if(card->hasType("land")){ - int x_offset = nb_lands % cards_x_limit; - int y_offset = nb_lands/ cards_x_limit; + int x_offset = nb_lands[player] % cards_x_limit; + int y_offset = nb_lands[player] / cards_x_limit; cardg->x=ZX_MAIN + (Z_CARDWIDTH * x_offset); cardg->y=ZY_MAIN + (Z_CARDHEIGHT * y_offset) + 200 * (1-player); - nb_lands++; + nb_lands[player]++; }else{ - int y_offset = nb_spells % Z_SPELLS_NBCARDS; - int x_offset = nb_spells/ Z_SPELLS_NBCARDS; + int y_offset = nb_spells[player] % Z_SPELLS_NBCARDS; + int x_offset = nb_spells[player] / Z_SPELLS_NBCARDS; cardg->x=ZX_SPELL - (Z_CARDWIDTH * x_offset); cardg->y=ZY_SPELL + (Z_CARDHEIGHT * y_offset) + 125 * (1-player); - nb_spells++; - cards_x_limit = 12 - (nb_spells + 2)/ Z_SPELLS_NBCARDS; + nb_spells[player]++; + cards_x_limit = 12 - (nb_spells[player] + 2)/ Z_SPELLS_NBCARDS; } adjustCardPosition(cardg); } @@ -208,6 +237,7 @@ int MTGGuiPlay::receiveEvent(WEvent *event){ } if (!ok) return 0; forceUpdateCards(); + updateCards(); return 1; } @@ -229,25 +259,27 @@ void MTGGuiPlay::updateCards(){ //This is just so that we display the cards of the current player first, so that blockers are correctly positionned + initCardsDisplay(); for (int j= 0; j < 2; j++){ - initCardsDisplay(); if (j != player0Mode){ for (int i =0; icard; + setCardPosition(cardGui, 0, player0Mode, 0); } }else{ for (int i =0; icard; + setCardPosition(cardGui, 1, !player0Mode,0); } } } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index aea6e62a2..36effbe43 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -130,7 +130,7 @@ MTGBlockRule::MTGBlockRule(int _id):MTGAbility(_id,NULL){ } int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana){ - if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->opponent()){ + if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() == game->currentlyActing()){ if (card->canBlock()) return 1; } return 0; @@ -166,6 +166,11 @@ ostream& MTGBlockRule::toString(ostream& out) const return MTGAbility::toString(out) << ")"; } + +// +// Attacker chooses blockers order +// + // // * Momir // diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index 702888893..5fcca70a5 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -3,6 +3,7 @@ #include "../include/MTGAbility.h" #include "../include/MTGRules.h" #include "../include/ActionLayer.h" +#include "../include/DamageResolverLayer.h" #include using std::string; @@ -63,6 +64,8 @@ int TestSuiteAI::Act(float dt){ string action = suite->getNextAction(); g->mLayers->stackLayer()->Dump(); + DamageResolverLayer * drl = g->mLayers->combatLayer(); + OutputDebugString(action.c_str()); OutputDebugString("\n"); @@ -87,7 +90,16 @@ int TestSuiteAI::Act(float dt){ g->userRequestNextGamePhase(); } else if (action.compare("next")==0){ - g->userRequestNextGamePhase(); + if (drl->orderingIsNeeded){ + drl->blockersOrderingDone(); + g->userRequestNextGamePhase(); + }else if (drl->mCount){ + OutputDebugString("End of combat damage!\n"); + drl->nextPlayer(); + g->userRequestNextGamePhase(); + }else{ + g->userRequestNextGamePhase(); + } }else if (action.compare("yes")==0){ g->mLayers->stackLayer()->setIsInterrupting(this); }else if (action.compare("endinterruption")==0){ @@ -121,7 +133,17 @@ int TestSuiteAI::Act(float dt){ if (card) { OutputDebugString("Clicking ON: "); OutputDebugString(card->name.c_str()); - g->cardClick(card,card); + if (drl->mCount){ + if (drl->orderingIsNeeded){ + OutputDebugString(" Ordering Card\n"); + drl->clickReorderBlocker(card); + }else{ + OutputDebugString(" Damaging Card\n"); + drl->clickDamage(card); + } + }else{ + g->cardClick(card,card); + } } } }else{