use crate::time::Instant;
use crate::types::Color;
pub type TimePoint = i64;
#[derive(Clone)]
pub struct LimitsType {
pub time: [TimePoint; Color::NUM],
pub inc: [TimePoint; Color::NUM],
pub byoyomi: [TimePoint; Color::NUM],
pub movetime: TimePoint,
pub rtime: TimePoint,
pub depth: i32,
pub mate: i32,
pub perft: i32,
pub infinite: bool,
pub nodes: u64,
pub ponder: bool,
pub multi_pv: usize,
pub search_moves: Vec<crate::types::Move>,
pub(crate) start_time: Option<Instant>,
}
impl Default for LimitsType {
fn default() -> Self {
Self {
time: [0; Color::NUM],
inc: [0; Color::NUM],
byoyomi: [0; Color::NUM],
movetime: 0,
rtime: 0,
depth: 0,
mate: 0,
perft: 0,
infinite: false,
nodes: 0,
ponder: false,
multi_pv: 1, search_moves: Vec::new(),
start_time: None,
}
}
}
impl LimitsType {
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn use_time_management(&self) -> bool {
self.mate == 0
&& self.movetime == 0
&& self.depth == 0
&& self.nodes == 0
&& self.perft == 0
&& !self.infinite
}
pub fn set_start_time(&mut self) {
self.start_time = Some(Instant::now());
}
pub fn elapsed(&self) -> TimePoint {
self.start_time.map(|t| t.elapsed().as_millis() as TimePoint).unwrap_or(0)
}
#[inline]
pub fn time_left(&self, color: Color) -> TimePoint {
self.time[color.index()]
}
#[inline]
pub fn byoyomi_time(&self, color: Color) -> TimePoint {
self.byoyomi[color.index()]
}
#[inline]
pub fn increment(&self, color: Color) -> TimePoint {
self.inc[color.index()]
}
#[inline]
pub fn has_depth_limit(&self) -> bool {
self.depth > 0
}
#[inline]
pub fn has_nodes_limit(&self) -> bool {
self.nodes > 0
}
#[inline]
pub fn has_movetime(&self) -> bool {
self.movetime > 0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_limits_default() {
let limits = LimitsType::default();
assert_eq!(limits.time[0], 0);
assert_eq!(limits.time[1], 0);
assert_eq!(limits.depth, 0);
assert_eq!(limits.rtime, 0);
assert!(!limits.infinite);
assert!(limits.search_moves.is_empty());
}
#[test]
fn test_use_time_management() {
let mut limits = LimitsType::new();
assert!(limits.use_time_management());
limits.depth = 10;
assert!(!limits.use_time_management());
limits.depth = 0;
limits.infinite = true;
assert!(!limits.use_time_management());
limits.infinite = false;
limits.nodes = 10000;
assert!(!limits.use_time_management());
limits.nodes = 0;
limits.movetime = 1000;
assert!(!limits.use_time_management());
}
#[test]
fn test_time_left() {
let mut limits = LimitsType::new();
limits.time[Color::Black.index()] = 60000; limits.time[Color::White.index()] = 30000;
assert_eq!(limits.time_left(Color::Black), 60000);
assert_eq!(limits.time_left(Color::White), 30000);
}
#[test]
fn test_byoyomi() {
let mut limits = LimitsType::new();
limits.byoyomi[Color::Black.index()] = 30000;
assert_eq!(limits.byoyomi_time(Color::Black), 30000);
assert_eq!(limits.byoyomi_time(Color::White), 0);
}
#[test]
fn test_elapsed() {
let mut limits = LimitsType::new();
limits.set_start_time();
std::thread::sleep(std::time::Duration::from_millis(10));
let elapsed = limits.elapsed();
assert!(elapsed >= 10);
assert!(elapsed < 1000); }
#[test]
fn test_has_limits() {
let mut limits = LimitsType::new();
assert!(!limits.has_depth_limit());
assert!(!limits.has_nodes_limit());
assert!(!limits.has_movetime());
limits.depth = 10;
assert!(limits.has_depth_limit());
limits.nodes = 10000;
assert!(limits.has_nodes_limit());
limits.movetime = 1000;
assert!(limits.has_movetime());
}
}