use crate::game::rules::Variant;
use crate::game::state::GameState;
use crate::search::symmetry::apply_transform;
pub const LO: i16 = -20;
pub const HI: i16 = 29;
pub const PSIDE: usize = (HI - LO + 1) as usize; pub const PCELLS: usize = PSIDE * PSIDE; pub const VALUE_LEN: usize = PCELLS + 3;
#[inline]
fn pindex(x: i16, y: i16) -> usize {
(x - LO) as usize * PSIDE + (y - LO) as usize
}
pub fn encode_value(state: &GameState, t: usize) -> Vec<f32> {
let k = 2 * state.variant.len() as i16 - 1; let mut plane = vec![0f32; PCELLS];
let (mut minx, mut miny, mut maxx, mut maxy) = (i16::MAX, i16::MAX, i16::MIN, i16::MIN);
for &cell in &state.board.cells {
let (x, y) = apply_transform(t, cell, k);
if (LO..=HI).contains(&x) && (LO..=HI).contains(&y) {
plane[pindex(x, y)] = 1.0;
}
minx = minx.min(x);
miny = miny.min(y);
maxx = maxx.max(x);
maxy = maxy.max(y);
}
let mut f = plane;
f.push(state.history.len() as f32 / 200.0);
let (w, h) = if state.board.cells.is_empty() {
(0.0, 0.0)
} else {
((maxx - minx) as f32 / 60.0, (maxy - miny) as f32 / 60.0)
};
f.push(w);
f.push(h);
f
}
pub fn encode_value_natural(state: &GameState) -> Vec<f32> {
encode_value(state, 0)
}
#[inline]
pub fn value_target(final_len: u32) -> f32 {
final_len as f32 / 200.0
}
#[inline]
pub fn is_t5(variant: Variant) -> bool {
variant == Variant::T5
}
#[cfg(test)]
mod tests {
use super::*;
use crate::game::moves::legal_moves;
#[test]
fn window_is_d4_invariant_and_holds_the_cross() {
let st = GameState::new(Variant::T5);
for t in 0..8 {
let f = encode_value(&st, t);
assert_eq!(f.len(), VALUE_LEN);
let occ: f32 = f[..PCELLS].iter().sum();
assert_eq!(
occ as usize,
st.board.cells.len(),
"transform {t} lost cells"
);
}
}
#[test]
fn occupancy_grows_with_moves() {
let mut st = GameState::new(Variant::T5);
let before: f32 = encode_value(&st, 0)[..PCELLS].iter().sum();
for _ in 0..10 {
let ms = legal_moves(&st);
if ms.is_empty() {
break;
}
st.apply(ms[0]);
}
let after: f32 = encode_value(&st, 0)[..PCELLS].iter().sum();
assert!(after > before, "occupancy should grow as moves are played");
}
}