int test_move(char *fen, int side, char *move, int move_correct) { IS_CHECKMATE = IS_DRAW = 0; B b = fen_to_board(fen); print_board(b); printf("\n"); Move m = find_move(b, side, 180); if(m == atomove(move, b) && move_correct) { printf("CORRECT\n\n"); goto SUCESS; } else if(m != atomove(move, b) && !move_correct) { printf("CORRECT\n\n"); print_move(m); printf("\n%s\n", movetoa(m)); goto SUCESS; } else goto FAILURE; SUCESS: printf("\n\n#############################\n"); free(b); return 1; FAILURE: printf("FAILURE: "); print_move(m); printf("\n%s\n", movetoa(m)); printf("\n\n#############################\n"); free(b); return 0; }
void bench(void) { Chess chess; SearchData sd; S64 timer; int npos = 0; int nfen = (int)(sizeof(bench_fen) / sizeof(char*)); double avg_bfactor; double t_elapsed; double hhit_rate; U64 nnodes_all; /* num. of all nodes (main + qs) */ int nps; /* nodes (all types) per second */ int i; init_chess(&chess); init_search_data(&sd); chess.max_depth = 8; chess.increment = 60000; printf("Running benchmark at search depth %d...\n", chess.max_depth); timer = get_ms(); progressbar(nfen, 0); for (i = 0; i < nfen; i++) { const char *fen = bench_fen[i]; if (strlen(fen) <= 1) continue; if (!fen_to_board(&chess.board, fen)) { id_search(&chess, NULLMOVE); if (chess.sd.cmd_type != CMDT_CONTINUE) { printf("Benchmark cancelled by user\n"); return; } sd.nnodes += chess.sd.nnodes; sd.nqs_nodes += chess.sd.nqs_nodes; sd.nhash_probes += chess.sd.nhash_probes; sd.nhash_hits += chess.sd.nhash_hits; sd.bfactor += chess.sd.bfactor; npos++; progressbar(nfen, npos); } else printf("\nInvalid FEN string: %s\n", fen); } timer = get_ms() - timer; t_elapsed = timer / 1000.0; avg_bfactor = sd.bfactor / npos; hhit_rate = (sd.nhash_hits * 100.0) / sd.nhash_probes; nnodes_all = sd.nnodes + sd.nqs_nodes; nps = (double)nnodes_all / ((double)timer / 1000.0); printf("\n\nBenchmark finished in %.2f seconds.\n", t_elapsed); printf("Main nodes searched: %" PRIu64 "\n", sd.nnodes); printf("Quiescence nodes searched: %" PRIu64 "\n", sd.nqs_nodes); printf("Total nodes per second: %d\n", nps); printf("Average branching factor: %.2f\n", avg_bfactor); printf("Hash table hit rate: %.2f%%\n", hhit_rate); }
/* Run a test position (eg. WAC, ECM, WCSAC). Format of pos: <FEN> <"bm" or "am"> <move>; <position id>; - "bm" means <move> is the best move, "am" means <move> should be avoided - the move is in SAN notation - position id can be omitted - example: R7/P4k2/8/8/8/8/r7/6K1 w - - bm Rg8; id "WAC.018"; The time limit must be defined in <chess> before running the test. Returns -1 on error 0 for unsolved test 1 for solved test 2 for cancelled test */ int test_pos(Chess *chess, const char *pos) { char tmp_pos[MAX_BUF]; char *pos_item = NULL; char *svptr = NULL; U32 move; bool find_best; strlcpy(tmp_pos, pos, MAX_BUF); /* See if we're looking for the best move or avoiding a move. By doing that we'll also get to the end of the FEN string. */ if ((pos_item = strstr(tmp_pos, " bm ")) != NULL) find_best = true; else if ((pos_item = strstr(tmp_pos, " am ")) != NULL) { find_best = false; my_error("'Avoid move' positions not currently allowed"); return -1; } else return -1; *pos_item = 0; /* end of FEN string */ pos_item += 4; /* best move or move to avoid */ if (fen_to_board(&chess->board, tmp_pos)) return -1; /* Get the move string. */ if ((pos_item = strtok_r(pos_item, ";", &svptr)) == NULL) return -1; /* Some positions have a series of moves (a pv) as the solution. We only care about the first one, so make sure to pick just one. */ svptr = strchr(pos_item, ' '); if (svptr != NULL) *svptr = '\0'; move = san_to_move(&chess->board, pos_item); if (move == NULLMOVE) { printf("Illegal test solution: %s\n", pos_item); return -1; } id_search(chess, move); if (chess->sd.cmd_type != CMDT_CONTINUE) return 2; if (chess->sd.move == move) return 1; return 0; }
/* Starts a new game in position <fen>. */ void new_game(Chess *chess, const char *fen, int new_cpu_color) { ASSERT(1, chess != NULL); ASSERT(1, fen != NULL); if (fen_to_board(&chess->board, fen)) { printf("Invalid FEN string: %s\n", fen); return; } chess->game_over = false; chess->in_book = false; chess->cpu_color = new_cpu_color; /* Delete the (possibly) existing GAME_LOG file. */ if (remove(GAME_LOG) && errno != ENOENT) my_perror("Can't delete file %s", GAME_LOG); }
int checkmate_puzzle(char *fen) { B b = fen_to_board(fen); printf("\n"); printf("-----------------"); print_board(b); Move m = find_move(b, b->side_to_move, 60); if(IS_CHECKMATE) { printf("\nSUCESS: %s", movetoa(m)); return 1; } else if(CHECKSTALEMATE_IN_X) { printf("SUCESS IN %d MOVES: %s\n", CHECKSTALEMATE_IN_X, movetoa(m)); CHECKSTALEMATE_IN_X = 0; return 1; } else { printf("\nFAILURE: %s", movetoa(m)); return 0; } }
/* Read a PGN file (a collection of one or more games in PGN format) and store the positions and their win/loss ratios in an AVL tree (**tree). The AVL tree can later be written in an opening book file (book.bin). Returns the number of new positions added to the tree, or -1 on error. */ int pgn_to_tree(const char *filename, AvlNode **tree) { PgnResult result; int prev_progress; int npos = 0; long file_len; FILE *fp; Board board; ASSERT(1, filename != NULL); if ((fp = fopen(filename, "r")) == NULL) { my_perror("Can't open PGN file %s", filename); return -1; } if (settings.book_type != BOOK_MEM) { settings.book_type = BOOK_MEM; printf("Changed book mode to \"book in memory\"\n"); } if (*tree == NULL && file_exists(settings.book_file)) { printf("Loading opening book to memory...\n"); book_to_tree(settings.book_file, tree); } else if (*tree == NULL) printf("Creating a new opening book...\n"); /* Find out how big the file is. */ fseek(fp, 0, SEEK_END); file_len = ftell(fp); rewind(fp); printf("Reading PGN file %s...\n", filename); prev_progress = 0; progressbar(50, 0); while ((result = get_pgn_result(fp)) != RESULT_ERROR) { int depth; int progress; int len; char san_move[MAX_BUF]; /* Games with an unknown result are ignored. */ ASSERT(1, result != RESULT_ERROR); if (result == NO_RESULT || result == DRAWN_GAME) continue; depth = 0; fen_to_board(&board, START_FEN); while ((len = read_move(san_move, MAX_BUF, fp)) >= 0) { int points = 0; U32 move; /* break out of the loop when a new game begins */ if (depth > 0 && san_move[0] == '[') break; if (len < 2) continue; move = san_to_move(&board, san_move); if (move == NULLMOVE) { #if DEBUG_LEVEL > 0 update_log("Illegal move in %s: %s, line: %d\n", filename, san_move, get_line_num(fp)); #endif /* DEBUG_LEVEL > 0 */ break; } if ((result == WHITE_WINS && board.color == WHITE) || (result == BLACK_WINS && board.color == BLACK)) points = 2; make_move(&board, move); if (save_book_pos(board.posp->key, points, tree)) npos++; if (++depth >= MAX_BOOK_PLIES) break; } progress = (ftell(fp) * 50) / file_len; if (progress > prev_progress) { progressbar(50, progress); prev_progress = progress; } } progressbar(50, 50); my_close(fp, filename); printf("\n"); return npos; }