summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2016-12-01 16:28:43 +0100
committerThomas White <taw@physics.org>2016-12-01 16:28:43 +0100
commitb960104fbe44f1cbae007c9967e1ce70dc153aa1 (patch)
treed01993c8417b487bc40eb3a6c9920dda37e4c5de
Initial import
-rwxr-xr-xtsumego293
1 files changed, 293 insertions, 0 deletions
diff --git a/tsumego b/tsumego
new file mode 100755
index 0000000..9b92aa0
--- /dev/null
+++ b/tsumego
@@ -0,0 +1,293 @@
+#!/usr/bin/env python3
+
+import sys
+import sgf
+import string
+from random import randint
+
+class Board:
+
+ board = {}
+ xs = 0
+ xe = 19
+ ys = 0
+ ye = 19
+ to_play = "B"
+ finished = False
+
+ def to_move(self):
+ if self.to_play == "B":
+ return "◯"
+ return "⬤"
+
+ def board_symbol(self, x, y):
+ if x+y in self.board:
+ if self.board[x+y] == "W":
+ if x=="a":
+ return " ⬤ "
+ else:
+ return "─⬤ "
+ if self.board[x+y] == "B":
+ if x=="a":
+ return " ◯ "
+ else:
+ return "─◯ "
+ 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"
+ if key == "W":
+ for pos in val:
+ self.board[pos] = "W"
+ self.process_captures("B")
+ self.to_play = "B"
+ 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 not node.variations:
+ self.current_node = node.next
+ if not node.next:
+ self.finished = True
+ else:
+ i = randint(0,len(node.variations)-1)
+ self.current_node = node.variations[i]
+
+ 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
+ if nmoves == 0:
+ while self.is_move(self.current_node.next):
+ self.add_node(self.current_node)
+ return
+ while 1:
+ if not self.current_node:
+ print("Finished!")
+ break
+ if self.is_move(self.current_node):
+ if nm == nmoves:
+ return
+ nm += 1
+ self.add_node(self.current_node)
+
+ def __init__(self,root):
+ self.current_node = root
+
+ def set_node(self,root):
+ self.current_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):
+
+ print("Looking for ",move)
+ print(self.current_node.properties)
+
+ # Is it just the next move?
+ if self.current_node.properties[self.to_play][0] == move:
+ return self.current_node
+
+ # Is it in one of the variations?
+ for var in self.current_node.variations:
+ print("Checking ",var.properties)
+ 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
+
+
+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:
+ fn = "/home/taw/tmp/tsumego/qjzm-a.sgf"
+else:
+ fn = sys.argv[1]
+
+with open(fn) as f:
+ c = sgf.parse(f.read())
+
+i=randint(0,len(c.children)-1)
+
+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(2)
+ board.show()