UNPKG

tsgammon-core

Version:

A Backgammon library for Typescript, formerly developed as a part of tsgammon-ui

252 lines (231 loc) 7.12 kB
import { EOGStatus } from '../EOGStatus' import { SGResult } from '../records/SGResult' import { CubeGameListener } from './CubeGameListener' import { CBAction, CBEoG, CBInPlay, CBOpening, CBResponse, CBState, CBToRoll, resultToCBEoG, } from './CubeGameState' import { concat0, concat1, concat2 } from './utils/concat' /** * キューブの状態のみを管理するDispatcher */ export type CubeGameDispatcher = { doStartCubeGame: () => ( listener: Partial<Pick<CubeGameListener, 'onCubeGameStarted'>> ) => void doDouble: ( state: CBAction ) => (listeners: Partial<Pick<CubeGameListener, 'onDoubled'>>) => void doTake: ( state: CBResponse ) => ( listeners: Partial<Pick<CubeGameListener, 'onDoubleAccepted'>> ) => void doPass: ( state: CBResponse ) => (listeners: Partial<Pick<CubeGameListener, 'onEndOfCubeGame'>>) => void // ゲームの進行状況に対応して受動的に使用される操作 doStartCubeAction: ( state: CBInPlay, skipCubeAction: (cbState: CBInPlay) => boolean ) => ( listeners: Partial< Pick< CubeGameListener, | 'onCubeActionStarted' | 'onCubeActionSkipped' | 'onAwaitCubeAction' > > ) => void doSkipCubeAction: ( state: CBAction ) => ( listeners: Partial<Pick<CubeGameListener, 'onCubeActionSkipped'>> ) => void doStartOpeningCheckerPlay: ( state: CBOpening, isRed: boolean ) => ( listeners: Partial<Pick<CubeGameListener, 'onAwaitCheckerPlay'>> ) => void doStartCheckerPlay: ( state: CBAction | CBToRoll ) => ( listeners: Partial<Pick<CubeGameListener, 'onAwaitCheckerPlay'>> ) => void doEndOfCubeGame: ( state: CBState, result: SGResult, eogStatus: EOGStatus ) => (listeners: Partial<Pick<CubeGameListener, 'onEndOfCubeGame'>>) => void } export function concatCBListeners( base: Partial<CubeGameListener>, ...listeners: Partial<CubeGameListener>[] ): Partial<CubeGameListener> { return listeners.reduce( (prev: Partial<CubeGameListener>, cur: Partial<CubeGameListener>) => { return { onCubeGameStarted: concat0( prev?.onCubeGameStarted, cur?.onCubeGameStarted ), onAwaitCubeAction: concat1( prev?.onAwaitCubeAction, cur?.onAwaitCubeAction ), onCubeActionStarted: concat1( prev?.onCubeActionStarted, cur?.onCubeActionStarted ), onAwaitCheckerPlay: concat1( prev?.onAwaitCheckerPlay, cur?.onAwaitCheckerPlay ), onDoubled: concat2(prev?.onDoubled, cur?.onDoubled), onDoubleAccepted: concat2( prev?.onDoubleAccepted, cur?.onDoubleAccepted ), onCubeActionSkipped: concat1( prev?.onCubeActionSkipped, cur?.onCubeActionSkipped ), onEndOfCubeGame: concat1( prev?.onEndOfCubeGame, cur?.onEndOfCubeGame ), } }, base ) } export function setCBStateListener( defaultState: CBState, setCBState: (cbState: CBState) => void ): CubeGameListener { return { onCubeGameStarted: () => setCBState(defaultState), onAwaitCubeAction: () => { // }, onCubeActionStarted: setCBState, onAwaitCheckerPlay: setCBState, onDoubled: setCBState, onDoubleAccepted: setCBState, onPassed: () => { // }, onCubeActionSkipped: setCBState, onEndOfCubeGame: setCBState, } } export const cubeGameDispatcher: CubeGameDispatcher = { doStartCubeGame, doDouble, doSkipCubeAction, doTake, doPass, doStartCubeAction, doStartOpeningCheckerPlay, doStartCheckerPlay, doEndOfCubeGame, } function doStartCubeGame() { return ( listeners: Partial<Pick<CubeGameListener, 'onCubeGameStarted'>> ) => { listeners.onCubeGameStarted?.() } } function doDouble(state: CBAction) { const nextState: CBResponse = state.doDouble() return (listeners: Partial<Pick<CubeGameListener, 'onDoubled'>>) => { listeners.onDoubled?.(nextState, state) } } function doSkipCubeAction(state: CBAction) { const nextState = state.doSkipCubeAction() return ( listeners: Partial<Pick<CubeGameListener, 'onCubeActionSkipped'>> ) => { listeners.onCubeActionSkipped?.(nextState) } } function doTake(state: CBResponse) { const nextState: CBToRoll = state.doTake() return (listeners: Partial<Pick<CubeGameListener, 'onDoubleAccepted'>>) => { listeners.onDoubleAccepted?.(nextState, state) } } function doPass(state: CBResponse) { const nextState: CBEoG = state.doPass() return ( listeners: Partial< Pick<CubeGameListener, 'onEndOfCubeGame' | 'onPassed'> > ) => { listeners.onPassed?.(state, state.isDoubleFromRed) listeners.onEndOfCubeGame?.(nextState) } } function doStartCubeAction( state: CBInPlay, skipCubeAction: (cbState: CBInPlay) => boolean ) { const nextState: CBAction | CBToRoll = state.doStartCubeAction( skipCubeAction(state) ) return ( listeners: Partial< Pick< CubeGameListener, | 'onCubeActionStarted' | 'onCubeActionSkipped' | 'onAwaitCubeAction' > > ) => { listeners.onAwaitCubeAction?.(nextState) if (nextState.tag === 'CBAction') { listeners.onCubeActionStarted?.(nextState) } else { listeners.onCubeActionSkipped?.(nextState) } } } function doStartOpeningCheckerPlay(state: CBOpening, isRed: boolean) { const nextState: CBInPlay = isRed ? state.doStartCheckerPlayRed() : state.doStartCheckerPlayWhite() return ( listeners: Partial<Pick<CubeGameListener, 'onAwaitCheckerPlay'>> ) => { listeners.onAwaitCheckerPlay?.(nextState) } } function doStartCheckerPlay(state: CBAction | CBToRoll) { const nextState: CBInPlay = state.doStartCheckerPlay() return ( listeners: Partial<Pick<CubeGameListener, 'onAwaitCheckerPlay'>> ) => { listeners.onAwaitCheckerPlay?.(nextState) } } function doEndOfCubeGame( state: CBState, sgResult: SGResult, eogStatus: EOGStatus ) { const nextState: CBEoG = resultToCBEoG(state.cubeState, sgResult, eogStatus) return (listeners: Partial<Pick<CubeGameListener, 'onEndOfCubeGame'>>) => { listeners.onEndOfCubeGame?.(nextState) } }