소스 검색

Merge pull request #316 from FeniksFire/improvingTheBattle

Refactoring.
ArseniyShestakov 8 년 전
부모
커밋
bd27636cd9
62개의 변경된 파일1312개의 추가작업 그리고 973개의 파일을 삭제
  1. 1 1
      AI/BattleAI/EnemyInfo.h
  2. 1 1
      AI/StupidAI/StupidAI.h
  3. 1 1
      CCallback.cpp
  4. 1 1
      client/Client.cpp
  5. 1 1
      client/Client.h
  6. 1 1
      client/NetPacksClient.cpp
  7. 1 1
      client/battle/CBattleAnimations.cpp
  8. 1 1
      client/battle/CBattleAnimations.h
  9. 1 1
      client/battle/CBattleInterfaceClasses.h
  10. 0 341
      lib/CBattleCallback.h
  11. 1 1
      lib/CGameInfoCallback.cpp
  12. 1 1
      lib/CGameInfoCallback.h
  13. 1 1
      lib/CGameInterface.h
  14. 1 1
      lib/CGameState.cpp
  15. 1 1
      lib/CHeroHandler.cpp
  16. 14 8
      lib/CMakeLists.txt
  17. 1 1
      lib/CStack.cpp
  18. 1 1
      lib/CStack.h
  19. 1 1
      lib/CTownHandler.h
  20. 1 1
      lib/IGameEventsReceiver.h
  21. 2 2
      lib/NetPacks.h
  22. 1 1
      lib/NetPacksLib.cpp
  23. 22 10
      lib/VCMI_lib.cbp
  24. 23 11
      lib/VCMI_lib.vcxproj
  25. 34 10
      lib/VCMI_lib.vcxproj.filters
  26. 51 0
      lib/battle/AccessibilityInfo.cpp
  27. 35 0
      lib/battle/AccessibilityInfo.h
  28. 10 12
      lib/battle/BattleAction.cpp
  29. 10 13
      lib/battle/BattleAction.h
  30. 51 0
      lib/battle/BattleAttackInfo.cpp
  31. 33 0
      lib/battle/BattleAttackInfo.h
  32. 0 0
      lib/battle/BattleHex.cpp
  33. 1 1
      lib/battle/BattleHex.h
  34. 14 14
      lib/battle/BattleInfo.cpp
  35. 4 4
      lib/battle/BattleInfo.h
  36. 142 507
      lib/battle/CBattleInfoCallback.cpp
  37. 110 0
      lib/battle/CBattleInfoCallback.h
  38. 349 0
      lib/battle/CBattleInfoEssentials.cpp
  39. 108 0
      lib/battle/CBattleInfoEssentials.h
  40. 42 0
      lib/battle/CCallbackBase.cpp
  41. 42 0
      lib/battle/CCallbackBase.h
  42. 4 4
      lib/battle/CObstacleInstance.cpp
  43. 0 0
      lib/battle/CObstacleInstance.h
  44. 54 0
      lib/battle/CPlayerBattleCallback.cpp
  45. 26 0
      lib/battle/CPlayerBattleCallback.h
  46. 43 0
      lib/battle/ReachabilityInfo.cpp
  47. 52 0
      lib/battle/ReachabilityInfo.h
  48. 1 1
      lib/registerTypes/RegisterTypes.h
  49. 1 1
      lib/registerTypes/TypesClientPacks2.cpp
  50. 1 1
      lib/registerTypes/TypesMapObjects2.cpp
  51. 1 1
      lib/spells/BattleSpellMechanics.cpp
  52. 1 1
      lib/spells/CDefaultSpellMechanics.cpp
  53. 2 2
      lib/spells/CSpellHandler.cpp
  54. 1 1
      lib/spells/CSpellHandler.h
  55. 1 1
      lib/spells/CreatureSpellMechanics.cpp
  56. 1 1
      lib/spells/ISpellMechanics.cpp
  57. 1 1
      lib/spells/ISpellMechanics.h
  58. 1 1
      server/CGameHandler.cpp
  59. 1 1
      server/CGameHandler.h
  60. 1 1
      server/CQuery.cpp
  61. 2 2
      server/NetPacksServer.cpp
  62. 1 1
      test/Battlefield.cpp

+ 1 - 1
AI/BattleAI/EnemyInfo.h

@@ -9,7 +9,7 @@
  */
 #pragma once
 
-#include "../../lib/BattleHex.h"
+#include "../../lib/battle/BattleHex.h"
 
 class CStack;
 

