use std::{str::FromStr, sync::mpsc::channel, thread};
use blunders_engine::Fen as _;
use shakmaty::{Chess, FromSetup as _, Move};
use shakmaty_uci::{ParseUciMoveError, UciMove};
use crate::state::Store;
use super::Engine;
pub struct BlunderEngine {
store: Store,
}
fn to_move(r: blunders_engine::SearchResult, game: &Chess) -> Option<Move> {
let bm = r.best_move;
UciMove::from_str(&format!("{}", bm))
.and_then(|um| um.to_move(game).map_err(|_| ParseUciMoveError))
.ok()
}
impl Engine for BlunderEngine {
fn new_game(&self) {}
fn go(
&self,
fen: shakmaty::fen::Fen,
white_time: chrono::Duration,
black_time: chrono::Duration,
) {
if let Ok(pos) = blunders_engine::Position::parse_fen(&fen.to_string()) {
let (tx, rx) = channel::<blunders_engine::SearchResult>();
let store = self.store.clone();
let game = Chess::from_setup(fen.as_setup().clone(), shakmaty::CastlingMode::Standard)
.unwrap();
let mut engine = blunders_engine::EngineBuilder::new()
.position(pos)
.transpositions_mb(10)
.debug(false)
.build();
thread::spawn(move || {
rx.recv().map(|result| {
let m =
to_move(result, &game).expect("blunders move failed to parse correctly");
store.update_engine(super::EngineState::PendingMove(m));
})
});
let _ = engine.search(
blunders_engine::Mode::standard(
white_time.num_milliseconds() as i32,
black_time.num_milliseconds() as i32,
None,
None,
None,
None,
),
tx,
);
}
}
}
pub fn connect_engine(store: Store) -> BlunderEngine {
BlunderEngine { store }
}