{\r
mId = identifier;\r
mMotion = new MovementManager(position);\r
- \r
+ mRetryInterval = 2 + (position.X * 25789 + position.Y * 259) % 30;\r
+\r
+\r
// We need to keep the game reference in order to get the grid when we\r
// need to find paths.\r
mGame = game;\r
\r
- pathFinder = null;\r
-\r
// Get the speed of the monster. If not set in the map, it defaults to\r
// whatever the default of MovementManager is... 1 I think.\r
string speedString;\r
foreach (string pathPoint in idlePathPoints)\r
{\r
Point? point = Parse.Coordinates(pathPoint);\r
- if (point != null) mIdlePath.Add(point.Value);\r
+ if (point != null) mWaypoints.Add(point.Value);\r
}\r
}\r
// Start doing something...\r
}\r
*/\r
\r
- // Find the path to get to the closest waypoint.\r
- if (pathFinder == null)\r
- pathFinder = new PathFinder(mGame.Grid);\r
-\r
- mPath = new List<Point>(32);\r
- mPath.Add(Coordinates);\r
- List<Point> path = pathFinder.GetPath(mMotion.Coordinates, new Point(X,Y));\r
- if (path != null)\r
- {\r
- mPath.AddRange(path);\r
- //mPath.Add(mIdlePath[mIdlePathIndex]);\r
- }\r
- mPathIndex = 0;\r
+ SetWaypoint(new Point(X, Y));\r
+ ChartPath();\r
}\r
\r
/// <summary>\r
/// </summary>\r
public void StartPacing()\r
{\r
- mState = AiState.Pacing;\r
+ if (mWaypoints.Count == 0) return;\r
\r
- if (mIdlePath.Count == 0) return;\r
+ mState = AiState.Pacing;\r
\r
// Determine the best (closest) waypoint to start at.\r
// We may not be on the path, so we have to walk to get on it.\r
- mIdlePathIndex = 0;\r
+ mWaypointIndex = 0;\r
int closest = int.MaxValue;\r
- for (int i = 0; i < mIdlePath.Count; i++)\r
+ for (int i = 0; i < mWaypoints.Count; i++)\r
{\r
- int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);\r
+ int distance = PathFinder.GetManhattanDistance(Coordinates, mWaypoints[i]);\r
if (distance < closest)\r
{\r
- mIdlePathIndex = i;\r
+ mWaypointIndex = i;\r
closest = distance;\r
}\r
}\r
\r
// Find the path to get to the closest waypoint.\r
- PathFinder pathFinder = new PathFinder(mGame.Grid);\r
- mPath = new List<Point>(32);\r
- mPath.Add(Coordinates);\r
- List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]);\r
- if (path != null)\r
- {\r
- mPath.AddRange(path);\r
- mPath.Add(mIdlePath[mIdlePathIndex]);\r
- }\r
- mPathIndex = 0;\r
+ ChartPath();\r
}\r
\r
Direction GetDirectionToNextCell()\r
{\r
- if (mPathIndex >= mPath.Count)\r
+ if (mPath != null)\r
{\r
- mState = AiState.Standing;\r
+ if (mPathIndex >= mPath.Count)\r
+ {\r
+ // We're done with the current path, so find the path to\r
+ // the next waypoint... forever.\r
+ switch (mState)\r
+ {\r
+ case AiState.Pacing:\r
+ SetWaypoint();\r
+ ChartPath();\r
+ break;\r
+\r
+ default:\r
+ mPathIndex = 0;\r
+ mPath = null;\r
+ mPathDirection = Direction.None;\r
+ break;\r
+ }\r
+ }\r
+\r
+ // We need to make sure our direction is set to the next cell\r
+ // we want to be. If our current coordinates match that, we need\r
+ // to change our direction to get to the next cell.\r
+ else if (mPath[mPathIndex] == mMotion.Coordinates)\r
+ {\r
+ mPathIndex++;\r
+ mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]);\r
+ }\r
+\r
+ return mPathDirection;\r
}\r
+ else return Direction.None;\r
+ }\r
\r
- // We need to make sure out direction is set to the next cell\r
- // we want to be. If our current coordinates match that, we need\r
- // to change our direction to get to the next cell.\r
- if (mPath[mPathIndex % mPath.Count] == mMotion.Coordinates)\r
+ void SetWaypoint()\r
+ {\r
+ mWaypointIndex++;\r
+ mWaypoint = mWaypoints[mWaypointIndex % mWaypoints.Count];\r
+ }\r
+\r
+ void SetWaypoint(Point point)\r
+ {\r
+ mWaypoint = point;\r
+ }\r
+\r
+ void ChartPath()\r
+ {\r
+ if (mPathSearch == null)\r
{\r
- mPathIndex++;\r
- mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]);\r
+ PathFinder pathFinder = new PathFinder(mGame.Grid);\r
+ Point? nearby = pathFinder.GetNearbyOpenCell(mWaypoint);\r
+ if (nearby != null) mPathSearch = pathFinder.GetPathAsync(mMotion.Coordinates, nearby.Value);\r
+\r
+ mPathIndex = 0;\r
+ mPath = null;\r
}\r
+ else if (mPathSearch.IsCompleted)\r
+ {\r
+ mPath = (List<Point>)mPathSearch.Path;\r
+ mPathSearch = null;\r
\r
- return mPathDirection;\r
+ if (mPath != null) mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[0]);\r
+ }\r
}\r
\r
\r
{\r
DefaultAction();\r
}\r
- \r
+\r
+ Direction direction = GetDirectionToNextCell();\r
+ Point destination = MovementManager.GetNeighbor(Coordinates, direction);\r
+\r
switch (mState)\r
{\r
case AiState.Pacing:\r
+\r
+ if (mGame.IsCellOpen(destination))\r
+ {\r
+ mMotion.Update(timeSpan, direction);\r
+ }\r
+ else\r
+ {\r
+ if (mGame.CurrentFrameNumber % mRetryInterval == 0) ChartPath();\r
+ mMotion.Update(timeSpan);\r
+ }\r
+ break;\r
+\r
case AiState.Chasing:\r
- mMotion.Update(timeSpan, GetDirectionToNextCell());\r
+\r
+ if (mGame.IsCellOpen(destination))\r
+ {\r
+ mMotion.Update(timeSpan, direction);\r
+ }\r
+ else\r
+ {\r
+ if (mGame.CurrentFrameNumber % mRetryInterval == 0) ChartPath();\r
+ mMotion.Update(timeSpan);\r
+ }\r
break;\r
+\r
case AiState.Standing:\r
+ mMotion.Update(timeSpan);\r
+ break;\r
case AiState.Dazed:\r
case AiState.Fighting:\r
case AiState.Retreating:\r
char mId;\r
MovementManager mMotion;\r
AI mAI;\r
- PathFinder pathFinder;\r
- List<Point> mIdlePath = new List<Point>(); // List of waypoints that we got from the map.\r
- int mIdlePathIndex; // Index to the waypoint we're heading for.\r
+ List<Point> mWaypoints = new List<Point>(); // List of waypoints that we got from the map.\r
+ int mWaypointIndex; // Index to the waypoint we're heading for.\r
+ Point mWaypoint;\r
\r
List<Point> mPath; // List of cells in the path between the position between where\r
// we started and the waypoint we're heading for.\r
int mPathIndex; // Index to the cell we're heading for.\r
Direction mPathDirection; // The direction between our current position and the place we're going.\r
+ int mRetryInterval;\r
+ PathFinder.AsyncTask mPathSearch; // If a path search is in progress, this is the task object.\r
\r
AiState mState; // What is the monster doing?\r
\r