wip
This commit is contained in:
parent
2dd886e285
commit
586a458c7a
12 changed files with 424 additions and 149 deletions
210
locales/index.d.ts
vendored
210
locales/index.d.ts
vendored
|
@ -9649,6 +9649,216 @@ export interface Locale extends ILocale {
|
|||
* 北
|
||||
*/
|
||||
"north": string;
|
||||
/**
|
||||
* ドラ
|
||||
*/
|
||||
"dora": string;
|
||||
/**
|
||||
* 赤ドラ
|
||||
*/
|
||||
"redDora": string;
|
||||
/**
|
||||
* 飜
|
||||
*/
|
||||
"fan": string;
|
||||
"_yakus": {
|
||||
/**
|
||||
* 立直
|
||||
*/
|
||||
"riichi": string;
|
||||
/**
|
||||
* 一発
|
||||
*/
|
||||
"ippatsu": string;
|
||||
/**
|
||||
* 門前清自摸和
|
||||
*/
|
||||
"tsumo": string;
|
||||
/**
|
||||
* 断么
|
||||
*/
|
||||
"tanyao": string;
|
||||
/**
|
||||
* 平和
|
||||
*/
|
||||
"pinfu": string;
|
||||
/**
|
||||
* 一盃口
|
||||
*/
|
||||
"iipeko": string;
|
||||
/**
|
||||
* 東
|
||||
*/
|
||||
"field-wind-e": string;
|
||||
/**
|
||||
* 南
|
||||
*/
|
||||
"field-wind-s": string;
|
||||
/**
|
||||
* 東
|
||||
*/
|
||||
"seat-wind-e": string;
|
||||
/**
|
||||
* 南
|
||||
*/
|
||||
"seat-wind-s": string;
|
||||
/**
|
||||
* 西
|
||||
*/
|
||||
"seat-wind-w": string;
|
||||
/**
|
||||
* 北
|
||||
*/
|
||||
"seat-wind-n": string;
|
||||
/**
|
||||
* 白
|
||||
*/
|
||||
"white": string;
|
||||
/**
|
||||
* 發
|
||||
*/
|
||||
"green": string;
|
||||
/**
|
||||
* 中
|
||||
*/
|
||||
"red": string;
|
||||
/**
|
||||
* 嶺上開花
|
||||
*/
|
||||
"rinshan": string;
|
||||
/**
|
||||
* 搶槓
|
||||
*/
|
||||
"chankan": string;
|
||||
/**
|
||||
* 海底摸月
|
||||
*/
|
||||
"haitei": string;
|
||||
/**
|
||||
* 河底撈魚
|
||||
*/
|
||||
"hotei": string;
|
||||
/**
|
||||
* 三色同順
|
||||
*/
|
||||
"sanshoku-dojun": string;
|
||||
/**
|
||||
* 三色同刻
|
||||
*/
|
||||
"sanshoku-doko": string;
|
||||
/**
|
||||
* 一気通貫
|
||||
*/
|
||||
"ittsu": string;
|
||||
/**
|
||||
* 混全帯么九
|
||||
*/
|
||||
"chanta": string;
|
||||
/**
|
||||
* 七対子
|
||||
*/
|
||||
"chitoitsu": string;
|
||||
/**
|
||||
* 対々
|
||||
*/
|
||||
"toitoi": string;
|
||||
/**
|
||||
* 三暗刻
|
||||
*/
|
||||
"sananko": string;
|
||||
/**
|
||||
* 混老頭
|
||||
*/
|
||||
"honroto": string;
|
||||
/**
|
||||
* 三槓子
|
||||
*/
|
||||
"sankantsu": string;
|
||||
/**
|
||||
* 小三元
|
||||
*/
|
||||
"shosangen": string;
|
||||
/**
|
||||
* ダブル立直
|
||||
*/
|
||||
"double-riichi": string;
|
||||
/**
|
||||
* 混一色
|
||||
*/
|
||||
"honitsu": string;
|
||||
/**
|
||||
* 清全帯么九
|
||||
*/
|
||||
"junchan": string;
|
||||
/**
|
||||
* ニ盃口
|
||||
*/
|
||||
"ryampeko": string;
|
||||
/**
|
||||
* 清一色
|
||||
*/
|
||||
"chinitsu": string;
|
||||
/**
|
||||
* 国士無双
|
||||
*/
|
||||
"kokushi": string;
|
||||
/**
|
||||
* 国士無双13面待ち
|
||||
*/
|
||||
"kokushi-13": string;
|
||||
/**
|
||||
* 四暗刻
|
||||
*/
|
||||
"suanko": string;
|
||||
/**
|
||||
* 四暗刻単騎待ち
|
||||
*/
|
||||
"suanko-tanki": string;
|
||||
/**
|
||||
* 大三元
|
||||
*/
|
||||
"daisangen": string;
|
||||
/**
|
||||
* 字一色
|
||||
*/
|
||||
"tsuiso": string;
|
||||
/**
|
||||
* 小四喜
|
||||
*/
|
||||
"shosushi": string;
|
||||
/**
|
||||
* 大四喜
|
||||
*/
|
||||
"daisushi": string;
|
||||
/**
|
||||
* 緑一色
|
||||
*/
|
||||
"ryuiso": string;
|
||||
/**
|
||||
* 清老頭
|
||||
*/
|
||||
"chinroto": string;
|
||||
/**
|
||||
* 四槓子
|
||||
*/
|
||||
"sukantsu": string;
|
||||
/**
|
||||
* 九蓮宝燈
|
||||
*/
|
||||
"churen": string;
|
||||
/**
|
||||
* 純正九連宝灯
|
||||
*/
|
||||
"pure-churen": string;
|
||||
/**
|
||||
* 天和
|
||||
*/
|
||||
"tenho": string;
|
||||
/**
|
||||
* 地和
|
||||
*/
|
||||
"chiho": string;
|
||||
};
|
||||
};
|
||||
"_offlineScreen": {
|
||||
/**
|
||||
|
|
|
@ -2571,6 +2571,59 @@ _mahjong:
|
|||
south: "南"
|
||||
west: "西"
|
||||
north: "北"
|
||||
dora: "ドラ"
|
||||
redDora: "赤ドラ"
|
||||
fan: "飜"
|
||||
_yakus:
|
||||
"riichi": "立直"
|
||||
"ippatsu": "一発"
|
||||
"tsumo": "門前清自摸和"
|
||||
"tanyao": "断么"
|
||||
"pinfu": "平和"
|
||||
"iipeko": "一盃口"
|
||||
"field-wind-e": "東"
|
||||
"field-wind-s": "南"
|
||||
"seat-wind-e": "東"
|
||||
"seat-wind-s": "南"
|
||||
"seat-wind-w": "西"
|
||||
"seat-wind-n": "北"
|
||||
"white": "白"
|
||||
"green": "發"
|
||||
"red": "中"
|
||||
"rinshan": "嶺上開花"
|
||||
"chankan": "搶槓"
|
||||
"haitei": "海底摸月"
|
||||
"hotei": "河底撈魚"
|
||||
"sanshoku-dojun": "三色同順"
|
||||
"sanshoku-doko": "三色同刻"
|
||||
"ittsu": "一気通貫"
|
||||
"chanta": "混全帯么九"
|
||||
"chitoitsu": "七対子"
|
||||
"toitoi": "対々"
|
||||
"sananko": "三暗刻"
|
||||
"honroto": "混老頭"
|
||||
"sankantsu": "三槓子"
|
||||
"shosangen": "小三元"
|
||||
"double-riichi": "ダブル立直"
|
||||
"honitsu": "混一色"
|
||||
"junchan": "清全帯么九"
|
||||
"ryampeko": "ニ盃口"
|
||||
"chinitsu": "清一色"
|
||||
"kokushi": "国士無双"
|
||||
"kokushi-13": "国士無双13面待ち"
|
||||
"suanko": "四暗刻"
|
||||
"suanko-tanki": "四暗刻単騎待ち"
|
||||
"daisangen": "大三元"
|
||||
"tsuiso": "字一色"
|
||||
"shosushi": "小四喜"
|
||||
"daisushi": "大四喜"
|
||||
"ryuiso": "緑一色"
|
||||
"chinroto": "清老頭"
|
||||
"sukantsu": "四槓子"
|
||||
"churen": "九蓮宝燈"
|
||||
"pure-churen": "純正九連宝灯"
|
||||
"tenho": "天和"
|
||||
"chiho": "地和"
|
||||
|
||||
_offlineScreen:
|
||||
title: "オフライン - サーバーに接続できません"
|
||||
|
|
|
@ -209,30 +209,30 @@ export interface MahjongRoomEventTypes {
|
|||
room: Packed<'MahjongRoomDetailed'>;
|
||||
};
|
||||
tsumo: {
|
||||
house: Mahjong.Common.House;
|
||||
tile: Mahjong.Common.Tile;
|
||||
house: Mahjong.House;
|
||||
tile: Mahjong.Tile;
|
||||
};
|
||||
dahai: {
|
||||
house: Mahjong.Common.House;
|
||||
tile: Mahjong.Common.Tile;
|
||||
house: Mahjong.House;
|
||||
tile: Mahjong.Tile;
|
||||
riichi: boolean;
|
||||
};
|
||||
dahaiAndTsumo: {
|
||||
dahaiHouse: Mahjong.Common.House;
|
||||
dahaiTile: Mahjong.Common.Tile;
|
||||
tsumoTile: Mahjong.Common.Tile;
|
||||
dahaiHouse: Mahjong.House;
|
||||
dahaiTile: Mahjong.Tile;
|
||||
tsumoTile: Mahjong.Tile;
|
||||
riichi: boolean;
|
||||
};
|
||||
ponned: {
|
||||
caller: Mahjong.Common.House;
|
||||
callee: Mahjong.Common.House;
|
||||
tile: Mahjong.Common.Tile;
|
||||
caller: Mahjong.House;
|
||||
callee: Mahjong.House;
|
||||
tile: Mahjong.Tile;
|
||||
};
|
||||
kanned: {
|
||||
caller: Mahjong.Common.House;
|
||||
callee: Mahjong.Common.House;
|
||||
tile: Mahjong.Common.Tile;
|
||||
rinsyan: Mahjong.Common.Tile;
|
||||
caller: Mahjong.House;
|
||||
callee: Mahjong.House;
|
||||
tile: Mahjong.Tile;
|
||||
rinsyan: Mahjong.Tile;
|
||||
};
|
||||
ronned: {
|
||||
};
|
||||
|
|
|
@ -77,11 +77,11 @@ type NextKyokuConfirmation = {
|
|||
user4: boolean;
|
||||
};
|
||||
|
||||
function getUserIdOfHouse(room: Room, engine: Mahjong.MasterGameEngine, house: Mahjong.Common.House): MiUser['id'] {
|
||||
function getUserIdOfHouse(room: Room, engine: Mahjong.MasterGameEngine, house: Mahjong.House): MiUser['id'] {
|
||||
return engine.state.user1House === house ? room.user1Id : engine.state.user2House === house ? room.user2Id : engine.state.user3House === house ? room.user3Id : room.user4Id;
|
||||
}
|
||||
|
||||
function getHouseOfUserId(room: Room, engine: Mahjong.MasterGameEngine, userId: MiUser['id']): Mahjong.Common.House {
|
||||
function getHouseOfUserId(room: Room, engine: Mahjong.MasterGameEngine, userId: MiUser['id']): Mahjong.House {
|
||||
return userId === room.user1Id ? engine.state.user1House : userId === room.user2Id ? engine.state.user2House : userId === room.user3Id ? engine.state.user3House : engine.state.user4House;
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
|||
pon: answers.pon ?? false,
|
||||
cii: answers.cii ?? false,
|
||||
kan: answers.kan ?? false,
|
||||
ron: [...(answers.ron.e ? ['e'] : []), ...(answers.ron.s ? ['s'] : []), ...(answers.ron.w ? ['w'] : []), ...(answers.ron.n ? ['n'] : [])] as Mahjong.Common.House[],
|
||||
ron: [...(answers.ron.e ? ['e'] : []), ...(answers.ron.s ? ['s'] : []), ...(answers.ron.w ? ['w'] : []), ...(answers.ron.n ? ['n'] : [])] as Mahjong.House[],
|
||||
});
|
||||
room.gameState = engine.state;
|
||||
await this.saveRoom(room);
|
||||
|
@ -376,7 +376,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
private async dahai(room: Room, engine: Mahjong.MasterGameEngine, house: Mahjong.Common.House, tile: Mahjong.Common.Tile, riichi = false) {
|
||||
private async dahai(room: Room, engine: Mahjong.MasterGameEngine, house: Mahjong.House, tile: Mahjong.Tile, riichi = false) {
|
||||
const res = engine.commit_dahai(house, tile, riichi);
|
||||
room.gameState = engine.state;
|
||||
await this.saveRoom(room);
|
||||
|
@ -482,7 +482,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
|||
const room = await this.getRoom(roomId);
|
||||
if (room == null) return;
|
||||
if (room.gameState == null) return;
|
||||
if (!Mahjong.Common.isTile(tile)) return;
|
||||
if (!Mahjong.isTile(tile)) return;
|
||||
|
||||
const engine = new Mahjong.MasterGameEngine(room.gameState);
|
||||
const myHouse = getHouseOfUserId(room, engine, user.id);
|
||||
|
@ -606,13 +606,13 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
|||
* @param engine
|
||||
*/
|
||||
@bindThis
|
||||
private async waitForTurn(room: Room, house: Mahjong.Common.House, engine: Mahjong.MasterGameEngine) {
|
||||
private async waitForTurn(room: Room, house: Mahjong.House, engine: Mahjong.MasterGameEngine) {
|
||||
const aiHouses = [[1, room.user1Ai], [2, room.user2Ai], [3, room.user3Ai], [4, room.user4Ai]].filter(([id, ai]) => ai).map(([id, ai]) => engine.getHouse(id));
|
||||
|
||||
if (engine.state.riichis[house]) {
|
||||
// リーチ時はアガリ牌でない限りツモ切り
|
||||
const handTiles = engine.state.handTiles[house];
|
||||
const horaSets = Mahjong.Common.getHoraSets(handTiles);
|
||||
const horaSets = Mahjong.getHoraSets(handTiles);
|
||||
if (horaSets.length === 0) {
|
||||
setTimeout(() => {
|
||||
this.dahai(room, engine, house, handTiles.at(-1));
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
@ -34,9 +34,9 @@ import * as Mahjong from 'misskey-mahjong';
|
|||
import XTile from './tile.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
huro: Mahjong.Common.Huro;
|
||||
huro: Mahjong.Huro;
|
||||
variation: string;
|
||||
doras: Mahjong.Common.Tile[];
|
||||
doras: Mahjong.Tile[];
|
||||
}>();
|
||||
</script>
|
||||
|
||||
|
|
|
@ -10,20 +10,20 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div style="text-align: center;">
|
||||
<div :class="$style.centerPanelTickerToi">
|
||||
<div style="position: absolute; left: 10px; bottom: 5px;">
|
||||
<span :class="$style.centerPanelHouse">{{ Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse)) === 'e' ? i18n.ts._mahjong.east : Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse)) === 's' ? i18n.ts._mahjong.south : Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse)) === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</span>
|
||||
<span :class="$style.centerPanelPoint">{{ engine.state.points[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))] }}</span>
|
||||
<span :class="$style.centerPanelHouse">{{ Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse)) === 'e' ? i18n.ts._mahjong.east : Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse)) === 's' ? i18n.ts._mahjong.south : Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse)) === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</span>
|
||||
<span :class="$style.centerPanelPoint">{{ engine.state.points[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.centerPanelTickerKami">
|
||||
<div style="position: absolute; left: 10px; bottom: 5px;">
|
||||
<span :class="$style.centerPanelHouse">{{ Mahjong.Common.prevHouse(engine.myHouse) === 'e' ? i18n.ts._mahjong.east : Mahjong.Common.prevHouse(engine.myHouse) === 's' ? i18n.ts._mahjong.south : Mahjong.Common.prevHouse(engine.myHouse) === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</span>
|
||||
<span :class="$style.centerPanelPoint">{{ engine.state.points[Mahjong.Common.prevHouse(engine.myHouse)] }}</span>
|
||||
<span :class="$style.centerPanelHouse">{{ Mahjong.prevHouse(engine.myHouse) === 'e' ? i18n.ts._mahjong.east : Mahjong.prevHouse(engine.myHouse) === 's' ? i18n.ts._mahjong.south : Mahjong.prevHouse(engine.myHouse) === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</span>
|
||||
<span :class="$style.centerPanelPoint">{{ engine.state.points[Mahjong.prevHouse(engine.myHouse)] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.centerPanelTickerSimo">
|
||||
<div style="position: absolute; left: 10px; bottom: 5px;">
|
||||
<span :class="$style.centerPanelHouse">{{ Mahjong.Common.nextHouse(engine.myHouse) === 'e' ? i18n.ts._mahjong.east : Mahjong.Common.nextHouse(engine.myHouse) === 's' ? i18n.ts._mahjong.south : Mahjong.Common.nextHouse(engine.myHouse) === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</span>
|
||||
<span :class="$style.centerPanelPoint">{{ engine.state.points[Mahjong.Common.nextHouse(engine.myHouse)] }}</span>
|
||||
<span :class="$style.centerPanelHouse">{{ Mahjong.nextHouse(engine.myHouse) === 'e' ? i18n.ts._mahjong.east : Mahjong.nextHouse(engine.myHouse) === 's' ? i18n.ts._mahjong.south : Mahjong.nextHouse(engine.myHouse) === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</span>
|
||||
<span :class="$style.centerPanelPoint">{{ engine.state.points[Mahjong.nextHouse(engine.myHouse)] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.centerPanelTickerMe">
|
||||
|
@ -39,33 +39,33 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
|
||||
<div :class="$style.handTilesOfToimen">
|
||||
<div v-for="tile in engine.state.handTiles[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" style="display: inline-block;">
|
||||
<div v-for="tile in engine.state.handTiles[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" style="display: inline-block;">
|
||||
<img :src="`/client-assets/mahjong/tile-back.png`" :class="$style.handTileImgOfToimen"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="$style.handTilesOfKamitya">
|
||||
<div v-for="tile in engine.state.handTiles[Mahjong.Common.prevHouse(engine.myHouse)]" :class="$style.sideTile">
|
||||
<div v-for="tile in engine.state.handTiles[Mahjong.prevHouse(engine.myHouse)]" :class="$style.sideTile">
|
||||
<img :src="`/client-assets/mahjong/tile-side.png`" style="display: inline-block; width: 32px;"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="$style.handTilesOfSimotya">
|
||||
<div v-for="tile in engine.state.handTiles[Mahjong.Common.nextHouse(engine.myHouse)]" :class="$style.sideTile">
|
||||
<div v-for="tile in engine.state.handTiles[Mahjong.nextHouse(engine.myHouse)]" :class="$style.sideTile">
|
||||
<img :src="`/client-assets/mahjong/tile-side.png`" style="display: inline-block; width: 32px; scale: -1 1;"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="$style.huroTilesOfToimen">
|
||||
<XHuro v-for="huro in engine.state.huros[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :huro="huro" :variation="1" :doras="engine.doras"/>
|
||||
<XHuro v-for="huro in engine.state.huros[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :huro="huro" :variation="1" :doras="engine.doras"/>
|
||||
</div>
|
||||
|
||||
<div :class="$style.huroTilesOfKamitya">
|
||||
<XHuro v-for="huro in engine.state.huros[Mahjong.Common.prevHouse(engine.myHouse)]" :huro="huro" :variation="1" :doras="engine.doras"/>
|
||||
<XHuro v-for="huro in engine.state.huros[Mahjong.prevHouse(engine.myHouse)]" :huro="huro" :variation="1" :doras="engine.doras"/>
|
||||
</div>
|
||||
|
||||
<div :class="$style.huroTilesOfSimotya">
|
||||
<XHuro v-for="huro in engine.state.huros[Mahjong.Common.nextHouse(engine.myHouse)]" :huro="huro" :variation="1" :doras="engine.doras"/>
|
||||
<XHuro v-for="huro in engine.state.huros[Mahjong.nextHouse(engine.myHouse)]" :huro="huro" :variation="1" :doras="engine.doras"/>
|
||||
</div>
|
||||
|
||||
<div :class="$style.huroTilesOfMe">
|
||||
|
@ -75,21 +75,21 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.hoTilesContainer">
|
||||
<div :class="$style.hoTilesContainerOfToimen">
|
||||
<div :class="$style.hoTilesOfToimen">
|
||||
<div v-for="(tile, i) in engine.state.hoTiles[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :class="$style.hoTile" :style="{ zIndex: engine.state.hoTiles[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))].length - i }">
|
||||
<div v-for="(tile, i) in engine.state.hoTiles[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :class="$style.hoTile" :style="{ zIndex: engine.state.hoTiles[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))].length - i }">
|
||||
<XTile :tile="tile" variation="2" :doras="engine.doras"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.hoTilesContainerOfKamitya">
|
||||
<div :class="$style.hoTilesOfKamitya">
|
||||
<div v-for="tile in engine.state.hoTiles[Mahjong.Common.prevHouse(engine.myHouse)]" :class="$style.hoTile">
|
||||
<div v-for="tile in engine.state.hoTiles[Mahjong.prevHouse(engine.myHouse)]" :class="$style.hoTile">
|
||||
<XTile :tile="tile" variation="4" :doras="engine.doras"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.hoTilesContainerOfSimotya">
|
||||
<div :class="$style.hoTilesOfSimotya">
|
||||
<div v-for="(tile, i) in engine.state.hoTiles[Mahjong.Common.nextHouse(engine.myHouse)]" :class="$style.hoTile" :style="{ zIndex: engine.state.hoTiles[Mahjong.Common.nextHouse(engine.myHouse)].length - i }">
|
||||
<div v-for="(tile, i) in engine.state.hoTiles[Mahjong.nextHouse(engine.myHouse)]" :class="$style.hoTile" :style="{ zIndex: engine.state.hoTiles[Mahjong.nextHouse(engine.myHouse)].length - i }">
|
||||
<XTile :tile="tile" variation="5" :doras="engine.doras"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -105,7 +105,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<div :class="$style.handTilesOfMe">
|
||||
<div
|
||||
v-for="tile in Mahjong.Common.sortTiles((isMyTurn && iTsumoed) ? engine.myHandTiles.slice(0, engine.myHandTiles.length - 1) : engine.myHandTiles)"
|
||||
v-for="tile in Mahjong.sortTiles((isMyTurn && iTsumoed) ? engine.myHandTiles.slice(0, engine.myHandTiles.length - 1) : engine.myHandTiles)"
|
||||
:class="[$style.myTile, { [$style.myTileNonSelectable]: selectableTiles != null && !selectableTiles.includes(tile), [$style.myTileDora]: engine.doras.includes(tile) }]"
|
||||
@click="chooseTile(tile, $event)"
|
||||
>
|
||||
|
@ -131,12 +131,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:enterFromClass="$style.transition_serif_enterFrom"
|
||||
:leaveToClass="$style.transition_serif_leaveTo"
|
||||
>
|
||||
<img v-if="ronSerifHouses[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/ron.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ciiSerifHouses[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/cii.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ponSerifHouses[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/pon.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="kanSerifHouses[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/kan.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="tsumoSerifHouses[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/tsumo.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="riichiSerifHouses[Mahjong.Common.prevHouse(Mahjong.Common.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/riichi.png`" style="display: block; width: 100%;"/>
|
||||
<img v-if="ronSerifHouses[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/ron.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ciiSerifHouses[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/cii.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ponSerifHouses[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/pon.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="kanSerifHouses[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/kan.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="tsumoSerifHouses[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/tsumo.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="riichiSerifHouses[Mahjong.prevHouse(Mahjong.prevHouse(engine.myHouse))]" :src="`/client-assets/mahjong/riichi.png`" style="display: block; width: 100%;"/>
|
||||
</Transition>
|
||||
</div>
|
||||
<div :class="$style.serifContainerOfKamitya">
|
||||
|
@ -146,12 +146,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:enterFromClass="$style.transition_serif_enterFrom"
|
||||
:leaveToClass="$style.transition_serif_leaveTo"
|
||||
>
|
||||
<img v-if="ronSerifHouses[Mahjong.Common.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/ron.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ciiSerifHouses[Mahjong.Common.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/cii.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ponSerifHouses[Mahjong.Common.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/pon.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="kanSerifHouses[Mahjong.Common.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/kan.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="tsumoSerifHouses[Mahjong.Common.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/tsumo.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="riichiSerifHouses[Mahjong.Common.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/riichi.png`" style="display: block; width: 100%;"/>
|
||||
<img v-if="ronSerifHouses[Mahjong.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/ron.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ciiSerifHouses[Mahjong.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/cii.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ponSerifHouses[Mahjong.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/pon.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="kanSerifHouses[Mahjong.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/kan.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="tsumoSerifHouses[Mahjong.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/tsumo.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="riichiSerifHouses[Mahjong.prevHouse(engine.myHouse)]" :src="`/client-assets/mahjong/riichi.png`" style="display: block; width: 100%;"/>
|
||||
</Transition>
|
||||
</div>
|
||||
<div :class="$style.serifContainerOfSimotya">
|
||||
|
@ -161,12 +161,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:enterFromClass="$style.transition_serif_enterFrom"
|
||||
:leaveToClass="$style.transition_serif_leaveTo"
|
||||
>
|
||||
<img v-if="ronSerifHouses[Mahjong.Common.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/ron.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ciiSerifHouses[Mahjong.Common.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/cii.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ponSerifHouses[Mahjong.Common.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/pon.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="kanSerifHouses[Mahjong.Common.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/kan.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="tsumoSerifHouses[Mahjong.Common.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/tsumo.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="riichiSerifHouses[Mahjong.Common.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/riichi.png`" style="display: block; width: 100%;"/>
|
||||
<img v-if="ronSerifHouses[Mahjong.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/ron.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ciiSerifHouses[Mahjong.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/cii.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="ponSerifHouses[Mahjong.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/pon.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="kanSerifHouses[Mahjong.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/kan.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="tsumoSerifHouses[Mahjong.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/tsumo.png`" style="display: block; width: 100%;"/>
|
||||
<img v-else-if="riichiSerifHouses[Mahjong.nextHouse(engine.myHouse)]" :src="`/client-assets/mahjong/riichi.png`" style="display: block; width: 100%;"/>
|
||||
</Transition>
|
||||
</div>
|
||||
<div :class="$style.serifContainerOfMe">
|
||||
|
@ -194,14 +194,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkButton v-if="isMyTurn && engine.canRiichi()" primary @click="riichi">Riichi</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="kyokuEnded" :class="$style.kyokuResult">
|
||||
<div v-if="showKyokuResults" :class="$style.kyokuResult">
|
||||
<div v-for="(res, house) in kyokuResults" :key="house">
|
||||
<div v-if="res != null">
|
||||
<div>{{ house === 'e' ? i18n.ts._mahjong.east : house === 's' ? i18n.ts._mahjong.south : house === 'w' ? i18n.ts._mahjong.west : i18n.ts._mahjong.north }}</div>
|
||||
<div v-for="yaku in res.yakus">
|
||||
<div>{{ yaku.name }} ({{ yaku.fan }})</div>
|
||||
<div>{{ i18n.ts._mahjong._yakus[yaku.name] }} {{ yaku.fan }}{{ i18n.ts._mahjong.fan }}</div>
|
||||
</div>
|
||||
<div>{{ res.doraCount }} dora</div>
|
||||
<div>{{ i18n.ts._mahjong.dora }} {{ res.doraCount }}{{ i18n.ts._mahjong.fan }}</div>
|
||||
<div>{{ res.pointDeltas.e }} / {{ res.pointDeltas.s }} / {{ res.pointDeltas.w }} / {{ res.pointDeltas.n }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -244,19 +244,19 @@ const isMyTurn = computed(() => {
|
|||
});
|
||||
|
||||
const canHora = computed(() => {
|
||||
return Mahjong.Common.getHoraSets(engine.value.myHandTiles).length > 0;
|
||||
return Mahjong.getHoraSets(engine.value.myHandTiles).length > 0;
|
||||
});
|
||||
|
||||
const selectableTiles = ref<Mahjong.Common.Tile[] | null>(null);
|
||||
const ronSerifHouses = reactive<Record<Mahjong.Common.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const ciiSerifHouses = reactive<Record<Mahjong.Common.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const ponSerifHouses = reactive<Record<Mahjong.Common.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const kanSerifHouses = reactive<Record<Mahjong.Common.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const tsumoSerifHouses = reactive<Record<Mahjong.Common.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const riichiSerifHouses = reactive<Record<Mahjong.Common.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const selectableTiles = ref<Mahjong.Tile[] | null>(null);
|
||||
const ronSerifHouses = reactive<Record<Mahjong.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const ciiSerifHouses = reactive<Record<Mahjong.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const ponSerifHouses = reactive<Record<Mahjong.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const kanSerifHouses = reactive<Record<Mahjong.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const tsumoSerifHouses = reactive<Record<Mahjong.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
const riichiSerifHouses = reactive<Record<Mahjong.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||
|
||||
/*
|
||||
console.log(Mahjong.Common.getTilesForRiichi([
|
||||
console.log(Mahjong.getTilesForRiichi([
|
||||
'm1',
|
||||
'm2',
|
||||
'm2',
|
||||
|
@ -274,7 +274,7 @@ console.log(Mahjong.Common.getTilesForRiichi([
|
|||
]));
|
||||
*/
|
||||
/*
|
||||
console.log(Mahjong.Common.getHoraSets([
|
||||
console.log(Mahjong.getHoraSets([
|
||||
'm3',
|
||||
'm3',
|
||||
'm4',
|
||||
|
@ -335,7 +335,7 @@ if (!props.room.isEnded) {
|
|||
|
||||
let riichiSelect = false;
|
||||
|
||||
function chooseTile(tile: Mahjong.Common.Tile, ev: MouseEvent) {
|
||||
function chooseTile(tile: Mahjong.Tile, ev: MouseEvent) {
|
||||
if (!isMyTurn.value) return;
|
||||
|
||||
iTsumoed.value = false;
|
||||
|
@ -353,8 +353,8 @@ function riichi() {
|
|||
if (!isMyTurn.value) return;
|
||||
|
||||
riichiSelect = true;
|
||||
selectableTiles.value = Mahjong.Common.getTilesForRiichi(engine.value.myHandTiles);
|
||||
console.log(Mahjong.Common.getTilesForRiichi(engine.value.myHandTiles));
|
||||
selectableTiles.value = Mahjong.getTilesForRiichi(engine.value.myHandTiles);
|
||||
console.log(Mahjong.getTilesForRiichi(engine.value.myHandTiles));
|
||||
}
|
||||
|
||||
function kakan() {
|
||||
|
@ -389,14 +389,14 @@ function skip() {
|
|||
}
|
||||
|
||||
const iTsumoed = ref(false);
|
||||
const kyokuEnded = ref(false);
|
||||
const kyokuResults = ref<Record<Mahjong.Common.House, {
|
||||
const showKyokuResults = ref(false);
|
||||
const kyokuResults = ref<Record<Mahjong.House, {
|
||||
yakus: {
|
||||
name: string;
|
||||
fan: number;
|
||||
}[];
|
||||
doraCount: number;
|
||||
pointDeltas: Record<Mahjong.Common.House, number>;
|
||||
pointDeltas: Record<Mahjong.House, number>;
|
||||
} | null>>({
|
||||
e: null,
|
||||
s: null,
|
||||
|
@ -405,7 +405,7 @@ const kyokuResults = ref<Record<Mahjong.Common.House, {
|
|||
});
|
||||
|
||||
function kyokuEnd() {
|
||||
kyokuEnded.value = true;
|
||||
showKyokuResults.value = true;
|
||||
}
|
||||
|
||||
function onStreamDahai(log) {
|
||||
|
@ -481,10 +481,10 @@ function onStreamDahaiAndTsumo(log) {
|
|||
}, 2000);
|
||||
|
||||
window.setTimeout(() => {
|
||||
engine.value.commit_tsumo(Mahjong.Common.nextHouse(log.dahaiHouse), log.tsumoTile);
|
||||
engine.value.commit_tsumo(Mahjong.nextHouse(log.dahaiHouse), log.tsumoTile);
|
||||
triggerRef(engine);
|
||||
|
||||
if (Mahjong.Common.nextHouse(log.dahaiHouse) === engine.value.myHouse) {
|
||||
if (Mahjong.nextHouse(log.dahaiHouse) === engine.value.myHouse) {
|
||||
iTsumoed.value = true;
|
||||
}
|
||||
}, 100);
|
||||
|
@ -521,7 +521,10 @@ function onStreamRonned(log) {
|
|||
triggerRef(engine);
|
||||
|
||||
kyokuResults.value = res;
|
||||
kyokuEnded.value = true;
|
||||
|
||||
window.setTimeout(() => {
|
||||
showKyokuResults.value = true;
|
||||
}, 1500);
|
||||
|
||||
for (const caller of log.callers) {
|
||||
ronSerifHouses[caller] = true;
|
||||
|
@ -537,7 +540,10 @@ function onStreamTsumoHora(log) {
|
|||
triggerRef(engine);
|
||||
|
||||
kyokuResults.value[log.house] = res;
|
||||
kyokuEnded.value = true;
|
||||
|
||||
window.setTimeout(() => {
|
||||
showKyokuResults.value = true;
|
||||
}, 1500);
|
||||
|
||||
tsumoSerifHouses[log.house] = true;
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import { computed } from 'vue';
|
|||
import * as Mahjong from 'misskey-mahjong';
|
||||
|
||||
const props = defineProps<{
|
||||
tile: Mahjong.Common.Tile;
|
||||
tile: Mahjong.Tile;
|
||||
variation: string;
|
||||
doras: Mahjong.Common.Tile[];
|
||||
doras: Mahjong.Tile[];
|
||||
}>();
|
||||
|
||||
const isDora = computed(() => props.doras.includes(props.tile));
|
||||
|
|
|
@ -101,59 +101,6 @@ export const NEXT_TILE_FOR_DORA_MAP: Record<Tile, Tile> = {
|
|||
chun: 'haku',
|
||||
};
|
||||
|
||||
export const yakuNames = [
|
||||
'riichi',
|
||||
'ippatsu',
|
||||
'tsumo',
|
||||
'tanyao',
|
||||
'pinfu',
|
||||
'iipeko',
|
||||
'field-wind',
|
||||
'seat-wind',
|
||||
'white',
|
||||
'green',
|
||||
'red',
|
||||
'rinshan',
|
||||
'chankan',
|
||||
'haitei',
|
||||
'hotei',
|
||||
'sanshoku-dojun',
|
||||
'sanshoku-doko',
|
||||
'ittsu',
|
||||
'chanta',
|
||||
'chitoitsu',
|
||||
'toitoi',
|
||||
'sananko',
|
||||
'honroto',
|
||||
'sankantsu',
|
||||
'shosangen',
|
||||
'double-riichi',
|
||||
'honitsu',
|
||||
'junchan',
|
||||
'ryampeko',
|
||||
'chinitsu',
|
||||
'dora',
|
||||
'red-dora',
|
||||
] as const;
|
||||
|
||||
export const yakumanNames = [
|
||||
'kokushi',
|
||||
'kokushi-13',
|
||||
'suanko',
|
||||
'suanko-tanki',
|
||||
'daisangen',
|
||||
'tsuiso',
|
||||
'shosushi',
|
||||
'daisushi',
|
||||
'ryuiso',
|
||||
'chinroto',
|
||||
'sukantsu',
|
||||
'churen',
|
||||
'pure-churen',
|
||||
'tenho',
|
||||
'chiho',
|
||||
] as const;
|
||||
|
||||
type EnvForCalcYaku = {
|
||||
house: House;
|
||||
|
||||
|
@ -260,15 +207,80 @@ export const YAKU_DEFINITIONS = [{
|
|||
);
|
||||
},
|
||||
}, {
|
||||
name: 'seat-wind',
|
||||
name: 'field-wind-e',
|
||||
fan: 1,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return (
|
||||
(state.handTiles.filter(t => t === state.house).length >= 3) ||
|
||||
return state.fieldWind === 'e' && (
|
||||
(state.handTiles.filter(t => t === 'e').length >= 3) ||
|
||||
(state.huros.filter(huro =>
|
||||
huro.type === 'pon' ? huro.tile === state.house :
|
||||
huro.type === 'ankan' ? huro.tile === state.house :
|
||||
huro.type === 'minkan' ? huro.tile === state.house :
|
||||
huro.type === 'pon' ? huro.tile === 'e' :
|
||||
huro.type === 'ankan' ? huro.tile === 'e' :
|
||||
huro.type === 'minkan' ? huro.tile === 'e' :
|
||||
false).length >= 3)
|
||||
);
|
||||
},
|
||||
}, {
|
||||
name: 'field-wind-s',
|
||||
fan: 1,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return state.fieldWind === 's' && (
|
||||
(state.handTiles.filter(t => t === 's').length >= 3) ||
|
||||
(state.huros.filter(huro =>
|
||||
huro.type === 'pon' ? huro.tile === 's' :
|
||||
huro.type === 'ankan' ? huro.tile === 's' :
|
||||
huro.type === 'minkan' ? huro.tile === 's' :
|
||||
false).length >= 3)
|
||||
);
|
||||
},
|
||||
}, {
|
||||
name: 'seat-wind-e',
|
||||
fan: 1,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return state.house === 'e' && (
|
||||
(state.handTiles.filter(t => t === 'e').length >= 3) ||
|
||||
(state.huros.filter(huro =>
|
||||
huro.type === 'pon' ? huro.tile === 'e' :
|
||||
huro.type === 'ankan' ? huro.tile === 'e' :
|
||||
huro.type === 'minkan' ? huro.tile === 'e' :
|
||||
false).length >= 3)
|
||||
);
|
||||
},
|
||||
}, {
|
||||
name: 'seat-wind-s',
|
||||
fan: 1,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return state.house === 's' && (
|
||||
(state.handTiles.filter(t => t === 's').length >= 3) ||
|
||||
(state.huros.filter(huro =>
|
||||
huro.type === 'pon' ? huro.tile === 's' :
|
||||
huro.type === 'ankan' ? huro.tile === 's' :
|
||||
huro.type === 'minkan' ? huro.tile === 's' :
|
||||
false).length >= 3)
|
||||
);
|
||||
},
|
||||
}, {
|
||||
name: 'seat-wind-w',
|
||||
fan: 1,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return state.house === 'w' && (
|
||||
(state.handTiles.filter(t => t === 'w').length >= 3) ||
|
||||
(state.huros.filter(huro =>
|
||||
huro.type === 'pon' ? huro.tile === 'w' :
|
||||
huro.type === 'ankan' ? huro.tile === 'w' :
|
||||
huro.type === 'minkan' ? huro.tile === 'w' :
|
||||
false).length >= 3)
|
||||
);
|
||||
},
|
||||
}, {
|
||||
name: 'seat-wind-n',
|
||||
fan: 1,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return state.house === 'n' && (
|
||||
(state.handTiles.filter(t => t === 'n').length >= 3) ||
|
||||
(state.huros.filter(huro =>
|
||||
huro.type === 'pon' ? huro.tile === 'n' :
|
||||
huro.type === 'ankan' ? huro.tile === 'n' :
|
||||
huro.type === 'minkan' ? huro.tile === 'n' :
|
||||
false).length >= 3)
|
||||
);
|
||||
},
|
||||
|
@ -450,12 +462,6 @@ export const SHUNTU_PATTERNS: [Tile, Tile, Tile][] = [
|
|||
['s7', 's8', 's9'],
|
||||
];
|
||||
|
||||
export type KyokuResult = {
|
||||
yakus: { name: string; fan: number; }[];
|
||||
doraCount: number;
|
||||
pointDeltas: { e: number; s: number; w: number; n: number; };
|
||||
};
|
||||
|
||||
function extractShuntsus(tiles: Tile[]): [Tile, Tile, Tile][] {
|
||||
const tempTiles = [...tiles];
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
export * as Serializer from './serializer.js';
|
||||
export * as Common from './common.js';
|
||||
export * from './common.js';
|
||||
|
||||
export { MasterGameEngine } from './engine.master.js';
|
||||
export type { MasterState } from './engine.master.js';
|
||||
|
|
Loading…
Reference in a new issue