1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-03 00:46:55 +02:00

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

This commit is contained in:
mateuszb
2009-08-02 14:21:18 +00:00
parent e3ce3f8496
commit 048ab62530
5 changed files with 65 additions and 42 deletions

View File

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

View File

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

View File

@ -264,9 +264,9 @@ CStack * BattleInfo::getStackT(int tileID)
} }
return NULL; 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) 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 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; 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 BattleInfo::isAccessible(int hex, bool * accessibility, bool twoHex, bool attackerOwned)
{ {
bool mac[BFIELD_SIZE]; if(twoHex)
getAccessibilityMap(mac,stackToOmmit); {
memcpy(accessibility,mac,BFIELD_SIZE); //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 //inits
for(int b=0; b<BFIELD_SIZE; ++b) 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(); hexq.pop();
for(unsigned int nr=0; nr<neighbours.size(); nr++) for(unsigned int nr=0; nr<neighbours.size(); nr++)
{ {
curNext = neighbours[nr]; curNext = neighbours[nr]; //if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext]) if(!isAccessible(curNext, accessibility, twoHex, attackerOwned) || (dists[curHex]+1)>=dists[curNext])
continue; continue;
hexq.push(curNext); hexq.push(curNext);
dists[curNext] = dists[curHex] + 1; dists[curNext] = dists[curHex] + 1;
@ -332,13 +361,12 @@ std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable)
std::vector<int> ret; std::vector<int> ret;
bool ac[BFIELD_SIZE]; bool ac[BFIELD_SIZE];
CStack *s = getStack(stackID); CStack *s = getStack(stackID);
if(s->creature->isDoubleWide()) std::set<int> occupyable;
getAccessibilityMapForTwoHex(ac,s->attackerOwned,stackID,addOccupiable);
else getAccessibilityMap(ac, s->creature->isDoubleWide(), s->attackerOwned, addOccupiable, occupyable, stackID);
getAccessibilityMap(ac,stackID);
int pr[BFIELD_SIZE], dist[BFIELD_SIZE]; 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()) 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)) if(s->attackerOwned ? (v%BFIELD_WIDTH)==1 : (v%BFIELD_WIDTH)==(BFIELD_WIDTH - 2))
ac[v] = false; 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) for(int i=0; i < BFIELD_SIZE ; ++i)
{ if(
ac[rem[g]] = false; (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])
for(int i=0;i<BFIELD_SIZE;i++)
if(dist[i] <= s->Speed() && ac[i])
{ {
ret.push_back(i); ret.push_back(i);
} }
@ -443,7 +459,7 @@ std::vector<int> BattleInfo::neighbouringTiles(int hex)
#undef CHECK_AND_PUSH #undef CHECK_AND_PUSH
return ret; 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 predecessor[BFIELD_SIZE]; //for getting the Path
int dist[BFIELD_SIZE]; //calculated distances 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; acc[b] = true;
} }
makeBFS(start, acc, predecessor, dist); makeBFS(start, acc, predecessor, dist, twoHex, attackerOwned);
} }
else else
{ {
makeBFS(start, accessibility, predecessor, dist); makeBFS(start, accessibility, predecessor, dist, twoHex, attackerOwned);
} }
//making the Path //making the Path

View File

@ -125,10 +125,10 @@ struct DLL_EXPORT BattleInfo
std::vector<CStack> getStackQueue(); //returns stack in order of their movement action std::vector<CStack> getStackQueue(); //returns stack in order of their movement action
CStack * getStack(int stackID); CStack * getStack(int stackID);
CStack * getStackT(int tileID); CStack * getStackT(int tileID);
void getAccessibilityMap(bool *accessibility, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes 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
void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit=-1, bool addOccupiable = false); //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); //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result 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); //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<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) 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 bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack

View File

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