Skip to content

Commit

Permalink
add multipv to report
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscoBSalgueiro committed Nov 11, 2023
1 parent 46b1c47 commit b09617c
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 34 deletions.
42 changes: 27 additions & 15 deletions src-tauri/src/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ pub async fn get_best_moves(
let multipv = best_moves.multipv;
let cur_depth = best_moves.depth;
proc.best_moves.push(best_moves);
if multipv == proc.options.multipv {
if multipv == proc.real_multipv {
if proc.best_moves.iter().all(|x| x.depth == cur_depth)
&& cur_depth >= proc.last_depth
{
Expand All @@ -425,7 +425,7 @@ pub async fn get_best_moves(

#[derive(Serialize, Debug, Default, Type)]
pub struct MoveAnalysis {
best: BestMoves,
best: Vec<BestMoves>,
novelty: bool,
}

Expand All @@ -451,7 +451,7 @@ pub async fn analyze_game(
let path = PathBuf::from(&engine);
let mut analysis: Vec<MoveAnalysis> = Vec::new();

let (mut process, mut reader) = EngineProcess::new(path)?;
let (mut proc, mut reader) = EngineProcess::new(path)?;

let fen = Fen::from_ascii(options.fen.as_bytes())?;

Expand All @@ -462,7 +462,9 @@ pub async fn analyze_game(
let san = San::from_ascii(m.as_bytes()).unwrap();
let m = san.to_move(&chess).unwrap();
chess.play_unchecked(&m);
fens.push(Fen::from_position(chess.clone(), EnPassantMode::Legal));
if !chess.is_game_over() {
fens.push(Fen::from_position(chess.clone(), EnPassantMode::Legal));
}
});

if options.reversed {
Expand All @@ -481,23 +483,33 @@ pub async fn analyze_game(
},
)?;

process
.set_options(EngineOptions {
threads: 4,
multipv: 1,
fen: fen.to_string(),
extra_options: Vec::new(),
})
.await?;
proc.set_options(EngineOptions {
threads: 4,
multipv: 2,
fen: fen.to_string(),
extra_options: Vec::new(),
})
.await?;

process.go(&go_mode).await?;
proc.go(&go_mode).await?;

let mut current_analysis = MoveAnalysis::default();
while let Ok(Some(line)) = reader.next_line().await {
match parse_one(&line) {
UciMessage::Info(attrs) => {
if let Ok(best_moves) = parse_uci_attrs(attrs, fen) {
current_analysis.best = best_moves;
if let Ok(best_moves) = parse_uci_attrs(attrs, &proc.options.fen.parse()?) {
let multipv = best_moves.multipv;
let cur_depth = best_moves.depth;
proc.best_moves.push(best_moves);
if multipv == proc.real_multipv {
if proc.best_moves.iter().all(|x| x.depth == cur_depth)
&& cur_depth >= proc.last_depth
{
current_analysis.best = proc.best_moves.clone();
proc.last_depth = cur_depth;
}
proc.best_moves.clear();
}
}
}
UciMessage::BestMove { .. } => {
Expand Down
2 changes: 1 addition & 1 deletion src/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ try {
else return { status: "error", error: e as any };
}
},
async analyzeGame(moves: string[], engine: string, goMode: GoMode, options: AnalysisOptions) : Promise<__Result__<{ best: BestMoves; novelty: boolean }[], string>> {
async analyzeGame(moves: string[], engine: string, goMode: GoMode, options: AnalysisOptions) : Promise<__Result__<{ best: BestMoves[]; novelty: boolean }[], string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("plugin:tauri-specta|analyze_game", { moves, engine, goMode, options }) };
} catch (e) {
Expand Down
1 change: 1 addition & 0 deletions src/components/panels/analysis/ReportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function ReportModal({
function analyze() {
setInProgress(true);
toggleReportingMode();
console.log(form.values);
commands
.analyzeGame(
moves,
Expand Down
18 changes: 13 additions & 5 deletions src/utils/score.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { minMax } from "@tiptap/react";
import { Color } from "chess.js";
import { Annotation } from "./chess";
import { Score } from "@/bindings";
import { BestMoves, Score } from "@/bindings";

export const INITIAL_SCORE: Score = {
type: "cp",
Expand Down Expand Up @@ -69,9 +69,9 @@ export function getAccuracy(prev: Score, next: Score, color: Color): number {
const { prevCP, nextCP } = normalizeScores(prev, next, color);
return minMax(
103.1668 *
Math.exp(-0.04354 * (getWinChance(prevCP) - getWinChance(nextCP))) -
3.1669 +
1,
Math.exp(-0.04354 * (getWinChance(prevCP) - getWinChance(nextCP))) -
3.1669 +
1,
0,
100
);
Expand All @@ -86,7 +86,8 @@ export function getCPLoss(prev: Score, next: Score, color: Color): number {
export function getAnnotation(
prev: Score,
next: Score,
color: Color
color: Color,
prevMoves: BestMoves[]
): Annotation {
const { prevCP, nextCP } = normalizeScores(prev, next, color);
const winChanceDiff = getWinChance(prevCP) - getWinChance(nextCP);
Expand All @@ -98,5 +99,12 @@ export function getAnnotation(
} else if (winChanceDiff > 5) {
return "?!";
}

if (prevMoves.length > 1) {
const scores = normalizeScores(prevMoves[0].score, prevMoves[1].score, color);
if (getWinChance(scores.prevCP) - getWinChance(scores.nextCP) > 10) {
return "!";
}
}
return "";
}
21 changes: 21 additions & 0 deletions src/utils/tests/score.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
formatScore,
getAccuracy,
getAnnotation,
getCPLoss,
getWinChance,
parseScore,
Expand Down Expand Up @@ -45,3 +46,23 @@ test("should calculate the cp loss correctly", () => {
expect(getCPLoss({ type: "cp", value: 0 }, { type: "cp", value: 50 }, "b")).toBe(50);
expect(getCPLoss({ type: "mate", value: -1 }, { type: "cp", value: 0 }, "b")).toBe(1000);
});

test("should annotate as ??", () => {
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: -500 }, "w", [])).toBe("??");
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: 500 }, "b", [])).toBe("??");
});

test("should annotate as ?", () => {
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: -200 }, "w", [])).toBe("?");
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: 200 }, "b", [])).toBe("?");
});

test("should annotate as ?!", () => {
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: -100 }, "w", [])).toBe("?!");
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: 100 }, "b", [])).toBe("?!");
});

