hathora-et-labora-game
Version:
Game logic reducer for Uwe Rosenberg's Ora et Labora
92 lines • 4.63 kB
JavaScript
import { match } from 'ts-pattern';
import { always, head, map, pipe, sum } from 'ramda';
import { pickFrameFlow } from './board/frame';
import { GameCommandEnum, SettlementRound, GameStatusEnum, } from './types';
import { completeBuild, completeCommit, completeConvert, completeCutPeat, completeFellTrees, completeSettle, completeUse, completeWorkContract, completeWithLaybrother, completeWithPrior, completeBuyPlot, completeBuyDistrict, } from './commands';
import { goodsPoints } from './board/resource';
import { allBuildingPoints, allDwellingPoints } from './board/landscape';
import { introduceBuildings, roundBuildings } from './board/buildings';
import { introduceGrapeToken, introduceStoneToken } from './board/rondel';
const computeFlow = (state) => {
const frameFlow = pickFrameFlow(state.config);
const flow = [];
let limit = 200;
let frameIndex;
let playerIndex = state.frame.activePlayerIndex;
let frame = state.frame;
let { round } = frame;
let lastSeenSettlementRound = SettlementRound.S;
do {
round = frame.round ?? round;
playerIndex = frame.currentPlayerIndex ?? playerIndex;
const settle = !!frame.bonusActions?.includes(GameCommandEnum.SETTLE) || !!frame.neutralBuildingPhase;
lastSeenSettlementRound = frame.settlementRound ?? lastSeenSettlementRound;
flow.push({
round,
player: state?.players?.[playerIndex]?.color,
settle,
bonus: !!frame.bonusRoundPlacement,
introduced: [
...(frame.upkeep?.includes(introduceBuildings) ? roundBuildings(state.config, lastSeenSettlementRound) : []),
...(frame.upkeep?.includes(introduceGrapeToken) ? ['grape'] : []),
...(frame.upkeep?.includes(introduceStoneToken) ? ['stone'] : []),
],
});
frameIndex = frame.next;
frame = frameFlow[frame.next];
} while (frame && frameIndex < frame.next && limit--);
return flow;
};
export const control = (state, partial, player) => {
const completion = match(head(partial))
.with(undefined, () => state.status === GameStatusEnum.FINISHED
? []
: [
...completeUse(state)([]),
...completeBuild(state)([]),
...completeCutPeat(state)([]),
...completeFellTrees(state)([]),
...completeWorkContract(state)([]),
...completeBuyPlot(state)([]),
...completeBuyDistrict(state)([]),
...completeConvert(state)([]),
...completeSettle(state)([]),
...completeWithLaybrother(state)([]),
...completeWithPrior(state)([]),
...completeCommit(state)([]),
])
// this can be prettier with https://github.com/gvergnaud/ts-pattern/pull/139
// git blame this line and see how it used to be, but i really want something like
// .with([GameCommandEnum.Use, P.rest], complete.USE(state))
.with(GameCommandEnum.USE, () => completeUse(state)(partial))
.with(GameCommandEnum.BUILD, () => completeBuild(state)(partial))
.with(GameCommandEnum.CUT_PEAT, () => completeCutPeat(state)(partial))
.with(GameCommandEnum.FELL_TREES, () => completeFellTrees(state)(partial))
.with(GameCommandEnum.WORK_CONTRACT, () => completeWorkContract(state)(partial))
.with(GameCommandEnum.BUY_PLOT, () => completeBuyPlot(state)(partial))
.with(GameCommandEnum.BUY_DISTRICT, () => completeBuyDistrict(state)(partial))
.with(GameCommandEnum.CONVERT, () => completeConvert(state)(partial))
.with(GameCommandEnum.SETTLE, () => completeSettle(state)(partial))
.with(GameCommandEnum.WITH_LAYBROTHER, () => completeWithLaybrother(state)(partial))
.with(GameCommandEnum.WITH_PRIOR, () => completeWithPrior(state)(partial))
.with(GameCommandEnum.COMMIT, () => completeCommit(state)(partial))
.otherwise(always([]));
const score = map(pipe((player) => ({
goods: goodsPoints(player) + 30 * player.wonders,
economic: allBuildingPoints(player.landscape),
settlements: allDwellingPoints(player.landscape),
total: -Infinity,
}), (score) => ({
...score,
total: sum([...score.settlements, score.goods, score.economic]),
})), state.players.slice(0, state.config.players) // this will remove neutral player
);
return {
active: player === state.frame.activePlayerIndex,
flow: computeFlow(state),
partial,
completion,
score,
};
};
//# sourceMappingURL=control.js.map