UNPKG

hathora-et-labora-game

Version:

Game logic reducer for Uwe Rosenberg's Ora et Labora

60 lines (53 loc) 2.1 kB
import { add, always, ap, concat, curry, map, min, pipe, range, reverse, unnest, view } from 'ramda' import { P, match } from 'ts-pattern' import { activeLens, getCost, payCost, withActivePlayer } from '../board/player' import { costMoney, parseResourceParam, stringRepeater } from '../board/resource' import { GameState, ResourceEnum, StateReducer } from '../types' export const cloisterLibrary = (inputs = ''): StateReducer => { const input = parseResourceParam(inputs) const { book = 0, ...inputWithoutBook } = input const newBooks = Math.min(costMoney(inputWithoutBook), 3) const soldBook = Math.min(book ?? 0, 1) return withActivePlayer( pipe( // payCost(inputWithoutBook), getCost({ book: newBooks }), payCost({ book: soldBook }), getCost({ meat: soldBook, wine: soldBook }) ) ) } export const complete = curry((partial: string[], state: GameState): string[] => match(partial) .with([], () => { const player = view(activeLens(state), state) const { penny = 0, book = 0 } = player // step 1: figure out how many times we might send in penny, given max pennies const pennyAmounts: number[] = reverse(range(0, 1 + Math.min(3, penny))) // step 2: for each amount of penny, figure out how many books they would have const paymentAmounts = map<number, [number, string]>( (pennyAmount): [number, string] => [pennyAmount + book, stringRepeater(ResourceEnum.Penny, pennyAmount)], pennyAmounts ) // then for each of those, sell 0 or 1 book if there are any const consumeBreadAmounts = unnest( map( ([sellableBooks, resourceString]) => pipe( // min<number>(1), add(1), range(0), reverse<number>, map(stringRepeater(ResourceEnum.Book)), map((s) => resourceString + String(s)) )(sellableBooks), paymentAmounts ) ) return consumeBreadAmounts }) .with([P._], always([''])) .otherwise(always([])) )