// pixel types: 
 //    [0] = wall
 //    [1] = floor
 ///   [2] = door
 // custom params:
 //    nLevels = max levels of subdivision
 //    corridorWidth = top-level corridor width; drops by 1 at each
 //       level below til it reaches 1
 public override List<MapRoom> Run(int[][] map, MapRectangle fillRegion,
    List<MapRoom> roomsToInclude)
 {
     bool debug = false;
     bool[][] pixelIsProtected = BuildProtectedMap(roomsToInclude,
        map.Length, map[0].Length);
     for (int i = 0; i < fillRegion.w; i++)
     {
         for (int j = 0; j < fillRegion.h; j++)
         {
             if (!pixelIsProtected[i + fillRegion.x][j + fillRegion.y])
             {
                 map[i + fillRegion.x][j + fillRegion.y] = pixelTypes[1];
             }
         }
     }
     List<MapRoom> rooms = BSPBlock(nLevels, corridorWidth, NextRandom(0, 2) == 1,
        pixelIsProtected, map, fillRegion);
     if (debug)
     {
         Console.WriteLine("Fill region " + fillRegion);
     }
     foreach (MapRoom room in rooms)
     {
         bool[] sideOk = new bool[] {true, true, true, true};
         int nSidesOk = 4;
         if (debug)
         {
             Console.WriteLine("Room at " + room.bounds);
         }
         if (room.bounds.x == fillRegion.x)
         {
             if (debug)
             {
                 Console.WriteLine("  W wall external");
             }
             sideOk[3] = false;
             nSidesOk--;
         }
         if (room.bounds.y == fillRegion.y)
         {
             if (debug)
             {
                 Console.WriteLine("  N wall external");
             }
             sideOk[0] = false;
             nSidesOk--;
         }
         if (room.bounds.x2 == fillRegion.x2)
         {
             if (debug)
             {
                 Console.WriteLine("  E wall external");
             }
             sideOk[1] = false;
             nSidesOk--;
         }
         if (room.bounds.y2 == fillRegion.y2)
         {
             if (debug)
             {
                 Console.WriteLine("  S wall external");
             }
             sideOk[2] = false;
             nSidesOk--;
         }
         if (debug)
         {
             Console.WriteLine("  # doorable sides = " + nSidesOk);
         }
         if (nSidesOk > 0)
         {
             int sideOffset = NextRandom(0, nSidesOk);
             int side = 0;
             while (!sideOk[side] || sideOffset > 0)
             {
                if (sideOk[side]) sideOffset--;
                side++;
             }
             int offset = NextRandom(2, (((side % 2) == 0) ?
                room.bounds.w : room.bounds.h) - 2);
             if (debug)
             {
                 Console.WriteLine("  door in side " + side + " offset " + offset);
             }
             MapRoomDoor door = new MapRoomDoor(side, offset, room);
             room.doors.Add(door);
             map[door.x][door.y] = pixelTypes[2];
             if (debug)
             {
                 Console.WriteLine("  door at " + door.x + ", " + door.y);
             }
         }
     }
     return rooms;
 }
        // pixel types:
        //    [0] = wall
        //    [1] = floor
        ///   [2] = door
        // custom params:
        //    nLevels = max levels of subdivision
        //    corridorWidth = top-level corridor width; drops by 1 at each
        //       level below til it reaches 1
        public override List <MapRoom> Run(int[][] map, MapRectangle fillRegion,
                                           List <MapRoom> roomsToInclude)
        {
            bool debug = false;

            bool[][] pixelIsProtected = BuildProtectedMap(roomsToInclude,
                                                          map.Length, map[0].Length);
            for (int i = 0; i < fillRegion.w; i++)
            {
                for (int j = 0; j < fillRegion.h; j++)
                {
                    if (!pixelIsProtected[i + fillRegion.x][j + fillRegion.y])
                    {
                        map[i + fillRegion.x][j + fillRegion.y] = pixelTypes[1];
                    }
                }
            }
            List <MapRoom> rooms = BSPBlock(nLevels, corridorWidth, NextRandom(0, 2) == 1,
                                            pixelIsProtected, map, fillRegion);

            if (debug)
            {
                Console.WriteLine("Fill region " + fillRegion);
            }
            foreach (MapRoom room in rooms)
            {
                bool[] sideOk   = new bool[] { true, true, true, true };
                int    nSidesOk = 4;
                if (debug)
                {
                    Console.WriteLine("Room at " + room.bounds);
                }
                if (room.bounds.x == fillRegion.x)
                {
                    if (debug)
                    {
                        Console.WriteLine("  W wall external");
                    }
                    sideOk[3] = false;
                    nSidesOk--;
                }
                if (room.bounds.y == fillRegion.y)
                {
                    if (debug)
                    {
                        Console.WriteLine("  N wall external");
                    }
                    sideOk[0] = false;
                    nSidesOk--;
                }
                if (room.bounds.x2 == fillRegion.x2)
                {
                    if (debug)
                    {
                        Console.WriteLine("  E wall external");
                    }
                    sideOk[1] = false;
                    nSidesOk--;
                }
                if (room.bounds.y2 == fillRegion.y2)
                {
                    if (debug)
                    {
                        Console.WriteLine("  S wall external");
                    }
                    sideOk[2] = false;
                    nSidesOk--;
                }
                if (debug)
                {
                    Console.WriteLine("  # doorable sides = " + nSidesOk);
                }
                if (nSidesOk > 0)
                {
                    int sideOffset = NextRandom(0, nSidesOk);
                    int side       = 0;
                    while (!sideOk[side] || sideOffset > 0)
                    {
                        if (sideOk[side])
                        {
                            sideOffset--;
                        }
                        side++;
                    }
                    int offset = NextRandom(2, (((side % 2) == 0) ?
                                                room.bounds.w : room.bounds.h) - 2);
                    if (debug)
                    {
                        Console.WriteLine("  door in side " + side + " offset " + offset);
                    }
                    MapRoomDoor door = new MapRoomDoor(side, offset, room);
                    room.doors.Add(door);
                    map[door.x][door.y] = pixelTypes[2];
                    if (debug)
                    {
                        Console.WriteLine("  door at " + door.x + ", " + door.y);
                    }
                }
            }
            return(rooms);
        }