-
Notifications
You must be signed in to change notification settings - Fork 0
/
minimax_template.py
93 lines (73 loc) · 3.03 KB
/
minimax_template.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
import pyspiel
from absl import app
def _minimax(state, maximizing_player_id):
"""
Implements a min-max algorithm
Arguments:
state: The current state node of the game.
maximizing_player_id: The id of the MAX player. The other player is assumed
to be MIN.
Returns:
The optimal value of the sub-game starting in state
"""
if state.is_terminal():
return state.player_return(maximizing_player_id)
player = state.current_player()
if player == maximizing_player_id:
selection = max
else:
selection = min
values_children = [_minimax(state.child(action), maximizing_player_id) for action in state.legal_actions()]
return selection(values_children)
def minimax_search(game,
state=None,
maximizing_player_id=None,
state_to_key=lambda state: state):
"""Solves deterministic, 2-players, perfect-information 0-sum game.
For small games only! Please use keyword arguments for optional arguments.
Arguments:
game: The game to analyze, as returned by `load_game`.
state: The state to run from. If none is specified, then the initial state is assumed.
maximizing_player_id: The id of the MAX player. The other player is assumed
to be MIN. The default (None) will suppose the player at the root to be
the MAX player.
Returns:
The value of the game for the maximizing player when both player play optimally.
"""
game_info = game.get_type()
if game.num_players() != 2:
raise ValueError("Game must be a 2-player game")
if game_info.chance_mode != pyspiel.GameType.ChanceMode.DETERMINISTIC:
raise ValueError("The game must be a Deterministic one, not {}".format(
game.chance_mode))
if game_info.information != pyspiel.GameType.Information.PERFECT_INFORMATION:
raise ValueError(
"The game must be a perfect information one, not {}".format(
game.information))
if game_info.dynamics != pyspiel.GameType.Dynamics.SEQUENTIAL:
raise ValueError("The game must be turn-based, not {}".format(
game.dynamics))
if game_info.utility != pyspiel.GameType.Utility.ZERO_SUM:
raise ValueError("The game must be 0-sum, not {}".format(game.utility))
if state is None:
state = game.new_initial_state()
if maximizing_player_id is None:
maximizing_player_id = state.current_player()
v = _minimax(
state.clone(),
maximizing_player_id=maximizing_player_id)
return v
def main(_):
games_list = pyspiel.registered_names()
assert "dots_and_boxes" in games_list
game_string = "dots_and_boxes(num_rows=2,num_cols=2)"
print("Creating game: {}".format(game_string))
game = pyspiel.load_game(game_string)
value = minimax_search(game)
if value == 0:
print("It's a draw")
else:
winning_player = 1 if value == 1 else 2
print(f"Player {winning_player} wins.")
if __name__ == "__main__":
app.run(main)