예제 #1
0
 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;
     });
 }
예제 #2
0
 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];
         }
     }
 }
예제 #3
0
 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;
 }
예제 #4
0
 /*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];
         }
     }
 }