- Modified DeckManager class to not use a global instance anymore when used within the game engine
- Modified DuelLayers to not use a global MTGPhaseGame instance anymore - Moved the reset of currentActionCard out of the ActionLayer render function : that fixes the remaing problematic tests in the multithreaded testsuite - Added a method in ActionLayer converting a card ability into a menu index - Used this new method in the game observer to log correctly AI ability actions - Added a DumpAssert method in the game observer, it can be used to dump the game and assert in order to easy crash reproduction - Cleaned up TargetList properties access - Added an optimisation in GuiMana to not compute update code if the rendering is not used (multi-threaded mode) - Added a deadlock detection in the test AI vs AI multithreaded mode - Fixed minor bugs in test AI vs AI multithreaded mode - Added a games/second counter in the test AI vs AI rendering
This commit is contained in:
@@ -37,6 +37,7 @@ public:
|
||||
int receiveEventPlus(WEvent * event);
|
||||
int reactToTargetClick(Targetable * card);
|
||||
int isReactingToClick(MTGCardInstance * card);
|
||||
bool getMenuIdFromCardAbility(MTGCardInstance *card, MTGAbility *ability, int& menuId);
|
||||
int reactToClick(MTGCardInstance * card);
|
||||
int reactToClick(ActionElement * ability, MTGCardInstance * card);
|
||||
int reactToTargetClick(ActionElement * ability, Targetable * card);
|
||||
|
||||
@@ -8,21 +8,19 @@ using namespace std;
|
||||
class DeckManager
|
||||
{
|
||||
private:
|
||||
static bool instanceFlag;
|
||||
vector<DeckMetaData*> playerDeckOrderList;
|
||||
vector<DeckMetaData*> aiDeckOrderList;
|
||||
map<string, StatsWrapper*> playerDeckStatsMap;
|
||||
map<string, StatsWrapper*> aiDeckStatsMap;
|
||||
|
||||
static DeckManager *mInstance;
|
||||
|
||||
public:
|
||||
DeckManager()
|
||||
{
|
||||
//private constructor
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
vector<DeckMetaData*> playerDeckOrderList;
|
||||
vector<DeckMetaData*> aiDeckOrderList;
|
||||
|
||||
map<string, StatsWrapper*> playerDeckStatsMap;
|
||||
map<string, StatsWrapper*> aiDeckStatsMap;
|
||||
|
||||
void updateMetaDataList(vector<DeckMetaData*>* refList, bool isAI);
|
||||
vector<DeckMetaData*> * getPlayerDeckOrderList();
|
||||
vector<DeckMetaData*> * getAIDeckOrderList();
|
||||
@@ -40,7 +38,7 @@ public:
|
||||
//convenience method to get the difficulty rating between two decks. This should be refined a little more
|
||||
//since the eventual move of all deck meta data should be managed by this class
|
||||
|
||||
static int getDifficultyRating(Player *statsPlayer, Player *player);
|
||||
int getDifficultyRating(Player *statsPlayer, Player *player);
|
||||
|
||||
~DeckManager();
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ class GuiCombat;
|
||||
class GuiAvatars;
|
||||
class CardSelectorBase;
|
||||
struct Pos;
|
||||
class MTGGamePhase;
|
||||
|
||||
class DuelLayers
|
||||
{
|
||||
@@ -27,6 +28,7 @@ protected:
|
||||
GuiHandSelf *hand;
|
||||
GuiAvatars * avatars;
|
||||
GameObserver* observer;
|
||||
MTGGamePhase* phaseHandler;
|
||||
|
||||
public:
|
||||
DuelLayers();
|
||||
@@ -36,6 +38,7 @@ public:
|
||||
ActionStack * stackLayer();
|
||||
GuiCombat * combatLayer();
|
||||
GuiAvatars * GetAvatars();
|
||||
MTGGamePhase* getPhaseHandler() {return phaseHandler;};
|
||||
void init(GameObserver* go);
|
||||
virtual void Update(float dt, Player * player);
|
||||
void CheckUserInput(int isAI);
|
||||
|
||||
@@ -23,6 +23,7 @@ class TargetChooser;
|
||||
class Rules;
|
||||
class TestSuiteGame;
|
||||
class Trash;
|
||||
class DeckManager;
|
||||
using namespace std;
|
||||
|
||||
class GameObserver{
|
||||
@@ -37,6 +38,8 @@ class GameObserver{
|
||||
RandomGenerator randomGenerator;
|
||||
WResourceManager* mResourceManager;
|
||||
JGE* mJGE;
|
||||
DeckManager* mDeckManager;
|
||||
|
||||
size_t updateCtr;
|
||||
#ifdef ACTION_LOGGING_TESTING
|
||||
GameObserver* oldGame;
|
||||
@@ -139,6 +142,8 @@ class GameObserver{
|
||||
CardSelectorBase* getCardSelector() { return mLayers->mCardSelector;};
|
||||
bool operator==(const GameObserver& aGame);
|
||||
JGE* getInput(){return mJGE;};
|
||||
DeckManager* getDeckManager(){ return mDeckManager; };
|
||||
void dumpAssert(bool val);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef AI_CHANGE_TESTING
|
||||
int startTime;
|
||||
int totalTestGames;
|
||||
int testPlayer2Victories;
|
||||
int totalAIDecks;
|
||||
|
||||
@@ -13,12 +13,10 @@ protected:
|
||||
float animation;
|
||||
int currentState;
|
||||
WFont * mFont;
|
||||
static MTGGamePhase* instance;
|
||||
GameObserver* observer;
|
||||
|
||||
public:
|
||||
MTGGamePhase(GameObserver* g, int id);
|
||||
static MTGGamePhase* GetInstance() { return instance; };
|
||||
virtual void Update(float dt);
|
||||
bool CheckUserInput(JButton key);
|
||||
virtual MTGGamePhase * clone() const;
|
||||
|
||||
@@ -14,15 +14,16 @@ using std::vector;
|
||||
|
||||
class TargetsList
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
size_t iterateTarget(Targetable * previous);
|
||||
vector<Targetable*> targets;
|
||||
public:
|
||||
TargetsList();
|
||||
TargetsList(Targetable * _targets[], int nbtargets);
|
||||
vector<Targetable*> targets;
|
||||
int alreadyHasTarget(Targetable * target);
|
||||
int removeTarget(Targetable * _card);
|
||||
int toggleTarget(Targetable * _card);
|
||||
size_t getNbTargets() {return targets.size();};
|
||||
virtual int addTarget(Targetable * _target);
|
||||
MTGCardInstance * getNextCardTarget(MTGCardInstance * previous = 0);
|
||||
Player * getNextPlayerTarget(Player * previous = 0);
|
||||
|
||||
@@ -236,7 +236,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards *
|
||||
deckid = 1 + WRand() % (nbdecks);
|
||||
}
|
||||
sprintf(deckFile, "ai/baka/deck%i.txt", deckid);
|
||||
DeckMetaData *aiMeta = DeckManager::GetInstance()->getDeckMetaDataByFilename( deckFile, true);
|
||||
DeckMetaData *aiMeta = observer->getDeckManager()->getDeckMetaDataByFilename( deckFile, true);
|
||||
avatarFilename = aiMeta->getAvatarFilename();
|
||||
sprintf(deckFileSmall, "ai_baka_deck%i", deckid);
|
||||
}
|
||||
@@ -245,7 +245,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards *
|
||||
if ( opponent )
|
||||
{
|
||||
bool isOpponentAI = opponent->isAI() == 1;
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
||||
DeckMetaData *meta = observer->getDeckManager()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
||||
if ( meta && meta->getVictoryPercentage() >= 65)
|
||||
deckSetting = HARD;
|
||||
}
|
||||
@@ -320,7 +320,7 @@ AIPlayer * AIPlayerFactory::createAIPlayerTest(GameObserver *observer, MTGAllCar
|
||||
deckid = 1 + WRand() % (nbdecks);
|
||||
|
||||
sprintf(deckFile, "%sdeck%i.txt", folder.c_str(), deckid);
|
||||
DeckMetaData *aiMeta = DeckManager::GetInstance()->getDeckMetaDataByFilename( deckFile, true);
|
||||
DeckMetaData *aiMeta = observer->getDeckManager()->getDeckMetaDataByFilename( deckFile, true);
|
||||
avatarFilename = aiMeta->getAvatarFilename();
|
||||
sprintf(deckFileSmall, "ai_baka_deck%i", deckid);
|
||||
|
||||
@@ -329,7 +329,7 @@ AIPlayer * AIPlayerFactory::createAIPlayerTest(GameObserver *observer, MTGAllCar
|
||||
if ( opponent )
|
||||
{
|
||||
bool isOpponentAI = opponent->isAI() == 1;
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
||||
DeckMetaData *meta = observer->getDeckManager()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI);
|
||||
if ( meta->getVictoryPercentage() >= 65)
|
||||
deckSetting = HARD;
|
||||
}
|
||||
|
||||
@@ -1188,7 +1188,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
||||
vector<Targetable*>realTargets;
|
||||
if(a->getActionTc()->maxtargets != 1)
|
||||
{
|
||||
if(a->getActionTc()->targets.size() && a->getActionTc()->attemptsToFill > 4)
|
||||
if(a->getActionTc()->getNbTargets() && a->getActionTc()->attemptsToFill > 4)
|
||||
{
|
||||
a->getActionTc()->done = true;
|
||||
return 0;
|
||||
|
||||
@@ -178,7 +178,7 @@ void ActionLayer::Update(float dt)
|
||||
without this, the game locks into a freeze state while you try to select the targets and dont have enough to
|
||||
fill the maxtargets list.
|
||||
*/
|
||||
if(int(ae->getActionTc()->targets.size()) == countTargets-1)
|
||||
if(int(ae->getActionTc()->getNbTargets()) == countTargets-1)
|
||||
ae->getActionTc()->done = true;
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ void ActionLayer::Render()
|
||||
abilitiesMenu->Render();
|
||||
return;
|
||||
}
|
||||
currentActionCard = NULL;
|
||||
|
||||
for (size_t i = 0; i < mObjects.size(); i++)
|
||||
{
|
||||
if (mObjects[i] != NULL)
|
||||
@@ -290,6 +290,29 @@ int ActionLayer::reactToTargetClick(Targetable * card)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ActionLayer::getMenuIdFromCardAbility(MTGCardInstance *card, MTGAbility *ability, int& menuId)
|
||||
{
|
||||
int ctr = 0;
|
||||
for (size_t i = 0; i < mObjects.size(); i++)
|
||||
{
|
||||
ActionElement * currentAction = (ActionElement *) mObjects[i];
|
||||
if (currentAction->isReactingToClick(card))
|
||||
{
|
||||
if(currentAction == ability) {
|
||||
menuId = ctr;
|
||||
}
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
|
||||
// ability not working with card or only one ability possible
|
||||
if(ctr == 0 || ctr == 1)
|
||||
return false;
|
||||
else
|
||||
// several abilities working with card, menuId set
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO Simplify with only object !!!
|
||||
int ActionLayer::isReactingToClick(MTGCardInstance * card)
|
||||
{
|
||||
@@ -422,11 +445,13 @@ void ActionLayer::ButtonPressed(int controllerid, int controlid)
|
||||
ActionElement * currentAction = (ActionElement *) mObjects[controlid];
|
||||
currentAction->reactToTargetClick(menuObject);
|
||||
menuObject = 0;
|
||||
currentActionCard = NULL;
|
||||
}
|
||||
else if (controlid == kCancelMenuID)
|
||||
{
|
||||
observer->mLayers->stackLayer()->endOfInterruption(false);
|
||||
menuObject = 0;
|
||||
currentActionCard = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -462,6 +487,7 @@ void ActionLayer::ButtonPressedOnMultipleChoice(int choice)
|
||||
observer->mLayers->stackLayer()->endOfInterruption(false);
|
||||
}
|
||||
menuObject = 0;
|
||||
currentActionCard = NULL;
|
||||
}
|
||||
|
||||
ActionLayer::ActionLayer(GameObserver *observer)
|
||||
|
||||
@@ -216,8 +216,12 @@ Interruptible(observer, id), tc(tc), cost(_cost), payResult(payResult)
|
||||
_source->backupTargets.clear();
|
||||
if (tc)
|
||||
{
|
||||
for(size_t i = 0;i < tc->targets.size();i++)
|
||||
_source->backupTargets.push_back(tc->targets[i]);
|
||||
Targetable* t = NULL;
|
||||
for(size_t i = 0;i < tc->getNbTargets();i++)
|
||||
{
|
||||
t = tc->getNextTarget(t);
|
||||
_source->backupTargets.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
// fill information on how the card came into this zone. Right now the quickest way is to do it here, based on how the mana was paid...
|
||||
@@ -356,7 +360,7 @@ int Spell::getNbTargets()
|
||||
{
|
||||
if (!tc)
|
||||
return 0;
|
||||
return (int) (tc->targets.size());
|
||||
return (int) (tc->getNbTargets());
|
||||
}
|
||||
|
||||
void Spell::Render()
|
||||
|
||||
@@ -206,7 +206,6 @@ StatsWrapper * DeckManager::getExtendedDeckStats( DeckMetaData *selectedDeck, MT
|
||||
|
||||
|
||||
DeckManager * DeckManager::mInstance = NULL;
|
||||
bool DeckManager::instanceFlag = false;
|
||||
|
||||
void DeckManager::EndInstance()
|
||||
{
|
||||
@@ -215,10 +214,9 @@ void DeckManager::EndInstance()
|
||||
|
||||
DeckManager* DeckManager::GetInstance()
|
||||
{
|
||||
if (!instanceFlag)
|
||||
if (!mInstance)
|
||||
{
|
||||
mInstance = NEW DeckManager();
|
||||
instanceFlag = true;
|
||||
}
|
||||
|
||||
return mInstance;
|
||||
@@ -230,7 +228,7 @@ int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
|
||||
{
|
||||
if(player->deckFile != "")
|
||||
{
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) );
|
||||
DeckMetaData *meta = getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) );
|
||||
return meta->getDifficulty();
|
||||
}
|
||||
else
|
||||
@@ -239,23 +237,22 @@ int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player)
|
||||
|
||||
DeckManager::~DeckManager()
|
||||
{
|
||||
instanceFlag = false;
|
||||
map<string, StatsWrapper *>::iterator it;
|
||||
vector<DeckMetaData *>::iterator metaDataIter;
|
||||
|
||||
for (it = mInstance->aiDeckStatsMap.begin(); it != mInstance->aiDeckStatsMap.end(); it++){
|
||||
for (it = aiDeckStatsMap.begin(); it != aiDeckStatsMap.end(); it++){
|
||||
SAFE_DELETE(it->second);
|
||||
}
|
||||
for (it = mInstance->playerDeckStatsMap.begin(); it != mInstance->playerDeckStatsMap.end(); it++){
|
||||
for (it = playerDeckStatsMap.begin(); it != playerDeckStatsMap.end(); it++){
|
||||
SAFE_DELETE(it->second);
|
||||
}
|
||||
|
||||
for( metaDataIter = mInstance->aiDeckOrderList.begin(); metaDataIter != mInstance->aiDeckOrderList.end(); ++metaDataIter)
|
||||
for( metaDataIter = aiDeckOrderList.begin(); metaDataIter != aiDeckOrderList.end(); ++metaDataIter)
|
||||
{
|
||||
SAFE_DELETE( *metaDataIter );
|
||||
}
|
||||
|
||||
for( metaDataIter = mInstance->playerDeckOrderList.begin(); metaDataIter != mInstance->playerDeckOrderList.end(); ++metaDataIter)
|
||||
for( metaDataIter = playerDeckOrderList.begin(); metaDataIter != playerDeckOrderList.end(); ++metaDataIter)
|
||||
{
|
||||
SAFE_DELETE( *metaDataIter );
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ void DuelLayers::init(GameObserver* go)
|
||||
mCardSelector = NEW CardSelector(go, this);
|
||||
//1 Action Layer
|
||||
action = NEW ActionLayer(go);
|
||||
action->Add(NEW MTGGamePhase(go, action->getMaxId())); //Phases handler
|
||||
action->Add(phaseHandler = NEW MTGGamePhase(go, action->getMaxId())); //Phases handler
|
||||
action->Add(NEW OtherAbilitiesEventReceiver(go, -1)); //autohand, etc... handler
|
||||
//Other display elements
|
||||
action->Add(NEW HUDDisplay(go, -1));
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "AIPlayerBaka.h"
|
||||
#include "MTGRules.h"
|
||||
#include "Trash.h"
|
||||
#include "DeckManager.h"
|
||||
#ifdef TESTSUITE
|
||||
#include "TestSuiteAI.h"
|
||||
#endif
|
||||
@@ -69,6 +70,8 @@ GameObserver::~GameObserver()
|
||||
ExtraRules = 0;
|
||||
LOG("==GameObserver Destroyed==");
|
||||
SAFE_DELETE(mTrash);
|
||||
SAFE_DELETE(mDeckManager);
|
||||
|
||||
}
|
||||
|
||||
GameObserver::GameObserver(WResourceManager *output, JGE* input)
|
||||
@@ -99,6 +102,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input)
|
||||
mLoading = false;
|
||||
mLayers = NULL;
|
||||
mTrash = new Trash();
|
||||
mDeckManager = new DeckManager();
|
||||
}
|
||||
|
||||
int GameObserver::getCurrentGamePhase()
|
||||
@@ -475,6 +479,16 @@ bool GameObserver::operator==(const GameObserver& aGame)
|
||||
return (error == 0);
|
||||
}
|
||||
|
||||
void GameObserver::dumpAssert(bool val)
|
||||
{
|
||||
if(!val)
|
||||
{
|
||||
cerr << *this << endl;
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GameObserver::Update(float dt)
|
||||
{
|
||||
/*******************/
|
||||
@@ -489,7 +503,7 @@ void GameObserver::Update(float dt)
|
||||
oldGame = new GameObserver();
|
||||
oldGame->mRules = mRules;
|
||||
oldGame->load(stream.str());
|
||||
assert(*this == *oldGame);
|
||||
DumpAssert(*this == *oldGame);
|
||||
}
|
||||
#endif // ACTION_LOGGING_TESTING
|
||||
|
||||
@@ -526,7 +540,7 @@ void GameObserver::Update(float dt)
|
||||
//Handles game state based effects
|
||||
void GameObserver::gameStateBasedEffects()
|
||||
{
|
||||
if(getCurrentTargetChooser() && int(getCurrentTargetChooser()->targets.size()) == getCurrentTargetChooser()->maxtargets)
|
||||
if(getCurrentTargetChooser() && int(getCurrentTargetChooser()->getNbTargets()) == getCurrentTargetChooser()->maxtargets)
|
||||
getCurrentTargetChooser()->done = true;
|
||||
if (mLayers->stackLayer()->count(0, NOT_RESOLVED) != 0)
|
||||
return;
|
||||
@@ -993,7 +1007,7 @@ void GameObserver::ButtonPressed(PlayGuiObject * target)
|
||||
}
|
||||
else if (dynamic_cast<GuiPhaseBar*>(target))
|
||||
{
|
||||
MTGGamePhase::GetInstance()->NextGamePhase();
|
||||
mLayers->getPhaseHandler()->NextGamePhase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,9 +1056,20 @@ bool GameObserver::WaitForExtraPayment(MTGCardInstance * card)
|
||||
int GameObserver::cardClick(MTGCardInstance * card, MTGAbility *ability)
|
||||
{
|
||||
MTGGameZone* zone = card->currentZone;
|
||||
size_t index = card->currentZone->getIndex(card);
|
||||
size_t index = 0;
|
||||
if(zone)
|
||||
index = zone->getIndex(card);
|
||||
int choice;
|
||||
bool logChoice = mLayers->actionLayer()->getMenuIdFromCardAbility(card, ability, choice);
|
||||
int result = ability->reactToClick(card);
|
||||
logAction(card, zone, index, result);
|
||||
|
||||
if(logChoice) {
|
||||
stringstream stream;
|
||||
stream << "choice " << choice;
|
||||
logAction(currentActionPlayer, stream.str());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1089,7 +1114,7 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object)
|
||||
if (card == cardWaitingForTargets)
|
||||
{
|
||||
int _result = targetChooser->ForceTargetListReady();
|
||||
if(targetChooser->targetMin && int(targetChooser->targets.size()) < targetChooser->maxtargets)
|
||||
if(targetChooser->targetMin && int(targetChooser->getNbTargets()) < targetChooser->maxtargets)
|
||||
_result = 0;
|
||||
if (_result)
|
||||
{
|
||||
@@ -1548,7 +1573,7 @@ bool GameObserver::processActions(bool undo)
|
||||
size_t begin = s.find("[")+1;
|
||||
size_t size = s.find("]")-begin;
|
||||
size_t index = atoi(s.substr(begin, size).c_str());
|
||||
assert(index < zone->cards.size());
|
||||
dumpAssert(index < zone->cards.size());
|
||||
cardClick(zone->cards[index], zone->cards[index]);
|
||||
} else if (s.find("yes") != string::npos) {
|
||||
mLayers->stackLayer()->setIsInterrupting(p);
|
||||
@@ -1571,20 +1596,20 @@ bool GameObserver::processActions(bool undo)
|
||||
// that would allow the AI to use it as well.
|
||||
shuffleLibrary(p);
|
||||
} else {
|
||||
assert(0);
|
||||
dumpAssert(0);
|
||||
}
|
||||
|
||||
size_t nb = actionsList.size();
|
||||
|
||||
for (int i = 0; i<3; i++)
|
||||
for (int i = 0; i<5; i++)
|
||||
{
|
||||
// let's fake an update
|
||||
Update(counter);
|
||||
counter += 1.000f;
|
||||
}
|
||||
assert(actionsList.back() == *loadingite);
|
||||
assert(nb == actionsList.size());
|
||||
assert(cmdIndex == (actionsList.size()-1));
|
||||
dumpAssert(actionsList.back() == *loadingite);
|
||||
dumpAssert(nb == actionsList.size());
|
||||
dumpAssert(cmdIndex == (actionsList.size()-1));
|
||||
}
|
||||
|
||||
mLoading = false;
|
||||
@@ -1618,7 +1643,7 @@ void GameObserver::logAction(const string& s)
|
||||
if(mLoading)
|
||||
{
|
||||
string toCheck = *loadingite;
|
||||
assert(toCheck == s);
|
||||
dumpAssert(toCheck == s);
|
||||
}
|
||||
actionsList.push_back(s);
|
||||
};
|
||||
@@ -1645,8 +1670,10 @@ void GameObserver::createPlayer(const string& playerMode)
|
||||
{
|
||||
case Player::MODE_AI:
|
||||
AIPlayerFactory playerCreator;
|
||||
// FIXME: gonna break in AI vs AI mode
|
||||
players.push_back(playerCreator.createAIPlayer(this, MTGCollection(), players[0]));
|
||||
if(players.size())
|
||||
players.push_back(playerCreator.createAIPlayer(this, MTGCollection(), players[0]));
|
||||
else
|
||||
players.push_back(playerCreator.createAIPlayer(this, MTGCollection(), 0));
|
||||
break;
|
||||
case Player::MODE_HUMAN:
|
||||
players.push_back(new HumanPlayer(this, "", ""));
|
||||
|
||||
@@ -284,12 +284,28 @@ void GameStateDuel::ThreadProc(void* inParam)
|
||||
while(instance->mGamePhase != DUEL_STATE_BACK_TO_MAIN_MENU)
|
||||
{
|
||||
GameObserver observer;
|
||||
int oldTurn = -1;
|
||||
int oldPhase = -1;
|
||||
int stagnationCounter = -1;
|
||||
|
||||
observer.loadPlayer(0, PLAYER_TYPE_TESTSUITE);
|
||||
observer.loadPlayer(1, PLAYER_TYPE_TESTSUITE);
|
||||
observer.startGame(instance->mParent->gameType, instance->mParent->rules);
|
||||
|
||||
while(!observer.gameOver)
|
||||
while(!observer.gameOver) {
|
||||
if(observer.turn == oldTurn && observer.currentGamePhase == oldPhase) {
|
||||
stagnationCounter++;
|
||||
} else {
|
||||
stagnationCounter = 0;
|
||||
oldTurn = observer.turn;
|
||||
oldPhase = observer.currentGamePhase;
|
||||
}
|
||||
if(stagnationCounter >= 1000)
|
||||
{
|
||||
observer.dumpAssert(false);
|
||||
}
|
||||
observer.Update(counter++);
|
||||
}
|
||||
|
||||
instance->handleResults(&observer);
|
||||
}
|
||||
@@ -441,22 +457,25 @@ void GameStateDuel::Update(float dt)
|
||||
else
|
||||
#endif
|
||||
#ifdef AI_CHANGE_TESTING
|
||||
if (mParent->players[0] == PLAYER_TYPE_CPU_TEST && mParent->players[1] == PLAYER_TYPE_CPU_TEST)
|
||||
{
|
||||
handleResults(game);
|
||||
End();
|
||||
Start();
|
||||
}
|
||||
if(mWorkerThread.empty())
|
||||
{ // "I don't like to wait" mode
|
||||
size_t thread_count = 1;
|
||||
#ifdef QT_CONFIG
|
||||
thread_count = QThread::idealThreadCount();
|
||||
#endif
|
||||
for(size_t i = 0; i < (thread_count-1); i++)
|
||||
mWorkerThread.push_back(boost::thread(ThreadProc, this));
|
||||
}
|
||||
if (mParent->players[0] == PLAYER_TYPE_CPU_TEST && mParent->players[1] == PLAYER_TYPE_CPU_TEST)
|
||||
{
|
||||
handleResults(game);
|
||||
End();
|
||||
Start();
|
||||
}
|
||||
if(mWorkerThread.empty())
|
||||
{ // "I don't like to wait" mode
|
||||
size_t thread_count = 1;
|
||||
startTime = JGEGetTime();
|
||||
|
||||
#ifdef QT_CONFIG
|
||||
thread_count = QThread::idealThreadCount();
|
||||
#endif
|
||||
for(size_t i = 0; i < (thread_count-1); i++)
|
||||
mWorkerThread.push_back(boost::thread(ThreadProc, this));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU)
|
||||
{
|
||||
@@ -566,6 +585,7 @@ void GameStateDuel::Render()
|
||||
if (game && totalTestGames)
|
||||
{
|
||||
char buf[4096];
|
||||
int currentTime = JGEGetTime();
|
||||
|
||||
if (totalTestGames < 2.5 * totalAIDecks)
|
||||
{
|
||||
@@ -580,7 +600,8 @@ void GameStateDuel::Render()
|
||||
mFont->SetColor(ARGB(255,255,0,0));
|
||||
if (ratio > 0.52)
|
||||
mFont->SetColor(ARGB(255,0,255,0));
|
||||
sprintf(buf, "Victories Player 2/total Games: %i/%i", testPlayer2Victories, totalTestGames);
|
||||
sprintf(buf, "Victories Player 2/total Games: %i/%i - Games/second: %f",
|
||||
testPlayer2Victories, totalTestGames, (float)(1000*totalTestGames)/(currentTime - startTime));
|
||||
mFont->DrawString(buf,0,SCREEN_HEIGHT/2);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -303,6 +303,7 @@ bool remove_dead(ManaIcon* m)
|
||||
|
||||
void GuiMana::Update(float dt)
|
||||
{
|
||||
if(observer->getResourceManager())
|
||||
{
|
||||
float shift = 0;
|
||||
for (vector<ManaIcon*>::iterator it = manas.begin(); it != manas.end(); ++it)
|
||||
|
||||
@@ -2834,7 +2834,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int
|
||||
a->canBeInterrupted = false;
|
||||
}
|
||||
|
||||
bool moreThanOneTarget = spell && spell->tc && spell->tc->targets.size() > 1;
|
||||
bool moreThanOneTarget = spell && spell->tc && spell->tc->getNbTargets() > 1;
|
||||
|
||||
if(moreThanOneTarget)
|
||||
a->target = spell->getNextTarget();
|
||||
@@ -2850,7 +2850,7 @@ int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card, int
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!aMay || (aMay && a->target == spell->tc->targets[0]))
|
||||
if(!aMay || (aMay && a->target == spell->tc->getNextTarget(0)))
|
||||
{
|
||||
MTGAbility * mClone = a->clone();
|
||||
mClone->addToGame();
|
||||
@@ -3990,7 +3990,7 @@ int TargetAbility::resolve()
|
||||
t = tc->getNextTarget(t);
|
||||
ability->target = t;
|
||||
}
|
||||
tc->targets.clear();
|
||||
tc->initTargets();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@@ -4002,7 +4002,7 @@ int TargetAbility::resolve()
|
||||
t = tc->getNextTarget(t);
|
||||
ability->target = t;
|
||||
}
|
||||
tc->targets.clear();
|
||||
tc->initTargets();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include "MTGGamePhase.h"
|
||||
#include "GuiPhaseBar.h"
|
||||
|
||||
MTGGamePhase* MTGGamePhase::instance = 0;
|
||||
|
||||
MTGGamePhase::MTGGamePhase(GameObserver* g, int id) :
|
||||
ActionElement(id), observer(g)
|
||||
{
|
||||
@@ -12,7 +10,6 @@ MTGGamePhase::MTGGamePhase(GameObserver* g, int id) :
|
||||
currentState = -1;
|
||||
mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
|
||||
mFont->SetBase(0); // using 2nd font
|
||||
instance = this;
|
||||
}
|
||||
|
||||
void MTGGamePhase::Update(float dt)
|
||||
|
||||
@@ -268,7 +268,7 @@ bool Player::parseLine(const string& s)
|
||||
if ( opponent() )
|
||||
{
|
||||
bool isOpponentAI = opponent()->isAI() == 1;
|
||||
DeckMetaData *meta = DeckManager::GetInstance()->getDeckMetaDataByFilename( opponent()->deckFile, isOpponentAI);
|
||||
DeckMetaData *meta = observer->getDeckManager()->getDeckMetaDataByFilename( opponent()->deckFile, isOpponentAI);
|
||||
if ( meta && meta->getVictoryPercentage() >= 65)
|
||||
deckSetting = HARD;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ void Rules::addExtraRules(GameObserver* g)
|
||||
#endif //NETWORK_SUPPORT
|
||||
)//keep this out of momir and other game modes.
|
||||
{
|
||||
difficultyRating = DeckManager::getDifficultyRating(g->players[0], g->players[1]);
|
||||
difficultyRating = g->getDeckManager()->getDifficultyRating(g->players[0], g->players[1]);
|
||||
}
|
||||
|
||||
if (a)
|
||||
|
||||
Reference in New Issue
Block a user