Beispiel #1
0
        /// <summary>
        /// Returns a list of wall edges with definite 4-directional normals
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="checkBlock">Determines if this is ground that can be burrowed into.</param>
        /// <param name="checkGround">Determines if this is ground that can reach a wall.</param>
        /// <returns></returns>
        public static List <LocRay4> DetectWalls(Rect rect, Grid.LocTest checkBlock, Grid.LocTest checkGround)
        {
            if (checkBlock == null)
            {
                throw new ArgumentNullException(nameof(checkBlock));
            }

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

            for (int xx = rect.X; xx < rect.Width; xx++)
            {
                for (int yy = rect.Y; yy < rect.Height; yy++)
                {
                    Loc testLoc = new Loc(xx, yy);
                    if (checkBlock(testLoc))
                    {
                        LocRay4 ray = GetWallDir(testLoc, checkBlock, checkGround);
                        if (ray.Dir != Dir4.None)
                        {
                            walls.Add(ray);
                        }
                    }
                }
            }

            return(walls);
        }
Beispiel #2
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 #3
0
        /// <summary>
        /// Sets the RoomGen found in the specified hall.
        /// </summary>
        /// <param name="locRay">The location of the room + the direction of the connecting hall relative to the room.</param>
        /// <param name="hallGen"></param>
        /// <param name="components">components to include in the hall</param>
        public void SetHall(LocRay4 locRay, IPermissiveRoomGen hallGen, ComponentCollection components)
        {
            if (locRay.Dir == Dir4.None)
            {
                throw new ArgumentException("Invalid direction.");
            }
            else if (!locRay.Dir.Validate())
            {
                throw new ArgumentOutOfRangeException("Invalid enum value.");
            }

            GridHallPlan plan = null;

            if (hallGen != null)
            {
                plan = new GridHallPlan((IPermissiveRoomGen)hallGen.Copy(), components);
            }

            switch (locRay.Dir)
            {
            case Dir4.Down:
                if (locRay.Loc.Y < this.GridHeight - 1)
                {
                    this.VHalls[locRay.Loc.X][locRay.Loc.Y].SetHall(plan);
                }
                break;

            case Dir4.Left:
                if (locRay.Loc.X > 0)
                {
                    this.HHalls[locRay.Loc.X - 1][locRay.Loc.Y].SetHall(plan);
                }
                break;

            case Dir4.Up:
                if (locRay.Loc.Y > 0)
                {
                    this.VHalls[locRay.Loc.X][locRay.Loc.Y - 1].SetHall(plan);
                }
                break;

            case Dir4.Right:
                if (locRay.Loc.X < this.GridWidth - 1)
                {
                    this.HHalls[locRay.Loc.X][locRay.Loc.Y].SetHall(plan);
                }
                break;

            case Dir4.None:
                throw new ArgumentException($"No hall for dir {nameof(Dir4.None)}");

            default:
                throw new ArgumentOutOfRangeException(nameof(locRay.Dir), "Invalid enum value.");
            }
        }
Beispiel #4
0
        public int GetRoomNum(LocRay4 locRay)
        {
            GridHallPlan hall = this.GetHall(locRay);

            if (hall != null)
            {
                Loc moveLoc = locRay.Traverse(1);
                return(this.Rooms[moveLoc.X][moveLoc.Y]);
            }

            return(-1);
        }
Beispiel #5
0
        public virtual LocRay4 ChooseRoomExpansion(IRandom rand, GridPlan floorPlan, bool branch)
        {
            List <LocRay4> availableRays = GetPossibleExpansions(floorPlan, branch);

            if (availableRays.Count == 0)
            {
                return(new LocRay4(Dir4.None));
            }

            LocRay4 chosenRay = availableRays[rand.Next(availableRays.Count)];

            return(chosenRay);
        }
Beispiel #6
0
        public static void SafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, IRoomGen roomGen, bool preferHall = false)
        {
            floorPlan.SetHall(locRay, hallGen);
            if (floorPlan.GetRoomPlan(locRay.Loc) == null)
            {
                floorPlan.AddRoom(locRay.Loc, roomGen, false, preferHall);
            }
            Loc dest = locRay.Traverse(1);

            if (floorPlan.GetRoomPlan(dest) == null)
            {
                floorPlan.AddRoom(dest, roomGen, false, preferHall);
            }
        }
