Beispiel #1
0
        public override void DrawOnMap(T map)
        {
            for (int x = 0; x < this.Draw.Size.X; x++)
            {
                for (int y = 0; y < this.Draw.Size.Y; y++)
                {
                    map.SetTile(new Loc(this.Draw.X + x, this.Draw.Y + y), map.RoomTerrain.Copy());
                }
            }

            GenContextDebug.DebugProgress("Room Rect");

            Loc blockSize  = new Loc(Math.Min(this.BlockWidth.Pick(map.Rand), this.Draw.Size.X - 2), Math.Min(this.BlockHeight.Pick(map.Rand), this.Draw.Size.Y - 2));
            Loc blockStart = new Loc(this.Draw.X + map.Rand.Next(1, this.Draw.Size.X - blockSize.X - 1), this.Draw.Y + map.Rand.Next(1, this.Draw.Size.Y - blockSize.Y - 1));

            for (int x = 0; x < blockSize.X; x++)
            {
                for (int y = 0; y < blockSize.Y; y++)
                {
                    map.SetTile(new Loc(blockStart.X + x, blockStart.Y + y), this.BlockTerrain.Copy());
                }
            }

            GenContextDebug.DebugProgress("Block Rect");

            // hall restrictions
            this.SetRoomBorders(map);
        }
Beispiel #2
0
        public override void ApplyToPath(IRandom rand, FloorPlan floorPlan)
        {
            int amount = this.Amount.Pick(rand);

            for (int kk = 0; kk < amount; kk++)
            {
                FloorPathBranch <T> .ListPathBranchExpansion?expansionResult = this.ChooseRoomExpansion(rand, floorPlan);

                if (!expansionResult.HasValue)
                {
                    continue;
                }

                var expansion = expansionResult.Value;

                RoomHallIndex from = expansion.From;
                if (expansion.Hall != null)
                {
                    floorPlan.AddHall(expansion.Hall, this.HallComponents.Clone(), from);
                    from = new RoomHallIndex(floorPlan.HallCount - 1, true);
                }

                floorPlan.AddRoom(expansion.Room, this.RoomComponents.Clone(), from);

                GenContextDebug.DebugProgress("Extended with Room");
            }
        }
Beispiel #3
0
        private (int area, int rooms) ExpandPath(IRandom rand, FloorPlan floorPlan, bool branch)
        {
            ListPathBranchExpansion?expansionResult = this.ChooseRoomExpansion(rand, floorPlan, branch);

            if (!expansionResult.HasValue)
            {
                return(0, 0);
            }

            var expansion = expansionResult.Value;

            int tilesCovered = 0;
            int roomsAdded   = 0;

            RoomHallIndex from = expansion.From;

            if (expansion.Hall != null)
            {
                floorPlan.AddHall(expansion.Hall, this.HallComponents.Clone(), from);
                from          = new RoomHallIndex(floorPlan.HallCount - 1, true);
                tilesCovered += expansion.Hall.Draw.Area;
                roomsAdded++;
            }

            floorPlan.AddRoom(expansion.Room, this.RoomComponents.Clone(), from);
            tilesCovered += expansion.Room.Draw.Area;
            roomsAdded++;
            GenContextDebug.DebugProgress(branch ? "Branched Path" : "Extended Path");

            // report the added area coverage
            return(tilesCovered, roomsAdded);
        }
Beispiel #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");
            }
        }
Beispiel #5
0
        // an initial create-map method
        public T GenMap(ulong seed)
        {
            // may not need floor ID
            T map = (T)Activator.CreateInstance(typeof(T));

            map.InitSeed(seed);

            GenContextDebug.DebugInit(map);

            // postprocessing steps:
            StablePriorityQueue <Priority, IGenStep> queue = new StablePriorityQueue <Priority, IGenStep>();

            foreach (Priority priority in this.GenSteps.GetPriorities())
            {
                foreach (IGenStep genStep in this.GenSteps.GetItems(priority))
                {
                    queue.Enqueue(priority, genStep);
                }
            }

            ApplyGenSteps(map, queue);

            map.FinishGen();

            return(map);
        }
