board min_node(board ¤t, vector <string> &traverse_log, const int depth, const bool prune, const node from, const bool save_log) const { assert(depth >= 0 && depth <= cutoff); //cout << get_node_name(current) << endl; int v = MAX_INT; /*if (depth == cutoff) { v = current.eval(who); }*/ board best = current; if ((current.who != current.whom && depth == cutoff) || !current.has_legal_move() || (!current.is_root && abs(current.eval(who)) == WINNING)) { best.val = current.eval(who); if (save_log) { traverse_log.push_back(log_string(current, depth, best.val, prune)); } return best; } if (save_log) { traverse_log.push_back(log_string(current, depth, v, prune)); } for (auto e: current.candidate) { board next = current.move(e); next.history.push_back(e); int delta_depth = current.whom != current.who; if (depth == cutoff && delta_depth) { best.val = current.eval(who); return best; } if (next.whom == next.who) { //Still player's turn next = min_node(next, traverse_log, depth + delta_depth, prune, MIN_NODE, save_log); } else { next = max_node(next, traverse_log, depth + delta_depth, prune, MIN_NODE, save_log); } if (next.val < v) { v = next.val; best = next; } if (prune) { if (best.val <= current.alpha) { if (save_log) { traverse_log.push_back(log_string(current, depth, v, prune)); } return best; } current.beta = min(current.beta, best.val); } if (save_log) { traverse_log.push_back(log_string(current, depth, v, prune)); } //cout << get_node_name(current) << endl; } return best; }
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; }
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; }