summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2006-11-12 15:40:23 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2006-11-12 15:40:23 +0000
commit3262d5319c5f2cc830b3b783880df4b1b5d95710 (patch)
tree4573e5097a54d35ff6937bd001a06ffe3f9146ae /src
parent3eca8915fd14dcebe88647a198bfce5d789a6efb (diff)
downloadmana-client-3262d5319c5f2cc830b3b783880df4b1b5d95710.tar.gz
mana-client-3262d5319c5f2cc830b3b783880df4b1b5d95710.tar.bz2
mana-client-3262d5319c5f2cc830b3b783880df4b1b5d95710.tar.xz
mana-client-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')
-rw-r--r--src/map.cpp53
-rw-r--r--src/map.h12
2 files changed, 42 insertions, 23 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)
diff --git a/src/map.h b/src/map.h
index 961326b8..15b9b0dc 100644
--- a/src/map.h
+++ b/src/map.h
@@ -129,7 +129,7 @@ class Map : public Properties
MetaTile *getMetaTile(int x, int y);
/**
- * Set walkability flag for a tile
+ * Set walkability flag for a tile.
*/
void setWalk(int x, int y, bool walkable);
@@ -199,6 +199,16 @@ class Map : public Properties
Tileset*
getTilesetWithGid(int gid);
+ /**
+ * Tells whether a tile is occupied by a being.
+ */
+ bool occupied(int x, int y);
+
+ /**
+ * Tells whether the given coordinates fall within the map boundaries.
+ */
+ bool contains(int x, int y);
+
int mWidth, mHeight;
int mTileWidth, mTileHeight;
MetaTile *mMetaTiles;