- fixed memory leaks introduced in previous revision

- removed incorrect casts of MTGCardInstance into Spell objects.
- AI Test system now allows you to put decks in ai/bakaA and ai/bakaB instead of ai/baka. This allows to let AIPlayerBaka and AIPlayerBakaB play with specific decks
- Test suite speed improvement. Improved the card name cache. Test suite now runs in 850 seconds instead of 950 on my machine.
- minor code cleanup
This commit is contained in:
wagic.the.homebrew
2011-09-22 04:43:05 +00:00
parent 997b154d46
commit ee4c7e23bd
15 changed files with 163 additions and 85 deletions
+33 -33
View File
@@ -286,46 +286,44 @@ void AIPlayer::Render()
}
#ifdef AI_CHANGE_TESTING
AIPlayer * AIPlayerFactory::createAIPlayerTest(MTGAllCards * collection, Player * opponent, int deckid)
AIPlayer * AIPlayerFactory::createAIPlayerTest(MTGAllCards * collection, Player * opponent, string _folder)
{
char deckFile[512];
string avatarFilename; // default imagename
char deckFileSmall[512];
if (deckid == GameStateDuel::MENUITEM_EVIL_TWIN)
{ //Evil twin
sprintf(deckFile, "%s", opponent->deckFile.c_str());
DebugTrace("Evil Twin => " << opponent->deckFile);
avatarFilename = "avatar.jpg";
sprintf(deckFileSmall, "%s", "ai_baka_eviltwin");
}
else
string folder = _folder.size() ? _folder : "ai/baka/";
int deckid = 0;
//random deck
int nbdecks = 0;
int found = 1;
while (found && nbdecks < options[Options::AIDECKS_UNLOCKED].number)
{
if (!deckid)
found = 0;
char buffer[512];
sprintf(buffer, "%sdeck%i.txt", folder.c_str(), nbdecks + 1);
if (FileExists(buffer))
{
//random deck
int nbdecks = 0;
int found = 1;
while (found && nbdecks < options[Options::AIDECKS_UNLOCKED].number)
{
found = 0;
char buffer[512];
sprintf(buffer, "ai/baka/deck%i.txt", nbdecks + 1);
if (FileExists(buffer))
{
found = 1;
nbdecks++;
}
}
if (!nbdecks)
return NULL;
deckid = 1 + WRand() % (nbdecks);
found = 1;
nbdecks++;
}
sprintf(deckFile, "ai/baka/deck%i.txt", deckid);
DeckMetaData *aiMeta = DeckManager::GetInstance()->getDeckMetaDataByFilename( deckFile, true);
avatarFilename = aiMeta->getAvatarFilename();
sprintf(deckFileSmall, "ai_baka_deck%i", deckid);
}
if (!nbdecks)
{
if (_folder.size())
return createAIPlayerTest(collection, opponent, "");
return NULL;
}
deckid = 1 + WRand() % (nbdecks);
sprintf(deckFile, "%sdeck%i.txt", folder.c_str(), deckid);
DeckMetaData *aiMeta = DeckManager::GetInstance()->getDeckMetaDataByFilename( deckFile, true);
avatarFilename = aiMeta->getAvatarFilename();
sprintf(deckFileSmall, "ai_baka_deck%i", deckid);
int deckSetting = EASY;
if ( opponent )
@@ -337,7 +335,9 @@ AIPlayer * AIPlayerFactory::createAIPlayerTest(MTGAllCards * collection, Player
}
// AIPlayerBaka will delete MTGDeck when it's time
AIPlayerBakaB * baka = NEW AIPlayerBakaB(deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting));
AIPlayerBaka * baka = opponent ?
NEW AIPlayerBakaB(deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting)) :
NEW AIPlayerBaka(deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting));
baka->deckId = deckid;
return baka;
}
+2 -4
View File
@@ -1754,10 +1754,8 @@ int AIPlayerBaka::computeActions()
return 0;
}
Interruptible * action = g->mLayers->stackLayer()->getAt(-1);
Spell * spell = (Spell *) action;
Player * lastStackActionController = NULL;
if(spell && spell->type == ACTION_SPELL)
lastStackActionController = spell->source->controller();
Spell * spell = dynamic_cast<Spell *>(action);
Player * lastStackActionController = spell ? spell->source->controller() : NULL;
if (g->isInterrupting == this
&& this == currentP
//and i am the currentlyActivePlayer
+4 -4
View File
@@ -243,7 +243,7 @@ Interruptible(id), tc(tc), cost(_cost), payResult(payResult)
int Spell::computeX(MTGCardInstance * card)
{
ManaCost * c = NEW ManaCost(cost->Diff(card->getManaCost()));
ManaCost * c = cost->Diff(card->getManaCost());
int x = c->getCost(Constants::MTG_NB_COLORS);
delete c;
return x;
@@ -763,7 +763,7 @@ int ActionStack::count(int type, int state, int display)
return result;
}
int ActionStack::getActionElementFromCard(MTGCardInstance * card)
Interruptible * ActionStack::getActionElementFromCard(MTGCardInstance * card)
{
if(!card)
@@ -773,10 +773,10 @@ int ActionStack::getActionElementFromCard(MTGCardInstance * card)
Interruptible * current = (Interruptible *) mObjects[i];
if (current->source == card)
{
return i;
return current;
}
}
return 0;
return NULL;
}
Interruptible * ActionStack::getNext(Interruptible * previous, int type, int state, int display)
+5 -5
View File
@@ -416,7 +416,7 @@ ACounterShroud::~ACounterShroud()
SAFE_DELETE(counter);
}
//sheild a card from a certain type of counter.
//shield a card from a certain type of counter.
ACounterTracker::ACounterTracker(int id, MTGCardInstance * source, MTGCardInstance * target, string scounter) :
MTGAbility(id, source, target),scounter(scounter)
{
@@ -428,7 +428,7 @@ int ACounterTracker::addToGame()
MTGCardInstance * _target = (MTGCardInstance*)target;
Counter * counter = NULL;
AbilityFactory af;
counter = af.parseCounter(scounter, _target, (Spell*)source);
counter = af.parseCounter(scounter, _target, NULL); //(Spell*)source);
if (!counter)
{
return 0;
@@ -455,7 +455,7 @@ int ACounterTracker::destroy()
MTGCardInstance * _target = (MTGCardInstance*)target;
Counter * counter = NULL;
AbilityFactory af;
counter = af.parseCounter(scounter, _target, (Spell*)source);
counter = af.parseCounter(scounter, _target, NULL); //(Spell*)source);
if (!counter)
{
return 0;
@@ -665,12 +665,12 @@ int AAFizzler::resolve()
if(!target && source->target)
{
//ai is casting a spell from it's hand to fizzle.
target = stack->getAt(stack->getActionElementFromCard(source->target));
target = stack->getActionElementFromCard(source->target);
}
else if(target->typeAsTarget() == TARGET_CARD)
{
//ai targeted using an ability on a card to fizzle.
target = stack->getAt(stack->getActionElementFromCard((MTGCardInstance*)target));
target = stack->getActionElementFromCard((MTGCardInstance*)target);
}
Spell * sTarget = (Spell *) target;
MTGCardInstance* sCard = (MTGCardInstance*)sTarget->source;
+6 -1
View File
@@ -48,8 +48,13 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app)
GameObserver * g = GameObserver::GetInstance();
if (!g->turn)
return;
//no credits when the AI plays :)
if (p1->isAI())
return;
PlayerData * playerdata = NEW PlayerData(MTGCollection());
if (!p1->isAI() && p2->isAI() && p1 != g->gameOver)
if (p2->isAI() && p1 != g->gameOver)
{
gameLength = time(0) - g->startedAt;
value = 400;
+9 -3
View File
@@ -238,8 +238,8 @@ void GameStateDuel::loadPlayer(int playerId, int decknb, bool isAI, bool isNetwo
Player * opponent = NULL;
if (playerId == 1) opponent = mPlayers[0];
#ifdef AI_CHANGE_TESTING
if (mParent->players[1] == PLAYER_TYPE_CPU_TEST && playerId == 1)
mPlayers[playerId] = playerCreator.createAIPlayerTest(MTGCollection(), opponent);
if (mParent->players[0] == PLAYER_TYPE_CPU_TEST)
mPlayers[playerId] = playerCreator.createAIPlayerTest(MTGCollection(), opponent, playerId == 0 ? "ai/bakaA/" : "ai/bakaB/");
else
#endif
{
@@ -646,6 +646,12 @@ void GameStateDuel::Render()
{
r->ClearScreen(ARGB(255,0,0,0));
char buf[4096];
mFont->SetColor(ARGB(255,255,255,255));
int elapsedTime = (testSuite->endTime - testSuite->startTime);
sprintf(buf, "Time to run the tests: %is", elapsedTime/1000);
mFont->DrawString(buf,0,SCREEN_HEIGHT/2 - 20);
int nbFailed = testSuite->nbFailed;
int nbTests = testSuite->nbTests;
if (!nbFailed)
@@ -656,7 +662,7 @@ void GameStateDuel::Render()
{
sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests);
}
mFont->SetColor(ARGB(255,255,255,255));
mFont->DrawString(buf,0,SCREEN_HEIGHT/2);
nbFailed = testSuite->nbAIFailed;
nbTests = testSuite->nbAITests;
+51 -15
View File
@@ -590,39 +590,75 @@ MTGCard * MTGAllCards::_(int index)
return getCardById(ids[index]);
}
MTGCard * MTGAllCards::getCardByName(string name)
#ifdef TESTSUITE
void MTGAllCards::prefetchCardNameCache()
{
if (!name.size()) return NULL;
if (name[0] == '#') return NULL;
map<int, MTGCard *>::iterator it;
for (it = collection.begin(); it != collection.end(); it++)
{
MTGCard * c = it->second;
map<string, MTGCard * >::iterator cached = mtgCardByNameCache.end();
if (mtgCardByNameCache.size() > 0)
cached = mtgCardByNameCache.find(name);
//Name only
string cardName = c->data->name;
std::transform(cardName.begin(), cardName.end(), cardName.begin(), ::tolower);
mtgCardByNameCache[cardName] = c;
//Name + set
int setId = c->setId;
MTGSetInfo* setInfo = setlist.getInfo(setId);
if (setInfo)
{
string setName = setInfo->getName();
std::transform(setName.begin(), setName.end(), setName.begin(), ::tolower);
cardName = cardName + " (" + setName + ")";
mtgCardByNameCache[cardName] = c;
}
// id
std::stringstream out;
out << c->getMTGId();
mtgCardByNameCache[out.str()] = c;
}
}
#endif
MTGCard * MTGAllCards::getCardByName(string nameDescriptor)
{
if (!nameDescriptor.size()) return NULL;
if (nameDescriptor[0] == '#') return NULL;
std::transform(nameDescriptor.begin(), nameDescriptor.end(), nameDescriptor.begin(), ::tolower);
map<string, MTGCard * >::iterator cached = mtgCardByNameCache.find(nameDescriptor);
if (cached!= mtgCardByNameCache.end())
{
return cached->second;
}
int cardnb = atoi(name.c_str());
int cardnb = atoi(nameDescriptor.c_str());
if (cardnb)
{
MTGCard * result = getCardById(cardnb);
mtgCardByNameCache[name] = result;
mtgCardByNameCache[nameDescriptor] = result;
return result;
}
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
int setId = -1;
size_t found = name.find(" (");
size_t found = nameDescriptor.find(" (");
string name = nameDescriptor;
if (found != string::npos)
{
size_t end = name.find(")");
string setName = name.substr(found + 2, end - found - 2);
size_t end = nameDescriptor.find(")");
string setName = nameDescriptor.substr(found + 2, end - found - 2);
trim(setName);
name = name.substr(0, found);
name = nameDescriptor.substr(0, found);
trim(name);
setId = setlist[setName];
//Reconstruct a clean string "name (set)" for cache consistency
nameDescriptor = name + " (" + setName + ")";
}
map<int, MTGCard *>::iterator it;
for (it = collection.begin(); it != collection.end(); it++)
@@ -632,12 +668,12 @@ MTGCard * MTGAllCards::getCardByName(string name)
string cardName = c->data->name;
std::transform(cardName.begin(), cardName.end(), cardName.begin(), ::tolower);
if (cardName.compare(name) == 0) {
mtgCardByNameCache[name] = c;
mtgCardByNameCache[nameDescriptor] = c;
return c;
}
}
mtgCardByNameCache[name] = NULL;
mtgCardByNameCache[nameDescriptor] = NULL;
return NULL;
}
+12 -4
View File
@@ -180,11 +180,19 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
{
targetMin = true;//if upto: is not found, then we need to have a minimum of the amount....
}
WParsedInt * howmuch = NEW WParsedInt(howmany, NULL, card);
howmany.find("anyamount") != string::npos?maxtargets = TargetChooser::UNLITMITED_TARGETS:maxtargets = howmuch->getValue();
if(howmany.find("anyamount") != string::npos)
if (howmany.find("anyamount") != string::npos)
{
maxtargets = TargetChooser::UNLITMITED_TARGETS;
targetMin = false;
delete howmuch;
}
else
{
WParsedInt * howmuch = NEW WParsedInt(howmany, NULL, card);
maxtargets = howmuch->getValue();
delete howmuch;
}
s1 = s1.substr(end + 1);
}
}
+8 -3
View File
@@ -566,7 +566,8 @@ TestSuite::TestSuite(const char * filename)
seed = 0;
forceAbility = false;
aiMaxCalls = -1;
startTime = JGEGetTime();
endTime = startTime;
std::string contents;
if (JFileSystem::GetInstance()->readIntoString(filename, contents))
{
@@ -585,6 +586,11 @@ TestSuite::TestSuite(const char * filename)
}
}
//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"))
{
@@ -603,6 +609,7 @@ TestSuite::TestSuite(const char * filename)
int TestSuite::loadNext()
{
endTime = JGEGetTime();
summoningSickness = 0;
seed = 0;
aiMaxCalls = -1;
@@ -613,8 +620,6 @@ int TestSuite::loadNext()
return loadNext();
else
cout << "Starting test : " << files[currentfile - 1] << endl;
//load(files[currentfile].c_str());
//currentfile++;
return currentfile;
}