test("should not annotate", () => {
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: -50 }, "w", [])).toBe("");
expect(getAnnotation({ type: "cp", value: 0 }, { type: "cp", value: 50 }, "b", [])).toBe("");
});
30 changes: 17 additions & 13 deletions src/utils/treeReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export type TreeAction =
| { type: "SET_FEN"; payload: string }
| { type: "SET_SCORE"; payload: Score }
| { type: "SET_SHAPES"; payload: DrawShape[] }
| { type: "ADD_ANALYSIS"; payload: { best: BestMoves, novelty: boolean }[] }
| { type: "ADD_ANALYSIS"; payload: { best: BestMoves[], novelty: boolean }[] }
| { type: "PROMOTE_VARIATION"; payload: number[] };

const treeReducer = (state: TreeState, action: TreeAction) => {
Expand Down Expand Up @@ -388,23 +388,27 @@ export function getColorFromFen(fen: string): "w" | "b" {
return "b";
}

function addAnalysis(state: TreeState, analysis: { best: BestMoves, novelty: boolean }[]) {
function addAnalysis(state: TreeState, analysis: { best: BestMoves[], novelty: boolean }[]) {
let cur = state.root;
let i = 0;
const initialColor = getColorFromFen(state.root.fen);
while (cur !== undefined && i < analysis.length) {
cur.score = analysis[i].best.score;
if (analysis[i].novelty) {
cur.commentHTML = "Novelty";
cur.commentText = "Novelty";
}
let prevScore: Score = { type: "cp", value: 0 };
if (i > 0) {
prevScore = analysis[i - 1].best.score;
if (!(new Chess(cur.fen).isGameOver())) {
cur.score = analysis[i].best[0].score;
if (analysis[i].novelty) {
cur.commentHTML = "Novelty";
cur.commentText = "Novelty";
}
let prevScore: Score = { type: "cp", value: 0 };
let prevMoves: BestMoves[] = [];
if (i > 0) {
prevScore = analysis[i - 1].best[0].score;
prevMoves = analysis[i - 1].best;
}
const curScore = analysis[i].best[0].score;
const color = i % 2 === (initialColor === "w" ? 1 : 0) ? "w" : "b";
cur.annotation = getAnnotation(prevScore, curScore, color, prevMoves);
}
const curScore = analysis[i].best.score;
const color = i % 2 === (initialColor === "w" ? 1: 0) ? "w" : "b";
cur.annotation = getAnnotation(prevScore, curScore, color);
cur = cur.children[0];
i++;
}
Expand Down

0 comments on commit b09617c

Please sign in to comment.