0

我尝试使用带有 alpha-beta 修剪的 Negamax 在 C 中创建一个国际象棋引擎,但我无法让它工作。它在游戏的前几个动作中按预期工作,并开始在没有目标的情况下牺牲棋子。但是当它接近尾声时,它似乎再次按预期运行。我已经尝试调试了大约一个星期,但没有任何成功。任何帮助是极大的赞赏。以下是相关代码:

#define INFINITY INT_MAX

char isCheckMateOrStaleMate(uint64_t const *board, uint64_t const *prevBoard, char brkrwrkr00, char isWhiteYourColor) {
    ...
}

struct node {
    unsigned long len;
    uint64_t *pos;
    uint64_t *basepos;
    char brkrwrkr00;
    struct node *branches;
    char *move;
    char color;
};

int max(int a, int b) {
    return a > b ? a : b;
}

int evaluateNode(struct node n) {
    char cmate = isCheckMateOrStaleMate(n.pos, n.basepos, n.brkrwrkr00, !n.color);

    if (cmate)
        return (isCheckOnKing(n.pos, 1) ? -64000 : isCheckOnKing(n.pos, 0) ? 64000 : 0) * (!n.color - n.color);

    int posAdv = 0;

    char p;
    for (char i = 0; i < 64; i++) {
        p = accessBoardAt(n.pos, i);
        posAdv += p == PAWN_B ? -10 : p == PAWN_W ? 10 : p == KNIGHT_B ? -29 : p == KNIGHT_W ? 29 : p == BISHOP_B ? -30 : p == BISHOP_W ? 30 : p == ROOK_B ? -50 : p == ROOK_W ? 50 : p == QUEEN_B ? -90 : p == QUEEN_W ? 90 : 0;
    }

    return (!n.color - n.color) * posAdv;
}

unsigned long generateNodes(uint64_t const *board, uint64_t const *prevBoard, char brkrwrkr00, char isWhiteYourColor, struct node **ret, int depth) {
    if (!depth)
        return 0;

    char *valids = 0;
    unsigned long _len_ = validMoves(board, prevBoard, brkrwrkr00, isWhiteYourColor, &valids);
    
    if (!_len_)
        return 0;

    *ret = malloc(_len_ / 3 * sizeof **ret);

    for (unsigned long i = 0, j = 0; i < _len_; i += 3, j++) {
        (*ret)[j].color = isWhiteYourColor;
        (*ret)[j].pos = {board[0], board[1], board[2], board[3]};
        (*ret)[j].basepos = {board[0], board[1], board[2], board[3]};
        (*ret)[j].brkrwrkr00 = brkrwrkr00;
        (*ret)[j].move = {valids[i], valids[i + 1], valids[i + 2]};
        makeForcedMove((*ret)[j].pos, &((*ret)[j].brkrwrkr00), (*ret)[j].move);
        (*ret)[j].len = generateNodes((*ret)[j].pos, board, (*ret)[j].brkrwrkr00, !isWhiteYourColor, &((*ret)[j].branches), depth - 1);
    }

    free(valids);

    return _len_ / 3;
};

int negamaxscore(struct node n, int depth, char maximizer, int alpha, int beta) {
    if (!depth || !n.len)
        return evaluateNode(n);

    int eval = -INFINITY;

    for (unsigned long i = 0; i < n.len; i++) {
        eval = max(-negamaxscore(n.branches[i], depth - 1, !maximizer, -beta, -alpha), eval);
        alpha = max(eval, alpha);

        if (beta <= alpha)
            break;
    }

    return eval;
}

char *theBestMove(uint64_t const *board, uint64_t const *prevBoard, char brkrwrkr00, char isWhiteYourColor, int depth) {
    if (!depth)
        return NULL;

    struct node *branches;
    unsigned long len = generateNodes(board, prevBoard, brkrwrkr00, isWhiteYourColor, &branches, depth);

    if (!len)
        return NULL;

    char *bestmove = NULL;
    int curr;
    int eval = -INFINITY;
    int alpha = -INFINITY;
    int beta = INFINITY;

    for (unsigned long i = 0; i < len; i++) {
        curr = -negamaxscore(branches[i], depth - 1, !isWhiteYourColor, -beta, -alpha);

        if (curr >= eval) {
            eval = curr;
            bestmove = branches[i].move;
        }

        alpha = max(eval, alpha);

        if (beta <= alpha)
            break;
    }

    bestmove = memcpy(malloc(3), bestmove, 3);

    return bestmove;
}

char *theBestMove(uint64_t const *board, uint64_t const *prevBoard, char brkrwrkr00, char isWhiteYourColor, int depth) {
    if (!depth)
        return NULL;

    struct node *branches;
    unsigned long len = generateNodes(board, prevBoard, brkrwrkr00, isWhiteYourColor, &branches, depth);

    if (!len)
        return NULL;

    char *bestmove = NULL;
    int curr;
    int eval = -INFINITY;
    int alpha = -INFINITY;
    int beta = INFINITY;

    char seq[depth * 5];

    for (unsigned long i = 0; i < len; i++) {
        curr = -negamaxscore(branches[i], depth - 1, !isWhiteYourColor, -beta, -alpha);

        if (curr >= eval) {
            eval = curr;
            bestmove = branches[i].move;
        }

        alpha = max(eval, alpha);

        if (beta <= alpha)
            break;
    }

    bestmove = memcpy(malloc(3), bestmove, 3);

    return bestmove;
}
4

0 回答 0