From 7952a34c883a9fe3ce820f992d0d732f0abc3b4f Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Fri, 7 Jul 2023 15:53:26 +0200 Subject: [PATCH] Add pos negamax function --- Makefile | 1 + src/move.c | 36 ++++++++++++++++++++++++------------ src/move.h | 2 +- src/search.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/search.h | 25 +++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/search.c create mode 100644 src/search.h diff --git a/Makefile b/Makefile index 0bf21b3..77a3121 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,7 @@ CPPFLAGS += -DDEBUG_FEN # FEN decoding CPPFLAGS += -DDEBUG_MOVE # move generation CPPFLAGS += -DDEBUG_EVAL # eval functions CPPFLAGS += -DDEBUG_PIECE # piece list management +CPPFLAGS += -DDEBUG_SEARCH # move search ##################################### General targets .PHONY: compile cflags all clean cleanall diff --git a/src/move.c b/src/move.c index 48af799..0b16334 100644 --- a/src/move.c +++ b/src/move.c @@ -62,6 +62,20 @@ void moves_pool_stats() pool_stats(moves_pool); } +/** + * move_print() - print a move + * @movenum: move number + * @move: &move to display + * @flags: options to display + * + * Possible flags are: + * M_PR_CAPT: print move if capture + * M_PR_NCAPT: print move if non capture + * M_PR_NUM: print also move number + * M_PR_LONG: print long notation + * + * @return: 0 if nothing printed, 1 otherwise + */ int move_print(int movenum, move_t *move, move_flags_t flags) { if (flags & M_PR_CAPT && !(move->flags & M_CAPTURE)) { @@ -88,10 +102,10 @@ int move_print(int movenum, move_t *move, move_flags_t flags) printf("%s%c%c", P_SYM(move->piece), FILE2C(F88(move->from)), RANK2C(R88(move->from))); - if (move->taken) { + if (move->flags & M_CAPTURE) { printf("x"); if (flags & M_PR_LONG) - printf("%s", P_SYM(move->taken)); + printf("%s", P_SYM(move->capture)); } else { printf("-"); } @@ -172,9 +186,9 @@ static move_t *move_add(pos_t *pos, piece_t piece, square_t from, move->piece = piece; move->from = from; move->to = to; - move->taken = board[to].piece; + move->capture = board[to].piece; move->flags = M_NORMAL; - if (move->taken) + if (move->capture) move->flags |= M_CAPTURE; # ifdef DEBUG_MOVE log_i(3, "added move from %c%c to %c%c\n", @@ -336,10 +350,10 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece, bool doit) # endif if (sq_file == ep_file - 1 || sq_file == ep_file + 1) { square_t t_square = SQ88(ep_file, rank5); /* taken pawn square */ - piece_t taken = board[t_square].piece; + piece_t captured = board[t_square].piece; move = move_pawn_add(pos, piece | color , square, pos->en_passant, rank7); move->flags |= M_EN_PASSANT | M_CAPTURE; - move->taken = taken; + move->capture = captured; pos->mobility[color]++; count++; } @@ -668,11 +682,7 @@ pos_t *move_do(pos_t *pos, move_t *move) int color = COLOR(piece); square_t from = move->from, to = move->to; - /* todo: en passant, castle - */ - SET_COLOR(new->turn, OPPONENT(color)); /* pos color */ - - if (move->taken || PIECE(piece) == PAWN) /* 50 moves */ + if (move->capture || PIECE(piece) == PAWN) /* 50 moves */ new->clock_50 = 0; else new->clock_50++; @@ -739,12 +749,14 @@ pos_t *move_do(pos_t *pos, move_t *move) new->board[from].piece = 0; new->board[from].s_piece = NULL; + SET_COLOR(new->turn, OPPONENT(color)); /* pos color */ + return new; } void move_undo(pos_t *pos, __unused move_t *move) { - pos_clear(pos); + pos_del(pos); } #ifdef BIN_move diff --git a/src/move.h b/src/move.h index f8a5f55..14ac6a5 100644 --- a/src/move.h +++ b/src/move.h @@ -41,7 +41,7 @@ typedef unsigned char move_flags_t; typedef struct move_s { piece_t piece; square_t from, to; - piece_t taken; /* captured piece */ + piece_t capture; /* captured piece */ piece_t promotion; /* promoted piece */ move_flags_t flags; struct list_head list; /* next move */ diff --git a/src/search.c b/src/search.c new file mode 100644 index 0000000..65e86c2 --- /dev/null +++ b/src/search.c @@ -0,0 +1,51 @@ +/* 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 + +#include "move.h" +#include "eval.h" +#include "search.h" + +/** + * negamax() - the negamax tree. + * + */ +eval_t negamax(pos_t *pos, int depth) +{ + move_t *move, *bestmove; + pos_t *newpos; + eval_t best = EVAL_MIN, score; + + moves_gen_all(pos); + if (depth == 0) + return eval(pos) * pos->turn == WHITE? 1: -1; + + list_for_each_entry(move, &pos->moves[pos->turn], list) { + newpos = move_do(pos, move); + score = -negamax(newpos, depth - 1 ); + if(score > best) { + best = score; + bestmove = move; +# ifdef DEBUG_SEARCH + log_f(2, "depth=%d best move=", best); + move_print(0, bestmove, M_PR_LONG); + log_f(2, " eval=%d\n", best); +# endif + } + } + return best; +} diff --git a/src/search.h b/src/search.h new file mode 100644 index 0000000..4269f78 --- /dev/null +++ b/src/search.h @@ -0,0 +1,25 @@ +/* search.h - search for perfect move. + * + * Copyright (C) 2021 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 + * + */ + +#ifndef SEARCH_H +#define SEARCH_H + +#include +#include "position.h" + +#define EVAL_MIN INT_MIN +#define EVAL_MAX INT_MAX + +eval_t negamax(pos_t *pos, int depth); + +#endif /* SEARCH_H */