diff --git a/FENTESTS.txt b/FENTESTS.txt index cc19f35..0249c43 100644 --- a/FENTESTS.txt +++ b/FENTESTS.txt @@ -1,8 +1,12 @@ -'4k3/4p3/8/b7/1BR1p2p/1Q3P2/5N2/4K3 w - - 0 1' -'r1bq1rk1/pppp1ppp/2n2n2/4p3/2B1P3/3PPN2/PPP3PP/RN1QK2R b KQ - 1 7' -'6k1/6pp/R2p4/p1p5/8/1P1r3P/6P1/6K1 b - - 3 37' +4k3/4p3/8/b7/1BR1p2p/1Q3P2/5N2/4K3 w - - 0 1 +r1bq1rk1/pppp1ppp/2n2n2/4p3/2B1P3/3PPN2/PPP3PP/RN1QK2R b KQ - 1 7 +6k1/6pp/R2p4/p1p5/8/1P1r3P/6P1/6K1 b - - 3 37 # both can castle queen only -'r3k2r/8/3B4/8/8/3b4/8/R3K2R w KQkq - 0 1' -'r3k2r/8/3BB3/8/8/3bb3/8/R3K2R w KQkq - 0 1' -'r2bkb1r/8/8/8/8/3bb3/8/R2BKB1R w KQkq - 0 1' +r3k2r/8/3B4/8/8/3b4/8/R3K2R w KQkq - 0 1 +r3k2r/8/3BB3/8/8/3bb3/8/R3K2R w KQkq - 0 1 +r2bkb1r/8/8/8/8/3bb3/8/R2BKB1R w KQkq - 0 1 + +# illegal positions +4k3/8/8/8/7b/8/8/4K3 b - - 0 1 +2r1k3/3P4/8/8/8/8/8/4K3 w - - 0 1 diff --git a/make.deps b/make.deps index caaabb4..f0f3f1d 100644 --- a/make.deps +++ b/make.deps @@ -13,4 +13,5 @@ src/list.h src/pool.h src/board.h src/position.h ./obj/pool.o:: src/pool.c src/list.h src/pool.h src/debug.h ./obj/position.o:: src/position.c src/chessdefs.h src/bits.h src/debug.h \ - src/position.h src/board.h src/piece.h src/list.h src/pool.h src/fen.h + src/position.h src/board.h src/piece.h src/list.h src/pool.h src/move.h \ + src/fen.h diff --git a/src/bodichess.c b/src/bodichess.c index c8e213a..8f7820f 100644 --- a/src/bodichess.c +++ b/src/bodichess.c @@ -48,13 +48,15 @@ COMMAND *find_command (char *); char *stripwhite (char *string); /* The names of functions that actually do the manipulation. */ -int do_help (pos_t *, char*); -int do_fen (pos_t *, char*); -int do_pos (pos_t *, char*); +int do_help(pos_t *, char*); +int do_fen(pos_t *, char*); +int do_pos(pos_t *, char*); int do_genmoves(pos_t *, char*); int do_prmoves(pos_t *, char*); -int do_eval (pos_t *, char*); -int do_quit (pos_t *, char*); +int do_memstats(pos_t *, char*); +int do_eval(pos_t *, char*); +int do_quit(pos_t *, char*); +int do_debug(pos_t *, char*); COMMAND commands[] = { { "help", do_help, "Display this text" }, @@ -62,10 +64,12 @@ COMMAND commands[] = { { "fen", do_fen, "Set position to FEN" }, { "pos", do_pos, "Print current position" }, { "quit", do_quit, "Quit" }, - { "genmv", do_genmoves, "Generate next move list" }, - { "prmv", do_prmoves, "Generate next move list" }, + { "genmove", do_genmoves, "Generate next move list" }, + { "prmoves", do_prmoves, "Generate next move list" }, + { "memstats", do_memstats, "Generate next move list" }, { "eval", do_eval, "Eval current position" }, - { NULL, (int (*)()) NULL, NULL } + { "debug", do_debug, "Set log level to LEVEL" }, + { NULL, (int(*)()) NULL, NULL } }; static int done=0; @@ -87,13 +91,13 @@ int bodichess(pos_t *pos) * Then, if there is anything left, add it to the history list * and execute it. */ - s = stripwhite (buffer); + s = stripwhite(buffer); if (*s) { - add_history (s); - execute_line (pos, s); + add_history(s); + execute_line(pos, s); } - free (buffer); + free(buffer); } return 0; @@ -170,15 +174,13 @@ char *escape(const char *original) int quote_detector(char *line, int index) { - return ( - index > 0 && - line[index - 1] == '\\' && - !quote_detector(line, index - 1) - ); + return index > 0 + && line[index - 1] == '\\' + &&!quote_detector(line, index - 1); } /* Execute a command line. */ -int execute_line (pos_t *pos, char *line) +int execute_line(pos_t *pos, char *line) { register int i; COMMAND *command; @@ -186,31 +188,31 @@ int execute_line (pos_t *pos, char *line) /* Isolate the command word. */ i = 0; - while (line[i] && whitespace (line[i])) + while (line[i] && whitespace(line[i])) i++; word = line + i; - while (line[i] && !whitespace (line[i])) + while (line[i] && !whitespace(line[i])) i++; if (line[i]) line[i++] = '\0'; - command = find_command (word); + command = find_command(word); if (!command) { - fprintf (stderr, "%s: Unknown command.\n", word); - return (-1); + fprintf(stderr, "%s: Unknown command.\n", word); + return -1; } /* Get argument to command, if any. */ - while (whitespace (line[i])) + while (whitespace(line[i])) i++; word = line + i; /* return command number */ - return ((*(command->func)) (pos, word)); + return (*command->func)(pos, word); } /* Look up NAME as the name of a command, and return a pointer to that @@ -220,10 +222,10 @@ COMMAND *find_command(char *name) register int i; for (i = 0; commands[i].name; i++) - if (strcmp (name, commands[i].name) == 0) - return (&commands[i]); + if (strcmp(name, commands[i].name) == 0) + return &commands[i]; - return ((COMMAND *)NULL); + return (COMMAND *)NULL; } /* Strip whitespace from the start and end of STRING. Return a pointer @@ -232,14 +234,14 @@ char *stripwhite(char *string) { register char *s, *t; - for (s = string; whitespace (*s); s++) + for (s = string; whitespace(*s); s++) ; if (*s == 0) - return (s); + return s; - t = s + strlen (s) - 1; - while (t > s && whitespace (*t)) + t = s + strlen(s) - 1; + while (t > s && whitespace(*t)) t--; *++t = '\0'; @@ -261,7 +263,7 @@ int do_fen(pos_t *pos, char *arg) return 1; } -int do_pos (pos_t *pos, +int do_pos(pos_t *pos, __attribute__((unused)) char *arg) { log_f(1, "%s\n", arg); @@ -286,12 +288,28 @@ int do_prmoves(pos_t *pos, return 1; } +int do_memstats(__attribute__((unused)) pos_t *pos, + __attribute__((unused)) char *arg) +{ + moves_pool_stats(); + piece_pool_stats(); + pos_pool_stats(); + return 1; +} + int do_quit(__attribute__((unused)) pos_t *pos, __attribute__((unused)) char *arg) { return done = 1; } +int do_debug(__attribute__((unused)) pos_t *pos, + __attribute__((unused)) char *arg) +{ + debug_level_set(atoi(arg)); + return 1; +} + /* Print out help for ARG, or for all of the commands if ARG is not present. */ int do_help(__attribute__((unused)) pos_t *pos, @@ -301,30 +319,30 @@ int do_help(__attribute__((unused)) pos_t *pos, int printed = 0; for (i = 0; commands[i].name; i++) { - if (!*arg || (strcmp (arg, commands[i].name) == 0)) { - printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); + if (!*arg || (strcmp(arg, commands[i].name) == 0)) { + printf("%s\t\t%s.\n", commands[i].name, commands[i].doc); printed++; } } if (!printed) { - printf ("No commands match `%s'. Possibilties are:\n", arg); + printf("No commands match `%s'. Possibilties are:\n", arg); for (i = 0; commands[i].name; i++) { /* Print in six columns. */ if (printed == 6) { printed = 0; - printf ("\n"); + printf("\n"); } - printf ("%s\t", commands[i].name); + printf("%s\t", commands[i].name); printed++; } if (printed) - printf ("\n"); + printf("\n"); } - return (0); + return 0; } #ifdef BIN_bodichess diff --git a/src/fen.c b/src/fen.c index 3f730a9..7b8d550 100644 --- a/src/fen.c +++ b/src/fen.c @@ -53,6 +53,7 @@ pos_t *fen2pos(pos_t *pos, char *fen) board_t *board = pos->board; # define SKIP_BLANK(p) for(;*(p) == ' '; (p)++) + pos_clear(pos); /* 1) get piece placement information */ for (rank = 7, file = 0; *p && *p != ' '; ++p) { diff --git a/src/move.c b/src/move.c index 01e7b8a..290b98a 100644 --- a/src/move.c +++ b/src/move.c @@ -54,6 +54,12 @@ pool_t *moves_pool_init() return moves_pool; } +void moves_pool_stats() +{ + if (moves_pool) + pool_stats(moves_pool); +} + int move_print(move_t *move, move_flags_t flags) { if (flags & M_PR_CAPT && !(move->flags & M_CAPTURE)) { @@ -141,8 +147,17 @@ static move_t *move_add(pos_t *pos, piece_t piece, square_t from, FILE2C(GET_F(to)), RANK2C(GET_R(to))); # endif + /* impossible if opponent king is attacked + */ if (COLOR(piece) != pos->turn) return NULL; + if (board[to].piece & KING) { +# ifdef DEBUG_MOVE + log_i(2, "invalid position: opponent king [%c%c] is in check.\n", + FILE2C(GET_F(to)), RANK2C(GET_R(to))); +# endif + return NULL; + } if (!(move = pool_get(moves_pool))) return NULL; @@ -165,6 +180,42 @@ static move_t *move_add(pos_t *pos, piece_t piece, square_t from, return move; } +void move_del(struct list_head *ptr) +{ + move_t *move = list_entry(ptr, move_t, list); + +# ifdef DEBUG_MOVE + log_i(3, "delete move from %c%c to %c%c\n", + FILE2C(GET_F(move->from)), RANK2C(GET_R(move->from)), + FILE2C(GET_F(move->to)), RANK2C(GET_R(move->to))); +# endif + + /* TODO: remove move->pos if non null */ + if (move->pos) { + pos_clear(move->pos); + } + list_del(ptr); + pool_add(moves_pool, move); + return; +} + +int moves_del(pos_t *pos) +{ + struct list_head *p_cur, *tmp, *head; + int count = 0; + + head = &pos->moves; + + list_for_each_safe(p_cur, tmp, head) { + move_del(p_cur); + count++; + } +# ifdef DEBUG_PIECE + log_f(3, "removed=%d\n", count); +# endif + return count; +} + /* TODO: return nmoves */ static move_t *move_pawn_add(pos_t *pos, piece_t piece, square_t from, square_t to, unsigned char rank7) @@ -217,7 +268,7 @@ int pseudo_moves_pawn(pos_t *pos, piece_list_t *ppiece, bool doit) } # ifdef DEBUG_MOVE - log_f(3, "pos:%p turn:%s piece:%d [%s %s] dir:%d at %#04x[%c%c]\n", + log_f(2, "pos:%p turn:%s piece:%d [%s %s] dir:%d at %#04x[%c%c]\n", pos, IS_WHITE(pos->turn)? "white": "black", piece, @@ -464,6 +515,7 @@ int moves_gen(pos_t *pos, bool color, bool doit) if (doit) pseudo_moves_castle(pos); list_for_each_safe(p_cur, tmp, piece_list) { + piece = list_entry(p_cur, piece_list_t, list); if (PIECE(piece->piece) != PAWN) pseudo_moves_gen(pos, piece, doit); diff --git a/src/move.h b/src/move.h index c7dd420..b769ce8 100644 --- a/src/move.h +++ b/src/move.h @@ -19,10 +19,6 @@ #include "pool.h" #include "piece.h" -/* move_add() return value when generating - */ - - /* move flags */ typedef unsigned char move_flags_t; @@ -48,14 +44,18 @@ typedef struct move_s { piece_t promotion; /* promoted piece */ move_flags_t flags; struct list_head list; /* next move */ - struct pos_t *pos; /* resulting position */ + struct pos_s *pos; /* resulting position */ } move_t; pool_t *moves_pool_init(); +void moves_pool_stats(); int move_print(move_t *move, move_flags_t flags); void moves_print(pos_t *move, move_flags_t flags); int pseudo_moves_castle(pos_t *pos); +void move_del(struct list_head *ptr); +int moves_del(pos_t *pos); + int pseudo_moves_gen(pos_t *pos, piece_list_t *piece, bool doit); int pseudo_moves_pawn(pos_t *pos, piece_list_t *piece, bool doit); int moves_gen(pos_t *pos, bool color, bool doit); diff --git a/src/piece.c b/src/piece.c index 8e777fb..8ab3376 100644 --- a/src/piece.c +++ b/src/piece.c @@ -54,6 +54,12 @@ pool_t *piece_pool_init() return pieces_pool; } +void piece_pool_stats() +{ + if (pieces_pool) + pool_stats(pieces_pool); +} + static eval_t pieces_values[] = { [PAWN] = PAWN_VALUE, [KNIGHT] = KNIGHT_VALUE, @@ -85,6 +91,34 @@ piece_list_t *piece_add(pos_t *pos, piece_t piece, square_t square) return new; } +void piece_del(struct list_head *ptr) +{ + piece_list_t *piece = list_entry(ptr, piece_list_t, list); +# ifdef DEBUG_PIECE + log_f(3, "piece=%02x square=%02x\n", piece->piece, piece->square); +# endif + list_del(ptr); + pool_add(pieces_pool, piece); + return; +} + +int pieces_del(pos_t *pos, short color) +{ + struct list_head *p_cur, *tmp, *head; + int count = 0; + + head = &pos->pieces[color]; + + list_for_each_safe(p_cur, tmp, head) { + piece_del(p_cur); + count++; + } +# ifdef DEBUG_PIECE + log_f(3, "color=%d removed=%d\n", color, count); +# endif + return count; +} + #ifdef BIN_piece #include "fen.h" int main(int ac, char**av) diff --git a/src/piece.h b/src/piece.h index 4e28b2a..096d7e3 100644 --- a/src/piece.h +++ b/src/piece.h @@ -62,6 +62,9 @@ extern struct piece_details { void piece_list_print(struct list_head *list); pool_t *piece_pool_init(); +void piece_pool_stats(); piece_list_t *piece_add(pos_t *pos, piece_t piece, square_t square); +void piece_del(struct list_head *ptr); +int pieces_del(pos_t *pos, short color); #endif diff --git a/src/position.c b/src/position.c index 426eef2..9c3ed7b 100644 --- a/src/position.c +++ b/src/position.c @@ -19,6 +19,7 @@ #include "chessdefs.h" #include "position.h" +#include "move.h" #include "fen.h" #include "piece.h" @@ -149,9 +150,10 @@ pos_t *pos_clear(pos_t *pos) pos->controlled[BLACK] = 0; pos->mobility[WHITE] = 0; pos->mobility[BLACK] = 0; - INIT_LIST_HEAD(&pos->pieces[WHITE]); - INIT_LIST_HEAD(&pos->pieces[BLACK]); - INIT_LIST_HEAD(&pos->moves); + /* remove pieces / moves */ + pieces_del(pos, WHITE); + pieces_del(pos, BLACK); + moves_del(pos); return pos; } @@ -167,15 +169,10 @@ pos_t *pos_get() { pos_t *pos = pool_get(pos_pool); if (pos) { - //printf("sizeof(board)=%lu\n", sizeof (board_t)); - //pos->board = malloc(sizeof (board_t)*BOARDSIZE); - //printf("board mem: %p-%p\n", pos->board, pos->board+sizeof (board_t)); - //if (pos->board) + INIT_LIST_HEAD(&pos->pieces[WHITE]); + INIT_LIST_HEAD(&pos->pieces[BLACK]); + INIT_LIST_HEAD(&pos->moves); pos_clear(pos); - //else { - // free(pos); - // pos = NULL; - //} } return pos; } @@ -207,3 +204,9 @@ pool_t *pos_pool_init() pos_pool = pool_init("positions", 128, sizeof(pos_t)); return pos_pool; } + +void pos_pool_stats() +{ + if (pos_pool) + pool_stats(pos_pool); +} diff --git a/src/position.h b/src/position.h index 8378c7a..5bf0da0 100644 --- a/src/position.h +++ b/src/position.h @@ -45,6 +45,7 @@ pos_t *pos_clear(pos_t *pos); pos_t *pos_startpos(pos_t *pos); pos_t *pos_create(); pool_t *pos_pool_init(); +void pos_pool_stats(); pos_t *pos_get(); pos_t *pos_dup(pos_t *pos);