+ 1 - 1
AI/StupidAI/StupidAI.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "../../lib/BattleHex.h"
+#include "../../lib/battle/BattleHex.h"
 
 class CStupidAI : public CBattleGameInterface
 {

+ 1 - 1
CCallback.cpp

@@ -18,7 +18,7 @@
 #include "lib/GameConstants.h"
 #include "lib/CPlayerState.h"
 #include "lib/UnlockGuard.h"
-#include "lib/BattleInfo.h"
+#include "lib/battle/BattleInfo.h"
 
 /*
  * CCallback.cpp, part of VCMI engine

+ 1 - 1
client/Client.cpp

@@ -11,7 +11,7 @@
 #include "../lib/CGameState.h"
 #include "CPlayerInterface.h"
 #include "../lib/StartInfo.h"
-#include "../lib/BattleInfo.h"
+#include "../lib/battle/BattleInfo.h"
 #include "../lib/CModHandler.h"
 #include "../lib/CArtHandler.h"
 #include "../lib/CGeneralTextHandler.h"

+ 1 - 1
client/Client.h

@@ -2,7 +2,7 @@
 
 
 #include "../lib/IGameCallback.h"
-#include "../lib/BattleAction.h"
+#include "../lib/battle/BattleAction.h"
 #include "../lib/CStopWatch.h"
 #include "../lib/int3.h"
 

+ 1 - 1
client/NetPacksClient.cpp

@@ -25,7 +25,7 @@
 #include "../lib/mapping/CCampaignHandler.h"
 #include "../lib/CGameState.h"
 #include "../lib/CStack.h"
-#include "../lib/BattleInfo.h"
+#include "../lib/battle/BattleInfo.h"
 #include "../lib/GameConstants.h"
 #include "../lib/CPlayerState.h"
 #include "gui/CGuiHandler.h"

+ 1 - 1
client/battle/CBattleAnimations.cpp

@@ -944,7 +944,7 @@ bool CSpellEffectAnimation::init()
 	{
 
 			const CStack* destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(destTile, false);
-			Rect &tilePos = owner->bfield[destTile]->pos;
+			Rect & tilePos = owner->bfield[destTile]->pos;
 			BattleEffect be;
 			be.effectID = ID;
 			be.anim = CDefHandler::giveDef(customAnim);

+ 1 - 1
client/battle/CBattleAnimations.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "../../lib/BattleHex.h"
+#include "../../lib/battle/BattleHex.h"
 #include "../widgets/Images.h"
 
 class CBattleInterface;

+ 1 - 1
client/battle/CBattleInterfaceClasses.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include "../gui/CIntObject.h"
-#include "../../lib/BattleHex.h"
+#include "../../lib/battle/BattleHex.h"
 #include "../windows/CWindowObject.h"
 
 struct SDL_Surface;

+ 0 - 341
lib/CBattleCallback.h

@@ -1,341 +0,0 @@
-#pragma once
-#include "BattleHex.h"
-
-/*
- * CBattleCallback.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
- *
- */
-
-class CGameState;
-class CGTownInstance;
-class CGHeroInstance;
-class CStack;
-class ISpellCaster;
-class CSpell;
-struct BattleInfo;
-struct CObstacleInstance;
-class IBonusBearer;
-struct InfoAboutHero;
-class CArmedInstance;
-class CRandomGenerator;
-
-namespace boost
-{class shared_mutex;}
-
-namespace BattleSide
-{
-	enum {ATTACKER = 0, DEFENDER = 1};
-}
-
-typedef std::vector<const CStack*> TStacks;
-typedef std::function<bool(const CStack *)> TStackFilter;
-
-class CBattleInfoEssentials;
-
-//Basic class for various callbacks (interfaces called by players to get info about game and so forth)
-class DLL_LINKAGE CCallbackBase
-{
-	const BattleInfo *battle; //battle to which the player is engaged, nullptr if none or not applicable
-
-	const BattleInfo * getBattle() const
-	{
-		return battle;
-	}
-
-protected:
-	CGameState *gs;
-	boost::optional<PlayerColor> player; // not set gives access to all information, otherwise callback provides only information "visible" for player
-
-	CCallbackBase(CGameState *GS, boost::optional<PlayerColor> Player)
-		: battle(nullptr), gs(GS), player(Player)
-	{}
-	CCallbackBase()
-		: battle(nullptr), gs(nullptr)
-	{}
-
-	void setBattle(const BattleInfo *B);
-	bool duringBattle() const;
-
-public:
-	boost::optional<PlayerColor> getPlayerID() const;
-
-	friend class CBattleInfoEssentials;
-};
-
-
-struct DLL_LINKAGE AttackableTiles
-{
-	std::set<BattleHex> hostileCreaturePositions;
-	std::set<BattleHex> friendlyCreaturePositions; //for Dragon Breath
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & hostileCreaturePositions & friendlyCreaturePositions;
-	}
-};
-
-//Accessibility is property of hex in battle. It doesn't depend on stack, side's perspective and so on.
-namespace EAccessibility
-{
-	enum EAccessibility
-	{
-		ACCESSIBLE,
-		ALIVE_STACK,
-		OBSTACLE,
-		DESTRUCTIBLE_WALL,
-		GATE, //sieges -> gate opens only for defender stacks
-		UNAVAILABLE, //indestructible wall parts, special battlefields (like boat-to-boat)
-		SIDE_COLUMN //used for first and last columns of hexes that are unavailable but wat machines can stand there
-	};
-}
-
-typedef std::array<EAccessibility::EAccessibility, GameConstants::BFIELD_SIZE> TAccessibilityArray;
-
-struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
-{
-	bool occupiable(const CStack *stack, BattleHex tile) const;
-	bool accessible(BattleHex tile, const CStack *stack) const; //checks for both tiles if stack is double wide
-	bool accessible(BattleHex tile, bool doubleWide, bool attackerOwned) const; //checks for both tiles if stack is double wide
-};
-
-namespace BattlePerspective
-{
-	enum BattlePerspective
-	{
-		INVALID = -2,
-		ALL_KNOWING = -1,
-		LEFT_SIDE,
-		RIGHT_SIDE
-	};
-}
-
-// Reachability info is result of BFS calculation. It's dependent on stack (it's owner, whether it's flying),
-// startPosition and perpective.
-struct DLL_LINKAGE ReachabilityInfo
-{
-	typedef std::array<int, GameConstants::BFIELD_SIZE> TDistances;
-	typedef std::array<BattleHex, GameConstants::BFIELD_SIZE> TPredecessors;
-
-	enum { 	INFINITE_DIST = 1000000 };
-
-	struct DLL_LINKAGE Parameters
-	{
-		const CStack *stack; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
-
-		bool attackerOwned;
-		bool doubleWide;
-		bool flying;
-		std::vector<BattleHex> knownAccessible; //hexes that will be treated as accessible, even if they're occupied by stack (by default - tiles occupied by stack we do reachability for, so it doesn't block itself)
-
-		BattleHex startPosition; //assumed position of stack
-		BattlePerspective::BattlePerspective perspective; //some obstacles (eg. quicksands) may be invisible for some side
-
-		Parameters();
-		Parameters(const CStack *Stack);
-	};
-
-	Parameters params;
-	AccessibilityInfo accessibility;
-	TDistances distances;
-	TPredecessors predecessors;
-
-	ReachabilityInfo()
-	{
-		distances.fill(INFINITE_DIST);
-		predecessors.fill(BattleHex::INVALID);
-	}
-
-	bool isReachable(BattleHex hex) const
-	{
-		return distances[hex] < INFINITE_DIST;
-	}
-};
-
-class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
-{
-protected:
-	bool battleDoWeKnowAbout(ui8 side) const;
-	const IBonusBearer * getBattleNode() const;
-public:
-	enum EStackOwnership
-	{
-		ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
-	};
-
-	BattlePerspective::BattlePerspective battleGetMySide() const;
-
-	ETerrainType battleTerrainType() const;
-	BFieldType battleGetBattlefieldType() const;
-	std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
-
-    /** @brief Main method for getting battle stacks
-     *
-     * @param predicate Functor that shall return true for desired stack
-     * @return filtered stacks
-     *
-     */
-	TStacks battleGetStacksIf(TStackFilter predicate) const;
-
-	bool battleHasNativeStack(ui8 side) const;
-	int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
-	const CGTownInstance * battleGetDefendedTown() const; //returns defended town if current battle is a siege, nullptr instead
-	const CStack *battleActiveStack() const;
-	si8 battleTacticDist() const; //returns tactic distance in current tactics phase; 0 if not in tactics phase
-	si8 battleGetTacticsSide() const; //returns which side is in tactics phase, undefined if none (?)
-	bool battleCanFlee(PlayerColor player) const;
-	bool battleCanSurrender(PlayerColor player) const;
-	si8 playerToSide(PlayerColor player) const;
-	bool playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const;
-	ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
-	bool battleHasHero(ui8 side) const;
-	int battleCastSpells(ui8 side) const; //how many spells has given side cast
-	const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
-	const CArmedInstance * battleGetArmyObject(ui8 side) const;
-	InfoAboutHero battleGetHeroInfo(ui8 side) const;
-
-	// for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall,
-	// [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
-	si8 battleGetWallState(int partOfWall) const;
-	EGateState battleGetGateState() const;
-
-	//helpers
-	///returns all stacks, alive or dead or undead or mechanical :)
-	TStacks battleGetAllStacks(bool includeTurrets = false) const;
-
-	///returns all alive stacks excluding turrets
-	TStacks battleAliveStacks() const;
-	///returns all alive stacks from particular side excluding turrets
-	TStacks battleAliveStacks(ui8 side) const;
-	const CStack * battleGetStackByID(int ID, bool onlyAlive = true) const; //returns stack info by given ID
-	bool battleIsObstacleVisibleForSide(const CObstacleInstance & coi, BattlePerspective::BattlePerspective side) const;
-
-	///returns player that controls given stack; mind control included
-	PlayerColor battleGetOwner(const CStack * stack) const;
-
-	///returns hero that controls given stack; nullptr if none; mind control included
-	const CGHeroInstance * battleGetOwnerHero(const CStack * stack) const;
-
-	///check that stacks are controlled by same|other player(s) depending on positiveness
-	///mind control included
-	bool battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness = false) const;
-};
-
-struct DLL_LINKAGE BattleAttackInfo
-{
-	const IBonusBearer *attackerBonuses, *defenderBonuses;
-	const CStack *attacker, *defender;
-	BattleHex attackerPosition, defenderPosition;
-
-	int attackerCount, defenderCount;
-	bool shooting;
-	int chargedFields;
-
-	bool luckyHit;
-	bool unluckyHit;
-	bool deathBlow;
-	bool ballistaDoubleDamage;
-
-	BattleAttackInfo(const CStack *Attacker, const CStack *Defender, bool Shooting = false);
-	BattleAttackInfo reverse() const;
-};
-
-class DLL_LINKAGE CBattleInfoCallback : public virtual CBattleInfoEssentials
-{
-public:
-	enum ERandomSpell
-	{
-		RANDOM_GENIE, RANDOM_AIMED
-	};
-
-	//battle
-	boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
-
-	std::shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
-	const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const; //returns stack info by given pos
-	void battleGetStackQueue(std::vector<const CStack *> &out, const int howMany, const int turn = 0, int lastMoved = -1) const;
-	void battleGetStackCountOutsideHexes(bool *ac) const; // returns hexes which when in front of a stack cause us to move the amount box back
-
-
-	std::vector<BattleHex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = nullptr) const; //returns hexes reachable by creature with id ID (valid movement destinations), DOES contain stack current position
-
-	int battleGetSurrenderCost(PlayerColor Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
-	ReachabilityInfo::TDistances battleGetDistances(const CStack * stack, BattleHex hex = BattleHex::INVALID, BattleHex * predecessors = nullptr) const; //returns vector of distances to [dest hex number]
-	std::set<BattleHex> battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const;
-
-	bool battleCanAttack(const CStack * stack, const CStack * target, BattleHex dest) const; //determines if stack with given ID can attack target at the selected destination
-	bool battleCanShoot(const CStack * stack, BattleHex dest) const; //determines if stack with given ID shoot at the selected destination
-	bool battleIsStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack
-	std::set<const CStack*>  batteAdjacentCreatures (const CStack * stack) const;
-
-	TDmgRange calculateDmgRange(const BattleAttackInfo &info) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
-	TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, TQuantity attackerCount, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
-	TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
-
-	//hextowallpart  //int battleGetWallUnderHex(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
-	std::pair<ui32, ui32> battleEstimateDamage(CRandomGenerator & rand, const BattleAttackInfo &bai, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
-	std::pair<ui32, ui32> battleEstimateDamage(CRandomGenerator & rand, const CStack * attacker, const CStack * defender, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
-	si8 battleHasDistancePenalty( const CStack * stack, BattleHex destHex ) const;
-	si8 battleHasDistancePenalty(const IBonusBearer *bonusBearer, BattleHex shooterPosition, BattleHex destHex ) const;
-	si8 battleHasWallPenalty(const CStack * stack, BattleHex destHex) const; //checks if given stack has wall penalty
-	si8 battleHasWallPenalty(const IBonusBearer *bonusBearer, BattleHex shooterPosition, BattleHex destHex) const; //checks if given stack has wall penalty
-
-	BattleHex wallPartToBattleHex(EWallPart::EWallPart part) const;
-	EWallPart::EWallPart battleHexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
-	bool isWallPartPotentiallyAttackable(EWallPart::EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not
-	std::vector<BattleHex> getAttackableBattleHexes() const;
-
-	//*** MAGIC
-	si8 battleMaxSpellLevel(ui8 side) const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
-	ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
-	ESpellCastProblem::ESpellCastProblem battleCanCastSpell(const ISpellCaster * caster, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell
-
-	SpellID battleGetRandomStackSpell(CRandomGenerator & rand, const CStack * stack, ERandomSpell mode) const;
-	SpellID getRandomBeneficialSpell(CRandomGenerator & rand, const CStack * subject) const;
-	SpellID getRandomCastedSpell(CRandomGenerator & rand, const CStack * caster) const; //called at the beginning of turn for Faerie Dragon
-
-	const CStack * getStackIf(std::function<bool(const CStack*)> pred) const;
-
-	si8 battleHasShootingPenalty(const CStack * stack, BattleHex destHex)
-	{
-		return battleHasDistancePenalty(stack, destHex) || battleHasWallPenalty(stack, destHex);
-	}
-	si8 battleCanTeleportTo(const CStack * stack, BattleHex destHex, int telportLevel) const; //checks if teleportation of given stack to given position can take place
-
-
-	//convenience methods using the ones above
-	bool isInTacticRange( BattleHex dest ) const;
-	si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
-
-	AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const; //TODO: apply rotation to two-hex attacker
-	std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
-	bool isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir) const; //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
-	bool isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir) const; //helper for isToReverse
-
-	ReachabilityInfo getReachability(const CStack *stack) const;
-	ReachabilityInfo getReachability(const ReachabilityInfo::Parameters &params) const;
-	AccessibilityInfo getAccesibility() const;
-	AccessibilityInfo getAccesibility(const CStack *stack) const; //Hexes ocupied by stack will be marked as accessible.
-	AccessibilityInfo getAccesibility(const std::vector<BattleHex> &accessibleHexes) const; //given hexes will be marked as accessible
-	std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const;
-protected:
-	ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters &params) const;
-	ReachabilityInfo makeBFS(const AccessibilityInfo &accessibility, const ReachabilityInfo::Parameters &params) const;
-	ReachabilityInfo makeBFS(const CStack *stack) const; //uses default parameters -> stack position and owner's perspective
-	std::set<BattleHex> getStoppers(BattlePerspective::BattlePerspective whichSidePerspective) const; //get hexes with stopping obstacles (quicksands)
-};
-
-class DLL_LINKAGE CPlayerBattleCallback : public CBattleInfoCallback
-{
-public:
-	bool battleCanFlee() const; //returns true if caller can flee from the battle
-	TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) const; //returns stacks on battlefield
-
-	int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible
-
-	const CGHeroInstance * battleGetMyHero() const;
-	InfoAboutHero battleGetEnemyHero() const;
-};

+ 1 - 1
lib/CGameInfoCallback.cpp

@@ -15,7 +15,7 @@
 #include "CGeneralTextHandler.h"
 #include "mapObjects/CObjectHandler.h" // for CGObjectInstance
 #include "StartInfo.h" // for StartInfo
-#include "BattleInfo.h" // for BattleInfo
+#include "battle/BattleInfo.h" // for BattleInfo
 #include "NetPacks.h" // for InfoWindow
 #include "CModHandler.h"
 #include "spells/CSpellHandler.h"

