public static List <Vector2Int> GetNeighbors(Vector2Int pos, MapHandler mapHnd) { // check that pos is a valid coordinate if (pos.x < 0 || pos.x >= mapHnd.mapTileWidth || pos.y < 0 || pos.y >= mapHnd.mapTileHeight) { return(null); } List <Vector2Int> neighbors = new List <Vector2Int> (); foreach (char s in "NSEW") { IntPoint newPos = IntPoint.FromCardinal(pos.x, pos.y, s); if (mapHnd.CanMove(newPos)) { neighbors.Add(new Vector2Int(newPos.x, newPos.y)); } } return(neighbors); }
// More accurate BFS lookup private List <IntPoint> MakeNewTravelPlan() { MapHandler mapHnd = MapHandler.GetComponent <MapHandler>(); // TODO: Allow appearing NEXT to either of these. TokenHandler other1 = mapHnd.LeadDate.GetComponent <TokenHandler>(); TokenHandler other2 = mapHnd.LeadPlayer.GetComponent <TokenHandler>(); Vector2Int start = new Vector2Int(TileX, TileY); Vector2Int dest = new Vector2Int(other1.TileX, other1.TileY); int infinity = 100 * 100; // Step 1: Make a new array with the "moves from destination" count. List <int> lookup = new List <int>(); for (int i = 0; i < mapHnd.mapTileWidth * mapHnd.mapTileHeight; i++) { lookup.Add(infinity); } // Step 1.1: Start at the destination and work outwards List <Vector2Int> todo = new List <Vector2Int>(); Dictionary <Vector2Int, bool> blacklist = new Dictionary <Vector2Int, bool>(); todo.Add(dest); blacklist.Add(dest, true); lookup [mapHnd.GetTileIndex(dest.x, dest.y)] = 0; while (todo.Count > 0) { // Next tile to consider Vector2Int next = todo [0]; todo.RemoveAt(0); // Consider all 4 neighbors foreach (char dir in "NSEW") { IntPoint newPosI = IntPoint.FromCardinal(next.x, next.y, dir); Vector2Int newPos = new Vector2Int(newPosI.x, newPosI.y); // Can we move here normally? if (!mapHnd.CanMove(newPosI)) { continue; } // Have we already queued up this tile? if (blacklist.ContainsKey(newPos)) { continue; } // Ok, enqueue it todo.Add(newPos); blacklist.Add(newPos, true); int newDist = lookup [mapHnd.GetTileIndex(next.x, next.y)] + 1; lookup [mapHnd.GetTileIndex(newPos.x, newPos.y)] = newDist; // TEMP: Useful debugging if (false) //mapHnd.showDebugMoves { mapHnd.debugArray [mapHnd.GetTileIndex(newPos.x, newPos.y)].text = "" + newDist; } } } // Step 2: Start from the source, and try to find a path forward. // Choose the least-cost pat at east junction, unless there is none. List <IntPoint> res = new List <IntPoint>(); IntPoint curr = new IntPoint(start.x, start.y); while (true) { // Are we done? if (lookup [mapHnd.GetTileIndex(curr.x, curr.y)] == 1) { return(res); } // Find the next jump List <IntPoint> options = new List <IntPoint>(); foreach (char dir in "NSEW") { IntPoint next = IntPoint.FromCardinal(curr.x, curr.y, dir); if (next.x >= 0 && next.x < mapHnd.mapTileWidth && next.y >= 0 && next.y < mapHnd.mapTileHeight) { int myDist = lookup [mapHnd.GetTileIndex(next.x, next.y)]; if (myDist != infinity) { // Compare it to the current best distance. if (options.Count > 0) { int otherDist = lookup [mapHnd.GetTileIndex(options [0].x, options [0].y)]; if (myDist < otherDist) { // It's strictly better options.Clear(); } if (myDist <= otherDist) { // It's tied or better (we're considering it) options.Add(next); } } else { // No contest options.Add(next); } } } } // Take it if (options.Count > 0) { IntPoint next = options[GameState.rng.Next(options.Count)]; res.Add(next); curr = next; } else { // Shouldn't happen break; } } return(null); }