Esempio n. 1
0
        public void EraseRoom(Loc loc)
        {
            int          roomIndex = this.Rooms[loc.X][loc.Y];
            GridRoomPlan room      = this.ArrayRooms[roomIndex];

            this.ArrayRooms.RemoveAt(roomIndex);
            for (int xx = room.Bounds.Start.X; xx < room.Bounds.End.X; xx++)
            {
                for (int yy = room.Bounds.Start.Y; yy < room.Bounds.End.Y; yy++)
                {
                    this.Rooms[xx][yy] = -1;
                }
            }

            for (int xx = 0; xx < this.GridWidth; xx++)
            {
                for (int yy = 0; yy < this.GridHeight; yy++)
                {
                    if (this.Rooms[xx][yy] > roomIndex)
                    {
                        this.Rooms[xx][yy]--;
                    }
                }
            }
        }
Esempio n. 2
0
        private static Loc GetBoundsSize(GridPlan floorPlan, GridRoomPlan plan)
        {
            Loc cellSize     = new Loc(plan.Bounds.Width * floorPlan.WidthPerCell, plan.Bounds.Height * floorPlan.HeightPerCell);
            Loc cellWallSize = new Loc((plan.Bounds.Width - 1) * floorPlan.CellWall, (plan.Bounds.Height - 1) * floorPlan.CellWall);

            return(cellSize + cellWallSize);
        }
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            // choose certain rooms in the list to be special rooms
            // special rooms are required; so make sure they don't overlap
            List <int> room_indices = new List <int>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                GridRoomPlan plan = floorPlan.GetRoomPlan(ii);
                if (!plan.Immutable && !plan.CountsAsHall())
                {
                    room_indices.Add(ii);
                }
            }

            if (room_indices.Count > 0)
            {
                int          ind  = rand.Next(room_indices.Count);
                GridRoomPlan plan = floorPlan.GetRoomPlan(room_indices[ind]);
                plan.RoomGen   = this.Rooms.Pick(rand).Copy();
                plan.Immutable = true;
                room_indices.RemoveAt(ind);
                GenContextDebug.DebugProgress("Set Special Room");
            }
        }
