private DialogPoint ReadGame(IEnumerator <char> charEnumer) { ReadGameStates state = ReadGameStates.ReadNothing; Dictionary <int, DialogPoint> dialogPointDictionary = new Dictionary <int, DialogPoint>(); DialogPoint currDialogPoint = new DialogPoint(); List <DialogLink> linkList = new List <DialogLink>(); DialogLink currLink = new DialogLink(); using (var baseTokenEnumer = GetBaseTokens(charEnumer)) { while (baseTokenEnumer.MoveNext()) { var token = baseTokenEnumer.Current; switch (state) { // reading transition equals to reading nothing case ReadGameStates.ReadLinkTransition: case ReadGameStates.ReadNothing: { // if we have read link transition and met minus, it means - now we're reading new transition if (state == ReadGameStates.ReadLinkTransition && token.Type == BaseTokenType.minus) { currLink = new DialogLink() { Number = linkList.Count, }; linkList.Add(currLink); state = ReadGameStates.ReadLinkStart; } // it means - now we're reading point number else if (token.Type == BaseTokenType.rndBrktContent) { // saving previous dialog-point's transitions if (state == ReadGameStates.ReadLinkTransition) { currDialogPoint.Links = linkList.ToArray(); } bool parseResult = int.TryParse(token.Content, out int result); if (!parseResult) { throw new SyntaxError($"Next point number reading error, found: '{token.Content}'"); } bool getResult = dialogPointDictionary.TryGetValue(result, out currDialogPoint); if (!getResult) { currDialogPoint = new DialogPoint() { ID = result }; dialogPointDictionary.Add(currDialogPoint.ID, currDialogPoint); } state = ReadGameStates.ReadPointNumber; } else { throw new SyntaxError($"Point number reading error: found '{token.Content}'"); } break; } case ReadGameStates.ReadPointNumber: { if (token.Type == BaseTokenType.text) { currDialogPoint.Text = token.Content; state = ReadGameStates.ReadPointText; } else { throw new SyntaxError($"Expected text after point number, found: '{token.Content}'"); } break; } case ReadGameStates.ReadPointActions: case ReadGameStates.ReadPointText: { if (token.Type == BaseTokenType.sqrBrktContent) { bool parseResult = int.TryParse(token.Content, out int result); if (!parseResult) { throw new SyntaxError($"Point number reading error: found '{token.Content}'"); } bool getResult = dialogPointDictionary.TryGetValue(result, out DialogPoint nextPoint); if (!getResult) { nextPoint = new DialogPoint() { ID = result }; dialogPointDictionary.Add(nextPoint.ID, nextPoint); } DialogLink link = new DialogLink() { Text = "next...", NextPoint = nextPoint, Number = 0, }; currDialogPoint.Links = new DialogLink[1] { link }; state = ReadGameStates.ReadNothing; } else if (token.Type == BaseTokenType.rndBrktContent && state == ReadGameStates.ReadPointText) { GameAction[] actions = ParseActions(token.Content); currDialogPoint.Actions = actions; state = ReadGameStates.ReadPointActions; } else if (token.Type == BaseTokenType.minus) { linkList.Clear(); currLink = new DialogLink() { Number = linkList.Count, }; linkList.Add(currLink); state = ReadGameStates.ReadLinkStart; } else { throw new SyntaxError($"Excpected actions, transitions or link start '-', found: '{token.Content}'"); // expected actions or transition or link start } break; } case ReadGameStates.ReadCondition: case ReadGameStates.ReadLinkStart: { if (token.Type == BaseTokenType.rndBrktContent && state == ReadGameStates.ReadLinkStart) { LinkCondition[] conditions = ParseCondition(token.Content); currLink.Conditions = conditions; state = ReadGameStates.ReadCondition; } else if (token.Type == BaseTokenType.text) { currLink.Text = token.Content; state = ReadGameStates.ReadLinkText; } break; } case ReadGameStates.ReadLinkAction: case ReadGameStates.ReadLinkText: { if (token.Type == BaseTokenType.rndBrktContent && state == ReadGameStates.ReadLinkText) { GameAction[] actions = ParseActions(token.Content); currLink.Actions = actions; state = ReadGameStates.ReadLinkAction; } else if (token.Type == BaseTokenType.sqrBrktContent) { bool parseResult = int.TryParse(token.Content, out int result); if (!parseResult) { // expected number } bool getResult = dialogPointDictionary.TryGetValue(result, out DialogPoint nextPoint); if (!getResult) { nextPoint = new DialogPoint() { ID = result }; dialogPointDictionary.Add(nextPoint.ID, nextPoint); } currLink.NextPoint = nextPoint; state = ReadGameStates.ReadLinkTransition; } else { throw new SyntaxError($"Expected next point number, found: '{token.Content}'"); } break; } } } if (state != ReadGameStates.ReadNothing && state != ReadGameStates.ReadLinkTransition) { throw new UnexpectedEndOfInputError($"Incorrect input, the state, when stop: '{state.ToString()}'"); } if (state == ReadGameStates.ReadLinkTransition) { currDialogPoint.Links = linkList.ToArray(); } } AnalizeGameGraph(dialogPointDictionary); dialogPointDictionary.TryGetValue(0, out DialogPoint root); return(root); }
private void AnalizeGameGraph(Dictionary <int, DialogPoint> pointDict) { // it should contain start-state (with number 0) // (throws exception) DialogPoint start = null; { bool containsStart = pointDict.TryGetValue(0, out start); if (!containsStart || (start.Links == null || start.Links.Length == 0)) { throw new ApplicationException("Game doesn't contain the start-state (state with number 0)"); } } // looking for defined dialog points, which don't exist // (adds warnings) using (var dictEnumer = pointDict.GetEnumerator()) { while (dictEnumer.MoveNext()) { var currPoint = dictEnumer.Current.Value; if (currPoint.Links == null) { continue; } for (int i = 0; i < currPoint.Links.Length; ++i) { var nextPoint = currPoint.Links[i].NextPoint; if (nextPoint.Links == null || nextPoint.Links.Length == 0) { var notDefinedNextPointWarning = $"in point({currPoint.ID}) in {i} position - " + $"transition to point({nextPoint.ID}), which hadn't been read (incorrect transition)"; nextPoint = currPoint; nextPoint.Text += "(INVALID TRANSITION)"; warnings.Add(notDefinedNextPointWarning); } } } } // find not-linked components var notConnectedPoints = new Dictionary <int, DialogPoint>(); using (var dictEnumer = pointDict.GetEnumerator()) { while (dictEnumer.MoveNext()) { notConnectedPoints.Add(dictEnumer.Current.Key, dictEnumer.Current.Value); } } using (var dictEnumer = notConnectedPoints.GetEnumerator()) { var pointQueue = new Queue <DialogPoint>(); var connectedPoints = new Dictionary <int, DialogPoint>(); pointQueue.Enqueue(start); while (pointQueue.Count > 0) { var currPoint = pointQueue.Dequeue(); for (int i = 0; i < currPoint.Links.Length; ++i) { } } } }