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
use Player;
use game_manager::{Game, State};
use gdl::{Move, Score, Role};
pub struct MinimaxPlayer {
min_bound: u8,
max_bound: u8
}
impl Player for MinimaxPlayer {
fn name(&self) -> String {
"MinimaxPlayer".to_string()
}
fn select_move(&mut self, game: &Game) -> Move {
let m = self.best_move(&game);
info!("Selecting move {}", m.to_string());
m
}
}
impl MinimaxPlayer {
pub fn new() -> MinimaxPlayer {
MinimaxPlayer { min_bound: 0, max_bound: 100 }
}
pub fn with_bounds(min_bound: u8, max_bound: u8) -> MinimaxPlayer {
MinimaxPlayer { min_bound: min_bound, max_bound: max_bound }
}
fn best_move(&self, game: &Game) -> Move {
let role = game.role();
let cur_state = game.current_state();
let moves = game.legal_moves(cur_state, role);
assert!(moves.len() >= 1, "No legal moves");
let mut max = 0;
let mut res = moves[0].clone();
let opponent = opponent(game, role);
for m in moves {
let score = self.min_score(game, cur_state, &opponent, m.clone());
if score >= self.max_bound {
return m;
} else if score > max {
max = score;
res = m
}
}
res
}
fn max_score(&self, game: &Game, state: &State, role: &Role) -> Score {
if game.is_terminal(state) {
return game.goal(state, game.role());
}
let moves = game.legal_moves(state, role);
assert!(moves.len() >= 1, "No legal moves");
let mut max = 0;
let opponent = opponent(game, role);
for m in moves {
let score = self.min_score(game, state, &opponent, m);
if score >= self.max_bound {
return score;
} else if score > max {
max = score;
}
}
max
}
fn min_score(&self, game: &Game, state: &State, role: &Role, last_move: Move) -> Score {
let moves = game.legal_moves(state, role);
assert!(moves.len() >= 1, "No legal moves");
let mut min = 100;
for m in moves {
let move_vec = if game.roles()[0] == *role {
vec![m, last_move.clone()]
} else {
vec![last_move.clone(), m]
};
let s = game.next_state(state, &*move_vec);
let opponent = opponent(game, role);
let score = self.max_score(game, &s, &opponent);
if score <= self.min_bound {
return score;
} else if score < min {
min = score;
}
}
min
}
}
fn opponent(game: &Game, role: &Role) -> Role {
let roles = game.roles();
assert!(roles.len() == 2, "Must be a two player game");
for r in roles {
if role != r {
return (*r).clone();
}
}
panic!("Shouldn't happen");
}