Esempio n. 4
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            List <int> candidates = new List <int>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                if (!floorPlan.GetRoomPlan(ii).Immutable)
                {
                    List <int> adjacents = floorPlan.GetAdjacentRooms(ii);
                    if (adjacents.Count > 1)
                    {
                        candidates.Add(ii);
                    }
                }
            }

            // our candidates are all rooms except immutables and terminals
            int amountToDefault = this.DefaultRatio.Pick(rand) * candidates.Count / 100;

            for (int ii = 0; ii < amountToDefault; ii++)
            {
                int          randIndex = rand.Next(candidates.Count);
                GridRoomPlan plan      = floorPlan.GetRoomPlan(candidates[randIndex]);
                plan.RoomGen    = new RoomGenDefault <T>();
                plan.PreferHall = true;
                candidates.RemoveAt(randIndex);
                GenContextDebug.DebugProgress("Defaulted Room");
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Decides on the room bounds for each room.
        /// </summary>
        /// <param name="rand"></param>
        /// <param name="roomIndex"></param>
        public void ChooseRoomBounds(IRandom rand, int roomIndex)
        {
            GridRoomPlan roomPair = this.ArrayRooms[roomIndex];

            // the RoomGens are allowed to choose any size period, but this function will cap them at the cell sizes
            Loc  size       = roomPair.RoomGen.ProposeSize(rand);
            Rect cellBounds = this.GetCellBounds(roomPair.Bounds);

            size = new Loc(Math.Min(size.X, cellBounds.Width), Math.Min(size.Y, cellBounds.Height));
            roomPair.RoomGen.PrepareSize(rand, size);

            Loc start = cellBounds.Start + new Loc(rand.Next(cellBounds.Size.X - size.X + 1), rand.Next(cellBounds.Size.Y - size.Y + 1));

            roomPair.RoomGen.SetLoc(start);
        }
Esempio n. 6
0
        public void AddRoom(Rect rect, IRoomGen gen, ComponentCollection components, bool preferHall)
        {
            Rect floorRect = new Rect(0, 0, this.GridWidth, this.GridHeight);

            if (!floorRect.Contains(rect))
            {
                throw new ArgumentOutOfRangeException(nameof(rect), "Cannot add room out of bounds!");
            }

            for (int xx = rect.Start.X; xx < rect.End.X; xx++)
            {
                for (int yy = rect.Start.Y; yy < rect.End.Y; yy++)
                {
                    if (this.Rooms[xx][yy] != -1)
                    {
                        throw new InvalidOperationException("Tried to add on top of an existing room!");
                    }
                    if (xx > rect.Start.X && this.HHalls[xx - 1][yy].MainHall != null)
                    {
                        throw new InvalidOperationException("Tried to add on top of an existing hall!");
                    }
                    if (yy > rect.Start.Y && this.VHalls[xx][yy - 1].MainHall != null)
                    {
                        throw new InvalidOperationException("Tried to add on top of an existing hall!");
                    }
                }
            }

            if (preferHall && !(gen is IPermissiveRoomGen))
            {
                throw new InvalidOperationException("Cannot prefer hall for a non-permissive gen!");
            }

            var room = new GridRoomPlan(rect, gen.Copy(), components)
            {
                PreferHall = preferHall,
            };

            this.ArrayRooms.Add(room);
            for (int xx = rect.Start.X; xx < rect.End.X; xx++)
            {
                for (int yy = rect.Start.Y; yy < rect.End.Y; yy++)
                {
                    this.Rooms[xx][yy] = this.ArrayRooms.Count - 1;
                }
            }
        }
Esempio n. 7
0
        public List <int> GetAdjacentRooms(int roomIndex)
        {
            List <int>   returnList = new List <int>();
            GridRoomPlan room       = this.ArrayRooms[roomIndex];

            for (int ii = 0; ii < room.Bounds.Size.X; ii++)
            {
                // above
                int up = this.GetRoomNum(new LocRay4(room.Bounds.X + ii, room.Bounds.Y, Dir4.Up));
                if (up > -1 && !returnList.Contains(up))
                {
                    returnList.Add(up);
                }

                // below
                int down = this.GetRoomNum(new LocRay4(room.Bounds.X + ii, room.Bounds.End.Y - 1, Dir4.Down));
                if (down > -1 && !returnList.Contains(down))
                {
                    returnList.Add(down);
                }
            }

            for (int ii = 0; ii < room.Bounds.Size.Y; ii++)
            {
                // left
                int left = this.GetRoomNum(new LocRay4(room.Bounds.X, room.Bounds.Y + ii, Dir4.Left));
                if (left > -1 && !returnList.Contains(left))
                {
                    returnList.Add(left);
                }

                // right
                int right = this.GetRoomNum(new LocRay4(room.Bounds.End.X - 1, room.Bounds.Y + ii, Dir4.Right));
                if (right > -1 && !returnList.Contains(right))
                {
                    returnList.Add(right);
                }
            }

            return(returnList);
        }
Esempio n. 8
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            IRoomGen newGen = this.Rooms.Pick(rand).Copy();
            Loc      size   = newGen.ProposeSize(rand);

            // choose certain rooms in the list to be special rooms
            // special rooms are required; so make sure they don't overlap
            List <int> room_indices = new List <int>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                GridRoomPlan plan = floorPlan.GetRoomPlan(ii);
                if (!BaseRoomFilter.PassesAllFilters(plan, this.Filters))
                {
                    continue;
                }
                if (plan.PreferHall)
                {
                    continue;
                }
                Loc boundsSize = GetBoundsSize(floorPlan, plan);
                if (boundsSize.X >= size.X && boundsSize.Y >= size.Y)
                {
                    room_indices.Add(ii);
                }
            }

            if (room_indices.Count > 0)
            {
                int          ind  = rand.Next(room_indices.Count);
                GridRoomPlan plan = floorPlan.GetRoomPlan(room_indices[ind]);
                plan.RoomGen = newGen;
                foreach (RoomComponent component in this.RoomComponents)
                {
                    plan.Components.Set(component.Clone());
                }
                room_indices.RemoveAt(ind);
                GenContextDebug.DebugProgress("Set Special Room");
            }
        }
