public void OrderMoves(Board board, List <Move> moves, bool useTT) { Move hashMove = invalidMove; if (useTT) { hashMove = transpositionTable.GetStoredMove(); } for (int i = 0; i < moves.Count; i++) { int score = 0; int movePieceType = Piece.PieceType(board.Square[moves[i].StartSquare]); int capturePieceType = Piece.PieceType(board.Square[moves[i].TargetSquare]); int flag = moves[i].MoveFlag; if (capturePieceType != Piece.None) { // Order moves to try capturing the most valuable opponent piece with least valuable of own pieces first // The capturedPieceValueMultiplier is used to make even 'bad' captures like QxP rank above non-captures score = capturedPieceValueMultiplier * GetPieceValue(capturePieceType) - GetPieceValue(movePieceType); } if (movePieceType == Piece.Pawn) { if (flag == Move.Flag.PromoteToQueen) { score += Evaluation.queenValue; } else if (flag == Move.Flag.PromoteToKnight) { score += Evaluation.knightValue; } else if (flag == Move.Flag.PromoteToRook) { score += Evaluation.rookValue; } else if (flag == Move.Flag.PromoteToBishop) { score += Evaluation.bishopValue; } } else { // Penalize moving piece to a square attacked by opponent pawn if (BitBoardUtility.ContainsSquare(moveGenerator.opponentPawnAttackMap, moves[i].TargetSquare)) { score -= squareControlledByOpponentPawnPenalty; } } if (Move.SameMove(moves[i], hashMove)) { score += 10000; } moveScores[i] = score; } Sort(moves); }
bool SquareAttackedAfterEPCapture(int epCaptureSquare, int capturingPawnStartSquare) { if (BitBoardUtility.ContainsSquare(opponentAttackMapNoPawns, friendlyKingSquare)) { return(true); } // Loop through the horizontal direction towards ep capture to see if any enemy piece now attacks king int dirIndex = (epCaptureSquare < friendlyKingSquare) ? 2 : 3; for (int i = 0; i < numSquaresToEdge[friendlyKingSquare][dirIndex]; i++) { int squareIndex = friendlyKingSquare + directionOffsets[dirIndex] * (i + 1); int piece = board.Square[squareIndex]; if (piece != Piece.None) { // Friendly piece is blocking view of this square from the enemy. if (Piece.IsColour(piece, friendlyColour)) { break; } // This square contains an enemy piece else { if (Piece.IsRookOrQueen(piece)) { return(true); } else { // This piece is not able to move in the current direction, and is therefore blocking any checks along this line break; } } } } // check if enemy pawn is controlling this square (can't use pawn attack bitboard, because pawn has been captured) for (int i = 0; i < 2; i++) { // Check if square exists diagonal to friendly king from which enemy pawn could be attacking it if (numSquaresToEdge[friendlyKingSquare][pawnAttackDirections[friendlyColourIndex][i]] > 0) { // move in direction friendly pawns attack to get square from which enemy pawn would attack int piece = board.Square[friendlyKingSquare + directionOffsets[pawnAttackDirections[friendlyColourIndex][i]]]; if (piece == (Piece.Pawn | opponentColour)) // is enemy pawn { return(true); } } } return(false); }
bool SquareIsAttacked(int square) { return(BitBoardUtility.ContainsSquare(opponentAttackMap, square)); }
void CalculateAttackData() { GenSlidingAttackMap(); // Search squares in all directions around friendly king for checks/pins by enemy sliding pieces (queen, rook, bishop) int startDirIndex = 0; int endDirIndex = 8; if (board.queens[opponentColourIndex].Count == 0) { startDirIndex = (board.rooks[opponentColourIndex].Count > 0) ? 0 : 4; endDirIndex = (board.bishops[opponentColourIndex].Count > 0) ? 8 : 4; } for (int dir = startDirIndex; dir < endDirIndex; dir++) { bool isDiagonal = dir > 3; int n = numSquaresToEdge[friendlyKingSquare][dir]; int directionOffset = directionOffsets[dir]; bool isFriendlyPieceAlongRay = false; ulong rayMask = 0; for (int i = 0; i < n; i++) { int squareIndex = friendlyKingSquare + directionOffset * (i + 1); rayMask |= 1ul << squareIndex; int piece = board.Square[squareIndex]; // This square contains a piece if (piece != Piece.None) { if (Piece.IsColour(piece, friendlyColour)) { // First friendly piece we have come across in this direction, so it might be pinned if (!isFriendlyPieceAlongRay) { isFriendlyPieceAlongRay = true; } // This is the second friendly piece we've found in this direction, therefore pin is not possible else { break; } } // This square contains an enemy piece else { int pieceType = Piece.PieceType(piece); // Check if piece is in bitmask of pieces able to move in current direction if (isDiagonal && Piece.IsBishopOrQueen(pieceType) || !isDiagonal && Piece.IsRookOrQueen(pieceType)) { // Friendly piece blocks the check, so this is a pin if (isFriendlyPieceAlongRay) { pinsExistInPosition = true; pinRayBitmask |= rayMask; } // No friendly piece blocking the attack, so this is a check else { checkRayBitmask |= rayMask; inDoubleCheck = inCheck; // if already in check, then this is double check inCheck = true; } break; } else { // This enemy piece is not able to move in the current direction, and so is blocking any checks/pins break; } } } } // Stop searching for pins if in double check, as the king is the only piece able to move in that case anyway if (inDoubleCheck) { break; } } // Knight attacks PieceList opponentKnights = board.knights[opponentColourIndex]; opponentKnightAttacks = 0; bool isKnightCheck = false; for (int knightIndex = 0; knightIndex < opponentKnights.Count; knightIndex++) { int startSquare = opponentKnights[knightIndex]; opponentKnightAttacks |= knightAttackBitboards[startSquare]; if (!isKnightCheck && BitBoardUtility.ContainsSquare(opponentKnightAttacks, friendlyKingSquare)) { isKnightCheck = true; inDoubleCheck = inCheck; // if already in check, then this is double check inCheck = true; checkRayBitmask |= 1ul << startSquare; } } // Pawn attacks PieceList opponentPawns = board.pawns[opponentColourIndex]; opponentPawnAttackMap = 0; bool isPawnCheck = false; for (int pawnIndex = 0; pawnIndex < opponentPawns.Count; pawnIndex++) { int pawnSquare = opponentPawns[pawnIndex]; ulong pawnAttacks = pawnAttackBitboards[pawnSquare][opponentColourIndex]; opponentPawnAttackMap |= pawnAttacks; if (!isPawnCheck && BitBoardUtility.ContainsSquare(pawnAttacks, friendlyKingSquare)) { isPawnCheck = true; inDoubleCheck = inCheck; // if already in check, then this is double check inCheck = true; checkRayBitmask |= 1ul << pawnSquare; } } int enemyKingSquare = board.KingSquare[opponentColourIndex]; opponentAttackMapNoPawns = opponentSlidingAttackMap | opponentKnightAttacks | kingAttackBitboards[enemyKingSquare]; opponentAttackMap = opponentAttackMapNoPawns | opponentPawnAttackMap; }