Skip to content

Commit 002bd60

Browse files
committed
Merge pull request #132 from iopq/playout
Remerging the pull request
2 parents 504c2c5 + 395c759 commit 002bd60

File tree

9 files changed

+93
-39
lines changed

9 files changed

+93
-39
lines changed

src/board/mod.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,8 @@ impl Board {
560560
fn remove_stone(&mut self, c: Coord) {
561561
// Resetting the chain_id is not strictly necessary, but will
562562
// make debugging easier.
563-
self.board[c.to_index(self.size)].chain_id = -1;
563+
//self.board[c.to_index(self.size)].chain_id = -1;
564+
//removed because compiler error
564565
self.board[c.to_index(self.size)].color = Empty;
565566
}
566567

@@ -594,6 +595,26 @@ impl Board {
594595
set.len() - 1 //minus the stone we're about to play
595596
}
596597

598+
pub fn new_chain_liberties_greater_than(&self, m: Move, limit: usize) -> bool {
599+
let mut set: HashSet<Coord> = HashSet::new();
600+
601+
for &c in self.neighbours(m.coord()).iter() {
602+
if(self.color(&c) == *m.color()) {
603+
//add the liberties the chain
604+
for &liberty in self.get_chain(c).unwrap().liberties() {
605+
set.insert(liberty);
606+
}
607+
} else if(self.color(&c) == Empty) {
608+
set.insert(c);
609+
}
610+
611+
if set.len() - 1 > limit {
612+
return true;
613+
}
614+
};
615+
false
616+
}
617+
597618
//the length of all merged chains after the current move
598619
pub fn new_chain_length(&self, m: Move) -> usize {
599620
let set: HashSet<&Coord> = self.neighbours(m.coord()).iter()
@@ -602,6 +623,23 @@ impl Board {
602623
.collect();
603624
set.len() + 1 //plus the stone we're about to play
604625
}
626+
627+
pub fn new_chain_length_less_than(&self, m: Move, limit: usize) -> bool {
628+
let mut set: HashSet<&Coord> = HashSet::new();
629+
630+
for &c in self.neighbours(m.coord()).iter() {
631+
if self.color(&c) == *m.color() {
632+
for coord in self.get_chain(c).unwrap().coords().iter() {
633+
set.insert(coord);
634+
if set.len() + 1 > limit {
635+
return false;
636+
}
637+
}
638+
}
639+
}
640+
641+
true
642+
}
605643

606644
pub fn score(&self) -> Score {
607645
Score::new(self)

src/board/movement/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use board::Coord;
2727

2828
mod test;
2929

30-
#[derive(Debug, Eq, PartialEq, Hash, Copy)]
30+
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
3131
pub enum Move {
3232
Pass(Color),
3333
Play(Color, u8, u8),

src/board/test/hypotheticals.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ fn two_stones_have_six_liberties() {
116116

117117
let play = Play(Black, 10, 12);
118118
assert_eq!(2, board.new_chain_length(play));
119+
assert!(board.new_chain_length_less_than(play, 3));
119120
assert_eq!(6, board.new_chain_liberties(play));
121+
assert!(board.new_chain_liberties_greater_than(play, 5));
120122
}
121123

122124
#[test]
@@ -126,7 +128,9 @@ fn three_stones_have_eight_liberties() {
126128
let board = game.board();
127129
let play = Play(Black, 10, 10);
128130
assert_eq!(3, board.new_chain_length(play));
131+
assert!(board.new_chain_length_less_than(play, 4));
129132
assert_eq!(8, board.new_chain_liberties(play));
133+
assert!(board.new_chain_liberties_greater_than(play, 7));
130134
}
131135

132136
#[test]
@@ -136,7 +140,9 @@ fn four_stones_have_eight_liberties() {
136140
let board = game.board();
137141
let play = Play(Black, 10, 7);
138142
assert_eq!(4, board.new_chain_length(play));
143+
assert!(board.new_chain_length_less_than(play, 5));
139144
assert_eq!(8, board.new_chain_liberties(play));
145+
assert!(board.new_chain_liberties_greater_than(play, 7));
140146
}
141147

142148
#[test]
@@ -146,7 +152,9 @@ fn five_stones_have_eight_liberties() {
146152
let board = game.board();
147153
let play = Play(Black, 10, 4);
148154
assert_eq!(5, board.new_chain_length(play));
155+
assert!(board.new_chain_length_less_than(play, 6));
149156
assert_eq!(8, board.new_chain_liberties(play));
157+
assert!(board.new_chain_liberties_greater_than(play, 7));
150158
}
151159

152160
#[test]
@@ -156,7 +164,9 @@ fn six_stones_have_nine_liberties() {
156164
let board = game.board();
157165
let play = Play(Black, 15, 17);
158166
assert_eq!(6, board.new_chain_length(play));
167+
assert!(board.new_chain_length_less_than(play, 7));
159168
assert_eq!(9, board.new_chain_liberties(play));
169+
assert!(board.new_chain_liberties_greater_than(play, 8));
160170
}
161171

162172
#[test]
@@ -165,8 +175,11 @@ fn seven_stones_have_ten_liberties() {
165175
let game = parser.game().unwrap();
166176
let board = game.board();
167177
let play = Play(Black, 15, 13);
178+
168179
assert_eq!(7, board.new_chain_length(play));
180+
assert!(board.new_chain_length_less_than(play, 8));
169181
assert_eq!(10, board.new_chain_liberties(play));
182+
assert!(board.new_chain_liberties_greater_than(play, 9));
170183
}
171184

172185
#[test]
@@ -176,5 +189,7 @@ fn nine_stones_have_twelve_liberties() {
176189
let board = game.board();
177190
let play = Play(Black, 15, 9);
178191
assert_eq!(9, board.new_chain_length(play));
192+
assert!(board.new_chain_length_less_than(play, 10));
179193
assert_eq!(12, board.new_chain_liberties(play));
194+
assert!(board.new_chain_liberties_greater_than(play, 11));
180195
}

src/engine/mc/amaf.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ impl McEngine for AmafMcEngine {
6262
fn record_playout(stats: &mut MoveStats, playout: &PlayoutResult, won: bool) {
6363
for m in playout.moves().iter() {
6464
if won {
65-
stats.record_win(&m);
65+
stats.record_win(*m);
6666
} else {
67-
stats.record_loss(&m);
67+
stats.record_loss(*m);
6868
}
6969
}
7070
}

src/engine/mc/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn finish(color: Color, game: &Game, stats: MoveStats, sender: Sender<Move>, hal
103103
}
104104
}
105105

106-
fn spin_up<'a, T: McEngine>(color: Color, config: Arc<Config>, moves: &'a Vec<Move>, game: &Game, send_result: Sender<(MoveStats<'a>, usize)>) -> (Vec<thread::JoinGuard<'a, ()>>, Vec<Sender<()>>) {
106+
fn spin_up<'a, T: McEngine>(color: Color, config: Arc<Config>, moves: &'a Vec<Move>, game: &Game, send_result: Sender<(MoveStats, usize)>) -> (Vec<thread::JoinGuard<'a, ()>>, Vec<Sender<()>>) {
107107
let mut guards = Vec::new();
108108
let mut halt_senders = Vec::new();
109109
for _ in 0..config.threads {
@@ -117,7 +117,7 @@ fn spin_up<'a, T: McEngine>(color: Color, config: Arc<Config>, moves: &'a Vec<Mo
117117
(guards, halt_senders)
118118
}
119119

120-
fn spin_up_worker<'a, T: McEngine>(color: Color, recv_halt: Receiver<()>, moves: &'a Vec<Move>, board: Board, config: Arc<Config>, send_result: Sender<(MoveStats<'a>, usize)>) -> thread::JoinGuard<'a, ()> {
120+
fn spin_up_worker<'a, T: McEngine>(color: Color, recv_halt: Receiver<()>, moves: &'a Vec<Move>, board: Board, config: Arc<Config>, send_result: Sender<(MoveStats, usize)>) -> thread::JoinGuard<'a, ()> {
121121
thread::scoped(move || {
122122
let runs = 100;
123123
let mut rng = weak_rng();

src/engine/mc/simple.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ impl McEngine for SimpleMcEngine {
6262
fn record_playout(stats: &mut MoveStats, playout: &PlayoutResult, won: bool) {
6363
let m = playout.moves()[0];
6464
if won {
65-
stats.record_win(&m);
65+
stats.record_win(m);
6666
} else {
67-
stats.record_loss(&m);
67+
stats.record_loss(m);
6868
}
6969
}
7070

src/engine/move_stats/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@ use std::collections::HashMap;
2828

2929
mod test;
3030

31-
pub struct MoveStats<'a> {
31+
pub struct MoveStats {
3232
color: Color,
33-
stats: HashMap<&'a Move, MoveStat>,
33+
stats: HashMap<Move, MoveStat>,
3434
}
3535

36-
impl<'a> MoveStats<'a> {
36+
impl MoveStats {
3737

3838
pub fn new(moves: &Vec<Move>, color: Color) -> MoveStats {
3939
let mut stats = HashMap::new();
40-
for m in moves.iter() {
40+
for &m in moves.iter() {
4141
stats.insert(m, MoveStat::new());
4242
}
4343
MoveStats {
@@ -46,14 +46,14 @@ impl<'a> MoveStats<'a> {
4646
}
4747
}
4848

49-
pub fn record_win(&mut self, m: &Move) {
49+
pub fn record_win(&mut self, m: Move) {
5050
match self.stats.get_mut(&m) {
5151
Some(stat) => stat.won(),
5252
None => {}
5353
}
5454
}
5555

56-
pub fn record_loss(&mut self, m: &Move) {
56+
pub fn record_loss(&mut self, m: Move) {
5757
match self.stats.get_mut(&m) {
5858
Some(stat) => stat.lost(),
5959
None => {}
@@ -73,7 +73,7 @@ impl<'a> MoveStats<'a> {
7373
let mut move_stats = MoveStat::new();
7474
for (m_new, ms) in self.stats.iter() {
7575
if ms.win_ratio() > move_stats.win_ratio() {
76-
m = **m_new;
76+
m = *m_new;
7777
move_stats = *ms;
7878
}
7979
}
@@ -92,7 +92,7 @@ impl<'a> MoveStats<'a> {
9292
}
9393

9494

95-
#[derive(Copy)]
95+
#[derive(Copy, Clone)]
9696
pub struct MoveStat {
9797
wins: usize,
9898
plays: usize

src/engine/move_stats/test.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ mod move_stats {
4545
fn returns_the_best_move() {
4646
let moves = vec![Play(Black, 1, 1), Play(Black, 2, 2)];
4747
let mut stats = MoveStats::new(&moves, Black);
48-
stats.record_win(&Play(Black, 1, 1));
49-
stats.record_loss(&Play(Black, 1, 1));
50-
stats.record_win(&Play(Black, 2, 2));
51-
stats.record_win(&Play(Black, 2, 2));
48+
stats.record_win(Play(Black, 1, 1));
49+
stats.record_loss(Play(Black, 1, 1));
50+
stats.record_win(Play(Black, 2, 2));
51+
stats.record_win(Play(Black, 2, 2));
5252
let (m, ms) = stats.best();
5353
assert_eq!(Play(Black, 2, 2), m);
5454
assert_eq!(ms.plays, 2);
@@ -59,58 +59,58 @@ mod move_stats {
5959
fn all_wins_returns_true_when_no_losses_were_recorded() {
6060
let moves = vec![Play(Black, 1, 1), Play(Black, 2, 2)];
6161
let mut stats = MoveStats::new(&moves, Black);
62-
stats.record_win(&Play(Black, 1, 1));
63-
stats.record_win(&Play(Black, 2, 2));
62+
stats.record_win(Play(Black, 1, 1));
63+
stats.record_win(Play(Black, 2, 2));
6464
assert!(stats.all_wins());
6565
}
6666

6767
#[test]
6868
fn all_wins_returns_false_when_a_loss_was_recorded() {
6969
let moves = vec![Play(Black, 1, 1), Play(Black, 2, 2)];
7070
let mut stats = MoveStats::new(&moves, Black);
71-
stats.record_loss(&Play(Black, 1, 1));
71+
stats.record_loss(Play(Black, 1, 1));
7272
assert!(!stats.all_wins());
7373
}
7474

7575
#[test]
7676
fn all_losses_returns_true_when_no_wins_were_recorded() {
7777
let moves = vec![Play(Black, 1, 1), Play(Black, 2, 2)];
7878
let mut stats = MoveStats::new(&moves, Black);
79-
stats.record_loss(&Play(Black, 1, 1));
80-
stats.record_loss(&Play(Black, 2, 2));
79+
stats.record_loss(Play(Black, 1, 1));
80+
stats.record_loss(Play(Black, 2, 2));
8181
assert!(stats.all_losses());
8282
}
8383

8484
#[test]
8585
fn all_losses_returns_false_when_a_win_was_recorded() {
8686
let moves = vec![Play(Black, 1, 1), Play(Black, 2, 2)];
8787
let mut stats = MoveStats::new(&moves, Black);
88-
stats.record_win(&Play(Black, 1, 1));
88+
stats.record_win(Play(Black, 1, 1));
8989
assert!(!stats.all_losses());
9090
}
9191

9292
#[test]
9393
fn record_win_does_nothing_for_untracked_moves() {
9494
let moves = vec!();
9595
let mut stats = MoveStats::new(&moves, Black);
96-
stats.record_win(&Play(Black, 1, 1));
96+
stats.record_win(Play(Black, 1, 1));
9797
}
9898

9999
#[test]
100100
fn record_loss_does_nothing_for_untracked_moves() {
101101
let moves = vec!();
102102
let mut stats = MoveStats::new(&moves, Black);
103-
stats.record_loss(&Play(Black, 1, 1));
103+
stats.record_loss(Play(Black, 1, 1));
104104
}
105105

106106
#[test]
107107
fn merge_merges_stats_existing_in_both() {
108108
let m = Play(Black, 1, 1);
109109
let moves = vec!(m);
110110
let mut stats = MoveStats::new(&moves, Black);
111-
stats.record_win(&m);
111+
stats.record_win(m);
112112
let mut other = MoveStats::new(&moves, Black);
113-
other.record_loss(&m);
113+
other.record_loss(m);
114114
stats.merge(&other);
115115
let ms = stats.stats.get(&m).unwrap();
116116
assert_eq!(ms.wins, 1);
@@ -124,7 +124,7 @@ mod move_stats {
124124
let mut stats = MoveStats::new(&moves, Black);
125125
let moves2 = vec!(m);
126126
let mut other = MoveStats::new(&moves2, Black);
127-
other.record_loss(&m);
127+
other.record_loss(m);
128128
stats.merge(&other);
129129
assert!(!stats.stats.get(&m).is_some());
130130
}

src/playout/no_eyes.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,20 @@ impl Playout for NoSelfAtariPlayout {
4545

4646
fn is_playable(&self, board: &Board, m: &Move) -> bool {
4747
!board.is_eye(&m.coord(), *m.color())
48-
&& (
49-
board.liberty_count(m.coord()) > 1 ||
48+
&& {
49+
let empty = board.liberty_count(m.coord());
50+
empty > 1 ||
5051
{
5152
let removed_enemies = board.removes_enemy_neighbouring_stones(*m);
5253

53-
removed_enemies > 1 ||
54+
empty + removed_enemies > 1 ||
5455
{
55-
let liberties = board.new_chain_liberties(*m);
56-
liberties + removed_enemies > 1
56+
(removed_enemies > 0 && board.new_chain_liberties_greater_than(*m, 0)) ||
57+
board.new_chain_liberties_greater_than(*m, 1)
5758
}
58-
}
59-
|| board.new_chain_length(*m) < 3 //don't suicide 3 stone groups in the playouts, only in the tree
60-
)
59+
}
60+
|| board.new_chain_length_less_than(*m, 3) //you can self-atari one or two stones in playouts
61+
}
6162
}
6263

6364
fn playout_type(&self) -> String {

0 commit comments

Comments
 (0)