UNPKG

hathora-et-labora-game

Version:

Plays Uwe Rosenberg's Ora et Labora for the Hathora engine. It reduces a list of moves into a board game state.

70 lines (64 loc) 2.73 kB
import { all, any, curry, lens, lensProp, pipe, view } from 'ramda' import { match } from 'ts-pattern' import { addBonusAction, revertActivePlayerToCurrent, setFrameToAllowFreeUsage, withFrame } from '../board/frame' import { moveClergyToOwnBuilding } from '../board/landscape' import { activeLens, isLayBrother, isPrior } from '../board/player' import { GameCommandEnum, GameStatePlaying, NextUseClergy, StateReducer } from '../types' // there are two modes of this, really... // first, if activePlayer == currentPlayer, then make it so the next "use" is with a prior // -> fail if they have no prior available // -> otherwise set the nextUse = NextUseClergy.OnlyPrior const withPriorForCurrentPlayer: StateReducer = (state) => { if (state === undefined) return undefined if (state.players[state.frame.activePlayerIndex].clergy.some(isPrior) === false) return undefined return withFrame((frame) => ({ ...frame, nextUse: NextUseClergy.OnlyPrior, mainActionUsed: true, }))(state) } // second, if activePlayer != currentPlayer, as in a work contract, then // -> move the player's prior onto the building in usableBuildings (work contracted building) // -> set the nextUse = NextUseClergy.Free // -> set the activePlayer back to currentPlayer const withPriorForWorkContract: StateReducer = (state) => { if (state === undefined) return undefined if (state.frame.usableBuildings.length !== 1) return undefined return pipe( // withPriorForCurrentPlayer, moveClergyToOwnBuilding(state.frame.usableBuildings[0]), setFrameToAllowFreeUsage([state.frame.usableBuildings[0]]), revertActivePlayerToCurrent )(state) } export const withPrior: StateReducer = (state) => { if (state === undefined) return undefined if (state.frame.activePlayerIndex === state.frame.currentPlayerIndex) { return pipe( // withPriorForCurrentPlayer, addBonusAction(GameCommandEnum.USE) )(state) } return withPriorForWorkContract(state) } export const complete = (state: GameStatePlaying) => (partial: string[]): string[] => match<string[], string[]>(partial) .with([], () => { const player = view(activeLens(state), state) const control = view(lensProp('frame'), state) if (control.activePlayerIndex === control.currentPlayerIndex) { // this is the normal case, outside of work_contract if (control.nextUse === NextUseClergy.OnlyPrior) return [] if (control.mainActionUsed) return [] } if (all(isLayBrother, player.clergy)) return [] return [GameCommandEnum.WITH_PRIOR] }) .with([GameCommandEnum.WITH_PRIOR], () => { return [''] }) .otherwise(() => [])