- Created a GamePhase type to ease debug.

- Modified the testsuite and gameobserver to be able to replay all the testcases based on the actions logged during the first pass. This allows to test the action logging and replay used during undo. It's only activated in multithreaded mode and it does not work on Momir tests.
-  Modified choice logging and replay to use menuId instead of ability index, as, for some obscur reasons related to Lord, those ability indexes may change.
- Fixed bug in nextphase logging wrongly generating click actions
- Added a "stack" zone to the click ability logging to be able to replay properly interrupt
- Fixed a wonderful bug mixing card names with zone names in the actions execution engine
- Added a "combatok" action logging/execution
- Added a "clone" virtual method to MTGCardInstance and Token to be able to clone correctly the right object type. Used that in MTGGameZones::removeCard
This commit is contained in:
Xawotihs
2011-11-29 21:50:16 +00:00
parent 104d134c1f
commit 3514476812
33 changed files with 433 additions and 286 deletions
+3 -2
View File
@@ -7,6 +7,7 @@
#ifndef _ACTIONELEMENT_H_
#define _ACTIONELEMENT_H_
#include <JGui.h>
#include "MTGDefinitions.h"
#define INACTIVE 0
#define ACTION_REQUESTED 1
@@ -24,8 +25,8 @@ protected:
int activeState;
TargetChooser * tc;
public:
int currentPhase;
int newPhase;
GamePhase currentPhase;
GamePhase newPhase;
int modal;
int waitingForAnswer;
int getActivity();
+34 -34
View File
@@ -1769,7 +1769,7 @@ public:
void Update(float dt)
{
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP) clear();
if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP) clear();
TargetAbility::Update(dt);
}
@@ -3259,7 +3259,7 @@ public:
void Update(float dt)
{
if (newPhase != currentPhase && (newPhase == Constants::MTG_PHASE_COMBATBEGIN || newPhase == Constants::MTG_PHASE_COMBATATTACKERS))
if (newPhase != currentPhase && (newPhase == MTG_PHASE_COMBATBEGIN || newPhase == MTG_PHASE_COMBATATTACKERS))
{
if (source->controller()->opponent()->game->inPlay->hasType(land))
{
@@ -3461,12 +3461,12 @@ public:
{
if (WEventPhaseChange* pe = dynamic_cast<WEventPhaseChange*>(event))
{
if (luckyWinner && Constants::MTG_PHASE_AFTER_EOT == pe->from->id)
if (luckyWinner && MTG_PHASE_AFTER_EOT == pe->from->id)
{
luckyWinner = NULL;
}
if (Constants::MTG_PHASE_COMBATATTACKERS == pe->from->id)
if (MTG_PHASE_COMBATATTACKERS == pe->from->id)
{
int nbattackers = 0;
MTGGameZone * z = source->controller()->game->inPlay;
@@ -3627,7 +3627,7 @@ public:
ManaCost * backupMana;
AUpkeep(GameObserver* observer, int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, int restrictions = 0, int _phase =
Constants::MTG_PHASE_UPKEEP, int _once = 0,bool Cumulative = false);
MTG_PHASE_UPKEEP, int _once = 0,bool Cumulative = false);
int receiveEvent(WEvent * event);
void Update(float dt);
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
@@ -3655,7 +3655,7 @@ public:
Player * abilityOwner;
APhaseAction(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int restrictions = 0, int _phase =
Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = true,bool opponentturn = true,bool once = false);
MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = true,bool opponentturn = true,bool once = false);
void Update(float dt);
int resolve();
const char * getMenuText();
@@ -3670,7 +3670,7 @@ public:
string sAbility;
APhaseAction * ability;
APhaseActionGeneric(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int restrictions = 0, int _phase =
Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = false,bool opponentturn = false,bool once = false);
MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = false,bool opponentturn = false,bool once = false);
int resolve();
const char * getMenuText();
APhaseActionGeneric * clone() const;
@@ -3819,11 +3819,11 @@ public:
{
if (newPhase != currentPhase)
{
if (newPhase == Constants::MTG_PHASE_UPKEEP && game->currentPlayer->game->inPlay->hasCard(source))
if (newPhase == MTG_PHASE_UPKEEP && game->currentPlayer->game->inPlay->hasCard(source))
{
counters++;
}
else if (newPhase == Constants::MTG_PHASE_DRAW && counters > 0 && game->currentPlayer->game->inPlay->hasCard(source))
else if (newPhase == MTG_PHASE_DRAW && counters > 0 && game->currentPlayer->game->inPlay->hasCard(source))
{ //End of upkeep = beginning of draw
game->mLayers->stackLayer()->addDamage(source, game->players[0],
counters);
@@ -3834,7 +3834,7 @@ public:
}
int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL)
{
if (counters > 0 && _card == source && currentPhase == Constants::MTG_PHASE_UPKEEP)
if (counters > 0 && _card == source && currentPhase == MTG_PHASE_UPKEEP)
{
if (game->currentlyActing()->getManaPool()->canAfford(&cost))
{
@@ -3979,7 +3979,7 @@ public:
void Update(float dt)
{
if (newPhase != currentPhase && newPhase != Constants::MTG_PHASE_UPKEEP)
if (newPhase != currentPhase && newPhase != MTG_PHASE_UPKEEP)
{
usedThisTurn = 0;
}
@@ -3989,7 +3989,7 @@ public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL)
{
if (!ActivatedAbility::isReactingToClick(card, mana)) return 0;
if (currentPhase != Constants::MTG_PHASE_UPKEEP) return 0;
if (currentPhase != MTG_PHASE_UPKEEP) return 0;
if (usedThisTurn) return 0;
return 1;
}
@@ -4028,7 +4028,7 @@ public:
{
if (newPhase != currentPhase)
{
if (newPhase == Constants::MTG_PHASE_COMBATEND)
if (newPhase == MTG_PHASE_COMBATEND)
{
nbOpponents = 0;
MTGCardInstance * opponent = source->getNextOpponent();
@@ -4051,7 +4051,7 @@ public:
int testDestroy()
{
if (!game->isInPlay(source) && currentPhase != Constants::MTG_PHASE_UNTAP)
if (!game->isInPlay(source) && currentPhase != MTG_PHASE_UNTAP)
{
return 0;
}
@@ -4129,12 +4129,12 @@ public:
if (newPhase != currentPhase)
{
Player * controller = source->controller();
if(newPhase == Constants::MTG_PHASE_ENDOFTURN)
if(newPhase == MTG_PHASE_ENDOFTURN)
{
if(!attackedThisTurn && game->currentPlayer == source->controller() && !source->fresh)
game->mLayers->stackLayer()->addDamage(source, controller, 2);
}
else if (newPhase == Constants::MTG_PHASE_UNTAP)
else if (newPhase == MTG_PHASE_UNTAP)
{
if (game->currentPlayer == controller)
@@ -4184,7 +4184,7 @@ public:
void Update(float dt)
{
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP)
if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP)
{
landsPlayedThisTurn = 0;
}
@@ -4358,7 +4358,7 @@ public:
void Update(float dt)
{
MTGCardInstance * _target = (MTGCardInstance *) target;
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UPKEEP && _target->controller() == game->currentPlayer)
if (newPhase != currentPhase && newPhase == MTG_PHASE_UPKEEP && _target->controller() == game->currentPlayer)
{
damagesToDealThisTurn = 2;
}
@@ -4368,7 +4368,7 @@ public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL)
{
MTGCardInstance * _target = (MTGCardInstance *) target;
if (damagesToDealThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && card == source && _target->controller()
if (damagesToDealThisTurn && currentPhase == MTG_PHASE_UPKEEP && card == source && _target->controller()
== game->currentPlayer)
{
if (game->currentPlayer->getManaPool()->canAfford(&cost)) return 1;
@@ -4386,7 +4386,7 @@ public:
int trigger()
{
MTGCardInstance * _target = (MTGCardInstance *) target;
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_DRAW && _target->controller() == game->currentPlayer)
if (newPhase != currentPhase && newPhase == MTG_PHASE_DRAW && _target->controller() == game->currentPlayer)
{
if (damagesToDealThisTurn) return 1;
}
@@ -4513,14 +4513,14 @@ public:
void Update(float dt)
{
if (currentPhase == Constants::MTG_PHASE_UNTAP && game->currentPlayer == source->controller())
if (currentPhase == MTG_PHASE_UNTAP && game->currentPlayer == source->controller())
{
initThisTurn = 0;
for(unsigned int i = 0; i < effectedCards.size(); i++)
effectedCards.at(i)->basicAbilities[(int)Constants::CANTATTACK] = 0;
effectedCards.clear();
}
if (initThisTurn && currentPhase == Constants::MTG_PHASE_COMBATBEGIN && game->currentPlayer != source->controller())
if (initThisTurn && currentPhase == MTG_PHASE_COMBATBEGIN && game->currentPlayer != source->controller())
{
MTGGameZone * zone = game->currentPlayer->game->inPlay;
for (int i = 0; i < zone->nb_cards; i++)
@@ -4584,11 +4584,11 @@ public:
//Upkeep Cost
if (newPhase != currentPhase)
{
if (newPhase == Constants::MTG_PHASE_UPKEEP)
if (newPhase == MTG_PHASE_UPKEEP)
{
paidThisTurn = 0;
}
else if (!paidThisTurn && newPhase > Constants::MTG_PHASE_UPKEEP && game->currentPlayer == source->controller())
else if (!paidThisTurn && newPhase > MTG_PHASE_UPKEEP && game->currentPlayer == source->controller())
{
game->currentPlayer->game->putInGraveyard(source);
paidThisTurn = 1;
@@ -4597,7 +4597,7 @@ public:
//Stasis Effect
for (int i = 0; i < 2; i++)
{
game->phaseRing->removePhase(Constants::MTG_PHASE_UNTAP, game->players[i]);
game->phaseRing->removePhase(MTG_PHASE_UNTAP, game->players[i]);
}
//Parent Class Method Call
@@ -4606,7 +4606,7 @@ public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL)
{
return (!paidThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card, mana));
return (!paidThisTurn && currentPhase == MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card, mana));
}
int resolve()
@@ -4619,7 +4619,7 @@ public:
{
for (int i = 0; i < 2; i++)
{
game->phaseRing->addPhaseBefore(Constants::MTG_PHASE_UNTAP, game->players[i], Constants::MTG_PHASE_UPKEEP,
game->phaseRing->addPhaseBefore(MTG_PHASE_UNTAP, game->players[i], MTG_PHASE_UPKEEP,
game->players[i]);
}
return 1;
@@ -4654,7 +4654,7 @@ public:
{
if (newPhase != currentPhase)
{
if (newPhase == Constants::MTG_PHASE_COMBATDAMAGE)
if (newPhase == MTG_PHASE_COMBATDAMAGE)
{
nbOpponents = 0;
MTGCardInstance * opponent = source->getNextOpponent();
@@ -4665,7 +4665,7 @@ public:
opponent = source->getNextOpponent(opponent);
}
}
else if (newPhase == Constants::MTG_PHASE_COMBATEND)
else if (newPhase == MTG_PHASE_COMBATEND)
{
for (int i = 0; i < nbOpponents; i++)
{
@@ -4753,11 +4753,11 @@ public:
{
if (newPhase != currentPhase && source->controller() == game->currentPlayer)
{
if (newPhase == Constants::MTG_PHASE_UNTAP)
if (newPhase == MTG_PHASE_UNTAP)
{
paidThisTurn = 0;
}
else if (newPhase == Constants::MTG_PHASE_UPKEEP + 1 && !paidThisTurn)
else if (newPhase == MTG_PHASE_UPKEEP + 1 && !paidThisTurn)
{
game->mLayers->stackLayer()->addDamage(source, source->controller(), 5);
source->tap();
@@ -4768,7 +4768,7 @@ public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL)
{
if (currentPhase != Constants::MTG_PHASE_UPKEEP || paidThisTurn) return 0;
if (currentPhase != MTG_PHASE_UPKEEP || paidThisTurn) return 0;
return TargetAbility::isReactingToClick(card, mana);
}
@@ -4824,7 +4824,7 @@ public:
}
else if (WEventPhaseChange* pe = dynamic_cast<WEventPhaseChange*>(event))
{
if (Constants::MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents > MaxOpponent)
if (MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents > MaxOpponent)
{
source->power -= PowerModifier * (nbOpponents - MaxOpponent);
source->addToToughness(-ToughnessModifier * (nbOpponents - MaxOpponent));
@@ -4922,7 +4922,7 @@ public:
}
else if (WEventPhaseChange* pe = dynamic_cast<WEventPhaseChange*>(event))
{
if (Constants::MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents)
if (MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents)
{
source->power -= PowerModifier;
source->addToToughness(-ToughnessModifier);
+21 -8
View File
@@ -51,12 +51,20 @@ class GameObserver{
string startupGameSerialized;
bool parseLine(const string& s);
void logAction(const string& s);
bool processActions(bool undo);
friend ostream& operator<<(ostream&, GameObserver&);
bool processActions(bool undo
#ifdef TESTSUITE
, TestSuiteGame* testgame
#endif
);
friend ostream& operator<<(ostream&, const GameObserver&);
bool mLoading;
void nextGamePhase();
void shuffleLibrary(Player* p);
void createPlayer(const string& playerMode);
void createPlayer(const string& playerMode
#ifdef TESTSUITE
, TestSuiteGame* testgame
#endif //TESTSUITE
);
public:
int currentPlayerId;
@@ -66,7 +74,7 @@ class GameObserver{
int targetListIsSet(MTGCardInstance * card);
PhaseRing * phaseRing;
int cancelCurrentAction();
int currentGamePhase;
GamePhase currentGamePhase;
ExtraCosts * mExtraPayment;
int oldGamePhase;
TargetChooser * targetChooser;
@@ -83,10 +91,11 @@ class GameObserver{
TargetChooser * getCurrentTargetChooser();
void stackObjectClicked(Interruptible * action);
int cardClickLog(bool log, Player* clickedPlayer, MTGGameZone* zone, MTGCardInstance*backup, size_t index, int toReturn);
int cardClick(MTGCardInstance * card, MTGAbility *ability);
int cardClick(MTGCardInstance * card, int abilityType);
int cardClick(MTGCardInstance * card,Targetable * _object = NULL );
int getCurrentGamePhase();
int cardClick(MTGCardInstance * card,Targetable * _object = NULL, bool log = true);
GamePhase getCurrentGamePhase();
const char * getCurrentGamePhaseName();
const char * getNextGamePhaseName();
void nextCombatStep();
@@ -131,7 +140,11 @@ class GameObserver{
logAction(players[playerId], s);
};
void logAction(MTGCardInstance* card, MTGGameZone* zone, size_t index, int result);
bool load(const string& s, bool undo = false);
bool load(const string& s, bool undo = false
#ifdef TESTSUITE
, TestSuiteGame* testgame = 0
#endif
);
bool undo();
bool isLoading(){ return mLoading; };
void Mulligan(Player* player = NULL);
@@ -144,7 +157,7 @@ class GameObserver{
JGE* getInput(){return mJGE;};
DeckManager* getDeckManager(){ return mDeckManager; };
void dumpAssert(bool val);
void resetStartupGame();
};
#endif
+1 -1
View File
@@ -289,7 +289,7 @@ public:
virtual void Update(float dt)
{
if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT)
if (newPhase != currentPhase && newPhase == MTG_PHASE_AFTER_EOT)
{
counters = 0;
}
+1
View File
@@ -208,6 +208,7 @@ public:
static MTGCardInstance NoCard;
bool parseLine(const string& ss);
virtual MTGCardInstance* clone();
};
+21 -17
View File
@@ -35,6 +35,27 @@ typedef enum
#endif //NETWORK_SUPPORT
} PlayerType;
typedef enum
{
MTG_PHASE_INVALID = -1,
MTG_PHASE_BEFORE_BEGIN = 0,
MTG_PHASE_UNTAP = 1,
MTG_PHASE_UPKEEP = 2,
MTG_PHASE_DRAW = 3,
MTG_PHASE_FIRSTMAIN = 4,
MTG_PHASE_COMBATBEGIN = 5,
MTG_PHASE_COMBATATTACKERS = 6,
MTG_PHASE_COMBATBLOCKERS = 7,
MTG_PHASE_COMBATDAMAGE = 8,
MTG_PHASE_COMBATEND = 9,
MTG_PHASE_SECONDMAIN = 10,
MTG_PHASE_ENDOFTURN = 11,
MTG_PHASE_CLEANUP = 12,
MTG_PHASE_AFTER_EOT = 13,
NB_MTG_PHASES = 14
} GamePhase;
class Constants
{
public:
@@ -95,23 +116,6 @@ class Constants
MTG_TYPE_LAND = 14,
MTG_TYPE_INSTANT = 15,
MTG_PHASE_BEFORE_BEGIN = 0,
MTG_PHASE_UNTAP = 1,
MTG_PHASE_UPKEEP = 2,
MTG_PHASE_DRAW = 3,
MTG_PHASE_FIRSTMAIN = 4,
MTG_PHASE_COMBATBEGIN = 5,
MTG_PHASE_COMBATATTACKERS = 6,
MTG_PHASE_COMBATBLOCKERS = 7,
MTG_PHASE_COMBATDAMAGE = 8,
MTG_PHASE_COMBATEND = 9,
MTG_PHASE_SECONDMAIN = 10,
MTG_PHASE_ENDOFTURN = 11,
MTG_PHASE_CLEANUP = 12,
MTG_PHASE_AFTER_EOT = 13,
NB_MTG_PHASES = 14,
TRAMPLE = 0,
FORESTWALK = 1,
ISLANDWALK = 2,
+5 -4
View File
@@ -3,6 +3,7 @@
#include <list>
#include <string>
#include "MTGDefinitions.h"
using namespace std;
/*
@@ -26,9 +27,9 @@ typedef enum
class Phase
{
public:
int id;
GamePhase id;
Player * player;
Phase(int id, Player *player) :
Phase(GamePhase id, Player *player) :
id(id), player(player)
{
}
@@ -49,10 +50,10 @@ public:
PhaseRing(GameObserver* observer);
~PhaseRing();
int addPhase(Phase * phase);
int addPhaseBefore(int id, Player* player, int after_id, Player * after_player, int allOccurences = 1);
int addPhaseBefore(GamePhase id, Player* player, int after_id, Player * after_player, int allOccurences = 1);
int removePhase(int id, Player * player, int allOccurences = 1);
const char * phaseName(int id);
static int phaseStrToInt(string s);
static GamePhase phaseStrToInt(string s);
};
+2 -1
View File
@@ -3,6 +3,7 @@
#include <string>
#include <vector>
#include "MTGDefinitions.h"
using namespace std;
class ManaCost;
@@ -28,7 +29,7 @@ public:
class RulesState
{
public:
int phase;
GamePhase phase;
int player;
void parsePlayerState(int playerId, string s);
RulesState();
+2 -1
View File
@@ -26,7 +26,7 @@ class TestSuiteAI;
class TestSuiteState
{
public:
int phase;
GamePhase phase;
void parsePlayerState(int playerId, string s);
TestSuiteState();
~TestSuiteState();
@@ -63,6 +63,7 @@ public:
virtual ~TestSuiteGame();
TestSuiteGame(TestSuite* testsuite);
TestSuiteGame(TestSuite* testsuite, string _filename);
void ResetManapools();
void initGame();
void assertGame();
MTGPlayerCards * buildDeck(Player* player, int playerId);
+2
View File
@@ -9,6 +9,8 @@ class Token: public MTGCardInstance
public:
Token(string _name, MTGCardInstance * source, int _power = 0, int _toughness = 0);
Token(int id);
Token(const Token& source);
virtual MTGCardInstance* clone();
};
#endif
+1 -1
View File
@@ -75,7 +75,7 @@ protected:
public:
RandomGenerator(bool doLog = false) : log(doLog) {};
void loadRandValues(string s);
ostream& saveUsedRandValues(ostream& out);
ostream& saveUsedRandValues(ostream& out) const;
ostream& saveLoadedRandValues(ostream& out);
int random();
template<typename Iter> void random_shuffle(Iter first, Iter last)