diff --git a/src/move-gen.c b/src/move-gen.c index 7ea6138..0113ca7 100644 --- a/src/move-gen.c +++ b/src/move-gen.c @@ -138,24 +138,52 @@ move_t pos_next_legal(const pos_t *pos, movelist_t *movelist, int *start) } /** - * pos_all_legal() - get the list of legal moves from pseudo-legal. + * pos_legal_dup() - get legal moves from pseudo-legal ones in new list. * @pos: position - * @movelist: &pseudo-legal movelist_t - * @dest: &destination movelist_t + * @pseudo: &movelist_t pseudo-legal moves list + * @legal: &movelist_t legal moves * * The pseudo-legal moves must be already calculated before calling this function. - * No check is done on @dest limits. + * No check is done on @legal limits. + * This function is similar to pos_legal(), but creates a new list for legal moves. + * It should only be used for debug purpose, when we want to keep a copy of + * pseudo-legal moves. * - * @Return: @dest + * @return: @legal */ -movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *dest) +movelist_t *pos_legal_dup(const pos_t *pos, movelist_t *pseudo, movelist_t *legal) { - int tmp = dest->nmoves = 0; + int tmp = legal->nmoves = 0; move_t move; - while ((move = pos_next_legal(pos, movelist, &tmp)) != MOVE_NONE) - dest->move[dest->nmoves++] = move; - return dest; + while ((move = pos_next_legal(pos, pseudo, &tmp)) != MOVE_NONE) + legal->move[legal->nmoves++] = move; + return legal; +} + +/** + * pos_legal() - get legal moves from pseudo-legal ones in new list. + * @pos: position + * @list: &movelist_t pseudo-legal moves list + * + * The pseudo-legal moves must be already calculated before calling this function. + * @list is replaced by legal moves. + * + * @return: @list + */ +movelist_t *pos_legal(const pos_t *pos, movelist_t *list) +{ + move_t *cur = list->move, *last = list->move + list->nmoves; + + while (cur < last) { + if (pseudo_is_legal(pos, *cur)) + cur++; + else { + *cur = *--last; + } + } + list->nmoves = last - list->move; + return list; } /** @@ -292,7 +320,7 @@ static inline move_t *moves_gen(move_t *moves, square_t from, bitboard_t to_bb) } /** - * pos_gen_pseudomoves() - generate position pseudo-legal moves + * pos_gen_pseudo() - generate position pseudo-legal moves * @pos: position * @movelist: &movelist_t array to store pseudo-moves * @@ -312,9 +340,9 @@ static inline move_t *moves_gen(move_t *moves, square_t from, bitboard_t to_bb) * * TODO: move code to specific functions (especially castling, pawn push/capture) * - * @Return: The total number of moves. + * @Return: movelist */ -int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist) +movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist) { color_t us = pos->turn; color_t them = OPPONENT(us); @@ -511,5 +539,7 @@ int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist) /* TODO: add function per piece, and type, for easier debug */ finish: - return movelist->nmoves = moves - movelist->move; + movelist->nmoves = moves - movelist->move; + return movelist; + //return movelist->nmoves = moves - movelist->move; } diff --git a/src/move-gen.h b/src/move-gen.h index 2b3d072..c7595c3 100644 --- a/src/move-gen.h +++ b/src/move-gen.h @@ -23,7 +23,9 @@ bool pseudo_is_legal(const pos_t *pos, const move_t move); move_t pos_next_legal(const pos_t *pos, movelist_t *movelist, int *start); -movelist_t *pos_all_legal(const pos_t *pos, movelist_t *movelist, movelist_t *dest); -int pos_gen_pseudomoves(pos_t *pos, movelist_t *movelist); +movelist_t *pos_legal_dup(const pos_t *pos, movelist_t *pseudo, movelist_t *legal); +movelist_t *pos_legal(const pos_t *pos, movelist_t *list); + +movelist_t *pos_gen_pseudo(pos_t *pos, movelist_t *movelist); #endif /* MOVEGEN_H */ diff --git a/src/search.c b/src/search.c index cb37cd6..b0579c4 100644 --- a/src/search.c +++ b/src/search.c @@ -33,8 +33,8 @@ * This version uses the algorithm: * if last depth * return 1; - * gen pseudo-legal moves - * loop for each legal move + * gen legal moves + * loop for legal move * do-move * perft (depth -1) * undo-move @@ -43,29 +43,32 @@ */ u64 perft(pos_t *pos, int depth, int ply) { - int subnodes, movetmp = 0; + int subnodes; u64 nodes = 0; - movelist_t pseudo; - move_t move; + movelist_t movelist; + move_t *move, *last; state_t state; - if (depth == 0) - return 1; - pseudo.nmoves = 0; + movelist.nmoves = 0; pos_set_checkers_pinners_blockers(pos); state = pos->state; - pos_gen_pseudomoves(pos, &pseudo); - while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) { - move_do(pos, move); - subnodes = perft(pos, depth - 1, ply + 1); - if (ply == 1) { - char movestr[8]; - printf("%s: %d\n", move_str(movestr, move, 0), subnodes); + pos_legal(pos, pos_gen_pseudo(pos, &movelist)); + last = movelist.move + movelist.nmoves; + for (move = movelist.move; move < last; ++move) { + if (depth == 1) { + nodes++; + } else { + move_do(pos, *move); + subnodes = perft(pos, depth - 1, ply + 1); + if (ply == 1) { + char movestr[8]; + printf("%s: %d\n", move_str(movestr, *move, 0), subnodes); + } + nodes += subnodes; + move_undo(pos, *move); + pos->state = state; } - nodes += subnodes; - move_undo(pos, move); - pos->state = state; } if (ply == 1) @@ -82,6 +85,15 @@ u64 perft(pos_t *pos, int depth, int ply) * Run perft on a position. This function displays the available moves at @depth * level for each possible first move, and the total of moves. * + * This version uses the algorithm: + * if last depth + * return 1; + * gen pseudo-legal moves + * loop for each legal move in pseudo-legal list + * do-move + * perft (depth -1) + * undo-move + * * @return: total moves found at @depth level. */ u64 perft_new_pinners(pos_t *pos, int depth, int ply) @@ -92,23 +104,25 @@ u64 perft_new_pinners(pos_t *pos, int depth, int ply) move_t move; state_t state; - if (depth == 0) - return 1; pseudo.nmoves = 0; pos_set_checkers_pinners_blockers(pos); state = pos->state; - pos_gen_pseudomoves(pos, &pseudo); + pos_gen_pseudo(pos, &pseudo); while ((move = pos_next_legal(pos, &pseudo, &movetmp)) != MOVE_NONE) { - move_do(pos, move); - subnodes = perft_new_pinners(pos, depth - 1, ply + 1); - if (ply == 1) { - char movestr[8]; - printf("%s: %d\n", move_str(movestr, move, 0), subnodes); + if (depth == 1) { + nodes++; + } else { + move_do(pos, move); + subnodes = perft_new_pinners(pos, depth - 1, ply + 1); + if (ply == 1) { + char movestr[8]; + printf("%s: %d\n", move_str(movestr, move, 0), subnodes); + } + nodes += subnodes; + move_undo(pos, move); + pos->state = state; } - nodes += subnodes; - move_undo(pos, move); - pos->state = state; } if (ply == 1) @@ -314,24 +328,24 @@ u64 perft_new_pinners(pos_t *pos, int depth, int ply) * @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; + { + 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; -} + 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; + } */ diff --git a/test/movedo-test.c b/test/movedo-test.c index ac24e44..1415c29 100644 --- a/test/movedo-test.c +++ b/test/movedo-test.c @@ -47,7 +47,7 @@ int main(int __unused ac, __unused char**av) pos->checkers = pos_checkers(pos, pos->turn); pos_set_pinners_blockers(pos); - pos_gen_pseudomoves(pos, &pseudo); + pos_gen_pseudo(pos, &pseudo); savepos = pos_dup(pos); state_t state = pos->state; diff --git a/test/movegen-test.c b/test/movegen-test.c index 93fa5eb..4452fd2 100644 --- a/test/movegen-test.c +++ b/test/movegen-test.c @@ -216,7 +216,7 @@ int main(int __unused ac, __unused char**av) FILE *outfd; char *fen; pos_t *pos, *fishpos = pos_new(); - movelist_t pseudo, legal, fishmoves; + movelist_t pseudo, fishmoves; //bitboard_t wrong = 0x5088000040, tmp, loop; //bit_for_each64(loop, tmp, ) //printf("fishpos 1=%p\n", fishpos); @@ -239,9 +239,9 @@ int main(int __unused ac, __unused char**av) send_stockfish_fen(outfd, fishpos, &fishmoves, fen); pos_set_checkers_pinners_blockers(pos); - pos_gen_pseudomoves(pos, &pseudo); + pos_gen_pseudo(pos, &pseudo); //moves_print(&pseudo, 0); - pos_all_legal(pos, &pseudo, &legal); + pos_legal(pos, &pseudo); //moves_print(&legal, 0); //printf("Fu "); @@ -253,7 +253,7 @@ int main(int __unused ac, __unused char**av) /* sort and print movelists */ move_sort_by_sq(&fishmoves); - move_sort_by_sq(&legal); + move_sort_by_sq(&pseudo); // printf("\nFs "); // moves_print(fishpos, 0); // fflush(stdout); @@ -262,14 +262,14 @@ int main(int __unused ac, __unused char**av) // fflush(stdout); /* compare movelists */ - if (!movelists_equal(&fishmoves, &legal)) { + if (!movelists_equal(&fishmoves, &pseudo)) { pos_print(pos); printf("F: "); moves_print(&fishmoves, 0); printf("M: "); - moves_print(&legal, 0); + moves_print(&pseudo, 0); } else { - printf("[%s]: OK (%d Moves)\n", fen, legal.nmoves); + printf("[%s]: OK (%d Moves)\n", fen, pseudo.nmoves); //moves_print(&fishpos->moves, 0); } //compare_moves(&fishpos->moves, &legal);