private static void AddBlackPawnMove(Board.Board board, int from, int to, MoveList list) { MoveGen.AddBlackPawnCapMove(board, from, to, (int)Piece.EMPTY, list); }
/// <summary> /// Generates all available moves for the current position on the board in the parameter MoveList. /// If the onlyCaptures parameter is true, it will only generate capture moves. /// </summary> /// <param name="board"> The current board position </param> /// <param name="list"> The MoveList to parse the available moves to. </param> /// <param name="onlyCaptures"> True if only generating for captures. </param> public static void GenerateAllMoves(Board.Board board, MoveList list, bool onlyCaptures) { Debug.Assert(BoardOperations.CheckBoard(board)); list.Count = 0; var side = (Colour)board.Side; var piece = side == Colour.WHITE ? (int)Piece.wP : (int)Piece.bP; for (var pceNum = 0; pceNum < board.PceNum[piece]; ++pceNum) { var sq = board.PList[piece, pceNum]; Debug.Assert(Validators.IsSq(sq), String.Format("Sq {0} is invalid", sq)); var leftCaptureSq = side == Colour.WHITE ? sq + 9 : sq - 9; var rightCaptureSq = side == Colour.WHITE ? sq + 11 : sq - 11; if (!onlyCaptures) { var sqInfront = side == Colour.WHITE ? sq + 10 : sq - 10; if (board[sqInfront] == (int)Piece.EMPTY && Validators.SqOnBoard(sqInfront)) { if (side == Colour.WHITE) { MoveGen.AddWhitePawnMove(board, sq, sqInfront, list); // Check if the number two square infront of the pawn is empty and that the rank is 2. if (Conversion.getRanksBrd(sq) == (int)Rank.RANK_2 && board[sq + 20] == (int)Piece.EMPTY) { MoveGen.AddQuietMove(board, MoveOperations.CreateMove(sq, sq + 20, (int)Piece.EMPTY, (int)Piece.EMPTY, MoveOperations.MoveFlagPawnStart), list); } } else // BLACK { MoveGen.AddBlackPawnMove(board, sq, sqInfront, list); // Check if the number two square infront of the pawn is empty and that the rank is 7. if (Conversion.getRanksBrd(sq) == (int)Rank.RANK_7 && board[sq - 20] == (int)Piece.EMPTY) { MoveGen.AddQuietMove(board, MoveOperations.CreateMove(sq, sq - 20, (int)Piece.EMPTY, (int)Piece.EMPTY, MoveOperations.MoveFlagPawnStart), list); } } } } if (Validators.IsSq(leftCaptureSq) && Data.PIECE_COLOURS[board[leftCaptureSq]] == (Colour)((int)side ^ 1)) { if (side == Colour.WHITE) { MoveGen.AddWhitePawnCapMove(board, sq, leftCaptureSq, board[leftCaptureSq], list); } else { // BLACK MoveGen.AddBlackPawnCapMove(board, sq, leftCaptureSq, board[leftCaptureSq], list); } } if (Validators.IsSq(rightCaptureSq) && Data.PIECE_COLOURS[board[rightCaptureSq]] == (Colour)((int)side ^ 1)) { if (side == Colour.WHITE) { MoveGen.AddWhitePawnCapMove(board, sq, rightCaptureSq, board[rightCaptureSq], list); } else { // BLACK MoveGen.AddBlackPawnCapMove(board, sq, rightCaptureSq, board[rightCaptureSq], list); } } if (Validators.IsSq(board.EnPas)) { if (leftCaptureSq == board.EnPas) { MoveGen.AddEnPassantMove(board, MoveOperations.CreateMove(sq, leftCaptureSq, (int)Piece.EMPTY , (int)Piece.EMPTY, MoveOperations.MoveFlagEnPas), list); } else if (rightCaptureSq == board.EnPas) { MoveGen.AddEnPassantMove(board, MoveOperations.CreateMove(sq, rightCaptureSq, (int)Piece.EMPTY , (int)Piece.EMPTY, MoveOperations.MoveFlagEnPas), list); } } } // Castling if (!onlyCaptures) { if (side == Colour.WHITE) { // If there is White King Castle Permission. if ((board.CastlePerm & (int)Castling.WKCA) != 0) { // Check if squares are empty before we call the less efficient SqAttacked method. var isSqG1F1Empty = board[(int)Square.F1] == (int)Piece.EMPTY && board[ (int)Square.G1] == (int)Piece.EMPTY; if (isSqG1F1Empty) { var IsSqE1OrF1NotAtt = !Attack.IsSqAttacked((int)Square.F1, (int)Colour.BLACK, board) && !Attack.IsSqAttacked((int)Square.E1, (int)Colour.BLACK, board); if (IsSqE1OrF1NotAtt) { MoveGen.AddQuietMove(board, MoveOperations.CreateMove((int)Square.E1, (int)Square.G1, (int)Piece.EMPTY, (int)Piece.EMPTY, MoveOperations.MoveFlagCastle), list); } } } // If there is White Queen Castle Permission. if ((board.CastlePerm & (int)Castling.WQCA) != 0) { var isSqB1C1D1Empty = board[(int)Square.B1] == (int)Piece.EMPTY && board[(int)Square.C1] == (int)Piece.EMPTY && board[(int)Square.D1] == (int)Piece.EMPTY; if (isSqB1C1D1Empty) { var isSqE1OrD1NotAtt = !Attack.IsSqAttacked((int)Square.E1, (int)Colour.BLACK, board) && !Attack.IsSqAttacked((int)Square.D1, (int)Colour.BLACK, board); if (isSqE1OrD1NotAtt) { MoveGen.AddQuietMove(board, MoveOperations.CreateMove((int)Square.E1, (int)Square.C1, (int)Piece.EMPTY, (int)Piece.EMPTY, MoveOperations.MoveFlagCastle), list); } } } } else { // If there is Black King Castle Permission. if ((board.CastlePerm & (int)Castling.BKCA) != 0) { // Check if squares are empty before we call the less efficient SqAttacked method. var isSqG8F8Empty = board[(int)Square.F8] == (int)Piece.EMPTY && board[(int)Square.G8] == (int)Piece.EMPTY; if (isSqG8F8Empty) { var isSqE8F8NotAttacked = !Attack.IsSqAttacked((int)Square.E8, (int)Colour.WHITE, board) && !Attack.IsSqAttacked((int)Square.F8, (int)Colour.WHITE, board); if (isSqE8F8NotAttacked) { MoveGen.AddQuietMove(board, MoveOperations.CreateMove((int)Square.E8, (int)Square.G8, (int)Piece.EMPTY, (int)Piece.EMPTY, MoveOperations.MoveFlagCastle), list); } } } // If there is White Queen Castle Permission. if ((board.CastlePerm & (int)Castling.BQCA) != 0) { // Check if squares are empty before we call the less efficient SqAttacked method. var isSqB8C8D8Empty = board[(int)Square.B8] == (int)Piece.EMPTY && board[(int)Square.C8] == (int)Piece.EMPTY && board[(int)Square.D8] == (int)Piece.EMPTY; if (isSqB8C8D8Empty) { var isSqE8D8NotAttacked = !Attack.IsSqAttacked((int)Square.E8, (int)Colour.WHITE, board) && !Attack.IsSqAttacked((int)Square.D8, (int)Colour.WHITE, board); if (isSqE8D8NotAttacked) { MoveGen.AddQuietMove(board, MoveOperations.CreateMove((int)Square.E8, (int)Square.C8, (int)Piece.EMPTY, (int)Piece.EMPTY, MoveOperations.MoveFlagCastle), list); } } } } } // Loop sliding pieces var pceIndex = MoveGen.LOOP_SLIDE_INDEX[board.Side]; // Increments AFTER it's run var pce = MoveGen.LOOP_SLIDE_PCE[pceIndex++]; while (pce != 0) { Debug.Assert(Validators.PieceValid(pce), String.Format("You have reached an invalid sliding piece {0}", pce)); for (var pceNum = 0; pceNum < board.PceNum[pce]; ++pceNum) { var sq = board.PList[pce, pceNum]; // Square check Debug.Assert(Validators.IsSq(sq), String.Format("Sq {0} is false", sq)); for (var index = 0; index < MoveGen.NUM_DIR[pce]; ++index) { var t_sq = sq + MoveGen.PCE_DIR[pce, index]; // Check if offboard if (!Validators.SqOnBoard(t_sq)) { continue; } while (Validators.SqOnBoard(t_sq)) { if (board[t_sq] != (int)Piece.EMPTY) { // 0 EXCLUSIVE OR 1 returns 1 = COLOUR.WHITE // 1 EXCLUSIVE OR 1 returns 0 = COLOUR.BLACK if ((int)Data.PIECE_COLOURS[board[t_sq]] == (board.Side ^ 1)) { AddCaptureMove(board, MoveOperations.CreateMove(sq, t_sq, board[t_sq], (int)Piece.EMPTY, 0), list); } break; } if (!onlyCaptures) { AddQuietMove(board, MoveOperations.CreateMove(sq, t_sq, (int)Piece.EMPTY, (int)Piece.EMPTY, 0), list); } t_sq += MoveGen.PCE_DIR[pce, index]; } } } pce = MoveGen.LOOP_SLIDE_PCE[pceIndex++]; } // Loop non_sliding pieces pceIndex = MoveGen.LOOP_NON_SLIDE_INDEX[board.Side]; pce = MoveGen.LOOP_NON_SLIDE_PCE[pceIndex++]; while (pce != 0) { Debug.Assert(Validators.PieceValid(pce), String.Format("You have reached an invalid sliding piece {0}", pce)); for (var pceNum = 0; pceNum < board.PceNum[pce]; ++pceNum) { var sq = board.PList[pce, pceNum]; // Square check Debug.Assert(Validators.IsSq(sq), String.Format("Sq {0} is invalid", sq)); for (var index = 0; index < MoveGen.NUM_DIR[pce]; ++index) { var t_sq = sq + MoveGen.PCE_DIR[pce, index]; // Check if offboard if (!Validators.SqOnBoard(t_sq)) { continue; } if (board[t_sq] != (int)Piece.EMPTY) { // 0 EXCLUSIVE OR 1 returns 1 = COLOUR.WHITE // 1 EXCLUSIVE OR 1 returns 0 = COLOUR.BLACK if ((int)Data.PIECE_COLOURS[board[t_sq]] == (board.Side ^ 1)) { AddCaptureMove(board, MoveOperations.CreateMove(sq, t_sq, board[t_sq], (int)Piece.EMPTY, 0), list); } continue; } if (!onlyCaptures) { AddQuietMove(board, MoveOperations.CreateMove(sq, t_sq, (int)Piece.EMPTY, (int)Piece.EMPTY, 0), list); } } } pce = MoveGen.LOOP_NON_SLIDE_PCE[pceIndex++]; } }