private List <Point> CorridorBetweenPoints(DungeonFloorSettings settings, int x1, int y1, int x2, int y2, Join joinType = Join.Either) { if (x1 == x2 && y1 == y2 || x1 == x2 || y1 == y2) { return(new List <Point> { new Point(x1, y1), new Point(x2, y2) }); } // 2 Corridors // NOTE: Never randomly choose a join that will go out of bounds // when the walls are added. Join join = joinType; if (joinType == Join.Either) { if (new[] { 0, 1 }.Intersect(new[] { x1, x2, y1, y2 }).Any()) { join = Join.Bottom; } else if (new[] { settings.Width - 1, settings.Width - 2 }.Intersect(new[] { x1, x2 }).Any() || new[] { settings.Height - 1, settings.Height - 2 }.Intersect(new[] { y1, y2 }).Any()) { join = Join.Top; } else { join = Random.NextDouble() > 0.5 ? Join.Top : Join.Bottom; } } if (join == Join.Top) { return(new List <Point> { new Point(x1, y1), new Point(x1, y2), new Point(x2, y2) }); } else { return(new List <Point> { new Point(x1, y1), new Point(x2, y1), new Point(x2, y2) }); } }
private Rectangle GenerateRoom(DungeonFloorSettings settings) { int w = Random.Next(settings.RoomSize.Min, settings.RoomSize.Max); int h = Random.Next(settings.RoomSize.Min, settings.RoomSize.Max); int x = Random.Next(1, settings.Width - w - 1); int y = Random.Next(1, settings.Height - h - 1); return(new Rectangle { W = w, H = h, X = x, Y = y }); }
public override Level Generate(Warp returnWarp) { int depth = DepthRange.Value; var floors = new List <Floor>(); var id = Guid.NewGuid(); var location = new Location(LocationType.Dungeon, id, 0); for (int i = 0; i < depth; i++) { var floor = GenerateFloor(DungeonFloorSettings.GetSettings(i, Random)); floor.GenerateMonsters(isFirstEnter: true); floors.Add(floor); } PlaceFloorWarps(floors, id, returnWarp); return(new Level(location, floors.AsReadOnly())); }
public Floor GenerateFloor(DungeonFloorSettings settings) { var level = new Dictionary <Point, Tile>(); // build an empty dungeon, blank the room and corridor lists for (int i = 0; i < settings.Width; i++) { for (int j = 0; j < settings.Height; j++) { level[new Point(i, j)] = Tile.Stone; } } var roomList = new List <Rectangle>(); var corridorList = new List <List <Point> >(); int maxIters = settings.MaxRooms * 5; for (int i = 0; i < maxIters; i++) { var tmpRoom = GenerateRoom(settings); if (settings.RoomsOverlap || roomList.Count == 0) { roomList.Add(tmpRoom); } else { tmpRoom = GenerateRoom(settings); var tmpRoomList = roomList.ToList(); if (RoomsOverlapping(tmpRoom, tmpRoomList) == false) { roomList.Add(tmpRoom); } } if (roomList.Count >= settings.MaxRooms) { break; } } // connect the rooms for (int i = 0; i < roomList.Count - 1; i++) { JoinRooms(settings, corridorList, roomList[i], roomList[i + 1]); } // do the Random joins for (int i = 0; i < settings.RandomConnections; i++) { var room1 = roomList[Random.Next(roomList.Count)]; var room2 = roomList[Random.Next(roomList.Count)]; JoinRooms(settings, corridorList, room1, room2); } // do the spurs for (int i = 0; i < settings.RandomSpurs; i++) { var room1 = new Rectangle { X = Random.Next(2, settings.Width - 2), Y = Random.Next(2, settings.Height - 2), W = 1, H = 1 }; var room2 = roomList[Random.Next(roomList.Count)]; JoinRooms(settings, corridorList, room1, room2); } // fill the map // paint rooms foreach (var room in roomList) { for (int x = 0; x < room.W; x++) { for (int y = 0; y < room.H; y++) { level[new Point(room.X + x, room.Y + y)] = Tile.Floor; } } } // paint corridors foreach (var corridor in corridorList) { int x1 = corridor[0].X; int y1 = corridor[0].Y; int x2 = corridor[1].X; int y2 = corridor[1].Y; for (int w = 0; w < (Math.Abs(x1 - x2) + 1); w++) { for (int h = 0; h < (Math.Abs(y1 - y2) + 1); h++) { level[new Point(w + Math.Min(x1, x2), h + Math.Min(y1, y2))] = Tile.Floor; } } if (corridor.Count == 3) { int x3 = corridor[2].X; int y3 = corridor[2].Y; for (int w = 0; w < (Math.Abs(x2 - x3) + 1); w++) { for (int h = 0; h < (Math.Abs(y2 - y3) + 1); h++) { level[new Point(w + Math.Min(x2, x3), h + Math.Min(y2, y3))] = Tile.Floor; } } } } var entities = new Map <Point, Entity>(); // paint the walls for (int col = 1; col < settings.Width - 1; col++) { for (int row = 1; row < settings.Height - 1; row++) { if (level[new Point(col, row)] == Tile.Floor) { if (level[new Point(col - 1, row - 1)] == Tile.Stone) { level[new Point(col - 1, row - 1)] = Tile.Wall; } if (level[new Point(col, row - 1)] == Tile.Stone) { level[new Point(col, row - 1)] = Tile.Wall; } if (level[new Point(col + 1, row - 1)] == Tile.Stone) { level[new Point(col + 1, row - 1)] = Tile.Wall; } if (level[new Point(col - 1, row)] == Tile.Stone) { level[new Point(col - 1, row)] = Tile.Wall; } if (level[new Point(col + 1, row)] == Tile.Stone) { level[new Point(col + 1, row)] = Tile.Wall; } if (level[new Point(col - 1, row + 1)] == Tile.Stone) { level[new Point(col - 1, row + 1)] = Tile.Wall; } if (level[new Point(col, row + 1)] == Tile.Stone) { level[new Point(col, row + 1)] = Tile.Wall; } if (level[new Point(col + 1, row + 1)] == Tile.Stone) { level[new Point(col + 1, row + 1)] = Tile.Wall; } } } } // paint doors foreach (var room in roomList) { // paint top doors for (int x = 1; x < room.W - 1; x++) { int top1y = room.Y - 1; var position = new Point(room.X + x, top1y); if (top1y <= 0 || entities.Forward.Contains(position)) { break; } if (level[new Point(room.X + x, top1y)] == Tile.Floor && level[new Point(room.X + x + 1, top1y)] != Tile.Floor && level[new Point(room.X + x - 1, top1y)] != Tile.Floor) { if (Random.NextDouble() > 0.25) { entities.Add(position, new Door()); } } } // paint bottom doors for (int x = 1; x < room.W - 1; x++) { int bottom1y = room.Y + room.H; var position = new Point(room.X + x, bottom1y); if (bottom1y >= settings.Height || entities.Forward.Contains(position)) { break; } if (level[new Point(room.X + x, bottom1y)] == Tile.Floor && level[new Point(room.X + x + 1, bottom1y)] != Tile.Floor && level[new Point(room.X + x - 1, bottom1y)] != Tile.Floor) { if (Random.NextDouble() > 0.25) { entities.Add(position, new Door()); } } } // paint left doors for (int y = 1; y < room.H - 1; y++) { int left1x = room.X - 1; var position = new Point(left1x, room.Y + y); if (left1x <= 0 || entities.Forward.Contains(position)) { break; } if (level[new Point(left1x, room.Y + y)] == Tile.Floor && level[new Point(left1x, room.Y + y + 1)] != Tile.Floor && level[new Point(left1x, room.Y + y - 1)] != Tile.Floor) { if (Random.NextDouble() > 0.25) { entities.Add(position, new Door()); } } } // paint right doors for (int y = 1; y < room.H - 1; y++) { int right1x = room.X + room.W; var position = new Point(right1x, room.Y + y); if (right1x <= 0 || entities.Forward.Contains(position)) { break; } if (level[new Point(right1x, room.Y + y)] == Tile.Floor && level[new Point(right1x, room.Y + y + 1)] != Tile.Floor && level[new Point(right1x, room.Y + y - 1)] != Tile.Floor) { if (Random.NextDouble() > 0.25) { entities.Add(position, new Door()); } } } } var floor = new Floor(level, entities, settings); return(floor); }
private void JoinRooms(DungeonFloorSettings settings, List <List <Point> > corridorList, Rectangle room1, Rectangle room2, Join joinType = Join.Either) { // sort by the value of x var sortedRooms = new List <Rectangle> { room1, room2 }; sortedRooms.Sort((r1, r2) => r1.X.CompareTo(r2.X)); int x1 = sortedRooms[0].X; int y1 = sortedRooms[0].Y; int w1 = sortedRooms[0].W; int h1 = sortedRooms[0].H; int x1_2 = x1 + w1 - 1; int y1_2 = y1 + h1 - 1; int x2 = sortedRooms[1].X; int y2 = sortedRooms[1].Y; int w2 = sortedRooms[1].W; int h2 = sortedRooms[1].H; int x2_2 = x2 + w2 - 1; int y2_2 = y2 + h2 - 1; if (x1 < (x2 + w2) && x2 < (x1 + w1)) // overlapping on x { int jx1 = Random.Next(x2, x1_2); int jx2 = jx1; var tmpY = new List <int> { y1, y2, y1_2, y2_2 }; tmpY.Sort(); int jy1 = tmpY[1] + 1; int jy2 = tmpY[2] - 1; var corridors = CorridorBetweenPoints(settings, jx1, jy1, jx2, jy2); corridorList.Add(corridors); } else if (y1 < (y2 + h2) && y2 < (y1 + h1)) // overlapping on y { int jy1; int jy2; if (y2 > y1) { jy1 = Random.Next(y2, y1_2); jy2 = jy1; } else { jy1 = Random.Next(y1, y2_2); jy2 = jy1; } var tmpX = new List <int> { x1, x2, x1_2, x2_2 }; tmpX.Sort(); int jx1 = tmpX[1] + 1; int jx2 = tmpX[2] - 1; var corridors = CorridorBetweenPoints(settings, jx1, jy1, jx2, jy2); corridorList.Add(corridors); } else // no overlap { Join join = joinType; if (joinType == Join.Either) { join = Random.NextDouble() > 0.5 ? Join.Top : Join.Bottom; } if (join == Join.Top) { if (y2 > y1) { int jx1 = x1_2 + 1; int jy1 = Random.Next(y1, y1_2); int jx2 = Random.Next(x2, x2_2); int jy2 = y2 - 1; var corridors = CorridorBetweenPoints(settings, jx1, jy1, jx2, jy2, Join.Bottom); corridorList.Add(corridors); } else { int jx1 = Random.Next(x1, x1_2); int jy1 = y1 - 1; int jx2 = x2 - 1; int jy2 = Random.Next(y2, y2_2); var corridors = CorridorBetweenPoints(settings, jx1, jy1, jx2, jy2, Join.Top); corridorList.Add(corridors); } } else if (join == Join.Bottom) { if (y2 > y1) { int jx1 = Random.Next(x1, x1_2); int jy1 = y1_2 + 1; int jx2 = x2 - 1; int jy2 = Random.Next(y2, y2_2); var corridors = CorridorBetweenPoints(settings, jx1, jy1, jx2, jy2, Join.Top); corridorList.Add(corridors); } } else { int jx1 = x1_2 + 1; int jy1 = Random.Next(y1, y1_2); int jx2 = Random.Next(x2, x2_2); int jy2 = y2_2 + 1; var corridors = CorridorBetweenPoints(settings, jx1, jy1, jx2, jy2, Join.Bottom); corridorList.Add(corridors); } } }