hathora-et-labora-game
Version:
Game logic reducer for Uwe Rosenberg's Ora et Labora
104 lines • 4.15 kB
JavaScript
import { always, assoc, curry, equals, isNil, pathSatisfies, propSatisfies, when } from 'ramda';
import { match } from 'ts-pattern';
import { ResourceEnum, } from '../types';
import { getCost, withActivePlayer } from './player';
import { multiplyGoods, parseResourceParam } from './resource';
const tokenToResource = (token) => {
switch (token) {
case 'grain':
return ResourceEnum.Grain;
case 'sheep':
return ResourceEnum.Sheep;
case 'clay':
return ResourceEnum.Clay;
case 'coin':
return ResourceEnum.Penny;
case 'wood':
return ResourceEnum.Wood;
case 'peat':
return ResourceEnum.Peat;
case 'grape':
return ResourceEnum.Grape;
case 'stone':
return ResourceEnum.Stone;
}
};
export const withRondel = (func) => {
return (state) => {
if (state === undefined)
return state;
const rondel = func(state.rondel);
if (rondel === undefined)
return undefined;
return assoc('rondel', rondel, state);
};
};
export const updateRondel = (token) => {
return (rondel) => {
if (rondel === undefined)
return undefined;
if (rondel[token] === undefined)
return rondel;
return assoc(token, rondel[token] !== undefined ? rondel.pointingBefore : rondel[token])(rondel);
};
};
const introduceToken = (token) => withRondel(when(propSatisfies(isNil, token), (rondel) => assoc(token, rondel.pointingBefore, rondel)));
export const introduceGrapeToken = when(pathSatisfies(equals('france'), ['config', 'country']), introduceToken('grape'));
export const introduceStoneToken = introduceToken('stone');
export const armValues = ({ length, players }) => {
if (players === 2 && length === 'short') {
return [0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 10];
}
return [0, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 10];
};
export const take = (armIndex, tokenIndex, config) => {
const armVals = armValues(config);
return armVals[(armIndex - tokenIndex + armVals.length) % armVals.length];
};
export const takePlayerJoker = (unitCost) => {
return (state) => {
if (state === undefined)
return undefined;
const { pointingBefore, joker } = state.rondel;
const config = state.config;
const takeValue = take(pointingBefore, joker ?? pointingBefore, config);
return withActivePlayer(getCost(multiplyGoods(takeValue)(unitCost)))(state);
};
};
export const advanceJokerOnRondel = withRondel((rondel) => rondel && assoc('joker', rondel.pointingBefore, rondel));
export const updateToken = (withToken, withJoker) => (rondel) => {
if (withJoker)
return updateRondel('joker')(rondel);
if (rondel[withToken] === undefined)
return updateRondel('joker')(rondel);
return updateRondel(withToken)(rondel);
};
export const standardSesourceGatheringAction = (usingToken, withJoker) => {
return (state) => {
if (state === undefined)
return state;
const { joker, pointingBefore } = state.rondel;
const config = state.config;
const main = state.rondel[usingToken];
const amount = take(pointingBefore, (withJoker ? joker : (main ?? joker)) ?? pointingBefore, config);
const resource = tokenToResource(usingToken);
const cost = parseResourceParam(resource);
const magnitude = multiplyGoods(amount)(cost);
return withActivePlayer(getCost(magnitude))(state);
};
};
export const standardSesourceGatheringCompletion = curry((usingToken, partial, state) => {
const jokerAvailable = state.rondel.joker !== undefined;
const mainAvailable = state.rondel[usingToken] !== undefined;
return match(partial)
.with([], () => {
if (jokerAvailable && mainAvailable)
return ['', 'Jo'];
if (jokerAvailable !== mainAvailable)
return [''];
return [];
})
.with(['Jo'], () => (jokerAvailable ? [''] : []))
.otherwise(always([]));
});
//# sourceMappingURL=rondel.js.map