Browse Source

* some changes in code handling movement of wide creatures in battles. It could solve a few bugs but I'm not sure

mateuszb 16 years ago
parent
commit
048ab62530
5 changed files with 65 additions and 42 deletions
  1. 1 1
      AI/GeniusAI/BattleLogic.cpp
  2. 2 0
      CConsoleHandler.cpp
  3. 52 36
      lib/CGameState.cpp
  4. 4 4
      lib/CGameState.h
  5. 6 1
      server/CGameHandler.cpp

+ 1 - 1
AI/GeniusAI/BattleLogic.cpp

@@ -529,7 +529,7 @@ BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID)
 		ba.side = 1;
 		//ba.actionType = 6; // go and attack
 		ba.stackNumber = attackerID;
-		ba.destinationTile = (ui16)dest_tile;
+		ba.destinationTile = static_cast<ui16>(dest_tile);
 		//simplified checking for possibility of attack (previous was too simplified)
 		int destStackPos = m_cb->battleGetPos(destinationID);
 		if(BattleInfo::mutualPosition(dest_tile, destStackPos) != -1)

+ 2 - 0
CConsoleHandler.cpp

@@ -197,7 +197,9 @@ CConsoleHandler::CConsoleHandler()
 	CONSOLE_SCREEN_BUFFER_INFO csbi;
 	GetConsoleScreenBufferInfo(handleOut,&csbi);
 	defColor = csbi.wAttributes;
+#ifndef _DEBUG
 	SetUnhandledExceptionFilter(onUnhandledException);
+#endif
 #else
 	defColor = "\x1b[0m";
 #endif

+ 52 - 36
lib/CGameState.cpp

@@ -264,9 +264,9 @@ CStack * BattleInfo::getStackT(int tileID)
 	}
 	return NULL;
 }
-void BattleInfo::getAccessibilityMap(bool *accessibility, int stackToOmmit)
+void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<int> & occupyable, int stackToOmmit)
 {
-	memset(accessibility,1,BFIELD_SIZE); //initialize array with trues
+	memset(accessibility, 1, BFIELD_SIZE); //initialize array with trues
 	for(unsigned int g=0; g<stacks.size(); ++g)
 	{
 		if(!stacks[g]->alive() || stacks[g]->ID==stackToOmmit) //we don't want to lock position of this stack
@@ -291,14 +291,43 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, int stackToOmmit)
 				accessibility[blocked[c]] = false;
 		}
 	}
+
+	if(addOccupiable && twoHex)
+	{
+		std::set<int> rem; //tiles to unlock
+		for(int h=0; h<BFIELD_HEIGHT; ++h)
+		{
+			for(int w=1; w<BFIELD_WIDTH-1; ++w)
+			{
+				int hex = h * BFIELD_WIDTH + w;
+				if(!isAccessible(hex, accessibility, twoHex, attackerOwned)
+					&& (attackerOwned ? isAccessible(hex+1, accessibility, twoHex, attackerOwned) : isAccessible(hex-1, accessibility, twoHex, attackerOwned) )
+					)
+					rem.insert(hex);
+			}
+		}
+		occupyable = rem;
+		for(std::set<int>::const_iterator it = rem.begin(); it != rem.end(); ++it)
+		{
+			accessibility[*it] = true;
+		}
+	}
 }
-void BattleInfo::getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit, bool addOccupiable) //send pointer to at least 187 allocated bytes
-{	
-	bool mac[BFIELD_SIZE];
-	getAccessibilityMap(mac,stackToOmmit);
-	memcpy(accessibility,mac,BFIELD_SIZE);
+
+bool BattleInfo::isAccessible(int hex, bool * accessibility, bool twoHex, bool attackerOwned)
+{
+	if(twoHex)
+	{
+		//if given hex is accessible and appropriate adjacent one is free too
+		return accessibility[hex] && accessibility[hex + (attackerOwned ? -1 : 1 )];
+	}
+	else
+	{
+		return accessibility[hex];
+	}
 }
-void BattleInfo::makeBFS(int start, bool*accessibility, int *predecessor, int *dists) //both pointers must point to the at least 187-elements int arrays
+
+void BattleInfo::makeBFS(int start, bool *accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned) //both pointers must point to the at least 187-elements int arrays
 {
 	//inits
 	for(int b=0; b<BFIELD_SIZE; ++b)
@@ -317,8 +346,8 @@ void BattleInfo::makeBFS(int start, bool*accessibility, int *predecessor, int *d
 		hexq.pop();
 		for(unsigned int nr=0; nr<neighbours.size(); nr++)
 		{
-			curNext = neighbours[nr];
-			if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
+			curNext = neighbours[nr]; //if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
+			if(!isAccessible(curNext, accessibility, twoHex, attackerOwned) || (dists[curHex]+1)>=dists[curNext])
 				continue;
 			hexq.push(curNext);
 			dists[curNext] = dists[curHex] + 1;
@@ -332,13 +361,12 @@ std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable)
 	std::vector<int> ret;
 	bool ac[BFIELD_SIZE];
 	CStack *s = getStack(stackID);
-	if(s->creature->isDoubleWide())
-		getAccessibilityMapForTwoHex(ac,s->attackerOwned,stackID,addOccupiable);
-	else
-		getAccessibilityMap(ac,stackID);
+	std::set<int> occupyable;
+
+	getAccessibilityMap(ac, s->creature->isDoubleWide(), s->attackerOwned, addOccupiable, occupyable, stackID);
 
 	int pr[BFIELD_SIZE], dist[BFIELD_SIZE];
-	makeBFS(s->position,ac,pr,dist);
+	makeBFS(s->position, ac, pr, dist, s->creature->isDoubleWide(), s->attackerOwned);
 
 	if(s->creature->isDoubleWide())
 	{
@@ -363,26 +391,14 @@ std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable)
 				if(s->attackerOwned ? (v%BFIELD_WIDTH)==1 : (v%BFIELD_WIDTH)==(BFIELD_WIDTH - 2))
 					ac[v] = false;
 		}
-		else
-		{
-			std::vector<int> rem;
-			for(int b=0; b<BFIELD_SIZE; ++b)
-			{
-				if( ac[b] && (!ac[b-1] || dist[b-1] > s->Speed() ) && ( !ac[b+1] || dist[b+1] > s->Speed() ) && b%BFIELD_WIDTH != 0 && b%BFIELD_WIDTH != (BFIELD_WIDTH-1))
-				{
-					rem.push_back(b);
-				}
-			}
-
-			for(unsigned int g=0; g<rem.size(); ++g)
-			{
-				ac[rem[g]] = false;
-			}
-		}
 	}
 	
-	for(int i=0;i<BFIELD_SIZE;i++)
-		if(dist[i] <= s->Speed() && ac[i])
+	for(int i=0; i < BFIELD_SIZE ; ++i)
+		if(
+			(dist[i] <= s->Speed() //we can reach it
+			|| (vstd::contains(occupyable, i) && dist[ i + (s->attackerOwned ? 1 : -1 ) ] <= s->Speed() ) //it's occupyable and we can reach adjacent hex
+			)
+			&& ac[i])
 		{
 			ret.push_back(i);
 		}
@@ -443,7 +459,7 @@ std::vector<int> BattleInfo::neighbouringTiles(int hex)
 #undef CHECK_AND_PUSH
 	return ret;
 }
-std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool*accessibility, bool flyingCreature)
+std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned)
 {							
 	int predecessor[BFIELD_SIZE]; //for getting the Path
 	int dist[BFIELD_SIZE]; //calculated distances
@@ -456,11 +472,11 @@ std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool
 			acc[b] = true;
 		}
 
-		makeBFS(start, acc, predecessor, dist);
+		makeBFS(start, acc, predecessor, dist, twoHex, attackerOwned);
 	}
 	else
 	{
-		makeBFS(start, accessibility, predecessor, dist);
+		makeBFS(start, accessibility, predecessor, dist, twoHex, attackerOwned);
 	}
 
 	//making the Path

+ 4 - 4
lib/CGameState.h

@@ -125,10 +125,10 @@ struct DLL_EXPORT BattleInfo
 	std::vector<CStack> getStackQueue(); //returns stack in order of their movement action
 	CStack * getStack(int stackID);
 	CStack * getStackT(int tileID);
-	void getAccessibilityMap(bool *accessibility, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes
-	void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit=-1, bool addOccupiable = false); //send pointer to at least 187 allocated bytes
-	void makeBFS(int start, bool*accessibility, int *predecessor, int *dists); //*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); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
+	void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<int> & occupyable, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes
+	static bool isAccessible(int hex, bool * accessibility, bool twoHex, bool attackerOwned); //helper for makeBFS
+	void makeBFS(int start, bool*accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned); //*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
 	std::vector<int> getAccessibility(int stackID, bool addOccupiable); //returns vector of accessible tiles (taking into account the creature range)
 
 	bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack

+ 6 - 1
server/CGameHandler.cpp

@@ -573,7 +573,7 @@ void 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, accessibility, curStack->creature->isFlying());
+	std::pair< std::vector<int>, int > path = gs->curB->getPath(curStack->position, dest, accessibility, curStack->creature->isFlying(), curStack->creature->isDoubleWide(), curStack->attackerOwned);
 	if(curStack->creature->isFlying())
 	{
 		if(path.second <= curStack->Speed() && path.first.size() > 0)
@@ -2310,6 +2310,11 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 				ok = false;
 			}
 
+			if(curStack->ID == stackAtEnd->ID) //we should just move, it will be handled by following check
+			{
+				stackAtEnd = NULL;
+			}
+
 			if(!stackAtEnd)
 			{
 				tlog3 << "There is no stack on " << ba.additionalInfo << " tile (no attack)!";