Skip to content

Commit bcd1126

Browse files
Merge pull request #308 from CSSLab/codex/maia-play-premoves
Add premoves against Maia
2 parents 1eabef0 + 1aa2739 commit bcd1126

6 files changed

Lines changed: 209 additions & 25 deletions

File tree

‎src/components/Board/GameBoard.tsx‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,17 @@ interface Props {
2828
availableMoves?: Map<string, string[]>
2929
onSelectSquare?: (square: Key) => void
3030
onPlayerMakeMove?: (move: [string, string]) => void
31+
onSetPremove?: (move: [string, string]) => void
32+
onUnsetPremove?: () => void
3133
setCurrentSquare?: Dispatch<SetStateAction<Key | null>>
3234
shapes?: DrawShape[]
3335
brushes?: DrawBrushes
3436
goToNode?: (node: GameNode) => void
3537
gameTree?: any
3638
destinationBadges?: DestinationBadge[]
39+
movableColor?: Color | 'both'
40+
premovesEnabled?: boolean
41+
premoveResetKey?: number
3742
}
3843

3944
const getBoardSquarePosition = (square: string, orientation: Color) => {
@@ -64,12 +69,17 @@ export const GameBoard: React.FC<Props> = ({
6469
orientation = 'white',
6570
availableMoves,
6671
onPlayerMakeMove,
72+
onSetPremove,
73+
onUnsetPremove,
6774
setCurrentSquare,
6875
onSelectSquare,
6976
destinationBadges = [],
77+
movableColor = 'both',
78+
premovesEnabled = false,
79+
premoveResetKey = 0,
7080
}: Props) => {
7181
const { playMoveSound } = useSound()
72-
const boardInstanceKey = game?.id ?? 'board'
82+
const boardInstanceKey = `${game?.id ?? 'board'}-${premoveResetKey}`
7383

7484
const after = useCallback(
7585
(from: string, to: string) => {
@@ -146,6 +156,9 @@ export const GameBoard: React.FC<Props> = ({
146156
? ((currentNode.turn === 'w' ? 'white' : 'black') as 'white' | 'black')
147157
: false,
148158
orientation: orientation as 'white' | 'black',
159+
turnColor: (currentNode.turn === 'w' ? 'white' : 'black') as
160+
| 'white'
161+
| 'black',
149162
}
150163
}, [currentNode, game, orientation])
151164

@@ -157,11 +170,23 @@ export const GameBoard: React.FC<Props> = ({
157170
config={{
158171
movable: {
159172
free: false,
173+
color: movableColor,
160174
dests: availableMoves as any,
161175
events: {
162176
after,
163177
},
164178
},
179+
premovable: {
180+
enabled: premovesEnabled,
181+
events: {
182+
set: (from, to) => {
183+
onSetPremove && onSetPremove([from, to])
184+
},
185+
unset: () => {
186+
onUnsetPremove && onUnsetPremove()
187+
},
188+
},
189+
},
165190
events: {
166191
select: (key) => {
167192
onSelectSquare && onSelectSquare(key)
@@ -176,6 +201,7 @@ export const GameBoard: React.FC<Props> = ({
176201
lastMove: boardConfig.lastMove as Key[],
177202
check: boardConfig.check as boolean | 'white' | 'black' | undefined,
178203
orientation: boardConfig.orientation,
204+
turnColor: boardConfig.turnColor,
179205
}}
180206
/>
181207
{destinationBadges.length > 0 ? (

‎src/components/Board/GameplayInterface.tsx‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
4242
currentNode,
4343
setCurrentNode,
4444
maiaVersion,
45+
playerActive,
4546
goToRootNode,
4647
goToNextNode,
4748
availableMoves,
4849
makePlayerMove,
4950
setOrientation,
5051
goToPreviousNode,
52+
premovesEnabled,
53+
setPremove,
54+
clearPremove,
55+
premoveResetKey,
5156
} = useContext(PlayControllerContext)
5257

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

7176
if (matching.length > 1) {
7277
// Multiple matching moves (i.e. promotion)
78+
clearPremove()
7379
setPromotionFromTo(move)
74-
} else {
80+
} else if (matching[0]) {
7581
const moveUci =
7682
matching[0].from + matching[0].to + (matching[0].promotion ?? '')
7783
makePlayerMove(moveUci)
7884
}
7985
}
8086
},
81-
[availableMoves, makePlayerMove, setPromotionFromTo],
87+
[availableMoves, clearPremove, makePlayerMove, setPromotionFromTo],
8288
)
8389

8490
const onPlayerSelectPromotion = useCallback(
@@ -207,9 +213,16 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
207213
game={game}
208214
availableMoves={availableMovesMapped}
209215
onPlayerMakeMove={onPlayerMakeMove}
216+
onSetPremove={([from, to]) => setPremove(from, to)}
217+
onUnsetPremove={clearPremove}
210218
shapes={props.boardShapes}
211219
currentNode={currentNode}
212220
orientation={orientation}
221+
movableColor={player}
222+
premovesEnabled={
223+
premovesEnabled && !game.termination && !playerActive
224+
}
225+
premoveResetKey={premoveResetKey}
213226
/>
214227
{promotionFromTo ? (
215228
<PromotionOverlay
@@ -281,9 +294,16 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
281294
game={game}
282295
availableMoves={availableMovesMapped}
283296
onPlayerMakeMove={onPlayerMakeMove}
297+
onSetPremove={([from, to]) => setPremove(from, to)}
298+
onUnsetPremove={clearPremove}
284299
shapes={props.boardShapes}
285300
currentNode={currentNode}
286301
orientation={orientation}
302+
movableColor={player}
303+
premovesEnabled={
304+
premovesEnabled && !game.termination && !playerActive
305+
}
306+
premoveResetKey={premoveResetKey}
287307
/>
288308
{promotionFromTo ? (
289309
<PromotionOverlay

‎src/contexts/PlayControllerContext.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ export interface IPlayControllerContext extends BaseTreeControllerContext {
2323
reset: ReturnType<typeof usePlayController>['reset']
2424
makePlayerMove: ReturnType<typeof usePlayController>['makePlayerMove']
2525
updateClock: ReturnType<typeof usePlayController>['updateClock']
26+
updateClockForColor: ReturnType<
27+
typeof usePlayController
28+
>['updateClockForColor']
2629
setCurrentNode: ReturnType<typeof usePlayController>['setCurrentNode']
2730
addMoveWithTime: ReturnType<typeof usePlayController>['addMoveWithTime']
31+
premovesEnabled: ReturnType<typeof usePlayController>['premovesEnabled']
32+
queuedPremove: ReturnType<typeof usePlayController>['queuedPremove']
33+
setPremove: ReturnType<typeof usePlayController>['setPremove']
34+
clearPremove: ReturnType<typeof usePlayController>['clearPremove']
35+
premoveResetKey: ReturnType<typeof usePlayController>['premoveResetKey']
2836
}
2937

3038
const fn = () => {
@@ -62,6 +70,7 @@ export const PlayControllerContext =
6270
reset: fn,
6371
makePlayerMove: fn,
6472
updateClock: fn,
73+
updateClockForColor: fn,
6574
gameTree: defaultGameTree,
6675
currentNode: defaultGameTree.getRoot(),
6776
setCurrentNode: fn,
@@ -70,4 +79,9 @@ export const PlayControllerContext =
7079
goToPreviousNode: fn,
7180
goToRootNode: fn,
7281
addMoveWithTime: fn,
82+
premovesEnabled: false,
83+
queuedPremove: null,
84+
setPremove: fn,
85+
clearPremove: fn,
86+
premoveResetKey: 0,
7387
})

‎src/hooks/usePlayController/usePlayController.ts‎

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Color, Check, GameTree, Termination, PlayGameConfig } from 'src/types'
22
import { AllStats } from '../useStats'
3-
import { PlayedGame } from 'src/types/play'
3+
import { PlayedGame, QueuedPremove } from 'src/types/play'
44
import { Chess, Piece, SQUARES } from 'chess.ts'
55
import { useTreeController } from '../useTreeController'
66
import { useMemo, useState, useCallback, useEffect } from 'react'
@@ -165,9 +165,13 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
165165
return { availableMoves, pieces }
166166
}, [controller.currentNode, playerActive, game.termination, treeVersion])
167167

168-
const updateClock = useCallback(
169-
(overrideTime: number | undefined = undefined): number => {
170-
if (moveList.length < 2) {
168+
const updateClockForColor = useCallback(
169+
(
170+
color: Color,
171+
overrideTime: number | undefined = undefined,
172+
forceClockUpdate = false,
173+
): number => {
174+
if (moveList.length < 2 && !forceClockUpdate) {
171175
return 0 // Clock does not start until first two moves made
172176
}
173177

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

178182
if (lastMoveTime > 0) {
179-
if (toPlay == 'white') {
183+
if (color == 'white') {
180184
setWhiteClock(
181185
Math.max(whiteClock - elapsed + incrementSeconds * 1000, 0),
182186
)
@@ -190,14 +194,18 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
190194
setLastMoveTime(now)
191195
return elapsed
192196
},
193-
[
194-
moveList.length,
195-
lastMoveTime,
196-
toPlay,
197-
whiteClock,
198-
blackClock,
199-
incrementSeconds,
200-
],
197+
[moveList.length, lastMoveTime, whiteClock, blackClock, incrementSeconds],
198+
)
199+
200+
const updateClock = useCallback(
201+
(overrideTime: number | undefined = undefined): number => {
202+
if (!toPlay) {
203+
return 0
204+
}
205+
206+
return updateClockForColor(toPlay, overrideTime)
207+
},
208+
[toPlay, updateClockForColor],
201209
)
202210

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

278-
const makePlayerMove = async (moveUci: string): Promise<void> => {
286+
const makePlayerMove = async (
287+
_moveUci: string,
288+
_moveTimeOverride?: number,
289+
): Promise<void> => {
279290
throw new Error(
280291
'makePlayerMove should be overridden by the consuming component',
281292
)
282293
}
283294

295+
const queuedPremove = null as QueuedPremove | null
296+
const setPremove = (_from: string, _to: string) => {
297+
return
298+
}
299+
const clearPremove = () => {
300+
return
301+
}
302+
284303
const stats: AllStats = {
285304
lifetime: undefined,
286305
session: { gamesWon: 0, gamesPlayed: 0 },
@@ -322,5 +341,11 @@ export const usePlayController = (id: string, config: PlayGameConfig) => {
322341
reset,
323342
makePlayerMove,
324343
updateClock,
344+
updateClockForColor,
345+
premovesEnabled: false,
346+
queuedPremove,
347+
setPremove,
348+
clearPremove,
349+
premoveResetKey: 0,
325350
}
326351
}

0 commit comments

Comments
 (0)