Beispiel #7
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);
        }
Beispiel #8
0
        /// <summary>
        /// Returns a list of wall edges with definite 4-directional normals, connected to a start position
        /// </summary>
        /// <param name="start"></param>
        /// <param name="rect"></param>
        /// <param name="checkBlock">Determines if this is ground that can be burrowed into.</param>
        /// <param name="checkGround">Determines if this is ground that can reach a wall.</param>
        /// <returns></returns>
        public static List <LocRay4> DetectWalls(Loc start, Rect rect, Grid.LocTest checkBlock, Grid.LocTest checkGround)
        {
            if (checkBlock == null)
            {
                throw new ArgumentNullException(nameof(checkBlock));
            }
            if (checkGround == null)
            {
                throw new ArgumentNullException(nameof(checkGround));
            }

            bool[][] checkGrid = new bool[rect.Width][];
            bool[][] fillGrid  = new bool[rect.Width][];
            for (int xx = 0; xx < rect.Width; xx++)
            {
                checkGrid[xx] = new bool[rect.Height];
                fillGrid[xx]  = new bool[rect.Height];
            }

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

            // scan and find solely-facing walls
            // cache already-checked walls since flood fill occasionally checks twice
            Grid.FloodFill(
                rect,
                (Loc testLoc) =>
            {
                if (fillGrid[testLoc.X][testLoc.Y])
                {
                    return(true);
                }
                if (!checkGrid[testLoc.X][testLoc.Y] && checkBlock(testLoc))
                {
                    LocRay4 ray = GetWallDir(testLoc, checkBlock, checkGround);
                    if (ray.Dir != Dir4.None)
                    {
                        walls.Add(ray);
                    }
                }

                checkGrid[testLoc.X][testLoc.Y] = true;
                return(!checkGround(testLoc));
            },
                (Loc testLoc) => true,
                (Loc fillLoc) => fillGrid[fillLoc.X][fillLoc.Y] = true,
                start);

            return(walls);
        }
Beispiel #9
0
        public static void SafeAddHall(LocRay4 locRay, GridPlan floorPlan, IPermissiveRoomGen hallGen, IRoomGen roomGen, ComponentCollection roomComponents, ComponentCollection hallComponents, bool preferHall = false)
        {
            floorPlan.SetHall(locRay, hallGen, hallComponents.Clone());
            ComponentCollection collection = preferHall ? hallComponents : roomComponents;

            if (floorPlan.GetRoomPlan(locRay.Loc) == null)
            {
                floorPlan.AddRoom(locRay.Loc, roomGen, collection.Clone(), preferHall);
            }
            Loc dest = locRay.Traverse(1);

            if (floorPlan.GetRoomPlan(dest) == null)
            {
                floorPlan.AddRoom(dest, roomGen, collection.Clone(), preferHall);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Returns the RoomGen found in the specified hall.
        /// </summary>
        /// <param name="locRay">The location of the room + the direction of the connecting hall relative to the room.</param>
        /// <returns></returns>
        public GridHallPlan GetHall(LocRay4 locRay)
        {
            switch (locRay.Dir)
            {
            case Dir4.Down:
                if (locRay.Loc.Y < this.GridHeight - 1)
                {
                    return(this.VHalls[locRay.Loc.X][locRay.Loc.Y].MainHall);
                }
                break;

            case Dir4.Left:
                if (locRay.Loc.X > 0)
                {
                    return(this.HHalls[locRay.Loc.X - 1][locRay.Loc.Y].MainHall);
                }
                break;

            case Dir4.Up:
                if (locRay.Loc.Y > 0)
                {
                    return(this.VHalls[locRay.Loc.X][locRay.Loc.Y - 1].MainHall);
                }
                break;

            case Dir4.Right:
                if (locRay.Loc.X < this.GridWidth - 1)
                {
                    return(this.HHalls[locRay.Loc.X][locRay.Loc.Y].MainHall);
                }
                break;

            case Dir4.None:
                break;

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

            return(null);
        }
Beispiel #11
0
        public override void ApplyToPath(IRandom rand, GridPlan floorPlan)
        {
            List <LocRay4> endBranches = new List <LocRay4>();

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

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

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

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

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

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

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

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

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

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

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