tsgammon-core
Version:
A Backgammon library for Typescript, formerly developed as a part of tsgammon-ui
179 lines (170 loc) • 5.29 kB
text/typescript
import {
matchStateEoG,
MatchStateEoG,
MatchStateInPlay,
matchStateLastGame,
matchStateNewGame,
} from '../MatchState'
import { GameConf, standardConf } from '../GameConf'
import {
gameRecordEoG,
GameRecordEoG,
GameRecordInPlay,
gameRecordInPlay,
} from './GameRecord'
import { PlyRecordEoG, PlyRecordInPlay } from './PlyRecord'
/**
* マッチ全体の記録
* @template T 手番に紐づけて保持される、局面を表す任意のオブジェクトの型
*/
export type MatchRecord<T> = MatchRecordInPlay<T> | MatchRecordEoG<T>
type _MatchRecord<T> = {
/** ルールなど、ゲームの設定 */
conf: GameConf
/** すでに終局したゲームの記録 */
gameRecords: GameRecordEoG<T>[]
}
export type MatchRecordInPlay<T> = _MatchRecord<T> & {
isEoG: false
matchState: MatchStateInPlay
/** 現ゲームの記録:すなわち、現在進行中、または最後に終局したゲームの記録 */
curGameRecord: GameRecordInPlay<T>
}
export type MatchRecordEoG<T> = _MatchRecord<T> & {
isEoG: true
matchState: MatchStateEoG
/** 現ゲームの記録:すなわち、現在進行中、または最後に終局したゲームの記録 */
curGameRecord: GameRecordEoG<T>
}
export function matchRecordInPlay<T>(
conf: GameConf = standardConf,
matchState: MatchStateInPlay
): MatchRecordInPlay<T> {
const curGameRecord = gameRecordInPlay<T>(matchState)
return {
isEoG: false,
conf,
matchState,
gameRecords: [],
curGameRecord,
}
}
/**
* 現在の記録について、一手番分の記録を追加して返す
*
* @param matchRecord 現在の記録
* @param plyRecord 追加される手番の記録
* @param state 手番に紐づけて記録される、局面の状態を示す任意のオブジェクト
* @returns 更新後の記録
*/
export function addPlyRecord<T>(
matchRecord: MatchRecordInPlay<T>,
plyRecord: PlyRecordInPlay,
state: T
): MatchRecordInPlay<T> {
return {
...matchRecord,
curGameRecord: {
...matchRecord.curGameRecord,
plyRecords: matchRecord.curGameRecord.plyRecords.concat({
plyRecord,
state,
}),
},
}
}
/**
* 現在の記録について、現ゲームの記録をリセットして返す
*
* 現ゲームが終局していれば、すでに終局したゲームの記録に追加する。そうでなければ破棄する。
*
* ※ 現ゲームが終局しても、画面表示上は終局状態として現ゲームの記録が必要なので、
* 終局の記録{@link eogRecord}と現ゲームの記録のリセットとで処理を分けている。
*
* @param matchRecord 現在の記録
* @returns 更新後の記録
*/
export function recordFinishedGame<T>(
matchRecord: MatchRecordEoG<T>
): MatchRecord<T> {
const { matchState } = matchRecord
if (matchState.isEoM) {
return matchRecord
} else {
const matchStateNext = matchStateNewGame(matchState)
return {
...matchRecord,
isEoG: false,
matchState: matchStateNext,
gameRecords: matchRecord.gameRecords.concat(
matchRecord.curGameRecord
),
curGameRecord: gameRecordInPlay(matchStateNext),
}
}
}
export function discardCurrentGame<T>(
matchRecord: MatchRecordInPlay<T>
): MatchRecordInPlay<T> {
return {
...matchRecord,
curGameRecord: gameRecordInPlay(matchRecord.matchState),
}
}
/**
* 現在の記録について、任意の手番に復帰し、それ以降の手番の記録を破棄して返す
* @param matchRecord 現在の記録
* @param index 復帰先となる手番
* @returns 更新後の記録
*/
export function trimPlyRecords<T>(
matchRecord: MatchRecord<T>,
index: number
): MatchRecordInPlay<T> {
const idx =
0 <= index && index < matchRecord.curGameRecord.plyRecords.length
? index
: matchRecord.curGameRecord.plyRecords.length - 1
const matchState: MatchStateInPlay = matchRecord.isEoG
? matchStateLastGame(matchRecord.matchState)
: matchRecord.matchState
return {
...matchRecord,
isEoG: false,
matchState,
curGameRecord: {
...matchRecord.curGameRecord,
plyRecords: matchRecord.curGameRecord.plyRecords.slice(0, idx),
isEoG: false,
},
}
}
/**
* 現在の記録について、現ゲームの記録に終局の記録を追加して返す
*
* @param matchRecord 現在の記録
* @param eogMatchState 終局時のMatchState
* @param eogRecord 終局の記録
* @returns 更新後の記録
*/
export function eogRecord<T>(
matchRecord: MatchRecordInPlay<T>,
eogRecord: PlyRecordEoG
): MatchRecordEoG<T> {
const matchState = matchStateEoG(
matchRecord.matchState,
eogRecord.stake,
eogRecord.eogStatus
)
const curGameRecord = gameRecordEoG(
matchRecord.curGameRecord,
eogRecord,
matchState.isEoM
)
return {
...matchRecord,
isEoG: true,
curGameRecord,
matchState,
}
}