private void HandleEngineOutputReceived(string outputText) { if (outputText == null || !this.isEval) { return; } EvaluatedLine line = null; lock (this.bestLines) { if (this.PositionFen == null) { throw new ArgumentException($"Cannot handle engine output because PositionFen is null."); } line = this.lineParser.ParseLineText(this.PositionFen, outputText); if (line == null) { return; } bool containsUpdate = false; if (!this.bestLines.ContainsKey(line.LineRank)) { this.bestLines.Add(line.LineRank, line); containsUpdate = true; } else if (line.LineSan.Split().Length >= this.bestLines[line.LineRank].LineSan.Split().Length) { this.bestLines[line.LineRank] = line; containsUpdate = true; } if (!containsUpdate) { return; } } var segment = new EngineOutputSegment() { Output = outputText, Line = line, BestLines = this.bestLines, }; this.ReceivedEvaluationUpdate?.Invoke(this, segment); }
/// <summary> /// Parse a single UCI evaluation output line. /// </summary> /// <param name="fenPosition">The starting FEN (used for SAN context).</param> /// <param name="text">The UCI output.</param> /// <returns>The parsed line.</returns> public EvaluatedLine ParseLineText(string fenPosition, string text) { var iterator = new WordIterator(text); var line = new EvaluatedLine(); while (iterator.HasRemainingWords) { string nextKeyword = iterator.SeekAny(LineKeywords); if (nextKeyword == null) { break; } switch (nextKeyword) { case Depth: line.Depth = iterator.NextWordAsInt(); break; case MultiPV: line.LineRank = iterator.NextWordAsInt(); break; case PV: var words = new List <string>(); while (iterator.HasRemainingWords) { words.Add(iterator.NextWord()); } line.LineUci = string.Join(' ', words); break; case Score: var scoreType = iterator.NextWord(); if (scoreType == ScoreMate) { line.Evaluation = new EvaluationScore() { MovesUntilMate = iterator.NextWordAsInt(), }; } else if (scoreType == ScoreCentipawn) { line.Evaluation = new EvaluationScore() { Centipawns = iterator.NextWordAsInt(), }; } break; } } if (line.Depth == 0 || line.LineRank == 0 || line.LineUci == null || line.Evaluation == null) { return(null); } var lineParts = line.LineUci.Split(' ').ToList(); var lineSan = this.UciToSan(fenPosition, lineParts); line.LineSan = string.Join(' ', lineSan); return(line); }
/// <summary> /// Initializes a new instance of the <see cref="LineReceivedEventArgs"/> struct. /// </summary> /// <param name="line">The parsed evaluated line.</param> public LineReceivedEventArgs(EvaluatedLine line) { this.Line = line; }