1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::prelude::v1::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
#[cfg(feature = "std")]
fn default_system_time() -> u128 {
use std::time::SystemTime;
SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis()
}
#[cfg(not(feature = "std"))]
fn default_system_time() -> u128 {
0
}
#[derive(Clone)]
pub struct Clock {
pub system_time: Arc<dyn Fn() -> u128 + Send + Sync + 'static>,
pub polling_nodes_count: u64,
pub started_at: u128,
moves_level: u16,
moves_remaining: u16,
time_remaining: u64,
last_nodes_count: u64,
is_finished: Arc<AtomicBool>,
is_level: bool
}
impl Clock {
pub fn new(moves: u16, time: u64) -> Clock {
let system_time = Arc::new(default_system_time);
Clock {
system_time: system_time,
polling_nodes_count: 100,
started_at: 0,
moves_level: moves,
moves_remaining: moves,
time_remaining: time,
last_nodes_count: 0,
is_finished: Arc::new(AtomicBool::new(false)),
is_level: true
}
}
pub fn start(&mut self, ply: usize) {
self.is_finished.store(false, Ordering::Relaxed);
self.last_nodes_count = 0;
self.started_at = (self.system_time)();
if self.is_level {
assert!(ply > 0);
let moves_done = (((ply - 1) / 2) as u16) % self.moves_level;
self.moves_remaining = self.moves_level - moves_done;
}
}
pub fn stop(&mut self) {
self.is_finished.store(true, Ordering::Relaxed);
}
pub fn disable_level(&mut self) {
self.is_level = false;
}
pub fn set_time(&mut self, time: u64) {
self.time_remaining = time;
}
pub fn allocated_time(&self) -> u64 {
self.time_remaining / self.moves_remaining as u64
}
pub fn elapsed_time(&self) -> u64 {
((self.system_time)() - self.started_at) as u64
}
pub fn poll(&mut self, nodes_count: u64) -> bool {
if nodes_count - self.last_nodes_count > self.polling_nodes_count {
self.last_nodes_count = nodes_count;
let time_between_polls = self.polling_nodes_count / 4;
let time_to_play = 25;
let delta = time_between_polls + time_to_play;
if delta + self.elapsed_time() > self.allocated_time() {
self.is_finished.store(true, Ordering::Relaxed);
}
}
self.is_finished.load(Ordering::Relaxed)
}
}