From 55629f2b39756853f5e560e14e63bb9277072372 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 28 Jan 2024 13:49:56 +0900 Subject: [PATCH] wip --- packages/backend/src/core/MahjongService.ts | 38 +- .../api/stream/channels/mahjong-room.ts | 6 +- .../frontend/assets/mahjong/tile-back.png | Bin 0 -> 6839 bytes .../frontend/assets/mahjong/tile-front.png | Bin 0 -> 6024 bytes .../frontend/assets/mahjong/tile-side.png | Bin 0 -> 4937 bytes packages/frontend/assets/mahjong/tile-top.png | Bin 0 -> 5956 bytes .../frontend/assets/mahjong/tiles/chun.png | Bin 0 -> 4154 bytes packages/frontend/assets/mahjong/tiles/e.png | Bin 0 -> 4587 bytes .../frontend/assets/mahjong/tiles/haku.png | Bin 0 -> 2061 bytes .../frontend/assets/mahjong/tiles/hatsu.png | Bin 0 -> 5694 bytes packages/frontend/assets/mahjong/tiles/m1.png | Bin 0 -> 5894 bytes packages/frontend/assets/mahjong/tiles/m2.png | Bin 0 -> 6324 bytes packages/frontend/assets/mahjong/tiles/m3.png | Bin 0 -> 6379 bytes packages/frontend/assets/mahjong/tiles/m4.png | Bin 0 -> 7515 bytes packages/frontend/assets/mahjong/tiles/m5.png | Bin 0 -> 6911 bytes packages/frontend/assets/mahjong/tiles/m6.png | Bin 0 -> 6778 bytes packages/frontend/assets/mahjong/tiles/m7.png | Bin 0 -> 6530 bytes packages/frontend/assets/mahjong/tiles/m8.png | Bin 0 -> 6573 bytes packages/frontend/assets/mahjong/tiles/m9.png | Bin 0 -> 6817 bytes packages/frontend/assets/mahjong/tiles/n.png | Bin 0 -> 4219 bytes packages/frontend/assets/mahjong/tiles/p1.png | Bin 0 -> 3274 bytes packages/frontend/assets/mahjong/tiles/p2.png | Bin 0 -> 3338 bytes packages/frontend/assets/mahjong/tiles/p3.png | Bin 0 -> 3569 bytes packages/frontend/assets/mahjong/tiles/p4.png | Bin 0 -> 3342 bytes packages/frontend/assets/mahjong/tiles/p5.png | Bin 0 -> 3784 bytes packages/frontend/assets/mahjong/tiles/p6.png | Bin 0 -> 3723 bytes packages/frontend/assets/mahjong/tiles/p7.png | Bin 0 -> 4042 bytes packages/frontend/assets/mahjong/tiles/p8.png | Bin 0 -> 3568 bytes packages/frontend/assets/mahjong/tiles/p9.png | Bin 0 -> 4131 bytes packages/frontend/assets/mahjong/tiles/s.png | Bin 0 -> 4848 bytes packages/frontend/assets/mahjong/tiles/s1.png | Bin 0 -> 3331 bytes packages/frontend/assets/mahjong/tiles/s2.png | Bin 0 -> 2341 bytes packages/frontend/assets/mahjong/tiles/s3.png | Bin 0 -> 2349 bytes packages/frontend/assets/mahjong/tiles/s4.png | Bin 0 -> 2366 bytes packages/frontend/assets/mahjong/tiles/s5.png | Bin 0 -> 2451 bytes packages/frontend/assets/mahjong/tiles/s6.png | Bin 0 -> 2407 bytes packages/frontend/assets/mahjong/tiles/s7.png | Bin 0 -> 2621 bytes packages/frontend/assets/mahjong/tiles/s8.png | Bin 0 -> 5050 bytes packages/frontend/assets/mahjong/tiles/s9.png | Bin 0 -> 2552 bytes packages/frontend/assets/mahjong/tiles/w.png | Bin 0 -> 4387 bytes .../frontend/src/pages/mahjong/room.game.vue | 436 ++++++++++++++---- packages/misskey-mahjong/src/engine.ts | 189 ++++---- packages/misskey-mahjong/src/utils.ts | 32 +- 43 files changed, 475 insertions(+), 226 deletions(-) create mode 100644 packages/frontend/assets/mahjong/tile-back.png create mode 100644 packages/frontend/assets/mahjong/tile-front.png create mode 100644 packages/frontend/assets/mahjong/tile-side.png create mode 100644 packages/frontend/assets/mahjong/tile-top.png create mode 100644 packages/frontend/assets/mahjong/tiles/chun.png create mode 100644 packages/frontend/assets/mahjong/tiles/e.png create mode 100644 packages/frontend/assets/mahjong/tiles/haku.png create mode 100644 packages/frontend/assets/mahjong/tiles/hatsu.png create mode 100644 packages/frontend/assets/mahjong/tiles/m1.png create mode 100644 packages/frontend/assets/mahjong/tiles/m2.png create mode 100644 packages/frontend/assets/mahjong/tiles/m3.png create mode 100644 packages/frontend/assets/mahjong/tiles/m4.png create mode 100644 packages/frontend/assets/mahjong/tiles/m5.png create mode 100644 packages/frontend/assets/mahjong/tiles/m6.png create mode 100644 packages/frontend/assets/mahjong/tiles/m7.png create mode 100644 packages/frontend/assets/mahjong/tiles/m8.png create mode 100644 packages/frontend/assets/mahjong/tiles/m9.png create mode 100644 packages/frontend/assets/mahjong/tiles/n.png create mode 100644 packages/frontend/assets/mahjong/tiles/p1.png create mode 100644 packages/frontend/assets/mahjong/tiles/p2.png create mode 100644 packages/frontend/assets/mahjong/tiles/p3.png create mode 100644 packages/frontend/assets/mahjong/tiles/p4.png create mode 100644 packages/frontend/assets/mahjong/tiles/p5.png create mode 100644 packages/frontend/assets/mahjong/tiles/p6.png create mode 100644 packages/frontend/assets/mahjong/tiles/p7.png create mode 100644 packages/frontend/assets/mahjong/tiles/p8.png create mode 100644 packages/frontend/assets/mahjong/tiles/p9.png create mode 100644 packages/frontend/assets/mahjong/tiles/s.png create mode 100644 packages/frontend/assets/mahjong/tiles/s1.png create mode 100644 packages/frontend/assets/mahjong/tiles/s2.png create mode 100644 packages/frontend/assets/mahjong/tiles/s3.png create mode 100644 packages/frontend/assets/mahjong/tiles/s4.png create mode 100644 packages/frontend/assets/mahjong/tiles/s5.png create mode 100644 packages/frontend/assets/mahjong/tiles/s6.png create mode 100644 packages/frontend/assets/mahjong/tiles/s7.png create mode 100644 packages/frontend/assets/mahjong/tiles/s8.png create mode 100644 packages/frontend/assets/mahjong/tiles/s9.png create mode 100644 packages/frontend/assets/mahjong/tiles/w.png diff --git a/packages/backend/src/core/MahjongService.ts b/packages/backend/src/core/MahjongService.ts index bf4bafa9a9..82bd7e8818 100644 --- a/packages/backend/src/core/MahjongService.ts +++ b/packages/backend/src/core/MahjongService.ts @@ -292,10 +292,10 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { await this.saveRoom(room); if (res.type === 'tsumo') { - this.globalEventService.publishMahjongRoomStream(room.id, 'log', { operation: 'tsumo', house: res.house, tile: res.tile }); + this.globalEventService.publishMahjongRoomStream(room.id, 'tsumo', { house: res.house, tile: res.tile }); this.next(room, engine); } else if (res.type === 'ponned') { - this.globalEventService.publishMahjongRoomStream(room.id, 'log', { operation: 'ponned', house: res.house, tile: res.tile }); + this.globalEventService.publishMahjongRoomStream(room.id, 'ponned', { source: res.source, target: res.target, tile: res.tile }); const userId = engine.state.user1House === engine.state.turn ? room.user1Id : engine.state.user2House === engine.state.turn ? room.user2Id : engine.state.user3House === engine.state.turn ? room.user3Id : room.user4Id; this.waitForDahai(room, userId, engine); } else if (res.type === 'kanned') { @@ -314,7 +314,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { const house = engine.state.turn; const handTiles = house === 'e' ? engine.state.eHandTiles : house === 's' ? engine.state.sHandTiles : house === 'w' ? engine.state.wHandTiles : engine.state.nHandTiles; this.dahai(room, engine, engine.state.turn, handTiles.at(-1)); - }, 1000); + }, 500); return; } else { const userId = engine.state.user1House === engine.state.turn ? room.user1Id : engine.state.user2House === engine.state.turn ? room.user2Id : engine.state.user3House === engine.state.turn ? room.user3Id : room.user4Id; @@ -323,7 +323,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { } @bindThis - private async dahai(room: Room, engine: Mahjong.Engine.MasterGameEngine, house: Mahjong.Common.House, tile: Mahjong.Common.Tile, operationId?: string) { + private async dahai(room: Room, engine: Mahjong.Engine.MasterGameEngine, house: Mahjong.Common.House, tile: Mahjong.Common.Tile) { const res = engine.op_dahai(house, tile); room.gameState = engine.state; await this.saveRoom(room); @@ -346,17 +346,23 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { }; if (aiHouses.includes(res.canPonHouse)) { - // TODO + // TODO: ちゃんと思考するようにする + //answers.pon = Math.random() < 0.25; + answers.pon = false; } - if (aiHouses.includes(res.canChiHouse)) { - // TODO + if (aiHouses.includes(res.canCiiHouse)) { + // TODO: ちゃんと思考するようにする + //answers.cii = Math.random() < 0.25; + answers.cii = false; } if (aiHouses.includes(res.canKanHouse)) { - // TODO + // TODO: ちゃんと思考するようにする + //answers.kan = Math.random() < 0.25; + answers.kan = false; } for (const h of res.canRonHouses) { if (aiHouses.includes(h)) { - // TODO + // TODO: ちゃんと思考するようにする } } @@ -376,24 +382,24 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { (res.canRonHouses.includes('n') && currentAnswers.ron.n == null) ); if (allAnswered || (Date.now() - waitingStartedAt > CALL_AND_RON_ASKING_TIMEOUT_MS)) { - console.log('answerd'); - await this.redisClient.del(`mahjong:gamePonAsking:${room.id}`); + console.log(allAnswered ? 'ask all answerd' : 'ask timeout'); + await this.redisClient.del(`mahjong:gameCallAndRonAsking:${room.id}`); clearInterval(interval); this.answer(room, engine, currentAnswers); return; } }, 2000); - this.globalEventService.publishMahjongRoomStream(room.id, 'log', { operation: 'dahai', house: house, tile, id: operationId }); + this.globalEventService.publishMahjongRoomStream(room.id, 'dahai', { house: house, tile }); } else { - this.globalEventService.publishMahjongRoomStream(room.id, 'log', { operation: 'dahaiAndTsumo', house: house, dahaiTile: tile, tsumoTile: res.tsumoTile, id: operationId }); + this.globalEventService.publishMahjongRoomStream(room.id, 'dahaiAndTsumo', { dahaiHouse: house, dahaiTile: tile, tsumoTile: res.tsumoTile }); this.next(room, engine); } } @bindThis - public async op_dahai(roomId: MiMahjongGame['id'], user: MiUser, tile: string, operationId: string) { + public async op_dahai(roomId: MiMahjongGame['id'], user: MiUser, tile: string) { const room = await this.getRoom(roomId); if (room == null) return; if (room.gameState == null) return; @@ -403,7 +409,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { const engine = new Mahjong.Engine.MasterGameEngine(room.gameState); const myHouse = user.id === room.user1Id ? engine.state.user1House : user.id === room.user2Id ? engine.state.user2House : user.id === room.user3Id ? engine.state.user3House : engine.state.user4House; - await this.dahai(room, engine, myHouse, tile, operationId); + await this.dahai(room, engine, myHouse, tile); } @bindThis @@ -462,7 +468,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { console.log('dahai timeout', userId, id); clearInterval(interval); const house = room.user1Id === userId ? engine.state.user1House : room.user2Id === userId ? engine.state.user2House : room.user3Id === userId ? engine.state.user3House : engine.state.user4House; - const handTiles = house === 'e' ? engine.state.eHandTiles : house === 's' ? engine.state.sHandTiles : house === 'w' ? engine.state.wHandTiles : engine.state.nHandTiles; + const handTiles = engine.getHandTilesOf(house); await this.dahai(room, engine, house, handTiles.at(-1)); return; } 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 0e55a62b8f..1472a7013a 100644 --- a/packages/backend/src/server/api/stream/channels/mahjong-room.ts +++ b/packages/backend/src/server/api/stream/channels/mahjong-room.ts @@ -38,7 +38,7 @@ class MahjongRoomChannel extends Channel { case 'ready': this.ready(body); break; case 'updateSettings': this.updateSettings(body.key, body.value); break; case 'addAi': this.addAi(); break; - case 'dahai': this.dahai(body.tile, body.id); break; + case 'dahai': this.dahai(body.tile); break; case 'pon': this.pon(); break; case 'nop': this.nop(); break; case 'claimTimeIsUp': this.claimTimeIsUp(); break; @@ -67,10 +67,10 @@ class MahjongRoomChannel extends Channel { } @bindThis - private async dahai(tile: string, id: string) { + private async dahai(tile: string) { if (this.user == null) return; - this.mahjongService.op_dahai(this.roomId!, this.user, tile, id); + this.mahjongService.op_dahai(this.roomId!, this.user, tile); } @bindThis diff --git a/packages/frontend/assets/mahjong/tile-back.png b/packages/frontend/assets/mahjong/tile-back.png new file mode 100644 index 0000000000000000000000000000000000000000..8f4f49532091b24859d06677db8abc386a145f39 GIT binary patch literal 6839 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tile-front.png b/packages/frontend/assets/mahjong/tile-front.png new file mode 100644 index 0000000000000000000000000000000000000000..e6bc7038e1760a1ca513167305ca2ecf8fc5579a GIT binary patch literal 6024 zcmd^Ddpy(szyFN6OjD#>a$A!qmklZ8vbm*;J98^6hGjO{F!wtpij+&`(nS}!ESJh9 z*K*0V+@p}R3Ui6b^*8!{yZpYt-#O?1^LXsN?e%`X?zhh#J8xoigqv#@7XSd!2X3V#^FQSrZG{==;exFj}n$F!!Ve&=SklQWir z{lD=4ERfm;_YbF-t^7ZF^h-vEL?C%FonywJwCU_G=%|j4i5JNQPhetXvm@HDqk1|A z6;ux%lv9*f*yP=)o0Y`hsH);Gbkn*ya~PQ>eyH52 zt=dr!tSin6?@V#~rR^7R0!MV+ME=sWiEPw};Jq;vmP9TNsWT15OAB+kFi4&C_ktlBmuuMYia~6(NzOZm2<|qV7&m zSPkp65w`~1(~IQn?SymQ%r7&HA1ImRLh;3V;n1$k?$v;!U0m?Y4Ee#Bdj#)F#CgFK zVT$rfe^vCSl&>3(sqx>M=(kQq{2tEV?x`dG5x|e=f7@A1xgU4TUC3Ojh@V@PN&MW) zI3lxyy_j1!{*8kX0D!{q%wGIQ4+4O6qIY8XaaJ@>OqKc`v;=Q4&m+!TnDfs$(ZUzN z4q5z1!M6`KrNtyPoK1n%U})UZ=MGkKt!^panahSY1wVR>DK=H5$MNtgHMa#X52Rsz z`EwuLxZFD#+$eC&)*1dG?Gl12Vr>1X_PnTr_N(r+Pt>^RZ$2`wPWNgSVMd>Zwl^YaT4912PLvRxkR55&RcK+{bd6s_QsT&qiS?n%FQ0Fs^2%huhL@seUUOVDT+H27 zzZ`}Q6bqjOwQZSSd9MkrinY&ke-UyTYd8yPea4(7dy5 zRpB3B*tQ3^sg_0bT?_1%oS4wAdS0GV379Il4muCA4l^I05KjXeG5~Dh+c+TL+6_Sf z*fxAr7i~ekF`0fUZcnde!}`LYUH4lhjl-j-+6&)FYuD`7E!^?J@i0s*frf@y!{39B zCr`6p78j{L3$wqY8)$I;5zo7l-bcM#OsT`WQPjf52G&^AbhtPi#R8FtKnjw2T%L`m zr+;STlr2n~Jjo$idbhXa`)Y_UtlVMb=dY!H(X0w!ls+jtv%{w;bA@p`^H^+NL-*X< z01HiF^5d&sn!B@ombcdCg$g;QtL-_S)*0b$Q@HZXm+U{&M6a3=1zs2x3>^%tqOJ#h zq%&3%wNB(e`);jRu4qskzMBosX4cxQ7yc}))IQv)T2+5UuoQQq_2pcw=2C-e<;)WY z>S&(tL4jutw>lmO7_ZJsjDCJ0z}|U$6s>KbT;s-O$aUup3ui#QK&ViU0#|cmZk?>} zQx{CZsYa`e#mR!om3zP}Lx!%G(3a`H7&SB2D`t00uug69gPm4ZR@RlskgDqGQy{@M zP?Xb-w%sx!cT4LqTTddT);~3+*awTC_$wa^>#UZTZwqprYjf8sI?y2~x$D91J?Y6q z#@}z%zN?-Lh{Nn{lna2!9#p#UIqcr)Ox$`tP;tgpT-V|1rIl@ zIZlVHD~dt6&CK}&KO7FoK1RM`ln^*9e@A>paLz*<9FIXCcQ2=&9I6`w7OPb zUyqy9s@!s-Kzkp`JxZ6)?6!iuyaxO5q3+&b`YYpXQt;HkL!F4Ru$ib#mbBfN;FaA_ z%~^AkHxu*po&1g$SoBO`?c@)7Ves}uI$JFKNCutOzvE-oI;eU5>w-7>sjAF0qqur~ zuh!yGC0de$5?Iizg9}%t;>Ge%YZ=_)A+@md6>_-4c|7=PJya$8k>9Ll%WGv3ze&4} z{SmvPB109%E+t*73=p^EQwQIX(uy6>Tn*U1!dg36eS2cpFeyzase9YV`}9oqI1n%D zPC{8z(DQ!h+-K;fFQV2#!)NbP<}^c~Bl=jz3HI;q-+HrwQ1aHIS7%SE%_Nx|L(8xg z_NShFoW{bXcB=m6YSq?bN62~Gze%+~7cmU0V)>Q{Zy;6lASOhx_u?P~6*ed`l0RW)LgEK~t^}b?(s`^eg(p zEt$%3KIdwC5Y)20xdaS2T^3_|kX=&xVrc%L3x0Ju#(qyNv?d)-pv`q zO@vPOCY$kar_ks2y}q^W0D84AU5cR3X%D1cr)fDjtExn5Nm}hHP8om??tj|!ZLpnX zL@~{B}xt zrBYPshL$nPbVq8dOJ83f%6@_xivr4dQ10>B*^7JPDeLV&UP%U@&jONRQnZXIZh+CzQz7ec`BP;F7N%Nu!VLLDG<=}-gd`Zh z0c=pDR+cNP`+nKD1=ZQalMq9OIzbsvN5NOjo_daGPfg9i)py0yf>#z9wgecuq-H*P zDgN5B=KRRwm=>?(ZPY^Re+$- zQc_n_)1Dy-^48UyJ@+p`=9+JUbJUJHPG6hlJk8-Mn(J-tP$imzaH#)?@mu?(_U57c z!wy@WK91t{Sx!Ch>s@!0;}n<|?%X*sqpb<*C)hn8xm7A6TEQY$rNO{w*o)cO+2u9W zC}GsT1Ob%$WK8J(MnE#pFC59I!jY$(oRR`iK^V-%iPjiiqM%;aOYlt~PrE}wg)`XO zM#HTB#yQTqn>QxE!fu5N^}mS9ir5kz)#J$)QpG1b+ zxldW0zs$CkC;d@SDqD_Hgr(HE`{G}9v=K*@o(5!8>+fhd$$*}bz5Ep{23{%; zjVKD0Q#a1Kga}VR4(+Ho^sqjmw&rF=bJ~L7wGnJdbLs0ao=SOY#JESx>!pQl&kPoO z?5{eU?BzhSyA2&fZWBBFA{U2xdumZBaxMh3M{Wt=>$>#Tuhu2fMAL`770PS#O+%d& zHrAM>^YR-rC;K%_l;W;n2XEe$(msk{JqPCHX`~IShr!XZvbiAL@VeUY!KoQKJ~a3obZb6{cbKPcOY*=&-O&4=F2Gns9I0pP z-hI@oVPP$9eicqbq`3l5#JCaNZ>B9RQrMtKtLBsP?dB)?tcpkZbKS+}*gg4-@^9Pw zfJAJI9BulZyNVyS<{HICtr`<_8z6EZ%r2K^nS_{HFxrE-}&%ZiZ9 zsxDtp%a(AXYw8bjd8I*e*xzo4Hv*QGS&R#H7sy6mLW58RVxz&2i7(=XCThL&5f`kg zTLL0X0J@05_~ap;Nm=;dE`GMRmI8Fv$&;cKdIgUtBEgSIb=H9^{HN_QsD^U{Bn`sG5 zyE?2dIeX7Hditr?d#dPuQ3`{fnX;d_d;8->3g}Q`27q2Fkn#<5Ag0Tdhtl}(m$BG^ z-|AeHZCAM7hD+Ha2O44=c3OXTG1g;A3F}*2QSu-SZ}RB>N?_a&KcHv|qMP_PU3&&6*xy z=;6DTP2LvYFskKXE9P`S1TK09X}j6ABUFm61ZThCLPU@8#g zXUXR*bhlGzZxUp0Ql5j_*9me6B5cd@r7Bh~`7GgV)hFCU(q02M#Zs73g) zpH*EQms#JxXw$uPualIn8MIV0UC@&L)^Ba1U#afZG&zF8eEy?sbHz{)c?5?-CU5W^^9Y9PN`k}%H7Xa zo#?X5f~JLn=}{~|wYhOn+Uq?*FZX;bvK>#%zo5+)_2r)aSpFzY%q=KXFD!X+3RRWG zxLDga_3EL|LUO<=mlnk0M4{~A>#pAgGS^>PEiEr-3~=$xjv<0R2fv=PF`I*AcX6?@ zhMpIiwAp{f|JYPW#Dp~m*gXi{=19MBU6p>2fOXgx`+g$LHFK3gTpL_xmCzl#_Hf*^ RV&f0=qk2ZV`Pz=*{{rMcDrW!y literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tile-side.png b/packages/frontend/assets/mahjong/tile-side.png new file mode 100644 index 0000000000000000000000000000000000000000..281e0a54df6e606b5267880eba20fb75a9f76475 GIT binary patch literal 4937 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tile-top.png b/packages/frontend/assets/mahjong/tile-top.png new file mode 100644 index 0000000000000000000000000000000000000000..861608a43d7b49b215905964ccf9fe7ac27d221d GIT binary patch literal 5956 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/chun.png b/packages/frontend/assets/mahjong/tiles/chun.png new file mode 100644 index 0000000000000000000000000000000000000000..819efe989e586d81b1a5466bb5213bb34f64e0c6 GIT binary patch literal 4154 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/e.png b/packages/frontend/assets/mahjong/tiles/e.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6b0675ad1379449cf30cb7a32e834bb06bfd1d GIT binary patch literal 4587 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 E06{jTyZ`_I literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m1.png b/packages/frontend/assets/mahjong/tiles/m1.png new file mode 100644 index 0000000000000000000000000000000000000000..de856fc358ea51c567a26ea9ebeb7f168ecb07fe GIT binary patch literal 5894 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 Nduu1FYZm_T{{vTny~O|k literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m3.png b/packages/frontend/assets/mahjong/tiles/m3.png new file mode 100644 index 0000000000000000000000000000000000000000..bd5ca8e1b1f171ee79d6d5da825d94b7e79a641e GIT binary patch literal 6379 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m4.png b/packages/frontend/assets/mahjong/tiles/m4.png new file mode 100644 index 0000000000000000000000000000000000000000..12fb1c9669f9c402d5021f4eb97f0fe6134a7612 GIT binary patch literal 7515 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m6.png b/packages/frontend/assets/mahjong/tiles/m6.png new file mode 100644 index 0000000000000000000000000000000000000000..e22926c2ea3e8d19a1d2f2f2335c40403d47f3a7 GIT binary patch literal 6778 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m7.png b/packages/frontend/assets/mahjong/tiles/m7.png new file mode 100644 index 0000000000000000000000000000000000000000..241e39696e3f34d129f78d5dd393e6a6c32b9998 GIT binary patch literal 6530 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 OqNin~S)pzh{r>>Z8!!X_ literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m8.png b/packages/frontend/assets/mahjong/tiles/m8.png new file mode 100644 index 0000000000000000000000000000000000000000..c807817d2485360f110bf5934e810046f5246953 GIT binary patch literal 6573 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

J(=?!wS~& ztG{vg&fkU3e|Jk+oJP~wQs^%SV!DIX>0hrmUW;MDy7J~c>(l_yYWHu3-ue;Ysk%@| zzt}t9X?I~w$R`&4W&4gSdhB64M$8V`D6!MhdI%6e7#XE(wq+N7fXi3Z%mLkHY#sHu zKSiuaXrBYL78^$uH(a>=Vg4ZZ+c_;iH582~gpzI}CE>;iMlI_0bRcsg_bEI`YG>Yg9tVX4Y~ zy2#*2M870T?@ESkQ*UHA?&FR2SPba@fLlR8VO zI&DUDR{AZoeXNO7c_5r!u!12s7B}NRy)`Z&N9iXliN!Np<(^R1x^yYVYVHP9uGYV& z8-k`313uo?G5lVIcv)&oMNgs0#|GUDi-pl0bwYL>KQx(IApDX1%58H7NyQ=UuitPq z2z)s{9!2b>k-ByGab+1+x{fi92=1I_gfu_DTt@q%NkiDvgG6hfy_&URZNr#aR*{2N zYoxjDh2V1oYMSiCXn+Ec@7{UGrh~DM!j*5Y-)#s4_?$TT<425WU^Q?ZQ{TpYBxc5^ zjl~Pb*T4GUTYdN2^f75i8NGP+Hy&zG9dT4iI~+uDE);x#x1p)bsMv$?|g%QVEhW3Nq8OQg~*_3UgOkC<q=mVQF03vZ%p;y#4de4hyo17VP9LLh;bYbZMTvJAewM z4M0gDM%*!buCG{{yr?;y86=K8HPQW>hpU)S{~#$#a^@IoKI(cKE8RMN9y}Echa`jK z%W<-4?%s~xK~KAcFd(f1?5rBCkA2s~`L6L9Nciw0nwC_M<${oxnWY!E%pYkaJok}K zrZA??g+nGEZ+Fb&unkcYHW~FfSf7W0C&3ZmQBm~wAke0ZdQLKtGw<$NzDFJOgMZGU zLS%FrNJR8myliHf71i#>xtD6J@8$zr!;UJuVxP@dsAL;oG?tC{ke&AROyVh}N$RZs zS%;M6U_pKd&kL}KMKQX+y>^5NReA;mlU5$Tv?VffgWPn7AC02j6!TB(C;`a?RjRqz zygXZXAT>i^^f4Q5Hc^|iTgSCG?#hs;=uS(cH~^z815+<}aZ`g|;mCM3ztO})>5^A4 zh5Q52b@!9iXDIYqJ{{cyo6GBW4i%(+z8KE~u8fEi(Blz%h7i)o+d{O7JQDMj4AGqw z&ux1`6JC!99Q5vLeO$A)^EkT7Bq{3!R3@UuU2FKQ!-AnybR}o~VehFE8lrXb^H7%N zL1bBtcem~YIX7}14Z*-@_6tWNPMzvG!-7={ceg%rRa!@e_UO*FvoC7$00))59gg~b z0r5aa+WSCFr$U~TnJFr@>4u+D8i<<;-DlBX>cYNUe&y8an8o!M*`L#HTx5F*+Hvc7 z`I;_0{qV@is&h*^@=1?QIjg=oME1H$VnN75?0`!>Rw+@i8j+ClqbNroSRo}orB(dv zaqE3B1djuj2bGMpUHYcM6NXy^hD}40Xu>SE`$EfK%&(nY4c6dg;lX7$=Ese_)>#YG za&>oLl`o}D2XjFK)9Ro^;+u)p+8(REhbw5{sISogIDLa>tM1dR!aLjhCxCaMk_#uk zE)fI$tzz6$@CPhaq zg>l0VUL|)v6nBb_=(76gRBhNQW)Qp7e7P>m)_U!qKfgTP2zMAtV}1MfQ`GLiEa($v KhULedqy7g?7F3}C literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/m9.png b/packages/frontend/assets/mahjong/tiles/m9.png new file mode 100644 index 0000000000000000000000000000000000000000..690698fc015e761cfe6f124119dba19b180a1a6f GIT binary patch literal 6817 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/n.png b/packages/frontend/assets/mahjong/tiles/n.png new file mode 100644 index 0000000000000000000000000000000000000000..9683db7a43a50ed45f61310976dbf0d10f71f5b8 GIT binary patch literal 4219 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 RVD>))8%ukO0(0M^{|3sH=A{4t literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/p1.png b/packages/frontend/assets/mahjong/tiles/p1.png new file mode 100644 index 0000000000000000000000000000000000000000..8961979d4631faf60b16c36faba669c75909bbd4 GIT binary patch literal 3274 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 RC)r;ZcNb4;q0`R&{{f~zDIWj; literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/p3.png b/packages/frontend/assets/mahjong/tiles/p3.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0cbbd434b4242418b1680402ff3acadb0e745f GIT binary patch literal 3569 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/p4.png b/packages/frontend/assets/mahjong/tiles/p4.png new file mode 100644 index 0000000000000000000000000000000000000000..01b8af51313ed05d22a2773ca3846fa3498e0b64 GIT binary patch literal 3342 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/p6.png b/packages/frontend/assets/mahjong/tiles/p6.png new file mode 100644 index 0000000000000000000000000000000000000000..28b455b030b82b28592da27923539fa31abdcaf0 GIT binary patch literal 3723 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 Z!{0S~6R}Q^4t_W&pAG(=m)&=y{s*sp^Opbs literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/p9.png b/packages/frontend/assets/mahjong/tiles/p9.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4019e1ec1a9090056fecfe1758b7a7e9ca4e3e GIT binary patch literal 4131 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/s.png b/packages/frontend/assets/mahjong/tiles/s.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5c849d968083281f93f62c6b6c7cf3f27b340f GIT binary patch literal 4848 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/s1.png b/packages/frontend/assets/mahjong/tiles/s1.png new file mode 100644 index 0000000000000000000000000000000000000000..ef7b2bf4746992774c0e1cb2e443fe9471a51fce GIT binary patch literal 3331 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 U-P)`~S1<&5gebKkV}FM1Lak^lez literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/s2.png b/packages/frontend/assets/mahjong/tiles/s2.png new file mode 100644 index 0000000000000000000000000000000000000000..af0f6490acc83de91d5dd2d916241d40a5c11721 GIT binary patch literal 2341 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/s6.png b/packages/frontend/assets/mahjong/tiles/s6.png new file mode 100644 index 0000000000000000000000000000000000000000..396a13e931de29f59402ac88f2be73131c0d6ce3 GIT binary patch literal 2407 zcmc&#drT8|9KR}V0+QfV=5yYT$&94EKBT2*TP!U?r$sukFdTSMCm5kRdvv zGGDM|D9YUCqKOM^fMl7lfjE3HHy3=&p>7yvHaB5v;+#>8``r~(7gv96a z033oe2|f>Q%_lfGk8qG~Epn^19f3)k7Rib;OU)hw;UrUv8Dd3oYNoX~->SAD3A!+i z4+92V1c$>u7v*L#pB549V&Ff2jUuoh!sTm`Y;ziHpcw*=lf+4+h%OA)Fg81uVO%n# z3{G0a$#EVGMZI3H#H*0dj02Ua)oN5KN9A%ckPx#)ZVvZ}-E1^(!f(S!uvUija3t-9 zd7F41UC3z>1mN&6GnXe|+|3R}5AuNea1SbzNYRnP9w*Jwtdo9X0uSB^wg${;FuUjc>@xbU0gYm1p&xP!F)gB!qaz%x90T!V25W3qj3YUU5KjKF(^H)P7>XZ8^USWhz1?yK_fITmO`=|%@mDrx`HSe?Nk_Y7#3O= z!>xS0TExT9wn8gm6G8^`{U}S@IWNu-dI#uQEuy#ENsyT$80-(y;U*YZ4$CEqp-Kj{ zyiNjG3^dP}4n;?XGfYo|jtRgY{fJ!!^!#^V2ZCja2DT|U1okoE2A#`*ZF}ZIbvguz zHjBAGxJn^NK!ta&u(k!~>R!&WZY2+d@`<7-b6iSlLyxrSeq4 zZn(qJ5HWwNvMuaUc=NQn3HtPq#?LLy>FVFMM^09pIa~VhN)7Ifs%xx$=h8sw=@(zi zu_4!McA>u6%d>ABub8tsvHN1p4d3?7_twRB=UvhrvHbGIhI&GMFm_Er*scYiSYFsa zb$_n-a10&lo!`^hbi1M<>)r6M-aW-lCzr=K)(+xLQQOKpF30qD4fb6}EloMO*}18- zF3VE-r?su~y#?PU5d&2{J5tL-6McK~woCQT&6qs5Gr3IE(+&4Nem`MpIy3Fgf@upa zrz;PZXI*H@T;8=eN;@w)`9%NY-nKt}|7dZ2OKgaF*XBFtp5JM{UpMpQ!;N^!OPdBn zXT$#*?9)wZe>=B6|Eu-aa<`n{)>3_S^O1-fUuI3o>08y*)qLpu?UG6L1-b~>ogDU(s3 z>8l<1sbj}+>D0ygsPrgR%K@n6@~k%-9Xl)Q`tN@?wKD$P`M*1=N-z=s_7y&{_j?|c z-F$TKvi0TOVqK|fgQ2JB?zrhU<;9})iYlFTT&Gwiva7C?%SC-5k*}7;i#kK$RH$Iw z)+vi?p=WTV?44cQ+{zR=05h+*q2lfgkOuzqL-nHgqd(K1Ro(hvpy3-l4X~?zIQN=! z32oXpe)=QPk%7a>*6?RVdvxy3yfNqIp>A&spF(EUF^V$zV;J0*aO~^3=%NQC!(W(^ LQjMP`uG#bt(MTlf literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/s7.png b/packages/frontend/assets/mahjong/tiles/s7.png new file mode 100644 index 0000000000000000000000000000000000000000..1e9cf6d71397425e6593757e995a2c610647c9d0 GIT binary patch literal 2621 zcmcIlYg80v7@iF+2Kdeg&tBht;PYgh*$hEG-;k;4T)J*5W~A*h+(c&*GT!b0 zI0UJqc?WKsPjGN1VIe6Ea{F*O0+S{Uk`|_u>m0F!l}yZKh?%*`sm9#-MwJPPj`CCU z7$C3{91in#8^vP01`&BN@LPC|BCu$}&DS95y6JE%%@A;yEKDXxqWoYrV=`ki;-+*t zgOdiaa-0K0QJ2dlbA`%i#)2wTDitbMqDrL{SV-9%io89hN9PR1tc zHyKgFM%W38V}ZS*S0I8XyL0X(OF;V2bENqx<^s~k9Mndq^9bri|0HX>y_X)Ai_ZoZ z*HwhS^80%>b+R21-_`k9D6bKWn-J(D%|D&RApIF*P zGe8{3AygFG4JF0KPG@K{X#*HLBOwM(ijNIfsKUdgN|{2m73zjfCwan_9!G+rv!Ew6 zh(a0p7j#xnG$Onk6{F7t!w5pSDTUf%Np{>qq>(1h+RfGtOeH9bh;%WDh)^S&Qy7Xj zC=ygvDFzXt^lnUpL@3c7foAoAgfWBFCL_j?oQ)7q?y=L_IQPkYw2{KBVK$tyXb@g% zBFwnc#vxI5+&Yh@EK<8tjSACgBfB`n(-RUk+AD%uY+fvpWI3A2=@E1$k<~k>IOH%a zwl0Png?u%LgP~1MBViI#2J+n~OPe_t&JbD)=vob;HJeFrGdVEWAEbpM7+47_WuaY_ z^mw_f1Yq(nmMQAlrr_Y&#{>mBmjT;Wzwylo z2$C!&K@axnJqQ}V-nstp>t0&_f^zlC+K|De{`-7C(-&6wYDcW}p8H8)lJ~aos?7!K zPG)U_kLvdh8vk~9ncp7+N&|NJXj8oR9nhDis2W%K4-WmII`47KX51CHYhTg37h3Wv zgI=3$LK-%&Mfs7_(wmMIj+z^D_Wb51e$|SH*%QxZUWnSSzjkoZZbG$vVn&wV+6g=L zFKm5rt3mqZSh~M!{KblrJB54G-W%Xo`$2BW_tVB&=C$J`fh(6Cy)?GDs=dAe)tAgR zq#Kgys5E`vEn`{5#tA>h6D{j6u1;RoKZgGxbCq1%Z`k1AiiCX0#j|j2=SR`6r!WC` zCj?B=SFYQ>EbZr#)M-^)0ySeo5>7OC)|UNxI?@l+U=K9dtH9;Yb#rN;o1dWfN9b_)XcWji{vTGi9UO>uA zs()zwYHM@>wC2heNADN6SGKZ_|4XlU9W{+p)(1ad=5zdVWWLkT(f<6yjCJh6H=1j= z1w|6$g1^Ji;)L6d)xT{E0!ifuS9kaxI7L0aQ2FTQkt3s2o!Gd}_%k#g%6FucSNTas zZahUTpc~qqhB8Cm!fR0Y;g;jE(*0|l1_LMtG`HXB&KvKPo(`z1^^%qpr!8&#IAD=) z;r~|>kmB+=CptoN7aOx5N_O49XKj7%WOK7uWK1yVn2S*ob#zL%;O``JHJU Yl@WoK-8^os11BgcJ~?hrOvaKw0sBUq@c;k- literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/s8.png b/packages/frontend/assets/mahjong/tiles/s8.png new file mode 100644 index 0000000000000000000000000000000000000000..605f4cfe102bd44bd4b6ec9ada8936da2c5615b0 GIT binary patch literal 5050 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/assets/mahjong/tiles/w.png b/packages/frontend/assets/mahjong/tiles/w.png new file mode 100644 index 0000000000000000000000000000000000000000..c18793b37602bf20d6fd492875f02383e63bfe81 GIT binary patch literal 4387 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 literal 0 HcmV?d00001 diff --git a/packages/frontend/src/pages/mahjong/room.game.vue b/packages/frontend/src/pages/mahjong/room.game.vue index cb9ddfb592..ab4572e508 100644 --- a/packages/frontend/src/pages/mahjong/room.game.vue +++ b/packages/frontend/src/pages/mahjong/room.game.vue @@ -4,47 +4,82 @@ SPDX-License-Identifier: AGPL-3.0-only --> diff --git a/packages/misskey-mahjong/src/engine.ts b/packages/misskey-mahjong/src/engine.ts index 3bab8e8390..01e37b1a64 100644 --- a/packages/misskey-mahjong/src/engine.ts +++ b/packages/misskey-mahjong/src/engine.ts @@ -7,6 +7,28 @@ import CRC32 from 'crc-32'; import { Tile, House, TILE_TYPES } from './common.js'; import * as Utils from './utils.js'; +type Huro = { + type: 'pon'; + tile: Tile; + from: House; +} | { + type: 'cii'; + tiles: [Tile, Tile, Tile]; + from: House; +} | { + type: 'kan'; + tile: Tile; + from: House; +} | { + type: 'kakan'; + tile: Tile; + from: House; +} | { + type: 'ankan'; + tile: Tile; + from: House; +}; + export type MasterState = { user1House: House; user2House: House; @@ -21,14 +43,10 @@ export type MasterState = { sHoTiles: Tile[]; wHoTiles: Tile[]; nHoTiles: Tile[]; - ePonnedTiles: { tile: Tile; from: House; }[]; - sPonnedTiles: { tile: Tile; from: House; }[]; - wPonnedTiles: { tile: Tile; from: House; }[]; - nPonnedTiles: { tile: Tile; from: House; }[]; - eCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; - sCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; - wCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; - nCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; + eHuros: Huro[]; + sHuros: Huro[]; + wHuros: Huro[]; + nHuros: Huro[]; eRiichi: boolean; sRiichi: boolean; wRiichi: boolean; @@ -38,6 +56,7 @@ export type MasterState = { wPoints: number; nPoints: number; turn: House | null; + nextTurnAfterAsking: House | null; ronAsking: { /** @@ -118,14 +137,10 @@ export class MasterGameEngine { sHoTiles: [], wHoTiles: [], nHoTiles: [], - ePonnedTiles: [], - sPonnedTiles: [], - wPonnedTiles: [], - nPonnedTiles: [], - eCiiedTiles: [], - sCiiedTiles: [], - wCiiedTiles: [], - nCiiedTiles: [], + eHuros: [], + sHuros: [], + wHuros: [], + nHuros: [], eRiichi: false, sRiichi: false, wRiichi: false, @@ -135,14 +150,18 @@ export class MasterGameEngine { wPoints: 25000, nPoints: 25000, turn: 'e', + nextTurnAfterAsking: null, ponAsking: null, ciiAsking: null, + kanAsking: null, + ronAsking: null, }; } private tsumo(): Tile { const tile = this.state.tiles.pop(); if (tile == null) throw new Error('No tiles left'); + if (this.state.turn == null) throw new Error('Not your turn'); this.getHandTilesOf(this.state.turn).push(tile); return tile; } @@ -235,6 +254,8 @@ export class MasterGameEngine { target: canCiiHouse, }; } + this.state.turn = null; + this.state.nextTurnAfterAsking = Utils.nextHouse(house); return { asking: true, canRonHouses: canRonHouses, @@ -278,8 +299,8 @@ export class MasterGameEngine { const source = this.state.kanAsking.source; const target = this.state.kanAsking.target; - const tile = this.getHoTilesOf(source).pop(); - this.getKannedTilesOf(target).push({ tile, from: source }); + const tile = this.getHoTilesOf(source).pop()!; + this.getHurosOf(target).push({ type: 'kan', tile, from: source }); clearAsking(); this.state.turn = target; @@ -291,14 +312,17 @@ export class MasterGameEngine { const source = this.state.ponAsking.source; const target = this.state.ponAsking.target; - const tile = this.getHoTilesOf(source).pop(); - this.getPonnedTilesOf(target).push({ tile, from: source }); + const tile = this.getHoTilesOf(source).pop()!; + this.getHandTilesOf(target).splice(this.getHandTilesOf(target).indexOf(tile), 1); + this.getHandTilesOf(target).splice(this.getHandTilesOf(target).indexOf(tile), 1); + this.getHurosOf(target).push({ type: 'pon', tile, from: source }); clearAsking(); this.state.turn = target; return { type: 'ponned', - house: this.state.turn, + source, + target, tile, }; } @@ -307,20 +331,22 @@ export class MasterGameEngine { const source = this.state.ciiAsking.source; const target = this.state.ciiAsking.target; - const tile = this.getHoTilesOf(source).pop(); + const tile = this.getHoTilesOf(source).pop()!; this.getCiiedTilesOf(target).push({ tile, from: source }); clearAsking(); this.state.turn = target; return { type: 'ciied', - house: this.state.turn, + source, + target, tile, }; } clearAsking(); - this.state.turn = Utils.nextHouse(this.state.turn); + this.state.turn = this.state.nextTurnAfterAsking; + this.state.nextTurnAfterAsking = null; const tile = this.tsumo(); @@ -364,6 +390,7 @@ export class MasterGameEngine { case 's': return this.state.sHandTiles; case 'w': return this.state.wHandTiles; case 'n': return this.state.nHandTiles; + default: throw new Error(`unrecognized house: ${house}`); } } @@ -373,33 +400,17 @@ export class MasterGameEngine { case 's': return this.state.sHoTiles; case 'w': return this.state.wHoTiles; case 'n': return this.state.nHoTiles; + default: throw new Error(`unrecognized house: ${house}`); } } - public getPonnedTilesOf(house: House): { tile: Tile; from: House; }[] { + public getHurosOf(house: House): Huro[] { switch (house) { - case 'e': return this.state.ePonnedTiles; - case 's': return this.state.sPonnedTiles; - case 'w': return this.state.wPonnedTiles; - case 'n': return this.state.nPonnedTiles; - } - } - - public getCiiedTilesOf(house: House): { tiles: [Tile, Tile, Tile]; from: House; }[] { - switch (house) { - case 'e': return this.state.eCiiedTiles; - case 's': return this.state.sCiiedTiles; - case 'w': return this.state.wCiiedTiles; - case 'n': return this.state.nCiiedTiles; - } - } - - public getKannedTilesOf(house: House): { tile: Tile; from: House; }[] { - switch (house) { - case 'e': return this.state.ePonnedTiles; - case 's': return this.state.sPonnedTiles; - case 'w': return this.state.wPonnedTiles; - case 'n': return this.state.nPonnedTiles; + case 'e': return this.state.eHuros; + case 's': return this.state.sHuros; + case 'w': return this.state.wHuros; + case 'n': return this.state.nHuros; + default: throw new Error(`unrecognized house: ${house}`); } } @@ -420,14 +431,10 @@ export class MasterGameEngine { sHoTiles: this.state.sHoTiles, wHoTiles: this.state.wHoTiles, nHoTiles: this.state.nHoTiles, - ePonnedTiles: this.state.ePonnedTiles, - sPonnedTiles: this.state.sPonnedTiles, - wPonnedTiles: this.state.wPonnedTiles, - nPonnedTiles: this.state.nPonnedTiles, - eCiiedTiles: this.state.eCiiedTiles, - sCiiedTiles: this.state.sCiiedTiles, - wCiiedTiles: this.state.wCiiedTiles, - nCiiedTiles: this.state.nCiiedTiles, + eHuros: this.state.eHuros, + sHuros: this.state.sHuros, + wHuros: this.state.wHuros, + nHuros: this.state.nHuros, eRiichi: this.state.eRiichi, sRiichi: this.state.sRiichi, wRiichi: this.state.wRiichi, @@ -472,14 +479,10 @@ export type PlayerState = { sHoTiles: Tile[]; wHoTiles: Tile[]; nHoTiles: Tile[]; - ePonnedTiles: { tile: Tile; from: House; }[]; - sPonnedTiles: { tile: Tile; from: House; }[]; - wPonnedTiles: { tile: Tile; from: House; }[]; - nPonnedTiles: { tile: Tile; from: House; }[]; - eCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; - sCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; - wCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; - nCiiedTiles: { tiles: [Tile, Tile, Tile]; from: House; }[]; + eHuros: Huro[]; + sHuros: Huro[]; + wHuros: Huro[]; + nHuros: Huro[]; eRiichi: boolean; sRiichi: boolean; wRiichi: boolean; @@ -490,7 +493,7 @@ export type PlayerState = { nPoints: number; latestDahaiedTile: Tile | null; turn: House | null; - canPonTo: House | null; + canPonSource: House | null; canCiiTo: House | null; canKanTo: House | null; canRonTo: House | null; @@ -543,6 +546,7 @@ export class PlayerGameEngine { case 's': return this.state.sHandTiles; case 'w': return this.state.wHandTiles; case 'n': return this.state.nHandTiles; + default: throw new Error(`unrecognized house: ${house}`); } } @@ -552,37 +556,23 @@ export class PlayerGameEngine { case 's': return this.state.sHoTiles; case 'w': return this.state.wHoTiles; case 'n': return this.state.nHoTiles; + default: throw new Error(`unrecognized house: ${house}`); } } - public getPonnedTilesOf(house: House): { tile: Tile; from: House; }[] { + public getHurosOf(house: House): Huro[] { switch (house) { - case 'e': return this.state.ePonnedTiles; - case 's': return this.state.sPonnedTiles; - case 'w': return this.state.wPonnedTiles; - case 'n': return this.state.nPonnedTiles; - } - } - - public getCiiedTilesOf(house: House): { tiles: [Tile, Tile, Tile]; from: House; }[] { - switch (house) { - case 'e': return this.state.eCiiedTiles; - case 's': return this.state.sCiiedTiles; - case 'w': return this.state.wCiiedTiles; - case 'n': return this.state.nCiiedTiles; - } - } - - public getKannedTilesOf(house: House): { tile: Tile; from: House; }[] { - switch (house) { - case 'e': return this.state.ePonnedTiles; - case 's': return this.state.sPonnedTiles; - case 'w': return this.state.wPonnedTiles; - case 'n': return this.state.nPonnedTiles; + case 'e': return this.state.eHuros; + case 's': return this.state.sHuros; + case 'w': return this.state.wHuros; + case 'n': return this.state.nHuros; + default: throw new Error(`unrecognized house: ${house}`); } } public op_tsumo(house: House, tile: Tile) { + console.log('op_tsumo', this.state.turn, house, tile); + this.state.turn = house; if (house === this.myHouse) { this.myHandTiles.push(tile); } else { @@ -591,8 +581,7 @@ export class PlayerGameEngine { } public op_dahai(house: House, tile: Tile) { - console.log(this.state.turn, house, tile); - + console.log('op_dahai', this.state.turn, house, tile); if (this.state.turn !== house) throw new PlayerGameEngine.InvalidOperationError(); if (house === this.myHouse) { @@ -603,7 +592,7 @@ export class PlayerGameEngine { this.getHoTilesOf(house).push(tile); } - this.state.turn = Utils.nextHouse(this.state.turn); + this.state.turn = null; if (house === this.myHouse) { } else { @@ -611,22 +600,34 @@ export class PlayerGameEngine { // TODO: canCii - if (canPon) this.state.canPonTo = house; + if (canPon) this.state.canPonSource = house; } } + /** + * ポンします + * @param source 牌を捨てた人 + * @param target ポンした人 + */ public op_pon(source: House, target: House) { - this.state.canPonTo = null; + this.state.canPonSource = null; const lastTile = this.getHoTilesOf(source).pop(); if (lastTile == null) throw new PlayerGameEngine.InvalidOperationError(); - this.getPonnedTilesOf(target).push({ tile: lastTile, from: source }); + if (target === this.myHouse) { + this.myHandTiles.splice(this.myHandTiles.indexOf(lastTile), 1); + this.myHandTiles.splice(this.myHandTiles.indexOf(lastTile), 1); + } else { + this.getHandTilesOf(target).unshift(); + this.getHandTilesOf(target).unshift(); + } + this.getHurosOf(target).push({ type: 'pon', tile: lastTile, from: source }); this.state.turn = target; } public op_nop() { - this.state.canPonTo = null; + this.state.canPonSource = null; } } diff --git a/packages/misskey-mahjong/src/utils.ts b/packages/misskey-mahjong/src/utils.ts index 72ec2cfb2c..e1b8de0c0b 100644 --- a/packages/misskey-mahjong/src/utils.ts +++ b/packages/misskey-mahjong/src/utils.ts @@ -24,6 +24,7 @@ export function nextHouse(house: House): House { case 's': return 'w'; case 'w': return 'n'; case 'n': return 'e'; + default: throw new Error(`unrecognized house: ${house}`); } } @@ -33,6 +34,7 @@ export function prevHouse(house: House): House { case 's': return 'e'; case 'w': return 's'; case 'n': return 'w'; + default: throw new Error(`unrecognized house: ${house}`); } } @@ -179,38 +181,36 @@ export function getHoraSets(handTiles: Tile[]): HoraSet[] { tempHandTilesWithoutKotsu.splice(tempHandTilesWithoutKotsu.indexOf(kotsuTile), 1); } - // 連番に並ぶようにソート tempHandTilesWithoutKotsu.sort((a, b) => { const aIndex = TILE_TYPES.indexOf(a); const bIndex = TILE_TYPES.indexOf(b); return aIndex - bIndex; }); - const tempTempHandTilesWithoutKotsuAndShuntsu: (Tile | null)[] = [...tempHandTilesWithoutKotsu]; + const tempHandTilesWithoutKotsuAndShuntsu: (Tile | null)[] = [...tempHandTilesWithoutKotsu]; const shuntsus: [Tile, Tile, Tile][] = []; - let i = 0; - while (i < tempHandTilesWithoutKotsu.length) { - const headThree = tempHandTilesWithoutKotsu.slice(i, i + 3); - if (headThree.length !== 3) break; - + while (tempHandTilesWithoutKotsuAndShuntsu.length > 0) { + let isShuntu = false; for (const shuntuPattern of SHUNTU_PATTERNS) { - if (headThree[0] === shuntuPattern[0] && headThree[1] === shuntuPattern[1] && headThree[2] === shuntuPattern[2]) { + if ( + tempHandTilesWithoutKotsuAndShuntsu[0] === shuntuPattern[0] && + tempHandTilesWithoutKotsuAndShuntsu.includes(shuntuPattern[1]) && + tempHandTilesWithoutKotsuAndShuntsu.includes(shuntuPattern[2]) + ) { shuntsus.push(shuntuPattern); - tempTempHandTilesWithoutKotsuAndShuntsu[i] = null; - tempTempHandTilesWithoutKotsuAndShuntsu[i + 1] = null; - tempTempHandTilesWithoutKotsuAndShuntsu[i + 2] = null; - i += 3; + tempHandTilesWithoutKotsuAndShuntsu.splice(0, 1); + tempHandTilesWithoutKotsuAndShuntsu.splice(tempHandTilesWithoutKotsuAndShuntsu.indexOf(shuntuPattern[1]), 1); + tempHandTilesWithoutKotsuAndShuntsu.splice(tempHandTilesWithoutKotsuAndShuntsu.indexOf(shuntuPattern[2]), 1); + isShuntu = true; break; } } - i++; + if (!isShuntu) tempHandTilesWithoutKotsuAndShuntsu.splice(0, 1); } - const tempHandTilesWithoutKotsuAndShuntsu = tempTempHandTilesWithoutKotsuAndShuntsu.filter(t => t != null) as Tile[]; - - if (tempHandTilesWithoutKotsuAndShuntsu.length === 0) { // アガリ形 + if (shuntsus.length * 3 === tempHandTilesWithoutKotsu.length) { // アガリ形 horaSets.push({ head, mentsus: [...kotsuPattern.map(t => [t, t, t] as [Tile, Tile, Tile]), ...shuntsus],