public void MoveToString(Move move, StringBuilder output) { if (!_chess960 && !move.IsCastlelingMove()) { output.Append(move.ToString()); } else { if (_xfen && move.GetToSquare() == ECastleling.Long.GetKingCastleTo(move.GetMovingSide())) { output.Append(ECastleling.Long.GetCastlelingString()); } else if (_xfen) { output.Append(ECastleling.Short.GetCastlelingString()); } else { output.Append(move.GetFromSquare().ToString()); output.Append(Position.GetRookCastleFrom(move.GetToSquare()).ToString()); } } }
/// <summary> /// Updates the hash key depending on a move /// </summary> /// <param name="move">The move the hash key is depending on</param> private void UpdateKey(Move move) { // TODO : Merge with MakeMove to avoid duplicate ifs var pawnKey = State.PawnStructureKey; var key = State.Key ^ pawnKey; pawnKey ^= Zobrist.GetZobristSide(); if (_stateList[PositionIndex - 1].EnPassantSquare != ESquare.none) { key ^= _stateList[PositionIndex - 1].EnPassantSquare.File().GetZobristEnPessant(); } if (State.EnPassantSquare != ESquare.none) { key ^= State.EnPassantSquare.File().GetZobristEnPessant(); } if (move.IsNullMove()) { State.Key = key ^ pawnKey; State.PawnStructureKey = pawnKey; return; } var pawnPiece = move.GetMovingPieceType() == EPieceType.Pawn; var squareTo = move.GetToSquare(); if (move.IsPromotionMove()) { key ^= move.GetPromotedPiece().GetZobristPst(squareTo); } else { if (pawnPiece) { pawnKey ^= move.GetMovingPiece().GetZobristPst(squareTo); } else { key ^= move.GetMovingPiece().GetZobristPst(squareTo); } } if (pawnPiece) { pawnKey ^= move.GetMovingPiece().GetZobristPst(move.GetFromSquare()); if (move.IsEnPassantMove()) { pawnKey ^= move.GetCapturedPiece().GetZobristPst(squareTo + State.SideToMove.PawnPushDistance()); } else if (move.IsCaptureMove()) { pawnKey ^= move.GetCapturedPiece().GetZobristPst(squareTo); } } else { key ^= move.GetMovingPiece().GetZobristPst(move.GetFromSquare()); if (move.IsCaptureMove()) { key ^= move.GetCapturedPiece().GetZobristPst(squareTo); } else if (move.IsCastlelingMove()) { var piece = EPieceType.Rook.MakePiece(Position.State.SideToMove); key ^= piece.GetZobristPst(Position.GetRookCastleFrom(squareTo)); key ^= piece.GetZobristPst(squareTo.GetRookCastleTo()); } } // castling rights if (State.CastlelingRights != _stateList[PositionIndex - 1].CastlelingRights) { key ^= _stateList[PositionIndex - 1].CastlelingRights.GetZobristCastleling(); key ^= State.CastlelingRights.GetZobristCastleling(); } State.Key = key ^ pawnKey; State.PawnStructureKey = pawnKey; }
/// <summary> /// Makes a chess move in the data structure /// </summary> /// <param name="move">The move to make</param> /// <returns>true if everything was fine, false if unable to progress - fx castleling position under attack</returns> public bool MakeMove(Move move) { if (!Position.MakeMove(move)) { return(false); } // advances the position var previous = _stateList[PositionIndex++]; Position.State = _stateList[PositionIndex]; State.SideToMove = ~previous.SideToMove; State.Material = previous.Material; State.HalfMoveCount = PositionIndex; State.LastMove = move; // compute in-check Position.InCheck = Position.IsAttacked(Position.GetPieceSquare(EPieceType.King, State.SideToMove), ~State.SideToMove); State.CastlelingRights = _stateList[PositionIndex - 1].CastlelingRights & _castleRightsMask[move.GetFromSquare().AsInt()] & _castleRightsMask[move.GetToSquare().AsInt()]; State.NullMovesInRow = 0; // compute reversible half move count State.ReversibleHalfMoveCount = move.IsCaptureMove() || move.GetMovingPieceType() == EPieceType.Pawn ? 0 : previous.ReversibleHalfMoveCount + 1; // compute en-passant if present State.EnPassantSquare = move.IsDoublePush() ? move.GetFromSquare() + move.GetMovingSide().PawnPushDistance() : ESquare.none; State.Key = previous.Key; State.PawnStructureKey = previous.PawnStructureKey; State.Material.MakeMove(move); UpdateKey(move); return(true); }
/// <summary> /// Updates the hash key depending on a move /// </summary> /// <param name="move">The move the hash key is depending on</param> private void UpdateKey(Move move) { // TODO : Merge with MakeMove to avoid duplicate ifs var pawnKey = State.PawnStructureKey; var key = State.Key ^ pawnKey; pawnKey ^= Zobrist.GetZobristSide(); if (_stateList[PositionIndex - 1].EnPassantSquare != ESquare.none) { key ^= Zobrist.GetZobristEnPessant(_stateList[PositionIndex - 1].EnPassantSquare.File().AsInt()); } if (State.EnPassantSquare != ESquare.none) { key ^= Zobrist.GetZobristEnPessant(State.EnPassantSquare.File().AsInt()); } if (move.IsNullMove()) { key ^= pawnKey; State.Key = key; State.PawnStructureKey = pawnKey; return; } var pawnPiece = move.GetMovingPieceType() == EPieceType.Pawn; if (pawnPiece) { pawnKey ^= Zobrist.GetZobristPst(move.GetMovingPiece(), move.GetFromSquare()); } else { key ^= Zobrist.GetZobristPst(move.GetMovingPiece(), move.GetFromSquare()); } var squareTo = move.GetToSquare(); if (move.IsPromotionMove()) { key ^= Zobrist.GetZobristPst(move.GetPromotedPiece(), squareTo); } else { if (pawnPiece) { pawnKey ^= Zobrist.GetZobristPst(move.GetMovingPiece(), squareTo); } else { key ^= Zobrist.GetZobristPst(move.GetMovingPiece(), squareTo); } } if (pawnPiece && move.IsEnPassantMove()) { pawnKey ^= Zobrist.GetZobristPst(move.GetCapturedPiece().Type() + (State.SideToMove << 3), squareTo + (State.SideToMove.Side == 0 ? 8 : -8)); } else if (move.IsCaptureMove()) { if (pawnPiece) { pawnKey ^= Zobrist.GetZobristPst(move.GetCapturedPiece(), squareTo); } else { key ^= Zobrist.GetZobristPst(move.GetCapturedPiece(), squareTo); } } else if (move.IsCastlelingMove()) { var piece = (EPieces)(EPieceType.Rook + move.GetSideMask()); key ^= Zobrist.GetZobristPst(piece, Position.GetRookCastleFrom(squareTo)); key ^= Zobrist.GetZobristPst(piece, squareTo.GetRookCastleTo()); } // castleling // castling rights if (State.CastlelingRights != _stateList[PositionIndex - 1].CastlelingRights) { key ^= Zobrist.GetZobristCastleling(_stateList[PositionIndex - 1].CastlelingRights); key ^= Zobrist.GetZobristCastleling(State.CastlelingRights); } key ^= pawnKey; State.Key = key; State.PawnStructureKey = pawnKey; }