示例#1
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            // random per room, not per-tile
            var spawningRooms = new SpawnList <RoomHallIndex>();
            var terminalRooms = new SpawnList <RoomHallIndex>();

            // TODO: higher likelihoods for terminals at the ends of longer paths
            for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++)
            {
                spawningRooms.Add(new RoomHallIndex(ii, false));
                List <int> adjacent = map.RoomPlan.GetAdjacentRooms(ii);
                if (adjacent.Count == 1)
                {
                    terminalRooms.Add(new RoomHallIndex(ii, false));
                }
            }

            if (this.IncludeHalls)
            {
                for (int ii = 0; ii < map.RoomPlan.HallCount; ii++)
                {
                    spawningRooms.Add(new RoomHallIndex(ii, true));
                    List <RoomHallIndex> adjacent = map.RoomPlan.GetRoomHall(new RoomHallIndex(ii, true)).Adjacents;
                    if (adjacent.Count == 1)
                    {
                        terminalRooms.Add(new RoomHallIndex(ii, true));
                    }
                }
            }

            // first attempt to spawn in the terminals; remove from terminal list if successful
            this.SpawnRandInCandRooms(map, terminalRooms, spawns, 0);

            this.SpawnRandInCandRooms(map, spawningRooms, spawns, 100);
        }
示例#2
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            // random per room, not per-tile
            var spawningRooms = new SpawnList <RoomHallIndex>();

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

            if (this.IncludeHalls)
            {
                for (int ii = 0; ii < map.RoomPlan.HallCount; ii++)
                {
                    if (!BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetHallPlan(ii), this.Filters))
                    {
                        continue;
                    }
                    spawningRooms.Add(new RoomHallIndex(ii, true), 10);
                }
            }

            this.SpawnRandInCandRooms(map, spawningRooms, spawns, 100);
        }
示例#3
0
        public virtual void SpawnRandInCandRooms(TGenContext map, SpawnList <RoomHallIndex> spawningRooms, List <TSpawnable> spawns, int successPercent)
        {
            while (spawningRooms.Count > 0 && spawns.Count > 0)
            {
                int           randIndex = spawningRooms.PickIndex(map.Rand);
                RoomHallIndex roomIndex = spawningRooms.GetSpawn(randIndex);

                // try to spawn the item
                if (this.SpawnInRoom(map, roomIndex, spawns[spawns.Count - 1]))
                {
                    GenContextDebug.DebugProgress("Placed Object");

                    // remove the item spawn
                    spawns.RemoveAt(spawns.Count - 1);

                    if (successPercent <= 0)
                    {
                        spawningRooms.RemoveAt(randIndex);
                    }
                    else
                    {
                        int newRate = Math.Max(1, spawningRooms.GetSpawnRate(randIndex) * successPercent / 100);
                        spawningRooms.SetSpawnRate(randIndex, newRate);
                    }
                }
                else
                {
                    spawningRooms.RemoveAt(randIndex);
                }
            }
        }
示例#4
0
 protected SpawnList(SpawnList <T> other)
 {
     this.spawns = new List <SpawnRate>(other.spawns);
     foreach (SpawnRate item in other.spawns)
     {
         this.spawns.Add(new SpawnRate(item.Spawn, item.Rate));
     }
 }
示例#5
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            // gather up all rooms and put in a spawn list
            // rooms that are farther from the start are more likely to have items
            var spawningRooms = new SpawnList <RoomHallIndex>();
            Dictionary <RoomHallIndex, int> roomWeights = new Dictionary <RoomHallIndex, int>();

            // get the start room
            int startRoom = 0;

            for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++)
            {
                FloorRoomPlan room = map.RoomPlan.GetRoomPlan(ii);
                if (Collision.InBounds(room.RoomGen.Draw, map.GetLoc(0)))
                {
                    startRoom = ii;
                    break;
                }
            }

            int maxVal = 1;

            void NodeAct(RoomHallIndex nodeIndex, int distance)
            {
                roomWeights[nodeIndex] = distance + 1;
                maxVal = Math.Max(maxVal, roomWeights[nodeIndex]);
            }

            Graph.TraverseBreadthFirst(new RoomHallIndex(startRoom, false), NodeAct, map.RoomPlan.GetAdjacents);

            int multFactor = int.MaxValue / maxVal / roomWeights.Count;

            foreach (RoomHallIndex idx in roomWeights.Keys)
            {
                IFloorRoomPlan room = map.RoomPlan.GetRoomHall(idx);
                if (idx.IsHall && !this.IncludeHalls)
                {
                    continue;
                }
                if (!BaseRoomFilter.PassesAllFilters(room, this.Filters))
                {
                    continue;
                }
                if (roomWeights[idx] == 0)
                {
                    continue;
                }
                spawningRooms.Add(idx, roomWeights[idx] * multFactor);
            }

            this.SpawnRandInCandRooms(map, spawningRooms, spawns, this.SuccessPercent);
        }
示例#6
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);
            }
        }
示例#7
0
 public CategorySpawnChooser(CategorySpawnChooser <T> other)
 {
     Spawns = new SpawnDict <string, SpawnList <T> >();
     foreach (string key in other.Spawns.GetKeys())
     {
         SpawnList <T> list      = new SpawnList <T>();
         SpawnList <T> otherList = other.Spawns.GetSpawn(key);
         for (int ii = 0; ii < otherList.Count; ii++)
         {
             list.Add(otherList.GetSpawn(ii), otherList.GetSpawnRate(ii));
         }
         Spawns.Add(key, list, other.Spawns.GetSpawnRate(key));
     }
 }
示例#8
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);
        }
