diff --git a/Cargo.lock b/Cargo.lock index 0ffe49c..285ce74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "ace" -version = "1.0.17" +version = "1.0.18" dependencies = [ "byteorder", "phf", diff --git a/Cargo.toml b/Cargo.toml index adc0756..e5d4d24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ace" -version = "1.0.17" +version = "1.0.18" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/engine/chara.rs b/src/engine/chara.rs index a08707b..7089df5 100644 --- a/src/engine/chara.rs +++ b/src/engine/chara.rs @@ -1,7 +1,7 @@ // The main module of the chess engine. // ANY changes to the board MUST be done through the character's methods! -use std::{cmp::max, collections::{HashMap, HashSet}, sync::mpsc::Receiver, thread, time::{Duration, Instant}}; +use std::{cmp::{max, Ordering}, collections::{HashMap, HashSet}, sync::mpsc::Receiver, thread, time::{Duration, Instant}}; use rand::{rngs::ThreadRng, Rng}; use crate::frame::{util::*, board::Board}; use super::{clock::Clock, options::Options, weights::Weights, zobrist::Zobrist}; @@ -64,7 +64,6 @@ pub struct Chara { last_score: i32, // last score for the current thinking side (?) force: bool, // do not start thinking or pondering hard: bool, // always pondering - nbc: u64, // nodes between comms (Dependent on ^) loop_force: bool, // ignore command input in listen() for a current cycle playother: bool, // send score for other side draw_offered: bool, // by engine itself @@ -115,7 +114,6 @@ impl Chara { last_score: 0, force: false, hard: true, - nbc: NODES_BETWEEN_COMMS_HARD, loop_force: false, playother: false, draw_offered: false, @@ -157,15 +155,10 @@ impl Chara { }, "easy" => { self.hard = false; - self.nbc = NODES_BETWEEN_COMMS_EASY; }, "draw" => { let temp = self.playother; - if self.hard { - self.playother = true; - } else { - self.playother = false; - } + self.playother = self.hard; if self.considerate_draw(0) { self.post(); println!("offer draw"); @@ -187,15 +180,18 @@ impl Chara { }, "hard" => { self.hard = true; - self.nbc = NODES_BETWEEN_COMMS_HARD; }, "level" => { - if cmd.len() > 4 { - println!("Error (too many parameters): {}", line.trim()); - } else if cmd.len() < 4 { - println!("Error (too few parameters): {}", line.trim()); - } else { - self.clock.level(cmd[1], cmd[2], cmd[3]); + match cmd.len().cmp(&4) { + Ordering::Equal => { + self.clock.level(cmd[1], cmd[2], cmd[3]); + }, + Ordering::Less => { + println!("Error (too few parameters): {}", line.trim()); + }, + Ordering::Greater => { + println!("Error (too many parameters): {}", line.trim()); + } } }, "new" => { @@ -206,7 +202,7 @@ impl Chara { self.post = false; }, "option" => { - if cmd.len() < 1 { + if cmd.is_empty() { println!("Error (too few parameters): {}", line.trim()); } else { self.options.parse(cmd[1]); @@ -387,7 +383,7 @@ impl Chara { self.abort = true; } - if self.nodes & self.nbc == 0 { + if self.nodes & NODES_BETWEEN_COMMS_PASSIVE == 0 || (self.playother && self.nodes & NODES_BETWEEN_COMMS_ACTIVE == 0) { let last = self.rx.try_recv(); if last.is_ok() { let line = last.unwrap(); @@ -407,7 +403,7 @@ impl Chara { self.post = false; }, "option" => { - if cmd.len() < 1 { + if cmd.is_empty() { println!("Error (too few parameters): {}", line.trim()); } else { self.options.parse(cmd[1]); @@ -550,7 +546,9 @@ impl Chara { } } - println!("DEBUG\tApproximate time spent: {} ms", self.ts.elapsed().as_millis()); + let approx = self.ts.elapsed().as_millis() + 1; + self.clock.time_deduct(&approx); + println!("DEBUG\tApproximate time spent: {} ms", approx); EvalMove::new(self.tpv[0][0], score) } diff --git a/src/engine/clock.rs b/src/engine/clock.rs index 123cd5a..37d151d 100644 --- a/src/engine/clock.rs +++ b/src/engine/clock.rs @@ -48,8 +48,7 @@ impl Clock { return 1; } alloc -= fs; - self.time -= alloc; - return alloc; + alloc }, TimeControl::Incremental => { let divider = 70 - min(fullmove_counter, 10) * 2 - min(fullmove_counter, 20); @@ -60,35 +59,38 @@ impl Clock { } // todo: fix when it's not 2 am self.time += alloc; - let nalloc = self.time - 200; - self.time -= nalloc; - return nalloc; + self.time - 200 }, TimeControl::Deadline => { - return self.inc - k - (self.inc >> 7); + self.inc - k - (self.inc >> 7) } } } + #[inline] + pub fn time_deduct(&mut self, penalty: &u128) { + self.time -= *penalty; + } + // ? pub fn is_it_time_for_draw(&self) -> i32 { match self.time_control { TimeControl::Conventional => { if self.time < 60000 || self.otim < 60000 { - return max(min((i32::try_from(self.otim).unwrap_or(120000) - i32::try_from(self.time).unwrap_or(120000)) / 100, 400), -400); + max(min((i32::try_from(self.otim).unwrap_or(120000) - i32::try_from(self.time).unwrap_or(120000)) / 100, 400), -400) } else { - return -200; + -200 } }, TimeControl::Incremental => { if self.time < 60000 || self.otim < 60000 { - return max(min((i32::try_from(self.otim).unwrap_or(120000) - i32::try_from(self.time).unwrap_or(120000)) / 100, 400), -400); + max(min((i32::try_from(self.otim).unwrap_or(120000) - i32::try_from(self.time).unwrap_or(120000)) / 100, 400), -400) } else { - return -200; + -200 } }, TimeControl::Deadline => { - return 0; + 0 }, } } @@ -98,7 +100,7 @@ impl Clock { pub fn level(&mut self, mps: &str, btr: &str, inc: &str) { self.mps = mps.parse::().unwrap(); - let bts = btr.split(":").collect::>(); + let bts = btr.split(':').collect::>(); let mut bt = bts[0].parse::().unwrap() * 60 * 1000; if bts.len() > 1 { bt += bts[1].parse::().unwrap() * 1000; diff --git a/src/engine/options.rs b/src/engine/options.rs index ab294bc..e20132c 100644 --- a/src/engine/options.rs +++ b/src/engine/options.rs @@ -21,7 +21,7 @@ impl Options { pub fn parse(&mut self, query: &str) { let cmd = query.split('=').collect::>(); - if cmd.len() < 1 { + if cmd.is_empty() { println!("Error (bad syntax for option): {}", query); return; } diff --git a/src/frame/util.rs b/src/frame/util.rs index 77577db..bb8dca2 100644 --- a/src/frame/util.rs +++ b/src/frame/util.rs @@ -7,7 +7,7 @@ use std::{cmp::min, fs, io::Cursor, path::Path}; use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian}; use phf::phf_map; -pub const MYNAME: &str = "Akira CE v1.0.17"; +pub const MYNAME: &str = "Akira CE v1.0.18"; /* LIMITATIONS */ @@ -17,10 +17,10 @@ pub const CACHED_LEAVES_LIMIT: usize = ( (MEMORY_LIMIT_MB >> 2) << 18 ) / 3; pub const CACHED_BRANCHES_LIMIT: usize = (MEMORY_LIMIT_MB >> 3) << 16; // 128 bit pub const HALF_DEPTH_LIMIT: usize = 64; pub const HALF_DEPTH_LIMIT_SAFE: i16 = 50; // for chara.think() -pub const NODES_BETWEEN_UPDATES: u64 = 0b00000000111111111111; -pub const NODES_BETWEEN_COMMS_EASY: u64 = 0b00000111111111111111; -pub const NODES_BETWEEN_COMMS_HARD: u64 = 0b00000000111111111111; -pub const NODES_BETWEEN_POSTS: u64 = 0b00011111111111111111; +pub const NODES_BETWEEN_UPDATES: u64 = 0b00000000111111111111; +pub const NODES_BETWEEN_COMMS_PASSIVE: u64 = 0b00000111111111111111; +pub const NODES_BETWEEN_COMMS_ACTIVE: u64 = 0b00000000111111111111; +pub const NODES_BETWEEN_POSTS: u64 = 0b00011111111111111111; pub const PONDER_TIME: u128 = 1 << 63; // no limit /* SPECIFIED PATHES */