summaryrefslogtreecommitdiff
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
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.
-rw-r--r--ChangeLog7
-rw-r--r--src/map.cpp53
-rw-r--r--src/map.h12
3 files changed, 49 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index e77de982..7d774b74 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-11-12 Bjørn Lindeijer <bjorn@lindeijer.nl>
+
+ * src/map.cpp, src/map.h: 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.
+
2006-11-09 Eugenio Favalli <elvenprogrammer@gmail.com>
* src/main.cpp, src/net/network.cpp, src/net/network.h,
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;