Files
wagic/projects/mtg/src/AIStats.cpp

172 lines
5.0 KiB
C++

#include "../include/config.h"
#include "../include/AIStats.h"
#include "../include/GameObserver.h"
#include "../include/Player.h"
#include "../include/MTGCardInstance.h"
#include "../include/WEvent.h"
#include "../include/AllAbilities.h"
bool compare_aistats(AIStat * first, AIStat * second){
float damage1 = first->value / first->occurences;
float damage2 = second->value/ second->occurences;
return (damage1 > damage2);
}
AIStats::AIStats(Player * _player, char * _filename){
filename = _filename;
load(_filename);
player = _player;
}
AIStats::~AIStats(){
list<AIStat *>::iterator it;
for ( it=stats.begin() ; it != stats.end(); it++ ){
AIStat * stat = *it;
delete stat;
}
}
void AIStats::updateStatsCard(MTGCardInstance * cardInstance, Damage * damage, float multiplier){
MTGCard * card = cardInstance->model;
AIStat * stat = find(card);
if (!stat){
stat = NEW AIStat(card->getMTGId(),0,1,0);
stats.push_back(stat);
}
if (damage->target == player){
stat->value+= multiplier * STATS_PLAYER_MULTIPLIER * damage->damage;
}else if (damage->target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){
MTGCardInstance * target = (MTGCardInstance *)damage->target;
if (target->controller() == player && !target->isInPlay()){
//One of my creatures got lethal damage...
stat->value+= multiplier * STATS_CREATURE_MULTIPLIER * damage->damage;
}
}
}
int AIStats::receiveEvent(WEvent * event){
WEventDamage * e = dynamic_cast<WEventDamage *>(event);
if (!e) return 0; //we take only Damage events into accountright now
Damage * damage = e->damage;
MTGGameZone * opponentZone = player->opponent()->game->inPlay;
MTGCardInstance * card = damage->source;
updateStatsCard(card,damage);
//Auras on damage source can be the cause
for (int i = 0; i < opponentZone->nb_cards; ++i){
MTGCardInstance * aura = opponentZone->cards[i];
if (aura->target == card){
updateStatsCard(aura,damage, STATS_AURA_MULTIPLIER);
}
}
GameObserver * g = GameObserver::GetInstance();
//Lords
map<MTGCardInstance *, int> lords;
for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish
MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]);
if (ALord * al = dynamic_cast<ALord*>(a)) {
if (al->cards.find(card)!= al->cards.end() && opponentZone->hasCard(al->source)){
lords[al->source] = 1;
}
}
}
if (size_t nb = lords.size()){
for (map<MTGCardInstance *, int>::iterator it = lords.begin();it !=lords.end();++it){
updateStatsCard(it->first,damage, STATS_LORD_MULTIPLIER/nb);
}
}
stats.sort(compare_aistats); //this could be slow, if it is, let's run it only at the end of the turn
return 1; //is this meant to return 0 or 1?
}
bool AIStats::isInTop(MTGCardInstance * card, unsigned int max, bool tooSmallCountsForTrue ){
if (stats.size()<max) return tooSmallCountsForTrue;
unsigned int n = 0;
MTGCard * source = card->model;
int id = source->getMTGId();
list<AIStat *>::iterator it;
for ( it=stats.begin() ; it != stats.end(); it++ ){
if (n >= max) return false;
AIStat * stat = *it;
if (stat->source == id){
if (stat->value>=0) return true;
return false;
}
n++;
}
return false;
}
AIStat * AIStats::find(MTGCard * source){
int id = source->getMTGId();
list<AIStat *>::iterator it;
for ( it=stats.begin() ; it != stats.end(); it++ ){
AIStat * stat = *it;
if (stat->source == id) return stat;
}
return NULL;
}
void AIStats::load(char * filename){
std::ifstream file(filename);
std::string s;
if(file){
while(std::getline(file,s)){
int cardid = atoi(s.c_str());
std::getline(file,s);
int value = atoi(s.c_str());
std::getline(file,s);
int direct = atoi(s.c_str());
AIStat * stat = NEW AIStat(cardid,value,1,direct);
stats.push_back(stat);
}
file.close();
}else{
//TODO Error management
}
}
void AIStats::save(){
std::ofstream file(filename.c_str());
char writer[128];
if (file){
list<AIStat *>::iterator it;
for ( it=stats.begin() ; it != stats.end(); it++ ){
AIStat * stat = *it;
if (stat->value > 0){
sprintf(writer,"%i\n%i\n%i\n", stat->source,stat->value/2,stat->direct);
file<<writer;
}
}
file.close();
}
}
void AIStats::Render(){
GameObserver * g = GameObserver::GetInstance();
float x0 = 10;
if (player == g->players[1]) x0 = 280;
JRenderer::GetInstance()->FillRoundRect(x0,10,200,180,5,ARGB(50,0,0,0));
WFont * f = resources.GetWFont(Fonts::MAIN_FONT);
int i = 0;
char buffer[512];
list<AIStat *>::iterator it;
for (it = stats.begin(); it !=stats.end(); ++it){
if (i>10) break;
AIStat * stat = *it;
if (stat->value > 0){
MTGCard * card = GameApp::collection->getCardById(stat->source);
if (card) {
sprintf(buffer, "%s %i", card->data->getName().c_str(), stat->value);
f->DrawString(buffer,x0+5,10 + 16 *(float)i);
i++;
}
}
}
}