/// <summary> /// 与えられた指し手が着手可能か調べ、もし着手可能な場合はそれを正式な表記に変換します。 /// </summary> /// <remarks> /// 「正式な表記」にするとは、たとえば不要な「打」を削除したり、 /// 右や直などの表記を正確なものに修正することです。 /// </remarks> public static LiteralMove NormalizeMove(this Board board, LiteralMove lmove) { if (board == null) { throw new ArgumentNullException("board"); } if (!board.Validate()) { throw new ArgumentException("board"); } if (lmove == null) { throw new ArgumentNullException("lmove"); } if (!lmove.Validate()) { throw new ArgumentException("lmove"); } // 投了などの特殊な指し手は常にさせることにします。 /*if (move.IsSpecialMove) * { * return move; * }*/ // 一度、指し手の正規化を行います(打を消したり、左を追加するなど) // あり得る指し手が複数ある場合は失敗とします。 var move = board.ConvertMoveFromLiteral(lmove, true); if (move == null || !board.CanMove(move)) { return(null); } // 指し手を表記形式に再度変換します。 // 移動元の情報は使いません。("65銀(55)"という表記にはしません) var newLMove = board.ConvertLiteralFromMove(move, false); if (newLMove == null) { return(null); } // 最後に元の文字列を保存して返します。 newLMove.OriginalText = lmove.OriginalText; return(newLMove); }
/// <summary> /// コメントからPVを探します。 /// </summary> public void SetupPVInfo(Board board) { Move move = null; if (VariationNode != null) { VariationNode.SetupPVInfo(board); } // このノードの手を指して、変化の基準局面を進めます。 if (LiteralMove != null && LiteralMove.Validate()) { move = MakeMove(board, new List <Exception>()); if (move == null || !move.Validate()) { Log.Error("'{0}'が正しく着手できません。", move); return; } } for (var i = 0; i < CommentList.Count();) { var pvInfo = ParsePVInfo(CommentList[i], board); if (pvInfo != null) { PVInfoList.Add(pvInfo); CommentList.RemoveAt(i); } else { ++i; } } if (NextNode != null) { NextNode.SetupPVInfo(board); } if (move != null) { board.Undo(); } }
/// <summary> /// 指し手のパースを行います。 /// </summary> public static LiteralMove ParseMoveEx(string text, bool isNeedEnd, ref string parsedText) { if (string.IsNullOrEmpty(text)) { return(null); } var move = new LiteralMove() { OriginalText = text.Trim(), }; // 投了などの特殊な指し手の判断を行います。 var m = SpecialMoveRegex.Match(text); if (m.Success) { // 手番が指定されていればそれを取得します。 move.BWType = GetBWType(m.Groups[1].Value); // 投了などの指し手の種類を取得します。 var smoveType = GetSpecialMoveType(m.Groups[2].Value); if (smoveType == SpecialMoveType.None) { return(null); } move.SpecialMoveType = smoveType; } else { m = MoveRegex.Match(text); if (!m.Success) { return(null); } // 手番が指定されていれば、それを取得します。 move.BWType = GetBWType(m.Groups[1].Value); // 33同銀などを有効にします。 // 筋・段 var file = GetNumber(m.Groups[2].Value); var rank = GetNumber(m.Groups[3].Value); // 「同~」であるかどうかを特定します。 // 3同銀などの指し手を受理しないように、数字があれば、 // ちゃんと二つとも設定されているか調べます。 move.SameAsOld = m.Groups[4].Success; if (!move.SameAsOld || file != null || rank != null) { // 筋 if (file == null) { return(null); } move.File = file.Value; // 段 if (rank == null) { return(null); } move.Rank = rank.Value; } // 駒の種類 var piece = GetPiece(m.Groups[5].Value); if (piece == null) { return(null); } move.Piece = piece; // 相対位置 move.RelFileType = GetRelFileType(m.Groups[6].Value); // 駒の移動の種類 move.RankMoveType = GetRankMoveType(m.Groups[7].Value); // 駒打ちなどのアクション move.ActionType = GetActionType(m.Groups[8].Value); // 移動前の位置 if (m.Groups[9].Success) { move.SrcSquare = new Square( int.Parse(m.Groups[10].Value), int.Parse(m.Groups[11].Value)); } } // 解析文字列が正しく終わっているか調べます。 if (isNeedEnd && (m.Length < text.Length && !char.IsWhiteSpace(text[m.Length]))) { return(null); } if (!move.Validate()) { return(null); } parsedText = m.Value; return(move); }