示例#1
0
        /// <summary>
        /// Choose a random point on the outside edge of this rectangle
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="rng"></param>
        /// <param name="endOffset"></param>
        /// <param name="i"></param>
        /// <param name="j"></param>
        public void RandomPointOnEdge(CompassDirection edge, Random rng, int endOffset, ref int i, ref int j)
        {
            if (edge == CompassDirection.North)
            {
                j = YMax + 1;
            }
            else if (edge == CompassDirection.East)
            {
                i = XMax + 1;
            }
            else if (edge == CompassDirection.South)
            {
                j = YMin - 1;
            }
            else if (edge == CompassDirection.West)
            {
                i = XMin - 1;
            }

            if (edge.IsHorizontal())
            {
                j = rng.Next(YMin, YMax - endOffset + 1);
            }
            else
            {
                i = rng.Next(XMin, XMax - endOffset + 1);
            }
        }
示例#2
0
        public bool GrowRoom(int iDoor, int jDoor, RoomTemplate template, CompassDirection direction, bool createDoor, Room parent)
        {
            bool result   = false;
            int  doorSize = template.EntryWidth;
            var  bounds   = new IntRectangle(iDoor, jDoor); // Current room bounds
            bool iFrozen  = false;                          // Is growth in the x-direction frozen?
            bool jFrozen  = false;                          // Is growth in the y-direction frozen?
            //Generate target dimensions:
            var dimensions = new IntInterval(
                template.Dimension1.Random(_RNG), template.Dimension2.Random(_RNG));

            //Create starting tiles in front of doorway:
            bounds.Move(direction, 1);
            if (direction == CompassDirection.North || direction == CompassDirection.South)
            {
                bounds.Grow(CompassDirection.East, doorSize - 1);
            }
            else
            {
                bounds.Grow(CompassDirection.North, doorSize - 1);
            }

            if (CheckAvailability(bounds))
            {
                // Grow outwards, checking availability:
                CompassDirection growDirection = direction;
                int persistance = 5; //Failures before abort
                while (persistance > 0)
                {
                    if (!(iFrozen && growDirection.IsHorizontal()) &&
                        !(jFrozen && growDirection.IsVertical()))
                    {
                        if (CheckAvailability(bounds.GrowZone(growDirection, 1)))
                        {
                            bounds.Grow(growDirection, 1);
                        }
                        else
                        {
                            persistance--;
                        }
                    }

                    if (bounds.XSize + 1 >= dimensions.Max)
                    {
                        iFrozen = true;
                    }
                    if (bounds.XSize + 1 > dimensions.Min && bounds.YSize + 1 == dimensions.Min)
                    {
                        jFrozen = true;
                    }

                    if (bounds.YSize + 1 >= dimensions.Max)
                    {
                        jFrozen = true;
                    }
                    if (bounds.YSize + 1 > dimensions.Min && bounds.XSize + 1 == dimensions.Min)
                    {
                        iFrozen = true;
                    }

                    if (jFrozen && iFrozen)
                    {
                        persistance = 0;
                    }
                    else
                    {
                        growDirection = ExitDirection(template.ExitPlacement, direction); //TODO: ExitPlacement from RoomTemplate?
                    }
                }

                if (template.RoomType == RoomType.Circulation &&
                    (!PreventParallelCorridors || IsParallelToCorridor(bounds)))
                {
                    return(false); //Abort parallel corridors
                }
                if ((bounds.XSize + 1 >= template.Dimension1.Min && bounds.YSize + 1 >= template.Dimension2.Min ||
                     (bounds.XSize + 1 >= template.Dimension2.Min && bounds.YSize + 1 >= template.Dimension1.Min)))
                {
                    // Reached target size - create room

                    // Create doorway:
                    if (createDoor)
                    {
                        GenerateDoorway(iDoor, jDoor, direction, doorSize);
                    }

                    // Create room:
                    Room newRoom = GenerateRoom(bounds, template);

                    //Take snapshot:
                    TakeSnapshot();

                    if (template.RoomType == RoomType.Exit)
                    {
                        ExitPlaced = true;
                    }

                    //TODO: Store room & connections
                    if (template.RoomType != RoomType.Circulation)
                    {
                        result = true;                                            //Circulation rooms cannot validate chains
                    }
                    //Sprout new rooms:

                    int tries = template.SproutTries;
                    CompassDirection doorDirection = direction;
                    int  iNewDoor     = 0;
                    int  jNewDoor     = 0;
                    bool symmetryLock = true;
                    while (tries > 0 &&
                           (template.MaxConnections < 0 ||
                            newRoom.Connections.Count < template.MaxConnections))
                    {
                        RoomTemplate nextRoom = NextRoom(template);

                        if (nextRoom != null)
                        {
                            int newDoorWidth = nextRoom.EntryWidth;

                            if (!symmetryLock && _RNG.NextDouble() < template.SymmetryChance)
                            {
                                symmetryLock = true;
                                //Create door opposite last
                                doorDirection = doorDirection.Reverse();
                            }
                            else
                            {
                                symmetryLock = false;
                                //Select random growth direction:
                                doorDirection = ExitDirection(template.ExitPlacement, direction);
                            }

                            //Select door position for this try:
                            bounds.RandomPointOnEdge(doorDirection, _RNG, newDoorWidth - 1, ref iNewDoor, ref jNewDoor);

                            if (RecursiveGrowth(iNewDoor, jNewDoor, nextRoom, doorDirection, true, newRoom))
                            {
                                result = true;
                            }
                        }
                        tries -= 1;
                    }

                    if (result == false)
                    {
                        DeleteRoom(newRoom);
                    }
                }
            }
            else
            {
                if (createDoor && AreAllType(bounds, CellGenerationType.Void) &&
                    AvailableForDoorway(iDoor, jDoor, direction, template.EntryWidth))
                {
                    // TODO: Check room connections
                    GenerateDoorway(iDoor, jDoor, direction, template.EntryWidth);
                }
            }

            return(result);
        }