diff --git a/src/hooks/usePlayController/useHandBrainController.ts b/src/hooks/usePlayController/useHandBrainController.ts index 4f373600..6ecf55ae 100644 --- a/src/hooks/usePlayController/useHandBrainController.ts +++ b/src/hooks/usePlayController/useHandBrainController.ts @@ -129,6 +129,7 @@ export const useHandBrainController = ( useEffect(() => { let canceled = false + let moveTimeout: ReturnType | undefined const makeMaiaMove = async () => { const maiaClock = @@ -160,8 +161,12 @@ export const useHandBrainController = ( return } - setTimeout( + moveTimeout = setTimeout( () => { + if (canceled) { + return + } + const moveTime = controller.updateClock() const chess = new Chess(controller.currentNode.fen) @@ -183,6 +188,10 @@ export const useHandBrainController = ( makeMaiaMove() return () => { canceled = true + + if (moveTimeout) { + clearTimeout(moveTimeout) + } } } }, [ diff --git a/src/hooks/usePlayController/usePlayController.ts b/src/hooks/usePlayController/usePlayController.ts index 89808944..22ba0ebd 100644 --- a/src/hooks/usePlayController/usePlayController.ts +++ b/src/hooks/usePlayController/usePlayController.ts @@ -61,6 +61,7 @@ export const usePlayController = (id: string, config: PlayGameConfig) => { const [treeVersion, setTreeVersion] = useState(0) const [resigned, setResigned] = useState(false) + const [timeExpired, setTimeExpired] = useState(null) const [baseMinutes, incrementSeconds] = config.timeControl == 'unlimited' @@ -89,15 +90,15 @@ export const usePlayController = (id: string, config: PlayGameConfig) => { const turn = lastNode.turn const chess = gameTree.toChess() - const termination = resigned - ? Math.min(whiteClock, blackClock) > 0 + const termination = timeExpired + ? computeTimeTermination(chess, timeExpired) + : resigned ? ({ result: turn == 'w' ? '0-1' : '1-0', winner: turn == 'w' ? 'black' : 'white', type: 'resign', } as Termination) - : computeTimeTermination(chess, turn == 'w' ? 'white' : 'black') - : computeTermination(chess) + : computeTermination(chess) const moves = [] const rootNode = gameTree.getRoot() @@ -131,7 +132,7 @@ export const usePlayController = (id: string, config: PlayGameConfig) => { tree: gameTree, turn: turn == 'b' ? 'black' : 'white', } - }, [gameTree, treeVersion, resigned, whiteClock, blackClock, id]) + }, [gameTree, treeVersion, resigned, timeExpired, whiteClock, blackClock, id]) const toPlay: Color | null = game.termination ? null : game.turn const playerActive = toPlay == config.player @@ -199,27 +200,41 @@ export const usePlayController = (id: string, config: PlayGameConfig) => { ], ) + const expireOnTime = useCallback((color: Color) => { + const now = Date.now() + + if (color == 'white') { + setWhiteClock(0) + } else { + setBlackClock(0) + } + + setLastMoveTime(now) + setTimeExpired(color) + }, []) + useEffect(() => { if ( - playerActive && + !game.termination && moveList.length > 1 && - config.timeControl != 'unlimited' + config.timeControl != 'unlimited' && + toPlay ) { - const timeRemaining = config.player == 'white' ? whiteClock : blackClock + const activeColor = toPlay + const timeRemaining = activeColor == 'white' ? whiteClock : blackClock const timeout = setTimeout(() => { - updateClock() - setResigned(true) + expireOnTime(activeColor) }, timeRemaining) return () => clearTimeout(timeout) } }, [ + expireOnTime, + game.termination, blackClock, moveList.length, - config.player, - playerActive, config.timeControl, - updateClock, + toPlay, whiteClock, ]) @@ -253,6 +268,7 @@ export const usePlayController = (id: string, config: PlayGameConfig) => { const newTree = new GameTree(config.startFen || nullFen) setGameTree(newTree) setResigned(false) + setTimeExpired(null) setLastMoveTime(0) setWhiteClock(initialClockValue) setBlackClock(initialClockValue) diff --git a/src/hooks/usePlayController/useVsMaiaController.ts b/src/hooks/usePlayController/useVsMaiaController.ts index 8bc46fbe..e81bb731 100644 --- a/src/hooks/usePlayController/useVsMaiaController.ts +++ b/src/hooks/usePlayController/useVsMaiaController.ts @@ -33,6 +33,7 @@ export const useVsMaiaPlayController = ( useEffect(() => { let canceled = false + let moveTimeout: ReturnType | undefined const makeMaiaMove = async () => { if ( @@ -73,7 +74,11 @@ export const useVsMaiaPlayController = ( const minimumDelayMs = 200 + Math.random() * 100 const delayMs = Math.max(moveDelay * 1000, minimumDelayMs) - setTimeout(() => { + moveTimeout = setTimeout(() => { + if (canceled) { + return + } + const moveTime = controller.updateClock() const chess = new Chess(controller.currentNode.fen) @@ -100,6 +105,10 @@ export const useVsMaiaPlayController = ( return () => { canceled = true + + if (moveTimeout) { + clearTimeout(moveTimeout) + } } }, [ controller.game.id,