From 9e464462c7f32645b68bca4e50e0dfe0f0542e85 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Fri, 13 May 2016 08:08:50 +0200 Subject: [PATCH 01/19] Remove ununsed import --- src/board/coord/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/board/coord/mod.rs b/src/board/coord/mod.rs index f1cc811b..40f3f79f 100644 --- a/src/board/coord/mod.rs +++ b/src/board/coord/mod.rs @@ -2,6 +2,7 @@ * * * Copyright 2014 Urban Hafner, Thomas Poinsot * * Copyright 2015 Urban Hafner, Igor Polyakov * + * Copyright 2016 Urban Hafner * * * * This file is part of Iomrascálaí. * * * @@ -20,7 +21,6 @@ * * ************************************************************************/ use core::fmt; -use std::cmp::Eq; mod test; From f106bd423644044b912f80b567e62cf74fb3a176 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Fri, 13 May 2016 08:12:48 +0200 Subject: [PATCH 02/19] Test cases for when the program crashes after loadsgf --- src/gtp/test.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index 30f57b63..da34af9e 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -275,6 +275,12 @@ describe! interpreter { assert_that(response, is(equal_to(ok("B+9.5")))); } + it "doesn't crash after loading a SGF file" { + interpreter.read("loadsgf fixtures/sgf/twomoves.sgf\n").unwrap(); + let response = interpreter.read("final_score\n"); + assert!(response.is_ok()); + } + } describe! name { @@ -356,6 +362,13 @@ describe! interpreter { let response = interpreter.read("final_status_list\n"); assert_that(response, is(equal_to(err("missing argument")))); } + + it "doesn't crash after loading a SGF file" { + interpreter.read("loadsgf fixtures/sgf/twomoves.sgf\n").unwrap(); + let response = interpreter.read("final_status_list dead\n"); + assert!(response.is_ok()); + } + } // Gogui extensions From 5c410b7b0ab1fff98d455db2ea9f2da541961a6d Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Fri, 13 May 2016 19:42:34 +0200 Subject: [PATCH 03/19] Calculate ownership for scoring --- src/engine/controller/mod.rs | 16 +++++++++-- src/engine/mod.rs | 51 +++++++++++++++++++++++++++++------- src/ownership/mod.rs | 21 ++++++++++++--- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/engine/controller/mod.rs b/src/engine/controller/mod.rs index eb3c1e16..9382df0f 100644 --- a/src/engine/controller/mod.rs +++ b/src/engine/controller/mod.rs @@ -34,6 +34,7 @@ use std::sync::Arc; pub struct EngineController { config: Arc, engine: Engine, + scoring: bool, } impl EngineController { @@ -42,31 +43,37 @@ impl EngineController { EngineController { config: config, engine: engine, + scoring: false, } } pub fn reset(&mut self, size: u8, komi: f32) { self.engine.reset(size, komi); + self.scoring = false; } pub fn ownership_statistics(&self) -> String { format!("{}", self.ownership()) } - pub fn final_score(&self, game: &Game) -> String { + pub fn final_score(&mut self, game: &Game) -> String { + self.calculate_score(game); FinalScore::new(self.config.clone(), game, self.ownership()).score() } - pub fn final_status_list(&self, game: &Game, kind: &str) -> Result { + pub fn final_status_list(&mut self, game: &Game, kind: &str) -> Result { + self.calculate_score(game); FinalScore::new(self.config.clone(), game, self.ownership()).status_list(kind) } pub fn genmove(&mut self, color: Color, game: &Game, timer: &Timer) -> (Move, usize) { + self.scoring = false; self.engine.genmove(color, game, timer) } pub fn genmove_cleanup(&mut self, color: Color, game: &Game, timer: &Timer) -> (Move, usize) { + self.scoring = false; self.engine.genmove_cleanup(color, game, timer) } @@ -74,4 +81,9 @@ impl EngineController { &self.engine.ownership() } + fn calculate_score(&mut self, game: &Game) { + if self.scoring { return; } + self.scoring = true; + self.engine.calculate_score(game); + } } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 16b8fff9..09d29d6e 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -28,6 +28,7 @@ use board::Move; use board::NoMove; use board::Pass; use board::Resign; +use board::White; use config::Config; use game::Game; use ownership::OwnershipStatistics; @@ -45,6 +46,7 @@ use std::sync::mpsc::Receiver; use std::sync::mpsc::Sender; use std::sync::mpsc::channel; use std::thread::spawn; +use time::Duration; use time::PreciseTime; macro_rules! check { @@ -145,19 +147,33 @@ impl Engine { } fn generic_genmove(&mut self, color: Color, game: &Game, timer: &Timer, cleanup: bool) -> (Move,usize) { - self.genmove_setup(color, game); if self.root.has_no_children() { self.config.log(format!("No moves to simulate!")); return (Pass(color), self.root.playouts()); } + let stop = |win_ratio, _: &OwnershipStatistics| { timer.ran_out_of_time(win_ratio) }; + self.genmove_setup(color, game); + self.search(game, stop); + let msg = format!("{} simulations ({}% wins on average, {} nodes)", self.root.playouts(), self.root.win_ratio()*100.0, self.root.descendants()); + self.config.log(msg); + let playouts = self.root.playouts(); + let m = self.best_move(game, color, cleanup); + self.set_new_root(&game.play(m).unwrap(), color); + (m,playouts) + } + + fn search(&mut self, game: &Game, stop: F) where F: for<'r> Fn(f32, &'r OwnershipStatistics) -> bool { self.spin_up(game); loop { let win_ratio = { let (best, _) = self.root.best(); best.win_ratio() }; - if timer.ran_out_of_time(win_ratio) { - return self.finish(game, color, cleanup); + let done = { + stop(win_ratio, &self.ownership) + }; + if done { + return self.spin_down(); } let r = self.receive_from_threads.recv(); check!(self.config, res = r => { @@ -166,6 +182,27 @@ impl Engine { } } + /// Run playouts until all coordinates have a clear owner. + pub fn calculate_score(&mut self, game: &Game) { + let start = PreciseTime::now(); + self.ownership = OwnershipStatistics::new(self.config.clone(), game.size(), game.komi()); + if self.root.has_no_children() { + let color = match game.last_move() { + NoMove => White, + _ => *game.last_move().color() + }; + self.root = Node::root(game, color, self.config.clone()); + } + let stop = |_, ownership: &OwnershipStatistics| { + if start.to(PreciseTime::now()) < Duration::seconds(10) { + false + } else { + ownership.decided(game) || (start.to(PreciseTime::now()) > Duration::seconds(30)) + } + }; + self.search(game, stop); + } + fn dead_stones_on_board(&self, game: &Game) -> bool { FinalScore::new(self.config.clone(), game, self.ownership()).dead_stones_on_board() } @@ -283,18 +320,12 @@ impl Engine { } } - fn finish(&mut self, game: &Game, color: Color, cleanup: bool) -> (Move,usize) { + fn spin_down(&mut self) { self.id += 1; for halt_sender in &self.halt_senders { check!(self.config, halt_sender.send(())); } self.halt_senders = vec!(); - let msg = format!("{} simulations ({}% wins on average, {} nodes)", self.root.playouts(), self.root.win_ratio()*100.0, self.root.descendants()); - self.config.log(msg); - let playouts = self.root.playouts(); - let m = self.best_move(game, color, cleanup); - self.set_new_root(&game.play(m).unwrap(), color); - (m,playouts) } fn spin_up(&mut self, game: &Game) { diff --git a/src/ownership/mod.rs b/src/ownership/mod.rs index e7d786c4..972e559f 100644 --- a/src/ownership/mod.rs +++ b/src/ownership/mod.rs @@ -25,6 +25,7 @@ use board::Coord; use board::Empty; use board::White; use config::Config; +use game::Game; use score::Score; use core::fmt::Display; @@ -79,10 +80,7 @@ impl OwnershipStatistics { let index = coord.to_index(self.size); let b = self.black[index]; let w = self.white[index]; - let e = self.empty[index]; - let count = b + w + e; - let fraction = cmp::max(b,w) as f32 / count as f32; - if fraction > self.config.scoring.ownership_cutoff { + if self.coord_decided(coord) { if b > w { Black } else { @@ -93,6 +91,21 @@ impl OwnershipStatistics { } } + fn coord_decided(&self, coord: &Coord) -> bool { + let index = coord.to_index(self.size); + let b = self.black[index]; + let w = self.white[index]; + let e = self.empty[index]; + let count = b + w + e; + let fraction = cmp::max(b,w) as f32 / count as f32; + fraction > self.config.scoring.ownership_cutoff + } + + pub fn decided(&self, game: &Game) -> bool { + Coord::for_board_size(game.size()).iter() + .all(|coord| self.coord_decided(coord)) + } + pub fn gfx(&self) -> String { let mut b = String::from("BLACK"); let mut w = String::from("WHITE"); From 6ba5e62bb17ed502600e7cfadf26eae81b19a210 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Fri, 13 May 2016 19:46:36 +0200 Subject: [PATCH 04/19] Add 2016 copyright --- src/ownership/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ownership/mod.rs b/src/ownership/mod.rs index 972e559f..6018cef3 100644 --- a/src/ownership/mod.rs +++ b/src/ownership/mod.rs @@ -1,6 +1,7 @@ /************************************************************************ * * * Copyright 2015 Urban Hafner * + * Copyright 2016 Urban Hafner * * * * This file is part of Iomrascálaí. * * * From 3324e7644b9fc592ac4014243cd5bed996221a2c Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Sun, 15 May 2016 20:48:24 +0200 Subject: [PATCH 05/19] Add tests for crashes when scoring after loading an SGF file --- fixtures/sgf/final_score_crash.sgf | 483 +++++++++++++++++++++++++++++ src/gtp/test.rs | 12 + 2 files changed, 495 insertions(+) create mode 100644 fixtures/sgf/final_score_crash.sgf diff --git a/fixtures/sgf/final_score_crash.sgf b/fixtures/sgf/final_score_crash.sgf new file mode 100644 index 00000000..796105ff --- /dev/null +++ b/fixtures/sgf/final_score_crash.sgf @@ -0,0 +1,483 @@ +(;FF[4]CA[UTF-8]AP[gogui-twogtp:1.4.9]SZ[13] +KM[6.5]PB[GNU Go:3.8]PW[Iomrascalai]DT[2016-05-13]RE[W+7.5] +C[Black command: gnugo --mode gtp --level 0 --chinese-rules --positional-superko +White command: cargo run --release -- --log --rules chinese +Black version: 3.8 +White version: 0.3.1 +Result[Black\]: W+7.5 +Result[White\]: W+44.5 +Referee: gnugo --mode gtp --level 0 --chinese-rules --positional-superko +Result[Referee\]: W+7.5 +Host: macaron.local +Date: May 13, 2016 9:34:10 PM CEST] +;B[jf];W[gk] +C[Thinking for 8121ms (600000ms time left) +31222 simulations (48.241135% wins on average, 5164067 nodes) +Best move win ratio: 52.591904% +3746pps (535pps per thread) +] +;B[kc];W[cg] +C[Thinking for 8105ms (591665ms time left) +Reusing 4782 nodes (3.6030471%) +30668 simulations (48.601643% wins on average, 4994961 nodes) +Best move win ratio: 51.944668% +3689pps (527pps per thread) +] +;B[fe];W[cj] +C[Thinking for 8088ms (583352ms time left) +Reusing 165 nodes (0.07876007%) +31699 simulations (48.5221% wins on average, 5071248 nodes) +Best move win ratio: 52.716076% +3826pps (547pps per thread) +] +;B[ce];W[dd] +C[Thinking for 8072ms (575067ms time left) +Reusing 163 nodes (0.12389219%) +32723 simulations (47.34047% wins on average, 5174856 nodes) +Best move win ratio: 52.15376% +3943pps (563pps per thread) +] +;B[cd];W[hg] +C[Thinking for 8055ms (566768ms time left) +Reusing 33222 nodes (20.048277%) +32104 simulations (47.32501% wins on average, 5042155 nodes) +Best move win ratio: 52.276672% +3872pps (553pps per thread) +] +;B[cc];W[jh] +C[Thinking for 8037ms (558477ms time left) +Reusing 7957 nodes (3.2195547%) +33406 simulations (47.409546% wins on average, 5143282 nodes) +Best move win ratio: 52.843254% +4032pps (576pps per thread) +] +;B[de];W[je] +C[Thinking for 8020ms (550192ms time left) +Reusing 22903 nodes (6.178511%) +31948 simulations (51.116455% wins on average, 4864677 nodes) +Best move win ratio: 54.526085% +3868pps (553pps per thread) +] +;B[le];W[if] +C[Thinking for 8002ms (541934ms time left) +Reusing 155 nodes (0.07865425%) +33338 simulations (53.465305% wins on average, 4991387 nodes) +Best move win ratio: 56.931824% +4040pps (577pps per thread) +] +;B[ed];W[kk] +C[Thinking for 7984ms (533683ms time left) +Reusing 17441 nodes (3.3164854%) +31913 simulations (61.41191% wins on average, 4704408 nodes) +Best move win ratio: 62.045246% +3768pps (538pps per thread) +] +;B[id];W[kf] +C[Thinking for 7962ms (525215ms time left) +Reusing 10886 nodes (0.31619594%) +31663 simulations (62.13313% wins on average, 4602824 nodes) +Best move win ratio: 62.6848% +3739pps (534pps per thread) +] +;B[lf];W[lg] +C[Thinking for 7939ms (516748ms time left) +Reusing 55431 nodes (1.4852384%) +32370 simulations (62.92435% wins on average, 4686282 nodes) +Best move win ratio: 63.658733% +3837pps (548pps per thread) +] +;B[eh];W[ke] +C[Thinking for 7917ms (508311ms time left) +Reusing 35991 nodes (1.005691%) +33681 simulations (60.532806% wins on average, 4794841 nodes) +Best move win ratio: 61.4297% +4027pps (575pps per thread) +] +;B[dg];W[ld] +C[Thinking for 7895ms (499948ms time left) +Reusing 50225 nodes (1.7218451%) +35298 simulations (63.833965% wins on average, 4978907 nodes) +Best move win ratio: 64.473015% +4187pps (598pps per thread) +] +;B[ej];W[ch] +C[Thinking for 7871ms (491518ms time left) +Reusing 41482 nodes (0.98971987%) +35176 simulations (61.358578% wins on average, 4884312 nodes) +Best move win ratio: 62.461918% +4220pps (603pps per thread) +] +;B[lc];W[kd] +C[Thinking for 7848ms (483183ms time left) +Reusing 74142 nodes (2.1851144%) +36105 simulations (59.7483% wins on average, 4981027 nodes) +Best move win ratio: 60.9254% +4339pps (620pps per thread) +] +;B[jd];W[ie] +C[Thinking for 7825ms (474862ms time left) +Reusing 31987 nodes (1.1272566%) +36962 simulations (58.991867% wins on average, 4989928 nodes) +Best move win ratio: 60.12091% +4502pps (643pps per thread) +] +;B[gd];W[jc] +C[Thinking for 7802ms (466653ms time left) +Reusing 9661 nodes (0.49812785%) +35712 simulations (60.920788% wins on average, 4716951 nodes) +Best move win ratio: 62.06233% +4328pps (618pps per thread) +] +;B[ic];W[jb] +C[Thinking for 7779ms (458401ms time left) +Reusing 4647 nodes (0.14890322%) +36777 simulations (64.106224% wins on average, 4775051 nodes) +Best move win ratio: 64.928314% +4442pps (635pps per thread) +] +;B[kb];W[ja] +C[Thinking for 7754ms (450122ms time left) +Reusing 45820 nodes (1.1632267%) +37060 simulations (62.73705% wins on average, 4792636 nodes) +Best move win ratio: 63.867302% +4538pps (648pps per thread) +] +;B[md];W[ka] +C[Thinking for 7730ms (441957ms time left) +Reusing 28971 nodes (1.028932%) +36173 simulations (66.166405% wins on average, 4587453 nodes) +Best move win ratio: 66.8433% +4401pps (629pps per thread) +] +;B[la];W[mb] +C[Thinking for 7705ms (433739ms time left) +Reusing 274227 nodes (6.877571%) +36682 simulations (66.8675% wins on average, 4851695 nodes) +Best move win ratio: 67.33505% +4460pps (637pps per thread) +] +;B[mc];W[mf] +C[Thinking for 7679ms (425515ms time left) +Reusing 218909 nodes (5.0981297%) +37660 simulations (68.77092% wins on average, 4922388 nodes) +Best move win ratio: 69.24402% +4597pps (657pps per thread) +] +;B[ib];W[dk] +C[Thinking for 7653ms (417323ms time left) +Reusing 263891 nodes (6.2689095%) +38015 simulations (65.789055% wins on average, 4948859 nodes) +Best move win ratio: 66.46935% +4657pps (665pps per thread) +] +;B[hi];W[me] +C[Thinking for 7626ms (409161ms time left) +Reusing 32525 nodes (0.8049111%) +37927 simulations (68.573326% wins on average, 4672761 nodes) +Best move win ratio: 68.92557% +4660pps (666pps per thread) +] +;B[ia];W[ek] +C[Thinking for 7237ms (401023ms time left) +Reusing 221295 nodes (5.096962%) +37363 simulations (66.90591% wins on average, 4714143 nodes) +Best move win ratio: 67.5539% +4854pps (693pps per thread) +] +;B[ji];W[gi] +C[Thinking for 7213ms (393326ms time left) +Reusing 83107 nodes (2.2820263%) +37269 simulations (70.07578% wins on average, 4496172 nodes) +Best move win ratio: 70.27321% +4824pps (689pps per thread) +] +;B[jk];W[kj] +C[Thinking for 7187ms (385600ms time left) +Reusing 112206 nodes (2.6195045%) +38085 simulations (69.33313% wins on average, 4563931 nodes) +Best move win ratio: 69.74305% +4966pps (709pps per thread) +] +;B[ij];W[kl] +C[Thinking for 7161ms (377932ms time left) +Reusing 65845 nodes (1.7582291%) +37872 simulations (72.52166% wins on average, 4402148 nodes) +Best move win ratio: 72.65884% +4942pps (706pps per thread) +] +;B[ih];W[jg] +C[Thinking for 7135ms (370270ms time left) +Reusing 26711 nodes (0.71107125%) +36735 simulations (75.03026% wins on average, 4117572 nodes) +Best move win ratio: 75.30669% +4818pps (688pps per thread) +] +;B[gh];W[gj] +C[Thinking for 7048ms (362647ms time left) +Reusing 125090 nodes (3.2763038%) +37853 simulations (73.64169% wins on average, 4292227 nodes) +Best move win ratio: 73.85924% +5112pps (730pps per thread) +] +;B[hh];W[ik] +C[Thinking for 7024ms (355242ms time left) +Reusing 350789 nodes (19.07372%) +40185 simulations (66.27491% wins on average, 4682878 nodes) +Best move win ratio: 67.2879% +5377pps (768pps per thread) +] +;B[jj];W[jl] +C[Thinking for 6998ms (347769ms time left) +Reusing 91700 nodes (2.9864852%) +40862 simulations (65.8207% wins on average, 4390513 nodes) +Best move win ratio: 66.319824% +5502pps (786pps per thread) +] +;B[ki];W[bf] +C[Thinking for 6972ms (340343ms time left) +Reusing 83462 nodes (2.9327297%) +41816 simulations (66.94781% wins on average, 4411681 nodes) +Best move win ratio: 67.31797% +5662pps (809pps per thread) +] +;B[li];W[fi] +C[Thinking for 6946ms (332957ms time left) +Reusing 87255 nodes (3.0792582%) +42550 simulations (66.87382% wins on average, 4409779 nodes) +Best move win ratio: 67.30227% +5708pps (815pps per thread) +] +;B[be];W[fh] +C[Thinking for 6917ms (325503ms time left) +Reusing 38021 nodes (1.0028315%) +41590 simulations (70.40868% wins on average, 4171756 nodes) +Best move win ratio: 70.643005% +5606pps (801pps per thread) +] +;B[gg];W[fg] +C[Thinking for 6888ms (318085ms time left) +Reusing 1643250 nodes (41.35164%) +42269 simulations (69.7895% wins on average, 5767504 nodes) +Best move win ratio: 70.73655% +5761pps (823pps per thread) +] +;B[gf];W[ef] +C[Thinking for 6860ms (310748ms time left) +Reusing 383288 nodes (16.205776%) +43495 simulations (66.454346% wins on average, 4556873 nodes) +Best move win ratio: 67.58252% +5965pps (852pps per thread) +] +;B[df];W[il] +C[Thinking for 6832ms (303457ms time left) +Reusing 86639 nodes (3.3540018%) +45326 simulations (64.484566% wins on average, 4317905 nodes) +Best move win ratio: 64.95096% +6175pps (882pps per thread) +] +;B[ml];W[ae] +C[Thinking for 6801ms (296117ms time left) +Reusing 28397 nodes (0.82536584%) +45089 simulations (68.64307% wins on average, 4153681 nodes) +Best move win ratio: 69.02889% +6261pps (894pps per thread) +] +;B[ad];W[af] +C[Thinking for 6773ms (288916ms time left) +Reusing 129665 nodes (6.0531154%) +45349 simulations (67.610725% wins on average, 4168714 nodes) +Best move win ratio: 67.9409% +6216pps (888pps per thread) +] +;B[ei];W[lk] +C[Thinking for 6741ms (281621ms time left) +Reusing 189260 nodes (4.9507294%) +46173 simulations (66.62185% wins on average, 4209723 nodes) +Best move win ratio: 67.190605% +6472pps (925pps per thread) +] +;B[mk];W[mh] +C[Thinking for 6711ms (274487ms time left) +Reusing 454156 nodes (20.320034%) +47500 simulations (64.08611% wins on average, 4478365 nodes) +Best move win ratio: 65.19527% +6635pps (948pps per thread) +] +;B[mi];W[dh] +C[Thinking for 6680ms (267328ms time left) +Reusing 180954 nodes (6.245166%) +46770 simulations (64.67066% wins on average, 4003829 nodes) +Best move win ratio: 65.86778% +6599pps (943pps per thread) +] +;B[eg];W[ac] +C[Thinking for 6649ms (260241ms time left) +Reusing 1670308 nodes (60.787434%) +48336 simulations (61.26681% wins on average, 5535353 nodes) +Best move win ratio: 62.499535% +6847pps (978pps per thread) +] +;B[bd];W[lj] +C[Thinking for 6617ms (253182ms time left) +Reusing 418451 nodes (17.670452%) +48781 simulations (59.24123% wins on average, 4206614 nodes) +Best move win ratio: 60.097607% +6853pps (979pps per thread) +] +;B[mj];W[ff] +C[Thinking for 6583ms (246064ms time left) +Reusing 900107 nodes (26.392464%) +48944 simulations (58.639492% wins on average, 4615849 nodes) +Best move win ratio: 59.472393% +6980pps (997pps per thread) +] +;B[ll];W[he] +C[Thinking for 6549ms (239052ms time left) +Reusing 55254 nodes (2.1879106%) +50176 simulations (64.92687% wins on average, 3760739 nodes) +Best move win ratio: 65.08444% +7169pps (1024pps per thread) +] +;B[ge];W[hj] +C[Thinking for 6514ms (232053ms time left) +Reusing 1333324 nodes (36.728848%) +53039 simulations (62.071312% wins on average, 5193809 nodes) +Best move win ratio: 63.858147% +7700pps (1100pps per thread) +] +;B[lh];W[fj] +C[Thinking for 6481ms (225166ms time left) +Reusing 19984 nodes (1.0056643%) +53278 simulations (63.564777% wins on average, 3857743 nodes) +Best move win ratio: 64.138275% +7830pps (1119pps per thread) +] +;B[cf];W[bg] +C[Thinking for 6448ms (218362ms time left) +Reusing 274786 nodes (14.669344%) +53997 simulations (62.482418% wins on average, 4028913 nodes) +Best move win ratio: 62.75731% +7862pps (1123pps per thread) +] +;B[hd];W[ee] +C[Thinking for 6412ms (211495ms time left) +Reusing 30965 nodes (1.1118217%) +54997 simulations (66.60876% wins on average, 3743512 nodes) +Best move win ratio: 66.97944% +7968pps (1138pps per thread) +] +;B[kh];W[dc] +C[Thinking for 6373ms (204593ms time left) +Reusing 646300 nodes (19.348387%) +54504 simulations (65.959045% wins on average, 4244432 nodes) +Best move win ratio: 66.70516% +8047pps (1150pps per thread) +] +;B[kg];W[ig] +C[Thinking for 6335ms (197821ms time left) +Reusing 73371 nodes (3.3854797%) +52955 simulations (66.92422% wins on average, 3469668 nodes) +Best move win ratio: 67.14722% +7873pps (1125pps per thread) +] +;B[lf];W[cb] +C[Thinking for 6297ms (191095ms time left) +Reusing 1047912 nodes (36.601593%) +52614 simulations (63.721233% wins on average, 4342408 nodes) +Best move win ratio: 65.06463% +7901pps (1129pps per thread) +] +;B[bb];W[db] +C[Thinking for 6259ms (184436ms time left) +Reusing 801553 nodes (37.546333%) +52894 simulations (59.583855% wins on average, 4001888 nodes) +Best move win ratio: 61.09957% +7989pps (1141pps per thread) +] +;B[mg];W[ba] +C[Thinking for 6035ms (177816ms time left) +Reusing 44482 nodes (2.5913696%) +49106 simulations (69.378136% wins on average, 3030197 nodes) +Best move win ratio: 69.49293% +7603pps (1086pps per thread) +] +;B[ec];W[ab] +C[Thinking for 5994ms (171357ms time left) +Reusing 199985 nodes (6.6939087%) +50077 simulations (75.15292% wins on average, 3300084 nodes) +Best move win ratio: 75.00686% +7802pps (1115pps per thread) +] +;B[eb];W[bc] +C[Thinking for 5953ms (164939ms time left) +Reusing 23206 nodes (0.7123523%) +Search stopped early. Fastplay rule triggered. +16289 simulations (82.97508% wins on average, 1052378 nodes) +Best move win ratio: 83.03365% +7675pps (1096pps per thread) +] +;B[da];W[dj] +C[Thinking for 5971ms (162817ms time left) +Reusing 16290 nodes (1.5681043%) +Search stopped early. Fastplay rule triggered. +17238 simulations (83.83056% wins on average, 1131641 nodes) +Best move win ratio: 84.12297% +8122pps (1160pps per thread) +] +;B[km];W[le] +C[Thinking for 6090ms (160695ms time left) +Reusing 16259 nodes (1.795882%) +Search stopped early. Fastplay rule triggered. +17674 simulations (84.745674% wins on average, 1128853 nodes) +Best move win ratio: 85.08527% +8221pps (1174pps per thread) +] +;B[lg];W[di] +C[Thinking for 6216ms (158546ms time left) +Reusing 12637 nodes (1.7932683%) +Search stopped early. Fastplay rule triggered. +18018 simulations (82.57628% wins on average, 1181549 nodes) +Best move win ratio: 82.832184% +8148pps (1164pps per thread) +] +;B[jm];W[im] +C[Thinking for 5078ms (156335ms time left) +Reusing 11617 nodes (1.1499327%) +Search stopped early. Fastplay rule triggered. +15031 simulations (83.87578% wins on average, 964688 nodes) +Best move win ratio: 84.24395% +8291pps (1184pps per thread) +] +;B[lm];W[de] +C[Thinking for 5167ms (154522ms time left) +Reusing 11945 nodes (1.3564769%) +Search stopped early. Fastplay rule triggered. +15532 simulations (85.60111% wins on average, 972104 nodes) +Best move win ratio: 85.91567% +8482pps (1212pps per thread) +] +;B[ea];W[cm] +C[Thinking for 5260ms (152691ms time left) +Reusing 16857 nodes (2.7933729%) +Search stopped early. Fastplay rule triggered. +15936 simulations (88.70726% wins on average, 978072 nodes) +Best move win ratio: 88.87556% +8469pps (1210pps per thread) +] +;B[ca];W[am] +C[Thinking for 5358ms (150810ms time left) +Reusing 14356 nodes (1.5361552%) +Search stopped early. Fastplay rule triggered. +16269 simulations (89.23937% wins on average, 959592 nodes) +Best move win ratio: 89.246574% +8499pps (1214pps per thread) +] +;B[];W[] +C[Thinking for 5374ms (148896ms time left) +Reusing 58 nodes (0.006165687%) +Search stopped early. Fastplay rule triggered. +88751 simulations (95.21559% wins on average, 11994 nodes) +Best move win ratio: 100% +49530pps (7076pps per thread) +] +) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index da34af9e..41c69e0a 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -281,6 +281,12 @@ describe! interpreter { assert!(response.is_ok()); } + it "doesn't crash after loading a completed game" { + interpreter.read("loadsgf fixtures/sgf/final_score_crash.sgf\n").unwrap(); + let response = interpreter.read("final_score\n"); + assert_that(response, is(equal_to(ok("W+7.5")))) + } + } describe! name { @@ -369,6 +375,12 @@ describe! interpreter { assert!(response.is_ok()); } + it "doesn't crash after loading a completed game" { + interpreter.read("loadsgf fixtures/sgf/final_score_crash.sgf\n").unwrap(); + let response = interpreter.read("final_status_list dead\n"); + assert_that(response, is(equal_to(ok("TBD")))) + } + } // Gogui extensions From 74be7a4f1d1befe69241409839e57b9c8860a2ef Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Mon, 16 May 2016 09:27:15 +0200 Subject: [PATCH 06/19] More tests that crash the bot --- src/gtp/test.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index 41c69e0a..1a3dfb27 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -282,11 +282,22 @@ describe! interpreter { } it "doesn't crash after loading a completed game" { + interpreter.read("boardsize 9\n").unwrap(); + interpreter.read("clear_board\n").unwrap(); + interpreter.read("play b pass\n").unwrap(); + interpreter.read("play w pass\n").unwrap(); + let response = interpreter.read("final_score\n"); + assert_that(response, is(equal_to(ok("W+6.5")))); + } + + it "reports the correct score" { interpreter.read("loadsgf fixtures/sgf/final_score_crash.sgf\n").unwrap(); let response = interpreter.read("final_score\n"); assert_that(response, is(equal_to(ok("W+7.5")))) } + + } describe! name { @@ -376,6 +387,15 @@ describe! interpreter { } it "doesn't crash after loading a completed game" { + interpreter.read("boardsize 9\n").unwrap(); + interpreter.read("clear_board\n").unwrap(); + interpreter.read("play b pass\n").unwrap(); + interpreter.read("play w pass\n").unwrap(); + let response = interpreter.read("final_status_list dead\n"); + assert_that(response, is(equal_to(ok("")))); + } + + it "reports the correct list of dead stones" { interpreter.read("loadsgf fixtures/sgf/final_score_crash.sgf\n").unwrap(); let response = interpreter.read("final_status_list dead\n"); assert_that(response, is(equal_to(ok("TBD")))) From a69acee60ce04129522ac8c006f16aa871c54789 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 08:34:47 +0200 Subject: [PATCH 07/19] Reset game over status to allow proper scoring --- src/gtp/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gtp/mod.rs b/src/gtp/mod.rs index 03f64162..9bcd5378 100644 --- a/src/gtp/mod.rs +++ b/src/gtp/mod.rs @@ -307,12 +307,14 @@ impl<'a> GTPInterpreter<'a> { } fn execute_final_score(&mut self, _: &[&str]) -> Result { + self.game.reset_game_over(); Ok(self.controller.final_score(&self.game)) } fn execute_final_status_list(&mut self, arguments: &[&str]) -> Result { match arguments.get(0) { Some(kind) => { + self.game.reset_game_over(); self.controller.final_status_list(&self.game, kind) }, None => Err("missing argument".to_string()) From 0d91aad00f884b5ee55312a06d112686ee77ebf8 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 08:35:30 +0200 Subject: [PATCH 08/19] Don't run tests in parallel Some of the tests run on all cores. So don't run the test runner in parallel as well. --- ci/script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/script.sh b/ci/script.sh index 3a099a26..96657b1f 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -39,7 +39,7 @@ run_test_suite() { fi cargo build --target $TARGET --verbose - cargo test --target $TARGET + cargo test --target $TARGET -j 1 } main() { From cc0126f4acb438e20d20c55c90058702365ace42 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 09:31:04 +0200 Subject: [PATCH 09/19] =?UTF-8?q?Output=20percentage=20of=20scores=20GnuGo?= =?UTF-8?q?=20and=20Iomrsc=C3=A1la=C3=AD=20are=20agreeing=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/wins-from-benchmark-results.rb | 36 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/bin/wins-from-benchmark-results.rb b/bin/wins-from-benchmark-results.rb index 0f87a3c7..0a2781f0 100644 --- a/bin/wins-from-benchmark-results.rb +++ b/bin/wins-from-benchmark-results.rb @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2015 Urban Hafner +# Copyright (c) 2016 Urban Hafner # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files @@ -21,22 +22,37 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +require 'csv' -def data(contents) - contents.each_line.find_all {|l| l !~ /^#/ }.map do |l| - l.split(/\s+/)[3] - end +def parse_file(fn) + contents = File.read(fn) + relevant_lines = contents.each_line.find_all {|l| l !~ /^#/ } + CSV.parse(relevant_lines.map(&:strip).join("\n"), col_sep: "\t") end -def wins(file) - contents = File.read(file) - white = data(contents).find_all {|l| l =~ /W\+/ }.count - black = data(contents).find_all {|l| l =~ /B\+/ }.count +RES_B = 1 +RES_W = 2 +RES_R = 3 + +def wins(fn) + data = parse_file(fn) + white = data.find_all {|row| row[RES_R] =~ /W\+/ }.count + black = data.find_all {|row| row[RES_R] =~ /B\+/ }.count n = white + black p = white.to_f/n "#{(p*100).round(2)}% wins (#{white} games of #{n}, ± #{error(p: p, n: n, confidence: 0.95).round(2)} at 95%, ± #{error(p: p, n: n, confidence: 0.99).round(2)} at 99%)" end +def scoring(fn) + data = parse_file(fn) + relevant = data.find_all {|row| row[RES_R] !~ /[BW]\+R/ } + relevant.map {|row| row[RES_R] }.uniq.each {|s| puts s } + agreeing = relevant.find_all {|row| row[RES_W] == row[RES_B] }.count + n = relevant.length + p = agreeing.to_f/n + "#{(p*100).round(2)}% same score as GnuGo (#{agreeing} of #{n}, ± #{error(p: p, n: n, confidence: 0.95).round(2)} at 95%, ± #{error(p: p, n: n, confidence: 0.99).round(2)} at 99%)" +end + def z(confidence:) alpha = 1 - confidence (1 - 0.5*alpha)*2 @@ -48,5 +64,7 @@ def error(p:, n:, confidence:) Dir["*.dat"].each do |fn| next if fn =~ /summary\.dat/ - puts "#{fn}: #{wins(fn)}" + puts "#{fn}:" + puts "\t\t#{wins(fn)}" + puts "\t\t#{scoring(fn)}" end From 76bba7a3aa13a13bf60090b91237c62b78a22d5e Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 09:46:13 +0200 Subject: [PATCH 10/19] Fix tests --- src/gtp/test.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index 1a3dfb27..73d8b43c 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -290,14 +290,6 @@ describe! interpreter { assert_that(response, is(equal_to(ok("W+6.5")))); } - it "reports the correct score" { - interpreter.read("loadsgf fixtures/sgf/final_score_crash.sgf\n").unwrap(); - let response = interpreter.read("final_score\n"); - assert_that(response, is(equal_to(ok("W+7.5")))) - } - - - } describe! name { @@ -349,10 +341,10 @@ describe! interpreter { describe! final_status_list { before_each { - interpreter.read("boardsize 3\n").unwrap(); + interpreter.read("boardsize 9\n").unwrap(); interpreter.read("clear_board\n").unwrap(); interpreter.read("play b a1\n").unwrap(); - interpreter.read("play w b2\n").unwrap(); + interpreter.read("play w b9\n").unwrap(); } it "reports no dead stones" { @@ -360,9 +352,9 @@ describe! interpreter { assert_that(response, is(equal_to(ok("")))); } - it "reports one alive stone" { + it "reports two alive stone" { let response = interpreter.read("final_status_list alive\n"); - assert_that(response, is(equal_to(ok("A1 B2")))); + assert_that(response, is(equal_to(ok("A1 B9")))); } it "reports no seki stones" { @@ -395,12 +387,6 @@ describe! interpreter { assert_that(response, is(equal_to(ok("")))); } - it "reports the correct list of dead stones" { - interpreter.read("loadsgf fixtures/sgf/final_score_crash.sgf\n").unwrap(); - let response = interpreter.read("final_status_list dead\n"); - assert_that(response, is(equal_to(ok("TBD")))) - } - } // Gogui extensions @@ -469,10 +455,10 @@ describe! interpreter { describe! final_status_list { before_each { - interpreter.read("boardsize 3\n").unwrap(); + interpreter.read("boardsize 9\n").unwrap(); interpreter.read("clear_board\n").unwrap(); interpreter.read("play b a1\n").unwrap(); - interpreter.read("play w b2\n").unwrap(); + interpreter.read("play w b9\n").unwrap(); } it "reports no dead stones" { @@ -480,9 +466,9 @@ describe! interpreter { assert_that(response, is(equal_to(ok("")))); } - it "reports one alive stone" { + it "reports two alive stone" { let response = interpreter.read("final_status_list alive\n"); - assert_that(response, is(equal_to(ok("A1 B2")))); + assert_that(response, is(equal_to(ok("A1 B9")))); } it "reports no seki stones" { From 39abd10f228239fd9b889a041f32a717c904be88 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 13:27:15 +0200 Subject: [PATCH 11/19] Remove debug output --- bin/wins-from-benchmark-results.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/wins-from-benchmark-results.rb b/bin/wins-from-benchmark-results.rb index 0a2781f0..e5254ead 100644 --- a/bin/wins-from-benchmark-results.rb +++ b/bin/wins-from-benchmark-results.rb @@ -46,7 +46,6 @@ def wins(fn) def scoring(fn) data = parse_file(fn) relevant = data.find_all {|row| row[RES_R] !~ /[BW]\+R/ } - relevant.map {|row| row[RES_R] }.uniq.each {|s| puts s } agreeing = relevant.find_all {|row| row[RES_W] == row[RES_B] }.count n = relevant.length p = agreeing.to_f/n From 117c7bf99c90490516c0a4b6429a6626a30eaaf5 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 13:29:01 +0200 Subject: [PATCH 12/19] Play more games on 13x13 and 19x19 --- bin/benchmark | 5 +++-- bin/benchmark-ec2 | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/benchmark b/bin/benchmark index 6d50e965..c5801a13 100755 --- a/bin/benchmark +++ b/bin/benchmark @@ -25,14 +25,15 @@ set -e -GAMES=500 - if [ $1 == "9" ]; then TIME="5m" + GAMES=500 elif [ $1 == "13" ]; then TIME="10m" + GAMES=1000 elif [ $1 == "19" ]; then TIME="20m" + GAMES=1000 else echo "Size '$1' isn't supported!" exit 1 diff --git a/bin/benchmark-ec2 b/bin/benchmark-ec2 index cd180924..71c885ed 100755 --- a/bin/benchmark-ec2 +++ b/bin/benchmark-ec2 @@ -28,14 +28,15 @@ set -e -GAMES=500 - if [ $1 == "9" ]; then TIME="5m" + GAMES=500 elif [ $1 == "13" ]; then TIME="10m" + GAMES=1000 elif [ $1 == "19" ]; then TIME="20m" + GAMES=1000 else echo "Size '$1' isn't supported!" exit 1 From b5e0c0f281d48e71e2b069693fe615782cc81566 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 19:17:39 +0200 Subject: [PATCH 13/19] Test for a bug in this scoring rewrite A bug in the board/GTP setup that builds an empty tree and no search is happening and therefore a pass is generated as the first move. --- src/gtp/test.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index 73d8b43c..037459d0 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -33,6 +33,7 @@ pub use super::GTPInterpreter; pub use hamcrest::assert_that; pub use hamcrest::equal_to; pub use hamcrest::is; +pub use hamcrest::is_not; pub use std::sync::Arc; pub fn err(s: &'static str) -> Result { @@ -141,6 +142,14 @@ describe! interpreter { let response = interpreter.read("genmove b\n"); assert!(response.is_ok()); } + + it "does not generate a pass on an empty board" { + interpreter.read("boardsize 9\n").unwrap(); + interpreter.read("clear_board\n").unwrap(); + let response = interpreter.read("genmove b\n"); + assert!(response.is_ok()); + assert_that(response.unwrap(), is_not(equal_to("pass".to_string()))); + } } describe! kgs { From f7a56fcc6f7d33b3aa93e4679c46362d0ab392c6 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 20:14:52 +0200 Subject: [PATCH 14/19] Remove SGF file for removed test --- fixtures/sgf/final_score_crash.sgf | 483 ----------------------------- 1 file changed, 483 deletions(-) delete mode 100644 fixtures/sgf/final_score_crash.sgf diff --git a/fixtures/sgf/final_score_crash.sgf b/fixtures/sgf/final_score_crash.sgf deleted file mode 100644 index 796105ff..00000000 --- a/fixtures/sgf/final_score_crash.sgf +++ /dev/null @@ -1,483 +0,0 @@ -(;FF[4]CA[UTF-8]AP[gogui-twogtp:1.4.9]SZ[13] -KM[6.5]PB[GNU Go:3.8]PW[Iomrascalai]DT[2016-05-13]RE[W+7.5] -C[Black command: gnugo --mode gtp --level 0 --chinese-rules --positional-superko -White command: cargo run --release -- --log --rules chinese -Black version: 3.8 -White version: 0.3.1 -Result[Black\]: W+7.5 -Result[White\]: W+44.5 -Referee: gnugo --mode gtp --level 0 --chinese-rules --positional-superko -Result[Referee\]: W+7.5 -Host: macaron.local -Date: May 13, 2016 9:34:10 PM CEST] -;B[jf];W[gk] -C[Thinking for 8121ms (600000ms time left) -31222 simulations (48.241135% wins on average, 5164067 nodes) -Best move win ratio: 52.591904% -3746pps (535pps per thread) -] -;B[kc];W[cg] -C[Thinking for 8105ms (591665ms time left) -Reusing 4782 nodes (3.6030471%) -30668 simulations (48.601643% wins on average, 4994961 nodes) -Best move win ratio: 51.944668% -3689pps (527pps per thread) -] -;B[fe];W[cj] -C[Thinking for 8088ms (583352ms time left) -Reusing 165 nodes (0.07876007%) -31699 simulations (48.5221% wins on average, 5071248 nodes) -Best move win ratio: 52.716076% -3826pps (547pps per thread) -] -;B[ce];W[dd] -C[Thinking for 8072ms (575067ms time left) -Reusing 163 nodes (0.12389219%) -32723 simulations (47.34047% wins on average, 5174856 nodes) -Best move win ratio: 52.15376% -3943pps (563pps per thread) -] -;B[cd];W[hg] -C[Thinking for 8055ms (566768ms time left) -Reusing 33222 nodes (20.048277%) -32104 simulations (47.32501% wins on average, 5042155 nodes) -Best move win ratio: 52.276672% -3872pps (553pps per thread) -] -;B[cc];W[jh] -C[Thinking for 8037ms (558477ms time left) -Reusing 7957 nodes (3.2195547%) -33406 simulations (47.409546% wins on average, 5143282 nodes) -Best move win ratio: 52.843254% -4032pps (576pps per thread) -] -;B[de];W[je] -C[Thinking for 8020ms (550192ms time left) -Reusing 22903 nodes (6.178511%) -31948 simulations (51.116455% wins on average, 4864677 nodes) -Best move win ratio: 54.526085% -3868pps (553pps per thread) -] -;B[le];W[if] -C[Thinking for 8002ms (541934ms time left) -Reusing 155 nodes (0.07865425%) -33338 simulations (53.465305% wins on average, 4991387 nodes) -Best move win ratio: 56.931824% -4040pps (577pps per thread) -] -;B[ed];W[kk] -C[Thinking for 7984ms (533683ms time left) -Reusing 17441 nodes (3.3164854%) -31913 simulations (61.41191% wins on average, 4704408 nodes) -Best move win ratio: 62.045246% -3768pps (538pps per thread) -] -;B[id];W[kf] -C[Thinking for 7962ms (525215ms time left) -Reusing 10886 nodes (0.31619594%) -31663 simulations (62.13313% wins on average, 4602824 nodes) -Best move win ratio: 62.6848% -3739pps (534pps per thread) -] -;B[lf];W[lg] -C[Thinking for 7939ms (516748ms time left) -Reusing 55431 nodes (1.4852384%) -32370 simulations (62.92435% wins on average, 4686282 nodes) -Best move win ratio: 63.658733% -3837pps (548pps per thread) -] -;B[eh];W[ke] -C[Thinking for 7917ms (508311ms time left) -Reusing 35991 nodes (1.005691%) -33681 simulations (60.532806% wins on average, 4794841 nodes) -Best move win ratio: 61.4297% -4027pps (575pps per thread) -] -;B[dg];W[ld] -C[Thinking for 7895ms (499948ms time left) -Reusing 50225 nodes (1.7218451%) -35298 simulations (63.833965% wins on average, 4978907 nodes) -Best move win ratio: 64.473015% -4187pps (598pps per thread) -] -;B[ej];W[ch] -C[Thinking for 7871ms (491518ms time left) -Reusing 41482 nodes (0.98971987%) -35176 simulations (61.358578% wins on average, 4884312 nodes) -Best move win ratio: 62.461918% -4220pps (603pps per thread) -] -;B[lc];W[kd] -C[Thinking for 7848ms (483183ms time left) -Reusing 74142 nodes (2.1851144%) -36105 simulations (59.7483% wins on average, 4981027 nodes) -Best move win ratio: 60.9254% -4339pps (620pps per thread) -] -;B[jd];W[ie] -C[Thinking for 7825ms (474862ms time left) -Reusing 31987 nodes (1.1272566%) -36962 simulations (58.991867% wins on average, 4989928 nodes) -Best move win ratio: 60.12091% -4502pps (643pps per thread) -] -;B[gd];W[jc] -C[Thinking for 7802ms (466653ms time left) -Reusing 9661 nodes (0.49812785%) -35712 simulations (60.920788% wins on average, 4716951 nodes) -Best move win ratio: 62.06233% -4328pps (618pps per thread) -] -;B[ic];W[jb] -C[Thinking for 7779ms (458401ms time left) -Reusing 4647 nodes (0.14890322%) -36777 simulations (64.106224% wins on average, 4775051 nodes) -Best move win ratio: 64.928314% -4442pps (635pps per thread) -] -;B[kb];W[ja] -C[Thinking for 7754ms (450122ms time left) -Reusing 45820 nodes (1.1632267%) -37060 simulations (62.73705% wins on average, 4792636 nodes) -Best move win ratio: 63.867302% -4538pps (648pps per thread) -] -;B[md];W[ka] -C[Thinking for 7730ms (441957ms time left) -Reusing 28971 nodes (1.028932%) -36173 simulations (66.166405% wins on average, 4587453 nodes) -Best move win ratio: 66.8433% -4401pps (629pps per thread) -] -;B[la];W[mb] -C[Thinking for 7705ms (433739ms time left) -Reusing 274227 nodes (6.877571%) -36682 simulations (66.8675% wins on average, 4851695 nodes) -Best move win ratio: 67.33505% -4460pps (637pps per thread) -] -;B[mc];W[mf] -C[Thinking for 7679ms (425515ms time left) -Reusing 218909 nodes (5.0981297%) -37660 simulations (68.77092% wins on average, 4922388 nodes) -Best move win ratio: 69.24402% -4597pps (657pps per thread) -] -;B[ib];W[dk] -C[Thinking for 7653ms (417323ms time left) -Reusing 263891 nodes (6.2689095%) -38015 simulations (65.789055% wins on average, 4948859 nodes) -Best move win ratio: 66.46935% -4657pps (665pps per thread) -] -;B[hi];W[me] -C[Thinking for 7626ms (409161ms time left) -Reusing 32525 nodes (0.8049111%) -37927 simulations (68.573326% wins on average, 4672761 nodes) -Best move win ratio: 68.92557% -4660pps (666pps per thread) -] -;B[ia];W[ek] -C[Thinking for 7237ms (401023ms time left) -Reusing 221295 nodes (5.096962%) -37363 simulations (66.90591% wins on average, 4714143 nodes) -Best move win ratio: 67.5539% -4854pps (693pps per thread) -] -;B[ji];W[gi] -C[Thinking for 7213ms (393326ms time left) -Reusing 83107 nodes (2.2820263%) -37269 simulations (70.07578% wins on average, 4496172 nodes) -Best move win ratio: 70.27321% -4824pps (689pps per thread) -] -;B[jk];W[kj] -C[Thinking for 7187ms (385600ms time left) -Reusing 112206 nodes (2.6195045%) -38085 simulations (69.33313% wins on average, 4563931 nodes) -Best move win ratio: 69.74305% -4966pps (709pps per thread) -] -;B[ij];W[kl] -C[Thinking for 7161ms (377932ms time left) -Reusing 65845 nodes (1.7582291%) -37872 simulations (72.52166% wins on average, 4402148 nodes) -Best move win ratio: 72.65884% -4942pps (706pps per thread) -] -;B[ih];W[jg] -C[Thinking for 7135ms (370270ms time left) -Reusing 26711 nodes (0.71107125%) -36735 simulations (75.03026% wins on average, 4117572 nodes) -Best move win ratio: 75.30669% -4818pps (688pps per thread) -] -;B[gh];W[gj] -C[Thinking for 7048ms (362647ms time left) -Reusing 125090 nodes (3.2763038%) -37853 simulations (73.64169% wins on average, 4292227 nodes) -Best move win ratio: 73.85924% -5112pps (730pps per thread) -] -;B[hh];W[ik] -C[Thinking for 7024ms (355242ms time left) -Reusing 350789 nodes (19.07372%) -40185 simulations (66.27491% wins on average, 4682878 nodes) -Best move win ratio: 67.2879% -5377pps (768pps per thread) -] -;B[jj];W[jl] -C[Thinking for 6998ms (347769ms time left) -Reusing 91700 nodes (2.9864852%) -40862 simulations (65.8207% wins on average, 4390513 nodes) -Best move win ratio: 66.319824% -5502pps (786pps per thread) -] -;B[ki];W[bf] -C[Thinking for 6972ms (340343ms time left) -Reusing 83462 nodes (2.9327297%) -41816 simulations (66.94781% wins on average, 4411681 nodes) -Best move win ratio: 67.31797% -5662pps (809pps per thread) -] -;B[li];W[fi] -C[Thinking for 6946ms (332957ms time left) -Reusing 87255 nodes (3.0792582%) -42550 simulations (66.87382% wins on average, 4409779 nodes) -Best move win ratio: 67.30227% -5708pps (815pps per thread) -] -;B[be];W[fh] -C[Thinking for 6917ms (325503ms time left) -Reusing 38021 nodes (1.0028315%) -41590 simulations (70.40868% wins on average, 4171756 nodes) -Best move win ratio: 70.643005% -5606pps (801pps per thread) -] -;B[gg];W[fg] -C[Thinking for 6888ms (318085ms time left) -Reusing 1643250 nodes (41.35164%) -42269 simulations (69.7895% wins on average, 5767504 nodes) -Best move win ratio: 70.73655% -5761pps (823pps per thread) -] -;B[gf];W[ef] -C[Thinking for 6860ms (310748ms time left) -Reusing 383288 nodes (16.205776%) -43495 simulations (66.454346% wins on average, 4556873 nodes) -Best move win ratio: 67.58252% -5965pps (852pps per thread) -] -;B[df];W[il] -C[Thinking for 6832ms (303457ms time left) -Reusing 86639 nodes (3.3540018%) -45326 simulations (64.484566% wins on average, 4317905 nodes) -Best move win ratio: 64.95096% -6175pps (882pps per thread) -] -;B[ml];W[ae] -C[Thinking for 6801ms (296117ms time left) -Reusing 28397 nodes (0.82536584%) -45089 simulations (68.64307% wins on average, 4153681 nodes) -Best move win ratio: 69.02889% -6261pps (894pps per thread) -] -;B[ad];W[af] -C[Thinking for 6773ms (288916ms time left) -Reusing 129665 nodes (6.0531154%) -45349 simulations (67.610725% wins on average, 4168714 nodes) -Best move win ratio: 67.9409% -6216pps (888pps per thread) -] -;B[ei];W[lk] -C[Thinking for 6741ms (281621ms time left) -Reusing 189260 nodes (4.9507294%) -46173 simulations (66.62185% wins on average, 4209723 nodes) -Best move win ratio: 67.190605% -6472pps (925pps per thread) -] -;B[mk];W[mh] -C[Thinking for 6711ms (274487ms time left) -Reusing 454156 nodes (20.320034%) -47500 simulations (64.08611% wins on average, 4478365 nodes) -Best move win ratio: 65.19527% -6635pps (948pps per thread) -] -;B[mi];W[dh] -C[Thinking for 6680ms (267328ms time left) -Reusing 180954 nodes (6.245166%) -46770 simulations (64.67066% wins on average, 4003829 nodes) -Best move win ratio: 65.86778% -6599pps (943pps per thread) -] -;B[eg];W[ac] -C[Thinking for 6649ms (260241ms time left) -Reusing 1670308 nodes (60.787434%) -48336 simulations (61.26681% wins on average, 5535353 nodes) -Best move win ratio: 62.499535% -6847pps (978pps per thread) -] -;B[bd];W[lj] -C[Thinking for 6617ms (253182ms time left) -Reusing 418451 nodes (17.670452%) -48781 simulations (59.24123% wins on average, 4206614 nodes) -Best move win ratio: 60.097607% -6853pps (979pps per thread) -] -;B[mj];W[ff] -C[Thinking for 6583ms (246064ms time left) -Reusing 900107 nodes (26.392464%) -48944 simulations (58.639492% wins on average, 4615849 nodes) -Best move win ratio: 59.472393% -6980pps (997pps per thread) -] -;B[ll];W[he] -C[Thinking for 6549ms (239052ms time left) -Reusing 55254 nodes (2.1879106%) -50176 simulations (64.92687% wins on average, 3760739 nodes) -Best move win ratio: 65.08444% -7169pps (1024pps per thread) -] -;B[ge];W[hj] -C[Thinking for 6514ms (232053ms time left) -Reusing 1333324 nodes (36.728848%) -53039 simulations (62.071312% wins on average, 5193809 nodes) -Best move win ratio: 63.858147% -7700pps (1100pps per thread) -] -;B[lh];W[fj] -C[Thinking for 6481ms (225166ms time left) -Reusing 19984 nodes (1.0056643%) -53278 simulations (63.564777% wins on average, 3857743 nodes) -Best move win ratio: 64.138275% -7830pps (1119pps per thread) -] -;B[cf];W[bg] -C[Thinking for 6448ms (218362ms time left) -Reusing 274786 nodes (14.669344%) -53997 simulations (62.482418% wins on average, 4028913 nodes) -Best move win ratio: 62.75731% -7862pps (1123pps per thread) -] -;B[hd];W[ee] -C[Thinking for 6412ms (211495ms time left) -Reusing 30965 nodes (1.1118217%) -54997 simulations (66.60876% wins on average, 3743512 nodes) -Best move win ratio: 66.97944% -7968pps (1138pps per thread) -] -;B[kh];W[dc] -C[Thinking for 6373ms (204593ms time left) -Reusing 646300 nodes (19.348387%) -54504 simulations (65.959045% wins on average, 4244432 nodes) -Best move win ratio: 66.70516% -8047pps (1150pps per thread) -] -;B[kg];W[ig] -C[Thinking for 6335ms (197821ms time left) -Reusing 73371 nodes (3.3854797%) -52955 simulations (66.92422% wins on average, 3469668 nodes) -Best move win ratio: 67.14722% -7873pps (1125pps per thread) -] -;B[lf];W[cb] -C[Thinking for 6297ms (191095ms time left) -Reusing 1047912 nodes (36.601593%) -52614 simulations (63.721233% wins on average, 4342408 nodes) -Best move win ratio: 65.06463% -7901pps (1129pps per thread) -] -;B[bb];W[db] -C[Thinking for 6259ms (184436ms time left) -Reusing 801553 nodes (37.546333%) -52894 simulations (59.583855% wins on average, 4001888 nodes) -Best move win ratio: 61.09957% -7989pps (1141pps per thread) -] -;B[mg];W[ba] -C[Thinking for 6035ms (177816ms time left) -Reusing 44482 nodes (2.5913696%) -49106 simulations (69.378136% wins on average, 3030197 nodes) -Best move win ratio: 69.49293% -7603pps (1086pps per thread) -] -;B[ec];W[ab] -C[Thinking for 5994ms (171357ms time left) -Reusing 199985 nodes (6.6939087%) -50077 simulations (75.15292% wins on average, 3300084 nodes) -Best move win ratio: 75.00686% -7802pps (1115pps per thread) -] -;B[eb];W[bc] -C[Thinking for 5953ms (164939ms time left) -Reusing 23206 nodes (0.7123523%) -Search stopped early. Fastplay rule triggered. -16289 simulations (82.97508% wins on average, 1052378 nodes) -Best move win ratio: 83.03365% -7675pps (1096pps per thread) -] -;B[da];W[dj] -C[Thinking for 5971ms (162817ms time left) -Reusing 16290 nodes (1.5681043%) -Search stopped early. Fastplay rule triggered. -17238 simulations (83.83056% wins on average, 1131641 nodes) -Best move win ratio: 84.12297% -8122pps (1160pps per thread) -] -;B[km];W[le] -C[Thinking for 6090ms (160695ms time left) -Reusing 16259 nodes (1.795882%) -Search stopped early. Fastplay rule triggered. -17674 simulations (84.745674% wins on average, 1128853 nodes) -Best move win ratio: 85.08527% -8221pps (1174pps per thread) -] -;B[lg];W[di] -C[Thinking for 6216ms (158546ms time left) -Reusing 12637 nodes (1.7932683%) -Search stopped early. Fastplay rule triggered. -18018 simulations (82.57628% wins on average, 1181549 nodes) -Best move win ratio: 82.832184% -8148pps (1164pps per thread) -] -;B[jm];W[im] -C[Thinking for 5078ms (156335ms time left) -Reusing 11617 nodes (1.1499327%) -Search stopped early. Fastplay rule triggered. -15031 simulations (83.87578% wins on average, 964688 nodes) -Best move win ratio: 84.24395% -8291pps (1184pps per thread) -] -;B[lm];W[de] -C[Thinking for 5167ms (154522ms time left) -Reusing 11945 nodes (1.3564769%) -Search stopped early. Fastplay rule triggered. -15532 simulations (85.60111% wins on average, 972104 nodes) -Best move win ratio: 85.91567% -8482pps (1212pps per thread) -] -;B[ea];W[cm] -C[Thinking for 5260ms (152691ms time left) -Reusing 16857 nodes (2.7933729%) -Search stopped early. Fastplay rule triggered. -15936 simulations (88.70726% wins on average, 978072 nodes) -Best move win ratio: 88.87556% -8469pps (1210pps per thread) -] -;B[ca];W[am] -C[Thinking for 5358ms (150810ms time left) -Reusing 14356 nodes (1.5361552%) -Search stopped early. Fastplay rule triggered. -16269 simulations (89.23937% wins on average, 959592 nodes) -Best move win ratio: 89.246574% -8499pps (1214pps per thread) -] -;B[];W[] -C[Thinking for 5374ms (148896ms time left) -Reusing 58 nodes (0.006165687%) -Search stopped early. Fastplay rule triggered. -88751 simulations (95.21559% wins on average, 11994 nodes) -Best move win ratio: 100% -49530pps (7076pps per thread) -] -) From 87300fbc4c8465a5a553209e2baafb47d5ca2e2e Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 17 May 2016 20:43:02 +0200 Subject: [PATCH 15/19] Setup tree before checking if it's empty If we do it the other way round we always pass as the tree appears to contain no children. --- src/engine/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 09d29d6e..69e569a8 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -147,12 +147,12 @@ impl Engine { } fn generic_genmove(&mut self, color: Color, game: &Game, timer: &Timer, cleanup: bool) -> (Move,usize) { + self.genmove_setup(color, game); if self.root.has_no_children() { self.config.log(format!("No moves to simulate!")); return (Pass(color), self.root.playouts()); } let stop = |win_ratio, _: &OwnershipStatistics| { timer.ran_out_of_time(win_ratio) }; - self.genmove_setup(color, game); self.search(game, stop); let msg = format!("{} simulations ({}% wins on average, {} nodes)", self.root.playouts(), self.root.win_ratio()*100.0, self.root.descendants()); self.config.log(msg); From a9300099ca171de2ecf87c768828ef9f2c6ac38d Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Wed, 18 May 2016 07:58:55 +0200 Subject: [PATCH 16/19] Test that scoring works on games without legal moves --- fixtures/sgf/no-legal-moves-left.sgf | 3 +++ src/gtp/test.rs | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 fixtures/sgf/no-legal-moves-left.sgf diff --git a/fixtures/sgf/no-legal-moves-left.sgf b/fixtures/sgf/no-legal-moves-left.sgf new file mode 100644 index 00000000..2e0d422e --- /dev/null +++ b/fixtures/sgf/no-legal-moves-left.sgf @@ -0,0 +1,3 @@ +(;FF[4]CA[UTF-8]AP[GoGui:1.4.9]SZ[3] +KM[0]DT[2016-05-18] +;B[ba];W[];B[bb];W[];B[bc];W[];B[ab];W[];B[cb]) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index 037459d0..62abfca5 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -299,6 +299,11 @@ describe! interpreter { assert_that(response, is(equal_to(ok("W+6.5")))); } + it "doesn't crash after loading a game with no legal moves" { + interpreter.read("loadsgf fixtures/sgf/no-legal-moves-left.sgf\n").unwrap(); + let response = interpreter.read("final_score\n"); + assert_that(response, is(equal_to(ok("B+9")))); + } } describe! name { @@ -361,7 +366,7 @@ describe! interpreter { assert_that(response, is(equal_to(ok("")))); } - it "reports two alive stone" { + it "reports two alive stones" { let response = interpreter.read("final_status_list alive\n"); assert_that(response, is(equal_to(ok("A1 B9")))); } @@ -396,6 +401,12 @@ describe! interpreter { assert_that(response, is(equal_to(ok("")))); } + it "doesn't crash after loading a game with no legal moves" { + interpreter.read("loadsgf fixtures/sgf/no-legal-moves-left.sgf\n").unwrap(); + let response = interpreter.read("final_status_list dead\n"); + assert_that(response, is(equal_to(ok("")))); + } + } // Gogui extensions From 6407d50e0894307892a738ea550ec9e5087dd39a Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Wed, 18 May 2016 09:21:13 +0200 Subject: [PATCH 17/19] Don't run tests in parallel on AppVeyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 38da8ffd..387a1694 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,7 @@ build: false # TODO modify this phase as you see fit test_script: - cargo build --verbose - - cargo test + - cargo test -j 1 before_deploy: # Generate artifacts for release From 0174bebf7b410c573ba23760656c6d62b3c69f2e Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Tue, 31 May 2016 20:27:05 +0200 Subject: [PATCH 18/19] Add imrscl-donplayouts command --- src/config/defaults.toml | 1 + src/config/mod.rs | 7 ++++++- src/engine/controller/mod.rs | 26 +++++++++++++++----------- src/engine/mod.rs | 20 +++++++------------- src/gtp/mod.rs | 17 +++++++++++++++++ src/gtp/test.rs | 2 +- src/ownership/mod.rs | 6 ------ 7 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/config/defaults.toml b/src/config/defaults.toml index ede32d81..2772bced 100644 --- a/src/config/defaults.toml +++ b/src/config/defaults.toml @@ -34,3 +34,4 @@ score_weight = 0.0653414 ownership_prior = 87 ownership_cutoff = 0.892867 +playouts = 10000 diff --git a/src/config/mod.rs b/src/config/mod.rs index ec2c7d24..fd8440a4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -286,6 +286,8 @@ pub struct ScoringConfig { /// Value between 0.0 and 1.0 which is the cutoff above which a /// point is considered to be owned by a color. pub ownership_cutoff: f32, + /// Number of playouts to run when trying to determine the final score of a board. + pub playouts: usize, } impl ScoringConfig { @@ -299,6 +301,7 @@ impl ScoringConfig { ScoringConfig { ownership_prior: Self::as_integer(&table, "ownership_prior"), ownership_cutoff: Self::as_float(&table, "ownership_cutoff"), + playouts: Self::as_integer(&table, "playouts"), } } @@ -351,7 +354,9 @@ impl Config { #[test] pub fn test_config() -> Config { - Self::default(false, false, Ruleset::KgsChinese, Some(1)) + let mut config = Self::default(false, false, Ruleset::KgsChinese, Some(1)); + config.scoring.playouts = 10; + config } /// Uses the TOML returned by `Config::toml()` and returns a diff --git a/src/engine/controller/mod.rs b/src/engine/controller/mod.rs index 9382df0f..53459caa 100644 --- a/src/engine/controller/mod.rs +++ b/src/engine/controller/mod.rs @@ -34,7 +34,7 @@ use std::sync::Arc; pub struct EngineController { config: Arc, engine: Engine, - scoring: bool, + run_playouts_for_scoring: bool, } impl EngineController { @@ -43,13 +43,13 @@ impl EngineController { EngineController { config: config, engine: engine, - scoring: false, + run_playouts_for_scoring: true, } } pub fn reset(&mut self, size: u8, komi: f32) { + self.run_playouts_for_scoring = true; self.engine.reset(size, komi); - self.scoring = false; } pub fn ownership_statistics(&self) -> String { @@ -57,23 +57,27 @@ impl EngineController { } pub fn final_score(&mut self, game: &Game) -> String { - self.calculate_score(game); + self.run_playouts(game); FinalScore::new(self.config.clone(), game, self.ownership()).score() } pub fn final_status_list(&mut self, game: &Game, kind: &str) -> Result { - self.calculate_score(game); + self.run_playouts(game); FinalScore::new(self.config.clone(), game, self.ownership()).status_list(kind) + } + pub fn donplayouts(&mut self, game: &Game, playouts: usize) { + self.run_playouts_for_scoring = false; + self.engine.donplayouts(game, playouts); } pub fn genmove(&mut self, color: Color, game: &Game, timer: &Timer) -> (Move, usize) { - self.scoring = false; + self.run_playouts_for_scoring = true; self.engine.genmove(color, game, timer) } pub fn genmove_cleanup(&mut self, color: Color, game: &Game, timer: &Timer) -> (Move, usize) { - self.scoring = false; + self.run_playouts_for_scoring = true; self.engine.genmove_cleanup(color, game, timer) } @@ -81,9 +85,9 @@ impl EngineController { &self.engine.ownership() } - fn calculate_score(&mut self, game: &Game) { - if self.scoring { return; } - self.scoring = true; - self.engine.calculate_score(game); + fn run_playouts(&mut self, game: &Game) { + if !self.run_playouts_for_scoring { return; } + let playouts = self.config.scoring.playouts; + self.donplayouts(game, playouts); } } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 69e569a8..0bba51b5 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -46,7 +46,6 @@ use std::sync::mpsc::Receiver; use std::sync::mpsc::Sender; use std::sync::mpsc::channel; use std::thread::spawn; -use time::Duration; use time::PreciseTime; macro_rules! check { @@ -152,7 +151,7 @@ impl Engine { self.config.log(format!("No moves to simulate!")); return (Pass(color), self.root.playouts()); } - let stop = |win_ratio, _: &OwnershipStatistics| { timer.ran_out_of_time(win_ratio) }; + let stop = |win_ratio, _| { timer.ran_out_of_time(win_ratio) }; self.search(game, stop); let msg = format!("{} simulations ({}% wins on average, {} nodes)", self.root.playouts(), self.root.win_ratio()*100.0, self.root.descendants()); self.config.log(msg); @@ -162,7 +161,7 @@ impl Engine { (m,playouts) } - fn search(&mut self, game: &Game, stop: F) where F: for<'r> Fn(f32, &'r OwnershipStatistics) -> bool { + fn search(&mut self, game: &Game, stop: F) where F: Fn(f32, usize) -> bool { self.spin_up(game); loop { let win_ratio = { @@ -170,7 +169,7 @@ impl Engine { best.win_ratio() }; let done = { - stop(win_ratio, &self.ownership) + stop(win_ratio, self.root.playouts()) }; if done { return self.spin_down(); @@ -182,9 +181,7 @@ impl Engine { } } - /// Run playouts until all coordinates have a clear owner. - pub fn calculate_score(&mut self, game: &Game) { - let start = PreciseTime::now(); + pub fn donplayouts(&mut self, game: &Game, playouts: usize) { self.ownership = OwnershipStatistics::new(self.config.clone(), game.size(), game.komi()); if self.root.has_no_children() { let color = match game.last_move() { @@ -193,12 +190,9 @@ impl Engine { }; self.root = Node::root(game, color, self.config.clone()); } - let stop = |_, ownership: &OwnershipStatistics| { - if start.to(PreciseTime::now()) < Duration::seconds(10) { - false - } else { - ownership.decided(game) || (start.to(PreciseTime::now()) > Duration::seconds(30)) - } + let initial_playouts = self.root.playouts(); + let stop = |_, current_playouts: usize| { + (current_playouts - initial_playouts) > playouts }; self.search(game, stop); } diff --git a/src/gtp/mod.rs b/src/gtp/mod.rs index 9bcd5378..20c13125 100644 --- a/src/gtp/mod.rs +++ b/src/gtp/mod.rs @@ -63,6 +63,7 @@ impl<'a> GTPInterpreter<'a> { "final_status_list", "genmove", "gogui-analyze_commands", + "imrscl-donplayouts", "imrscl-ownership", "kgs-genmove_cleanup", "known_command", @@ -125,6 +126,7 @@ impl<'a> GTPInterpreter<'a> { "final_status_list" => self.execute_final_status_list(arguments), "genmove" => self.execute_genmove(arguments), "gogui-analyze_commands" => self.execute_gogui_analyze_commands(arguments), + "imrscl-donplayouts" => self.execute_imrscl_donplayouts(arguments), "imrscl-ownership" => self.execute_imrscl_ownership(arguments), "kgs-genmove_cleanup" => self.execute_kgs_genmove_cleanup(arguments), "known_command" => self.execute_known_command(arguments), @@ -276,6 +278,21 @@ impl<'a> GTPInterpreter<'a> { } } + fn execute_imrscl_donplayouts(&mut self, arguments: &[&str]) -> Result { + match arguments.get(0) { + Some(playouts_str) => { + match playouts_str.parse() { + Ok(playouts) => { + self.controller.donplayouts(&self.game, playouts); + Ok("".to_string()) + }, + Err(e) => Err(format!("{:?}", e)) + } + } + None => Err("missing argument".to_string()), + } + } + fn execute_imrscl_ownership(&mut self, _: &[&str]) -> Result { let stats = self.controller.ownership_statistics(); Ok(stats) diff --git a/src/gtp/test.rs b/src/gtp/test.rs index 62abfca5..4b443e9e 100644 --- a/src/gtp/test.rs +++ b/src/gtp/test.rs @@ -238,7 +238,7 @@ describe! interpreter { it "no newline at end" { let response = interpreter.read("list_commands\n"); - let expected = "boardsize\nclear_board\nfinal_score\nfinal_status_list\ngenmove\ngogui-analyze_commands\nimrscl-ownership\nkgs-genmove_cleanup\nknown_command\nkomi\nlist_commands\nloadsgf\nname\nplay\nprotocol_version\nquit\nreg_genmove\nshowboard\ntime_left\ntime_settings\nversion"; + let expected = "boardsize\nclear_board\nfinal_score\nfinal_status_list\ngenmove\ngogui-analyze_commands\nimrscl-donplayouts\nimrscl-ownership\nkgs-genmove_cleanup\nknown_command\nkomi\nlist_commands\nloadsgf\nname\nplay\nprotocol_version\nquit\nreg_genmove\nshowboard\ntime_left\ntime_settings\nversion"; assert_that(response, is(equal_to(ok(expected)))); } diff --git a/src/ownership/mod.rs b/src/ownership/mod.rs index 6018cef3..feba39cb 100644 --- a/src/ownership/mod.rs +++ b/src/ownership/mod.rs @@ -26,7 +26,6 @@ use board::Coord; use board::Empty; use board::White; use config::Config; -use game::Game; use score::Score; use core::fmt::Display; @@ -102,11 +101,6 @@ impl OwnershipStatistics { fraction > self.config.scoring.ownership_cutoff } - pub fn decided(&self, game: &Game) -> bool { - Coord::for_board_size(game.size()).iter() - .all(|coord| self.coord_decided(coord)) - } - pub fn gfx(&self) -> String { let mut b = String::from("BLACK"); let mut w = String::from("WHITE"); From 360688f37b6e17aad607c4521978bf46cda6e527 Mon Sep 17 00:00:00 2001 From: Urban Hafner Date: Wed, 1 Jun 2016 08:51:35 +0200 Subject: [PATCH 19/19] Lower time limit for 9x9 benchmarks --- bin/benchmark | 2 +- bin/benchmark-ec2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/benchmark b/bin/benchmark index c5801a13..ac4f0496 100755 --- a/bin/benchmark +++ b/bin/benchmark @@ -26,7 +26,7 @@ set -e if [ $1 == "9" ]; then - TIME="5m" + TIME="2m" GAMES=500 elif [ $1 == "13" ]; then TIME="10m" diff --git a/bin/benchmark-ec2 b/bin/benchmark-ec2 index 71c885ed..748c104f 100755 --- a/bin/benchmark-ec2 +++ b/bin/benchmark-ec2 @@ -29,7 +29,7 @@ set -e if [ $1 == "9" ]; then - TIME="5m" + TIME="2m" GAMES=500 elif [ $1 == "13" ]; then TIME="10m"