Exemple #1
0
 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)
Exemple #2
0
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)
Exemple #3
0
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))
Exemple #4
0
 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)
Exemple #5
0
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()
Exemple #7
0
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)
Exemple #8
0
def init(engine, options):
    # note: multipv not set here
    engine.configure({
        'Hash': options.hash,
        'Syzygypath': options.syzygy,
        'Threads': options.cores
    })
    print("engine ready")
Exemple #9
0
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()
Exemple #10
0
    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()
Exemple #12
0
 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
Exemple #15
0
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
Exemple #17
0
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()
Exemple #18
0
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()
Exemple #21
0
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
Exemple #22
0
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)
Exemple #23
0
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])
Exemple #24
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()
Exemple #25
0
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}

Exemple #26
0
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()
Exemple #27
0
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()
Exemple #29
0
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: