Files
wagic/projects/mtg/src/TestSuiteAI.cpp
Eduardo MG 8ca0eaaf40 Fixed _SCAVENGE_, other bug fixes, macros for _ETERNALIZE_
Typo in successful
Lux Cannon so that the AI can use the destroy ability
Throatseeker
Icingdeath, Frost Tyrant you don't "cast" the token
Insubordination
Infectious Curse
Igneous Elemental
Abu Jafar both?
_ETERNALIZE_
2023-04-29 23:54:41 -06:00

949 lines
28 KiB
C++

#include "PrecompiledHeader.h"
#include "TestSuiteAI.h"
#include "MTGAbility.h"
#include "MTGRules.h"
#include "ActionLayer.h"
#include "GuiCombat.h"
#include "Rules.h"
#include "GameObserver.h"
#include "GameStateShop.h"
#ifdef QT_CONFIG
#include <QThread>
#endif
using std::string;
#ifdef TESTSUITE
// number of frames between 2 actions.
// SLOW_TEST defines the speed of the very first test. It is intentionally slow so that when you debug one specific test, you get to see what happens on the screen
// FAST_TEST is for other tests, any value below 3 is known to have bad side effects.
// Higher values == slower. Lower values == faster
#define SLOW_TEST 40
#define FAST_TEST 6
// NULL is sent in place of a MTGDeck since there is no way to create a MTGDeck without a proper deck file.
// TestSuiteAI will be responsible for managing its own deck state.
TestSuiteAI::TestSuiteAI(TestSuiteGame *tsGame, int playerId) :
AIPlayerBaka(tsGame->observer, "testsuite", "testsuite", "baka.jpg", NULL)
{
SAFE_DELETE(game); //game might have been set in the parent with default values
game = tsGame->buildDeck(this, playerId);
game->setOwner(this);
suite = tsGame;
timer = 0;
playMode = MODE_TEST_SUITE;
this->deckName = "Test Suite AI";
this->comboHint = NULL;
}
MTGCardInstance * TestSuiteAI::getCard(string action)
{
int mtgid = Rules::getMTGId(action);
if (mtgid) return Rules::getCardByMTGId(observer, mtgid);
//This mostly handles tokens
std::transform(action.begin(), action.end(), action.begin(), ::tolower);
for (int i = 0; i < 2; i++)
{
Player * p = observer->players[i];
MTGGameZone * zones[] = { p->game->library, p->game->hand, p->game->inPlay, p->game->graveyard, p->game->commandzone, p->game->sideboard, p->game->removedFromGame };
for (int j = 0; j < 7; j++)
{
MTGGameZone * zone = zones[j];
for (int k = 0; k < zone->nb_cards; k++)
{
MTGCardInstance * card = zone->cards[k];
if (!card) return NULL;
string name = card->getLCName();
if (name.compare(action) == 0) return card;
}
}
}
DebugTrace("TESTUISTEAI: Can't find card:" << action.c_str());
return NULL;
}
Interruptible * TestSuiteGame::getActionByMTGId(int mtgid)
{
ActionStack * as = observer->mLayers->stackLayer();
Interruptible * action = NULL;
while ((action = as->getNext(action, 0, 0, 1)))
{
if (action->source && action->source->getMTGId() == mtgid)
{
return action;
}
}
return NULL;
}
int TestSuiteAI::displayStack()
{
if (playMode == MODE_AI) return 0;
return 1;
}
int TestSuiteAI::Act(float)
{
observer->setLoser(NULL); // Prevent draw rule from losing the game
//Last bits of initialization require to be done here, after the first "update" call of the game
if (suite->currentAction == 0)
{
for (int i = 0; i < 2; ++ i)
observer->players[i]->getManaPool()->copy(suite->initState.players[i]->getManaPool());
}
if (playMode == MODE_AI && suite->aiMaxCalls)
{
float static counter = 1.0f;
suite->aiMaxCalls--;
suite->timerLimit = SLOW_TEST; //TODO Remove this limitation when AI is not using a stupid timer anymore...
AIPlayerBaka::Act(counter++);//dt);
}
if (playMode == MODE_HUMAN)
{
observer->mLayers->CheckUserInput(0);
suite->currentAction++; //hack to avoid repeating the initialization of manapool
return 1;
}
timer += 1;
if (timer < suite->timerLimit) return 1;
timer = 0;
string action = suite->getNextAction();
// observer->mLayers->stackLayer()->Dump();
DebugTrace("TESTSUITE command: " << action);
if (observer->mLayers->stackLayer()->askIfWishesToInterrupt == this)
{
if (action.compare("no") != 0 && action.compare("yes") != 0)
{
observer->mLayers->stackLayer()->cancelInterruptOffer();
suite->currentAction--;
return 1;
}
}
if (action == "")
{
//end of game
suite->assertGame();
observer->setLoser(observer->players[0]);
DebugTrace("================================ END OF TEST =======================\n");
return 1;
}
if (action.compare("eot") == 0)
{
if (observer->getCurrentGamePhase() != MTG_PHASE_CLEANUP) suite->currentAction--;
observer->userRequestNextGamePhase();
}
else if (action.compare("human") == 0)
{
DebugTrace("TESTSUITE You have control");
playMode = MODE_HUMAN;
return 1;
}
else if (action.compare("ai") == 0)
{
DebugTrace("TESTSUITE Switching to AI");
playMode = MODE_AI;
return 1;
}
else if (action.compare("next") == 0 || action.find("goto") != string::npos)
{
if(action.find("goto ")!= string::npos)
{
size_t found = action.find("goto ");
string phase = action.substr(found + 5);
int phaseToGo = 0;
for (int i = 0; i < NB_MTG_PHASES; i++)
{
if (phase.find(Constants::MTGPhaseCodeNames[i]) != string::npos)
{
phaseToGo = i;
}
}
if(observer->getCurrentGamePhase() != phaseToGo)
suite->currentAction--;
else
{
return 1;
}
GuiCombat * gc = observer->mLayers->combatLayer();
if (ORDER == observer->combatStep || DAMAGE == observer->combatStep)
{
gc->clickOK();
}
else
{
observer->userRequestNextGamePhase();
}
}
else
{
GuiCombat * gc = observer->mLayers->combatLayer();
if (ORDER == observer->combatStep || DAMAGE == observer->combatStep)
gc->clickOK();
else
observer->userRequestNextGamePhase();
}
}
else if (action.compare("yes") == 0)
observer->mLayers->stackLayer()->setIsInterrupting(this);
else if (action.compare("endinterruption") == 0)
observer->mLayers->stackLayer()->endOfInterruption();
else if (action.compare("no") == 0)
{
if (observer->mLayers->stackLayer()->askIfWishesToInterrupt == this)
observer->mLayers->stackLayer()->cancelInterruptOffer();
}
else if (action.find("choice ") != string::npos)
{
DebugTrace("TESTSUITE choice !!!");
int choice = atoi(action.substr(action.find("choice ") + 7).c_str());
observer->mLayers->actionLayer()->doReactTo(choice);
}
else if (action.find(" -momir- ") != string::npos)
{
int start = action.find(" -momir- ");
int cardId = Rules::getMTGId(action.substr(start + 9).c_str());
int cardIdHand = Rules::getMTGId(action.substr(0, start).c_str());
MTGMomirRule * a = ((MTGMomirRule *) observer->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR));
a->reactToClick(Rules::getCardByMTGId(observer, cardIdHand), cardId);
observer->mLayers->actionLayer()->stuffHappened = 1;
}
else if (action.find("p1") != string::npos || action.find("p2") != string::npos)
{
Player * p = observer->players[1];
size_t start = action.find("p1");
if (start != string::npos) p = observer->players[0];
observer->cardClick(NULL, p);
}
else
{
int mtgid = Rules::getMTGId(action);
Interruptible * toInterrupt = NULL;
if (mtgid)
{
DebugTrace("TESTSUITE CARD ID:" << mtgid);
toInterrupt = suite->getActionByMTGId(mtgid);
}
if (toInterrupt)
{
observer->stackObjectClicked(toInterrupt);
return 1;
}
MTGCardInstance * card = getCard(action);
if (card)
{
DebugTrace("TESTSUITE Clicking ON: " << card->name);
card->currentZone->needShuffle = true; //mimic library shuffle
observer->cardClick(card, card);
observer->forceShuffleLibraries(); //mimic library shuffle
return 1;
}
}
return 0;
}
TestSuiteActions::TestSuiteActions()
{
nbitems = 0;
}
void TestSuiteActions::add(string s)
{
actions[nbitems] = s;
nbitems++;
}
TestSuiteState::TestSuiteState()
{
players.clear();
}
TestSuiteState::~TestSuiteState()
{
if(players.size())
{
if(players[0])
SAFE_DELETE(players[0]);
if(players[1])
SAFE_DELETE(players[1]);
}
};
void TestSuiteState::parsePlayerState(int playerId, string s)
{
players[playerId]->parseLine(s);
}
string TestSuiteGame::getNextAction()
{
currentAction++;
if (actions.nbitems && currentAction <= actions.nbitems)
{
return actions.actions[currentAction - 1];
}
return "";
}
void TestSuiteGame::handleResults(bool wasAI, int error)
{
testsuite->handleResults(wasAI, error);
};
void TestSuite::initGame(GameObserver* g)
{
observer = g;
//The first test runs slowly, the other ones run faster.
//This way a human can see what happens when testing a specific file,
// or go faster when it comes to the whole test suite.
//Warning, putting this value too low (< 3) will give unexpected results
if (!timerLimit)
{
timerLimit = SLOW_TEST;
}
else
{
timerLimit = FAST_TEST;
}
TestSuiteGame::initGame();
}
int TestSuiteGame::Log(const char * text)
{
ofstream file;
if (JFileSystem::GetInstance()->openForWrite(file, "test/results.html", ios_base::app))
{
file << text;
file << "\n";
file.close();
}
DebugTrace(text);
return 1;
}
void TestSuiteGame::assertGame()
{
mMutex.lock();
//compare the game state with the results
char result[4096];
sprintf(result, "<h3>%s</h3>", filename.c_str());
Log(result);
int error = 0;
bool wasAI = false;
if (observer->getCurrentGamePhase() != endState.phase)
{
sprintf(result, "<span class=\"error\">==phase problem. Expected [ %s ](%i), got [ %s ](%i)==</span><br />",
Constants::MTGPhaseNames[endState.phase].c_str(),endState.phase,
Constants::MTGPhaseNames[observer->getCurrentGamePhase()].c_str(), observer->getCurrentGamePhase());
Log(result);
error++;
}
for (int i = 0; i < 2; i++)
{
TestSuiteAI * p = (TestSuiteAI *) (observer->players[i]);
if (p->playMode == Player::MODE_AI) wasAI = true;
if (p->life != endState.players[i]->life)
{
sprintf(result, "<span class=\"error\">==life problem for player %i. Expected %i, got %i==</span><br />", i,
endState.players[i]->life, p->life);
Log(result);
error++;
}
if (p->poisonCount != endState.players[i]->poisonCount)
{
sprintf(result, "<span class=\"error\">==poison counter problem for player %i. Expected %i, got %i==</span><br />", i,
endState.players[i]->poisonCount, p->poisonCount);
Log(result);
error++;
} if (!p->getManaPool()->canAfford(endState.players[i]->getManaPool(),0))
{
sprintf(result, "<span class=\"error\">==Mana problem. Was expecting %i but got %i for player %i==</span><br />",
endState.players[i]->getManaPool()->getConvertedCost(), p->getManaPool()->getConvertedCost(), i);
Log(result);
error++;
}
if (!endState.players[i]->getManaPool()->canAfford(p->getManaPool(),0))
{
sprintf(result, "<span class=\"error\">==Mana problem. Was expecting %i but got %i for player %i==</span><br />",
endState.players[i]->getManaPool()->getConvertedCost(), p->getManaPool()->getConvertedCost(), i);
Log(result);
if ( endState.players[i]->getManaPool()->getConvertedCost() == p->getManaPool()->getConvertedCost())
{
sprintf(result, "<span class=\"error\">====(Apparently Mana Color issues since converted cost is the same)==</span><br />");
Log(result);
}
error++;
}
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->commandzone, p->game->sideboard, p->game->removedFromGame };
MTGGameZone * endstateZones[] = { endState.players[i]->game->graveyard,
endState.players[i]->game->library,
endState.players[i]->game->hand,
endState.players[i]->game->inPlay,
endState.players[i]->game->commandzone,
endState.players[i]->game->sideboard,
endState.players[i]->game->removedFromGame };
for (int j = 0; j < 7; j++)
{
MTGGameZone * zone = playerZones[j];
if (zone->nb_cards != endstateZones[j]->nb_cards)
{
sprintf(
result,
"<span class=\"error\">==Card number not the same in player %i's %s==, expected %i, got %i</span><br />",
i, zone->getName(), endstateZones[j]->nb_cards, zone->nb_cards);
Log(result);
error++;
}
for (size_t k = 0; k < (size_t)endstateZones[j]->nb_cards; k++)
{
MTGCardInstance* cardToCheck = (k<endstateZones[j]->cards.size())?endstateZones[j]->cards[k]:0;
if(cardToCheck)
{ // Can be NULL if used "*" in the testcase.
MTGCardInstance* card = Rules::getCardByMTGId(observer, cardToCheck->getId());
if (card != 0 && !zone->hasCard(card))
{
sprintf(result, "<span class=\"error\">==Card ID not the same. Didn't find %i</span><br />", card->getId());
Log(result);
error++;
}
}
}
}
}
handleResults(wasAI, error);
if(!error)
Log("<span class=\"success\">==Test Successful !==</span>");
else
Log("<span class=\"error\">==Test Failed !==</span>");
#ifdef CAPTURE_STDERR
if (error)
{
OutputCapturer::debugAndClear();
} else
{
OutputCapturer::clear();
}
#endif
mMutex.unlock();
}
void TestSuite::handleResults(bool wasAI, int error)
{
if (wasAI)
{
nbAITests++;
if (error)
{
nbAIFailed++;
}
}
else
{
nbTests++;
if (error)
{
nbFailed++;
}
}
}
TestSuite::~TestSuite()
{
mProcessing = false;
while(mWorkerThread.size())
{
mWorkerThread.back()->join();
SAFE_DELETE(mWorkerThread.back());
mWorkerThread.pop_back();
}
observer = 0;
}
TestSuite::TestSuite(const char * filename)
: TestSuiteGame(0), mRules(0), mProcessing(false)
{
timerLimit = 0;
testsuite = this;
std::string s;
nbfiles = 0;
currentfile = 0;
nbFailed = 0;
nbTests = 0;
nbAIFailed = 0;
nbAITests = 0;
int comment = 0;
seed = 0;
forceAbility = false;
aiMaxCalls = -1;
startTime = JGEGetTime();
endTime = startTime;
std::string contents;
if (JFileSystem::GetInstance()->readIntoString(filename, contents))
{
std::stringstream stream(contents);
while (std::getline(stream, s))
{
if (!s.size()) continue;
if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files
if (!s.size()) continue;
if (s[0] == '/' && s[1] == '*') comment = 1;
if (s[0] && s[0] != '#' && !comment)
{
files[nbfiles] = s;
nbfiles++;
}
if (s[0] == '*' && s[1] == '/') comment = 0;
}
}
//If more than 1 test, prefecth names to make the suite run faster
if (nbfiles > 1)
MTGCollection()->prefetchCardNameCache();
ofstream file2;
if (JFileSystem::GetInstance()->openForWrite(file2, "/test/results.html"))
{
file2 << "<html><head>";
#ifdef WIN32
file2 << "<meta http-equiv=\"refresh\" content=\"10\" >";
#endif
file2 << "<STYLE type='text/css'>";
file2 << ".success {color:green}\n";
file2 << ".error {color:red}\n";
file2 << "</STYLE></head><body>\n";
file2.close();
}
SAFE_DELETE(observer);
}
int TestSuite::loadNext()
{
endTime = JGEGetTime();
summoningSickness = 0;
seed = 0;
aiMaxCalls = -1;
if (!nbfiles) return 0;
filename = getNextFile();
if (filename == "") {
// we let GameStateDuel delete the latest gameObserver.
mProcessing = false;
observer = 0;
return 0;
}
if (filename == "+pregametests")
{
pregameTests();
return loadNext();
}
if(!mProcessing)
{ // "I don't like to wait" mode
mProcessing = true;
while(mWorkerThread.size())
{
mWorkerThread.back()->join();
SAFE_DELETE(mWorkerThread.back());
mWorkerThread.pop_back();
}
size_t thread_count = 1;
#ifdef QT_CONFIG
thread_count = QThread::idealThreadCount();
#elif defined(IOS)
thread_count = 6;
#else
thread_count = 4;
#endif
for(size_t i = 0; i < (thread_count-1); i++)
mWorkerThread.push_back(new boost::thread(ThreadProc, this));
}
cleanup();
if (!load())
return loadNext();
else
cout << "Starting test : " << files[currentfile - 1] << endl;
return currentfile;
}
void TestSuite::ThreadProc(void* inParam)
{
LOG("Entering TestSuite::ThreadProc");
TestSuite* instance = reinterpret_cast<TestSuite*>(inParam);
#ifdef CAPTURE_STDERR
OutputCapturer::debugAndClear();
#endif
if (instance)
{
string filename;
float counter = 1.0f;
while(instance->mProcessing && (filename = instance->getNextFile()) != "")
{
TestSuiteGame theGame(instance, filename);
if(theGame.isOK)
{
theGame.observer->loadTestSuitePlayer(0, &theGame);
theGame.observer->loadTestSuitePlayer(1, &theGame);
theGame.observer->startGame(theGame.gameType, /*instance->mRules*/Rules::getRulesByFilename("testsuite.txt"));
theGame.initGame();
while(!theGame.observer->didWin())
theGame.observer->Update(counter++);
}
}
}
LOG("Leaving TestSuite::ThreadProc");
}
int TestSuite::run()
{
mProcessing = true;
// loadNext();
ThreadProc(this);
return nbFailed + nbAIFailed;
}
void TestSuiteActions::cleanup()
{
nbitems = 0;
}
void TestSuiteState::cleanup(TestSuiteGame* tsGame)
{
for (size_t i = 0; i < players.size(); i++)
{
SAFE_DELETE(players[i]);
}
players.clear();
players.push_back(new TestSuiteAI(tsGame, 0));
players.push_back(new TestSuiteAI(tsGame, 1));
}
void TestSuite::cleanup()
{
currentAction = 0;
observer = 0;
initState.cleanup(this);
endState.cleanup(this);
actions.cleanup();
}
bool TestSuiteGame::load()
{
summoningSickness = 0;
forceAbility = false;
gameType = GAME_TYPE_CLASSIC;
std::string s;
int state = -1;
std::string contents;
if (JFileSystem::GetInstance()->readIntoString("test/"+filename, contents))
{
std::stringstream stream(contents);
while (std::getline(stream, s))
{
if (!s.size()) continue;
if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files
if (!s.size()) continue;
if (s[0] == '#') continue;
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
if (s.compare("summoningsickness") == 0)
{
summoningSickness = 1;
continue;
}
if (s.compare("forceability") == 0)
{
forceAbility = true;
continue;
}
if (s.find("seed ") == 0)
{
seed = atoi(s.substr(5).c_str());
continue;
}
if (s.find("aicalls ") == 0)
{
aiMaxCalls = atoi(s.substr(8).c_str());
continue;
}
if (s.compare("momir") == 0)
{
gameType = GAME_TYPE_MOMIR;
continue;
}
switch (state)
{
case -1:
if (s.compare("[init]") == 0) state++;
break;
case 0:
if (s.compare("[player1]") == 0)
{
state++;
}
else
{
initState.phase = PhaseRing::phaseStrToInt(s);
}
break;
case 1:
if (s.compare("[player2]") == 0)
{
state++;
}
else
{
initState.parsePlayerState(0, s);
}
break;
case 2:
if (s.compare("[do]") == 0)
{
state++;
}
else
{
initState.parsePlayerState(1, s);
}
break;
case 3:
if (s.compare("[assert]") == 0)
{
state++;
}
else
{
actions.add(s);
}
break;
case 4:
if (s.compare("[player1]") == 0)
{
state++;
}
else
{
endState.phase = PhaseRing::phaseStrToInt(s);
}
break;
case 5:
if (s.compare("[player2]") == 0)
{
state++;
}
else
{
endState.parsePlayerState(0, s);
}
break;
case 6:
if (s.compare("[end]") == 0)
{
state++;
}
else
{
endState.parsePlayerState(1, s);
}
break;
}
}
}
else
{
return false;
}
return true;
}
void TestSuite::pregameTests()
{
//Test Booster Generation
srand(1024);
char result[1024];
ShopBooster sb;
for (int i = 0; i < 5; i++)
{
nbTests++;
sprintf(result, "<h3>pregame/BoosterTest#%i</h3>", i);
Log(result);
if (!sb.unitTest()) nbFailed++;
}
}
boost::mutex TestSuiteGame::mMutex;
TestSuiteGame::~TestSuiteGame()
{
SAFE_DELETE(observer);
}
TestSuiteGame::TestSuiteGame(TestSuite* testsuite)
: summoningSickness(0), forceAbility(false), gameType(GAME_TYPE_CLASSIC), timerLimit(0),
currentAction(0), observer(0), testsuite(testsuite)
{
}
TestSuiteGame::TestSuiteGame(TestSuite* testsuite, string _filename)
: summoningSickness(0), forceAbility(false), gameType(GAME_TYPE_CLASSIC), timerLimit(FAST_TEST),
currentAction(0), observer(0), testsuite(testsuite)
{
filename = _filename;
observer = new GameObserver();
initState.cleanup(this);
endState.cleanup(this);
isOK = load();
}
void TestSuiteGame::ResetManapools()
{
for (int i = 0; i < 2; ++ i)
observer->players[i]->getManaPool()->copy(initState.players[i]->getManaPool());
}
void TestSuiteGame::initGame()
{
DebugTrace("TESTSUITE Init Game");
observer->phaseRing->goToPhase(initState.phase, observer->players[0], false);
observer->setCurrentGamePhase(initState.phase);
observer->resetStartupGame();
for (int i = 0; i < 2; i++)
{
AIPlayerBaka * p = (AIPlayerBaka *) (observer->players[i]);
p->forceBestAbilityUse = forceAbility;
p->life = initState.players[i]->life;
p->poisonCount = initState.players[i]->poisonCount;
stringstream stream;
initState.players[i]->getRandomGenerator()->saveLoadedRandValues(stream);
p->getRandomGenerator()->loadRandValues(stream.str());
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay, p->game->commandzone, p->game->sideboard, p->game->removedFromGame };
MTGGameZone * loadedPlayerZones[] = { initState.players[i]->game->graveyard,
initState.players[i]->game->library,
initState.players[i]->game->hand,
initState.players[i]->game->inPlay,
initState.players[i]->game->commandzone,
initState.players[i]->game->sideboard,
initState.players[i]->game->removedFromGame };
for (int j = 0; j < 7; j++)
{
MTGGameZone * zone = playerZones[j];
for (size_t k = 0; k < loadedPlayerZones[j]->cards.size(); k++)
{
MTGCardInstance * card = Rules::getCardByMTGId(observer, loadedPlayerZones[j]->cards[k]->getId());
if (card && zone != p->game->library)
{
if (zone == p->game->inPlay)
{
//MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack);
MTGCardInstance * copy = zone->owner->game->putInZone(card, p->game->library, p->game->stack);
Spell * spell = NEW Spell(observer, copy);
spell->resolve();
if (!summoningSickness && (size_t)p->game->inPlay->nb_cards > k) p->game->inPlay->cards[k]->summoningSickness = 0;
delete spell;
}
else
{
if (!p->game->library->hasCard(card))
{
LOG ("TESTUITE ERROR, CARD NOT FOUND IN LIBRARY\n");
}
//p->game->putInZone(card, p->game->library, zone);
zone->owner->game->putInZone(card, p->game->library, zone);
}
}
else
{
if (!card)
{
LOG ("TESTUITE ERROR, card is NULL\n");
}
}
}
zone->cardsSeenThisTurn.clear(); //don't consider those cards as having moved in this area during this turn
}
p->game->stack->cardsSeenThisTurn.clear(); //don't consider those cards as having moved in this area during this turn
}
DebugTrace("TESTUITE Init Game Done !");
}
MTGPlayerCards * TestSuiteGame::buildDeck(Player* player, int playerId)
{
int list[100];
int nbcards = 0;
MTGPlayerCards * deck = NULL;
if(initState.players.size() > (size_t)playerId)
{
MTGGameZone * loadedPlayerZones[] = { initState.players[playerId]->game->graveyard,
initState.players[playerId]->game->library,
initState.players[playerId]->game->hand,
initState.players[playerId]->game->removedFromGame,
initState.players[playerId]->game->commandzone,
initState.players[playerId]->game->sideboard,
initState.players[playerId]->game->inPlay };
for (int j = 0; j < 7; j++)
{
for (size_t k = 0; k < loadedPlayerZones[j]->cards.size(); k++)
{
int cardid = loadedPlayerZones[j]->cards[k]->getId();
list[nbcards] = cardid;
nbcards++;
}
}
deck = NEW MTGPlayerCards(player, list, nbcards);
}
else
{
deck = NEW MTGPlayerCards();
}
return deck;
}
#endif