/// <summary> /// Perform a flood-fill search from a door to another room's door or a path. /// </summary> /// <param name="door"></param> /// <param name="chanceToTurn"></param> public void CorridorWalk(Tile door, double chanceToTurn, bool allowConnectionToConnectedArea) { bool DoorLeadsToOtherRoom(List <Tile> doors) { foreach (Tile d in doors) { if (door.Area != d.Area) { return(true); } } return(false); } HashSet <CorridorTile> visited = new HashSet <CorridorTile>(); Stack <CorridorTile> path = new Stack <CorridorTile>(); Tile firstTile = Dungeon.GetTileByDirection(door); CorridorTile start = new CorridorTile(door, null, door.Direction); CorridorTile head = new CorridorTile(firstTile, start, door.Direction); path.Push(head); visited.Add(head); while (path.Count > 0) { head = path.Peek(); // Can we carve this tile? // If a door is on the head of the stack, it belongs to the room we came from. // (If we had found a door to another room, we would already have exited the while loop) // Treat these doors as walls. if (head.Space == Space.Wall || head.Space == Space.Granite || head.Space == Space.Door) { path.Pop(); continue; } // Have we found any doors? // If all adjacent doors lead to the room we came from, carry on if (Dungeon.IsTileAdjacentTo(head.Tile, Space.Door, head.From.Tile) && DoorLeadsToOtherRoom(Dungeon.GetAdjacentTilesOfType(head.Tile, Space.Door, head.From.Tile))) { CarveCorridor(path); return; } // Have we found an existing path? Connect to it and end // If we are not allowed to connect to it, then we must skirt around it if (Dungeon.IsTileAdjacentTo(head.Tile, Space.Path, head.From.Tile)) { if (allowConnectionToConnectedArea || RoomUnconnectedToAdjacentArea(door.Area, Dungeon.GetAdjacentTilesOfType(head.Tile, Space.Path, head.From.Tile))) { CarveCorridor(path); return; } else { // Do not allow our path to touch existing paths. Treat this tile as non-carvable path.Pop(); continue; } } // Decide where to go next, or step back one tile if all paths have been explored if (head.DirectionsToTry.Count > 0) { CorridorTile next; do { next = head.ChooseNextTile(Dungeon, chanceToTurn); } while (visited.Contains(next) && head.DirectionsToTry.Count > 0); if (visited.Contains(next)) { path.Pop(); } else { path.Push(next); visited.Add(next); } } else { path.Pop(); } } // There are no doors or paths to connect to, so erase this door EraseDoor(door); }
public Form1(Dungeon d) { dungeon = d; InitializeComponent(); }
/// <summary> /// Commits a stack of wrapped corridor tiles to the dungeon. /// </summary> /// <param name="path"></param> public void CarveCorridor(Stack <CorridorTile> path) { // Unwrap the tiles in the stack to populate a set HashSet <Tile> tiles = new HashSet <Tile>(); foreach (CorridorTile wrappedTile in path) { tiles.Add(wrappedTile.Tile); } // Get an existing Path object if there is one; otherwise make a new object Area area; List <Tile> adjacentPaths = Dungeon.GetAdjacentTilesOfType(path.Peek().Tile, Space.Path); if (adjacentPaths.Count > 0) { area = adjacentPaths[0].Area; } else { area = new Path(); area.InitializeArea(); } // Connect the *end* of the path to any adjacent Area objects Tile end = path.Peek().Tile; end.Area = area; ConnectAreas(end); // Finally begin carving the corridor CorridorTile head = null; while (path.Count > 0) { head = path.Pop(); tiles.Remove(head.Tile); List <Tile> adjacents = Dungeon.GetAdjacentTiles(head.Tile, head.From.Tile); foreach (Tile adjacent in adjacents) { if (tiles.Contains(adjacent)) { // Loops exists, trim it while (path.Peek().Tile != adjacent) { Tile remove = path.Pop().Tile; tiles.Remove(remove); } } } head.Tile.Space = Space.Path; head.Tile.Area = area; } // Connect the *start* of the path to the room it came from ConnectAreas(head.Tile); }