+ 1 - 1
lib/CGameInfoCallback.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include "ResourceSet.h" // for Res::ERes
-#include "CBattleCallback.h" //for CCallbackBase
+#include "battle/CPlayerBattleCallback.h"
 
 /*
  * CGameInfoCallback.h, part of VCMI engine

+ 1 - 1
lib/CGameInterface.h

@@ -1,7 +1,7 @@
 #pragma once
 
 
-#include "BattleAction.h"
+#include "battle/BattleAction.h"
 #include "IGameEventsReceiver.h"
 #include "CGameStateFwd.h"
 

+ 1 - 1
lib/CGameState.cpp

@@ -16,7 +16,7 @@
 #include "StartInfo.h"
 #include "NetPacks.h"
 #include "registerTypes/RegisterTypes.h"
-#include "BattleInfo.h"
+#include "battle/BattleInfo.h"
 #include "JsonNode.h"
 #include "filesystem/Filesystem.h"
 #include "GameConstants.h"

+ 1 - 1
lib/CHeroHandler.cpp

@@ -6,7 +6,7 @@
 #include "VCMI_Lib.h"
 #include "JsonNode.h"
 #include "StringConstants.h"
-#include "BattleHex.h"
+#include "battle/BattleHex.h"
 #include "CCreatureHandler.h"
 #include "CModHandler.h"
 #include "CTownHandler.h"

+ 14 - 8
lib/CMakeLists.txt

@@ -76,14 +76,20 @@ set(lib_SRCS
 		spells/CDefaultSpellMechanics.cpp
 		spells/ViewSpellInt.cpp
 
-		BattleAction.cpp
-		BattleHex.cpp
-                BattleInfo.cpp
-                SiegeInfo.cpp
-                SideInBattle.cpp
-                CStack.cpp
+		battle/BattleAction.cpp
+		battle/BattleHex.cpp
+		battle/BattleInfo.cpp
+		battle/AccessibilityInfo.cpp
+		battle/BattleAttackInfo.cpp
+		battle/CBattleInfoCallback.cpp
+		battle/CBattleInfoEssentials.cpp
+		battle/CCallbackBase.cpp
+		battle/CPlayerBattleCallback.cpp
+		battle/ReachabilityInfo.cpp
+		SiegeInfo.cpp
+		SideInBattle.cpp
+		CStack.cpp
 		CArtHandler.cpp
-		CBattleCallback.cpp
 		CBonusTypeHandler.cpp
 		CBuildingHandler.cpp
 		CConfigHandler.cpp
@@ -94,7 +100,7 @@ set(lib_SRCS
 		CGeneralTextHandler.cpp
 		CHeroHandler.cpp
 		CModHandler.cpp
-		CObstacleInstance.cpp
+		battle/CObstacleInstance.cpp
 		CRandomGenerator.cpp
 
 		CThreadHelper.cpp

+ 1 - 1
lib/CStack.cpp

@@ -9,7 +9,7 @@
  */
 #include "StdInc.h"
 #include "CStack.h"
-#include "BattleInfo.h"
+#include "battle/BattleInfo.h"
 #include "spells/CSpellHandler.h"
 #include "CRandomGenerator.h"
 #include "NetPacks.h"

+ 1 - 1
lib/CStack.h

@@ -8,7 +8,7 @@
  *
  */
 #pragma once
-#include "BattleHex.h"
+#include "battle/BattleHex.h"
 #include "CCreatureHandler.h"
 #include "mapObjects/CGHeroInstance.h" // for commander serialization
 

+ 1 - 1
lib/CTownHandler.h

@@ -6,7 +6,7 @@
 #include "GameConstants.h"
 #include "IHandlerBase.h"
 #include "LogicalExpression.h"
-#include "BattleHex.h"
+#include "battle/BattleHex.h"
 
 /*
  * CTownHandler.h, part of VCMI engine

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -10,7 +10,7 @@
 #pragma once
 
 
-#include "BattleHex.h"
+#include "battle/BattleHex.h"
 #include "int3.h"
 
 class CGTownInstance;

+ 2 - 2
lib/NetPacks.h

@@ -2,14 +2,14 @@
 
 #include "NetPacksBase.h"
 
-#include "BattleAction.h"
+#include "battle/BattleAction.h"
 #include "mapObjects/CGHeroInstance.h"
 #include "ConstTransitivePtr.h"
 #include "int3.h"
 #include "ResourceSet.h"
 #include "CGameStateFwd.h"
 #include "mapping/CMapDefines.h"
-#include "CObstacleInstance.h"
+#include "battle/CObstacleInstance.h"
 
 #include "spells/ViewSpellInt.h"
 

+ 1 - 1
lib/NetPacksLib.cpp

@@ -13,7 +13,7 @@
 #include "CCreatureHandler.h"
 #include "CGameState.h"
 #include "CStack.h"
-#include "BattleInfo.h"
+#include "battle/BattleInfo.h"
 #include "CTownHandler.h"
 #include "mapping/CMapInfo.h"
 #include "StartInfo.h"

+ 22 - 10
lib/VCMI_lib.cbp

@@ -125,16 +125,28 @@
 		<Unit filename="../Version.h" />
 		<Unit filename="../include/vstd/CLoggerBase.h" />
 		<Unit filename="AI_Base.h" />
-		<Unit filename="BattleAction.cpp" />
-		<Unit filename="BattleAction.h" />
-		<Unit filename="BattleHex.cpp" />
-		<Unit filename="BattleHex.h" />
-		<Unit filename="BattleInfo.cpp" />
-		<Unit filename="BattleInfo.h" />
+		<Unit filename="battle/BattleAction.cpp" />
+		<Unit filename="battle/BattleAction.h" />
+		<Unit filename="battle/BattleHex.cpp" />
+		<Unit filename="battle/BattleHex.h" />
+		<Unit filename="battle/BattleInfo.cpp" />
+		<Unit filename="battle/BattleInfo.h" />
+		<Unit filename="battle/AccessibilityInfo.cpp" />
+		<Unit filename="battle/AccessibilityInfo.h" />
+		<Unit filename="battle/BattleAttackInfo.cpp" />
+		<Unit filename="battle/BattleAttackInfo.h" />
+		<Unit filename="battle/CBattleInfoCallback.cpp" />
+		<Unit filename="battle/CBattleInfoCallback.h" />
+		<Unit filename="battle/CBattleInfoEssentials.cpp" />
+		<Unit filename="battle/CBattleInfoEssentials.h" />
+		<Unit filename="battle/CCallbackBase.cpp" />
+		<Unit filename="battle/CCallbackBase.h" />
+		<Unit filename="battle/CPlayerBattleCallback.cpp" />
+		<Unit filename="battle/CPlayerBattleCallback.h" />
+		<Unit filename="battle/ReachabilityInfo.cpp" />
+		<Unit filename="battle/ReachabilityInfo.h" />
 		<Unit filename="CArtHandler.cpp" />
 		<Unit filename="CArtHandler.h" />
-		<Unit filename="CBattleCallback.cpp" />
-		<Unit filename="CBattleCallback.h" />
 		<Unit filename="CBonusTypeHandler.cpp" />
 		<Unit filename="CBonusTypeHandler.h" />
 		<Unit filename="CBuildingHandler.cpp" />
@@ -161,8 +173,8 @@
 		<Unit filename="CMakeLists.txt" />
 		<Unit filename="CModHandler.cpp" />
 		<Unit filename="CModHandler.h" />
-		<Unit filename="CObstacleInstance.cpp" />
-		<Unit filename="CObstacleInstance.h" />
+		<Unit filename="battle/CObstacleInstance.cpp" />
+		<Unit filename="battle/CObstacleInstance.h" />
 		<Unit filename="CPathfinder.cpp" />
 		<Unit filename="CPathfinder.h" />
 		<Unit filename="CPlayerState.h" />

+ 23 - 11
lib/VCMI_lib.vcxproj

@@ -168,9 +168,16 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include="BattleAction.cpp" />
-    <ClCompile Include="BattleHex.cpp" />
-    <ClCompile Include="BattleInfo.cpp" />
+    <ClCompile Include="battle\BattleAction.cpp" />
+    <ClCompile Include="battle\BattleHex.cpp" />
+    <ClCompile Include="battle\BattleInfo.cpp" />
+    <ClCompile Include="battle\AccessibilityInfo.cpp" />
+    <ClCompile Include="battle\BattleAttackInfo.cpp" />
+    <ClCompile Include="battle\CBattleInfoCallback.cpp" />
+    <ClCompile Include="battle\CBattleInfoEssentials.cpp" />
+    <ClCompile Include="battle\CCallbackBase.cpp" />
+    <ClCompile Include="battle\CPlayerBattleCallback.cpp" />
+    <ClCompile Include="battle\ReachabilityInfo.cpp" />
     <ClCompile Include="CArtHandler.cpp" />
     <ClCompile Include="CBonusTypeHandler.cpp" />
     <ClCompile Include="CBuildingHandler.cpp" />
@@ -183,7 +190,7 @@
     <ClCompile Include="CGeneralTextHandler.cpp" />
     <ClCompile Include="CHeroHandler.cpp" />
     <ClCompile Include="CModHandler.cpp" />
-    <ClCompile Include="CObstacleInstance.cpp" />
+    <ClCompile Include="battle\CObstacleInstance.cpp" />
     <ClCompile Include="CPathfinder.cpp" />
     <ClCompile Include="CStack.cpp" />
     <ClCompile Include="CThreadHelper.cpp" />
@@ -262,7 +269,6 @@
     <ClCompile Include="logging\CLogger.cpp" />
     <ClCompile Include="logging\CBasicLogConfigurator.cpp" />
     <ClCompile Include="HeroBonus.cpp" />
-    <ClCompile Include="CBattleCallback.cpp" />
     <ClCompile Include="IGameCallback.cpp" />
     <ClCompile Include="CGameInfoCallback.cpp" />
     <ClCompile Include="JsonNode.cpp" />
@@ -290,9 +296,16 @@
     <ClInclude Include="..\Global.h" />
     <ClInclude Include="..\Version.h" />
     <ClInclude Include="AI_Base.h" />
-    <ClInclude Include="BattleAction.h" />
-    <ClInclude Include="BattleHex.h" />
-    <ClInclude Include="BattleInfo.h" />
+    <ClInclude Include="battle\BattleAction.h" />
+    <ClInclude Include="battle\BattleHex.h" />
+    <ClInclude Include="battle\BattleInfo.h" />
+    <ClInclude Include="battle\AccessibilityInfo.h" />
+    <ClInclude Include="battle\BattleAttackInfo.h" />
+    <ClInclude Include="battle\CBattleInfoCallback.h" />
+    <ClInclude Include="battle\CBattleInfoEssentials.h" />
+    <ClInclude Include="battle\CCallbackBase.h" />
+    <ClInclude Include="battle\CPlayerBattleCallback.h" />
+    <ClInclude Include="battle\ReachabilityInfo.h" />
     <ClInclude Include="CArtHandler.h" />
     <ClInclude Include="CBonusTypeHandler.h" />
     <ClInclude Include="CBuildingHandler.h" />
@@ -306,7 +319,7 @@
     <ClInclude Include="CGeneralTextHandler.h" />
     <ClInclude Include="CHeroHandler.h" />
     <ClInclude Include="CModHandler.h" />
-    <ClInclude Include="CObstacleInstance.h" />
+    <ClInclude Include="battle\CObstacleInstance.h" />
     <ClInclude Include="CondSh.h" />
     <ClInclude Include="ConstTransitivePtr.h" />
     <ClInclude Include="CPathfinder.h" />
@@ -376,7 +389,6 @@
     <ClInclude Include="logging\CBasicLogConfigurator.h" />
     <ClInclude Include="GameConstants.h" />
     <ClInclude Include="HeroBonus.h" />
-    <ClInclude Include="CBattleCallback.h" />
     <ClInclude Include="IGameCallback.h" />
     <ClInclude Include="CGameInfoCallback.h" />
     <ClInclude Include="IGameEventsReceiver.h" />
@@ -425,4 +437,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>

+ 34 - 10
lib/VCMI_lib.vcxproj.filters

@@ -31,7 +31,7 @@
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="BattleAction.cpp" />
+    <ClCompile Include="battle\BattleAction.cpp" />
     <ClCompile Include="CArtHandler.cpp" />
     <ClCompile Include="CBuildingHandler.cpp" />
     <ClCompile Include="CCreatureHandler.cpp" />
@@ -49,14 +49,20 @@
     <ClCompile Include="ResourceSet.cpp" />
     <ClCompile Include="CGameInterface.cpp" />
     <ClCompile Include="JsonNode.cpp" />
-    <ClCompile Include="BattleHex.cpp" />
+    <ClCompile Include="battle\BattleHex.cpp" />
     <ClCompile Include="CConsoleHandler.cpp" />
     <ClCompile Include="CThreadHelper.cpp" />
     <ClCompile Include="StdInc.cpp" />
-    <ClCompile Include="CObstacleInstance.cpp" />
+    <ClCompile Include="battle\CObstacleInstance.cpp" />
     <ClCompile Include="CModHandler.cpp" />
     <ClCompile Include="CConfigHandler.cpp" />
-    <ClCompile Include="CBattleCallback.cpp" />
+    <ClCompile Include="battle\AccessibilityInfo.cpp" />
+    <ClCompile Include="battle\BattleAttackInfo.cpp" />
+    <ClCompile Include="battle\CBattleInfoCallback.cpp" />
+    <ClCompile Include="battle\CBattleInfoEssentials.cpp" />
+    <ClCompile Include="battle\CCallbackBase.cpp" />
+    <ClCompile Include="battle\CPlayerBattleCallback.cpp" />
+    <ClCompile Include="battle\ReachabilityInfo.cpp" />
     <ClCompile Include="Mapping\CCampaignHandler.cpp" />
     <ClCompile Include="GameConstants.cpp" />
     <ClCompile Include="VCMIDirs.cpp" />
@@ -263,7 +269,7 @@
     <ClCompile Include="CStack.cpp" />
     <ClCompile Include="SideInBattle.cpp" />
     <ClCompile Include="SiegeInfo.cpp" />
-    <ClCompile Include="BattleInfo.cpp" />
+    <ClCompile Include="battle\BattleInfo.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="CCreatureSet.h">
@@ -317,10 +323,10 @@
     <ClInclude Include="CTownHandler.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="BattleAction.h">
+    <ClInclude Include="battle\BattleAction.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="CObstacleInstance.h">
+    <ClInclude Include="battle\CObstacleInstance.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="IGameEventsReceiver.h">
@@ -344,7 +350,7 @@
     <ClInclude Include="AI_Base.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="BattleHex.h">
+    <ClInclude Include="battle\BattleHex.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="CConsoleHandler.h">
@@ -380,7 +386,25 @@
     <ClInclude Include="CConfigHandler.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="CBattleCallback.h">
+    <ClInclude Include="AccessibilityInfo.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="BattleAttackInfo.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="CBattleInfoCallback.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="CBattleInfoEssentials.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="CCallbackBase.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="CPlayerBattleCallback.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="ReachabilityInfo.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="Mapping\CCampaignHandler.h">
@@ -656,7 +680,7 @@
     <ClInclude Include="serializer\Connection.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="BattleInfo.h">
+    <ClInclude Include="battle\BattleInfo.h">
       <Filter>Header Files</Filter>
     </ClInclude>
     <ClInclude Include="CStack.h">

+ 51 - 0
lib/battle/AccessibilityInfo.cpp

@@ -0,0 +1,51 @@
+/*
+ * AccessibilityInfo.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 "AccessibilityInfo.h"
+#include "CStack.h"
+
+bool AccessibilityInfo::accessible(BattleHex tile, const CStack * stack) const
+{
+	return accessible(tile, stack->doubleWide(), stack->attackerOwned);
+}
+
+bool AccessibilityInfo::accessible(BattleHex tile, bool doubleWide, bool attackerOwned) const
+{
+	// All hexes that stack would cover if standing on tile have to be accessible.
+	for(auto hex : CStack::getHexes(tile, doubleWide, attackerOwned))
+	{
+		// If the hex is out of range then the tile isn't accessible
+		if(!hex.isValid())
+			return false;
+		// If we're no defender which step on gate and the hex isn't accessible, then the tile
+		// isn't accessible
+		else if(at(hex) != EAccessibility::ACCESSIBLE &&
+				!(at(hex) == EAccessibility::GATE && !attackerOwned))
+		{
+			return false;
+		}
+	}
+	return true;
+}
+
+bool AccessibilityInfo::occupiable(const CStack * stack, BattleHex tile) const
+{
+	//obviously, we can occupy tile by standing on it
+	if(accessible(tile, stack))
+		return true;
+	if(stack->doubleWide())
+	{
+		//Check the tile next to -> if stack stands there, it'll also occupy considered hex
+		const BattleHex anotherTile = tile + (stack->attackerOwned ? BattleHex::RIGHT : BattleHex::LEFT);
+		if(accessible(anotherTile, stack))
+			return true;
+	}
+	return false;
+}

+ 35 - 0
lib/battle/AccessibilityInfo.h

@@ -0,0 +1,35 @@
+/*
+ * AccessibilityInfo.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
+#include "BattleHex.h"
+
+class CStack;
+
+//Accessibility is property of hex in battle. It doesn't depend on stack, side's perspective and so on.
+enum class EAccessibility
+{
+	ACCESSIBLE,
+	ALIVE_STACK,
+	OBSTACLE,
+	DESTRUCTIBLE_WALL,
+	GATE, //sieges -> gate opens only for defender stacks
+	UNAVAILABLE, //indestructible wall parts, special battlefields (like boat-to-boat)
+	SIDE_COLUMN //used for first and last columns of hexes that are unavailable but wat machines can stand there
+};
+
+
+typedef std::array<EAccessibility, GameConstants::BFIELD_SIZE> TAccessibilityArray;
+
+struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
+{
+	bool occupiable(const CStack * stack, BattleHex tile) const;
+	bool accessible(BattleHex tile, const CStack * stack) const; //checks for both tiles if stack is double wide
+	bool accessible(BattleHex tile, bool doubleWide, bool attackerOwned) const; //checks for both tiles if stack is double wide
+};

+ 10 - 12
lib/BattleAction.cpp → lib/battle/BattleAction.cpp

@@ -1,9 +1,3 @@
-#include "StdInc.h"
-#include "BattleAction.h"
-
-#include "CStack.h"
-
-
 /*
  * BattleAction.cpp, part of VCMI engine
  *
@@ -14,6 +8,10 @@
  *
  */
 
