/// <summary> /// KifMoveNodeからMoveNodeへ構造を変換します。 /// 結果は<paramref name="root"/>以下に設定されます。 /// </summary> private void ConvertToMoveNode(MoveNode root, Board board, List <Exception> errors) { for (var node = this; node != null; node = node.VariationNode) { // 指し手を実際に指してみます。 var move = node.MakeMove(board, errors); if (move == null) { continue; } var moveNode = new MoveNode { Move = move, MoveCount = node.MoveCount, Duration = node.Duration, PVInfoList = node.PVInfoList, CommentList = node.CommentList, }; // 次の指し手とその変化を変換します。 if (node.NextNode != null) { // 次の手以降の手はこのノードを親として追加していきます。 node.NextNode.ConvertToMoveNode(moveNode, board, errors); } root.AddNextNode(moveNode); board.Undo(); } }
/// <summary> /// KifMoveNodeからMoveNodeへ構造を変換します。 /// 結果は<paramref name="root"/>以下に設定されます。 /// </summary> private void ConvertToMoveNode(Board board, MoveNode root, List <Exception> errors) { for (var node = this; node != null; node = node.Variation) { var cloned = board.Clone(); // 指し手を実際に指してみます。 var bmove = node.MakeMove(cloned, errors); if (bmove == null) { continue; } var moveNode = new MoveNode { Move = bmove, MoveCount = node.MoveCount, Duration = node.Duration, Comment = node.Comment, }; // 次の指し手とその変化を変換します。 if (node.Next != null) { node.Next.ConvertToMoveNode(cloned, moveNode, errors); } root.AddNext(moveNode); } }
/// <summary> /// 指し手リストをツリー形式に変換します。 /// </summary> public static MoveNode Convert2Node(IEnumerable <BoardMove> moveList, int firstMoveCount) { if (moveList == null) { throw new ArgumentNullException("moveList"); } var root = new MoveNode(); var last = root; foreach (var move in moveList) { var node = new MoveNode() { MoveCount = firstMoveCount++, Move = move, }; last.AddNext(node); last = node; } return(root); }
/// <summary> /// コンストラクタ /// </summary> public KifuObject(KifuHeader header, Board startBoard, MoveNode root, Exception error = null) { Error = error; SetHeader(header); SetBoard(startBoard, true); SetRootNode(root); }
/// <summary> /// 変化ツリーのルートノードを設定します。 /// </summary> public void SetRootNode(MoveNode root) { if (root == null) { throw new ArgumentNullException("root"); } RootNode = root; MoveList = Convert2List(root).ToList(); }
/// <summary> /// コンストラクタ /// </summary> public KifuObject(KifuHeader header, Board startBoard, Exception error = null) { MoveList = new List <BoardMove>(); RootNode = new MoveNode(); Error = error; SetHeader(header); SetBoard(startBoard, false); }
/// <summary> /// 指し手ツリーをリスト形式に変換します。 /// </summary> public static IEnumerable <BoardMove> Convert2List(MoveNode root) { if (root == null) { throw new ArgumentNullException("root"); } // 先頭ノードの手はnullのため、次のノードから手を取得します。 for (var node = root.NextNode; node != null; node = node.NextNode) { yield return(node.Move); } }
/// <summary> /// ノード全体を正規化し、変化の重複などをなくします。 /// </summary> private static void RegulalizeStatic(MoveNode node, int moveCount) { while (node != null) { // 変化の重複を削除します。 for (var i = 0; i < node.NextNodes.Count(); ++i) { for (var j = i + 1; j < node.NextNodes.Count();) { var baseNode = node.NextNodes[i]; var compNode = node.NextNodes[j]; if (baseNode.Move == compNode.Move) { // もし同じ指し手の変化があれば、子の指し手をマージします。 // 子の重複チェックはこの後行うので、 // ここで重複があっても構いません。 compNode.NextNodes.ForEach(_ => _.ParentNode = null); compNode.NextNodes.ForEach(_ => baseNode.AddNextNode(_)); node.NextNodes.RemoveAt(j); } else { ++j; } } } // 手数の再設定 node.MoveCount = moveCount; if (node.NextNodeCount == 1) { // 手数が長くなったときスタックオーバーフローになるため、 // 子ノードが一つの場合はループ内で回します。 node = node.NextNode; moveCount += 1; } else { // 子ノードに関してもチェックを行います。 foreach (var child in node.NextNodes) { RegulalizeStatic(child, moveCount + 1); } return; } } }
/// <summary> /// 次の指し手ノードを追加します。 /// </summary> public void AddNext(MoveNode node) { if (node == null) { throw new ArgumentNullException("node"); } if (node.ParentNode != null) { throw new InvalidOperationException( "すでに親ノードが登録されています。"); } NextNodes.Add(node); node.ParentNode = this; }
/// <summary> /// ノード全体を比較します。 /// </summary> public bool NodeEquals(MoveNode other, bool compareComment) { if (ReferenceEquals(other, null)) { return(false); } if (MoveCount != other.MoveCount) { return(false); } if (Move != other.Move) { return(false); } if (Duration != other.Duration) { return(false); } if (NextNodeCount != other.NextNodeCount) { return(false); } if (compareComment && Comment != other.Comment) { return(false); } for (var i = 0; i < NextNodeCount; ++i) { if (!NextNodes[i].NodeEquals(other.NextNodes[i], compareComment)) { return(false); } } return(true); }
/// <summary> /// KifMoveNodeからMoveNodeへ構造を変換します。 /// </summary> public MoveNode ConvertToMoveNode(Board board, KifMoveNode head, out Exception error) { var errors = new List <Exception>(); var root = new MoveNode { MoveCount = head.MoveCount, Duration = head.Duration, Comment = head.Comment, }; // これでrootの子要素に指し手ツリーが設定されます。 ConvertToMoveNode(board, root, errors); error = ( !errors.Any() ? null : errors.Count() == 1 ? errors.FirstOrDefault() : new AggregateException(errors)); return(root); }