diff --git a/src/search.c-move-to-temp-migration-bitboard__search.c b/src/search.c-move-to-temp-migration-bitboard__search.c new file mode 100644 index 0000000..bb0dd78 --- /dev/null +++ b/src/search.c-move-to-temp-migration-bitboard__search.c @@ -0,0 +1,237 @@ +/* search.c - search good moves. + * + * Copyright (C) 2023 Bruno Raoult ("br") + * Licensed under the GNU General Public License v3.0 or later. + * Some rights reserved. See COPYING. + * + * You should have received a copy of the GNU General Public License along with this + * program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + + +#include +#include +#include "debug.h" + +#include "move.h" +#include "eval.h" +#include "search.h" + +/** + * negamax() - search position negamax. + * @pos: &position to search + * @depth: Wanted depth. + * @color: 1 for white, -1 for black. + * + * Calculate the negamax value of @pos. This is an extensive search, with + * absolutely no cutoff. + * + * @return: The @pos negamax evaluation. + */ +eval_t negamax(pos_t *pos, int depth, int color) +{ + move_t *move; + pos_t *newpos; + eval_t best = EVAL_MIN, score; + + pos->node_count++; + if (depth == 0) { + moves_gen_all_nomoves(pos); + score = eval(pos) * color; + return score; + } + moves_gen_all(pos); + list_for_each_entry(move, &pos->moves[pos->turn], list) { + newpos = move_do(pos, move); + score = -negamax(newpos, depth - 1, -color); + pos->node_count += newpos->node_count; + move->negamax = score; + if (score > best) { + best = score; + pos->bestmove = move; + } + move_undo(newpos, move); + } + return best; +} + + +/** + * pvs() - Principal Variation Search. + * @pos: &position to search + * @depth: wanted depth. + * @alpha: alpha value. + * @beta: beta value. + * @color: 1 for white, -1 for black. + * + * Calculate the PVS value of @pos. + * See https://en.wikipedia.org/wiki/Principal_variation_search + * + * Moves list should be first generated and evaluated/sorted. + * + * @return: The @pos PVS evaluation. + */ +eval_t pvs(pos_t *pos, int depth, int alpha, int beta, int color) +{ + move_t *move; + pos_t *newpos; + eval_t score = EVAL_INVALID; + bool firstchild = true; + + pos->node_count++; + + if (depth == 0) { + //return quiesce(p, alpha, beta); /* leaf node */ + moves_gen_all_nomoves(pos); + score = eval(pos) * color; + log_f(2, "Terminal: depth=%d ", depth); + log_f(2, "score=%d alpha=%d beta=%d\n", score, alpha, beta); + return score; + } + + moves_gen_all(pos); + //moves_print(pos, M_PR_EVAL); + /* do the full search for first child */ + //move = list_first_entry_or_null(&pos->moves[pos->turn], move_t, list); + + list_for_each_entry(move, &pos->moves[pos->turn], list) { + newpos = move_do(pos, move); + log(2, "%.*s", 5 - depth, " "); + if (firstchild) { /* first child */ + score = -pvs(newpos, depth - 1, -beta, -alpha, -color); + log_f(2, "First child depth=%d move=", depth); + //move_print(0, move, 0); + log(2, "score=%d alpha=%d beta=%d\n", score, alpha, beta); + pos->bestmove = move; + } else { + /* search with a null window */ + score = -pvs(newpos, depth - 1, -alpha - 1, -alpha, -color); + log_f(2, "Other child depth=%d move=", depth); + //move_print(0, move, 0); + log_f(2, "score=%d alpha=%d beta=%d ", score, alpha, beta); + /* for fail-soft: if (score > alpha && score < beta) */ + if (score > alpha) { + /* if failed high, do a full re-search */ + log_f(2, "doing full search."); + score = -pvs(newpos, depth - 1, -beta, -alpha, -color); + } + log(2, "\n"); + } + pos->node_count += newpos->node_count; + move_undo(newpos, move); + if (score >= beta) { /* fail-hard hard beta cut-off */ + log(2, "%.*s", 5 - depth, " "); + log_f(2, "depth=%d score=%d alpha=%d beta=%d beta cut-off.\n", + depth, score, alpha, beta); + return beta; + } + if (score > alpha) { + log(2, "%.*s", 5 - depth, " "); + log_f(2, "depth=%d setting new alpha from %d to %d\n", + depth, alpha, score); + alpha = score; + pos->bestmove = move; + } + move->pos = NULL; + move->negamax = score; + firstchild = false; + } + + return alpha; +} + +/* + * int negascout (pos_t *pos, int depth, int alpha, int beta ) + * { /\* compute minimax value of position p *\/ + * move_t *move; + * pos_t *newpos; + * eval_t best = EVAL_MIN, score; + * + * int a, b, t, i; + * + * if (depth == 0) { + * //return quiesce(p, alpha, beta); /\* leaf node *\/ + * moves_gen_all_nomoves(pos); + * score = eval(pos) * color; + * return score; + * } + * moves_gen_all(pos); + * a = alpha; + * b = beta; + * list_for_each_entry(move, &pos->moves[pos->turn], list) { + * log(1, "%.*s", 5 - depth, " "); + * newpos = move_do(pos, move); + * // for ( i = 1; i <= w; i++ ) { + * t = -negascout (newpos, depth - 1, -b, -alpha); + * if ( (t > a) && (t < beta) && (i > 1) ) + * t = -NegaScout ( p_i, -beta, -alpha ); /\* re-search *\/ + * alpha = max( alpha, t ); + * if ( alpha >= beta ) + * return alpha; /\* cut-off *\/ + * b = alpha + 1; /\* set new null window *\/ + * } + * return alpha; + * } + */ + +/* + * int quiesce(pos_t *pos, int alpha, int beta) + * { + * int stand_pat = eval(pos); + * + * if( stand_pat >= beta ) + * return beta; + * if( alpha < stand_pat ) + * alpha = stand_pat; + * + * /\* + * * until( every_capture_has_been_examined ) { + * * MakeCapture(); + * * score = -Quiesce( -beta, -alpha ); + * * TakeBackMove(); + * * + * * if( score >= beta ) + * * return beta; + * * if( score > alpha ) + * * alpha = score; + * * } + * *\/ + * return alpha; + * } + */ + +/** + * ab_negamax() - search position negamax with alpha-beta cutoff. + * @pos: &position to search + * @depth: Wanted depth. + * @color: 1 for white, -1 for black. + * + * Calculate the negamax value of @pos, with alpha-beta pruning. + * + * @return: The @pos negamax evaluation. + */ +/*int ab_negamax(pos_t *pos, int alpha, int beta, int depth) +{ + move_t *move; + pos_t *newpos; + eval_t best = EVAL_MIN, score; + + if(depth == 0) { + //return quiesce( alpha, beta ); + moves_gen_all_nomoves(pos); + score = eval(pos) * color; + return score; + } + for ( all moves) { + score = -alphaBeta( -beta, -alpha, depthleft - 1 ); + if( score >= beta ) + return beta; // fail hard beta-cutoff + if( score > alpha ) + alpha = score; // alpha acts like max in MiniMax + } + return alpha; +} +*/