Explorar el Código

* minor refactoring
* minor improvements in battle interface

mateuszb hace 15 años
padre
commit
56ec829049

+ 1 - 1
AI/StupidAI/StupidAI.cpp

@@ -242,7 +242,7 @@ void CStupidAI::print(const std::string &text) const
 BattleAction CStupidAI::goTowards(const CStack * stack, THex hex)
 {
 	THex realDest = hex;
-	int predecessors[BFIELD_SIZE];
+	THex predecessors[BFIELD_SIZE];
 	std::vector<int> dists = cb->battleGetDistances(stack, hex);
 	if(distToNearestNeighbour(hex, dists, &realDest) > BFIELD_SIZE)
 	{

+ 10 - 9
CCallback.cpp

@@ -523,20 +523,20 @@ const CStack* CBattleCallback::battleGetStackByPos(THex pos, bool onlyAlive)
 	return gs->curB->battleGetStack(pos, onlyAlive);
 }
 
-int CBattleCallback::battleGetPos(int stack)
+THex CBattleCallback::battleGetPos(int stack)
 {
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	if(!gs->curB)
 	{
 		tlog2<<"battleGetPos called when there is no battle!"<<std::endl;
-		return -1;
+		return THex::INVALID;
 	}
 	for(size_t g=0; g<gs->curB->stacks.size(); ++g)
 	{
 		if(gs->curB->stacks[g]->ID == stack)
 			return gs->curB->stacks[g]->position;
 	}
-	return -1;
+	return THex::INVALID;
 }
 
 std::vector<const CStack*> CBattleCallback::battleGetStacks(bool onlyAlive /*= true*/)
@@ -592,7 +592,7 @@ bool CBattleCallback::battleCanCastSpell()
 	if(!gs->curB) //there is no battle
 		return false;
 
-	if(gs->curB->side1 == player)
+	if(gs->curB->sides[0] == player)
 		return gs->curB->castSpells[0] == 0 && gs->curB->heroes[0] && gs->curB->heroes[0]->getArt(17);
 	else
 		return gs->curB->castSpells[1] == 0 && gs->curB->heroes[1] && gs->curB->heroes[1]->getArt(17);
@@ -620,7 +620,7 @@ ui8 CBattleCallback::battleGetWallState(int partOfWall)
 	return gs->curB->si.wallState[partOfWall];
 }
 
-int CBattleCallback::battleGetWallUnderHex(int hex)
+int CBattleCallback::battleGetWallUnderHex(THex hex)
 {
 	if(!gs->curB || gs->curB->siege == 0)
 	{
@@ -637,7 +637,7 @@ TDmgRange CBattleCallback::battleEstimateDamage(const CStack * attacker, const C
 	const CGHeroInstance * attackerHero, * defenderHero;
 	bool shooting = battleCanShoot(attacker, defender->position);
 
-	if(gs->curB->side1 == player)
+	if(gs->curB->sides[0] == player)
 	{
 		attackerHero = gs->curB->heroes[0];
 		defenderHero = gs->curB->heroes[1];
@@ -1060,14 +1060,15 @@ CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C )
 	cl = C;
 }
 
-std::vector<int> CBattleCallback::battleGetDistances(const CStack * stack, THex hex /*= THex::INVALID*/, int * predecessors /*= NULL*/)
+std::vector<int> CBattleCallback::battleGetDistances(const CStack * stack, THex hex /*= THex::INVALID*/, THex * predecessors /*= NULL*/)
 {
 	if(!hex.isValid())
 		hex = stack->position;
 
 	std::vector<int> ret;
 	bool ac[BFIELD_SIZE];
-	int pr[BFIELD_SIZE], dist[BFIELD_SIZE];
+	THex pr[BFIELD_SIZE];
+	int dist[BFIELD_SIZE];
 	gs->curB->makeBFS(stack->position, ac, pr, dist, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), false);
 
 	for(int i=0; i<BFIELD_SIZE; ++i)
@@ -1080,7 +1081,7 @@ std::vector<int> CBattleCallback::battleGetDistances(const CStack * stack, THex
 
 	if(predecessors)
 	{
-		memcpy(predecessors, pr, BFIELD_SIZE * sizeof(int));
+		memcpy(predecessors, pr, BFIELD_SIZE * sizeof(THex));
 	}
 
 	return ret;

+ 6 - 6
CCallback.h

@@ -80,18 +80,18 @@ public:
 	virtual std::vector<CObstacleInstance> battleGetAllObstacles()=0; //returns all obstacles on the battlefield
 	virtual const CStack * battleGetStackByID(int ID, bool onlyAlive = true)=0; //returns stack info by given ID
 	virtual const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true)=0; //returns stack info by given pos
-	virtual int battleGetPos(int stack)=0; //returns position (tile ID) of stack
+	virtual THex battleGetPos(int stack)=0; //returns position (tile ID) of stack
 	virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
 	virtual std::vector<const CStack*> battleGetStacks(bool onlyAlive = true)=0; //returns stacks on battlefield
 	virtual void getStackQueue( std::vector<const CStack *> &out, int howMany )=0; //returns vector of stack in order of their move sequence
 	virtual std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable)=0; //returns numbers of hexes reachable by creature with id ID
-	virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, int * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
+	virtual std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL)=0; //returns vector of distances to [dest hex number]
 	virtual bool battleCanShoot(const CStack * stack, THex dest)=0; //returns true if unit with id ID can shoot to dest
 	virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
 	virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle
 	virtual const CGTownInstance * battleGetDefendedTown()=0; //returns defended town if current battle is a siege, NULL instead
 	virtual ui8 battleGetWallState(int partOfWall)=0; //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
