From 144b9a75e82875ceb16615e16efed05d290bd4f9 Mon Sep 17 00:00:00 2001 From: kanitabe Date: Mon, 10 Mar 2025 16:40:45 +0900 Subject: [PATCH 1/2] feat: extend SGF property handling to include comments and labels --- GoSharpCore/Game.cs | 60 +++++++++++++++++++++++++++++++++++--- GoSharpCore/SGFProperty.cs | 3 +- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/GoSharpCore/Game.cs b/GoSharpCore/Game.cs index 3886fd1..3ef0167 100644 --- a/GoSharpCore/Game.cs +++ b/GoSharpCore/Game.cs @@ -30,7 +30,8 @@ public class Game { private static readonly Dictionary> PropertyHandlers = new Dictionary>(); - private static readonly HashSet PropertiesToExclude = new HashSet { "W", "B", "AE", "AB", "AW" }; + private static readonly HashSet PropertiesToExclude = new HashSet { "W", "B", "AE", "AB", "AW", "C", + "LB", "TR", "MA", "CR", "SQ" }; static Game() { foreach (var kvp in SGFPropToColor) { @@ -51,6 +52,12 @@ static Game() { PropertyHandlers["WR"] = ((x, y) => x.HandleWR(y)); PropertyHandlers["BR"] = ((x, y) => x.HandleBR(y)); PropertyHandlers["TM"] = ((x, y) => x.HandleTM(y)); + PropertyHandlers["C"] = ((x, y) => x.HandleC(y)); + PropertyHandlers["LB"] = ((x, y) => x.HandleLB(y)); + PropertyHandlers["TR"] = ((x, y) => x.HandleMarks(y, "△")); + PropertyHandlers["MA"] = ((x, y) => x.HandleMarks(y, "✕")); + PropertyHandlers["CR"] = ((x, y) => x.HandleMarks(y, "◯")); + PropertyHandlers["SQ"] = ((x, y) => x.HandleMarks(y, "□")); } /// @@ -60,6 +67,11 @@ static Game() { private readonly List _moves = new List(); + public void PopMoves() + { + _moves.Clear(); + } + private readonly Dictionary _captures = new Dictionary() { { Content.Black, 0 }, @@ -73,12 +85,12 @@ static Game() { /// /// Gets the board object of the current game position. /// - public Board Board { get; private set; } + public Board Board { get; set; } /// /// Gets the color of the player whose turn it is to play. /// - public Content Turn { get; private set; } + public Content Turn { get; set; } /// /// Gets the GameInfo object of this game. This is null except for root @@ -159,6 +171,9 @@ public Dictionary SetupMoves { [PublicAPI] public int BlackCaptures => _captures[Content.Black]; + public string Comment => _comment; + private string _comment; + /// /// Constructs a root game object based on a GameInfo object. /// @@ -321,7 +336,7 @@ public Game MakeMove(int x, int y, out bool legal, bool dontAddVariationIfIllega var g = new Game(this); legal = g.InternalMakeMove(x, y); if (!dontAddVariationIfIllegal || legal) { - _moves.Add(new Variation(new Point(x, y), g)); + _moves.Add(new Variation(new Point(x, y), g)); } return g; } @@ -569,6 +584,15 @@ public static List SerializeFromSGF(TextReader sr) { coll.Read(sr); return coll.GameTrees.Select(c => new Game(c)).ToList(); } + + public static List SerializeFromSGFText(string text) { + using(TextReader sr = new StringReader(text)) + { + var coll = new SGFCollection(); + coll.Read(sr); + return coll.GameTrees.Select(c => new Game(c)).ToList(); + } + } private static void CreateGameTree(SGFGameTree root, Game p) { if (p.GameInfo != null) { @@ -690,5 +714,33 @@ private Game HandleTM(SGFProperty p) { GameInfo.MainTime = TimeSpan.FromSeconds(p.Values[0].Num); return this; } + + private Game HandleC(SGFProperty p) + { + _comment = p.Values[0].Value; + return this; + } + + public List<(Point, string)> Labels => _labels; + private List<(Point, string)> _labels = new List<(Point, string)>(); + + private Game HandleLB(SGFProperty p) + { + foreach (var v in p.Values) { + // Value is the content of []. + // MoveA is to the left of ":", MoveB is to the right of ":" + int colonPos = v.Value.IndexOf(":"); + _labels.Add((v.MoveA, v.Value.Substring(colonPos + 1))); // Get the characters after ":" + } + return this; + } + + private Game HandleMarks(SGFProperty p, string mark) + { + foreach (var v in p.Values) { + _labels.Add( (v.Move, mark) ); + } + return this; + } } } diff --git a/GoSharpCore/SGFProperty.cs b/GoSharpCore/SGFProperty.cs index 1d5ffed..360a000 100644 --- a/GoSharpCore/SGFProperty.cs +++ b/GoSharpCore/SGFProperty.cs @@ -31,7 +31,8 @@ public class SGFProperty { private readonly HashSet _moveProperties = new HashSet { - "W","B","AB","AW","AE" + "W","B","AB","AW","AE", "C", + "LB", "TR", "MA", "CR", "SQ" }; /// /// Returns true if this property is a file format property. From eac2781fb5a13a95547204440a1cdeb5f39625bd Mon Sep 17 00:00:00 2001 From: kanitabe Date: Mon, 10 Mar 2025 16:48:46 +0900 Subject: [PATCH 2/2] tweak --- GoSharpCore/Game.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GoSharpCore/Game.cs b/GoSharpCore/Game.cs index 3ef0167..f965e54 100644 --- a/GoSharpCore/Game.cs +++ b/GoSharpCore/Game.cs @@ -85,12 +85,12 @@ public void PopMoves() /// /// Gets the board object of the current game position. /// - public Board Board { get; set; } + public Board Board { get; private set; } /// /// Gets the color of the player whose turn it is to play. /// - public Content Turn { get; set; } + public Content Turn { get; private set; } /// /// Gets the GameInfo object of this game. This is null except for root @@ -336,7 +336,7 @@ public Game MakeMove(int x, int y, out bool legal, bool dontAddVariationIfIllega var g = new Game(this); legal = g.InternalMakeMove(x, y); if (!dontAddVariationIfIllegal || legal) { - _moves.Add(new Variation(new Point(x, y), g)); + _moves.Add(new Variation(new Point(x, y), g)); } return g; }