Esempio n. 9
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            if (floorPlan.GridWidth < 3 || floorPlan.GridHeight < 3)
            {
                throw new InvalidOperationException("Not enough room to create path.");
            }

            int maxRooms = (2 * floorPlan.GridWidth) + (2 * floorPlan.GridHeight) - 4;
            int roomOpen = maxRooms * this.CircleRoomRatio.Pick(rand) / 100;
            int paths    = this.Paths.Pick(rand);

            if (roomOpen < 1 && paths < 1)
            {
                roomOpen = 1;
            }

            GenContextDebug.StepIn("Outer Circle");

            // draw the top and bottom
            for (int xx = 0; xx < floorPlan.GridWidth; xx++)
            {
                this.RollOpenRoom(rand, floorPlan, new Loc(xx, 0), ref roomOpen, ref maxRooms);
                GenContextDebug.DebugProgress("Room");
                this.RollOpenRoom(rand, floorPlan, new Loc(xx, floorPlan.GridHeight - 1), ref roomOpen, ref maxRooms);
                GenContextDebug.DebugProgress("Room");
                if (xx > 0)
                {
                    floorPlan.SetHall(new LocRay4(new Loc(xx, 0), Dir4.Left), this.GenericHalls.Pick(rand), this.HallComponents.Clone());
                    GenContextDebug.DebugProgress("Hall");
                    floorPlan.SetHall(new LocRay4(new Loc(xx, floorPlan.GridHeight - 1), Dir4.Left), this.GenericHalls.Pick(rand), this.HallComponents.Clone());
                    GenContextDebug.DebugProgress("Hall");
                }
            }

            // draw the left and right (excluding the top and bottom)
            for (int yy = 0; yy < floorPlan.GridHeight; yy++)
            {
                // exclude the top and bottom
                if (yy > 0 && yy < floorPlan.GridHeight - 1)
                {
                    this.RollOpenRoom(rand, floorPlan, new Loc(0, yy), ref roomOpen, ref maxRooms);
                    GenContextDebug.DebugProgress("Room");
                    this.RollOpenRoom(rand, floorPlan, new Loc(floorPlan.GridWidth - 1, yy), ref roomOpen, ref maxRooms);
                    GenContextDebug.DebugProgress("Room");
                }

                if (yy > 0)
                {
                    floorPlan.SetHall(new LocRay4(new Loc(0, yy), Dir4.Up), this.GenericHalls.Pick(rand), this.HallComponents.Clone());
                    GenContextDebug.DebugProgress("Hall");
                    floorPlan.SetHall(new LocRay4(new Loc(floorPlan.GridWidth - 1, yy), Dir4.Up), this.GenericHalls.Pick(rand), this.HallComponents.Clone());
                    GenContextDebug.DebugProgress("Hall");
                }
            }

            GenContextDebug.StepOut();

            GenContextDebug.StepIn("Inner Paths");

            Rect innerRect = new Rect(1, 1, floorPlan.GridWidth - 2, floorPlan.GridHeight - 2);

            // create inner paths
            for (int pathsMade = 0; pathsMade < paths; pathsMade++)
            {
                GenContextDebug.StepIn($"Path {pathsMade}");

                Dir4 startDir = DirExt.VALID_DIR4.ElementAt(rand.Next(DirExt.DIR4_COUNT));
                int  x        = rand.Next(innerRect.Start.X, innerRect.End.X);
                int  y        = rand.Next(innerRect.Start.Y, innerRect.End.Y);
                switch (startDir)
                {
                case Dir4.Down:
                    y = 0;
                    break;

                case Dir4.Left:
                    x = floorPlan.GridWidth - 1;
                    break;

                case Dir4.Up:
                    y = floorPlan.GridHeight - 1;
                    break;

                case Dir4.Right:
                    x = 0;
                    break;

                case Dir4.None:
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(startDir), "Invalid enum value.");
                }

                Loc  wanderer   = new Loc(x, y);
                Dir4 prevDir    = Dir4.None; // direction of movement
                int  pathLength = (startDir.ToAxis() == Axis4.Vert) ? innerRect.Height : innerRect.Width;
                for (int currentLength = 0; currentLength < pathLength; currentLength++)
                {
                    Dir4 chosenDir = startDir;

                    // avoid this block the first time
                    if (currentLength > 0)
                    {
                        List <Dir4> dirs = new List <Dir4>();
                        foreach (Dir4 dir in DirExt.VALID_DIR4)
                        {
                            // do not backtrack
                            if (dir == prevDir)
                            {
                                continue;
                            }

                            // do not hit edge
                            if (!Collision.InBounds(innerRect, wanderer + dir.GetLoc()))
                            {
                                continue;
                            }
                            dirs.Add(dir);
                        }

                        chosenDir = dirs[rand.Next(dirs.Count)];
                    }

                    Loc dest = wanderer + chosenDir.GetLoc();

                    GridRoomPlan existingRoom = floorPlan.GetRoomPlan(dest);
                    if (existingRoom == null)
                    {
                        if (currentLength == pathLength - 1) // only the end room can be a non-hall
                        {
                            floorPlan.AddRoom(dest, this.GenericRooms.Pick(rand), this.RoomComponents.Clone());
                        }
                        else
                        {
                            floorPlan.AddRoom(dest, this.GetDefaultGen(), this.HallComponents.Clone(), true);
                        }
                        GenContextDebug.DebugProgress("Room");
                    }
                    else if (existingRoom.PreferHall)
                    {
                        if (currentLength == pathLength - 1)
                        {
                            // override the hall room
                            existingRoom.RoomGen    = this.GenericRooms.Pick(rand).Copy();
                            existingRoom.PreferHall = false;
                        }
                    }

                    floorPlan.SetHall(new LocRay4(wanderer, chosenDir), this.GenericHalls.Pick(rand), this.HallComponents.Clone());
                    GenContextDebug.DebugProgress("Hall");

                    wanderer = dest;
                    prevDir  = chosenDir.Reverse();
                }

                GenContextDebug.StepOut();
            }

            GenContextDebug.StepOut();
        }
