private bool RegionOverlapsRoom(int x, int y, int h, int w,
    MapRoom room)
 {
     if (room.bounds.x + room.bounds.w < x) return false;
     if (x + w < room.bounds.x) return false;
     if (room.bounds.y + room.bounds.h < y) return false;
     if (y + h < room.bounds.y) return false;
     return true;
 }
Beispiel #2
0
 private bool RegionOverlapsRoom(int x, int y, int h, int w,
                                 MapRoom room)
 {
     if (room.bounds.x + room.bounds.w < x)
     {
         return(false);
     }
     if (x + w < room.bounds.x)
     {
         return(false);
     }
     if (room.bounds.y + room.bounds.h < y)
     {
         return(false);
     }
     if (y + h < room.bounds.y)
     {
         return(false);
     }
     return(true);
 }
Beispiel #3
0
        // pixel types:
        //    [0] = wall
        //    [1] = floor
        //    [2] = door
        //    >2  = other sorts of wall
        //    not on list = impenetrable
        // custom params:
        //    none; skips rooms with doNotConnect set to true
        public override List <MapRoom> Run(int[][] map, MapRectangle fillRegion,
                                           List <MapRoom> roomsToInclude)
        {
            bool debug = false;

            if (debug)
            {
                Console.WriteLine("DCMG start, " + roomsToInclude.Count +
                                  " rooms");
            }
            int corridorPixelType = 1234567;

            // pass 1 : get all the rooms connected to each other

            List <int> alreadyConnectedRoomIndices = new List <int>();

            for (int i = 0; (i < roomsToInclude.Count) &&
                 (alreadyConnectedRoomIndices.Count < 1); i++)
            {
                if (!roomsToInclude[i].doNotConnect)
                {
                    alreadyConnectedRoomIndices.Add(i);
                    if (debug)
                    {
                        Console.WriteLine("DCMG to connect room " + i);
                    }
                }
            }

            if (alreadyConnectedRoomIndices.Count < 1)
            {
                // none of the rooms want to be hooked up to each other
                return(roomsToInclude);
            }

            // distanceMap = -1 for impassable squares
            int[][] distanceMap = Allocate2DIntArray(fillRegion.w,
                                                     fillRegion.h);
            // fromDirectionMap = -1 for unvisited, 0 1 2 3 = from N S E W
            int[][] fromDirectionMap = Allocate2DIntArray(fillRegion.w,
                                                          fillRegion.h);
            // set true for the goal squares of a search
            bool[][] goalMap = Allocate2DBoolArray(fillRegion.w,
                                                   fillRegion.h);
            // > 0 for squares that are expensive to step into
            int[][] extraCostMap = Allocate2DIntArray(fillRegion.w,
                                                      fillRegion.h);
            if (intoPixelCostPenalty != null)
            {
                for (int i = 0; i < fillRegion.w; i++)
                {
                    for (int j = 0; j < fillRegion.h; j++)
                    {
                        int pixel = map[fillRegion.x + i][fillRegion.y + j];
                        if (pixel >= 0 && pixel < intoPixelCostPenalty.Length)
                        {
                            extraCostMap[i][j] = intoPixelCostPenalty[pixel];
                        }
                    }
                }
            }

            for (int i = alreadyConnectedRoomIndices[0] + 1;
                 i < roomsToInclude.Count; i++)
            {
                MapRoom thisRoom = roomsToInclude[i];
                if (!thisRoom.doNotConnect)
                {
                    if (debug)
                    {
                        Console.WriteLine("DCMG try to connect " + i +
                                          " to net");
                    }
                    int bestDoorIndex           = -1;
                    int bestDoorDistanceSquared = 0;
                    int bestTargetRoomIndex     = -1;
                    for (int j = 0; j < thisRoom.doors.Count; j++)
                    {
                        for (int k = 0; k < alreadyConnectedRoomIndices.Count;
                             k++)
                        {
                            int     testRoomIndex       = alreadyConnectedRoomIndices[k];
                            MapRoom r2                  = roomsToInclude[testRoomIndex];
                            int     dx                  = thisRoom.doors[j].x - r2.bounds.xCenter;
                            int     dy                  = thisRoom.doors[j].y - r2.bounds.yCenter;
                            int     testDistanceSquared = dx * dx + dy * dy;
                            if (bestTargetRoomIndex == -1 ||
                                testDistanceSquared < bestDoorDistanceSquared)
                            {
                                bestTargetRoomIndex     = testRoomIndex;
                                bestDoorIndex           = j;
                                bestDoorDistanceSquared = testDistanceSquared;
                                if (debug)
                                {
                                    Console.WriteLine("   new closest door is "
                                                      + j + " to room " + testRoomIndex +
                                                      " from room " + i);
                                }
                            }
                        }
                    }
                    if (bestDoorIndex != -1)
                    {
                        // run a BFS corridor from door bestDoor of
                        // roomsToInclude[i] to any existing corridor or
                        // any door of roomsToInclude[bestTargetRoomIndex]

                        Clear2DIntArray(fromDirectionMap, -1); // unvisited

                        // set all of the rooms interiors and walls to
                        // impassable

                        Clear2DIntArray(distanceMap, 100000000);
                        foreach (MapRoom r in roomsToInclude)
                        {
                            for (int j = 1; j < r.bounds.w - 1; j++)
                            {
                                int dx = r.bounds.x + j - fillRegion.x;
                                for (int k = 1; k < r.bounds.h - 1; k++)
                                {
                                    int dy = r.bounds.y + k - fillRegion.y;
                                    distanceMap[dx][dy] = -1;
                                }
                            }
                        }

                        // set up the goals

                        Clear2DBoolArray(goalMap);
                        MapRoom targetRoom = roomsToInclude[
                            bestTargetRoomIndex];
                        for (int j = 1; j < targetRoom.bounds.w - 1; j++)
                        {
                            for (int k = 1; k < targetRoom.bounds.h - 1; k++)
                            {
                                goalMap[j + targetRoom.bounds.x - fillRegion.x][
                                    k + targetRoom.bounds.y - fillRegion.y] =
                                    true;
                            }
                        }
                        for (int j = 0; j < targetRoom.doors.Count; j++)
                        {
                            int dx = targetRoom.doors[j].x - fillRegion.x;
                            int dy = targetRoom.doors[j].y - fillRegion.y;
                            goalMap[dx][dy]     = true;
                            distanceMap[dx][dy] = 1000000;
                        }

                        // also load the existing cooridors into the goal map
                        for (int j = 0; j < fillRegion.w; j++)
                        {
                            for (int k = 0; k < fillRegion.h; k++)
                            {
                                if (map[fillRegion.x + j][fillRegion.y + k] ==
                                    corridorPixelType)
                                {
                                    goalMap[j][k] = true;
                                }
                            }
                        }

                        bool success = ExtendBFSCorridor(goalMap, distanceMap,
                                                         extraCostMap, fromDirectionMap,
                                                         thisRoom.doors[bestDoorIndex].x - fillRegion.x,
                                                         thisRoom.doors[bestDoorIndex].y - fillRegion.y,
                                                         map, fillRegion, corridorPixelType, debug);
                        if (success)
                        {
                            alreadyConnectedRoomIndices.Add(i);
                        }
                        if (debug)
                        {
                            Console.WriteLine("   ran route from door " +
                                              bestDoorIndex + " success = " + success);
                        }
                    }
                }
            }

            // convert corridorPixelType to pixelTypes[1]

            SearchAndReplace2DIntArray(map, corridorPixelType, pixelTypes[1]);

            return(roomsToInclude);
        }
