using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using Uber.HabboHotel.GameClients; using Uber.HabboHotel.Rooms; namespace Uber.HabboHotel.Pathfinding { class Pathfinder { Point[] Movements; CompleteSquare[,] Squares; Room Room; RoomModel Model; RoomUser User; int mapSizeX; int mapSizeY; public Pathfinder(Room Room, RoomUser User) { this.Room = Room; this.Model = Room.Model; this.User = User; if (Room == null || Model == null || User == null) { return; } InitMovements(0); mapSizeX = Model.MapSizeX; mapSizeY = Model.MapSizeY; Squares = new CompleteSquare[mapSizeX, mapSizeY]; for (int x = 0; x < mapSizeX; x++) { for (int y = 0; y < mapSizeY; y++) { Squares[x, y] = new CompleteSquare(x, y); } } } private IEnumerable GetSquares() { for (int x = 0; x < mapSizeX; x++) { for (int y = 0; y < mapSizeY; y++) { yield return new Point(x, y); } } } private IEnumerable ValidMoves(int x, int y) { foreach (Point movePoint in Movements) { int newX = x + movePoint.X; int newY = y + movePoint.Y; if (ValidCoordinates(newX, newY) && IsSquareOpen(newX, newY, true)) { yield return new Point(newX, newY); } } } public List FindPath() { // Locate the user, and set the distance to zero int UserX = User.X; int UserY = User.Y; Squares[User.X, User.Y].DistanceSteps = 0; // Find all possible moves while (true) { Boolean MadeProgress = false; foreach (Point MainPoint in GetSquares()) { int x = MainPoint.X; int y = MainPoint.Y; if (IsSquareOpen(x, y, true)) { int passHere = Squares[x, y].DistanceSteps; foreach (Point movePoint in ValidMoves(x, y)) { int newX = movePoint.X; int newY = movePoint.Y; int newPass = passHere + 1; if (Squares[newX, newY].DistanceSteps > newPass) { Squares[newX, newY].DistanceSteps = newPass; MadeProgress = true; } } } } if (!MadeProgress) { break; } } // Locate the goal int goalX = User.GoalX; int goalY = User.GoalY; if (goalX == -1 || goalY == -1) { return null; } // Now trace the shortest possible route to our goal List Path = new List(); Path.Add(new Coord(User.GoalX, User.GoalY)); while (true) { Point lowestPoint = Point.Empty; int lowest = 100; foreach (Point movePoint in ValidMoves(goalX, goalY)) { int count = Squares[movePoint.X, movePoint.Y].DistanceSteps; if (count < lowest) { lowest = count; lowestPoint.X = movePoint.X; lowestPoint.Y = movePoint.Y; } } if (lowest != 100) { Squares[lowestPoint.X, lowestPoint.Y].IsPath = true; goalX = lowestPoint.X; goalY = lowestPoint.Y; Path.Add(new Coord(lowestPoint.X, lowestPoint.Y)); } else { break; } if (goalX == UserX && goalY == UserY) { break; } } return Path; } private Boolean IsSquareOpen(int x, int y, Boolean CheckHeight) { if (Room.ValidTile(x, y) && User.AllowOverride) { return true; } if (User.X == x && User.Y == y) { return true; } bool isLastStep = false; if (User.GoalX == x && User.GoalY == y) { isLastStep = true; } if (!Room.CanWalk(x, y, 0, isLastStep)) { return false; } return true; } private Boolean ValidCoordinates(int x, int y) { if (x < 0 || y < 0 || x > mapSizeX || y > mapSizeY) { return false; } return true; } public void InitMovements(int movementCount) { if (movementCount == 4) { Movements = new Point[] { new Point(0, -1), new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(-1, -1), new Point(1, -1), new Point(1, 1), new Point(-1, 1) }; } else { Movements = new Point[] { new Point(0, -1), new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(-1, -1), new Point(1, -1), new Point(1, 1), new Point(-1, 1) }; } } } class CompleteSquare { public int x = 0; public int y = 0; int _distanceSteps = 100; public int DistanceSteps { get { return _distanceSteps; } set { _distanceSteps = value; } } bool _isPath = false; public bool IsPath { get { return _isPath; } set { _isPath = value; } } public CompleteSquare(int x, int y) { this.x = x; this.y = y; } } }