Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ tsconfig.tsbuildinfo
.cdk.staging
cdk.out
cdk.context.json

._*
Binary file added public/sound/futuristic/Capture.mp3
Binary file not shown.
Binary file added public/sound/futuristic/Check.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/futuristic/Checkmate.mp3
1 change: 1 addition & 0 deletions public/sound/futuristic/Confirmation.mp3
Binary file added public/sound/futuristic/Draw.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/futuristic/Error.mp3
Binary file added public/sound/futuristic/Move.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/futuristic/OutOfBound.mp3
Binary file added public/sound/lisp/Capture.mp3
Binary file not shown.
Binary file added public/sound/lisp/Check.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/lisp/Checkmate.mp3
Binary file added public/sound/lisp/Draw.mp3
Binary file not shown.
Binary file added public/sound/lisp/Move.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/lisp/OutOfBound.mp3
Binary file added public/sound/nes/Capture.mp3
Binary file not shown.
Binary file added public/sound/nes/Check.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/nes/Checkmate.mp3
1 change: 1 addition & 0 deletions public/sound/nes/Confirmation.mp3
Binary file added public/sound/nes/Draw.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/nes/Error.mp3
Binary file added public/sound/nes/Move.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/nes/OutOfBound.mp3
Binary file added public/sound/piano/Capture.mp3
Binary file not shown.
Binary file added public/sound/piano/Check.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/piano/Checkmate.mp3
1 change: 1 addition & 0 deletions public/sound/piano/Confirmation.mp3
Binary file added public/sound/piano/Draw.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/piano/Error.mp3
Binary file added public/sound/piano/Move.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/piano/OutOfBound.mp3
Binary file added public/sound/robot/Capture.mp3
Binary file not shown.
Binary file added public/sound/robot/Check.mp3
Binary file not shown.
Binary file added public/sound/robot/Checkmate.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/robot/Confirmation.mp3
Binary file added public/sound/robot/Draw.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/robot/Error.mp3
1 change: 1 addition & 0 deletions public/sound/robot/Move.mp3
1 change: 1 addition & 0 deletions public/sound/robot/OutOfBound.mp3
1 change: 1 addition & 0 deletions public/sound/robot/TournamentOther.mp3
Binary file added public/sound/sfx/Capture.mp3
Binary file not shown.
Binary file added public/sound/sfx/Check.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/sfx/Checkmate.mp3
1 change: 1 addition & 0 deletions public/sound/sfx/Confirmation.mp3
Binary file added public/sound/sfx/Draw.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/sfx/Error.mp3
Binary file added public/sound/sfx/Move.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/sfx/OutOfBound.mp3
File renamed without changes.
1 change: 1 addition & 0 deletions public/sound/standard/Check.mp3
1 change: 1 addition & 0 deletions public/sound/standard/Checkmate.mp3
1 change: 1 addition & 0 deletions public/sound/standard/Defeat.mp3
1 change: 1 addition & 0 deletions public/sound/standard/Draw.mp3
File renamed without changes.
1 change: 1 addition & 0 deletions public/sound/standard/NewChallenge.mp3
1 change: 1 addition & 0 deletions public/sound/standard/NewPM.mp3
1 change: 1 addition & 0 deletions public/sound/standard/TournamentOther.mp3
1 change: 1 addition & 0 deletions public/sound/standard/Victory.mp3
Binary file added public/sound/woodland/Capture.mp3
Binary file not shown.
Binary file added public/sound/woodland/Check.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/woodland/Checkmate.mp3
Binary file added public/sound/woodland/Draw.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions public/sound/woodland/Error.mp3
Binary file added public/sound/woodland/Move.mp3
Binary file not shown.
Binary file removed public/sounds/error.mp3
Binary file not shown.
43 changes: 43 additions & 0 deletions src/hooks/useGameSound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Chess } from "chess.js";
import { PrimitiveAtom, useAtomValue } from "jotai";
import { useEffect, useRef } from "react";
import { soundThemeAtom } from "@/sections/play/states";

export const useGameSound = (gameAtom: PrimitiveAtom<Chess>) => {
const game = useAtomValue(gameAtom);
const soundTheme = useAtomValue(soundThemeAtom);
const previousMoveCount = useRef(game.history().length);

useEffect(() => {
const history = game.history({ verbose: true });
const currentMoveCount = history.length;

if (currentMoveCount === previousMoveCount.current) {
return;
}

previousMoveCount.current = currentMoveCount;

const lastMove = history.at(-1);
if (!lastMove) return;

let soundFile = "Move.mp3";

if (game.isGameOver()) {
if (game.isCheckmate()) {
soundFile = "Checkmate.mp3";
} else if (game.isDraw()) {
soundFile = "Draw.mp3";
} else {
soundFile = "Error.mp3";
}
} else if (game.inCheck()) {
soundFile = "Check.mp3";
} else if (lastMove.captured || lastMove.promotion) {
soundFile = "Capture.mp3";
}

const audio = new Audio(`/sound/${soundTheme}/${soundFile}`);
audio.play().catch((e) => console.error("Error playing sound:", e));
}, [game, soundTheme]);
};
3 changes: 3 additions & 0 deletions src/sections/analysis/board/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useScreenSize } from "@/hooks/useScreenSize";
import { Color } from "@/types/enums";
import Board from "@/components/board";
import { usePlayersData } from "@/hooks/usePlayersData";
import { useGameSound } from "@/hooks/useGameSound";

export default function BoardContainer() {
const screenSize = useScreenSize();
Expand All @@ -31,6 +32,8 @@ export default function BoardContainer() {
return Math.min(width - 700, height * 0.92);
}, [screenSize]);

