def cruncher(thread_id: int): eval_nb = 0 db = pymongo.MongoClient()['puzzler'] bad_coll = db['puzzle2_bad_maybe'] play_coll = db['puzzle2_puzzle'] engine = SimpleEngine.popen_uci('./stockfish') engine.configure({'Threads': 4}) for doc in bad_coll.find({"bad": {"$exists": False}}): try: if ord(doc["_id"][4]) % threads != thread_id: continue doc = play_coll.find_one({'_id': doc['_id']}) if not doc: continue puzzle = read(doc) board = puzzle.mainline[len(puzzle.mainline) - 2].board() info = engine.analyse( board, multipv=5, limit=chess.engine.Limit(nodes=30_000_000)) bad = False for score in [pv["score"].pov(puzzle.pov) for pv in info]: if score < Mate(1) and score > Cp(250): bad = True # logger.info(puzzle.id) bad_coll.update_one({"_id": puzzle.id}, {"$set": { "bad": bad }}) except Exception as e: logger.error(e)
def worker(request_queue, response_queue, score_config, num_threads): logger = create_sub_logger('stockfish_queue_worker') engine = stockfish.create_engine() if num_threads: engine.configure({'Threads': num_threads}) while True: if not request_queue.empty(): board, move, prev_turn_score = request_queue.get() try: score = calculate_score(board=board, move=move, prev_turn_score=prev_turn_score or 0, engine=engine, score_config=score_config) except chess.engine.EngineTerminatedError: logger.error('Stockfish engine died while analysing (%s).', make_cache_key(board, move, prev_turn_score)) # If the analysis crashes the engine, something went really wrong. This tends to happen when the # board is not valid, but that is meant to be filtered in calculate_score. Just in case, do not # re-query the engine, instead assign the move a conservative score (here: as though into check). response_queue.put({ make_cache_key(board, move, prev_turn_score): score_config.into_check_score }) engine = stockfish.create_engine() if num_threads: engine.configure({'Threads': num_threads}) else: response_queue.put( {make_cache_key(board, move, prev_turn_score): score}) else: sleep(0.001)
def main() -> None: args = parse_args() setup_logging(args) # setup the engine enginepath = args.engine engine = SimpleEngine.popen_uci(enginepath) engine.configure({'Threads': args.threads}) with open(args.file) as pgn: for game in iter(lambda: chess.pgn.read_game(pgn), None): res = analyze_game(engine, game) if res is None: logger.debug("No only move sequence found.") else: node, solution, kind = res # Compose and print the puzzle puzzle: Dict[str, Any] = { 'game_id': game.headers.get("Site", "?")[20:], 'fen': node.board().fen(), 'ply': ply_of(node.board()), 'moves': list(map(lambda m: m.uci(), solution)), 'kind': kind, 'generator_version': version, } r = requests.post(post_url, json=puzzle) logger.info(r.text if r.ok else "FAILURE {}".format(r.text))
def cruncher(thread_id: int): eval_nb = 0 build_coll = pymongo.MongoClient()['puzzler']['puzzle2'] engine = SimpleEngine.popen_uci('./stockfish') engine.configure({'Threads': 4}) engine_limit = chess.engine.Limit(depth=30, time=15, nodes=12_000_000) for doc in build_coll.find({"cp": None}): try: if ord(doc["_id"][4]) % threads != thread_id: continue puzzle = read(doc) board = puzzle.game.end().board() if board.is_checkmate(): cp = 999999999 eval_nb += 1 logger.info(f'{thread_id} {eval_nb} {puzzle.id}: mate') else: info = engine.analyse(board, limit=engine_limit) score = info["score"].pov(puzzle.pov) score_cp = score.score() cp = 999999999 if score.is_mate() else ( 999999998 if score_cp is None else score_cp) eval_nb += 1 logger.info( f'{thread_id} {eval_nb} {puzzle.id}: {cp} knps: {int(info["nps"] / 1000)} kn: {int(info["nodes"] / 1000)} depth: {info["depth"]} time: {info["time"]}' ) build_coll.update_one({"_id": puzzle.id}, {"$set": { "cp": cp }}) except Exception as e: print(doc) logger.error(e)
def main(): args = parse_args() games = [] for game, g in pgn_reader(args.pgn_file): print("Game %d: %s: %s - %s" % (g['index'], g.get('Event'), g.get('White'), g.get('Black'))) basename = "%03d" % g['index'] svg_plot = f'{basename}-plot.svg' svg_board = f'{basename}-board.svg' svg_combined = f'{basename}.svg' g['ECO'], g['Opening'] = chesstoc.classify_opening(game) g['svg_plot'] = svg_plot g['svg_board'] = svg_board g['svg_combined'] = svg_combined games.append(g) chesstoc.write_board(game, svg_board) if not args.dryrun: with chess.engine.SimpleEngine.popen_uci(args.engine) as engine: engine.configure({"Threads": args.threads}) scores = chesstoc.analyze_game(game, engine, args.time_per_move) chesstoc.write_plot(scores, svg_plot) chesstoc.compose_svg(svg_board, svg_plot, svg_combined) if args.maxgames is not None and g['index'] == args.maxgames: break if args.html: write_html(games, args)
def main(): counter = positions_db.count_not_evaluated_positions() print('Number of not yet evaluated positions: {0}'.format(counter)) if not counter: print('Nothing to do, quiting.') return engine = chess.engine.SimpleEngine.popen_uci(engine_path()) engine.configure({'Threads': 6}) while True: record = positions_db.get_not_evaluated_position() if record is None: break position_id, fen = record (score, bestmove, is_bestmove_capture, is_bestmove_check, is_check) = evaluate_position(engine, fen) positions_db.update_position_evaluation( position_id, score, bestmove, is_bestmove_capture, is_bestmove_check, is_check) engine.quit()
def main(): #login_info = open('credentials.txt', 'r') logged_in = False engine = chess.engine.SimpleEngine.popen_uci("engine") book = chess.polyglot.open_reader("lichess_bot.bin") engine.configure({"UCI_Elo": "1900", "Hash": "64"}) while True: game_finished = False searching_side = True Lela = Bot() if not logged_in: #Lela.login(login_info) logged_in = True while not game_finished: if Lela.is_match_over(): game_finished = True else: if searching_side: side = Lela.find_side() if not side == 'NULL': searching_side = False if side == 'black' or side == 'white': Lela.play_move(engine, book, side)
def init(engine, options): # note: multipv not set here engine.configure({ 'Hash': options.hash, 'Syzygypath': options.syzygy, 'Threads': options.cores }) print("engine ready")
def compare_model(time, stockfish=True): if stockfish: engine = chess.engine.SimpleEngine.popen_uci( "/home/albb762/chessai/stockfish/Linux/stockfish_10_x64") engine.configure({'Skill Level': 1}) first = 0 second = 0 draw = 0 for i in range(time): print(i) flag = 'stockfish' board = chess.Board() if random.randint(0, 1): board, _ = v.play_one_step(board) battle = 'model vs stockfish:' flag = 'model' while True: if not board.is_game_over(): if stockfish: result = engine.play( board, chess.engine.Limit(time=0.00100, depth=1)) board.push(result.move) else: board.push(random.choice(list(board.legal_moves))) else: break if not board.is_game_over(): board, _ = v.play_one_step(board) else: break res = board.result() if flag == 'stockfish': if '1-0' == res: first += 1 if '0-1' == res: second += 1 if '1/2-1/2' == res: draw += 1 if flag == 'model': if '1-0' == res: second += 1 if '0-1' == res: first += 1 if '1/2-1/2' == res: draw += 1 if stockfish: print('stockfish vs model : ', first, second, draw) else: print('random vs model : ', first, second, draw) engine.quit()
def __init__(self, movetime = _movetime, depth = 30, sfPath = _stockfishPath, engine = None, name = None): #self.skill = skill self.name = name self.stockfishPath = sfPath engine = chess.engine.SimpleEngine.popen_uci([self.stockfishPath], stderr = subprocess.PIPE) engine.configure({'UCI_AnalyseMode' : 'false'}) super().__init__(engine, f'd{depth} {movetime}', movetime = movetime, depth = depth)
def engine_analyze_position(): engine = chess.engine.SimpleEngine.popen_uci( "C:\Program Files (x86)\Tarrasch\Engines\stockfish_11_x64.exe") engine.configure({"Hash": 2048, "Threads": 8}) board = chess.Board( "r1b1k1nr/p1q1ppbp/2pp2p1/2p5/4PP2/2NP1N2/PPP3PP/R1BQ1RK1 b kq - 0 8") info = engine.analyse(board, chess.engine.Limit(depth=40)) print("Score:", info["score"]) # Score: PovScore(Mate(+1), WHITE) engine.quit()
def cruncher(thread_id: int): db = pymongo.MongoClient()['puzzler'] round_coll = db['puzzle2_round'] play_coll = db['puzzle2_puzzle'] engine = SimpleEngine.popen_uci('./stockfish') engine.configure({'Threads': 2}) for doc in round_coll.aggregate([{ "$match": { "_id": { "$regex": "^lichess:" }, "t": { "$nin": ['+zugzwang', '-zugzwang'] } } }, { '$lookup': { 'from': 'puzzle2_puzzle', 'as': 'puzzle', 'localField': 'p', 'foreignField': '_id' } }, { '$unwind': '$puzzle' }, { '$replaceRoot': { 'newRoot': '$puzzle' } }]): try: if ord(doc["_id"][4]) % threads != thread_id: continue puzzle = read(doc) round_id = f'lichess:{puzzle.id}' zug = zugzwang(engine, puzzle) if zug: cook.log(puzzle) round_coll.update_one({"_id": round_id}, { "$addToSet": { "t": "+zugzwang" if zug else "-zugzwang" } }) play_coll.update_one({"_id": puzzle.id}, {"$set": { "dirty": True }}) except Exception as e: print(doc) logger.error(e) engine.close() exit(1) engine.close()
def generate_chess_demos(env, num_demos): """ Generate a number of demonstrations using stockfish. Parameters ---------- env : ChessEnv The chess env that is used for creating the demonstrations. num_demos : int The number of demonstrations to be created. Returns ------- Tuple A tuple containing the demonstrations, as an array of observations, and the rewards, an array of int showing the reward for each demonstration. """ trajectories = [] rewards = [] engine = chess.engine.SimpleEngine.popen_uci('/usr/games/stockfish') rootEnv = env.envs[0].env.env.env #who the f**k though this was a good arcitecture to make? for i in range(num_demos): traj = [] done = False skill = random.choice(range(0, 21)) if skill != 21: #random engine.configure({"Skill Level": skill}) obs = env.reset() traj.append(obs) while not done: moves = list(rootEnv.board.generate_legal_moves()) if skill == 21: move = random.choice(range(len(moves))) else: result = engine.play(rootEnv.board, limit=chess.engine.Limit(depth=1)) move = moves.index(result.move) obs, reward, done, _ = env.step(move) traj.append(obs) print(" {}:finished demo with skill level {}, Result = {}".format(i,skill, reward)) trajectories.append(traj) if skill ==21: rewards.append(reward - 5) else: rewards.append(reward + (skill*2)) return trajectories, rewards
def open_chess_engine(): path = os.getcwd() path = os.path.abspath(os.path.join(path, os.pardir)) #engine_path = path+'/stockfish/stockfish-11-linux/Linux/stockfish_20011801_x64' engine_path = '/home/mingyu/catkin_build_ws/src/ros-chess-agent/chess_ai/src/stockfish/stockfish-11-linux/Linux/stockfish_20011801_x64' engine = chess.engine.SimpleEngine.popen_uci(engine_path) extreme_setup = { 'Threads': 10, 'Hash': 5000, 'Skill Level': 20, } engine.configure(extreme_setup) return engine
def set_threads(engine, numthreads: int): """Configure the number of threads or 'cores' for the engine based on protocol.""" if numthreads <= 0 or numthreads > MAX_THREADS: logging.warn(f'Invalid demand for {numthreads} threads. Ignoring.') return if engine.protocol == chess.engine.UciProtocol: if "Threads" in engine.options: engine.configure({'Threads': numthreads}) else: logging.warn(f'Engine {engine.id["name"]} has no Threads option') elif engine.protocol == chess.engine.XBoardProtocol: if "cores" in engine.options: engine.configure({'cores': numthreads}) else: logging.warn(f'Engine {engine.id["name"]} has no cores option')
def evaluate( boardFEN, time=5000, enginename="stockfish"): #Evaluates the board state, default White #'time' determines the time engine spends thinking in milliseconds (default: 500ms = 0.5s) #'engine' determines the name of engine to be used (default: 100ms) #The higher the return value the better it is for White #The lower the return value the better it is for Black #Positive means good for White #Negative means good for Black time = time / 1000 #Calculate time in seconds board = chess.Board(boardFEN) enginefile = engine_name(enginename) if enginefile is None: #Name of the engine was undefined return False #Returns False whe error try: engine = chess.engine.SimpleEngine.popen_uci( enginefile) #Opens the engine if "stockfish" in enginefile: engine.configure({"use NNUE": True}) #Use Stockfish neural network info = engine.analyse(board, chess.engine.Limit( time=time)) #Sets the time given to engine for evaluation except: print("No engine found!") return False #Returns False when error if board.is_stalemate() or board.is_insufficient_material( ) or board.is_game_over( ): #If it is impossible for the engine to make any meaningful progress return None #Returns None because it is not possible to create any meaningful progress if (info["score"].is_mate()): #Check if engine found mate centipawn = info["score"] engine.quit() return centipawn else: #No mate found centipawn = ( info["score"].white().score()) / 100 #To get the centipawn value engine.quit() return centipawn
def generate_dataset(n_games, skill=20, threads=1): def play(engine, limit=0.01): board = chess.Board() # raw_history = [] history = [] while not board.is_game_over(): result = engine.play(board, chess.engine.Limit(time=limit)) # raw_history.append(board.copy()) history.append(to_bitboard(board, pack=True)) board.push(result.move) return history, board.result() def create_empty_games(): return {WHITE_WON: [], BLACK_WON: []} engine = chess.engine.SimpleEngine.popen_uci(engine_path, timeout=None) engine.configure({"Threads": threads, "Skill Level": skill}) games = create_empty_games() print('playing....') i = 1 while i != n_games + 1: history, result = play(engine) if result != DRAW: print(f'.....{i}/{n_games}') games[result].append((history, results[result])) if i % 1000 == 0: filename = f'dataset-{i // 1000}' date = get_date() save(games[WHITE_WON], f'{filename}-white-{len(games[WHITE_WON])}-{date}') save(games[BLACK_WON], f'{filename}-black-{len(games[BLACK_WON])}-{date}') games = create_empty_games() i += 1 engine.quit()
def On_Level(event=None): global close_enabled ''' The Level button (or L key) has been pressed. Ask the user to set the engine skill level (if that option is available). ''' if 'Skill Level' in eo: min_lv = eo['Skill Level'].min max_lv = eo['Skill Level'].max mess = 'Set Skill Level (' + str(min_lv) + '-' + \ str(max_lv) + ')' close_enabled = False level = simpledialog.askinteger(TITLE, mess,\ minvalue=min_lv,\ maxvalue = max_lv) close_enabled = True if level: print('Skill level', level) mess_label.configure(text='Skill Level ' + str(level)) engine.configure({'Skill Level': level}) next_button.focus_set()
def evaluate_random_moves(self): engine = chess.engine.SimpleEngine.popen_uci(self.stockfish_exe) engine.configure({"Threads": 1, "Hash": 64}) new_position_dict = {} new_positions = 0 for i, position in enumerate(self.score_dict): # print(position) score = self.score_dict[position] if abs(score) <= self.score_threshold: board = chess.Board(position) moves = [b for b in board.generate_legal_moves()] if len(moves) < self.expansion_factor: moves = random.sample(moves, k=len(moves)) else: moves = random.sample(moves, k=self.expansion_factor) # original_eval = engine.analyse(board, chess.engine.Limit(time=0.300)).score.white().score(mate_score=50000) for move in moves: board.push(move) if board.fen() in self.score_dict or board.fen( ) in new_position_dict: board.pop() continue evaluation = engine.analyse(board, chess.engine.Limit(time=0.300)) new_position_dict[board.fen()] = evaluation.score.white( ).score(mate_score=50000) new_positions += 1 board.pop() # print('From: {} To: {}'.format(score, evaluation.score.white().score(mate_score=50000))) if new_positions % self.export_period == 0 and new_positions > 0: print('Exporting with length: ' + str(len(new_position_dict))) self.export_hash_table(new_position_dict) print('Exporting with length: ' + str(len(new_position_dict))) self.export_hash_table(new_position_dict)
def main(): engine = chess.engine.SimpleEngine.popen_uci(ENG_PATH) if "Threads" in engine.options: engine.configure({"Threads": THREADS}) with open(OUT_PATH, "wb") as file: positions = 0 while True: try: board = randpos() result = engine.analyse(board, chess.engine.Limit(depth=DEPTH)) append_result(file, board, result) file.flush() positions += 1 log(f"Analyzed {positions} positions.") except KeyboardInterrupt: file.flush() print("Terminated") break engine.quit()
def run_test(eng, wt, f, mem, threads): engine = chess.engine.SimpleEngine.popen_uci("../igel") engine.configure({"Threads": threads}) engine.configure({"Hash": mem}) file = open(f, 'r') epds = file.read() score = 0.0 total = 0 for epd in epds.split("\n"): sys.stdout.flush() if len(epd): total = total + 1 score += test_epd(engine, epd, wt) sys.stdout.flush() engine.quit() print ("%g / %g" % (score, total)) sys.stdout.flush() return score
def main(): random.seed(0) model_path = 'models/axia_15_626000.pt' player = Player(model_path) engine = chess.engine.SimpleEngine.popen_uci( 'stockfish/Mac/stockfish-10-64') all_results = [] for i in range(0, 21, 3): print('Level: ', i) engine.configure({'Skill Level': i}) # white = random.randint(0, 1) white = 1 board = chess.Board() results = [] for _ in range(10): while not board.is_game_over(): # print(board) if (board.turn + white) % 2 == 0: move = player.play(board, white) board.push(move) # print('Our move:', move, white) else: result = engine.play(board, chess.engine.Limit(time=0.0100)) board.push(result.move) # print('Stockfish move:', result.move, white) white += 1 print(board.result()) results.append(board.result()) all_results.append(results) print(results)
def evaluate(thr, mvt, mate, fen): # setup engine engine = chess.engine.SimpleEngine.popen_uci("../igel") engine.configure({"Threads": thr}) # setup board board = chess.Board(fen) engine_move_time = engine_def_move_time if mvt != None: engine_move_time = mvt # run engine start_time = timeit.default_timer() info = engine.analyse(board, chess.engine.Limit(time=engine_move_time)) elapsed = timeit.default_timer() - start_time elapsed = elapsed * 1000 print(fen) print(board) print(info) print("search time: %d ms" % elapsed) if elapsed > ((1000 * engine_move_time) + 200): engine.quit() raise Exception("exceeded a go time", elapsed) expected_mate = "#" if mate > 0: expected_mate += "+" expected_mate += str(mate) obtained_mate = str(info["score"]) if expected_mate != obtained_mate: raise Exception(expected_mate, obtained_mate) engine.quit() bestmove = info["pv"] return board.san(bestmove[0])
def simulate(): starting_moves = [["e2e4", "e7e5"], ["e2e4", "c7c5"], ["d2d4", "g8f6"], ["d2d4", "d7d5"], ["g1f3"], ["c2c4"], ["f2f3"]] depths = [20] setup_output(output_root, depths, starting_moves) # logging.basicConfig(level=logging.DEBUG) engine = chess.engine.SimpleEngine.popen_uci( "D:/Users/frozen/Documents/99_temp/stockfish_12/stockfish.exe") engine.configure({"Threads": 6}) engine.configure({"Hash": 4096}) engine.configure({ "SyzygyPath": "D:/Users/frozen/Documents/03_programming/online/stockfish/syzygy" }) with open(f"{output_root}/log.txt", "w") as log: with open(f"{output_root}/summary.txt", "w") as summary: for d in depths: for s_moves in starting_moves: play(engine, s_moves, use_opening_book=True, matches=2, depth=d, log_file=log, summary_file=summary) play(engine, s_moves, use_opening_book=False, matches=2, depth=d, log_file=log, summary_file=summary) print("") log.write("\n") summary.write("\n") engine.quit()
def main(): key = '8/8/8/8/6b1/8/5k2/5n1K b - - 0 1' val = ['g4f4'] policy, mcts = get_lc0_move(key,val) myfile = open('moves.csv', 'w') wr = csv.writer(myfile, delimiter = ',') wr.writerow(['key','policy','mcts']) wr.writerow([key,policy,mcts]) print("done") if __name__ == '__main__': engine = chess.engine.SimpleEngine.popen_uci("/lc0/build/release/lc0") engine.configure({"backend": 'blas',"WeightsFile":'/weights/weights_run1_10970.pb'}) main() engine.quit() ''' with open('output.csv', mode='r') as infile: reader = csv.reader(infile) best_moves = {rows[0]:rows[1] for rows in reader}
def computer_move(skill_level): print('computer_move') skill_level = int(skill_level) engine.configure({"Skill Level": skill_level}) result = engine.play(board, chess.engine.Limit(time=0.1)) return result.move.uci()
def prepare_data(): engine = chess.engine.SimpleEngine.popen_uci( "../stockfish/stockfish_20011801_x64_bmi2") engine.configure({"Threads": 4, 'Contempt': 0}) blunders_counter = {tc: {} for tc in time_controls} all_moves_counter = {tc: {} for tc in time_controls} current_tc_ix = 0 current_rating_band_ix = 0 num_games_studied = 0 for game in games_iterator(): if game.headers['TimeControl'] != time_controls[current_tc_ix]: continue board = game.board() moves = list(game.mainline_moves()) if len(moves) < 5: continue move_ix = randint(2, len(moves) - 1) for curr_move_ix, move in enumerate(moves): if curr_move_ix + 1 < move_ix: board.push(move) continue info = engine.analyse(board, chess.engine.Limit(time=2)) theoretical_score = info['score'] theoretical_move = info['pv'][0] elo = int(game.headers['WhiteElo']) if theoretical_score.turn == chess.BLACK: elo = int(game.headers['BlackElo']) for move_rating_band_ix, band in enumerate(rating_bands): if band[0] <= elo <= band[1]: break if move_rating_band_ix not in all_moves_counter[ game.headers['TimeControl']]: all_moves_counter[ game.headers['TimeControl']][move_rating_band_ix] = 0 all_moves_counter[ game.headers['TimeControl']][move_rating_band_ix] += 1 board.push(move) if move == theoretical_move: # player did the best move, this can't be blunder break info = engine.analyse(board, chess.engine.Limit(time=2)) actual_score = chess.engine.PovScore(-info['score'].relative, theoretical_score.turn) if theoretical_score.relative.score( ) is not None and actual_score.relative.score() is not None: if theoretical_score.relative.score( ) - actual_score.relative.score() > 200: if move_rating_band_ix not in blunders_counter[ game.headers['TimeControl']]: blunders_counter[game.headers['TimeControl']][ move_rating_band_ix] = 0 blunders_counter[ game.headers['TimeControl']][move_rating_band_ix] += 1 break num_games_studied += 1 current_tc_ix += 1 current_tc_ix = current_tc_ix % len(time_controls) print(num_games_studied) print(blunders_counter) print(all_moves_counter) engine.quit() return blunders_counter, all_moves_counter
def main(): parser = argparse.ArgumentParser( prog='Chess Chiller {}'.format(__version__), description='Generates interesting positions using an engine and ' + 'some user defined score thresholds', epilog='%(prog)s') parser.add_argument('-i', '--inpgn', help='input pgn file', required=True) parser.add_argument('-o', '--outepd', help='output epd file, (default=interesting.epd)', default='interesting.epd', required=False) parser.add_argument('-e', '--engine', help='engine file or path', required=True) parser.add_argument('-t', '--threads', help='engine threads (default=1)', default=1, type=int, required=False) parser.add_argument('-a', '--hash', help='engine hash in MB (default=128)', default=128, type=int, required=False) parser.add_argument('-w', '--weight', help='weight file for NN engine like Lc0', required=False) parser.add_argument('-n', '--mintime', help='analysis minimum time in sec (default=5.0)', default=5.0, type=float, required=False) parser.add_argument('-x', '--maxtime', help='analysis maximum time in sec (default=15.0)', default=15.0, type=float, required=False) parser.add_argument('--skipdraw', help='a flag to skip games with draw results', action='store_true') parser.add_argument( '--log', help= 'values can be debug, info, warning, error and critical (default=critical)', default='critical', required=False) parser.add_argument('--pin', help='a flag when enabled will only save interesting' + 'position if not stm piece is pinned', action='store_true') parser.add_argument('--positional', help='a flag to save positional positions', action='store_true') parser.add_argument( '--minpiecevalue', help='minimum piece value on the board, N=B=3, R=5, Q=9, (default=0)', default=0, type=int, required=False) parser.add_argument( '--maxpiecevalue', help='maximum piece value on the board, N=B=3, R=5, Q=9, (default=62)', default=62, type=int, required=False) parser.add_argument('--minbs1th1', help='minimum best score 1 threshold 1 (default=2000)', default=2000, type=int, required=False) parser.add_argument('--minbs1th2', help='minimum best score 1 threshold 2 (default=1000)', default=1000, type=int, required=False) parser.add_argument('--minbs1th3', help='minimum best score 1 threshold 3 (default=500)', default=500, type=int, required=False) parser.add_argument('--maxbs2th1', help='maximum best score 2 threshold 1 (default=300)', default=300, type=int, required=False) parser.add_argument('--maxbs2th2', help='maximum best score 2 threshold 2 (default=200)', default=200, type=int, required=False) parser.add_argument('--maxbs2th3', help='maximum best score 3 threshold 3 (default=100)', default=100, type=int, required=False) parser.add_argument('--analysis-start-move', help='move number to start the analysis (default=16)', default=16, type=int, required=False) parser.add_argument( '--disable-complexity', help= 'a flag to exclude complexity as a criteria in saving the position', action='store_true') parser.add_argument( '--save-last-move', help='a flag to save the last move before the blunder move in a game.', action='store_true') args = parser.parse_args() pgnfn = args.inpgn outepdfn = args.outepd thread_val = args.threads hash_val = args.hash enginefn = args.engine weightsfile = args.weight mintime = args.mintime maxtime = args.maxtime skipdraw = args.skipdraw pin = args.pin positional = args.positional minpiecevalue = args.minpiecevalue maxpiecevalue = args.maxpiecevalue disable_complexity = args.disable_complexity # Define logging levels if args.log == 'debug': # logging.DEBUG includes engine logs initialize_logger(logging.DEBUG) elif args.log == 'info': initialize_logger(logging.INFO) elif args.log == 'warning': initialize_logger(logging.WARNING) elif args.log == 'error': initialize_logger(logging.ERROR) else: initialize_logger(logging.CRITICAL) start_move = args.analysis_start_move dullfn = 'dull.epd' # Save uninteresting positions in this file outpgnfn = 'interesting.pgn' # Adjust score thresholds to save interesting positions # (1) Positional score threshold, if flag --positional is set if positional: minbs1th1 = 100 # min bs1 (best score 1) threshold 1 in cp (centipawn) minbs1th2 = 50 minbs1th3 = 0 maxbs2th1 = 50 # max bs2 (best score 2) threshold 1 maxbs2th2 = 0 maxbs2th3 = -50 # (2) Other score thresholds else: minbs1th1 = args.minbs1th1 minbs1th2 = args.minbs1th2 minbs1th3 = args.minbs1th3 maxbs2th1 = args.maxbs2th1 maxbs2th2 = args.maxbs2th2 maxbs2th3 = args.maxbs2th3 # Calculate minimum score diff check, while engine is seaching we exit # early if minscorediffcheck is not satisfied. scoredifflist = [] scoredifflist.append(minbs1th1 - maxbs2th1) scoredifflist.append(minbs1th2 - maxbs2th2) scoredifflist.append(minbs1th3 - maxbs2th3) minscorediffcheck = min(scoredifflist) / 2 logging.info('pgn file: {}'.format(pgnfn)) logging.info('Conditions:') logging.info('mininum time : {}s'.format(mintime)) logging.info('maximum time : {}s'.format(maxtime)) logging.info('mininum score diff check : {}'.format(minscorediffcheck)) logging.info('mininum best score 1 th 1 : {}'.format(minbs1th1)) logging.info('mininum best score 1 th 2 : {}'.format(minbs1th2)) logging.info('mininum best score 1 th 3 : {}'.format(minbs1th3)) logging.info('maximum best score 2 th 1 : {}'.format(maxbs2th1)) logging.info('maximum best score 2 th 2 : {}'.format(maxbs2th2)) logging.info('maximum best score 2 th 3 : {}'.format(maxbs2th3)) logging.info('stm is not in check : {}'.format('Yes')) logging.info('stop analysis move number : {}'.format(start_move)) logging.info(f'disable complexity : {disable_complexity}') # Define analyzing engine engine = chess.engine.SimpleEngine.popen_uci(enginefn) engname = engine.id['name'] # Set Lc0 SmartPruningFactor to 0 to avoid analysis time pruning if 'lc0' in engname.lower(): try: engine.configure({"SmartPruningFactor": 0}) except: pass else: try: engine.configure({"Hash": hash_val}) except: pass try: engine.configure({"Threads": thread_val}) except: pass # For NN engine that uses uci option WeightsFile similar to Lc0 if weightsfile is not None: try: engine.configure({"WeightsFile": weightsfile}) except: pass # Read pgn file and analyze positions in the game gcnt = 0 with open(pgnfn, 'r') as pgn: game = chess.pgn.read_game(pgn) while game: gcnt += 1 analyze_game(game, engine, enginefn, hash_val, thread_val, start_move, outepdfn, gcnt, engname, dullfn, outpgnfn, mintime=mintime, maxtime=maxtime, minscorediffcheck=minscorediffcheck, minbs1th1=minbs1th1, minbs1th2=minbs1th2, minbs1th3=minbs1th3, maxbs2th1=maxbs2th1, maxbs2th2=maxbs2th2, maxbs2th3=maxbs2th3, weightsfile=weightsfile, skipdraw=skipdraw, pin=pin, positional=positional, minpiecevalue=minpiecevalue, maxpiecevalue=maxpiecevalue, disable_complexity=args.disable_complexity, save_last_move=args.save_last_move) # Analyze another game game = chess.pgn.read_game(pgn) engine.quit()
def make_engine(executable: str, threads: int) -> SimpleEngine: engine = SimpleEngine.popen_uci(executable) engine.configure({'Threads': threads}) return engine
import numpy as np import time import os import csv #number of threads n_threads = 8 depth = 18 gamma = 1 mate_score = 10000 multipv = 10 board = chess.Board() engine = chess.engine.SimpleEngine.popen_uci( "../engine/stockfish_10_x64_modern") engine.configure(options={'Threads': n_threads}) game_id = 0 explored = {} path = "data/depth%d_gamma%d/" % (depth, gamma) os.makedirs(path, exist_ok=True) with open(path + "moves.csv", "r") as f: r = csv.reader(f) for fen, _ in r: explored[fen] = True writer = csv.writer(open(path + "moves.csv", "a")) while True: