Guest User

Untitled

a guest
Oct 20th, 2017
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.31 KB | None | 0 0
  1. """
  2. Prototype made by Gabriel Lisaca 2017-10-19 11:06pm
  3. Made for the discord bot for the '4D' tic tac toe"""
  4.  
  5. from typing import Tuple
  6. # TODO: check this with mypy + run tests if you want to
  7.  
  8. # Constants used to access the rows and columns (for the internal boards) in an easy manner
  9. ROW_ONE = 0
  10. ROW_TWO = 1
  11. ROW_THREE = 2
  12.  
  13. COLUMN_ONE = 0
  14. COLUMN_TWO = 1
  15. COLUMN_THREE = 2
  16.  
  17. # Constants used to access the internal boards from the main board
  18. BOARD_UPPER_LEFT = 0
  19. BOARD_UPPER_MID = 1
  20. BOARD_UPPER_RIGHT = 2
  21.  
  22. BOARD_MIDLEFT = 3
  23. BOARD_MID = 4
  24. BOARD_MIDRIGHT = 5
  25.  
  26. BOARD_BOTTOM_LEFT = 6
  27. BOARD_BOTTOM_MID = 7
  28. BOARD_BOTTOM_RIGHT = 8
  29.  
  30.  
  31. class OutOfBoardBoundsError(Exception):
  32. pass
  33.  
  34. class InternalBoard:
  35. row_max_idx = 2
  36. col_max_idx = 2
  37.  
  38. def __init__(self, upper_row_num:int):
  39. self._board = [
  40. [0, 0, 0],
  41. [0, 0, 0],
  42. [0, 0, 0]
  43. ]
  44. self._upper_global_row_num = upper_row_num
  45. self._mid_global_row_num = upper_row_num + 1
  46. self._bottom_global_row_num = upper_row_num + 2
  47.  
  48. def get_row(self, row_num:int):
  49. if self._is_in_row_bounds(row_num):
  50. return self._board[row_num]
  51. else:
  52. raise OutOfBoardBoundsError("in `get_row` in `InternalBoard` with row_num={}".format(row_num))
  53.  
  54. def get_row_num_from_global_num(self, row_num:int) -> int:
  55. """Takes a row number from the main board and translates it to this boards own internal row number"""
  56. if row_num == self._upper_global_row_num:
  57. return ROW_ONE
  58. elif row_num == self._mid_global_row_num:
  59. return ROW_TWO
  60. elif row_num == self._bottom_global_row_num:
  61. return ROW_THREE
  62. else:
  63. raise ValueError("`row_num` is not in the row numbers of this `InternalBoard` object")
  64.  
  65. # These 3 properties may be unnecessary. Decide whether to remove later.
  66. @property
  67. def row_1(self):
  68. return self._board[0]
  69.  
  70. @property
  71. def row_2(self):
  72. return self._board[1]
  73.  
  74. @property
  75. def row_3(self):
  76. return self._board[2]
  77.  
  78. def _is_in_row_bounds(self, row:int) -> bool:
  79. return row <= InternalBoard.row_max_idx and row >= 0
  80.  
  81. def _is_in_column_bounds(self, col:int) -> bool:
  82. return col <= InternalBoard.col_max_idx and col >= 0
  83.  
  84. def _mark_row(self, row:int, mark:int, idx:int):
  85. if self._is_in_row_bounds(row) and self._is_in_column_bounds(idx):
  86. self._board[row][idx] = mark
  87. else:
  88. raise OutOfBoardBoundsError("in `_mark_row` in `InternalBoard`")
  89.  
  90. def mark_first_row(self, mark:int, idx:int):
  91. self._mark_row(ROW_ONE, mark, idx)
  92.  
  93. def mark_second_row(self, mark:int, idx:int):
  94. self._mark_row(ROW_TWO, mark, idx)
  95.  
  96. def mark_third_row(self, mark:int, idx:int):
  97. self._mark_row(ROW_THREE, mark, idx)
  98.  
  99.  
  100. class GameBoard4DTicTacToe:
  101. board_max_idx = 8
  102. board_row_num = 9
  103. def __init__(self, num_players:int=0):
  104. self._upper_boards = (InternalBoard(0) for _ in range(3))
  105. self._mid_boards = (InternalBoard(3) for _ in range(3))
  106. self._bottom_boards = (InternalBoard(6) for _ in range(3))
  107. self._boards = [*self._upper_boards, *self._mid_boards, *self._bottom_boards]
  108.  
  109. self._upper_board_range = range(0, 3) # Rows 0-2 internally
  110. self._mid_board_range = range(3, 6) # Rows 3-5 internally
  111. self._bottom_board_range = range(6, 9) # Rows 6-8 internally
  112.  
  113. def place_mark(self, mark:int, place:int, row:int, column:int):
  114. self.get_board(place)._mark_row(row, mark, column)
  115.  
  116. def get_board(self, board_num:int) -> InternalBoard:
  117. if board_num <= GameBoard4DTicTacToe.board_max_idx and board_num >= 0:
  118. return self._boards[board_num]
  119. else:
  120. raise OutOfBoardBoundsError("in `get_board` in `GameBoard4DTicTacToe")
  121.  
  122. def _stringify_board_row(self, row_num:int, board_num:int) -> str:
  123. """Example return value:
  124. -----------------------
  125. '[1][2][3]'"""
  126. board = self.get_board(board_num)
  127. board_local_row_num = board.get_row_num_from_global_num(row_num)
  128.  
  129. column_1 = board.get_row(board_local_row_num)[COLUMN_ONE]
  130. column_2 = board.get_row(board_local_row_num)[COLUMN_TWO]
  131. column_3 = board.get_row(board_local_row_num)[COLUMN_THREE]
  132.  
  133. return "[{}][{}][{}]".format(column_1, column_2, column_3)
  134.  
  135. def _get_board_nums_in_row(self, row_num:int) -> Tuple[int, int, int]:
  136. if row_num in self._upper_board_range:
  137. return (BOARD_UPPER_LEFT, BOARD_UPPER_MID, BOARD_UPPER_RIGHT)
  138. elif row_num in self._mid_board_range:
  139. return (BOARD_MIDLEFT, BOARD_MID, BOARD_MIDRIGHT)
  140. elif row_num in self._bottom_board_range:
  141. return (BOARD_BOTTOM_LEFT, BOARD_BOTTOM_MID, BOARD_BOTTOM_RIGHT)
  142. else:
  143. raise OutOfBoardBoundsError("in `_get_boards_in_row` in `GameBoard4DTicTacToe`")
  144.  
  145. def _stringify_whole_board_row(self, row_num:int) -> str:
  146. """Example return value:
  147. -----------------------
  148. '[1][2][3]|[4][5][6]|[7][8][9]'"""
  149. board_1, board_2, board_3 = self._get_board_nums_in_row(row_num)
  150.  
  151. str_board_1 = self._stringify_board_row(row_num, board_1)
  152. str_board_2 = self._stringify_board_row(row_num, board_2)
  153. str_board_3 = self._stringify_board_row(row_num, board_3)
  154.  
  155. return "{}|{}|{}".format(str_board_1, str_board_2, str_board_3)
  156.  
  157. def _stringify_whole_board(self) -> str:
  158. """Stringifies all the boards in `self._boards`"""
  159. upper_boards = "\n".join(self._stringify_whole_board_row(row) for row in self._upper_board_range)
  160. mid_boards = "\n".join(self._stringify_whole_board_row(row) for row in self._mid_board_range)
  161. bottom_boards = "\n".join(self._stringify_whole_board_row(row) for row in self._bottom_board_range)
  162.  
  163. joiner = "\n{}\n".format("-" * 30)
  164.  
  165. return joiner.join((upper_boards, mid_boards, bottom_boards))
  166.  
  167. def __str__(self):
  168. return "{0}\n" \
  169. "{1}\n" \
  170. "{0}\n".format("-" * 30, self._stringify_whole_board())
  171.  
  172. board_inputs = {
  173. "UL": BOARD_UPPER_LEFT,
  174. "UM": BOARD_UPPER_MID,
  175. "UR": BOARD_UPPER_RIGHT,
  176.  
  177. "ML": BOARD_MIDLEFT,
  178. "M" : BOARD_MID,
  179. "MR": BOARD_MIDRIGHT,
  180.  
  181. "BL": BOARD_BOTTOM_LEFT,
  182. "BM": BOARD_BOTTOM_MID,
  183. "BR": BOARD_BOTTOM_RIGHT
  184. }
  185.  
  186. row_inputs = {
  187. "TOP": ROW_ONE,
  188. "MID": ROW_TWO,
  189. "BOT": ROW_THREE
  190. }
  191.  
  192. col_inputs = {
  193. "LEFT" : COLUMN_ONE,
  194. "MID" : COLUMN_TWO,
  195. "RIGHT": COLUMN_THREE
  196. }
  197.  
  198. if __name__ == "__main__":
  199. done = False
  200. mark = 5
  201. game = GameBoard4DTicTacToe()
  202. while not done:
  203. print(game)
  204. board_input = input("Which board? (UL|UM|UR|ML|M|MR|BL|BM|BR)").strip().upper()
  205. row_input = input("Which row? (TOP|MID|BOT)").strip().upper()
  206. col_input = input("Which column? (LEFT|MID|RIGHT)").strip().upper()
  207.  
  208. try:
  209. board_input_ = board_inputs[board_input]
  210. row_input_ = row_inputs[row_input]
  211. col_input_ = col_inputs[col_input]
  212. except:
  213. print("Invalid input.")
  214. continue
  215. else:
  216. try:
  217. game.place_mark(mark=mark, place=board_input_, row=row_input_, column=col_input_)
  218. except OutOfBoardBoundsError:
  219. print("Invalid input: Not in board")
  220. continue
Add Comment
Please, Sign In to add comment