/* ******************************************************************************* * * * Analyze() is used to handle the "analyze" command. This mode basically * * puts Crafty into a "permanent pondering" state, where it reads a move * * from the input stream, and then "ponders" for the opposite side. * * Whenever a move is entered, Crafty reads this move, updates the game * * board, and then starts "pondering" for the other side. * * * * The purpose of this mode is to force Crafty to follow along in a game, * * providing analysis continually for the side on move until a move is * * entered, advancing the game to the next position. * * * ******************************************************************************* */ void Analyze() { int i, move, back_number, readstat = 1; TREE *const tree = block[0]; /* ************************************************************ * * * Initialize. * * * ************************************************************ */ int save_swindle_mode = swindle_mode; swindle_mode = 0; ponder_move = 0; analyze_mode = 1; if (!xboard) display_options |= 1 + 2 + 4; _printf("Analyze Mode: type \"exit\" to terminate.\n"); /* ************************************************************ * * * Now loop waiting on input, searching the current * * position continually until a move comes in. * * * ************************************************************ */ do { do { last_pv.pathd = 0; last_pv.pathl = 0; input_status = 0; pondering = 1; tree->status[1] = tree->status[0]; Iterate(game_wtm, think, 0); pondering = 0; if (book_move) moves_out_of_book = 0; if (!xboard) { if (game_wtm) _printf("analyze.White(%d): ", move_number); else _printf("analyze.Black(%d): ", move_number); fflush(stdout); } /* ************************************************************ * * * If we get back to here, something has been typed in and * * is in the command buffer normally, unless the search * * terminated naturally due to finding a mate or reaching * * the max depth allowable. * * * ************************************************************ */ if (!input_status) do { readstat = Read(1, buffer); if (readstat < 0) break; nargs = ReadParse(buffer, args, " ;"); Print(128, "%s\n", buffer); if (strstr(args[0], "timeleft") && !xboard) { if (game_wtm) _printf("analyze.White(%d): ", move_number); else _printf("analyze.Black(%d): ", move_number); fflush(stdout); } } while (strstr(args[0], "timeleft")); else nargs = ReadParse(buffer, args, " ;"); if (readstat < 0) break; move = 0; if (!strcmp(args[0], "exit")) break; /* ************************************************************ * * * First, check for the special analyze command "back n" * * and handle it if present, otherwise try Option() to see * * if it recognizes the input as a command. * * * ************************************************************ */ if (OptionMatch("back", args[0])) { if (nargs > 1) back_number = atoi(args[1]); else back_number = 1; for (i = 0; i < back_number; i++) { game_wtm = Flip(game_wtm); if (Flip(game_wtm)) move_number--; } if (move_number == 0) { move_number = 1; game_wtm = 1; } sprintf(buffer, "reset %d", move_number); Option(tree); display = tree->position; } else if (Option(tree)) { display = tree->position; } /* ************************************************************ * * * If InputMove() can recognize this as a move, make it, * * swap sides, and return to the top of the loop to call * * search from this new position. * * * ************************************************************ */ else if ((move = InputMove(tree, buffer, 0, game_wtm, 1, 0))) { char *outmove = OutputMove(tree, move, 0, game_wtm); if (history_file) { fseek(history_file, ((move_number - 1) * 2 + 1 - game_wtm) * 10, SEEK_SET); fprintf(history_file, "%9s\n", outmove); } if (game_wtm) Print(128, "White(%d): ", move_number); else Print(128, "Black(%d): ", move_number); Print(128, "%s\n", outmove); if (speech) { char announce[64]; //strcpy(announce, SPEAK); //strcat(announce, outmove); //system(announce); SPEAK(outmove); } MakeMoveRoot(tree, move, game_wtm); display = tree->position; last_mate_score = 0; if (log_file) DisplayChessBoardFile(log_file, tree->position); } /* ************************************************************ * * * If Option() didn't handle the input, then it is illegal * * and should be reported to the user. * * * ************************************************************ */ else { pondering = 0; if (Option(tree) == 0) _printf("illegal move: %s\n", buffer); pondering = 1; display = tree->position; } } while (!move); if (readstat < 0 || !strcmp(args[0], "exit")) break; game_wtm = Flip(game_wtm); if (game_wtm) move_number++; } while (1); analyze_mode = 0; _printf("analyze complete.\n"); pondering = 0; swindle_mode = save_swindle_mode; }
/* ******************************************************************************* * * * Interrupt() is used to read in a move when the operator types something * * while a search is in progress (during pondering as one example.) This * * routine reads in a command (move) and then makes two attempts to use this * * input: (1) call Option() to see if the command can be executed; (2) try * * InputMove() to see if this input is a legal move; If so, and we are * * pondering see if it matches the move we are pondering. * * * ******************************************************************************* */ void Interrupt(int ply) { int temp, i, left = 0, readstat, result, time_used; int save_move_number; TREE *const tree = block[0]; /* ************************************************************ * * * If trying to find a move to ponder, and the operator * * types a command, exit a.s.a.p. * * * ************************************************************ */ if (puzzling) abort_search = 1; /* ************************************************************ * * * First check to see if this is a command by calling * * Option(). Option() will return a 0 if it didn't * * recognize the command; otherwise it returns a 1 if * * the command was executed, or a 2 if we need to abort * * the search to execute the command. * * * ************************************************************ */ else do { readstat = Read(0, buffer); if (readstat <= 0) break; nargs = ReadParse(buffer, args, " ;"); if (nargs == 0) { Print(128, "ok.\n"); break; } if (strcmp(args[0], ".")) { save_move_number = move_number; if (!wtm) move_number--; if (root_wtm) Print(128, "Black(%d): %s\n", move_number, buffer); else Print(128, "White(%d): %s\n", move_number, buffer); move_number = save_move_number; } /* ************************************************************ * * * "." command displays status of current search. * * * ************************************************************ */ if (!strcmp(args[0], ".")) { if (xboard) { end_time = ReadClock(); time_used = (end_time - start_time); printf("stat01: %d ", time_used); printf(BMF " ", tree->nodes_searched); printf("%d ", iteration_depth); for (i = 0; i < n_root_moves; i++) if (!(root_moves[i].status & 128)) left++; printf("%d %d\n", left, n_root_moves); fflush(stdout); break; } else { end_time = ReadClock(); time_used = (end_time - start_time); printf("time:%s ", DisplayTime(time_used)); printf("nodes:" BMF "\n", tree->nodes_searched); DisplayTreeState(block[0], 1, 0, ply); } } /* ************************************************************ * * * "mn" command is used to set the move number to a * * specific value... * * * ************************************************************ */ else if (!strcmp("mn", args[0])) { if (nargs == 2) { move_number = atoi(args[1]); Print(128, "move number set to %d\n", move_number); } } /* ************************************************************ * * * "?" command says "move now!" * * * ************************************************************ */ else if (!strcmp(args[0], "?")) { if (thinking) { time_abort = 1; abort_search = 1; } } /* ************************************************************ * * * Next see if Option() recognizes this as a command. * * * ************************************************************ */ else { save_move_number = move_number; if (!analyze_mode && !wtm) move_number--; result = Option(tree); move_number = save_move_number; if (result >= 2) { if (thinking && result != 3) Print(128, "command not legal now.\n"); else { abort_search = 1; input_status = 2; break; } } else if ((result != 1) && analyze_mode) { abort_search = 1; input_status = 2; break; } /* ************************************************************ * * * Now, check to see if the operator typed a move. If * * so, and it matched the predicted move, switch from * * pondering to thinking to start the timer. If this * * is a move, but not the predicted move, abort the * * search, and start over with the right move. * * * ************************************************************ */ else if (!result) { if (pondering) { nargs = ReadParse(buffer, args, " ;"); temp = InputMove(tree, args[0], 0, Flip(root_wtm), 1, 1); if (temp) { if ((From(temp) == From(ponder_move)) && (To(temp) == To(ponder_move)) && (Piece(temp) == Piece(ponder_move)) && (Captured(temp) == Captured(ponder_move)) && (Promote(temp) == Promote(ponder_move))) { predicted++; input_status = 1; pondering = 0; thinking = 1; opponent_end_time = ReadClock(); program_start_time = ReadClock(); Print(128, "predicted move made.\n"); } else { input_status = 2; abort_search = 1; break; } } else if (!strcmp(args[0], "go") || !strcmp(args[0], "move") || !strcmp(args[0], "SP")) { abort_search = 1; break; } else Print(4095, "Illegal move: %s\n", args[0]); } else Print(4095, "unrecognized/illegal command: %s\n", args[0]); } } } while (1); if (log_file) fflush(log_file); }