+#include "StdInc.h"
+#include "BattleAction.h"
+#include "CStack.h"
+
 using namespace Battle;
 
 BattleAction::BattleAction():
@@ -26,7 +24,7 @@ BattleAction::BattleAction():
 {
 }
 
-BattleAction BattleAction::makeHeal(const CStack *healer, const CStack *healed)
+BattleAction BattleAction::makeHeal(const CStack * healer, const CStack * healed)
 {
 	BattleAction ba;
 	ba.side = !healer->attackerOwned;
@@ -36,7 +34,7 @@ BattleAction BattleAction::makeHeal(const CStack *healer, const CStack *healed)
 	return ba;
 }
 
-BattleAction BattleAction::makeDefend(const CStack *stack)
+BattleAction BattleAction::makeDefend(const CStack * stack)
 {
 	BattleAction ba;
 	ba.side = !stack->attackerOwned;
@@ -46,7 +44,7 @@ BattleAction BattleAction::makeDefend(const CStack *stack)
 }
 
 
-BattleAction BattleAction::makeMeleeAttack(const CStack *stack, const CStack * attacked, BattleHex attackFrom /*= BattleHex::INVALID*/)
+BattleAction BattleAction::makeMeleeAttack(const CStack * stack, const CStack * attacked, BattleHex attackFrom /*= BattleHex::INVALID*/)
 {
 	BattleAction ba;
 	ba.side = !stack->attackerOwned;
@@ -57,7 +55,7 @@ BattleAction BattleAction::makeMeleeAttack(const CStack *stack, const CStack * a
 	return ba;
 
 }
-BattleAction BattleAction::makeWait(const CStack *stack)
+BattleAction BattleAction::makeWait(const CStack * stack)
 {
 	BattleAction ba;
 	ba.side = !stack->attackerOwned;
@@ -66,7 +64,7 @@ BattleAction BattleAction::makeWait(const CStack *stack)
 	return ba;
 }
 
-BattleAction BattleAction::makeShotAttack(const CStack *shooter, const CStack *target)
+BattleAction BattleAction::makeShotAttack(const CStack * shooter, const CStack * target)
 {
 	BattleAction ba;
 	ba.side = !shooter->attackerOwned;
@@ -76,7 +74,7 @@ BattleAction BattleAction::makeShotAttack(const CStack *shooter, const CStack *t
 	return ba;
 }
 
-BattleAction BattleAction::makeMove(const CStack *stack, BattleHex dest)
+BattleAction BattleAction::makeMove(const CStack * stack, BattleHex dest)
 {
 	BattleAction ba;
 	ba.side = !stack->attackerOwned;

+ 10 - 13
lib/BattleAction.h → lib/battle/BattleAction.h

@@ -1,8 +1,3 @@
-#pragma once
-
-
-#include "BattleHex.h"
-
 /*
  * BattleAction.h, part of VCMI engine
  *
@@ -12,14 +7,16 @@
  * Full text of license available in license.txt file, in main folder
  *
  */
+#pragma once
+#include "BattleHex.h"
 
-/// A struct which handles battle actions like defending, walking,... - represents a creature stack in a battle
 class CStack;
 
+/// A struct which handles battle actions like defending, walking,... - represents a creature stack in a battle
 struct DLL_LINKAGE BattleAction
 {
 	ui8 side; //who made this action: false - left, true - right player
-	ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
+	ui32 stackNumber; //stack ID, -1 left hero, -2 right hero,
 	Battle::ActionType actionType; //use ActionType enum for values
 	BattleHex destinationTile;
 	si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6
@@ -32,12 +29,12 @@ struct DLL_LINKAGE BattleAction
 
 	BattleAction();
 
-	static BattleAction makeHeal(const CStack *healer, const CStack *healed);
-	static BattleAction makeDefend(const CStack *stack);
-	static BattleAction makeWait(const CStack *stack);
-	static BattleAction makeMeleeAttack(const CStack *stack, const CStack * attacked, BattleHex attackFrom = BattleHex::INVALID);
-	static BattleAction makeShotAttack(const CStack *shooter, const CStack *target);
-	static BattleAction makeMove(const CStack *stack, BattleHex dest);
+	static BattleAction makeHeal(const CStack * healer, const CStack * healed);
+	static BattleAction makeDefend(const CStack * stack);
+	static BattleAction makeWait(const CStack * stack);
+	static BattleAction makeMeleeAttack(const CStack * stack, const CStack * attacked, BattleHex attackFrom = BattleHex::INVALID);
+	static BattleAction makeShotAttack(const CStack * shooter, const CStack * target);
+	static BattleAction makeMove(const CStack * stack, BattleHex dest);
 	static BattleAction makeEndOFTacticPhase(ui8 side);
 };
 

+ 51 - 0
lib/battle/BattleAttackInfo.cpp

@@ -0,0 +1,51 @@
+/*
+ * BattleAttackInfo.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 "BattleAttackInfo.h"
+#include "CStack.h"
+
+
+BattleAttackInfo::BattleAttackInfo(const CStack * Attacker, const CStack * Defender, bool Shooting)
+{
+	attacker = Attacker;
+	defender = Defender;
+
+	attackerBonuses = Attacker;
+	defenderBonuses = Defender;
+
+	attackerPosition = Attacker->position;
+	defenderPosition = Defender->position;
+
+	attackerCount = Attacker->count;
+	defenderCount = Defender->count;
+
+	shooting = Shooting;
+	chargedFields = 0;
+
+	luckyHit = false;
+	unluckyHit = false;
+	deathBlow = false;
+	ballistaDoubleDamage = false;
+}
+
+BattleAttackInfo BattleAttackInfo::reverse() const
+{
+	BattleAttackInfo ret = *this;
+	std::swap(ret.attacker, ret.defender);
+	std::swap(ret.attackerBonuses, ret.defenderBonuses);
+	std::swap(ret.attackerPosition, ret.defenderPosition);
+	std::swap(ret.attackerCount, ret.defenderCount);
+
+	ret.shooting = false;
+	ret.chargedFields = 0;
+	ret.luckyHit = ret.ballistaDoubleDamage = ret.deathBlow = false;
+
+	return ret;
+}

+ 33 - 0
lib/battle/BattleAttackInfo.h

@@ -0,0 +1,33 @@
+/*
+ * BattleAttackInfo.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
+#include "BattleHex.h"
+
+class CStack;
+class IBonusBearer;
+
+struct DLL_LINKAGE BattleAttackInfo
+{
+	const IBonusBearer *attackerBonuses, *defenderBonuses;
+	const CStack *attacker, *defender;
+	BattleHex attackerPosition, defenderPosition;
+
+	int attackerCount, defenderCount;
+	bool shooting;
+	int chargedFields;
+
+	bool luckyHit;
+	bool unluckyHit;
+	bool deathBlow;
+	bool ballistaDoubleDamage;
+
+	BattleAttackInfo(const CStack * Attacker, const CStack * Defender, bool Shooting = false);
+	BattleAttackInfo reverse() const;
+};

+ 0 - 0
lib/BattleHex.cpp → lib/battle/BattleHex.cpp


+ 1 - 1
lib/BattleHex.h → lib/battle/BattleHex.h

@@ -8,7 +8,7 @@
  *
  */
 #pragma once
-#include "GameConstants.h"
+#include "../GameConstants.h"
 
 // for battle stacks' positions
 struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class for better code design

+ 14 - 14
lib/BattleInfo.cpp → lib/battle/BattleInfo.cpp

@@ -57,7 +57,7 @@ int BattleInfo::getAvaliableHex(CreatureID creID, bool attackerOwned, int initia
 	return BattleHex::getClosestTile(attackerOwned, pos, occupyable);
 }
 
-std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, BattleHex dest, const CStack *stack)
+std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, BattleHex dest, const CStack * stack)
 {
 	auto reachability = getReachability(stack);
 
@@ -78,8 +78,8 @@ std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, Ba
 	return std::make_pair(path, reachability.distances[dest]);
 }
 
-ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender,
-	bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand )
+ui32 BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender,
+	bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand)
 {
 	TDmgRange range = calculateDmgRange(attacker, defender, shooting, charge, lucky, unlucky, deathBlow, ballistaDoubleDmg);
 
@@ -96,7 +96,7 @@ ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender,
 		return range.first;
 }
 
