mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
BattleAI: retreat
This commit is contained in:
parent
e2b373a784
commit
82a9f82e1c
@ -17,6 +17,7 @@
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
#include "../../lib/battle/BattleStateInfoForRetreat.h"
|
||||
#include "../../lib/CStack.h" // TODO: remove
|
||||
// Eventually only IBattleInfoCallback and battle::Unit should be used,
|
||||
// CUnitState should be private and CStack should be removed completely
|
||||
@ -728,13 +729,31 @@ void CBattleAI::print(const std::string &text) const
|
||||
|
||||
boost::optional<BattleAction> CBattleAI::considerFleeingOrSurrendering()
|
||||
{
|
||||
if(cb->battleCanSurrender(playerID))
|
||||
BattleStateInfoForRetreat bs;
|
||||
|
||||
bs.canFlee = cb->battleCanFlee();
|
||||
bs.canSurrender = cb->battleCanSurrender(playerID);
|
||||
bs.ourSide = cb->battleGetMySide();
|
||||
bs.ourHero = cb->battleGetMyHero();
|
||||
bs.enemyHero = cb->battleGetFightingHero(!bs.ourSide);
|
||||
|
||||
for(auto stack : cb->battleGetAllStacks(false))
|
||||
{
|
||||
if(stack->alive())
|
||||
{
|
||||
if(stack->side == bs.ourSide)
|
||||
bs.ourStacks.push_back(stack);
|
||||
else
|
||||
bs.enemyStacks.push_back(stack);
|
||||
}
|
||||
}
|
||||
if(cb->battleCanFlee())
|
||||
|
||||
if(!bs.canFlee || !bs.canSurrender)
|
||||
{
|
||||
return boost::none;
|
||||
}
|
||||
return boost::none;
|
||||
|
||||
return cb->makeSurrenderRetreatDecision(bs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../../lib/serializer/CTypeList.h"
|
||||
#include "../../lib/serializer/BinarySerializer.h"
|
||||
#include "../../lib/serializer/BinaryDeserializer.h"
|
||||
#include "../../lib/battle/BattleStateInfoForRetreat.h"
|
||||
|
||||
#include "AIGateway.h"
|
||||
#include "Goals/Goals.h"
|
||||
@ -488,6 +489,23 @@ void AIGateway::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositio
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
boost::optional<BattleAction> AIGateway::makeSurrenderRetreatDecision(
|
||||
const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
|
||||
double fightRatio = battleState.getOurStrength() / (double)battleState.getEnemyStrength();
|
||||
|
||||
if(fightRatio < 0.3 && battleState.canFlee)
|
||||
{
|
||||
return BattleAction::makeRetreat(battleState.ourSide);
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
|
||||
void AIGateway::init(std::shared_ptr<Environment> env, std::shared_ptr<CCallback> CB)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
|
@ -166,6 +166,7 @@ public:
|
||||
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
|
||||
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override;
|
||||
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;
|
||||
boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override;
|
||||
void battleEnd(const BattleResult * br) override;
|
||||
|
@ -387,3 +387,9 @@ bool CBattleCallback::battleMakeTacticAction( BattleAction * action )
|
||||
sendRequest(&ma);
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::optional<BattleAction> CBattleCallback::makeSurrenderRetreatDecision(
|
||||
const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return cl->playerint[getPlayerID().get()]->makeSurrenderRetreatDecision(battleState);
|
||||
}
|
@ -32,6 +32,7 @@ struct CPackForServer;
|
||||
class IBattleEventsReceiver;
|
||||
class IGameEventsReceiver;
|
||||
struct ArtifactLocation;
|
||||
class BattleStateInfoForRetreat;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@ -48,6 +49,7 @@ public:
|
||||
//battle
|
||||
virtual int battleMakeAction(const BattleAction * action) = 0;//for casting spells by hero - DO NOT use it for moving active stack
|
||||
virtual bool battleMakeTacticAction(BattleAction * action) = 0; // performs tactic phase actions
|
||||
virtual boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) = 0;
|
||||
};
|
||||
|
||||
class IGameActionCallback
|
||||
@ -104,6 +106,7 @@ public:
|
||||
CBattleCallback(boost::optional<PlayerColor> Player, CClient *C);
|
||||
int battleMakeAction(const BattleAction * action) override;//for casting spells by hero - DO NOT use it for moving active stack
|
||||
bool battleMakeTacticAction(BattleAction * action) override; // performs tactic phase actions
|
||||
boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
scripting::Pool * getContextPool() const override;
|
||||
|
@ -12,6 +12,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/battle/BattleHex.cpp
|
||||
${MAIN_LIB_DIR}/battle/BattleInfo.cpp
|
||||
${MAIN_LIB_DIR}/battle/BattleProxy.cpp
|
||||
${MAIN_LIB_DIR}/battle/BattleStateInfoForRetreat.cpp
|
||||
${MAIN_LIB_DIR}/battle/CBattleInfoCallback.cpp
|
||||
${MAIN_LIB_DIR}/battle/CBattleInfoEssentials.cpp
|
||||
${MAIN_LIB_DIR}/battle/CCallbackBase.cpp
|
||||
@ -241,6 +242,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/battle/BattleAttackInfo.h
|
||||
${MAIN_LIB_DIR}/battle/BattleHex.h
|
||||
${MAIN_LIB_DIR}/battle/BattleInfo.h
|
||||
${MAIN_LIB_DIR}/battle/BattleStateInfoForRetreat.h
|
||||
${MAIN_LIB_DIR}/battle/BattleProxy.h
|
||||
${MAIN_LIB_DIR}/battle/CBattleInfoCallback.h
|
||||
${MAIN_LIB_DIR}/battle/CBattleInfoEssentials.h
|
||||
|
@ -58,7 +58,9 @@ class CLoadFile;
|
||||
class CSaveFile;
|
||||
class BinaryDeserializer;
|
||||
class BinarySerializer;
|
||||
class BattleStateInfo;
|
||||
struct ArtifactLocation;
|
||||
class BattleStateInfoForRetreat;
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
namespace scripting
|
||||
@ -93,7 +95,7 @@ public:
|
||||
|
||||
//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID)=0;
|
||||
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID)=0;
|
||||
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID)=0;
|
||||
|
||||
// Show a dialog, player must take decision. If selection then he has to choose between one of given components,
|
||||
// if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called
|
||||
@ -108,6 +110,11 @@ public:
|
||||
|
||||
virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions){};
|
||||
|
||||
virtual boost::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
virtual void saveGame(BinarySerializer & h, const int version) = 0;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) = 0;
|
||||
};
|
||||
|
@ -105,6 +105,22 @@ BattleAction BattleAction::makeEndOFTacticPhase(ui8 side)
|
||||
return ba;
|
||||
}
|
||||
|
||||
BattleAction BattleAction::makeSurrender(ui8 side)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = side;
|
||||
ba.actionType = EActionType::SURRENDER;
|
||||
return ba;
|
||||
}
|
||||
|
||||
BattleAction BattleAction::makeRetreat(ui8 side)
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.side = side;
|
||||
ba.actionType = EActionType::RETREAT;
|
||||
return ba;
|
||||
}
|
||||
|
||||
std::string BattleAction::toString() const
|
||||
{
|
||||
std::stringstream actionTypeStream;
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
static BattleAction makeCreatureSpellcast(const battle::Unit * stack, const battle::Target & target, SpellID spellID);
|
||||
static BattleAction makeMove(const battle::Unit * stack, BattleHex dest);
|
||||
static BattleAction makeEndOFTacticPhase(ui8 side);
|
||||
static BattleAction makeRetreat(ui8 side);
|
||||
static BattleAction makeSurrender(ui8 side);
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
|
52
lib/battle/BattleStateInfoForRetreat.cpp
Normal file
52
lib/battle/BattleStateInfoForRetreat.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* BattleStateInfoForRetreat.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "BattleStateInfoForRetreat.h"
|
||||
#include "Unit.h"
|
||||
#include "CBattleInfoCallback.h"
|
||||
#include "../CCreatureSet.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
BattleStateInfoForRetreat::BattleStateInfoForRetreat()
|
||||
: canFlee(false), canSurrender(false), isLastTurnBeforeDie(false), ourStacks(), enemyStacks(), ourHero(nullptr), enemyHero(nullptr), ourSide(-1)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t getFightingStrength(std::vector<const battle::Unit *> stacks, const CGHeroInstance * hero = nullptr)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
|
||||
for(const battle::Unit * stack : stacks)
|
||||
{
|
||||
result += stack->creatureId().toCreature()->AIValue * stack->getCount();
|
||||
}
|
||||
|
||||
if(hero)
|
||||
{
|
||||
result = (uint64_t)(result * hero->getFightingStrength());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t BattleStateInfoForRetreat::getOurStrength() const
|
||||
{
|
||||
return getFightingStrength(ourStacks, ourHero);
|
||||
}
|
||||
|
||||
uint64_t BattleStateInfoForRetreat::getEnemyStrength() const
|
||||
{
|
||||
return getFightingStrength(enemyStacks, enemyHero);
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
38
lib/battle/BattleStateInfoForRetreat.h
Normal file
38
lib/battle/BattleStateInfoForRetreat.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* BattleStateInfoForRetreat.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
namespace battle
|
||||
{
|
||||
class Unit;
|
||||
}
|
||||
|
||||
class CGHeroInstance;
|
||||
|
||||
class DLL_LINKAGE BattleStateInfoForRetreat
|
||||
{
|
||||
public:
|
||||
bool canFlee;
|
||||
bool canSurrender;
|
||||
bool isLastTurnBeforeDie;
|
||||
ui8 ourSide;
|
||||
std::vector<const battle::Unit *> ourStacks;
|
||||
std::vector<const battle::Unit *> enemyStacks;
|
||||
const CGHeroInstance * ourHero;
|
||||
const CGHeroInstance * enemyHero;
|
||||
|
||||
BattleStateInfoForRetreat();
|
||||
uint64_t getOurStrength() const;
|
||||
uint64_t getEnemyStrength() const;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
Loading…
Reference in New Issue
Block a user