Beispiel #6
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            List <Loc> freeTiles = new List <Loc>();

            for (int xx = 0; xx < map.Width; xx++)
            {
                for (int yy = 0; yy < map.Height; yy++)
                {
                    ITile tile = map.GetTile(new Loc(xx, yy));

                    if (tile.TileEquivalent(this.Terrain))
                    {
                        freeTiles.Add(new Loc(xx, yy));
                    }
                }
            }

            for (int ii = 0; ii < spawns.Count && freeTiles.Count > 0; ii++)
            {
                TSpawnable item = spawns[ii];

                int randIndex = map.Rand.Next(freeTiles.Count);
                map.PlaceItem(freeTiles[randIndex], item);
                freeTiles.RemoveAt(randIndex);
                GenContextDebug.DebugProgress("Placed Object");
            }
        }
Beispiel #7
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);
                }
            }
        }
Beispiel #8
0
        public override void Apply(TGenContext map)
        {
            Loc defaultLoc = Loc.Zero;

            for (int ii = 0; ii < this.Entrance.Count; ii++)
            {
                Loc start = GetOutlet <TEntrance>(map);
                if (start == new Loc(-1))
                {
                    start = defaultLoc;
                }
                else
                {
                    defaultLoc = start;
                }
                ((IPlaceableGenContext <TEntrance>)map).PlaceItem(start, this.Entrance[ii]);
                GenContextDebug.DebugProgress(nameof(this.Entrance));
            }

            for (int ii = 0; ii < this.Exit.Count; ii++)
            {
                Loc end = GetOutlet <TExit>(map);
                if (end == new Loc(-1))
                {
                    end = defaultLoc;
                }
                ((IPlaceableGenContext <TExit>)map).PlaceItem(end, this.Exit[ii]);
                GenContextDebug.DebugProgress(nameof(this.Exit));
            }
        }
        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");
            }
        }
Beispiel #10
0
 public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
 {
     for (int ii = 0; ii < spawns.Count && ii < this.SpawnLocs.Count; ii++)
     {
         TSpawnable item = spawns[ii];
         map.PlaceItem(this.SpawnLocs[ii], item);
         GenContextDebug.DebugProgress("Placed Object");
     }
 }
Beispiel #11
0
 public static void UnsafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, ComponentCollection components)
 {
     floorPlan.SetHall(locRay, hallGen, components.Clone());
     GenContextDebug.DebugProgress("Hall");
     if (floorPlan.GetRoomPlan(locRay.Loc) == null || floorPlan.GetRoomPlan(locRay.Traverse(1)) == null)
     {
         floorPlan.Clear();
         throw new InvalidOperationException("Can't create a hall without rooms to connect!");
     }
 }
Beispiel #12
0
 protected static void ApplyGenSteps(T map, StablePriorityQueue <Priority, IGenStep> queue)
 {
     while (queue.Count > 0)
     {
         IGenStep postProc = queue.Dequeue();
         GenContextDebug.StepIn(postProc.ToString());
         postProc.Apply(map);
         GenContextDebug.StepOut();
     }
 }
Beispiel #13
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);
                }
            }
        }
Beispiel #14
0
        public override void DistributeSpawns(TGenContext map, List <TSpawnable> spawns)
        {
            List <Loc> freeTiles = map.GetAllFreeTiles();

            for (int ii = 0; ii < spawns.Count && freeTiles.Count > 0; ii++)
            {
                TSpawnable item = spawns[ii];

                int randIndex = map.Rand.Next(freeTiles.Count);
                map.PlaceItem(freeTiles[randIndex], item);
                freeTiles.RemoveAt(randIndex);
                GenContextDebug.DebugProgress("Placed Object");
            }
        }
