C Negamax算法不提供常数行为

C Negamax算法不提供常数行为,c,chess,negamax,C,Chess,Negamax,我尝试使用Negamax和alpha-beta修剪在C中创建一个国际象棋引擎,但我无法让它工作。在游戏的前几步中,它的效果和预期的一样,并开始毫无目的地牺牲棋子。但当它接近尾声时,它的表现似乎又如预期的那样。我已经试着调试了大约一个星期,但没有成功。非常感谢您的帮助。以下是相关代码: #define INFINITY INT_MAX char isCheckMateOrStaleMate(uint64_t const *board, uint64_t const *prevBoard, cha

我尝试使用Negamax和alpha-beta修剪在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;
}
#定义无穷大INT_MAX
字符为checkmate或talemate(uint64常数*板,uint64常数*板,字符为brkrwrkr00,字符为whiteyourcolor){
...
}
结构节点{
无符号长透镜;
uint64_t*位置;
uint64_t*basepos;
char brkrwrkr00;
结构节点*分支;
字符*移动;
炭色;
};
最大整数(整数a,整数b){
返回a>b?a:b;
}
int evaluateNode(结构节点n){
char cmate=isCheckMateOrStaleMate(n.pos,n.basepos,n.brkrwrkr00,!n.color);
if(cmate)
返回(ischecking(n.pos,1)?-64000:ischecking(n.pos,0)?64000:0)*(!n.color-n.color);
int-posAdv=0;
charp;
对于(字符i=0;i<64;i++){
p=接入板(n位置,i);
posAdv+=p==PAWN\u B?-10:p==PAWN\u W?10:p==KNIGHT\u B?-29:p==KNIGHT\u W?29:p==BISHOP\u B?-30:p==BISHOP\u W?30:p==ROOK\u B?-50:p==ROOK\u W?50:p==QUEEN\u B?-90:p==QUEEN\u W?90:0;
}
返回(!n.color-n.color)*posAdv;
}
无符号长生成节点(uint64常量*板,uint64常量*板,字符brkrwrkr00,字符isWhiteYourColor,结构节点**ret,整数深度){
如果(!深度)
返回0;
char*valids=0;
未签名长字符=有效移动(board、prevBoard、brkrwrkr00、isWhiteYourColor和valids);
如果(!\u len)
返回0;
*ret=malloc(\u len\u3*sizeof**ret);
for(无符号长i=0,j=0;i<\u 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].branchs),depth-1;
}
免费(有效期);
返回长度/3;
};
int negamaxscore(结构节点n、int深度、字符最大化器、int alpha、int beta){
如果(!深度| |!n.len)
返回节点(n);
int eval=-无穷大;
for(无符号长i=0;i如果(beta版)可能会评论TT代码并进行调试,那么?@谢谢你的建议,我编辑了这个问题并尝试了调试,但再次尝试了相同的行为:(非常量行为——看起来像是使用未赋值变量的值,也可能是缓冲区溢出、指针悬空,…@pmg抱歉,如果我对“非常量”这个词的用法不清楚——非常量行为的意思是,引擎似乎并不总是玩最好的动作,也不总是玩最差的动作。如果我玩相同的序列在两个游戏中的移动中,它与另一个游戏中的移动相同。似乎您使用的是固定深度,没有换位表(尚未)。没有静止搜索?是否有全局棋盘+撤消/重做?[这可能会泄漏值]