diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-11-12 15:40:23 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-11-12 15:40:23 +0000 |
commit | 3262d5319c5f2cc830b3b783880df4b1b5d95710 (patch) | |
tree | 4573e5097a54d35ff6937bd001a06ffe3f9146ae /src/map.cpp | |
parent | 3eca8915fd14dcebe88647a198bfce5d789a6efb (diff) | |
download | mana-3262d5319c5f2cc830b3b783880df4b1b5d95710.tar.gz mana-3262d5319c5f2cc830b3b783880df4b1b5d95710.tar.bz2 mana-3262d5319c5f2cc830b3b783880df4b1b5d95710.tar.xz mana-3262d5319c5f2cc830b3b783880df4b1b5d95710.zip |
Made pathfinding algorithm cope better with beings blocking the road. This is
done by allowing walking over other beings, but at an additional cost so that
it is preferable to walk around them.
Diffstat (limited to 'src/map.cpp')
-rw-r--r-- | src/map.cpp | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/src/map.cpp b/src/map.cpp index 05dea951..897fbe22 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -282,33 +282,35 @@ Map::setWalk(int x, int y, bool walkable) bool Map::getWalk(int x, int y) { - // Check for being walkable - if (tileCollides(x, y)) { - return false; - } + return !tileCollides(x, y) && !occupied(x, y); +} - // Check for collision with a being +bool +Map::occupied(int x, int y) +{ Beings &beings = beingManager->getAll(); - for (BeingIterator i = beings.begin(); i != beings.end(); i++) { + for (BeingIterator i = beings.begin(); i != beings.end(); i++) + { // job 45 is a portal, they don't collide - if ((*i)->mX == x && (*i)->mY == y && (*i)->mJob != 45) { - return false; + if ((*i)->mX == x && (*i)->mY == y && (*i)->mJob != 45) + { + return true; } } - return true; + return false; } bool Map::tileCollides(int x, int y) { - // You can't walk outside of the map - if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) { - return true; - } + return !(contains(x, y) && mMetaTiles[x + y * mWidth].walkable); +} - // Check if the tile is walkable - return !mMetaTiles[x + y * mWidth].walkable; +bool +Map::contains(int x, int y) +{ + return x >= 0 && y >= 0 && x < mWidth && y < mHeight; } void @@ -351,8 +353,9 @@ Map::findPath(int startX, int startY, int destX, int destY) // Declare open list, a list with open tiles sorted on F cost std::priority_queue<Location> openList; - // Return empty path when destination not walkable - if (!getWalk(destX, destY)) return path; + // Return empty path when destination collides + if (tileCollides(destX, destY)) + return path; // Reset starting tile's G cost to 0 MetaTile *startTile = getMetaTile(startX, startY); @@ -391,16 +394,15 @@ Map::findPath(int startX, int startY, int destX, int destY) // Skip if if we're checking the same tile we're leaving from, // or if the new location falls outside of the map boundaries - if ((dx == 0 && dy == 0) || - (x < 0 || y < 0 || x >= mWidth || y >= mHeight)) + if ((dx == 0 && dy == 0) || !contains(x, y)) { continue; } MetaTile *newTile = getMetaTile(x, y); - // Skip if the tile is on the closed list or is not walkable - if (newTile->whichList == mOnClosedList || !getWalk(x, y)) + // Skip if the tile is on the closed list or collides + if (newTile->whichList == mOnClosedList || tileCollides(x, y)) { continue; } @@ -420,9 +422,16 @@ Map::findPath(int startX, int startY, int destX, int destY) } // Calculate G cost for this route, 10 for moving straight and - // 14 for moving diagonal + // 14 for moving diagonal (sqrt(200) = 14.1421...) int Gcost = curr.tile->Gcost + ((dx == 0 || dy == 0) ? 10 : 14); + // It costs extra to walk through a being (needs to be enough + // to make it more attractive to walk around). + if (occupied(x, y)) + { + Gcost += 30; + } + // Skip if Gcost becomes too much // Warning: probably not entirely accurate if (Gcost > 200) |