From 2d6f9b083f6a73532980350d57ac1a698097c795 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 6 Feb 2024 15:41:57 +0900 Subject: [PATCH] wip --- packages/backend/src/core/MahjongService.ts | 54 ++++-- .../api/stream/channels/mahjong-room.ts | 5 + packages/frontend/assets/mahjong/kaisi.png | Bin 0 -> 69570 bytes .../frontend/src/pages/mahjong/hand-tiles.vue | 8 +- .../frontend/src/pages/mahjong/room.game.vue | 59 +++++- packages/misskey-mahjong/src/common.ts | 17 +- packages/misskey-mahjong/src/engine.master.ts | 177 +++++++++++++----- packages/misskey-mahjong/src/engine.player.ts | 61 ++++-- 8 files changed, 286 insertions(+), 95 deletions(-) create mode 100644 packages/frontend/assets/mahjong/kaisi.png diff --git a/packages/backend/src/core/MahjongService.ts b/packages/backend/src/core/MahjongService.ts index a10720bf79..ca8c2f685e 100644 --- a/packages/backend/src/core/MahjongService.ts +++ b/packages/backend/src/core/MahjongService.ts @@ -280,28 +280,18 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { room.gameState = Mmj.MasterGameEngine.createInitialState(); room.isStarted = true; - await this.saveRoom(room); this.globalEventService.publishMahjongRoomStream(room.id, 'started', { room: room }); - return room; + this.kyokuStarted(room); } @bindThis - public async packRoom(room: Room, me: MiUser) { - if (room.gameState) { - const mj = new Mmj.MasterGameEngine(room.gameState); - const myIndex = room.user1Id === me.id ? 1 : room.user2Id === me.id ? 2 : room.user3Id === me.id ? 3 : 4; - return { - ...room, - gameState: mj.createPlayerState(myIndex), - }; - } else { - return { - ...room, - }; - } + private kyokuStarted(room: Room) { + const mj = new Mmj.MasterGameEngine(room.gameState); + + this.waitForTurn(room, mj.turn, mj); } @bindThis @@ -379,6 +369,17 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { }, 2000); } + @bindThis + private async nextKyoku(room: Room, mj: Mmj.MasterGameEngine) { + const res = mj.commit_nextKyoku(); + room.gameState = mj.getState(); + await this.saveRoom(room); + this.globalEventService.publishMahjongRoomStream(room.id, 'nextKyoku', { + room: room, + }); + this.kyokuStarted(room); + } + @bindThis private async dahai(room: Room, mj: Mmj.MasterGameEngine, house: Mmj.House, tile: Mmj.TileId, riichi = false) { const res = mj.commit_dahai(house, tile, riichi); @@ -551,6 +552,8 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { await this.saveRoom(room); this.globalEventService.publishMahjongRoomStream(room.id, 'tsumoHora', { house: myHouse, handTiles: res.handTiles, tsumoTile: res.tsumoTile }); + + this.endKyoku(room, mj); } @bindThis @@ -700,6 +703,27 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit { await this.redisClient.del(`mahjong:gameTurnWaiting:${roomId}`); } + @bindThis + public packState(room: Room, me: MiUser) { + const mj = new Mmj.MasterGameEngine(room.gameState); + const myIndex = room.user1Id === me.id ? 1 : room.user2Id === me.id ? 2 : room.user3Id === me.id ? 3 : 4; + return mj.createPlayerState(myIndex); + } + + @bindThis + public async packRoom(room: Room, me: MiUser) { + if (room.gameState) { + return { + ...room, + gameState: this.packState(room, me), + }; + } else { + return { + ...room, + }; + } + } + @bindThis public dispose(): void { } 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 de7fc4f467..7daac7839c 100644 --- a/packages/backend/src/server/api/stream/channels/mahjong-room.ts +++ b/packages/backend/src/server/api/stream/channels/mahjong-room.ts @@ -40,6 +40,11 @@ class MahjongRoomChannel extends Channel { this.send('started', { room: packed, }); + } else if (message.type === 'nextKyoku') { + const packed = this.mahjongService.packState(message.body.room, this.user!); + this.send('nextKyoku', { + state: packed, + }); } else { this.send(message.type, message.body); } diff --git a/packages/frontend/assets/mahjong/kaisi.png b/packages/frontend/assets/mahjong/kaisi.png new file mode 100644 index 0000000000000000000000000000000000000000..322d2e08e3dc4d6e07770948f537e1adda7c71f0 GIT binary patch literal 69570 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

o9WERj?l_65+YpMa{<@Tz!HTniA97(& z_PMp=)ioJlqsW6>hnYD`>Lrn@aAZ5UwzCG%Wqm05(4` z|9J%BFCARbgk{tG+BjY7qMS6f&j)bI^P!8z&6+J(TCQy>uWvSPHv4{1Wp3iD-Q%_n z>^k#qwi#7WL4k-_cT^I z_z=OR%RaJE66}YHXA1lNXxPfTfer7Ui~dkUjXwNCN6<^&GCSCJkNgikR&*%C8K5oj zVLAWs9iJZBPf=z4WU@s?!D`xFCM#KJA|)BIXV#mt!NUF8vDhf#5}V}Lm~x)A3phgkC*no% zA8kB5Jdko%1VLo2B01FA>xoE?pgw6o>bHgCBPvm0n37mEW|O}nx~dfwR|oCZE+|!+ z4!;Y6&CtligemL0++0t-jwJ4XSX+;uZq0pI+Rli^Dt+@lcVmAOuo{@r5P5m#EQ#Yt zsk_~`$a{G#h9^%Jhet+SL?Oz%gqX+oN?)|SkZo0Ih@>}d;a_z=HTu-M?HFv(S`AT9 z)r4Gv?s(LC`u^n4+1ZLQD({hRNDY*YjHdjGl-gdBIVi{s9XDTCTXGSHQRj zTW*weS-I`yBI9Wz7CCPm_|1!fa_F?u(I$VnTZ^&8^72(~4)&5GB(e?dq)^~vh-E^D zYHhllzuQ>^9RKjV&Fo&BhyMlB_tdB~z<$fQ+oFb8y)U5sTr+4&5WPj&2U;T2H%z?2 zlUxtF&E|>~u-T>!kG7{DLGLA0Yc_OHDE?Eot@J|0>L%lq-w{?-U2nIVG)7(93$%X^ zXL0`di3g-nd81ERZbm6c-4@Io?p|3Yq-H8R(-D4D*o8X=g`~Dk&)~{P=;D+MP$s z?}swgK<97aBCG@-BZ4_g*>=S$log+SwwB!Qygonp%Ft-zD{h_y{9C3>?vD`kzT;dl zQ-;fe=TPup@S-pr(Et%Q4wOaA?#kf_{nCf1L|x6#Rj3fBpG_Gv#KjATPjEMr;9*}; zFEHC-pvkC(CO2jeq?)Q|ItHO{Ls~Sh%ncSAiX+EFO#PuPRq&T}BwiK`ai%DK`%9Sq z{{El_*)VVmmGF_k2-IiqpP!H99Hj718AK*si2ey3h@t>+0;Zo~M}Vg{1%wm=%ASOH z4QdwL*YV+Sxb;S@pUC`%Y&tidgd@Kr&>2D5dE~oy?;tJXDtQOnAsV?!N+&OW;-2m* z*c&L4HD?vNR?%mprTd3tL<@8uk0tF!}S^ zP}(mEdjgGgXW?IaZ$AP46*vS;ISH|we`)66EYhi5`}5~57)TadNSbi;2kNBvii^Jc zQ`DnF6|PH}MTg>Ibt$eweb_%aiNCVKWP(NKu{&oh$h|cI`9}{ka4*&AoA}GFWVS$P z)NPzyHB!Iu1G4;d_MW?8c4Kj5={xV=Rvj6{2!%1Ho9B2)ilSa}C9HmLGR8R)=jEP6 zASb=-WgQiz)Cb>K<+T4Ur^`d$cPfmAzbQ`LOJsb;4+@J@7&$F0RY}NiKUpj^QYcbs zW-vuu|NWUV;XLanNOZZrwg#c5riM<))T1lnGD@NS`_iB<67&{p!DP}l=LQD{As;6P zM`v(+PLt*e8hKwiIXR(4VHvrhAkMpcqb>z6|DXZX!#+Wp3Jb?|d+6<#(n`4;`nF-+ zW(?y|%>tqjA+R)5Vd#K>yExO+|H&p5J|QVY;Z$ zAr$kEehdLqzG>jtk3Qzpq1gTwFZ0?>N?jva7a=TL3Q@vauamV9L8zc2D)F?d#Rw9j zDfh75+~TpccATbn7Ez7b!mqgjl?6Op$!5ET?(FBoyfLWJ(5`!i(%!VMX`uOu8OCn_ z+B%7#i4+hu6hv)}(-LAJEZRnB%M1(tPs9u#qKXaM960j8sByek=nWWe!+BGt!pdFy zO$)=a<_35hxRsrc>YWwQ8az;!a|)hL8&w;iVqmdyPgWEmlwNu97VjqujL$ex$ES*j zhrA}KG{BZ$CI0tOtJ*pLskq0vUO7uy$#28ohoxEX8Zc*plJIMHHx|I`vHv8eu}l@E zP3<&%T$ekqDI)Qty-+3DL17P?ZQ=@dqNT}fl$ETPd-i7`bz{?Y=Y|GQjlm4vDTtPo zH1gTI*8b0l@TnMQ^&Y|SMh5#HNuo0L(bVGIlWQGkl2%{}YiMcd2d{0EEHu||ZPaOJx{4nu*5g!%xT&7jMT5>>gll03}NPDg)3*e-qg3{(P zU;dB~5~ii3$PfMoyCgl70wndhq9IY?t~VG6gRk;ab3ztwSw7kM*3C`LrBBF%)LJKj zF=+E(jnWew!}IcJbuy)T@#&J7nwzaEeC(-=DrHVw3fPbNK?4Z4Ni#<9d5jBc;K{|x zs~?UoR0JK^Vquh-0?cyb;D;QmKoa%y`T31ncrzatHr|Gt5RB~} z`Y95UP#|NF9jw*%K?%+%o4x5M-<69+=n#oJodIGvfQgui2&-v!?P0t({u-qocogj}L--)2I0=s5r+cBLZA0RHsirsa46=XE^WNlFqp(vNi;y@tZuc zi|QLxaB=x>_Itf0we0(pWJ1UgHFW)4dUvSX7sZOz&I1GVhP>mCutmi=`BNiQoBr&} zkDp2Q6CZkvrwa0T(6563(TI7eTu?ta&4J$vU>(q*&=?c-Hy`4-Af!A5lvxqf?E0@e z!f%GmQPbO&i&CX;yXg2G*rBB_j{}CrDWSZ)yb7DC-3EFWxvmVUej0d=%Z<+z3fGW~ zlg3HasQ#c`^6hJTDk>_IZV*-IT0h7Y^90QxD=?J0c;TrAyv;lRzZo|;5OIV0ePj=D zALv;Iouf7Y@%Ip50T+dblDMCr+cI~?e0E|*gYRh{wZZ)~;FC}4PbKIVpa`1#Gl`4<)!jiaTB4VfF_yjT$= z#9s_{q3VRZeE1#_3O5o>wY5B7050l0Jhl|1(H6Q3co*8`Ve8^gJr!FiRxbr8GbdHc zp-8~*RcpDhQB%d!^jsorIgXD-A5beg`rgHo=U*4TYg+gXvLiks*)%QV>T2XN)izANiKN+J#LcF1v$?{xn8Dl>?PVT9vLM z8SIwR=Nyqp#Q?Rz5BgFfEFYU8RNvrtZO`iqB!k}q3zCrQ{8)4R0G+HAwuWP<6 znKcfar7s~=0`M-z37C?CPq(eBc(z1mw5r24`grhM#x1F9lQ2R|oAJyUgG(dlCreMg4& zX!d1qgWI=PHjL>59FrHW)82<4y)im>e7cNc~7&v8O>O=||JV`?Zqa zYOz3$zp}cz+UjH48h3yMaLK_T4ET?osQ(5>h;k6Xe>3h<6jF?epnE7%VH?=7uw}Hr zgXpGxO-$U>H*u_lU!9fCp-{sTqN8O&Fh|`Pfv=22qg&hm8@x6an3Z=_haLOTYWDS+ zt7iwaU`C9ocrpunoZ1@=@&H*jw1S95iQ|+xPPsQ|6N>0?-I)iQT5ZT!6%pJ)5UKY- z%{)BbR8^kM6JLeC2-}!YD*r|E%=N=!Dv|!h*3h-Ql|F%ol-!UL76edzll0y~kbqyL zDPwWORr}e}yvvvr5gDm~e-sSzBxwN(wb?pZ*fMXv+0~kOm5QX3*|Cr{I(ps3ZFOHW ztZhExd3FpMlfj#dirt`r?&FFdVF`EOgZ-mHVJdO9IqHnP*h0Rol{qLvUUi47KV|Qp zd`V1=j&nw=QvsZfb93iZ44Td>UX3$n2FQciHZ4XjKqE+Lx!RQ9Yq=j)n6-9&7Mn)2 z=?s-8g0}koHNkgvbyaR}2EIoOuxMfHRm=ZUEFo-V)(vvDhMw+1%{rJQLJGJNRiR~&4|e@wxC!of+psc%d;dj&%@H8s&f-f$N1;=2kRNg9wz z*4ul1A|p%1Gio%bFx&hh1~Pe4ATF%Z2kh;4K;9l(oSK??wEhAlbl(9jDcgdre9Cuh zxMGa7{C4xU7*^5^?;(__z=s$pttb(jknd6#M-&cai1{N#8HF& zOswCh(n6ZO3i19*f^+u0=Vxn?v>e$wL*Y9?nM$U%h`PYvR~v2(UUxTv;o51IQjq{r zgPAJLOOb?P}3xA*f!0X&}r;{9vzR8 zUCvbUXtlpRl>8KO1;Y8;KU%oF0_F`XiDbgwrp8*D;-|HbveiavHbvJn^aD_ z2N+EOrzwVE|9wz7C&JFY%~HA&X0eH|{KkLbKnMZnaAks+9M-uiJRb*Fy&hvv5w|QX z;t7!|v5iiwK7vmHxQPrg4%K>`d#l~_ARbvgCZ_f6ovhM;g1s5 zuw(%9X6nC_lQ#(o_y7_7f>S-P0Aman<&S1Ls_j0B)gRaz-DGSwzcp;W&OCNC?4DLK zIK~MrkV%Au^GnM2K0$&;pYlfLCznRgfg9V95Gfpm<_xMjnbCds76foWf#~5%X_AbI z_;Sewiu0B*wJWlnJo2`GBn)sI0pu;hRbY4WuO5508{ zD0t*gzXo^+y60Xv>&dE-hvwLH_*d$oG6)R~O-)Y=^>{`@zH~QJIDM>MC4%-Efz4F< zZ>oq$P7_$3ZY{tJYvMR`^#UBBO~9@WlYb6!qTtx+5cKLFjFM5k3%zcs^stqJ1`Ps` zqy!ZBh&X8C@XeR-fk)M%0EY5Lr%c8A{G~PFby^Pc?59lmJPECjSE^yEL>&tE}K_cT+o_dj+7dELEo5EFt{%>vYcl}bECar`Mpz)huG3=j$a|# zULjlR4}x8-=cPBS;>(yf-!aoM@!hsuFC`3Hz+!KQ(s>X>3HD^ z$2pkfdSQ1+_=$Vwo-62%qjCd>PK>o5fUr$a(9yrn>Jn`zf+C)(goH^TN&OQwhhda2 z8>YAuK|y7iFf^6CJ8X~Q9g|Kaq`silgVOZ3i|ey_nu0OKe$!I91UPYM8fO^TLmp`N zfW|;t=)4&2^;pH?@&P9XLXBU+>4KT0poW<>iRINnk=`XbDrylxUO0gZYJ}m<-=}Mz zSx#R)HMQE;v%%jO1s3zEYD2!cDt%R%s6G`xKM@eASF1lWNbUCVvXdJ|+s{-R@>)40 zdIQ-E{rc_OH{4<{umX&|Cnz;b7&tU=lmphUYgaFH4hv?6->9p@i)}E3-Gm_TG_^^# zGp6l~0Q|kP@N9~5>Qx{@Z?7<2QeM2kK-Worr{z#t;``-wFuR5X z4T2`V#-jc+OaXG-8I}1=v8g~|l{iQW{8Z?x&U~Q*WfqF=)2T=#yos2+E%U{OeBX6{4qiri|; zJrAD<)r3T*=j6l!AL{lQO-ei}olPLkHYdnjki0kRLBLX z+MTE*7}VbTfE?>?I;Xyh*5~c5t#^{a|1ih`o@5ETlEGjw66w!PO~f4&Lu;)}7mTi- zjtfB$1JEHEANCl)`BRXI&r8Cr!6|kLpC5mo)f*?5)L|~OS{uZIkqNc6vC#sAam;A~ zE?_KCm@cM~jS&-EXra|w!EFtSmAeE66!*KiQ#LEfvd+)~tUYO14FQ@h>Rygp6GMW{Lzfp>Kh$C1$1`znwUl&uu@!zJXp zCtUFfweqtsDsvJr#j?<{zk7TI9 zUC9Xjg&*+0#SR>h<7*A!TFKp;*mLndrN(%Ia(b4=c~8WmvIcg|h0fs5g$m`Z_H10@ zd3a#ac^C_U`8Tun9VFcO;WGgz$X{SL+Wz^ue(eM(61_la1YdgN?OuOi$Ltn|VP?AG zuji)JSpI-*i|f#})DcJwR*HUrso)R03)x#>+_*Tk(y6cMwLfWg(KbpTO;cGQOtgGI z7y}A3xa5CT#gKBTXuJd`{@36Cn(}WI79Tol;6;u?3ymLH_4tgi3`Dc%jdK7bd!{$o zxck9UU>S0>u7G(&!1aL5lb1&U2w?hvpdhR(!UnHB?!yZX{<+xR1+F*jj+Qm-{K10y zgbSdB%}7UZvm_`#XE!NrjhbEh3@+(0)P5{6UQ(4#-sYZbu& zI|MZeV$f{DqX=5=z&enne~0iwL1I{AyL;lt0d6D67?`|Ph7GA&bdW8C#ksPdvhaAP z^{wEsk8;&X`tRpPsB0*{r<3GFqJ68z)Z@^Ed>a)VvOYdy<;CkZZjQfq(iz)*ec~TN zNg2_ka`k+`Q-gP^y=jVI6D06KcgX2|xsTOwL8|!3aM|;+Hq{E7d4ld=Gd|eWH(YJc z_zP-kBQqQL&Tb02QQm5zeL6_ty!ZS)z{trtQgaOANVd2d8Zn zjNPxH7 zL?@)Cjs=6S2lOYSb_ z6VvjN(agH=_9U6qorjdObdVcK5IwWU3`%4nb`G$(d{!K5>A++8*CuD@=LIcbYh#B{ zf=)r_2NW-6m?t=gske*-aarBz!6Ym7g)k46;Jg;7LH_sfpi0l$*4Ea>&4)*JM5d(3){9py zNz{|o;j2hYY6B>~djsAoWx4GKL!1HN%`#woy}xn%`tSzm*O?g;>BA~8=K&i+-Fs|y zRyV!TL>Y|n)ix_gN1?ypCRukJ^Y#9P^eJYgr?VD0qE*Oy0d+@514@uzs{HJDzLvZ4 zjg73h*dG?vdFb_fuX;YSRs_hZ^z8Wqqa3S1;j1h7;2q-|>cVYGo6cm-(b?uj~_8Jzl9;JZjc?QBd2 zYfc;ZnmU^tC%e$rh!2t`f`N?$C9z+kF-wW}pl5BZOmMviY5P5U%D8op!sit~AAtclPd^(1^b#*zm2JzGvL(Q29)5=t zSH5--NTi-zSjYvYL+qhu_w@AiW`9mj5*=DYqc4tVQ6XG6t&DNlWn?Zx*_-TxTrsM8 zo|HuS=w~AtEQvIEJRTUj-z=aNp~ZmXy};-nT03r182b$YD>n&e1m?h+gfEykB0BAx z2$O>tVhM$eyVC{Qf^i;AivXA-A_A_i(H|9hMnrtAMwEt4&-4{aM*d5oKR?FrfDJB8 z*)&?FivzJZ3S22>+gI?{JNY^aesug(ZgMDYE^+QWrOM!6=Gf5>!d_;KS6Om%i_^Nd8>NEOywcl`tw`Sm7KaWq@M-kIv z7Ba3I|C=*1&{)!YqUmL9l4RrViM*8Ilsro@Su{!fLvc)obN+%z=r!Ik`TTSIhL?Mm zLaA9-60ME&(^jqINRGj<`i%`T3i)w=bk&=DVd&!D`qfYCfm-@B`mR4?-xwO{pQl%P z_<7I2_<#hEsyuwSJOI<0ea-(S3S|&c(Ddk%mz5>;KSwuXw^H_j|1K=|bLgB`qzT@L zQ}?_=xgV}l7(|{N{VGM{wW^qXp0zNx)a)~EyXt#bJaO1#8GpZ->Cr~K5>)(1S9*)+ zGGiwr-JhPnZ0=V5y%i?ZbV~o)k;Fu{C~g@~d=!YY@4b!CUu1gQfW&zaM3!OeC%TiX|R|Gk22ny~TZ z>({T8?L&8QY#(~8{JQc%70#I0N6ebs0_>bS%(b;HNM}~-`>E^ib1D`7w!hXTl+qom z{y~<6TU3(-MW zuS!4j)4oc+uIAAxuOe!tqmvZ#;te!BZ~#I0&;|F@pOJ!Dp|gm(&c7nDAey*n;_?vo zKW`p$grvn*O!BZ%^1X4z#L5>w`o7gQ8Pm7ugFr>_yus8-Hi)1|IuN`zoKt| zHsU`dpfhuOnCWKqi4A_#zTMs(((sLqM?|9-<5%oU+mPnB#EB0oW=a3<;;Culk>{k0 zIbc4sn3x!b$cpRIui@#r_Ytx1;AdJg7Q-HUOV(TL~jW;9yN=~{PY;;PkGa1 zwZp_%QuHo~&@j}2(O2&te zR)gd59dD00;FesSH(o;)WM0Voyj?tk1g#G>T{FR6tn#a)UhE{Ppu>$aAc-AAgvw3X z`0^Zf*ybZMGsh<&MmH(Q$)#Tk6Ol$HbUd%ahBopU$Ohd29@^ECv!(Pt(>hiCL1Gz8 zHvjk`7Wnu~Sd0d731lr_W;*HZ!_pQfHdBX0L5>I3!}4xU$=*f=7t^k zr+O}fUslEak95ev8=$D+9&S)QP4cbvkM!mg)8A+zHa)^W%9rbvcKU9%>vYy&`Sf^b zkcV&n@fVF;SaSz^=#H70`+Aez{ZM{aL5kWU`l8y(PPV?nC%kgI{gs9iT11IV9#6tn6G z-~I8{kmMRTwrc8x@`k{Fh=Ed-g^P=eqW4IV`gb?r*j|&8GIY0n^X82klr@8;Ax`s^$-7(AJE(F(BnYTO#wFyC6b+wo-5AT}cvr=$1DH{r6A*g{1`<`hHj= zHGic@)O{l^xvT$v(aaCEN8Hcvpg4#SspP-oi58++`@(ZI>mY41@WEKQpC^*dvZ~va zy!Ig{=g-CG=VJCfqMeRE%wxJ&0%ONHqgF&p`KhU?QxJME_dPR5XUSswE%AzmaJZw{ zVnsSovoq6ns11oA%$v3lLt<_~6-J=f7p2go1h!w=EZN2;DF(d$Dez8n!s@ zZtZvlG3kCJ(fq?ozUqmu84}nNcmiTX^a`5Bco?t%GBQc%DZGFQV)F<5&oP|Fj3C@5 z^&Z+EY?}g*W3quUREn3dZrY`tcPps3q`z~sFL`lvmbggl$ue(bQ9Pe+)_6$s+p(XV zJ?icAp>(Qqlw@`O9MmG*8k0Re_Gg%++Y0&iDXdh5-2B*q5l#~}GqLt6XG@LR-iE1_ z^j{2g9_O<*Y8?@_K!|GmW70yux02%o{FjDu*t5J>J^r(}s3(abfrtx1;Gr>*a5gMtI5Sc&nDxmo(% z8jL=6_V-htoa}Q!a0hCpkZ0Dl3T*E_V`S%l(Bi+# z`BIX~M%kqzVv8j__a{z5f|mWAEN6Ssk$;)#H=XmNw${h~;dI2wj1usQ<2PNr5H+^p zdJ8d%dSe74it>l1ri#ax{`L@D*oEU<)FP-c{$(aojb!ZJYnN}gWnm#GJ5hRHn2D(O zBthZBB`T^z$?56tj)JEN1floAVx6FaA(ej#{s(2WdUVl&T54X2B zb9cM{zJdnuEFa>e#A3qHcKb!fUtuFaxT`wyW{bRW^Np7ihi}tFxa<|$B;@7w+f7$@ z_~2*de_zGDe~7U2@$sz#w}V0>Q$(13X=AuB8eviN5*pVSQ@Is8S4+9nG#QhXtxm)zq| zW#GbrRlO5$xTJ!@$1gyixX2%0Cy6<-`$|YTfIit5!?-@5VlE1%A_|91Rqh*d=&Og% zJ=vwUkYDDh-%8qoPdu$_ZMwOK+1jSt!z?K|9{swGAMWfiza5emi1SP${O)L1Kiqb0 zpz0c9XdhG|?}5@kDfuk^b$E-*D=e}X&ptEW8rCEbt zX=!P=@aQl~$)HII=1F3P*93|+yHm2W(O)4hnV`=hK;T}Qj$g;=Y^8rZ_jLKcndtCs zZ&z0IPA3J}`w^C!Ho50-$a?x>uZ<#8GNn~<;b^ptndG}*E=w<02GX>#;}sR4*Vos3o0Ah5LyaTqP5 z0+IM9MMd0Q-QD@OlR2?PLcE|IJq!e|kgz*1L^-JSqP`eyV5^DWz9D84N751!6OYth zXQ$&r9zeFyz6_+>I;db%yP3d=hz(9iG#F{c^vpQmHnJeDb2y<4L`~@n0?f<&&(*A1 zSG)+6b8m_$C@{su#6$wfP&xLwzrWuUtr$8{@6Lh0T2=7!K1s<<0q67;#_%~Kr1WaP z;5>*Y#q7z@lTOm`YRz}LAJbK@p7%05QA<8NOA`_PZCz~g?jgq2{+gm<{tqV)V7y~! zo+{jF>3GcYWXy6T-p(Y?Sy6^K;pm2omvPD2!CJg`lPxoaGSy;YV*`ex?eya1B|@-n%}QW%WJ zH39i``4UzQne=3fD0Rj42F z{N=5?&6|tMX0TR(FB|pMXhVZ|HoH!SCFS#JuJBw110`Z?W_Am#9!~f}EXs5^V2&j? z*RL!seP|A;hF6UE#>V|;Zm5hej~o75RFUw^6;u?r!*pX)jV>Rzp~$a`+JbEs6;K_= zHDNqM=nqM1&X94+sKI#kio~HW0dleKXP)MJaB8U!`i5wEL%F}D5Nplh3-)`g*nY1a zGFBzY&)%B@O`S*lCm19Z0{S~uH%(5+26EI*+7^TQ8W}<{@bEEQTMRP<%EUXB>7dB} z1f=}4<$Z`D|D*WSmIlE0I}uO_j8-F{HIeV%%YeK<1Yq45Q7;GrnTF>G#y-^!Cauq+(9`;{*w2)Q z#?3ds)dy)$t!HXnqHeU-!QvxCaUBVn12W;E50=s~$rUR81em*OD#axvv`M+o zcPPTP$VlHmT5ew6WdqQ<;R9K;)lVbEnm4+0!HVAETkWV--b05~1}*YA)UO~T)?QgL zF{+gz&52yh93OfTlu8ADQmwR|QjO!~N}h%0L#Z+4W&&qTV^Mz|1v7TpC+?2ugGG>0 zPh<8{QTZ&`n`p*kjtj*&_iR+KChr zo_evc>wT9L1<$UQek0kV+;|V%z)xTfxxe_e7=Eop=_t7G3-*``UT~>y)$5z$VZwch zSUayRTLzvP_no&UhToDGjz;Hxq&B9}LUGihkAEl11|3##M-yWfvDp5LXFAIKYc?YJ zwI`8{rz#2-=kg?&QO8e#d}4(@-i5EK2e1sgAcC6DhoxbE|4@OtDUYg{ksD6o!xWWY zNB582dJl0rf~aVBp=!1pUWIS%h~3oorId4{guJ}GYMmGtMpz1kLNFDFg#Fk58I80A zNH9vJ{JD>Gz`c|K7MBwCNI+@PMEB1Zr{<4HZ6S85dKLhHb^ERn;l8L|8|l0*g@XYT zy&~mtLNuE+J!zd?0f=1v!DYv&s$@aAIC+_l?yz*a4bDR?=s-<>@FBSoO&;}5;GVaM#WkJvw;|Ds481l=KX5qAvOxL#NTswRn7MX9E=L&2zwc{C9&wLqj8<-PB;L;Y#a` z7nwtXOK_~I7TmBfMpl^hPylsJNEk6DHWC+5(FD`>9Np7go}^g&pDo61jiQ|Pbq-kF|J{s>^+FWw@KOeM3P>e`E03MBu>a$UGAwP4o_2_ z<9fhz?b@|9jOztEjZ=kg;eTsT>uE|^U@gH3K2`AD@JE)(TzR70$l2KKQMOpUbu~3f z$i*?oLo+7q(iom|ymafsKd9s@bD^ZqQbFN@lE#Bl5Z0U$;Ees~F#iaLd|MvcY186$ z-ST_FUAp|Mo%#BDFd;sUht-SI1Y<@BiI7Vd;Jl^$*{-?~K2C2nMD_HMrsU9w(y#Kb??w%- zD6+}1GzmBzOM%H9@E0_*Ns;5z?e=YyN#;(E@_I$xs(9OjeYSnH$w>)2YB_7pR*mKI z<#DKFiW7^A?SdLi2di~t9@^SY2f-m;(u5H>uy&r~TGLCm*pofkq`fnT=V!fy3X>Dx z?i2pCuur*i-hHuu^H6OIhLxePc1pMIEpPHP5io5`oJe_Tf|MDM8;eG147TB->p~T3 zqB6IHP3z0@8u$^gC$aTg8+BZRPU~`9I~xN-3?$%{_4lyIO98HK$N&DloDq?f{0qq3 zhn#TH=r4&I&(gEtw-e(wH#d36BF||!jVf*Oae_~ASj=?({&vPmF%CGOqZhl=n~T|} zeEV)$6B_o8iBlnE@J9RkKvitK5zs%%Cb6r}zOuVf z<}s5;&rk^3e5<@7C3SEWvre(|4#oo|56!O7ek&z$UyIx^m7Bow;u}`95xWv`9VJ_h zH4X;J+`4ZdQp`hzSV0hdO9z-OiOPlU! zXlU%grsZQGSOi@DoMy`#{sj!a=vc4$yWcP}GV%keDicsIUu9=!r@>fH#r zT3~ywy*&(stHXHjzGfa$V3TT+GT;gY;PH96UU4itn=~Y(N3$)He*@32qBw#+BeHVT z0z*HKP}RCBiD%#y^f~YP<1ZEz;Yd6L;WYOWXwhGe2o>EXc=EEOK1Xp zeAh|XfwW?kYQGmRzqJ*@e(f6C2`a0LrrWE)O!4ht;lKk+<@}R4w@eEl%q$@B38Nk4-kHfL|8sF+Wq_2+{M~D zU-l6Nvn&GqF#U1yd$AvpxDv|sZ0e|o77Gfg;ZG}sjBAkd^Ycg-3+N;3K@JxSLhs=@ zI6-n(#h42e8ZRCS^5y5}dwuj-_obdzq#FO$kJUp8FCmB9dP)T2fQ%K;zkzj!Oz>WEq9KY#x5&aov{WJ3N+c(QjLQzKbU1fFTo(sp-3|eSV z%-e!Zqzzi&ujc|ZjyU=nfn09bH73+os5%)j!t{zHv{$%SCj>H}&$1*ZCjJ)$C=mtw zbKcmMS8_NY>@9hZ8y^L5vABYQLc}K->(97YNL4U{m8vDXKbw2BvvjO=2x0mVb1i}DH0Qu+Xy-CW* zz)#nR0*1{e)tE9o>!2xsP@f*n=|EaJIU z0~jy^919!vzwG;WN-#t3HF(if(Xc~*|JhRvZsvIbZU8s_OJuvCpQis_X~ONV7y$b(vdF_#?LAotrWbj6g6x5{HHhu&2)q~hcJqg(E{ao+Y+ zPzwK<>hr|pUQLYQI35YzJeWn*<^KGMEp-Je(?2=8t_pSfFx=i={$uLp@BnA_pEr1~ zI{tV|3rvPf3hBJOylqDZ2WQT}UaakH-!pnkNEvjlk?`k200-rW?2#er4#a!?mR}Ld z%!@w7xK0stNN-N`h@5~69Q~3Ws5+;9RGRtas}&}vG1l&ZppiN%QaW&cyteC;B_-pR zGrov!rlxVgzrmR1l@%uFZUFgMI}Z9@67~?7;9$0(8dVcU{{YV&?nv|-FEfY$m%Oro zzR0U~AA*t&e7L*UCxZ;cak-}v7#a&o0w^aJ*xJ@U;uZ?s_Bb4;qEPV=->K8t8=*mSj*pm$xr3SJsgxYxCR=TS``gNFud;)I#hSs1W% z-@|F2q02o5lEM5^Hy*yXyp=!O9;Ia)R^*X>PDnVLP77gr$694LgJyW#c=H)xlK2Z> z``X&t?gKe#KwLj|r5Zmx5bA?LMMcGxXNl`xw$LO+gViZBzKAF1e>}Upw>@KTKC;@S zRkzSJ{`4E3k?_w3=l79e!4P4~bRQSu3s~a6kTn3Om5zTolCMqVeAX_(fx8=m?!tCZAhf_k9B$@U7_s3|Zj3g2*$eb1P|0BnA`Yuq zTFfdMYUPH~*y7>>iCM2m%-irbEvfr}Q$NqFkq$@67GHcP(A)?05(@aa5@J!rAM(|tqqgqbkk(B$9U@=V9rnh^Cu3mrmm(q^&1gRwEWl) z2kPAk!o8?ENLdv>!Mo$0St9d*vz|YI5)C7i$81t%E=N(kzK=fff(8L%3QbDmI37&) znZSaZ6z0&t<%@`l!h`uAE+|rf28z68mnLLHd3i{J67y-TdS5LCw%tUCdD|>6>`9Ts zu;OU{T3x+=%XFNmm)JVuxLqVk&FC42g4 z{L&JS)z$A#;g(NnIHHRgxY&R3L@jRZ{CV)vdo}W#j(YRerxa|gP0)u2QDT`wM{qh; zVd9lEUAx2sPw@U2sN0^wFn#c;q)p+X;!6o+aYVX;pW%h)f5o!hw&Dol@ZRO;SONUX zISe@PEwwpIo*I@%EJ>8D=f|^td-gnhGztkubXLl`=VJ<0UJ)9Kxo3%Uk5r|hIPLxVb?er7W_MFu%FT#yk0)5} zHHCySUiJ7$pqLlm&hw93}`=rf^Y$d_@6)e zF&Ag4k@=5eeW=G}48AqfJh8;bMKj??J<;@Pof4Gp*2i_H@)j-vDtH`gO>*biF1hc#AfXr%)(ME;$g zvRTwS470euewMPAIdCD!fM|H7Tqs#WukY#*Dr&M3P>-n3x$J_9#C#1^?|r z7&T#ELr?(=j$CCA9=eJ|J%a%Z!QBYmcXE{Akhtj%`QeivjD>^xySwdDzSQm}s?XOO zR9nor0?(NY5}8>QV6RKUK%0WCH4TVi;HV2@`tLwrqCNyT8&;>^mKHekCp_t6!1DB2 zMxSu581~;cYL??{S^@u`#{=ntmpd-%n70Z7Zdm!d*%16N!{Q3V+uCENC1a9SRee&g zGy(4y1QEtr21pX#f`(M#&z%Bh~!UuLqDkKQ=wPp$p5e`$pL3eX9cZ+TH>K;XSB{x91pL>R?9QY$5CuR^50fDaOiai%ieq~DPr=y^zKz9-;D`tU`WOCx5HhY0nnc44Y)%o_0HY6 zx5$Ysd-g2XFa`HH2lp}Hm=0f*+=5aeuFABbzZ!;lcNV|OC@HbRh_v^Y54pfP@t3_~ z>H3Q{{Df?ruNEbN?mVj#wOl3IIkEr6(|SDP&4TJ-7)q#`{#-YNe^%i(R`|l7%NJ8I zD`pnDG9HW_=4*ExxB6m^Wefq$djo+u;Ca!^hT;bKn>Hf4`Y8lOGCCxs@c&Juj zvWnk$N=mi&07uq$;|2E>!)9jDAJJ92FXU8k=Ao^1nA9_NNCB$Nx8dRBN(wq=eH|U0 z-!MrflNwK3ZHM`m*j*@j12$p88}~$ufwzd`qNRobukSSO;=<;{QVf}}_lm2ZzCgPi zpCUz<6T>`~&Sm^|mB*2!pt#e>f&#hXD%!(RDECFfCHuvG-H~NF!f`C zb+{0`rJ%lcH=9DOjn#pOi^Z1PDF3;xaYo{vR3lZ?4j~bd<4loyDtzN2)K8MkAD7yE zO>+yS=WCuudcTi5HMo0uL1D*oDX4CL33`pI_FrC5(NRdPHA;b__P zkFP6wi?Q}neFYsx2mdnD(i&Dk%KddE{cX|oWnj@`x|vTwV}W@$B=YPPILn&@F4Ol2 z;(@$XE%J*T0jzx=DuLEJ%giS||FvsVKd@MyWDbk*XMGk?tu^=7b=ng&|<17JvaT);9@aO@nKvXfTzWW}BwohySJUkC=Udd5+PSq3LV zt|P^2Cb&4oQ><>89jd<7Z>01A+Ae8;^*cS|)gEx2gK*Mo4&a7yaBu`P;^38y1;A=V ztm1!w(qwGGk*8ZeW!dR84ZbO)bhnt&Gn5RGdw}Xo{c`sOO;SQBS`C-`X$LfqrOh8d zYQDvV606u)LMUVMo&9g9?+3>lktFz`2hNA0_2(x{lp^xzQ`>|mMR^Ac8WeJ3mwi&> zI%sXT`Ud@ez;Ky~PQ={5G=-`LiizjU0(LA$Z}{))_}F1q7ti%X>R~hcDiz1{Ou^4tw@E06V-Lda!1w z2h*f`7%|}Cq84DiaLyH6YCSYGh}mkdmK4$Hw+f04(ixn@^^6)BqASo>8IX;O zlSWm$#&nuy$#8#E!hX(08(95@(sIeB0zTtxgc(e=Zt3BFff^blCnxP;h zZ1Mmyg^}1_2-ivGTy_DSH3;rVrsP_~iq+PEBTyK8lbQxvh)H z1z@^afmPNL;imK1U`g|3aVX1kji0w~-M& zmEO)wh(8=ag@-vFCX7H;%RVljdG+}o#be3r;xy%ZoXo#+3;nSL1t{gXI~4>*LUg~0+<5w0k}ma`)xb!1N-=!+b5DJz+DB&!dYeh1`h`v4Z4@EFaagd-02e z_}^Z7tH)tPCg@g^G+Dn^LP=ak6ho=|B+aGZ;jl=-+gQq?WYbGKytLPQBjw|+n2`u1 zJ+Vp0H%OEGG*homTlAy^-++()cM*xW?d-0c{c@Y~VbI}``dI7H%zE?w^0dT?-^1nB zqtcy8``joP0@MI>Sp&iDpyxd~>$T&*F!9#!wo?q7E$f##`wds8ZGTk%E}09a`GMiq z7>s4t%m9=j_44xC2fD>OeSLkl_QNS>wmVu{Xuh;K5jkS3v)QQk^H-0O+w(TwKli0V z_9ptb8p5~jI5_^~XjIiUs8#a`_TA@_z&i;yV{mXI%wJi`w4AMn(=Z1EDTV7rj)!suNu+*71_48@;hw^=&lmZ~DgBs~>!ifmlugEi)UdtouA$e&daiI;tUych=Sf#XcG@?~eZV%h(xv(o}CW zQ;7V^m;vy*F$e(dx9lXp)-8(_y#MIP`fZsXua#GS2D$+~1A~d^23yw4m;W};j^-|+ zlP>4V?K+2*Bq1tlb?#&- zfMMByQ{~)HJ@G_=v$KA7Z{)l3S3%T8(hVA)fXeg`= zLZ{1+;?eZY(u9#PDeJ9}U?VfPWSaY?dmK0)c<~osl5TSiWVnx}WM+JG#YV9PMOZ2v zeq;R?D1QEs5DCahk8-+x>ooG^EJWIAfWgPuz{Ol?Y<%448YfKUCMjUm{v7?87X`hcNw3gd}BM54sPJ zs&0xZD__h3h5Xt+Sf9S82;CX)ax+!FW977N&0SnzTz;#s_eE4@+34sgjN8q&+D^A_ zz~Hu=WPp5se?J#6mPbc4cR??{ICN@1WlWF{+jguPFH9~+XnXt4M+X&@Sz>;Ollpp( zMz@K+BLNoWu6UdpZuofqC>O%W!{;u+?RvX~p@MjplZ2kL7GKz|4 zyFgl1x&}bq;>3h8`jA|>$$#J6ai{hkv-9?Sk|wIk!n(-T48!Hf_Iqs3f_UM4Uq(54 z0ns9W+0loU1cj}#Ghd!hFnYZV{AxaMR=JRtmk+$&Y#)4eSgo$G_E9m}-M~+l>q(w2 z_P8k)gqQ_D`#JyL@s=1s9{)lQD=Fx_ zA(__=m)*5kc@eknGJ1WNLP9s|#f#(F8x)Fv*8$Eym(+KC@%nY>esQLSd=s3ZxB^$6 zgRy_NoMW}k+_T6pO1H1h3c9vBW}4R=-8&6B%dEJi>1c$N$C7E0s+V%dn5>l^4wD)A z7_HNf@`L1h1H!*>GgIdpL2%sCe0+vxD*I=%-KBwmz&^Z6E#p`}gSZuqrnv zr`7jlZz&Amp|!^Vt)2OVhR&YeHvV_sk{D?sT}Q_i@JZRelUnFPaJTcJ?HiIu2QcV4 zcL&JvBlLRjX9WL(*kOzN?n1ZnER55lQ$M7UUYK=m?#ZQg4(Z{lR(zSD>9t@_Us~qh z%x&9^!icDf%E}(!4hy?T3#b%%>OxWYN)b-g51y<9$y~RNHH& z^UQ-C)o@{tTb%VZI)wiFR(dC<`}b#M z;`_8l0?S&DUfKBga~x;IH>RHoyzZ!QqHxwg&W(`e=_RO?~EeW7RX;F{-0~ zL*&>g;I|EvEs)$36K*sN&94pFkv!3QtGnU*jN3$Gl?YyPP zc3#AmuOJ@VU%GCY(<`fd+KujBRy<+2zd2)G#e5!KnYm6)ox-|ez^8WGOYHQghB%sU z!i>*S8`MfP<_C$8a+dNb(}Wh|#tfffwNTrKZXqgtW~sV&+kY4Y(*5S8?NdyOm;Pcy z5Ey6B_um7Cq~DDSlkFT;wRPdgI#tA$e&?o7Cx!b*o_@65DHDHQ(P|lEXQYW3SNDl) z;N||9bQ&Mf=Bj*rRBA_Adp5EiIsWv5%kgLbb1oS+$H{(@^TD0e6miqd#MPkKw(qn~ zE~%V96@_o@iwzO9uGD&~ehIwlm{T9(Ql6gv(I{5N#*ZubY@`2BYkkaTJy@N|j1yI! z%7?3WogELQ)A*Wx82#TX;=R{2Cv6R98Q&AIt$1j1xI+jFzN@ZW8Po`Lb*YpSW3a6k z_uRjK549`Ls;-R`om%va5%&ylBojwmIlTR|o^Lc(LeAWA@;_?FvCmwBzmMcgDNX09 zD*q$#7yqLvRvJ_7|CJgk-pq>C)}%D%?07e5a}u>oA@Gv0DPUb{vT^Su;pbaycKRh# zn~r{T!-rmZN8h6jH=?e_-D+)WBxiyuJ;|4N*I4QKOV2U+vOf;HzuwV(Hr95)6LH3R zE;DKfvzKbKf({yb!(5uH@1CuA72eIDOoET5Z|-;dF!q~XzXQuy*aVOwK7Wh-j3TncE`)nyYj96 z+5_B@L0v)uQ{BYpuaVnF!ao;rO$8r^Da;dTx~K|2Y|Ie;J+_}}UTQhgcwk<5c2{uo zMMh`0-^mVMab(#oSFnN`^!4zIjq2n>Q3Gp77z?@YxG{ zu4P2=*p=9&ef3MfGDEqiZ4~&Zb&Rydv(j2eIIk#7>`&3*GnI~4xoIphQn-$l@?R&_ zNzPq{um6a+H3pnEAwHQ9+HL|rfHu3FUqI&DDd58DcD|KkG3M@atU|F=#C@=M<=|-7PBfWPEss5}!iR4sm_Wpb3 z2FdRN9tp*s>;tT;&6FFY{0){ZB@BY8!q=@PwZ@EC-y0GbVmY#{2M0c~d&6_2F7bV2 zelE80zD8Kmko}Z$-=Q#Bo8dp|!R0-v!N&N};$g47mpph_-%R|o?gVPfzm{5YoZ)gU zNB3Q%FF79l@gC6@WgYNZ4QOVZdZ!s9yWbV=Q+aP_={a4tqwuW&hcl4-SBWKFUFvi_Pyu&kUss$)dAz_xf~Y}9X6)QixUAd>_=AooYp(>HlP ziAQ>GCo=vhP^YnOdMP}8Fo;WNw)t6R)>vwTue^oAz}bi{onTT1afEqDh4VEH)o4D% zb4f^mF#PK$y}H#<$DWM!#gQ}f{~ny>774TD5v9TL`^)o*FNH*DqBK;wwkm!xm`l+} zO4gf`XLDn-w5M763K_aM?O&G9#<1>r6!ORXt@oq7h7s$p-tF9}<_THa0z54DwGrbB zwl|#L77xZQt{Q1<=DT<;;-Xx`L4hJj1ZS07<4LvfvT`S_H)$M;>omxVbjJ}oj*S-!eERb_%*KI`0pV0}B0 ztm`eN!kgChy03{!pSNHP*H~7m)f6^F7Y;{RPc^5HY&AEQ`yIENj7MN&Tb_>nJp$9#r#XuZ)&SnsaQq+KijxMGXMYp literal 0 HcmV?d00001 diff --git a/packages/frontend/src/pages/mahjong/hand-tiles.vue b/packages/frontend/src/pages/mahjong/hand-tiles.vue index ebfb6e8cc1..81ad21b1b2 100644 --- a/packages/frontend/src/pages/mahjong/hand-tiles.vue +++ b/packages/frontend/src/pages/mahjong/hand-tiles.vue @@ -40,12 +40,12 @@ import { computed } from 'vue'; import * as Mmj from 'misskey-mahjong'; //#region syntax suger -function mj$(tileId: Mmj.TileId): Mmj.TileInstance { - return Mmj.findTileByIdOrFail(tileId); +function mj$(tid: Mmj.TileId): Mmj.TileInstance { + return Mmj.findTileByIdOrFail(tid); } -function mj$type(tileId: Mmj.TileId): Mmj.TileType { - return mj$(tileId).t; +function mj$type(tid: Mmj.TileId): Mmj.TileType { + return mj$(tid).t; } //#endregion diff --git a/packages/frontend/src/pages/mahjong/room.game.vue b/packages/frontend/src/pages/mahjong/room.game.vue index 2f8b7af8cb..f51d192a0d 100644 --- a/packages/frontend/src/pages/mahjong/room.game.vue +++ b/packages/frontend/src/pages/mahjong/room.game.vue @@ -168,6 +168,17 @@ SPDX-License-Identifier: AGPL-3.0-only +

+ + + +
+
{{ res.pointDeltas.e }} / {{ res.pointDeltas.s }} / {{ res.pointDeltas.w }} / {{ res.pointDeltas.n }}
+ OK @@ -235,12 +247,12 @@ import * as os from '@/os.js'; import { confetti } from '@/scripts/confetti.js'; //#region syntax suger -function mj$(tileId: Mmj.TileId): Mmj.TileInstance { - return Mmj.findTileByIdOrFail(tileId); +function mj$(tid: Mmj.TileId): Mmj.TileInstance { + return Mmj.findTileByIdOrFail(tid); } -function mj$type(tileId: Mmj.TileId): Mmj.TileType { - return mj$(tileId).t; +function mj$type(tid: Mmj.TileId): Mmj.TileType { + return mj$(tid).t; } //#endregion @@ -256,11 +268,11 @@ const myUserNumber = computed(() => room.value.user1Id === $i.id ? 1 : room.valu const mj = shallowRef(new Mmj.PlayerGameEngine(myUserNumber.value, room.value.gameState)); const isMyTurn = computed(() => { - return mj.value.state.turn === mj.value.myHouse; + return mj.value.turn === mj.value.myHouse; }); const canHora = computed(() => { - return Mmj.getHoraSets(mj.value.myHandTiles).length > 0; + return Mmj.getHoraSets(mj.value.myHandTileTypes).length > 0; }); const selectableTiles = ref(null); @@ -286,6 +298,7 @@ const kyokuResults = ref { + ronSerifHouses[caller] = false; + }, 2000); } console.log('ronned', res); @@ -620,6 +641,9 @@ function onStreamTsumoHora(log) { }, 1500); tsumoSerifHouses[log.house] = true; + window.setTimeout(() => { + tsumoSerifHouses[log.house] = false; + }, 2000); console.log('tsumohora', res); } @@ -634,6 +658,23 @@ function onStreamRyuukyoku(log) { }, 1500); } +function onStreamNextKyoku(log) { + console.log('onStreamNextKyoku', log); + + const res = mj.value.commit_nextKyoku(log.state); + triggerRef(mj); + + iTsumoed.value = false; + showKyokuResults.value = false; + kyokuResults.value = { + e: null, + s: null, + w: null, + n: null, + }; + ryuukyokued.value = false; +} + function restoreRoom(_room) { room.value = deepClone(_room); @@ -653,6 +694,7 @@ onMounted(() => { props.connection.on('ronned', onStreamRonned); props.connection.on('tsumoHora', onStreamTsumoHora); props.connection.on('ryuukyoku', onStreamRyuukyoku); + props.connection.on('nextKyoku', onStreamNextKyoku); } }); @@ -669,6 +711,7 @@ onActivated(() => { props.connection.on('ronned', onStreamRonned); props.connection.on('tsumoHora', onStreamTsumoHora); props.connection.on('ryuukyoku', onStreamRyuukyoku); + props.connection.on('nextKyoku', onStreamNextKyoku); } }); @@ -685,6 +728,7 @@ onDeactivated(() => { props.connection.off('ronned', onStreamRonned); props.connection.off('tsumoHora', onStreamTsumoHora); props.connection.off('ryuukyoku', onStreamRyuukyoku); + props.connection.off('nextKyoku', onStreamNextKyoku); } }); @@ -701,6 +745,7 @@ onUnmounted(() => { props.connection.off('ronned', onStreamRonned); props.connection.off('tsumoHora', onStreamTsumoHora); props.connection.off('ryuukyoku', onStreamRyuukyoku); + props.connection.off('nextKyoku', onStreamNextKyoku); } }); diff --git a/packages/misskey-mahjong/src/common.ts b/packages/misskey-mahjong/src/common.ts index cb88faa8d2..52d6421750 100644 --- a/packages/misskey-mahjong/src/common.ts +++ b/packages/misskey-mahjong/src/common.ts @@ -92,14 +92,14 @@ export const TILE_ID_MAP = new Map([ /* eslint-enable no-multi-spaces */ ]); -export function findTileByIdOrFail(tileId: TileId): TileInstance { - const tile = TILE_ID_MAP.get(tileId); - if (tile == null) throw new Error(`tile not found: ${tileId}`); +export function findTileByIdOrFail(tid: TileId): TileInstance { + const tile = TILE_ID_MAP.get(tid); + if (tile == null) throw new Error(`tile not found: ${tid}`); return tile; } -export function findTileById(tileId: TileId): TileInstance | null { - return TILE_ID_MAP.get(tileId) ?? null; +export function findTileById(tid: TileId): TileInstance | null { + return TILE_ID_MAP.get(tid) ?? null; } export type House = 'e' | 's' | 'w' | 'n'; @@ -300,6 +300,13 @@ export const YAKU_DEFINITIONS = [{ calc: (state: EnvForCalcYaku) => { return state.tsumoTile != null; }, +}, { + name: 'ippatsu', + fan: 1, + isYakuman: false, + calc: (state: EnvForCalcYaku) => { + + }, }, { name: 'red', fan: 1, diff --git a/packages/misskey-mahjong/src/engine.master.ts b/packages/misskey-mahjong/src/engine.master.ts index 8361aaf34f..3e2025cb75 100644 --- a/packages/misskey-mahjong/src/engine.master.ts +++ b/packages/misskey-mahjong/src/engine.master.ts @@ -9,12 +9,12 @@ import * as Common from './common.js'; import { PlayerState } from './engine.player.js'; //#region syntax suger -function $(tileId: TileId): Common.TileInstance { - return Common.findTileByIdOrFail(tileId); +function $(tid: TileId): Common.TileInstance { + return Common.findTileByIdOrFail(tid); } -function $type(tileId: TileId): TileType { - return $(tileId).t; +function $type(tid: TileId): TileType { + return $(tid).t; } //#endregion @@ -26,7 +26,7 @@ export type MasterState = { round: 'e' | 's' | 'w' | 'n'; kyoku: number; - + turnCount: number; tiles: TileId[]; kingTiles: TileId[]; activatedDorasCount: number; @@ -59,6 +59,12 @@ export type MasterState = { w: boolean; n: boolean; }; + ippatsus: { + e: boolean; + s: boolean; + w: boolean; + n: boolean; + }; points: { e: number; s: number; @@ -176,6 +182,10 @@ export class MasterGameEngine { return this.state.user4House; } + public get turn(): House | null { + return this.state.turn; + } + public static createInitialState(): MasterState { const ikasama: TileId[] = [125, 129, 9, 56, 57, 61, 77, 81, 85, 133, 134, 135, 121, 122]; @@ -201,6 +211,7 @@ export class MasterGameEngine { user4House: 'n', round: 'e', kyoku: 1, + turnCount: 0, tiles, kingTiles, activatedDorasCount: 1, @@ -253,12 +264,12 @@ export class MasterGameEngine { return tile; } - private canRon(house: House, tileId: TileId): boolean { + private canRon(house: House, tid: TileId): boolean { // フリテン // TODO: ポンされるなどして自分の河にない場合の考慮 - if (this.hoTileTypes[house].includes($type(tileId))) return false; + if (this.hoTileTypes[house].includes($type(tid))) return false; - const horaSets = Common.getHoraSets(this.handTileTypes[house].concat($type(tileId))); + const horaSets = Common.getHoraSets(this.handTileTypes[house].concat($type(tid))); if (horaSets.length === 0) return false; // 完成形じゃない // TODO @@ -268,15 +279,19 @@ export class MasterGameEngine { return true; } - private canPon(house: House, tileId: TileId): boolean { - return this.handTileTypes[house].filter(t => t === $type(tileId)).length === 2; + private canPon(house: House, tid: TileId): boolean { + return this.handTileTypes[house].filter(t => t === $type(tid)).length === 2; } - private canCii(caller: House, callee: House, tileId: TileId): boolean { + private canDaiminkan(caller: House, tid: TileId): boolean { + return this.handTileTypes[caller].filter(t => t === $type(tid)).length === 3; + } + + private canCii(caller: House, callee: House, tid: TileId): boolean { if (callee !== Common.prevHouse(caller)) return false; const hand = this.handTileTypes[caller]; return Common.SHUNTU_PATTERNS.some(pattern => - pattern.includes($type(tileId)) && + pattern.includes($type(tid)) && pattern.filter(t => hand.includes(t)).length >= 2); } @@ -325,68 +340,104 @@ export class MasterGameEngine { this.endKyoku(); } - public commit_dahai(house: House, tileId: TileId, riichi = false) { + public startTransaction() { + const newState = structuredClone(this.state); + return { + state: newState, + commit: () => { + this.state = newState; + }, + }; + } + + public commit_nextKyoku() { + const newState = MasterGameEngine.createInitialState(); + newState.kyoku = this.state.kyoku + 1; + newState.points = this.state.points; + newState.turn = 'e'; + newState.user1House = Common.nextHouse(this.state.user1House); + newState.user2House = Common.nextHouse(this.state.user2House); + newState.user3House = Common.nextHouse(this.state.user3House); + newState.user4House = Common.nextHouse(this.state.user4House); + this.state = newState; + } + + public commit_dahai(house: House, tid: TileId, riichi = false) { + const { state, commit } = this.startTransaction(); + if (this.state.turn !== house) throw new Error('Not your turn'); if (riichi) { + if (this.state.riichis[house]) throw new Error('Already riichi'); const tempHandTiles = [...this.handTileTypes[house]]; - tempHandTiles.splice(tempHandTiles.indexOf($type(tileId)), 1); + tempHandTiles.splice(tempHandTiles.indexOf($type(tid)), 1); if (Common.getHoraTiles(tempHandTiles).length === 0) throw new Error('Not tenpai'); if (this.state.points[house] < 1000) throw new Error('Not enough points'); } const handTiles = this.state.handTiles[house]; - if (!handTiles.includes(tileId)) throw new Error('No such tile in your hand'); - handTiles.splice(handTiles.indexOf(tileId), 1); - this.state.hoTiles[house].push(tileId); + if (!handTiles.includes(tid)) throw new Error('No such tile in your hand'); + handTiles.splice(handTiles.indexOf(tid), 1); + this.state.hoTiles[house].push(tid); + + if (this.state.riichis[house]) { + this.state.ippatsus[house] = false; + } if (riichi) { this.state.riichis[house] = true; + this.state.ippatsus[house] = true; } const canRonHouses: House[] = []; switch (house) { case 'e': - if (this.canRon('s', tileId)) canRonHouses.push('s'); - if (this.canRon('w', tileId)) canRonHouses.push('w'); - if (this.canRon('n', tileId)) canRonHouses.push('n'); + if (this.canRon('s', tid)) canRonHouses.push('s'); + if (this.canRon('w', tid)) canRonHouses.push('w'); + if (this.canRon('n', tid)) canRonHouses.push('n'); break; case 's': - if (this.canRon('e', tileId)) canRonHouses.push('e'); - if (this.canRon('w', tileId)) canRonHouses.push('w'); - if (this.canRon('n', tileId)) canRonHouses.push('n'); + if (this.canRon('e', tid)) canRonHouses.push('e'); + if (this.canRon('w', tid)) canRonHouses.push('w'); + if (this.canRon('n', tid)) canRonHouses.push('n'); break; case 'w': - if (this.canRon('e', tileId)) canRonHouses.push('e'); - if (this.canRon('s', tileId)) canRonHouses.push('s'); - if (this.canRon('n', tileId)) canRonHouses.push('n'); + if (this.canRon('e', tid)) canRonHouses.push('e'); + if (this.canRon('s', tid)) canRonHouses.push('s'); + if (this.canRon('n', tid)) canRonHouses.push('n'); break; case 'n': - if (this.canRon('e', tileId)) canRonHouses.push('e'); - if (this.canRon('s', tileId)) canRonHouses.push('s'); - if (this.canRon('w', tileId)) canRonHouses.push('w'); + if (this.canRon('e', tid)) canRonHouses.push('e'); + if (this.canRon('s', tid)) canRonHouses.push('s'); + if (this.canRon('w', tid)) canRonHouses.push('w'); break; } - const canKanHouse: House | null = null; + let canKanHouse: House | null = null; + switch (house) { + case 'e': canKanHouse = this.canDaiminkan('s', tid) ? 's' : this.canDaiminkan('w', tid) ? 'w' : this.canDaiminkan('n', tid) ? 'n' : null; break; + case 's': canKanHouse = this.canDaiminkan('e', tid) ? 'e' : this.canDaiminkan('w', tid) ? 'w' : this.canDaiminkan('n', tid) ? 'n' : null; break; + case 'w': canKanHouse = this.canDaiminkan('e', tid) ? 'e' : this.canDaiminkan('s', tid) ? 's' : this.canDaiminkan('n', tid) ? 'n' : null; break; + case 'n': canKanHouse = this.canDaiminkan('e', tid) ? 'e' : this.canDaiminkan('s', tid) ? 's' : this.canDaiminkan('w', tid) ? 'w' : null; break; + } let canPonHouse: House | null = null; switch (house) { - case 'e': canPonHouse = this.canPon('s', tileId) ? 's' : this.canPon('w', tileId) ? 'w' : this.canPon('n', tileId) ? 'n' : null; break; - case 's': canPonHouse = this.canPon('e', tileId) ? 'e' : this.canPon('w', tileId) ? 'w' : this.canPon('n', tileId) ? 'n' : null; break; - case 'w': canPonHouse = this.canPon('e', tileId) ? 'e' : this.canPon('s', tileId) ? 's' : this.canPon('n', tileId) ? 'n' : null; break; - case 'n': canPonHouse = this.canPon('e', tileId) ? 'e' : this.canPon('s', tileId) ? 's' : this.canPon('w', tileId) ? 'w' : null; break; + case 'e': canPonHouse = this.canPon('s', tid) ? 's' : this.canPon('w', tid) ? 'w' : this.canPon('n', tid) ? 'n' : null; break; + case 's': canPonHouse = this.canPon('e', tid) ? 'e' : this.canPon('w', tid) ? 'w' : this.canPon('n', tid) ? 'n' : null; break; + case 'w': canPonHouse = this.canPon('e', tid) ? 'e' : this.canPon('s', tid) ? 's' : this.canPon('n', tid) ? 'n' : null; break; + case 'n': canPonHouse = this.canPon('e', tid) ? 'e' : this.canPon('s', tid) ? 's' : this.canPon('w', tid) ? 'w' : null; break; } let canCiiHouse: House | null = null; switch (house) { - case 'e': canCiiHouse = this.canCii('s', house, tileId) ? 's' : this.canCii('w', house, tileId) ? 'w' : this.canCii('n', house, tileId) ? 'n' : null; break; - case 's': canCiiHouse = this.canCii('e', house, tileId) ? 'e' : this.canCii('w', house, tileId) ? 'w' : this.canCii('n', house, tileId) ? 'n' : null; break; - case 'w': canCiiHouse = this.canCii('e', house, tileId) ? 'e' : this.canCii('s', house, tileId) ? 's' : this.canCii('n', house, tileId) ? 'n' : null; break; - case 'n': canCiiHouse = this.canCii('e', house, tileId) ? 'e' : this.canCii('s', house, tileId) ? 's' : this.canCii('w', house, tileId) ? 'w' : null; break; + case 'e': canCiiHouse = this.canCii('s', house, tid) ? 's' : this.canCii('w', house, tid) ? 'w' : this.canCii('n', house, tid) ? 'n' : null; break; + case 's': canCiiHouse = this.canCii('e', house, tid) ? 'e' : this.canCii('w', house, tid) ? 'w' : this.canCii('n', house, tid) ? 'n' : null; break; + case 'w': canCiiHouse = this.canCii('e', house, tid) ? 'e' : this.canCii('s', house, tid) ? 's' : this.canCii('n', house, tid) ? 'n' : null; break; + case 'n': canCiiHouse = this.canCii('e', house, tid) ? 'e' : this.canCii('s', house, tid) ? 's' : this.canCii('w', house, tid) ? 'w' : null; break; } - if (canRonHouses.length > 0 || canPonHouse != null || canCiiHouse != null) { + if (canRonHouses.length > 0 || canKanHouse != null || canPonHouse != null || canCiiHouse != null) { if (canRonHouses.length > 0) { this.state.askings.ron = { callee: house, @@ -445,13 +496,18 @@ export class MasterGameEngine { }; } - public commit_kakan(house: House, tileId: TileId) { - const pon = this.state.huros[house].find(h => h.type === 'pon' && $type(h.tiles[0]) === $type(tileId)); + public commit_kakan(house: House, tid: TileId) { + const pon = this.state.huros[house].find(h => h.type === 'pon' && $type(h.tiles[0]) === $type(tid)); if (pon == null) throw new Error('No such pon'); - this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(tileId), 1); - const tiles = [tileId, ...pon.tiles]; + this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(tid), 1); + const tiles = [tid, ...pon.tiles]; this.state.huros[house].push({ type: 'minkan', tiles: tiles, from: pon.from }); + this.state.ippatsus.e = false; + this.state.ippatsus.s = false; + this.state.ippatsus.w = false; + this.state.ippatsus.n = false; + this.state.activatedDorasCount++; const rinsyan = this.tsumo(); @@ -463,14 +519,14 @@ export class MasterGameEngine { }; } - public commit_ankan(house: House, tileId: TileId) { - const t1 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(0); + public commit_ankan(house: House, tid: TileId) { + const t1 = this.state.handTiles[house].filter(t => $type(t) === $type(tid)).at(0); if (t1 == null) throw new Error('No such tile'); - const t2 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(1); + const t2 = this.state.handTiles[house].filter(t => $type(t) === $type(tid)).at(1); if (t2 == null) throw new Error('No such tile'); - const t3 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(2); + const t3 = this.state.handTiles[house].filter(t => $type(t) === $type(tid)).at(2); if (t3 == null) throw new Error('No such tile'); - const t4 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(3); + const t4 = this.state.handTiles[house].filter(t => $type(t) === $type(tid)).at(3); if (t4 == null) throw new Error('No such tile'); this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(t1), 1); this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(t2), 1); @@ -479,6 +535,11 @@ export class MasterGameEngine { const tiles = [t1, t2, t3, t4]; this.state.huros[house].push({ type: 'ankan', tiles: tiles }); + this.state.ippatsus.e = false; + this.state.ippatsus.s = false; + this.state.ippatsus.w = false; + this.state.ippatsus.n = false; + this.state.activatedDorasCount++; const rinsyan = this.tsumo(); @@ -567,6 +628,11 @@ export class MasterGameEngine { const tiles = [tile, t1, t2, t3]; this.state.huros[kan.caller].push({ type: 'minkan', tiles: tiles, from: kan.callee }); + this.state.ippatsus.e = false; + this.state.ippatsus.s = false; + this.state.ippatsus.w = false; + this.state.ippatsus.n = false; + this.state.activatedDorasCount++; const rinsyan = this.tsumo(); @@ -594,6 +660,11 @@ export class MasterGameEngine { const tiles = [tile, t1, t2]; this.state.huros[pon.caller].push({ type: 'pon', tiles: tiles, from: pon.callee }); + this.state.ippatsus.e = false; + this.state.ippatsus.s = false; + this.state.ippatsus.w = false; + this.state.ippatsus.n = false; + this.state.turn = pon.caller; return { @@ -654,6 +725,11 @@ export class MasterGameEngine { this.state.huros[cii.caller].push({ type: 'cii', tiles: tiles, from: cii.callee }); + this.state.ippatsus.e = false; + this.state.ippatsus.s = false; + this.state.ippatsus.w = false; + this.state.ippatsus.n = false; + this.state.turn = cii.caller; return { @@ -699,6 +775,7 @@ export class MasterGameEngine { user4House: this.state.user4House, round: this.state.round, kyoku: this.state.kyoku, + turnCount: this.state.turnCount, tilesCount: this.state.tiles.length, doraIndicateTiles: this.state.kingTiles.slice(0, this.state.activatedDorasCount), handTiles: { @@ -756,3 +833,7 @@ export class MasterGameEngine { return structuredClone(this.state); } } + +function commit_dahai(state: MasterState): MasterState { + +} diff --git a/packages/misskey-mahjong/src/engine.player.ts b/packages/misskey-mahjong/src/engine.player.ts index f2ba137eff..d88e43df38 100644 --- a/packages/misskey-mahjong/src/engine.player.ts +++ b/packages/misskey-mahjong/src/engine.player.ts @@ -8,12 +8,12 @@ import { TileType, House, Huro, TileId, YAKU_DEFINITIONS } from './common.js'; import * as Common from './common.js'; //#region syntax suger -function $(tileId: TileId): Common.TileInstance { - return Common.findTileByIdOrFail(tileId); +function $(tid: TileId): Common.TileInstance { + return Common.findTileByIdOrFail(tid); } -function $type(tileId: TileId): TileType { - return $(tileId).t; +function $type(tid: TileId): TileType { + return $(tid).t; } //#endregion @@ -26,6 +26,7 @@ export type PlayerState = { round: 'e' | 's' | 'w' | 'n'; kyoku: number; + turnCount: number; tilesCount: number; doraIndicateTiles: TileId[]; @@ -111,6 +112,10 @@ export class PlayerGameEngine { return this.state.huros; } + public get turnCount(): number { + return this.state.turnCount; + } + public get tilesCount(): number { return this.state.tilesCount; } @@ -131,6 +136,26 @@ export class PlayerGameEngine { return this.state.canCii; } + public get turn(): House | null { + return this.state.turn; + } + + public get user1House(): House { + return this.state.user1House; + } + + public get user2House(): House { + return this.state.user2House; + } + + public get user3House(): House { + return this.state.user3House; + } + + public get user4House(): House { + return this.state.user4House; + } + public get myHouse(): House { switch (this.myUserNumber) { case 1: return this.state.user1House; @@ -152,19 +177,23 @@ export class PlayerGameEngine { return this.state.riichis[this.myHouse]; } - public commit_tsumo(house: House, tileId: TileId) { - console.log('commit_tsumo', this.state.turn, house, tileId); + public commit_nextKyoku(state: PlayerState) { + this.state = state; + } + + public commit_tsumo(house: House, tid: TileId) { + console.log('commit_tsumo', this.state.turn, house, tid); this.state.tilesCount--; this.state.turn = house; if (house === this.myHouse) { - this.myHandTiles.push(tileId); + this.myHandTiles.push(tid); } else { this.state.handTiles[house].push(0); } } - public commit_dahai(house: House, tileId: TileId, riichi = false) { - console.log('commit_dahai', this.state.turn, house, tileId, riichi); + public commit_dahai(house: House, tid: TileId, riichi = false) { + console.log('commit_dahai', this.state.turn, house, tid, riichi); if (this.state.turn !== house) throw new PlayerGameEngine.InvalidOperationError(); if (riichi) { @@ -172,23 +201,23 @@ export class PlayerGameEngine { } if (house === this.myHouse) { - this.myHandTiles.splice(this.myHandTiles.indexOf(tileId), 1); - this.state.hoTiles[this.myHouse].push(tileId); + this.myHandTiles.splice(this.myHandTiles.indexOf(tid), 1); + this.state.hoTiles[this.myHouse].push(tid); } else { this.state.handTiles[house].pop(); - this.state.hoTiles[house].push(tileId); + this.state.hoTiles[house].push(tid); } this.state.turn = null; if (house === this.myHouse) { } else { - const canRon = Common.getHoraSets(this.myHandTiles.concat(tileId).map(id => $type(id))).length > 0; - const canPon = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tileId)).length === 2; - const canKan = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tileId)).length === 3; + const canRon = Common.getHoraSets(this.myHandTiles.concat(tid).map(id => $type(id))).length > 0; + const canPon = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tid)).length === 2; + const canKan = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tid)).length === 3; const canCii = !this.isMeRiichi && house === Common.prevHouse(this.myHouse) && Common.SHUNTU_PATTERNS.some(pattern => - pattern.includes($type(tileId)) && + pattern.includes($type(tid)) && pattern.filter(t => this.myHandTileTypes.includes(t)).length >= 2); this.state.canRon = canRon ? { callee: house } : null;