Erwan
-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:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user