示例#9
0
        public SpawnList <T> GetSpawnList(int level)
        {
            SpawnList <T> newList = new SpawnList <T>();

            foreach (SpawnRange spawn in this.spawns)
            {
                if (spawn.Range.Min <= level && level < spawn.Range.Max)
                {
                    newList.Add(spawn.Spawn, spawn.Rate);
                }
            }

            return(newList);
        }
示例#10
0
        public T Pick(IRandom rand)
        {
            SpawnDict <string, SpawnList <T> > tempSpawn = new SpawnDict <string, SpawnList <T> >();

            foreach (string key in Spawns.GetKeys())
            {
                SpawnList <T> otherList = Spawns.GetSpawn(key);
                if (!otherList.CanPick)
                {
                    continue;
                }
                tempSpawn.Add(key, otherList, Spawns.GetSpawnRate(key));
            }
            SpawnList <T> choice = tempSpawn.Pick(rand);

            return(choice.Pick(rand));
        }
示例#11
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            // gather up all rooms and put in a spawn list
            // rooms that are farther from the start are more likely to have items
            var spawningRooms = new SpawnList <RoomHallIndex>();

            int[] roomWeights = new int[map.RoomPlan.RoomCount];

            // get the start room
            int startRoom = 0;

            for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++)
            {
                IRoomGen room = map.RoomPlan.GetRoom(ii);
                if (Collision.InBounds(room.Draw, map.GetLoc(0)))
                {
                    startRoom = ii;
                    break;
                }
            }

            int maxVal = 1;

            void NodeAct(int nodeIndex, int distance)
            {
                roomWeights[nodeIndex] = distance + 1;
                maxVal = Math.Max(maxVal, roomWeights[nodeIndex]);
            }

            List <int> GetAdjacents(int nodeIndex) => map.RoomPlan.GetAdjacentRooms(nodeIndex);

            Graph.TraverseBreadthFirst(roomWeights.Length, startRoom, NodeAct, GetAdjacents);

            int multFactor = int.MaxValue / maxVal / roomWeights.Length;

            for (int ii = 0; ii < roomWeights.Length; ii++)
            {
                spawningRooms.Add(new RoomHallIndex(ii, false), roomWeights[ii] * multFactor);
            }

            this.SpawnRandInCandRooms(map, spawningRooms, spawns, this.SuccessPercent);
        }
示例#12
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            // random per room, not per-tile
            var spawningRooms = new SpawnList <RoomHallIndex>();

            for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++)
            {
                spawningRooms.Add(new RoomHallIndex(ii, false));
            }

            if (this.IncludeHalls)
            {
                for (int ii = 0; ii < map.RoomPlan.HallCount; ii++)
                {
                    spawningRooms.Add(new RoomHallIndex(ii, true));
                }
            }

            this.SpawnRandInCandRooms(map, spawningRooms, spawns, 100);
        }
示例#13
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);
            }
        }
示例#14
0
        public SpawnList <Loc> GetPossiblePlacements(Dictionary <Dir4, List <IRoomGen> > adjacentsByDir, IRoomGen newGen, IRoomGen oldGen)
        {
            // test all positions around perimeter
            Rect            oldRect            = oldGen.Draw;
            SpawnList <Loc> possiblePlacements = new SpawnList <Loc>();

            // top and bottom
            for (int xx = oldRect.Left; xx < oldRect.Right - newGen.Draw.Width + 1; xx++)
            {
                Loc topLoc   = new Loc(xx, oldRect.Top);
                int topMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, topLoc);
                if (topMatch > 0)
                {
                    possiblePlacements.Add(topLoc, topMatch);
                }

                Loc bottomLoc = new Loc(xx, oldRect.Bottom - newGen.Draw.Height);
                if (bottomLoc != topLoc)
                {
                    int bottomMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, bottomLoc);
                    if (bottomMatch > 0)
                    {
                        possiblePlacements.Add(bottomLoc, bottomMatch);
                    }
                }
            }

            // left and right
            for (int yy = oldRect.Top + 1; yy < oldRect.Bottom - newGen.Draw.Height; yy++)
            {
                Loc leftLoc   = new Loc(oldRect.Left, yy);
                int leftMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, leftLoc);
                if (leftMatch > 0)
                {
                    possiblePlacements.Add(leftLoc, leftMatch);
                }

                Loc rightLoc = new Loc(oldRect.Right - newGen.Draw.Width, yy);
                if (rightLoc != leftLoc)
                {
                    int rightMatch = this.GetAllBorderMatch(adjacentsByDir, newGen, oldGen, rightLoc);
                    if (rightMatch > 0)
                    {
                        possiblePlacements.Add(rightLoc, rightMatch);
                    }
                }
            }

            if (possiblePlacements.SpawnTotal == 0)
            {
                if (oldRect.Width >= newGen.Draw.Width + 2 &&
                    oldRect.Height >= newGen.Draw.Height + 2)
                {
                    for (int xx = oldRect.Left + 1; xx < oldRect.Right - newGen.Draw.Width; xx++)
                    {
                        for (int yy = oldRect.Top + 1; yy < oldRect.Bottom - newGen.Draw.Height; yy++)
                        {
                            possiblePlacements.Add(new Loc(xx, yy), 1);
                        }
                    }
                }
            }

            return(possiblePlacements);
        }
示例#15
0
        public Loc FindPlacement(IRandom rand, Dictionary <Dir4, List <IRoomGen> > adjacentsByDir, IRoomGen newGen, IRoomGen oldGen)
        {
            SpawnList <Loc> possiblePlacements = this.GetPossiblePlacements(adjacentsByDir, newGen, oldGen);

            return(possiblePlacements.SpawnTotal == 0 ? new Loc(-1) : possiblePlacements.Pick(rand));
        }
示例#16
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;
            }
        }
示例#17
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);
        }