override public void StartDigging(VirtualMap map, CellLocation starting_location, int directionChangeModifier) { CellLocation currentLocation = starting_location; map.MarkAsVisited(currentLocation); // Pick a starting previous direction VirtualMap.DirectionType previousDirection = VirtualMap.DirectionType.North; List <CellLocation> previousLocations = new List <CellLocation>(); // Repeat until all cells have been visited while (!map.AllCellsVisited) { // Get a starting direction DirectionPicker directionPicker = new DirectionPicker(map, currentLocation, directionChangeModifier, previousDirection); VirtualMap.DirectionType direction = directionPicker.GetNextDirection(map, currentLocation); if (direction != VirtualMap.DirectionType.None) { // Create a corridor in the current cell and flag it as visited previousLocations.Add(currentLocation); previousDirection = direction; currentLocation = map.CreateCorridor(currentLocation, direction); map.FlagCellAsVisited(currentLocation); } else { // Backtrack currentLocation = previousLocations[previousLocations.Count - 1]; previousLocations.RemoveAt(previousLocations.Count - 1); } } }
override public void StartDigging(VirtualMap map, CellLocation starting_location, int directionChangeModifier) { CellLocation currentLocation = starting_location; map.MarkAsVisited(currentLocation); // Pick a previous direction VirtualMap.DirectionType previousDirection = VirtualMap.DirectionType.North; // Repeat until all cells have been visited while (!map.AllCellsVisited) { // Get a starting direction DirectionPicker directionPicker = new DirectionPicker(map, currentLocation, directionChangeModifier, previousDirection); VirtualMap.DirectionType direction = directionPicker.GetNextDirection(map, currentLocation); if (direction != VirtualMap.DirectionType.None) { // Create a corridor in the current cell and flag it as visited currentLocation = map.CreateCorridor(currentLocation, direction); map.FlagCellAsVisited(currentLocation); previousDirection = direction; } // or start from another visited cell // NOTE: This may be less performant! else { currentLocation = map.GetRandomVisitedCell(currentLocation); // No visited cell available: proceed from a random unvisited cell if (currentLocation.x == -1) { currentLocation = map.PickRandomUnvisitedLocation(); map.MarkAsVisited(currentLocation); } } } }
// Open dead ends by linking them to rooms private void OpenDeadEnds(VirtualMap map) { // Console.WriteLine("DEAD END MOD: " + openDeadEndModifier); if (openDeadEndModifier == 0) { return; } IEnumerable <CellLocation> deads = map.DeadEndCellLocations; foreach (CellLocation deadEnd in deads) { if (DungeonGenerator.Random.Instance.Next(1, 99) < openDeadEndModifier) { CellLocation currentLocation = deadEnd; // int count=0; do { // Initialize the direction picker not to select the dead-end corridor direction DirectionPicker directionPicker = new DirectionPicker(map, currentLocation, map.CalculateDeadEndCorridorDirection(currentLocation)); // Debug.Log("We have a dead and " + directionPicker); VirtualMap.DirectionType direction = directionPicker.GetNextDirection(map, currentLocation); // Debug.Log("We choose dir " + direction); if (direction == VirtualMap.DirectionType.None) { throw new InvalidOperationException("Could not remove the dead end!"); } // Debug.Log("Cannot go that way!"); else { // Create a corridor in the selected direction currentLocation = map.CreateCorridor(currentLocation, direction); } // count++; } while (map.IsDeadEnd(currentLocation) && currentLocation != deadEnd); // Stop when you intersect an existing corridor, or when you end back to the starting cell (that means we could not remove the dead end, happens with really small maps // Debug.Log("Dead end removed"); } } }
private void CreateVerticalCorridor(VirtualMap map, BSPTreeNodeBounds roomBoundsBottom, BSPTreeNodeBounds roomBoundsTop) { BSPTreeNodeBounds higherRoomBounds = null, lowerRoomBounds = null; int v_start = 0; bool createLShape = false; int higher_min_v = Mathf.Max(roomBoundsBottom.min_x, roomBoundsTop.min_x); int lower_max_v = Mathf.Min(roomBoundsBottom.max_x, roomBoundsTop.max_x); int overlapping_v_range = lower_max_v - higher_min_v; if (overlapping_v_range > 0) { // They overlap: we choose randomly the start where the sides overlap v_start = DungeonGenerator.Random.Instance.Next(higher_min_v, lower_max_v - 1); } else { // They do not overlap! We'll need a L-shaped corridor! // We do so starting from one room, then going OVER the other, and then going down //Debug.Log("L"); createLShape = true; // We now need to check which is the higher one if (roomBoundsBottom.max_x > roomBoundsTop.max_x) { // B higher than T higherRoomBounds = roomBoundsBottom; lowerRoomBounds = roomBoundsTop; } else { // T higher than B higherRoomBounds = roomBoundsTop; lowerRoomBounds = roomBoundsBottom; } // The v_start comes from the higher one v_start = DungeonGenerator.Random.Instance.Next( higherRoomBounds.min_x, higherRoomBounds.max_x - 1); } // We create a corridor from south to north int corridorWidth = 1; if (!createLShape) { corridorWidth = Mathf.Min(overlapping_v_range, maxCorridorWidth); if (corridorWidth > 1 && overlapping_v_range > 0) { int overflow = v_start + (corridorWidth - 1) - (lower_max_v - 1); v_start -= overflow; //Debug.Log(overflow); } } for (int y = roomBoundsBottom.max_y - 1; y < roomBoundsTop.min_y; y++) { CellLocation l = new CellLocation(v_start * 2 + 1, y * 2 + 1); // If already entering a corridor, we stop here! /*CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l, VirtualMap.DirectionType.North); * bool makeDoor = !(map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor); * makeDoor = true;*/ map.CreateCorridor(l, VirtualMap.DirectionType.North, corridorWidth, makeDoor: true); } if (createLShape) { // We also create the W-E corridor for (int x = lowerRoomBounds.max_x - 1; x < v_start; x++) { int y_start = 0; if (lowerRoomBounds == roomBoundsTop) { y_start = roomBoundsTop.min_y; } else { y_start = roomBoundsBottom.max_y - 1; } CellLocation l = new CellLocation(x * 2 + 1, y_start * 2 + 1); // If already entering a corridor, we stop here! //CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l, VirtualMap.DirectionType.East); //bool makeDoor = !(map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor); //CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l, VirtualMap.DirectionType.East); //if (map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor) return; map.CreateCorridor(l, VirtualMap.DirectionType.East, makeDoor: true); } } }
private void CreateHorizontalCorridor(VirtualMap map, BSPTreeNodeBounds roomBoundsLeft, BSPTreeNodeBounds roomBoundsRight) { BSPTreeNodeBounds higherRoomBounds = null, lowerRoomBounds = null; int v_start = 0; bool createLShape = false; int higher_min_v = Mathf.Max(roomBoundsLeft.min_y, roomBoundsRight.min_y); int lower_max_v = Mathf.Min(roomBoundsLeft.max_y, roomBoundsRight.max_y); int overlapping_v_range = lower_max_v - higher_min_v; if (overlapping_v_range > 0) { // They overlap: we choose randomly the start where the sides overlap v_start = DungeonGenerator.Random.Instance.Next( higher_min_v, lower_max_v - 1); } else { // They do not overlap! We'll need a L-shaped corridor! // We do so starting from one room, then going OVER the other, and then going down //Debug.Log("L"); createLShape = true; // We now need to check which is the higher one if (roomBoundsLeft.max_y > roomBoundsRight.max_y) { // L higher than R higherRoomBounds = roomBoundsLeft; lowerRoomBounds = roomBoundsRight; } else { // R higher than L higherRoomBounds = roomBoundsRight; lowerRoomBounds = roomBoundsLeft; } // The y_start comes from the higher one v_start = DungeonGenerator.Random.Instance.Next( higherRoomBounds.min_y, higherRoomBounds.max_y - 1); } // We create a corridor from west to east int corridorWidth = 1; if (!createLShape) { corridorWidth = Mathf.Min(overlapping_v_range, maxCorridorWidth); if (corridorWidth > 1 && overlapping_v_range > 0) { //Debug.Log("Start: " + v_start); int overflow = higher_min_v - (v_start - (corridorWidth - 1)); //(v_start - (corridorWidth - 1)) + (higher_min_v - 1); v_start += overflow; //Debug.Log("Overflow: " + overflow); //Debug.Log("End: " + v_start); } } for (int x = roomBoundsLeft.max_x - 1; x < roomBoundsRight.min_x; x++) { CellLocation l = new CellLocation(x * 2 + 1, v_start * 2 + 1); //Debug.Log("EAST: " + l); // If already entering a corridor, we stop here! //CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l,VirtualMap.DirectionType.East); //if (map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor) return; //CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l, VirtualMap.DirectionType.East); //bool makeDoor = !(map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor); map.CreateCorridor(l, VirtualMap.DirectionType.East, corridorWidth, makeDoor: true); } if (createLShape) { // We also create the S-N corridor for (int y = lowerRoomBounds.max_y - 1; y < v_start; y++) { int x_start = 0; if (lowerRoomBounds == roomBoundsRight) { x_start = roomBoundsRight.min_x; } else { x_start = roomBoundsLeft.max_x - 1; } CellLocation l = new CellLocation(x_start * 2 + 1, y * 2 + 1); // If already entering a corridor, we stop here! //CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l, VirtualMap.DirectionType.East); //if (map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor) return; // If already entering a corridor, we stop here! //CellLocation target_l = map.GetNeighbourCellLocationOfSameType(l, VirtualMap.DirectionType.North); //bool makeDoor = !(map.GetCell(target_l).Type == VirtualCell.CellType.CorridorFloor); map.CreateCorridor(l, VirtualMap.DirectionType.North, makeDoor: true); } } }