From cab8f9e11dc361343bc6262fe2edeede77369b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Wed, 23 Feb 2011 03:57:45 +0000 Subject: [PATCH] AI for neutral creatures and battles and player AIs can be different. StupidAI will handle neutrals by default. Fixes for issues with deserialization and handling Tactics secondary skill. --- AI/GeniusAI/DLLMain.cpp | 5 +++++ CCallback.cpp | 2 +- CGameInterface.cpp | 10 +++++----- CGameInterface.h | 4 ++-- client/CBattleInterface.cpp | 7 ++++++- client/CConfigHandler.cpp | 3 ++- client/CConfigHandler.h | 2 +- client/Client.cpp | 32 ++++++++++++++++++++++---------- config/settings.txt | 3 ++- global.h | 2 +- lib/CGameState.h | 2 +- lib/HeroBonus.cpp | 16 +++++++++++----- lib/HeroBonus.h | 8 +++++--- 13 files changed, 64 insertions(+), 32 deletions(-) diff --git a/AI/GeniusAI/DLLMain.cpp b/AI/GeniusAI/DLLMain.cpp index f2bd001eb..2868295d9 100644 --- a/AI/GeniusAI/DLLMain.cpp +++ b/AI/GeniusAI/DLLMain.cpp @@ -32,4 +32,9 @@ extern "C" DLL_F_EXPORT CGlobalAI* GetNewAI() extern "C" DLL_F_EXPORT void ReleaseAI(CGlobalAI* i) { delete (CGeniusAI*)i; +} + +extern "C" DLL_F_EXPORT CBattleGameInterface* GetNewBattleAI() +{ + return new CGeniusAI(); } \ No newline at end of file diff --git a/CCallback.cpp b/CCallback.cpp index 6e0b35f80..70a7f45f3 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -551,7 +551,7 @@ TStacks CBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AND_ENEM BOOST_FOREACH(const CStack *s, gs->curB->stacks) { - bool ownerMatches = whose == MINE_AND_ENEMY || whose == ONLY_MINE && s->owner == player; + bool ownerMatches = whose == MINE_AND_ENEMY || whose == ONLY_MINE && s->owner == player || whose == ONLY_ENEMY && s->owner != player; bool alivenessMatches = s->alive() || !onlyAlive; if(ownerMatches && alivenessMatches) ret.push_back(s); diff --git a/CGameInterface.cpp b/CGameInterface.cpp index a2b1e3935..cf84441e6 100644 --- a/CGameInterface.cpp +++ b/CGameInterface.cpp @@ -20,7 +20,7 @@ */ template -rett * createAnyAI(CCallback * cb, std::string dllname, std::string methodName) +rett * createAnyAI(std::string dllname, std::string methodName) { char temp[50]; rett * ret=NULL; @@ -62,14 +62,14 @@ rett * createAnyAI(CCallback * cb, std::string dllname, std::string methodName) return ret; } -CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname) +CGlobalAI * CAIHandler::getNewAI(std::string dllname) { - return createAnyAI(cb, dllname, "GetNewAI"); + return createAnyAI(dllname, "GetNewAI"); } -CBattleGameInterface * CAIHandler::getNewBattleAI( CCallback * cb, std::string dllname ) +CBattleGameInterface * CAIHandler::getNewBattleAI(std::string dllname ) { - return createAnyAI(cb, dllname, "GetNewBattleAI"); + return createAnyAI(dllname, "GetNewBattleAI"); } BattleAction CGlobalAI::activeStack( const CStack * stack ) diff --git a/CGameInterface.h b/CGameInterface.h index 8522bfcd2..119b0b75e 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -153,8 +153,8 @@ public: class CAIHandler { public: - static CGlobalAI * getNewAI(CCallback * cb, std::string dllname); - static CBattleGameInterface * getNewBattleAI(CCallback * cb, std::string dllname); + static CGlobalAI * getNewAI(std::string dllname); + static CBattleGameInterface * getNewBattleAI(std::string dllname); }; class CGlobalAI : public CGameInterface // AI class (to derivate) { diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index 6f6163c4a..6ff0b8fc2 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -3334,6 +3334,9 @@ void CBattleInterface::endAction(const BattleAction* action) } queue->update(); + + if(tacticsMode) //we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed + redrawBackgroundWithHexes(activeStack); } void CBattleInterface::hideQueue() @@ -3461,9 +3464,11 @@ void CBattleInterface::waitForAnims() void CBattleInterface::bEndTacticPhase() { + btactEnd->block(true); + bDefence->block(false); + bWait->block(false); BattleAction endt = BattleAction::makeEndOFTacticPhase(curInt->cb->battleGetMySide()); curInt->cb->battleMakeTacticAction(&endt); - btactEnd->block(true); } void CBattleInterface::bTacticNextStack() diff --git a/client/CConfigHandler.cpp b/client/CConfigHandler.cpp index 9a135a380..ded76f26d 100644 --- a/client/CConfigHandler.cpp +++ b/client/CConfigHandler.cpp @@ -210,7 +210,8 @@ struct SettingsGrammar : public grammar | str_p("localInformation=") >> (uint_p[assign_a(conf.cc.localInformation)] | eps_p[lerror("Wrong localInformation!")]) | str_p("fullscreen=") >> (uint_p[assign_a(conf.cc.fullscreen)] | eps_p[lerror("Wrong fullscreen!")]) | str_p("server=") >> ( ( +digit_p >> *('.' >> +digit_p) )[assign_a(conf.cc.server)] | eps_p[lerror("Wrong server!")]) - | str_p("defaultAI=") >> ((+(anychar_p - ';'))[assign_a(conf.cc.defaultAI)] | eps_p[lerror("Wrong defaultAI!")]) + | str_p("defaultPlayerAI=") >> ((+(anychar_p - ';'))[assign_a(conf.cc.defaultPlayerAI)] | eps_p[lerror("Wrong defaultAI!")]) + | str_p("neutralBattleAI=") >> ((+(anychar_p - ';'))[assign_a(conf.cc.defaultBattleAI)] | eps_p[lerror("Wrong defaultAI!")]) | (+(anychar_p - '}'))[lerror2("Unrecognized client option: ")] ; clientOptionsSequence = *(clientOption >> (';' | eps_p[lerror("Semicolon lacking after client option!")])); diff --git a/client/CConfigHandler.h b/client/CConfigHandler.h index 87c253d2f..7809d5500 100644 --- a/client/CConfigHandler.h +++ b/client/CConfigHandler.h @@ -23,7 +23,7 @@ namespace config int pregameResx, pregameResy; //real screen resolution of preGame int port, localInformation; std::string server, //server address (e.g. 127.0.0.1) - defaultAI; //dll name + defaultPlayerAI, defaultBattleAI; //dll names }; struct ButtonInfo diff --git a/client/Client.cpp b/client/Client.cpp index 76676da47..62fb1408f 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -398,7 +398,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) CCallback *cb = new CCallback(gs,color,this); if(!it->second.human) { - playerint[color] = static_cast(CAIHandler::getNewAI(cb,conf.cc.defaultAI)); + playerint[color] = static_cast(CAIHandler::getNewAI(conf.cc.defaultPlayerAI)); } else { @@ -412,7 +412,7 @@ void CClient::newGame( CConnection *con, StartInfo *si ) else { CBattleCallback * cbc = new CBattleCallback(gs, color, this); - battleints[color] = CAIHandler::getNewBattleAI(cb,"StupidAI"); + battleints[color] = CAIHandler::getNewBattleAI("StupidAI"); battleints[color]->init(cbc); } } @@ -428,9 +428,10 @@ void CClient::newGame( CConnection *con, StartInfo *si ) } else { - playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI); - playerint[255]->init(new CCallback(gs,255,this)); - battleints[255] = playerint[255]; + battleints[255] = CAIHandler::getNewBattleAI(conf.cc.defaultBattleAI); + battleints[255]->init(new CBattleCallback(gs, 255, this)); +// playerint[255]->init(new CCallback(gs,255,this)); +// battleints[255] = playerint[255]; } serv->addStdVecItems(const_cast(CGI)->state); @@ -465,16 +466,27 @@ void CClient::serialize( Handler &h, const int version ) ui8 pid; h & pid & dllname; - CCallback *callback = new CCallback(gs,pid,this); - callbacks.insert(callback); + CGameInterface *nInt = NULL; - - if(dllname.length()) - nInt = CAIHandler::getNewAI(callback,dllname); + { + if(pid == 255) + { + CBattleCallback * cbc = new CBattleCallback(gs, pid, this); + CBattleGameInterface *cbgi = CAIHandler::getNewBattleAI(dllname); + battleints[pid] = cbgi; + cbgi->init(cb); + //TODO? consider serialization + continue; + } + else + nInt = CAIHandler::getNewAI(dllname); + } else nInt = new CPlayerInterface(pid); + CCallback *callback = new CCallback(gs,pid,this); + callbacks.insert(callback); battleints[pid] = playerint[pid] = nInt; nInt->init(callback); nInt->serialize(h, version); diff --git a/config/settings.txt b/config/settings.txt index 419cf4e11..a721276d3 100644 --- a/config/settings.txt +++ b/config/settings.txt @@ -10,7 +10,8 @@ clientSettings fullscreen=0; //0 - windowed mode, 1 - fullscreen server=127.0.0.1; //use 127.0.0.1 for localhost localInformation=2; //0 - *all* information sent from server (safest and slowest); 1 - map information sent from server; 2 - all information local-storaged - defaultAI=GeniusAI; + defaultPlayerAI=GeniusAI; + neutralBattleAI=StupidAI; } GUISettings { diff --git a/global.h b/global.h index 2316589fa..85e164228 100644 --- a/global.h +++ b/global.h @@ -685,6 +685,6 @@ static inline ui32 read_unaligned_u32(const void *p) #define OVERRIDE //is there any working counterpart? #endif -#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving) deserializationFix(); +#define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix(); #endif // __GLOBAL_H__ diff --git a/lib/CGameState.h b/lib/CGameState.h index a706d48df..e287de3ce 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -145,7 +145,6 @@ public: PlayerState(); std::string nodeName() const OVERRIDE; - void deserializationFix(); //override //void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; @@ -371,6 +370,7 @@ public: { loadTownDInfos(); } + BONUS_TREE_DESERIALIZATION_FIX } friend class CCallback; diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 680412621..8094ca020 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -386,10 +386,7 @@ void CBonusSystemNode::addNewBonus(Bonus *b) { assert(!vstd::contains(exportedBonuses,b)); exportedBonuses.push_back(b); - if(b->propagator) - propagateBonus(b); - else - bonuses.push_back(b); + exportBonus(b); } void CBonusSystemNode::removeBonus(Bonus *b) @@ -478,7 +475,8 @@ std::string CBonusSystemNode::nodeName() const void CBonusSystemNode::deserializationFix() { - tlog2 << "Deserialization fix called on bare CBSN? Shouldn't be...\n"; + BOOST_FOREACH(Bonus *b, exportedBonuses) + exportBonus(b); } void CBonusSystemNode::getRedParents(TNodes &out) @@ -567,6 +565,14 @@ void CBonusSystemNode::battleTurnPassed() } } +void CBonusSystemNode::exportBonus(Bonus * b) +{ + if(b->propagator) + propagateBonus(b); + else + bonuses.push_back(b); +} + int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/) { if(obj) diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index d0a30a5b9..bbc8045b8 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -55,6 +55,7 @@ namespace PrimarySkill BONUS_NAME(EARTH_SPELL_DMG_PREMY) \ BONUS_NAME(FIRE_SPELL_DMG_PREMY) \ BONUS_NAME(WATER_SPELL_DMG_PREMY) \ + BONUS_NAME(BLOCK_SPELLS_ABOVE_LEVEL) \ BONUS_NAME(WATER_WALKING) /*subtype 1 - without penalty, 2 - with penalty*/ \ BONUS_NAME(NO_SHOTING_PENALTY) /* duplicates NO_DISTANCE_PENALTY or FREE_SHOOTHING?*/\ BONUS_NAME(NEGATE_ALL_NATURAL_IMMUNITIES) \ @@ -253,7 +254,7 @@ struct DLL_EXPORT Bonus template void serialize(Handler &h, const int version) { - h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & limiter; + h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & limiter & propagator; } static bool OneDay(const Bonus *hb) @@ -448,15 +449,16 @@ public: void popBonuses(const CSelector &s); virtual std::string nodeName() const; void deserializationFix(); + void exportBonus(Bonus * b); template void serialize(Handler &h, const int version) { - h & bonuses & nodeType; + h & /*bonuses & */nodeType; h & exportedBonuses; h & description; + BONUS_TREE_DESERIALIZATION_FIX //h & parents & children; } - enum ENodeTypes { UNKNOWN, STACK_INSTANCE, STACK_BATTLE, SPECIALITY, ARTIFACT, CREATURE, ARTIFACT_INSTANCE, HERO, PLAYER, TEAM