예제 #1
0
        public override void ApplyToPath(IRandom rand, FloorPlan floorPlan)
        {
            List <RoomHallIndex> candBranchPoints = new List <RoomHallIndex>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                if (!BaseRoomFilter.PassesAllFilters(floorPlan.GetRoomPlan(ii), this.Filters))
                {
                    continue;
                }
                candBranchPoints.Add(new RoomHallIndex(ii, false));
            }

            // compute a goal amount of terminals to connect
            // this computation ignores the fact that some terminals may be impossible
            int connectionsLeft = this.ConnectFactor.Pick(rand) * candBranchPoints.Count / 2 / 100;

            while (candBranchPoints.Count > 0 && connectionsLeft > 0)
            {
                // choose random point to connect from
                int randIndex        = rand.Next(candBranchPoints.Count);
                var chosenDestResult = ChooseConnection(rand, floorPlan, candBranchPoints);

                if (chosenDestResult is ListPathTraversalNode chosenDest)
                {
                    // connect
                    PermissiveRoomGen <T> hall = (PermissiveRoomGen <T>) this.GenericHalls.Pick(rand).Copy();
                    hall.PrepareSize(rand, chosenDest.Connector.Size);
                    hall.SetLoc(chosenDest.Connector.Start);
                    floorPlan.AddHall(hall, this.Components.Clone(), chosenDest.From, chosenDest.To);
                    candBranchPoints.RemoveAt(randIndex);
                    connectionsLeft--;
                    GenContextDebug.DebugProgress("Added Connection");

                    // check to see if connection destination was also a candidate,
                    // counting this as a double if so
                    for (int jj = 0; jj < candBranchPoints.Count; jj++)
                    {
                        if (candBranchPoints[jj] == chosenDest.To)
                        {
                            candBranchPoints.RemoveAt(jj);
                            connectionsLeft--;
                            break;
                        }
                    }
                }
                else
                {
                    // remove the list anyway, but don't call it a success
                    candBranchPoints.RemoveAt(randIndex);
                }
            }
        }
예제 #2
0
        protected static ListPathTraversalNode?ChooseConnection(IRandom rand, FloorPlan floorPlan, List <RoomHallIndex> candList)
        {
            SpawnList <ListPathTraversalNode> expansions = GetPossibleExpansions(floorPlan, candList);

            if (expansions.Count > 0)
            {
                return(expansions.Pick(rand));
            }
            else
            {
                return(null);
            }
        }
예제 #3
0
        protected static SpawnList <ListPathTraversalNode> GetPossibleExpansions(FloorPlan floorPlan, List <RoomHallIndex> candList)
        {
            // get all probabilities.
            // the probability of an extension is the distance that the target room is from the start room, in rooms
            var expansions = new SpawnList <ListPathTraversalNode>();

            for (int nn = 0; nn < candList.Count; nn++)
            {
                // find the room to connect to
                // go through all sides of all rooms (randomly)
                RoomHallIndex  chosenFrom = candList[nn];
                IFloorRoomPlan planFrom   = floorPlan.GetRoomHall(chosenFrom);

                // exhausting all possible directions (randomly)
                foreach (Dir4 dir in DirExt.VALID_DIR4)
                {
                    bool forbidExtend = false;
                    foreach (RoomHallIndex adjacent in planFrom.Adjacents)
                    {
                        Rect adjRect = floorPlan.GetRoomHall(adjacent).RoomGen.Draw;
                        if (planFrom.RoomGen.Draw.GetScalar(dir) == adjRect.GetScalar(dir.Reverse()))
                        {
                            forbidExtend = true;
                            break;
                        }
                    }

                    if (!forbidExtend)
                    {
                        // find a rectangle to connect it with
                        ListPathTraversalNode?expandToResult = GetRoomToConnect(floorPlan, chosenFrom, dir);

                        if (expandToResult is ListPathTraversalNode expandTo)
                        {
                            int prb = floorPlan.GetDistance(expandTo.From, expandTo.To);
                            if (prb < 0)
                            {
                                expansions.Add(expandTo, 1);
                            }
                            else if (prb > 0)
                            {
                                expansions.Add(expandTo, prb);
                            }
                        }
                    }
                }
            }

            return(expansions);
        }
