mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	BattleAI: retreat
This commit is contained in:
		| @@ -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 | ||||
		Reference in New Issue
	
	Block a user