hathora-et-labora-game
Version:
Game logic reducer for Uwe Rosenberg's Ora et Labora
38 lines • 2.54 kB
JavaScript
import { add, always, ap, concat, curry, map, min, multiply, pipe, range, reverse, unnest, view } from 'ramda';
import { P, match } from 'ts-pattern';
import { activeLens, getCost, payCost, withActivePlayer } from '../board/player';
import { canAfford, costEnergy, energyCostOptions, parseResourceParam, stringRepeater } from '../board/resource';
export const bakery = (param = '') => {
// parse the input string and create variables for each resource, defaulting to 0 if none
const { flour = 0, wood = 0, coal = 0, straw = 0, peat = 0, bread = 0 } = parseResourceParam(param);
// total up all the energy, divide by 1/2, and if they are sending in more flour than that
if (flour > costEnergy({ wood, coal, straw, peat }) / 0.5)
return always(undefined);
return withActivePlayer(pipe(
// make sure the player has this much stuff (for bread, reduce that amount by the number of flour)
canAfford({ flour, wood, coal, straw, peat, bread: bread - flour }),
// remove all of the stuff from the player, except bread
payCost({ flour, wood, coal, straw, peat }),
// then give them n bread, where n is the amount of flour
getCost({ bread: flour }),
// then take away how many breads they sent in as input
payCost({ bread }),
// and give them 4 coins per bread
getCost({ penny: (Math.min(bread, 2) * 4) % 5, nickel: Math.floor((Math.min(bread, 2) * 4) / 5) })));
};
export const complete = curry((partial, state) => match(partial)
.with([], () => {
const player = view(activeLens(state), state);
const { flour = 0, wood = 0, coal = 0, straw = 0, peat = 0, bread = 0 } = player;
// step 1: figure out how many times we might send in flour, given flour and energy constraint
const flourAmounts = pipe(costEnergy, multiply(2), Math.ceil, min(flour), add(1), range(0), (reverse))(player);
// step 2: for each amount of flour to use up, multiply by ways of getting that energy
const paymentAmounts = unnest(map((flourAmount) => map((s) => [bread + flourAmount, s], ap([concat(stringRepeater('Fl', flourAmount))], energyCostOptions(flourAmount / 2, { coal, peat, wood, straw }))), flourAmounts));
const consumeBreadAmounts = unnest(map(([sellableBread, resourceString]) => pipe(
//
min(2), add(1), range(0), (reverse), ap([stringRepeater('Br')]), map((s) => resourceString + String(s)))(sellableBread), paymentAmounts));
return consumeBreadAmounts;
})
.with([P._], always(['']))
.otherwise(always([])));
//# sourceMappingURL=bakery.js.map