hathora-et-labora-game
Version:
Game logic reducer for Uwe Rosenberg's Ora et Labora
55 lines (49 loc) • 1.85 kB
text/typescript
import { always, curry, identity, pipe, reduce, view } from 'ramda'
import { P, match } from 'ts-pattern'
import { activeLens, getCost, payCost, withActivePlayer } from '../board/player'
import { costPoints, parseResourceParam, rewardCostOptions } from '../board/resource'
import { Cost, GameState, StateReducer, TableauReducer, Tile } from '../types'
import { LANDSCAPES, forestLocations, moorLocations } from '../board/landscape'
// TODO: refactor this with houseOfTheBrotherhood
const countForestsAndMoors: (landscape: readonly Tile[][]) => number = reduce(
(accum: number, row: Tile[]) =>
accum +
reduce(
(accum: number, [, erection]: Tile) => (erection && LANDSCAPES.includes(erection) ? accum + 1 : accum),
0,
row
),
0
)
const checkPointsForMoorsAndForests =
(output: Cost): TableauReducer =>
(player) => {
if (player === undefined) return undefined
const forestsAndMoors = countForestsAndMoors(player.landscape)
if (costPoints(output) > forestsAndMoors) return undefined
return player
}
export const festivalGround = (input = '', output = ''): StateReducer => {
const inputBeer = parseResourceParam(input)
const outputPoints = parseResourceParam(output)
if (inputBeer.beer !== 1) return identity
return withActivePlayer(
pipe(
//
payCost(inputBeer),
checkPointsForMoorsAndForests(outputPoints),
getCost(outputPoints)
)
)
}
export const complete = curry((partial: string[], state: GameState): string[] => {
const player = view(activeLens(state), state)
return match(partial)
.with([], () => {
if (player.beer) return ['Be', '']
return ['']
})
.with([P._], () => rewardCostOptions(forestLocations(player).length + moorLocations(player).length))
.with([P._, P._], always(['']))
.otherwise(always([]))
})