Erwan
- Fix issue 194 - Attempt at doing basic AI tests
This commit is contained in:
@@ -73,14 +73,13 @@ beacon_of_unrest.txt
|
|||||||
belligerent_hatchling.txt
|
belligerent_hatchling.txt
|
||||||
benalish_knight.txt
|
benalish_knight.txt
|
||||||
blessed_wine.txt
|
blessed_wine.txt
|
||||||
blinking_spirit.txt
|
|
||||||
bloodfire_colossus.txt
|
bloodfire_colossus.txt
|
||||||
bloodhall_ooze.txt
|
bloodhall_ooze.txt
|
||||||
body_double.txt
|
body_double.txt
|
||||||
boggart_arsonists.txt
|
|
||||||
borderland_behemoth.txt
|
borderland_behemoth.txt
|
||||||
bottle_gnomes.txt
|
bottle_gnomes.txt
|
||||||
bottle_gnomes2.txt
|
bottle_gnomes2.txt
|
||||||
|
boggart_arsonists.txt
|
||||||
brass_man.txt
|
brass_man.txt
|
||||||
cage_of_hands.txt
|
cage_of_hands.txt
|
||||||
Call_to_Heel_1.txt
|
Call_to_Heel_1.txt
|
||||||
@@ -105,8 +104,8 @@ counterspell.txt
|
|||||||
counterspell2.txt
|
counterspell2.txt
|
||||||
counterspell3.txt
|
counterspell3.txt
|
||||||
counterspell4.txt
|
counterspell4.txt
|
||||||
creature_bond.txt
|
|
||||||
crimson_kobolds.txt
|
crimson_kobolds.txt
|
||||||
|
creature_bond.txt
|
||||||
dauntless_escort.txt
|
dauntless_escort.txt
|
||||||
dauthi_embrace.txt
|
dauthi_embrace.txt
|
||||||
death_ward.txt
|
death_ward.txt
|
||||||
@@ -127,17 +126,16 @@ elvish_promenade.txt
|
|||||||
emblem_of_the_warmind.txt
|
emblem_of_the_warmind.txt
|
||||||
enervate.txt
|
enervate.txt
|
||||||
erg_raiders_i157.txt
|
erg_raiders_i157.txt
|
||||||
farhaven_elf.txt
|
|
||||||
farmstead.txt
|
farmstead.txt
|
||||||
|
flagstones.txt
|
||||||
|
farhaven_elf.txt
|
||||||
fastbond.txt
|
fastbond.txt
|
||||||
fastbond2.txt
|
fastbond2.txt
|
||||||
fault_line.txt
|
fault_line.txt
|
||||||
fists_of_ironwood.txt
|
fists_of_ironwood.txt
|
||||||
flagstones.txt
|
|
||||||
flare.txt
|
flare.txt
|
||||||
fledgling_imp.txt
|
fledgling_imp.txt
|
||||||
fledgling_imp2.txt
|
fledgling_imp2.txt
|
||||||
flowstone_hellion.txt
|
|
||||||
flowstone_slide.txt
|
flowstone_slide.txt
|
||||||
foratog.txt
|
foratog.txt
|
||||||
force_of_nature.txt
|
force_of_nature.txt
|
||||||
@@ -160,14 +158,12 @@ harpoon_sniper.txt
|
|||||||
hellfire.txt
|
hellfire.txt
|
||||||
howl_from_beyond.txt
|
howl_from_beyond.txt
|
||||||
howl_of_the_night_pack.txt
|
howl_of_the_night_pack.txt
|
||||||
hyalopterous_lemure.txt
|
|
||||||
hymn_of_rebirth.txt
|
hymn_of_rebirth.txt
|
||||||
hypnotic_specter.txt
|
hypnotic_specter.txt
|
||||||
icatian_priest.txt
|
icatian_priest.txt
|
||||||
imaginary_pet.txt
|
imaginary_pet.txt
|
||||||
immaculate_magistrate.txt
|
immaculate_magistrate.txt
|
||||||
instill_energy_i166.txt
|
instill_energy_i166.txt
|
||||||
jodahs_avenger.txt
|
|
||||||
jump.txt
|
jump.txt
|
||||||
keldon_warlord.txt
|
keldon_warlord.txt
|
||||||
keldon_warlord2.txt
|
keldon_warlord2.txt
|
||||||
@@ -239,26 +235,26 @@ seedcradle_witch.txt
|
|||||||
seismic_assault.txt
|
seismic_assault.txt
|
||||||
seismic_spike_i191.txt
|
seismic_spike_i191.txt
|
||||||
selesnya_guildmage.txt
|
selesnya_guildmage.txt
|
||||||
|
siege_gang_commander.txt
|
||||||
shepherd_of_rot.txt
|
shepherd_of_rot.txt
|
||||||
shivan_hellkite.txt
|
shivan_hellkite.txt
|
||||||
shock.txt
|
shock.txt
|
||||||
shock2.txt
|
shock2.txt
|
||||||
siege_gang_commander.txt
|
|
||||||
slate_of_ancestry.txt
|
slate_of_ancestry.txt
|
||||||
sleeper_agent.txt
|
sleeper_agent.txt
|
||||||
slith_bloodletter.txt
|
slith_bloodletter.txt
|
||||||
soulblast.txt
|
soulblast.txt
|
||||||
spark_elemental.txt
|
|
||||||
sphinx_summoner.txt
|
sphinx_summoner.txt
|
||||||
spirit_link.txt
|
|
||||||
spitting_earth.txt
|
spitting_earth.txt
|
||||||
|
spark_elemental.txt
|
||||||
|
spirit_link.txt
|
||||||
spoils_of_evil.txt
|
spoils_of_evil.txt
|
||||||
stasis.txt
|
stasis.txt
|
||||||
steelclad_serpent1.txt
|
steelclad_serpent1.txt
|
||||||
steelclad_serpent2.txt
|
steelclad_serpent2.txt
|
||||||
stillmoon_cavalier.txt
|
stillmoon_cavalier.txt
|
||||||
stonebrow2.txt
|
|
||||||
stonebrow_i159.txt
|
stonebrow_i159.txt
|
||||||
|
stonebrow2.txt
|
||||||
stronghold_discipline.txt
|
stronghold_discipline.txt
|
||||||
sword_to_plowshares.txt
|
sword_to_plowshares.txt
|
||||||
symbiotic_wurm.txt
|
symbiotic_wurm.txt
|
||||||
@@ -271,9 +267,10 @@ titanic_ultimatum.txt
|
|||||||
torture.txt
|
torture.txt
|
||||||
tranquil_domain.txt
|
tranquil_domain.txt
|
||||||
twitch.txt
|
twitch.txt
|
||||||
unstable_mutation.txt
|
|
||||||
unstable_mutation2.txt
|
unstable_mutation2.txt
|
||||||
unwilling_recruit.txt
|
unwilling_recruit.txt
|
||||||
|
unstable_mutation.txt
|
||||||
|
unstable_mutation2.txt
|
||||||
vampire_bats.txt
|
vampire_bats.txt
|
||||||
vampiric_link.txt
|
vampiric_link.txt
|
||||||
volcanic_eruption.txt
|
volcanic_eruption.txt
|
||||||
@@ -292,3 +289,7 @@ zombify.txt
|
|||||||
########################
|
########################
|
||||||
momir/keldon_warlord.txt
|
momir/keldon_warlord.txt
|
||||||
momir/overcost.txt
|
momir/overcost.txt
|
||||||
|
########################
|
||||||
|
#AI Tests
|
||||||
|
########################
|
||||||
|
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]
|
||||||
@@ -21,17 +21,21 @@ class AIStats;
|
|||||||
class AIAction{
|
class AIAction{
|
||||||
protected:
|
protected:
|
||||||
int efficiency;
|
int efficiency;
|
||||||
|
static int currentId;
|
||||||
|
static MTGAbility * getCoreAbility(MTGAbility * a);
|
||||||
public:
|
public:
|
||||||
MTGAbility * ability;
|
MTGAbility * ability;
|
||||||
Player * player;
|
Player * player;
|
||||||
|
int id;
|
||||||
MTGCardInstance * click;
|
MTGCardInstance * click;
|
||||||
MTGCardInstance * target; // TODO Improve
|
MTGCardInstance * target; // TODO Improve
|
||||||
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL):ability(a),click(c),target(t){player = 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;};
|
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;};
|
AIAction(Player * p):player(p){ability = NULL; target = NULL; click = NULL; efficiency = -1;};
|
||||||
int getEfficiency();
|
int getEfficiency();
|
||||||
int Act();
|
int Act();
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CmpAbilities { // compares Abilities efficiency
|
class CmpAbilities { // compares Abilities efficiency
|
||||||
@@ -39,7 +43,7 @@ class CmpAbilities { // compares Abilities efficiency
|
|||||||
bool operator()(AIAction * a1, AIAction * a2) const {
|
bool operator()(AIAction * a1, AIAction * a2) const {
|
||||||
int e1 = a1->getEfficiency();
|
int e1 = a1->getEfficiency();
|
||||||
int e2 = a2->getEfficiency();
|
int e2 = a2->getEfficiency();
|
||||||
if (e1 == e2) return a1 > a2; //TODO improve
|
if (e1 == e2) return a1->id < a2->id;
|
||||||
return (e1 > e2);
|
return (e1 > e2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -59,7 +63,9 @@ class AIPlayer: public Player{
|
|||||||
int effectBadOrGood(MTGCardInstance * card, int mode = MODE_PUTINTOPLAY, TargetChooser * tc = NULL);
|
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);
|
int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0);
|
||||||
AIStats * getStats();
|
AIStats * getStats();
|
||||||
|
//Variables used by Test suite
|
||||||
public:
|
public:
|
||||||
|
bool forceBestAbilityUse;
|
||||||
void End(){};
|
void End(){};
|
||||||
virtual int displayStack() {return 0;};
|
virtual int displayStack() {return 0;};
|
||||||
int receiveEvent(WEvent * event);
|
int receiveEvent(WEvent * event);
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ class GameStateDuel: public GameState, public JGuiListener
|
|||||||
virtual void End();
|
virtual void End();
|
||||||
virtual void Update(float dt);
|
virtual void Update(float dt);
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
|
void initRand (unsigned seed = 0);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,11 @@ class TestSuite{
|
|||||||
public:
|
public:
|
||||||
MTGAllCards* collection;
|
MTGAllCards* collection;
|
||||||
int summoningSickness;
|
int summoningSickness;
|
||||||
|
bool forceAbility;
|
||||||
int gameType;
|
int gameType;
|
||||||
float timerLimit;
|
float timerLimit;
|
||||||
|
unsigned int seed;
|
||||||
|
int aiMaxCalls;
|
||||||
int currentAction;
|
int currentAction;
|
||||||
TestSuiteState initState;
|
TestSuiteState initState;
|
||||||
TestSuiteState endState;
|
TestSuiteState endState;
|
||||||
@@ -60,7 +63,7 @@ class TestSuite{
|
|||||||
string files[1024];
|
string files[1024];
|
||||||
int nbfiles;
|
int nbfiles;
|
||||||
int currentfile;
|
int currentfile;
|
||||||
int nbFailed, nbTests;
|
int nbFailed, nbTests, nbAIFailed, nbAITests;
|
||||||
int load(const char * filename);
|
int load(const char * filename);
|
||||||
TestSuite(const char * filename,MTGAllCards* _collection);
|
TestSuite(const char * filename,MTGAllCards* _collection);
|
||||||
void initGame();
|
void initGame();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -34,8 +35,12 @@ using std::string;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int loadRandValues(string s);
|
||||||
int filesize(const char * filename);
|
int filesize(const char * filename);
|
||||||
int fileExists(const char * filename);
|
int fileExists(const char * filename);
|
||||||
|
int WRand();
|
||||||
|
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
void dumpStack();
|
void dumpStack();
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ int AIMomirPlayer::momir(){
|
|||||||
int converted = potentialMana->getConvertedCost();
|
int converted = potentialMana->getConvertedCost();
|
||||||
SAFE_DELETE(potentialMana);
|
SAFE_DELETE(potentialMana);
|
||||||
int efficiency = 100;
|
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 == 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 == 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;
|
if (converted > 8 ) converted = 8;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"};
|
const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"};
|
||||||
|
|
||||||
|
int AIAction::currentId = 0;
|
||||||
|
|
||||||
int AIAction::Act(){
|
int AIAction::Act(){
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
if (player){
|
if (player){
|
||||||
@@ -30,6 +32,7 @@ AIPlayer::AIPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Playe
|
|||||||
nextCardToPlay = NULL;
|
nextCardToPlay = NULL;
|
||||||
stats = NULL;
|
stats = NULL;
|
||||||
agressivity = 50;
|
agressivity = 50;
|
||||||
|
forceBestAbilityUse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AIPlayer::~AIPlayer(){
|
AIPlayer::~AIPlayer(){
|
||||||
@@ -139,6 +142,18 @@ int AIPlayer::canHandleCost(MTGAbility * ability){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTGAbility * AIAction::getCoreAbility(MTGAbility * a){
|
||||||
|
GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*>(a);
|
||||||
|
if (gta) return getCoreAbility(gta->ability);
|
||||||
|
|
||||||
|
GenericActivatedAbility * gaa = dynamic_cast<GenericActivatedAbility*>(a);
|
||||||
|
if (gaa) return getCoreAbility(gaa->ability);
|
||||||
|
|
||||||
|
if (MultiAbility * abi = dynamic_cast<MultiAbility*>(a)) return getCoreAbility(abi->abilities[0]);
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
int AIAction::getEfficiency(){
|
int AIAction::getEfficiency(){
|
||||||
//TODO add multiplier according to what the player wants
|
//TODO add multiplier according to what the player wants
|
||||||
if (efficiency != -1) return efficiency;
|
if (efficiency != -1) return efficiency;
|
||||||
@@ -148,12 +163,7 @@ int AIAction::getEfficiency(){
|
|||||||
Player * p = g->currentlyActing();
|
Player * p = g->currentlyActing();
|
||||||
if (s->has(ability)) return 0;
|
if (s->has(ability)) return 0;
|
||||||
|
|
||||||
MTGAbility * a = ability;
|
MTGAbility * a = getCoreAbility(ability);
|
||||||
GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*>(a);
|
|
||||||
if (gta) a = gta->ability;
|
|
||||||
|
|
||||||
GenericActivatedAbility * gaa = dynamic_cast<GenericActivatedAbility*>(a);
|
|
||||||
if (gaa) a = gaa->ability;
|
|
||||||
|
|
||||||
if (!a){
|
if (!a){
|
||||||
OutputDebugString("FATAL: Ability is NULL in AIAction::getEfficiency()");
|
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())){
|
if ((suggestion == BAKA_EFFECT_BAD && p==target->controller()) ||(suggestion == BAKA_EFFECT_GOOD && p!=target->controller())){
|
||||||
efficiency =0;
|
efficiency =0;
|
||||||
}else{
|
}else{
|
||||||
efficiency = rand() % 5; //Small percentage of chance for unknown abilities
|
efficiency = WRand() % 5; //Small percentage of chance for unknown abilities
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
efficiency = rand() % 10;
|
efficiency = WRand() % 10;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -262,7 +272,8 @@ int AIPlayer::selectAbility(){
|
|||||||
|
|
||||||
if (ranking.size()){
|
if (ranking.size()){
|
||||||
AIAction * a = ranking.begin()->first;
|
AIAction * a = ranking.begin()->first;
|
||||||
int chance = 1 + rand() % 100;
|
int chance = 1;
|
||||||
|
if (!forceBestAbilityUse) chance = 1 + WRand() % 100;
|
||||||
if (getEfficiency(a) < chance){
|
if (getEfficiency(a) < chance){
|
||||||
a = NULL;
|
a = NULL;
|
||||||
}else{
|
}else{
|
||||||
@@ -354,7 +365,7 @@ int AIPlayer::chooseTarget(TargetChooser * tc){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nbtargets){
|
if (nbtargets){
|
||||||
int i = rand() % nbtargets;
|
int i = WRand() % nbtargets;
|
||||||
int type = potentialTargets[i]->typeAsTarget();
|
int type = potentialTargets[i]->typeAsTarget();
|
||||||
switch(type){
|
switch(type){
|
||||||
case TARGET_CARD:
|
case TARGET_CARD:
|
||||||
@@ -575,7 +586,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!nbdecks) return NULL;
|
if (!nbdecks) return NULL;
|
||||||
deckid = 1 + rand() % (nbdecks);
|
deckid = 1 + WRand() % (nbdecks);
|
||||||
}
|
}
|
||||||
sprintf(deckFile, RESPATH"/ai/baka/deck%i.txt",deckid);
|
sprintf(deckFile, RESPATH"/ai/baka/deck%i.txt",deckid);
|
||||||
sprintf(avatarFile, "avatar%i.jpg",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));
|
shouldPlayPercentage = shouldPlayPercentage - ((shouldPlayPercentage * 1.9) / (1 + xDiff));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rand() % 100 > shouldPlayPercentage) continue;
|
if (WRand() % 100 > shouldPlayPercentage) continue;
|
||||||
nextCardToPlay = card;
|
nextCardToPlay = card;
|
||||||
maxCost = currentCost;
|
maxCost = currentCost;
|
||||||
if(hasX) maxCost = pMana->getConvertedCost();
|
if(hasX) maxCost = pMana->getConvertedCost();
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app){
|
|||||||
p1 = _p1;
|
p1 = _p1;
|
||||||
p2 = _p2;
|
p2 = _p2;
|
||||||
app = _app;
|
app = _app;
|
||||||
showMsg = (rand() % 5);
|
showMsg = (WRand() % 5);
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
if (!g->turn) return;
|
if (!g->turn) return;
|
||||||
if (!p1->isAI() && p2->isAI() && p1!= g->gameOver){
|
if (!p1->isAI() && p2->isAI() && p1!= g->gameOver){
|
||||||
@@ -238,7 +238,7 @@ int Credits::isRandomDeckUnlocked(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Credits::unlockRandomSet(){
|
int Credits::unlockRandomSet(){
|
||||||
int setId = rand() % MtgSets::SetsList->nb_items;
|
int setId = WRand() % MtgSets::SetsList->nb_items;
|
||||||
|
|
||||||
if (1 == options[Options::optionSet(setId)].number)
|
if (1 == options[Options::optionSet(setId)].number)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <JGE.h>
|
#include <JGE.h>
|
||||||
#include <JRenderer.h>
|
#include <JRenderer.h>
|
||||||
#if defined (WIN32) || defined (LINUX)
|
#if defined (WIN32) || defined (LINUX)
|
||||||
|
#include <time.h>
|
||||||
#else
|
#else
|
||||||
#include <pspfpu.h>
|
#include <pspfpu.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -65,6 +66,7 @@ GameApp::~GameApp()
|
|||||||
|
|
||||||
void GameApp::Create()
|
void GameApp::Create()
|
||||||
{
|
{
|
||||||
|
srand(time(0)); // initialize random
|
||||||
#if defined (WIN32)
|
#if defined (WIN32)
|
||||||
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
||||||
#elif not defined (LINUX)
|
#elif not defined (LINUX)
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
#include "../include/TestSuiteAI.h"
|
#include "../include/TestSuiteAI.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined (WIN32) || defined (LINUX)
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
enum ENUM_DUEL_STATE
|
enum ENUM_DUEL_STATE
|
||||||
{
|
{
|
||||||
DUEL_STATE_START,
|
DUEL_STATE_START,
|
||||||
@@ -103,8 +107,8 @@ void GameStateDuel::Start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameStateDuel::loadPlayerRandom(int playerId, int isAI, int mode){
|
void GameStateDuel::loadPlayerRandom(int playerId, int isAI, int mode){
|
||||||
int color1 = 1 + rand() % 5;
|
int color1 = 1 + WRand() % 5;
|
||||||
int color2 = 1 + rand() % 5;
|
int color2 = 1 + WRand() % 5;
|
||||||
int color0 = Constants::MTG_COLOR_ARTIFACT;
|
int color0 = Constants::MTG_COLOR_ARTIFACT;
|
||||||
if (mode == GAME_TYPE_RANDOM1) color2 = color1;
|
if (mode == GAME_TYPE_RANDOM1) color2 = color1;
|
||||||
int colors[]={color1,color2,color0};
|
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
|
#ifdef TESTSUITE
|
||||||
void GameStateDuel::loadTestSuitePlayers(){
|
void GameStateDuel::loadTestSuitePlayers(){
|
||||||
if (!testSuite) return;
|
if (!testSuite) return;
|
||||||
|
initRand(testSuite->seed);
|
||||||
for (int i = 0; i < 2; i++){
|
for (int i = 0; i < 2; i++){
|
||||||
SAFE_DELETE(mPlayers[i]);
|
SAFE_DELETE(mPlayers[i]);
|
||||||
SAFE_DELETE(deck[i]);
|
SAFE_DELETE(deck[i]);
|
||||||
@@ -407,8 +417,15 @@ void GameStateDuel::Render()
|
|||||||
}else{
|
}else{
|
||||||
sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests);
|
sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests);
|
||||||
}
|
}
|
||||||
|
|
||||||
mFont->DrawString(buf,0,SCREEN_HEIGHT/2);
|
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
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ void GameStateMenu::loadLangMenu(){
|
|||||||
mDip = opendir("Res/lang");
|
mDip = opendir("Res/lang");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mDit = readdir(mDip)){
|
while ((mDit = readdir(mDip))){
|
||||||
string filename = "Res/lang/";
|
string filename = "Res/lang/";
|
||||||
filename += mDit->d_name;
|
filename += mDit->d_name;
|
||||||
std::ifstream file(filename.c_str());
|
std::ifstream file(filename.c_str());
|
||||||
|
|||||||
@@ -187,7 +187,6 @@ void MTGAllCards::init(){
|
|||||||
tempCard = NULL;
|
tempCard = NULL;
|
||||||
total_cards = 0;
|
total_cards = 0;
|
||||||
initCounters();
|
initCounters();
|
||||||
srand(time(0)); // initialize random
|
|
||||||
#if defined (_DEBUG)
|
#if defined (_DEBUG)
|
||||||
committed = true;
|
committed = true;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
|
|||||||
void MTGPlayerCards::discardRandom(MTGGameZone * from){
|
void MTGPlayerCards::discardRandom(MTGGameZone * from){
|
||||||
if (!from->nb_cards)
|
if (!from->nb_cards)
|
||||||
return;
|
return;
|
||||||
int r = rand() % (from->nb_cards);
|
int r = WRand() % (from->nb_cards);
|
||||||
putInZone(from->cards[r],from, graveyard);
|
putInZone(from->cards[r],from, graveyard);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,10 +263,9 @@ void MTGGameZone::cleanupPhase(){
|
|||||||
void MTGGameZone::shuffle(){
|
void MTGGameZone::shuffle(){
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<(nb_cards); 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;
|
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;
|
if (nbcards>nb_cards) nbcards = nb_cards;
|
||||||
MTGCardInstance * _cards[MTG_MAX_PLAYER_CARDS];
|
MTGCardInstance * _cards[MTG_MAX_PLAYER_CARDS];
|
||||||
for (int i= nb_cards-nbcards; i<(nb_cards); i++) {
|
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;
|
MTGCardInstance * temp = cards[i]; cards[i] = cards[r]; cards[r] = temp;
|
||||||
}
|
}
|
||||||
for (int i= 0; i < nbcards; i++){
|
for (int i= 0; i < nbcards; i++){
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ int MTGMomirRule::genRandomCreatureId(int convertedCost){
|
|||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
if (!total_cards) return 0;
|
if (!total_cards) return 0;
|
||||||
int start = (rand() % total_cards);
|
int start = (WRand() % total_cards);
|
||||||
return pool[convertedCost][start];
|
return pool[convertedCost][start];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,11 @@ int TestSuiteAI::displayStack(){
|
|||||||
int TestSuiteAI::Act(float dt){
|
int TestSuiteAI::Act(float dt){
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
g->gameOver = NULL; // Prevent draw rule from losing the game
|
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){
|
if (playMode == MODE_HUMAN){
|
||||||
g->mLayers->CheckUserInput(0);
|
g->mLayers->CheckUserInput(0);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -95,7 +99,7 @@ int TestSuiteAI::Act(float dt){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == ""){
|
if (action == ""){
|
||||||
//end of game
|
//end of game
|
||||||
suite->assertGame();
|
suite->assertGame();
|
||||||
g->gameOver = g->players[0];
|
g->gameOver = g->players[0];
|
||||||
@@ -284,7 +288,8 @@ void TestSuite::initGame(){
|
|||||||
g->phaseRing->goToPhase(initState.phase, g->players[0]);
|
g->phaseRing->goToPhase(initState.phase, g->players[0]);
|
||||||
g->currentGamePhase = initState.phase;
|
g->currentGamePhase = initState.phase;
|
||||||
for (int i = 0; i < 2; i++){
|
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->life = initState.playerData[i].life;
|
||||||
p->getManaPool()->copy(initState.playerData[i].manapool);
|
p->getManaPool()->copy(initState.playerData[i].manapool);
|
||||||
MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay};
|
MTGGameZone * playerZones[] = {p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay};
|
||||||
@@ -335,6 +340,8 @@ int TestSuite::assertGame(){
|
|||||||
Log(result);
|
Log(result);
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
bool wasAI = false;
|
||||||
|
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
if (g->currentGamePhase != endState.phase){
|
if (g->currentGamePhase != endState.phase){
|
||||||
sprintf(result, "<span class=\"error\">==phase problem. Expected %i, got %i==</span><br />",endState.phase, g->currentGamePhase);
|
sprintf(result, "<span class=\"error\">==phase problem. Expected %i, got %i==</span><br />",endState.phase, g->currentGamePhase);
|
||||||
@@ -342,7 +349,9 @@ int TestSuite::assertGame(){
|
|||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 2; i++){
|
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){
|
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);
|
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);
|
Log(result);
|
||||||
@@ -380,10 +389,18 @@ int TestSuite::assertGame(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nbTests++;
|
if (wasAI) {
|
||||||
if (error) {
|
nbAITests++;
|
||||||
nbFailed++;
|
if (error) {
|
||||||
return 0;
|
nbAIFailed++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nbTests++;
|
||||||
|
if (error) {
|
||||||
|
nbFailed++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Log("<span class=\"success\">==Test Succesful !==</span>");
|
Log("<span class=\"success\">==Test Succesful !==</span>");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -398,7 +415,12 @@ TestSuite::TestSuite(const char * filename,MTGAllCards* _collection){
|
|||||||
currentfile = 0;
|
currentfile = 0;
|
||||||
nbFailed = 0;
|
nbFailed = 0;
|
||||||
nbTests = 0;
|
nbTests = 0;
|
||||||
|
nbAIFailed = 0;
|
||||||
|
nbAITests = 0;
|
||||||
int comment = 0;
|
int comment = 0;
|
||||||
|
seed = 0;
|
||||||
|
forceAbility = false;
|
||||||
|
aiMaxCalls = -1;
|
||||||
if(file){
|
if(file){
|
||||||
while(std::getline(file,s)){
|
while(std::getline(file,s)){
|
||||||
if (!s.size()) continue;
|
if (!s.size()) continue;
|
||||||
@@ -430,6 +452,8 @@ TestSuite::TestSuite(const char * filename,MTGAllCards* _collection){
|
|||||||
|
|
||||||
int TestSuite::loadNext(){
|
int TestSuite::loadNext(){
|
||||||
summoningSickness = 0;
|
summoningSickness = 0;
|
||||||
|
seed = 0;
|
||||||
|
aiMaxCalls = -1;
|
||||||
if (!nbfiles) return 0;
|
if (!nbfiles) return 0;
|
||||||
if (currentfile >= nbfiles) return 0;
|
if (currentfile >= nbfiles) return 0;
|
||||||
currentfile++;
|
currentfile++;
|
||||||
@@ -489,15 +513,18 @@ void TestSuite::cleanup(){
|
|||||||
initState.cleanup();
|
initState.cleanup();
|
||||||
endState.cleanup();
|
endState.cleanup();
|
||||||
actions.cleanup();
|
actions.cleanup();
|
||||||
|
loadRandValues("");
|
||||||
}
|
}
|
||||||
|
|
||||||
int TestSuite::load(const char * _filename){
|
int TestSuite::load(const char * _filename){
|
||||||
summoningSickness = 0;
|
summoningSickness = 0;
|
||||||
|
forceAbility = false;
|
||||||
gameType = GAME_TYPE_CLASSIC;
|
gameType = GAME_TYPE_CLASSIC;
|
||||||
char filename[4096];
|
char filename[4096];
|
||||||
sprintf(filename, RESPATH"/test/%s", _filename);
|
sprintf(filename, RESPATH"/test/%s", _filename);
|
||||||
std::ifstream file(filename);
|
std::ifstream file(filename);
|
||||||
std::string s;
|
std::string s;
|
||||||
|
loadRandValues("");
|
||||||
|
|
||||||
int state = -1;
|
int state = -1;
|
||||||
|
|
||||||
@@ -513,6 +540,22 @@ int TestSuite::load(const char * _filename){
|
|||||||
summoningSickness = 1;
|
summoningSickness = 1;
|
||||||
continue;
|
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) {
|
if (s.compare("momir") == 0) {
|
||||||
gameType = GAME_TYPE_MOMIR;
|
gameType = GAME_TYPE_MOMIR;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "../include/TextScroller.h"
|
#include "../include/TextScroller.h"
|
||||||
|
#include "../include/utils.h"
|
||||||
#include <JLBFont.h>
|
#include <JLBFont.h>
|
||||||
|
|
||||||
TextScroller::TextScroller(JLBFont * font, float x, float y, float width, float speed):JGuiObject(0){
|
TextScroller::TextScroller(JLBFont * font, float x, float y, float width, float speed):JGuiObject(0){
|
||||||
|
|||||||
@@ -1,9 +1,37 @@
|
|||||||
#include "../include/config.h"
|
#include "../include/config.h"
|
||||||
#include "../include/utils.h"
|
#include "../include/utils.h"
|
||||||
|
#include <vector>
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
int randValuesCursor = -1;
|
||||||
|
vector<int>randValues;
|
||||||
|
|
||||||
|
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 filesize(const char * filename){
|
||||||
int file_size = 0;
|
int file_size = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user