Esempio n. 10
0
        /// <summary>
        /// Decides on the bounds for each hall.  Also writes to the adjacent rooms' SideReqs and tile permissions
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="vertical"></param>
        /// <param name="rand">todo: describe rand parameter on ChooseHallBounds</param>
        public void ChooseHallBounds(IRandom rand, int x, int y, bool vertical)
        {
            GridRoomPlan startRoom = this.GetRoomPlan(new Loc(x, y));
            GridRoomPlan endRoom   = this.GetRoomPlan(new Loc(x + (vertical ? 0 : 1), y + (vertical ? 1 : 0)));

            GridHallGroup hallGroup = vertical ? this.VHalls[x][y] : this.HHalls[x][y];

            if (hallGroup.MainHall != null)
            {
                // also sets the sidereqs
                int      tier          = vertical ? x : y;
                Dir4     dir           = vertical ? Dir4.Down : Dir4.Right;
                IntRange startRange    = this.GetHallTouchRange(startRoom.RoomGen, dir, tier);
                IntRange endRange      = this.GetHallTouchRange(endRoom.RoomGen, dir.Reverse(), tier);
                IntRange combinedRange = new IntRange(Math.Min(startRange.Min, endRange.Min), Math.Max(startRange.Max, endRange.Max));
                Loc      start         = startRoom.RoomGen.Draw.End;
                Loc      end           = endRoom.RoomGen.Draw.Start;

                Rect startCell = this.GetCellBounds(startRoom.Bounds);
                Rect endCell   = this.GetCellBounds(endRoom.Bounds);

                Rect bounds = vertical ? new Rect(combinedRange.Min, start.Y, combinedRange.Length, end.Y - start.Y)
                    : new Rect(start.X, combinedRange.Min, end.X - start.X, combinedRange.Length);

                // a side constitutes intruding bound when the rectangle moves forward enough to go to the other side
                // and the other side touched is outside of side B's bound (including borders)

                // startRange intrudes if startRange goes outside end's tier (borders included)
                bool startIntrude = !endCell.GetSide(dir.ToAxis()).Contains(startRange);

                // and end is greater than the edge (borders excluded)
                bool endTouch = bounds.GetScalar(dir) == endCell.GetScalar(dir.Reverse());

                bool endIntrude = !startCell.GetSide(dir.ToAxis()).Contains(endRange);

                // and end is greater than the edge (borders excluded)
                bool startTouch = bounds.GetScalar(dir.Reverse()) == startCell.GetScalar(dir);

                // neither side intrudes bound: use the computed rectangle
                if ((!startIntrude && !endIntrude) || (endTouch && startTouch) ||
                    (!(startIntrude && endIntrude) && ((startIntrude && endTouch) || (endIntrude && startTouch))))
                {
                    hallGroup.MainHall.RoomGen.PrepareSize(rand, bounds.Size);
                    hallGroup.MainHall.RoomGen.SetLoc(bounds.Start);
                }
                else
                {
                    int      divPoint      = startCell.GetScalar(dir) + 1;
                    IntRange startDivRange = startRange;
                    IntRange endDivRange   = endRange;
                    if (startIntrude && !endIntrude)
                    {
                        // side A intrudes bound, side B does not: divide A and B; doesn't matter who gets border
                        // side A touches border, side B does not: divide A and B; A gets border
                        //
                        // side A does not, side B touches border: A gets border; don't need B - this cannot happen
                        // side A touches border, side B touches border: A gets border; don't need B - this cannot happen
                        //
                        // in short, divide with start getting the border
                        // startDivRange needs to contain endRange
                        startDivRange = combinedRange;
                    }
                    else if (!startIntrude && endIntrude)
                    {
                        // side A does not, side B intrudes bound: divide A and B; doesn't matter who gets border
                        // side A does not, side B touches border: divide A and B; B gets border
                        //
                        // side A touches border, side B does not: B gets border; don't need A - this cannot happen
                        // side A touches border, side B touches border: B gets border; don't need B - this cannot happen
                        //
                        // in short, divide with end getting the border
                        // endDivRange needs to contain startRange
                        divPoint    = startCell.GetScalar(dir);
                        endDivRange = combinedRange;
                    }
                    else
                    {
                        // side A intrudes bound, side B intrudes bound: divide A and B; doesn't matter who gets border
                        if (startTouch)
                        {
                            // side A touches border, side B does not: divide A and B; A gets border
                        }

                        if (endTouch)
                        {
                            // side A does not, side B touches border: divide A and B; B gets border
                            divPoint = startCell.GetScalar(dir);
                        }

                        // side A touches border, side B touches border: A gets border; don't need B -  this cannot happen
                        // both sides need to cover the intersection of their cells
                        IntRange interCellSide = IntRange.Intersect(startCell.GetSide(dir.ToAxis()), endCell.GetSide(dir.ToAxis()));
                        startDivRange = IntRange.IncludeRange(startDivRange, interCellSide);
                        endDivRange   = IntRange.IncludeRange(endDivRange, interCellSide);
                    }

                    Rect startBox = vertical ? new Rect(startDivRange.Min, start.Y, startDivRange.Length, divPoint - start.Y)
                        : new Rect(start.X, startDivRange.Min, divPoint - start.X, startDivRange.Length);
                    Rect endBox = vertical ? new Rect(endDivRange.Min, divPoint, endDivRange.Length, end.Y - divPoint)
                        : new Rect(divPoint, endDivRange.Min, end.X - divPoint, endDivRange.Length);

                    GridHallPlan originalHall = hallGroup.MainHall;
                    hallGroup.HallParts.Add(new GridHallPlan((IPermissiveRoomGen)originalHall.RoomGen.Copy(), originalHall.Components));
                    hallGroup.HallParts[0].RoomGen.PrepareSize(rand, startBox.Size);
                    hallGroup.HallParts[0].RoomGen.SetLoc(startBox.Start);
                    hallGroup.HallParts[1].RoomGen.PrepareSize(rand, endBox.Size);
                    hallGroup.HallParts[1].RoomGen.SetLoc(endBox.Start);
                }
            }
        }
