def board_step(move_uci: str): """ Updates board and cursor to step by given UCI """ global cursor print('Stepping from:') print(cursor) found = False for reply in cursor['theory'] + cursor['moves']: if reply['uci'] == move_uci: old_cursor = cursor.copy() cursor = database.find_cursor(reply['leads_to']) if cursor is None or \ 'score' not in cursor or \ cursor['score'] is None: print('The move is known, but not evaluated') database.analyse_position(old_cursor, b, [chess.Move.from_uci(move_uci)]) cursor = database.find_cursor(reply['leads_to']) b.push_uci(reply['uci']) found = True break if not found: print('Want to analyse this new move,', move_uci) database.analyse_position(cursor, b, [chess.Move.from_uci(move_uci)]) b.push_uci(move_uci) cursor = database.find_cursor(b.fen())
def crawl_troubleshoot_scoring(adjust=False): """ Will report on inconsistencies, might correct obvious errors """ b = chess.Board() cursor = database.find_cursor(b.fen()) def rec_crawler(): """ Walks and looks for oddities """ nonlocal cursor if not cursor: return if cursor['score'] is None: return for move in cursor['theory'] + cursor['moves']: if move['score_diff'] is not None: future = db.boards.find_one({'_id': move['leads_to']}) if future: if future['score'] is None: if not adjust: print('Found a board lacking score') print(cursor) print('and problem is below:') print(future) if adjust and cursor['score'] is not None: print('Fixing a board lacking score!') fix_score = -(cursor['score'] + move['score_diff']) db.boards.update_one( {'_id': future['_id']}, {'$set': {'score': fix_score}}) safe = cursor.copy() cursor = db.boards.find_one({'_id': move['leads_to']}) rec_crawler() cursor = safe rec_crawler()
def get_empty_board(is_white: bool) -> chess.Board: """ Return a starting SVG board """ global b, cursor b = chess.Board() cursor = database.find_cursor(b.fen()) print('Empty board setting') return chess.svg.board(board=b, flipped=not is_white)
def swap_move(do_reject: bool) -> Dict: """ Pops a move, unlinks it if signal is given, then pushes another move """ global cursor recent_move = b.pop() cursor = database.find_cursor(b.fen()) if do_reject: game_unlink_move(recent_move.uci()) return push_practise_move([recent_move.uci()])
def rec_crawler(depth): """ Recursive evaluating function """ nonlocal cursor if not cursor: # Done! return # Those that shall be recursed into target_moves = cursor['theory'] + cursor['moves'] if depth < len(uci_moves): target_moves = [tm for tm in target_moves if tm['uci'] == uci_moves[depth]] # Those that shall be analysed root_moves = [chess.Move.from_uci(tm['uci']) for tm in target_moves if tm['score_diff'] is None] if root_moves: database.analyse_position(cursor, b, root_moves) for move_obj in target_moves: b.push_uci(move_obj['uci']) cursor = database.find_cursor(b.fen()) rec_crawler(depth+1) b.pop() cursor = database.find_cursor(b.fen())
def load_favorite_by_name(name: str, ret_dict: Dict): """ Resets board and steps through a favorite move stack, Populates ret_dict. Returns success boolean. """ global cursor favorite_object = database.find_favorite(name) if not favorite_object: return False while b.move_stack: b.pop() cursor = database.find_cursor(b.fen()) # Reset board cursor ret_dict['moves'] = [] for move_uci in favorite_object['uci_stack']: ret_dict['moves'].append(game_move(move_uci)) print('Loaded', ret_dict) return True
def crawl_evaluate(uci_moves=None): """ Recursive evaluator """ global engine try: engine.options except chess.engine.EngineTerminatedError: print('Restarting engine') engine = chess.engine.SimpleEngine.popen_uci('/usr/bin/stockfish') b = chess.Board() cursor = database.find_cursor(b.fen()) database.set_position_score(cursor['_id'], 0) cursor = database.refresh_cursor(cursor) if not uci_moves: uci_moves = [] def rec_crawler(depth): """ Recursive evaluating function """ nonlocal cursor if not cursor: # Done! return # Those that shall be recursed into target_moves = cursor['theory'] + cursor['moves'] if depth < len(uci_moves): target_moves = [tm for tm in target_moves if tm['uci'] == uci_moves[depth]] # Those that shall be analysed root_moves = [chess.Move.from_uci(tm['uci']) for tm in target_moves if tm['score_diff'] is None] if root_moves: database.analyse_position(cursor, b, root_moves) for move_obj in target_moves: b.push_uci(move_obj['uci']) cursor = database.find_cursor(b.fen()) rec_crawler(depth+1) b.pop() cursor = database.find_cursor(b.fen()) rec_crawler(0)
def step_back(): """ Pops the Board stack and updates cursor """ global cursor b.pop() cursor = database.find_cursor(b.fen())
and uses Stockfish to analyze legal moves' scores. """ from typing import List, Dict import random import chess import chess.engine import chess.polyglot import chess.svg from chess import Board import backend.database as database engine = chess.engine.SimpleEngine.popen_uci('/usr/bin/stockfish') b: Board = Board() cursor = database.find_cursor(b.fen()) def board_step(move_uci: str): """ Updates board and cursor to step by given UCI """ global cursor print('Stepping from:') print(cursor) found = False for reply in cursor['theory'] + cursor['moves']: if reply['uci'] == move_uci: old_cursor = cursor.copy() cursor = database.find_cursor(reply['leads_to']) if cursor is None or \ 'score' not in cursor or \ cursor['score'] is None: