817 lines
23 KiB
C++
817 lines
23 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"
|
|
|
|
using std::string;
|
|
|
|
#ifdef TESTSUITE
|
|
|
|
// 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(TestSuite * _suite, int playerId) :
|
|
AIPlayerBaka("testsuite", "testsuite", "baka.jpg", NULL)
|
|
{
|
|
this->game = _suite->buildDeck(playerId);
|
|
game->setOwner(this);
|
|
suite = _suite;
|
|
timer = 0;
|
|
playMode = MODE_TEST_SUITE;
|
|
this->deckName = "Test Suite AI";
|
|
}
|
|
|
|
MTGCardInstance * TestSuiteAI::getCard(string action)
|
|
{
|
|
int mtgid = Rules::getMTGId(action);
|
|
if (mtgid) return Rules::getCardByMTGId(mtgid);
|
|
|
|
//This mostly handles tokens
|
|
GameObserver * g = GameObserver::GetInstance();
|
|
std::transform(action.begin(), action.end(), action.begin(), ::tolower);
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
Player * p = g->players[i];
|
|
MTGGameZone * zones[] = { p->game->library, p->game->hand, p->game->inPlay, p->game->graveyard };
|
|
for (int j = 0; j < 4; 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 * TestSuite::getActionByMTGId(int mtgid)
|
|
{
|
|
ActionStack * as = GameObserver::GetInstance()->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 dt)
|
|
{
|
|
GameObserver * g = GameObserver::GetInstance();
|
|
g->gameOver = 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)
|
|
g->players[i]->getManaPool()->copy(suite->initState.playerData[i].manapool);
|
|
}
|
|
|
|
if (playMode == MODE_AI && suite->aiMaxCalls)
|
|
{
|
|
suite->aiMaxCalls--;
|
|
suite->timerLimit = 40; //TODO Remove this limitation when AI is not using a stupid timer anymore...
|
|
AIPlayerBaka::Act(dt);
|
|
}
|
|
if (playMode == MODE_HUMAN)
|
|
{
|
|
g->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();
|
|
g->mLayers->stackLayer()->Dump();
|
|
DebugTrace("TESTSUITE command: " << action);
|
|
|
|
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this)
|
|
{
|
|
if (action.compare("no") != 0 && action.compare("yes") != 0)
|
|
{
|
|
g->mLayers->stackLayer()->cancelInterruptOffer();
|
|
suite->currentAction--;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (action == "")
|
|
{
|
|
//end of game
|
|
suite->assertGame();
|
|
g->gameOver = g->players[0];
|
|
DebugTrace("================================ END OF TEST =======================\n");
|
|
return 1;
|
|
}
|
|
|
|
if (action.compare("eot") == 0)
|
|
{
|
|
if (g->getCurrentGamePhase() != Constants::MTG_PHASE_CLEANUP) suite->currentAction--;
|
|
g->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 < Constants::NB_MTG_PHASES; i++)
|
|
{
|
|
if (phase.find(Constants::MTGPhaseCodeNames[i]) != string::npos)
|
|
{
|
|
phaseToGo = i;
|
|
}
|
|
}
|
|
if(g->currentGamePhase != phaseToGo)
|
|
suite->currentAction--;
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
GuiCombat * gc = g->mLayers->combatLayer();
|
|
if (ORDER == g->combatStep || DAMAGE == g->combatStep)
|
|
{
|
|
gc->clickOK();
|
|
}
|
|
else
|
|
{
|
|
g->userRequestNextGamePhase();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GuiCombat * gc = g->mLayers->combatLayer();
|
|
if (ORDER == g->combatStep || DAMAGE == g->combatStep)
|
|
gc->clickOK();
|
|
else
|
|
g->userRequestNextGamePhase();
|
|
}
|
|
}
|
|
else if (action.compare("yes") == 0)
|
|
g->mLayers->stackLayer()->setIsInterrupting(this);
|
|
else if (action.compare("endinterruption") == 0)
|
|
g->mLayers->stackLayer()->endOfInterruption();
|
|
else if (action.compare("no") == 0)
|
|
{
|
|
if (g->mLayers->stackLayer()->askIfWishesToInterrupt == this) g->mLayers->stackLayer()->cancelInterruptOffer();
|
|
}
|
|
else if (action.find("choice ") != string::npos)
|
|
{
|
|
DebugTrace("TESTSUITE choice !!!");
|
|
int choice = atoi(action.substr(action.find("choice ") + 7).c_str());
|
|
g->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 *) g->mLayers->actionLayer()->getAbility(MTGAbility::MOMIR));
|
|
a->reactToClick(Rules::getCardByMTGId(cardIdHand), cardId);
|
|
g->mLayers->actionLayer()->stuffHappened = 1;
|
|
}
|
|
else if (action.find("p1") != string::npos || action.find("p2") != string::npos)
|
|
{
|
|
Player * p = g->players[1];
|
|
size_t start = action.find("p1");
|
|
if (start != string::npos) p = g->players[0];
|
|
g->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)
|
|
{
|
|
g->stackObjectClicked(toInterrupt);
|
|
return 1;
|
|
}
|
|
|
|
MTGCardInstance * card = getCard(action);
|
|
if (card)
|
|
{
|
|
DebugTrace("TESTSUITE Clicking ON: " << card->name);
|
|
card->currentZone->needShuffle = true; //mimic library shuffle
|
|
g->cardClick(card, card);
|
|
g->forceShuffleLibraries(); //mimic library shuffle
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
TestSuiteActions::TestSuiteActions()
|
|
{
|
|
nbitems = 0;
|
|
}
|
|
|
|
void TestSuiteActions::add(string s)
|
|
{
|
|
actions[nbitems] = s;
|
|
nbitems++;
|
|
}
|
|
|
|
TestSuitePlayerData::TestSuitePlayerData()
|
|
{
|
|
life = 20;
|
|
manapool = NEW ManaCost();
|
|
}
|
|
|
|
TestSuitePlayerData::~TestSuitePlayerData()
|
|
{
|
|
SAFE_DELETE(manapool);
|
|
}
|
|
|
|
TestSuitePlayerZone::TestSuitePlayerZone()
|
|
{
|
|
nbitems = 0;
|
|
}
|
|
|
|
void TestSuitePlayerZone::add(int cardId)
|
|
{
|
|
cards[nbitems] = cardId;
|
|
nbitems++;
|
|
}
|
|
|
|
TestSuiteState::TestSuiteState()
|
|
{
|
|
|
|
}
|
|
|
|
void TestSuiteState::parsePlayerState(int playerId, string s)
|
|
{
|
|
size_t limiter = s.find(":");
|
|
string areaS;
|
|
int area;
|
|
if (limiter != string::npos)
|
|
{
|
|
areaS = s.substr(0, limiter);
|
|
if (areaS.compare("graveyard") == 0)
|
|
{
|
|
area = 0;
|
|
}
|
|
else if (areaS.compare("library") == 0)
|
|
{
|
|
area = 1;
|
|
}
|
|
else if (areaS.compare("hand") == 0)
|
|
{
|
|
area = 2;
|
|
}
|
|
else if (areaS.compare("inplay") == 0 || areaS.compare("battlefield") == 0)
|
|
{
|
|
area = 3;
|
|
}
|
|
else if (areaS.compare("life") == 0)
|
|
{
|
|
playerData[playerId].life = atoi((s.substr(limiter + 1)).c_str());
|
|
return;
|
|
}
|
|
else if (areaS.compare("manapool") == 0)
|
|
{
|
|
SAFE_DELETE(playerData[playerId].manapool);
|
|
playerData[playerId].manapool = ManaCost::parseManaCost(s.substr(limiter + 1));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
return; // ERROR
|
|
}
|
|
s = s.substr(limiter + 1);
|
|
while (s.size())
|
|
{
|
|
unsigned int value;
|
|
limiter = s.find(",");
|
|
if (limiter != string::npos)
|
|
{
|
|
string ss = s.substr(0, limiter); // ss is needed because trim requires a non-const reference,
|
|
value = Rules::getMTGId(trim(ss)); // while in g++ functions cannot take non-const references from temporary values
|
|
s = s.substr(limiter + 1);
|
|
}
|
|
else
|
|
{
|
|
value = Rules::getMTGId(trim(s));
|
|
s = "";
|
|
}
|
|
if (value) playerData[playerId].zones[area].add(value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//ERROR
|
|
}
|
|
}
|
|
|
|
string TestSuite::getNextAction()
|
|
{
|
|
currentAction++;
|
|
if (actions.nbitems && currentAction <= actions.nbitems)
|
|
{
|
|
return actions.actions[currentAction - 1];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
MTGPlayerCards * TestSuite::buildDeck(int playerId)
|
|
{
|
|
int list[100];
|
|
int nbcards = 0;
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
for (int k = 0; k < initState.playerData[playerId].zones[j].nbitems; k++)
|
|
{
|
|
int cardid = initState.playerData[playerId].zones[j].cards[k];
|
|
list[nbcards] = cardid;
|
|
nbcards++;
|
|
}
|
|
}
|
|
MTGPlayerCards * deck = NEW MTGPlayerCards(list, nbcards);
|
|
return deck;
|
|
}
|
|
|
|
void TestSuite::initGame()
|
|
{
|
|
//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 = 40;
|
|
}
|
|
else
|
|
{
|
|
timerLimit = 3;
|
|
}
|
|
//Put the GameObserver in the initial state
|
|
GameObserver * g = GameObserver::GetInstance();
|
|
DebugTrace("TESTSUITE Init Game");
|
|
g->phaseRing->goToPhase(initState.phase, g->players[0]);
|
|
g->currentGamePhase = initState.phase;
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
AIPlayer * p = (AIPlayer *) (g->players[i]);
|
|
p->forceBestAbilityUse = forceAbility;
|
|
p->life = initState.playerData[i].life;
|
|
MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay };
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
MTGGameZone * zone = playerZones[j];
|
|
for (int k = 0; k < initState.playerData[i].zones[j].nbitems; k++)
|
|
{
|
|
MTGCardInstance * card = Rules::getCardByMTGId(initState.playerData[i].zones[j].cards[k]);
|
|
if (card && zone != p->game->library)
|
|
{
|
|
if (zone == p->game->inPlay)
|
|
{
|
|
MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack);
|
|
Spell * spell = NEW Spell(copy);
|
|
spell->resolve();
|
|
if (!summoningSickness && 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);
|
|
}
|
|
}
|
|
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 !");
|
|
}
|
|
int TestSuite::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;
|
|
|
|
}
|
|
int TestSuite::assertGame()
|
|
{
|
|
//compare the game state with the results
|
|
char result[4096];
|
|
sprintf(result, "<h3>%s</h3>", files[currentfile - 1].c_str());
|
|
Log(result);
|
|
|
|
int error = 0;
|
|
bool wasAI = false;
|
|
|
|
GameObserver * g = GameObserver::GetInstance();
|
|
if (g->currentGamePhase != endState.phase)
|
|
{
|
|
sprintf(result, "<span class=\"error\">==phase problem. Expected [ %s ](%i), got [ %s ](%i)==</span><br />",
|
|
Constants::MTGPhaseNames[endState.phase],endState.phase,
|
|
Constants::MTGPhaseNames[g->currentGamePhase], g->currentGamePhase);
|
|
Log(result);
|
|
error++;
|
|
}
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
TestSuiteAI * p = (TestSuiteAI *) (g->players[i]);
|
|
if (p->playMode == Player::MODE_AI) wasAI = true;
|
|
|
|
if (p->life != endState.playerData[i].life)
|
|
{
|
|
sprintf(result, "<span class=\"error\">==life problem for player %i. Expected %i, got %i==</span><br />", i,
|
|
endState.playerData[i].life, p->life);
|
|
Log(result);
|
|
error++;
|
|
}
|
|
if (!p->getManaPool()->canAfford(endState.playerData[i].manapool))
|
|
{
|
|
sprintf(result, "<span class=\"error\">==Mana problem. Was expecting %i but got %i for player %i==</span><br />",
|
|
endState.playerData[i].manapool->getConvertedCost(), p->getManaPool()->getConvertedCost(), i);
|
|
Log(result);
|
|
error++;
|
|
}
|
|
if (!endState.playerData[i].manapool->canAfford(p->getManaPool()))
|
|
{
|
|
sprintf(result, "<span class=\"error\">==Mana problem. Was expecting %i but got %i for player %i==</span><br />",
|
|
endState.playerData[i].manapool->getConvertedCost(), p->getManaPool()->getConvertedCost(), i);
|
|
Log(result);
|
|
|
|
if ( endState.playerData[i].manapool->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 };
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
MTGGameZone * zone = playerZones[j];
|
|
if (zone->nb_cards != endState.playerData[i].zones[j].nbitems)
|
|
{
|
|
sprintf(
|
|
result,
|
|
"<span class=\"error\">==Card number not the same in player %i's %s==, expected %i, got %i</span><br />",
|
|
i, zone->getName(), endState.playerData[i].zones[j].nbitems, zone->nb_cards);
|
|
Log(result);
|
|
error++;
|
|
}
|
|
for (int k = 0; k < endState.playerData[i].zones[j].nbitems; k++)
|
|
{
|
|
int cardid = endState.playerData[i].zones[j].cards[k];
|
|
if (cardid != -1)
|
|
{
|
|
MTGCardInstance * card = Rules::getCardByMTGId(cardid);
|
|
if (!card || !zone->hasCard(card))
|
|
{
|
|
sprintf(result, "<span class=\"error\">==Card ID not the same. Didn't find %i</span><br />", cardid);
|
|
Log(result);
|
|
error++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (wasAI)
|
|
{
|
|
nbAITests++;
|
|
if (error)
|
|
{
|
|
nbAIFailed++;
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nbTests++;
|
|
if (error)
|
|
{
|
|
nbFailed++;
|
|
return 0;
|
|
}
|
|
}
|
|
Log("<span class=\"success\">==Test Succesful !==</span>");
|
|
return 1;
|
|
}
|
|
|
|
TestSuite::TestSuite(const char * filename, MTGAllCards* _collection)
|
|
{
|
|
collection = _collection;
|
|
timerLimit = 0;
|
|
|
|
std::string s;
|
|
nbfiles = 0;
|
|
currentfile = 0;
|
|
nbFailed = 0;
|
|
nbTests = 0;
|
|
nbAIFailed = 0;
|
|
nbAITests = 0;
|
|
int comment = 0;
|
|
seed = 0;
|
|
forceAbility = false;
|
|
aiMaxCalls = -1;
|
|
|
|
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[0] == '/' && s[1] == '*') comment = 1;
|
|
if (s[0] && s[0] != '#' && !comment)
|
|
{
|
|
files[nbfiles] = s;
|
|
nbfiles++;
|
|
}
|
|
if (s[0] == '*' && s[1] == '/') comment = 0;
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
}
|
|
|
|
int TestSuite::loadNext()
|
|
{
|
|
summoningSickness = 0;
|
|
seed = 0;
|
|
aiMaxCalls = -1;
|
|
if (!nbfiles) return 0;
|
|
if (currentfile >= nbfiles) return 0;
|
|
currentfile++;
|
|
if (!load(files[currentfile - 1].c_str()))
|
|
return loadNext();
|
|
else
|
|
cout << "Starting test : " << files[currentfile - 1] << endl;
|
|
//load(files[currentfile].c_str());
|
|
//currentfile++;
|
|
return currentfile;
|
|
}
|
|
|
|
void TestSuiteActions::cleanup()
|
|
{
|
|
nbitems = 0;
|
|
}
|
|
|
|
void TestSuitePlayerZone::cleanup()
|
|
{
|
|
nbitems = 0;
|
|
}
|
|
|
|
void TestSuitePlayerData::cleanup()
|
|
{
|
|
if (manapool) delete manapool;
|
|
manapool = NULL;
|
|
manapool = NEW ManaCost();
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
zones[i].cleanup();
|
|
}
|
|
life = 20;
|
|
}
|
|
|
|
void TestSuiteState::cleanup()
|
|
{
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
playerData[i].cleanup();
|
|
}
|
|
}
|
|
|
|
void TestSuite::cleanup()
|
|
{
|
|
currentAction = 0;
|
|
initState.cleanup();
|
|
endState.cleanup();
|
|
actions.cleanup();
|
|
loadRandValues("");
|
|
}
|
|
|
|
int TestSuite::load(const char * _filename)
|
|
{
|
|
summoningSickness = 0;
|
|
forceAbility = false;
|
|
gameType = GAME_TYPE_CLASSIC;
|
|
char filename[4096];
|
|
sprintf(filename, "test/%s", _filename);
|
|
|
|
std::string s;
|
|
loadRandValues("");
|
|
|
|
int state = -1;
|
|
|
|
std::string contents;
|
|
if (JFileSystem::GetInstance()->readIntoString(filename, contents))
|
|
{
|
|
std::stringstream stream(contents);
|
|
|
|
cleanup();
|
|
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("rvalues:") == 0)
|
|
{
|
|
loadRandValues(s.substr(8).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 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
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++;
|
|
}
|
|
}
|
|
#endif
|