/* * * Squares is an array of square objects. * * */ public Pathfinder(Map _map) { InitMovements(4); _squares = new CompleteSquare[_map.Width, _map.Height]; map = _map; path = new List<CompleteSquare>(); }
/// <summary> /// Get a map in a thread-safe way. It's expected that multiple bots will try /// to grab the same map simultaneously. This prevents them from: /// a) allocating more than one Map object; /// b) reading the same file simultaneously, causing locking issues; and /// c) downloading the map more than once. /// </summary> /// <param name="filename">File name of the map.</param> /// <param name="saveTo">The location of the map on the hard drive.</param> /// <param name="main">Main communicator.</param> /// <returns>The map object.</returns> public static Map GetMap(string filename, string saveTo, MasterCommunicator main) { lock (locker) { Map playableMap = null; FileInfo file = new FileInfo(saveTo); if (!file.Exists) { playableMap = AttemptDownload(filename, main); } else { playableMap = new Map(saveTo); string hash = playableMap.SHA1Hash; if (!main.GetProxy().HashIsValid(filename, hash)) { Debugger.Write("Map {0} is outdated; downloading it...", filename); playableMap = AttemptDownload(filename, main); } } cachedMap = playableMap; cachedMapName = filename; return playableMap; } }
/// <summary> /// Disposes of the game mode. /// </summary> public virtual void Dispose() { if (OnDispose != null) OnDispose.Invoke(); OnDispose = null; CurrentMap = null; }
/// <summary> /// Find the shortest path to the destination using the A* algorithm. /// </summary> /// <param name="map"></param> /// <param name="player"></param> /// <param name="destinationX">The destination x (in "pixels").</param> /// <param name="destinationY">The destination y (in "pixels").</param> /// <exception cref="InvalidOperationException">Thrown if the target destination /// is unreachable.</exception> public Path FindPath(Map map, Player player, int destinationX, int destinationY) { MinotaurPathfinder.Pathfinder pathfinder = new MinotaurPathfinder.Pathfinder(map); pathfinder.Pathfind(map, player, destinationX, destinationY); Path path = new Path(); foreach (MinotaurPathfinder.MetaCompleteSquare square in pathfinder.FullPath()) { path.AppendNode(new Node(square.X, square.Y)); } pathfinder.Dispose(); return path; }
/// <summary> /// Performs the actual map download operation. /// </summary> /// <param name="localPath">Local path in the operating system.</param> /// <param name="mapFileName"></param> /// <returns></returns> private Map DownloadMap(string mapFileName) { Debugger.Write("Downloading map {0}...", mapFileName); VTankObject.Map map = MainServer.GetProxy().DownloadMap(mapFileName); string title = map.title; int width = map.width; int height = map.height; VTankObject.Tile[] tiles = map.tileData; Map newMap = new Map(title, mapFileName, (uint)width, (uint)height); int size = width * height; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { VTankObject.Tile relevantTile = tiles[y * width + x]; newMap.SetTile((uint)x, (uint)y, new Tile( (uint)relevantTile.id, (ushort)relevantTile.objectId, (ushort)relevantTile.eventId, relevantTile.passable, (ushort)relevantTile.height, (ushort)relevantTile.type, (ushort)relevantTile.effect)); } } List<int> buf = new List<int>(); for (int i = 0; i < map.supportedGameModes.Length; i++) { buf.Add(map.supportedGameModes[i]); } newMap.SetGameModes(buf); return newMap; }
/// <summary> /// Get a new list of spawn points. /// </summary> private void RefreshSpawnPointList() { bool ctf = GameMode == VTankObject.GameMode.CAPTURETHEFLAG; bool ctb = GameMode == VTankObject.GameMode.CAPTURETHEBASE; int halfTile = Tile.TILE_SIZE_IN_PIXELS / 2; spawnPointList.Clear(); AIFramework.Bot.Game.Map map = CurrentMap; for (int y = 0; y < map.Height; ++y) { for (int x = 0; x < map.Width; ++x) { AIFramework.Bot.Game.Tile tile = map.GetTile(x, y); if (GameMode == VTankObject.GameMode.DEATHMATCH) { if (tile.EventID == 1) // '1' represents a spawn point. { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS - halfTile, y * Tile.TILE_SIZE_IN_PIXELS - halfTile)); } } else if (ctf) { if (tile.EventID == 4 || tile.EventID == 5) { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS, y * Tile.TILE_SIZE_IN_PIXELS)); } } else if (ctb) { if (tile.EventID >= 8 && tile.EventID < 14) { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS, y * Tile.TILE_SIZE_IN_PIXELS)); } } else /*if (GameMode == VTankObject.GameMode.TEAMDEATHMATCH)*/ { if (tile.EventID == 3 || tile.EventID == 2) { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS - halfTile, y * Tile.TILE_SIZE_IN_PIXELS - halfTile)); } } } } foreach (TileNode node in spawnPointList) { int tileX = (int)Math.Round((double)node.X / Tile.TILE_SIZE_IN_PIXELS); int tileY = (int)Math.Round((double)node.Y / Tile.TILE_SIZE_IN_PIXELS); Tile tile = map.GetTile(tileX, tileY); if (!tile.IsPassable) { Console.Error.WriteLine("[WARNING] ({0}, {1}) => ({2}, {3}) is unpassable.", node.X, node.Y, tileX, tileY); } } refreshSpawnPointList = false; spawnPointIndex = 0; Shuffle <TileNode>(spawnPointList); }
public static Path FindPath(Map map, Player player, int destinationPixelsX, int destinationPixelsY) { return Path.Optimize( Algorithm.FindPath(map, player, destinationPixelsX, destinationPixelsY)); }
public void Pathfind(Map map, Player player, int destinationX, int destinationY) { /* * * Find path from hero to monster. First, get coordinates * of hero. * * */ Point startingPoint = new Point((int)player.Position.x / 64, -(int)player.Position.y / 64); startingX = startingPoint.X; startingY = startingPoint.Y; this.destinationX = destinationX / 64; this.destinationY = (destinationY / 64); // Initialize path. for (int y = 0; y < map.Height; ++y) { for (int x = 0; x < map.Width; ++x) { SquareContent content = SquareContent.Empty; Tile tile = map.GetTile(x, y); if (!tile.IsPassable) { content = SquareContent.Wall; } else if (x == startingX && y == startingY) { content = SquareContent.Starting; } _squares[x, y] = new CompleteSquare() { X = -1, Y = -1, IsPath = false, ContentCode = content, DistanceSteps = 10000 }; } } /* * * Hero starts at distance of 0. * * */ _squares[startingPoint.X, startingPoint.Y].DistanceSteps = 0; while (true) { bool madeProgress = false; /* * * Look at each square on the board. * * */ foreach (Point mainPoint in AllSquares()) { int x = mainPoint.X; int y = mainPoint.Y; /* * * If the square is open, look through valid moves given * the coordinates of that square. * * */ Tile relevantTile = map.GetTile(x, y); if (relevantTile.IsPassable) { 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; } } HighlightPath(); }
public void Dispose() { map = null; path.Clear(); path = null; _squares = null; }
/// <summary> /// Constructs the game mode. /// </summary> /// <param name="currentMap"></param> /// <param name="currentGameMode"></param> public GameModeHandler(Map currentMap, VTankObject.GameMode currentGameMode) { CurrentMap = currentMap; CurrentGameMode = currentGameMode; }