Beispiel #15
0
        protected bool ExpandPath(IRandom rand, GridPlan floorPlan, bool branch)
        {
            LocRay4 chosenRay = this.ChooseRoomExpansion(rand, floorPlan, branch);

            if (chosenRay.Dir == Dir4.None)
            {
                return(false);
            }
            floorPlan.SetHall(chosenRay, this.GenericHalls.Pick(rand));
            floorPlan.AddRoom(chosenRay.Traverse(1), this.GenericRooms.Pick(rand));

            GenContextDebug.DebugProgress(branch ? "Branched Path" : "Extended Path");
            return(true);
        }
        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);
                }
            }
        }
Beispiel #17
0
        public override void Apply(T map)
        {
            Loc start = map.RoomPlan.Size;
            Loc end   = Loc.Zero;

            foreach (IRoomPlan plan in map.RoomPlan.GetAllPlans())
            {
                Rect roomRect = plan.RoomGen.Draw;
                start = new Loc(Math.Min(start.X, roomRect.Start.X), Math.Min(start.Y, roomRect.Start.Y));
                end   = new Loc(Math.Max(end.X, roomRect.End.X), Math.Max(end.Y, roomRect.End.Y));
            }

            map.RoomPlan.Resize(end, Dir8.DownRight, Dir8.UpLeft);
            map.RoomPlan.Resize(end, Dir8.UpLeft, Dir8.DownRight);
            GenContextDebug.DebugProgress("Clamped Floor");
        }
Beispiel #18
0
        public override void Apply(TGenContext map)
        {
            List <int> room_indices = new List <int>();

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

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

            Loc defaultLoc = Loc.Zero;

            for (int ii = 0; ii < this.Entrances.Count; ii++)
            {
                int startRoom = NextRoom(map.Rand, room_indices, used_indices);
                Loc start     = GetOutlet <TEntrance>(map, startRoom);
                if (start == new Loc(-1))
                {
                    start = defaultLoc;
                }
                else
                {
                    defaultLoc = start;
                }
                ((IPlaceableGenContext <TEntrance>)map).PlaceItem(start, this.Entrances[ii]);
                GenContextDebug.DebugProgress(nameof(this.Entrances));
            }

            for (int ii = 0; ii < this.Exits.Count; ii++)
            {
                int endRoom = NextRoom(map.Rand, room_indices, used_indices);
                Loc end     = GetOutlet <TExit>(map, endRoom);
                if (end == new Loc(-1))
                {
                    end = defaultLoc;
                }
                ((IPlaceableGenContext <TExit>)map).PlaceItem(end, this.Exits[ii]);
                GenContextDebug.DebugProgress(nameof(this.Exits));
            }
        }
Beispiel #19
0
        public override void Apply(T map)
        {
            // draw on map
            map.CreateNew(
                map.RoomPlan.DrawRect.Width + (2 * this.Padding),
                map.RoomPlan.DrawRect.Height + (2 * this.Padding));
            for (int ii = 0; ii < map.Width; ii++)
            {
                for (int jj = 0; jj < map.Height; jj++)
                {
                    map.SetTile(new Loc(ii, jj), map.WallTerrain.Copy());
                }
            }

            map.RoomPlan.MoveStart(new Loc(this.Padding));
            GenContextDebug.DebugProgress("Moved Floor");
            map.RoomPlan.DrawOnMap(map);
        }
