Search code examples
c++chessalpha-beta-pruning

Alpha-beta pruning with a silly move


After learning about alpha-beta pruning algorithm for a while, I decided to write a simple chess program. However, when running the program, the computer decides to make a silly move. I don't know where the functions are written wrong.

What do I have to fix for the program to work properly.

This is my static evaluation function, where m_turn is the side in turn, and m_xturn is the side that has not yet turned.:

int CChess::Evaluate()
{
    int score = 0;
    for (int r = 0; r < CHEIGHT; r++)
        for (int c = 0; c < CWIDTH; c++)
            if (m_color[r][c] == m_turn)
                score += PIECE_VALUE[m_piece[r][c]];
            else if (m_color[r][c] == m_xturn)
                score -= PIECE_VALUE[m_piece[r][c]];
    return score;
}

Alpha-beta pruning function:

int CChess::AlphaBeta(int depth, int alpha, int beta, bool isMaxPlayer)
{
    if (depth == 0)
        return Evaluate();
    std::vector<CChessMove> move_list = GenMove();
    size_t n = move_list.size();
    if (isMaxPlayer)
    {
        for (size_t i = 0; i < n; i++)
        {
            CChessPiece piece = Move(move_list[i]);
            int value = AlphaBeta(depth - 1, alpha, beta, false);
            UnMove(move_list[i], piece);
            if (value > alpha)
                alpha = value;
            if (alpha >= beta)
                break;
        }
        return alpha;
    }
    for (size_t i = 0; i < n; i++)
    {
        CChessPiece piece = Move(move_list[i]);
        int value = AlphaBeta(depth - 1, alpha, beta, true);
        UnMove(move_list[i], piece);
        if (value < beta)
            beta = value;
        if (alpha >= beta)
            break;
    }
    return beta;
}

The function to find the best move.

CChessMove CChess::ComputerThinks()
{
    int best_value = -CCHESS_INFINITY;
    CChessMove best_move = { {-1, -1}, {-1, -1 } };
    std::vector<CChessMove> move_list = GenMove();
    size_t n = move_list.size();
    for (size_t i = 0; i < n; i++)
    {
        CChessPiece piece = Move(move_list[i]);
        int value = AlphaBeta(CCHESS_DEPTH, -CCHESS_INFINITY, CCHESS_INFINITY, false);
        UnMove(move_list[i], piece);
        if (value > best_value)
        {
            best_value = value;
            best_move = move_list[i];
        }
    }
    return best_move;
}

Solution

  • What this really means is that your engine thought it found a refutation. For example, perhaps it analyzed QxP at depth 1. It would think that it had just won a pawn, which is great! But, one move later it realizes that it would lose the queen. This is a problem even at higher depths - an engine might thing QxP leads to a series of captures that ends with it being a pawn up, but in reality loses a rook at the very last capture that it didn't see. I would recommend implementing quiescience search as others in the comments have suggested, which plays through all captures instead of directly evaluating. Since there are very few captures compared to normal moves in a given position this is cheaper than trying to add a few extra depth.

    I would also highly recommend putting it in a Negamax framework rather than the standard Alpha-Beta. It's much simpler.