From c74fb2fbe1a99fd0641747c1e2a492b0253011cd Mon Sep 17 00:00:00 2001 From: Francisco Salgueiro Date: Sun, 29 Oct 2023 11:49:32 +0000 Subject: [PATCH] add custom settings to engine --- src-tauri/src/chess.rs | 22 +- src/atoms/atoms.ts | 2 + src/bindings.ts | 3 +- src/components/panels/analysis/BestMoves.tsx | 3 +- .../panels/analysis/CoresSlider.tsx | 10 +- .../panels/analysis/DepthSlider.tsx | 6 +- .../panels/analysis/EngineSettings.tsx | 270 ++++++++++++++++-- .../panels/analysis/LinesSlider.tsx | 6 +- 8 files changed, 276 insertions(+), 46 deletions(-) diff --git a/src-tauri/src/chess.rs b/src-tauri/src/chess.rs index a6f4009c..583ec2b6 100644 --- a/src-tauri/src/chess.rs +++ b/src-tauri/src/chess.rs @@ -90,6 +90,11 @@ impl EngineProcess { .await?; self.set_option("MultiPV", &options.multipv.to_string()) .await?; + + for option in options.extra_options { + self.set_option(&option.name, &option.value).await?; + } + self.set_position(&options.fen).await?; self.last_depth = 0; self.best_moves.clear(); @@ -262,10 +267,18 @@ async fn send_command(stdin: &mut ChildStdin, command: impl AsRef) { } #[derive(Deserialize, Debug, Clone, Type)] +#[serde(rename_all = "camelCase")] pub struct EngineOptions { pub multipv: u16, pub threads: u16, pub fen: String, + pub extra_options: Vec, +} + +#[derive(Deserialize, Debug, Clone, Type)] +pub struct EngineOption { + name: String, + value: String, } #[derive(Deserialize, Debug, Clone, Type)] @@ -430,14 +443,6 @@ pub async fn analyze_game( let mut chess: Chess = fen.into_position(CastlingMode::Standard)?; - process - .set_options(EngineOptions { - threads: 4, - multipv: 1, - fen: options.fen.to_string(), - }) - .await?; - let len_moves = moves.len(); let mut novelty_found = false; @@ -465,6 +470,7 @@ pub async fn analyze_game( threads: 4, multipv: 1, fen: fen.to_string(), + extra_options: Vec::new(), }) .await?; diff --git a/src/atoms/atoms.ts b/src/atoms/atoms.ts index 86ab8804..9f3c2a4a 100644 --- a/src/atoms/atoms.ts +++ b/src/atoms/atoms.ts @@ -242,6 +242,7 @@ export type EngineSettings = { go: GoMode; cores: number; numberLines: number; + extraOptions: { name: string, value: string }[]; }; export const tabEngineSettingsFamily = atomFamily( @@ -254,6 +255,7 @@ export const tabEngineSettingsFamily = atomFamily( }, cores: 2, numberLines: 3, + extraOptions: [], }), (a, b) => a.tab === b.tab && a.engine === b.engine ); diff --git a/src/bindings.ts b/src/bindings.ts index 6f8e5927..08b4813d 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -65,7 +65,8 @@ bestMovesPayload: "plugin:tauri-specta:best-moves-payload" export type AnalysisOptions = { fen: string; annotateNovelties: boolean; referenceDb: string | null } export type BestMoves = { depth: number; score: Score; uciMoves: string[]; sanMoves: string[]; multipv: number; nps: number } export type BestMovesPayload = { bestLines: BestMoves[]; engine: string; tab: string } -export type EngineOptions = { multipv: number; threads: number; fen: string } +export type EngineOption = { name: string; value: string } +export type EngineOptions = { multipv: number; threads: number; fen: string; extraOptions: EngineOption[] } export type GoMode = { t: "Depth"; c: number } | { t: "Time"; c: number } | { t: "Nodes"; c: number } | { t: "Infinite" } export type Score = { type: "cp"; value: number } | { type: "mate"; value: number } diff --git a/src/components/panels/analysis/BestMoves.tsx b/src/components/panels/analysis/BestMoves.tsx index 38cb3ed8..037c0790 100644 --- a/src/components/panels/analysis/BestMoves.tsx +++ b/src/components/panels/analysis/BestMoves.tsx @@ -132,7 +132,8 @@ export default function BestMovesComponent({ .getBestMoves(engine.path, activeTab!, settings.go, { fen: threat ? swapMove(fen) : fen, multipv: settings.numberLines, - threads: 2 ** settings.cores, + threads: settings.cores, + extraOptions: settings.extraOptions, }) .then((res) => { unwrap(res); diff --git a/src/components/panels/analysis/CoresSlider.tsx b/src/components/panels/analysis/CoresSlider.tsx index 7daf723f..a4b9c87b 100644 --- a/src/components/panels/analysis/CoresSlider.tsx +++ b/src/components/panels/analysis/CoresSlider.tsx @@ -1,5 +1,5 @@ import { Slider } from "@mantine/core"; -import { useState } from "react"; +import { useEffect, useState } from "react"; export default function CoresSlide({ value, @@ -8,7 +8,7 @@ export default function CoresSlide({ value: number; setValue: (v: number) => void; }) { - const [tempValue, setTempValue] = useState(value); + const [tempValue, setTempValue] = useState(Math.log2(value)); const MARKS = [ { value: 0 }, { value: 1 }, @@ -19,6 +19,10 @@ export default function CoresSlide({ { value: 6 }, ]; + useEffect(() => { + setTempValue(Math.log2(value)); + }, [value]); + return ( <> setValue(2 ** v)} marks={MARKS} label={(value) => 2 ** value} /> diff --git a/src/components/panels/analysis/DepthSlider.tsx b/src/components/panels/analysis/DepthSlider.tsx index 8c679476..f9411093 100644 --- a/src/components/panels/analysis/DepthSlider.tsx +++ b/src/components/panels/analysis/DepthSlider.tsx @@ -1,6 +1,6 @@ import { GoMode } from "@/bindings"; import { Slider } from "@mantine/core"; -import { useState } from "react"; +import { useEffect, useState } from "react"; export default function DepthSlider({ value, @@ -19,6 +19,10 @@ export default function DepthSlider({ { value: 60 }, ]; + useEffect(() => { + setTempValue(value); + }, [value]); + const v = tempValue.t === "Infinite" ? 60 : tempValue.c; const handleSliderChange = (v: number, setState: (v: GoMode) => void) => { if (v === 60) { diff --git a/src/components/panels/analysis/EngineSettings.tsx b/src/components/panels/analysis/EngineSettings.tsx index aa7daa04..23272e33 100644 --- a/src/components/panels/analysis/EngineSettings.tsx +++ b/src/components/panels/analysis/EngineSettings.tsx @@ -1,9 +1,23 @@ import { EngineSettings } from "@/atoms/atoms"; -import { Collapse, Group, Text } from "@mantine/core"; -import React, { memo } from "react"; +import { + ActionIcon, + Button, + Center, + Collapse, + Group, + Modal, + NumberInput, + Select, + SimpleGrid, + Table, + Text, + TextInput, +} from "@mantine/core"; +import React, { memo, useState } from "react"; import CoresSlide from "./CoresSlider"; import DepthSlider from "./DepthSlider"; import LinesSlider from "./LinesSlider"; +import { IconPlus, IconX } from "@tabler/icons-react"; interface EngineSettingsProps { settingsOn: boolean; @@ -16,36 +30,230 @@ function EngineSettings({ settings, setSettings, }: EngineSettingsProps) { + const [advancedOptions, setAdvancedOptions] = useState(false); + return ( - - - - Number of Lines - - setSettings((prev) => ({ ...prev, numberLines: v }))} - /> - - - - Engine Depth - - setSettings((prev) => ({ ...prev, go: v }))} - /> - - - - Number of cores - - setSettings((prev) => ({ ...prev, cores: v }))} - /> - - + <> + + + + + Number of Lines + + + setSettings((prev) => ({ ...prev, numberLines: v })) + } + /> + {settings.go.t === "Infinite" || settings.go.t === "Depth" ? ( + <> + + Depth + + setSettings((prev) => ({ ...prev, go: v }))} + /> + + ) : ( + <> + + {settings.go.t} + + + setSettings((prev) => { + return { + ...prev, + go: { + ...prev.go, + c: v || 1, + }, + }; + }) + } + /> + + )} + + Number of cores + + setSettings((prev) => ({ ...prev, cores: v }))} + /> + + + + + + ); +} + +function AdvancedOptions({ + opened, + setOpened, + settings, + setSettings, +}: { + opened: boolean; + setOpened: React.Dispatch>; + settings: EngineSettings; + setSettings: React.Dispatch>; +}) { + return ( + setOpened(false)} + > + + + + + + + + + + + + + + + {settings.extraOptions.map((option, i) => ( + + + + + ))} + +
+ + {settings.go.t !== "Infinite" && ( + + setSettings((prev) => { + return { + ...prev, + go: { + ...prev.go, + c: v || 1, + }, + }; + }) + } + /> + )} +
Threads + + setSettings((prev) => ({ ...prev, cores: v || 1 })) + } + /> +
MultiPV + + setSettings((prev) => ({ ...prev, numberLines: v || 1 })) + } + /> +
+ { + const newOptions = settings.extraOptions; + newOptions[i].name = e.currentTarget.value; + setSettings((prev) => ({ + ...prev, + extraOptions: newOptions, + })); + }} + /> + + + { + const newOptions = settings.extraOptions; + newOptions[i].value = e.currentTarget.value; + setSettings((prev) => ({ + ...prev, + extraOptions: newOptions, + })); + }} + /> + {/* Remove button */} + { + const newOptions = settings.extraOptions; + newOptions.splice(i, 1); + setSettings((prev) => ({ + ...prev, + extraOptions: newOptions, + })); + }} + > + + + +
+ +
+ +
+
); } diff --git a/src/components/panels/analysis/LinesSlider.tsx b/src/components/panels/analysis/LinesSlider.tsx index b91cd214..51ab0bfb 100644 --- a/src/components/panels/analysis/LinesSlider.tsx +++ b/src/components/panels/analysis/LinesSlider.tsx @@ -1,5 +1,5 @@ import { Slider } from "@mantine/core"; -import { useState } from "react"; +import { useEffect, useState } from "react"; export default function DepthSlider({ value, @@ -17,6 +17,10 @@ export default function DepthSlider({ { value: 5 }, ]; + useEffect(() => { + setTempValue(value); + }, [value]); + return ( <>