import { DiceCombo, DieResult } from './dieState' import { PlayerSide } from './gameState' export enum IncomingEventType { // Chooses the action to be performed for this round but does not lock it in until the player rolls. // Valid during GameState.ROUND_START SelectAction = 'select_action', // Dice buttons toggle the selection of that die // Valid during GameState.TURN_ROLLED ToggleSelectDie = 'toggle_select_die', // Button 1 is Select All/Deselect All // Select All appears if no dice are selected // Deselect All displays if at least one die is selected // Both valid during GameState.TURN_ROLLED SelectAllDice = 'select_all_dice', DeselectAllDice = 'deselect_all_dice', // Button 2 is Hold/Release selected dice // If only held dice are selected, Release appears // For selections with at least one unheld die, Hold appears // Both valid during GameState.TURN_ROLLED HoldSelectedDice = 'hold_selected_dice', ReleaseSelectedDice = 'release_selected_dice', // Button 3 is End Turn/Score Selected Dice // End Turn appears by default; if there are not enough stop dice rolled it is "Fail Turn" instead // If there are not enough points, it is "End Turn" with a warning // Score Selected Dice appears when any dice are selected, but is only enabled if at least one scoreable die is // selected and no non-scoreable dice are selected // Both appear during GameState.TURN_ROLLED // End Turn also appears and must be pressed to move to the next round (or end the game) in GameState.TURN_FAILED EndTurn = 'end_turn', ScoreSelectedDice = 'score_selected_dice', // Button 4 is Roll Dice // It's always visible, but is disabled if there are no unheld dice or if the action has not been chosen // Valid during GameState.ROUND_START, GameState.TURN_START, and GameState.TURN_ROLLED RollDice = 'roll_dice', // Abort ends the game without a victor // Valid during any state except GameState.ABORTED or GameState.VICTORY Abort = 'abort', } export interface IncomingBaseEvent { // The type of event to execute. readonly type: IncomingEventType } export interface IncomingIndexedEvent extends IncomingBaseEvent { readonly type: IncomingEventType.SelectAction | IncomingEventType.ToggleSelectDie readonly index: number } export interface IncomingSimpleEvent extends IncomingBaseEvent { readonly type: | IncomingEventType.SelectAllDice | IncomingEventType.HoldSelectedDice | IncomingEventType.ReleaseSelectedDice | IncomingEventType.ScoreSelectedDice | IncomingEventType.EndTurn | IncomingEventType.DeselectAllDice | IncomingEventType.RollDice } export interface IncomingPlayerEvent extends IncomingBaseEvent { readonly type: IncomingEventType.Abort readonly player: PlayerSide } export type IncomingEvent = IncomingIndexedEvent | IncomingSimpleEvent | IncomingPlayerEvent export enum ErrorType { NotValidRightNow = 'not_valid_right_now', InvalidIndex = 'invalid_index', InsufficientMatchingDice = 'insufficient_matching_dice', DataLoadFailed = 'data_load_failed', UnexpectedError = 'unexpected_error', } export interface GameError { readonly type: ErrorType readonly message: string } export enum OutgoingEventType { Dialogue = 'dialogue', Description = 'description', DamageOrRecovery = 'damage', ChangeStops = 'change_stops', ChangeFails = 'change_fails', ChangeDamageBonus = 'change_damage_bonus', ScoreDice = 'score_dice', GainFailures = 'gain_failures', PassTurn = 'pass_turn', FailTurn = 'fail_turn', AbandonTurn = 'abandon_turn', LoseRound = 'lose_round', LoseGame = 'lose_game', StartRoll = 'new_roll', StartTurn = 'new_turn', StartRound = 'new_round', } export enum TextSender { Top = 'top', Bottom = 'bottom', Narrator = 'narrator', } export interface OutgoingBaseEvent { readonly type: OutgoingEventType } export interface OutgoingTextEvent extends OutgoingBaseEvent { readonly type: OutgoingEventType.Description | OutgoingEventType.Dialogue readonly sender: TextSender readonly text: string } export interface OutgoingBaseTargetedEvent extends OutgoingBaseEvent { readonly type: | OutgoingEventType.DamageOrRecovery | OutgoingEventType.ChangeStops | OutgoingEventType.ChangeFails | OutgoingEventType.ChangeDamageBonus | OutgoingEventType.LoseRound | OutgoingEventType.LoseGame | OutgoingEventType.ScoreDice | OutgoingEventType.GainFailures | OutgoingEventType.PassTurn | OutgoingEventType.StartRoll | OutgoingEventType.StartTurn | OutgoingEventType.StartRound readonly target: PlayerSide } export interface OutgoingSimpleTargetedEvent extends OutgoingBaseTargetedEvent { readonly type: | OutgoingEventType.LoseGame | OutgoingEventType.StartTurn | OutgoingEventType.StartRound | OutgoingEventType.PassTurn } export interface OutgoingDamageEvent extends OutgoingBaseTargetedEvent { readonly type: | OutgoingEventType.DamageOrRecovery | OutgoingEventType.ChangeStops | OutgoingEventType.ChangeFails | OutgoingEventType.ChangeDamageBonus | OutgoingEventType.LoseRound | OutgoingEventType.GainFailures readonly delta: number } export interface OutgoingStartRollEvent extends OutgoingBaseTargetedEvent { readonly type: OutgoingEventType.StartRoll readonly newDice: readonly DieResult[] } export interface OutgoingScoreDiceEvent extends OutgoingBaseTargetedEvent { readonly type: OutgoingEventType.ScoreDice readonly scoredCombo: DiceCombo readonly scoredDice: readonly DieResult[] readonly scoreDelta: number } export type OutgoingEvent = | OutgoingTextEvent | OutgoingSimpleTargetedEvent | OutgoingDamageEvent | OutgoingStartRollEvent | OutgoingScoreDiceEvent export interface BaseEventResult { readonly newState: T } export interface SuccessResult extends BaseEventResult { readonly events: readonly OutgoingEvent[] } export interface FailedResult extends BaseEventResult { readonly error: GameError } export type EventResult = SuccessResult | FailedResult