namespace Otaku.Virtual.Rooms.Pathfinding { using Otaku.Virtual.Rooms; using System; using System.Collections; public class Pathfinder { private Heap closedList; private mapNode goalNode; private byte[,] heightMap; private int maxX; private int maxY; private Heap openList; private ArrayList solutionList; private mapNode startNode; private virtualRoom.squareState[,] stateMap; private ArrayList successorList; private bool[,] unitMap; public Pathfinder(virtualRoom.squareState[,] stateMap, byte[,] heightMap, bool[,] unitMap) { this.stateMap = stateMap; this.heightMap = heightMap; this.unitMap = unitMap; this.maxX = unitMap.GetLength(1) - 1; this.maxY = unitMap.GetLength(0) - 1; this.openList = new Heap(); this.closedList = new Heap(); this.solutionList = new ArrayList(); this.successorList = new ArrayList(); } public int[] getNext(int X, int Y, int goalX, int goalY) { if ((X == goalX) && (Y == goalY)) { return null; } int num = this.maxX * this.maxY; int num2 = 0; this.goalNode = new mapNode(goalX, goalY, 0.0, null, null, this); this.startNode = new mapNode(X, Y, 0.0, null, this.goalNode, this); this.openList.Add(this.startNode); while (this.openList.Count > 0) { if (num2 == num) { return null; } num2++; mapNode parentNode = (mapNode) this.openList.Pop(); if (parentNode.sameCoordsAs(this.goalNode)) { while (parentNode != null) { this.solutionList.Insert(0, parentNode); parentNode = parentNode.parentNode; } break; } parentNode.getSuccessors(); this.successorList = parentNode.allSuccessors; foreach (mapNode node2 in this.successorList) { mapNode node3 = null; if (this.openList.Contains(node2)) { node3 = (mapNode) this.openList[this.openList.IndexOf(node2)]; if (node2.totalCost > node3.totalCost) { continue; } } mapNode node4 = null; if (this.closedList.Contains(node2)) { node4 = (mapNode) this.closedList[this.closedList.IndexOf(node2)]; if (node2.totalCost > node4.totalCost) { continue; } } this.openList.Remove(node3); this.closedList.Remove(node4); this.openList.Push(node2); } this.closedList.Add(parentNode); } if (this.solutionList.Count == 0) { return null; } mapNode node5 = (mapNode) this.solutionList[1]; return new int[] { node5.X, node5.Y }; } private bool spotMoveHeightOK(int X, int Y, int goalX, int goalY) { try { int num = this.heightMap[X, Y]; int num2 = this.heightMap[goalX, goalY]; for (int i = -1; i <= 1; i++) { if (num == (num2 - i)) { return true; } } return false; } catch { return false; } } private bool spotOpen(int X, int Y) { try { if (this.unitMap[X, Y]) { return false; } if ((this.stateMap[X, Y] != virtualRoom.squareState.Open) && (this.stateMap[X, Y] != virtualRoom.squareState.Rug)) { return false; } return true; } catch { return false; } } private class mapNode : IComparable { private double _Cost; private double _GoalEstimate; private Pathfinder _Pathfinder; private Pathfinder.mapNode goalNode; internal Pathfinder.mapNode parentNode; private ArrayList Successors; internal int X; internal int Y; internal mapNode(int X, int Y, double Cost, Pathfinder.mapNode parentNode, Pathfinder.mapNode goalNode, Pathfinder parentPathfinder) { this.X = X; this.Y = Y; this.parentNode = parentNode; this.goalNode = goalNode; this._Cost = Cost; this._Pathfinder = parentPathfinder; this.Successors = new ArrayList(); } private void addSuccessor(int X, int Y) { if (this._Pathfinder.spotOpen(X, Y) && this._Pathfinder.spotMoveHeightOK(this.X, this.Y, X, Y)) { Pathfinder.mapNode node = new Pathfinder.mapNode(X, Y, this._Cost, this, this.goalNode, this._Pathfinder); this.Successors.Add(node); } } internal void getSuccessors() { this.addSuccessor(this.X - 1, this.Y); this.addSuccessor(this.X + 1, this.Y); this.addSuccessor(this.X, this.Y - 1); this.addSuccessor(this.X, this.Y + 1); if (this._Pathfinder.spotOpen(this.X, this.Y - 1)) { if (this._Pathfinder.spotOpen(this.X - 1, this.Y)) { this.addSuccessor(this.X - 1, this.Y - 1); } if (this._Pathfinder.spotOpen(this.X + 1, this.Y)) { this.addSuccessor(this.X + 1, this.Y - 1); } } if (this._Pathfinder.spotOpen(this.X + 1, this.Y) && this._Pathfinder.spotOpen(this.X, this.Y + 1)) { this.addSuccessor(this.X + 1, this.Y + 1); } if (this._Pathfinder.spotOpen(this.X - 1, this.Y) && this._Pathfinder.spotOpen(this.X, this.Y - 1)) { this.addSuccessor(this.X - 1, this.Y + 1); } } internal bool sameCoordsAs(Pathfinder.mapNode Node) { return ((this.X == Node.X) && (this.Y == Node.Y)); } int IComparable.CompareTo(object obj) { return -this.totalCost.CompareTo(((Pathfinder.mapNode) obj).totalCost); } internal ArrayList allSuccessors { get { return this.Successors; } } internal double Cost { get { return this._Cost; } set { this._Cost = value; } } internal double goalEstimate { get { if (this.goalNode == null) { this._GoalEstimate = 0.0; } else { double x = this.X - this.goalNode.X; double num2 = this.Y - this.goalNode.Y; this._GoalEstimate = Math.Sqrt(Math.Pow(x, 2.0) + Math.Pow(num2, 2.0)); } return this._GoalEstimate; } set { this._GoalEstimate = value; } } internal double totalCost { get { return (this._Cost + this.goalEstimate); } } } } }