83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
import { Board, Card, Hand, Pile, Stack, Suit } from "./types/cards";
|
|
import { clone } from "./fn";
|
|
|
|
const AGG: Suit = "spades";
|
|
const CUL: Suit = "hearts";
|
|
const TECH: Suit = "diamonds";
|
|
const MIL: Suit = "clubs";
|
|
|
|
type GameState = {
|
|
mainPile: Pile;
|
|
discardStack: Stack;
|
|
deadPile: Pile;
|
|
players: {
|
|
hand: Hand;
|
|
board: Board;
|
|
}[];
|
|
playerTurn: number;
|
|
lastMove: Move;
|
|
prevState: GameState | null;
|
|
};
|
|
|
|
type Move =
|
|
| {
|
|
type: "draw";
|
|
fromPile: "main" | "discard";
|
|
}
|
|
| { type: "play"; card: Card }
|
|
| { type: "remove"; card: Card }
|
|
| { type: "attack"; army: Card[] }
|
|
| { type: "pass" };
|
|
|
|
type Action = Move | { type: "discard"; cards: Card[] };
|
|
|
|
const techTier = (techValue: number) => Math.ceil(techValue / 14);
|
|
const moveCost = (move: Move) => (move.type == "attack" ? move.army.length : 1);
|
|
const movesSpent = (state: GameState): number =>
|
|
state.playerTurn != state.prevState?.playerTurn
|
|
? 0
|
|
: moveCost(state.lastMove) + movesSpent(state.prevState);
|
|
|
|
const value = (suit: Suit) => (board: Board) =>
|
|
board
|
|
.filter((card) => card.suit === suit)
|
|
.reduce((v, card) => v + card.value, 0);
|
|
|
|
export const getNextState = (p: {
|
|
state: GameState;
|
|
move: Move;
|
|
}): GameState | { illegal: string } => {
|
|
const { state, move } = p;
|
|
|
|
const currentPlayer = state.players[state.playerTurn];
|
|
|
|
const population = currentPlayer.board.thru(value(AGG));
|
|
const culture = currentPlayer.board.thru(value(CUL));
|
|
const tech = techTier(currentPlayer.board.thru(value(TECH)));
|
|
|
|
const movesRemaining = tech - movesSpent(state);
|
|
|
|
const newState = clone(state);
|
|
if (move.type === "draw") {
|
|
const pile =
|
|
move.fromPile === "main"
|
|
? newState.mainPile
|
|
: newState.discardStack;
|
|
|
|
if (pile.length === 0) {
|
|
return {
|
|
illegal: `The ${move.fromPile} pile is empty; cannot draw`,
|
|
};
|
|
}
|
|
|
|
newState.players[newState.playerTurn].hand.push(pile.pop()!);
|
|
if (movesRemaining == 1) {
|
|
newState.playerTurn =
|
|
(newState.playerTurn + 1) % newState.players.length;
|
|
}
|
|
return newState;
|
|
}
|
|
|
|
return { illegal: "idk bruh" };
|
|
};
|