示例#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
        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 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);
        }
示例#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
 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));
     }
 }
示例#7
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);
        }
示例#8
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);
        }
示例#9
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);
            }
        }
示例#10
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);
        }
示例#11
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;
            }
        }