public void AlterRooms(int no_change_freq,int add_pillars_freq,int cross_room_freq,int cave_widen_freq,int cave_fill_freq) { List<int> modification = new List<int>(); for(int i=0;i<no_change_freq;++i){ modification.Add(0); } for(int i=0;i<add_pillars_freq;++i){ modification.Add(1); } for(int i=0;i<cross_room_freq;++i){ modification.Add(2); } for(int i=0;i<cave_widen_freq;++i){ modification.Add(3); } for(int i=0;i<cave_fill_freq;++i){ modification.Add(4); } if(modification.Count == 0){ return; } ForEachRectangularRoom((start_r,start_c,end_r,end_c) => { int mod = modification.Random(); switch(mod){ case 0: return true; case 1: { int height = end_r - start_r + 1; int width = end_c - start_c + 1; if(height > 3 || width > 3){ List<PillarArrangement> layouts = new List<PillarArrangement>(); if(height % 2 == 1 && width % 2 == 1){ layouts.Add(PillarArrangement.Single); } if((height % 2 == 1 || width % 2 == 1) && height != 4 && width != 4){ layouts.Add(PillarArrangement.Row); } if(height >= 5 && width >= 5){ layouts.Add(PillarArrangement.Corners); } if(height > 2 && width > 2 && height != 4 && width != 4){ layouts.Add(PillarArrangement.Full); } if((width % 2 == 1 && width >= 5) || (height % 2 == 1 && height >= 5)){ layouts.Add(PillarArrangement.StatueEdges); } if(layouts.Count == 0 || CoinFlip()){ //otherwise they're too common layouts.Add(PillarArrangement.StatueCorners); } if(layouts.Count > 0){ CellType pillar = CellType.Pillar; switch(layouts.Random()){ case PillarArrangement.Single: map[(start_r + end_r)/2,(start_c + end_c)/2] = pillar; break; case PillarArrangement.Row: { bool vertical; if(width % 2 == 1 && height % 2 == 0){ vertical = true; } else{ if(height % 2 == 1 && width % 2 == 0){ vertical = false; } else{ vertical = CoinFlip(); } } if(vertical){ if(height % 2 == 1){ for(int i=start_r+1;i<=end_r-1;i+=2){ map[i,(start_c + end_c)/2] = pillar; } } else{ int offset = 0; if(height % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_r+1+offset;i<(start_r + end_r)/2;i+=2){ map[i,(start_c + end_c)/2] = pillar; } for(int i=end_r-1-offset;i>(start_r + end_r)/2+1;i-=2){ map[i,(start_c + end_c)/2] = pillar; } } } else{ if(width % 2 == 1){ for(int i=start_c+1;i<=end_c-1;i+=2){ map[(start_r + end_r)/2,i] = pillar; } } else{ int offset = 0; if(width % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_c+1+offset;i<(start_c + end_c)/2;i+=2){ map[(start_r + end_r)/2,i] = pillar; } for(int i=end_c-1-offset;i>(start_c + end_c)/2+1;i-=2){ map[(start_r + end_r)/2,i] = pillar; } } } break; } case PillarArrangement.Corners: { int v_offset = 0; int h_offset = 0; if(height % 4 == 0){ v_offset = Roll(2) - 1; } if(width % 4 == 0){ h_offset = Roll(2) - 1; } map[start_r + 1 + v_offset,start_c + 1 + h_offset] = pillar; map[start_r + 1 + v_offset,end_c - 1 - h_offset] = pillar; map[end_r - 1 - v_offset,start_c + 1 + h_offset] = pillar; map[end_r - 1 - v_offset,end_c - 1 - h_offset] = pillar; break; } case PillarArrangement.Full: { int v_offset = 0; int h_offset = 0; if(height % 4 == 0){ v_offset = Roll(2) - 1; } if(width % 4 == 0){ h_offset = Roll(2) - 1; } int half_r = (start_r + end_r)/2; int half_c = (start_c + end_c)/2; int half_r_offset = (start_r + end_r + 1)/2; int half_c_offset = (start_c + end_c + 1)/2; for(int i=start_r+1+v_offset;i<half_r;i+=2){ for(int j=start_c+1+h_offset;j<half_c;j+=2){ map[i,j] = pillar; } } for(int i=start_r+1+v_offset;i<half_r;i+=2){ for(int j=end_c-1-h_offset;j>half_c_offset;j-=2){ map[i,j] = pillar; } } for(int i=end_r-1-v_offset;i>half_r_offset;i-=2){ for(int j=start_c+1+h_offset;j<half_c;j+=2){ map[i,j] = pillar; } } for(int i=end_r-1-v_offset;i>half_r_offset;i-=2){ for(int j=end_c-1-h_offset;j>half_c_offset;j-=2){ map[i,j] = pillar; } } if((width+1) % 4 == 0){ if(height % 2 == 1){ for(int i=start_r+1;i<=end_r-1;i+=2){ map[i,half_c] = pillar; } } else{ int offset = 0; if(height % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_r+1+offset;i<half_r;i+=2){ map[i,half_c] = pillar; } for(int i=end_r-1-offset;i>half_r_offset;i-=2){ map[i,half_c] = pillar; } } } if((height+1) % 4 == 0){ if(width % 2 == 1){ for(int i=start_c+1;i<=end_c-1;i+=2){ map[half_r,i] = pillar; } } else{ int offset = 0; if(width % 4 == 0){ offset = Roll(2) - 1; } for(int i=start_c+1+offset;i<half_c;i+=2){ map[half_r,i] = pillar; } for(int i=end_c-1-offset;i>half_c_offset;i-=2){ map[half_r,i] = pillar; } } } break; } case PillarArrangement.StatueCorners: map[start_r,start_c] = CellType.Statue; map[start_r,end_c] = CellType.Statue; map[end_r,start_c] = CellType.Statue; map[end_r,end_c] = CellType.Statue; break; case PillarArrangement.StatueEdges: { map[start_r,start_c] = CellType.Statue; map[start_r,end_c] = CellType.Statue; map[end_r,start_c] = CellType.Statue; map[end_r,end_c] = CellType.Statue; if(width % 2 == 1 && width > 3){ int half_c = (start_c + end_c)/2; int corridors = new pos(start_r,half_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[start_r,half_c] = CellType.Statue; } corridors = new pos(end_r,half_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[end_r,half_c] = CellType.Statue; } } if(height % 2 == 1 && height > 3){ int half_r = (start_r + end_r)/2; int corridors = new pos(half_r,start_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[half_r,start_c] = CellType.Statue; } corridors = new pos(half_r,end_c).CardinalAdjacentPositions().Where(x => BoundsCheck(x) && map[x].IsCorridorType()).Count; if(corridors == 0){ map[half_r,end_c] = CellType.Statue; } } break; } default: break; } } } return true; } case 2: { int height = end_r - start_r + 1; int width = end_c - start_c + 1; if(height < 4 || width < 4){ //nothing happens until we get above 4x4 return true; } int rows_to_convert = Roll((height/2)-1); int cols_to_convert = Roll((width/2)-1); if(rows_to_convert == 1 && cols_to_convert == 1){ return true; } List<pos> blocked = new List<pos>(); for(int i=start_r;i<=end_r;++i){ for(int j=start_c;j<=end_c;++j){ if((i < start_r + rows_to_convert || i > end_r - rows_to_convert) && (j < start_c + cols_to_convert || j > end_c - cols_to_convert)){ pos p = new pos(i,j); foreach(pos neighbor in p.CardinalAdjacentPositions()){ if(map[neighbor].IsCorridorType()){ blocked.Add(p); } } map[i,j] = CellType.Wall; } } } blocked.Randomize(); foreach(pos p in blocked){ bool done = false; foreach(pos neighbor in p.CardinalAdjacentPositions()){ if(map[neighbor].IsRoomType()){ map[p] = CellType.RoomInterior; done = true; break; } } if(!done){ List<int> valid_dirs = new List<int>(); foreach(int dir in U.FourDirections){ pos next = p.PosInDir(dir); while(next.row >= start_r && next.row <= end_r && next.col >= start_c && next.col <= end_c){ if(next.CardinalAdjacentPositions().Any(x=>map[x].IsRoomType())){ valid_dirs.Add(dir); break; } next = next.PosInDir(dir); } } int valid_dir = valid_dirs.RandomOrDefault(); pos next2 = p.PosInDir(valid_dir); List<pos> new_corridor = new List<pos>{p}; while(true){ new_corridor.Add(next2); if(next2.CardinalAdjacentPositions().Any(x=>map[x].IsRoomType())){ break; } next2 = next2.PosInDir(valid_dir); } foreach(pos p2 in new_corridor){ map[p2] = CellType.RoomInterior; } } } return true; } case 3: { List<pos> list = map.PositionsWhere(x=>x.row >= start_r && x.row <= end_r && x.col >= start_c && x.col <= end_c); PosArray<CellType> old_map = new PosArray<CellType>(H,W); foreach(pos p in list){ old_map[p] = map[p]; map[p] = CellType.Wall; } PosArray<bool> rock = new PosArray<bool>(H,W); for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); rock[p] = true; if(BoundsCheck(i,j,false)){ foreach(pos neighbor in p.AdjacentPositionsClockwise()){ if(map[neighbor] != CellType.Wall){ rock[p] = false; break; } } } } } foreach(pos p in list){ map[p] = CellType.RoomInterior; //todo: might this step be extraneous? } List<pos> frontier = new List<pos>(); { PosArray<bool> in_list = new PosArray<bool>(H,W); foreach(pos p in list){ in_list[p] = true; } for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); if(in_list[p]){ foreach(pos neighbor in p.PositionsAtDistance(1,in_list)){ if(!in_list[neighbor]){ frontier.Add(p); break; } } } } } } int fail_counter = 0; int num_added = 0; bool finished = false; while(!finished){ if(frontier.Count == 0 || num_added >= 30){ //todo check this value finished = true; break; } pos f = frontier.RemoveRandom(); foreach(pos neighbor in f.CardinalAdjacentPositions()){ if(!BoundsCheck(neighbor,false) || !rock[neighbor.row,neighbor.col]){ ++fail_counter; //this might now be unreachable if(!BoundsCheck(neighbor,false)){ fail_counter += 25; //fail quicker when against the edge of the map to prevent ugliness } //however, this doesn't actually fail as quickly as it should - i've overlooked something. if(fail_counter >= 50){ finished = true; break; } } else{ if(map[neighbor] != CellType.RoomInterior){ map[neighbor] = CellType.RoomInterior; ++num_added; bool add_neighbor = true; foreach(pos n2 in neighbor.CardinalAdjacentPositions()){ if(!BoundsCheck(n2,false) || !rock[n2.row,n2.col]){ add_neighbor = false; ++fail_counter; //this might now be unreachable if(!BoundsCheck(neighbor,false)){ fail_counter += 25; //fail quicker when against the edge of the map to prevent ugliness } //however, this doesn't actually fail as quickly as it should - i've overlooked something. if(fail_counter >= 50){ finished = true; } break; } } if(finished){ break; } if(add_neighbor){ frontier.Add(neighbor); } } } } } foreach(pos p in list){ map[p] = old_map[p]; } return true; } case 4: { List<pos> list = map.PositionsWhere(x=>x.row >= start_r && x.row <= end_r && x.col >= start_c && x.col <= end_c); Dungeon room = new Dungeon((end_r - start_r) + 3,(end_c - start_c) + 3); //includes borders List<pos> map_exits = list.Where(x=>x.CardinalAdjacentPositions().Any(y=>map[y].IsCorridorType())); //grab the positions from list that have any adjacent corridor-type cells if(map_exits.Count < 2){ return true; } List<pos> room_exits = new List<pos>(); foreach(pos exit in map_exits){ room_exits.Add(new pos(exit.row-start_r+1,exit.col-start_c+1)); } int tries = 0; while(true){ room.FillWithRandomWalls(25); room.ApplyCellularAutomataXYRule(3); room.ConnectDiagonals(); room.RemoveDeadEndCorridors(); room.RemoveUnconnectedAreas(); bool exits_open = true; foreach(pos p in room_exits){ if(!room[p].IsPassable()){ exits_open = false; } } if(exits_open){ for(int i=start_r;i<=end_r;++i){ for(int j=start_c;j<=end_c;++j){ if(list.Contains(new pos(i,j))){ map[i,j] = room[(i-start_r)+1,(j-start_c)+1]; } } } break; } ++tries; if(tries > 50){ return false; } } return true; } default: break; } return true; }); }
public void CaveWidenRooms(int percent_chance_per_room,int number_of_tiles_to_add) { List<List<pos>> roomlist = new List<List<pos>>(); ForEachRoom(list=>{ if(PercentChance(percent_chance_per_room)){ roomlist.Add(list); } return true; }); while(roomlist.Count > 0){ List<pos> list = roomlist.RemoveRandom(); PosArray<CellType> old_map = new PosArray<CellType>(H,W); foreach(pos p in list){ old_map[p] = map[p]; map[p] = CellType.Wall; } PosArray<bool> rock = new PosArray<bool>(H,W); for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); rock[p] = true; if(BoundsCheck(i,j,false)){ foreach(pos neighbor in p.AdjacentPositionsClockwise()){ if(map[neighbor] != CellType.Wall){ rock[p] = false; break; } } } } } foreach(pos p in list){ map[p] = CellType.RoomInterior; //todo: might this step be extraneous? } List<pos> frontier = new List<pos>(); { PosArray<bool> in_list = new PosArray<bool>(H,W); foreach(pos p in list){ in_list[p] = true; } for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); if(in_list[p]){ foreach(pos neighbor in p.PositionsAtDistance(1,in_list)){ if(!in_list[neighbor]){ frontier.Add(p); break; } } } } } } int fail_counter = 0; int num_added = 0; bool finished = false; while(!finished){ if(frontier.Count == 0 || num_added >= number_of_tiles_to_add){ finished = true; break; } pos f = frontier.RemoveRandom(); foreach(pos neighbor in f.CardinalAdjacentPositions()){ if(!BoundsCheck(neighbor,false) || !rock[neighbor.row,neighbor.col]){ ++fail_counter; //this might now be unreachable if(!BoundsCheck(neighbor,false)){ fail_counter += 25; //fail quicker when against the edge of the map to prevent ugliness } //however, this doesn't actually fail as quickly as it should - i've overlooked something. if(fail_counter >= 50){ finished = true; break; } } else{ if(map[neighbor] != CellType.RoomInterior){ map[neighbor] = CellType.RoomInterior; ++num_added; bool add_neighbor = true; foreach(pos n2 in neighbor.CardinalAdjacentPositions()){ if(!BoundsCheck(n2,false) || !rock[n2.row,n2.col]){ add_neighbor = false; ++fail_counter; //this might now be unreachable if(!BoundsCheck(neighbor,false)){ fail_counter += 25; //fail quicker when against the edge of the map to prevent ugliness } //however, this doesn't actually fail as quickly as it should - i've overlooked something. if(fail_counter >= 50){ finished = true; } break; } } if(finished){ break; } if(add_neighbor){ frontier.Add(neighbor); } } } } } foreach(pos p in list){ map[p] = old_map[p]; } } }
public bool IsLegal(pos p) { switch(map[p]){ //case CellType.RoomInterior: case CellType.Pillar: case CellType.RoomFeature1: case CellType.RoomFeature2: case CellType.RoomFeature3: case CellType.InterestingLocation: foreach(pos neighbor in p.AdjacentPositionsClockwise()){ if(!map[neighbor].IsRoomType()){ return false; } } break; case CellType.RoomEdge: { int roomdir = 0; foreach(int dir in FourDirections){ pos neighbor = p.PosInDir(dir); if(BoundsCheck(neighbor) && !map[neighbor].IsRoomType()){ roomdir = dir.RotateDir(true,4); break; } } if(roomdir == 0){ return false; //no room found, error - disable this if you want tiny rooms with h/w of 2 /*char[] rotated = new char[8]; for(int i=0;i<8;++i){ rotated[i] = Map(PosInDir(r,c,RotateDir(8,true,i))); } int successive_corridors = 0; if(IsCorridor(rotated[7])){ successive_corridors++; } for(int i=0;i<8;++i){ if(IsCorridor(rotated[i])){ successive_corridors++; } else{ successive_corridors = 0; } if(successive_corridors == 2){ return false; } } int successive_room_tiles = 0; if(IsRoom(rotated[5])){ successive_room_tiles++; } if(IsRoom(rotated[6])){ successive_room_tiles++; } else{ successive_room_tiles = 0; } if(IsRoom(rotated[7])){ successive_room_tiles++; } else{ successive_room_tiles = 0; } for(int i=0;i<8;++i){ if(IsRoom(rotated[i])){ successive_room_tiles++; } else{ successive_room_tiles = 0; } if(successive_room_tiles == 5){ return true; } }*/ } else{ List<pos> rotated = p.AdjacentPositionsClockwise(roomdir); foreach(int dir in new int[]{0,1,7}){ if(!map[rotated[dir]].IsRoomType()){ return false; } } foreach(int dir in new int[]{2,6}){ if(!map[rotated[dir]].IsRoomEdgeType()){ return false; } } if((map[rotated[4]].IsWall() || (map[rotated[3]].IsWall() && map[rotated[5]].IsWall())) == false){ return false; } } break; } case CellType.RoomCorner: { int roomdir = 0; foreach(int dir in DiagonalDirections){ pos neighbor = p.PosInDir(dir); if(BoundsCheck(neighbor) && map[neighbor].IsRoomInteriorType()){ roomdir = dir; break; } } if(roomdir == 0){ return false; //no room found, error } List<pos> rotated = p.AdjacentPositionsClockwise(roomdir); foreach(int dir in new int[]{1,7}){ if(!map[rotated[dir]].IsRoomEdgeType()){ return false; } } if(AllowAllCornerConnections){ if(!map[rotated[2]].IsWall() && !map[rotated[3]].IsWall()){ return false; } if(!map[rotated[6]].IsWall() && !map[rotated[5]].IsWall()){ return false; } if(!map[rotated[4]].IsWall()){ //if the corner isn't a wall... if(!map[rotated[3]].IsWall() && !map[rotated[5]].IsWall()){ return false; } if(map[rotated[3]].IsWall() && map[rotated[5]].IsWall()){ //...reject it if there's not exactly 1 adjacent corridor return false; } } } else{ foreach(int dir in new int[]{3,4,5}){ if(!map[rotated[dir]].IsWall()){ return false; } } } break; } case CellType.RoomInteriorCorner: { List<int> wall_dirs = new List<int>(); List<int> edge_dirs = new List<int>(); foreach(int dir in DiagonalDirections){ pos neighbor = p.PosInDir(dir); if(BoundsCheck(neighbor) && map[neighbor].IsWall()){ wall_dirs.Add(dir); edge_dirs.AddUnique(dir.RotateDir(true)); edge_dirs.AddUnique(dir.RotateDir(false)); } } if(wall_dirs.Count == 0){ return false; //no room found, error } foreach(int dir in EightDirections){ if(wall_dirs.Contains(dir)){ if(!map[p.PosInDir(dir)].IsWall()){ return false; } } else{ if(edge_dirs.Contains(dir)){ if(!map[p.PosInDir(dir)].IsRoomEdgeType()){ return false; } } else{ if(!map[p.PosInDir(dir)].IsRoomType()){ return false; } } } } break; } case CellType.CorridorHorizontal: foreach(int dir in new int[]{2,8}){ pos next = p; for(int i=1;i<=MinimumSpaceBetweenCorridors;++i){ next = next.PosInDir(dir); if(BoundsCheck(next) && map[next] == CellType.CorridorHorizontal){ return false; } } } break; case CellType.CorridorVertical: foreach(int dir in new int[]{4,6}){ pos next = p; for(int i=1;i<=MinimumSpaceBetweenCorridors;++i){ next = next.PosInDir(dir); if(BoundsCheck(next) && map[next] == CellType.CorridorVertical){ return false; } } } break; case CellType.CorridorIntersection: if(p.ConsecutiveAdjacent(x => map[x].IsPassable()) >= 3){ return false; } break; case CellType.Door: { int dir_of_wall = 0; if(map[p.PosInDir(8)].IsWall()){ dir_of_wall = 8; } else{ dir_of_wall = 4; } if(!map[p.PosInDir(dir_of_wall)].IsWall() || !map[p.PosInDir(dir_of_wall.RotateDir(true,4))].IsWall() || map[p.PosInDir(dir_of_wall.RotateDir(true,2))].IsWall() || map[p.PosInDir(dir_of_wall.RotateDir(false,2))].IsWall()){ return false; //needs 2 walls on opposite sides, 2 nonwalls on opposite sides } break; } } return true; }
/*public void FillUsingFlowDisplacedRockLayers(){ while(true){ double layer_width = (double)(Roll(3)+5); //was Roll(3) + 5, heh double layer_angle = (double)(Roll(360) - 1); double center_row = ((double)(H-1)) / 2.0f; double center_col = ((double)(W-1)) / 2.0f; int[,] row_displacement = GetDiamondSquarePlasmaFractal(H,W); int[,] col_displacement = GetDiamondSquarePlasmaFractal(H,W); int[,] layer; for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ row_displacement[i,j] /= 2; //was * 1 col_displacement[i,j] /= 2; } } layer = new int[H,W]; for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ int row = i + row_displacement[i,j]; int col = j + col_displacement[i,j]; double opp = Math.Abs(center_row - (double)row); double adj = Math.Abs(center_col - (double)col); double hyp = Math.Sqrt(opp*opp + adj*adj); double point_angle_radians = Math.Asin(opp/hyp); double point_angle = point_angle_radians * 180.0 / Math.PI; if(row < center_row){ if(col < center_col){ point_angle += 180.0; } else{ point_angle = 360.0 - point_angle; } } else{ if(col < center_col){ point_angle = 180.0 - point_angle; } } double angle_difference = point_angle - layer_angle; double angle_difference_radians = angle_difference * Math.PI / 180.0; double distance_from_line = Math.Sin(angle_difference_radians) * hyp; for(int layer_num = 1;;++layer_num){ if(distance_from_line > layer_width * (layer_num-1) && distance_from_line <= layer_width * layer_num){ layer[i,j] = layer_num; break; } if(distance_from_line < layer_width * -(layer_num-1) && distance_from_line >= layer_width * -layer_num){ layer[i,j] = -layer_num; break; } } } } int[,] rd2 = new int[H,W]; int[,] cd2 = new int[H,W]; for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ int k = (Math.Abs(layer[i,j])) % 14; ++k; //now 1-14 if(layer[i,j] < 0){ k = 15 - k; } if(k == 7){ k = 15; } Screen.Write(i+2,j+3,'#',(ConsoleColor)k); int new_row = i - row_displacement[i,j]; int new_col = j - col_displacement[i,j]; if(ArrayBoundsCheck(rd2,new_row,j)){ rd2[i,j] = row_displacement[new_row,j]; } else{ rd2[i,j] = 0; } if(ArrayBoundsCheck(cd2,i,new_col)){ cd2[i,j] = col_displacement[i,new_col]; } else{ cd2[i,j] = 0; } if(ArrayBoundsCheck(rd2,i,new_col)){ rd2[i,j] = row_displacement[i,new_col]; } else{ rd2[i,j] = 0; } if(ArrayBoundsCheck(cd2,new_row,j)){ cd2[i,j] = col_displacement[new_row,j]; } else{ cd2[i,j] = 0; } if(ArrayBoundsCheck(rd2,new_row,new_col)){ rd2[i,j] = row_displacement[new_row,new_col]; cd2[i,j] = col_displacement[new_row,new_col]; } else{ rd2[i,j] = 0; cd2[i,j] = 0; } } } row_displacement = rd2; col_displacement = cd2; Console.ReadKey(true); } Environment.Exit(0); }*/ public void ApplyCellularAutomataXYRule(int target_number_of_walls) { CellType[,] result = new CellType[H,W]; for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ pos p = new pos(i,j); int num_walls = p.AdjacentPositionsClockwise().Where(x => !BoundsCheck(x,true) || map[x].IsWall()).Count; if(map[p].IsWall()){ ++num_walls; } if(num_walls >= target_number_of_walls){ result[i,j] = CellType.Wall; } else{ result[i,j] = CellType.RoomInterior; } } } for(int i=0;i<H;++i){ for(int j=0;j<W;++j){ map[i,j] = result[i,j]; } } }