collin/mahjong · 7a1ed833
Give the table more to say about a tile in its lap
Collin Richards · 2026-08-19 21:57 UTC · 7a1ed833496862d77ba4e85d0af2751d22de6b9f · parent bbdef458 · browse files
modifiedREADME.md+4 −3
| ⋯ 74 unchanged lines | |||
| 75 | 75 | - **Throw it badly** and it ends up in somebody's tiles — the middle stops | |
| 76 | 76 | exactly where their hand starts, so a tile that comes off the pool arrives in | |
| 77 | 77 | their lap, and one that falls short lands out by their seat. Either way their | |
| 78 | - | row takes the knock and rocks back, and with 報牌 on they tell you about it | |
| 79 | - | (喂,小心點). How hard it got there only decides how loudly. Never your own | |
| 80 | - | edge: you cannot be barged by your own discard. | |
| 78 | + | row takes the knock and rocks back, and with 報牌 on they tell you about it — | |
| 79 | + | 喂,小心點 if you are lucky, 是在哈囉 or 你牌品很差欸 if you are not, and | |
| 80 | + | never the same line twice running. How hard it got there only decides how | |
| 81 | + | loudly. Never your own edge: you cannot be barged by your own discard. | |
| 81 | 82 | - **Arranging** — drag any tile in your hand to reorder it; 理牌 sorts it back | |
| 82 | 83 | into suit order. Hands are never auto-sorted after the deal, so an arrangement | |
| 83 | 84 | you set up survives draws, claims and kongs. | |
| ⋯ 334 unchanged lines | |||
modifiedpublic/voice/manifest.json+1 −1
| 1 | - | ["t0","t9","t18","t1","t10","t19","t2","t11","t20","t3","t12","t21","t4","t13","t22","t5","t14","t23","t6","t15","t24","t7","t16","t25","t8","t17","t26","t27","t28","t29","t30","t31","t32","t33","t34","t35","t36","t37","t38","t39","t40","t41","pung","chow","kong","hu","selfDraw","drawGame","flower","watchIt","watchIt2"] | |
| 1 | + | ["t0","t9","t18","t1","t10","t19","t2","t11","t20","t3","t12","t21","t4","t13","t22","t5","t14","t23","t6","t15","t24","t7","t16","t25","t8","t17","t26","t27","t28","t29","t30","t31","t32","t33","t34","t35","t36","t37","t38","t39","t40","t41","pung","chow","kong","hu","selfDraw","drawGame","flower","watchIt","watchIt2","watchIt3","watchIt4","watchIt5","watchIt6","watchIt7","watchIt8"] |
addedpublic/voice/watchIt3.mp3binary
Binary file
addedpublic/voice/watchIt4.mp3binary
Binary file
addedpublic/voice/watchIt5.mp3binary
Binary file
addedpublic/voice/watchIt6.mp3binary
Binary file
addedpublic/voice/watchIt7.mp3binary
Binary file
addedpublic/voice/watchIt8.mp3binary
Binary file
modifiedscripts/voice.mjs+10 −2
| ⋯ 61 unchanged lines | |||
| 62 | 62 | selfDraw: '自摸', | |
| 63 | 63 | drawGame: '流局', | |
| 64 | 64 | flower: '補花', | |
| 65 | - | // Said to whoever threw a tile hard enough to come off the pool and into | |
| 66 | - | // your tiles. Two of them, so a rough table does not sound like a parrot. | |
| 65 | + | // Said to whoever has just put a tile in your lap. Eight of them, so a rough | |
| 66 | + | // table does not sound like a parrot — the first two straight, the rest the | |
| 67 | + | // way it would actually come out at a table in Taipei. The particles (啦, 喔, | |
| 68 | + | // 欸) are most of what makes a line sound like a person rather than a sign. | |
| 67 | 69 | watchIt: '喂,小心點', | |
| 68 | 70 | watchIt2: '輕一點啦', | |
| 71 | + | watchIt3: '是在哈囉', | |
| 72 | + | watchIt4: '你是在丟飛鏢喔', | |
| 73 | + | watchIt5: '這是麻將,不是棒球', | |
| 74 | + | watchIt6: '差一點就打到我了', | |
| 75 | + | watchIt7: '你牌品很差欸', | |
| 76 | + | watchIt8: '手下留情啦', | |
| 69 | 77 | }); | |
| 70 | 78 | ||
| 71 | 79 | mkdirSync(OUT, { recursive: true }); | |
| ⋯ 27 unchanged lines | |||
modifiedsrc/game/sound.ts+22 −3
| ⋯ 276 unchanged lines | |||
| 277 | 277 | // Two notes falling, which is what a grumble sounds like. | |
| 278 | 278 | tone(c, { freq: 300, to: 190, at: 0.05, dur: 0.14, gain: 0.16, type: 'triangle' }); | |
| 279 | 279 | tone(c, { freq: 240, to: 150, at: 0.2, dur: 0.22, gain: 0.13, type: 'triangle' }); | |
| 280 | - | say(WATCH_IT[Math.floor(Math.random() * WATCH_IT.length)]); | |
| 280 | + | // Never the same line twice running: the repeat is what makes a stock phrase | |
| 281 | + | // sound like a machine, and this one fires often enough for that to show. | |
| 282 | + | let pick = Math.floor(Math.random() * WATCH_IT.length); | |
| 283 | + | if (WATCH_IT[pick] === lastWords) pick = (pick + 1) % WATCH_IT.length; | |
| 284 | + | lastWords = WATCH_IT[pick]; | |
| 285 | + | say(lastWords); | |
| 281 | 286 | } | |
| 282 | 287 | ||
| 283 | - | /** 喂,小心點 — said by whoever's tiles were hit. Rendered by scripts/voice.mjs. */ | |
| 284 | - | const WATCH_IT = ['watchIt', 'watchIt2']; | |
| 288 | + | /** | |
| 289 | + | * What gets said. 喂,小心點 and 輕一點啦 straight, and then the way it would | |
| 290 | + | * actually come out at a table — 是在哈囉, 你牌品很差欸, 這是麻將不是棒球. | |
| 291 | + | * Rendered by scripts/voice.mjs; a missing clip just means silence. | |
| 292 | + | */ | |
| 293 | + | const WATCH_IT = [ | |
| 294 | + | 'watchIt', | |
| 295 | + | 'watchIt2', | |
| 296 | + | 'watchIt3', | |
| 297 | + | 'watchIt4', | |
| 298 | + | 'watchIt5', | |
| 299 | + | 'watchIt6', | |
| 300 | + | 'watchIt7', | |
| 301 | + | 'watchIt8', | |
| 302 | + | ]; | |
| 303 | + | let lastWords = ''; | |
| 285 | 304 | ||
| 286 | 305 | /** | |
| 287 | 306 | * Each cue has its own shape so it is identifiable without looking up — the | |
| ⋯ 71 unchanged lines | |||