feat : add stockfish 17

This commit is contained in:
GuillaumeSD
2025-01-07 00:43:58 +01:00
parent 151277524b
commit 49bbc87fa5
18 changed files with 121 additions and 22 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,6 +2,7 @@ import { isWasmSupported } from "@/lib/engine/shared";
import { Stockfish11 } from "@/lib/engine/stockfish11"; import { Stockfish11 } from "@/lib/engine/stockfish11";
import { Stockfish16 } from "@/lib/engine/stockfish16"; import { Stockfish16 } from "@/lib/engine/stockfish16";
import { Stockfish16_1 } from "@/lib/engine/stockfish16_1"; import { Stockfish16_1 } from "@/lib/engine/stockfish16_1";
import { Stockfish17 } from "@/lib/engine/stockfish17";
import { UciEngine } from "@/lib/engine/uciEngine"; import { UciEngine } from "@/lib/engine/uciEngine";
import { EngineName } from "@/types/enums"; import { EngineName } from "@/types/enums";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -29,6 +30,10 @@ export const useEngine = (engineName: EngineName | undefined) => {
const pickEngine = (engine: EngineName): Promise<UciEngine> => { const pickEngine = (engine: EngineName): Promise<UciEngine> => {
switch (engine) { switch (engine) {
case EngineName.Stockfish17:
return Stockfish17.create(false);
case EngineName.Stockfish17Lite:
return Stockfish17.create(true);
case EngineName.Stockfish16_1: case EngineName.Stockfish16_1:
return Stockfish16_1.create(false); return Stockfish16_1.create(false);
case EngineName.Stockfish16_1Lite: case EngineName.Stockfish16_1Lite:

View File

@@ -1,3 +1,9 @@
import { EngineName } from "@/types/enums";
import { Stockfish11 } from "./stockfish11";
import { Stockfish16 } from "./stockfish16";
import { Stockfish16_1 } from "./stockfish16_1";
import { Stockfish17 } from "./stockfish17";
export const isWasmSupported = () => export const isWasmSupported = () =>
typeof WebAssembly === "object" && typeof WebAssembly === "object" &&
WebAssembly.validate( WebAssembly.validate(
@@ -5,3 +11,19 @@ export const isWasmSupported = () =>
); );
export const isMultiThreadSupported = () => SharedArrayBuffer !== undefined; export const isMultiThreadSupported = () => SharedArrayBuffer !== undefined;
export const isEngineSupported = (name: EngineName): boolean => {
switch (name) {
case EngineName.Stockfish17:
case EngineName.Stockfish17Lite:
return Stockfish17.isSupported();
case EngineName.Stockfish16_1:
case EngineName.Stockfish16_1Lite:
return Stockfish16_1.isSupported();
case EngineName.Stockfish16:
case EngineName.Stockfish16NNUE:
return Stockfish16.isSupported();
case EngineName.Stockfish11:
return Stockfish11.isSupported();
}
};

View File

@@ -8,4 +8,8 @@ export class Stockfish11 {
return UciEngine.create(EngineName.Stockfish11, worker); return UciEngine.create(EngineName.Stockfish11, worker);
} }
public static isSupported() {
return true;
}
} }

View File

@@ -5,7 +5,7 @@ import { getEngineWorker } from "./worker";
export class Stockfish16 { export class Stockfish16 {
public static async create(nnue?: boolean): Promise<UciEngine> { public static async create(nnue?: boolean): Promise<UciEngine> {
if (!isWasmSupported()) { if (!Stockfish16.isSupported()) {
throw new Error("Stockfish 16 is not supported"); throw new Error("Stockfish 16 is not supported");
} }
@@ -29,4 +29,8 @@ export class Stockfish16 {
return UciEngine.create(EngineName.Stockfish16, worker, customEngineInit); return UciEngine.create(EngineName.Stockfish16, worker, customEngineInit);
} }
public static isSupported() {
return isWasmSupported();
}
} }

View File

@@ -5,7 +5,7 @@ import { getEngineWorker } from "./worker";
export class Stockfish16_1 { export class Stockfish16_1 {
public static async create(lite?: boolean): Promise<UciEngine> { public static async create(lite?: boolean): Promise<UciEngine> {
if (!isWasmSupported()) { if (!Stockfish16_1.isSupported()) {
throw new Error("Stockfish 16.1 is not supported"); throw new Error("Stockfish 16.1 is not supported");
} }
@@ -23,4 +23,8 @@ export class Stockfish16_1 {
return UciEngine.create(engineName, worker); return UciEngine.create(engineName, worker);
} }
public static isSupported() {
return isWasmSupported();
}
} }

View File

@@ -0,0 +1,27 @@
import { EngineName } from "@/types/enums";
import { UciEngine } from "./uciEngine";
import { isMultiThreadSupported, isWasmSupported } from "./shared";
import { getEngineWorker } from "./worker";
export class Stockfish17 {
public static async create(lite?: boolean): Promise<UciEngine> {
if (!Stockfish17.isSupported()) {
throw new Error("Stockfish 17 is not supported");
}
const enginePath = lite
? "engines/stockfish-17/stockfish-17-lite-02843c1.js"
: "engines/stockfish-17/stockfish-17-aaa11cd.js";
const engineName = lite
? EngineName.Stockfish17Lite
: EngineName.Stockfish17;
const worker = getEngineWorker(enginePath);
return UciEngine.create(engineName, worker);
}
public static isSupported() {
return isWasmSupported() && isMultiThreadSupported();
}
}

View File

@@ -22,7 +22,8 @@ import {
import ArrowOptions from "./arrowOptions"; import ArrowOptions from "./arrowOptions";
import { useAtomLocalStorage } from "@/hooks/useAtomLocalStorage"; import { useAtomLocalStorage } from "@/hooks/useAtomLocalStorage";
import { useEffect } from "react"; import { useEffect } from "react";
import { isWasmSupported } from "@/lib/engine/shared"; import { isEngineSupported } from "@/lib/engine/shared";
import { Stockfish16_1 } from "@/lib/engine/stockfish16_1";
interface Props { interface Props {
open: boolean; open: boolean;
@@ -44,10 +45,14 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
); );
useEffect(() => { useEffect(() => {
if (!isWasmSupported()) { if (!isEngineSupported(engineName)) {
setEngineName(EngineName.Stockfish11); if (Stockfish16_1.isSupported()) {
setEngineName(EngineName.Stockfish16_1Lite);
} else {
setEngineName(EngineName.Stockfish11);
}
} }
}, [setEngineName]); }, [setEngineName, engineName]);
return ( return (
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth> <Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
@@ -56,9 +61,10 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
</DialogTitle> </DialogTitle>
<DialogContent sx={{ paddingBottom: 0 }}> <DialogContent sx={{ paddingBottom: 0 }}>
<Typography> <Typography>
Stockfish 16.1 Lite is the default engine. It offers the best balance Stockfish 17 Lite is the default engine if your device support its
between speed and strength. Stockfish 16.1 is the strongest engine requirements. It offers the best balance between speed and strength.
available, note that it requires a one time download of 64MB. Stockfish 17 is the strongest engine available, note that it requires
a one time download of 75MB.
</Typography> </Typography>
<Grid <Grid
marginTop={4} marginTop={4}
@@ -84,9 +90,7 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
<MenuItem <MenuItem
key={engine} key={engine}
value={engine} value={engine}
disabled={ disabled={!isEngineSupported(engine)}
engine !== EngineName.Stockfish11 && !isWasmSupported()
}
> >
{engineLabel[engine]} {engineLabel[engine]}
</MenuItem> </MenuItem>
@@ -126,6 +130,8 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
} }
const engineLabel: Record<EngineName, string> = { const engineLabel: Record<EngineName, string> = {
[EngineName.Stockfish17]: "Stockfish 17 (75MB)",
[EngineName.Stockfish17Lite]: "Stockfish 17 Lite (6MB)",
[EngineName.Stockfish16_1]: "Stockfish 16.1 (64MB)", [EngineName.Stockfish16_1]: "Stockfish 16.1 (64MB)",
[EngineName.Stockfish16_1Lite]: "Stockfish 16.1 Lite (6MB)", [EngineName.Stockfish16_1Lite]: "Stockfish 16.1 Lite (6MB)",
[EngineName.Stockfish16NNUE]: "Stockfish 16 (40MB)", [EngineName.Stockfish16NNUE]: "Stockfish 16 (40MB)",

View File

@@ -30,7 +30,8 @@ import { useChessActions } from "@/hooks/useChessActions";
import { playGameStartSound } from "@/lib/sounds"; import { playGameStartSound } from "@/lib/sounds";
import { logAnalyticsEvent } from "@/lib/firebase"; import { logAnalyticsEvent } from "@/lib/firebase";
import { useEffect } from "react"; import { useEffect } from "react";
import { isWasmSupported } from "@/lib/engine/shared"; import { isEngineSupported } from "@/lib/engine/shared";
import { Stockfish16_1 } from "@/lib/engine/stockfish16_1";
interface Props { interface Props {
open: boolean; open: boolean;
@@ -69,10 +70,14 @@ export default function GameSettingsDialog({ open, onClose }: Props) {
}; };
useEffect(() => { useEffect(() => {
if (!isWasmSupported()) { if (!isEngineSupported(engineName)) {
setEngineName(EngineName.Stockfish11); if (Stockfish16_1.isSupported()) {
setEngineName(EngineName.Stockfish16_1Lite);
} else {
setEngineName(EngineName.Stockfish11);
}
} }
}, [setEngineName]); }, [setEngineName, engineName]);
return ( return (
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth> <Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
@@ -81,9 +86,10 @@ export default function GameSettingsDialog({ open, onClose }: Props) {
</DialogTitle> </DialogTitle>
<DialogContent sx={{ paddingBottom: 0 }}> <DialogContent sx={{ paddingBottom: 0 }}>
<Typography> <Typography>
Stockfish 16.1 Lite is the default engine. It offers the best balance Stockfish 17 Lite is the default engine if your device support its
between speed and strength. Stockfish 16.1 is the strongest engine requirements. It offers the best balance between speed and strength.
available, note that it requires a one time download of 64MB. Stockfish 17 is the strongest engine available, note that it requires
a one time download of 75MB.
</Typography> </Typography>
<Grid <Grid
marginTop={4} marginTop={4}
@@ -109,9 +115,7 @@ export default function GameSettingsDialog({ open, onClose }: Props) {
<MenuItem <MenuItem
key={engine} key={engine}
value={engine} value={engine}
disabled={ disabled={!isEngineSupported(engine)}
engine !== EngineName.Stockfish11 && !isWasmSupported()
}
> >
{engineLabel[engine]} {engineLabel[engine]}
</MenuItem> </MenuItem>
@@ -164,6 +168,8 @@ export default function GameSettingsDialog({ open, onClose }: Props) {
} }
const engineLabel: Record<EngineName, string> = { const engineLabel: Record<EngineName, string> = {
[EngineName.Stockfish17]: "Stockfish 17 (75MB)",
[EngineName.Stockfish17Lite]: "Stockfish 17 Lite (6MB)",
[EngineName.Stockfish16_1]: "Stockfish 16.1 (64MB)", [EngineName.Stockfish16_1]: "Stockfish 16.1 (64MB)",
[EngineName.Stockfish16_1Lite]: "Stockfish 16.1 Lite (6MB)", [EngineName.Stockfish16_1Lite]: "Stockfish 16.1 Lite (6MB)",
[EngineName.Stockfish16NNUE]: "Stockfish 16 (40MB)", [EngineName.Stockfish16NNUE]: "Stockfish 16 (40MB)",

View File

@@ -5,6 +5,8 @@ export enum GameOrigin {
} }
export enum EngineName { export enum EngineName {
Stockfish17 = "stockfish_17",
Stockfish17Lite = "stockfish_17_lite",
Stockfish16_1 = "stockfish_16_1", Stockfish16_1 = "stockfish_16_1",
Stockfish16_1Lite = "stockfish_16_1_lite", Stockfish16_1Lite = "stockfish_16_1_lite",
Stockfish16NNUE = "stockfish_16_nnue", Stockfish16NNUE = "stockfish_16_nnue",