Added go borad simulator to remove dead stones.
This commit is contained in:
@@ -5,3 +5,4 @@
|
||||
*.log
|
||||
*.ps
|
||||
*.pdf
|
||||
__pycache__/
|
||||
|
||||
+23
-35
@@ -3,6 +3,9 @@ import os
|
||||
import sys
|
||||
from subprocess import check_call, DEVNULL, STDOUT, CalledProcessError
|
||||
from shutil import copyfile, rmtree
|
||||
from pprint import pprint
|
||||
|
||||
import simpleGoBoard
|
||||
|
||||
parser = argparse.ArgumentParser(description='Convert sgf go records into a kifu format.')
|
||||
|
||||
@@ -26,6 +29,8 @@ header = sgfData[0]
|
||||
moves = sgfData[1:]
|
||||
|
||||
def format_date(date):
|
||||
if date == "":
|
||||
return ""
|
||||
months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
|
||||
ds = date.split("-") # year month day
|
||||
ds.reverse()
|
||||
@@ -67,45 +72,28 @@ def generate_title():
|
||||
|
||||
return "".join(out)
|
||||
|
||||
def generate_moves():
|
||||
finished = False
|
||||
|
||||
def init_simpleGoBoard():
|
||||
for move in moves:
|
||||
if len(move) == 5:
|
||||
coordinates = (ord(move[2].lower())-ord("a")+1, parsedHeader["boardSize"]-ord(move[3].lower())+ord("a"))
|
||||
if move[0].lower() == "w":
|
||||
simpleGoBoard.whiteMoves.append(coordinates)
|
||||
elif move[0].lower() == "b":
|
||||
simpleGoBoard.blackMoves.append(coordinates)
|
||||
|
||||
|
||||
def generate_boards():
|
||||
init_simpleGoBoard()
|
||||
outText = []
|
||||
for i in range(len(splitBoardAt)-1):
|
||||
currentSplit = splitBoardAt[i]
|
||||
nextSplit = splitBoardAt[i+1]
|
||||
|
||||
outText.append("\\begin{psgoboard}\n\t")
|
||||
|
||||
# old moves
|
||||
for j in range(currentSplit):
|
||||
firstCoordinate, secondCoordinate = extract_coordinates(moves[j])
|
||||
if not (firstCoordinate == -1 or secondCoordinate == -1):
|
||||
outText.append(f"\\move*{{{firstCoordinate}}}{{{secondCoordinate}}} ")
|
||||
if j % 5 == 4:
|
||||
outText.append("\n\t")
|
||||
elif secondCoordinate < 10: # nice spacing
|
||||
outText.append(" ")
|
||||
|
||||
# new moves
|
||||
for j in range(nextSplit-currentSplit):
|
||||
firstCoordinate, secondCoordinate = extract_coordinates(moves[currentSplit+j])
|
||||
if not (firstCoordinate == -1 or secondCoordinate == -1):
|
||||
outText.append(f"\\move{{{firstCoordinate}}}{{{secondCoordinate}}} ")
|
||||
if j % 5 == 4:
|
||||
outText.append("\n\t")
|
||||
elif secondCoordinate < 10: # nice spacing
|
||||
outText.append(" ")
|
||||
|
||||
# was it the last move?
|
||||
if currentSplit+j == len(moves)-1:
|
||||
finished = True
|
||||
break
|
||||
|
||||
outText.append("\n\\end{psgoboard}\n")
|
||||
board, finished = simpleGoBoard.produce_latex(currentSplit, nextSplit, args.cn)
|
||||
outText.extend(board)
|
||||
if finished:
|
||||
break
|
||||
elif not args.cn:
|
||||
outText.append("\n\\setcounter{gomove}{0}\n")
|
||||
|
||||
return "".join(outText)
|
||||
|
||||
@@ -135,7 +123,7 @@ if parsedHeader["rankBlack"] != "":
|
||||
playerBlack += f" ({parsedHeader['rankBlack']})"
|
||||
if parsedHeader["rankWhite"] != "":
|
||||
playerWhite += f" ({parsedHeader['rankWhite']})"
|
||||
moves = generate_moves()
|
||||
boards = generate_boards()
|
||||
|
||||
outText = f"""
|
||||
\\documentclass[a4paper]{{article}}
|
||||
@@ -167,7 +155,7 @@ outText = f"""
|
||||
\\end{{tabularx}}
|
||||
\\vspace{{3cm}}
|
||||
|
||||
{moves}
|
||||
{boards}
|
||||
|
||||
\\end{{center}}
|
||||
\\end{{document}}
|
||||
@@ -195,4 +183,4 @@ if not args.t:
|
||||
rmtree(f"{fileBase}/")
|
||||
# hould output be opened?
|
||||
if args.o:
|
||||
os.system(f'"{fileBase}.pdf"')
|
||||
os.startfile(f'"{fileBase}.pdf"')
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 132 KiB |
@@ -0,0 +1,216 @@
|
||||
import itertools
|
||||
from pprint import pprint
|
||||
|
||||
blackMoves = []
|
||||
whiteMoves = []
|
||||
boardSize = 19
|
||||
|
||||
board = []
|
||||
blackGroups = []
|
||||
whiteGroups = []
|
||||
|
||||
def get_neighbouring_coordinates(point):
|
||||
neighbours = []
|
||||
potentialNeighbours = [
|
||||
(point[0]-1,point[1]),
|
||||
(point[0]+1,point[1]),
|
||||
(point[0],point[1]-1),
|
||||
(point[0],point[1]+1)
|
||||
]
|
||||
|
||||
for point in potentialNeighbours:
|
||||
if 1 <= point[0] <= 19 and 1 <= point[1] <= 19:
|
||||
neighbours.append(point)
|
||||
|
||||
return neighbours
|
||||
|
||||
def get_neighbouring_groups(position, color):
|
||||
groups = whiteGroups if color == "w" else blackGroups
|
||||
|
||||
neighbouringGroups = set()
|
||||
neighbours = get_neighbouring_coordinates(position)
|
||||
|
||||
for point in neighbours:
|
||||
for index, group in enumerate(groups):
|
||||
if point in group:
|
||||
neighbouringGroups.add(index)
|
||||
|
||||
return list(neighbouringGroups)
|
||||
|
||||
|
||||
def get_liberties(group):
|
||||
ret = set()
|
||||
for point in group:
|
||||
neighbours = get_neighbouring_coordinates(point)
|
||||
for neighbour in neighbours:
|
||||
if board[neighbour[0]-1][neighbour[1]-1] == "":
|
||||
ret.add(neighbour)
|
||||
return ret
|
||||
|
||||
|
||||
def remove_dead_groups(color):
|
||||
bothGroups = []
|
||||
|
||||
# get the order right so that black can kill a white
|
||||
# group by playing into whites only eye (and not killing himself first)
|
||||
if color == "w":
|
||||
bothGroups = whiteGroups + blackGroups
|
||||
else:
|
||||
bothGroups = blackGroups + whiteGroups
|
||||
|
||||
# remove dead from board
|
||||
for group in bothGroups:
|
||||
if len(get_liberties(group)) == 0:
|
||||
for pos in group:
|
||||
board[pos[0]-1][pos[1]-1] = ""
|
||||
|
||||
# remove dead from groups lists
|
||||
whiteGroups[:] = [ group for group in whiteGroups if len(get_liberties(group)) != 0 ]
|
||||
blackGroups[:] = [ group for group in blackGroups if len(get_liberties(group)) != 0 ]
|
||||
|
||||
def play_move(color, move):
|
||||
playerGroups = whiteGroups if color == "w" else blackGroups
|
||||
|
||||
neighbouringGroups = get_neighbouring_groups(move, color)
|
||||
|
||||
# no neighbouring groups make new one
|
||||
if len(neighbouringGroups) == 0:
|
||||
playerGroups.append([(move[0], move[1])])
|
||||
else:
|
||||
# we want to merge everything into the first group and then pop the others in
|
||||
# reverse index order so no indecies are getting wrong
|
||||
neighbouringGroups.sort()
|
||||
neighbouringGroups[1:] = neighbouringGroups[1:][::-1]
|
||||
|
||||
# 1 or more neighbouring groups -> extend first one
|
||||
playerGroups[neighbouringGroups[0]].append((move[0], move[1]))
|
||||
|
||||
# if also more than one group -> merge with others
|
||||
for i, group in enumerate(neighbouringGroups[1:]):
|
||||
playerGroups[neighbouringGroups[0]].extend(playerGroups.pop(group))
|
||||
|
||||
board[move[0]-1][move[1]-1] = color
|
||||
remove_dead_groups("w" if color == "b" else "b")
|
||||
|
||||
|
||||
def simulate_board_up_to(lastMoveNumber):
|
||||
global board
|
||||
global whiteGroups
|
||||
global blackGroups
|
||||
|
||||
# reset board and groups
|
||||
blackGroups = []
|
||||
whiteGroups = []
|
||||
board = [ [ "" for i in range(boardSize) ] for y in range(boardSize) ]
|
||||
moveSequence = [ j for i in itertools.zip_longest(blackMoves,whiteMoves) for j in i ]
|
||||
|
||||
for i in range(len(blackMoves) + len(whiteMoves)):
|
||||
if i == lastMoveNumber:
|
||||
break
|
||||
|
||||
# blacks turn
|
||||
if i % 2 == 0:
|
||||
if len(blackMoves) == 0: continue
|
||||
play_move("b", blackMoves[i//2])
|
||||
else:
|
||||
if len(whiteMoves) == 0: continue
|
||||
play_move("w", whiteMoves[i//2])
|
||||
|
||||
|
||||
def show_board():
|
||||
print(" "*3 + "A B C D E F G H J K L M N O P Q R S T")
|
||||
i = 0
|
||||
for y in range(boardSize):
|
||||
i += 1
|
||||
if boardSize-i+1 < 10:
|
||||
print(f" {boardSize-i+1}", end="")
|
||||
else:
|
||||
print(f"{boardSize-i+1}", end="")
|
||||
|
||||
for x in range(boardSize):
|
||||
if board[x][boardSize-y-1] == "":
|
||||
print(" .", end="")
|
||||
else:
|
||||
print(" " + board[x][boardSize-y-1], end ="")
|
||||
|
||||
print(f" {boardSize-i+1}")
|
||||
print(" "*3 + "A B C D E F G H J K L M N O P Q R S T")
|
||||
|
||||
def get_latex_at_move(fromMove):
|
||||
latexList = []
|
||||
|
||||
simulate_board_up_to(fromMove)
|
||||
# just dumping the baord, nothing special
|
||||
for y in range(len(board)):
|
||||
for x in range(len(board)):
|
||||
if board[x][y] != "":
|
||||
color = "white" if board[x][y] == "w" else "black"
|
||||
if ord("a")+x < ord("i"):
|
||||
firstCoordinate = chr(ord("a")+x)
|
||||
else:
|
||||
firstCoordinate = chr(ord("a")+x+1)
|
||||
latexList.append(f"\\stone{{{color}}}{{{firstCoordinate}}}{{{y+1}}}\n")
|
||||
|
||||
return latexList
|
||||
|
||||
def produce_latex(fromMove, toMove, continousCounting):
|
||||
# old moves
|
||||
latexList = ["\\begin{psgoboard}\n\t"]
|
||||
latexList.extend(get_latex_at_move(fromMove))
|
||||
|
||||
finished = False
|
||||
moveCount = 1
|
||||
if continousCounting:
|
||||
moveCount = fromMove + 1
|
||||
|
||||
# new moves
|
||||
for i in range(fromMove, len(blackMoves) + len(whiteMoves)):
|
||||
if i == toMove: break
|
||||
moves = []
|
||||
color = ""
|
||||
|
||||
if i % 2 == 0: # blacks turn
|
||||
moves = blackMoves
|
||||
color = "black"
|
||||
else: # whites turn
|
||||
moves = whiteMoves
|
||||
color = "white"
|
||||
|
||||
# if this player has no moves left -> continue
|
||||
if len(moves) == 0: continue
|
||||
|
||||
x, y = moves[i//2]
|
||||
|
||||
# skip the 'i' coordinate
|
||||
if ord("a")+x-1 < ord("i"):
|
||||
firstCoordinate = chr(ord("a")+x-1)
|
||||
else:
|
||||
firstCoordinate = chr(ord("a")+x)
|
||||
|
||||
latexList.append(f"\\stone[\\marklb{{{moveCount}}}]{{{color}}}{{{firstCoordinate}}}{{{y}}}")
|
||||
moveCount += 1
|
||||
|
||||
else:
|
||||
# played the last move
|
||||
finished = True
|
||||
|
||||
latexList.append("\n\\end{psgoboard}\n")
|
||||
return latexList, finished
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
blackMoves.append((4,4))
|
||||
whiteMoves.append((4,3))
|
||||
blackMoves.append((5,3))
|
||||
whiteMoves.append((5,4))
|
||||
blackMoves.append((3,3))
|
||||
whiteMoves.append((3,4))
|
||||
blackMoves.append((4,2))
|
||||
whiteMoves.append((4,5))
|
||||
blackMoves.append((10,10))
|
||||
whiteMoves.append((4,3))
|
||||
blackMoves.append((4,4))
|
||||
whiteMoves.append((4,3))
|
||||
|
||||
produce_latex(7, 200)
|
||||
show_board()
|
||||
Reference in New Issue
Block a user