Exemple #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="room"></param>
        /// <param name="dir">Direction from room to hall.</param>
        /// <param name="tier"></param>
        /// <returns></returns>
        public virtual IntRange GetHallTouchRange(IRoomGen room, Dir4 dir, int tier)
        {
            bool vertical = dir.ToAxis() == Axis4.Vert;

            // The hall will touch the entire side of each room under normal circumstances.
            // Things get tricky for a target room that occupies more than one cell.
            // First, try to cover only the part of the target room that's in the cell.
            // If that's not possible, try to extend the hall until it covers one tile of the target room.
            IntRange startRange = room.Draw.GetSide(dir.ToAxis());

            // factor possibletiles into this calculation
            int borderLength = room.GetBorderLength(dir);

            for (int ii = 0; ii < borderLength; ii++)
            {
                if (room.GetFulfillableBorder(dir, ii))
                {
                    startRange.Min += ii;
                    break;
                }
            }

            for (int ii = 0; ii < borderLength; ii++)
            {
                if (room.GetFulfillableBorder(dir, borderLength - 1 - ii))
                {
                    startRange.Max -= ii;
                    break;
                }
            }

            int      tierStart  = vertical ? tier * (this.WidthPerCell + this.CellWall) : tier * (this.HeightPerCell + this.CellWall);
            int      tierLength = vertical ? this.WidthPerCell : this.HeightPerCell;
            IntRange newRange   = new IntRange(Math.Max(startRange.Min, tierStart), Math.Min(startRange.Max, tierStart + tierLength));

            if (newRange.Max <= newRange.Min)
            {
                // try to extend the hall until it covers one tile of the target room.
                // first, note that the current end range is covering the zone between the tier and the edge of the room (inverted)
                // un-invert this and inflate by 1, and you will have a zone that covers 1 tile with the room
                // get the intersection of this zone and the room.
                newRange = new IntRange(Math.Max(startRange.Min, newRange.Max - 1), Math.Min(startRange.Max, newRange.Min + 1));
            }

            return(newRange);
        }
Exemple #2
0
        protected static bool HasBorderOpening(IRoomGen roomFrom, Rect rectTo, Dir4 expandTo)
        {
            Loc diff   = roomFrom.Draw.Start - rectTo.Start; // how far ahead the start of source is to dest
            int offset = diff.GetScalar(expandTo.ToAxis().Orth());

            // Traverse the region that both borders touch
            int sourceLength = roomFrom.GetBorderLength(expandTo);
            int destLength   = rectTo.Size.GetScalar(expandTo.ToAxis().Orth());

            for (int ii = Math.Max(0, offset); ii - offset < sourceLength && ii < destLength; ii++)
            {
                bool sourceFulfill = roomFrom.GetFulfillableBorder(expandTo, ii - offset);
                if (sourceFulfill)
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #3
0
        public static int GetBorderMatch(IRoomGen roomFrom, IRoomGen room, Loc candLoc, Dir4 expandTo)
        {
            int totalMatch = 0;

            Loc diff   = roomFrom.Draw.Start - candLoc; // how far ahead the start of source is to dest
            int offset = diff.GetScalar(expandTo.ToAxis().Orth());

            // Traverse the region that both borders touch
            int sourceLength = roomFrom.GetBorderLength(expandTo);
            int destLength   = room.GetBorderLength(expandTo.Reverse());

            for (int ii = Math.Max(0, offset); ii - offset < sourceLength && ii < destLength; ii++)
            {
                bool sourceFulfill = roomFrom.GetFulfillableBorder(expandTo, ii - offset);
                bool destFulfill   = room.GetFulfillableBorder(expandTo.Reverse(), ii);
                if (sourceFulfill && destFulfill)
                {
                    totalMatch++;
                }
            }

            return(totalMatch);
        }
Exemple #4
0
        /// <summary>
        /// Gets the minimum range along the side of a room that includes all of its fulfillable borders.
        /// Special cases arise if the room is multi-cell.
        /// </summary>
        /// <param name="room"></param>
        /// <param name="dir">Direction from room to hall.</param>
        /// <param name="tier"></param>
        /// <returns></returns>
        public virtual IntRange GetHallTouchRange(IRoomGen room, Dir4 dir, int tier)
        {
            bool vertical = dir.ToAxis() == Axis4.Vert;

            // The hall will touch the whole fulfillable side of each room under normal circumstances.
            // Things get tricky for a target room that occupies more than one cell.
            // First, try to cover only the part of the target room that's in the cell.
            int      tierStart  = vertical ? tier * (this.WidthPerCell + this.CellWall) : tier * (this.HeightPerCell + this.CellWall);
            int      tierLength = vertical ? this.WidthPerCell : this.HeightPerCell;
            IntRange tierRange  = new IntRange(tierStart, tierStart + tierLength);
            IntRange roomRange  = room.Draw.GetSide(dir.ToAxis());

            // factor possibletiles into this calculation
            int borderStart = tierStart - roomRange.Min;

            if (borderStart < 0)
            {
                tierRange.Min -= borderStart;
                borderStart    = 0;
            }

            for (int ii = borderStart; ii < roomRange.Length; ii++)
            {
                if (room.GetFulfillableBorder(dir, ii))
                {
                    break;
                }
                else
                {
                    tierRange.Min += 1;
                }
            }

            int borderEnd = tierStart + tierLength - roomRange.Min;

            if (borderEnd > roomRange.Length)
            {
                tierRange.Max += roomRange.Length - borderEnd;
                borderEnd      = roomRange.Length;
            }

            for (int ii = borderEnd - 1; ii >= 0; ii--)
            {
                if (room.GetFulfillableBorder(dir, ii))
                {
                    break;
                }
                else
                {
                    tierRange.Max -= 1;
                }
            }

            if (tierRange.Max > tierRange.Min)
            {
                return(tierRange);
            }

            // If that's not possible, then it means that the room must have fulfillable tiles outside of the current bound.
            // Try to extend the hall until it covers one fulfillable tile of the target room.
            // Easy method: note that the current tierRange range is covering the zone between the tier and the edge of the room (inverted)
            // There will be either a workable range at the start or a workable range at the end, never neither.
            IntRange startRange = new IntRange(tierRange.Max - 1, tierStart + 1);
            IntRange endRange   = new IntRange(tierStart + tierLength - 1, tierRange.Min + 1);

            bool chooseStart = true;
            bool chooseEnd   = true;

            // if tierRanges reached the absolute limits of the roomRange, then there is no fulfillable tile on that side
            if (startRange.Min < roomRange.Min)
            {
                chooseStart = false;
            }
            else if (endRange.Length > startRange.Length)
            {
                chooseEnd = false;
            }

            if (endRange.Max > roomRange.Max)
            {
                chooseEnd = false;
            }
            else if (startRange.Length > endRange.Length)
            {
                chooseStart = false;
            }

            if (!chooseStart && !chooseEnd)
            {
                throw new ArgumentException("PrepareFulfillableBorders did not open at least one open tile for each direction!");
            }

            if (chooseStart)
            {
                return(startRange);
            }
            return(endRange);
        }