#!/usr/bin/env python3 import sys import sgf import string import random from random import randint import os class Board: board = {} xs = 0 xe = 19 ys = 0 ye = 19 to_play = "B" finished = False last_move = "" def to_move(self): if self.to_play == "B": return "\u25ef" return "\u2b24" def board_symbol(self, x, y): if x+y == self.last_move: pre = "" else: pre = "" if x+y in self.board: if self.board[x+y] == "W": if x=="a": return " "+pre+"\u2b24 " else: return "─"+pre+"\u2b24 " if self.board[x+y] == "B": if x=="a": return " "+pre+"\u25ef " else: return "─"+pre+"\u25ef " if (y=="d") or (y=="p") or (y=="j"): if (x=="d") or (x=="p") or (x=="j"): return "─*─" if (x=="a"): if (y=="s"): return " └─" if (y=="a"): return " ┌─" return " ├─" if (x=="s"): if (y=="s"): return "─┘ " if (y=="a"): return "─┐ " return "─┤ " if (y=="s"): return "─┴─" if (y=="a"): return "─┬─" return "─┼─" def l2n(self,l): return str(string.ascii_lowercase[0:19].index(l)+1) def n2l(self,n): return string.ascii_lowercase[n-1] def check_liberties(self,x,y,c,checked): k = self.n2l(x)+self.n2l(y) if k in checked: return 0 checked.append(k) if not k in self.board: return 1 if self.board[k] == c: return self.liberties(x, y, c, checked) return 0 def liberties(self,x,y,c,checked): lib = 0 if x > 1: lib += self.check_liberties(x-1, y, c, checked) if y > 1: lib += self.check_liberties(x, y-1, c, checked) if x < 19: lib += self.check_liberties(x+1, y, c, checked) if y < 19: lib += self.check_liberties(x, y+1, c, checked) return lib def process_captures(self,c): captured = [] for x in range(1,20): for y in range(1,20): k = self.n2l(x)+self.n2l(y) if not k in self.board: continue if self.board[k] == c: if self.liberties(x,y,c,[]) == 0: captured.append(k) for capture in captured: del self.board[capture] def add_node(self,node): for key in node.properties.keys(): val = node.properties[key] if key == "AB": for pos in val: self.board[pos] = "B" if key == "AW": for pos in val: self.board[pos] = "W" if key == "B": for pos in val: self.board[pos] = "B" self.process_captures("W") self.to_play = "W" self.last_move = pos if key == "W": for pos in val: self.board[pos] = "W" self.process_captures("B") self.to_play = "B" self.last_move = pos if key == "PL": if val[0] == "1" or val[0] == "b" or val[0] == "B": self.to_play = "B" if val[0] == "2" or val[0] == "w" or val[0] == "W": self.to_play = "W" if key == "C": print("---> "+val[0]) if key == "DI": print("Level "+val[0]) def is_move(self,node): for key in node.properties.keys(): val = node.properties[key] if key == "B" or key == "W": return True return False def add_next(self,nmoves): nm = 0 while 1: # Decide which node comes next if not self.current_node.variations: n = self.current_node.next if not self.current_node.next: self.finished = True else: i = randint(0,len(self.current_node.variations)-1) n = self.current_node.variations[i] if self.finished: print("Finished!") return if self.is_move(n): if nm == nmoves: return nm += 1 self.add_node(n) self.current_node = n def __init__(self,root): self.current_node = root self.add_node(root) def set_node(self,root): self.current_node = root self.add_node(root) def fit_board(self): self.ys = 0 self.ye = 19 self.xs = 0 self.xe = 19 for y in string.ascii_lowercase[0:18]: blank = 1 for x in string.ascii_lowercase[0:18]: if x+y in self.board: blank = 0 break if not blank: break self.ys += 1 for y in string.ascii_lowercase[18:0:-1]: blank = 1 for x in string.ascii_lowercase[0:18]: if x+y in self.board: blank = 0 break if not blank: break self.ye -= 1 for x in string.ascii_lowercase[0:18]: blank = 1 for y in string.ascii_lowercase[0:18]: if x+y in self.board: blank = 0 break if not blank: break self.xs += 1 for x in string.ascii_lowercase[18:0:-1]: blank = 1 for y in string.ascii_lowercase[0:18]: if x+y in self.board: blank = 0 break if not blank: break self.xe -= 1 if self.xs > 0: self.xs -= 1 if self.ys > 0: self.ys -= 1 if self.xe < 19: self.xe += 1 if self.ye < 19: self.ye += 1 def header(self): print(" ",end="") for x in string.ascii_lowercase[self.xs:self.xe]: print(x+" ",end="") print("") def show(self): self.header() for y in string.ascii_lowercase[self.ys:self.ye]: print(self.l2n(y).rjust(3)+" ",end="") for x in string.ascii_lowercase[self.xs:self.xe]: print(self.board_symbol(x,y),end="") print(" "+self.l2n(y)) self.header() def find_variation(self,move): # Is it in one of the variations? for var in self.current_node.variations: if not self.to_play in var.properties: print("No move in this variation!") print(var.properties) if var.properties[self.to_play][0] == move: return var # Is it just the next move? if self.current_node.next.properties[self.to_play][0] == move: return self.current_node.next print("Not found!") def n2l(n): return string.ascii_lowercase[n-1] def coord_to_sgf(a): n2 = ''.join([i for i in a if i.isdigit()]) if not n2: return numbers = int(n2) letters = ''.join([i for i in a if not i.isdigit()]) if not letters: return return letters+n2l(numbers) if len(sys.argv) < 2: dn = "/home/taw/tsumego/Chikun_v1/" fn = dn+random.choice(os.listdir(dn)) else: fn = sys.argv[1] with open(fn) as f: c = sgf.parse(f.read()) i=randint(0,len(c.children)-1) print(fn+" puzzle "+str(i)) puzzle = c.children[i] board = Board(puzzle.root) board.add_next(0) board.fit_board() board.show() print(board.to_move()+" to move.") while not board.finished: ans = input("-> ") move = coord_to_sgf(ans) var = board.find_variation(move) if not var: print("Incorrect.") exit(0) board.set_node(var) board.add_next(1) board.show()