private void CreateBranches(RoomPrototype firstRoomWrapper)
        {
            var branchDataWrapper = _loadedStructure.NodeMetaData.BranchDataWrapper;

            if (branchDataWrapper == null)
            {
                return;
            }

            var branchPrototypeNames = branchDataWrapper.BranchPrototypeNames;
            var openConnections      = new Stack <RoomPrototypeConnection>(CollectOpenConnections(firstRoomWrapper).Shuffle(_random));

            uint remainingBranchNum;

            if (branchDataWrapper.BranchCount.HasValue)
            {
                remainingBranchNum = branchDataWrapper.BranchCount.Value;
            }
            else if (branchDataWrapper.BranchPercentage.HasValue)
            {
                remainingBranchNum = (uint)(branchDataWrapper.BranchPercentage.Value * openConnections.Count / 100);
            }
            else
            {
                return;
            }

            int extremeCntr      = 100;
            var embeddedDungeons = new ReadOnlyDictionary <string, AbstractDungeonStructure>(_loadedStructure.AbstractStructure.EmbeddedDungeons);

            while (openConnections.Count > 0 && remainingBranchNum > 0 && extremeCntr > 0)
            {
                var connection = openConnections.Pop();
                foreach (var selectedBranchType in branchPrototypeNames.Shuffle(_random))
                {
                    AbstractDungeonStructure embeddedBranchDungeon = _loadedStructure.AbstractStructure.EmbeddedDungeons[selectedBranchType];
                    DungeonNode concretizedDungeonBranch           = DungeonStructureConcretizer.ConcretizeDungeonTree(
                        embeddedBranchDungeon.StartElement,
                        _random,
                        embeddedDungeons);

                    _stepBackCounter.ResetBranch();

                    try
                    {
                        if (GetPossibleRoomsForConnection(connection, concretizedDungeonBranch).Any(BuildPrototypeRoomRecur))
                        {
                            remainingBranchNum--;
                            connection.ParentRoomPrototype.ActualGraphElement.AddSubElement(concretizedDungeonBranch);
                            concretizedDungeonBranch.TraverseDepthFirst().ForEach(n => n.MetaData.AddTag(BRANCH_TAG));
                            break;
                        }
                    }
                    catch (MaxStepsReachedException e)
                    {
                        Debug.LogWarning(e.Message);
                    }
                }

                extremeCntr--;
            }
        }
Example #2
0
        internal static DungeonNode ConcretizeDungeonTree(AbstractDungeonElement inputElement, Random random, ReadOnlyDictionary <string, AbstractDungeonStructure> embeddedDungeons)
        {
            {
                if (inputElement is NodeElement node)
                {
                    DungeonNode copyNode;
                    if (node.IsEndNode)
                    {
                        copyNode = new DungeonNode(node.Style, (NodeMetaData)node.ElementMetaData.Clone());
                    }
                    else
                    {
                        List <DungeonNode> subElements = node.SubElements.Select(element => ConcretizeDungeonTree(element, random, embeddedDungeons)).ToList();
                        copyNode = new DungeonNode(node.Style, (NodeMetaData)node.ElementMetaData.Clone(), subElements);
                    }

                    return(copyNode);
                }
            }
            {
                if (inputElement is ConnectionElement connection)
                {
                    var         connectionLength = connection.Length.RandomNumberInRange(random);
                    DungeonNode replacementNode  = null;
                    if (connection.SubElements.Count == 1)
                    {
                        DungeonNode nextElement = ConcretizeDungeonTree(connection.SubElements.Single(), random, embeddedDungeons);
                        replacementNode = nextElement;
                    }

                    for (int i = 0; i < connectionLength; i++)
                    {
                        replacementNode = replacementNode != null
                            ? new DungeonNode(connection.Style, (NodeMetaData)connection.ElementMetaData.Clone(), new List <DungeonNode> {
                            replacementNode
                        })
                            : new DungeonNode(connection.Style, (NodeMetaData)connection.ElementMetaData.Clone());
                    }

                    if (replacementNode == null)
                    {
                        throw new Exception("This should not happen");
                    }

                    return(replacementNode);
                }
            }

            {
                if (inputElement is NestedDungeon nested)
                {
                    DungeonNode[] abstractSubElements = nested.SubElements.Select(element => ConcretizeDungeonTree(element, random, embeddedDungeons)).ToArray();
                    DungeonNode   nestedStartNode     = ConcretizeStructure(embeddedDungeons[nested.Path], random).StartElement;

                    nestedStartNode.TraverseDepthFirst().ForEach(x => x.MetaData.AddTag(NESTED_TAG));

                    if (abstractSubElements.Length > 0)
                    {
                        List <DungeonNode> endNodeCollector = new List <DungeonNode>();
                        CollectEndNodes(nestedStartNode, endNodeCollector);

                        endNodeCollector.Shuffle(random);

                        for (int i = 0; i < abstractSubElements.Length; i++)
                        {
                            endNodeCollector[i].AddSubElement(abstractSubElements[i]);
                        }
                    }

                    return(nestedStartNode);
                }
            }

            throw
                new Exception($"Unknown AbstractDungeonElement type: {inputElement.GetType()}");
        }