export enum DieFace { FAIL = 'F', STOP = 'S', WILD = '*', BONUS = 'B', USELESS = 'X', SCORE_0 = '0', SCORE_1 = '1', SCORE_2 = '2', SCORE_3 = '3', SCORE_4 = '4', SCORE_5 = '5', SCORE_6 = '6', SCORE_7 = '7', SCORE_8 = '8', SCORE_9 = '9', SCORE_10 = '10', } export type SpecialDie = DieFace.FAIL | DieFace.STOP | DieFace.WILD | DieFace.BONUS | DieFace.USELESS export type ScoringDie = | DieFace.SCORE_0 | DieFace.SCORE_1 | DieFace.SCORE_2 | DieFace.SCORE_3 | DieFace.SCORE_4 | DieFace.SCORE_5 | DieFace.SCORE_6 | DieFace.SCORE_7 | DieFace.SCORE_8 | DieFace.SCORE_9 | DieFace.SCORE_10 type DieFaceCount = { [v in DieFace]?: number } export enum DieState { ROLLED = 'rolled', SELECTED = 'selected', HELD = 'held', HELD_SELECTED = 'held_selected', SCORED = 'scored', } export function isHeldState(d: DieState): d is DieState.HELD | DieState.HELD_SELECTED { return d === DieState.HELD || d === DieState.HELD_SELECTED } export function isSelectedState(d: DieState): d is DieState.SELECTED | DieState.HELD_SELECTED { return d === DieState.SELECTED || d === DieState.HELD_SELECTED } export function setSelected(d: DieState): DieState.SELECTED | DieState.HELD_SELECTED | DieState.SCORED { switch (d) { case DieState.ROLLED: return DieState.SELECTED case DieState.HELD: return DieState.HELD_SELECTED case DieState.SELECTED: case DieState.HELD_SELECTED: case DieState.SCORED: return d } } export function setDeselected(d: DieState): DieState.ROLLED | DieState.HELD | DieState.SCORED { switch (d) { case DieState.SELECTED: return DieState.ROLLED case DieState.HELD_SELECTED: return DieState.HELD case DieState.ROLLED: case DieState.HELD: case DieState.SCORED: return d } } export function toggleSelected(d: DieState): DieState { switch (d) { case DieState.ROLLED: return DieState.SELECTED case DieState.SELECTED: return DieState.ROLLED case DieState.HELD: return DieState.HELD_SELECTED case DieState.HELD_SELECTED: return DieState.HELD case DieState.SCORED: return DieState.SCORED } } export interface DieResult { readonly type: DieType readonly face: DieFace readonly state: DieState } export interface DieType { // The name of this die type readonly name: string // The faces of this die type; faces may be repeated to increase their odds readonly faces: readonly DieFace[] } export interface DiceCombo { // The name of this combo, for the UI readonly name: string // How many points this combo is worth readonly points: number // Which dice are needed to satisfy this combo readonly dice: readonly ScoringDie[] // How many dice can be replaced for the combo readonly wildMaxDice?: number } export interface DiceComboResult { // combo used readonly combo: DiceCombo // total number of points readonly points: number // number of dice used readonly usesDice: DieFaceCount // number of wild dice used readonly wildDice: number // number of bonus dice used readonly bonusDice: number }