-	virtual int battleGetWallUnderHex(int hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
+	virtual int battleGetWallUnderHex(THex hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
 	virtual TDmgRange battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg = NULL)=0; //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>
 	virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
 	virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding to given side (0 - attacker, 1 - defender)
@@ -208,18 +208,18 @@ public:
 	std::vector<CObstacleInstance> battleGetAllObstacles() OVERRIDE; //returns all obstacles on the battlefield
 	const CStack * battleGetStackByID(int ID, bool onlyAlive = true) OVERRIDE; //returns stack info by given ID
 	const CStack * battleGetStackByPos(THex pos, bool onlyAlive = true) OVERRIDE; //returns stack info by given pos
-	int battleGetPos(int stack) OVERRIDE; //returns position (tile ID) of stack
+	THex battleGetPos(int stack) OVERRIDE; //returns position (tile ID) of stack
 	int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack
 	std::vector<const CStack*> battleGetStacks(bool onlyAlive = true) OVERRIDE; //returns stacks on battlefield
 	void getStackQueue( std::vector<const CStack *> &out, int howMany ) OVERRIDE; //returns vector of stack in order of their move sequence
 	std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable) OVERRIDE; //reutrns numbers of hexes reachable by creature with id ID
-	std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, int * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory
+	std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL) OVERRIDE; //returns vector of distances to [dest hex number]; if predecessors is not null, it must point to BFIELD_SIZE * sizeof(int) of allocated memory
 	bool battleCanShoot(const CStack * stack, THex dest) OVERRIDE; //returns true if unit with id ID can shoot to dest
 	bool battleCanCastSpell() OVERRIDE; //returns true, if caller can cast a spell
 	bool battleCanFlee() OVERRIDE; //returns true if caller can flee from the battle
 	const CGTownInstance * battleGetDefendedTown() OVERRIDE; //returns defended town if current battle is a siege, NULL instead
 	ui8 battleGetWallState(int partOfWall) OVERRIDE; //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
-	int battleGetWallUnderHex(int hex) OVERRIDE; //returns part of destructible wall / gate / keep under given hex or -1 if not found
+	int battleGetWallUnderHex(THex hex) OVERRIDE; //returns part of destructible wall / gate / keep under given hex or -1 if not found
 	TDmgRange battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg = NULL) OVERRIDE; //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>
 	ui8 battleGetSiegeLevel() OVERRIDE; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
 	const CGHeroInstance * battleGetFightingHero(ui8 side) const OVERRIDE; //returns hero corresponding ot given side (0 - attacker, 1 - defender)

