diff --git a/src/Game/cube.ts b/src/Game/cube.ts index 40981e6..58da8db 100644 --- a/src/Game/cube.ts +++ b/src/Game/cube.ts @@ -35,7 +35,7 @@ export function canOfferDouble( game.cube.stateKind !== 'offered' && (!game.cube.owner || game.cube.owner.id === player.id) && // Disallow repeat doubles in same turn unless Beaver is implemented - (game.cube as any).offeredThisTurnBy?.id !== player.id + game.cube.offeredThisTurnBy?.id !== player.id ) } @@ -107,13 +107,16 @@ export function acceptDouble( ...offeringPlayer, stateKind: 'rolling', dice: Dice.initialize(offeringPlayer.color, 'rolling'), - rollForStartValue: (offeringPlayer as any).rollForStartValue, + // Non-null: an active player mid-game has a rollForStartValue; the base + // player type declares it optional, the rolling player type requires it. + rollForStartValue: offeringPlayer.rollForStartValue!, } const updatedInactivePlayer: BackgammonPlayerInactive = { ...player, stateKind: 'inactive', dice: Dice.initialize(player.color, 'inactive'), - rollForStartValue: (player as any).rollForStartValue, + // Non-null: see above; inactive player type also requires rollForStartValue. + rollForStartValue: player.rollForStartValue!, } const updatedPlayers = game.players.map((p) => { @@ -130,8 +133,10 @@ export function acceptDouble( activePlayer: updatedActivePlayer, inactivePlayer: updatedInactivePlayer, activeColor: updatedActivePlayer.color, - activePlay: undefined as any, - } as any) + activePlay: undefined, + // as unknown as BackgammonGameRolling: the spread yields a generic players + // array (not the rolling-game tuple) that TS can't narrow structurally. + } as unknown as BackgammonGameRolling) } export function canRefuseDouble( diff --git a/src/Game/index.ts b/src/Game/index.ts index 2f0996d..d260306 100644 --- a/src/Game/index.ts +++ b/src/Game/index.ts @@ -88,6 +88,8 @@ export class Game { */ get gnuPositionId(): string { try { + // as any: the Game class instance is structurally a BackgammonGame but + // TS does not treat the class as assignable to the discriminated union. return exportToGnuPositionId(this as any) } catch (error) { logger.warn('Failed to generate gnuPositionId:', error) diff --git a/src/Game/turnFlow.ts b/src/Game/turnFlow.ts index aea86ea..1443e91 100644 --- a/src/Game/turnFlow.ts +++ b/src/Game/turnFlow.ts @@ -752,14 +752,14 @@ export function move( ): BackgammonGameMoving | BackgammonGameMoved | BackgammonGameCompleted { // Push a pre-move snapshot to the turn-local undo stack try { - const ap: any = (game as any).activePlay + const ap = game.activePlay if (ap) { - if (!ap.undo) ap.undo = { frames: [] } + const undo = ap.undo ?? (ap.undo = { frames: [] }) const snapshot = typeof structuredClone === 'function' ? structuredClone(game) - : (JSON.parse(JSON.stringify(game)) as any) - ap.undo.frames.push(snapshot) + : (JSON.parse(JSON.stringify(game)) as BackgammonGameMoving) + undo.frames.push(snapshot) } } catch (e) { logger?.warn?.('Failed to push undo snapshot in Game.move', e) @@ -1207,14 +1207,14 @@ export function executeAndRecalculate( // Push a pre-move snapshot try { - const ap: any = (game as any).activePlay + const ap = game.activePlay if (ap) { - if (!ap.undo) ap.undo = { frames: [] } + const undo = ap.undo ?? (ap.undo = { frames: [] }) const snapshot = typeof structuredClone === 'function' ? structuredClone(game) - : (JSON.parse(JSON.stringify(game)) as any) - ap.undo.frames.push(snapshot) + : (JSON.parse(JSON.stringify(game)) as BackgammonGameMoving) + undo.frames.push(snapshot) } } catch (e) { logger?.warn?.('Failed to push undo snapshot before move', e)