/// <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);
        }
Exemple #2
0
        /// <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();
            }
        }
Exemple #3
0
        /// <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);
        }