/* print_result() checks to see if the game is over */ void print_result() { int i; /* is there a legal move? */ for (i = 0; i < first_move[1]; ++i) if (makemove(gen_dat[i].m.b)) { takeback(); break; } if (i == first_move[1]) { if (in_check(side)) { if (side == LIGHT) gprintf("Black mates"); else gprintf("White mates"); } else gprintf("Stalemate"); } else if (reps() == 3) gprintf("Draw by repetition"); else if (fifty >= 100) gprintf("Draw by fifty move rule"); }
void print_result() { int i; /* is there a legal move? */ for (i = 0; i < first_move[1]; ++i) if (makemove(gen_dat[i].m.b)) { takeback(); break; } if (i == first_move[1]) { if (in_check(side)) { if (side == LIGHT) printf("0-1 {Black mates}\n"); else printf("1-0 {White mates}\n"); } else printf("1/2-1/2 {Stalemate}\n"); } else if (reps() == 3) printf("1/2-1/2 {Draw by repetition}\n"); else if (fifty >= 100) printf("1/2-1/2 {Draw by fifty move rule}\n"); }
int quiesce(int alpha,int beta) { int i, j, x; ++nodes; /* do some housekeeping every 1024 nodes */ if ((nodes & 1023) == 0) checkup(); pv_length[ply] = ply; /* are we too deep? */ if (ply >= MAX_PLY - 1) return eval(); if (hply >= HIST_STACK - 1) return eval(); /* check with the evaluation function */ x = eval(); if (x >= beta) return beta; if (x > alpha) alpha = x; gen_caps(); if (follow_pv) /* are we following the PV? */ sort_pv(); /* loop through the moves */ for (i = first_move[ply]; i < first_move[ply + 1]; ++i) { sort(i); if (!makemove(gen_dat[i].m.b)) continue; x = -quiesce(-beta, -alpha); takeback(); if (x > alpha) { if (x >= beta) return beta; alpha = x; /* update the PV */ pv[ply][ply] = gen_dat[i].m; for (j = ply + 1; j < pv_length[ply + 1]; ++j) pv[ply][j] = pv[ply + 1][j]; pv_length[ply] = pv_length[ply + 1]; } } return alpha; }
int Search::printDtm() { int side = getSide(); u64 friends = side == WHITE ? getBitmap<WHITE>() : getBitmap<BLACK>(); u64 enemies = side == BLACK ? getBitmap<WHITE>() : getBitmap<BLACK>(); display(); int res = side ? getGtb().getDtm<WHITE, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100) : getGtb().getDtm<BLACK, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100); cout << " res: " << res; incListId(); generateCaptures(side, enemies, friends); generateMoves(side, friends | enemies); _Tmove *move; u64 oldKey = 0; cout << "\n succ. \n"; int best = -_INFINITE; for (int i = 0; i < getListSize(); i++) { move = &gen_list[listId].moveList[i]; makemove(move, false, false); cout << "\n" << decodeBoardinv(move->type, move->from, getSide()) << decodeBoardinv(move->type, move->to, getSide()) << " "; res = side ? -getGtb().getDtm<BLACK, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100) : getGtb().getDtm<WHITE, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100); if (res != -INT_MAX) { cout << " res: " << res; } cout << "\n"; takeback(move, oldKey, false); if (res > best) { best = res; } } if (best > 0) { best = _INFINITE - best; } else if (best < 0) { best = -(_INFINITE - best); } cout << endl; decListId(); return best; }
/* print_result() checks to see if the game is over */ void print_result() { int i; /* is there a legal move? */ for (i = 0; i < first_move[1]; ++i) { if (makemove(gen_dat[i].m.b)) { takeback(); break; } } if (i == first_move[1]) { if (in_check(side)) { if (side == LIGHT) { printf("GR_RGB(0,0,0) mates"); if (is_mini) { draw_message("GR_RGB(0,0,0)","Mates"); } else { pz_draw_header("GR_RGB(0,0,0) mates"); } draw_end('b'); } else { printf("GR_RGB(255,255,255) mates"); if (is_mini) { draw_message("GR_RGB(255,255,255)","Mates"); } else { pz_draw_header("GR_RGB(255,255,255) mates"); } draw_end('w'); } } else { printf("Stalemate"); if (is_mini) { draw_message("Stale","Mate"); } else { pz_draw_header("Stalemate"); } draw_end('d'); } } /* else if (reps() == 3) { printf("Draw by repetition"); if (is_mini == 0) pz_draw_header("Draw by repetition"); draw_end('d'); } */ else if (fifty >= 100) { printf("Draw by fifty move rule"); if (is_mini == 0) { pz_draw_header("Draw : fifty moves"); } draw_end('d'); } }
int mainConsoleChess(int pick_side) { int computer_side; char s[256]; int m; printf("\n"); printf("Phung Nhat Huy and Pham Duy Hung's Console Chess\n"); printf("\n"); printf("Type \"help\" to displays a list of commands.\n"); printf("\n"); init_hash(); init_board(); gen(); computer_side = EMPTY; max_time = 1 << 25; max_depth = 4; for (;;) { if (side == computer_side) { /* computer's turn */ /* think about the move and make it */ //think(1); if (!pv[0][0].u) { printf("(no legal moves)\n"); computer_side = EMPTY; continue; } printf("Your enermy's move: %s\n", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen(); print_result(); continue; } /* get user input */ printf("ConsoleChess > "); if (scanf("%s", s) == EOF) return 0; if (!strcmp(s, "on")) { computer_side = side; continue; } if (!strcmp(s, "off")) { computer_side = EMPTY; continue; } if (!strcmp(s, "undo")) { if (!hply) continue; computer_side = EMPTY; takeback(); ply = 0; gen(); continue; } if (!strcmp(s, "new")) { computer_side = EMPTY; init_board(); gen(); continue; } if (!strcmp(s, "d")) { print_board(); continue; } /*if (!strcmp(s, "bench")) { computer_side = EMPTY; bench(); continue; }*/ if (!strcmp(s, "bye")) { printf("Thanks for playing. Enjoy!\n"); break; } if (!strcmp(s, "help")) { printf("on - computer plays for the side to move\n"); printf("off - computer stops playing\n"); printf("undo - takes back a move\n"); printf("new - starts a new game\n"); printf("d - display the board\n"); printf("bye - exit the program\n"); printf("Enter moves in coordinate notation, e.g., e2e4, e7e8Q (for promote moving)\n"); continue; } /* maybe the user entered a move? */ m = parse_move(s); if (m == -1 || !makemove(gen_dat[m].m.b)) printf("Illegal move.\n"); else { ply = 0; gen(); print_result(); } } //close_book(); return 0; }
int search(int alpha, int beta, int depth) { int i, j, x; BOOL c, f; /* we're as deep as we want to be; call quiesce() to get a reasonable score and return it. */ if (!depth) return quiesce(alpha,beta); ++nodes; /* do some housekeeping every 1024 nodes */ if ((nodes & 1023) == 0) checkup(); pv_length[ply] = ply; /* if this isn't the root of the search tree (where we have to pick a move and can't simply return 0) then check to see if the position is a repeat. if so, we can assume that this line is a draw and return 0. */ if (ply && reps()) return 0; /* are we too deep? */ if (ply >= MAX_PLY - 1) return eval(); if (hply >= HIST_STACK - 1) return eval(); /* are we in check? if so, we want to search deeper */ c = in_check(side); if (c) ++depth; gen(); if (follow_pv) /* are we following the PV? */ sort_pv(); f = FALSE; /* loop through the moves */ for (i = first_move[ply]; i < first_move[ply + 1]; ++i) { sort(i); if (!makemove(gen_dat[i].m.b)) continue; f = TRUE; x = -search(-beta, -alpha, depth - 1); takeback(); if (x > alpha) { /* this move caused a cutoff, so increase the history value so it gets ordered high next time we can search it */ history[(int)gen_dat[i].m.b.from][(int)gen_dat[i].m.b.to] += depth; if (x >= beta) return beta; alpha = x; /* update the PV */ pv[ply][ply] = gen_dat[i].m; for (j = ply + 1; j < pv_length[ply + 1]; ++j) pv[ply][j] = pv[ply + 1][j]; pv_length[ply] = pv_length[ply + 1]; } } /* no legal moves? then we're in checkmate or stalemate */ if (!f) { if (c) return -10000 + ply; else return 0; } /* fifty move draw rule */ if (fifty >= 100) return 0; return alpha; }
BOOL makemove(move_bytes m) { /* test to see if a castle move is legal and move the rook (the king is moved with the usual move code later) */ if (m.bits & 2) { int from, to; if (in_check(side)) return FALSE; switch (m.to) { case 62: if (color[F1] != EMPTY || color[G1] != EMPTY || attack(F1, xside) || attack(G1, xside)) return FALSE; from = H1; to = F1; break; case 58: if (color[B1] != EMPTY || color[C1] != EMPTY || color[D1] != EMPTY || attack(C1, xside) || attack(D1, xside)) return FALSE; from = A1; to = D1; break; case 6: if (color[F8] != EMPTY || color[G8] != EMPTY || attack(F8, xside) || attack(G8, xside)) return FALSE; from = H8; to = F8; break; case 2: if (color[B8] != EMPTY || color[C8] != EMPTY || color[D8] != EMPTY || attack(C8, xside) || attack(D8, xside)) return FALSE; from = A8; to = D8; break; default: /* shouldn't get here */ from = -1; to = -1; break; } color[to] = color[from]; piece[to] = piece[from]; color[from] = EMPTY; piece[from] = EMPTY; } /* back up information so we can take the move back later. */ hist_dat[hply].m.b = m; hist_dat[hply].capture = piece[(int)m.to]; hist_dat[hply].castle = castle; hist_dat[hply].ep = ep; hist_dat[hply].fifty = fifty; ++ply; ++hply; /* update the castle, en passant, and fifty-move-draw variables */ castle &= castle_mask[(int)m.from] & castle_mask[(int)m.to]; if (m.bits & 8) { if (side == LIGHT) ep = m.to + 8; else ep = m.to - 8; } else ep = -1; if (m.bits & 17) fifty = 0; else ++fifty; /* move the piece */ color[(int)m.to] = side; if (m.bits & 32) piece[(int)m.to] = m.promote; else piece[(int)m.to] = piece[(int)m.from]; color[(int)m.from] = EMPTY; piece[(int)m.from] = EMPTY; /* erase the pawn if this is an en passant move */ if (m.bits & 4) { if (side == LIGHT) { color[m.to + 8] = EMPTY; piece[m.to + 8] = EMPTY; } else { color[m.to - 8] = EMPTY; piece[m.to - 8] = EMPTY; } } /* switch sides and test for legality (if we can capture the other guy's king, it's an illegal position and we need to take the move back) */ side ^= 1; xside ^= 1; if (in_check(xside)) { takeback(); return FALSE; } return TRUE; }
int main() { int computer_side; char s[256]; int m; printf("\n"); printf("Tom Kerrigan's Simple Chess Program (TSCP)\n"); printf("version 1.81, 2/5/03\n"); printf("Copyright 1997 Tom Kerrigan\n"); printf("\n"); printf("\"help\" displays a list of commands.\n"); printf("\n"); init_hash(); init_board(); open_book(); gen(); computer_side = EMPTY; max_time = 1 << 25; max_depth = 4; for (;;) { if (side == computer_side) { /* computer's turn */ /* think about the move and make it */ think(1); if (!pv[0][0].u) { printf("(no legal moves)\n"); computer_side = EMPTY; continue; } printf("Computer's move: %s\n", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen(); print_result(); continue; } /* get user input */ printf("tscp> "); if (scanf("%s", s) == EOF) return 0; if (!strcmp(s, "on")) { computer_side = side; continue; } if (!strcmp(s, "off")) { computer_side = EMPTY; continue; } if (!strcmp(s, "st")) { scanf("%d", &max_time); max_time *= 1000; max_depth = 32; continue; } if (!strcmp(s, "sd")) { scanf("%d", &max_depth); max_time = 1 << 25; continue; } if (!strcmp(s, "undo")) { if (!hply) continue; computer_side = EMPTY; takeback(); ply = 0; gen(); continue; } if (!strcmp(s, "new")) { computer_side = EMPTY; init_board(); gen(); continue; } if (!strcmp(s, "d")) { print_board(); continue; } if (!strcmp(s, "bench")) { computer_side = EMPTY; bench(); continue; } if (!strcmp(s, "bye")) { printf("Share and enjoy!\n"); break; } if (!strcmp(s, "xboard")) { xboard(); break; } if (!strcmp(s, "help")) { printf("on - computer plays for the side to move\n"); printf("off - computer stops playing\n"); printf("st n - search for n seconds per move\n"); printf("sd n - search n ply per move\n"); printf("undo - takes back a move\n"); printf("new - starts a new game\n"); printf("d - display the board\n"); printf("bench - run the built-in benchmark\n"); printf("bye - exit the program\n"); printf("xboard - switch to XBoard mode\n"); printf("Enter moves in coordinate notation, e.g., e2e4, e7e8Q\n"); continue; } /* maybe the user entered a move? */ m = parse_move(s); if (m == -1 || !makemove(gen_dat[m].m.b)) printf("Illegal move.\n"); else { ply = 0; gen(); print_result(); } } close_book(); return 0; }
void xboard() { int computer_side; char line[256], command[256]; int m; int post = 0; signal(SIGINT, SIG_IGN); printf("\n"); init_board(); gen(); computer_side = EMPTY; for (;;) { fflush(stdout); if (side == computer_side) { think(post); if (!pv[0][0].u) { computer_side = EMPTY; continue; } printf("move %s\n", move_str(pv[0][0].b)); makemove(pv[0][0].b); ply = 0; gen(); print_result(); continue; } if (!fgets(line, 256, stdin)) return; if (line[0] == '\n') continue; sscanf(line, "%s", command); if (!strcmp(command, "xboard")) continue; if (!strcmp(command, "new")) { init_board(); gen(); computer_side = DARK; continue; } if (!strcmp(command, "quit")) return; if (!strcmp(command, "force")) { computer_side = EMPTY; continue; } if (!strcmp(command, "white")) { side = LIGHT; xside = DARK; gen(); computer_side = DARK; continue; } if (!strcmp(command, "black")) { side = DARK; xside = LIGHT; gen(); computer_side = LIGHT; continue; } if (!strcmp(command, "st")) { sscanf(line, "st %d", &max_time); max_time *= 1000; max_depth = 32; continue; } if (!strcmp(command, "sd")) { sscanf(line, "sd %d", &max_depth); max_time = 1 << 25; continue; } if (!strcmp(command, "time")) { sscanf(line, "time %d", &max_time); max_time *= 10; max_time /= 30; max_depth = 32; continue; } if (!strcmp(command, "otim")) { continue; } if (!strcmp(command, "go")) { computer_side = side; continue; } if (!strcmp(command, "hint")) { think(0); if (!pv[0][0].u) continue; printf("Hint: %s\n", move_str(pv[0][0].b)); continue; } if (!strcmp(command, "undo")) { if (!hply) continue; takeback(); ply = 0; gen(); continue; } if (!strcmp(command, "remove")) { if (hply < 2) continue; takeback(); takeback(); ply = 0; gen(); continue; } if (!strcmp(command, "post")) { post = 2; continue; } if (!strcmp(command, "nopost")) { post = 0; continue; } m = parse_move(line); if (m == -1 || !makemove(gen_dat[m].m.b)) printf("Error (unknown command): %s\n", command); else { ply = 0; gen(); print_result(); } } }
int Search::search(int depth, int alpha, int beta, _TpvLine *pline, int N_PIECE, int *mateIn) { ASSERT_RANGE(depth, 0, MAX_PLY); INC(cumulativeMovesCount); *mateIn = INT_MAX; ASSERT_RANGE(side, 0, 1); if (!getRunning()) { return 0; } int score = -_INFINITE; /* gtb */ if (gtb && pline->cmove && maxTimeMillsec > 1000 && gtb->isInstalledPieces(N_PIECE) && depth >= gtb->getProbeDepth()) { int v = gtb->getDtm<side, false>(chessboard, (uchar) chessboard[RIGHT_CASTLE_IDX], depth); if (abs(v) != INT_MAX) { *mateIn = v; int res = 0; if (v == 0) { res = 0; } else { res = _INFINITE - (abs(v)); if (v < 0) { res = -res; } } ASSERT_RANGE(res, -_INFINITE, _INFINITE); ASSERT(mainDepth >= depth); return res; } } u64 oldKey = chessboard[ZOBRISTKEY_IDX]; #ifdef DEBUG_MODE double betaEfficiencyCount = 0.0; #endif ASSERT(chessboard[KING_BLACK]); ASSERT(chessboard[KING_WHITE]); ASSERT(chessboard[KING_BLACK + side]); int extension = 0; int is_incheck_side = inCheck<side>(); if (!is_incheck_side && depth != mainDepth) { if (checkInsufficientMaterial(N_PIECE)) { if (inCheck<side ^ 1>()) { return _INFINITE - (mainDepth - depth + 1); } return -lazyEval<side>() * 2; } if (checkDraw(chessboard[ZOBRISTKEY_IDX])) { return -lazyEval<side>() * 2; } } if (is_incheck_side) { extension++; } depth += extension; if (depth == 0) { return quiescence<side, smp>(alpha, beta, -1, N_PIECE, 0); } //************* hash **************** u64 zobristKeyR = chessboard[ZOBRISTKEY_IDX] ^_random::RANDSIDE[side]; _TcheckHash checkHashStruct; if (checkHash<Hash::HASH_GREATER, smp>(false, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; if (checkHash<Hash::HASH_ALWAYS, smp>(false, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; ///********** end hash *************** if (!(numMoves & 1023)) { setRunning(checkTime()); } ++numMoves; ///********* null move *********** int n_pieces_side; _TpvLine line; line.cmove = 0; if (!is_incheck_side && !nullSearch && depth >= NULLMOVE_DEPTH && (n_pieces_side = getNpiecesNoPawnNoKing<side>()) >= NULLMOVES_MIN_PIECE) { nullSearch = true; int nullScore = -search<side ^ 1, smp>(depth - (NULLMOVES_R1 + (depth > (NULLMOVES_R2 + (n_pieces_side < NULLMOVES_R3 ? NULLMOVES_R4 : 0)))) - 1, -beta, -beta + 1, &line, N_PIECE, mateIn); nullSearch = false; if (nullScore >= beta) { INC(nNullMoveCut); return nullScore; } } ///******* null move end ******** /**************Futility Pruning****************/ /**************Futility Pruning razor at pre-pre-frontier*****/ bool futilPrune = false; int futilScore = 0; if (depth <= 3 && !is_incheck_side) { int matBalance = lazyEval<side>(); if ((futilScore = matBalance + FUTIL_MARGIN) <= alpha) { if (depth == 3 && (matBalance + RAZOR_MARGIN) <= alpha && getNpiecesNoPawnNoKing<side ^ 1>() > 3) { INC(nCutRazor); depth--; } else ///**************Futility Pruning at pre-frontier***** if (depth == 2 && (futilScore = matBalance + EXT_FUTILY_MARGIN) <= alpha) { futilPrune = true; score = futilScore; } else ///**************Futility Pruning at frontier***** if (depth == 1) { futilPrune = true; score = futilScore; } } } /************ end Futility Pruning*************/ incListId(); ASSERT_RANGE(KING_BLACK + side, 0, 11); ASSERT_RANGE(KING_BLACK + (side ^ 1), 0, 11); u64 friends = getBitmap<side>(); u64 enemies = getBitmap<side ^ 1>(); if (generateCaptures<side>(enemies, friends)) { decListId(); score = _INFINITE - (mainDepth - depth + 1); return score; } generateMoves<side>(friends | enemies); int listcount = getListSize(); if (!listcount) { --listId; if (is_incheck_side) { return -_INFINITE + (mainDepth - depth + 1); } else { return -lazyEval<side>() * 2; } } _Tmove *best = nullptr; if (checkHashStruct.hashFlag[Hash::HASH_GREATER]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_GREATER]); } else if (checkHashStruct.hashFlag[Hash::HASH_ALWAYS]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_ALWAYS]); } INC(totGen); _Tmove *move; bool checkInCheck = false; int countMove = 0; char hashf = Hash::hashfALPHA; while ((move = getNextMove(&gen_list[listId]))) { countMove++; INC(betaEfficiencyCount); if (!makemove(move, true, checkInCheck)) { takeback(move, oldKey, true); continue; } checkInCheck = true; if (futilPrune && ((move->type & 0x3) != PROMOTION_MOVE_MASK) && futilScore + PIECES_VALUE[move->capturedPiece] <= alpha && !inCheck<side>()) { INC(nCutFp); takeback(move, oldKey, true); continue; } //Late Move Reduction int val = INT_MAX; if (countMove > 4 && !is_incheck_side && depth >= 3 && move->capturedPiece == SQUARE_FREE && move->promotionPiece == NO_PROMOTION) { currentPly++; val = -search<side ^ 1, smp>(depth - 2, -(alpha + 1), -alpha, &line, N_PIECE, mateIn); ASSERT(val != INT_MAX); currentPly--; } if (val > alpha) { int doMws = (score > -_INFINITE + MAX_PLY); int lwb = max(alpha, score); int upb = (doMws ? (lwb + 1) : beta); currentPly++; val = -search<side ^ 1, smp>(depth - 1, -upb, -lwb, &line, move->capturedPiece == SQUARE_FREE ? N_PIECE : N_PIECE - 1, mateIn); ASSERT(val != INT_MAX); currentPly--; if (doMws && (lwb < val) && (val < beta)) { currentPly++; val = -search<side ^ 1, smp>(depth - 1, -beta, -val + 1, &line, move->capturedPiece == SQUARE_FREE ? N_PIECE : N_PIECE - 1, mateIn); currentPly--; } } score = max(score, val); takeback(move, oldKey, true); move->score = score; if (score > alpha) { if (score >= beta) { decListId(); ASSERT(move->score == score); INC(nCutAB); ADD(betaEfficiency, betaEfficiencyCount / (double) listcount * 100.0); ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth - extension, Hash::hashfBETA, zobristKeyR, score, move); setKillerHeuristic(move->from, move->to, 0x400); return score; } alpha = score; hashf = Hash::hashfEXACT; best = move; move->score = score; //used in it updatePv(pline, &line, move); } } ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth - extension, hashf, zobristKeyR, score, best); decListId(); return score; }
int Search::quiescence(int alpha, int beta, const char promotionPiece, int N_PIECE, int depth) { if (!getRunning()) { return 0; } ASSERT(chessboard[KING_BLACK + side]); if (!(numMovesq++ & 1023)) { setRunning(checkTime()); } int score = getScore(side, N_PIECE, alpha, beta, false); if (score >= beta) { return beta; } ///************* hash **************** char hashf = Hash::hashfALPHA; u64 zobristKeyR = chessboard[ZOBRISTKEY_IDX] ^_random::RANDSIDE[side]; _TcheckHash checkHashStruct; if (checkHash<Hash::HASH_GREATER, smp>(true, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; if (checkHash<Hash::HASH_ALWAYS, smp>(true, alpha, beta, depth, zobristKeyR, checkHashStruct)) { return checkHashStruct.res; }; ///********** end hash *************** /**************Delta Pruning ****************/ char fprune = 0; int fscore; if ((fscore = score + (promotionPiece == NO_PROMOTION ? VALUEQUEEN : 2 * VALUEQUEEN)) < alpha) { fprune = 1; } /************ end Delta Pruning *************/ if (score > alpha) { alpha = score; } incListId(); u64 friends = getBitmap<side>(); u64 enemies = getBitmap<side ^ 1>(); if (generateCaptures<side>(enemies, friends)) { decListId(); return _INFINITE - (mainDepth + depth); } if (!getListSize()) { --listId; return score; } _Tmove *move; _Tmove *best = nullptr; u64 oldKey = chessboard[ZOBRISTKEY_IDX]; if (checkHashStruct.hashFlag[Hash::HASH_GREATER]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_GREATER]); } else if (checkHashStruct.hashFlag[Hash::HASH_ALWAYS]) { sortHashMoves(listId, checkHashStruct.phasheType[Hash::HASH_ALWAYS]); } while ((move = getNextMove(&gen_list[listId]))) { if (!makemove(move, false, true)) { takeback(move, oldKey, false); continue; } /**************Delta Pruning ****************/ if (fprune && ((move->type & 0x3) != PROMOTION_MOVE_MASK) && fscore + PIECES_VALUE[move->capturedPiece] <= alpha) { INC(nCutFp); takeback(move, oldKey, false); continue; } /************ end Delta Pruning *************/ int val = -quiescence<side ^ 1, smp>(-beta, -alpha, move->promotionPiece, N_PIECE - 1, depth - 1); score = max(score, val); takeback(move, oldKey, false); if (score > alpha) { if (score >= beta) { decListId(); ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth, Hash::hashfBETA, zobristKeyR, score, move); return beta; } best = move; alpha = score; hashf = Hash::hashfEXACT; } } ASSERT(checkHashStruct.rootHash[Hash::HASH_GREATER]); ASSERT(checkHashStruct.rootHash[Hash::HASH_ALWAYS]); recordHash<smp>(getRunning(), checkHashStruct.rootHash, depth, hashf, zobristKeyR, score, best); decListId(); return score; }