-fix issue 76. There's a huge performance cost for this fix, I hope it won't show too much in the PSP version.
This commit is contained in:
wagic.the.homebrew@gmail.com
2009-10-04 10:52:13 +00:00
parent c7aa12054d
commit b2b88f1f23
3 changed files with 60 additions and 49 deletions
+2 -3
View File
@@ -48,9 +48,8 @@ class AIPlayer: public Player{
protected: protected:
MTGCardInstance * nextCardToPlay; MTGCardInstance * nextCardToPlay;
int agressivity; int agressivity;
ManaCost * potentialMana;
queue<AIAction *> clickstream; queue<AIAction *> clickstream;
void tapLandsForMana(ManaCost * potentialMana, ManaCost * cost); void tapLandsForMana(ManaCost * cost, MTGCardInstance * card = NULL);
int orderBlockers(); int orderBlockers();
int combatDamages(); int combatDamages();
int interruptIfICan(); int interruptIfICan();
@@ -64,7 +63,7 @@ class AIPlayer: public Player{
void End(){}; void End(){};
virtual int displayStack() {return 0;}; virtual int displayStack() {return 0;};
AIStats * stats; AIStats * stats;
ManaCost * getPotentialMana(); ManaCost * getPotentialMana(MTGCardInstance * card = NULL);
AIPlayer(MTGPlayerCards * deck, string deckFile, string deckFileSmall); AIPlayer(MTGPlayerCards * deck, string deckFile, string deckFileSmall);
virtual ~AIPlayer(); virtual ~AIPlayer();
virtual MTGCardInstance * chooseCard(TargetChooser * tc, MTGCardInstance * source, int random = 0); virtual MTGCardInstance * chooseCard(TargetChooser * tc, MTGCardInstance * source, int random = 0);
+23 -18
View File
@@ -36,8 +36,9 @@ int AIMomirPlayer::momir(){
int result = 0; int result = 0;
int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES); int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES);
int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES ); int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES );
getPotentialMana(); ManaCost * potentialMana = getPotentialMana();
int converted = potentialMana->getConvertedCost(); int converted = potentialMana->getConvertedCost();
SAFE_DELETE(potentialMana);
int efficiency = 100; int efficiency = 100;
int chance = 1 + (rand() % 100); int chance = 1 + (rand() % 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
@@ -51,7 +52,7 @@ int AIMomirPlayer::momir(){
MTGAbility * ability = getMomirAbility(); MTGAbility * ability = getMomirAbility();
MTGCardInstance * card = game->hand->cards[0]; MTGCardInstance * card = game->hand->cards[0];
if (ability->isReactingToClick(card,cost)){ if (ability->isReactingToClick(card,cost)){
tapLandsForMana(potentialMana,cost); tapLandsForMana(cost);
AIAction * a = NEW AIAction(ability,card); AIAction * a = NEW AIAction(ability,card);
clickstream.push(a); clickstream.push(a);
result = 1; result = 1;
@@ -80,26 +81,30 @@ the general rule is this: if you want to get to Eight, you have to skip two drop
}else if (p == this && g->mLayers->stackLayer()->count(0,NOT_RESOLVED) == 0){ //standard actions }else if (p == this && g->mLayers->stackLayer()->count(0,NOT_RESOLVED) == 0){ //standard actions
CardDescriptor cd; CardDescriptor cd;
MTGCardInstance * card = NULL; MTGCardInstance * card = NULL;
//No mana, try to get some
getPotentialMana();
switch(currentGamePhase){ switch(currentGamePhase){
case Constants::MTG_PHASE_FIRSTMAIN: case Constants::MTG_PHASE_FIRSTMAIN:
if (canPutLandsIntoPlay && (potentialMana->getConvertedCost() <8 || game->hand->nb_cards > 1) ){ {
//Attempt to put land into play ManaCost * potentialMana = getPotentialMana();
cd.init(); int converted = potentialMana->getConvertedCost();
cd.setColor(Constants::MTG_COLOR_LAND); SAFE_DELETE(potentialMana);
card = cd.match(game->hand); if (canPutLandsIntoPlay && ( converted <8 || game->hand->nb_cards > 1) ){
if (card){ //Attempt to put land into play
MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY); cd.init();
AIAction * a = NEW AIAction(putIntoPlay,card); //TODO putinplay action cd.setColor(Constants::MTG_COLOR_LAND);
clickstream.push(a); card = cd.match(game->hand);
return 1; if (card){
} MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY);
AIAction * a = NEW AIAction(putIntoPlay,card); //TODO putinplay action
clickstream.push(a);
return 1;
}
}
momir();
return 1;
break;
} }
momir();
return 1;
break;
case Constants::MTG_PHASE_SECONDMAIN: case Constants::MTG_PHASE_SECONDMAIN:
selectAbility(); selectAbility();
return 1; return 1;
+34 -27
View File
@@ -27,14 +27,12 @@ int AIAction::Act(){
} }
AIPlayer::AIPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Player(deck, file, fileSmall) { AIPlayer::AIPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Player(deck, file, fileSmall) {
potentialMana = NEW ManaCost();
nextCardToPlay = NULL; nextCardToPlay = NULL;
stats = NULL; stats = NULL;
agressivity = 50; agressivity = 50;
} }
AIPlayer::~AIPlayer(){ AIPlayer::~AIPlayer(){
SAFE_DELETE(potentialMana);
if (stats){ if (stats){
stats->save(); stats->save();
SAFE_DELETE(stats); SAFE_DELETE(stats);
@@ -63,12 +61,14 @@ int AIPlayer::Act(float dt){
} }
void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){ void AIPlayer::tapLandsForMana(ManaCost * cost,MTGCardInstance * target){
#if defined (WIN32) || defined (LINUX) #if defined (WIN32) || defined (LINUX)
OutputDebugString("tapping land for mana\n"); OutputDebugString("tapping land for mana\n");
#endif #endif
if (!cost) return; if (!cost) return;
ManaCost * diff = potentialMana->Diff(cost); ManaCost * pMana = getPotentialMana(target);
ManaCost * diff = pMana->Diff(cost);
delete(pMana);
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
map<MTGCardInstance *,bool>used; map<MTGCardInstance *,bool>used;
@@ -78,6 +78,7 @@ void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){
AManaProducer * amp = dynamic_cast<AManaProducer*>(a); AManaProducer * amp = dynamic_cast<AManaProducer*>(a);
if (amp && canHandleCost(amp)){ if (amp && canHandleCost(amp)){
MTGCardInstance * card = amp->source; MTGCardInstance * card = amp->source;
if (card == target) used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76
if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){ if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){
used[card] = true; used[card] = true;
int doTap = 1; int doTap = 1;
@@ -99,9 +100,8 @@ void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){
} }
ManaCost * AIPlayer::getPotentialMana(){ ManaCost * AIPlayer::getPotentialMana(MTGCardInstance * target){
SAFE_DELETE(potentialMana); ManaCost * result = NEW ManaCost();
potentialMana = NEW ManaCost();
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
map<MTGCardInstance *,bool>used; map<MTGCardInstance *,bool>used;
for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish
@@ -110,14 +110,15 @@ ManaCost * AIPlayer::getPotentialMana(){
AManaProducer * amp = dynamic_cast<AManaProducer*>(a); AManaProducer * amp = dynamic_cast<AManaProducer*>(a);
if (amp && canHandleCost(amp)){ if (amp && canHandleCost(amp)){
MTGCardInstance * card = amp->source; MTGCardInstance * card = amp->source;
if (card == target) used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76
if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){ if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){
potentialMana->add(amp->output); result->add(amp->output);
used[card] = true; used[card] = true;
} }
} }
} }
return potentialMana; return result;
} }
@@ -203,6 +204,7 @@ int AIAction::getEfficiency(){
} }
break; break;
} }
if (p->game->hand->nb_cards == 0) efficiency *= 1.3; //increase chance of using ability if hand is empty
return efficiency; return efficiency;
} }
@@ -237,18 +239,26 @@ int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map<AIAc
int AIPlayer::selectAbility(){ int AIPlayer::selectAbility(){
map<AIAction *, int,CmpAbilities>ranking; map<AIAction *, int,CmpAbilities>ranking;
list<int>::iterator it; list<int>::iterator it;
ManaCost * pMana = getPotentialMana();
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
//This loop is extrmely inefficient. TODO: optimize!
ManaCost * totalPotentialMana = getPotentialMana();
for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish
//Make sure we can use the ability
MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]);
//Skip mana abilities for performance
if (dynamic_cast<AManaProducer*>(a)) continue;
//Make sure we can use the ability
for (int j=0; j < game->inPlay->nb_cards; j++){ for (int j=0; j < game->inPlay->nb_cards; j++){
MTGCardInstance * card = game->inPlay->cards[j]; MTGCardInstance * card = game->inPlay->cards[j];
if (a->isReactingToClick(card,pMana)){ if (a->isReactingToClick(card,totalPotentialMana)){ //This test is to avod the huge call to getPotentialManaCost after that
createAbilityTargets(a, card, &ranking); ManaCost * pMana = getPotentialMana(card);
if (a->isReactingToClick(card,pMana))
createAbilityTargets(a, card, &ranking);
delete(pMana);
} }
} }
} }
delete totalPotentialMana;
if (ranking.size()){ if (ranking.size()){
AIAction * a = ranking.begin()->first; AIAction * a = ranking.begin()->first;
@@ -257,7 +267,7 @@ int AIPlayer::selectAbility(){
a = NULL; a = NULL;
}else{ }else{
OutputDebugString("AIPlayer:Using Activated ability\n"); OutputDebugString("AIPlayer:Using Activated ability\n");
tapLandsForMana(pMana, a->ability->cost); tapLandsForMana(a->ability->cost,a->click);
clickstream.push(a); clickstream.push(a);
} }
map<AIAction *, int, CmpAbilities>::iterator it2; map<AIAction *, int, CmpAbilities>::iterator it2;
@@ -580,7 +590,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op
} }
MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const char * type){ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * type){
int maxCost = -1; int maxCost = -1;
MTGCardInstance * nextCardToPlay = NULL; MTGCardInstance * nextCardToPlay = NULL;
MTGCardInstance * card = NULL; MTGCardInstance * card = NULL;
@@ -593,7 +603,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const c
if (card->has(Constants::LEGENDARY) && game->inPlay->findByName(card->name)) continue; if (card->has(Constants::LEGENDARY) && game->inPlay->findByName(card->name)) continue;
int currentCost = card->getManaCost()->getConvertedCost(); int currentCost = card->getManaCost()->getConvertedCost();
int hasX = card->getManaCost()->hasX(); int hasX = card->getManaCost()->hasX();
if ((currentCost > maxCost || hasX) && potentialMana->canAfford(card->getManaCost())){ if ((currentCost > maxCost || hasX) && pMana->canAfford(card->getManaCost())){
TargetChooserFactory * tcf = NEW TargetChooserFactory(); TargetChooserFactory * tcf = NEW TargetChooserFactory();
TargetChooser * tc = tcf->createTargetChooser(card); TargetChooser * tc = tcf->createTargetChooser(card);
delete tcf; delete tcf;
@@ -613,7 +623,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const c
} }
//Reduce the chances of playing a spell with X cost if available mana is low //Reduce the chances of playing a spell with X cost if available mana is low
if (hasX){ if (hasX){
int xDiff = potentialMana->getConvertedCost() - currentCost; int xDiff = pMana->getConvertedCost() - currentCost;
if (xDiff < 0) xDiff = 0; if (xDiff < 0) xDiff = 0;
shouldPlayPercentage = shouldPlayPercentage - ((shouldPlayPercentage * 1.9) / (1 + xDiff)); shouldPlayPercentage = shouldPlayPercentage - ((shouldPlayPercentage * 1.9) / (1 + xDiff));
} }
@@ -621,7 +631,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const c
if (rand() % 100 > shouldPlayPercentage) continue; if (rand() % 100 > shouldPlayPercentage) continue;
nextCardToPlay = card; nextCardToPlay = card;
maxCost = currentCost; maxCost = currentCost;
if(hasX) maxCost = potentialMana->getConvertedCost(); if(hasX) maxCost = pMana->getConvertedCost();
} }
} }
return nextCardToPlay; return nextCardToPlay;
@@ -668,11 +678,11 @@ int AIPlayerBaka::computeActions(){
case Constants::MTG_PHASE_SECONDMAIN: case Constants::MTG_PHASE_SECONDMAIN:
{ {
//No mana, try to get some bool potential = false;
SAFE_DELETE(potentialMana);
ManaCost * currentMana = manaPool; ManaCost * currentMana = manaPool;
if (!currentMana->getConvertedCost()){ if (!currentMana->getConvertedCost()){
currentMana = getPotentialMana(); currentMana = getPotentialMana();
potential = true;
} }
nextCardToPlay = FindCardToPlay(currentMana, "land"); nextCardToPlay = FindCardToPlay(currentMana, "land");
@@ -683,14 +693,11 @@ int AIPlayerBaka::computeActions(){
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "artifact"); if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "artifact");
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "sorcery"); if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "sorcery");
if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "instant"); if (!nextCardToPlay) nextCardToPlay = FindCardToPlay(currentMana, "instant");
if (potential) delete(currentMana);
if (nextCardToPlay){ if (nextCardToPlay){
#if defined (WIN32) || defined (LINUX) if (potential){
char buffe[4096]; tapLandsForMana(nextCardToPlay->getManaCost());
sprintf(buffe, "Putting Card Into Play: %s", nextCardToPlay->getName().c_str()); }
OutputDebugString(buffe);
#endif
if (currentMana == potentialMana) tapLandsForMana(currentMana,nextCardToPlay->getManaCost());
AIAction * a = NEW AIAction(nextCardToPlay); AIAction * a = NEW AIAction(nextCardToPlay);
clickstream.push(a); clickstream.push(a);
return 1; return 1;