-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgamestate.py
92 lines (76 loc) · 3.39 KB
/
gamestate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import numpy as np
import copy
from move import Move
class GameState:
playerX = 1
playerO = -1
playerX_win_factor = 1
playerO_win_factor = 100
def __init__(self, initial_board=np.zeros(shape=(3, 3)), initial_player=1):
assert len(initial_board.shape) == 2 and \
initial_board.shape[0] == 3 and \
initial_board.shape[1] == 3, print("Only 3x3 boards are allowed")
self.board = initial_board
self.next_player = initial_player
def print_board(self):
def convert(number):
if number == self.playerX:
return "X"
if number == self.playerO:
return "O"
return " "
for row in range(3):
print(f"| {convert(self.board[row, 0])} | {convert(self.board[row, 1])} | {convert(self.board[row, 2])} |")
def is_move_legal(self, move):
if self.next_player != move.player:
return False
return True if self.board[move.x, move.y] == 0 else False
def make_move(self, move: Move):
assert self.is_move_legal(move), print("Move is illegal!")
new_board = copy.deepcopy(self.board)
new_board[move.x, move.y] = move.player
return GameState(initial_board=new_board, initial_player=-1 * self.next_player)
def legal_moves(self):
moves = []
n_rows = self.board.shape[0]
n_cols = self.board.shape[1]
for x in range(n_rows):
for y in range(n_cols):
move = Move(x=x, y=y, player=self.next_player)
if self.is_move_legal(move):
moves.append(move)
return moves
def is_game_over(self):
return self.get_game_result() is not None
def get_game_result(self):
# if playerX is winner return 1
# if playerX is loser return -1 * lose_factor
# otherwise return 0
playerX_win_sum = self.playerX * 3
playerO_win_sum = self.playerO * 3
# Check for win in rows or columns
row_sums = np.sum(self.board, axis=0)
col_sums = np.sum(self.board, axis=1)
for row_sum in row_sums:
if row_sum == playerX_win_sum:
return self.playerX*self.playerX_win_factor
if row_sum == playerO_win_sum:
return self.playerO*self.playerO_win_factor
for col_sum in col_sums:
if col_sum == playerX_win_sum:
return self.playerX*self.playerX_win_factor
if col_sum == playerO_win_sum:
return self.playerO*self.playerO_win_factor
# Check for win in diagonals
if self.board[0, 0] == self.playerX and self.board[1, 1] == self.playerX and self.board[2, 2] == self.playerX:
return self.playerX*self.playerX_win_factor
if self.board[0, 2] == self.playerX and self.board[1, 1] == self.playerX and self.board[2, 0] == self.playerX:
return self.playerX*self.playerX_win_factor
if self.board[0, 0] == self.playerO and self.board[1, 1] == self.playerO and self.board[2, 2] == self.playerO:
return self.playerO*self.playerO_win_factor
if self.board[0, 2] == self.playerO and self.board[1, 1] == self.playerO and self.board[2, 0] == self.playerO:
return self.playerO*self.playerO_win_factor
if np.all(self.board != 0):
return 0 # its a tie
# if not over - no result
return None