Beispiel #20
0
        public void DrawOnMap(ITiledGenContext map)
        {
            GenContextDebug.StepIn("Main Rooms");
            for (int ii = 0; ii < this.Rooms.Count; ii++)
            {
                // take in the broad fulfillables from adjacent rooms that have not yet drawn
                IFloorRoomPlan plan = this.Rooms[ii];
                foreach (RoomHallIndex adj in plan.Adjacents)
                {
                    if (adj.IsHall || adj.Index > ii)
                    {
                        IRoomGen adjacentGen = this.GetRoomHall(adj).RoomGen;
                        plan.RoomGen.ReceiveFulfillableBorder(adjacentGen, GetDirAdjacent(plan.RoomGen, adjacentGen));
                    }
                }

                plan.RoomGen.DrawOnMap(map);
                this.TransferBorderToAdjacents(new RoomHallIndex(ii, false));
                GenContextDebug.DebugProgress("Draw Room");
            }

            GenContextDebug.StepOut();

            GenContextDebug.StepIn("Connecting Halls");
            for (int ii = 0; ii < this.Halls.Count; ii++)
            {
                // take in the broad fulfillables from adjacent rooms that have not yet drawn
                IFloorRoomPlan plan = this.Halls[ii];
                foreach (RoomHallIndex adj in plan.Adjacents)
                {
                    if (adj.IsHall && adj.Index > ii)
                    {
                        IRoomGen adjacentGen = this.GetRoomHall(adj).RoomGen;
                        plan.RoomGen.ReceiveFulfillableBorder(adjacentGen, GetDirAdjacent(plan.RoomGen, adjacentGen));
                    }
                }

                plan.RoomGen.DrawOnMap(map);
                this.TransferBorderToAdjacents(new RoomHallIndex(ii, true));
                GenContextDebug.DebugProgress("Draw Hall");
            }

            GenContextDebug.StepOut();
        }
Beispiel #21
0
        /// <summary>
        /// Draws a hall in a straight cardinal direction, starting with one point and ending with another (inclusive).
        /// </summary>
        /// <param name="map"></param>
        /// <param name="point1"></param>
        /// <param name="point2"></param>
        /// <param name="vertical"></param>
        private void DrawHall(ITiledGenContext map, Loc point1, Loc point2, bool vertical)
        {
            if (point1 == point2)
            {
                this.Brush.DrawHallBrush(map, this.Draw, point1, vertical);
            }
            else if (point1.X == point2.X)
            {
                if (point2.Y > point1.Y)
                {
                    for (int ii = point1.Y; ii <= point2.Y; ii++)
                    {
                        this.Brush.DrawHallBrush(map, this.Draw, new Loc(point1.X, ii), vertical);
                    }
                }
                else if (point2.Y < point1.Y)
                {
                    for (int ii = point1.Y; ii >= point2.Y; ii--)
                    {
                        this.Brush.DrawHallBrush(map, this.Draw, new Loc(point1.X, ii), vertical);
                    }
                }
            }
            else if (point1.Y == point2.Y)
            {
                if (point2.X > point1.X)
                {
                    for (int ii = point1.X; ii <= point2.X; ii++)
                    {
                        this.Brush.DrawHallBrush(map, this.Draw, new Loc(ii, point1.Y), vertical);
                    }
                }
                else if (point2.X < point1.X)
                {
                    for (int ii = point1.X; ii >= point2.X; ii--)
                    {
                        this.Brush.DrawHallBrush(map, this.Draw, new Loc(ii, point1.Y), vertical);
                    }
                }
            }

            GenContextDebug.DebugProgress("Hall Line");
        }
Beispiel #22
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;
                    }
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Draws a hall in a straight cardinal direction, starting with one point and ending with another (inclusive).
        /// </summary>
        /// <param name="map"></param>
        /// <param name="point1"></param>
        /// <param name="point2"></param>
        /// <param name="terrain"></param>
        private static void DrawHall(ITiledGenContext map, Loc point1, Loc point2, ITile terrain)
        {
            if (point1 == point2)
            {
                map.SetTile(point1, terrain.Copy());
            }
            else if (point1.X == point2.X)
            {
                if (point2.Y > point1.Y)
                {
                    for (int ii = point1.Y; ii <= point2.Y; ii++)
                    {
                        map.SetTile(new Loc(point1.X, ii), terrain.Copy());
                    }
                }
                else if (point2.Y < point1.Y)
                {
                    for (int ii = point1.Y; ii >= point2.Y; ii--)
                    {
                        map.SetTile(new Loc(point1.X, ii), terrain.Copy());
                    }
                }
            }
            else if (point1.Y == point2.Y)
            {
                if (point2.X > point1.X)
                {
                    for (int ii = point1.X; ii <= point2.X; ii++)
                    {
                        map.SetTile(new Loc(ii, point1.Y), terrain.Copy());
                    }
                }
                else if (point2.X < point1.X)
                {
                    for (int ii = point1.X; ii >= point2.X; ii--)
                    {
                        map.SetTile(new Loc(ii, point1.Y), terrain.Copy());
                    }
                }
            }

            GenContextDebug.DebugProgress("Hall Line");
        }