-void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const
+void BattleInfo::calculateCasualties(std::map<ui32,si32> * casualties) const
 {
 	for(auto & elem : stacks)//setting casualties
 	{
@@ -112,12 +112,12 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerO
 {
 	int stackID = getIdForNewStack();
 	PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
-	assert((owner >= PlayerColor::PLAYER_LIMIT)  ||
-		   (base.armyObj && base.armyObj->tempOwner == owner));
+	assert((owner >= PlayerColor::PLAYER_LIMIT) ||
+		(base.armyObj && base.armyObj->tempOwner == owner));
 
-	auto  ret = new CStack(&base, owner, stackID, attackerOwned, slot);
+	auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
 	ret->position = getAvaliableHex (base.getCreatureID(), attackerOwned, position); //TODO: what if no free tile on battlefield was found?
-	ret->state.insert(EBattleStackState::ALIVE);  //alive state indication
+	ret->state.insert(EBattleStackState::ALIVE); //alive state indication
 	return ret;
 }
 
@@ -125,9 +125,9 @@ CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool at
 {
 	int stackID = getIdForNewStack();
 	PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
-	auto  ret = new CStack(&base, owner, stackID, attackerOwned, slot);
+	auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
 	ret->position = position;
-	ret->state.insert(EBattleStackState::ALIVE);  //alive state indication
+	ret->state.insert(EBattleStackState::ALIVE); //alive state indication
 	return ret;
 }
 
@@ -261,7 +261,7 @@ struct RangeGenerator
 	std::function<int()> myRand;
 };
 
-BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town )
+BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town)
 {
 	CMP_stack cmpst;
 	auto curB = new BattleInfo();
@@ -644,7 +644,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
 	return curB;
 }
 
-const CGHeroInstance * BattleInfo::getHero( PlayerColor player ) const
+const CGHeroInstance * BattleInfo::getHero(PlayerColor player) const
 {
 	for(int i = 0; i < sides.size(); i++)
 		if(sides[i].color == player)
@@ -741,7 +741,7 @@ CGHeroInstance * BattleInfo::battleGetFightingHero(ui8 side) const
 }
 
 
