From f530a13481137e2ea4528b87e5928fef165b7f05 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Wed, 19 Jun 2024 11:01:48 +0200 Subject: [PATCH] prepare brchess, eval, eval-simple for future use --- scripts/git-split.sh | 45 +++-- src/brchess.c | 424 ++++++++++++++++++++++++------------------- src/eval-simple.c | 390 +++++++++++++++++++-------------------- src/eval.c | 182 ++++++++++--------- 4 files changed, 543 insertions(+), 498 deletions(-) diff --git a/scripts/git-split.sh b/scripts/git-split.sh index 3271e47..5d593b7 100755 --- a/scripts/git-split.sh +++ b/scripts/git-split.sh @@ -1,38 +1,35 @@ #!/usr/bin/env bash # -# Copy a git file, keeping history. -# Source: https://stackoverflow.com/a/53849613/3079831 +# Duplicate file, with history (well, sort of) # -# Buggy, "to" file has no history... -# Maybe try: +# Copy a git file, keeping history. +# Sources: +# https://stackoverflow.com/a/53849613/3079831 # https://stackoverflow.com/a/75942970/3079831 +CMDNAME=${0##*/} # script name -# if (( $# != 2 )) ; then -# echo "Usage: git-split.sh original copy" -# exit 1 -# fi +if (( $# != 2 )); then + printf "Usage: %s original copy\n" "$CMDNAME" + exit 1 +fi -# from="$1" -# to="$2" -# branch="split-file" -# tmp="$from-temp-copy" +from="$1" +to="$2" +branch="split-file" -# git switch -c "$branch" -# git mv "$from" "$to" -# git commit -n -m "Split $from to $to - step 1" +printf "Dup from=[%s] to=[%s] branch=[%s]\n" "$from" "$to" "$branch" -# #REV=$(git rev-parse HEAD) -# git switch - +git checkout -b "$branch" # create and switch to branch -# git mv "$from" "$tmp" -# git commit -n -m "Split $from to $to - step 2" -# git merge "$branch" +git mv "$from" "$to" # make the duplicate +git commit -m "Duplicate $from to $to" -# git commit -a -n -m "Split $from to $to - step 3" -# git mv "$tmp" "$from" -# git commit -n -m "Split file $from to $to - step 4" +git checkout HEAD~ "$from" # bring back the original +git commit -m "Restore duplicated $from" + +git checkout - # switch back to source branch +git merge --no-ff "$branch" -m "Merge $branch" # merge dup into source branch -# git branch -d "$branch" exit 0 diff --git a/src/brchess.c b/src/brchess.c index 9af49e7..522d6bc 100644 --- a/src/brchess.c +++ b/src/brchess.c @@ -19,17 +19,19 @@ #include #include -#include -#include +//#include +//#include -#include "brchess.h" #include "chessdefs.h" -#include "board.h" -#include "piece.h" -#include "move.h" +#include "position.h" +#include "brchess.h" +#include "hash.h" +//#include "board.h" +//#include "piece.h" +//#include "move.h" #include "fen.h" -#include "eval.h" -#include "eval-simple.h" +//#include "eval.h" +//#include "eval-simple.h" #include "search.h" struct command { @@ -51,48 +53,49 @@ struct command *find_command (char *); char *stripwhite (char *string); /* The names of functions that actually do the manipulation. */ +int do_ucinewgame(pos_t *, char*); +int do_uci(pos_t *, char*); +int do_isready(pos_t *, char*); + +int do_position(pos_t *, char*); +int do_prpos(pos_t *, char*); +int do_perft(pos_t *, char*); + int do_help(pos_t *, char*); -int do_fen(pos_t *, char*); -int do_init(pos_t *, char*); -int do_pos(pos_t *, char*); -int do_genmoves(pos_t *, char*); -int do_prmoves(pos_t *, char*); -//int do_prmovepos(pos_t *pos, char *arg); -int do_prpieces(pos_t *pos, char *arg); -int do_memstats(pos_t *, char*); -int do_eval(pos_t *, char*); -int do_simple_eval(pos_t *, char*); -int do_move(pos_t *, char*); int do_quit(pos_t *, char*); -int do_debug(pos_t *, char*); -int do_depth(pos_t *, char*); -int do_search(pos_t *, char*); -int do_pvs(pos_t *, char*); struct command commands[] = { + { "ucinewgame", do_ucinewgame, "new game" }, + { "uci", do_uci, "start uci" }, + { "isready", do_isready, "start uci" }, + + { "position", do_position, "position startpos|fen [moves ...]" }, + { "prpos", do_prpos, "Print current position" }, + { "perft", do_perft, "perft depth [yes]" }, + { "help", do_help, "Display this text" }, - { "?", do_help, "Synonym for 'help'" }, - { "fen", do_fen, "Set position to FEN" }, - { "init", do_init, "Set position to normal start position" }, - { "pos", do_pos, "Print current position" }, { "quit", do_quit, "Quit" }, - { "genmove", do_genmoves, "Generate move list for " }, - { "prmoves", do_prmoves, "Print position move list" }, -// { "prmovepos", do_prmovepos, "Print Nth move resulting position" }, - { "prpieces", do_prpieces, "Print Pieces (from pieces lists)" }, - { "memstats", do_memstats, "Generate next move list" }, - { "eval", do_eval, "Eval current position" }, - { "simple-eval", do_simple_eval, "Simple eval current position" }, - { "do_move", do_move, "execute nth move on current position" }, - { "debug", do_debug, "Set log level to LEVEL" }, - { "depth", do_depth, "Set search depth to N" }, - { "search", do_search, "Search best move (negamax)" }, - { "pvs", do_pvs, "Search best move (Principal Variation Search)" }, + /* + * { "init", do_init, "Set position to normal start position" }, + + * { "genmove", do_genmoves, "Generate move list for " }, + * { "prmoves", do_prmoves, "Print position move list" }, + * // { "prmovepos", do_prmovepos, "Print Nth move resulting position" }, + * { "prpieces", do_prpieces, "Print Pieces (from pieces lists)" }, + * { "memstats", do_memstats, "Generate next move list" }, + * { "eval", do_eval, "Eval current position" }, + * { "simple-eval", do_simple_eval, "Simple eval current position" }, + * { "do_move", do_move, "execute nth move on current position" }, + * { "debug", do_debug, "Set log level to LEVEL" }, + * { "depth", do_depth, "Set search depth to N" }, + * { "search", do_search, "Search best move (negamax)" }, + * { "pvs", do_pvs, "Search best move (Principal Variation Search)" }, + */ { NULL, (int(*)()) NULL, NULL } }; static int done=0; -static int depth=1; +//static int depth=1; int brchess(pos_t *pos) { @@ -104,7 +107,7 @@ int brchess(pos_t *pos) rl_char_is_quoted_p = "e_detector; while (!done) { - buffer = readline("chess> "); + buffer = readline(NULL); if (!buffer) break; /* Remove leading and trailing whitespace from the line. @@ -123,7 +126,6 @@ int brchess(pos_t *pos) return 0; } -//char **commands_completion(const char *text, int start, int end) char **commands_completion(const char *text, __unused int start, __unused int end) { rl_attempted_completion_over = 1; @@ -193,8 +195,8 @@ char *escape(const char *original) int quote_detector(char *line, int index) { return index > 0 - && line[index - 1] == '\\' - &&!quote_detector(line, index - 1); + && line[index - 1] == '\\' + &&!quote_detector(line, index - 1); } /* Execute a command line. */ @@ -204,6 +206,7 @@ int execute_line(pos_t *pos, char *line) struct command *command; char *word; + /* strip multiple blank characters */ /* Isolate the command word. */ i = 0; while (line[i] && whitespace(line[i])) @@ -219,7 +222,7 @@ int execute_line(pos_t *pos, char *line) command = find_command(word); if (!command) { - fprintf(stderr, "%s: Unknown command.\n", word); + fprintf(stderr, "%s: Unknown command. Try 'help'.\n", word); return -1; } @@ -250,7 +253,7 @@ struct command *find_command(char *name) into STRING. */ char *stripwhite(char *string) { - register char *s, *t; + char *s, *t; for (s = string; whitespace(*s); s++) ; @@ -266,61 +269,55 @@ char *stripwhite(char *string) return s; } -int do_eval(__unused pos_t *pos, __unused char *arg) -{ - eval_t material[2], control[2], mobility[2]; - for (int color = WHITE; color <= BLACK; ++color) { - material[color] = eval_material(pos, color); - control[color] = eval_square_control(pos, color); - mobility[color] = eval_mobility(pos, color); - printf("%s: material=%d mobility=%d controlled=%d\n", - color? "Black": "White", material[color], - mobility[color], control[color]); - } - eval_t res = eval(pos); - printf("eval = %d centipawns\n", res); - return 1; -} +/* + * int do_eval(__unused pos_t *pos, __unused char *arg) + * { + * eval_t material[2], control[2], mobility[2]; + * for (int color = WHITE; color <= BLACK; ++color) { + * material[color] = eval_material(pos, color); + * control[color] = eval_square_control(pos, color); + * mobility[color] = eval_mobility(pos, color); + * printf("%s: material=%d mobility=%d controlled=%d\n", + * color? "Black": "White", material[color], + * mobility[color], control[color]); + * } + * eval_t res = eval(pos); + * printf("eval = %d centipawns\n", res); + * return 1; + * } + * + * int do_simple_eval(__unused pos_t *pos, __unused char *arg) + * { + * eval_t eval = eval_simple(pos); + * printf("eval = %d centipawns\n", eval); + * return 1; + * } + */ -int do_simple_eval(__unused pos_t *pos, __unused char *arg) -{ - eval_t eval = eval_simple(pos); - printf("eval = %d centipawns\n", eval); - return 1; -} +/* + * int do_init(pos_t *pos, __unused char *arg) + * { + * startpos(pos); + * return 1; + * } + */ -int do_fen(pos_t *pos, char *arg) -{ - fen2pos(pos, arg); - return 1; -} - -int do_init(pos_t *pos, __unused char *arg) -{ - pos_startpos(pos); - return 1; -} - -int do_pos(pos_t *pos, __unused char *arg) -{ - pos_print(pos); - return 1; -} - -int do_genmoves(pos_t *pos, __unused char *arg) -{ - moves_gen_all(pos); - return 1; -} - -int do_prmoves(pos_t *pos, __unused char *arg) -{ - uint debug_level = debug_level_get(); - debug_level_set(1); - moves_print(pos, M_PR_SEPARATE | M_PR_NUM | M_PR_LONG); - debug_level_set(debug_level); - return 1; -} +/* + * int do_genmoves(pos_t *pos, __unused char *arg) + * { + * moves_gen_all(pos); + * return 1; + * } + * + * int do_prmoves(pos_t *pos, __unused char *arg) + * { + * uint debug_level = debug_level_get(); + * debug_level_set(1); + * moves_print(pos, M_PR_SEPARATE | M_PR_NUM | M_PR_LONG); + * debug_level_set(debug_level); + * return 1; + * } + */ /* * int do_prmovepos(pos_t *pos, char *arg) @@ -342,58 +339,98 @@ int do_prmoves(pos_t *pos, __unused char *arg) * } */ -int do_prpieces(pos_t *pos, __unused char *arg) +/* + * int do_prpieces(pos_t *pos, __unused char *arg) + * { + * log_f(1, "%s\n", arg); + * pos_pieces_print(pos); + * return 1; + * } + * + * int do_memstats(__unused pos_t *pos,__unused char *arg) + * { + * moves_pool_stats(); + * piece_pool_stats(); + * pos_pool_stats(); + * return 1; + * } + */ + +/* + * int do_move(__unused pos_t *pos, __unused char *arg) + * { + * int i = 1, nmove = atoi(arg); + * move_t *move; + * pos_t *newpos; + * + * if (list_empty(&pos->moves[pos->turn])) { + * log_f(1, "No moves list.\n"); + * return 0; + * } + * list_for_each_entry(move, &pos->moves[pos->turn], list) { + * if (i == nmove) + * goto doit; + * i++; + * } + * log_f(1, "Invalid <%d> move, should be <1-%d>.\n", nmove, i); + * return 0; + * doit: + * newpos = move_do(pos, move); + * pos_print(newpos); + * + * return 1; + * } + */ + +int do_ucinewgame(__unused pos_t *pos, __unused char *arg) { - log_f(1, "%s\n", arg); - pos_pieces_print(pos); + tt_clear(); return 1; } -int do_memstats(__unused pos_t *pos,__unused char *arg) +int do_uci(__unused pos_t *pos, __unused char *arg) { - moves_pool_stats(); - piece_pool_stats(); - pos_pool_stats(); + printf("id name brchess " VERSION "\n"); + printf("id author Bruno Raoult\n"); + printf("option option name Hash type spin default %d min %d max %d\n", + hash_tt.mb, HASH_SIZE_MIN, HASH_SIZE_MAX); + printf("uciok\n"); return 1; } -int do_move(__unused pos_t *pos, __unused char *arg) +int do_isready(__unused pos_t *pos, __unused char *arg) { - int i = 1, nmove = atoi(arg); - move_t *move; - pos_t *newpos; - - if (list_empty(&pos->moves[pos->turn])) { - log_f(1, "No moves list.\n"); - return 0; - } - list_for_each_entry(move, &pos->moves[pos->turn], list) { - if (i == nmove) - goto doit; - i++; - } - log_f(1, "Invalid <%d> move, should be <1-%d>.\n", nmove, i); - return 0; -doit: - newpos = move_do(pos, move); - pos_print(newpos); - + printf("readyok\n"); return 1; } -int do_quit(__unused pos_t *pos, __unused char *arg) +int do_position(pos_t *pos, char *arg) { - return done = 1; -} - -int do_debug(__unused pos_t *pos, __unused char *arg) -{ - debug_level_set(atoi(arg)); + printf("position:[%s]\n", arg); + fen2pos(pos, arg); return 1; } -/* Print out help for ARG, or for all of the commands if ARG is - not present. */ +int do_prpos(pos_t *pos, __unused char *arg) +{ + pos_print(pos); + return 1; +} + +int do_perft(pos_t *pos, __unused char *arg) +{ + pos_print(pos); + return 1; +} + +/* + * int do_debug(__unused pos_t *pos, __unused char *arg) + * { + * debug_level_set(atoi(arg)); + * return 1; + * } + */ + int do_help(__unused pos_t *pos, __unused char *arg) { int i; @@ -426,57 +463,68 @@ int do_help(__unused pos_t *pos, __unused char *arg) return 0; } -int do_depth(__unused pos_t *pos, char *arg) +int do_quit(__unused pos_t *pos, __unused char *arg) { - depth = atoi(arg); - printf("depth = %d\n", depth); - return 1; - + return done = 1; } -int do_search(pos_t *pos, __unused char *arg) -{ - int debug_level = debug_level_get(); - float timer1, timer2, nodes_sec; +/* Print out help for ARG, or for all of the commands if ARG is + not present. */ +/* + * int do_depth(__unused pos_t *pos, char *arg) + * { + * depth = atoi(arg); + * printf("depth = %d\n", depth); + * return 1; + * + * } + * + * int do_search(pos_t *pos, __unused char *arg) + * { + * int debug_level = debug_level_get(); + * float timer1, timer2, nodes_sec; + * + * timer1 = debug_timer_elapsed(); + * negamax(pos, depth, pos->turn == WHITE ? 1 : -1); + * timer2 = debug_timer_elapsed(); + * nodes_sec = (float) pos->node_count / ((float) (timer2 - timer1) / (float)NANOSEC); + * log(1, "best="); + * debug_level_set(1); + * move_print(0, pos->bestmove, 0); + * debug_level_set(debug_level); + * log(1, " negamax=%d\n", pos->bestmove->negamax); + * printf("Depth:%d Nodes:%luK time:%.02fs (%.0f kn/s)\n", depth, + * pos->node_count / 1000, (timer2 - timer1)/NANOSEC, nodes_sec/1000); + * return 1; + * } + */ - timer1 = debug_timer_elapsed(); - negamax(pos, depth, pos->turn == WHITE ? 1 : -1); - timer2 = debug_timer_elapsed(); - nodes_sec = (float) pos->node_count / ((float) (timer2 - timer1) / (float)NANOSEC); - log(1, "best="); - debug_level_set(1); - move_print(0, pos->bestmove, 0); - debug_level_set(debug_level); - log(1, " negamax=%d\n", pos->bestmove->negamax); - printf("Depth:%d Nodes:%luK time:%.02fs (%.0f kn/s)\n", depth, - pos->node_count / 1000, (timer2 - timer1)/NANOSEC, nodes_sec/1000); - return 1; -} - -int do_pvs(pos_t *pos, __unused char *arg) -{ - int debug_level = debug_level_get(); - float timer1, timer2, nodes_sec; - eval_t _pvs; - - timer1 = debug_timer_elapsed(); - moves_gen_eval_sort(pos); - _pvs = pvs(pos, depth, EVAL_MIN, EVAL_MAX, pos->turn == WHITE ? 1 : -1); - timer2 = debug_timer_elapsed(); - nodes_sec = (float) pos->node_count / ((float) (timer2 - timer1) / (float)NANOSEC); - log(1, "best="); - if (pos->bestmove) { - debug_level_set(1); - move_print(0, pos->bestmove, 0); - debug_level_set(debug_level); - log(1, " pvs=%d stored=%d\n", _pvs, pos->bestmove->negamax); - } else { - log(1, ""); - } - printf("Depth:%d Nodes:%luK time:%.02fs (%.0f kn/s)\n", depth, - pos->node_count / 1000, (timer2 - timer1)/NANOSEC, nodes_sec/1000); - return 1; -} +/* + * int do_pvs(pos_t *pos, __unused char *arg) + * { + * int debug_level = debug_level_get(); + * float timer1, timer2, nodes_sec; + * eval_t _pvs; + * + * timer1 = debug_timer_elapsed(); + * moves_gen_eval_sort(pos); + * _pvs = pvs(pos, depth, EVAL_MIN, EVAL_MAX, pos->turn == WHITE ? 1 : -1); + * timer2 = debug_timer_elapsed(); + * nodes_sec = (float) pos->node_count / ((float) (timer2 - timer1) / (float)NANOSEC); + * log(1, "best="); + * if (pos->bestmove) { + * debug_level_set(1); + * move_print(0, pos->bestmove, 0); + * debug_level_set(debug_level); + * log(1, " pvs=%d stored=%d\n", _pvs, pos->bestmove->negamax); + * } else { + * log(1, ""); + * } + * printf("Depth:%d Nodes:%luK time:%.02fs (%.0f kn/s)\n", depth, + * pos->node_count / 1000, (timer2 - timer1)/NANOSEC, nodes_sec/1000); + * return 1; + * } + */ /** main() * options: @@ -493,20 +541,16 @@ static int usage(char *prg) int main(int ac, char **av) { - pos_t *pos; + pos_t *pos = pos_new(); int opt; - piece_pool_init(); - moves_pool_init(); - pos_pool_init(); - pos = pos_get(); - debug_init(1, stderr, true); - eval_simple_init(); + init_all(); + printf("brchess " VERSION "\n"); while ((opt = getopt(ac, av, "d:f:")) != -1) { switch (opt) { case 'd': - debug_level_set(atoi(optarg)); + //debug_level_set(atoi(optarg)); break; case 'f': fen2pos(pos, optarg); diff --git a/src/eval-simple.c b/src/eval-simple.c index a56d599..7d10e31 100644 --- a/src/eval-simple.c +++ b/src/eval-simple.c @@ -1,199 +1,201 @@ -/* eval-simple.c - simple position evaluation. - * - * 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 "br.h" -#include "debug.h" - -#include "piece.h" -#include "eval-simple.h" -#include "position.h" - /* - * Tables are from https://www.chessprogramming.org/Simplified_Evaluation_Function + * /\* eval-simple.c - simple position evaluation. + * * + * * 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 + * * + * *\/ * - * Attention! Tables are black point of view (to be visually easier to read). - */ - -static int mg_pawn[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50, 50, 50, 50, 50, 50, - 10, 10, 20, 30, 30, 20, 10, 10, - 5, 5, 10, 25, 25, 10, 5, 5, - 0, 0, 0, 20, 20, 0, 0, 0, - 5, -5, -10, 0, 0, -10, -5, 5, - 5, 10, 10, -20, -20, 10, 10, 5, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static int mg_knight[] = { - -50, -40, -30, -30, -30, -30, -40, -50, - -40, -20, 0, 0, 0, 0, -20, -40, - -30, 0, 10, 15, 15, 10, 0, -30, - -30, 5, 15, 20, 20, 15, 5, -30, - -30, 0, 15, 20, 20, 15, 0, -30, - -30, 5, 10, 15, 15, 10, 5, -30, - -40, -20, 0, 5, 5, 0, -20, -40, - -50, -40, -30, -30, -30, -30, -40, -50 -}; - -static int mg_bishop[] = { - -20, -10, -10, -10, -10, -10, -10, -20, - -10, 0, 0, 0, 0, 0, 0, -10, - -10, 0, 5, 10, 10, 5, 0, -10, - -10, 5, 5, 10, 10, 5, 5, -10, - -10, 0, 10, 10, 10, 10, 0, -10, - -10, 10, 10, 10, 10, 10, 10, -10, - -10, 5, 0, 0, 0, 0, 5, -10, - -20, -10, -10, -10, -10, -10, -10, -20 -}; - -static int mg_rook[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 10, 10, 10, 10, 10, 10, 5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - -5, 0, 0, 0, 0, 0, 0, -5, - 0, 0, 0, 5, 5, 0, 0, 0 -}; - -static int mg_queen[] = { - -20, -10, -10, -5, -5, -10, -10, -20, - -10, 0, 0, 0, 0, 0, 0, -10, - -10, 0, 5, 5, 5, 5, 0, -10, - -5, 0, 5, 5, 5, 5, 0, -5, - 0, 0, 5, 5, 5, 5, 0, -5, - -10, 5, 5, 5, 5, 5, 0, -10, - -10, 0, 5, 0, 0, 0, 0, -10, - -20, -10, -10, -5, -5, -10, -10, -20 -}; - -static int mg_king[] = { - -30, -40, -40, -50, -50, -40, -40, -30, - -30, -40, -40, -50, -50, -40, -40, -30, - -30, -40, -40, -50, -50, -40, -40, -30, - -30, -40, -40, -50, -50, -40, -40, -30, - -20, -30, -30, -40, -40, -30, -30, -20, - -10, -20, -20, -20, -20, -20, -20, -10, - 20, 20, 0, 0, 0, 0, 20, 20, - 20, 30, 10, 0, 0, 10, 30, 20 -}; - -static int eg_king[] = { - -50, -40, -30, -20, -20, -30, -40, -50, - -30, -20, -10, 0, 0, -10, -20, -30, - -30, -10, 20, 30, 30, 20, -10, -30, - -30, -10, 30, 40, 40, 30, -10, -30, - -30, -10, 30, 40, 40, 30, -10, -30, - -30, -10, 20, 30, 30, 20, -10, -30, - -30, -30, 0, 0, 0, 0, -30, -30, - -50, -30, -30, -30, -30, -30, -30, -50 -}; - -/* as pieces bitboard tables start at position 2; we make these tables - * bigger. - */ -static int *mg_tables[] = { - NULL, - NULL, - mg_pawn, - mg_knight, - mg_bishop, - mg_rook, - mg_queen, - mg_king -}; - -static int *eg_tables[] = { - NULL, - NULL, - mg_pawn, - mg_knight, - mg_bishop, - mg_rook, - mg_queen, - eg_king -}; - -/* to flip vertically a square, we need to XOR it with 56 - */ -static int mg_table[2][6 + 2][64]; -static int eg_table[2][6 + 2][64]; - -void eval_simple_init(void) -{ -# ifdef DEBUG_EVAL - log_f(1, "initializing piece tables\n"); -# endif - for (int piece = BB_PAWN; piece <= BB_KING; ++piece) { - for (int square = 0; square < 64; ++square) { - mg_table[WHITE][piece][square] = mg_tables[piece][FLIP_V(square)]; - eg_table[WHITE][piece][square] = eg_tables[piece][FLIP_V(square)]; - mg_table[BLACK][piece][square] = mg_tables[piece][square]; - eg_table[BLACK][piece][square] = eg_tables[piece][square]; - } - } -} - -/** - * eval_simple() - simple and fast position evaluation - * @pos: &position to evaluate + * #include "br.h" + * #include "debug.h" * - * This function is normally used only during initialization, - * or when changing phase (middlegame <--> endgame), as the eval - * will be done increntally when doing moves. + * #include "piece.h" + * #include "eval-simple.h" + * #include "position.h" * - * @return: the @pos evaluation in centipawns + * /\* + * * Tables are from https://www.chessprogramming.org/Simplified_Evaluation_Function + * * + * * Attention! Tables are black point of view (to be visually easier to read). + * *\/ + * + * static int mg_pawn[] = { + * 0, 0, 0, 0, 0, 0, 0, 0, + * 50, 50, 50, 50, 50, 50, 50, 50, + * 10, 10, 20, 30, 30, 20, 10, 10, + * 5, 5, 10, 25, 25, 10, 5, 5, + * 0, 0, 0, 20, 20, 0, 0, 0, + * 5, -5, -10, 0, 0, -10, -5, 5, + * 5, 10, 10, -20, -20, 10, 10, 5, + * 0, 0, 0, 0, 0, 0, 0, 0 + * }; + * + * static int mg_knight[] = { + * -50, -40, -30, -30, -30, -30, -40, -50, + * -40, -20, 0, 0, 0, 0, -20, -40, + * -30, 0, 10, 15, 15, 10, 0, -30, + * -30, 5, 15, 20, 20, 15, 5, -30, + * -30, 0, 15, 20, 20, 15, 0, -30, + * -30, 5, 10, 15, 15, 10, 5, -30, + * -40, -20, 0, 5, 5, 0, -20, -40, + * -50, -40, -30, -30, -30, -30, -40, -50 + * }; + * + * static int mg_bishop[] = { + * -20, -10, -10, -10, -10, -10, -10, -20, + * -10, 0, 0, 0, 0, 0, 0, -10, + * -10, 0, 5, 10, 10, 5, 0, -10, + * -10, 5, 5, 10, 10, 5, 5, -10, + * -10, 0, 10, 10, 10, 10, 0, -10, + * -10, 10, 10, 10, 10, 10, 10, -10, + * -10, 5, 0, 0, 0, 0, 5, -10, + * -20, -10, -10, -10, -10, -10, -10, -20 + * }; + * + * static int mg_rook[] = { + * 0, 0, 0, 0, 0, 0, 0, 0, + * 5, 10, 10, 10, 10, 10, 10, 5, + * -5, 0, 0, 0, 0, 0, 0, -5, + * -5, 0, 0, 0, 0, 0, 0, -5, + * -5, 0, 0, 0, 0, 0, 0, -5, + * -5, 0, 0, 0, 0, 0, 0, -5, + * -5, 0, 0, 0, 0, 0, 0, -5, + * 0, 0, 0, 5, 5, 0, 0, 0 + * }; + * + * static int mg_queen[] = { + * -20, -10, -10, -5, -5, -10, -10, -20, + * -10, 0, 0, 0, 0, 0, 0, -10, + * -10, 0, 5, 5, 5, 5, 0, -10, + * -5, 0, 5, 5, 5, 5, 0, -5, + * 0, 0, 5, 5, 5, 5, 0, -5, + * -10, 5, 5, 5, 5, 5, 0, -10, + * -10, 0, 5, 0, 0, 0, 0, -10, + * -20, -10, -10, -5, -5, -10, -10, -20 + * }; + * + * static int mg_king[] = { + * -30, -40, -40, -50, -50, -40, -40, -30, + * -30, -40, -40, -50, -50, -40, -40, -30, + * -30, -40, -40, -50, -50, -40, -40, -30, + * -30, -40, -40, -50, -50, -40, -40, -30, + * -20, -30, -30, -40, -40, -30, -30, -20, + * -10, -20, -20, -20, -20, -20, -20, -10, + * 20, 20, 0, 0, 0, 0, 20, 20, + * 20, 30, 10, 0, 0, 10, 30, 20 + * }; + * + * static int eg_king[] = { + * -50, -40, -30, -20, -20, -30, -40, -50, + * -30, -20, -10, 0, 0, -10, -20, -30, + * -30, -10, 20, 30, 30, 20, -10, -30, + * -30, -10, 30, 40, 40, 30, -10, -30, + * -30, -10, 30, 40, 40, 30, -10, -30, + * -30, -10, 20, 30, 30, 20, -10, -30, + * -30, -30, 0, 0, 0, 0, -30, -30, + * -50, -30, -30, -30, -30, -30, -30, -50 + * }; + * + * /\* as pieces bitboard tables start at position 2; we make these tables + * * bigger. + * *\/ + * static int *mg_tables[] = { + * NULL, + * NULL, + * mg_pawn, + * mg_knight, + * mg_bishop, + * mg_rook, + * mg_queen, + * mg_king + * }; + * + * static int *eg_tables[] = { + * NULL, + * NULL, + * mg_pawn, + * mg_knight, + * mg_bishop, + * mg_rook, + * mg_queen, + * eg_king + * }; + * + * /\* to flip vertically a square, we need to XOR it with 56 + * *\/ + * static int mg_table[2][6 + 2][64]; + * static int eg_table[2][6 + 2][64]; + * + * void eval_simple_init(void) + * { + * # ifdef DEBUG_EVAL + * log_f(1, "initializing piece tables\n"); + * # endif + * for (int piece = BB_PAWN; piece <= BB_KING; ++piece) { + * for (int square = 0; square < 64; ++square) { + * mg_table[WHITE][piece][square] = mg_tables[piece][FLIP_V(square)]; + * eg_table[WHITE][piece][square] = eg_tables[piece][FLIP_V(square)]; + * mg_table[BLACK][piece][square] = mg_tables[piece][square]; + * eg_table[BLACK][piece][square] = eg_tables[piece][square]; + * } + * } + * } + * + * /\** + * * eval_simple() - simple and fast position evaluation + * * @pos: &position to evaluate + * * + * * This function is normally used only during initialization, + * * or when changing phase (middlegame <--> endgame), as the eval + * * will be done increntally when doing moves. + * * + * * @return: the @pos evaluation in centipawns + * *\/ + * eval_t eval_simple(pos_t *pos) + * { + * eval_t eval[2] = { 0, 0 }; + * int eg = simple_is_endgame(pos); + * int (*gg)[6 + 2][64]= eg? eg_table: mg_table; + * + * pos->eval_simple_phase = ENDGAME; + * # ifdef DEBUG_EVAL + * log_f(5, "phase = %s.\n", eg? "endgame": "midgame"); + * # endif + * + * for (int color = WHITE; color <= BLACK; ++color) { + * for (uint piece = PAWN; piece <= KING; piece <<= 1) { + * int bb = PIECETOBB(piece), cur; + * u64 _t; + * + * # ifdef DEBUG_EVAL + * log_f(5, "p=%u bb=%d %s %s: count=%d val=%ld ", piece, bb, color? "black": "white", + * P_SYM(piece), popcount64(pos->bb[color][bb]), + * popcount64(pos->bb[color][bb]) * P_VALUE(piece)); + * # endif + * + * eval[color] += popcount64(pos->bb[color][bb]) * P_LETTER(piece); + * bit_for_each64(cur, _t, pos->bb[color][bb]) { + * # ifdef DEBUG_EVAL + * log(5, "sq=%d:%d ", cur, gg[color][bb][cur]); + * # endif + * eval[color] += gg[color][bb][cur]; + * } + * # ifdef DEBUG_EVAL + * log(5, "\n"); + * # endif + * } + * } + * # ifdef DEBUG_EVAL + * log_f(2, "eval:%d white:%d black:%d\n", eval[WHITE] - eval[BLACK], + * eval[WHITE], eval[BLACK]); + * # endif + * + * return eval[WHITE] - eval[BLACK]; + * } */ -eval_t eval_simple(pos_t *pos) -{ - eval_t eval[2] = { 0, 0 }; - int eg = simple_is_endgame(pos); - int (*gg)[6 + 2][64]= eg? eg_table: mg_table; - - pos->eval_simple_phase = ENDGAME; -# ifdef DEBUG_EVAL - log_f(5, "phase = %s.\n", eg? "endgame": "midgame"); -# endif - - for (int color = WHITE; color <= BLACK; ++color) { - for (uint piece = PAWN; piece <= KING; piece <<= 1) { - int bb = PIECETOBB(piece), cur; - u64 _t; - -# ifdef DEBUG_EVAL - log_f(5, "p=%u bb=%d %s %s: count=%d val=%ld ", piece, bb, color? "black": "white", - P_SYM(piece), popcount64(pos->bb[color][bb]), - popcount64(pos->bb[color][bb]) * P_VALUE(piece)); -# endif - - eval[color] += popcount64(pos->bb[color][bb]) * P_LETTER(piece); - bit_for_each64(cur, _t, pos->bb[color][bb]) { -# ifdef DEBUG_EVAL - log(5, "sq=%d:%d ", cur, gg[color][bb][cur]); -# endif - eval[color] += gg[color][bb][cur]; - } -# ifdef DEBUG_EVAL - log(5, "\n"); -# endif - } - } -# ifdef DEBUG_EVAL - log_f(2, "eval:%d white:%d black:%d\n", eval[WHITE] - eval[BLACK], - eval[WHITE], eval[BLACK]); -# endif - - return eval[WHITE] - eval[BLACK]; -} diff --git a/src/eval.c b/src/eval.c index 0462bd5..69e606d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1,95 +1,97 @@ -/* eval.c - static position evaluation. +/* + * /\* eval.c - static position evaluation. + * * + * * Copyright (C) 2021-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 + * * + * *\/ * - * Copyright (C) 2021-2023 Bruno Raoult ("br") - * Licensed under the GNU General Public License v3.0 or later. - * Some rights reserved. See COPYING. + * #include * - * You should have received a copy of the GNU General Public License along with this - * program. If not, see . + * #include + * #include * - * SPDX-License-Identifier: GPL-3.0-or-later + * #include "position.h" + * #include "eval.h" + * #include "eval-simple.h" * + * inline eval_t eval_material(pos_t *pos, bool color) + * { + * eval_t res = 0; + * + * /\* I need to do something about the king, if it can be potentially taken + * * if pseudo-moves include a pinned piece on King. + * *\/ + * for (uint piece = PAWN; piece < KING; piece <<= 1) { + * uint bb = PIECETOBB(piece); + * # ifdef DEBUG_EVAL + * log_f(2, "color=%u piece=%u bb=%u=%c count=%ul val=%ld\n", + * color, piece, bb, P_LETTER(piece), popcount64(pos->bb[color][bb]), + * P_VALUE(piece)); + * # endif + * /\* attention here *\/ + * res += popcount64(pos->bb[color][bb]) * P_VALUE(piece); + * } + * return res; + * } + * + * inline eval_t eval_mobility(pos_t *pos, bool color) + * { + * return pos->mobility[color]; + * } + * + * inline eval_t eval_square_control(pos_t *pos, bool color) + * { + * return popcount64(pos->controlled[color]); + * } + * + * eval_t eval(pos_t *pos) + * { + * eval_t simple = 0, control[2] = {0}; + * + * if (pos->eval != EVAL_INVALID) + * return pos->eval; + * + * /\* 1) pieces value *\/ + * //material[WHITE] = eval_material(pos, WHITE); + * //material[BLACK] = eval_material(pos, BLACK); + * simple = eval_simple(pos); + * + * # ifdef DEBUG_EVAL + * log_f(2, "eval_simple=%d\n", simple); + * # endif + * + * /\* 2) square control: 10 square controls diff = 1 pawn *\/ + * control[WHITE] = eval_square_control(pos, WHITE); + * control[BLACK] = eval_square_control(pos, BLACK); + * + * # ifdef DEBUG_EVAL + * log_f(2, "square control: W:%d B:%d diff=%d\n", + * control[WHITE], control[BLACK], + * (control[WHITE] - control[BLACK]) * 10); + * # endif + * + * /\* 3) mobility: 10 mobility diff = 1 pawn + * *\/ + * # ifdef DEBUG_EVAL + * log_f(2, "mobility: W:%u B:%u diff=%d\n", + * pos->mobility[WHITE], pos->mobility[BLACK], + * (pos->mobility[WHITE] - pos->mobility[BLACK]) * 10); + * # endif + * + * eval_t res = simple + + * (control[WHITE] - control[BLACK]) * 10 + + * (pos->mobility[WHITE] - pos->mobility[BLACK]) * 10; + * # ifdef DEBUG_EVAL + * log_f(2, "eval: %d\n", res); + * # endif + * pos->eval = res; + * return res; + * } */ - -#include - -#include -#include - -#include "position.h" -#include "eval.h" -#include "eval-simple.h" - -inline eval_t eval_material(pos_t *pos, bool color) -{ - eval_t res = 0; - - /* I need to do something about the king, if it can be potentially taken - * if pseudo-moves include a pinned piece on King. - */ - for (uint piece = PAWN; piece < KING; piece <<= 1) { - uint bb = PIECETOBB(piece); -# ifdef DEBUG_EVAL - log_f(2, "color=%u piece=%u bb=%u=%c count=%ul val=%ld\n", - color, piece, bb, P_LETTER(piece), popcount64(pos->bb[color][bb]), - P_VALUE(piece)); -# endif - /* attention here */ - res += popcount64(pos->bb[color][bb]) * P_VALUE(piece); - } - return res; -} - -inline eval_t eval_mobility(pos_t *pos, bool color) -{ - return pos->mobility[color]; -} - -inline eval_t eval_square_control(pos_t *pos, bool color) -{ - return popcount64(pos->controlled[color]); -} - -eval_t eval(pos_t *pos) -{ - eval_t simple = 0, control[2] = {0}; - - if (pos->eval != EVAL_INVALID) - return pos->eval; - - /* 1) pieces value */ - //material[WHITE] = eval_material(pos, WHITE); - //material[BLACK] = eval_material(pos, BLACK); - simple = eval_simple(pos); - -# ifdef DEBUG_EVAL - log_f(2, "eval_simple=%d\n", simple); -# endif - - /* 2) square control: 10 square controls diff = 1 pawn */ - control[WHITE] = eval_square_control(pos, WHITE); - control[BLACK] = eval_square_control(pos, BLACK); - -# ifdef DEBUG_EVAL - log_f(2, "square control: W:%d B:%d diff=%d\n", - control[WHITE], control[BLACK], - (control[WHITE] - control[BLACK]) * 10); -# endif - - /* 3) mobility: 10 mobility diff = 1 pawn - */ -# ifdef DEBUG_EVAL - log_f(2, "mobility: W:%u B:%u diff=%d\n", - pos->mobility[WHITE], pos->mobility[BLACK], - (pos->mobility[WHITE] - pos->mobility[BLACK]) * 10); -# endif - - eval_t res = simple + - (control[WHITE] - control[BLACK]) * 10 + - (pos->mobility[WHITE] - pos->mobility[BLACK]) * 10; -# ifdef DEBUG_EVAL - log_f(2, "eval: %d\n", res); -# endif - pos->eval = res; - return res; -}