tsgammon-core
Version:
A Backgammon library for Typescript, formerly developed as a part of tsgammon-ui
220 lines (210 loc) • 6.63 kB
text/typescript
import { nodeWithEmptyDice } from '../../BoardStateNode'
import { boardState as _boardState } from '../../BoardState'
import { cube, CubeState } from '../../CubeState'
import { DicePip } from '../../Dices'
import { eog } from '../../EOGStatus'
import { GameConf, standardConf } from '../../GameConf'
import { Ply } from '../../Ply'
import { SGResult } from '../../records/SGResult'
import { Score } from '../../Score'
import {
cbActionRed,
cbActionWhite,
cbInPlayRed,
cbInPlayWhite,
cbOpening,
cbResponseRed,
cbResponseWhite,
CBState,
cbToRollRed,
cbToRollWhite,
resultToCBEoG,
} from '../CubeGameState'
import {
eogStateRed,
eogStateWhite,
inPlayStateRed,
inPlayStateWhite,
openingState,
SGState,
toRollStateRed,
toRollStateWhite,
} from '../SingleGameState'
import {
redViewAbsoluteBoard,
whiteViewAbsoluteBoard,
} from '../../AbsoluteBoardState'
export enum GameStatus {
OPENING,
INPLAY_RED,
INPLAY_WHITE,
CUBEACTION_RED,
CUBEACTION_WHITE,
CUBERESP_RED,
CUBERESP_WHITE,
TOROLL_RED,
TOROLL_WHITE,
EOG_REDWON,
EOG_WHITEWON,
}
/**
* ゲーム中の一局面を表すオブジェクトを構成するためのパラメーターの定義:局面に応じて、必要な項目は変化する
*/
export type GameSetup =
// 開始局面では、駒の配置とキューブだけ決まっていれば良い
| {
gameStatus?: GameStatus.OPENING
absPos?: number[]
cubeState?: CubeState
}
// ロール前の局面
| {
gameStatus:
| GameStatus.TOROLL_RED
| GameStatus.TOROLL_WHITE
| GameStatus.CUBEACTION_RED
| GameStatus.CUBEACTION_WHITE
| GameStatus.CUBERESP_RED
| GameStatus.CUBERESP_WHITE
absPos: number[]
cubeState?: CubeState
lastPly?: Ply
}
// 終局後の局面
| {
gameStatus: GameStatus.EOG_REDWON | GameStatus.EOG_WHITEWON
absPos: number[]
stake: Score
cubeState?: CubeState
lastPly?: Ply
}
//ロール後の局面
| {
gameStatus: GameStatus.INPLAY_RED | GameStatus.INPLAY_WHITE
dice1: DicePip
dice2: DicePip
absPos: number[]
cubeState?: CubeState
lastPly?: Ply
}
export function toCBState(gameState: GameSetup = {}): CBState {
const { gameStatus, cubeState = cube(1) } = gameState
if (gameStatus === undefined) {
return cbOpening(cubeState)
}
switch (gameStatus) {
case GameStatus.OPENING:
return cbOpening(cubeState)
case GameStatus.INPLAY_RED:
return cbInPlayRed(cubeState)
case GameStatus.INPLAY_WHITE:
return cbInPlayWhite(cubeState)
case GameStatus.CUBEACTION_RED:
return cbActionRed(cubeState)
case GameStatus.CUBEACTION_WHITE:
return cbActionWhite(cubeState)
case GameStatus.CUBERESP_RED:
return cbResponseRed(cubeState)
case GameStatus.CUBERESP_WHITE:
return cbResponseWhite(cubeState)
case GameStatus.TOROLL_RED:
return cbToRollRed(cubeState, 'Skip')
case GameStatus.TOROLL_WHITE:
return cbToRollWhite(cubeState, 'Skip')
case GameStatus.EOG_REDWON:
return resultToCBEoG(cubeState, SGResult.REDWON, eog())
case GameStatus.EOG_WHITEWON:
return resultToCBEoG(cubeState, SGResult.WHITEWON, eog())
}
}
export function toSGState(
gameState: GameSetup = {},
gameConf: GameConf = standardConf
): SGState {
const { movesForDoublet = 4 } = gameConf
if (gameState.gameStatus === undefined) {
return openingState(
boardState(gameState.absPos ?? standardConf.initialPos),
undefined,
movesForDoublet
)
}
switch (gameState.gameStatus) {
case GameStatus.OPENING:
return openingState(
boardState(gameState.absPos ?? standardConf.initialPos),
undefined,
movesForDoublet
)
case GameStatus.CUBEACTION_RED:
case GameStatus.TOROLL_RED:
case GameStatus.CUBERESP_WHITE: {
const board = boardState(gameState.absPos)
const lastStateNode = nodeWithEmptyDice(board)
return toRollStateRed(
lastStateNode.board.revert(),
gameState.lastPly,
movesForDoublet
)
}
case GameStatus.CUBEACTION_WHITE:
case GameStatus.TOROLL_WHITE:
case GameStatus.CUBERESP_RED: {
const lastBoardState = boardState(gameState.absPos).revert()
const lastStateNode = nodeWithEmptyDice(lastBoardState)
return toRollStateWhite(
lastStateNode.board.revert(),
gameState.lastPly,
movesForDoublet
)
}
case GameStatus.INPLAY_RED:
return inPlayStateRed(
boardState(gameState.absPos).revert(),
gameState,
movesForDoublet
)
case GameStatus.INPLAY_WHITE:
return inPlayStateWhite(
boardState(gameState.absPos),
gameState,
movesForDoublet
)
case GameStatus.EOG_REDWON: {
const lastBoardState = boardState(gameState.absPos).revert()
return eogStateRed(
1,
eog(),
redViewAbsoluteBoard(lastBoardState),
lastBoardState
)
}
case GameStatus.EOG_WHITEWON: {
const lastBoardState = boardState(gameState.absPos).revert()
return eogStateWhite(
1,
eog(),
whiteViewAbsoluteBoard(lastBoardState),
lastBoardState
)
}
}
function boardState(pos: number[]) {
const pieces = pos.reduce(
(prev: { me: number; opp: number }, cur: number) => {
return cur > 0
? { me: prev.me + cur, opp: prev.opp }
: cur < 0
? { me: prev.me, opp: prev.opp - cur }
: prev
},
{ me: 0, opp: 0 }
)
return _boardState(
pos,
[15 - pieces.me, 15 - pieces.opp],
gameConf.innerPos,
gameConf.isEoGFunc
)
}
}