Skip to content
Merged
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
28 changes: 27 additions & 1 deletion src/components/Board/GameBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ interface Props {
availableMoves?: Map<string, string[]>
onSelectSquare?: (square: Key) => void
onPlayerMakeMove?: (move: [string, string]) => void
onSetPremove?: (move: [string, string]) => void
onUnsetPremove?: () => void
setCurrentSquare?: Dispatch<SetStateAction<Key | null>>
shapes?: DrawShape[]
brushes?: DrawBrushes
goToNode?: (node: GameNode) => void
gameTree?: any
destinationBadges?: DestinationBadge[]
movableColor?: Color | 'both'
premovesEnabled?: boolean
premoveResetKey?: number
}

const getBoardSquarePosition = (square: string, orientation: Color) => {
Expand Down Expand Up @@ -64,12 +69,17 @@ export const GameBoard: React.FC<Props> = ({
orientation = 'white',
availableMoves,
onPlayerMakeMove,
onSetPremove,
onUnsetPremove,
setCurrentSquare,
onSelectSquare,
destinationBadges = [],
movableColor = 'both',
premovesEnabled = false,
premoveResetKey = 0,
}: Props) => {
const { playMoveSound } = useSound()
const boardInstanceKey = game?.id ?? 'board'
const boardInstanceKey = `${game?.id ?? 'board'}-${premoveResetKey}`

const after = useCallback(
(from: string, to: string) => {
Expand Down Expand Up @@ -146,6 +156,9 @@ export const GameBoard: React.FC<Props> = ({
? ((currentNode.turn === 'w' ? 'white' : 'black') as 'white' | 'black')
: false,
orientation: orientation as 'white' | 'black',
turnColor: (currentNode.turn === 'w' ? 'white' : 'black') as
| 'white'
| 'black',
}
}, [currentNode, game, orientation])

Expand All @@ -157,11 +170,23 @@ export const GameBoard: React.FC<Props> = ({
config={{
movable: {
free: false,
color: movableColor,
dests: availableMoves as any,
events: {
after,
},
},
premovable: {
enabled: premovesEnabled,
events: {
set: (from, to) => {
onSetPremove && onSetPremove([from, to])
},
unset: () => {
onUnsetPremove && onUnsetPremove()
},
},
},
events: {
select: (key) => {
onSelectSquare && onSelectSquare(key)
Expand All @@ -176,6 +201,7 @@ export const GameBoard: React.FC<Props> = ({
lastMove: boardConfig.lastMove as Key[],
check: boardConfig.check as boolean | 'white' | 'black' | undefined,
orientation: boardConfig.orientation,
turnColor: boardConfig.turnColor,
}}
/>
{destinationBadges.length > 0 ? (
Expand Down
24 changes: 22 additions & 2 deletions src/components/Board/GameplayInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
currentNode,
setCurrentNode,
maiaVersion,
playerActive,
goToRootNode,
goToNextNode,
availableMoves,
makePlayerMove,
setOrientation,
goToPreviousNode,
premovesEnabled,
setPremove,
clearPremove,
premoveResetKey,
} = useContext(PlayControllerContext)

const { user } = useContext(AuthContext)
Expand All @@ -70,15 +75,16 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (

if (matching.length > 1) {
// Multiple matching moves (i.e. promotion)
clearPremove()
setPromotionFromTo(move)
} else {
} else if (matching[0]) {
const moveUci =
matching[0].from + matching[0].to + (matching[0].promotion ?? '')
makePlayerMove(moveUci)
}
}
},
[availableMoves, makePlayerMove, setPromotionFromTo],
[availableMoves, clearPremove, makePlayerMove, setPromotionFromTo],
)

const onPlayerSelectPromotion = useCallback(
Expand Down Expand Up @@ -207,9 +213,16 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
game={game}
availableMoves={availableMovesMapped}
onPlayerMakeMove={onPlayerMakeMove}
onSetPremove={([from, to]) => setPremove(from, to)}
onUnsetPremove={clearPremove}
shapes={props.boardShapes}
currentNode={currentNode}
orientation={orientation}
movableColor={player}
premovesEnabled={
premovesEnabled && !game.termination && !playerActive
}
premoveResetKey={premoveResetKey}
/>
{promotionFromTo ? (
<PromotionOverlay
Expand Down Expand Up @@ -281,9 +294,16 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
game={game}
availableMoves={availableMovesMapped}
onPlayerMakeMove={onPlayerMakeMove}
onSetPremove={([from, to]) => setPremove(from, to)}
onUnsetPremove={clearPremove}
shapes={props.boardShapes}
currentNode={currentNode}
orientation={orientation}
movableColor={player}
premovesEnabled={
premovesEnabled && !game.termination && !playerActive
}
premoveResetKey={premoveResetKey}
/>
{promotionFromTo ? (
<PromotionOverlay
Expand Down
14 changes: 14 additions & 0 deletions src/contexts/PlayControllerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ export interface IPlayControllerContext extends BaseTreeControllerContext {
reset: ReturnType<typeof usePlayController>['reset']
makePlayerMove: ReturnType<typeof usePlayController>['makePlayerMove']
updateClock: ReturnType<typeof usePlayController>['updateClock']
updateClockForColor: ReturnType<
typeof usePlayController
>['updateClockForColor']
setCurrentNode: ReturnType<typeof usePlayController>['setCurrentNode']
addMoveWithTime: ReturnType<typeof usePlayController>['addMoveWithTime']
premovesEnabled: ReturnType<typeof usePlayController>['premovesEnabled']
queuedPremove: ReturnType<typeof usePlayController>['queuedPremove']
setPremove: ReturnType<typeof usePlayController>['setPremove']
clearPremove: ReturnType<typeof usePlayController>['clearPremove']
premoveResetKey: ReturnType<typeof usePlayController>['premoveResetKey']
}

const fn = () => {
Expand Down Expand Up @@ -62,6 +70,7 @@ export const PlayControllerContext =
reset: fn,
makePlayerMove: fn,
updateClock: fn,
updateClockForColor: fn,
gameTree: defaultGameTree,
currentNode: defaultGameTree.getRoot(),
setCurrentNode: fn,
Expand All @@ -70,4 +79,9 @@ export const PlayControllerContext =
goToPreviousNode: fn,
goToRootNode: fn,
addMoveWithTime: fn,
premovesEnabled: false,
queuedPremove: null,
setPremove: fn,
clearPremove: fn,
premoveResetKey: 0,
})
53 changes: 39 additions & 14 deletions src/hooks/usePlayController/usePlayController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Color, Check, GameTree, Termination, PlayGameConfig } from 'src/types'
import { AllStats } from '../useStats'
import { PlayedGame } from 'src/types/play'
import { PlayedGame, QueuedPremove } from 'src/types/play'
import { Chess, Piece, SQUARES } from 'chess.ts'
import { useTreeController } from '../useTreeController'
import { useMemo, useState, useCallback, useEffect } from 'react'
Expand Down Expand Up @@ -165,9 +165,13 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
return { availableMoves, pieces }
}, [controller.currentNode, playerActive, game.termination, treeVersion])

const updateClock = useCallback(
(overrideTime: number | undefined = undefined): number => {
if (moveList.length < 2) {
const updateClockForColor = useCallback(
(
color: Color,
overrideTime: number | undefined = undefined,
forceClockUpdate = false,
): number => {
if (moveList.length < 2 && !forceClockUpdate) {
return 0 // Clock does not start until first two moves made
}

Expand All @@ -176,7 +180,7 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
overrideTime === undefined ? now - lastMoveTime : overrideTime

if (lastMoveTime > 0) {
if (toPlay == 'white') {
if (color == 'white') {
setWhiteClock(
Math.max(whiteClock - elapsed + incrementSeconds * 1000, 0),
)
Expand All @@ -190,14 +194,18 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
setLastMoveTime(now)
return elapsed
},
[
moveList.length,
lastMoveTime,
toPlay,
whiteClock,
blackClock,
incrementSeconds,
],
[moveList.length, lastMoveTime, whiteClock, blackClock, incrementSeconds],
)

const updateClock = useCallback(
(overrideTime: number | undefined = undefined): number => {
if (!toPlay) {
return 0
}

return updateClockForColor(toPlay, overrideTime)
},
[toPlay, updateClockForColor],
)

const expireOnTime = useCallback((color: Color) => {
Expand Down Expand Up @@ -275,12 +283,23 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
setTreeVersion((prev) => prev + 1)
}

const makePlayerMove = async (moveUci: string): Promise<void> => {
const makePlayerMove = async (
_moveUci: string,
_moveTimeOverride?: number,
): Promise<void> => {
throw new Error(
'makePlayerMove should be overridden by the consuming component',
)
}

const queuedPremove = null as QueuedPremove | null
const setPremove = (_from: string, _to: string) => {
return
}
const clearPremove = () => {
return
}

const stats: AllStats = {
lifetime: undefined,
session: { gamesWon: 0, gamesPlayed: 0 },
Expand Down Expand Up @@ -322,5 +341,11 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
reset,
makePlayerMove,
updateClock,
updateClockForColor,
premovesEnabled: false,
queuedPremove,
setPremove,
clearPremove,
premoveResetKey: 0,
}
}
Loading
Loading