hathora-et-labora-game
Version:
Game logic reducer for Uwe Rosenberg's Ora et Labora
63 lines (55 loc) • 2.34 kB
text/typescript
import { always, curry, flatten, identity, map, pipe, reduce, sum, view } from 'ramda'
import { P, match } from 'ts-pattern'
import { isCloisterBuilding } from '../board/buildings'
import { activeLens, getCost, payCost, withActivePlayer } from '../board/player'
import { costMoney, costPoints, parseResourceParam, rewardCostOptions, coinCostOptions } from '../board/resource'
import { GameCommandConfigParams, GameState, Tile } from '../types'
const pointsPerCloister = (config: GameCommandConfigParams) =>
match(config)
.with({ players: 1 }, () => 1.0)
.with({ players: 2, length: 'long' }, () => 1.5)
.otherwise(() => 2.0)
// given a row of tiles, return all of the buildings where there is a building AND a clergy
const cloistersInRow = map(([_, building]: Tile) => (isCloisterBuilding(building) ? 1 : 0))
// given a list of rows, do the thing
const cloistersInLandscape = map((landRow: Tile[]) => cloistersInRow(landRow))
const entitledPointCount = (state: GameState | undefined): number => {
if (state === undefined) return -1
const multiplier = pointsPerCloister(state.config!)
const cloisters = sum(flatten(cloistersInLandscape(state.players![state.frame!.activePlayerIndex].landscape)))
return multiplier * cloisters
}
// TODO: turn into R.when
const checkCloistersForPoints = (points: number) => (state: GameState | undefined) => {
if (entitledPointCount(state) < points) return undefined
return state
}
export const houseOfTheBrotherhood = (param1 = '', param2 = '') => {
const input = parseResourceParam(param1)
const output = parseResourceParam(param2)
const costOutput = costPoints(output)
if (costMoney(input) < 5) return identity
return pipe(
//
checkCloistersForPoints(costOutput),
withActivePlayer(
pipe(
//
payCost(input),
getCost(output)
)
)
)
}
export const complete = curry((partial: string[], state: GameState): string[] => {
const player = view(activeLens(state), state)
return match(partial)
.with([], () => [...coinCostOptions(5, player), ''])
.with([P._], ([paidNickels]) => {
const input = parseResourceParam(paidNickels)
if (costMoney(input) < 5) return []
return rewardCostOptions(entitledPointCount(state))
})
.with([P._, P._], always(['']))
.otherwise(always([]))
})