+ 18 - 29
client/CBattleInterface.cpp

@@ -876,54 +876,44 @@ bool CMeleeAttack::init()
 		return false;
 	}
 
-	int reversedShift = 0; //shift of attacking stack's position due to reversing
-	if(attackingStack->attackerOwned)
-	{
-		if(attackingStack->doubleWide() && THex::mutualPosition(attackingStackPosBeforeReturn, dest) == -1)
-		{
-			if(THex::mutualPosition(attackingStackPosBeforeReturn + (attackingStack->attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
-			{
-				reversedShift = (attackingStack->attackerOwned ? -1 : 1);
-			}
-		}
-	}
-	else //if(astack->attackerOwned)
-	{
-		if(attackingStack->doubleWide() && THex::mutualPosition(attackingStackPosBeforeReturn, dest) == -1)
-		{
-			if(THex::mutualPosition(attackingStackPosBeforeReturn + (attackingStack->attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
-			{
-				reversedShift = (attackingStack->attackerOwned ? -1 : 1);
-			}
-		}
+	bool toReverse = isToReverse(attackingStackPosBeforeReturn, dest, owner->creDir[stack->ID], attackedStack->doubleWide(), owner->creDir[attackedStack->ID]);
 
-	}
-
-	//reversing stack if necessary
-	if(isToReverse(attackingStackPosBeforeReturn, dest, owner->creDir[stack->ID], attackedStack->doubleWide(), owner->creDir[attackedStack->ID]))
+	if(toReverse)
 	{
+
 		owner->addNewAnim(new CReverseAnim(owner, stack, attackingStackPosBeforeReturn, true));
 		return false;
 	}
 	//reversed
 
 	shooting = false;
-	posShiftDueToDist = reversedShift;
 
 	static const int mutPosToGroup[] = {11, 11, 12, 13, 13, 12};
 
-	int mutPos = THex::mutualPosition(attackingStackPosBeforeReturn + reversedShift, dest);
+	int revShiftattacker = (attackingStack->attackerOwned ? -1 : 1);
+
+	int mutPos = THex::mutualPosition(attackingStackPosBeforeReturn, dest);
 	if(mutPos == -1 && attackedStack->doubleWide())
 	{
-		mutPos = THex::mutualPosition(attackingStackPosBeforeReturn + reversedShift, attackedStack->occupiedHex());
+		mutPos = THex::mutualPosition(attackingStackPosBeforeReturn + revShiftattacker, attackedStack->position);
+	}
+	if (mutPos == -1 && attackedStack->doubleWide())
+	{
+		mutPos = THex::mutualPosition(attackingStackPosBeforeReturn, attackedStack->occupiedHex());
+	}
+	if (mutPos == -1 && attackedStack->doubleWide() && attackingStack->doubleWide())
+	{
+		mutPos = THex::mutualPosition(attackingStackPosBeforeReturn + revShiftattacker, attackedStack->occupiedHex());
 	}
+
+
 	switch(mutPos) //attack direction
 	{
 	case 0: case 1: case 2: case 3: case 4: case 5:
 		group = mutPosToGroup[mutPos];
 		break;
 	default:
-		tlog1<<"Critical Error! Wrong dest in stackAttacking! dest: "<<dest<<" attacking stack pos: "<<attackingStackPosBeforeReturn<<" reversed shift: "<<reversedShift<<std::endl;
+		tlog1<<"Critical Error! Wrong dest in stackAttacking! dest: "<<dest<<" attacking stack pos: "<<attackingStackPosBeforeReturn<<" mutual pos: "<<mutPos<<std::endl;
 		group = 11;
 		break;
 	}
@@ -1041,7 +1031,6 @@ bool CShootingAnim::init()
 
 	//attack aniamtion
 
-	posShiftDueToDist = 0;
 	shooting = true;
 
 	if(projectileAngle > straightAngle) //upper shot

+ 0 - 1
client/CBattleInterface.h

@@ -190,7 +190,6 @@ class CBattleAttack : public CBattleStackAnimation
 {
 protected:
 	THex dest; //atacked hex
-	int posShiftDueToDist;
 	bool shooting;
 	int group; //if shooting is true, print this animation group
 	const CStack * attackedStack;

+ 8 - 8
client/Client.cpp

@@ -547,23 +547,23 @@ void CClient::stopConnection()
 void CClient::battleStarted(const BattleInfo * info)
 {
 	CPlayerInterface * att, * def;
-	if(vstd::contains(playerint, info->side1) && playerint[info->side1]->human)
-		att = static_cast<CPlayerInterface*>( playerint[info->side1] );
+	if(vstd::contains(playerint, info->sides[0]) && playerint[info->sides[0]]->human)
+		att = static_cast<CPlayerInterface*>( playerint[info->sides[0]] );
 	else
 		att = NULL;
 
-	if(vstd::contains(playerint, info->side2) && playerint[info->side2]->human)
-		def = static_cast<CPlayerInterface*>( playerint[info->side2] );
+	if(vstd::contains(playerint, info->sides[1]) && playerint[info->sides[1]]->human)
+		def = static_cast<CPlayerInterface*>( playerint[info->sides[1]] );
 	else
 		def = NULL;
 
 
 	new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1], Rect((conf.cc.resx - 800)/2, (conf.cc.resy - 600)/2, 800, 600), att, def);
 
-	if(vstd::contains(battleints,info->side1))
-		battleints[info->side1]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 0);
-	if(vstd::contains(battleints,info->side2))
-		battleints[info->side2]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
+	if(vstd::contains(battleints,info->sides[0]))
+		battleints[info->sides[0]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 0);
+	if(vstd::contains(battleints,info->sides[1]))
+		battleints[info->sides[1]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
 	if(vstd::contains(battleints,254))
 		battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
 }

+ 3 - 3
client/NetPacksClient.cpp

@@ -37,8 +37,8 @@
 			cl->battleints[player]->function(__VA_ARGS__);
 
 #define BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(function,...) 	\
-	BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1, function, __VA_ARGS__) \
-	BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2, function, __VA_ARGS__) \
+	BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->sides[0], function, __VA_ARGS__) \
+	BATTLE_INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->sides[1], function, __VA_ARGS__) \
 	BATTLE_INTERFACE_CALL_IF_PRESENT(254, function, __VA_ARGS__)
 /*
  * NetPacksClient.cpp, part of VCMI engine
@@ -530,7 +530,7 @@ void BattleSetActiveStack::applyCl( CClient *cl )
 	int playerToCall = -1; //player that will move activated stack
 	if( activated->hasBonusOfType(Bonus::HYPNOTIZED) )
 	{
-		playerToCall = ( GS(cl)->curB->side1 == activated->owner ? GS(cl)->curB->side2 : GS(cl)->curB->side1 );
+		playerToCall = ( GS(cl)->curB->sides[0] == activated->owner ? GS(cl)->curB->sides[1] : GS(cl)->curB->sides[0] );
 	}
 	else
 	{

+ 26 - 24
lib/BattleState.cpp

@@ -216,7 +216,7 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool atta
 	}
 }
 
-bool BattleInfo::isAccessible(int hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos)
+bool BattleInfo::isAccessible(THex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos)
 {
 	if(flying && !lastPos)
 		return true;
@@ -232,7 +232,7 @@ bool BattleInfo::isAccessible(int hex, bool * accessibility, bool twoHex, bool a
 	}
 }
 
-void BattleInfo::makeBFS(THex start, bool *accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const //both pointers must point to the at least 187-elements int arrays
+void BattleInfo::makeBFS(THex start, bool *accessibility, THex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const //both pointers must point to the at least 187-elements int arrays
 {
 	//inits
 	for(int b=0; b<BFIELD_SIZE; ++b)
@@ -282,7 +282,8 @@ std::vector<THex> BattleInfo::getAccessibility(const CStack * stack, bool addOcc
 
 	getAccessibilityMap(ac, stack->doubleWide(), stack->attackerOwned, addOccupiable, occupyable, stack->hasBonusOfType(Bonus::FLYING), stack);
 
-	int pr[BFIELD_SIZE], dist[BFIELD_SIZE];
+	THex pr[BFIELD_SIZE];
+	int dist[BFIELD_SIZE];
 	makeBFS(stack->position, ac, pr, dist, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), false);
 
 	if(stack->doubleWide())
@@ -354,21 +355,21 @@ bool BattleInfo::isStackBlocked(const CStack * stack) const
 }
 
 
-std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned)
+std::pair< std::vector<THex>, int > BattleInfo::getPath(THex start, THex dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned)
 {
-	int predecessor[BFIELD_SIZE]; //for getting the Path
+	THex predecessor[BFIELD_SIZE]; //for getting the Path
 	int dist[BFIELD_SIZE]; //calculated distances
 
 	makeBFS(start, accessibility, predecessor, dist, twoHex, attackerOwned, flyingCreature, false);
 	
 	if(predecessor[dest] == -1) //cannot reach destination
 	{
-		return std::make_pair(std::vector<int>(), 0);
+		return std::make_pair(std::vector<THex>(), 0);
 	}
 
 	//making the Path
-	std::vector<int> path;
-	int curElem = dest;
+	std::vector<THex> path;
+	THex curElem = dest;
 	while(curElem != start)
 	{
 		path.push_back(curElem);
@@ -630,7 +631,7 @@ void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const
 	}
 }
 
-std::set<CStack*> BattleInfo::getAttackedCreatures( const CSpell * s, int skillLevel, ui8 attackerOwner, int destinationTile )
+std::set<CStack*> BattleInfo::getAttackedCreatures( const CSpell * s, int skillLevel, ui8 attackerOwner, THex destinationTile )
 {
 	std::set<ui16> attackedHexes = s->rangeInHexes(destinationTile, skillLevel);
 	std::set<CStack*> attackedCres; /*std::set to exclude multiple occurrences of two hex creatures*/
@@ -715,9 +716,9 @@ int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstan
 	}
 }
 
-CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, int position) const
+CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, THex position) const
 {
-	int owner = attackerOwned ? side1 : side2;
+	int owner = attackerOwned ? sides[0] : sides[1];
 	assert(owner >= PLAYER_LIMIT  ||  base.armyObj && base.armyObj->tempOwner == owner);
 
 	CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
@@ -725,9 +726,9 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, b
 	return ret;
 }
 
-CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, int position) const
+CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, THex position) const
 {
-	int owner = attackerOwned ? side1 : side2;
+	int owner = attackerOwned ? sides[0] : sides[1];
 	CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
 	ret->position = position;
 	return ret;
@@ -781,14 +782,15 @@ int BattleInfo::lineToWallHex( int line ) const
 	return lineToHex[line];
 }
 
-std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const
+std::pair<const CStack *, THex> BattleInfo::getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const
 {	
 	bool ac[BFIELD_SIZE];
 	std::set<THex> occupyable;
 
 	getAccessibilityMap(ac, closest->doubleWide(), closest->attackerOwned, false, occupyable, closest->hasBonusOfType(Bonus::FLYING), closest);
 
-	int predecessor[BFIELD_SIZE], dist[BFIELD_SIZE];
+	THex predecessor[BFIELD_SIZE];
+	int dist[BFIELD_SIZE];
 	makeBFS(closest->position, ac, predecessor, dist, closest->doubleWide(), closest->attackerOwned, closest->hasBonusOfType(Bonus::FLYING), true);
 
 	std::vector< std::pair< std::pair<int, int>, const CStack *> > stackPairs; //pairs <<distance, hex>, stack>
@@ -828,7 +830,7 @@ std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closes
 		return std::make_pair(minPair.second, predecessor[minPair.first.second]);
 	}
 