Beispiel #4
0
        // pixel types:
        //    [0] = wall
        //    [1] = floor
        //    [2] = door
        // custom params:
        //    none
        public override List <MapRoom> Run(int[][] map, MapRectangle fillRegion,
                                           List <MapRoom> roomsToInclude)
        {
            List <MapRoom> generatedRooms = new List <MapRoom>();

            // generate the rooms

            int mapArea         = map[0].Length * map.Length;
            int typicalRoomArea = (minSide + maxSide) * (minSide + maxSide) / 4;
            int nRooms          = mapArea * openPercentage / typicalRoomArea;

            for (int i = 0; i < nRooms; i++)
            {
                int  maxPlacementTries = 10;
                bool placed            = false;
                int  width             = NextRandom(minSide, maxSide + 1);
                int  height            = NextRandom(minSide, maxSide + 1);
                if (width < fillRegion.w && height < fillRegion.h)
                {
                    int x0 = 0, y0 = 0;
                    for (int j = 0; (j < maxPlacementTries) && (!placed); j++)
                    {
                        x0     = NextRandom(0, fillRegion.w - width);
                        y0     = NextRandom(0, fillRegion.h - height);
                        placed = true;
                        for (int k = 0; k < roomsToInclude.Count && placed; k++)
                        {
                            if (RegionOverlapsRoom(x0, y0, height, width,
                                                   roomsToInclude[k]))
                            {
                                placed = false;
                            }
                        }
                        for (int k = 0; k < generatedRooms.Count && placed; k++)
                        {
                            if (RegionOverlapsRoom(x0, y0, height, width,
                                                   generatedRooms[k]))
                            {
                                placed = false;
                            }
                        }
                    }
                    if (placed)
                    {
                        generatedRooms.Add(new MapRoom(new MapRectangle(
                                                           x0, y0, width, height)));
                    }
                }
            }

            // add doors to generatedRooms
            for (int i = 0; i < generatedRooms.Count; i++)
            {
                int     nDoors = NextRandom(1, maxDoorsPerRoom + 1);
                MapRoom r      = generatedRooms[i];
                for (int j = 0; j < nDoors; j++)
                {
                    int side   = NextRandom(0, 4);
                    int offset = NextRandom(1, ((side == 0 || side == 2) ?
                                                r.bounds.w : r.bounds.h) - 1);
                    r.doors.Add(new MapRoomDoor(side, offset, r));
                }
                // clean out any duplicated doors
                for (int j = r.doors.Count - 1; j > 0; j--)
                {
                    bool dupe = false;
                    for (int k = 0; k < j; k++)
                    {
                        if (r.doors[j].side == r.doors[k].side &&
                            r.doors[j].offset == r.doors[k].offset)
                        {
                            dupe = true;
                        }
                    }
                    if (dupe)
                    {
                        r.doors.RemoveAt(j);
                    }
                }
            }

            // now set the map tiles for doors, walls, and floors
            for (int i = 0; i < generatedRooms.Count; i++)
            {
                MapRoom r = generatedRooms[i];
                for (int j = r.bounds.x; j < r.bounds.x + r.bounds.w; j++)
                {
                    for (int k = r.bounds.y; k < r.bounds.y + r.bounds.h; k++)
                    {
                        bool isBorder = (j == r.bounds.x) ||
                                        (j == r.bounds.x + r.bounds.w - 1) ||
                                        (k == r.bounds.y) ||
                                        (k == r.bounds.y + r.bounds.h - 1);
                        map[j][k] = pixelTypes[isBorder ? 0 : 1];
                    }
                }
                for (int j = 0; j < r.doors.Count; j++)
                {
                    int x = r.bounds.x, y = r.bounds.y;
                    switch (r.doors[j].side)
                    {
                    case 0:     // N, offset from W
                        x += r.doors[j].offset;
                        break;

                    case 1:     // E, offset from N
                        x += r.bounds.w - 1;
                        y += r.doors[j].offset;
                        break;

                    case 2:     // S, offset from W
                        x += r.doors[j].offset;
                        y += r.bounds.h - 1;
                        break;

                    case 3:     // W, offset from N
                        y += r.doors[j].offset;
                        break;
                    }
                    map[x][y] = pixelTypes[2];
                }
            }

            return(generatedRooms);
        }
Beispiel #5
0
 public MapRoomDoor(int side, int offset, MapRoom parent)
 {
     this.side   = side;
     this.offset = offset;
     this.parent = parent;
 }
Beispiel #6
0
 public MapRoomDoor(int side, int offset, MapRoom parent)
 {
     this.side = side;
     this.offset = offset;
     this.parent = parent;
 }