useGameSound(boardAtom);

return (
<Board
id="AnalysisBoard"
Expand Down
27 changes: 26 additions & 1 deletion src/sections/engineSettings/engineSettingsDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Slider from "@/components/slider";
import { EngineName } from "@/types/enums";
import { EngineName, SoundTheme } from "@/types/enums";
import {
MenuItem,
Select,
Expand Down Expand Up @@ -37,6 +37,7 @@ import {
STRONGEST_ENGINE,
} from "@/constants";
import { getRecommendedWorkersNb } from "@/lib/engine/worker";
import { soundThemeAtom } from "../play/states";

interface Props {
open: boolean;
Expand All @@ -63,6 +64,11 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
const theme = useTheme();
const isDarkMode = theme.palette.mode === "dark";

const [soundTheme, setSoundTheme] = useAtomLocalStorage(
"sound-theme",
soundThemeAtom
);

useEffect(() => {
if (!isEngineSupported(engineName)) {
if (Stockfish16_1.isSupported()) {
Expand Down Expand Up @@ -202,6 +208,25 @@ export default function EngineSettingsDialog({ open, onClose }: Props) {
))}
</Select>
</FormControl>

<FormControl variant="outlined">
<InputLabel id="sound-theme-select-label">Sound Theme</InputLabel>
<Select
labelId="sound-theme-select-label"
id="sound-theme-select"
displayEmpty
input={<OutlinedInput label="Sound Theme" />}
value={soundTheme}
onChange={(e) => setSoundTheme(e.target.value as SoundTheme)}
sx={{ width: 280, maxWidth: "100%" }}
>
{Object.values(SoundTheme).map((theme) => (
<MenuItem key={theme} value={theme}>
{theme.charAt(0).toUpperCase() + theme.slice(1)}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>

<Grid
Expand Down
2 changes: 2 additions & 0 deletions src/sections/play/board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Board from "@/components/board";
import { useGameData } from "@/hooks/useGameData";
import { usePlayersData } from "@/hooks/usePlayersData";
import { sleep } from "@/lib/helpers";
import { useGameSound } from "@/hooks/useGameSound";

export default function BoardContainer() {
const screenSize = useScreenSize();
Expand Down Expand Up @@ -68,6 +69,7 @@ export default function BoardContainer() {
}, [screenSize]);

useGameData(gameAtom, gameDataAtom);
useGameSound(gameAtom);

return (
<Board
Expand Down
29 changes: 28 additions & 1 deletion src/sections/play/gameSettings/gameSettingsDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Slider from "@/components/slider";
import { Color, EngineName } from "@/types/enums";
import { Color, EngineName, SoundTheme } from "@/types/enums";
import {
MenuItem,
Select,
Expand All @@ -26,6 +26,7 @@ import {
isGameInProgressAtom,
gameAtom,
enginePlayNameAtom,
soundThemeAtom,
} from "../states";
import { useChessActions } from "@/hooks/useChessActions";
import { logAnalyticsEvent } from "@/lib/firebase";
Expand All @@ -49,6 +50,11 @@ export default function GameSettingsDialog({ open, onClose }: Props) {
"engine-play-name",
enginePlayNameAtom
);
const [soundTheme, setSoundTheme] = useAtomLocalStorage(
"sound-theme",
soundThemeAtom
);

const [playerColor, setPlayerColor] = useAtom(playerColorAtom);
const setIsGameInProgress = useSetAtom(isGameInProgressAtom);
const { reset: resetGame } = useChessActions(gameAtom);
Expand Down Expand Up @@ -211,6 +217,27 @@ export default function GameSettingsDialog({ open, onClose }: Props) {
</Typography>
</FormControl>
)}

<Grid container justifyContent="center" size={12}>
<FormControl variant="outlined">
<InputLabel id="sound-theme-select-label">Sound Theme</InputLabel>
<Select
labelId="sound-theme-select-label"
id="sound-theme-select"
displayEmpty
input={<OutlinedInput label="Sound Theme" />}
value={soundTheme}
onChange={(e) => setSoundTheme(e.target.value as SoundTheme)}
sx={{ width: 280, maxWidth: "100%" }}
>
{Object.values(SoundTheme).map((theme) => (
<MenuItem key={theme} value={theme}>
{theme.charAt(0).toUpperCase() + theme.slice(1)}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
</DialogContent>
<DialogActions sx={{ m: 2 }}>
Expand Down
3 changes: 2 additions & 1 deletion src/sections/play/states.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DEFAULT_ENGINE } from "@/constants";
import { Color, EngineName } from "@/types/enums";
import { Color, EngineName, SoundTheme } from "@/types/enums";
import { CurrentPosition } from "@/types/eval";
import { Chess } from "chess.js";
import { atom } from "jotai";
Expand All @@ -10,3 +10,4 @@ export const playerColorAtom = atom<Color>(Color.White);
export const enginePlayNameAtom = atom<EngineName>(DEFAULT_ENGINE);
export const engineEloAtom = atom(1320);
export const isGameInProgressAtom = atom(false);
export const soundThemeAtom = atom<SoundTheme>(SoundTheme.Standard);
11 changes: 11 additions & 0 deletions src/types/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,14 @@ export enum Color {
White = "w",
Black = "b",
}

export enum SoundTheme {
Standard = "standard",
Piano = "piano",
NES = "nes",
SFX = "sfx",
Futuristic = "futuristic",
Lisp = "lisp",
Woodland = "woodland",
Robot = "robot",
}