#!/usr/bin/env python try: from sgfpars import Node, Cursor, SGFError, SGFescape except: from sgfparser import Node, Cursor, SGFError, SGFescape import os, sys, getopt, re def writeheader(outfile, rootnode): global boardsize if (rootnode.has_key('PW')): outfile.write("# White: " + rootnode['PW'][0]+"\n") if (rootnode.has_key('PB')): outfile.write("# Black: " + rootnode['PB'][0]+"\n") if (rootnode.has_key('HA')): outfile.write("# Handicap: " + rootnode['HA'][0]+"\n") if (rootnode.has_key('RE')): outfile.write("# Result: " + rootnode['RE'][0]+"\n") for el in ['DT', 'EV', 'RO']: if (rootnode.has_key(el)): outfile.write("# " + rootnode[el][0]+"\n") outfile.write("\n") if (rootnode.has_key('SZ')): try: boardsize = int(rootnode['SZ'][0]) except TypeError: print "SGF trouble: Don't understand board size." sys.exit(2) outfile.write("boardsize %d\n" % boardsize) outfile.write("clear_board\n") if (rootnode.has_key('KM')): outfile.write("komi " + rootnode['KM'][0]+"\n") outfile.write(""" reset_connection_node_counter reset_owl_node_counter reset_reading_node_counter reset_trymove_counter """ ) def sgfpos2gtp(pos): if len(pos) == 0 or pos == 'tt': return "PASS" elif len(pos) != 2: raise SGFError("Couldn't parse coordinate.") x, y = ord(pos[0])-ord('a'), ord(pos[1])-ord('a') if (x < 8): I = chr(ord('A') + x) else: I = chr(ord('A') + x + 1) J = "%d" % (boardsize - y) return I+J def writegame(outfile, cursor, color): nodenum = 0 while nodenum < to and not cursor.atEnd: try: thisnode = cursor.next() except SGFError: break if thisnode.has_key('AB'): for pos in thisnode['AB']: outfile.write("play black %s\n" \ % sgfpos2gtp(pos)) if thisnode.has_key('AW'): for pos in thisnode['AW']: outfile.write("play white %s\n" \ % sgfpos2gtp(pos)) if thisnode.has_key('B'): thiscolor = 'black' thispos = sgfpos2gtp(thisnode['B'][0]) elif thisnode.has_key('W'): thiscolor = 'white' thispos = sgfpos2gtp(thisnode['W'][0]) else: continue nodenum = nodenum + 1 if (color == thiscolor and nodenum > start): outfile.write("%d reg_genmove %s\n" % (nodenum, thiscolor)) outfile.write("play %s %s\n" % (thiscolor, thispos)) def writefooter(outfile): outfile.write(""" 10000 get_reading_node_counter 10001 get_owl_node_counter 10002 get_connection_node_counter 10003 get_trymove_counter """ ) # Main Program. ############### help_string = """ sgf2gtp.py converts .sgf-files to .gtp files to let a GTP engine replay parts of the games via reg_genmove. Usage: sgf2gtp.py [--start ] [--to ] --color creates .gtp-files that let the engine replay all games from the viewpoint of the given color, starting and ending at the given move numbers. sgf2gtp.py --auto [--auto-max ] rotates the start and end move numbers so that * the given number of moves is played per game, * no move beyond the given maximal move number is considered (default 300) * and chooses the color automatically by parsing the PW[] and PB[] properties, trying to determine which color GNU Go played originally. """ color = [] start = 0 to = 100000 boardsize = 19 auto = 0 maxauto = 300 try: opts, args = getopt.getopt(sys.argv[1:], "", ["help", "start=", "to=", "color=", "auto=", "auto-max="]) except getopt.GetoptError: print "Unrecognized option. Try sgf2gtp.py --help" sys.exit(2) for o, a in opts: if (o == "--help"): print help_string sys.exit() if (o == "--color"): if (a == "black"): color = "black" elif (a == "white"): color = "white" else: print "Unrecognized color %s." % a sys.exit(2) if (o == "--start"): try: start = int(a) except TypeError: print "Cannot convert", a, "into a number." sys.exit(2) if (o == "--to"): try: to = int(a) except TypeError: print "Cannot convert", a, "into a number." sys.exit(2) if (o == "--auto"): try: auto = int(a) except TypeError: print "Must specifiy number with --auto." sys.exit(2) # This should match all common speelings of "GNU Go": gnugo_re = re.compile("gnu *go", re.IGNORECASE) if (o == "--auto-max"): try: maxauto = int(a) except TypeError: print "Must specifiy number with --auto-max." sys.exit(2) if len(args) == 0: print "No file specified. Nothing to do." sys.exit() fileno = 0 for filename in args: try: file = open(filename) sgf = file.read() file.close() cursor = Cursor(sgf) rootnode = cursor.getRootNode(0) except IOError: print "Couldn't read file %s." % filename sys.exit(2) except SGFError, message: print "Couldn't parse SGF in file %s: %s" % (filename, message) sys.exit(2) if (filename.endswith(".sgf")): outfilename = filename[:-4] + ".gtp" else: outfilename = filename + ".gtp" outfile = open(outfilename, 'w') if auto: start = fileno * 2 * auto % maxauto to = start + 2 * auto if rootnode.has_key('PB') \ and gnugo_re.match(rootnode['PB'][0]): color = "black" elif rootnode.has_key('PW') \ and gnugo_re.match(rootnode['PW'][0]): color = "white" else: print "Cannot decide which color GNU Go played in game", print filename sys.exit(2) writeheader(outfile, rootnode) writegame(outfile, cursor, color) writefooter(outfile) outfile.close() fileno = fileno + 1