diff --git a/packages/backend/src/core/MahjongService.ts b/packages/backend/src/core/MahjongService.ts index 8957edd4e8..e4abbe8076 100644 --- a/packages/backend/src/core/MahjongService.ts +++ b/packages/backend/src/core/MahjongService.ts @@ -60,7 +60,7 @@ type Room = { type CallingAnswers = { pon: null | boolean; - cii: null | false | [Mahjong.Tile, Mahjong.Tile, Mahjong.Tile]; + cii: null | false | 'x__' | '_x_' | '__x'; kan: null | boolean; ron: { e: null | boolean; @@ -594,7 +594,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { } @bindThis - public async commit_cii(roomId: MiMahjongGame['id'], user: MiUser, tiles: [Mahjong.Tile, Mahjong.Tile, Mahjong.Tile]) { + public async commit_cii(roomId: MiMahjongGame['id'], user: MiUser, pattern: 'x__' | '_x_' | '__x') { const room = await this.getRoom(roomId); if (room == null) return; if (room.gameState == null) return; @@ -605,7 +605,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`); if (current == null) throw new Error('no asking found'); const currentAnswers = JSON.parse(current) as CallingAnswers; - currentAnswers.cii = tiles; + currentAnswers.cii = pattern; await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers)); } diff --git a/packages/backend/src/server/api/stream/channels/mahjong-room.ts b/packages/backend/src/server/api/stream/channels/mahjong-room.ts index 53363bd5f3..b2e2ccdb92 100644 --- a/packages/backend/src/server/api/stream/channels/mahjong-room.ts +++ b/packages/backend/src/server/api/stream/channels/mahjong-room.ts @@ -56,7 +56,7 @@ class MahjongRoomChannel extends Channel { case 'tsumoHora': this.tsumoHora(); break; case 'ronHora': this.ronHora(); break; case 'pon': this.pon(); break; - case 'cii': this.cii(body.tiles); break; + case 'cii': this.cii(body.pattern); break; case 'kan': this.kan(); break; case 'ankan': this.ankan(body.tile); break; case 'kakan': this.kakan(body.tile); break; @@ -122,10 +122,10 @@ class MahjongRoomChannel extends Channel { } @bindThis - private async cii(tiles: string[]) { + private async cii(pattern: string) { if (this.user == null) return; - this.mahjongService.commit_cii(this.roomId!, this.user, tiles); + this.mahjongService.commit_cii(this.roomId!, this.user, pattern); } @bindThis diff --git a/packages/frontend/assets/mahjong/tiles/chun.png b/packages/frontend/assets/mahjong/tiles/chun.png index 819efe989e..5d57fcc4ab 100644 Binary files a/packages/frontend/assets/mahjong/tiles/chun.png and b/packages/frontend/assets/mahjong/tiles/chun.png differ diff --git a/packages/frontend/assets/mahjong/tiles/e.png b/packages/frontend/assets/mahjong/tiles/e.png index bd6b0675ad..0443b5046d 100644 Binary files a/packages/frontend/assets/mahjong/tiles/e.png and b/packages/frontend/assets/mahjong/tiles/e.png differ diff --git a/packages/frontend/assets/mahjong/tiles/hatsu.png b/packages/frontend/assets/mahjong/tiles/hatsu.png index c09cf8e62a..6481e5d2ec 100644 Binary files a/packages/frontend/assets/mahjong/tiles/hatsu.png and b/packages/frontend/assets/mahjong/tiles/hatsu.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m1.png b/packages/frontend/assets/mahjong/tiles/m1.png index de856fc358..a514dd3df0 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m1.png and b/packages/frontend/assets/mahjong/tiles/m1.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m2.png b/packages/frontend/assets/mahjong/tiles/m2.png index a3a21ed398..5499cc3660 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m2.png and b/packages/frontend/assets/mahjong/tiles/m2.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m3.png b/packages/frontend/assets/mahjong/tiles/m3.png index bd5ca8e1b1..6748b8734c 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m3.png and b/packages/frontend/assets/mahjong/tiles/m3.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m4.png b/packages/frontend/assets/mahjong/tiles/m4.png index 12fb1c9669..82debd6789 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m4.png and b/packages/frontend/assets/mahjong/tiles/m4.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m5.png b/packages/frontend/assets/mahjong/tiles/m5.png index c3c008f865..0f088c9893 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m5.png and b/packages/frontend/assets/mahjong/tiles/m5.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m6.png b/packages/frontend/assets/mahjong/tiles/m6.png index e22926c2ea..35c5972ec5 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m6.png and b/packages/frontend/assets/mahjong/tiles/m6.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m7.png b/packages/frontend/assets/mahjong/tiles/m7.png index 241e39696e..a4929ebb1e 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m7.png and b/packages/frontend/assets/mahjong/tiles/m7.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m8.png b/packages/frontend/assets/mahjong/tiles/m8.png index c807817d24..2caddd9b19 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m8.png and b/packages/frontend/assets/mahjong/tiles/m8.png differ diff --git a/packages/frontend/assets/mahjong/tiles/m9.png b/packages/frontend/assets/mahjong/tiles/m9.png index 690698fc01..1577fd2139 100644 Binary files a/packages/frontend/assets/mahjong/tiles/m9.png and b/packages/frontend/assets/mahjong/tiles/m9.png differ diff --git a/packages/frontend/assets/mahjong/tiles/n.png b/packages/frontend/assets/mahjong/tiles/n.png index 9683db7a43..9ab59fef2e 100644 Binary files a/packages/frontend/assets/mahjong/tiles/n.png and b/packages/frontend/assets/mahjong/tiles/n.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p1.png b/packages/frontend/assets/mahjong/tiles/p1.png index 8961979d46..a6f79386f5 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p1.png and b/packages/frontend/assets/mahjong/tiles/p1.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p2.png b/packages/frontend/assets/mahjong/tiles/p2.png index e9c4bec04f..f5182ad582 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p2.png and b/packages/frontend/assets/mahjong/tiles/p2.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p3.png b/packages/frontend/assets/mahjong/tiles/p3.png index 6c0cbbd434..af2cd17fbf 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p3.png and b/packages/frontend/assets/mahjong/tiles/p3.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p4.png b/packages/frontend/assets/mahjong/tiles/p4.png index 01b8af5131..485dd20511 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p4.png and b/packages/frontend/assets/mahjong/tiles/p4.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p5.png b/packages/frontend/assets/mahjong/tiles/p5.png index b7948d29e7..6ee0ab6075 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p5.png and b/packages/frontend/assets/mahjong/tiles/p5.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p6.png b/packages/frontend/assets/mahjong/tiles/p6.png index 28b455b030..a14a3f9f7f 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p6.png and b/packages/frontend/assets/mahjong/tiles/p6.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p7.png b/packages/frontend/assets/mahjong/tiles/p7.png index cc7f7870c0..685559b936 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p7.png and b/packages/frontend/assets/mahjong/tiles/p7.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p8.png b/packages/frontend/assets/mahjong/tiles/p8.png index 16710868cf..91017184a9 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p8.png and b/packages/frontend/assets/mahjong/tiles/p8.png differ diff --git a/packages/frontend/assets/mahjong/tiles/p9.png b/packages/frontend/assets/mahjong/tiles/p9.png index 5c4019e1ec..aebddf3d2c 100644 Binary files a/packages/frontend/assets/mahjong/tiles/p9.png and b/packages/frontend/assets/mahjong/tiles/p9.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s.png b/packages/frontend/assets/mahjong/tiles/s.png index 5b5c849d96..d163b4deb3 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s.png and b/packages/frontend/assets/mahjong/tiles/s.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s1.png b/packages/frontend/assets/mahjong/tiles/s1.png index ef7b2bf474..52c2fe3f83 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s1.png and b/packages/frontend/assets/mahjong/tiles/s1.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s2.png b/packages/frontend/assets/mahjong/tiles/s2.png index af0f6490ac..7f90ce68bb 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s2.png and b/packages/frontend/assets/mahjong/tiles/s2.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s3.png b/packages/frontend/assets/mahjong/tiles/s3.png index 47b7426c74..ffa7275f30 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s3.png and b/packages/frontend/assets/mahjong/tiles/s3.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s4.png b/packages/frontend/assets/mahjong/tiles/s4.png index 4d63354552..75638ec7a2 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s4.png and b/packages/frontend/assets/mahjong/tiles/s4.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s5.png b/packages/frontend/assets/mahjong/tiles/s5.png index d8f377f61f..18d1dd296b 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s5.png and b/packages/frontend/assets/mahjong/tiles/s5.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s6.png b/packages/frontend/assets/mahjong/tiles/s6.png index 396a13e931..578f7c495f 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s6.png and b/packages/frontend/assets/mahjong/tiles/s6.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s7.png b/packages/frontend/assets/mahjong/tiles/s7.png index 1e9cf6d713..077c5c0a12 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s7.png and b/packages/frontend/assets/mahjong/tiles/s7.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s8.png b/packages/frontend/assets/mahjong/tiles/s8.png index 605f4cfe10..187cb89ceb 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s8.png and b/packages/frontend/assets/mahjong/tiles/s8.png differ diff --git a/packages/frontend/assets/mahjong/tiles/s9.png b/packages/frontend/assets/mahjong/tiles/s9.png index c4c6246bf5..2c4134ecdb 100644 Binary files a/packages/frontend/assets/mahjong/tiles/s9.png and b/packages/frontend/assets/mahjong/tiles/s9.png differ diff --git a/packages/frontend/assets/mahjong/tiles/w.png b/packages/frontend/assets/mahjong/tiles/w.png index c18793b376..ac576f8a47 100644 Binary files a/packages/frontend/assets/mahjong/tiles/w.png and b/packages/frontend/assets/mahjong/tiles/w.png differ diff --git a/packages/frontend/src/pages/mahjong/room.game.vue b/packages/frontend/src/pages/mahjong/room.game.vue index dec7add7b2..99471d50da 100644 --- a/packages/frontend/src/pages/mahjong/room.game.vue +++ b/packages/frontend/src/pages/mahjong/room.game.vue @@ -781,7 +781,6 @@ onUnmounted(() => { display: inline-block; vertical-align: bottom; width: 32px; - box-shadow: 0px 8px 2px 0px #0003; } .handTilesOfKamitya { diff --git a/packages/misskey-mahjong/src/common.ts b/packages/misskey-mahjong/src/common.ts index c4b1f7b97a..c0f44d4c1f 100644 --- a/packages/misskey-mahjong/src/common.ts +++ b/packages/misskey-mahjong/src/common.ts @@ -101,6 +101,80 @@ export const NEXT_TILE_FOR_DORA_MAP: Record = { chun: 'haku', }; +export const NEXT_TILE_FOR_SHUNTSU: Record = { + m1: 'm2', + m2: 'm3', + m3: 'm4', + m4: 'm5', + m5: 'm6', + m6: 'm7', + m7: 'm8', + m8: 'm9', + m9: null, + p1: 'p2', + p2: 'p3', + p3: 'p4', + p4: 'p5', + p5: 'p6', + p6: 'p7', + p7: 'p8', + p8: 'p9', + p9: null, + s1: 's2', + s2: 's3', + s3: 's4', + s4: 's5', + s5: 's6', + s6: 's7', + s7: 's8', + s8: 's9', + s9: null, + e: null, + s: null, + w: null, + n: null, + haku: null, + hatsu: null, + chun: null, +}; + +export const PREV_TILE_FOR_SHUNTSU: Record = { + m1: null, + m2: 'm1', + m3: 'm2', + m4: 'm3', + m5: 'm4', + m6: 'm5', + m7: 'm6', + m8: 'm7', + m9: 'm8', + p1: null, + p2: 'p1', + p3: 'p2', + p4: 'p3', + p5: 'p4', + p6: 'p5', + p7: 'p6', + p8: 'p7', + p9: 'p8', + s1: null, + s2: 's1', + s3: 's2', + s4: 's3', + s5: 's4', + s6: 's5', + s7: 's6', + s8: 's7', + s9: 's8', + e: null, + s: null, + w: null, + n: null, + haku: null, + hatsu: null, + chun: null, +}; + type EnvForCalcYaku = { house: House; @@ -627,3 +701,27 @@ export function getTilesForRiichi(handTiles: Tile[]): Tile[] { export function nextTileForDora(tile: Tile): Tile { return NEXT_TILE_FOR_DORA_MAP[tile]; } + +export function getAvailableCiiPatterns(handTiles: Tile[], targetTile: Tile): [Tile, Tile, Tile][] { + const patterns: [Tile, Tile, Tile][] = []; + const prev1 = PREV_TILE_FOR_SHUNTSU[targetTile]; + const prev2 = prev1 != null ? PREV_TILE_FOR_SHUNTSU[prev1] : null; + const next1 = NEXT_TILE_FOR_SHUNTSU[targetTile]; + const next2 = next1 != null ? NEXT_TILE_FOR_SHUNTSU[next1] : null; + if (prev2 != null && prev1 != null) { + if (handTiles.includes(prev2) && handTiles.includes(prev1)) { + patterns.push([prev2, prev1, targetTile]); + } + } + if (prev1 != null && next1 != null) { + if (handTiles.includes(prev1) && handTiles.includes(next1)) { + patterns.push([prev1, targetTile, next1]); + } + } + if (next1 != null && next2 != null) { + if (handTiles.includes(next1) && handTiles.includes(next2)) { + patterns.push([targetTile, next1, next2]); + } + } + return patterns; +} diff --git a/packages/misskey-mahjong/src/engine.master.ts b/packages/misskey-mahjong/src/engine.master.ts index 11992d877e..4bd436a2e3 100644 --- a/packages/misskey-mahjong/src/engine.master.ts +++ b/packages/misskey-mahjong/src/engine.master.ts @@ -436,7 +436,7 @@ export class MasterGameEngine { public commit_resolveCallingInterruption(answers: { pon: boolean; - cii: false | [Tile, Tile, Tile]; + cii: false | 'x__' | '_x_' | '__x'; kan: boolean; ron: House[]; }) { @@ -497,9 +497,42 @@ export class MasterGameEngine { }; } else if (cii != null && answers.cii) { const tile = this.state.hoTiles[cii.callee].pop()!; - this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(answers.cii[0]), 1); - this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(answers.cii[1]), 1); - this.state.huros[cii.caller].push({ type: 'cii', tiles: [tile, answers.cii[0], answers.cii[1]], from: cii.callee }); + let tiles: [Tile, Tile, Tile]; + + switch (answers.cii) { + case 'x__': { + const a = Common.NEXT_TILE_FOR_SHUNTSU[tile]; + if (a == null) throw new Error(); + const b = Common.NEXT_TILE_FOR_SHUNTSU[a]; + if (b == null) throw new Error(); + this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(a), 1); + this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(b), 1); + tiles = [tile, a, b]; + break; + } + case '_x_': { + const a = Common.PREV_TILE_FOR_SHUNTSU[tile]; + if (a == null) throw new Error(); + const b = Common.NEXT_TILE_FOR_SHUNTSU[tile]; + if (b == null) throw new Error(); + this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(a), 1); + this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(b), 1); + tiles = [a, tile, b]; + break; + } + case '__x': { + const a = Common.PREV_TILE_FOR_SHUNTSU[tile]; + if (a == null) throw new Error(); + const b = Common.PREV_TILE_FOR_SHUNTSU[a]; + if (b == null) throw new Error(); + this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(a), 1); + this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(b), 1); + tiles = [b, a, tile]; + break; + } + } + + this.state.huros[cii.caller].push({ type: 'cii', tiles: tiles, from: cii.callee }); this.state.turn = cii.caller; @@ -507,7 +540,7 @@ export class MasterGameEngine { type: 'ciied' as const, caller: cii.caller, callee: cii.callee, - tiles: [tile, answers.cii[0], answers.cii[1]], + tiles: tiles, turn: this.state.turn, }; } else if (this.state.tiles.length === 0) {