-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.py
140 lines (114 loc) · 4.48 KB
/
player.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
""" Handles actions for HumanPlayer and ComputerPlayer classes """
from board import GameBoard
class Player:
""" Provides base functions for AI and Humanplayer clases."""
def __init__(self, player_type):
"""
Check if the game is in a terminal state.
Returns:
The symbol of the winning player, if there is one.
If the game is a draw, returns 0.
If the game is not over, returns None.
"""
self.player_type = player_type
def make_move(self, board):
"""
Make a move on the game board.
This method should be overridden by subclasses.
Args:
board: The current state of the game board.
"""
class HumanPlayer(Player):
""" Provides base functions for HumanPlayer to interacti with the game. """
def __init__(self, player_type):
"""
Initialize a human player with a specified type.
Args:
player_type: The type of the player (e.g., "X" or "O").
"""
super().__init__(player_type)
def make_move(self, board, row, column):
"""
Make a move on the game board at the specified row and column.
Args:
board: The current state of the game board.
row: The row of the board where the player wants to make a move.
column: The column of the board where the player wants to make a move
Returns:
A tuple containing the player's type and
the index of the board where the move was made.
"""
x, y = int(row) - 1, int(column) - 1
index = 3 * x + y
return (self.player_type, index)
class ComputerPlayer(Player):
""" Provides base functions for ComputerPlayer to act counterpart for single player games """
def __init__(self, player_type):
"""
Initialize a computer player with a specified type.
Args:
player_type: The type of the player (e.g., "X" or "O").
"""
super().__init__(player_type)
def minimax(self, board, depth, is_maximizing):
"""
Implement the minimax algorithm to determine the best move.
Args:
board: The current state of the game board.
depth: The current depth of the game tree.
is_maximizing: boolean indicating if the
current player is maximizing or minimizing.
Returns:
The best score that can be achieved with the current game state.
"""
terminal_state = board.check_terminal_state()
if terminal_state is not None:
return self.evaluate_terminal_state(terminal_state, depth)
if is_maximizing:
best_score = float('-inf')
for action in board.available_actions():
board.apply_action(action)
score = self.minimax(board, depth + 1, False)
board.board[action[1]] = GameBoard.BOARD_EMPTY
best_score = max(score, best_score)
return best_score
best_score = float('inf')
for action in board.available_actions():
board.apply_action(action)
score = self.minimax(board, depth + 1, True)
board.board[action[1]] = GameBoard.BOARD_EMPTY
best_score = min(score, best_score)
return best_score
def evaluate_terminal_state(self, state, depth):
"""
Evaluate the score of a terminal game state.
Args:
state: The terminal state of the game.
depth: The depth of the game tree when the terminal state was reached
Returns:
The score of the terminal state.
"""
if state == self.player_type:
return 10 - depth
if state == GameBoard.BOARD_EMPTY: # It's a draw
return 0
# The opponent wins
return depth - 10
def make_move(self, board):
"""
Make the best move on the game board using the minimax algorithm.
Args:
board: The current state of the game board.
Returns:
The best action that can be taken on the current game board.
"""
best_score = float('-inf')
best_action = None
for action in board.available_actions():
board.apply_action(action)
score = self.minimax(board, 0, False)
board.board[action[1]] = GameBoard.BOARD_EMPTY
if score > best_score:
best_score = score
best_action = action
return best_action