/// <summary> /// 実際に指し手を進めます。 /// </summary> private void DoMove(BoardMove move) { if (move == null || !move.Validate()) { return; } this.RaiseEvent(new BoardPieceRoutedEventArgs( BoardPieceChangingEvent, Board.Clone(), move)); Board.DoMove(move); this.RaiseEvent(new BoardPieceRoutedEventArgs( BoardPieceChangedEvent, Board.Clone(), move)); }
/// <summary> /// 実際に指し手を進めます。 /// </summary> private void MakeMove(BoardMove move) { if (move == null || !move.Validate()) { return; } BoardPieceChanging.SafeRaiseEvent(this, new BoardPieceEventArgs(Board.Clone(), move)); Board.DoMove(move); BoardPieceChanged.SafeRaiseEvent(this, new BoardPieceEventArgs(Board.Clone(), move)); }
/// <summary> /// 指し手をSFEN形式の文字列に変換します。 /// </summary> /// <remarks> /// 筋に関しては1から9までの数字で表記され、段に関してはaからiまでの /// アルファベット(1段目がa、2段目がb、・・・、9段目がi) /// というように表記されます。位置の表記はこの2つを組み合わせ、 /// 5一なら5a、1九なら1iとなります。 /// /// 指し手に関しては、駒の移動元の位置と移動先の位置を並べて書きます。 /// 7七の駒が7六に移動したのであれば、7g7fと表記します。 /// (駒の種類を表記する必要はありません。) /// 駒が成るときは最後に+を追加します。8八の駒が2二に移動して /// 成るなら8h2b+です。 /// 持ち駒を打つときは "[駒の種類(大文字)]*[打った場所]" となります。 /// 金を5二に打つ場合はG*5bとなります /// </remarks> public static string ToSfen(this BoardMove move) { if (move == null) { throw new ArgumentNullException("move"); } if (!move.Validate()) { throw new ArgumentException("move"); } if (move.IsSpecialMove) { // 投了などの特殊な指し手 throw new SfenException( move + ": sfenに変換することはできません。"); } var dstFile = move.DstSquare.File; var dstRank = (char)((int)'a' + (move.DstSquare.Rank - 1)); if (move.ActionType == ActionType.Drop) { // 駒打ちの場合 var piece = SfenUtil.PieceTypeToSfen(move.DropPieceType); return(string.Format("{0}*{1}{2}", piece, dstFile, dstRank)); } else { // 駒の移動の場合 var srcFile = move.SrcSquare.File; var srcRank = (char)((int)'a' + (move.SrcSquare.Rank - 1)); var isPromote = (move.ActionType == ActionType.Promote); return(string.Format("{0}{1}{2}{3}{4}", srcFile, srcRank, dstFile, dstRank, (isPromote ? "+" : ""))); } }
/// <summary> /// <paramref name="move"/>をCSA形式に変換します。 /// </summary> public static string ToCsa(this BoardMove move) { if (move == null) { throw new ArgumentNullException("move"); } if (!move.Validate()) { throw new ArgumentException("move"); } if (move.IsSpecialMove) { return(move.SpecialMoveType.ToCsa()); } var sb = new StringBuilder(); sb.Append( move.BWType == BWType.Black ? "+" : move.BWType == BWType.White ? "-" : ""); if (move.SrcSquare != null) { sb.Append(move.SrcSquare.File); sb.Append(move.SrcSquare.Rank); } else { // 駒打の場合 sb.Append("00"); } if (move.DstSquare != null) { sb.Append(move.DstSquare.File); sb.Append(move.DstSquare.Rank); } else { // ほんとはエラー sb.Append("00"); } var piece = ( move.ActionType == ActionType.Drop ? new Piece(move.DropPieceType) : move.MovePiece); if (move.IsPromote) { // 駒を成った場合は、なった後の駒を出力します。 piece = new Piece(piece.PieceType, true); } sb.Append(CsaUtil.PieceToStr(piece)); return(sb.ToString()); }
/// <summary> /// 指し手をXX->YYの形式から、ZZ銀上などの形に変換します。 /// </summary> /// <remarks> /// <paramref name="useSrcSquare"/>を真にすると、差し手の後に /// 古い位置の情報が付加されるようになります。(例: 32金(22)) /// </remarks> public static Move ConvertMove(this Board board, BoardMove move, bool useSrcSquare) { if (board == null) { throw new ArgumentNullException("board"); } if (move == null || !move.Validate()) { throw new ArgumentNullException("move"); } var fromPiece = ( move.ActionType == ActionType.Drop ? new Piece(move.DropPieceType) : move.MovePiece); if (fromPiece == null) { return null; } // 駒の種類と最終位置から、あり得る指し手をすべて検索します。 var boardMoveList = board.ListupMoves( fromPiece, move.BWType, move.DstSquare) .ToList(); return FilterMove( board, boardMoveList, move, fromPiece, useSrcSquare); }
/// <summary> /// 駒を動かすか、または駒が動かせるか調べます。 /// </summary> private bool CheckAndDoMove(BoardMove move, MoveFlags flags) { if (move == null || !move.Validate()) { throw new ArgumentNullException("move"); } using (LazyLock()) { // 手番があわなければ失敗とします。 if (EnumEx.HasFlag(flags, MoveFlags.CheckTurn)) { if (this.turn == BWType.None || this.turn != move.BWType) { return false; } } if (move.ActionType == ActionType.Drop) { return CheckAndDoDrop(move, flags); } else { return CheckAndDoMoveOnly(move, flags); } } }
/// <summary> /// 駒を動かすか、または駒が動かせるか調べます。 /// </summary> private bool CheckAndMakeMove(BoardMove move, MoveFlags flags) { if (move == null || !move.Validate()) { throw new ArgumentNullException("move"); } // 投了などの特殊な指し手がある場合はゲームが既に終了しているので // 指し手を進めることはできません。 if (HasSpecialMove) { if (flags.HasFlag(MoveFlags.CheckOnly)) { // CheckOnlyの場合は、ここで失敗させません。 } else if (flags.HasFlag(MoveFlags.AutoRemoveSpecialMove)) { // 特殊な指し手を取り除きます。 RemoveSpecialMove(); } else { return false; } } using (LazyLock()) { // 手番があわなければ失敗とします。 if (EnumEx.HasFlag(flags, MoveFlags.CheckTurn)) { if (this.turn == BWType.None || this.turn != move.BWType) { return false; } } if (move.IsSpecialMove) { return CheckAndMakeSpecialMove(move, flags); } else if (move.ActionType == ActionType.Drop) { return CheckAndMakeDrop(move, flags); } else { return CheckAndMakeMoveOnly(move, flags); } } }