def open_file( self, infilename): # expects that there is already a valid self.node try: unlink_target = self.node.get_root_node() self.node = gofish.load(infilename) unlink_target.unlink_recursive( ) # remove the old tree's circular references, so GC can work try: print("<--- Loaded: {}".format(infilename)) except: print( "<--- Loaded: --- Exception when trying to print filename ---" ) print(" Dyer: {}\n".format(self.node.dyer())) self.node.dump(include_comments=False) print() self.directory = os.path.dirname(os.path.realpath(infilename)) except FileNotFoundError: print("error while loading: file not found") except gofish.BadBoardSize: print("error while loading: SZ (board size) was not in range 1:19") except gofish.ParserFail: print("error while loading: parser failed (invalid SGF?)")
def main(): global process global config if len(sys.argv) == 1: print("Usage: {} <filename>".format(sys.argv[0])) sys.exit() root = gofish.load(sys.argv[1]) # Find and load the config file... scriptpath = os.path.realpath(__file__) configfile = os.path.join(os.path.dirname(scriptpath), "config.json") with open(configfile) as cfg: config = json.load(cfg) # Start the engine... cmd = "\"{}\" -v {} {} -w \"{}\"".format( config["engine"], config["visits"], extras, os.path.join(config["network_dir"], config["network"])) process = subprocess.Popen( cmd, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) # Start a thread to watch stderr and put its output on a queue... # This allows us to search recent stderr messages without blocking. threading.Thread(target=stderr_watcher, daemon=True).start() save_time = time.monotonic() # Make a list of Info objects... all_info = [] node = root while 1: # Totally ignore empty nodes. Everything else gets put in the list... if "B" in node.properties or "W" in node.properties or "AB" in node.properties or "AW" in node.properties: new_info = Info(node) if len(all_info) > 0: new_info.parent = all_info[ -1] # Might not correspond to the node's actual parent node (due to empty nodes) if node.move_colour(): new_info.colour = { gofish.BLACK: "black", gofish.WHITE: "white" }[node.move_colour()] all_info.append(new_info) node = node.main_child() if node == None: break # Main loop... for info in all_info: # Send any handicap stones etc... info.send_AB_AW() # At this moment, the engine's idea of the board matches this node BEFORE the node's move. # We can thus get the score_before_move... if info.colour: info.best_move, info.score_before_move, info.PV = analyse( info.colour, info.node.board.boardsize) if info.parent: info.parent.score_after_move = info.score_before_move info.send_move() # The previous Info now has all the info it's getting... if info.parent: info.parent.node_markup() # Save often... if time.monotonic() - save_time > 10: root.save(sys.argv[1] + ".lza.sgf") save_time = time.monotonic() # Display... if config["showboard"]: info.node.board.dump(highlight=info.node.move_coords()) print() # The final node needs its score_after_move before it can be marked up... colour = "white" if info.colour == "black" else "black" _, info.score_after_move, _ = analyse(colour, info.node.board.boardsize) info.node_markup() # Final save... root.save(sys.argv[1] + ".lza.sgf")
#!/usr/bin/env python3 # This script extracts a winrate graph from an lza.py-produced SGF file. import sys, time import gofish import matplotlib.pyplot as plt node = gofish.load(sys.argv[1]) winrates = [] while 1: val = node.get_value("SBKV") try: winrates.append(float(val)) except: winrates.append(None) node = node.main_child() if node == None: break if len(winrates) < 2: print(s) time.sleep(0.5) sys.exit() plt.style.use("dark_background") _, ax = plt.subplots() ax.spines["right"].set_visible(False) ax.spines["top"].set_visible(False)
def main(): root = gofish.load(sys.argv[1]) record = Record(root) record.print()
def main(): global config if len(sys.argv) == 1: print("Usage: {} <filename>".format(sys.argv[0])) sys.exit() scriptpath = os.path.realpath(__file__) configfile = os.path.join(os.path.dirname(scriptpath), "config.json") with open(configfile) as cfg: config = json.load(cfg) cmd = [config["engine"]] + config["extras"] + ["-w", os.path.join(config["network_dir"], config["network"])] print("Starting Leela Zero...") print(cmd) conn = Connection(cmd) conn.send_and_receive("name") # Ensure we can communicate. print("Working.") root = gofish.load(sys.argv[1]) root.set_value("AP", "github.com/fohristiwhirl/leela_zero_analysis") # Make a list of Info objects... all_info = [] node = root while 1: # Totally ignore empty nodes (except root). Everything else gets put in the list... if node is root or "B" in node.properties or "W" in node.properties or "AB" in node.properties or "AW" in node.properties: new_info = Info(node) if len(all_info) > 0: new_info.parent = all_info[-1] # Might not correspond to the node's actual parent node (due to empty nodes) if node.move_colour(): new_info.colour = {gofish.BLACK: "b", gofish.WHITE: "w"}[node.move_colour()] all_info.append(new_info) node = node.main_child() if node == None: break # Main loop... save_time = time.monotonic() progress = Progress(len(all_info)) progress.update(0) for n, info in enumerate(all_info): info.send_AB_AW(conn) if not info.node.get_value("SBKV"): info.analyze(conn) # Note: analysis for the node is done before the node's move (B or W tag) is sent. if info.parent: info.parent.score_after_move = info.score_before_move info.send_move(conn) if info.parent: info.parent.node_markup() if time.monotonic() - save_time > 10: root.save(sys.argv[1] + ".lza.sgf") save_time = time.monotonic() progress.update(n) # The final node needs its score_after_move before it can be marked up... colour = "w" if info.colour == "b" else "b" _, info.score_after_move, _, _ = conn.get_lz_analysis(colour, info.node.board.boardsize) info.node_markup() # Save and finish. root.save(sys.argv[1] + ".lza.sgf") progress.finish()