static void AdvanceHallwayPath(GenRoom hub, List <GenRoom> visited) { if (hub != null && hub.Exists) { visited.Add(hub); if (!visited.Contains(hub.LeftRoom)) { AdvanceBorderPath(hub.LeftRoom, visited); } if (!visited.Contains(hub.RightRoom)) { AdvanceBorderPath(hub.RightRoom, visited); } if (!visited.Contains(hub.TopRoom)) { AdvanceBorderPath(hub.TopRoom, visited); } if (!visited.Contains(hub.BotRoom)) { AdvanceBorderPath(hub.BotRoom, visited); } } }
public static void AddCurve(HashSet <GenRoom> rooms, GenEdge ed) { GenRoom higher = ed.r1.r.GetCenter().y > ed.r2.r.GetCenter().y ? ed.r1.r : ed.r2.r; GenRoom lower = ed.r1.r.GetCenter().y > ed.r2.r.GetCenter().y ? ed.r2.r : ed.r1.r; GenRoom righter = ed.r1.r.GetCenter().x > ed.r2.r.GetCenter().x ? ed.r1.r : ed.r2.r; GenRoom lefter = ed.r1.r.GetCenter().x > ed.r2.r.GetCenter().x ? ed.r2.r : ed.r1.r; RectInt r = new RectInt(lefter.GetCenter().x, lower.GetCenter().y, righter.GetCenter().x - lefter.GetCenter().x, higher.GetCenter().y - lower.GetCenter().y); GenRoom verticalLefter = new GenRoom(); verticalLefter.bounds.x = r.x - TUNNEL_THICKNESS / 2; verticalLefter.bounds.y = r.y - TUNNEL_THICKNESS / 2; verticalLefter.bounds.width = TUNNEL_THICKNESS; verticalLefter.bounds.height = r.height + TUNNEL_THICKNESS; GenRoom horizontalLower = new GenRoom(); horizontalLower.bounds.x = r.x - TUNNEL_THICKNESS / 2; horizontalLower.bounds.y = r.y - TUNNEL_THICKNESS / 2; horizontalLower.bounds.width = r.width + TUNNEL_THICKNESS; horizontalLower.bounds.height = TUNNEL_THICKNESS; GenRoom verticalRighter = new GenRoom(); verticalRighter.bounds.x = r.x + r.width - TUNNEL_THICKNESS / 2; verticalRighter.bounds.y = r.y - TUNNEL_THICKNESS / 2; verticalRighter.bounds.width = TUNNEL_THICKNESS; verticalRighter.bounds.height = r.height + TUNNEL_THICKNESS; GenRoom horizontalHigher = new GenRoom(); horizontalHigher.bounds.x = r.x - TUNNEL_THICKNESS / 2; horizontalHigher.bounds.y = r.y + r.height - TUNNEL_THICKNESS / 2; horizontalHigher.bounds.width = r.width + TUNNEL_THICKNESS; horizontalHigher.bounds.height = TUNNEL_THICKNESS; if (lower == lefter) { horizontalLower.bounds.x = r.x + lower.bounds.width / 2; horizontalLower.bounds.width = r.width - lower.bounds.width / 2 + TUNNEL_THICKNESS / 2; horizontalHigher.bounds.width = r.width - higher.bounds.width / 2 + TUNNEL_THICKNESS / 2; verticalLefter.bounds.y = r.y + lower.bounds.height / 2; verticalLefter.bounds.height = r.height - lower.bounds.height / 2 + TUNNEL_THICKNESS / 2; verticalRighter.bounds.height = r.height - higher.bounds.height / 2 + TUNNEL_THICKNESS / 2; } if (lower == righter) { horizontalHigher.bounds.x = r.x + higher.bounds.width / 2; horizontalHigher.bounds.width = r.width - higher.bounds.width / 2 + TUNNEL_THICKNESS / 2; horizontalLower.bounds.width = r.width - lower.bounds.width / 2 + TUNNEL_THICKNESS / 2; verticalRighter.bounds.y = r.y + lower.bounds.height / 2; verticalRighter.bounds.height = r.height - lower.bounds.height / 2 + TUNNEL_THICKNESS / 2; verticalLefter.bounds.height = r.height - higher.bounds.height / 2 + TUNNEL_THICKNESS / 2; } bool flip = UnityEngine.Random.value > 0.5; bool diffX = ed.r2.r.GetCenter().x - ed.r1.r.GetCenter().x > 0; bool diffY = ed.r2.r.GetCenter().y - ed.r1.r.GetCenter().y > 0; bool addHorizontal1 = false, addHorizontal2 = false, addVertical1 = false, addVertical2 = false; if (diffX && diffY) { if (flip) { addVertical1 = true; addHorizontal2 = true; } else { addVertical2 = true; addHorizontal1 = true; } } else if (diffX && !diffY) { if (flip) { addVertical2 = true; addHorizontal2 = true; } else { addVertical1 = true; addHorizontal1 = true; } } else if (!diffX && diffY) { if (flip) { addVertical1 = true; addHorizontal1 = true; } else { addVertical2 = true; addHorizontal2 = true; } } else if (!diffX && !diffY) { if (flip) { addVertical2 = true; addHorizontal1 = true; } else { addVertical1 = true; addHorizontal2 = true; } } if (addHorizontal1) { rooms.Add(horizontalLower); if (lower == lefter) { for (int i = 0; i < TUNNEL_THICKNESS; i++) { lower.doorsRight.Add(new Vector2Int(horizontalLower.bounds.x - 1, horizontalLower.bounds.y + i)); } } else { for (int i = 0; i < TUNNEL_THICKNESS; i++) { lower.doorsLeft.Add(new Vector2Int(horizontalLower.bounds.x + horizontalLower.bounds.width, horizontalLower.bounds.y + i)); } } } if (addHorizontal2) { rooms.Add(horizontalHigher); if (lower == righter) { for (int i = 0; i < TUNNEL_THICKNESS; i++) { higher.doorsRight.Add(new Vector2Int(horizontalHigher.bounds.x - 1, horizontalHigher.bounds.y + i)); } } else { for (int i = 0; i < TUNNEL_THICKNESS; i++) { higher.doorsLeft.Add(new Vector2Int(horizontalHigher.bounds.x + horizontalHigher.bounds.width, horizontalHigher.bounds.y + i)); } } } if (addVertical1) { rooms.Add(verticalLefter); if (lower == lefter) { for (int i = 0; i < TUNNEL_THICKNESS; i++) { lower.doorsUp.Add(new Vector2Int(verticalLefter.bounds.x + i, verticalLefter.bounds.y - 1)); } } else { for (int i = 0; i < TUNNEL_THICKNESS; i++) { higher.doorsDown.Add(new Vector2Int(verticalLefter.bounds.x + i, verticalLefter.bounds.y + verticalLefter.bounds.height)); } } } if (addVertical2) { rooms.Add(verticalRighter); if (lower == righter) { for (int i = 0; i < TUNNEL_THICKNESS; i++) { lower.doorsUp.Add(new Vector2Int(verticalRighter.bounds.x + i, verticalRighter.bounds.y - 1)); } } else { for (int i = 0; i < TUNNEL_THICKNESS; i++) { higher.doorsDown.Add(new Vector2Int(verticalRighter.bounds.x + i, verticalRighter.bounds.y + verticalRighter.bounds.height)); } } } }
public void Generate() { int minRoomSize = 50; rooms = new HashSet <GenRoom>(); for (int i = 0; i < 7 + ( int )(UnityEngine.Random.value * 4); i++) { GenRoom room = new GenRoom(); room.bounds.width = ((15 + ( int )(UnityEngine.Random.value * 20)) / 2) * 2; room.bounds.height = ((15 + ( int )(UnityEngine.Random.value * 20)) / 2) * 2; rooms.Add(room); } while (true) { bool changed = false; foreach (GenRoom r1 in rooms) { foreach (GenRoom r2 in rooms) { if (r1 == r2) { continue; } Vector2Int p1 = new Vector2Int(r1.bounds.x + r1.bounds.width / 2, r1.bounds.y + r1.bounds.height / 2); Vector2Int p2 = new Vector2Int(r2.bounds.x + r2.bounds.width / 2, r2.bounds.y + r2.bounds.height / 2); if (Math.Pow(Vector2Int.Distance(p1, p2), 2) < 2 * minRoomSize * minRoomSize + 2) { r2.bounds.x += ( int )((UnityEngine.Random.value - 0.5) * 5); r2.bounds.y += ( int )((UnityEngine.Random.value - 0.5) * 2.5); changed = true; break; } } if (changed) { break; } } if (!changed) { break; } } HashSet <GenVertex> Q = new HashSet <GenVertex>(); foreach (GenRoom r in rooms) { Q.Add(new GenVertex(r)); } GenVertex root = null; foreach (GenVertex v in Q) { if (root == null || v.r.bounds.x < root.r.bounds.x) { root = v; } } root.value = 0; HashSet <GenEdge> E = new HashSet <GenEdge>(); HashSet <GenEdge> G = new HashSet <GenEdge>(); HashSet <GenVertex> F = new HashSet <GenVertex>(); foreach (GenVertex r1 in Q) { foreach (GenVertex r2 in Q) { if (r1 == r2) { goto outer; } foreach (GenEdge e in E) { if (e.r2 == r1 && e.r1 == r2) { goto outer; } } E.Add(new GenEdge(r1, r2)); } outer :; } F.Add(root); Q.Remove(root); while (Q.Count > 0) { GenEdge start2 = null; foreach (GenEdge e in E) { if (F.Contains(e.r1) ^ F.Contains(e.r2)) { if (start2 == null || e.dist < start2.dist) { start2 = e; } } } Q.Remove(start2.r2); Q.Remove(start2.r1); F.Add(start2.r2); F.Add(start2.r1); E.Remove(start2); G.Add(start2); if (start2.r1.value < start2.r2.value) { start2.r2.value = ( float )(start2.r1.value + start2.dist); } else { start2.r1.value = ( float )(start2.r2.value + start2.dist); } } // G list of edges // rooms list of rooms HashSet <GenRoom> rooms2 = new HashSet <GenRoom>(); foreach (GenEdge ed in G) { // horizontal float diff1 = ed.r1.r.bounds.y - ed.r2.r.bounds.y - ed.r2.r.bounds.height + TUNNEL_THICKNESS; float diff2 = ed.r2.r.bounds.y - ed.r1.r.bounds.y - ed.r1.r.bounds.height + TUNNEL_THICKNESS; // vertical float diff3 = ed.r1.r.bounds.x - ed.r2.r.bounds.x - ed.r2.r.bounds.width + TUNNEL_THICKNESS; float diff4 = ed.r2.r.bounds.x - ed.r1.r.bounds.x - ed.r1.r.bounds.width + TUNNEL_THICKNESS; if (diff1 < 0 && diff2 < 0) { AddStraightHorizontal(rooms2, ed); } else if (diff3 < 0 && diff4 < 0) { AddStraightVertical(rooms2, ed); } else { AddCurve(rooms2, ed); } } HashSet <Vector2Int> allDoors = new HashSet <Vector2Int>(); foreach (GenRoom r in rooms) { for (int x1 = r.bounds.x; x1 < r.bounds.x + r.bounds.width; x1++) { for (int y1 = r.bounds.y; y1 < r.bounds.y + r.bounds.height; y1++) { int xMode = (x1 == r.bounds.x) ? -1 : (x1 == r.bounds.x + r.bounds.width - 1) ? 1 : 0; int yMode = (y1 == r.bounds.y) ? -1 : (y1 == r.bounds.y + r.bounds.height - 1) ? 1 : 0; r.tiles.Add(new Vector2Int(x1, y1), new GenTile(Room.TileType.WALL, GenTile.GetPosition(xMode, yMode))); } } for (int x1 = r.bounds.x + 1; x1 < r.bounds.x + r.bounds.width - 1; x1++) { for (int y1 = r.bounds.y + 1; y1 < r.bounds.y + r.bounds.height - 1; y1++) { r.tiles[new Vector2Int(x1, y1)].type = Room.TileType.GROUND; } } allDoors.UnionWith(r.AllDoors()); foreach (Vector2Int v in r.doorsDown) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.BOTTOM; } foreach (Vector2Int v in r.doorsUp) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.TOP; } foreach (Vector2Int v in r.doorsLeft) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.LEFT; } foreach (Vector2Int v in r.doorsRight) { r.tiles[v].type = Room.TileType.DOOR; r.tiles[v].position = GenTile.Position.RIGHT; } } path = new GenRoom(); foreach (GenRoom r in rooms2) { for (int x1 = r.bounds.x; x1 < r.bounds.x + r.bounds.width; x1++) { for (int y1 = r.bounds.y; y1 < r.bounds.y + r.bounds.height; y1++) { Vector2Int pos1 = new Vector2Int(x1, y1); if (path.tiles.ContainsKey(pos1)) { path.tiles[pos1].type = Room.TileType.GROUND; } else { path.tiles.Add(pos1, new GenTile(Room.TileType.GROUND)); } Vector2Int pos2 = new Vector2Int(x1 + 1, y1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.RIGHT)); } pos2 = new Vector2Int(x1 - 1, y1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.LEFT)); } pos2 = new Vector2Int(x1, y1 + 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.TOP)); } pos2 = new Vector2Int(x1, y1 - 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.BOTTOM)); } } } for (int x1 = r.bounds.x; x1 < r.bounds.x + r.bounds.width; x1++) { for (int y1 = r.bounds.y; y1 < r.bounds.y + r.bounds.height; y1++) { Vector2Int pos2 = new Vector2Int(x1 + 1, y1 + 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.TOP_RIGHT)); } pos2 = new Vector2Int(x1 - 1, y1 + 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.TOP_LEFT)); } pos2 = new Vector2Int(x1 + 1, y1 - 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.BOTTOM_RIGHT)); } pos2 = new Vector2Int(x1 - 1, y1 - 1); if (!path.tiles.ContainsKey(pos2) && !allDoors.Contains(pos2)) { path.tiles.Add(pos2, new GenTile(Room.TileType.WALL, GenTile.Position.BOTTOM_LEFT)); } } } if (r.AllDoors().Count > 0) { throw new NotSupportedException("Paths should not have any doors"); } } start = root.r; end = null; foreach (GenRoom r in rooms) { if (end == null || r.bounds.x > end.bounds.x) { end = r; } } rooms.Remove(start); rooms.Remove(end); foreach (GenRoom r in rooms) { GenerateInterior(r); } start.spawnpoints.Add(start.GetCenter()); end.spawnpoints.Add(end.GetCenter()); foreach (Vector2Int v in allDoors) { foreach (GenRoom r in rooms) { for (int x = -TUNNEL_THICKNESS; x < TUNNEL_THICKNESS; x++) { for (int y = -TUNNEL_THICKNESS; y < TUNNEL_THICKNESS; y++) { if (r.tiles.ContainsKey(v + new Vector2Int(x, y)) && r.tiles[v + new Vector2Int(x, y)].type == Room.TileType.ROCK) { r.tiles[v + new Vector2Int(x, y)].type = Room.TileType.GROUND; } } } } { GenRoom r = path; if (r.tiles.ContainsKey(v + new Vector2Int(0, 1)) && r.tiles[v + new Vector2Int(0, 1)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(0, 1)); } if (r.tiles.ContainsKey(v + new Vector2Int(0, -1)) && r.tiles[v + new Vector2Int(0, -1)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(0, -1)); } if (r.tiles.ContainsKey(v + new Vector2Int(1, 0)) && r.tiles[v + new Vector2Int(1, 0)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(1, 0)); } if (r.tiles.ContainsKey(v + new Vector2Int(-1, 0)) && r.tiles[v + new Vector2Int(-1, 0)].type == Room.TileType.WALL) { r.tiles.Remove(v + new Vector2Int(-1, 0)); } } } foreach (GenRoom r in rooms) { MakeRoomRelative(r); } MakeRoomRelative(start); MakeRoomRelative(end); MakeRoomRelative(path); }
public void PlaceRoom(int x, int y, GenRoom room) { room.PosX = x; room.PosY = y; Rooms.Add(room); }
/// <summary> /// checks if Position is in the corner (floor, not wall) /// </summary> public bool IsCornerGR(int gx, int gy, GenRoom room, GenDetail.DetailType[] checkFor = null, GenDetail.DetailType[] noWall = null) { if (checkFor == null) { checkFor = new GenDetail.DetailType[] { GenDetail.DetailType.Wall }; } if (noWall == null) { noWall = new GenDetail.DetailType[] { GenDetail.DetailType.Door }; } bool vertical = false; bool horizontal = false; GenTile tile; if (room != null) { tile = room.GetAtWorldspaceG(gx, gy); if (tile != null) { GenTile check = room.GetAtWorldspaceG(gx + 1, gy); if (check != null && check.AnyTypes(checkFor) && check.NonTypes(noWall)) { horizontal = true; } check = room.GetAtWorldspaceG(gx - 1, gy); if (check != null && check.AnyTypes(checkFor) && check.NonTypes(noWall)) { horizontal = true; } check = room.GetAtWorldspaceG(gx, gy + 1); if (check != null && check.AnyTypes(checkFor) && check.NonTypes(noWall)) { vertical = true; } check = room.GetAtWorldspaceG(gx, gy - 1); if (check != null && check.AnyTypes(checkFor) && check.NonTypes(noWall)) { vertical = true; } return(horizontal && vertical); } return(false); } else { tile = GetTile(gx, gy); if (tile != null) { GenTile check = GetTile(gx + 1, gy); if (check != null && check.AnyTypes(GenDetail.DetailType.Wall)) { horizontal = true; } check = GetTile(gx - 1, gy); if (check != null && check.AnyTypes(GenDetail.DetailType.Wall)) { horizontal = true; } check = GetTile(gx, gy + 1); if (check != null && check.AnyTypes(GenDetail.DetailType.Wall)) { vertical = true; } check = GetTile(gx, gy - 1); if (check != null && check.AnyTypes(GenDetail.DetailType.Wall)) { vertical = true; } return(horizontal && vertical); } return(false); } }
public static IEnumerator GetSimpleTemple() { GenData temple = new GenData(Random.Range(TempleWidth.start, TempleWidth.end), Random.Range(TempleHeight.start, TempleHeight.end)); List <GenRoom> AutoFillRoom = new List <GenRoom>(); // list of all rooms that are not allowed to be used for door placement List <GenRoom> NoAutoDoor = new List <GenRoom>(); List <GenRoom> SecretRooms = new List <GenRoom>(); GenTile Chest = GenTile.GetEmpty(); Chest.Details.Add(new GenDetail() { Char = '=', Type = GenDetail.DetailType.Entity, Entity = GenDetail.EntityType.Chest }); GenTile pillar = GenTile.GetEmpty(); //pillar.Details.Add(new GenDetail() { Char = '\u01C1', Type = GenDetail.DetailType.Decoration }); pillar.Details.Add(new GenDetail() { Char = 'O', Type = GenDetail.DetailType.Decoration }); GenTile[,] pillars = new GenTile[, ] { { GenTile.Copy(pillar), GenTile.Copy(pillar) }, { GenTile.Copy(pillar), GenTile.Copy(pillar) } }; GenTile Door = GenTile.GetEmpty(); Door.Details.Add(new GenDetail() { Char = '+', Type = GenDetail.DetailType.Door, Entity = GenDetail.EntityType.Door }); GenRoom outer = GenRoom.Sized(temple.Width, temple.Height); outer.FillFloor('+'); outer.SpacePriority = -2; temple.PlaceRoom(0, 0, outer); temple.EdgeWalls('#', outer); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- int w = Random.Range(9, 12); int h = Random.Range(10, 16); // EntryHall temple.TryGrowRect(1, outer.Outer.GetCenter().y, w, h, out GenRect EntrySize, false); GenRoom EntryHall = GenRoom.At(EntrySize.MinX, EntrySize.MinY, EntrySize.WidthT, EntrySize.HeightT); EntryHall.FillFloor('.'); temple.PlaceRoom(EntrySize.MinX, EntrySize.MinY, EntryHall); temple.EdgeWalls('#'); EntryHall.GetAtWorldspaceG( EntrySize.MinX + 1, EntrySize.GetCenter().y) .Details .Add(new GenDetail() { Char = '>', Type = GenDetail.DetailType.Entity, Entity = GenDetail.EntityType.StairsDown }); int posX = EntrySize.MinX + 2; int posy = EntrySize.MinY + 2; GenTile[,] sym = GenUtil.GetSymetry(pillars.GetCopy(), ref posX, ref posy, EntryHall, GenUtil.Axis.Horizontal | GenUtil.Axis.Vertical); EntryHall.PlaceDetailsAt(posX, posy, sym); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // hall to big thing int whall = Random.Range(10, 25); int hhall = Random.Range(5, 7); int space = Random.Range(2, 4); temple.TryGrowRect(EntrySize.MaxX + 1, EntrySize.GetCenter().y, whall, hhall, out GenRect HallSize); GenRoom PillarHall = GenRoom.Sized(HallSize.WidthT, HallSize.HeightT); PillarHall.FillFloor('.'); PillarHall.SpacePriority = 3; temple.PlaceRoom(HallSize.MinX, HallSize.MinY, PillarHall); temple.EdgeWalls('#', PillarHall); NoAutoDoor.Add(PillarHall); // place doors to the entry if (hhall == 5) { // a single door in the middle PillarHall.AddDetails(HallSize.MinX, HallSize.MinY + 2, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MaxX, HallSize.MinY + 2, GenTile.Copy(Door)); } else { // place symetric doors PillarHall.AddDetails(HallSize.MinX, HallSize.MinY + 2, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MinX, HallSize.MinY + 3, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MaxX, HallSize.MinY + 2, GenTile.Copy(Door)); PillarHall.AddDetails(HallSize.MaxX, HallSize.MinY + 3, GenTile.Copy(Door)); } int currBar = HallSize.MinX + space; GenTile[,] singlePillar = new GenTile[, ] { { GenTile.Copy(pillar) } }; while (temple.IsInsideRoom(currBar, HallSize.MinY + 1, PillarHall)) { int fx = currBar; int fy = HallSize.MinY + 1; GenTile[,] feature = GenUtil.GetSymetry(singlePillar, ref fx, ref fy, PillarHall, GenUtil.Axis.Vertical); PillarHall.PlaceDetailsAt(fx, fy, feature); currBar += space; } temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // holy water or something int waterHeight = Random.Range(2, 4); int waterWidth = Random.Range(2, 4); int waterPillarWidth = Random.Range(2, 3); int waterRoomHeight = waterHeight + 4 + waterPillarWidth * 2; int waterRoomWidth = waterWidth + 6 + waterPillarWidth * 2; temple.TryGrowRect(HallSize.MaxX + 1, HallSize.GetCenter().y, waterRoomWidth, waterRoomHeight, out GenRect WaterSize, false, GenUtil.Direction4.Top); GenRoom waterRoom = GenRoom.Sized(WaterSize.WidthT, WaterSize.HeightT); waterRoom.FillFloor(); waterRoom.SpacePriority = 2; temple.PlaceRoom(WaterSize.MinX, WaterSize.MinY, waterRoom); temple.EdgeWalls('#', waterRoom); int BackDoorWater = Random.Range(1, waterRoom.Height / 2); waterRoom.AddDetails(WaterSize.MaxX, WaterSize.MinY + BackDoorWater, GenTile.Copy(Door)); waterRoom.AddDetails(WaterSize.MaxX, WaterSize.MaxY - BackDoorWater, GenTile.Copy(Door)); GenTile waterSingle = GenTile.GetEmpty(); waterSingle.Details.Add(new GenDetail() { Char = '~', Type = GenDetail.DetailType.Background }); GenTile[,] water = GenUtil.Fill(waterWidth, waterHeight, waterSingle); waterRoom.PlaceDetailsAt(WaterSize.MinX + 3 + waterPillarWidth, WaterSize.MinY + 2 + waterPillarWidth, water); int waterPX = WaterSize.MinX + 3; int waterPY = WaterSize.MinY + 2; GenTile[,] waterPillarPlace = GenUtil.GetSymetry(pillars.GetCopy(), ref waterPX, ref waterPY, waterRoom, GenUtil.Axis.Horizontal | GenUtil.Axis.Vertical); waterRoom.PlaceDetailsAt(waterPX, waterPY, waterPillarPlace); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // pillar spam int spamWidth = Random.Range(10, 20); int spamHeight = WaterSize.HeightT + Random.Range(8, 15); temple.TryGrowRect(WaterSize.MaxX + 1, WaterSize.GetCenter().y, spamWidth, spamHeight, out GenRect SpamSize, true, GenUtil.Direction4.Top); GenRoom Spam = GenRoom.Sized(SpamSize.WidthT, SpamSize.HeightT); Spam.FillFloor(); Spam.SpacePriority = 1; temple.PlaceRoom(SpamSize.MinX, SpamSize.MinY, Spam); temple.EdgeWalls('#', Spam); int spamPX = SpamSize.MinX + 2; int spamPY = SpamSize.MinY + 2; for (int x = spamPX; temple.IsInsideRoom(x, spamPY, Spam); x += 2) { for (int y = spamPY; temple.IsInsideRoom(x, y, Spam); y += 2) { GenTile p = GenTile.Copy(pillar); Spam.AddDetails(x, y, p); } } Spam.AddDetail( SpamSize.MaxX - 1, SpamSize.GetCenter().y, new GenDetail() { Char = '<', Type = GenDetail.DetailType.Entity, Entity = GenDetail.EntityType.StairsUp }); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- //temple.Rooms.Remove(outer); // we dont have boundries for (int x = outer.Inner.MinX; x < outer.Outer.MaxX; x++) { for (int y = outer.Inner.MinY; y < outer.Outer.MaxY; y++) { outer.RemoveTileAtG(x, y); } } //GenRoom Mark = GenRoom.Sized(0, 0); //Mark.FillFloor('X'); //Mark.SpacePriority = 100; // lets go ham with randomly sized rooms int spawnAttemptsRemaining = 1000; while (spawnAttemptsRemaining-- > 0)// lol the arrow { int rWidth = Random.Range(RandomWidth.start, RandomWidth.end); int rHeight = Random.Range(RandomHeight.start, RandomHeight.end); int rX = Random.Range(2, temple.Width - 2); int rY = Random.Range(2, temple.Height - 2); GenRect rHopeSize = new GenRect(rX, rX + rWidth + 1, rY, rY + rWidth - 1); if (temple.IsInsideRoom(rX, rY) || temple.GetTile(rX, rY) != null) { continue; } temple.TryGrowRect(rX, rY, rWidth, rHeight, out GenRect rSize, true); GenRoom add = GenRoom.Sized(rSize.WidthT, rSize.HeightT); add.FillFloor(); add.SpacePriority = 01; temple.PlaceRoom(rSize.MinX, rSize.MinY, add); AutoFillRoom.Add(add); temple.EdgeWalls('#', add); temple.FixOverlap(); /* * if (rWidth * 2 < rHeight || rHeight * 2 < rWidth) * { * if (Random.Range(0,10)>4) * { * // we are making a hallway * * //TODO: hallway * * temple.PlaceRoom(rX, rY, Mark); * Log(temple); * if (Logging!=null) * { * yield return new WaitForSeconds(0.25f); * } * temple.Rooms.Remove(Mark); * continue; * } * } */ /* * int randomChance = Random.Range(0, 4); * switch (randomChance) * { * case 0: * // random pillars in the room * * for (int i = 0; i < 7 + (rSize.WidthT + rSize.HeightT)/5; i++) * { * int px = Random.Range(rSize.MinX + 1, rSize.MaxX); * int py = Random.Range(rSize.MinY + 1, rSize.MaxY); * add.AddDetails(px, py, pillar); * } * * break; * case 1: * // random water * for (int i = 0; i < 15 + (rSize.WidthT + rSize.HeightT)/3; i++) * { * int px = Random.Range(rSize.MinX + 1, rSize.MaxX); * int py = Random.Range(rSize.MinY + 1, rSize.MaxY); * GenDetail littleWater= new GenDetail() { Char = '~', Type = GenDetail.DetailType.Background}; * add.AddDetail(px, py, littleWater); * } * break; * case 2: * // random room inside if possible else empty * if (rSize.WidthT>=7&& rSize.HeightT >= 7) * { * int insideX = rSize.GetCenter().x; * int insideY = rSize.GetCenter().y; * * temple.TryGrowRect(insideX, insideY, 100, 100, out GenRect insideSize, false); * GenRoom inside = GenRoom.Sized(insideSize.WidthT, insideSize.HeightT); * inside.FillFloor(); * inside.SpacePriority = 2; * temple.PlaceRoom(insideSize.MinX, insideSize.MinY, inside); * temple.EdgeWalls('#',inside); * temple.FixOverlap(); * * } * else * { * for (int i = 0; i < 7; i++) * { * int px = Random.Range(rSize.MinX + 1, rSize.MaxX); * int py = Random.Range(rSize.MinY + 1, rSize.MaxY); * add.AddDetails(px, py, pillar); * } * } * break; * default: * break; * } * * Log(temple); * if (Logging!=null) * { * yield return new WaitForSeconds(0.25f); * } */ } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // now fill the rooms with things var adjList = temple.GetAdjacentRoomMap(); // remove any Room that is too small and have no connections List <GenRoom> tooSmall = new List <GenRoom>(); foreach (var room in temple.Rooms) { if (room.Width >= 5 && room.Height == 3) { tooSmall.Add(room); continue; } if (room.Height >= 5 && room.Width == 3) { tooSmall.Add(room); continue; } if (room.Height <= 3 && room.Width <= 3) { tooSmall.Add(room); continue; } if (adjList[room].Count == 0) { tooSmall.Add(room); continue; } } foreach (var room in tooSmall) { temple.Rooms.Remove(room); } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- List <GenRoom> PotentialSecret = new List <GenRoom>(); foreach (var room in temple.Rooms) { if (room.Width + room.Height <= 12) { PotentialSecret.Add(room); } } Debug.Log("potential " + PotentialSecret.Count + "Secret rooms"); // 1 room --> 0,1,2,3 // 2 room --> 4,5 int SecretCount = Mathf.Min(Mathf.FloorToInt(Mathf.Sqrt(Random.Range(1, 6))), PotentialSecret.Count); // this goes to 5 Debug.Log(SecretCount + " Secret rooms chosen"); foreach (var secret in PotentialSecret.GetRandom(SecretCount)) { // we get random door // add a chest // remove it from door spawn GenPositionTile entry = temple.GetDoorableTiles(secret.GetAllTiles()).GetRandom(); secret.AddDetail(entry.PositionG.x, entry.PositionG.y, new GenDetail() { Char = '*', Entity = GenDetail.EntityType.Door, Type = GenDetail.DetailType.Door }); GenPositionTile myChest = secret .GetAllTiles() .Where(t => temple.IsInsideRoom(t.PositionG.x, t.PositionG.y, secret) && temple.IsCornerGR(t.PositionG.x, t.PositionG.y, secret)) .ToList() .GetRandom(); secret.AddDetails(myChest.PositionG.x, myChest.PositionG.y, GenTile.Copy(Chest)); AutoFillRoom.Remove(secret); SecretRooms.Add(secret); NoAutoDoor.Add(secret); } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // go through all other rooms and determin what they are foreach (GenRoom room in AutoFillRoom) { // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // pillar hallway if (room.Height <= 7 && room.Height >= 5 && room.Width > 6) { // potential horizontal hallway if (Random.value < 0.4f) { // hallway confirmed // left to right GenTile[,] p = new GenTile[, ] { { GenTile.Copy(pillar) } }; int spacing = Random.Range(2, 5); int tmpX = room.Outer.MinX + spacing; int tmpY = room.Outer.MinY + 1; p = GenUtil.GetSymetry(p, ref tmpX, ref tmpY, room, GenUtil.Axis.Vertical); while (temple.IsInsideRoom(tmpX, tmpY, room)) { room.PlaceDetailsAt(tmpX, tmpY, p); tmpX = tmpX + spacing; } int enemyCount = Random.Range(0, 4); for (int i = 0; i < enemyCount; i++) { SpawnEnemy(temple, room); } int itemCount = Random.Range(-1, 3); for (int i = 0; i < itemCount; i++) { SpawnItem(temple, room, true); } int chestCount = Random.Range(-2, 2); for (int i = 0; i < chestCount; i++) { SpawnChest(temple, room, true); } continue; } } if (room.Width <= 7 && room.Width >= 5 && room.Height > 6) { // potential horizontal hallway if (Random.value < 0.4f) { // hallway confirmed // left to right GenTile[,] p = new GenTile[, ] { { GenTile.Copy(pillar) } }; int spacing = Random.Range(2, 5); int tmpX = room.Outer.MinX + 1; int tmpY = room.Outer.MinY + spacing; p = GenUtil.GetSymetry(p, ref tmpX, ref tmpY, room, GenUtil.Axis.Horizontal); while (temple.IsInsideRoom(tmpX, tmpY, room)) { room.PlaceDetailsAt(tmpX, tmpY, p); tmpY = tmpY + spacing; } int enemyCount = Random.Range(0, 4); for (int i = 0; i < enemyCount; i++) { SpawnEnemy(temple, room); } int itemCount = Random.Range(-1, 3); for (int i = 0; i < itemCount; i++) { SpawnItem(temple, room, true); } int chestCount = Random.Range(-2, 2); for (int i = 0; i < chestCount; i++) { SpawnChest(temple, room, true); } continue; } } if (room.Height >= 8 && room.Width >= 8) { // can either be pillar spam or room in room if (Random.value < 0.6f) { if (Random.value < 0.7f && room.Width % 2 == 1 && room.Height % 2 == 1) { // pillar spam for (int x = 2; x < room.Width - 2; x += 2) { for (int y = 2; y < room.Height - 2; y += 2) { room.AddDetails(room.PosX + x, room.PosY + y, GenTile.Copy(pillar)); } } int enemyCount = Random.Range(0, 5); for (int i = 0; i < enemyCount; i++) { SpawnEnemy(temple, room); } int itemCount = Random.Range(-1, 3); for (int i = 0; i < itemCount; i++) { SpawnItem(temple, room, true); } int chestCount = Random.Range(-3, 3); for (int i = 0; i < chestCount; i++) { SpawnChest(temple, room, true); } } else { // room in room // find where to put the inner room temple.TryGrowRect(room.Inner.GetCenter().x, room.Inner.GetCenter().y, 100, 100, out GenRect InnerSize); if (InnerSize.WidthT >= 4 && InnerSize.HeightT >= 4) { if (InnerSize.WidthT >= 10 || InnerSize.HeightT >= 10) { if (Mathf.Abs(InnerSize.WidthT - InnerSize.HeightT) > 3) { // we want to divide if (InnerSize.WidthT > InnerSize.HeightT) { // divide left and right int singleWidth = InnerSize.WidthT / 2 - 2; // left GenRect LeftRoom = new GenRect(InnerSize.MinX, InnerSize.MinX + singleWidth, InnerSize.MinY, InnerSize.MaxY); // right GenRect RightRoom = new GenRect(InnerSize.MaxX - singleWidth, InnerSize.MaxX, InnerSize.MinY, InnerSize.MaxY); GenRoom left = GenRoom.Sized(LeftRoom.WidthT, LeftRoom.HeightT); left.FillFloor(); left.SpacePriority = 4; GenRoom right = GenRoom.Sized(RightRoom.WidthT, RightRoom.HeightT); right.FillFloor(); right.SpacePriority = 4; temple.PlaceRoom(LeftRoom.MinX, LeftRoom.MinY, left); temple.PlaceRoom(RightRoom.MinX, RightRoom.MinY, right); NoAutoDoor.Add(left); NoAutoDoor.Add(right); temple.EdgeWalls('#', left); temple.EdgeWalls('#', right); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- var leftDoor = temple.GetDoorableTiles(left.GetAllTiles()).GetRandom(1); var rightDoor = temple.GetDoorableTiles(right.GetAllTiles()).GetRandom(1); for (int i = 0; i < leftDoor.Count; i++) { left.AddDetails(leftDoor[i].PositionG.x, leftDoor[i].PositionG.y, GenTile.Copy(Door)); } for (int i = 0; i < rightDoor.Count; i++) { right.AddDetails(rightDoor[i].PositionG.x, rightDoor[i].PositionG.y, GenTile.Copy(Door)); } SpawnItem(temple, left); SpawnItem(temple, right); if (Random.value < 0.4f) { SpawnItem(temple, right); } if (Random.value < 0.4f) { SpawnItem(temple, left); } if (Random.value < 0.2f) { SpawnChest(temple, left, true); } if (Random.value < 0.2f) { SpawnChest(temple, left, true); } } else { // divide top bot Debug.Log("currently not implemented, sorry"); } } } else { // one single room if (InnerSize.WidthT > 5) { InnerSize = InnerSize.Transform(-1, 0, -1, 0); } if (InnerSize.HeightT > 5) { InnerSize = InnerSize.Transform(0, -1, 0, -1); } Debug.Log("HERE"); GenRoom single = GenRoom.Sized(InnerSize.WidthT, InnerSize.HeightT); single.SpacePriority = 4; single.FillFloor(); NoAutoDoor.Add(single); temple.PlaceRoom(InnerSize.MinX, InnerSize.MinY, single); temple.EdgeWalls('#', single); temple.FixOverlap(); // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.25f)); } // ----------- // double doors var doorables = single.GetAllTiles();// single.GetEdge().ToList(); var theDoors = temple.GetDoorableTiles(doorables).GetRandom(2); for (int i = 0; i < theDoors.Count; i++) { single.AddDetails(theDoors[i].PositionG.x, theDoors[i].PositionG.y, GenTile.Copy(Door)); } SpawnItem(temple, single); if (Random.value < 0.2f) { SpawnChest(temple, single, true); } if (Random.value < 0.2f) { SpawnChest(temple, single, true); } } } SpawnEnemy(temple, room); if (Random.value < 0.5f) { SpawnEnemy(temple, room); } if (Random.value < 0.2f) { SpawnEnemy(temple, room); } } continue; } } // something random //room.FillFloor('~'); SpawnEnemy(temple, room); SpawnEnemy(temple, room); if (Random.value < 0.5f) { SpawnEnemy(temple, room); } if (Random.value < 0.2f) { SpawnEnemy(temple, room); } SpawnItem(temple, room); if (Random.value < 0.3f) { SpawnItem(temple, room); } if (Random.value < 0.3f) { SpawnItem(temple, room); } if (Random.value < 0.4f) { SpawnChest(temple, room); } if (Random.value < 0.1f) { SpawnChest(temple, room); } } List <GenRoom> RequireDoor = new List <GenRoom>(temple.Rooms); foreach (var doo in NoAutoDoor) { RequireDoor.Remove(doo); } List <GenRoom> DoorIteration = new List <GenRoom>(RequireDoor); GenRoom start = EntryHall; Dictionary <GenRoom, List <GenRoom> > adj = temple.GetAdjacentRoomMap(); void RandomDoorTo(GenRoom a, GenRoom b) { var tiles = temple.GetDoorableTiles(temple.GetConnectingTiles(a, b)); var location = tiles.GetRandom(); a.AddDetails(location.PositionG.x, location.PositionG.y, GenTile.Copy(Door)); } while (RequireDoor.Count > 0) { DoorIteration.Clear(); DoorIteration.AddRange(RequireDoor); foreach (var room in DoorIteration) { if (temple.IsReachable(start, room)) { // reachable so we dont have to do a thing RequireDoor.Remove(room); } else { // place random door var available = adj[room]; RandomDoorTo(room, available.GetRandom()); } // ----------- Log(temple); if (Logging != null) { yield return(new WaitForSeconds(0.1f)); } // ----------- } } foreach (var room in adj[Spam].GetRandom(2)) { RandomDoorTo(Spam, room); } Log(temple); Debug.Log("Done"); LastOutput = GenUtil.Print(temple, false); Done?.Invoke(); }
public IEnumerator GrowTest() { TestDrawer.text = "Grow Test"; GenUtil.PrintCount = 0; GenData growArea = new GenData(40, 25); GenRoom left = GenRoom.Sized(10, 15); left.FillFloor('.'); growArea.PlaceRoom(0, 0, left); GenRoom right = GenRoom.Sized(10, 15); right.FillFloor('.'); growArea.PlaceRoom(11, 0, right); growArea.EdgeWalls('#'); TestDrawer.text = growArea.Print(false); yield return(new WaitForSeconds(1f)); for (int x = 0; x < 8; x++) { for (int y = 0; y < 13; y++) { { TestDrawer.text = growArea.Print(false); //yield return new WaitForSeconds(0.05f); bool sucL = growArea.TryGrowRect(1 + x, 1 + y, 5, 6, out GenRect oL, true); GenRoom resultL = GenRoom.Sized(oL.WidthT, oL.HeightT); resultL.FillFloor('O'); growArea.PlaceRoom(oL.MinX, oL.MinY, resultL); growArea.EdgeWalls('#'); bool sucR = growArea.TryGrowRect(12 + x, 1 + y, 5, 6, out GenRect oR, false); GenRoom resultR = GenRoom.Sized(oR.WidthT, oR.HeightT); resultR.FillFloor('O'); growArea.PlaceRoom(oR.MinX, oR.MinY, resultR); growArea.EdgeWalls('#'); GenRoom dotL = GenRoom.Sized(1, 1); dotL.FillFloor('+'); growArea.PlaceRoom(1 + x, 1 + y, dotL); GenRoom dotR = GenRoom.Sized(1, 1); dotR.FillFloor('X'); growArea.PlaceRoom(12 + x, 1 + y, dotR); TestDrawer.text = growArea.Print(false); yield return(new WaitForSeconds(0.50f)); growArea.Rooms.Remove(dotR); growArea.Rooms.Remove(dotL); growArea.Rooms.Remove(resultL); growArea.Rooms.Remove(resultR); } } } /* * for (int x = 0; x < 8; x++) * { * for (int y = 0; y < 13; y++) * { * * { * TestDrawer.text = growArea.Print(false); * //yield return new WaitForSeconds(0.05f); * * bool suc = growArea.TryGrowRect(3 + x, 3 + y, 5, 6, out GenRect o, false); * * GenRoom result = GenRoom.Sized(o.WidthT, o.HeightT); * result.FillFloor('O'); * growArea.PlaceRoom(o.MinX, o.MinY, result); * growArea.EdgeWalls('#'); * * GenRoom dot = GenRoom.Sized(1, 1); * dot.FillFloor('X'); * growArea.PlaceRoom(3 + x, 3 + y, dot); * * TestDrawer.text = growArea.Print(false); * yield return new WaitForSeconds(0.50f); * * growArea.Rooms.Remove(dot); * growArea.Rooms.Remove(result); * } * } * } * */ }
public IEnumerator RunGenerationTest() { GenUtil.PrintCount = 0; GenData sym = new GenData(20, 15); GenRoom Hallway = GenRoom.Sized(15, 5); Hallway.FillFloor('.'); Hallway.SpacePriority = 2; sym.PlaceRoom(1, 1, Hallway); TestDrawer.text = sym.Print(false); yield return(new WaitForSeconds(1f)); GenRoom OtherRooom = GenRoom.Sized(8, 10); OtherRooom.FillFloor('.'); OtherRooom.SpacePriority = 3; sym.PlaceRoom(11, 3, OtherRooom); TestDrawer.text = sym.Print(false); yield return(new WaitForSeconds(1f)); sym.EdgeWalls('#'); TestDrawer.text = sym.Print(false); yield return(new WaitForSeconds(1f)); OtherRooom.SpacePriority = 1; sym.FixOverlap(); TestDrawer.text = sym.Print(false); yield return(new WaitForSeconds(1f)); int wantX = 3; int wantY = 2; bool done = false; while (!done) { var got = Hallway.GetAtWorldspaceG(wantX, wantY); if (!sym.IsInsideRoom(wantX, wantY)) { done = true; } else { GenTile tile = GenTile.GetEmpty(); tile.Details.Add(new GenDetail() { Type = GenDetail.DetailType.Decoration, Char = 'O' }); GenTile[,] feature = new GenTile[, ] { { tile } }; int fposX = wantX; int fposY = wantY; GenTile[,] final = GenUtil.GetSymetry(feature, ref fposX, ref fposY, Hallway, GenUtil.Axis.Vertical); Hallway.SetTilesAtG(fposX, fposY, final); TestDrawer.text = sym.Print(false); yield return(new WaitForSeconds(0.5f)); wantX += 2; } } for (int x = 0; x < 20; x++) { for (int y = 0; y < 15; y++) { if (sym.IsCornerG(x, y, GenDetail.DetailType.Wall, GenDetail.DetailType.Decoration)) { GenRoom corner = GenRoom.Sized(1, 1); corner.FillFloor('X'); sym.PlaceRoom(x, y, corner); TestDrawer.text = sym.Print(false); yield return(new WaitForSeconds(0.25f)); } } } /* * GenData data = new GenData(40, 20); * * GenRoom startRoom = GenRoom.Sized(5,8,true); * startRoom.SpacePriority = 0; * * GenRoom room2 = GenRoom.Sized(8, 8, true); * room2.FillFloor('a'); * * GenRoom room3 = GenRoom.Sized(5, 5, true); * room3.FillFloor('b'); * room3.SpacePriority = 2; * * GenRoom room4 = GenRoom.Sized(10, 10, true); * room4.FillFloor('c'); * * data.PlaceRoom(1, 0, startRoom); * data.PlaceRoom(4, 1, room2); * data.PlaceRoom(25, 11, room3); * data.PlaceRoom(23, 3, room4); * * data.FixOverlap(); * data.EdgeWalls('#'); * * data.Print(false); */ }
public GenVertex(GenRoom r) { this.r = r; value = float.PositiveInfinity; }
public static Dungeon GenerateDungeon(Quest quest, int seed = 0) { if (seed != 0) { Random.InitState(seed); } string[] lengthes = new string[] { "", "short", "medium", "long" }; Dungeon dungeon = new Dungeon(); DungeonGenerationData genData = DarkestDungeonManager.Data.DungeonGenerationData.Find(item => item.Dungeon == quest.Dungeon && item.Length == lengthes[quest.Length] && item.QuestType == quest.Type); DungeonEnviromentData envData = DarkestDungeonManager.Data.DungeonEnviromentData[quest.Dungeon]; int RoomsLeft = genData.BaseRoomNumber; int HallsLeft = genData.BaseCorridorNumber; int xSize = genData.GridSizeX; int ySize = genData.GridSizeY; dungeon.GridSizeX = xSize; dungeon.GridSizeY = ySize; List <GenRoom> Areas = new List <GenRoom>(); GenRoom[,] areaGrid = new GenRoom[xSize, ySize]; GenerateRooms(Areas, areaGrid, RoomsLeft, xSize, ySize); GenRoom hub = GetHub(Areas); List <GenRoom> ExistingRooms = ForceBorderRooms(Areas, hub, RoomsLeft); List <GenHall> ExistingHalls = ForceHallConnection(Areas, hub, ExistingRooms, HallsLeft); dungeon.Rooms = GetFinalRooms(ExistingRooms, genData); dungeon.Hallways = GetFinalHallways(dungeon, ExistingHalls, genData); MarkEntrance(dungeon); switch (quest.Goal.Type) { case "kill_monster": if (quest.Goal.QuestData is QuestKillMonsterData) { var bossData = quest.Goal.QuestData as QuestKillMonsterData; envData.BattleMashes.Find(mash => mash.BossEncounters.Find(encounter => encounter.MonsterSet.Contains(bossData.MonsterNameIds[0])) != null); var bossGenRoom = LongestPathRoom(ExistingRooms.Find(room => room.Id == dungeon.StartingRoomId), ExistingRooms); var bossRoom = dungeon.Rooms[bossGenRoom.Id]; bossRoom.Type = AreaType.Boss; var bossEncounter = envData.BattleMashes.Find(mash => mash.MashId == quest.Difficulty). BossEncounters.Find(encounter => encounter.MonsterSet.Contains(bossData.MonsterNameIds[0])); bossRoom.BattleEncounter = new BattleEncounter(bossEncounter.MonsterSet); } else { Debug.LogError("Missing boss data in dungeon!"); } break; case "activate": if (quest.Goal.QuestData is QuestActivateData) { var activateData = quest.Goal.QuestData as QuestActivateData; var lastRoom = LongestPathRoom(ExistingRooms.Find(room => room.Id == dungeon.StartingRoomId), ExistingRooms); for (int i = 0; i < activateData.Amount; i++) { var availableRooms = ExistingRooms.FindAll(room => room.MinPath >= (float)i / activateData.Amount * lastRoom.MinPath && room.MinPath <= (float)(i + 1) / activateData.Amount * lastRoom.MinPath); int randomRoom = Random.Range(0, availableRooms.Count - 1); var questRoom = dungeon.Rooms[availableRooms[randomRoom].Id]; if (questRoom.Type == AreaType.Empty) { var curio = new Curio(activateData.CurioName); curio.IsQuestCurio = true; if (quest.Goal.StartingItems.Count > 0) { curio.ItemInteractions.Add(new ItemInteraction() { Chance = 1, ItemId = quest.Goal.StartingItems[0].Id, ResultType = "loot", Results = new List <CurioResult>(), }); } questRoom.Type = AreaType.Curio; questRoom.Prop = curio; } else { i--; } } } break; case "gather": if (quest.Goal.QuestData is QuestGatherData) { var gatherData = quest.Goal.QuestData as QuestGatherData; var lastRoom = LongestPathRoom(ExistingRooms.Find(room => room.Id == dungeon.StartingRoomId), ExistingRooms); for (int i = 0; i < gatherData.Item.Amount; i++) { var availableRooms = ExistingRooms.FindAll(room => room.MinPath >= (float)i / gatherData.Item.Amount * lastRoom.MinPath && room.MinPath <= (float)(i + 1) / gatherData.Item.Amount * lastRoom.MinPath); int randomRoom = Random.Range(0, availableRooms.Count - 1); var questRoom = dungeon.Rooms[availableRooms[randomRoom].Id]; if (questRoom.Type == AreaType.Empty) { var curio = new Curio(gatherData.CurioName); curio.IsQuestCurio = true; var curioInteraction = new CurioInteraction(); curioInteraction.Chance = 1; curioInteraction.ResultType = "loot"; curioInteraction.Results = new List <CurioResult>(); curioInteraction.Results.Add(new CurioResult() { Chance = 1, Draws = 1, Item = gatherData.Item.Id, }); curio.Results.Add(curioInteraction); questRoom.Type = AreaType.Curio; questRoom.Prop = curio; } else { i--; } } } break; default: break; } PopulateRooms(dungeon, genData); LoadRoomEnviroment(dungeon, envData, quest.Difficulty); PopulateHalls(dungeon, genData); LoadHallEnviroment(dungeon, envData, quest.Difficulty); dungeon.GridSizeX = 1 + (xSize - 1) * 7; dungeon.GridSizeY = 1 + (ySize - 1) * 7; dungeon.Name = quest.Dungeon; dungeon.DungeonMash = envData.BattleMashes.Find(mash => mash.MashId == quest.Difficulty); dungeon.SharedMash = DarkestDungeonManager.Data.DungeonEnviromentData["shared"]. BattleMashes.Find(mash => mash.MashId == quest.Difficulty); return(dungeon); }
public int genGateEvent(GenRoom newRoom, int direction) { // prepare event to open the gate // before everything start, lets check if any monsters int gateOpenMethod; List <GenMonster> targetMonsters = new List <GenMonster>(); if (newRoom.monsters == null) { gateOpenMethod = 0; // TODO: add chance to trigger/treasure open gate event here (or not here? need a better flow) } else { // lets check how many target monster here for (int i = 0; i < newRoom.monsters.Length; i++) { // lets assume monsterObjId 1 as target monster if (newRoom.monsters[i].monsterObjId == 1) { targetMonsters.Add(newRoom.monsters[i]); } } // currently there should be three type of method to open gate gateOpenMethod = randomGen(new int[] { 0, 1 }); if (targetMonsters.Count > 0) { // kill specific monsters can only be done when target monsters exists gateOpenMethod = randomGen(new int[] { 1, 2 }); } } switch (gateOpenMethod) { case 0: { // if no monster, gate must be opened already, so add an event on level start // GenEvent gateOpeningEvent = new GenEvent(); // gateOpeningEvent.triggerTypeId = GenEvent.TriggerType.LEVEL_ENTER; // gateOpeningEvent.results = new GenEventResult[1]; // gateOpeningEvent.results[0] = new GenEventResult(); // gateOpeningEvent.results[0].resultTypeId = GenEvent.ResultType.GATE_OPEN; // gateOpeningEvent.results[0].resultParams = new float[]{currentWorkingLevel.levelId, newRoom.roomId, direction}; // // currentWorkingLevel.events.Add(gateOpeningEvent); } break; // 1) kill all monsters // Event setting: all monster will add 1 to a global variable when being killed // when that global variable reach the number of monsters, trigger an event to open the gate case 1: { // 1. set monster event, when die, add a counter GenVariable newVar = new GenVariable(); newVar.variableId = variablesCounter++; newVar.initValue = 0; variablesList.Add(newVar); // 2. Create an event that, when a monster dead, add up a counter // GenEvent monsterDieEvent = new GenEvent(); // monsterDieEvent.triggerTypeId = GenEvent.TriggerType.MONSTER_DIE; // monsterDieEvent.results = new GenEventResult[1]; // monsterDieEvent.results[0] = new GenEventResult(); // monsterDieEvent.results[0].resultTypeId = GenEvent.ResultType.VAR_SET_AS_VAR_PLUS_NUM; // monsterDieEvent.results[0].resultParams = new float[]{newVar.variableId, newVar.variableId, 1f}; // // // 3. Create an event that, when a monster dead, check if thee counter is larger than or equal to room monster num, if yes then open the gate // GenEvent gateOpeningEvent = new GenEvent(); // gateOpeningEvent.triggerTypeId = GenEvent.TriggerType.MONSTER_DIE; // gateOpeningEvent.conds = new GenEventCond[1]; // gateOpeningEvent.conds[0] = new GenEventCond(); // gateOpeningEvent.conds[0].condTypeId = GenEvent.CondType.LOGIC_LARGER_OR_EQUAL_NUM; // gateOpeningEvent.conds[0].condParams = new float[]{newVar.variableId, newRoom.monsters.Length}; // gateOpeningEvent.results = new GenEventResult[1]; // gateOpeningEvent.results[0] = new GenEventResult(); // gateOpeningEvent.results[0].resultTypeId = GenEvent.ResultType.GATE_OPEN; // gateOpeningEvent.results[0].resultParams = new float[]{currentWorkingLevel.levelId, newRoom.roomId, direction}; // // // 4. now assign both event to every monster in room // for(int i=0;i<newRoom.monsters.Length;i++) { // if(newRoom.monsters[i].events == null) { // newRoom.monsters[i].events = new List<GenEvent>(); // } // newRoom.monsters[i].events.Add(monsterDieEvent); // newRoom.monsters[i].events.Add (gateOpeningEvent); // } } break; // 2) kill specific monsters // Event setting: similar to above, be the counter variable is not all monsters, // and not all monsters have the triggering event case 2: { // 1. set monster event, when die, add a counter GenVariable newVar = new GenVariable(); newVar.variableId = variablesCounter++; newVar.initValue = 0; // 2. Create an event that, when a monster dead, add up a counter // GenEvent monsterDieEvent = new GenEvent(); // monsterDieEvent.triggerTypeId = GenEvent.TriggerType.MONSTER_DIE; // monsterDieEvent.results = new GenEventResult[1]; // monsterDieEvent.results[0] = new GenEventResult(); // monsterDieEvent.results[0].resultTypeId = GenEvent.ResultType.VAR_SET_AS_VAR_PLUS_NUM; // monsterDieEvent.results[0].resultParams = new float[]{newVar.variableId, newVar.variableId, 1f}; // // // 3. Create an event that, when a monster dead, check if thee counter is larger than or equal to room monster num, if yes then open the gate // GenEvent gateOpeningEvent = new GenEvent(); // gateOpeningEvent.triggerTypeId = GenEvent.TriggerType.MONSTER_DIE; // gateOpeningEvent.conds = new GenEventCond[1]; // gateOpeningEvent.conds[0] = new GenEventCond(); // gateOpeningEvent.conds[0].condTypeId = GenEvent.CondType.LOGIC_LARGER_OR_EQUAL_NUM; // gateOpeningEvent.conds[0].condParams = new float[]{newVar.variableId, targetMonsters.Count}; // gateOpeningEvent.results = new GenEventResult[1]; // gateOpeningEvent.results[0] = new GenEventResult(); // gateOpeningEvent.results[0].resultTypeId = GenEvent.ResultType.GATE_OPEN; // gateOpeningEvent.results[0].resultParams = new float[]{currentWorkingLevel.levelId, newRoom.roomId, direction}; // // // 4. now assign both event to every monster in room // for(int i=0;i<targetMonsters.Count;i++) { // if(targetMonsters[i].events == null) { // targetMonsters[i].events = new List<GenEvent>(); // } // targetMonsters[i].events.Add(monsterDieEvent); // targetMonsters[i].events.Add (gateOpeningEvent); // } } break; // 3) use key // Event setting: TODO <--- seems need to expand data structure } return(gateOpenMethod); }
public GenRoom genNextRoom(int x, int y, bool isMainline, bool isLastLevel = false, int length = 0, int incomeDirection = -1) { GenRoom newRoom = new GenRoom(); newRoom.roomObjId = randomGen(roomIds); Room roomData = new Room(newRoom.roomObjId); newRoom.roomId = roomIdCounter++; int monsterNum = 0; // first calibrate the position if (incomeDirection != -1) { x -= roomData.gates [incomeDirection].pos.x; y -= roomData.gates [incomeDirection].pos.y; } else { x -= 8; y -= 8; } // check collision Rect newArea = new Rect(x, y, 16, 16); if (collisionCheck(newArea)) { return(null); } occupiedArea.Add(newArea); // add monster to room // check if needed (not starting room) if (length == mainlineLength) { // starting room need character starting position //bool validPos = false; newRoom.charPosition = new Pos(5, 5); // while(!validPos) { // newRoom.charPosition.x = Random.Range (0, 13); // newRoom.charPosition.y = Random.Range (0, 13); // if(roomData.landscape[newRoom.charPosition.y][newRoom.charPosition.x] == 1) { // validPos = true; // } // } } else if (length == 1) { // last room, let this be the teleport gate room newRoom.teleportGate = new GenTGate(); newRoom.teleportGate.teleportGateObjId = 1; bool validPos = false; newRoom.teleportGate.position = new Pos(0, 0); while (!validPos) { newRoom.teleportGate.position.x = Random.Range(0, 13); newRoom.teleportGate.position.y = Random.Range(0, 13); if (roomData.landscape[newRoom.teleportGate.position.y][newRoom.teleportGate.position.x] == 1) { validPos = true; } } if (isLastLevel) { newRoom.teleportGate.target = "boss"; } else { newRoom.teleportGate.target = "level"; } } // else { // random number of monsters monsterNum = maxMonsterNum;// randomGen(monsterNums); newRoom.monsters = new GenMonster[monsterNum]; for (int i = 0; i < monsterNum; i++) { // get a position // TODO: stop using silly method bool validPos = false; Pos position = new Pos(0, 0); while (!validPos) { position.x = Random.Range(0, 13); position.y = Random.Range(0, 13); if (roomData.landscape[position.y][position.x] == 1) { // mark area around nolonger avaliable roomData.landscape[position.y - 1][position.x] = 0; roomData.landscape[position.y + 1][position.x] = 0; roomData.landscape[position.y][position.x - 1] = 0; roomData.landscape[position.y][position.x + 1] = 0; roomData.landscape[position.y][position.x] = 0; validPos = true; } } newRoom.monsters[i] = genMonster(i, position); } //} // mark all gate position for (int i = 0; i < 4; i++) { newRoom.gates[i].x = x + roomData.gates[i].pos.x; newRoom.gates[i].y = y + roomData.gates[i].pos.y; } if (isMainline) { // get the next room (recursion), attach to the bridge if (length > 1) { // random a gate int direction; GenBridge newBridge = null; GenRoom nextRoom = null; int[] directions = new int[] { 0, 1, 2, 3 }; List <int> directionList = new List <int>(directions); List <float> ratioList = new List <float>(directionRatio); if (directionList.Remove(incomeDirection) == true) { ratioList.RemoveAt(incomeDirection); } do { if (directionList.Count == 0) { return(null); } direction = randomGen(directionList.ToArray(), ratioList.ToArray()); int directionIndex = directionList.IndexOf(direction); directionList.RemoveAt(directionIndex); ratioList.RemoveAt(directionIndex); newBridge = genBridge(newRoom.gates[direction].x, newRoom.gates[direction].y, direction); nextRoom = genNextRoom(newBridge.x, newBridge.y, isMainline, isLastLevel, length - 1, (direction < 2?direction + 2:direction - 2)); } while (nextRoom == null); // open the gate newRoom.gates[direction].isGateOpen = true; int gateOpenMethod = genGateEvent(newRoom, direction); // TODO: Old open gate method, get ride of this when have time to implement event system on client side newRoom.gates[direction].gateOpenCondId = gateOpenMethod; if (newRoom.monsters == null) { newRoom.gates[direction].gateOpenCondId = 0; } else if (newRoom.gates[direction].gateOpenCondId == 2) { // need to kill specific monster, mark which one // temp all monsterObj = 1 List <int> targetMonsters = new List <int>(); for (int i = 0; i < monsterNum; i++) { if (newRoom.monsters[i].monsterObjId == 1) { targetMonsters.Add(i); } } newRoom.gates[direction].gateOpenCondParam = targetMonsters.ToArray(); } // get a bridge and connect to the gate newRoom.gates[direction].bridge = newBridge; newRoom.gates[direction].bridge.targetRoom = nextRoom; // gather list of unused gate for branching if (length != mainlineLength) { for (int i = 0; i < 4; i++) { if (i != direction && i != incomeDirection) { branchableGates.Add(newRoom.gates[i]); } } } } } else { } return(newRoom); }
public List <GenTile> GetNeighbouringTiles(GenRoom room) { return(Data.ToList().Union(room.Data.ToList()).ToList()); }
public bool IsNeighbour(GenRoom room) { return(Data.ToList().Union(room.Data.ToList()).ToList().Count > 0); }
public GenConnection(GenRoom a, GenRoom b) { this.a = a; this.b = b; }
public static bool GenerateLayout(LevelGenerator generator, uint generationIndex) { Queue <GenRoom> rooms = new Queue <GenRoom>(4); List <GenRoom> genRooms = new List <GenRoom>(12); rooms.Enqueue(generator.firstRoom); while (rooms.Count > 0) { GenRoom room = rooms.Dequeue(); if (room.generationIndex != generationIndex) { GenRoom firstGeneratedPrevRoom = null; int connectionCount = 0; for (GenRoomConnection connection = room.firstConnection; connection != null; connection = connection.next, connectionCount++) { GenRoom otherRoom = room.GetOtherRoom(connection); if (otherRoom.generationIndex != generationIndex) { rooms.Enqueue(otherRoom); } else if (firstGeneratedPrevRoom == null) { firstGeneratedPrevRoom = otherRoom; } } GenRoomInfo roomInfo = generator.collection.GetRandomRoom(room.type); Debug.Assert(roomInfo.doors.Count >= connectionCount); // TODO: GetRandomRoom based on connectionCount if (firstGeneratedPrevRoom != null) { List <GenRoom> connectedRooms = new List <GenRoom>(1) { firstGeneratedPrevRoom }; List <Vector2Int> positions = GetUnconnectedPositions(firstGeneratedPrevRoom, roomInfo); int positionCount = positions.Count; for (GenRoomConnection connection = room.firstConnection; connection != null; connection = connection.next) { GenRoom otherRoom = room.GetOtherRoom(connection); if (otherRoom.generationIndex == generationIndex && otherRoom != firstGeneratedPrevRoom) { connectedRooms.Add(otherRoom); List <Vector2Int> otherPositions = GetUnconnectedPositions(otherRoom, roomInfo); for (int i = positions.Count - 1; i >= 0; --i) { if (!otherPositions.Contains(positions[i])) { positions.RemoveAt(i); } } if (positions.Count == 0) { Debug.Log($"FAILED: Couldn't find any connected positions for the room: {room.name} from the {positionCount} started positions!"); return(false); } } } RemoveCollidedPositions(genRooms, connectedRooms, positions, roomInfo.size); if (positions.Count == 0) { if (positionCount == 0) { Debug.Log($"FAILED: Couldn't find any started positions for the room: {room.name} from the previous room: {firstGeneratedPrevRoom.name}"); } else { Debug.Log($"FAILED: Couldn't find any uncollided positions for the room: {room.name} from the {positionCount} started positions!"); } return(false); } Vector2Int randomPos = positions.RandomElement(); InitGenRoom(genRooms, room, roomInfo, randomPos, generationIndex); for (GenRoomConnection connection = room.firstConnection; connection != null; connection = connection.next) { GenRoom otherRoom = room.GetOtherRoom(connection); if (otherRoom.generationIndex == generationIndex) { RectInt door = GetUnconnectedMatchDoors(room, otherRoom).RandomElement(); connection.connection.rect = door; Debug.Assert(room.unconnectedDoors.Remove(new RectInt(door.position - room.rect.position, door.size))); Debug.Assert(otherRoom.unconnectedDoors.Remove(new RectInt(door.position - otherRoom.rect.position, door.size))); } } } else { InitGenRoom(genRooms, room, roomInfo, Vector2Int.zero, generationIndex); } } } return(true);