anvilsign in

collin/mahjong

master / src / game / types.ts
1import type { Tile } from './tiles';
2
3export type SeatId = 0 | 1 | 2 | 3;
4
5/** Placeholder names, until somebody types their own on the settings screen. */
6export const DEFAULT_NAMES = ['玩家 1', '玩家 2', '玩家 3', '玩家 4'];
7
8/** What the three computer players are called, in seat order after the human. */
9export const BOT_NAMES = ['電腦 甲', '電腦 乙', '電腦 丙'];
10
11export type MeldKind =
12 | 'chow' // 吃
13 | 'pung' // 碰
14 | 'kong' // 明槓 (claimed from a discard)
15 | 'ankong' // 暗槓 (four from hand)
16 | 'addkong'; // 加槓 (fourth tile added to an exposed pung)
17
18export interface Meld {
19 kind: MeldKind;
20 /** Sorted tiles making up the meld. */
21 tiles: Tile[];
22 /** Whose discard it came from, if any. */
23 from?: SeatId;
24}
25
26export const meldIsConcealed = (m: Meld) => m.kind === 'ankong';
27export const meldIsKong = (m: Meld) => m.kind === 'kong' || m.kind === 'ankong' || m.kind === 'addkong';
28
29export interface Player {
30 name: string;
31 hand: Tile[]; // concealed, sorted
32 melds: Meld[];
33 flowers: Tile[];
34 discards: Tile[];
35 score: number;
36}
37
38export interface Rules {
39 /** 底 — flat amount every payer contributes. */
40 base: number;
41 /** 台 — value of one tai. */
42 taiValue: number;
43 /** Tiles left in the wall when the hand is declared a draw (流局). */
44 wallReserve: number;
45 /** Starting chips per player. */
46 startingScore: number;
47 /**
48 * 過水 — pass on a tile you could have won on and it is dead to you until
49 * your own next draw.
50 */
51 sacredDiscard: boolean;
52 /**
53 * Whether taking a 碰/吃/槓 also lifts a 過水 lock, or only drawing does.
54 * Tables genuinely differ, hence the flag.
55 */
56 sacredClearedByClaim: boolean;
57 /** 一炮多響 — one discard pays out to every seat that declares on it. */
58 multipleWinners: boolean;
59 /**
60 * 包牌 — feed the third dragon or wind pung to an obvious 大三元 / 大四喜
61 * and you answer for the whole hand yourself.
62 */
63 liability: boolean;
64}
65
66export const DEFAULT_RULES: Rules = {
67 base: 3,
68 taiValue: 1,
69 wallReserve: 16,
70 startingScore: 100,
71 sacredDiscard: true,
72 sacredClearedByClaim: false,
73 multipleWinners: false,
74 liability: true,
75};