import * as React from "react"; import { FunctionComponent, useState } from "react"; import { useTranslation } from "react-i18next"; import { BoardViewModel, Game, getSowingPath } from "@mancala/core"; import { Pit } from "mancala.js"; import { Context } from "../../context/context"; import { getWebTheme } from "../../theme/themes"; import PitView, { PitMarks } from "./PitView"; import StoreView from "./StoreView"; import "./BoardView.css"; // The board as the bottom player sees it: their pits along the bottom from left to right, their store on the right. // It fills its container's width. const BoardView: FunctionComponent<{ game: Game; context: Context; boardViewModel: BoardViewModel; // Show player 2 at the bottom. revert: boolean; topName: string; bottomName: string; // Makes the bottom player's pits buttons. onPitSelect?: (index: number, pit: Pit) => void; // The bottom player can move now: their pits with stones are highlighted and preview their move. canPlay?: boolean; // Board index of the pit the last move was played from. lastMoveIndex?: number; // Board index where the shown move's last stone landed. landIndex?: number; }> = ({ game, context, boardViewModel, revert, topName, bottomName, onPitSelect, canPlay, lastMoveIndex, landIndex }) => { const { t } = useTranslation(); const [previewIndex, setPreviewIndex] = useState(undefined); const board = game.mancalaGame.board; const themeId = getWebTheme(context.themeManager.theme).id; const stones = boardViewModel.pits.map((pit) => pit.stoneCount); // Pits the hovered move drops stones into, with how many each, and where its last stone lands. const preview: Record = {}; const path = canPlay && previewIndex !== undefined ? getSowingPath(stones, previewIndex) : []; path.forEach((index) => (preview[index] = (preview[index] ?? 0) + 1)); const previewLand = path.length > 0 ? path[path.length - 1] : undefined; const marksOf = (index: number): PitMarks => ({ highlight: boardViewModel.pits[index]?.highlight, preview: preview[index], land: previewLand !== undefined ? index === previewLand : index === landIndex, last: index === lastMoveIndex, }); const topPits = revert ? board.player1Pits : board.player2Pits; const bottomPits = revert ? board.player2Pits : board.player1Pits; const [topStore, bottomStore] = revert ? [board.player1BankIndex(), board.player2BankIndex()] : [board.player2BankIndex(), board.player1BankIndex()]; const pitView = (pit: Pit, position: number, top: boolean) => { const stoneCount = stones[pit.index]; const playable = !top && !!canPlay && stoneCount > 0; const pitNumber = (top ? 5 - position : position) + 1; return ( onPitSelect(pit.index, board.pits[pit.index]) : undefined} onPreview={(active) => setPreviewIndex(active ? pit.index : undefined)} /> ); }; return (
{[...topPits].reverse().map((pit, position) => pitView(pit, position, true))} {bottomPits.map((pit, position) => pitView(pit, position, false))}
); }; export default BoardView;