use super::super::interface::*;
use rand::Rng;
pub(super) fn clamp_value(value: Evaluation) -> Evaluation {
if value > BEST_EVAL - 100 {
value - 1
} else if value < WORST_EVAL + 100 {
value + 1
} else {
value
}
}
pub(super) fn unclamp_value(value: Evaluation) -> Evaluation {
if value > BEST_EVAL - 100 {
BEST_EVAL
} else if value < WORST_EVAL + 100 {
WORST_EVAL
} else {
value
}
}
pub(super) fn move_id<G: Game>(s: &<G as Game>::S, m: Option<<G as Game>::M>) -> String {
if let Some(mov) = m {
G::notation(s, mov).unwrap_or("no notation impl".to_string())
} else {
"none".to_string()
}
}
pub(super) fn pv_string<G: Game>(path: &[<G as Game>::M], state: &<G as Game>::S) -> String
where
<G as Game>::M: Copy,
<G as Game>::S: Clone,
{
let mut state = state.clone();
let mut out = String::new();
for (i, &m) in (0..).zip(path.iter()) {
if i > 0 {
out.push_str("; ");
}
out.push_str(move_id::<G>(&state, Some(m)).as_str());
if let Some(new_state) = G::apply(&mut state, m) {
state = new_state;
}
}
out
}
pub(super) fn move_to_front<M: Eq>(m: M, moves: &mut [M]) {
for i in 0..moves.len() {
if moves[i] == m {
moves[0..i + 1].rotate_right(1);
break;
}
}
}
pub(super) struct ValueMove<M> {
pub(super) value: Evaluation,
pub(super) m: M,
}
impl<M> ValueMove<M> {
pub(super) fn new(value: Evaluation, m: M) -> Self {
Self { value, m }
}
#[cfg(not(target_arch = "wasm32"))]
pub(super) fn max(&mut self, value: Evaluation, m: M) {
if value > self.value {
self.value = value;
self.m = m;
}
}
#[cfg(not(target_arch = "wasm32"))]
pub(super) fn into_inner(self) -> (Evaluation, M) {
(self.value, self.m)
}
}
static PRIMES: [usize; 16] = [
14323, 18713, 19463, 30553, 33469, 45343, 50221, 51991, 53201, 56923, 64891, 72763, 74471,
81647, 92581, 94693,
];
pub(super) fn random_best<T, F: Fn(&T) -> f32>(set: &[T], score_fn: F) -> Option<&T> {
let n = set.len();
let r = rand::rng().random_range(0..n * PRIMES.len());
let mut i = r / PRIMES.len();
let stride = PRIMES[r % PRIMES.len()];
let mut best_score = f32::NEG_INFINITY;
let mut best = None;
for _ in 0..n {
let score = score_fn(&set[i]);
debug_assert!(!score.is_nan());
if score > best_score {
best_score = score;
best = Some(&set[i]);
}
i = (i + stride) % n;
}
best
}