Skip to content

Commit

Permalink
fix uci bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscoBSalgueiro committed Oct 16, 2023
1 parent 31435d5 commit 089973d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 45 deletions.
87 changes: 49 additions & 38 deletions src-tauri/src/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub struct EngineProcess {
last_depth: u8,
best_moves: Vec<BestMoves>,
fen: Fen,
multipv: u16,
logs: Vec<EngineLog>,
}

Expand All @@ -64,6 +65,7 @@ impl EngineProcess {
best_moves: Vec::new(),
fen: Fen::default(),
logs: Vec::new(),
multipv: 1,
},
BufReader::new(child.stdout.take().ok_or(Error::NoStdout)?).lines(),
))
Expand All @@ -78,6 +80,12 @@ impl EngineProcess {
}

async fn set_options(&mut self, options: EngineOptions) -> Result<(), Error> {
let fen: Fen = options.fen.parse()?;
let pos: Chess = match fen.into_position(CastlingMode::Standard) {
Ok(p) => p,
Err(e) => e.ignore_too_much_material()?,
};
self.multipv = options.multipv.min(pos.legal_moves().len() as u16);
self.set_option("Threads", &options.threads.to_string())
.await?;
self.set_option("MultiPV", &options.multipv.to_string())
Expand Down Expand Up @@ -190,12 +198,20 @@ fn parse_uci_attrs(attrs: Vec<UciInfoAttribute>, fen: &Fen) -> Result<BestMoves,
UciInfoAttribute::MultiPv(multipv) => {
best_moves.multipv = multipv;
}
UciInfoAttribute::Score { cp, mate, .. } => {
UciInfoAttribute::Score {
cp,
mate,
lower_bound,
upper_bound,
} => {
if let Some(cp) = cp {
best_moves.score = Score::Cp(cp);
} else if let Some(mate) = mate {
best_moves.score = Score::Mate(mate);
}
if lower_bound.unwrap_or(false) || upper_bound.unwrap_or(false) {
return Err(Error::LowerOrUpperBound);
}
}
_ => (),
}
Expand Down Expand Up @@ -325,28 +341,23 @@ pub async fn get_best_moves(
) -> Result<(), Error> {
let path = PathBuf::from(&engine);

let parsed_fen: Fen = options.fen.parse()?;
let pos: Chess = match parsed_fen.clone().into_position(CastlingMode::Standard) {
Ok(p) => p,
Err(e) => e.ignore_too_much_material()?,
};

let mut options = options.clone();
options.multipv = options.multipv.min(pos.legal_moves().len() as u16);

let key = (tab.clone(), engine.clone());

if state.engine_processes.contains_key(&key) {
{
let process = state.engine_processes.get_mut(&key).unwrap();
let mut process = process.lock().await;
if process.stop().await.is_ok() {
process.set_options(options.clone()).await?;
process.go(&go_mode).await?;
return Ok(());
}
process.stop().await?;
}
state.engine_processes.remove(&key).unwrap();
// give time for engine to stop and process previous lines
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
{
let process = state.engine_processes.get_mut(&key).unwrap();
let mut process = process.lock().await;
process.set_options(options.clone()).await?;
process.go(&go_mode).await?;
}
return Ok(());
}

let (mut process, mut reader) = EngineProcess::new(path)?;
Expand All @@ -355,36 +366,36 @@ pub async fn get_best_moves(

let process = Arc::new(Mutex::new(process));

state.engine_processes.insert(key, process.clone());
state.engine_processes.insert(key.clone(), process.clone());

loop {
let line_opt = reader.next_line().await?;
while let Some(line) = reader.next_line().await? {
let mut proc = process.lock().await;
if let Some(line) = line_opt {
if let UciMessage::Info(attrs) = parse_one(&line) {
if let Ok(best_moves) = parse_uci_attrs(attrs, &proc.fen) {
let multipv = best_moves.multipv;
let cur_depth = best_moves.depth;
proc.best_moves.push(best_moves);
if multipv == options.multipv {
if proc.best_moves.iter().all(|x| x.depth == cur_depth)
&& cur_depth >= proc.last_depth
{
BestMovesPayload {
best_lines: proc.best_moves.clone(),
engine: engine.clone(),
tab: tab.clone(),
}
.emit_all(&app)?;
proc.last_depth = cur_depth;
if let UciMessage::Info(attrs) = parse_one(&line) {
if let Ok(best_moves) = parse_uci_attrs(attrs, &proc.fen) {
let multipv = best_moves.multipv;
let cur_depth = best_moves.depth;
proc.best_moves.push(best_moves);
if multipv == proc.multipv {
if proc.best_moves.iter().all(|x| x.depth == cur_depth)
&& cur_depth >= proc.last_depth
{
BestMovesPayload {
best_lines: proc.best_moves.clone(),
engine: engine.clone(),
tab: tab.clone(),
}
proc.best_moves.clear();
.emit_all(&app)?;
proc.last_depth = cur_depth;
}
proc.best_moves.clear();
}
}
proc.logs.push(EngineLog::Engine(line));
}
proc.logs.push(EngineLog::Engine(line));
}
info!("Engine process finished: tab: {}, engine: {}", tab, engine);
state.engine_processes.remove(&key).unwrap();
Ok(())
}

#[derive(Serialize, Debug, Default, Type)]
Expand Down
3 changes: 3 additions & 0 deletions src-tauri/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub enum Error {
#[error("No moves found")]
NoMovesFound,

#[error("Lower or upper bound")]
LowerOrUpperBound,

#[error("Search stopped")]
SearchStopped,

Expand Down
25 changes: 18 additions & 7 deletions src/components/panels/analysis/BestMoves.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,12 @@ export default function BestMovesComponent({
};
}
waitForMove();
}, []);
}, [activeTab, dispatch, engine.path, id, setArrows]);

const chess = new Chess(fen);
const isGameOver = useMemo(() => {
const chess = new Chess(fen);
return chess.isGameOver();
}, [fen]);

useThrottledEffect(
() => {
Expand Down Expand Up @@ -166,7 +169,7 @@ export default function BestMovesComponent({
onClick={() => {
setSettings((prev) => ({ ...prev, enabled: !prev.enabled }));
}}
disabled={chess.isGameOver()}
disabled={isGameOver}
ml={12}
>
{settings.enabled ? (
Expand Down Expand Up @@ -295,15 +298,23 @@ export default function BestMovesComponent({
),
[
settings.enabled,
settings.numberLines,
settings.maxDepth,
settings.cores,
settings.maxDepth,
settings.numberLines,
theme.primaryColor,
isGameOver,
engine.name,
engineVariations,
threat,
settingsOn,
progress,
nps,
classes.subtitle,
depth,
threat,
settingsOn,
setSettings,
toggleThreat,
toggleSettingsOn,
halfMoves,
]
);
}

0 comments on commit 089973d

Please sign in to comment.