/// <summary> /// 通常の駒の移動 /// </summary> /// <param name="moveData"></param> /// <returns></returns> private bool MoveNormal(MoveData moveData) { Piece piece; // 一応最初に簡易なチェックk Debug.Assert(moveData.FromSquare >= 0 && moveData.FromSquare < Square.NSQUARE, "引数エラー"); // from側に駒がある if (!(this.board[moveData.FromSquare] != Piece.NoPiece)) { Debug.Assert(false, "引数エラー"); return(false); } // 色が一致 2手差し対応のため色チェックは外す // Debug.Assert(this.board[move_data.from_square].ColorOf() == turn); // 移動先が空白か相手の駒 if (!((this.board[moveData.ToSquare] == Piece.NoPiece) || (this.board[moveData.ToSquare].ColorOf() == this.turn.Opp()))) { Debug.Assert(false, "引数エラー"); return(false); } piece = moveData.Piece | PieceExtensions.PieceFlagFromColor(this.turn); // 棋譜からの指し手だと色フラグが付いていないので現在のターンで先後を決める Debug.Assert(this.board[moveData.FromSquare] == piece, "引数エラー"); // from位置の駒が違う // 成りなり判定 if (moveData.MoveType.HasFlag(MoveType.Promotion)) { // 成りのチェック成っていない駒->成るのみOk Debug.Assert(!piece.IsPromoted(), "すでになっている駒を成ろうとしている"); piece |= Piece.PromotionFlag; } this.board[moveData.FromSquare] = Piece.NoPiece; this.board[moveData.ToSquare] = piece; if (moveData.CapturePiece != Piece.NoPiece) { if (this.turn == PlayerColor.White) { this.whiteHand[(int)moveData.CapturePiece.ToHnadIndex()] += 1; } else { this.blackHand[(int)moveData.CapturePiece.ToHnadIndex()] += 1; } } return(true); }
/// <summary> /// 持ち駒を打つ /// </summary> /// <param name="moveData"></param> /// <returns></returns> private bool MoveDrop(MoveData moveData) { Piece piece; // 一応最初に簡易なチェックk piece = moveData.Piece | PieceExtensions.PieceFlagFromColor(this.turn); // 持ってない if (!this.IsHand(this.turn, moveData.Piece.ToHnadIndex())) { Debug.Assert(false, "持っていない駒は打てない"); return(false); } Debug.Assert(this.board[moveData.ToSquare] == Piece.NoPiece, "移動先が空白でない"); Debug.Assert(!piece.IsPromoted(), "成っている状態で打てない"); this.hand[(int)this.turn][(int)moveData.Piece.ToHnadIndex()] -= 1; this.board[moveData.ToSquare] = piece; return(true); }
/// <summary> /// 指し手文字列をパースして指し手を返す /// </summary> public static MoveData ParseMove(SPosition position, string move) { if (move == "resign") { return(new MoveData(MoveType.Resign)); } else if (move == "win") { // 反則勝ち return(new MoveData(MoveType.WinNyugyoku)); } else if (move == "draw") { return(new MoveData(MoveType.Draw)); } else if (move == "pass" || move == "0000") { // uci的には0000でgpsはpass return(new MoveData(MoveType.Pass)); } if (move.Length < 4) { return(null); } MoveData moveData = new MoveData(); if (move[1] == '*') { // 打つ手 moveData.MoveType = MoveType.Drop; PieceType pieceType; if (CharToPieceHashtable.TryGetValue((char)move[0], out pieceType)) { moveData.Piece = (Piece)pieceType | PieceExtensions.PieceFlagFromColor(position.Turn); } else { // 不明な文字列 moveData.Piece = Piece.NoPiece; } int file = FileFromChar(move[2]); int rank = RankFromChar(move[3]); if (file < 0 || rank < 0) { return(null); } moveData.ToSquare = Square.Make(file, rank); } else { // 移動 moveData.MoveType = MoveType.Normal; // from int file = FileFromChar(move[0]); int rank = RankFromChar(move[1]); moveData.FromSquare = Square.Make(file, rank); file = FileFromChar(move[2]); rank = RankFromChar(move[3]); if (file < 0 || rank < 0) { return(null); } moveData.ToSquare = Square.Make(file, rank); moveData.Piece = position.GetPiece(moveData.FromSquare); if (move.Length >= 5 && move[4] == '+') { // 成り moveData.MoveType = MoveType.Promotion; } } // 盤面を進める if (moveData.MoveType.IsMoveWithoutPass()) { // 指し手の場合 if (position.MoveLast.MoveType.IsMove() && moveData.ToSquare == position.MoveLast.ToSquare) { moveData.MoveType |= MoveType.Same; // 同ほげ用のフラグ設定 } if (position.GetPiece(moveData.ToSquare) != Piece.NoPiece) { moveData.MoveType |= MoveType.Capture; // 駒とったフラグ設定 moveData.CapturePiece = position.GetPiece(moveData.ToSquare); // 駒をいれる } } return(moveData); }