Skip to content

Commit

Permalink
Add move tags in the chessboard (#79)
Browse files Browse the repository at this point in the history
* add annotation tags in the chessboard

* use avatar instead of badge for hint

* change last move color according to annotation

* make badge color darker
  • Loading branch information
franciscoBSalgueiro authored Nov 10, 2023
1 parent 642281b commit 5de96cd
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 49 deletions.
129 changes: 97 additions & 32 deletions src/components/boards/BoardPlay.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
import {
autoPromoteAtom,
autoSaveAtom,
currentInvisibleAtom,
currentPracticingAtom,
currentTabAtom,
deckAtomFamily,
forcedEnPassantAtom,
moveInputAtom,
showArrowsAtom,
showCoordinatesAtom,
showDestsAtom,
} from "@/atoms/atoms";
import { Chessground } from "@/chessground/Chessground";
import { chessboard } from "@/styles/Chessboard.css";
import {
ANNOTATION_INFO,
Annotation,
PiecesCount,
handleMove,
moveToCoordinates,
moveToKey,
parseKeyboardMove,
parseUci,
toDests,
useMaterialDiff,
} from "@/utils/chess";
import { Outcome } from "@/utils/db";
import { formatMove } from "@/utils/format";
import { invoke } from "@/utils/invoke";
import { getBoardSize } from "@/utils/misc";
import { GameHeaders, TreeNode } from "@/utils/treeReducer";
import {
ActionIcon,
Alert,
Avatar,
Box,
Global,
Group,
Input,
Stack,
Expand All @@ -20,44 +54,15 @@ import {
IconPlus,
IconSwitchVertical,
} from "@tabler/icons-react";
import { Chess, PieceSymbol, Square } from "chess.js";
import { Chess, Move, PieceSymbol, Square } from "chess.js";
import { DrawShape } from "chessground/draw";
import { Color } from "chessground/types";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import { memo, useContext, useMemo, useState } from "react";
import {
handleMove,
moveToKey,
parseKeyboardMove,
parseUci,
PiecesCount,
toDests,
useMaterialDiff,
} from "@/utils/chess";
import { Outcome } from "@/utils/db";
import { formatMove } from "@/utils/format";
import { invoke } from "@/utils/invoke";
import { getBoardSize } from "@/utils/misc";
import { GameHeaders, TreeNode } from "@/utils/treeReducer";
import { TreeDispatchContext } from "../common/TreeStateContext";
import { updateCardPerformance } from "../files/opening";
import EvalBar from "./EvalBar";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import {
autoPromoteAtom,
autoSaveAtom,
currentInvisibleAtom,
currentPracticingAtom,
currentTabAtom,
deckAtomFamily,
forcedEnPassantAtom,
moveInputAtom,
showArrowsAtom,
showCoordinatesAtom,
showDestsAtom,
} from "@/atoms/atoms";
import PromotionModal from "./PromotionModal";
import { updateCardPerformance } from "../files/opening";
import { chessboard } from "@/styles/Chessboard.css";
import { Chessground } from "@/chessground/Chessground";

interface ChessboardProps {
dirty: boolean;
Expand Down Expand Up @@ -284,6 +289,13 @@ function BoardPlay({
</Alert>
)}
<Box className={chessboard} ref={boardRef} mt={10}>
{currentNode.annotation && currentNode.move && (
<AnnotationHint
orientation={orientation}
move={currentNode.move}
annotation={currentNode.annotation}
/>
)}
<PromotionModal
pendingMove={pendingMove}
cancelMove={() => setPendingMove(null)}
Expand Down Expand Up @@ -487,4 +499,57 @@ function ShowMaterial({
);
}

function AnnotationHint({
move,
annotation,
orientation,
}: {
move: Move;
annotation: Annotation;
orientation: Color;
}) {
const { file, rank } = moveToCoordinates(move, orientation);
const { color } = ANNOTATION_INFO[annotation];

return (
<Box
sx={{
position: "absolute",
zIndex: 100,
width: "12.5%",
height: "12.5%",
left: `${(file - 1) * 12.5}%`,
bottom: `${(rank - 1) * 12.5}%`,
}}
>
<Avatar
sx={{
transform: "translateY(-40%) translateX(-50%)",
}}
ml="90%"
radius="xl"
color={color}
fz="lg"
variant="filled"
>
{annotation}
</Avatar>
<Global
styles={(theme) => ({
"cg-board": {
"square.last-move": {
background: theme.fn.rgba(
theme.colors[color][
theme.colorScheme === "dark" ? 8 : 6
],
0.4
),
},
},
})}
/>
</Box>
);
}

export default memo(BoardPlay);
19 changes: 2 additions & 17 deletions src/components/boards/PromotionModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,7 @@ import { useClickOutside } from "@mantine/hooks";
import { BISHOP, KNIGHT, PieceSymbol, QUEEN, ROOK, Square } from "chess.js";
import { memo } from "react";
import Piece from "../common/Piece";

const fileToNumber: Record<string, number> = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
};
import { moveToCoordinates } from "@/utils/chess";

const PromotionModal = memo(function PromotionModal({
pendingMove,
Expand All @@ -28,12 +18,7 @@ const PromotionModal = memo(function PromotionModal({
turn?: "white" | "black";
orientation: "white" | "black";
}) {
let file = fileToNumber[pendingMove?.to[0] ?? "a"];
let rank = parseInt(pendingMove?.to[1] ?? "1");
if (orientation === "black") {
file = 9 - file;
rank = 9 - rank;
}
const { file, rank } = moveToCoordinates(pendingMove, orientation)
const ref = useClickOutside(() => cancelMove());

const promotionPieces: PieceSymbol[] = [QUEEN, KNIGHT, ROOK, BISHOP];
Expand Down
23 changes: 23 additions & 0 deletions src/utils/chess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,29 @@ export function moveToKey(move: Move | null) {
return move ? ([move.from, move.to] as Key[]) : [];
}


const fileToNumber: Record<string, number> = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
};


export function moveToCoordinates(move: { from: string, to: string } | null, orientation: "white" | "black") {
let file = fileToNumber[move?.to[0] ?? "a"];
let rank = parseInt(move?.to[1] ?? "1");
if (orientation === "black") {
file = 9 - file;
rank = 9 - rank;
}
return { file, rank }
}

export function toDests(
chess: Chess | null,
forcedEP: boolean
Expand Down

0 comments on commit 5de96cd

Please sign in to comment.