Skip to content

Commit

Permalink
feat(webapp): add end game event card handler
Browse files Browse the repository at this point in the history
  • Loading branch information
ben196888 committed Jul 19, 2024
1 parent 12053b4 commit 6cecf04
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 7 deletions.
23 changes: 23 additions & 0 deletions packages/webapp/src/game/core/handler/eventCardHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { RuleMutator } from "@/game/store/slice/rule";
import { GameHookHandler } from "../type"
import { ScoreBoardSelector } from "@/game/store/slice/scoreBoard";

type EventCardHandler = {
start: GameHookHandler;
end?: GameHookHandler;
}

const endGameAfterThisRound: EventCardHandler = {
start: ({ G }) => {
// Leftover action tokens are converted to 1 victory points
RuleMutator.setSettlementLastContributorVictoryPoints(G.rules, 1);
},
end: ({ G, events }) => {
RuleMutator.setSettlementLastContributorVictoryPoints(G.rules, 0);
events.endGame({ winner: ScoreBoardSelector.getWinner(G.table.scoreBoard) });
},
}

export const eventCardHandlers: Record<string, EventCardHandler> = {
end_game_after_this_round: endGameAfterThisRound,
};
13 changes: 9 additions & 4 deletions packages/webapp/src/game/core/handler/playEventCard.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { DeckMutator, DeckSelector } from "@/game/store/slice/deck";
import { GameHookHandler } from "../type";
import { TableMutator } from "@/game/store/slice/table";
import { eventCardHandlers } from "./eventCardHandlers";

