diff --git a/Makefile b/Makefile index 03ba8b4..a0979e3 100644 --- a/Makefile +++ b/Makefile @@ -415,7 +415,7 @@ TEST += movedo-test perft-test tt-test PIECE_OBJS := piece.o FEN_OBJS := $(PIECE_OBJS) fen.o position.o bitboard.o board.o \ - hq.o attack.o hash.o init.o misc.o alloc.o move.o eval-simple.o + hq.o attack.o hash.o init.o misc.o alloc.o move.o eval-defs.o BB_OBJS := $(FEN_OBJS) MOVEGEN_OBJS := $(BB_OBJS) move-gen.o ATTACK_OBJS := $(MOVEGEN_OBJS) diff --git a/src/brchess.c b/src/brchess.c index 1c7a11b..7273931 100644 --- a/src/brchess.c +++ b/src/brchess.c @@ -20,478 +20,10 @@ #include -#include "chessdefs.h" #include "position.h" -#include "brchess.h" -#include "hash.h" #include "fen.h" -#include "search.h" #include "hist.h" -#include "move-gen.h" -#include "move-do.h" - -struct command { - char *name; /* User printable name */ - int (*func)(pos_t *, char *); /* function doing the job */ - char *doc; /* function doc */ -}; - -int execute_line (pos_t *, struct command *, char *); - -struct command *find_command (char *); -int string_trim (char *str); - -/* The names of functions that actually do the manipulation. */ - -/* standard UCI commands */ -int do_ucinewgame(pos_t *, char *); -int do_uci(pos_t *, char *); -int do_isready(pos_t *, char *); - -int do_position(pos_t *, char *); - -/* commands *NOT* in UCI standard */ -int do_moves(pos_t *, char *); -int do_diagram(pos_t *, char *); -int do_perft(pos_t *, char *); - -int do_hist(pos_t *, char *); -int do_help(pos_t *, char *); -int do_quit(pos_t *, char *); - -struct command commands[] = { - { "help", do_help, "(not UCI) This help" }, - { "?", do_help, "(not UCI) This help" }, - { "quit", do_quit, "Quit" }, - - { "uci", do_uci, "" }, - { "ucinewgame", do_ucinewgame, "" }, - { "isready", do_isready, "" }, - - { "position", do_position, "position startpos|fen [moves ...]" }, - - { "perft", do_perft, "(not UCI) perft [divide] [alt] depth" }, - { "moves", do_moves, "(not UCI) moves ..." }, - { "diagram", do_diagram, "(not UCI) print current position diagram" }, - { "hist", do_hist, "(not UCI) print history states" }, - - { NULL, (int(*)()) NULL, NULL } -}; - -static int done = 0; - -int brchess(pos_t *pos) -{ - char *str = NULL, *saveptr, *token, *args; - int len; - size_t lenstr = 0; - struct command *command; - - while (!done && getline(&str, &lenstr, stdin) >= 0) { - if (!(len = string_trim(str))) - continue; - token = strtok_r(str, " ", &saveptr); - if (! (command= find_command(token))) { - fprintf(stderr, "Unknown [%s] command. Try 'help'.\n", token); - continue; - } - args = strtok_r(NULL, "", &saveptr); - execute_line(pos, command, args); - } - - if (str) - free(str); - - return 0; -} - -/* Execute a command line. */ -int execute_line(pos_t *pos, struct command *command, char *args) -{ - return (*command->func)(pos, args); -} - -/** - * find_command - lookup UCI command. - * @name: &command string - * - * Look up NAME as the name of a command, and return a pointer to that - * command. Return a NULL pointer if NAME isn't a command name. - */ -struct command *find_command(char *name) -{ - register int i; - - for (i = 0; commands[i].name; i++) - if (!strcmp(name, commands[i].name)) - return commands + i; - - return NULL; -} - -/* - * 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_init(pos_t *pos, __unused char *arg) - * { - * startpos(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_prmovepos(pos_t *pos, char *arg) - * { - * struct list_head *p_cur, *tmp; - * int movenum = atoi(arg), cur = 0; /\* starts with 0 *\/ - * move_t *move; - * - * log_f(1, "%s\n", arg); - * list_for_each_safe(p_cur, tmp, &pos->moves[pos->turn]) { - * move = list_entry(p_cur, move_t, list); - * if (cur++ == movenum) { - * pos_print(move->newpos); - * break; - * } - * } - * - * return 1; - * } - */ - -/* - * 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) -{ - pos_clear(pos); - tt_clear(); - return 1; -} - -int do_uci(__unused pos_t *pos, __unused char *arg) -{ - 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_isready(__unused pos_t *pos, __unused char *arg) -{ - printf("readyok\n"); - return 1; -} - -int do_position(pos_t *pos, char *arg) -{ - char *saveptr, *token, *fen, *moves; - - hist_init(); - - /* separate "moves" section */ - if ((moves = strstr(arg, "moves"))) { - *(moves - 1) = 0; - } - saveptr = NULL; - token = strtok_r(arg, " ", &saveptr); - if (!strcmp(token, "startpos")) { - startpos(pos); - do_diagram(pos, ""); - } else if (!strcmp(token, "fen")) { - fen = strtok_r(NULL, "", &saveptr); /* full fen (till '\0') */ - //printf("fen=%s\n", fen); - if (!fen) - return 1; - if (!fen2pos(pos, fen)) - return 1; - //do_diagram(pos, ""); - } else { - return 1; - } - //puts("zob"); - //move_t move_none = MOVE_NONE; - //hist_push(&pos->state, &move_none); - - if (moves) { - //puts("zobi"); - saveptr = NULL; - moves = strtok_r(moves, " ", &saveptr); /* skip "moves" */ - moves = strtok_r(NULL, "", &saveptr); /* all moves (till '\0') */ - //printf("moves = %s\n", moves); - do_moves(pos, moves); - } - /* link last position t history */ - //hist_pop(); - hist_link(pos); - return 1; -} - -int do_moves(__unused pos_t *pos, char *arg) -{ - char *saveptr = NULL, *token, check[8]; - move_t move; - state_t state; - movelist_t movelist; - saveptr = NULL; - token = strtok_r(arg, " ", &saveptr); - while (token) { - move = move_from_str(token); - move_to_str(check, move, 0); - - printf("move: [%s] %s\n", token, check); - pos_set_checkers_pinners_blockers(pos); - pos_legal(pos, pos_gen_pseudo(pos, &movelist)); - move = move_find_in_movelist(move, &movelist); - if (move == MOVE_NONE) { - /* should we reset here ? */ - return 1; - } - //printf("move: %s\n", move_to_str(check, move, 0)); - hist_push(&pos->state); /* push previous state */ - move_do(pos, move, &state); - pos_print(pos); - hist_static_print(); - token = strtok_r(NULL, " ", &saveptr); - } - //hist_static_print(); - return 1; -} - -int do_diagram(pos_t *pos, __unused char *arg) -{ - pos_print(pos); - return 1; -} - -int do_perft(__unused pos_t *pos, __unused char *arg) -{ - char *saveptr, *token; - int divide = 0, depth = 6, alt = 0; - - token = strtok_r(arg, " ", &saveptr); - if (!strcmp(token, "divide")) { - divide = 1; - token = strtok_r(NULL, " ", &saveptr); - } - if (!strcmp(token, "alt")) { - alt = 1; - token = strtok_r(NULL, " ", &saveptr); - } - depth = atoi(token); - printf("perft: divide=%d alt=%d depth=%d\n", divide, alt, depth); - if (depth > 0) { - if (!alt) - perft(pos, depth, 1, divide); - else - perft_alt(pos, depth, 1, divide); - } - return 1; -} - - -int do_hist(__unused pos_t *pos, __unused char *arg) -{ - hist_static_print(); - return 0; -} - -int do_help(__unused pos_t *pos, __unused char *arg) -{ - for (struct command *cmd = commands; cmd->name; ++cmd) { - printf("%12s:\t%s\n", cmd->name, cmd->doc); - /* Print in six columns. */ - } - - return 0; -} - -int do_quit(__unused pos_t *pos, __unused char *arg) -{ - return done = 1; -} - -/* - * 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; - * } - */ - -/* - * 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; - * } - */ - -/** - * string_trim - cleanup (trim) blank characters in string. - * @str: &string to clean - * - * str is cleaned and packed with the following rules: - * - Leading and trailing blank characters are removed. - * - consecutive blank characters are replaced by one space. - * - non printable characters are removed. - * - * "blank" means characters as understood by isspace(3): space, form-feed ('\f'), - * newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical - * tab ('\v'). - * - * @return: new @str len. - */ -int string_trim(char *str) -{ - char *to = str, *from = str; - int state = 1; - - while (*from) { - switch (state) { - case 1: /* blanks */ - while (*from && isspace(*from)) - from++; - state = 0; - break; - case 0: /* token */ - while (*from && !isspace(*from)) { - if (isprint(*from)) - *to++ = *from; - from++; - } - *to++ = ' '; - state = 1; - } - } - if (to > str) - to--; - *to = 0; - return to - str; -} - +#include "uci.h" /** * usage - brchess usage function. @@ -536,5 +68,5 @@ int main(int ac, char **av) if (optind < ac) return usage(*av); - return brchess(pos); + return uci(pos); } diff --git a/src/brchess.h b/src/brchess.h index e8863d3..2ec0253 100644 --- a/src/brchess.h +++ b/src/brchess.h @@ -14,8 +14,4 @@ #ifndef BRCHESS_H #define BRCHESS_H -#include "position.h" - -int brchess(pos_t *pos); - #endif /* BRCHESS_H */ diff --git a/src/eval-defs.c b/src/eval-defs.c index 116705d..96eaf69 100644 --- a/src/eval-defs.c +++ b/src/eval-defs.c @@ -1,6 +1,6 @@ -/* eval-simple.c - simple position evaluation. +/* eval-values.c - eval static definitions. * - * Copyright (C) 2023 Bruno Raoult ("br") + * Copyright (C) 2024 Bruno Raoult ("br") * Licensed under the GNU General Public License v3.0 or later. * Some rights reserved. See COPYING. * @@ -15,10 +15,11 @@ #include #include "chessdefs.h" -#include "piece.h" #include "position.h" -#include "eval-simple.h" -#include "eval.h" +#include "piece.h" +#include "eval-defs.h" +//#include "eval-simple.h" +//#include "eval.h" /* * Piece-square tables. For easier reading, they are defined for black side: @@ -30,7 +31,7 @@ * A1 .... H1 * } */ -const struct pc_sq pc_sq_def[] = { +const struct pst pst_defs[] = { { /* * rofchade: @@ -457,10 +458,10 @@ const struct pc_sq pc_sq_def[] = { }, /* sjeng */ }; -const int nb_pc_sq = ARRAY_SIZE(pc_sq_def); /* # of predefined pc_sq tables */ -int pc_sq_current = 0; -int pc_sq_mg[COLOR_NB][PT_NB][SQUARE_NB]; -int pc_sq_eg[COLOR_NB][PT_NB][SQUARE_NB]; +const int nb_pc_sq = ARRAY_SIZE(pst_defs); /* # of predefined pc_sq tables */ +int pst_current = 0; +int pst_mg[COLOR_NB][PT_NB][SQUARE_NB]; +int pst_eg[COLOR_NB][PT_NB][SQUARE_NB]; /* phase calculation from Fruit: * https://github.com/Warpten/Fruit-2.1 @@ -492,108 +493,33 @@ s16 calc_phase(pos_t *pos) return phase; } -int eval_simple_find(char *str) +static int pst_find(char *str) { for (int i = 0; i < nb_pc_sq; ++i) - if (!strcmp(pc_sq_def[i].name, str)) + if (!strcmp(pst_defs[i].name, str)) return i; return -1; } -void eval_simple_set(int set) +void pst_init(char *name) { - const struct pc_sq *cur = pc_sq_def + set; + const struct pst *cur; + int set = pst_find(name); # ifdef DEBUG_EVAL - printf("initializing piece-square tables %d\n", set); + printf("initializing piece-square tables `%s`(%d)\n", name, set); # endif - pc_sq_current = set; + if (set < 0) + set = 0; + + cur = pst_defs + set; + pst_current = set; for (piece_type_t pt = PAWN; pt < PT_NB; ++pt) { for (square_t sq = 0; sq < SQUARE_NB; ++sq) { - pc_sq_mg[BLACK][pt][sq] = cur->val[MIDGAME][pt][sq]; - pc_sq_mg[WHITE][pt][sq] = cur->val[MIDGAME][pt][FLIP_V(sq)]; + pst_mg[BLACK][pt][sq] = cur->val[MIDGAME][pt][sq]; + pst_mg[WHITE][pt][sq] = cur->val[MIDGAME][pt][FLIP_V(sq)]; - pc_sq_eg[BLACK][pt][sq] = cur->val[ENDGAME][pt][sq]; - pc_sq_eg[WHITE][pt][sq] = cur->val[ENDGAME][pt][FLIP_V(sq)]; + pst_eg[BLACK][pt][sq] = cur->val[ENDGAME][pt][sq]; + pst_eg[WHITE][pt][sq] = cur->val[ENDGAME][pt][FLIP_V(sq)]; } } } - -void eval_simple_init(char *set) -{ - int n = eval_simple_find(set); -# ifdef DEBUG_EVAL - printf("initializing eval_simple with set=%s: found=%d\n", set, n); -# endif - - if (n >= 0) - pc_sq_current = n; - eval_simple_set(pc_sq_current); -} - -/** - * eval_material() - eval position material - * @pos: &position to evaluate - * - * Basic material evaluation. Only midgame value is used. - * - * @return: the @pos material evaluation in centipawns - */ -eval_t eval_material(pos_t *pos) -{ - eval_t val[COLOR_NB] = { 0 }; - - for (piece_type_t pt = PAWN; pt < KING; ++pt) { - eval_t pval = piece_midval(pt); - val[WHITE] += popcount64(pos->bb[WHITE][pt]) * pval; - val[BLACK] += popcount64(pos->bb[BLACK][pt]) * pval; - } -# ifdef DEBUG_EVAL - printf("material: w:%d b:%d\n", val[WHITE], val[BLACK]); -# endif - - return val[WHITE] - val[BLACK]; -} - -/** - * 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 incrementally when doing moves. - * - * @return: the @pos evaluation in centipawns - */ -eval_t eval_simple(pos_t *pos) -{ - eval_t eval[2] = { 0, 0 }; - eval_t mg_eval[2], eg_eval[2]; - //struct pc_sq = sq_ int (*gg)[6 + 2][64] = eg? pc_sq_eg: pc_sq_mg; - - //pos->eval_simple_phase = ENDGAME; - - for (color_t color = WHITE; color < COLOR_NB; ++color) { - mg_eval[color] = 0; - eg_eval[color] = 0; - for (piece_type_t pt = PAWN; pt < KING; pt++) { - bitboard_t bb = pos->bb[color][pt]; - while (bb) { - square_t sq = bb_next(&bb); - mg_eval[color] += pc_sq_mg[color][pt][sq]; - eg_eval[color] += pc_sq_eg[color][pt][sq]; - } - -# ifdef DEBUG_EVAL - printf("c=%d pt=%d mg=%d eg=%d\n", color, pt, - mg_eval[color], eg_eval[color]); -# endif - - } - } -# ifdef DEBUG_EVAL - printf("phase:%d mg[WHITE]:%d mg[BLACK]:%d eg[WHITE]:%d eg[BLACK]:%d\n", - pos->phase, mg_eval[WHITE], mg_eval[BLACK], eg_eval[WHITE], eg_eval[BLACK]); -# endif - - return eval[WHITE] - eval[BLACK]; -} diff --git a/src/eval-simple.c b/src/eval-simple.c index 116705d..c8348c5 100644 --- a/src/eval-simple.c +++ b/src/eval-simple.c @@ -20,516 +20,6 @@ #include "eval-simple.h" #include "eval.h" -/* - * Piece-square tables. For easier reading, they are defined for black side: - * - * { - * A8 .... H8 - * .......... - * .......... - * A1 .... H1 - * } - */ -const struct pc_sq pc_sq_def[] = { - { - /* - * rofchade: - * https://www.talkchess.com/forum3/viewtopic.php?f=2&t=68311&start=19 - */ - "rofchade", - { - [PAWN] = { - { /* midgame */ - 0, 0, 0, 0, 0, 0, 0, 0, - 98, 134, 61, 95, 68, 126, 34, -11, - -6, 7, 26, 31, 65, 56, 25, -20, - -14, 13, 6, 21, 23, 12, 17, -23, - -27, -2, -5, 12, 17, 6, 10, -25, - -26, -4, -4, -10, 3, 3, 33, -12, - -35, -1, -20, -23, -15, 24, 38, -22, - 0, 0, 0, 0, 0, 0, 0, 0, - }, - { /* endgame */ - 0, 0, 0, 0, 0, 0, 0, 0, - 178, 173, 158, 134, 147, 132, 165, 187, - 94, 100, 85, 67, 56, 53, 82, 84, - 32, 24, 13, 5, -2, 4, 17, 17, - 13, 9, -3, -7, -7, -8, 3, -1, - 4, 7, -6, 1, 0, -5, -1, -8, - 13, 8, 8, 10, 13, 0, 2, -7, - 0, 0, 0, 0, 0, 0, 0, 0, - } - }, - [KNIGHT] = { - { /* midgame */ - -167, -89, -34, -49, 61, -97, -15, -107, - -73, -41, 72, 36, 23, 62, 7, -17, - -47, 60, 37, 65, 84, 129, 73, 44, - -9, 17, 19, 53, 37, 69, 18, 22, - -13, 4, 16, 13, 28, 19, 21, -8, - -23, -9, 12, 10, 19, 17, 25, -16, - -29, -53, -12, -3, -1, 18, -14, -19, - -105, -21, -58, -33, -17, -28, -19, -23, - }, - { /* endgame */ - -58, -38, -13, -28, -31, -27, -63, -99, - -25, -8, -25, -2, -9, -25, -24, -52, - -24, -20, 10, 9, -1, -9, -19, -41, - -17, 3, 22, 22, 22, 11, 8, -18, - -18, -6, 16, 25, 16, 17, 4, -18, - -23, -3, -1, 15, 10, -3, -20, -22, - -42, -20, -10, -5, -2, -20, -23, -44, - -29, -51, -23, -15, -22, -18, -50, -64, - } - }, - [BISHOP] = { - { /* midgame */ - -29, 4, -82, -37, -25, -42, 7, -8, - -26, 16, -18, -13, 30, 59, 18, -47, - -16, 37, 43, 40, 35, 50, 37, -2, - -4, 5, 19, 50, 37, 37, 7, -2, - -6, 13, 13, 26, 34, 12, 10, 4, - 0, 15, 15, 15, 14, 27, 18, 10, - 4, 15, 16, 0, 7, 21, 33, 1, - -33, -3, -14, -21, -13, -12, -39, -21, - }, - { /* endgame */ - -14, -21, -11, -8, -7, -9, -17, -24, - -8, -4, 7, -12, -3, -13, -4, -14, - 2, -8, 0, -1, -2, 6, 0, 4, - -3, 9, 12, 9, 14, 10, 3, 2, - -6, 3, 13, 19, 7, 10, -3, -9, - -12, -3, 8, 10, 13, 3, -7, -15, - -14, -18, -7, -1, 4, -9, -15, -27, - -23, -9, -23, -5, -9, -16, -5, -17, - }, - }, - [ROOK] = { - { /* midgame */ - 32, 42, 32, 51, 63, 9, 31, 43, - 27, 32, 58, 62, 80, 67, 26, 44, - -5, 19, 26, 36, 17, 45, 61, 16, - -24, -11, 7, 26, 24, 35, -8, -20, - -36, -26, -12, -1, 9, -7, 6, -23, - -45, -25, -16, -17, 3, 0, -5, -33, - -44, -16, -20, -9, -1, 11, -6, -71, - -19, -13, 1, 17, 16, 7, -37, -26, - }, - { /* endgame */ - 13, 10, 18, 15, 12, 12, 8, 5, - 11, 13, 13, 11, -3, 3, 8, 3, - 7, 7, 7, 5, 4, -3, -5, -3, - 4, 3, 13, 1, 2, 1, -1, 2, - 3, 5, 8, 4, -5, -6, -8, -11, - -4, 0, -5, -1, -7, -12, -8, -16, - -6, -6, 0, 2, -9, -9, -11, -3, - -9, 2, 3, -1, -5, -13, 4, -20, - }, - }, - [QUEEN] = { - { /* midgame */ - -28, 0, 29, 12, 59, 44, 43, 45, - -24, -39, -5, 1, -16, 57, 28, 54, - -13, -17, 7, 8, 29, 56, 47, 57, - -27, -27, -16, -16, -1, 17, -2, 1, - -9, -26, -9, -10, -2, -4, 3, -3, - -14, 2, -11, -2, -5, 2, 14, 5, - -35, -8, 11, 2, 8, 15, -3, 1, - -1, -18, -9, 10, -15, -25, -31, -50, - }, - { /* endgame */ - -9, 22, 22, 27, 27, 19, 10, 20, - -17, 20, 32, 41, 58, 25, 30, 0, - -20, 6, 9, 49, 47, 35, 19, 9, - 3, 22, 24, 45, 57, 40, 57, 36, - -18, 28, 19, 47, 31, 34, 39, 23, - -16, -27, 15, 6, 9, 17, 10, 5, - -22, -23, -30, -16, -16, -23, -36, -32, - -33, -28, -22, -43, -5, -32, -20, -41, - }, - }, - [KING] = { /* midgame */ - { - -65, 23, 16, -15, -56, -34, 2, 13, - 29, -1, -20, -7, -8, -4, -38, -29, - -9, 24, 2, -16, -20, 6, 22, -22, - -17, -20, -12, -27, -30, -25, -14, -36, - -49, -1, -27, -39, -46, -44, -33, -51, - -14, -14, -22, -46, -44, -30, -15, -27, - 1, 7, -8, -64, -43, -16, 9, 8, - -15, 36, 12, -54, 8, -28, 24, 14, - }, - { /* endgame */ - -74, -35, -18, -18, -11, 15, 4, -17, - -12, 17, 14, 17, 17, 38, 23, 11, - 10, 17, 23, 15, 20, 45, 44, 13, - -8, 22, 24, 27, 26, 33, 26, 3, - -18, -4, 21, 24, 27, 23, 9, -11, - -19, -3, 11, 21, 23, 16, 7, -9, - -27, -11, 4, 13, 14, 4, -5, -17, - -53, -34, -21, -11, -28, -14, -24, -43 - } - } - } - }, /* CPW */ - { - /* - * CPW: - * https://www.chessprogramming.org/Simplified_Evaluation_Function - * Note: ≠ https://github.com/nescitus/cpw-engine - */ - "cpw", - { - [PAWN] = { - { /* midgame */ - 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, - }, - { /* endgame */ - 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, - }, - }, - [KNIGHT] = { - { /* midgame */ - -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 - }, - { /* endgame */ - -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 - }, - }, - [BISHOP] = { - { /* midgame */ - -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, - }, - { /* endgame */ - -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, - }, - }, - [ROOK] = { - { /* midgame */ - 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, - }, - { /* endgame */ - 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, - }, - }, - [QUEEN] = { - { /* midgame */ - -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, - }, - { /* endgame */ - -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, - }, - }, - [KING] = { /* midgame */ - { - -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, - }, - { /* endgame */ - -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, - } - } - } - }, /* CPW */ - { - /* - * sjeng: https://github.com/gcp/sjeng - * Rook and Queen from CPW. - */ - "sjeng", - { - [PAWN] = { - { /* midgame */ - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 10, 15, 20, 20, 15, 10, 5, - 4, 8, 12, 16, 16, 12, 8, 4, - 3, 6, 9, 14, 14, 9, 6, 3, - 2, 4, 6, 12, 12, 6, 4, 2, - 1, 2, 3, 10, 10, 3, 2, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }, - { /* endgame */ - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 10, 15, 20, 20, 15, 10, 5, - 4, 8, 12, 16, 16, 12, 8, 4, - 3, 6, 9, 14, 14, 9, 6, 3, - 2, 4, 6, 12, 12, 6, 4, 2, - 1, 2, 3, 10, 10, 3, 2, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }, - }, - [KNIGHT] = { - { /* midgame */ - -20, -10, -10, -10, -10, -10, -10, -20, - -10, 0, 0, 3, 3, 0, 0, -10, - -10, 0, 5, 5, 5, 5, 0, -10, - -10, 0, 5, 10, 10, 5, 0, -10, - -10, 0, 5, 10, 10, 5, 0, -10, - -10, 0, 5, 5, 5, 5, 0, -10, - -10, 0, 0, 3, 3, 0, 0, -10, - -20, -10, -10, -10, -10, -10, -10, -20, - }, - { /* endgame */ - -20, -10, -10, -10, -10, -10, -10, -20, - -10, 0, 0, 3, 3, 0, 0, -10, - -10, 0, 5, 5, 5, 5, 0, -10, - -10, 0, 5, 10, 10, 5, 0, -10, - -10, 0, 5, 10, 10, 5, 0, -10, - -10, 0, 5, 5, 5, 5, 0, -10, - -10, 0, 0, 3, 3, 0, 0, -10, - -20, -10, -10, -10, -10, -10, -10, -20, - }, - }, - [BISHOP] = { - { /* midgame */ - -2, -2, -2, -2, -2, -2, -2, -2, - -2, 8, 5, 5, 5, 5, 8, -2, - -2, 3, 3, 5, 5, 3, 3, -2, - -2, 2, 5, 4, 4, 5, 2, -2, - -2, 2, 5, 4, 4, 5, 2, -2, - -2, 3, 3, 5, 5, 3, 3, -2, - -2, 8, 5, 5, 5, 5, 8, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - }, - { /* endgame */ - -2, -2, -2, -2, -2, -2, -2, -2, - -2, 8, 5, 5, 5, 5, 8, -2, - -2, 3, 3, 5, 5, 3, 3, -2, - -2, 2, 5, 4, 4, 5, 2, -2, - -2, 2, 5, 4, 4, 5, 2, -2, - -2, 3, 3, 5, 5, 3, 3, -2, - -2, 8, 5, 5, 5, 5, 8, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - }, - }, - [ROOK] = { - { /* midgame */ - 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, - }, - { /* endgame */ - 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, - }, - }, - [QUEEN] = { - { /* midgame */ - -20, -10, -10, -5, -5, -10, -10, -20, - -10, 0, 5, 0, 0, 0, 0, -10, - -10, 5, 5, 5, 5, 5, 0, -10, - 0, 0, 5, 5, 5, 5, 0, -5, - -5, 0, 5, 5, 5, 5, 0, -5, - -10, 0, 5, 5, 5, 5, 0, -10, - -10, 0, 0, 0, 0, 0, 0, -10, - -20, -10, -10, -5, -5, -10, -10, -20, - }, - { /* endgame */ - -20, -10, -10, -5, -5, -10, -10, -20, - -10, 0, 5, 0, 0, 0, 0, -10, - -10, 5, 5, 5, 5, 5, 0, -10, - 0, 0, 5, 5, 5, 5, 0, -5, - -5, 0, 5, 5, 5, 5, 0, -5, - -10, 0, 5, 5, 5, 5, 0, -10, - -10, 0, 0, 0, 0, 0, 0, -10, - -20, -10, -10, -5, -5, -10, -10, -20, - }, - }, - [KING] = { /* midgame */ - { - -55, -55, -89, -89, -89, -89, -55, -55, - -34, -34, -55, -55, -55, -55, -34, -34, - -21, -21, -34, -34, -34, -34, -21, -21, - -13, -13, -21, -21, -21, -21, -13, -13, - -8, -8, -13, -13, -13, -13, -8, -8, - -5, -5, -8, -8, -8, -8, -5, -5, - -3, -5, -6, -6, -6, -6, -5, -3, - 2, 14, 0, 0, 0, 9, 14, 2, - }, - { /* endgame */ - -5, -3, -1, 0, 0, -1, -3, -5, - -3, 10, 10, 10, 10, 10, 10, -3, - -1, 10, 25, 25, 25, 25, 10, -1, - 0, 10, 25, 30, 30, 25, 10, 0, - 0, 10, 25, 30, 30, 25, 10, 0, - -1, 10, 25, 25, 25, 25, 10, -1, - -3, 10, 10, 10, 10, 10, 10, -3, - -5, -3, -1, 0, 0, -1, -3, -5, - } - } - }, - }, /* sjeng */ -}; - -const int nb_pc_sq = ARRAY_SIZE(pc_sq_def); /* # of predefined pc_sq tables */ -int pc_sq_current = 0; -int pc_sq_mg[COLOR_NB][PT_NB][SQUARE_NB]; -int pc_sq_eg[COLOR_NB][PT_NB][SQUARE_NB]; - -/* phase calculation from Fruit: - * https://github.com/Warpten/Fruit-2.1 -*/ - -/** - * calc_phase - calculate position phase - * @pos: &position - * - * This function should be calculated when a new position is setup, or as - * a verification of an incremental one. - * phase is clamped between 0 (opening) and 24 (ending). - * - * @return: - */ -s16 calc_phase(pos_t *pos) -{ - int phase = ALL_PHASE; - phase -= P_PHASE * popcount64(pos->bb[WHITE][PAWN] | pos->bb[BLACK][PAWN]); - phase -= N_PHASE * popcount64(pos->bb[WHITE][KNIGHT] | pos->bb[BLACK][KNIGHT]); - phase -= B_PHASE * popcount64(pos->bb[WHITE][BISHOP] | pos->bb[BLACK][BISHOP]); - phase -= R_PHASE * popcount64(pos->bb[WHITE][ROOK] | pos->bb[BLACK][ROOK]); - phase -= Q_PHASE * popcount64(pos->bb[WHITE][QUEEN] | pos->bb[BLACK][QUEEN]); - - phase = clamp(phase, 0, ALL_PHASE); -# ifdef DEBUG_EVAL - printf("calc phase:%d\n", phase); -# endif - return phase; -} - -int eval_simple_find(char *str) -{ - for (int i = 0; i < nb_pc_sq; ++i) - if (!strcmp(pc_sq_def[i].name, str)) - return i; - return -1; -} - -void eval_simple_set(int set) -{ - const struct pc_sq *cur = pc_sq_def + set; -# ifdef DEBUG_EVAL - printf("initializing piece-square tables %d\n", set); -# endif - pc_sq_current = set; - for (piece_type_t pt = PAWN; pt < PT_NB; ++pt) { - for (square_t sq = 0; sq < SQUARE_NB; ++sq) { - pc_sq_mg[BLACK][pt][sq] = cur->val[MIDGAME][pt][sq]; - pc_sq_mg[WHITE][pt][sq] = cur->val[MIDGAME][pt][FLIP_V(sq)]; - - pc_sq_eg[BLACK][pt][sq] = cur->val[ENDGAME][pt][sq]; - pc_sq_eg[WHITE][pt][sq] = cur->val[ENDGAME][pt][FLIP_V(sq)]; - } - } -} - -void eval_simple_init(char *set) -{ - int n = eval_simple_find(set); -# ifdef DEBUG_EVAL - printf("initializing eval_simple with set=%s: found=%d\n", set, n); -# endif - - if (n >= 0) - pc_sq_current = n; - eval_simple_set(pc_sq_current); -} - /** * eval_material() - eval position material * @pos: &position to evaluate @@ -579,8 +69,8 @@ eval_t eval_simple(pos_t *pos) bitboard_t bb = pos->bb[color][pt]; while (bb) { square_t sq = bb_next(&bb); - mg_eval[color] += pc_sq_mg[color][pt][sq]; - eg_eval[color] += pc_sq_eg[color][pt][sq]; + mg_eval[color] += pst_mg[color][pt][sq]; + eg_eval[color] += pst_mg[color][pt][sq]; } # ifdef DEBUG_EVAL diff --git a/src/eval-simple.h b/src/eval-simple.h index a833605..fde1145 100644 --- a/src/eval-simple.h +++ b/src/eval-simple.h @@ -14,37 +14,10 @@ #ifndef EVAL_SIMPLE_H #define EVAL_SIMPLE_H - #include "chessdefs.h" #include "piece.h" #include "eval.h" -struct pc_sq { - char *name; /* one word only, no spaces */ - int val[PIECE_TYPE_NB][PHASE_NB][SQUARE_NB]; /* MG then EG */ -}; - -/* pieces weight in phase calculation. - */ -enum { - P_PHASE = 0, - N_PHASE = 1, - B_PHASE = 1, - R_PHASE = 2, - Q_PHASE = 4, - ALL_PHASE = P_PHASE*16 + N_PHASE*4 + B_PHASE*4 + R_PHASE*4 + Q_PHASE*2 -}; - -/** - * pc_sq - pre-defined piece-square tables. - */ -extern const struct pc_sq pc_sq_def[]; -extern const int nb_pc_sq; /* # of pc_sq_def */ - -extern int pc_sq_current; -extern int pc_sq_mg[COLOR_NB][PT_NB][SQUARE_NB]; -extern int pc_sq_eg[COLOR_NB][PT_NB][SQUARE_NB]; - /* no queen on board */ #define simple_no_queen(p, c) \ ( !(p)->bb[c][QUEEN] ) @@ -69,10 +42,10 @@ extern int pc_sq_eg[COLOR_NB][PT_NB][SQUARE_NB]; simple_no_rook(p, BLACK) && \ simple_one_minor_piece(p, BLACK))) ) -s16 calc_phase(pos_t *pos); -int eval_simple_find(char *str); -void eval_simple_set(int set); -void eval_simple_init(char *set); +//s16 calc_phase(pos_t *pos); +//int eval_simple_find(char *str); +//void eval_simple_set(int set); +//void eval_simple_init(char *set); eval_t eval_material(pos_t *pos); eval_t eval_simple(pos_t *pos); diff --git a/src/eval.h b/src/eval.h index e6b45ee..fca8e78 100644 --- a/src/eval.h +++ b/src/eval.h @@ -17,25 +17,7 @@ #include #include "chessdefs.h" - -/* game phases - */ -enum { - MIDGAME, - ENDGAME, - PHASE_NB -}; -typedef s16 phase_t; - -/* max pieces eval is 9*QUEEN_VALUE + 2*ROOK_VALUE + 2*BISHOP_VALUE - * + 2*KNIGHT_VALUE which is (for a pawn valued at 100) well less than 15,000. - */ -#define EVAL_MAX (SHRT_MAX) /* 32767 */ -#define EVAL_MIN (-EVAL_MAX) - -#define EVAL_INVALID EVAL_MIN - -#define EVAL_MATE 30000 +#include "eval-defs.h" eval_t eval_mobility(pos_t *pos, bool color); eval_t eval_square_control(pos_t *pos, bool color); diff --git a/src/fen.c b/src/fen.c index 403e6c2..fc98d22 100644 --- a/src/fen.c +++ b/src/fen.c @@ -23,7 +23,7 @@ #include "chessdefs.h" #include "alloc.h" #include "position.h" -#include "eval-simple.h" +#include "eval-defs.h" #include "fen.h" /* FEN description: diff --git a/src/init.c b/src/init.c index 4c06d81..c0e49ef 100644 --- a/src/init.c +++ b/src/init.c @@ -19,11 +19,12 @@ #include "bitboard.h" #include "hq.h" -#include "eval-simple.h" +#include "eval-defs.h" #include "hash.h" #include "hist.h" #define printff(x) ({ printf(x); fflush(stdout); }) + void init_all(void) { /* line-buffered stdout */ @@ -53,8 +54,8 @@ void init_all(void) tt_create(HASH_SIZE_DEFAULT); /* eval tables */ - printf("eval data... "); - eval_simple_init("cpw"); + printf("pst data... "); + pst_init("cpw"); printf("done.\n"); } diff --git a/src/uci.c b/src/uci.c index 1c7a11b..780ea7f 100644 --- a/src/uci.c +++ b/src/uci.c @@ -1,6 +1,6 @@ -/* brchess.c - main loop. +/* uci.c - uci protocol * - * Copyright (C) 2021-2024 Bruno Raoult ("br") + * Copyright (C) 2024 Bruno Raoult ("br") * Licensed under the GNU General Public License v3.0 or later. * Some rights reserved. See COPYING. * @@ -22,13 +22,12 @@ #include "chessdefs.h" #include "position.h" -#include "brchess.h" -#include "hash.h" -#include "fen.h" -#include "search.h" +#include "uci.h" #include "hist.h" +#include "fen.h" #include "move-gen.h" #include "move-do.h" +#include "search.h" struct command { char *name; /* User printable name */ @@ -80,7 +79,7 @@ struct command commands[] = { static int done = 0; -int brchess(pos_t *pos) +int uci(pos_t *pos) { char *str = NULL, *saveptr, *token, *args; int len; @@ -491,50 +490,3 @@ int string_trim(char *str) *to = 0; return to - str; } - - -/** - * usage - brchess usage function. - * - */ -static int usage(char *prg) -{ - fprintf(stderr, "Usage: %s [-ilw] [file...]\n", prg); - return 1; -} - -int main(int ac, char **av) -{ - pos_t *pos; - int opt; - - init_all(); - pos = pos_new(); - hist_link(pos); - printf("\nWelcome to brchess " VERSION "\nEngine ready.\n"); - - // size_t len = 0; - // char *str = NULL; - //while (getline(&str, &len, stdin) >= 0) { - // printf("[%s] -> ", str); - // int newlen = string_trim(str); - // printf("%d [%s]\n", newlen, str); - //} - //exit(0); - while ((opt = getopt(ac, av, "d:f:")) != -1) { - switch (opt) { - case 'd': - //debug_level_set(atoi(optarg)); - break; - case 'f': - fen2pos(pos, optarg); - break; - default: - return usage(*av); - } - } - if (optind < ac) - return usage(*av); - - return brchess(pos); -}