public PosArray<CellType> GenerateMap(LevelType type) { PosArray<CellType> result = new PosArray<CellType>(ROWS,COLS); Dungeon d = new Dungeon(ROWS,COLS); switch(type){ case LevelType.Standard: while(true){ d.CreateBasicMap(); d.ConnectDiagonals(); d.RemoveUnconnectedAreas(); d.RemoveDeadEndCorridors(); d.AddDoors(25); d.AlterRooms(5,2,2,1,0); d.MarkInterestingLocations(); d.RemoveUnconnectedAreas(); if(d.NumberOfFloors() < 320 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } case LevelType.Cave: { int roll = R.Roll(2); if(R.OneIn(20)){ roll = 3; } switch(roll){ //three different algorithms case 1: { while(true){ d.FillWithRandomWalls(25); d.ApplyCellularAutomataXYRule(3); d.ConnectDiagonals(); d.ImproveMapEdges(5); d.RemoveDeadEndCorridors(); d.RemoveUnconnectedAreas(); d.MarkInterestingLocationsNonRectangular(); if(d.NumberOfFloors() < 320 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } } case 2: { while(true){ d.CreateTwistyCave(true,40); U.DefaultMetric = DistanceMetric.Manhattan; var dijk = d.map.GetDijkstraMap(x=>!d.map[x].IsWall(),x=>false); for(int i=1;i<ROWS-1;++i){ for(int j=1;j<COLS-1;++j){ U.DefaultMetric = DistanceMetric.Manhattan; if(dijk[i,j] == 1){ pos p = new pos(i,j); List<pos> floors = null; foreach(int dir in U.FourDirections){ pos n = p.PosInDir(dir); if(dijk[n] == 1){ if(floors == null){ floors = p.PositionsAtDistance(1,dijk).Where(x=>dijk[x] == 0); } List<pos> floors2 = new List<pos>(); foreach(pos n2 in n.PositionsAtDistance(1,dijk)){ if(dijk[n2] == 0 && !floors.Contains(n2)){ floors2.Add(n2); } } if(floors2.Count > 0 && R.OneIn(5)){ //IIRC this checks each pair twice, so that affects the chance here pos f1 = floors.Random(); pos f2 = floors2.Random(); U.DefaultMetric = DistanceMetric.Chebyshev; int dist = d.map.PathingDistanceFrom(f1,f2,x=>!d.map[x].IsPassable() && d.map[x] != CellType.Door); if(dist > 22 || (dist > 8 && R.OneIn(4))){ CellType rubble = R.OneIn(8)? CellType.Rubble : CellType.CorridorIntersection; d[p] = R.OneIn(3)? rubble : CellType.CorridorIntersection; d[n] = R.OneIn(3)? rubble : CellType.CorridorIntersection; List<pos> neighbors = new List<pos>(); foreach(pos nearby in p.PositionsAtDistance(1)){ if(nearby.BoundsCheck(d.map,false) && nearby.DistanceFrom(n) == 1){ neighbors.Add(nearby); } } while(neighbors.Count > 0){ pos neighbor = neighbors.RemoveRandom(); if(R.OneIn(neighbors.Count + 3) && !d.SeparatesMultipleAreas(neighbor)){ d[neighbor] = R.OneIn(2)? CellType.Rubble : CellType.CorridorIntersection; } } } } break; } } } } } /*List<pos> thin_walls = d.map.AllPositions().Where(x=>d.map[x].IsWall() && x.HasOppositePairWhere(true,y=>y.BoundsCheck() && d.map[y].IsFloor())); while(thin_walls.Count > 0){ pos p = thin_walls.Random(); foreach(int dir in new int[]{8,4}){ if(d.map[p.PosInDir(dir)] != CellType.Wall && d.map[p.PosInDir(dir.RotateDir(true,4))] != CellType.Wall){ var dijkstra = d.map.GetDijkstraMap(x=>d[x] == CellType.Wall,new List<pos>{p.PosInDir(dir)}); //todo: this would be better as "get distance" if(Math.Abs(dijkstra[p.PosInDir(dir)] - dijkstra[p.PosInDir(dir.RotateDir(true,4))]) > 30){ d.map[p] = CellType.CorridorIntersection; break; } } } thin_walls.Remove(p); //todo: move thin-wall-removal to schism }*/ d.ConnectDiagonals(); d.RemoveUnconnectedAreas(); d.ImproveMapEdges(5); d.SmoothCorners(60); d.RemoveDeadEndCorridors(); d.MarkInterestingLocationsNonRectangular(); if(d.NumberOfFloors() < 320 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } U.DefaultMetric = DistanceMetric.Chebyshev; return result; } } } case 3: { d.RoomHeightMax = 3; d.RoomWidthMax = 3; while(true){ int successes = 0; int consecutive_failures = 0; while(successes < 13){ if(d.CreateRoom()){ ++successes; consecutive_failures = 0; } else{ if(consecutive_failures++ >= 50){ d.Clear(); successes = 0; consecutive_failures = 0; } } } d.CaveWidenRooms(100,50); d.AddRockFormations(40,2); List<pos> thin_walls = d.map.AllPositions().Where(x=>d.map[x].IsWall() && x.HasOppositePairWhere(true,y=>y.BoundsCheck(tile) && d.map[y].IsFloor())); while(!d.IsFullyConnected() && thin_walls.Count > 0){ pos p = thin_walls.Random(); d.map[p] = CellType.CorridorIntersection; foreach(pos neighbor in p.PositionsWithinDistance(1,d.map)){ thin_walls.Remove(neighbor); } } d.ConnectDiagonals(); d.RemoveDeadEndCorridors(); d.RemoveUnconnectedAreas(); d.MarkInterestingLocationsNonRectangular(); if(d.NumberOfFloors() < 320 || d.HasLargeUnusedSpaces(300)){ //todo: add 'proper coverage' check here - make sure it stretches across enough of the map. d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } } } break; } case LevelType.Hive: { d.RoomHeightMax = 3; d.RoomWidthMax = 3; while(true){ int successes = 0; int consecutive_failures = 0; while(successes < 35){ if(d.CreateRoom()){ ++successes; consecutive_failures = 0; } else{ if(consecutive_failures++ >= 40){ d.Clear(); successes = 0; consecutive_failures = 0; } } } d.CaveWidenRooms(100,10); d.CaveWidenRooms(3,20); List<pos> thin_walls = d.map.AllPositions().Where(x=>d.map[x].IsWall() && x.HasOppositePairWhere(true,y=>y.BoundsCheck(tile) && d.map[y].IsFloor())); while(!d.IsFullyConnected() && thin_walls.Count > 0){ pos p = thin_walls.Random(); d.map[p] = CellType.CorridorIntersection; foreach(pos neighbor in p.PositionsWithinDistance(2,d.map)){ thin_walls.Remove(neighbor); } } d.ConnectDiagonals(); d.RemoveDeadEndCorridors(); d.RemoveUnconnectedAreas(); d.MarkInterestingLocations(); //to find rooms big enough for stuff in the center: //var dijkstra = d.map.GetDijkstraMap(x=>d.map[x].IsWall(),d.map.AllPositions().Where(x=>d.map[x].IsWall() && x.HasAdjacentWhere(y=>d.map.BoundsCheck(y) && !d.map[y].IsWall()))); if(d.NumberOfFloors() < 340 || d.HasLargeUnusedSpaces(300)){ //todo: add 'proper coverage' check here - make sure it stretches across enough of the map. d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } } case LevelType.Mine: { d.CorridorExtraLengthChance = 0; d.CorridorChainSizeMax = 10; while(true){ d.RoomHeightMin = 8; d.RoomWidthMin = 8; d.RoomHeightMax = 8; d.RoomWidthMax = 10; d.MinimumSpaceBetweenCorridors = 3; d.CorridorLengthMin = 3; d.CorridorLengthMax = 5; while(!d.CreateRoom()){} d.RoomHeightMin = 5; d.RoomWidthMin = 5; d.RoomHeightMax = 5; d.RoomWidthMax = 5; while(!d.CreateRoom()){} while(!d.CreateRoom()){} /*for(int i=0;i<10;++i){ d.CreateRoom(); } d.AddRockFormations(100,2);*/ d.MinimumSpaceBetweenCorridors = 5; d.CorridorLengthMin = 4; d.CorridorLengthMax = 12; for(int i=0;i<70;++i){ d.CreateCorridor(); } d.CorridorLengthMin = 3; d.CorridorLengthMax = 5; d.MinimumSpaceBetweenCorridors = 3; for(int i=0;i<350;++i){ d.CreateCorridor(); } d.RemoveUnconnectedAreas(); d.ConnectDiagonals(true); d.RemoveUnconnectedAreas(); d.MarkInterestingLocations(); if(d.NumberOfFloors() < 250 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } } case LevelType.Fortress: while(true){ int H = ROWS; int W = COLS; for(int i=H/2-1;i<H/2+1;++i){ for(int j=1;j<W-1;++j){ if(j==1 || j==W-2){ d.map[i,j] = CellType.RoomCorner; } else{ d.map[i,j] = CellType.RoomEdge; } } } for(int i=0;i<700;++i){ if(R.OneIn(5)){ d.CreateCorridor(); } else{ d.CreateRoom(); } } bool reflect_features = R.PercentChance(80); if(reflect_features){ d.AddDoors(25); d.AddPillars(30); } d.Reflect(true,false); d.ConnectDiagonals(); d.RemoveDeadEndCorridors(); d.RemoveUnconnectedAreas(); if(!reflect_features){ d.AddDoors(25); d.AddPillars(30); } bool door_right = false; bool door_left = false; int rightmost_door = 0; int leftmost_door = 999; for(int j=0;j<22;++j){ if(d[H/2-2,j].IsCorridorType()){ door_left = true; if(leftmost_door == 999){ leftmost_door = j; } } if(d[H/2-2,W-1-j].IsCorridorType()){ door_right = true; if(rightmost_door == 0){ rightmost_door = W-1-j; } } } if(!door_left || !door_right){ d.Clear(); continue; } for(int j=1;j<leftmost_door-6;++j){ d[H/2-1,j] = CellType.Wall; d[H/2,j] = CellType.Wall; } for(int j=W-2;j>rightmost_door+6;--j){ d[H/2-1,j] = CellType.Wall; d[H/2,j] = CellType.Wall; } for(int j=1;j<W-1;++j){ if(d[H/2-1,j].IsFloor()){ d[H/2-1,j] = CellType.Statue; d[H/2,j] = CellType.Statue; break; } else{ if(d[H/2-1,j] == CellType.Statue){ break; } } } for(int j=W-2;j>0;--j){ if(d[H/2-1,j].IsFloor()){ d[H/2-1,j] = CellType.Statue; d[H/2,j] = CellType.Statue; break; } else{ if(d[H/2-1,j] == CellType.Statue){ break; } } } for(int i=H/2-1;i<H/2+1;++i){ for(int j=1;j<W-1;++j){ if(d[i,j] == CellType.RoomCorner || d[i,j] == CellType.RoomEdge){ d[i,j] = CellType.CorridorIntersection; } } } d.MarkInterestingLocations(); if(d.NumberOfFloors() < 420 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } case LevelType.Slime: while(true){ /*for(int i=1;i<ROWS-1;++i){ for(int j=1;j<COLS-1;++j){ if(d[i,j].IsWall()){ if(!d[i+1,j+1].IsWall()){ d[i,j] = d[i+1,j+1]; } else{ if(!d[i+1,j].IsWall()){ d[i,j] = d[i+1,j]; } else{ if(!d[i,j+1].IsWall()){ d[i,j] = d[i,j+1]; } } } } } }*/ d.CreateBasicMap(); d.ConnectDiagonals(); d.RemoveUnconnectedAreas(); d.AddDoors(25); d.CaveWidenRooms(30,30); d.RemoveDeadEndCorridors(); d.AddPillars(30); d.MarkInterestingLocations(); if(d.NumberOfFloors() < 120 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } case LevelType.Garden: { d.RoomHeightMin = 4; d.RoomHeightMax = 10; d.RoomWidthMin = 4; d.RoomWidthMax = 10; while(true){ d.CreateBasicMap(); d.ConnectDiagonals(); d.RemoveUnconnectedAreas(); d.RemoveDeadEndCorridors(); var dijkstra = d.map.GetDijkstraMap(x=>d[x].IsPassable(),x=>false); List<pos> possible_room_centers = d.map.PositionsWhere(x=>dijkstra[x] == 3 && x.row > 1 && x.row < ROWS-2 && x.col > 1 && x.col < COLS-2); int rooms = 0; while(rooms < 6 && possible_room_centers.Count > 0){ pos p = possible_room_centers.RemoveRandom(); List<int> valid_dirs = new List<int>(); foreach(int dir in U.FourDirections){ pos p2 = p.PosInDir(dir).PosInDir(dir).PosInDir(dir); if(p2.BoundsCheck(d.map) && d[p2].IsPassable() && d[p2] != CellType.RoomCorner){ valid_dirs.Add(dir); } } if(valid_dirs.Count > 0){ foreach(pos neighbor in p.PositionsWithinDistance(1,d.map)){ d[neighbor] = CellType.RoomInterior; } possible_room_centers.RemoveWhere(x=>p.DistanceFrom(x) <= 3); foreach(int dir in valid_dirs){ d[p.PosInDir(dir).PosInDir(dir)] = CellType.CorridorIntersection; } ++rooms; } } CellType water_type = CellType.ShallowWater; if(R.OneIn(8)){ water_type = CellType.Ice; } d.ForEachRectangularRoom((start_r,start_c,end_r,end_c)=>{ int room_height = (end_r - start_r) + 1; int room_width = (end_c - start_c) + 1; if(room_height <= 4 && room_width <= 4){ if(room_height == 3 && room_width == 3){ return true; } List<pos> water = new List<pos>(); if(!new pos(start_r+1,start_c).PositionsAtDistance(1,d.map).Any(x=>d[x].IsCorridorType())){ water.Add(new pos(start_r+1,start_c)); water.Add(new pos(start_r+2,start_c)); } if(!new pos(start_r,start_c+1).PositionsAtDistance(1,d.map).Any(x=>d[x].IsCorridorType())){ water.Add(new pos(start_r,start_c+1)); water.Add(new pos(start_r,start_c+2)); } if(!new pos(end_r-1,end_c).PositionsAtDistance(1,d.map).Any(x=>d[x].IsCorridorType())){ water.Add(new pos(end_r-1,end_c)); water.Add(new pos(end_r-2,end_c)); } if(!new pos(end_r,end_c-1).PositionsAtDistance(1,d.map).Any(x=>d[x].IsCorridorType())){ water.Add(new pos(end_r,end_c-1)); water.Add(new pos(end_r,end_c-2)); } foreach(pos p in water){ d[p] = water_type; } d[start_r,start_c] = CellType.Statue; d[start_r,end_c] = CellType.Statue; d[end_r,start_c] = CellType.Statue; d[end_r,end_c] = CellType.Statue; } else{ CellType center_type = CellType.RoomFeature1; switch(R.Roll(3)){ case 1: center_type = water_type; break; case 2: center_type = CellType.Poppies; break; case 3: center_type = CellType.Brush; break; } bool statues = R.CoinFlip(); CellType statue_type = CellType.Statue; if(room_height <= 8 && room_width <= 8 && R.OneIn(8)){ statue_type = CellType.Torch; } CellType edge_type = CellType.ShallowWater; if(center_type != water_type && !R.OneIn(4)){ edge_type = CellType.ShallowWater; } else{ int vine_chance = 50; if(!statues){ vine_chance = 80; } if(R.PercentChance(vine_chance)){ edge_type = CellType.Vine; } else{ edge_type = CellType.Gravel; } if(R.OneIn(32)){ if(R.CoinFlip()){ edge_type = CellType.Statue; } else{ edge_type = CellType.GlowingFungus; } } } bool gravel = R.OneIn(16); bool edges = R.CoinFlip(); if(room_height < 6 || room_width < 6){ edges = false; } if(room_height >= 8 && room_width >= 8){ edges = !R.OneIn(4); } if(edges){ for(int i=start_r;i<=end_r;++i){ for(int j=start_c;j<=end_c;++j){ if(i == start_r || i == end_r || j == start_c || j == end_c){ //edges if(statues && (i == start_r || i == end_r) && (j == start_c || j == end_c)){ //corners d[i,j] = statue_type; } else{ pos p = new pos(i,j); if(!p.CardinalAdjacentPositions().Any(x=>d[x].IsCorridorType())){ d[i,j] = edge_type; } } } else{ if(i == start_r+1 || i == end_r-1 || j == start_c+1 || j == end_c-1){ //the path if(gravel){ d[i,j] = CellType.Gravel; } } else{ d[i,j] = center_type; } } } } } else{ for(int i=start_r;i<=end_r;++i){ for(int j=start_c;j<=end_c;++j){ if(i == start_r || i == end_r || j == start_c || j == end_c){ if(gravel){ d[i,j] = CellType.Gravel; } } else{ d[i,j] = center_type; } } } } if(center_type == water_type && room_height % 2 == 1 && room_width % 2 == 1){ statue_type = CellType.Statue; if(room_height <= 7 && room_width <= 7 && R.OneIn(12)){ statue_type = CellType.Torch; } d[(start_r+end_r)/2,(start_c+end_c)/2] = statue_type; } } return true; }); d.ConnectDiagonals(); d.RemoveUnconnectedAreas(); d.AddDoors(10); d.RemoveDeadEndCorridors(); d.MarkInterestingLocations(); if(d.NumberOfFloors() < 320 || d.HasLargeUnusedSpaces(300)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } } case LevelType.Crypt: { while(true){ pos room1origin = new pos(ROWS/2,R.Roll(COLS/8 - 1) + COLS/8 - 1); pos room2origin = new pos(ROWS/2,R.Roll(COLS/8 - 1) + (COLS*6 / 8) - 1); while(!d.CreateRoom(room1origin.row,room1origin.col)){} //left half while(!d.CreateRoom(room2origin.row,room2origin.col)){} //right half d.CaveWidenRooms(100,150); d.MoveRoom(room1origin,4); d.MoveRoom(room2origin,6); var dijkstra = d.map.GetDijkstraMap(x=>d.map[x] == CellType.Wall,x=>false); //todo: among these Map dijkstra maps I have, like, 3 different ways of testing for walls. are these all correct? int distance_from_walls = 3; List<pos> central_room = d.map.PositionsWhere(x=>dijkstra[x] > distance_from_walls); int required_consecutive = 3; for(int i=0;i<ROWS;++i){ //first, check each row... for(int j=0;j<COLS;++j){ List<pos> this_row = new List<pos>(); while(j < COLS && dijkstra[i,j] > distance_from_walls){ this_row.Add(new pos(i,j)); ++j; } if(this_row.Count < required_consecutive){ foreach(pos p in this_row){ central_room.Remove(p); } } } } for(int j=0;j<COLS;++j){ //...then each column for(int i=0;i<ROWS;++i){ List<pos> this_col = new List<pos>(); while(i < ROWS && dijkstra[i,j] > distance_from_walls){ this_col.Add(new pos(i,j)); ++i; } if(this_col.Count < required_consecutive){ foreach(pos p in this_col){ central_room.Remove(p); } } } } central_room = d.map.GetFloodFillPositions(central_room.Where(x=>x.PositionsWithinDistance(1).All(y=>central_room.Contains(y))),false,x=>central_room.Contains(x)); List<pos> walls = new List<pos>(); foreach(pos p in central_room){ d.map[p] = CellType.InterestingLocation; foreach(pos neighbor in p.PositionsAtDistance(1,d.map)){ if(!central_room.Contains(neighbor)){ d.map[neighbor] = CellType.Wall; walls.Add(neighbor); } } } while(true){ List<pos> potential_doors = new List<pos>(); foreach(pos p in walls){ foreach(int dir in U.FourDirections){ if(d.map[p.PosInDir(dir)] == CellType.InterestingLocation && d.map[p.PosInDir(dir.RotateDir(true,4))].IsRoomType() && d.map[p.PosInDir(dir.RotateDir(true,4))] != CellType.InterestingLocation){ potential_doors.Add(p); break; } } } if(potential_doors.Count > 0){ pos p = potential_doors.Random(); d.map[p] = CellType.Door; List<pos> room = d.map.GetFloodFillPositions(p,true,x=>d.map[x] == CellType.InterestingLocation); foreach(pos p2 in room){ d.map[p2] = CellType.RoomInterior; } } else{ break; } } dijkstra = d.map.GetDijkstraMap(x=>d.map[x] == CellType.Wall,x=>false); int num_chests = 0; d.ForEachRoom(list=>{ if(central_room.Contains(list[0])){ if(num_chests++ < 2){ d[list.Random()] = CellType.Chest; } return true; } List<pos> room = list.Where(x=>dijkstra[x] > 1); int start_r = room.WhereLeast(x=>x.row)[0].row; int end_r = room.WhereGreatest(x=>x.row)[0].row; int start_c = room.WhereLeast(x=>x.col)[0].col; int end_c = room.WhereGreatest(x=>x.col)[0].col; List<List<pos>> offsets = new List<List<pos>>(); for(int i=0;i<4;++i){ offsets.Add(new List<pos>()); } for(int i=start_r;i<=end_r;i+=2){ for(int j=start_c;j<=end_c;j+=2){ if(room.Contains(new pos(i,j))){ offsets[0].Add(new pos(i,j)); } if(i+1 <= end_r && room.Contains(new pos(i+1,j))){ offsets[1].Add(new pos(i+1,j)); } if(j+1 <= end_c && room.Contains(new pos(i,j+1))){ offsets[2].Add(new pos(i,j+1)); } if(i+1 <= end_r && j+1 <= end_c && room.Contains(new pos(i+1,j+1))){ offsets[3].Add(new pos(i+1,j+1)); } } } List<pos> tombstones = offsets.WhereGreatest(x=>x.Count).RandomOrDefault(); if(tombstones != null){ foreach(pos p in tombstones){ d.map[p] = CellType.Tombstone; } } return true; }); for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ if(d[i,j] == CellType.Door){ pos p = new pos(i,j); List<pos> potential_statues = p.PositionsAtDistance(1,d.map).Where(x=>!d[x].IsWall() && !central_room.Contains(x) && p.DirectionOf(x) % 2 != 0 && !x.PositionsAtDistance(1,d.map).Any(y=>d[y].Is(CellType.Tombstone))); if(potential_statues.Count == 2){ d[potential_statues[0]] = CellType.Statue; d[potential_statues[1]] = CellType.Statue; } } } } List<pos> room_one = null; List<pos> room_two = null; for(int j=0;j<COLS && room_one == null;++j){ for(int i=0;i<ROWS;++i){ if(d[i,j] != CellType.Wall){ room_one = d.map.GetFloodFillPositions(new pos(i,j),false,x=>!d[x].IsWall()); break; } } } for(int j=COLS-1;j>=0 && room_two == null;--j){ for(int i=0;i<ROWS;++i){ if(d[i,j] != CellType.Wall){ room_two = d.map.GetFloodFillPositions(new pos(i,j),false,x=>!d[x].IsWall()); break; } } } if(room_one.WhereGreatest(x=>x.col).Random().DistanceFrom(room_two.WhereLeast(x=>x.col).Random()) < 12){ d.Clear(); continue; } Dungeon d2 = new Dungeon(ROWS,COLS); int tries = 0; while(tries < 10){ d2.CreateBasicMap(); d2.ConnectDiagonals(); for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ if(d[i,j] != CellType.Wall){ pos p = new pos(i,j); foreach(pos neighbor in p.PositionsAtDistance(1,d2.map)){ d2[neighbor] = CellType.Wall; } } } } d2.RemoveUnconnectedAreas(); List<pos> room_one_walls = new List<pos>(); List<pos> room_two_walls = new List<pos>(); for(int i=0;i<ROWS;++i){ for(int j=COLS-1;j>=0;--j){ pos p = new pos(i,j); if(room_one.Contains(p)){ room_one_walls.Add(p); break; } } for(int j=0;j<COLS;++j){ pos p = new pos(i,j); if(room_two.Contains(p)){ room_two_walls.Add(p); break; } } } List<pos> room_one_valid_connections = new List<pos>(); List<pos> room_two_valid_connections = new List<pos>(); foreach(pos p in room_one_walls){ pos next = p.PosInDir(6); while(BoundsCheck(next) && p.DistanceFrom(next) < 7){ if(d2[next] != CellType.Wall){ room_one_valid_connections.Add(p.PosInDir(6)); break; } next = next.PosInDir(6); } } foreach(pos p in room_two_walls){ pos next = p.PosInDir(4); while(BoundsCheck(next) && p.DistanceFrom(next) < 7){ if(d2[next] != CellType.Wall){ room_two_valid_connections.Add(p.PosInDir(4)); break; } next = next.PosInDir(4); } } if(room_one_valid_connections.Count > 0 && room_two_valid_connections.Count > 0){ pos one = room_one_valid_connections.Random(); while(true){ if(d2[one] == CellType.Wall){ d2[one] = CellType.CorridorHorizontal; } else{ break; } one = one.PosInDir(6); } pos two = room_two_valid_connections.Random(); while(true){ if(d2[two] == CellType.Wall){ d2[two] = CellType.CorridorHorizontal; } else{ break; } two = two.PosInDir(4); } break; } else{ d2.Clear(); } ++tries; } if(tries == 10){ d.Clear(); continue; } for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ if(d2[i,j] != CellType.Wall){ d[i,j] = d2[i,j]; } } } //d.CaveWidenRooms(100,20); //d.MakeCavesMoreRectangular(4); //d.RemoveDeadEndCorridors(); //d.MakeCavesMoreRectangular(1 + num++ / 10); //d.Clear(); //continue; d.ConnectDiagonals(); d.RemoveUnconnectedAreas(); d.RemoveDeadEndCorridors(); d.MarkInterestingLocations(); d.RemoveUnconnectedAreas(); if(d.NumberOfFloors() < 340 || d.HasLargeUnusedSpaces(350)){ d.Clear(); } else{ for(int i=0;i<ROWS;++i){ for(int j=0;j<COLS;++j){ result[i,j] = d.map[i,j]; } } return result; } } } } return null; }