@journey-to-code/games 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/backgammon.d.ts +146 -0
- package/dist/backgammon.js +1221 -0
- package/dist/backgammon.js.map +1 -0
- package/dist/blackjack.d.ts +66 -0
- package/dist/blackjack.js +452 -0
- package/dist/blackjack.js.map +1 -0
- package/dist/bluff.d.ts +60 -0
- package/dist/bluff.js +239 -0
- package/dist/bluff.js.map +1 -0
- package/dist/board.d.ts +387 -0
- package/dist/board.js +105 -0
- package/dist/board.js.map +1 -0
- package/dist/bridge.d.ts +86 -0
- package/dist/bridge.js +494 -0
- package/dist/bridge.js.map +1 -0
- package/dist/canasta.d.ts +88 -0
- package/dist/canasta.js +646 -0
- package/dist/canasta.js.map +1 -0
- package/dist/checkers.d.ts +108 -0
- package/dist/checkers.js +756 -0
- package/dist/checkers.js.map +1 -0
- package/dist/chess.d.ts +162 -0
- package/dist/chess.js +904 -0
- package/dist/chess.js.map +1 -0
- package/dist/chesscore.d.ts +136 -0
- package/dist/chesscore.js +1121 -0
- package/dist/chesscore.js.map +1 -0
- package/dist/combat.d.ts +102 -0
- package/dist/combat.js +772 -0
- package/dist/combat.js.map +1 -0
- package/dist/contractrummy.d.ts +77 -0
- package/dist/contractrummy.js +430 -0
- package/dist/contractrummy.js.map +1 -0
- package/dist/crazy8.d.ts +65 -0
- package/dist/crazy8.js +366 -0
- package/dist/crazy8.js.map +1 -0
- package/dist/cribbage.d.ts +75 -0
- package/dist/cribbage.js +428 -0
- package/dist/cribbage.js.map +1 -0
- package/dist/cuckoo.d.ts +43 -0
- package/dist/cuckoo.js +216 -0
- package/dist/cuckoo.js.map +1 -0
- package/dist/drinkingpyramid.d.ts +54 -0
- package/dist/drinkingpyramid.js +213 -0
- package/dist/drinkingpyramid.js.map +1 -0
- package/dist/drinks.d.ts +25 -0
- package/dist/drinks.js +40 -0
- package/dist/drinks.js.map +1 -0
- package/dist/dropfour.d.ts +103 -0
- package/dist/dropfour.js +577 -0
- package/dist/dropfour.js.map +1 -0
- package/dist/durak.d.ts +58 -0
- package/dist/durak.js +332 -0
- package/dist/durak.js.map +1 -0
- package/dist/euchre.d.ts +80 -0
- package/dist/euchre.js +453 -0
- package/dist/euchre.js.map +1 -0
- package/dist/fivedraw.d.ts +50 -0
- package/dist/fivedraw.js +289 -0
- package/dist/fivedraw.js.map +1 -0
- package/dist/fivehundred.d.ts +90 -0
- package/dist/fivehundred.js +504 -0
- package/dist/fivehundred.js.map +1 -0
- package/dist/freecell.d.ts +50 -0
- package/dist/freecell.js +327 -0
- package/dist/freecell.js.map +1 -0
- package/dist/fruitsalad.d.ts +69 -0
- package/dist/fruitsalad.js +427 -0
- package/dist/fruitsalad.js.map +1 -0
- package/dist/gin.d.ts +72 -0
- package/dist/gin.js +393 -0
- package/dist/gin.js.map +1 -0
- package/dist/go.d.ts +132 -0
- package/dist/go.js +659 -0
- package/dist/go.js.map +1 -0
- package/dist/goboard.d.ts +218 -0
- package/dist/goboard.js +880 -0
- package/dist/goboard.js.map +1 -0
- package/dist/gofish.d.ts +37 -0
- package/dist/gofish.js +235 -0
- package/dist/gofish.js.map +1 -0
- package/dist/golf.d.ts +64 -0
- package/dist/golf.js +343 -0
- package/dist/golf.js.map +1 -0
- package/dist/handfoot.d.ts +86 -0
- package/dist/handfoot.js +515 -0
- package/dist/handfoot.js.map +1 -0
- package/dist/hearts.d.ts +65 -0
- package/dist/hearts.js +390 -0
- package/dist/hearts.js.map +1 -0
- package/dist/holdem.d.ts +45 -0
- package/dist/holdem.js +286 -0
- package/dist/holdem.js.map +1 -0
- package/dist/horserace.d.ts +49 -0
- package/dist/horserace.js +207 -0
- package/dist/horserace.js.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/kingscorner.d.ts +59 -0
- package/dist/kingscorner.js +374 -0
- package/dist/kingscorner.js.map +1 -0
- package/dist/kingscup.d.ts +44 -0
- package/dist/kingscup.js +185 -0
- package/dist/kingscup.js.map +1 -0
- package/dist/kit.d.ts +283 -0
- package/dist/kit.js +73 -0
- package/dist/kit.js.map +1 -0
- package/dist/klondike.d.ts +57 -0
- package/dist/klondike.js +314 -0
- package/dist/klondike.js.map +1 -0
- package/dist/liarspoker.d.ts +61 -0
- package/dist/liarspoker.js +298 -0
- package/dist/liarspoker.js.map +1 -0
- package/dist/memory.d.ts +36 -0
- package/dist/memory.js +181 -0
- package/dist/memory.js.map +1 -0
- package/dist/minigolf.d.ts +104 -0
- package/dist/minigolf.js +724 -0
- package/dist/minigolf.js.map +1 -0
- package/dist/minigolfcourse.d.ts +127 -0
- package/dist/minigolfcourse.js +470 -0
- package/dist/minigolfcourse.js.map +1 -0
- package/dist/offers.d.ts +136 -0
- package/dist/offers.js +279 -0
- package/dist/offers.js.map +1 -0
- package/dist/ohhell.d.ts +66 -0
- package/dist/ohhell.js +331 -0
- package/dist/ohhell.js.map +1 -0
- package/dist/oldmaid.d.ts +40 -0
- package/dist/oldmaid.js +186 -0
- package/dist/oldmaid.js.map +1 -0
- package/dist/pinochle.d.ts +94 -0
- package/dist/pinochle.js +466 -0
- package/dist/pinochle.js.map +1 -0
- package/dist/pitch.d.ts +77 -0
- package/dist/pitch.js +362 -0
- package/dist/pitch.js.map +1 -0
- package/dist/poker.d.ts +79 -0
- package/dist/poker.js +268 -0
- package/dist/poker.js.map +1 -0
- package/dist/president.d.ts +56 -0
- package/dist/president.js +339 -0
- package/dist/president.js.map +1 -0
- package/dist/pyramid.d.ts +39 -0
- package/dist/pyramid.js +200 -0
- package/dist/pyramid.js.map +1 -0
- package/dist/registry.d.ts +17 -0
- package/dist/registry.js +70 -0
- package/dist/registry.js.map +1 -0
- package/dist/reversi.d.ts +69 -0
- package/dist/reversi.js +584 -0
- package/dist/reversi.js.map +1 -0
- package/dist/ridethebus.d.ts +48 -0
- package/dist/ridethebus.js +257 -0
- package/dist/ridethebus.js.map +1 -0
- package/dist/rummy500.d.ts +89 -0
- package/dist/rummy500.js +474 -0
- package/dist/rummy500.js.map +1 -0
- package/dist/sevens.d.ts +48 -0
- package/dist/sevens.js +221 -0
- package/dist/sevens.js.map +1 -0
- package/dist/slapjack.d.ts +42 -0
- package/dist/slapjack.js +224 -0
- package/dist/slapjack.js.map +1 -0
- package/dist/speed.d.ts +44 -0
- package/dist/speed.js +201 -0
- package/dist/speed.js.map +1 -0
- package/dist/spider.d.ts +51 -0
- package/dist/spider.js +320 -0
- package/dist/spider.js.map +1 -0
- package/dist/spite.d.ts +75 -0
- package/dist/spite.js +372 -0
- package/dist/spite.js.map +1 -0
- package/dist/sport.d.ts +266 -0
- package/dist/sport.js +48 -0
- package/dist/sport.js.map +1 -0
- package/dist/switch.d.ts +69 -0
- package/dist/switch.js +393 -0
- package/dist/switch.js.map +1 -0
- package/dist/table.d.ts +284 -0
- package/dist/table.js +67 -0
- package/dist/table.js.map +1 -0
- package/dist/talk.d.ts +17 -0
- package/dist/talk.js +44 -0
- package/dist/talk.js.map +1 -0
- package/dist/thirtyone.d.ts +66 -0
- package/dist/thirtyone.js +372 -0
- package/dist/thirtyone.js.map +1 -0
- package/dist/tictactoe.d.ts +68 -0
- package/dist/tictactoe.js +541 -0
- package/dist/tictactoe.js.map +1 -0
- package/dist/tricks.d.ts +21 -0
- package/dist/tricks.js +48 -0
- package/dist/tricks.js.map +1 -0
- package/dist/war.d.ts +44 -0
- package/dist/war.js +185 -0
- package/dist/war.js.map +1 -0
- package/dist/whist.d.ts +52 -0
- package/dist/whist.js +218 -0
- package/dist/whist.js.map +1 -0
- package/dist/yacht.d.ts +96 -0
- package/dist/yacht.js +653 -0
- package/dist/yacht.js.map +1 -0
- package/package.json +41 -4
- package/README.md +0 -3
package/dist/kingscup.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { botGiveTarget, drink, DRINK_NOTE, newTally } from "./drinks.js";
|
|
2
|
+
import { clone, FULL, GameError, makeDeck, nextRandom, rankLabel, rankSeats, shuffled, SYMBOL, who } from "./kit.js";
|
|
3
|
+
export const classicKingsCup = { id: "kingscup-classic", name: "Kings Cup", sips: 2 };
|
|
4
|
+
export const gentleKingsCup = { ...classicKingsCup, id: "kingscup-gentle", name: "Gentle (one sip)", sips: 1 };
|
|
5
|
+
/** Each rank's rule: its name, what to do, and whether whoever drew picks someone. */
|
|
6
|
+
export const KINGS_RULES = {
|
|
7
|
+
14: { name: "Waterfall", text: "Everyone drinks, starting with whoever drew; nobody stops until the person before them does." },
|
|
8
|
+
2: { name: "You", text: "Pick someone to drink.", pick: "Who drinks?" },
|
|
9
|
+
3: { name: "Me", text: "Whoever drew drinks." },
|
|
10
|
+
4: { name: "Floor", text: "Everyone touch the floor! Last one drinks.", pick: "Who was last to touch the floor?" },
|
|
11
|
+
5: { name: "Thumb master", text: "Whoever drew is thumb master: put your thumb on the table any time, and the last to copy drinks." },
|
|
12
|
+
6: { name: "Social", text: "Everyone drinks!" },
|
|
13
|
+
7: { name: "Heaven", text: "Everyone point up! Last one drinks.", pick: "Who was last to point up?" },
|
|
14
|
+
8: { name: "Mate", text: "Pick a mate: whenever you drink, they drink too.", pick: "Who's your mate?" },
|
|
15
|
+
9: { name: "Rhyme", text: "Say a word; round the table, everyone rhymes with it. Whoever can't, drinks.", pick: "Who couldn't rhyme?" },
|
|
16
|
+
10: { name: "Categories", text: "Name a category; round the table, everyone names one thing in it. Whoever can't, drinks.", pick: "Who ran out?" },
|
|
17
|
+
11: { name: "Make a rule", text: "Make a rule everyone has to follow (no saying 'drink', left hands only…). Break it, drink." },
|
|
18
|
+
12: { name: "Question master", text: "Whoever drew is question master: answer any question they ask with a question… or drink." },
|
|
19
|
+
13: { name: "King's Cup", text: "Pour some of your drink into the King's Cup. Whoever draws the fourth king drinks the cup!" },
|
|
20
|
+
};
|
|
21
|
+
const rank = (c) => c.rank;
|
|
22
|
+
const label = (c) => `${rankLabel(rank(c))}${SYMBOL[c.suit]}`;
|
|
23
|
+
export function newKingsCup(rules, seats, seed) {
|
|
24
|
+
const s = { game: "kingscup", rules, seats, rng: seed >>> 0, hand: 0, dealer: seed % seats, phase: "draw", last: null, kings: 0, thumb: null, question: null, rule: null, loser: null, narration: null };
|
|
25
|
+
s.deck = shuffled(makeDeck({ ranks: FULL }), nextRandom(s));
|
|
26
|
+
s.mates = Array(seats).fill(null);
|
|
27
|
+
s.tally = newTally(seats);
|
|
28
|
+
s.turn = (s.dealer + 1) % seats;
|
|
29
|
+
return s;
|
|
30
|
+
}
|
|
31
|
+
/** Drink, and take your mates along. */
|
|
32
|
+
function drinkWithMates(s, seats, n) {
|
|
33
|
+
const all = new Set(seats);
|
|
34
|
+
for (const x of seats)
|
|
35
|
+
if (s.mates[x] !== null)
|
|
36
|
+
all.add(s.mates[x]);
|
|
37
|
+
return drink(s.tally, [...all], n);
|
|
38
|
+
}
|
|
39
|
+
function apply(state, seat, move) {
|
|
40
|
+
const s = clone(state);
|
|
41
|
+
if (s.phase === "finished")
|
|
42
|
+
throw new GameError("The game is over.");
|
|
43
|
+
if (s.turn !== seat)
|
|
44
|
+
throw new GameError("It's not your turn.");
|
|
45
|
+
const everyone = Array.from({ length: s.seats }, (_, i) => i);
|
|
46
|
+
if (move.type === "pick") {
|
|
47
|
+
if (s.phase !== "pick" || !s.last)
|
|
48
|
+
throw new GameError("Draw a card first.");
|
|
49
|
+
const to = Number(move.to);
|
|
50
|
+
const r = rank(s.last);
|
|
51
|
+
if (!(to >= 0 && to < s.seats) || (to === seat && (r === 2 || r === 8)))
|
|
52
|
+
throw new GameError("Pick someone else.");
|
|
53
|
+
if (r === 8) {
|
|
54
|
+
for (const x of [seat, to])
|
|
55
|
+
if (s.mates[x] !== null)
|
|
56
|
+
s.mates[s.mates[x]] = null;
|
|
57
|
+
s.mates[seat] = to;
|
|
58
|
+
s.mates[to] = seat;
|
|
59
|
+
s.narration = `${who(seat)} and ${who(to)} are mates 🤝`;
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
s.narration = `${KINGS_RULES[r].name}: ${drinkWithMates(s, [to], s.rules.sips)}`;
|
|
63
|
+
s.phase = "draw";
|
|
64
|
+
s.turn = (seat + 1) % s.seats;
|
|
65
|
+
return s;
|
|
66
|
+
}
|
|
67
|
+
if (move.type !== "draw" || s.phase !== "draw")
|
|
68
|
+
throw new GameError("Pick someone first.");
|
|
69
|
+
const c = s.deck.pop();
|
|
70
|
+
s.last = c;
|
|
71
|
+
const r = rank(c);
|
|
72
|
+
const rule = KINGS_RULES[r];
|
|
73
|
+
let line = "";
|
|
74
|
+
if (r === 14)
|
|
75
|
+
line = drinkWithMates(s, everyone, s.rules.sips + 1);
|
|
76
|
+
else if (r === 3)
|
|
77
|
+
line = drinkWithMates(s, [seat], s.rules.sips);
|
|
78
|
+
else if (r === 6)
|
|
79
|
+
line = drinkWithMates(s, everyone, 1);
|
|
80
|
+
else if (r === 5)
|
|
81
|
+
s.thumb = seat;
|
|
82
|
+
else if (r === 12)
|
|
83
|
+
s.question = seat;
|
|
84
|
+
else if (r === 11)
|
|
85
|
+
s.rule = seat;
|
|
86
|
+
else if (r === 13) {
|
|
87
|
+
s.kings += 1;
|
|
88
|
+
if (s.kings === 4) {
|
|
89
|
+
s.loser = seat;
|
|
90
|
+
s.phase = "finished";
|
|
91
|
+
s.narration = `${who(seat)} drew the fourth king: ${drinkWithMates(s, [seat], 99)} (the King's Cup!) 👑`;
|
|
92
|
+
return s;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
s.narration = `${who(seat)} drew the ${label(c)}: ${rule.name}${line ? ` · ${line}` : ""}${r === 13 ? ` (${s.kings} of 4)` : ""}`;
|
|
96
|
+
if (rule.pick) {
|
|
97
|
+
s.phase = "pick";
|
|
98
|
+
return s;
|
|
99
|
+
}
|
|
100
|
+
s.turn = (seat + 1) % s.seats;
|
|
101
|
+
if (!s.deck.length) {
|
|
102
|
+
s.phase = "finished";
|
|
103
|
+
s.narration += " · That's the deck!";
|
|
104
|
+
}
|
|
105
|
+
return s;
|
|
106
|
+
}
|
|
107
|
+
function view(s, seat) {
|
|
108
|
+
const over = s.phase === "finished";
|
|
109
|
+
const mine = !over && s.turn === seat;
|
|
110
|
+
let choices = null;
|
|
111
|
+
if (mine && s.phase === "draw")
|
|
112
|
+
choices = { prompt: "", options: [{ label: "Draw a card", move: { type: "draw" }, primary: true }] };
|
|
113
|
+
if (mine && s.phase === "pick" && s.last) {
|
|
114
|
+
const r = rank(s.last);
|
|
115
|
+
const options = Array.from({ length: s.seats }, (_, i) => i)
|
|
116
|
+
.filter((i) => !((r === 2 || r === 8) && i === seat))
|
|
117
|
+
.map((i) => ({ label: i === seat ? "Me" : who(i), move: { type: "pick", to: i } }));
|
|
118
|
+
choices = { prompt: KINGS_RULES[r].pick, options, layout: "list" };
|
|
119
|
+
}
|
|
120
|
+
const roles = (i) => [i === s.thumb ? "👍 Thumb master" : "", i === s.question ? "❓ Question master" : "", i === s.rule ? "📜 Rule maker" : "", s.mates[i] !== null ? "🤝 Has a mate" : ""].filter(Boolean).join(" · ");
|
|
121
|
+
const rule = s.last ? KINGS_RULES[rank(s.last)] : null;
|
|
122
|
+
return {
|
|
123
|
+
game: "kingscup",
|
|
124
|
+
seats: s.seats,
|
|
125
|
+
me: seat,
|
|
126
|
+
teams: false,
|
|
127
|
+
phase: s.phase,
|
|
128
|
+
turn: over ? null : s.turn,
|
|
129
|
+
dealer: s.dealer,
|
|
130
|
+
hand: [],
|
|
131
|
+
handHidden: "none",
|
|
132
|
+
tap: null,
|
|
133
|
+
pick: null,
|
|
134
|
+
choices,
|
|
135
|
+
players: s.tally.drank.map((d, i) => ({ cards: 0, line: [`🍺 ${d}`, roles(i)].filter(Boolean).join(" · "), dealer: i === s.dealer })),
|
|
136
|
+
center: { kind: "piles", stock: s.deck.length, discard: s.last ? [s.last] : [], discardCount: s.last ? 52 - s.deck.length : 0, drawMove: mine && s.phase === "draw" ? { type: "draw" } : null, takeMove: null, stockLabel: `👑 ${s.kings} of 4 kings`, discardLabel: rule ? rule.name : "Draw to start" },
|
|
137
|
+
melds: [],
|
|
138
|
+
info: [...(rule ? [rule.text] : ["Draw a card and do what it says."]), DRINK_NOTE],
|
|
139
|
+
narration: s.narration,
|
|
140
|
+
scores: s.tally.drank.map((value, i) => ({ seats: [i], value })),
|
|
141
|
+
result: null,
|
|
142
|
+
over: over ? { winners: Array.from({ length: s.seats }, (_, i) => i).filter((i) => i !== s.loser), title: s.loser !== null ? `${who(s.loser)} drinks the King's Cup!` : "That's the deck!" } : null,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function bot(s, seat, _style) {
|
|
146
|
+
if (s.phase === "finished" || s.turn !== seat)
|
|
147
|
+
return null;
|
|
148
|
+
if (s.phase === "draw")
|
|
149
|
+
return { type: "draw" };
|
|
150
|
+
return { type: "pick", to: botGiveTarget(s.tally, seat, s.seats) };
|
|
151
|
+
}
|
|
152
|
+
export const kingsCup = {
|
|
153
|
+
id: "kingscup",
|
|
154
|
+
name: "Kings Cup",
|
|
155
|
+
emoji: "👑",
|
|
156
|
+
blurb: "Drinking game: every card has a rule",
|
|
157
|
+
tagline: "A drinking game. Draw a card and follow its rule. Whoever draws the fourth king drinks the King's Cup!",
|
|
158
|
+
seats: { min: 2, max: 10, default: 5 },
|
|
159
|
+
teams: false,
|
|
160
|
+
presets: [classicKingsCup, gentleKingsCup],
|
|
161
|
+
fields: [{ key: "sips", label: "Sips for You, Me and the rest", kind: "choice", options: [[1, "1"], [2, "2"], [3, "3"]] }],
|
|
162
|
+
normalize(rules) {
|
|
163
|
+
const given = (rules && typeof rules === "object" ? rules : {});
|
|
164
|
+
const base = [classicKingsCup, gentleKingsCup].find((p) => p.id === given.id) ?? classicKingsCup;
|
|
165
|
+
const r = { ...base, ...given };
|
|
166
|
+
return { ...r, sips: Math.min(5, Math.max(1, Number(r.sips) || 2)) };
|
|
167
|
+
},
|
|
168
|
+
validate: () => [],
|
|
169
|
+
describe: () => [
|
|
170
|
+
`${DRINK_NOTE} Adults only.`,
|
|
171
|
+
"Take turns drawing a card. Each rank has a rule:",
|
|
172
|
+
...[14, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].map((r) => `${rankLabel(r)} · ${KINGS_RULES[r].name}: ${KINGS_RULES[r].text}`),
|
|
173
|
+
"For the rules played out at the table, whoever drew picks who drinks.",
|
|
174
|
+
],
|
|
175
|
+
newGame: newKingsCup,
|
|
176
|
+
apply,
|
|
177
|
+
view,
|
|
178
|
+
bot,
|
|
179
|
+
thinkingTime: (s) => (s.phase === "pick" ? 2200 : 1600),
|
|
180
|
+
summary(s) {
|
|
181
|
+
const over = s.phase === "finished";
|
|
182
|
+
return { game: "kingscup", rules: s.rules.name, phase: s.phase, over, hand: 1, scoreLine: s.tally.drank.join(" · ") + " drinks", order: over ? rankSeats(s.tally.drank.map((score, i) => ({ seats: [i], score })), true) : null, winners: over ? Array.from({ length: s.seats }, (_, i) => i).filter((i) => i !== s.loser) : null, teams: false, seats: s.seats };
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
//# sourceMappingURL=kingscup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kingscup.js","sourceRoot":"","sources":["../src/kingscup.ts"],"names":[],"mappings":"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"}
|
package/dist/kit.d.ts
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import type { Card, Suit } from "@journey-to-code/rules";
|
|
2
|
+
import { type BaseRules, type CardGameId, type Choices, type GameOver, type RoundResult, type RuleField, type Scores, type TableGame } from "./table.js";
|
|
3
|
+
export * from "./table.js";
|
|
4
|
+
export type PipCard = Extract<Card, {
|
|
5
|
+
kind: "pip";
|
|
6
|
+
}>;
|
|
7
|
+
export declare const SUITS: Suit[];
|
|
8
|
+
export declare const SYMBOL: Record<Suit, string>;
|
|
9
|
+
export declare const rankLabel: (rank: number) => string;
|
|
10
|
+
export declare const rankWord: (rank: number) => string;
|
|
11
|
+
/**
|
|
12
|
+
* A card with its own id. Games with two decks (Pinochle, Canasta) have identical cards, so every
|
|
13
|
+
* card a kit game deals carries a unique `id` ("A♠", or "A♠·2" for the second copy). Moves name
|
|
14
|
+
* cards by id.
|
|
15
|
+
*/
|
|
16
|
+
/** A card from a colour-card deck (Fruit Salad): a fruit and a number or an action; wild cards have no fruit. */
|
|
17
|
+
export type FruitCard = {
|
|
18
|
+
kind: "fruit";
|
|
19
|
+
fruit: Fruit | null;
|
|
20
|
+
face: FruitFace;
|
|
21
|
+
};
|
|
22
|
+
export type Fruit = "cherry" | "lemon" | "pear" | "grape";
|
|
23
|
+
export type FruitFace = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | "hop" | "turn" | "plus2" | "salad" | "salad4";
|
|
24
|
+
export type KCard = (Card | FruitCard) & {
|
|
25
|
+
id: string;
|
|
26
|
+
};
|
|
27
|
+
/** Decks: which ranks, how many copies, how many jokers. Copies after the first get "·2", "·3". */
|
|
28
|
+
export declare function makeDeck({ ranks, copies, jokers }: {
|
|
29
|
+
ranks: number[];
|
|
30
|
+
copies?: number;
|
|
31
|
+
jokers?: number;
|
|
32
|
+
}): KCard[];
|
|
33
|
+
export declare const FULL: number[];
|
|
34
|
+
export declare const isPip: (c: Card | FruitCard) => c is PipCard & {
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
export declare const plainId: (c: Card) => string;
|
|
38
|
+
/** Find cards in a hand by id; throws a GameError when one isn't there. */
|
|
39
|
+
export declare function takeCards(hand: KCard[], ids: string[]): {
|
|
40
|
+
taken: KCard[];
|
|
41
|
+
rest: KCard[];
|
|
42
|
+
};
|
|
43
|
+
/** Sort by suit (alternating colours: ♠ ♥ ♣ ♦), then high to low, with an optional rank order. */
|
|
44
|
+
export declare function sortCards(cards: KCard[], power?: (c: KCard) => number, suitOf?: (c: KCard) => Suit | "joker"): KCard[];
|
|
45
|
+
export interface SeatInfo {
|
|
46
|
+
/** Cards in hand. */
|
|
47
|
+
cards: number;
|
|
48
|
+
/** A short line under the name: "Bid 3 · Took 1", "12 points". */
|
|
49
|
+
line: string;
|
|
50
|
+
/** Partners: 0 or 1 (seats 0 and 2 are team 0). */
|
|
51
|
+
team?: 0 | 1;
|
|
52
|
+
dealer?: boolean;
|
|
53
|
+
/** Out of this hand, or sitting it out (a partner going alone). */
|
|
54
|
+
out?: boolean;
|
|
55
|
+
/** A small badge: "Called it", "Alone", "Knocked". */
|
|
56
|
+
badge?: string;
|
|
57
|
+
}
|
|
58
|
+
export type Center = {
|
|
59
|
+
kind: "trick";
|
|
60
|
+
plays: {
|
|
61
|
+
seat: number;
|
|
62
|
+
card: KCard;
|
|
63
|
+
}[];
|
|
64
|
+
winner: number | null;
|
|
65
|
+
lead?: string | null;
|
|
66
|
+
} | {
|
|
67
|
+
kind: "piles";
|
|
68
|
+
/** Cards left to draw, or null for no stock. */
|
|
69
|
+
stock: number | null;
|
|
70
|
+
/** The discard pile, newest last (the last few). */
|
|
71
|
+
discard: KCard[];
|
|
72
|
+
discardCount: number;
|
|
73
|
+
/** Tapping the stock or the top discard sends these moves (when it's your move). */
|
|
74
|
+
drawMove: Record<string, unknown> | null;
|
|
75
|
+
takeMove: Record<string, unknown> | null;
|
|
76
|
+
/** A note on the pile: "Frozen", "Suit: ♥". */
|
|
77
|
+
note?: string | null;
|
|
78
|
+
/** What to call the piles, when it isn't "N to draw" and "N in the pile" (Euchre's kitty). */
|
|
79
|
+
stockLabel?: string;
|
|
80
|
+
discardLabel?: string;
|
|
81
|
+
/** The discard pile is face down (Bluff): drawn as backs, discardCount of them. */
|
|
82
|
+
faceDown?: boolean;
|
|
83
|
+
/** Only a stock, no discard pile beside it (Go Fish's pond). */
|
|
84
|
+
noDiscard?: boolean;
|
|
85
|
+
/** The discard pile spread out so every card shows; tapping one of `cards` sends { type, card } (Rummy 500). */
|
|
86
|
+
spread?: {
|
|
87
|
+
type: string;
|
|
88
|
+
cards: string[];
|
|
89
|
+
};
|
|
90
|
+
/** Face-down cards after the spread (the dealer's hole card in Blackjack). */
|
|
91
|
+
spreadHidden?: number;
|
|
92
|
+
/** A card just drawn, shown beside the piles until it's placed (Golf). */
|
|
93
|
+
held?: KCard | null;
|
|
94
|
+
heldLabel?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* A solitaire layout (Klondike, FreeCell): the stock and the turned cards, the foundations (their
|
|
98
|
+
* top cards), free cells, and the columns (how many face down, then the face-up cards). Tapping one
|
|
99
|
+
* of `tap.cards` sends { type, card }; tapping the stock sends drawMove.
|
|
100
|
+
*/
|
|
101
|
+
| {
|
|
102
|
+
kind: "solitaire";
|
|
103
|
+
stock: number | null;
|
|
104
|
+
waste: KCard[];
|
|
105
|
+
foundations: (KCard | null)[];
|
|
106
|
+
/** What an empty foundation shows (suit marks by default). */
|
|
107
|
+
foundationLabels?: string[];
|
|
108
|
+
cells: (KCard | null)[] | null;
|
|
109
|
+
columns: {
|
|
110
|
+
down: number;
|
|
111
|
+
up: KCard[];
|
|
112
|
+
}[];
|
|
113
|
+
tap: {
|
|
114
|
+
type: string;
|
|
115
|
+
cards: string[];
|
|
116
|
+
} | null;
|
|
117
|
+
/**
|
|
118
|
+
* Dragging one of `tap.cards` to a place of your choosing sends { type, card, to, index }:
|
|
119
|
+
* `to` is "column" or "cell" with its index, or "foundation" (only when `foundations` is true).
|
|
120
|
+
*/
|
|
121
|
+
drop?: {
|
|
122
|
+
type: string;
|
|
123
|
+
foundations: boolean;
|
|
124
|
+
} | null;
|
|
125
|
+
drawMove: Record<string, unknown> | null;
|
|
126
|
+
stockLabel?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A cross of piles round the stock (Kings in the Corner): the four sides (top, right, bottom, left)
|
|
130
|
+
* then the four corners (top-left, top-right, bottom-right, bottom-left). Each pile shows its top
|
|
131
|
+
* card with its bottom card peeking out; tapping a pile sends its move.
|
|
132
|
+
*/
|
|
133
|
+
| {
|
|
134
|
+
kind: "cross";
|
|
135
|
+
stock: number;
|
|
136
|
+
piles: {
|
|
137
|
+
cards: KCard[];
|
|
138
|
+
empty?: string;
|
|
139
|
+
move: Record<string, unknown> | null;
|
|
140
|
+
label: string;
|
|
141
|
+
note?: string;
|
|
142
|
+
}[];
|
|
143
|
+
/** In a row beside the stock instead (Spite and Malice's building piles). */
|
|
144
|
+
layout?: "row";
|
|
145
|
+
}
|
|
146
|
+
/** Pyramid solitaire: rows of cards (null once cleared), the stock and the turned-up card. */
|
|
147
|
+
| {
|
|
148
|
+
kind: "pyramid";
|
|
149
|
+
/** null: an empty place; "back": a card still face down. */
|
|
150
|
+
rows: (KCard | null | "back")[][];
|
|
151
|
+
/** No stock beside it (the drinking-game pyramids). */
|
|
152
|
+
noStock?: boolean;
|
|
153
|
+
tap: {
|
|
154
|
+
type: string;
|
|
155
|
+
cards: string[];
|
|
156
|
+
} | null;
|
|
157
|
+
held: string | null;
|
|
158
|
+
stock: number;
|
|
159
|
+
waste: KCard | null;
|
|
160
|
+
drawMove: Record<string, unknown> | null;
|
|
161
|
+
stockLabel: string;
|
|
162
|
+
}
|
|
163
|
+
/** Cards in a grid in the middle (Memory); null is face down. Tapping a cell sends { type, index }. */
|
|
164
|
+
| {
|
|
165
|
+
kind: "board";
|
|
166
|
+
cols: number;
|
|
167
|
+
cards: (KCard | null)[];
|
|
168
|
+
empty: number[];
|
|
169
|
+
tap: {
|
|
170
|
+
type: string;
|
|
171
|
+
cells: number[];
|
|
172
|
+
} | null;
|
|
173
|
+
}
|
|
174
|
+
/** Attacks and the cards that beat them (Durak), beside the stock with the trump card under it. */
|
|
175
|
+
| {
|
|
176
|
+
kind: "pairs";
|
|
177
|
+
stock: number;
|
|
178
|
+
trumpCard: KCard | null;
|
|
179
|
+
trumpLabel: string;
|
|
180
|
+
pairs: {
|
|
181
|
+
attack: KCard;
|
|
182
|
+
defense: KCard | null;
|
|
183
|
+
}[];
|
|
184
|
+
discards: number;
|
|
185
|
+
}
|
|
186
|
+
/** Another player's hand, face down: tap a card to take it (Old Maid). Sends { type: takeType, index }. */
|
|
187
|
+
| {
|
|
188
|
+
kind: "fan";
|
|
189
|
+
from: number;
|
|
190
|
+
count: number;
|
|
191
|
+
takeType: string | null;
|
|
192
|
+
label?: string;
|
|
193
|
+
} | {
|
|
194
|
+
kind: "none";
|
|
195
|
+
};
|
|
196
|
+
export interface Meld {
|
|
197
|
+
/** Whose: a seat, or a team (0 or 1) when the game melds by team. */
|
|
198
|
+
owner: number;
|
|
199
|
+
byTeam?: boolean;
|
|
200
|
+
label?: string;
|
|
201
|
+
cards: KCard[];
|
|
202
|
+
}
|
|
203
|
+
export interface KitView {
|
|
204
|
+
game: CardGameId;
|
|
205
|
+
seats: number;
|
|
206
|
+
me: number;
|
|
207
|
+
teams: boolean;
|
|
208
|
+
phase: string;
|
|
209
|
+
/** Whose move it is, or null when everyone may move (passing cards, say). */
|
|
210
|
+
turn: number | null;
|
|
211
|
+
dealer: number;
|
|
212
|
+
hand: KCard[];
|
|
213
|
+
/** Your own cards are face down and unseen (War): the table shows your pile, not a hand. "none": no cards of your own at all (Memory). */
|
|
214
|
+
handHidden?: boolean | "none";
|
|
215
|
+
/** Tapping one of these cards in your hand sends { type, card: id }. */
|
|
216
|
+
tap: {
|
|
217
|
+
type: string;
|
|
218
|
+
cards: string[];
|
|
219
|
+
} | null;
|
|
220
|
+
/** Pick several cards, then press one of the buttons: sends { type, cards: ids }. */
|
|
221
|
+
pick: {
|
|
222
|
+
min: number;
|
|
223
|
+
max: number;
|
|
224
|
+
prompt: string;
|
|
225
|
+
cards: string[];
|
|
226
|
+
actions: {
|
|
227
|
+
label: string;
|
|
228
|
+
type: string;
|
|
229
|
+
primary?: boolean;
|
|
230
|
+
extra?: Record<string, unknown>;
|
|
231
|
+
}[];
|
|
232
|
+
} | null;
|
|
233
|
+
/** Buttons: a bid, a trump call, "Next hand". */
|
|
234
|
+
choices: Choices | null;
|
|
235
|
+
players: SeatInfo[];
|
|
236
|
+
center: Center;
|
|
237
|
+
melds: Meld[];
|
|
238
|
+
/** Cards laid out in front of each player in rows and columns (Golf); null is a face-down card. */
|
|
239
|
+
grids?: {
|
|
240
|
+
owner: number;
|
|
241
|
+
cols: number;
|
|
242
|
+
cards: (KCard | null)[]; /** Cells drawn as empty spaces. */
|
|
243
|
+
empty?: number[];
|
|
244
|
+
}[];
|
|
245
|
+
/** Cells of your own grid you can tap now: sends { type, index }. */
|
|
246
|
+
gridTap?: {
|
|
247
|
+
type: string;
|
|
248
|
+
cells: number[];
|
|
249
|
+
prompt?: string;
|
|
250
|
+
} | null;
|
|
251
|
+
/** A score track (Cribbage's board): each side's front peg, and the back peg where it was before. */
|
|
252
|
+
track?: {
|
|
253
|
+
to: number;
|
|
254
|
+
pegs: {
|
|
255
|
+
seats: number[];
|
|
256
|
+
value: number;
|
|
257
|
+
back: number;
|
|
258
|
+
}[];
|
|
259
|
+
};
|
|
260
|
+
/** Small facts for the table: "Trump ♥", "Hearts broken", "Hand 3 of 13". */
|
|
261
|
+
info: string[];
|
|
262
|
+
/** What just happened, in words. */
|
|
263
|
+
narration: string | null;
|
|
264
|
+
/** The scoreboard: one entry per side (team or player): the seats on that side and its score. */
|
|
265
|
+
scores: Scores;
|
|
266
|
+
/** After a hand: what it scored, a column per side (the seats on it), until everyone moves on. */
|
|
267
|
+
result: RoundResult | null;
|
|
268
|
+
over: GameOver | null;
|
|
269
|
+
}
|
|
270
|
+
/** A card game: an engine whose seats see a `KitView`. */
|
|
271
|
+
export interface CardGame<R extends BaseRules = BaseRules, S = unknown, M = Record<string, unknown>> extends TableGame<R, S, M, KitView> {
|
|
272
|
+
id: CardGameId;
|
|
273
|
+
}
|
|
274
|
+
/** The house-rule switch, for a game's `fields`. */
|
|
275
|
+
export declare const drinkingField: <R>(hint?: string) => RuleField<R>;
|
|
276
|
+
/** "Lou drinks 2" (one or more seats). */
|
|
277
|
+
export declare function drinkLine(seats: number[], n: number): string;
|
|
278
|
+
/** Add a drinking line to a narration when drinking mode is on. */
|
|
279
|
+
export declare const withDrinks: (on: boolean, narration: string | null, seats: number[], n: number) => string | null;
|
|
280
|
+
/** Give a game a drinking mode: the house-rule switch, and a line in its rules when it's on. */
|
|
281
|
+
export declare function withDrinking<R extends BaseRules & {
|
|
282
|
+
drinking?: boolean;
|
|
283
|
+
}, S, M>(game: CardGame<R, S, M>, hint: string, line: string): CardGame<R, S, M>;
|
package/dist/kit.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { GameError, who } from "./table.js";
|
|
2
|
+
export * from "./table.js";
|
|
3
|
+
export const SUITS = ["spades", "hearts", "diamonds", "clubs"];
|
|
4
|
+
export const SYMBOL = { spades: "♠", hearts: "♥", diamonds: "♦", clubs: "♣" };
|
|
5
|
+
const RANK_LABEL = { 11: "J", 12: "Q", 13: "K", 14: "A" };
|
|
6
|
+
export const rankLabel = (rank) => RANK_LABEL[rank] ?? String(rank);
|
|
7
|
+
const RANK_WORD = { 11: "jack", 12: "queen", 13: "king", 14: "ace" };
|
|
8
|
+
export const rankWord = (rank) => RANK_WORD[rank] ?? String(rank);
|
|
9
|
+
const baseId = (c) => (c.kind === "joker" ? (c.size === "big" ? "BJ" : "LJ") : `${rankLabel(c.rank)}${SYMBOL[c.suit]}`);
|
|
10
|
+
/** Decks: which ranks, how many copies, how many jokers. Copies after the first get "·2", "·3". */
|
|
11
|
+
export function makeDeck({ ranks, copies = 1, jokers = 0 }) {
|
|
12
|
+
const out = [];
|
|
13
|
+
for (let copy = 1; copy <= copies; copy++) {
|
|
14
|
+
const tag = copy === 1 ? "" : `·${copy}`;
|
|
15
|
+
for (const suit of SUITS)
|
|
16
|
+
for (const rank of ranks)
|
|
17
|
+
out.push({ kind: "pip", suit, rank, id: `${rankLabel(rank)}${SYMBOL[suit]}${tag}` });
|
|
18
|
+
for (let j = 0; j < jokers; j++) {
|
|
19
|
+
const size = j % 2 === 0 ? "big" : "little";
|
|
20
|
+
out.push({ kind: "joker", size, id: `${size === "big" ? "BJ" : "LJ"}${copy === 1 && j < 2 ? "" : `·${copy}${j >= 2 ? j : ""}`}` });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
export const FULL = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
|
|
26
|
+
export const isPip = (c) => c.kind === "pip";
|
|
27
|
+
export const plainId = baseId;
|
|
28
|
+
/** Find cards in a hand by id; throws a GameError when one isn't there. */
|
|
29
|
+
export function takeCards(hand, ids) {
|
|
30
|
+
if (new Set(ids).size !== ids.length)
|
|
31
|
+
throw new GameError("Pick each card once.");
|
|
32
|
+
const taken = [];
|
|
33
|
+
for (const id of ids) {
|
|
34
|
+
const card = hand.find((c) => c.id === id);
|
|
35
|
+
if (!card)
|
|
36
|
+
throw new GameError("You don't have that card.");
|
|
37
|
+
taken.push(card);
|
|
38
|
+
}
|
|
39
|
+
return { taken, rest: hand.filter((c) => !ids.includes(c.id)) };
|
|
40
|
+
}
|
|
41
|
+
/** Sort by suit (alternating colours: ♠ ♥ ♣ ♦), then high to low, with an optional rank order. */
|
|
42
|
+
export function sortCards(cards, power = (c) => (isPip(c) ? c.rank : 100), suitOf = (c) => (isPip(c) ? c.suit : "joker")) {
|
|
43
|
+
const order = { joker: -1, spades: 0, hearts: 1, clubs: 2, diamonds: 3 };
|
|
44
|
+
return [...cards].sort((a, b) => order[suitOf(a)] - order[suitOf(b)] || power(b) - power(a));
|
|
45
|
+
}
|
|
46
|
+
// ---- Drinking mode -----------------------------------------------------------------------------
|
|
47
|
+
// A house rule some party games offer (off unless a table turns it on): the round's losers drink.
|
|
48
|
+
/** The house-rule switch, for a game's `fields`. */
|
|
49
|
+
export const drinkingField = (hint = "Adults only. Losers drink (or sip water).") => ({ key: "drinking", label: "Drinking mode 🍺", hint, kind: "toggle" });
|
|
50
|
+
/** "Lou drinks 2" (one or more seats). */
|
|
51
|
+
export function drinkLine(seats, n) {
|
|
52
|
+
if (!seats.length || n <= 0)
|
|
53
|
+
return "";
|
|
54
|
+
return `🍺 ${seats.map(who).join(" and ")} drink${seats.length === 1 ? "s" : ""} ${n === 99 ? "the rest of the glass" : n}`;
|
|
55
|
+
}
|
|
56
|
+
/** Add a drinking line to a narration when drinking mode is on. */
|
|
57
|
+
export const withDrinks = (on, narration, seats, n) => on && seats.length && n > 0 ? [narration, drinkLine(seats, n)].filter(Boolean).join(" · ") : narration;
|
|
58
|
+
/** Give a game a drinking mode: the house-rule switch, and a line in its rules when it's on. */
|
|
59
|
+
export function withDrinking(game, hint, line) {
|
|
60
|
+
return {
|
|
61
|
+
...game,
|
|
62
|
+
// A preset too, so it's one pick in the house-rules list.
|
|
63
|
+
presets: [...game.presets, { ...game.presets[0], id: `${game.presets[0].id}-drinking`, name: `Drinking ${game.name} 🍺`, drinking: true }],
|
|
64
|
+
fields: [...game.fields, drinkingField(hint)],
|
|
65
|
+
normalize: (rules) => {
|
|
66
|
+
const given = rules;
|
|
67
|
+
const preset = given?.id === `${game.presets[0].id}-drinking`;
|
|
68
|
+
return { ...game.normalize(preset ? { ...given, id: game.presets[0].id } : rules), ...(preset ? { id: given.id, name: `Drinking ${game.name} 🍺` } : {}), drinking: given?.drinking !== undefined ? !!given.drinking : preset };
|
|
69
|
+
},
|
|
70
|
+
describe: (r) => [...game.describe(r), ...(r.drinking ? [`🍺 Drinking mode: ${line}`] : [])],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=kit.js.map
|
package/dist/kit.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kit.js","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type BaseRules, type CardGame, type KCard } from "./kit.js";
|
|
2
|
+
export interface KlondikeRules extends BaseRules {
|
|
3
|
+
/** Cards turned from the stock at a time. */
|
|
4
|
+
draw: 1 | 3;
|
|
5
|
+
}
|
|
6
|
+
export declare const klondikeOne: KlondikeRules;
|
|
7
|
+
export declare const klondikeThree: KlondikeRules;
|
|
8
|
+
type Phase = "playing" | "finished";
|
|
9
|
+
export interface Column {
|
|
10
|
+
down: KCard[];
|
|
11
|
+
up: KCard[];
|
|
12
|
+
}
|
|
13
|
+
export interface KlondikeState {
|
|
14
|
+
game: "klondike";
|
|
15
|
+
rules: KlondikeRules;
|
|
16
|
+
seats: 1;
|
|
17
|
+
rng: number;
|
|
18
|
+
hand: number;
|
|
19
|
+
dealer: 0;
|
|
20
|
+
phase: Phase;
|
|
21
|
+
stock: KCard[];
|
|
22
|
+
/** Turned cards, the playable one last. */
|
|
23
|
+
waste: KCard[];
|
|
24
|
+
/** One pile per suit, in SUITS order, ace first. */
|
|
25
|
+
foundations: KCard[][];
|
|
26
|
+
columns: Column[];
|
|
27
|
+
moves: number;
|
|
28
|
+
passes: number;
|
|
29
|
+
/** Draws since anything else happened: a computer player who has gone all the way round gives up. */
|
|
30
|
+
idle: number;
|
|
31
|
+
won: boolean;
|
|
32
|
+
/** Earlier positions for Undo (the most recent last). */
|
|
33
|
+
history: string[];
|
|
34
|
+
narration: string | null;
|
|
35
|
+
}
|
|
36
|
+
export declare function newKlondike(rules: KlondikeRules, _seats: number, seed: number): KlondikeState;
|
|
37
|
+
type Move = {
|
|
38
|
+
type: "auto";
|
|
39
|
+
card: string;
|
|
40
|
+
}
|
|
41
|
+
/** The card (and anything on it) to a place you choose: a column by its index, or home. */
|
|
42
|
+
| {
|
|
43
|
+
type: "move";
|
|
44
|
+
card: string;
|
|
45
|
+
to: "foundation" | "column";
|
|
46
|
+
index?: number;
|
|
47
|
+
} | {
|
|
48
|
+
type: "draw";
|
|
49
|
+
} | {
|
|
50
|
+
type: "undo";
|
|
51
|
+
} | {
|
|
52
|
+
type: "finish";
|
|
53
|
+
} | {
|
|
54
|
+
type: "resign";
|
|
55
|
+
};
|
|
56
|
+
export declare const klondike: CardGame<KlondikeRules, KlondikeState, Move>;
|
|
57
|
+
export {};
|