bool calcMove(board b, move &bestMove) { vector<move> moves = b.genMoves(); moveOrderer order(b); sort(moves.begin(), moves.end(), order); if (moves.size() == 0) return false; int besti = -1; int bestScore = -MATESCORE_MAX; for (int i=0; i<moves.size(); i++) { board temp = b; temp.executeMove(moves[i]); pushHistory(temp); int curScore = minimax(DEPTH, temp, -MATESCORE_MAX, -bestScore+50, 0)+rand()%50; popHistory(); if (curScore > bestScore) { besti = i; bestScore = curScore; } } bestMove = moves[besti]; return true; }
int quiesence(board b, int alpha, int beta, bool hasPass) { if (b.inCheck().first || b.inCheck().second) return minimax(1, b, alpha, beta, 0); lookupResult res; bool haveHit = queryTable(b, res); int bestSoFar; if (hasPass) { alpha = max(b.eval(), alpha); if (alpha >= beta) return alpha; if (haveHit) { if (res.type == SCORE_LOWERBOUND) { if (res.evaluation >= beta) return -res.evaluation; else alpha = max(alpha, res.evaluation); } if (res.type == SCORE_UPPERBOUND) { if (res.evaluation <= alpha) return -alpha; else beta = min(beta, res.evaluation); } if (res.type == SCORE_EXACT) return -max(alpha, res.evaluation); } bestSoFar = alpha; } else { if (haveHit) { if (res.type == SCORE_LOWERBOUND) { if (res.evaluation >= beta) return -res.evaluation; else alpha = max(alpha, res.evaluation); } if (res.type == SCORE_UPPERBOUND) { if (res.evaluation <= alpha) return -res.evaluation; else beta = min(beta, res.evaluation); } if (res.type == SCORE_EXACT) return -res.evaluation; } b.flipToMove(); bestSoFar = quiesence(b, -beta, -alpha, true); b.flipToMove(); } vector<move> moves = b.genMoves(); moveOrderer order(b); sort(moves.begin(), moves.end(), order); int besti = 0; for (int i=0; i<moves.size(); i++) { if (b.moveGains(moves[i]) < 300) break; board temp = b; temp.executeMove(moves[i]); int curScore = quiesence(temp, -beta, -max(alpha, bestSoFar), false); if (curScore > bestSoFar) { bestSoFar = curScore; besti = i; } if (bestSoFar >= beta) break; } putTable(b, 0, bestSoFar, moves[besti], alpha, beta); return -bestSoFar; }
bool calcMoveID(board b, move &bestMove, clock_t deadline, clock_t hardline) { vector<move> moves = b.genMoves(); vector<pair<int, move> > moveEvalPairs; movePairOrderer order(b); if (moves.size() == 0) return false; for (int i=0; i<moves.size(); i++) moveEvalPairs.push_back(make_pair(0, moves[i])); sort(moveEvalPairs.begin(), moveEvalPairs.end(), order); for (int depth = 0; deadline > clock() && moveEvalPairs.size() > 1; depth++) { cout << "info depth " << depth << endl; int besti = -1; int bestScore = -MATESCORE_MAX; vector<pair<int, move> > newPairs; int qref = 0; for (int i=0; i<moveEvalPairs.size(); i++) { if ((i)*DONE_FACTOR < moveEvalPairs.size()*TOTAL_FACTOR && deadline <= clock()) goto retMove; if (hardline <= clock()) goto retMove; board temp = b; temp.executeMove(moveEvalPairs[i].second); pushHistory(temp); int curScore = minimax(depth, temp, -bestScore, -bestScore+1, 0); if (curScore >= bestScore) curScore = minimax(depth, temp, -MATESCORE_MAX, -bestScore+1, 0); else qref++; popHistory(); newPairs.push_back(make_pair(curScore, moveEvalPairs[i].second)); if (curScore > bestScore) { besti = i; bestScore = curScore; } } cout << "info string quickrefute " << qref << "/" << moveEvalPairs.size() << endl; cout << "info string quickrefute " << (double(qref)/double(moveEvalPairs.size())) << endl; moveEvalPairs.swap(newPairs); sort(moveEvalPairs.begin(), moveEvalPairs.end(), order); if (moveEvalPairs[0].first >= MATESCORE_MIN || moveEvalPairs[0].first <= -MATESCORE_MIN) break; // mate found, further calc not neccessary // eliminate known bad moves int nSize = 1; while (nSize < moveEvalPairs.size() && moveEvalPairs[nSize].first > -MATESCORE_MIN) nSize++; moveEvalPairs.resize(nSize); } retMove: int range = 1; while (range < moveEvalPairs.size() && moveEvalPairs[range].first == moveEvalPairs[0].first) range++; int index = rand()%range; bestMove = moveEvalPairs[index].second; return true; }
int minimax(int depth, board b, int alpha, int beta, int movesDone) { lookupResult res; bool haveHit = queryTable(b, res); if (haveHit && depth <= res.depth) { if (res.type == SCORE_LOWERBOUND) { if (res.evaluation >= beta) return -res.evaluation; else alpha = max(alpha, res.evaluation); } if (res.type == SCORE_UPPERBOUND) { if (res.evaluation <= alpha) return -res.evaluation; else beta = min(beta, res.evaluation); } if (res.type == SCORE_EXACT) return -res.evaluation; } //if (depth == 0) // return quiesence(b, alpha, beta, false); if (depth == 0) return -b.eval(); if (inHistory(b)) return 0; moveOrderer order(b); vector<move> moves = b.genMoves(); sort(moves.begin(), moves.end(), order); if (moves.size() == 0) { if (b.inCheck().first && !b.getToMove()) return MATESCORE(movesDone); if (b.inCheck().second && b.getToMove()) return MATESCORE(movesDone); return 0; } if (b.getPlyClock() >= 100) return 0; int bestSoFar = -MATESCORE_MAX; if (haveHit) { board temp = b; temp.executeMove(res.bestMove); pushHistory(temp); bestSoFar = minimax(depth-1, temp, -beta, -alpha, movesDone+1); popHistory(); } int besti = -1; for (int i=0; i<moves.size() && bestSoFar < beta; i++) { if (haveHit && moves[i] == res.bestMove) continue; board temp = b; temp.executeMove(moves[i]); pushHistory(temp); int curScore = minimax(depth-1, temp, -beta, -max(alpha, bestSoFar), movesDone+1); popHistory(); if (curScore > bestSoFar) { bestSoFar = curScore; besti = i; } } if (besti == -1 && haveHit) putTable(b, depth, bestSoFar, res.bestMove, alpha, beta); else putTable(b, depth, bestSoFar, moves[besti], alpha, beta); return -bestSoFar; }