예제 #4
0
        public override void ApplyToPath(IRandom rand, FloorPlan floorPlan)
        {
            List <List <RoomHallIndex> > candBranchPoints = GetBranchArms(floorPlan);

            // compute a goal amount of branches 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 from
                int randIndex        = rand.Next(candBranchPoints.Count);
                var chosenDestResult = ChooseConnection(rand, floorPlan, candBranchPoints[randIndex]);

                if (chosenDestResult is ListPathTraversalNode chosenDest)
                {
                    // connect
                    PermissiveRoomGen <T> hall = (PermissiveRoomGen <T>) this.GenericHalls.Pick(rand).Copy();
                    hall.PrepareSize(rand, chosenDest.Connector.Size);
                    hall.SetLoc(chosenDest.Connector.Start);
                    floorPlan.AddHall(hall, chosenDest.From, chosenDest.To);
                    candBranchPoints.RemoveAt(randIndex);
                    connectionsLeft--;
                    GenContextDebug.DebugProgress("Added Connection");

                    // 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--)
                    {
                        for (int jj = 0; jj < candBranchPoints[ii].Count; jj++)
                        {
                            if (candBranchPoints[ii][jj] == chosenDest.To)
                            {
                                candBranchPoints.RemoveAt(ii);
                                connectionsLeft--;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    // remove the list anyway, but don't call it a success
                    candBranchPoints.RemoveAt(randIndex);
                }
            }
        }
예제 #5
0
        public override void ApplyToPath(IRandom rand, FloorPlan floorPlan)
        {
            int amount = this.Amount.Pick(rand);

            for (int ii = 0; ii < amount; ii++)
            {
                // choose a room
                RoomGen <T> room = this.GenericRooms.Pick(rand).Copy();

                // decide on acceptable border/size/fulfillables
                Loc size = room.ProposeSize(rand);
                if (size.X > floorPlan.DrawRect.Width)
                {
                    size.X = floorPlan.DrawRect.Width;
                }
                if (size.Y > floorPlan.DrawRect.Height)
                {
                    size.Y = floorPlan.DrawRect.Height;
                }
                room.PrepareSize(rand, size);

                for (int jj = 0; jj < 30; jj++)
                {
                    // place in a random location
                    Loc testStart = new Loc(
                        rand.Next(floorPlan.DrawRect.Left, floorPlan.DrawRect.Right - room.Draw.Width + 1),
                        rand.Next(floorPlan.DrawRect.Top, floorPlan.DrawRect.Bottom - room.Draw.Height + 1));

                    Rect tryRect = new Rect(testStart, room.Draw.Size);

                    tryRect.Inflate(1, 1);

                    List <RoomHallIndex> collisions = floorPlan.CheckCollision(tryRect);
                    if (collisions.Count == 0)
                    {
                        room.SetLoc(testStart);
                        floorPlan.AddRoom(room, this.Components.Clone());
                        GenContextDebug.DebugProgress("Place Disconnected Room");
                        break;
                    }
                }
            }
        }
예제 #6
0
        public override void ApplyToPath(IRandom rand, FloorPlan floorPlan)
        {
            // choose certain rooms in the list to be special rooms
            // special rooms are required; so make sure they don't overlap
            IRoomGen newGen = this.Rooms.Pick(rand).Copy();
            Loc      size   = newGen.ProposeSize(rand);

            newGen.PrepareSize(rand, size);
            int factor = floorPlan.DrawRect.Area / newGen.Draw.Area;

            // TODO: accept smaller rooms to replace
            // bulldozing the surrounding rooms to get the space
            var room_indices = new SpawnList <RoomHallIndex>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                FloorRoomPlan plan = floorPlan.GetRoomPlan(ii);
                if (!plan.Immutable &&
                    plan.RoomGen.Draw.Width >= newGen.Draw.Width &&
                    plan.RoomGen.Draw.Height >= newGen.Draw.Height)
                {
                    room_indices.Add(new RoomHallIndex(ii, false), ComputeRoomChance(factor, plan.RoomGen.Draw, newGen.Draw));
                }
            }

            for (int ii = 0; ii < floorPlan.HallCount; ii++)
            {
                var            roomHall = new RoomHallIndex(ii, true);
                IFloorRoomPlan plan     = floorPlan.GetRoomHall(roomHall);
                if (plan.RoomGen.Draw.Width >= newGen.Draw.Width &&
                    plan.RoomGen.Draw.Height >= newGen.Draw.Height)
                {
                    room_indices.Add(roomHall, ComputeRoomChance(factor, plan.RoomGen.Draw, newGen.Draw));
                }
            }

            while (room_indices.Count > 0)
            {
                int           ind         = room_indices.PickIndex(rand);
                RoomHallIndex oldRoomHall = room_indices.GetSpawn(ind);
                Dictionary <Dir4, List <RoomHallIndex> > adjacentIndicesByDir = GetDirectionAdjacents(floorPlan, oldRoomHall);
                var adjacentsByDir = new Dictionary <Dir4, List <IRoomGen> >();
                foreach (Dir4 dir in DirExt.VALID_DIR4)
                {
                    adjacentsByDir[dir] = new List <IRoomGen>();
                    foreach (RoomHallIndex adj in adjacentIndicesByDir[dir])
                    {
                        adjacentsByDir[dir].Add(floorPlan.GetRoomHall(adj).RoomGen);
                    }
                }

                Loc placement = this.FindPlacement(rand, adjacentsByDir, newGen, floorPlan.GetRoomHall(oldRoomHall).RoomGen);
                if (placement != new Loc(-1))
                {
                    newGen.SetLoc(placement);
                    this.PlaceRoom(rand, floorPlan, newGen, oldRoomHall);
                    GenContextDebug.DebugProgress("Set Special Room");
                    return;
                }

                room_indices.RemoveAt(ind);
            }
        }
예제 #7
0
        private static Dictionary <Dir4, List <RoomHallIndex> > GetDirectionAdjacents(FloorPlan floorPlan, RoomHallIndex oldRoomHall)
        {
            var            adjacentsByDir = new Dictionary <Dir4, List <RoomHallIndex> >();
            IFloorRoomPlan oldPlan        = floorPlan.GetRoomHall(oldRoomHall);

            foreach (Dir4 dir in DirExt.VALID_DIR4)
            {
                adjacentsByDir[dir] = new List <RoomHallIndex>();
                foreach (RoomHallIndex adjacent in oldPlan.Adjacents)
                {
                    IFloorRoomPlan adjPlan = floorPlan.GetRoomHall(adjacent);
                    if (oldPlan.RoomGen.Draw.GetScalar(dir) ==
                        adjPlan.RoomGen.Draw.GetScalar(dir.Reverse()))
                    {
                        adjacentsByDir[dir].Add(adjacent);
                    }
                }
            }

            return(adjacentsByDir);
        }
예제 #8
0
        public static void AddLegalPlacements(SpawnList <Loc> possiblePlacements, FloorPlan floorPlan, RoomHallIndex indexFrom, IRoomGen roomFrom, IRoomGen room, Dir4 expandTo)
        {
            bool vertical = expandTo.ToAxis() == Axis4.Vert;

            // this scaling factor equalizes the chances of long sides vs short sides
            int reverseSideMult = vertical ? roomFrom.Draw.Width * room.Draw.Width : roomFrom.Draw.Height * room.Draw.Height;

            IntRange side = roomFrom.Draw.GetSide(expandTo.ToAxis());

            // subtract the room's original size, not the inflated trialrect size
            side.Min -= (vertical ? room.Draw.Size.X : room.Draw.Size.Y) - 1;

            Rect tryRect = room.Draw;

            // expand in every direction
            // this will create a one-tile buffer to check for collisions
            tryRect.Inflate(1, 1);
            int currentScalar = side.Min;

            while (currentScalar < side.Max)
            {
                // compute the location
                Loc trialLoc = roomFrom.GetEdgeRectLoc(expandTo, room.Draw.Size, currentScalar);
                tryRect.Start = trialLoc + new Loc(-1, -1);

                // check for collisions (not counting the rectangle from)
                List <RoomHallIndex> collisions = floorPlan.CheckCollision(tryRect);

                // find the first tile in which no collisions will be found
                int  maxCollideScalar = currentScalar;
                bool collided         = false;
                foreach (RoomHallIndex collision in collisions)
                {
                    if (collision != indexFrom)
                    {
                        IRoomGen collideRoom = floorPlan.GetRoomHall(collision).RoomGen;

                        // this is the point at which the new room will barely touch the collided room
                        // the +1 at the end will move it into the safe zone
                        maxCollideScalar = Math.Max(maxCollideScalar, vertical ? collideRoom.Draw.Right : collideRoom.Draw.Bottom);
                        collided         = true;
                    }
                }

                // if no collisions were hit, do final checks and add the room
                if (!collided)
                {
                    Loc locTo = roomFrom.GetEdgeRectLoc(expandTo, room.Draw.Size, currentScalar);

                    // must be within the borders of the floor!
                    if (floorPlan.DrawRect.Contains(new Rect(locTo, room.Draw.Size)))
                    {
                        // check the border match and if add to possible placements
                        int chanceTo = FloorPlan.GetBorderMatch(roomFrom, room, locTo, expandTo);
                        if (chanceTo > 0)
                        {
                            possiblePlacements.Add(locTo, chanceTo * reverseSideMult);
                        }
                    }
                }

                currentScalar = maxCollideScalar + 1;
            }
        }
예제 #9
0
        public virtual ListPathBranchExpansion?ChooseRoomExpansion(IRandom rand, FloorPlan floorPlan, bool branch)
        {
            List <RoomHallIndex> possibles = GetPossibleExpansions(floorPlan, branch);

            return(ChooseRoomExpansion(this.PrepareRoom, this.HallPercent, rand, floorPlan, possibles));
        }
예제 #10
0
        public override void ApplyToPath(IRandom rand, FloorPlan floorPlan)
        {
            for (int ii = 0; ii < 10; ii++)
            {
                // always clear before trying
                floorPlan.Clear();

                int tilesToOpen = floorPlan.DrawRect.Area * this.FillPercent.Pick(rand) / 100;
                if (tilesToOpen < 1)
                {
                    tilesToOpen = 1;
                }
                int addBranch = this.BranchRatio.Pick(rand);
                int tilesLeft = tilesToOpen;

                // choose a room
                IRoomGen room = this.PrepareRoom(rand, floorPlan, false);

                // place in a random location
                room.SetLoc(new Loc(
                                rand.Next(floorPlan.DrawRect.Left, floorPlan.DrawRect.Right - room.Draw.Width + 1),
                                rand.Next(floorPlan.DrawRect.Top, floorPlan.DrawRect.Bottom - room.Draw.Height + 1)));
                floorPlan.AddRoom(room, this.RoomComponents.Clone());
                GenContextDebug.DebugProgress("Start Room");

                tilesLeft -= room.Draw.Area;

                // repeat this process until the requisite room amount is met
                int pendingBranch = 0;
                while (tilesLeft > 0)
                {
                    (int area, int rooms)terminalResult = this.ExpandPath(rand, floorPlan, false);
                    (int area, int rooms)branchResult   = (0, 0);
                    if (terminalResult.area > 0)
                    {
                        tilesLeft -= terminalResult.area;

                        // add branch PER ROOM when we add over the min threshold
                        for (int jj = 0; jj < terminalResult.rooms; jj++)
                        {
                            if (floorPlan.RoomCount + floorPlan.HallCount - terminalResult.rooms + jj + 1 > 2)
                            {
                                pendingBranch += addBranch;
                            }
                        }
                    }
                    else if (this.NoForcedBranches)
                    {
                        break;
                    }
                    else
                    {
                        pendingBranch = 100;
                    }

                    while (pendingBranch >= 100 && tilesLeft > 0)
                    {
                        branchResult = this.ExpandPath(rand, floorPlan, true);
                        if (branchResult.area == 0)
                        {
                            break;
                        }
                        pendingBranch -= 100;

                        // if we add any more than one room, that also counts as a branchable node
                        pendingBranch += (branchResult.rooms - 1) * addBranch;
                        tilesLeft     -= branchResult.area;
                    }

                    if (terminalResult.area == 0 && branchResult.area == 0)
                    {
                        break;
                    }
                }

                if (tilesLeft <= 0)
                {
                    break;
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Chooses a node to expand the path from based on the specified branch setting.
        /// </summary>
        /// <param name="availableExpansions">todo: describe availableExpansions parameter on ChooseRoomExpansion</param>
        /// <param name="prepareRoom">todo: describe prepareRoom parameter on ChooseRoomExpansion</param>
        /// <param name="hallPercent">todo: describe hallPercent parameter on ChooseRoomExpansion</param>
        /// <param name="rand"></param>
        /// <param name="floorPlan"></param>
        /// <returns>A set of instructions on how to expand the path.</returns>
        public static ListPathBranchExpansion?ChooseRoomExpansion(RoomPrep prepareRoom, int hallPercent, IRandom rand, FloorPlan floorPlan, List <RoomHallIndex> availableExpansions)
        {
            if (availableExpansions.Count == 0)
            {
                return(null);
            }

            for (int ii = 0; ii < 30; ii++)
            {
                // choose the next room to add to
                RoomHallIndex firstExpandFrom = availableExpansions[rand.Next(availableExpansions.Count)];
                RoomHallIndex expandFrom      = firstExpandFrom;
                IRoomGen      roomFrom        = floorPlan.GetRoomHall(firstExpandFrom).RoomGen;

                // choose the next room to add
                // choose room size/fulfillables
                // note: by allowing halls to be picked as extensions, we run the risk of adding dead-end halls
                // halls should always terminate at rooms?
                // this means... doubling up with hall+room?
                bool     addHall = rand.Next(100) < hallPercent;
                IRoomGen hall    = null;
                if (addHall)
                {
                    hall = prepareRoom(rand, floorPlan, true);

                    // randomly choose a perimeter to assign this to
                    SpawnList <Loc> possibleHallPlacements = new SpawnList <Loc>();
                    foreach (Dir4 dir in DirExt.VALID_DIR4)
                    {
                        AddLegalPlacements(possibleHallPlacements, floorPlan, expandFrom, roomFrom, hall, dir);
                    }

                    // at this point, all possible factors for whether a placement is legal or not is accounted for
                    // therefor just pick one
                    if (possibleHallPlacements.Count == 0)
                    {
                        continue;
                    }

                    // randomly choose one
                    Loc hallCandLoc = possibleHallPlacements.Pick(rand);

                    // set location
                    hall.SetLoc(hallCandLoc);

                    // change the roomfrom for the upcoming room
                    expandFrom = new RoomHallIndex(-1, false);
                    roomFrom   = hall;
                }

                IRoomGen room = prepareRoom(rand, floorPlan, false);

                // randomly choose a perimeter to assign this to
                SpawnList <Loc> possiblePlacements = new SpawnList <Loc>();
                foreach (Dir4 dir in DirExt.VALID_DIR4)
                {
                    AddLegalPlacements(possiblePlacements, floorPlan, expandFrom, roomFrom, room, dir);
                }

                // at this point, all possible factors for whether a placement is legal or not is accounted for
                // therefore just pick one
                if (possiblePlacements.Count > 0)
                {
                    // randomly choose one
                    Loc candLoc = possiblePlacements.Pick(rand);

                    // set location
                    room.SetLoc(candLoc);
                    return(new ListPathBranchExpansion(firstExpandFrom, room, (IPermissiveRoomGen)hall));
                }
            }

            return(null);
        }
예제 #12
0
        public void PlaceRoom(IRandom rand, FloorPlan floorPlan, IRoomGen newGen, RoomHallIndex oldRoomHall)
        {
            // first get the adjacents of the removed room
            Dictionary <Dir4, List <RoomHallIndex> > adjacentsByDir = GetDirectionAdjacents(floorPlan, oldRoomHall);
            IRoomPlan oldPlan = floorPlan.GetRoomHall(oldRoomHall);

            // remove the room; update the adjacents too
            floorPlan.EraseRoomHall(oldRoomHall);
            foreach (Dir4 dir in DirExt.VALID_DIR4)
            {
                for (int jj = 0; jj < adjacentsByDir[dir].Count; jj++)
                {
                    RoomHallIndex adjRoomHall = adjacentsByDir[dir][jj];
                    if (adjRoomHall.IsHall == oldRoomHall.IsHall &&
                        adjRoomHall.Index > oldRoomHall.Index)
                    {
                        adjacentsByDir[dir][jj] = new RoomHallIndex(adjRoomHall.Index - 1, adjRoomHall.IsHall);
                    }
                }
            }

            var newAdjacents = new List <RoomHallIndex>();
            var supportHalls = new Dictionary <Dir4, IPermissiveRoomGen>();

            foreach (Dir4 dir in DirExt.VALID_DIR4)
            {
                if (newGen.Draw.GetScalar(dir) == oldPlan.RoomGen.Draw.GetScalar(dir))
                {
                    newAdjacents.AddRange(adjacentsByDir[dir]);
                }
                else if (adjacentsByDir[dir].Count > 0)
                {
                    Rect supportRect = GetSupportRect(floorPlan, oldPlan.RoomGen, newGen, dir, adjacentsByDir[dir]);
                    var  supportHall = (IPermissiveRoomGen)this.Halls.Pick(rand).Copy();
                    supportHall.PrepareSize(rand, supportRect.Size);
                    supportHall.SetLoc(supportRect.Start);
                    supportHalls[dir] = supportHall;
                }
            }

            // add the new room
            var newRoomInd = new RoomHallIndex(floorPlan.RoomCount, false);
            ComponentCollection newCollection = oldPlan.Components.Clone();

            foreach (RoomComponent component in this.RoomComponents)
            {
                newCollection.Set(component.Clone());
            }
            floorPlan.AddRoom(newGen, newCollection, newAdjacents.ToArray());

            // add supporting halls
            foreach (Dir4 dir in DirExt.VALID_DIR4)
            {
                if (supportHalls.ContainsKey(dir))
                {
                    // include an attachment to the newly added room
                    List <RoomHallIndex> adjToAdd = new List <RoomHallIndex> {
                        newRoomInd
                    };
                    adjToAdd.AddRange(adjacentsByDir[dir]);
                    ComponentCollection newHallCollection = oldPlan.Components.Clone();
                    foreach (RoomComponent component in this.HallComponents)
                    {
                        newHallCollection.Set(component.Clone());
                    }
                    floorPlan.AddHall(supportHalls[dir], newHallCollection.Clone(), adjToAdd.ToArray());
                }
            }
        }
예제 #13
0
        protected static ListPathTraversalNode?GetRoomToConnect(FloorPlan floorPlan, RoomHallIndex chosenFrom, Dir4 dir)
        {
            // extend a rectangle to the border of the floor in the chosen direction
            bool     vertical   = dir.ToAxis() == Axis4.Vert;
            int      dirSign    = dir.GetLoc().GetScalar(dir.ToAxis());
            IRoomGen genFrom    = floorPlan.GetRoomHall(chosenFrom).RoomGen;
            Rect     sampleRect = genFrom.Draw;

            // expand from the start of that border direction to the borders of the floor
            sampleRect.Start += dir.GetLoc() * sampleRect.Size.GetScalar(dir.ToAxis());

            // it doesn't have to be exactly the borders so just add the total size to be sure
            sampleRect.Expand(dir, vertical ? floorPlan.Size.Y : floorPlan.Size.X);

            // find the closest room.
            var chosenTo = new RoomHallIndex(-1, false);

            foreach (RoomHallIndex collision in floorPlan.CheckCollision(sampleRect))
            {
                Rect collidedRect = floorPlan.GetRoomHall(collision).RoomGen.Draw;

                // limit the expansion by direction
                int  sampleScalar   = sampleRect.GetScalar(dir);
                int  collidedScalar = collidedRect.GetScalar(dir.Reverse());
                bool limit          = dirSign == Math.Sign(sampleScalar - collidedScalar);
                if (limit)
                {
                    // update the boundaries
                    sampleRect.SetScalar(dir, collidedScalar);
                    chosenTo = collision;
                }
            }

            // if it didn't collide with ANYTHING, then quit
            if (chosenTo.Index == -1)
            {
                return(null);
            }

            IRoomGen genTo = floorPlan.GetRoomHall(chosenTo).RoomGen;

            // narrow the rectangle if touching something on the side
            // widen the rectangle by width
            Rect widthRect = sampleRect;

            widthRect.Inflate(vertical ? 1 : 0, vertical ? 0 : 1);
            bool retractLeft  = false;
            bool retractRight = false;
            Dir4 leftDir      = DirExt.AddAngles(dir, Dir4.Left);
            Dir4 rightDir     = DirExt.AddAngles(dir, Dir4.Right);

            foreach (RoomHallIndex collision in floorPlan.CheckCollision(widthRect))
            {
                Rect collidedRect = floorPlan.GetRoomHall(collision).RoomGen.Draw;
                if (!retractLeft)
                {
                    if (collidedRect.GetScalar(leftDir.Reverse()) == sampleRect.GetScalar(leftDir))
                    {
                        retractLeft = true;
                    }
                }

                if (!retractRight)
                {
                    if (collidedRect.GetScalar(rightDir.Reverse()) == sampleRect.GetScalar(rightDir))
                    {
                        retractRight = true;
                    }
                }
            }

            // retract the rectangle
            if (retractLeft)
            {
                sampleRect.Expand(leftDir, -1);
            }
            if (retractRight)
            {
                sampleRect.Expand(rightDir, -1);
            }

            // if the rectangle has been retracted too much, we can't go on
            if (sampleRect.Area <= 0)
            {
                return(null);
            }

            // check for border availability between start and end
            bool foundFrom = HasBorderOpening(genFrom, sampleRect, dir);
            bool foundTo   = HasBorderOpening(genTo, sampleRect, dir.Reverse());

            // return the expansion if one is found
            if (foundFrom && foundTo)
            {
                return(new ListPathTraversalNode(chosenFrom, chosenTo, sampleRect));
            }
            else
            {
                return(null);
            }
        }
예제 #14
0
        private protected static List <List <RoomHallIndex> > GetBranchArms(FloorPlan floorPlan)
        {
            List <ListPathTraversalNode> endBranches = new List <ListPathTraversalNode>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                FloorRoomPlan roomPlan = floorPlan.GetRoomPlan(ii);
                if (roomPlan.Adjacents.Count == 1)
                {
                    endBranches.Add(new ListPathTraversalNode(new RoomHallIndex(-1, false), new RoomHallIndex(ii, false)));
                }
            }

            List <List <RoomHallIndex> > branchArms = new List <List <RoomHallIndex> >();

            for (int nn = 0; nn < endBranches.Count; nn++)
            {
                ListPathTraversalNode chosenBranch = endBranches[nn];
                List <RoomHallIndex>  arm          = new List <RoomHallIndex>();

                while (true)
                {
                    List <RoomHallIndex> connectors = new List <RoomHallIndex>();
                    List <RoomHallIndex> adjacents  = floorPlan.GetRoomHall(chosenBranch.To).Adjacents;
                    foreach (RoomHallIndex dest in adjacents)
                    {
                        if (dest != chosenBranch.From)
                        {
                            connectors.Add(dest);
                        }
                    }

                    if (connectors.Count == 1)
                    {
                        arm.Add(chosenBranch.To);
                        chosenBranch = new ListPathTraversalNode(chosenBranch.To, connectors[0]);
                    }
                    else if (connectors.Count == 0)
                    {
                        // we've reached the other side of a single line; add
                        arm.Add(chosenBranch.To);

                        // but also find the other pending arm and remove it
                        for (int ii = endBranches.Count - 1; ii > nn; ii--)
                        {
                            ListPathTraversalNode otherBranch = endBranches[ii];
                            if (chosenBranch.To == otherBranch.To)
                            {
                                endBranches.RemoveAt(ii);
                            }
                        }

                        // end the loop
                        break;
                    }
                    else
                    {
                        break;
                    }
                }

                branchArms.Add(arm);
            }

            return(branchArms);
        }
예제 #15
0
        public virtual FloorPathBranch <T> .ListPathBranchExpansion?ChooseRoomExpansion(IRandom rand, FloorPlan floorPlan)
        {
            List <RoomHallIndex> availableExpansions = new List <RoomHallIndex>();

            for (int ii = 0; ii < floorPlan.RoomCount; ii++)
            {
                if (!BaseRoomFilter.PassesAllFilters(floorPlan.GetRoomPlan(ii), this.Filters))
                {
                    continue;
                }
                availableExpansions.Add(new RoomHallIndex(ii, false));
            }

            for (int ii = 0; ii < floorPlan.HallCount; ii++)
            {
                if (!BaseRoomFilter.PassesAllFilters(floorPlan.GetHallPlan(ii), this.Filters))
                {
                    continue;
                }
                availableExpansions.Add(new RoomHallIndex(ii, true));
            }

            return(FloorPathBranch <T> .ChooseRoomExpansion(this.PrepareRoom, this.HallPercent, rand, floorPlan, availableExpansions));
        }
예제 #16
0
 public abstract void ApplyToPath(IRandom rand, FloorPlan floorPlan);