25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.1 KiB

  1. import itertools
  2. from pprint import pprint
  3. blackMoves = []
  4. whiteMoves = []
  5. boardSize = 19
  6. board = []
  7. blackGroups = []
  8. whiteGroups = []
  9. def get_neighbouring_coordinates(point):
  10. neighbours = []
  11. potentialNeighbours = [
  12. (point[0]-1,point[1]),
  13. (point[0]+1,point[1]),
  14. (point[0],point[1]-1),
  15. (point[0],point[1]+1)
  16. ]
  17. for point in potentialNeighbours:
  18. if 1 <= point[0] <= 19 and 1 <= point[1] <= 19:
  19. neighbours.append(point)
  20. return neighbours
  21. def get_neighbouring_groups(position, color):
  22. groups = whiteGroups if color == "w" else blackGroups
  23. neighbouringGroups = set()
  24. neighbours = get_neighbouring_coordinates(position)
  25. for point in neighbours:
  26. for index, group in enumerate(groups):
  27. if point in group:
  28. neighbouringGroups.add(index)
  29. return list(neighbouringGroups)
  30. def get_liberties(group):
  31. ret = set()
  32. for point in group:
  33. neighbours = get_neighbouring_coordinates(point)
  34. for neighbour in neighbours:
  35. if board[neighbour[0]-1][neighbour[1]-1] == "":
  36. ret.add(neighbour)
  37. return ret
  38. def remove_dead_groups(color):
  39. bothGroups = []
  40. # get the order right so that black can kill a white
  41. # group by playing into whites only eye (and not killing himself first)
  42. if color == "w":
  43. bothGroups = whiteGroups + blackGroups
  44. else:
  45. bothGroups = blackGroups + whiteGroups
  46. # remove dead from board
  47. for group in bothGroups:
  48. if len(get_liberties(group)) == 0:
  49. for pos in group:
  50. board[pos[0]-1][pos[1]-1] = ""
  51. # remove dead from groups lists
  52. whiteGroups[:] = [ group for group in whiteGroups if len(get_liberties(group)) != 0 ]
  53. blackGroups[:] = [ group for group in blackGroups if len(get_liberties(group)) != 0 ]
  54. def play_move(color, move):
  55. playerGroups = whiteGroups if color == "w" else blackGroups
  56. neighbouringGroups = get_neighbouring_groups(move, color)
  57. # no neighbouring groups make new one
  58. if len(neighbouringGroups) == 0:
  59. playerGroups.append([(move[0], move[1])])
  60. else:
  61. # we want to merge everything into the first group and then pop the others in
  62. # reverse index order so no indecies are getting wrong
  63. neighbouringGroups.sort()
  64. neighbouringGroups[1:] = neighbouringGroups[1:][::-1]
  65. # 1 or more neighbouring groups -> extend first one
  66. playerGroups[neighbouringGroups[0]].append((move[0], move[1]))
  67. # if also more than one group -> merge with others
  68. for i, group in enumerate(neighbouringGroups[1:]):
  69. playerGroups[neighbouringGroups[0]].extend(playerGroups.pop(group))
  70. board[move[0]-1][move[1]-1] = color
  71. remove_dead_groups("w" if color == "b" else "b")
  72. def simulate_board_up_to(lastMoveNumber):
  73. global board
  74. global whiteGroups
  75. global blackGroups
  76. # reset board and groups
  77. blackGroups = []
  78. whiteGroups = []
  79. board = [ [ "" for i in range(boardSize) ] for y in range(boardSize) ]
  80. moveSequence = [ j for i in itertools.zip_longest(blackMoves,whiteMoves) for j in i ]
  81. for i in range(len(blackMoves) + len(whiteMoves)):
  82. if i == lastMoveNumber:
  83. break
  84. # blacks turn
  85. if i % 2 == 0:
  86. if len(blackMoves) == 0: continue
  87. play_move("b", blackMoves[i//2])
  88. else:
  89. if len(whiteMoves) == 0: continue
  90. play_move("w", whiteMoves[i//2])
  91. def show_board():
  92. print(" "*3 + "A B C D E F G H J K L M N O P Q R S T")
  93. i = 0
  94. for y in range(boardSize):
  95. i += 1
  96. if boardSize-i+1 < 10:
  97. print(f" {boardSize-i+1}", end="")
  98. else:
  99. print(f"{boardSize-i+1}", end="")
  100. for x in range(boardSize):
  101. if board[x][boardSize-y-1] == "":
  102. print(" .", end="")
  103. else:
  104. print(" " + board[x][boardSize-y-1], end ="")
  105. print(f" {boardSize-i+1}")
  106. print(" "*3 + "A B C D E F G H J K L M N O P Q R S T")
  107. def get_latex_at_move(fromMove):
  108. latexList = []
  109. simulate_board_up_to(fromMove)
  110. # just dumping the baord, nothing special
  111. for y in range(len(board)):
  112. for x in range(len(board)):
  113. if board[x][y] != "":
  114. color = "white" if board[x][y] == "w" else "black"
  115. if ord("a")+x < ord("i"):
  116. firstCoordinate = chr(ord("a")+x)
  117. else:
  118. firstCoordinate = chr(ord("a")+x+1)
  119. latexList.append(f"\\stone{{{color}}}{{{firstCoordinate}}}{{{y+1}}}\n")
  120. return latexList
  121. def produce_latex(fromMove, toMove, continousCounting):
  122. # old moves
  123. latexList = ["\\begin{psgoboard}\n\t"]
  124. latexList.extend(get_latex_at_move(fromMove))
  125. finished = False
  126. moveCount = 1
  127. if continousCounting:
  128. moveCount = fromMove + 1
  129. # new moves
  130. for i in range(fromMove, len(blackMoves) + len(whiteMoves)):
  131. if i == toMove: break
  132. moves = []
  133. color = ""
  134. if i % 2 == 0: # blacks turn
  135. moves = blackMoves
  136. color = "black"
  137. else: # whites turn
  138. moves = whiteMoves
  139. color = "white"
  140. # if this player has no moves left -> continue
  141. if len(moves) == 0: continue
  142. x, y = moves[i//2]
  143. # skip the 'i' coordinate
  144. if ord("a")+x-1 < ord("i"):
  145. firstCoordinate = chr(ord("a")+x-1)
  146. else:
  147. firstCoordinate = chr(ord("a")+x)
  148. latexList.append(f"\\stone[\\marklb{{{moveCount}}}]{{{color}}}{{{firstCoordinate}}}{{{y}}}")
  149. moveCount += 1
  150. else:
  151. # played the last move
  152. finished = True
  153. latexList.append("\n\\end{psgoboard}\n")
  154. return latexList, finished
  155. if __name__ == '__main__':
  156. blackMoves.append((4,4))
  157. whiteMoves.append((4,3))
  158. blackMoves.append((5,3))
  159. whiteMoves.append((5,4))
  160. blackMoves.append((3,3))
  161. whiteMoves.append((3,4))
  162. blackMoves.append((4,2))
  163. whiteMoves.append((4,5))
  164. blackMoves.append((10,10))
  165. whiteMoves.append((4,3))
  166. blackMoves.append((4,4))
  167. whiteMoves.append((4,3))
  168. produce_latex(7, 200)
  169. show_board()