Skip to content

Commit

Permalink
first try at assigning great moves
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscoBSalgueiro committed Nov 15, 2023
1 parent b09617c commit dff1eff
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 15 deletions.
81 changes: 77 additions & 4 deletions src-tauri/src/chess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ pub async fn get_best_moves(
pub struct MoveAnalysis {
best: Vec<BestMoves>,
novelty: bool,
maybe_brilliant: bool,
}

#[derive(Deserialize, Debug, Default, Type)]
Expand Down Expand Up @@ -456,14 +457,20 @@ pub async fn analyze_game(
let fen = Fen::from_ascii(options.fen.as_bytes())?;

let mut chess: Chess = fen.clone().into_position(CastlingMode::Standard)?;
let mut fens: Vec<Fen> = vec![fen];
let mut fens: Vec<(Fen, bool)> = vec![(fen, false)];

moves.iter().for_each(|m| {
let san = San::from_ascii(m.as_bytes()).unwrap();
let m = san.to_move(&chess).unwrap();
let mut previous_setup = chess.clone().into_setup(EnPassantMode::Legal);
previous_setup.swap_turn();
chess.play_unchecked(&m);
let current_setup = chess.clone().into_setup(EnPassantMode::Legal);
if !chess.is_game_over() {
fens.push(Fen::from_position(chess.clone(), EnPassantMode::Legal));
fens.push((
Fen::from_position(chess.clone(), EnPassantMode::Legal),
count_attacked_material(&previous_setup) <= count_attacked_material(&current_setup),
));
}
});

Expand All @@ -473,7 +480,7 @@ pub async fn analyze_game(

let mut novelty_found = false;

for (i, fen) in fens.iter().enumerate() {
for (i, (fen, maybe_brilliant)) in fens.iter().enumerate() {
app.emit_all(
"report_progress",
ProgressPayload {
Expand Down Expand Up @@ -527,9 +534,10 @@ pub async fn analyze_game(
}

for (i, analysis) in analysis.iter_mut().enumerate() {
let fen = &fens[i];
let fen = &fens[i].0;
let query = PositionQuery::exact_from_fen(&fen.to_string())?;

analysis.maybe_brilliant = fens[i].1;
if options.annotate_novelties && !novelty_found {
if let Some(reference) = options.reference_db.clone() {
analysis.novelty = !is_position_in_db(reference, query, state.clone()).await?;
Expand All @@ -552,6 +560,71 @@ pub async fn analyze_game(
Ok(analysis)
}

fn count_attacked_material(pos: &Setup) -> i32 {
let mut attacked_material = 0;
let mut seen_attacked = Vec::new();
for s in Square::ALL.iter() {
if let Some(piece) = pos.board.piece_at(*s) {
if piece.color == pos.turn {
let squares_attacked = pos.board.attacks_from(*s);
for square in Square::ALL.iter() {
if squares_attacked.contains(*square) && !seen_attacked.contains(square) {
if let Some(attacked_piece) = pos.board.piece_at(*square) {
seen_attacked.push(*square);
if attacked_piece.color != pos.turn {
attacked_material += match attacked_piece.role {
Role::Pawn => 1,
Role::Knight => 3,
Role::Bishop => 3,
Role::Rook => 5,
Role::Queen => 9,
Role::King => 1000,
}
}
}
}
}
}
}
}
attacked_material
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_count_attacked_material() {
assert_eq!(count_attacked_material(&Setup::default()), 0);

let fen: Fen = "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2"
.parse()
.unwrap();
assert_eq!(count_attacked_material(&fen.into_setup()), 1);

let fen: Fen = "r1bqkbnr/ppp1pppp/2n5/1B1p4/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3"
.parse()
.unwrap();
assert_eq!(count_attacked_material(&fen.into_setup()), 1);

let fen: Fen = "r1bqkbnr/ppp2ppp/2n5/1B1pp3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 4"
.parse()
.unwrap();
assert_eq!(count_attacked_material(&fen.into_setup()), 5);

let fen: Fen = "r1bqkbnr/ppp2ppp/2B5/3pp3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 0 4"
.parse()
.unwrap();
assert_eq!(count_attacked_material(&fen.into_setup()), 4);

let fen: Fen = "r1bqkbnr/ppp2ppp/2B5/3pp3/4P3/5N2/PPPP1PPP/RNBQK2R w KQkq"
.parse()
.unwrap();
assert_eq!(count_attacked_material(&fen.into_setup()), 1003);
}
}

#[tauri::command]
pub async fn get_single_best_move(
skill_level: usize,
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; maybe_brilliant: 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: 0 additions & 1 deletion src/components/panels/analysis/ReportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ function ReportModal({
function analyze() {
setInProgress(true);
toggleReportingMode();
console.log(form.values);
commands
.analyzeGame(
moves,
Expand Down
22 changes: 16 additions & 6 deletions src/utils/score.ts
Original file line number Diff line number Diff line change
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 @@ -87,7 +87,9 @@ export function getAnnotation(
prev: Score,
next: Score,
color: Color,
prevMoves: BestMoves[]
prevMoves: BestMoves[],
maybe_brilliant: boolean,
move: string
): Annotation {
const { prevCP, nextCP } = normalizeScores(prev, next, color);
const winChanceDiff = getWinChance(prevCP) - getWinChance(nextCP);
Expand All @@ -101,8 +103,16 @@ export function getAnnotation(
}

if (prevMoves.length > 1) {
const scores = normalizeScores(prevMoves[0].score, prevMoves[1].score, color);
if (getWinChance(scores.prevCP) - getWinChance(scores.nextCP) > 10) {
const scores = normalizeScores(
prevMoves[0].score,
prevMoves[1].score,
color
);
if (
getWinChance(scores.prevCP) - getWinChance(scores.nextCP) > 10 &&
maybe_brilliant &&
move === prevMoves[0].sanMoves[0]
) {
return "!";
}
}
Expand Down
6 changes: 3 additions & 3 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, maybe_brilliant: boolean }[] }
| { type: "PROMOTE_VARIATION"; payload: number[] };

const treeReducer = (state: TreeState, action: TreeAction) => {
Expand Down Expand Up @@ -388,7 +388,7 @@ 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, maybe_brilliant: boolean }[]) {
let cur = state.root;
let i = 0;
const initialColor = getColorFromFen(state.root.fen);
Expand All @@ -407,7 +407,7 @@ function addAnalysis(state: TreeState, analysis: { best: BestMoves[], novelty: b
}
const curScore = analysis[i].best[0].score;
const color = i % 2 === (initialColor === "w" ? 1 : 0) ? "w" : "b";
cur.annotation = getAnnotation(prevScore, curScore, color, prevMoves);
cur.annotation = getAnnotation(prevScore, curScore, color, prevMoves, analysis[i].maybe_brilliant, cur.move?.san ?? "");
}
cur = cur.children[0];
i++;
Expand Down

0 comments on commit dff1eff

Please sign in to comment.