-bool CMP_stack::operator()( const CStack* a, const CStack* b )
+bool CMP_stack::operator()(const CStack* a, const CStack* b)
 {
 	switch(phase)
 	{
@@ -772,7 +772,7 @@ bool CMP_stack::operator()( const CStack* a, const CStack* b )
 
 }
 
-CMP_stack::CMP_stack( int Phase /*= 1*/, int Turn )
+CMP_stack::CMP_stack(int Phase /*= 1*/, int Turn)
 {
 	phase = Phase;
 	turn = Turn;

+ 4 - 4
lib/BattleInfo.h → lib/battle/BattleInfo.h

@@ -11,7 +11,7 @@
 #include "SiegeInfo.h"
 #include "SideInBattle.h"
 #include "HeroBonus.h"
-#include "CBattleCallback.h"
+#include "battle/CBattleInfoCallback.h"
 #include "int3.h"
 
 class CStack;
@@ -61,7 +61,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
 	//static bool isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
 	int getAvaliableHex(CreatureID creID, bool attackerOwned, int initialPos = -1) const; //find place for summon / clone effects
 	//void makeBFS(BattleHex start, bool*accessibility, BattleHex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const; //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
-	std::pair< std::vector<BattleHex>, int > getPath(BattleHex start, BattleHex dest, const CStack *stack); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
+	std::pair< std::vector<BattleHex>, int > getPath(BattleHex start, BattleHex dest, const CStack * stack); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
 	//std::vector<BattleHex> getAccessibility(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = nullptr, bool forPassingBy = false) const; //returns vector of accessible tiles (taking into account the creature range)
 
 	//bool isObstacleVisibleForSide(const CObstacleInstance &obstacle, ui8 side) const;
@@ -69,7 +69,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
 	std::set<BattleHex> getStoppers(bool whichSidePerspective) const;
 
 	ui32 calculateDmg(const CStack * attacker, const CStack * defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand); //charge - number of hexes travelled before attack (for champion's jousting)
-	void calculateCasualties(std::map<ui32,si32> *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
+	void calculateCasualties(std::map<ui32,si32> * casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
 
 	//void getPotentiallyAttackableHexes(AttackableTiles &at, const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos); //hexes around target that could be attacked in melee
 	//std::set<CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks
@@ -84,7 +84,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
 	void localInit();
 
 	void localInitStack(CStack * s);
-	static BattleInfo * setupBattle( int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town );
+	static BattleInfo * setupBattle(int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town);
 	//bool hasNativeStack(ui8 side) const;
 
 	PlayerColor theOtherPlayer(PlayerColor player) const;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 142 - 507
lib/battle/CBattleInfoCallback.cpp


+ 110 - 0
lib/battle/CBattleInfoCallback.h

@@ -0,0 +1,110 @@
+/*
+ * CBattleCallback.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
+#include "CCallbackBase.h"
+#include "ReachabilityInfo.h"
+#include "BattleAttackInfo.h"
+
+class CGHeroInstance;
+class CStack;
+class ISpellCaster;
+class CSpell;
+struct CObstacleInstance;
+class IBonusBearer;
+class CRandomGenerator;
+
+struct DLL_LINKAGE AttackableTiles
+{
+	std::set<BattleHex> hostileCreaturePositions;
+	std::set<BattleHex> friendlyCreaturePositions; //for Dragon Breath
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & hostileCreaturePositions & friendlyCreaturePositions;
+	}
+};
+
+class DLL_LINKAGE CBattleInfoCallback : public virtual CBattleInfoEssentials
+{
+public:
+	enum ERandomSpell
+	{
+		RANDOM_GENIE, RANDOM_AIMED
+	};
+	//battle
+	boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
+
+	std::shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
+	const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const; //returns stack info by given pos
+	void battleGetStackQueue(std::vector<const CStack *> &out, const int howMany, const int turn = 0, int lastMoved = -1) const;
+	void battleGetStackCountOutsideHexes(bool *ac) const; // returns hexes which when in front of a stack cause us to move the amount box back
+
+	std::vector<BattleHex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = nullptr) const; //returns hexes reachable by creature with id ID (valid movement destinations), DOES contain stack current position
+
+	int battleGetSurrenderCost(PlayerColor Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
+	ReachabilityInfo::TDistances battleGetDistances(const CStack * stack, BattleHex hex = BattleHex::INVALID, BattleHex * predecessors = nullptr) const; //returns vector of distances to [dest hex number]
+	std::set<BattleHex> battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const;
+
+	bool battleCanAttack(const CStack * stack, const CStack * target, BattleHex dest) const; //determines if stack with given ID can attack target at the selected destination
+	bool battleCanShoot(const CStack * stack, BattleHex dest) const; //determines if stack with given ID shoot at the selected destination
+	bool battleIsStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack
+	std::set<const CStack*> batteAdjacentCreatures (const CStack * stack) const;
+
+	TDmgRange calculateDmgRange(const BattleAttackInfo & info) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
+	TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, TQuantity attackerCount, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
+	TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
+
+	//hextowallpart //int battleGetWallUnderHex(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
+	std::pair<ui32, ui32> battleEstimateDamage(CRandomGenerator & rand, const BattleAttackInfo & bai, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
+	std::pair<ui32, ui32> battleEstimateDamage(CRandomGenerator & rand, const CStack * attacker, const CStack * defender, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
+	si8 battleHasDistancePenalty(const CStack * stack, BattleHex destHex) const;
+	si8 battleHasDistancePenalty(const IBonusBearer * bonusBearer, BattleHex shooterPosition, BattleHex destHex) const;
+	si8 battleHasWallPenalty(const CStack * stack, BattleHex destHex) const; //checks if given stack has wall penalty
+	si8 battleHasWallPenalty(const IBonusBearer * bonusBearer, BattleHex shooterPosition, BattleHex destHex) const; //checks if given stack has wall penalty
+
+	BattleHex wallPartToBattleHex(EWallPart::EWallPart part) const;
+	EWallPart::EWallPart battleHexToWallPart(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
+	bool isWallPartPotentiallyAttackable(EWallPart::EWallPart wallPart) const; // returns true if the wall part is potentially attackable (independent of wall state), false if not
+	std::vector<BattleHex> getAttackableBattleHexes() const;
+
+	//*** MAGIC
+	si8 battleMaxSpellLevel(ui8 side) const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
+	ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
+	ESpellCastProblem::ESpellCastProblem battleCanCastSpell(const ISpellCaster * caster, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell
+
+	SpellID battleGetRandomStackSpell(CRandomGenerator & rand, const CStack * stack, ERandomSpell mode) const;
+	SpellID getRandomBeneficialSpell(CRandomGenerator & rand, const CStack * subject) const;
+	SpellID getRandomCastedSpell(CRandomGenerator & rand, const CStack * caster) const; //called at the beginning of turn for Faerie Dragon
+
+	const CStack * getStackIf(std::function<bool(const CStack*)> pred) const;
+
+	si8 battleHasShootingPenalty(const CStack * stack, BattleHex destHex);
+	si8 battleCanTeleportTo(const CStack * stack, BattleHex destHex, int telportLevel) const; //checks if teleportation of given stack to given position can take place
+
+	//convenience methods using the ones above
+	bool isInTacticRange(BattleHex dest) const;
+	si8 battleGetTacticDist() const; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
+
+	AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const; //TODO: apply rotation to two-hex attacker
+	std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
+	bool isToReverse(BattleHex hexFrom, BattleHex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir) const; //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
+	bool isToReverseHlp(BattleHex hexFrom, BattleHex hexTo, bool curDir) const; //helper for isToReverse
+
+	ReachabilityInfo getReachability(const CStack *stack) const;
+	ReachabilityInfo getReachability(const ReachabilityInfo::Parameters & params) const;
+	AccessibilityInfo getAccesibility() const;
+	AccessibilityInfo getAccesibility(const CStack *stack) const; //Hexes ocupied by stack will be marked as accessible.
+	AccessibilityInfo getAccesibility(const std::vector<BattleHex> & accessibleHexes) const; //given hexes will be marked as accessible
+	std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const;
+protected:
+	ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters & params) const;
+	ReachabilityInfo makeBFS(const AccessibilityInfo & accessibility, const ReachabilityInfo::Parameters & params) const;
+	ReachabilityInfo makeBFS(const CStack * stack) const; //uses default parameters -> stack position and owner's perspective
+	std::set<BattleHex> getStoppers(BattlePerspective::BattlePerspective whichSidePerspective) const; //get hexes with stopping obstacles (quicksands)
+};

+ 349 - 0
lib/battle/CBattleInfoEssentials.cpp

@@ -0,0 +1,349 @@
+/*
+ * CBattleInfoEssentials.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 "CBattleInfoEssentials.h"
+#include "CStack.h"
+#include "BattleInfo.h"
+#include "NetPacks.h"
+#include "mapObjects/CGTownInstance.h"
+
+ETerrainType CBattleInfoEssentials::battleTerrainType() const
+{
+	RETURN_IF_NOT_BATTLE(ETerrainType::WRONG);
+	return getBattle()->terrainType;
+}
+
+BFieldType CBattleInfoEssentials::battleGetBattlefieldType() const
+{
+	RETURN_IF_NOT_BATTLE(BFieldType::NONE);
+	return getBattle()->battlefieldType;
+}
+
+std::vector<std::shared_ptr<const CObstacleInstance> > CBattleInfoEssentials::battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective /*= boost::none*/) const
+{
+	std::vector<std::shared_ptr<const CObstacleInstance> > ret;
+	RETURN_IF_NOT_BATTLE(ret);
+
+	if(!perspective)
+	{
+		//if no particular perspective request, use default one
+		perspective = battleGetMySide();
+	}
+	else
+	{
+		if(!!player && *perspective != battleGetMySide())
+		{
+			logGlobal->error("Unauthorized access attempt!");
+			assert(0); //I want to notice if that happens
+			//perspective = battleGetMySide();
+		}
+	}
+
+	for(auto oi : getBattle()->obstacles)
+	{
+		if(getBattle()->battleIsObstacleVisibleForSide(*oi, *perspective))
+			ret.push_back(oi);
+	}
+
+	return ret;
+}
+
+bool CBattleInfoEssentials::battleIsObstacleVisibleForSide(const CObstacleInstance & coi, BattlePerspective::BattlePerspective side) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	return side == BattlePerspective::ALL_KNOWING || coi.visibleForSide(side, battleHasNativeStack(side));
+}
+
+bool CBattleInfoEssentials::battleHasNativeStack(ui8 side) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+
+	for(const CStack * s : battleGetAllStacks())
+	{
+		if(s->attackerOwned == !side && s->getCreature()->isItNativeTerrain(getBattle()->terrainType))
+			return true;
+	}
+
+	return false;
+}
+
+TStacks CBattleInfoEssentials::battleGetAllStacks(bool includeTurrets /*= false*/) const
+{
+	return battleGetStacksIf([=](const CStack * s)
+	{
+		return !s->isGhost() && (includeTurrets || !s->isTurret());
+	});
+}
+
+TStacks CBattleInfoEssentials::battleGetStacksIf(TStackFilter predicate) const
+{
+	TStacks ret;
+	RETURN_IF_NOT_BATTLE(ret);
+
+	vstd::copy_if(getBattle()->stacks, std::back_inserter(ret), predicate);
+
+	return ret;
+}
+
+TStacks CBattleInfoEssentials::battleAliveStacks() const
+{
+	return battleGetStacksIf([](const CStack * s){
+		return s->isValidTarget(false);
+	});
+}
+
+TStacks CBattleInfoEssentials::battleAliveStacks(ui8 side) const
+{
+	return battleGetStacksIf([=](const CStack * s){
+		return s->isValidTarget(false) && s->attackerOwned == !side;
+	});
+}
+
+int CBattleInfoEssentials::battleGetMoatDmg() const
+{
+	RETURN_IF_NOT_BATTLE(0);
+	auto town = getBattle()->town;
+	if(!town)
+		return 0;
+	return town->town->moatDamage;
+}
+
+const CGTownInstance * CBattleInfoEssentials::battleGetDefendedTown() const
+{
+	RETURN_IF_NOT_BATTLE(nullptr);
+	if(!getBattle() || getBattle()->town == nullptr)
+		return nullptr;
+	return getBattle()->town;
+}
+
+BattlePerspective::BattlePerspective CBattleInfoEssentials::battleGetMySide() const
+{
+	RETURN_IF_NOT_BATTLE(BattlePerspective::INVALID);
+	if(!player || player.get().isSpectator())
+		return BattlePerspective::ALL_KNOWING;
+	if(*player == getBattle()->sides[0].color)
+		return BattlePerspective::LEFT_SIDE;
+	if(*player == getBattle()->sides[1].color)
+		return BattlePerspective::RIGHT_SIDE;
+
+	logGlobal->errorStream() << "Cannot find player " << *player << " in battle!";
+	return BattlePerspective::INVALID;
+}
+
+const CStack * CBattleInfoEssentials::battleActiveStack() const
+{
+	RETURN_IF_NOT_BATTLE(nullptr);
+	return battleGetStackByID(getBattle()->activeStack);
+}
+
+const CStack* CBattleInfoEssentials::battleGetStackByID(int ID, bool onlyAlive) const
+{
+	RETURN_IF_NOT_BATTLE(nullptr);
+
+	auto stacks = battleGetStacksIf([=](const CStack * s)
+	{
+		return s->ID == ID && (!onlyAlive || s->alive());
+	});
+
+	if(stacks.empty())
+		return nullptr;
+	else
+		return stacks[0];
+}
+
+bool CBattleInfoEssentials::battleDoWeKnowAbout(ui8 side) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	auto p = battleGetMySide();
+	return p == BattlePerspective::ALL_KNOWING || p == side;
+}
+
+si8 CBattleInfoEssentials::battleTacticDist() const
+{
+	RETURN_IF_NOT_BATTLE(0);
+	return getBattle()->tacticDistance;
+}
+
+si8 CBattleInfoEssentials::battleGetTacticsSide() const
+{
+	RETURN_IF_NOT_BATTLE(-1);
+	return getBattle()->tacticsSide;
+}
+
+const CGHeroInstance * CBattleInfoEssentials::battleGetFightingHero(ui8 side) const
+{
+	RETURN_IF_NOT_BATTLE(nullptr);
+	if(side > 1)
+	{
+		logGlobal->errorStream() << "FIXME: " <<  __FUNCTION__ << " wrong argument!";
+		return nullptr;
+	}
+
+	if(!battleDoWeKnowAbout(side))
+	{
+		logGlobal->errorStream() << "FIXME: " <<  __FUNCTION__ << " access check ";
+		return nullptr;
+	}
+
+	return getBattle()->sides[side].hero;
+}
+
+const CArmedInstance * CBattleInfoEssentials::battleGetArmyObject(ui8 side) const
+{
+	RETURN_IF_NOT_BATTLE(nullptr);
+	if(side > 1)
+	{
+		logGlobal->errorStream() << "FIXME: " <<  __FUNCTION__ << " wrong argument!";
+		return nullptr;
+	}
+	if(!battleDoWeKnowAbout(side))
+	{
+		logGlobal->errorStream() << "FIXME: " <<  __FUNCTION__ << " access check ";
+		return nullptr;
+	}
+	return getBattle()->sides[side].armyObject;
+}
+
+InfoAboutHero CBattleInfoEssentials::battleGetHeroInfo(ui8 side) const
+{
+	auto hero = getBattle()->sides[side].hero;
+	if(!hero)
+	{
+		logGlobal->warnStream() << __FUNCTION__ << ": side " << (int)side << " does not have hero!";
+		return InfoAboutHero();
+	}
+	InfoAboutHero::EInfoLevel infoLevel = battleDoWeKnowAbout(side) ? InfoAboutHero::EInfoLevel::DETAILED : InfoAboutHero::EInfoLevel::BASIC;
+	return InfoAboutHero(hero, infoLevel);
+}
+
+int CBattleInfoEssentials::battleCastSpells(ui8 side) const
+{
+	RETURN_IF_NOT_BATTLE(-1);
+	return getBattle()->sides[side].castSpellsCount;
+}
+
+const IBonusBearer * CBattleInfoEssentials::getBattleNode() const
+{
+	return getBattle();
+}
+
+bool CBattleInfoEssentials::battleCanFlee(PlayerColor player) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	const si8 mySide = playerToSide(player);
+	const CGHeroInstance *myHero = battleGetFightingHero(mySide);
+
+	//current player have no hero
+	if(!myHero)
+		return false;
+
+	//eg. one of heroes is wearing shakles of war
+	if(myHero->hasBonusOfType(Bonus::BATTLE_NO_FLEEING))
+		return false;
+
+	//we are besieged defender
+	if(mySide == BattleSide::DEFENDER && battleGetSiegeLevel())
+	{
+		auto town = battleGetDefendedTown();
+		if(!town->hasBuilt(BuildingID::ESCAPE_TUNNEL, ETownType::STRONGHOLD))
+			return false;
+	}
+
+	return true;
+}
+
+si8 CBattleInfoEssentials::playerToSide(PlayerColor player) const
+{
+	RETURN_IF_NOT_BATTLE(-1);
+	int ret = vstd::find_pos_if(getBattle()->sides, [=](const SideInBattle &side){ return side.color == player; });
+	if(ret < 0)
+		logGlobal->warnStream() << "Cannot find side for player " << player;
+
+	return ret;
+}
+
+bool CBattleInfoEssentials::playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	const si8 playerSide = playerToSide(player);
+	if (playerSide >= 0)
+	{
+		if (getBattle()->sides[!playerSide].hero == h)
+			return true;
+	}
+	return false;
+}
+
+ui8 CBattleInfoEssentials::battleGetSiegeLevel() const
+{
+	RETURN_IF_NOT_BATTLE(0);
+	return getBattle()->town ? getBattle()->town->fortLevel() : CGTownInstance::NONE;
+}
+
+bool CBattleInfoEssentials::battleCanSurrender(PlayerColor player) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	ui8 mySide = playerToSide(player);
+	bool iAmSiegeDefender = (mySide == BattleSide::DEFENDER && battleGetSiegeLevel());
+	//conditions like for fleeing (except escape tunnel presence) + enemy must have a hero
+	return battleCanFlee(player) && !iAmSiegeDefender && battleHasHero(!mySide);
+}
+
+bool CBattleInfoEssentials::battleHasHero(ui8 side) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	assert(side < 2);
+	return getBattle()->sides[side].hero;
+}
+
+si8 CBattleInfoEssentials::battleGetWallState(int partOfWall) const
+{
+	RETURN_IF_NOT_BATTLE(0);
+	if(getBattle()->town == nullptr || getBattle()->town->fortLevel() == CGTownInstance::NONE)
+		return EWallState::NONE;
+
+	assert(partOfWall >= 0 && partOfWall < EWallPart::PARTS_COUNT);
+	return getBattle()->si.wallState[partOfWall];
+}
+
+EGateState CBattleInfoEssentials::battleGetGateState() const
+{
+	RETURN_IF_NOT_BATTLE(EGateState::NONE);
+	if(getBattle()->town == nullptr || getBattle()->town->fortLevel() == CGTownInstance::NONE)
+		return EGateState::NONE;
+
+	return getBattle()->si.gateState;
+}
+
+PlayerColor CBattleInfoEssentials::battleGetOwner(const CStack * stack) const
+{
+	RETURN_IF_NOT_BATTLE(PlayerColor::CANNOT_DETERMINE);
+	if(stack->hasBonusOfType(Bonus::HYPNOTIZED))
+		return getBattle()->theOtherPlayer(stack->owner);
+	else
+		return stack->owner;
+}
+
+const CGHeroInstance * CBattleInfoEssentials::battleGetOwnerHero(const CStack * stack) const
+{
+	RETURN_IF_NOT_BATTLE(nullptr);
+	return getBattle()->sides.at(playerToSide(battleGetOwner(stack))).hero;
+}
+
+bool CBattleInfoEssentials::battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness /* = false*/) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	if(boost::logic::indeterminate(positivness))
+		return true;
+	else if(defender->owner != battleGetOwner(defender))
+		return true; //mind controlled unit is attackable for both sides
+	else
+		return (battleGetOwner(attacker) == battleGetOwner(defender)) == positivness;
+}

