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--; } }
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()}"); }