def export(self, pgn_headers=None) -> Game: """ pgn_headers - PGN headers to include in the exported PGN """ fen = self.puzzle.initial_board.fen() board = chess.Board(fen) game = Game().from_board(board) game_node = game game_node.comment = "score: %s -> %s" % (_score_to_str( self.puzzle.initial_score), _score_to_str(self.puzzle.final_score)) comment = self._candidate_moves_annotations(self.puzzle.analyzed_moves) for position in self.puzzle.positions: game_node = game_node.add_variation( chess.Move.from_uci(position.initial_move.uci())) if comment: game_node.comment = comment comment = self._candidate_moves_annotations( position.candidate_moves) if pgn_headers: for h in pgn_headers: if h == "FEN": continue game.headers[h] = pgn_headers[h] game.headers['PuzzleCategory'] = self.puzzle.category() puzzle_winner = self.puzzle.winner() if puzzle_winner: game.headers['PuzzleWinner'] = puzzle_winner game.headers['PuzzleEngine'] = AnalysisEngine.name() game.headers['PuzzleMakerVersion'] = __version__ return game
def find_puzzle_candidates(game: Game, scan_depth=SCAN_DEPTH) -> List[Puzzle]: """ finds puzzle candidates from a chess game """ log(Color.DIM, "Scanning game for puzzles (depth: %d)..." % scan_depth) prev_score = Cp(0) puzzles = [] i = 0 node = game while not node.is_end(): next_node = node.variation(0) next_board = next_node.board() cur_score = AnalysisEngine.best_move(next_board, scan_depth).score board = node.board() highlight_move = False if should_investigate(prev_score, cur_score, board): highlight_move = True puzzle = Puzzle( board, next_node.move, ) puzzles.append(puzzle) log_move(board, next_node.move, cur_score, highlight=highlight_move) prev_score = cur_score node = next_node i += 1 return puzzles
def _calculate_candidate_moves(self, depth): """ Find the best move from board position using multipv 3 """ multipv = NUM_CANDIDATE_MOVES log(Color.BLACK, "Evaluating best %d moves (depth %d)..." % (multipv, depth)) self.candidate_moves = AnalysisEngine.best_moves(self.board, depth, multipv) for analyzed_move in self.candidate_moves: self._log_move(analyzed_move.move, analyzed_move.score)
def _calculate_final_score(self, depth): """ Get the score of the final board position in the puzzle after the last move is made """ final_score = self.positions[-1].score if final_score: self.final_score = final_score else: self.final_score = AnalysisEngine.score(self.positions[-1].board, depth)
def _calculate_best_move(self, depth): """ Find the best move from board position using multipv 1 """ log(Color.BLACK, "Evaluating best move (depth %d)..." % depth) best_move = AnalysisEngine.best_move(self.board, depth) self.best_move = best_move.move self.score = best_move.score if self._num_legal_moves() == 1: self.candidate_moves = [best_move] self._log_move(self.best_move, self.score)
def _analyze_best_initial_move(self, depth) -> Move: log(Color.BLACK, "Evaluating best initial move (depth %d)..." % depth) best_move = AnalysisEngine.best_move(self.initial_board, depth) if best_move.move: self.analyzed_moves.append(best_move) log_move(self.initial_board, best_move.move, best_move.score, show_uci=True) self.initial_score = best_move.score return best_move.move
def _analyze_initial_moves(self, depth): """ get the score of the position before the initial move also get the score of the position after the initial move """ best_move = self._analyze_best_initial_move(depth) if not self.initial_move: return elif self.initial_move == best_move: log(Color.BLACK, "The move played was the best move") else: log(Color.BLACK, "Evaluating played initial move (depth %d)..." % depth) analyzed_move = AnalysisEngine.evaluate_move( self.initial_board, self.initial_move, depth) self.analyzed_moves.append(analyzed_move) log_move(self.initial_board, self.initial_move, analyzed_move.score, show_uci=True)
def tearDownClass(self): AnalysisEngine.quit()
def setUpClass(self): AnalysisEngine.instance()
if len(sys.argv) < 2: parser.print_usage() sys.exit(0) settings = parser.parse_args() try: # Optionally fix colors on Windows and in journals if the colorama module # is available. import colorama wrapper = colorama.AnsiToWin32(sys.stdout) if wrapper.should_wrap(): sys.stdout = wrapper.stream except ImportError: pass engine = AnalysisEngine.instance() engine.configure({ 'Threads': settings.threads, 'Hash': settings.memory, 'Contempt': 0, }) if settings.quiet: configure_logging(level=logging.INFO) else: configure_logging(level=logging.DEBUG) def print_puzzle_pgn(puzzle, pgn_headers=None): puzzle_pgn = puzzle.to_pgn(pgn_headers=pgn_headers) log(Color.MAGENTA, "NEW PUZZLE GENERATED\n")