+ 108 - 0
lib/battle/CBattleInfoEssentials.h

@@ -0,0 +1,108 @@
+/*
+ * CBattleInfoEssentials.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
+#include "CCallbackBase.h"
+
+class CGTownInstance;
+class CGHeroInstance;
+class CStack;
+struct CObstacleInstance;
+class IBonusBearer;
+struct InfoAboutHero;
+class CArmedInstance;
+
+typedef std::vector<const CStack*> TStacks;
+typedef std::function<bool(const CStack *)> TStackFilter;
+
+namespace BattlePerspective
+{
+	enum BattlePerspective
+	{
+		INVALID = -2,
+		ALL_KNOWING = -1,
+		LEFT_SIDE,
+		RIGHT_SIDE
+	};
+}
+
+namespace BattleSide
+{
+	enum {ATTACKER = 0, DEFENDER = 1};
+}
+
+
+class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
+{
+protected:
+	bool battleDoWeKnowAbout(ui8 side) const;
+	const IBonusBearer * getBattleNode() const;
+public:
+	enum EStackOwnership
+	{
+		ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
+	};
+
+	BattlePerspective::BattlePerspective battleGetMySide() const;
+
+	ETerrainType battleTerrainType() const;
+	BFieldType battleGetBattlefieldType() const;
+	std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
+
+	/** @brief Main method for getting battle stacks
+	 *
+	 * @param predicate Functor that shall return true for desired stack
+	 * @return filtered stacks
+	 *
+	 */
+	TStacks battleGetStacksIf(TStackFilter predicate) const;
+
+	bool battleHasNativeStack(ui8 side) const;
+	int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
+	const CGTownInstance * battleGetDefendedTown() const; //returns defended town if current battle is a siege, nullptr instead
+	const CStack *battleActiveStack() const;
+	si8 battleTacticDist() const; //returns tactic distance in current tactics phase; 0 if not in tactics phase
+	si8 battleGetTacticsSide() const; //returns which side is in tactics phase, undefined if none (?)
+	bool battleCanFlee(PlayerColor player) const;
+	bool battleCanSurrender(PlayerColor player) const;
+	si8 playerToSide(PlayerColor player) const;
+	bool playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const;
+	ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
+	bool battleHasHero(ui8 side) const;
+	int battleCastSpells(ui8 side) const; //how many spells has given side cast
+	const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
+	const CArmedInstance * battleGetArmyObject(ui8 side) const;
+	InfoAboutHero battleGetHeroInfo(ui8 side) const;
+
+	// for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall,
+	// [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
+	si8 battleGetWallState(int partOfWall) const;
+	EGateState battleGetGateState() const;
+
+	//helpers
+	///returns all stacks, alive or dead or undead or mechanical :)
+	TStacks battleGetAllStacks(bool includeTurrets = false) const;
+
+	///returns all alive stacks excluding turrets
+	TStacks battleAliveStacks() const;
+	///returns all alive stacks from particular side excluding turrets
+	TStacks battleAliveStacks(ui8 side) const;
+	const CStack * battleGetStackByID(int ID, bool onlyAlive = true) const; //returns stack info by given ID
+	bool battleIsObstacleVisibleForSide(const CObstacleInstance & coi, BattlePerspective::BattlePerspective side) const;
+
+	///returns player that controls given stack; mind control included
+	PlayerColor battleGetOwner(const CStack * stack) const;
+
+	///returns hero that controls given stack; nullptr if none; mind control included
+	const CGHeroInstance * battleGetOwnerHero(const CStack * stack) const;
+
+	///check that stacks are controlled by same|other player(s) depending on positiveness
+	///mind control included
+	bool battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness = false) const;
+};

+ 42 - 0
lib/battle/CCallbackBase.cpp

@@ -0,0 +1,42 @@
+/*
+ * CCallbackBase.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 "CCallbackBase.h"
+#include "BattleInfo.h"
+#include "CGameState.h"
+
+bool CCallbackBase::duringBattle() const
+{
+	return getBattle() != nullptr;
+}
+
+const BattleInfo *CCallbackBase::getBattle() const
+{
+	return battle;
+}
+
+CCallbackBase::CCallbackBase(CGameState * GS, boost::optional<PlayerColor> Player)
+	: battle(nullptr), gs(GS), player(Player)
+{}
+
+CCallbackBase::CCallbackBase()
+	: battle(nullptr), gs(nullptr)
+{}
+
+void CCallbackBase::setBattle(const BattleInfo * B)
+{
+	battle = B;
+}
+
+boost::optional<PlayerColor> CCallbackBase::getPlayerID() const
+{
+	return player;
+}
+

+ 42 - 0
lib/battle/CCallbackBase.h

@@ -0,0 +1,42 @@
+/*
+ * CCallbackBase.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
+#include "GameConstants.h"
+
+#define RETURN_IF_NOT_BATTLE(X) if(!duringBattle()) {logGlobal->errorStream() << __FUNCTION__ << " called when no battle!"; return X; }
+
+class CGameState;
+struct BattleInfo;
+
+class CBattleInfoEssentials;
+
+//Basic class for various callbacks (interfaces called by players to get info about game and so forth)
+class DLL_LINKAGE CCallbackBase
+{
+	const BattleInfo * battle; //battle to which the player is engaged, nullptr if none or not applicable
+
+	const BattleInfo * getBattle() const;
+
+protected:
+	CGameState * gs;
+	boost::optional<PlayerColor> player; // not set gives access to all information, otherwise callback provides only information "visible" for player
+
+	CCallbackBase(CGameState * GS, boost::optional<PlayerColor> Player);
+	CCallbackBase();
+
+	void setBattle(const BattleInfo * B);
+	bool duringBattle() const;
+
+public:
+	boost::optional<PlayerColor> getPlayerID() const;
+
+	friend class CBattleInfoEssentials;
+};
+

+ 4 - 4
lib/CObstacleInstance.cpp → lib/battle/CObstacleInstance.cpp

@@ -69,7 +69,7 @@ std::vector<BattleHex> CObstacleInstance::getAffectedTiles() const
 
 // bool CObstacleInstance::spellGenerated() const
 // {
-// 	if(obstacleType == USUAL  ||  obstacleType == ABSOLUTE_OBSTACLE)
+// 	if(obstacleType == USUAL || obstacleType == ABSOLUTE_OBSTACLE)
 // 		return false;
 //
 // 	return true;
@@ -83,12 +83,12 @@ bool CObstacleInstance::visibleForSide(ui8 side, bool hasNativeStack) const
 
 bool CObstacleInstance::stopsMovement() const
 {
-	return obstacleType == QUICKSAND  ||  obstacleType == MOAT;
+	return obstacleType == QUICKSAND || obstacleType == MOAT;
 }
 
 bool CObstacleInstance::blocksTiles() const
 {
-	return obstacleType == USUAL  ||  obstacleType == ABSOLUTE_OBSTACLE  ||  obstacleType == FORCE_FIELD;
+	return obstacleType == USUAL || obstacleType == ABSOLUTE_OBSTACLE || obstacleType == FORCE_FIELD;
 }
 
 SpellCreatedObstacle::SpellCreatedObstacle()
@@ -113,7 +113,7 @@ bool SpellCreatedObstacle::visibleForSide(ui8 side, bool hasNativeStack) const
 		//we hide mines and not discovered quicksands
 		//quicksands are visible to the caster or if owned unit stepped into that particular patch
 		//additionally if side has a native unit, mines/quicksands will be visible
-		return casterSide == side  ||  visibleForAnotherSide  ||  hasNativeStack;
+		return casterSide == side || visibleForAnotherSide || hasNativeStack;
 	default:
 		assert(0);
 		return false;

+ 0 - 0
lib/CObstacleInstance.h → lib/battle/CObstacleInstance.h


+ 54 - 0
lib/battle/CPlayerBattleCallback.cpp

@@ -0,0 +1,54 @@
+/*
+ * CPlayerBattleCallback.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 "CPlayerBattleCallback.h"
+#include "CStack.h"
+#include "CGameState.h"
+
+bool CPlayerBattleCallback::battleCanFlee() const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	ASSERT_IF_CALLED_WITH_PLAYER
+			return CBattleInfoEssentials::battleCanFlee(*player);
+}
+
+TStacks CPlayerBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AND_ENEMY*/, bool onlyAlive /*= true*/) const
+{
+	if(whose != MINE_AND_ENEMY)
+	{
+		ASSERT_IF_CALLED_WITH_PLAYER
+	}
+
+	return battleGetStacksIf([=](const CStack * s){
+		const bool ownerMatches = (whose == MINE_AND_ENEMY)
+								|| (whose == ONLY_MINE && s->owner == player)
+								|| (whose == ONLY_ENEMY && s->owner != player);
+
+		return ownerMatches && s->isValidTarget(!onlyAlive);
+	});
+}
+
+int CPlayerBattleCallback::battleGetSurrenderCost() const
+{
+	RETURN_IF_NOT_BATTLE(-3)
+			ASSERT_IF_CALLED_WITH_PLAYER
+			return CBattleInfoCallback::battleGetSurrenderCost(*player);
+}
+
+const CGHeroInstance * CPlayerBattleCallback::battleGetMyHero() const
+{
+	return CBattleInfoEssentials::battleGetFightingHero(battleGetMySide());
+}
+
+InfoAboutHero CPlayerBattleCallback::battleGetEnemyHero() const
+{
+	return battleGetHeroInfo(!battleGetMySide());
+}
+