-	return std::make_pair<const CStack * , int>(NULL, -1);
+	return std::make_pair<const CStack * , THex>(NULL, THex::INVALID);
 }
 ui32 BattleInfo::calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const
 {
@@ -1139,7 +1141,7 @@ bool BattleInfo::battleCanShoot(const CStack * stack, THex dest) const
 
 bool BattleInfo::battleCanFlee(int player) const
 {
-	if (player == side1)
+	if (player == sides[0])
 	{
 		if (!heroes[0])
 			return false;//current player have no hero
@@ -1154,7 +1156,7 @@ bool BattleInfo::battleCanFlee(int player) const
 		|| ( heroes[1] && heroes[1]->hasBonusOfType(Bonus::ENEMY_CANT_ESCAPE)))
 		return false;
 
-	if (player == side2 && siege //defender in siege
+	if (player == sides[1] && siege //defender in siege
 		&& !(town->subID == 6 && vstd::contains(town->builtBuildings, 17)))//without escape tunnel
 		return false;
 
@@ -1256,10 +1258,10 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const
 {
 	CMP_stack cmpst;
 	BattleInfo *curB = new BattleInfo;
-	curB->side1 = armies[0]->tempOwner;
-	curB->side2 = armies[1]->tempOwner;
-	if(curB->side2 == 254) 
-		curB->side2 = 255;
+	curB->sides[0] = armies[0]->tempOwner;
+	curB->sides[1] = armies[1]->tempOwner;
+	if(curB->sides[1] == 254) 
+		curB->sides[1] = 255;
 
 	std::vector<CStack*> & stacks = (curB->stacks);
 
@@ -1883,7 +1885,7 @@ bool CStack::doubleWide() const
 	return getCreature()->doubleWide;
 }
 
-int CStack::occupiedHex() const
+THex CStack::occupiedHex() const
 {
 	if (doubleWide())
 	{
@@ -1894,7 +1896,7 @@ int CStack::occupiedHex() const
 	} 
 	else
 	{
-		return -1;
+		return THex::INVALID;
 	}
 }
 BonusList CStack::getSpellBonuses() const

+ 10 - 10
lib/BattleState.h

@@ -47,7 +47,7 @@ struct DLL_EXPORT SiegeInfo
 
 struct DLL_EXPORT BattleInfo : public CBonusSystemNode
 {
-	ui8 side1, side2; //side1 - attacker, side2 - defender
+	ui8 sides[2]; //sides[0] - attacker, sides[1] - defender
 	si32 round, activeStack;
 	ui8 siege; //    = 0 ordinary battle    = 1 a siege with a Fort    = 2 a siege with a Citadel    = 3 a siege with a Castle
 	const CGTownInstance * town; //used during town siege - id of attacked town; -1 if not town defence
@@ -62,7 +62,7 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & side1 & side2 & round & activeStack & siege & town & tile & stacks & belligerents & obstacles
+		h & sides & round & activeStack & siege & town & tile & stacks & belligerents & obstacles
 			& castSpells & si & battlefieldType;
 		h & heroes;
 		h & static_cast<CBonusSystemNode&>(*this);
@@ -79,9 +79,9 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
 	CStack * getStackT(THex tileID, bool onlyAlive = true);
 	const CStack * getStackT(THex tileID, bool onlyAlive = true) const;
 	void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<THex> & occupyable, bool flying, const CStack* stackToOmmit = NULL) const; //send pointer to at least 187 allocated bytes
-	static bool isAccessible(int hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
-	void makeBFS(THex start, bool*accessibility, int *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<int>, int > getPath(int start, int dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
+	static bool isAccessible(THex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
+	void makeBFS(THex start, bool*accessibility, THex *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<THex>, int > getPath(THex start, THex dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
 	std::vector<THex> getAccessibility(const CStack * stack, bool addOccupiable) const; //returns vector of accessible tiles (taking into account the creature range)
 
 	bool isStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack
@@ -90,14 +90,14 @@ struct DLL_EXPORT BattleInfo : public CBonusSystemNode
 	TDmgRange calculateDmgRange( const CStack* attacker, const CStack* defender, TQuantity attackerCount, TQuantity defenderCount, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky) 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, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
 	void calculateCasualties(std::map<ui32,si32> *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
-	std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, int destinationTile); //calculates stack affected by given spell
+	std::set<CStack*> getAttackedCreatures(const CSpell * s, int skillLevel, ui8 attackerOwner, THex destinationTile); //calculates stack affected by given spell
 	static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster, int usedSpellPower);
-	CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
-	CStack * generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
+	CStack * generateNewStack(const CStackInstance &base, int stackID, bool attackerOwned, int slot, THex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
+	CStack * generateNewStack(const CStackBasicDescriptor &base, int stackID, bool attackerOwned, int slot, THex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
 	ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
 	int hexToWallPart(THex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
 	int lineToWallHex(int line) const; //returns hex with wall in given line
-	std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
+	std::pair<const CStack *, THex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
 	ui32 calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const;
 	ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell
 	ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack) const;
@@ -171,7 +171,7 @@ public:
 	static bool isMeleeAttackPossible(const CStack * attacker, const CStack * defender, THex attackerPos = THex::INVALID, THex defenderPos = THex::INVALID);
 
 	bool doubleWide() const;
-	int occupiedHex() const; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1
+	THex occupiedHex() const; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1
 
 	void prepareAttacked(BattleStackAttacked &bsa) const; //requires bsa.damageAmout filled
 

+ 2 - 2
lib/CGameState.cpp

@@ -906,12 +906,12 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 			h->initHero(1);
 			h->initObj();
 			h->setCreature(0, 110, 1);
-			h->setCreature(1, 69, 61);
+			h->setCreature(1, 69, 1);
 
 			CGCreature *c = new CGCreature();
 			c->setOwner(1);
 			c->putStack(0, new CStackInstance(69, 6));
-			//c->putStack(1, new CStackInstance(11, 3));
+			c->putStack(1, new CStackInstance(11, 3));
 			c->subID = 34;
 			c->initObj();
 

+ 2 - 1
lib/NetPacks.h

@@ -1159,7 +1159,8 @@ struct BattleResult : public CPackForClient//3003
 
 struct BattleStackMoved : public CPackForClient//3004
 {
-	ui32 stack, tile;
+	ui32 stack;
+	THex tile;
 	ui8 ending, distance, teleporting;
 	BattleStackMoved(){type = 3004;};
 	void applyFirstCl(CClient *cl);

+ 7 - 5
server/CGameHandler.cpp

@@ -322,7 +322,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 	BattleResultsApplied resultsApplied;
 
 	const CArmedInstance *bEndArmy1 = gs->curB->belligerents[0];
-	const CArmedInstance *bEndArmy2 = gs->curB->belligerents[0];
+	const CArmedInstance *bEndArmy2 = gs->curB->belligerents[1];
 	resultsApplied.player1 = bEndArmy1->tempOwner;
 	resultsApplied.player2 = bEndArmy2->tempOwner;
 
@@ -343,8 +343,10 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
 		battleResult.data->exp[1] *= (100+hero2->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0f;
 
 	ui8 sides[2];
-	sides[0] = gs->curB->side1;
-	sides[1] = gs->curB->side2;
+	for(int i=0; i<2; ++i)
+	{
+		sides[i] = gs->curB->sides[i];
+	}
 	ui8 loser = sides[!battleResult.data->winner];
 
 	CasualtiesAfterBattle cab1(bEndArmy1, gs->curB), cab2(bEndArmy2, gs->curB); //calculate casualties before deleting battle
@@ -616,7 +618,7 @@ int CGameHandler::moveStack(int stack, int dest)
 	//if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
 	//	return false;
 
-	std::pair< std::vector<int>, int > path = gs->curB->getPath(curStack->position, dest, accessibilityWithOccupyable, curStack->hasBonusOfType(Bonus::FLYING), curStack->doubleWide(), curStack->attackerOwned);
+	std::pair< std::vector<THex>, int > path = gs->curB->getPath(curStack->position, dest, accessibilityWithOccupyable, curStack->hasBonusOfType(Bonus::FLYING), curStack->doubleWide(), curStack->attackerOwned);
 
 	ret = path.second;
 
@@ -3039,7 +3041,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 		}
 	case BattleAction::RETREAT: //retreat/flee
 		{
-			if( !gs->curB->battleCanFlee(ba.side ? gs->curB->side2 : gs->curB->side1) )
+			if( !gs->curB->battleCanFlee(ba.side ? gs->curB->sides[1] : gs->curB->sides[0]) )
 				break;
 			//TODO: remove retreating hero from map and place it in recruitment list
 			BattleResult *br = new BattleResult;