export const playEventCard: GameHookHandler = ({ G }) => {
const eventCard = DeckSelector.peek(G.decks.events, 1);
export const playEventCard: GameHookHandler = (context) => {
const { G } = context;
const eventCard = DeckSelector.peek(G.decks.events, 1)[0];
DeckMutator.draw(G.decks.events, 1);
console.log('play event card', eventCard[0].name);
TableMutator.playEvent(G.table, eventCard[0]);
console.log('play event card', eventCard.name);
TableMutator.playEvent(G.table, eventCard);

const eventCardHandler = eventCardHandlers[eventCard.function_name];
eventCardHandler?.start(context);
};
11 changes: 9 additions & 2 deletions packages/webapp/src/game/core/handler/removeEventCard.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { TableMutator, TableSelector } from "@/game/store/slice/table";
import { GameHookHandler } from "../type";
import { eventCardHandlers } from "./eventCardHandlers";
import { DeckMutator } from "@/game/store/slice/deck";

export const removeEventCard: GameHookHandler = ({ G }) => {
export const removeEventCard: GameHookHandler = (context) => {
const { G } = context;
const eventCard = TableSelector.getCurrentEvent(G.table);
console.log('remove event card', eventCard?.name);
console.log('remove event card', eventCard!.name);
const eventCardHandler = eventCardHandlers[eventCard!.function_name];
eventCardHandler?.end?.(context);

TableMutator.removeEvent(G.table);
DeckMutator.discard(G.decks.events, [eventCard!]);
};
19 changes: 19 additions & 0 deletions packages/webapp/src/game/core/handler/scoreLeftoverActionTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PlayersSelector } from "@/game/store/slice/players";
import { GameHookHandler } from "../type";
import { RuleSelector } from "@/game/store/slice/rule";
import { ScoreBoardMutator } from "@/game/store/slice/scoreBoard";

export const scoreLeftoverActionTokens: GameHookHandler = ({ G, ctx }) => {
console.log('score leftover action tokens');
const victoryPointsPerActionToken = RuleSelector.getSettlementLeftoverActionTokensVictoryPoints(G.rules);
if (victoryPointsPerActionToken <= 0) {
console.log('no victory points for leftover action tokens');
return;
}

const currentPlayer = ctx.currentPlayer;
const leftoverActionTokens = PlayersSelector.getNumActionTokens(G.players, currentPlayer);
const victoryPoints = leftoverActionTokens * victoryPointsPerActionToken;
ScoreBoardMutator.add(G.table.scoreBoard, currentPlayer, victoryPoints);
console.log('end score leftover action tokens');
}
2 changes: 1 addition & 1 deletion packages/webapp/src/game/core/handler/settleProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const settleProjects: GameHookHandler = (({ G }) => {
// score bonus points
// last contributor bonus
const lastContributorBonusPoints = RuleSelector.getSettlementLastContributorVictoryPoints(G.rules);
ScoreBoardMutator.add(G.table.scoreBoard, projectSlot.lastContributor!, lastContributorBonusPoints);
ScoreBoardMutator.add(G.table.scoreBoard, projectSlot.lastContributor, lastContributorBonusPoints);

// owner bonus
const ownerBonusPoints = RuleSelector.getSettlementProjectOwnerVictoryPoints(G.rules);
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/src/game/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { removeEventCard } from './core/handler/removeEventCard';
import { passStartPlayerToken } from './core/handler/passStartPlayerToken';
import { PlayersSelector } from './store/slice/players';
import { settleProjects } from './core/handler/settleProjects';
import { scoreLeftoverActionTokens } from './core/handler/scoreLeftoverActionTokens';
import { refill } from './core/handler/refill';

export const OpenStarTerVillage: Game<GameState> = {
Expand Down Expand Up @@ -42,6 +43,7 @@ export const OpenStarTerVillage: Game<GameState> = {
onEnd: (context) => {
const { ctx } = context;
settleProjects(context);
scoreLeftoverActionTokens(context);
refill(context);
if (ctx.playOrderPos === ctx.numPlayers - 1) {
console.log('last player ends');
Expand Down
15 changes: 15 additions & 0 deletions packages/webapp/src/game/store/slice/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface Rule {
maxProjectCards: number;
},
settlement: {
leftoverActionTokensVictoryPoints: number;
projectOwnerVictoryPoints: number;
lastContributorVictoryPoints: number;
},
Expand Down Expand Up @@ -109,12 +110,17 @@ const initialState = (): Rule => {
maxProjectCards: 2,
},
settlement: {
leftoverActionTokensVictoryPoints: 0,
projectOwnerVictoryPoints: 2,
lastContributorVictoryPoints: 2,
},
};
}

const setSettlementLastContributorVictoryPoints = (rule: Rule, victoryPoints: number): void => {
rule.settlement.lastContributorVictoryPoints = victoryPoints;
};

const isStandardRule = (rule: Rule): boolean => {
return rule.type === 'standard';
}
Expand Down Expand Up @@ -207,6 +213,10 @@ const getPlayerMaxProjectCards = (rule: Rule): number => {
return rule.player.maxProjectCards;
}

const getSettlementLeftoverActionTokensVictoryPoints = (rule: Rule): number => {
return rule.settlement.leftoverActionTokensVictoryPoints;
}

const getSettlementProjectOwnerVictoryPoints = (rule: Rule): number => {
return rule.settlement.projectOwnerVictoryPoints;
};
Expand All @@ -217,6 +227,9 @@ const getSettlementLastContributorVictoryPoints = (rule: Rule): number => {

const RuleSlice = {
initialState,
mutators: {
setSettlementLastContributorVictoryPoints,
},
selectors: {
isStandardRule,
getNonEndGameNumberOfEventCards,
Expand All @@ -232,10 +245,12 @@ const RuleSlice = {
getPlayerMaxActionTokens,
getPlayerMaxWorkerTokens,
getPlayerMaxProjectCards,
getSettlementLeftoverActionTokensVictoryPoints,
getSettlementProjectOwnerVictoryPoints,
getSettlementLastContributorVictoryPoints,
},
};

export const RuleMutator = RuleSlice.mutators;
export const RuleSelector = RuleSlice.selectors;
export default RuleSlice;
19 changes: 19 additions & 0 deletions packages/webapp/src/game/store/slice/scoreBoard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,29 @@ const mutators = {
},
};

const selectors = {
getPlayerPoints: (state: ScoreBoard, playerId: PlayerID): number => {
return state[playerId];
},
getWinner: (state: ScoreBoard): PlayerID => {
let winner: PlayerID = '';
let maxPoints = -Infinity;
Object.entries(state).forEach(([playerId, points]) => {
if (points > maxPoints) {
maxPoints = points;
winner = playerId;
}
});
return winner;
},
};

const ScoreBoardSlice = {
initialState,
selectors,
mutators,
};

export const ScoreBoardMutator = ScoreBoardSlice.mutators;
export const ScoreBoardSelector = ScoreBoardSlice.selectors;
export default ScoreBoardSlice;

0 comments on commit 6cecf04

Please sign in to comment.