+ 26 - 0
lib/battle/CPlayerBattleCallback.h

@@ -0,0 +1,26 @@
+/*
+ * CPlayerBattleCallback.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
+#include "CBattleInfoCallback.h"
+
+class CGHeroInstance;
+
+class DLL_LINKAGE CPlayerBattleCallback : public CBattleInfoCallback
+{
+public:
+	bool battleCanFlee() const; //returns true if caller can flee from the battle
+	TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) const; //returns stacks on battlefield
+
+	int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible
+
+	const CGHeroInstance * battleGetMyHero() const;
+	InfoAboutHero battleGetEnemyHero() const;
+};
+

+ 43 - 0
lib/battle/ReachabilityInfo.cpp

@@ -0,0 +1,43 @@
+/*
+ * ReachabilityInfo.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 "ReachabilityInfo.h"
+#include "CStack.h"
+
+
+ReachabilityInfo::Parameters::Parameters()
+{
+	stack = nullptr;
+	perspective = BattlePerspective::ALL_KNOWING;
+	attackerOwned = doubleWide = flying = false;
+}
+
+ReachabilityInfo::Parameters::Parameters(const CStack * Stack)
+{
+	stack = Stack;
+	perspective = (BattlePerspective::BattlePerspective)(!Stack->attackerOwned);
+	startPosition = Stack->position;
+	doubleWide = stack->doubleWide();
+	attackerOwned = stack->attackerOwned;
+	flying = stack->hasBonusOfType(Bonus::FLYING);
+	knownAccessible = stack->getHexes();
+}
+
+ReachabilityInfo::ReachabilityInfo()
+{
+	distances.fill(INFINITE_DIST);
+	predecessors.fill(BattleHex::INVALID);
+}
+
+bool ReachabilityInfo::isReachable(BattleHex hex) const
+{
+	return distances[hex] < INFINITE_DIST;
+}

+ 52 - 0
lib/battle/ReachabilityInfo.h

@@ -0,0 +1,52 @@
+/*
+ * ReachabilityInfo.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
+#include "BattleHex.h"
+#include "CBattleInfoEssentials.h"
+#include "AccessibilityInfo.h"
+
+class CStack;
+
+// Reachability info is result of BFS calculation. It's dependent on stack (it's owner, whether it's flying),
+// startPosition and perpective.
+struct DLL_LINKAGE ReachabilityInfo
+{
+	typedef std::array<int, GameConstants::BFIELD_SIZE> TDistances;
+	typedef std::array<BattleHex, GameConstants::BFIELD_SIZE> TPredecessors;
+
+	enum { INFINITE_DIST = 1000000 };
+
+	struct DLL_LINKAGE Parameters
+	{
+		const CStack * stack; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
+
+		bool attackerOwned;
+		bool doubleWide;
+		bool flying;
+		std::vector<BattleHex> knownAccessible; //hexes that will be treated as accessible, even if they're occupied by stack (by default - tiles occupied by stack we do reachability for, so it doesn't block itself)
+
+		BattleHex startPosition; //assumed position of stack
+		BattlePerspective::BattlePerspective perspective; //some obstacles (eg. quicksands) may be invisible for some side
+
+		Parameters();
+		Parameters(const CStack * Stack);
+	};
+
+	Parameters params;
+	AccessibilityInfo accessibility;
+	TDistances distances;
+	TPredecessors predecessors;
+
+	ReachabilityInfo();
+
+	bool isReachable(BattleHex hex) const;
+};
+
+

+ 1 - 1
lib/registerTypes/RegisterTypes.h

@@ -11,7 +11,7 @@
 #include "../mapObjects/CRewardableConstructor.h"
 #include "../mapObjects/CommonConstructors.h"
 #include "../mapObjects/MapObjects.h"
-#include "../CObstacleInstance.h"
+#include "../battle/CObstacleInstance.h"
 
 /*
  * RegisterTypes.h, part of VCMI engine

+ 1 - 1
lib/registerTypes/TypesClientPacks2.cpp

@@ -3,7 +3,7 @@
 
 #include "../StartInfo.h"
 #include "../CStack.h"
-#include "../BattleInfo.h"
+#include "../battle/BattleInfo.h"
 #include "../CGameState.h"
 #include "../mapping/CMap.h"
 #include "../CModHandler.h"

+ 1 - 1
lib/registerTypes/TypesMapObjects2.cpp

@@ -3,7 +3,7 @@
 
 #include "../StartInfo.h"
 #include "../CStack.h"
-#include "../BattleInfo.h"
+#include "../battle/BattleInfo.h"
 #include "../CGameState.h"
 #include "../mapping/CMap.h"
 #include "../CModHandler.h"

+ 1 - 1
lib/spells/BattleSpellMechanics.cpp

@@ -13,7 +13,7 @@
 
 #include "../NetPacks.h"
 #include "../CStack.h"
-#include "../BattleInfo.h"
+#include "../battle/BattleInfo.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../mapObjects/CGTownInstance.h"
 

+ 1 - 1
lib/spells/CDefaultSpellMechanics.cpp

@@ -13,7 +13,7 @@
 #include "CDefaultSpellMechanics.h"
 
 #include "../CStack.h"
-#include "../BattleInfo.h"
+#include "../battle/BattleInfo.h"
 
 #include "../CGeneralTextHandler.h"
 

+ 2 - 2
lib/spells/CSpellHandler.cpp

@@ -23,8 +23,8 @@
 #include "../StringConstants.h"
 
 #include "../CStack.h"
-#include "../BattleInfo.h"
-#include "../CBattleCallback.h"
+#include "../battle/BattleInfo.h"
+#include "../battle/CBattleInfoCallback.h"
 #include "../CGameState.h" //todo: remove
 
 #include "../NetPacks.h" //todo: remove

+ 1 - 1
lib/spells/CSpellHandler.h

@@ -14,7 +14,7 @@
 #include "../ConstTransitivePtr.h"
 #include "../int3.h"
 #include "../GameConstants.h"
-#include "../BattleHex.h"
+#include "../battle/BattleHex.h"
 #include "../HeroBonus.h"
 
 class CGObjectInstance;

+ 1 - 1
lib/spells/CreatureSpellMechanics.cpp

@@ -14,7 +14,7 @@
 
 #include "../NetPacks.h"
 #include "../CStack.h"
-#include "../BattleInfo.h"
+#include "../battle/BattleInfo.h"
 
 ///AcidBreathDamageMechanics
 void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const

+ 1 - 1
lib/spells/ISpellMechanics.cpp

@@ -12,7 +12,7 @@
 #include "ISpellMechanics.h"
 
 #include "../CStack.h"
-#include "../BattleInfo.h"
+#include "../battle/BattleInfo.h"
 
 #include "../NetPacks.h"
 

+ 1 - 1
lib/spells/ISpellMechanics.h

@@ -11,7 +11,7 @@
 #pragma once
 
 #include "CSpellHandler.h"
-#include "../BattleHex.h"
+#include "../battle/BattleHex.h"
 
 
 ///callback to be provided by server

+ 1 - 1
server/CGameHandler.cpp

@@ -16,7 +16,7 @@
 #include "../lib/CCreatureHandler.h"
 #include "../lib/CGameState.h"
 #include "../lib/CStack.h"
-#include "../lib/BattleInfo.h"
+#include "../lib/battle/BattleInfo.h"
 #include "../lib/CondSh.h"
 #include "../lib/NetPacks.h"
 #include "../lib/VCMI_Lib.h"

+ 1 - 1
server/CGameHandler.h

@@ -3,7 +3,7 @@
 
 #include "../lib/FunctionList.h"
 #include "../lib/IGameCallback.h"
-#include "../lib/BattleAction.h"
+#include "../lib/battle/BattleAction.h"
 #include "CQuery.h"
 
 

+ 1 - 1
server/CQuery.cpp

@@ -1,7 +1,7 @@
 #include "StdInc.h"
 #include "CQuery.h"
 #include "CGameHandler.h"
-#include "../lib/BattleInfo.h"
+#include "../lib/battle/BattleInfo.h"
 #include "../lib/mapObjects/MiscObjects.h"
 
 boost::mutex Queries::mx;

+ 2 - 2
server/NetPacksServer.cpp

@@ -6,8 +6,8 @@
 #include "../lib/mapping/CMap.h"
 #include "../lib/CGameState.h"
 #include "../lib/CStack.h"
-#include "../lib/BattleInfo.h"
-#include "../lib/BattleAction.h"
+#include "../lib/battle/BattleInfo.h"
+#include "../lib/battle/BattleAction.h"
 #include "../lib/serializer/Connection.h"
 
 

+ 1 - 1
test/Battlefield.cpp

@@ -9,7 +9,7 @@
  */
 #include "StdInc.h"
 #include <boost/test/unit_test.hpp>
-#include "../lib/BattleHex.h"
+#include "../lib/battle/BattleHex.h"
 BOOST_AUTO_TEST_SUITE(BattlefieldHex_Suite)
 
 BOOST_AUTO_TEST_CASE(getNeighbouringTiles)

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.