static int Quiescent(BOARD *board, int alpha, int beta, int root, CONTROL *control, MOVE killers[][2]) { int nmoves, nlegal = 0; int val; MOVE moves[MAXMOVES]; if(!control->ponder && clock() - control->init_time >= control->max_time*CPMS){ control->stop = 1; } val = LazyEval(board); if(val-LAZYBETA >= beta) return beta; if(val+LAZYALPHA < alpha) return alpha; val = StaticEval(board); UpdateTable(&hash_table, board->zobrist_key, val, 0, 0, HASH_EXACT); if (val >= beta) return beta; if (val > alpha) alpha = val; nmoves = CaptureGen(board, moves); nmoves = FilterWinning(board, moves, nmoves); // nmoves = SortMoves(board, moves, nmoves, killers[root]); for(int i = 0; i < nmoves; i++){ control->node_count++; MakeMove(board, &moves[i]); if(!LeftInCheck(board)){ nlegal++; val = -Quiescent(board, -beta, -alpha, root+1, control, killers); Takeback(board, moves[i]); if(val >= beta){ return beta; } if(val > alpha){ alpha = val; } }else Takeback(board, moves[i]); } return alpha; }
static int AlphaBeta(BOARD *board, unsigned int depth, int alpha, int beta, int root, CONTROL *control, char skip_null, MOVE killers[][2]) { int nmoves, nlegal = 0; MOVE moves[MAXMOVES]; MOVE best_move = 0; char str_mov[MVLEN]; int val = ERRORVALUE; char hash_flag = HASH_ALPHA; int reduce = 0, LMR = 0; if(depth){ if(root > 0){ val = GetHashEval(&hash_table, board->zobrist_key, depth, alpha, beta); if(val != ERRORVALUE) return val; } if(depth > 2 && !InCheck(board, 0)){ if(!skip_null && board->piece_material[board->white_to_move] != 0){ MOVE null_mv = NULL_MOVE; MakeMove(board, &null_mv); val = -AlphaBeta(board, depth-3, -beta, -beta+1, root+1, control, 1, killers); Takeback(board, null_mv); if(val >= beta) return beta; } reduce = 1; /*Try Late Move reductions.*/ } nmoves = MoveGen(board, moves, 1); int good = SortMoves(board, moves, nmoves, killers[root]); for(int i = 0; i < nmoves; i++){ MakeMove(board, &moves[i]); control->node_count++; if(!LeftInCheck(board)){ if(root == 0){ if(!control->best_move) control->best_move = moves[i]; /* Better than nothing. */ if(depth > 6 && !control->ponder){ MoveToAlgeb(moves[i], str_mov); printf("info depth %i hashfull %i currmove %s currmovenumber %i\n", depth, hash_table.full/(hash_table.size/1000), str_mov, i+1); } } nlegal++; val = AssesDraw(board); if(val) { if(best_move){ LMR = (reduce && i > good && !CAPTMASK(moves[i]) && !InCheck(board, 0)) ? 1 : 0; val = -AlphaBeta(board, depth-LMR-1, -alpha-1, -alpha, root+1, control, 0, killers); if(val > alpha){ val = -AlphaBeta(board, depth-1, -alpha-1, -alpha, root+1, control, 0, killers); if(val > alpha && val < beta){ val = -AlphaBeta(board, depth-1, -beta, -alpha, root+1, control, 0, killers); } } }else val = -AlphaBeta(board, depth-1, -beta, -alpha, root+1, control, 0, killers); } Takeback(board, moves[i]); if(!control->ponder && control->stop) return alpha; if(val >= beta){ UpdateTable(&hash_table, board->zobrist_key, val, moves[i], depth, HASH_BETA); if(CAPTMASK(moves[i]) == 0 && killers[root][0] != moves[i] && killers[root][1] != moves[i]){ killers[root][1] = killers[root][0]; killers[root][0] = moves[i]; } return beta; } if(val > alpha){ alpha = val; hash_flag = HASH_EXACT; best_move = moves[i]; if(root == 0) control->best_move = best_move; } if(root == 0 && ((clock() - control->init_time) > control->wish_time*CPMS)){ /* if short of time, don't search anymore after current move */ control->stop = 1; return alpha; } }else Takeback(board, moves[i]); } if(nlegal == 0){ if(InCheck(board, 0)){ /*UpdateTable(&hash_table, board->zobrist_key, MATE_VALUE+root, 0, depth, HASH_EXACT, hash_table.entries);*/ return MATE_VALUE; }else{ /*UpdateTable(&hash_table, board->zobrist_key, DRAW_VALUE, 0, depth, HASH_EXACT, hash_table.entries);*/ return DRAW_VALUE; /*Stalemate*/ } }else UpdateTable(&hash_table, board->zobrist_key, alpha, best_move, depth, hash_flag); }else if(InCheck(board, 0)){ alpha = AlphaBeta(board, 1, alpha, beta, root+1, control, 1, killers); }else{ alpha = Quiescent(board, alpha, beta, root, control, killers); } return alpha; }
static int AlphaBeta (BOARD *board, int depth, int alpha, int beta, int root, CONTROL *control, char skip_null, MOVE killers[][2]) { int nmoves, good = 0, nlegal = 0; MOVE moves[MAXMOVES]; MOVE best_move = 0; char str_mov[MVLEN]; int val = ERRORVALUE; char hash_flag = HASH_ALPHA; int in_check = InCheck(board, 0); if (root > control->seldepth) control->seldepth = root; if (depth > 0 || in_check) { if (root > 0) { val = GetHashEval(&hash_table, board->zobrist_key, depth, alpha, beta); if (val != ERRORVALUE) return val; } if (depth > 2 && !in_check) { if (!skip_null && board->piece_material[board->white_to_move] != 0) { MOVE null_mv = NULL_MOVE; MakeMove(board, &null_mv); val = -AlphaBeta(board, depth-3, -beta, -beta+1, root+1, control, 1, killers); Takeback(board, null_mv); if (val >= beta) return beta; } } nmoves = MoveGen(board, moves, 1); good = SortMoves(board, moves, nmoves, killers[root]); } else { if (!control->ponder && clock() - control->init_time >= control->max_time*CPMS) { control->stop = 1; } val = LazyEval(board); if (val-LAZYBETA >= beta) return beta; if (val+LAZYALPHA < alpha) return alpha; val = StaticEval(board); UpdateTable(&hash_table, board->zobrist_key, val, 0, 0, HASH_EXACT); if (val >= beta) return beta; if (val > alpha) alpha = val; nmoves = CaptureGen(board, moves); nmoves = FilterWinning(board, moves, nmoves); } for (int i = 0; i < nmoves; i++) { MakeMove(board, &moves[i]); control->node_count++; if (LeftInCheck(board)) { Takeback(board, moves[i]); continue; } if (root == 0) { if (!control->best_move) control->best_move = moves[i]; /* Better than nothing. */ if (depth > 6 && !control->ponder) { MoveToAlgeb(moves[i], str_mov); printf("info depth %i seldepth %i hashfull %i currmove %s currmovenumber %i\n", depth, control->seldepth, hash_table.full/(hash_table.size/1000), str_mov, i+1); } } nlegal++; val = AssessDraw(board, control->contempt); if (val == ERRORVALUE) { int ext = 0; //InCheck(board, 0) ? 1 : 0; if (best_move) { int LMR = (depth > 2 && !in_check && i > good && !CAPTMASK(moves[i]) && !InCheck(board, 0)) ? 1 : 0; val = -AlphaBeta(board, depth+ext-LMR-1, -alpha-1, -alpha, root+1, control, 0, killers); if (val > alpha) { val = -AlphaBeta(board, depth+ext-1, -alpha-1, -alpha, root+1, control, 0, killers); if (val > alpha && val < beta) { val = -AlphaBeta(board, depth+ext-1, -beta, -alpha, root+1, control, 0, killers); } } } else { val = -AlphaBeta(board, depth+ext-1, -beta, -alpha, root+1, control, 0, killers); } } Takeback(board, moves[i]); if (!control->ponder && control->stop) return alpha; if (val >= beta) { UpdateTable(&hash_table, board->zobrist_key, val, moves[i], depth, HASH_BETA); if (CAPTMASK(moves[i]) == 0 && killers[root][0] != moves[i] && killers[root][1] != moves[i]) { killers[root][1] = killers[root][0]; killers[root][0] = moves[i]; } return beta; } if (val > alpha) { alpha = val; hash_flag = HASH_EXACT; best_move = moves[i]; if (root == 0) control->best_move = best_move; } if (root == 0 && ((clock() - control->init_time) > control->wish_time*CPMS)) { /* if short of time, don't search anymore after current move */ control->stop = 1; return alpha; } } if (nlegal == 0) { if (in_check) { /*UpdateTable(&hash_table, board->zobrist_key, MATE_VALUE+root, 0, depth, HASH_EXACT, hash_table.entries);*/ return MATE_VALUE; } else if (depth > 0) { /*UpdateTable(&hash_table, board->zobrist_key, DRAW_VALUE, 0, depth, HASH_EXACT, hash_table.entries);*/ return DRAW_VALUE; /*Stalemate*/ } } else { UpdateTable(&hash_table, board->zobrist_key, alpha, best_move, depth, hash_flag); } return alpha; }