diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 4bcfc38d8..ddf47c7ed 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -73,14 +73,13 @@ beacon_of_unrest.txt belligerent_hatchling.txt benalish_knight.txt blessed_wine.txt -blinking_spirit.txt bloodfire_colossus.txt bloodhall_ooze.txt body_double.txt -boggart_arsonists.txt borderland_behemoth.txt bottle_gnomes.txt bottle_gnomes2.txt +boggart_arsonists.txt brass_man.txt cage_of_hands.txt Call_to_Heel_1.txt @@ -105,8 +104,8 @@ counterspell.txt counterspell2.txt counterspell3.txt counterspell4.txt -creature_bond.txt crimson_kobolds.txt +creature_bond.txt dauntless_escort.txt dauthi_embrace.txt death_ward.txt @@ -127,17 +126,16 @@ elvish_promenade.txt emblem_of_the_warmind.txt enervate.txt erg_raiders_i157.txt -farhaven_elf.txt farmstead.txt +flagstones.txt +farhaven_elf.txt fastbond.txt fastbond2.txt fault_line.txt fists_of_ironwood.txt -flagstones.txt flare.txt fledgling_imp.txt fledgling_imp2.txt -flowstone_hellion.txt flowstone_slide.txt foratog.txt force_of_nature.txt @@ -160,14 +158,12 @@ harpoon_sniper.txt hellfire.txt howl_from_beyond.txt howl_of_the_night_pack.txt -hyalopterous_lemure.txt hymn_of_rebirth.txt hypnotic_specter.txt icatian_priest.txt imaginary_pet.txt immaculate_magistrate.txt instill_energy_i166.txt -jodahs_avenger.txt jump.txt keldon_warlord.txt keldon_warlord2.txt @@ -239,26 +235,26 @@ seedcradle_witch.txt seismic_assault.txt seismic_spike_i191.txt selesnya_guildmage.txt +siege_gang_commander.txt shepherd_of_rot.txt shivan_hellkite.txt shock.txt shock2.txt -siege_gang_commander.txt slate_of_ancestry.txt sleeper_agent.txt slith_bloodletter.txt soulblast.txt -spark_elemental.txt sphinx_summoner.txt -spirit_link.txt spitting_earth.txt +spark_elemental.txt +spirit_link.txt spoils_of_evil.txt stasis.txt steelclad_serpent1.txt steelclad_serpent2.txt stillmoon_cavalier.txt -stonebrow2.txt stonebrow_i159.txt +stonebrow2.txt stronghold_discipline.txt sword_to_plowshares.txt symbiotic_wurm.txt @@ -271,9 +267,10 @@ titanic_ultimatum.txt torture.txt tranquil_domain.txt twitch.txt -unstable_mutation.txt unstable_mutation2.txt unwilling_recruit.txt +unstable_mutation.txt +unstable_mutation2.txt vampire_bats.txt vampiric_link.txt volcanic_eruption.txt @@ -292,3 +289,7 @@ zombify.txt ######################## momir/keldon_warlord.txt momir/overcost.txt +######################## +#AI Tests +######################## +ai/goblin_artillery.txt \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/ai/goblin_artillery.txt b/projects/mtg/bin/Res/test/ai/goblin_artillery.txt new file mode 100644 index 000000000..d840cde62 --- /dev/null +++ b/projects/mtg/bin/Res/test/ai/goblin_artillery.txt @@ -0,0 +1,22 @@ +#Bug:ai uses goblin artilery on own creature +# http://code.google.com/p/wagic/issues/detail?id=194 +FORCEABILITY +RValues:2 +AICALLS 10 +[INIT] +FIRSTMAIN +[PLAYER1] +inplay:,grizzly bears,goblin artillery +[PLAYER2] +inplay:raging goblin +[DO] +ai +ai +[ASSERT] +FIRSTMAIN +[PLAYER1] +life:17 +inplay:goblin artillery,grizzly bears +[PLAYER2] +graveyard:raging goblin +[END] \ No newline at end of file diff --git a/projects/mtg/include/AIPlayer.h b/projects/mtg/include/AIPlayer.h index 5d67f45d0..9a5956ba6 100644 --- a/projects/mtg/include/AIPlayer.h +++ b/projects/mtg/include/AIPlayer.h @@ -21,16 +21,20 @@ class AIStats; class AIAction{ protected: int efficiency; + static int currentId; + static MTGAbility * getCoreAbility(MTGAbility * a); public: MTGAbility * ability; Player * player; + int id; MTGCardInstance * click; MTGCardInstance * target; // TODO Improve - AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL):ability(a),click(c),target(t){player = NULL; efficiency = -1;}; - AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL):click(c),target(t){player = NULL; ability = NULL; efficiency = -1;}; + AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL):ability(a),click(c),target(t){player = NULL; efficiency = -1; id = currentId++;}; + AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL):click(c),target(t){player = NULL; ability = NULL; efficiency = -1; id = currentId++;}; AIAction(Player * p):player(p){ability = NULL; target = NULL; click = NULL; efficiency = -1;}; int getEfficiency(); int Act(); + }; @@ -39,7 +43,7 @@ class CmpAbilities { // compares Abilities efficiency bool operator()(AIAction * a1, AIAction * a2) const { int e1 = a1->getEfficiency(); int e2 = a2->getEfficiency(); - if (e1 == e2) return a1 > a2; //TODO improve + if (e1 == e2) return a1->id < a2->id; return (e1 > e2); } }; @@ -59,7 +63,9 @@ class AIPlayer: public Player{ int effectBadOrGood(MTGCardInstance * card, int mode = MODE_PUTINTOPLAY, TargetChooser * tc = NULL); int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0); AIStats * getStats(); + //Variables used by Test suite public: + bool forceBestAbilityUse; void End(){}; virtual int displayStack() {return 0;}; int receiveEvent(WEvent * event); diff --git a/projects/mtg/include/GameStateDuel.h b/projects/mtg/include/GameStateDuel.h index 1b658bdfc..89ab8a9e9 100644 --- a/projects/mtg/include/GameStateDuel.h +++ b/projects/mtg/include/GameStateDuel.h @@ -48,6 +48,7 @@ class GameStateDuel: public GameState, public JGuiListener virtual void End(); virtual void Update(float dt); virtual void Render(); + void initRand (unsigned seed = 0); }; diff --git a/projects/mtg/include/TestSuiteAI.h b/projects/mtg/include/TestSuiteAI.h index a90d7796d..3e3795ae0 100644 --- a/projects/mtg/include/TestSuiteAI.h +++ b/projects/mtg/include/TestSuiteAI.h @@ -51,8 +51,11 @@ class TestSuite{ public: MTGAllCards* collection; int summoningSickness; + bool forceAbility; int gameType; float timerLimit; + unsigned int seed; + int aiMaxCalls; int currentAction; TestSuiteState initState; TestSuiteState endState; @@ -60,7 +63,7 @@ class TestSuite{ string files[1024]; int nbfiles; int currentfile; - int nbFailed, nbTests; + int nbFailed, nbTests, nbAIFailed, nbAITests; int load(const char * filename); TestSuite(const char * filename,MTGAllCards* _collection); void initGame(); diff --git a/projects/mtg/include/utils.h b/projects/mtg/include/utils.h index 375b97c38..99904aec5 100644 --- a/projects/mtg/include/utils.h +++ b/projects/mtg/include/utils.h @@ -24,6 +24,7 @@ #include #include #include + #include #include #include @@ -34,8 +35,12 @@ using std::string; + + +int loadRandValues(string s); int filesize(const char * filename); int fileExists(const char * filename); +int WRand(); #ifdef LINUX void dumpStack(); diff --git a/projects/mtg/src/AIMomirPlayer.cpp b/projects/mtg/src/AIMomirPlayer.cpp index a42b63870..c31565743 100644 --- a/projects/mtg/src/AIMomirPlayer.cpp +++ b/projects/mtg/src/AIMomirPlayer.cpp @@ -40,7 +40,7 @@ int AIMomirPlayer::momir(){ int converted = potentialMana->getConvertedCost(); SAFE_DELETE(potentialMana); int efficiency = 100; - int chance = 1 + (rand() % 100); + int chance = 1 + (WRand() % 100); if (converted == 5 && myCreatures > opponentCreatures && game->hand->nb_cards<4) efficiency = 5 ; //Strategy: skip 5 drop if (converted == 7 && myCreatures > opponentCreatures && game->hand->nb_cards<2) efficiency = 50; //Strategy: 7 drops have bad upkeep costs and the AI doesn't handle those right now... if (converted > 8 ) converted = 8; diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index bbc22b863..bcbfedb28 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -8,6 +8,8 @@ const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"}; +int AIAction::currentId = 0; + int AIAction::Act(){ GameObserver * g = GameObserver::GetInstance(); if (player){ @@ -30,6 +32,7 @@ AIPlayer::AIPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Playe nextCardToPlay = NULL; stats = NULL; agressivity = 50; + forceBestAbilityUse = false; } AIPlayer::~AIPlayer(){ @@ -139,6 +142,18 @@ int AIPlayer::canHandleCost(MTGAbility * ability){ return 1; } +MTGAbility * AIAction::getCoreAbility(MTGAbility * a){ + GenericTargetAbility * gta = dynamic_cast(a); + if (gta) return getCoreAbility(gta->ability); + + GenericActivatedAbility * gaa = dynamic_cast(a); + if (gaa) return getCoreAbility(gaa->ability); + + if (MultiAbility * abi = dynamic_cast(a)) return getCoreAbility(abi->abilities[0]); + + return a; +} + int AIAction::getEfficiency(){ //TODO add multiplier according to what the player wants if (efficiency != -1) return efficiency; @@ -148,12 +163,7 @@ int AIAction::getEfficiency(){ Player * p = g->currentlyActing(); if (s->has(ability)) return 0; - MTGAbility * a = ability; - GenericTargetAbility * gta = dynamic_cast(a); - if (gta) a = gta->ability; - - GenericActivatedAbility * gaa = dynamic_cast(a); - if (gaa) a = gaa->ability; + MTGAbility * a = getCoreAbility(ability); if (!a){ OutputDebugString("FATAL: Ability is NULL in AIAction::getEfficiency()"); @@ -197,10 +207,10 @@ int AIAction::getEfficiency(){ if ((suggestion == BAKA_EFFECT_BAD && p==target->controller()) ||(suggestion == BAKA_EFFECT_GOOD && p!=target->controller())){ efficiency =0; }else{ - efficiency = rand() % 5; //Small percentage of chance for unknown abilities + efficiency = WRand() % 5; //Small percentage of chance for unknown abilities } }else{ - efficiency = rand() % 10; + efficiency = WRand() % 10; } break; } @@ -262,7 +272,8 @@ int AIPlayer::selectAbility(){ if (ranking.size()){ AIAction * a = ranking.begin()->first; - int chance = 1 + rand() % 100; + int chance = 1; + if (!forceBestAbilityUse) chance = 1 + WRand() % 100; if (getEfficiency(a) < chance){ a = NULL; }else{ @@ -354,7 +365,7 @@ int AIPlayer::chooseTarget(TargetChooser * tc){ } } if (nbtargets){ - int i = rand() % nbtargets; + int i = WRand() % nbtargets; int type = potentialTargets[i]->typeAsTarget(); switch(type){ case TARGET_CARD: @@ -575,7 +586,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op } } if (!nbdecks) return NULL; - deckid = 1 + rand() % (nbdecks); + deckid = 1 + WRand() % (nbdecks); } sprintf(deckFile, RESPATH"/ai/baka/deck%i.txt",deckid); sprintf(avatarFile, "avatar%i.jpg",deckid); @@ -628,7 +639,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty shouldPlayPercentage = shouldPlayPercentage - ((shouldPlayPercentage * 1.9) / (1 + xDiff)); } - if (rand() % 100 > shouldPlayPercentage) continue; + if (WRand() % 100 > shouldPlayPercentage) continue; nextCardToPlay = card; maxCost = currentCost; if(hasX) maxCost = pMana->getConvertedCost(); diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index eda8f399a..f1fce8770 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -38,7 +38,7 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app){ p1 = _p1; p2 = _p2; app = _app; - showMsg = (rand() % 5); + showMsg = (WRand() % 5); GameObserver * g = GameObserver::GetInstance(); if (!g->turn) return; if (!p1->isAI() && p2->isAI() && p1!= g->gameOver){ @@ -238,7 +238,7 @@ int Credits::isRandomDeckUnlocked(){ } int Credits::unlockRandomSet(){ - int setId = rand() % MtgSets::SetsList->nb_items; + int setId = WRand() % MtgSets::SetsList->nb_items; if (1 == options[Options::optionSet(setId)].number) return 0; diff --git a/projects/mtg/src/GameApp.cpp b/projects/mtg/src/GameApp.cpp index 3931c2cb0..f5a70e410 100644 --- a/projects/mtg/src/GameApp.cpp +++ b/projects/mtg/src/GameApp.cpp @@ -2,6 +2,7 @@ #include #include #if defined (WIN32) || defined (LINUX) +#include #else #include #endif @@ -65,6 +66,7 @@ GameApp::~GameApp() void GameApp::Create() { + srand(time(0)); // initialize random #if defined (WIN32) _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #elif not defined (LINUX) diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 75aacd2ea..3c38d5feb 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -14,6 +14,10 @@ #include "../include/TestSuiteAI.h" #endif +#if defined (WIN32) || defined (LINUX) +#include +#endif + enum ENUM_DUEL_STATE { DUEL_STATE_START, @@ -103,8 +107,8 @@ void GameStateDuel::Start() } void GameStateDuel::loadPlayerRandom(int playerId, int isAI, int mode){ - int color1 = 1 + rand() % 5; - int color2 = 1 + rand() % 5; + int color1 = 1 + WRand() % 5; + int color2 = 1 + WRand() % 5; int color0 = Constants::MTG_COLOR_ARTIFACT; if (mode == GAME_TYPE_RANDOM1) color2 = color1; int colors[]={color1,color2,color0}; @@ -178,9 +182,15 @@ void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI){ } } +void GameStateDuel::initRand(unsigned int seed){ + if (!seed) seed = time(0); + srand(seed); +} + #ifdef TESTSUITE void GameStateDuel::loadTestSuitePlayers(){ if (!testSuite) return; + initRand(testSuite->seed); for (int i = 0; i < 2; i++){ SAFE_DELETE(mPlayers[i]); SAFE_DELETE(deck[i]); @@ -407,8 +417,15 @@ void GameStateDuel::Render() }else{ sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests); } - mFont->DrawString(buf,0,SCREEN_HEIGHT/2); + nbFailed = testSuite->nbAIFailed; + nbTests = testSuite->nbAITests; + if (!nbFailed){ + sprintf(buf, "AI Tests: All %i tests successful!", nbTests); + }else{ + sprintf(buf, "AI Tests: %i tests out of %i FAILED!", nbFailed, nbTests); + } + mFont->DrawString(buf,0,SCREEN_HEIGHT/2+20); } #endif break; diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index 57481ac21..e3251c0df 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -290,7 +290,7 @@ void GameStateMenu::loadLangMenu(){ mDip = opendir("Res/lang"); } - while (mDit = readdir(mDip)){ + while ((mDit = readdir(mDip))){ string filename = "Res/lang/"; filename += mDit->d_name; std::ifstream file(filename.c_str()); diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index 166e69d70..4a4acbeb4 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -187,7 +187,6 @@ void MTGAllCards::init(){ tempCard = NULL; total_cards = 0; initCounters(); - srand(time(0)); // initialize random #if defined (_DEBUG) committed = true; #endif diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 3b29c62b7..cc211e14b 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -160,7 +160,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone void MTGPlayerCards::discardRandom(MTGGameZone * from){ if (!from->nb_cards) return; - int r = rand() % (from->nb_cards); + int r = WRand() % (from->nb_cards); putInZone(from->cards[r],from, graveyard); } @@ -263,10 +263,9 @@ void MTGGameZone::cleanupPhase(){ void MTGGameZone::shuffle(){ int i; for (i=0; i<(nb_cards); i++) { - int r = i + (rand() % (nb_cards-i)); // Random remaining position. + int r = i + (WRand() % (nb_cards-i)); // Random remaining position. MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp; } - //srand(time(0)); // initialize seed "randomly" TODO :improve } @@ -365,7 +364,7 @@ void MTGLibrary::shuffleTopToBottom(int nbcards){ if (nbcards>nb_cards) nbcards = nb_cards; MTGCardInstance * _cards[MTG_MAX_PLAYER_CARDS]; for (int i= nb_cards-nbcards; i<(nb_cards); i++) { - int r = i + (rand() % (nbcards-i)); // Random remaining position. + int r = i + (WRand() % (nbcards-i)); // Random remaining position. MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp; } for (int i= 0; i < nbcards; i++){ diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 7c6d3adaf..622d7ea06 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -304,7 +304,7 @@ int MTGMomirRule::genRandomCreatureId(int convertedCost){ i--; } if (!total_cards) return 0; - int start = (rand() % total_cards); + int start = (WRand() % total_cards); return pool[convertedCost][start]; } diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index 02a94c114..8fea2d3d4 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -68,7 +68,11 @@ int TestSuiteAI::displayStack(){ int TestSuiteAI::Act(float dt){ GameObserver * g = GameObserver::GetInstance(); g->gameOver = NULL; // Prevent draw rule from losing the game - if (playMode == MODE_AI) return AIPlayerBaka::Act(dt); + 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); return 1; @@ -95,7 +99,7 @@ int TestSuiteAI::Act(float dt){ } } - if (action == ""){ + if (action == ""){ //end of game suite->assertGame(); g->gameOver = g->players[0]; @@ -284,7 +288,8 @@ void TestSuite::initGame(){ g->phaseRing->goToPhase(initState.phase, g->players[0]); g->currentGamePhase = initState.phase; for (int i = 0; i < 2; i++){ - Player * p = g->players[i]; + AIPlayer * p = (AIPlayer *) (g->players[i]); + p->forceBestAbilityUse = forceAbility; p->life = initState.playerData[i].life; p->getManaPool()->copy(initState.playerData[i].manapool); MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay}; @@ -335,6 +340,8 @@ int TestSuite::assertGame(){ Log(result); int error = 0; + bool wasAI = false; + GameObserver * g = GameObserver::GetInstance(); if (g->currentGamePhase != endState.phase){ sprintf(result, "==phase problem. Expected %i, got %i==
",endState.phase, g->currentGamePhase); @@ -342,7 +349,9 @@ int TestSuite::assertGame(){ error++; } for (int i = 0; i < 2; i++){ - Player * p = g->players[i]; + TestSuiteAI * p = (TestSuiteAI *)(g->players[i]); + if (p->playMode == MODE_AI) wasAI = true; + if (p->life != endState.playerData[i].life){ sprintf(result, "==life problem for player %i. Expected %i, got %i==
",i,endState.playerData[i].life, p->life); Log(result); @@ -380,10 +389,18 @@ int TestSuite::assertGame(){ } } } - nbTests++; - if (error) { - nbFailed++; - return 0; + if (wasAI) { + nbAITests++; + if (error) { + nbAIFailed++; + return 0; + } + } else { + nbTests++; + if (error) { + nbFailed++; + return 0; + } } Log("==Test Succesful !=="); return 1; @@ -398,7 +415,12 @@ TestSuite::TestSuite(const char * filename,MTGAllCards* _collection){ currentfile = 0; nbFailed = 0; nbTests = 0; + nbAIFailed = 0; + nbAITests = 0; int comment = 0; + seed = 0; + forceAbility = false; + aiMaxCalls = -1; if(file){ while(std::getline(file,s)){ if (!s.size()) continue; @@ -430,6 +452,8 @@ TestSuite::TestSuite(const char * filename,MTGAllCards* _collection){ int TestSuite::loadNext(){ summoningSickness = 0; + seed = 0; + aiMaxCalls = -1; if (!nbfiles) return 0; if (currentfile >= nbfiles) return 0; currentfile++; @@ -489,15 +513,18 @@ void TestSuite::cleanup(){ 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, RESPATH"/test/%s", _filename); std::ifstream file(filename); std::string s; + loadRandValues(""); int state = -1; @@ -513,6 +540,22 @@ int TestSuite::load(const char * _filename){ 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; diff --git a/projects/mtg/src/TextScroller.cpp b/projects/mtg/src/TextScroller.cpp index 42b177865..17e8f70e9 100644 --- a/projects/mtg/src/TextScroller.cpp +++ b/projects/mtg/src/TextScroller.cpp @@ -1,5 +1,5 @@ #include "../include/TextScroller.h" - +#include "../include/utils.h" #include TextScroller::TextScroller(JLBFont * font, float x, float y, float width, float speed):JGuiObject(0){ diff --git a/projects/mtg/src/utils.cpp b/projects/mtg/src/utils.cpp index 4a35bfd43..e3af55aca 100644 --- a/projects/mtg/src/utils.cpp +++ b/projects/mtg/src/utils.cpp @@ -1,9 +1,37 @@ #include "../include/config.h" #include "../include/utils.h" +#include +using std::vector; +int randValuesCursor = -1; +vectorrandValues; +int loadRandValues(string s){ + randValues.clear(); + randValuesCursor = -1; + while (s.size()){ + unsigned int value; + size_t limiter = s.find(","); + if (limiter != string::npos){ + value = atoi(s.substr(0,limiter).c_str()); + s = s.substr(limiter+1); + }else{ + value = atoi(s.c_str()); + s = ""; + } + if (value) randValues.push_back(value); + } + if (randValues.size()) randValuesCursor = 0; + return 1; +} - +int WRand(){ + if (randValuesCursor == -1) return rand(); + int result = randValues[randValuesCursor]; + randValuesCursor++; + if ((size_t)randValuesCursor >= randValues.size()) randValuesCursor = 0; + return result; +} int filesize(const char * filename){ int file_size = 0; @@ -60,92 +88,92 @@ void dumpStack() } #endif - -/* RAM simple check functions source */ - - -// *** FUNCTIONS *** - -u32 ramAvailableLineareMax (void) -{ - u32 size, sizeblock; - u8 *ram; - - - // Init variables - size = 0; - sizeblock = RAM_BLOCK; - - // Check loop - while (sizeblock) - { - // Increment size - size += sizeblock; - - // Allocate ram - ram = (u8 *) malloc(size); - - // Check allocate - if (!(ram)) - { - // Restore old size - size -= sizeblock; - - // Size block / 2 - sizeblock >>= 1; - } - else - free(ram); - } - - return size; -} - -u32 ramAvailable (void) -{ - u8 **ram, **temp; - u32 size, count, x; - - - // Init variables - ram = NULL; - size = 0; - count = 0; - - // Check loop - for (;;) - { - // Check size entries - if (!(count % 10)) - { - // Allocate more entries if needed - temp = (u8**) realloc(ram,sizeof(u8 *) * (count + 10)); - if (!(temp)) break; - - // Update entries and size (size contains also size of entries) - ram = temp; - size += (sizeof(u8 *) * 10); - } - - // Find max lineare size available - x = ramAvailableLineareMax(); - if (!(x)) break; - - // Allocate ram - ram[count] = (u8 *) malloc(x); - if (!(ram[count])) break; - - // Update variables - size += x; - count++; - } - - // Free ram - if (ram) - { - for (x=0;x>= 1; + } + else + free(ram); + } + + return size; +} + +u32 ramAvailable (void) +{ + u8 **ram, **temp; + u32 size, count, x; + + + // Init variables + ram = NULL; + size = 0; + count = 0; + + // Check loop + for (;;) + { + // Check size entries + if (!(count % 10)) + { + // Allocate more entries if needed + temp = (u8**) realloc(ram,sizeof(u8 *) * (count + 10)); + if (!(temp)) break; + + // Update entries and size (size contains also size of entries) + ram = temp; + size += (sizeof(u8 *) * 10); + } + + // Find max lineare size available + x = ramAvailableLineareMax(); + if (!(x)) break; + + // Allocate ram + ram[count] = (u8 *) malloc(x); + if (!(ram[count])) break; + + // Update variables + size += x; + count++; + } + + // Free ram + if (ram) + { + for (x=0;x