Skip to content

Commit

Permalink
refactor(webapp): remove namespace and restructure the game logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ben196888 committed Jun 29, 2024
1 parent 06063c2 commit 04ddd01
Show file tree
Hide file tree
Showing 20 changed files with 287 additions and 249 deletions.
3 changes: 2 additions & 1 deletion packages/webapp/src/components/BoardGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import Table from '@/components/Table/Table';
import Players from '@/components/Players/Players';
import DevActions from '@/components/DevActions/DevActions';
import ActionBoard from './ActionBoard/ActionBoard';
import { GameState } from '@/game/game';

const Board: React.FC<BoardProps<OpenStarTerVillageType.State.Root>> = (props) => {
const Board: React.FC<BoardProps<GameState>> = (props) => {
const { G, ctx, debug } = props;
return (
<div className='Board'>
Expand Down
6 changes: 4 additions & 2 deletions packages/webapp/src/components/DevActions/DevActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import {
Tab,
} from '@mui/material';
import { TabContext, TabList, TabPanel } from '@mui/lab';
import { GameState } from '@/game/game';
import { AllMoves } from '@/game/moves/actionMoves';

const DevActions: React.FC<BoardProps<OpenStarTerVillageType.State.Root>> = (props) => {
const DevActions: React.FC<BoardProps<GameState>> = (props) => {
const { G, playerID, moves: nonTypeMoves, events, ctx } = props;
const moves = nonTypeMoves as unknown as OpenStarTerVillageType.Move.AllMoves;
const moves = nonTypeMoves as unknown as AllMoves;

const [tabValue, setTabValue] = useState('create-project');
const onTabChange = (event: React.SyntheticEvent, newValue: string) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/webapp/src/components/Players/Players.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { List, ListItem, Typography, Stack } from '@mui/material';
import { Players as PlayersState } from '@/game/players/players';

interface Props {
players: OpenStarTerVillageType.State.Root['players'];
players: PlayersState;
}

const Players: React.FC<Props> = (props) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/webapp/src/components/Project/ActiveProject.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Project } from '@/game/table/table';
import {
Box,
Table,
Expand All @@ -11,7 +12,7 @@ import {
} from '@mui/material';

type Props = {
project?: OpenStarTerVillageType.State.Project;
project?: Project;
};

const ActiveProject: React.FC<Props> = ({ project }) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/webapp/src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Box, Grid } from '@mui/material';
import ActiveProject from '../Project/ActiveProject';
import { Table as TableState } from '@/game/table/table';

interface Props {
table: OpenStarTerVillageType.State.Root['table'];
table: TableState;
}

const Table: React.FC<Props> = (props) => {
Expand Down
12 changes: 12 additions & 0 deletions packages/webapp/src/game/cards/card.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type BaseCard = { name: string };

export type ProjectCard = BaseCard & {
requirements: Record<JobName, number>;
};

export type JobCard = BaseCard;
export type JobName = string;

export type ForceCard = BaseCard;

export type EventCard = BaseCard;
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { filterInplace } from './utils';
import { filterInplace } from '../utils';

export interface ICards {
GetById<T>(cards: T[], index: number): T;
Expand Down
37 changes: 0 additions & 37 deletions packages/webapp/src/game/deck.ts

This file was deleted.

File renamed without changes.
40 changes: 40 additions & 0 deletions packages/webapp/src/game/decks/deck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export interface Deck<T> {
drawPile: T[];
discardPile: T[];
}

export function newCardDeck<T>(drawPile: T[] = [], discardPile: T[] = []): Deck<T> {
return {
drawPile,
discardPile,
};
}

export interface IDeck {
ShuffleDrawPile<T>(deck: Deck<T>, shuffler: (pile: T[]) => T[]): void;
ShuffleDiscardPile<T>(deck: Deck<T>, shuffler: (pile: T[]) => T[]): void;
PutDiscardPileToDrawPile<T>(deck: Deck<T>): void;
Draw<T>(deck: Deck<T>, n: number): T[];
Discard<T>(deck: Deck<T>, ts: T[]): void;
}

export const Deck: IDeck = {
ShuffleDrawPile<T>(deck: Deck<T>, shuffler: (pile: T[]) => T[]): void {
deck.drawPile = shuffler(deck.drawPile);
},
ShuffleDiscardPile<T>(deck: Deck<T>, shuffler: (pile: T[]) => T[]): void {
deck.discardPile = shuffler(deck.discardPile);
},
PutDiscardPileToDrawPile<T>(deck: Deck<T>): void {
deck.drawPile = [...deck.drawPile, ...deck.discardPile];
deck.discardPile = [];
},
Draw<T>(deck: Deck<T>, n: number): T[] {
const result = deck.drawPile.slice(0, n);
deck.drawPile = deck.drawPile.slice(n);
return result;
},
Discard<T>(deck: Deck<T>, ts: T[]) {
deck.discardPile = [...deck.discardPile, ...ts];
}
}
18 changes: 18 additions & 0 deletions packages/webapp/src/game/decks/decks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { EventCard, ForceCard, JobCard, ProjectCard } from "../cards/card";
import { Deck, newCardDeck } from "./deck";

export type Decks = {
projects: Deck<ProjectCard>;
jobs: Deck<JobCard>;
forces: Deck<ForceCard>;
events: Deck<EventCard>;
};

export const setupDecks = (projectCards: ProjectCard[], jobCards: JobCard[], forceCards: ForceCard[], eventCards: EventCard[]): Decks => {
return {
projects: newCardDeck<ProjectCard>(projectCards),
jobs: newCardDeck<JobCard>(jobCards),
forces: newCardDeck<ForceCard>(forceCards),
events: newCardDeck<EventCard>(eventCards),
};
}
72 changes: 30 additions & 42 deletions packages/webapp/src/game/game.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,39 @@
import { Game, MoveFn, PlayerID } from 'boardgame.io';
import { INVALID_MOVE } from 'boardgame.io/core';
import { Deck, newCardDeck } from './deck';
import { Cards } from './cards';
import { Deck } from './decks/deck';
import { Cards } from './cards/cards';
import projectCards from './data/card/projects.json';
import jobCards from './data/card/jobs.json';
import forceCards from './data/card/forces.json';
import eventCards from './data/card/events.json';
import { ActiveProject, ActiveProjects } from './activeProjects';
import { contributeJoinedProjects, contributeOwnedProjects, createProject, mirror, recruit, removeAndRefillJobs } from './moves/actionMoves';
import { ActiveProject, ActiveProjects } from './table/activeProjects';
import { ActionMoves, Contribution, contributeJoinedProjects, contributeOwnedProjects, createProject, mirror, recruit, removeAndRefillJobs } from './moves/actionMoves';
import { ProjectCard } from './cards/card';
import { Decks, setupDecks } from './decks/decks';
import { Table, setupTable } from './table/table';
import { Player, Players, setupPlayers } from './players/players';

type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

export const OpenStarTerVillage: Game<OpenStarTerVillageType.State.Root> = {
export interface GameState {
rules: Rule;
decks: Decks;
table: Table;
players: Players;
}

export interface Rule {
}

export const OpenStarTerVillage: Game<GameState> = {
setup: ({ ctx }) => {
const rules: OpenStarTerVillageType.State.Root['rules'] = {};

const players: OpenStarTerVillageType.State.Root['players'] = ctx.playOrder
.reduce((s: Record<PlayerID, OpenStarTerVillageType.State.Player>, playerId) => {
s[playerId] = {
hand: { projects: [], forces: [] },
token: { workers: 0, actions: 0 },
completed: { projects: [] },
victoryPoints: 0,
};
return s;
}, {});

const decks: OpenStarTerVillageType.State.Root['decks'] = {
projects: newCardDeck<OpenStarTerVillageType.Card.Project>(projectCards as unknown as OpenStarTerVillageType.Card.Project[]),
jobs: newCardDeck<OpenStarTerVillageType.Card.Job>(jobCards),
forces: newCardDeck<OpenStarTerVillageType.Card.Force>(forceCards),
events: newCardDeck<OpenStarTerVillageType.Card.Event>(eventCards),
};
const rules: Rule = {};

const table: OpenStarTerVillageType.State.Root['table'] = {
activeEvent: null,
activeProjects: [],
activeJobs: [],
activeMoves: {
contributeJoinedProjects: true,
contributeOwnedProjects: true,
createProject: true,
recruit: true,
removeAndRefillJobs: true,
mirror: true,
},
};
const players = setupPlayers(ctx.playOrder);

const decks = setupDecks(projectCards as unknown as ProjectCard[], jobCards, forceCards, eventCards);

const table = setupTable();

return {
rules,
Expand Down Expand Up @@ -196,14 +184,14 @@ export const OpenStarTerVillage: Game<OpenStarTerVillageType.State.Root> = {
refillAndEnd: {
client: false,
move: (context) => {
const refillProject: MoveFn<OpenStarTerVillageType.State.Root> = (({G, ctx}) => {
const refillProject: MoveFn<GameState> = (({G, ctx}) => {
const maxProjectCards = 2;
const refillCardNumber = maxProjectCards - G.players[ctx.currentPlayer].hand.projects.length;
const projectCards = Deck.Draw(G.decks.projects, refillCardNumber);
Cards.Add(G.players[ctx.currentPlayer].hand.projects, projectCards);
});

const refillForce: MoveFn<OpenStarTerVillageType.State.Root> = (({G, ctx}) => {
const refillForce: MoveFn<GameState> = (({G, ctx}) => {
const maxForceCards = 2;
const refillCardNumber = maxForceCards - G.players[ctx.currentPlayer].hand.forces.length;
const forceCards = Deck.Draw(G.decks.forces, refillCardNumber);
Expand All @@ -222,8 +210,8 @@ export const OpenStarTerVillage: Game<OpenStarTerVillageType.State.Root> = {
G.players[ctx.currentPlayer].token.actions = 3;

// reset active moves
Object.keys(G.table.activeMoves).forEach(move => {
G.table.activeMoves[move as keyof OpenStarTerVillageType.Move.ActionMoves] = true;
Object.keys(G.table.activeActionMoves).forEach(move => {
G.table.activeActionMoves[move as keyof ActionMoves] = true;
});
events.endTurn()
},
Expand All @@ -235,7 +223,7 @@ export const OpenStarTerVillage: Game<OpenStarTerVillageType.State.Root> = {
},
playerView: ({ G, ctx, playerID}) => {
const { decks, players, ...view } = G;
const publicPlayers: Record<PlayerID, PartialBy<OpenStarTerVillageType.State.Player, 'hand'>> = {};
const publicPlayers: Record<PlayerID, PartialBy<Player, 'hand'>> = {};
for (let id in players) {
if (id === playerID) {
publicPlayers[id] = players[id];
Expand Down
Loading

0 comments on commit 04ddd01

Please sign in to comment.