Beispiel #24
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            if (floorPlan.GridWidth != this.SpecificVHalls.Length ||
                floorPlan.GridWidth - 1 != this.SpecificHHalls.Length ||
                floorPlan.GridHeight - 1 != this.SpecificVHalls[0].Length ||
                floorPlan.GridHeight != this.SpecificHHalls[0].Length)
            {
                throw new InvalidOperationException("Incorrect hall path sizes.");
            }

            foreach (var chosenRoom in this.SpecificRooms)
            {
                floorPlan.AddRoom(chosenRoom.Bounds, chosenRoom.RoomGen, chosenRoom.Components.Clone(), chosenRoom.PreferHall);
                GenContextDebug.DebugProgress("Room");
            }

            // place halls
            for (int x = 0; x < this.SpecificVHalls.Length; x++)
            {
                for (int y = 0; y < this.SpecificHHalls[0].Length; y++)
                {
                    if (x > 0)
                    {
                        if (this.SpecificHHalls[x - 1][y] != null)
                        {
                            UnsafeAddHall(new LocRay4(new Loc(x, y), Dir4.Left), floorPlan, this.SpecificHHalls[x - 1][y], this.HallComponents);
                        }
                    }

                    if (y > 0)
                    {
                        if (this.SpecificVHalls[x][y - 1] != null)
                        {
                            UnsafeAddHall(new LocRay4(new Loc(x, y), Dir4.Up), floorPlan, this.SpecificVHalls[x][y - 1], this.HallComponents);
                        }
                    }
                }
            }
        }
Beispiel #25
0
        protected void DrawBlob(T map, BlobMap blobMap, int index, Loc offset, bool encroach)
        {
            BlobMap.Blob mapBlob = blobMap.Blobs[index];
            for (int xx = Math.Max(0, offset.X); xx < Math.Min(map.Width, offset.X + mapBlob.Bounds.Width); xx++)
            {
                for (int yy = Math.Max(0, offset.Y); yy < Math.Min(map.Height, offset.Y + mapBlob.Bounds.Height); yy++)
                {
                    Loc destLoc = new Loc(xx, yy);
                    Loc srcLoc  = destLoc + mapBlob.Bounds.Start - offset;
                    if (blobMap.Map[srcLoc.X][srcLoc.Y] == index)
                    {
                        // can place anything if encroaching
                        // otherwise, can place anything except roomterrain
                        if (encroach || !map.GetTile(destLoc).TileEquivalent(map.RoomTerrain))
                        {
                            map.TrySetTile(new Loc(xx, yy), this.Terrain.Copy());
                        }
                    }
                }
            }

            GenContextDebug.DebugProgress("Draw Blob");
        }
Beispiel #26
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();
        }
Beispiel #27
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);
            }
        }