Esempio n. 11
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            List <LocRay4> endBranches = new List <LocRay4>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                GridRoomPlan roomPlan = floorPlan.GetRoomPlan(ii);

                if (!BaseRoomFilter.PassesAllFilters(roomPlan, this.Filters))
                {
                    continue;
                }

                if (roomPlan.Bounds.Size == new Loc(1))
                {
                    List <int> adjacents = floorPlan.GetAdjacentRooms(ii);
                    if (adjacents.Count == 1)
                    {
                        endBranches.Add(new LocRay4(roomPlan.Bounds.Start));
                    }
                }
            }

            List <List <LocRay4> > candBranchPoints = new List <List <LocRay4> >();

            for (int nn = 0; nn < endBranches.Count; nn++)
            {
                LocRay4 chosenBranch = endBranches[nn];

                while (chosenBranch.Loc != new Loc(-1))
                {
                    List <LocRay4> connectors = new List <LocRay4>();
                    List <LocRay4> candBonds  = new List <LocRay4>();
                    foreach (Dir4 dir in DirExt.VALID_DIR4)
                    {
                        if (dir != chosenBranch.Dir)
                        {
                            if (floorPlan.GetHall(new LocRay4(chosenBranch.Loc, dir)) != null)
                            {
                                connectors.Add(new LocRay4(chosenBranch.Loc, dir));
                            }
                            else
                            {
                                Loc loc = chosenBranch.Loc + dir.GetLoc();
                                if (Collision.InBounds(floorPlan.GridWidth, floorPlan.GridHeight, loc) &&
                                    floorPlan.GetRoomIndex(loc) > -1)
                                {
                                    candBonds.Add(new LocRay4(chosenBranch.Loc, dir));
                                }
                            }
                        }
                    }

                    if (connectors.Count == 1)
                    {
                        if (candBonds.Count > 0)
                        {
                            candBranchPoints.Add(candBonds);
                            chosenBranch = new LocRay4(new Loc(-1));
                        }
                        else
                        {
                            chosenBranch = new LocRay4(connectors[0].Traverse(1), connectors[0].Dir.Reverse());
                        }
                    }
                    else
                    {
                        chosenBranch = new LocRay4(new Loc(-1));
                    }
                }
            }

            // compute a goal amount of terminals to connect
            // this computation ignores the fact that some terminals may be impossible
            var randBin         = new RandBinomial(candBranchPoints.Count, this.ConnectPercent);
            int connectionsLeft = randBin.Pick(rand);

            while (candBranchPoints.Count > 0 && connectionsLeft > 0)
            {
                // choose random point to connect
                int            randIndex = rand.Next(candBranchPoints.Count);
                List <LocRay4> candBonds = candBranchPoints[randIndex];
                LocRay4        chosenDir = candBonds[rand.Next(candBonds.Count)];

                // connect
                floorPlan.SetHall(chosenDir, this.GenericHalls.Pick(rand), this.HallComponents);
                candBranchPoints.RemoveAt(randIndex);
                GenContextDebug.DebugProgress("Connected Branch");
                connectionsLeft--;

                // check to see if connection destination was also a candidate,
                // counting this as a double if so
                for (int ii = candBranchPoints.Count - 1; ii >= 0; ii--)
                {
                    if (candBranchPoints[ii][0].Loc == chosenDir.Traverse(1))
                    {
                        candBranchPoints.RemoveAt(ii);
                        connectionsLeft--;
                    }
                }
            }
        }