starting to abstract the game

This commit is contained in:
2025-08-28 22:20:24 -04:00
parent d69336027a
commit 0d6d3d6d32
8 changed files with 59 additions and 21 deletions

View File

@@ -14,6 +14,7 @@ import { createObservable, createObservableWithInit, cx } from "~/fn";
import { me, mePromise } from "~/profile"; import { me, mePromise } from "~/profile";
import Game from "./Game"; import Game from "./Game";
import Player from "./Player"; import Player from "./Player";
import games from "@games/shared/games/index";
export const TableContext = createContext<{ export const TableContext = createContext<{
view: Accessor<any>; view: Accessor<any>;
@@ -110,7 +111,14 @@ export default (props: { tableKey: string }) => {
}} }}
> >
<Show when={view() == null}> <Show when={view() == null}>
<div class="absolute center"> <div class="absolute tc mt-8 flex gap-4">
<select>
<For each={Object.entries(games)}>
{([gameId, game]) => (
<option value={gameId}>{game.title}</option>
)}
</For>
</select>
<button <button
onClick={() => setReady((prev) => !prev)} onClick={() => setReady((prev) => !prev)}
class="button p-1 " class="button p-1 "

View File

@@ -25,20 +25,16 @@ export default defineConfig({
"bc", "bc",
{ {
bottom: 0, bottom: 0,
left: 0, left: "50%",
right: 0, transform: "translateX(-50%)",
"margin-left": "auto",
"margin-right": "auto",
}, },
], ],
[ [
"tc", "tc",
{ {
top: 0, top: 0,
left: 0, left: "50%",
right: 0, transform: "translateX(-50%)",
"margin-left": "auto",
"margin-right": "auto",
}, },
], ],

View File

@@ -4,7 +4,7 @@ import {
SimpleAction, SimpleAction,
SimpleConfiguration, SimpleConfiguration,
SimpleGameState, SimpleGameState,
} from "./games/simple"; } from "@games/shared/games/simple";
import { human } from "./human"; import { human } from "./human";
import dayjs from "dayjs"; import dayjs from "dayjs";
import db from "./db"; import db from "./db";

View File

@@ -1,10 +0,0 @@
import * as renaissance from "./renaissance";
import * as simple from "./simple";
const games = {
renaissance,
simple,
};
export default games;
export type Game = keyof typeof games;

View File

@@ -7,7 +7,7 @@ import {
SimpleAction, SimpleAction,
SimpleConfiguration, SimpleConfiguration,
SimpleGameState, SimpleGameState,
} from "./games/simple"; } from "@games/shared/games/simple";
import { transform } from "./kefir-extension"; import { transform } from "./kefir-extension";
export const WsOut = t.Object({ export const WsOut = t.Object({

View File

@@ -0,0 +1,25 @@
import * as renaissance from "./renaissance";
import simple from "./simple";
export type Game<
C extends { game: string },
S,
A,
E extends { error: any },
V
> = {
title: string;
rules: string;
init: (config: C) => S;
resolveAction: (p: { config: C; state: S; action: A }) => S | E;
getView: (p: { config: C; state: S; humanKey: string }) => V;
resolveQuit: (p: { config: C; state: S; humanKey: string }) => S;
};
const games = {
// renaissance,
simple,
} satisfies { [key: string]: Game<any, any, any, any, any> };
export default games;
export type GameId = keyof typeof games;

View File

@@ -1,5 +1,6 @@
import { Card, Hand, newDeck, Pile, shuffle, vCard } from "@games/shared/cards"; import { Card, Hand, newDeck, Pile, shuffle, vCard } from "@games/shared/cards";
import { heq } from "@games/shared/utils"; import { heq } from "@games/shared/utils";
import type { Game } from ".";
export type SimpleConfiguration = { export type SimpleConfiguration = {
game: "simple"; game: "simple";
@@ -101,3 +102,21 @@ export const resolveSimpleAction = ({
}; };
} }
}; };
type SimpleError = { error: "whoops!" };
export default {
title: "Simple",
rules: "You can draw, or you can discard. Then your turn is up.",
init: newSimpleGameState,
resolveAction: resolveSimpleAction,
getView: ({ config, state, humanKey }) =>
getSimplePlayerView(config, state, humanKey),
resolveQuit: () => null,
} satisfies Game<
SimpleConfiguration,
SimpleGameState,
SimpleAction,
SimpleError,
SimplePlayerView
>;