Beispiel #28
0
        /// <summary>
        /// Generates the position and size of each room and hall, and places it in the specified IFloorPlanGenContext.
        /// </summary>
        /// <param name="map"></param>
        public void PlaceRoomsOnFloor(IFloorPlanGenContext map)
        {
            // decide on room sizes
            for (int ii = 0; ii < this.ArrayRooms.Count; ii++)
            {
                this.ChooseRoomBounds(map.Rand, ii);
            }

            // decide on halls; write to RoomSideReqs
            for (int xx = 0; xx < this.VHalls.Length; xx++)
            {
                for (int yy = 0; yy < this.VHalls[xx].Length; yy++)
                {
                    this.ChooseHallBounds(map.Rand, xx, yy, true);
                }
            }

            for (int xx = 0; xx < this.HHalls.Length; xx++)
            {
                for (int yy = 0; yy < this.HHalls[xx].Length; yy++)
                {
                    this.ChooseHallBounds(map.Rand, xx, yy, false);
                }
            }

            GenContextDebug.StepIn("Main Rooms");

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

            foreach (var plan in this.ArrayRooms)
            {
                if (plan.PreferHall)
                {
                    roomToHall.Add(new RoomHallIndex(map.RoomPlan.HallCount, true));
                    map.RoomPlan.AddHall((IPermissiveRoomGen)plan.RoomGen, plan.Components);
                    GenContextDebug.DebugProgress("Add Hall Room");
                }
                else
                {
                    roomToHall.Add(new RoomHallIndex(map.RoomPlan.RoomCount, false));
                    map.RoomPlan.AddRoom(plan.RoomGen, plan.Components);
                    GenContextDebug.DebugProgress("Added Room");
                }
            }

            GenContextDebug.StepOut();

            GenContextDebug.StepIn("Connecting Halls");

            for (int xx = 0; xx < this.VHalls.Length; xx++)
            {
                for (int yy = 0; yy < this.VHalls[xx].Length; yy++)
                {
                    GridHallGroup hallGroup = this.VHalls[xx][yy];
                    for (int ii = 0; ii < hallGroup.HallParts.Count; ii++)
                    {
                        List <RoomHallIndex> adj = new List <RoomHallIndex>();
                        if (ii == 0)
                        {
                            int upRoom = this.Rooms[xx][yy];
                            if (upRoom > -1)
                            {
                                adj.Add(roomToHall[upRoom]);
                            }
                        }
                        else
                        {
                            adj.Add(new RoomHallIndex(map.RoomPlan.HallCount - 1, true));
                        }

                        if (ii == hallGroup.HallParts.Count - 1)
                        {
                            int downRoom = this.Rooms[xx][yy + 1];
                            if (downRoom > -1)
                            {
                                adj.Add(roomToHall[downRoom]);
                            }
                        }

                        map.RoomPlan.AddHall(hallGroup.HallParts[ii].RoomGen, hallGroup.HallParts[ii].Components, adj.ToArray());
                        GenContextDebug.DebugProgress("Add Hall");
                    }
                }
            }

            for (int xx = 0; xx < this.HHalls.Length; xx++)
            {
                for (int yy = 0; yy < this.HHalls[xx].Length; yy++)
                {
                    GridHallGroup hallGroup = this.HHalls[xx][yy];

                    for (int ii = 0; ii < hallGroup.HallParts.Count; ii++)
                    {
                        List <RoomHallIndex> adj = new List <RoomHallIndex>();
                        if (ii == 0)
                        {
                            int leftRoom = this.Rooms[xx][yy];
                            if (leftRoom > -1)
                            {
                                adj.Add(roomToHall[leftRoom]);
                            }
                        }
                        else
                        {
                            adj.Add(new RoomHallIndex(map.RoomPlan.HallCount - 1, true));
                        }

                        if (ii == hallGroup.HallParts.Count - 1)
                        {
                            int rightRoom = this.Rooms[xx + 1][yy];
                            if (rightRoom > -1)
                            {
                                adj.Add(roomToHall[rightRoom]);
                            }
                        }

                        map.RoomPlan.AddHall(hallGroup.HallParts[ii].RoomGen, hallGroup.HallParts[ii].Components, adj.ToArray());
                        GenContextDebug.DebugProgress("Add Hall");
                    }
                }
            }

            GenContextDebug.StepOut();
        }
Beispiel #29
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;
                }
            }
        }