/// <summary> /// 与えられた指し手に従い、局面を更新する。 /// </summary> /// <param name="move"></param> public void DoMove(Move move) { Debug.Assert(SideToMove == move.SideToMove); Debug.Assert(move.Drop || Board[move.FileFrom, move.RankFrom] == move.PieceFrom); Debug.Assert(move.Drop || Board[move.FileTo, move.RankTo] == move.PieceTo); // 相手の駒を取る if (move.PieceTo != Piece.NoPiece) { RemovePiece(move.FileTo, move.RankTo); Debug.Assert(move.PieceTo.ToColor() != SideToMove); Debug.Assert(move.PieceTo.AsOpponentHandPiece().ToColor() == SideToMove); PutHandPiece(move.PieceTo.AsOpponentHandPiece()); } if (move.Drop) { // 駒を打つ指し手 Debug.Assert(move.PieceFrom.ToColor() == SideToMove); RemoveHandPiece(move.PieceFrom); } else { // 駒を移動する指し手 RemovePiece(move.FileFrom, move.RankFrom); } PutPiece(move.FileTo, move.RankTo, move.Promotion ? move.PieceFrom.AsPromoted() : move.PieceFrom); Debug.Assert(Board[move.FileTo, move.RankTo].ToColor() == SideToMove); SideToMove = SideToMove.ToOpponent(); Hash ^= Zobrist.Instance.Side; if (move.PieceFrom == Piece.BlackKing) { BlackKingFile = move.FileTo; BlackKingRank = move.RankTo; } else if (move.PieceFrom == Piece.WhiteKing) { WhiteKingFile = move.FileTo; WhiteKingRank = move.RankTo; } ++Play; LastMove = move; var newState = new PositionState(); newState.Previous = State; State = newState; }
/// <summary> /// sfen文字列をセットする /// </summary> /// <param name="sfen"></param> public void Set(string sfen) { SideToMove = Color.Black; Array.Clear(Board, 0, Board.Length); Array.Clear(HandPieces, 0, HandPieces.Length); Play = 1; Hash = 0; BlackKingFile = 0; BlackKingRank = 0; WhiteKingFile = 0; WhiteKingRank = 0; State = null; LastMove = null; // 盤面 int file = BoardSize - 1; int rank = 0; int index = 0; bool promotion = false; while (true) { var ch = sfen[index++]; if (ch == ' ') { break; } else if (ch == '/') { Debug.Assert(file == -1); ++rank; file = BoardSize - 1; } else if (ch == '+') { promotion = true; } else if (Char.IsDigit(ch)) { int numNoPieces = ch - '0'; do { Board[file, rank] = Piece.NoPiece; --file; } while (--numNoPieces > 0); } else { var piece = CharToPiece[ch]; Debug.Assert(piece != Piece.NoPiece); if (promotion) { piece = piece.AsPromoted(); promotion = false; } Board[file, rank] = piece; Hash += Zobrist.Instance.PieceSquare[(int)piece, file, rank]; if (piece == Piece.BlackKing) { BlackKingFile = file; BlackKingRank = rank; } else if (piece == Piece.WhiteKing) { WhiteKingFile = file; WhiteKingRank = rank; } --file; } } // 手番 var sideToMove = sfen[index++]; Debug.Assert(sideToMove == 'b' || sideToMove == 'w'); if (sideToMove == 'b') { SideToMove = Color.Black; } else { SideToMove = Color.White; Hash ^= Zobrist.Instance.Side; } ++index; // 持ち駒 for (int handPieceIndex = 0; handPieceIndex < (int)Piece.NumPieces; ++handPieceIndex) { HandPieces[handPieceIndex] = 0; } int numAddedHandPieces = 0; while (true) { var ch = sfen[index++]; if (ch == ' ') { break; } else if (ch == '-') { continue; } else if (Char.IsDigit(ch)) { // 2桁の場合に対応する numAddedHandPieces *= 10; numAddedHandPieces += ch - '0'; continue; } var piece = CharToPiece[ch]; Debug.Assert(piece != Piece.NoPiece); HandPieces[(int)piece] += Max(1, numAddedHandPieces); Hash += Zobrist.Instance.HandPiece[(int)piece]; numAddedHandPieces = 0; } Play = int.Parse(sfen.Substring(index)); State = new PositionState(); }