diff --git a/Cargo.lock b/Cargo.lock index a263e80..191ea32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "cfg-if" version = "1.0.0" @@ -101,6 +107,16 @@ version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -115,6 +131,7 @@ name = "min_max" version = "0.1.0" dependencies = [ "console", + "parking_lot", "rand", "rayon", "strum", @@ -122,6 +139,29 @@ dependencies = [ "thousands", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -196,6 +236,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -208,6 +257,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + [[package]] name = "strum" version = "0.25.0" @@ -268,7 +323,7 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", ] [[package]] @@ -277,13 +332,28 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -292,38 +362,80 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index 9485828..e91d685 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,10 @@ rayon = "1.8" rand = "0.8" console = "0.15" thousands = "0.2" +parking_lot = "0.12" [profile.release] debug = true +lto = 'thin' +panic = 'abort' +codegen-units = 1 diff --git a/src/game/connect4.rs b/src/game/connect4.rs index 75ddeef..95f5e60 100644 --- a/src/game/connect4.rs +++ b/src/game/connect4.rs @@ -151,9 +151,7 @@ impl ConnectFour { self.play(player, NonZeroUsize::new(column).unwrap()) } - pub fn get_winner_coords( - &self, - ) -> Option<[::Coordinate; 4]> { + pub fn get_winner_coords(&self) -> Option<[::Coordinate; 4]> { if self.last_played_coords.is_none() { return None; } @@ -304,11 +302,8 @@ impl ConnectFour { self.winner = Some(counting_player); return; } - let count_opposite = self.count_in_direction( - last_coords, - count_direction.opposite(), - 3 - count, - ); + let count_opposite = + self.count_in_direction(last_coords, count_direction.opposite(), 3 - count); if count + count_opposite == 3 { self.winner = Some(counting_player); return; @@ -337,7 +332,7 @@ impl ConnectFour { } } - const RANDOMIZE_POSSIBLE_PLAYS: bool = false; + const RANDOMIZE_POSSIBLE_PLAYS: bool = true; } impl Game for ConnectFour { @@ -460,8 +455,8 @@ impl Game for ConnectFour { let order: [usize; 7] = if Self::RANDOMIZE_POSSIBLE_PLAYS { match rand::thread_rng().gen_range(0..=2) { 0 => [4, 3, 5, 2, 6, 1, 7], - 1 => [3, 5, 4, 2, 6, 1, 7], - _ => [2, 6, 4, 3, 5, 1, 7], + 1 => [3, 5, 4, 6, 2, 1, 7], + _ => [6, 2, 4, 5, 3, 1, 7], } } else { [4, 3, 5, 2, 6, 1, 7] diff --git a/src/min_max.rs b/src/min_max.rs index 96dd7bf..64aa444 100644 --- a/src/min_max.rs +++ b/src/min_max.rs @@ -1,7 +1,8 @@ use std::sync::atomic::Ordering::Relaxed; use std::sync::atomic::{AtomicBool, AtomicI32}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use rayon::iter::*; use crate::game::player::Player; @@ -58,7 +59,9 @@ impl GameNode { } } - const FORK_DEPTH: u32 = 4; + const FIRST_FORK: i32 = 3; + + const FORK_INTERVAL: i32 = 4; const USE_GAME_SCORE: bool = true; @@ -85,7 +88,7 @@ impl GameNode { worst_sibling_score: Arc>, #[cfg(debug_assertions)] call_count: Arc, ) -> G::Score { - assert!(self.depth() >= real_plays, "Negative exploration"); + debug_assert!(self.depth() >= real_plays, "Negative exploration"); #[cfg(debug_assertions)] call_count.fetch_add(1, Relaxed); @@ -125,7 +128,7 @@ impl GameNode { #[cfg(debug_assertions)] call_count.clone(), ); - let mut worst_child_score = worst_child_score.lock().unwrap(); + let mut worst_child_score = worst_child_score.lock(); // println!("maximize: {maximize}, child: {child_score} worst child: {worst_child_score}"); if (maximize && child_score > *worst_child_score) @@ -134,7 +137,7 @@ impl GameNode { *worst_child_score = child_score; } let parent_maximize = !maximize; - let worst_sibling_score = worst_sibling_score.lock().unwrap(); + let worst_sibling_score = worst_sibling_score.lock(); // if the parent will not choose us if (parent_maximize && *worst_child_score < *worst_sibling_score) @@ -158,14 +161,14 @@ impl GameNode { //print!("F"); maybe_explore_children(child) }); - let weight = (*worst_child_score.lock().unwrap()).into(); + let weight = (*worst_child_score.lock()).into(); self.set_weight(weight); weight.unwrap() } else { self.children .iter_mut() .try_for_each(|(_, child)| maybe_explore_children(child)); - let weight = (*worst_child_score.lock().unwrap()).into(); + let weight = (*worst_child_score.lock()).into(); self.set_weight(weight); weight.unwrap() }; @@ -178,8 +181,8 @@ impl GameNode { } fn is_parallelize_depth(&self, real_plays: u32) -> bool { - // no need to check whether it overflows as there won't be u32::MAX plays - self.depth().overflowing_sub(real_plays).0 == Self::FORK_DEPTH && Self::MULTI_THREADING + let depth = self.depth() as i32 - real_plays as i32; + (depth - Self::FIRST_FORK) % Self::FORK_INTERVAL == 0 && Self::MULTI_THREADING } /// Returns true if childrens should be checked for win or draw, false if they were already checked