fix: lint
This commit is contained in:
parent
131605070a
commit
977218bda5
|
@ -1,25 +1,25 @@
|
||||||
import { build } from "esbuild";
|
import { build } from 'esbuild';
|
||||||
import { globSync } from "glob";
|
import { globSync } from 'glob';
|
||||||
|
|
||||||
const entryPoints = globSync("./src/**/**.{ts,tsx}");
|
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||||
|
|
||||||
/** @type {import('esbuild').BuildOptions} */
|
/** @type {import('esbuild').BuildOptions} */
|
||||||
const options = {
|
const options = {
|
||||||
entryPoints,
|
entryPoints,
|
||||||
minify: true,
|
minify: true,
|
||||||
outdir: "./built/esm",
|
outdir: './built/esm',
|
||||||
target: "es2022",
|
target: 'es2022',
|
||||||
platform: "browser",
|
platform: 'browser',
|
||||||
format: "esm",
|
format: 'esm',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (process.env.WATCH === "true") {
|
if (process.env.WATCH === 'true') {
|
||||||
options.watch = {
|
options.watch = {
|
||||||
onRebuild(error, result) {
|
onRebuild(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("watch build failed:", error);
|
console.error('watch build failed:', error);
|
||||||
} else {
|
} else {
|
||||||
console.log("watch build succeeded:", result);
|
console.log('watch build succeeded:', result);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FourMentsuOneJyantou, mentsuEquals, TILE_NUMBER_MAP, TileType } from "./common.js";
|
import { FourMentsuOneJyantou, mentsuEquals, TILE_NUMBER_MAP, TileType } from './common.js';
|
||||||
|
|
||||||
export type Shape = 'fourMentsuOneJyantou' | 'chitoitsu' | 'kokushi';
|
export type Shape = 'fourMentsuOneJyantou' | 'chitoitsu' | 'kokushi';
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export function calcWaitPatterns(fourMentsuOneJyantou: FourMentsuOneJyantou | nu
|
||||||
|
|
||||||
const result: FourMentsuOneJyantouWithWait[] = [];
|
const result: FourMentsuOneJyantouWithWait[] = [];
|
||||||
|
|
||||||
if (fourMentsuOneJyantou.head == agariTile) {
|
if (fourMentsuOneJyantou.head === agariTile) {
|
||||||
result.push({
|
result.push({
|
||||||
head: fourMentsuOneJyantou.head,
|
head: fourMentsuOneJyantou.head,
|
||||||
mentsus: fourMentsuOneJyantou.mentsus,
|
mentsus: fourMentsuOneJyantou.mentsus,
|
||||||
|
@ -44,7 +44,7 @@ export function calcWaitPatterns(fourMentsuOneJyantou: FourMentsuOneJyantou | nu
|
||||||
waitedFor: 'mentsu',
|
waitedFor: 'mentsu',
|
||||||
agariTile,
|
agariTile,
|
||||||
waitedTaatsu: mentsu.toSpliced(agariTileIndex, 1) as [TileType, TileType],
|
waitedTaatsu: mentsu.toSpliced(agariTileIndex, 1) as [TileType, TileType],
|
||||||
})
|
});
|
||||||
checkedMentsus.push(mentsu);
|
checkedMentsus.push(mentsu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ export function isRyanmen(taatsu: [TileType, TileType]): boolean {
|
||||||
const number1 = TILE_NUMBER_MAP[taatsu[0]];
|
const number1 = TILE_NUMBER_MAP[taatsu[0]];
|
||||||
const number2 = TILE_NUMBER_MAP[taatsu[1]];
|
const number2 = TILE_NUMBER_MAP[taatsu[1]];
|
||||||
if (number1 == null || number2 == null) return false;
|
if (number1 == null || number2 == null) return false;
|
||||||
return number1 != 1 && number2 != 9 && number1 + 1 == number2;
|
return number1 !== 1 && number2 !== 9 && number1 + 1 === number2;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isToitsu(taatsu: [TileType, TileType]): boolean {
|
export function isToitsu(taatsu: [TileType, TileType]): boolean {
|
||||||
return taatsu[0] == taatsu[1];
|
return taatsu[0] === taatsu[1];
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ export type TileId = number;
|
||||||
|
|
||||||
// NOTE: 0 は"不明"(他プレイヤーの手牌など)を表すものとして予約されている
|
// NOTE: 0 は"不明"(他プレイヤーの手牌など)を表すものとして予約されている
|
||||||
export const TILE_ID_MAP = new Map<TileId, TileInstance>([
|
export const TILE_ID_MAP = new Map<TileId, TileInstance>([
|
||||||
/* eslint-disable no-multi-spaces */
|
/* eslint-disable @stylistic/no-multi-spaces */
|
||||||
[1, { t: 'm1' }], [2, { t: 'm1' }], [3, { t: 'm1' }], [4, { t: 'm1' }],
|
[1, { t: 'm1' }], [2, { t: 'm1' }], [3, { t: 'm1' }], [4, { t: 'm1' }],
|
||||||
[5, { t: 'm2' }], [6, { t: 'm2' }], [7, { t: 'm2' }], [8, { t: 'm2' }],
|
[5, { t: 'm2' }], [6, { t: 'm2' }], [7, { t: 'm2' }], [8, { t: 'm2' }],
|
||||||
[9, { t: 'm3' }], [10, { t: 'm3' }], [11, { t: 'm3' }], [12, { t: 'm3' }],
|
[9, { t: 'm3' }], [10, { t: 'm3' }], [11, { t: 'm3' }], [12, { t: 'm3' }],
|
||||||
|
@ -89,7 +89,7 @@ export const TILE_ID_MAP = new Map<TileId, TileInstance>([
|
||||||
[125, { t: 'haku' }], [126, { t: 'haku' }], [127, { t: 'haku' }], [128, { t: 'haku' }],
|
[125, { t: 'haku' }], [126, { t: 'haku' }], [127, { t: 'haku' }], [128, { t: 'haku' }],
|
||||||
[129, { t: 'hatsu' }], [130, { t: 'hatsu' }], [131, { t: 'hatsu' }], [132, { t: 'hatsu' }],
|
[129, { t: 'hatsu' }], [130, { t: 'hatsu' }], [131, { t: 'hatsu' }], [132, { t: 'hatsu' }],
|
||||||
[133, { t: 'chun' }], [134, { t: 'chun' }], [135, { t: 'chun' }], [136, { t: 'chun' }],
|
[133, { t: 'chun' }], [134, { t: 'chun' }], [135, { t: 'chun' }], [136, { t: 'chun' }],
|
||||||
/* eslint-enable no-multi-spaces */
|
/* eslint-enable @stylistic/no-multi-spaces */
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export function findTileByIdOrFail(tid: TileId): TileInstance {
|
export function findTileByIdOrFail(tid: TileId): TileInstance {
|
||||||
|
@ -130,7 +130,7 @@ export type PointFactor = {
|
||||||
} | {
|
} | {
|
||||||
isYakuman: true;
|
isYakuman: true;
|
||||||
value: number;
|
value: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const CALL_HURO_TYPES = ['pon', 'cii', 'minkan'] as const;
|
export const CALL_HURO_TYPES = ['pon', 'cii', 'minkan'] as const;
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ export function calcTsumoHoraPointDeltas(house: House, fansOrFactor: number | Po
|
||||||
n: 0,
|
n: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const point = typeof fansOrFactor == 'number' ? fanToPoint(fansOrFactor, isParent) : calcPoint(fansOrFactor, isParent);
|
const point = typeof fansOrFactor === 'number' ? fanToPoint(fansOrFactor, isParent) : calcPoint(fansOrFactor, isParent);
|
||||||
deltas[house] = point;
|
deltas[house] = point;
|
||||||
if (isParent) {
|
if (isParent) {
|
||||||
const childPoint = Math.ceil(point / 3);
|
const childPoint = Math.ceil(point / 3);
|
||||||
|
@ -464,7 +464,7 @@ export function isKotsu(tiles: [TileType, TileType, TileType]): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mentsuEquals(tiles1: [TileType, TileType, TileType], tiles2: [TileType, TileType, TileType]): boolean {
|
export function mentsuEquals(tiles1: [TileType, TileType, TileType], tiles2: [TileType, TileType, TileType]): boolean {
|
||||||
return tiles1[0] == tiles2[0] && tiles1[1] == tiles2[1] && tiles1[2] == tiles2[2];
|
return tiles1[0] === tiles2[0] && tiles1[1] === tiles2[1] && tiles1[2] === tiles2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SHUNTU_PATTERNS: [TileType, TileType, TileType][] = [
|
export const SHUNTU_PATTERNS: [TileType, TileType, TileType][] = [
|
||||||
|
|
|
@ -68,7 +68,7 @@ export const YAKUMAN_NAMES = [
|
||||||
'chiho',
|
'chiho',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
type NormalYakuName = typeof NORMAL_YAKU_NAMES[number]
|
type NormalYakuName = typeof NORMAL_YAKU_NAMES[number];
|
||||||
|
|
||||||
type YakumanName = typeof YAKUMAN_NAMES[number];
|
type YakumanName = typeof YAKUMAN_NAMES[number];
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ function countIndenticalMentsuPairs(mentsus: [TileType, TileType, TileType][]) {
|
||||||
let result = 0;
|
let result = 0;
|
||||||
const singleMentsus: [TileType, TileType, TileType][] = [];
|
const singleMentsus: [TileType, TileType, TileType][] = [];
|
||||||
loop: for (const mentsu of mentsus) {
|
loop: for (const mentsu of mentsus) {
|
||||||
for (let i = 0 ; i < singleMentsus.length ; i++) {
|
for (let i = 0; i < singleMentsus.length; i++) {
|
||||||
if (mentsuEquals(mentsu, singleMentsus[i])) {
|
if (mentsuEquals(mentsu, singleMentsus[i])) {
|
||||||
result++;
|
result++;
|
||||||
singleMentsus.splice(i, 1);
|
singleMentsus.splice(i, 1);
|
||||||
|
@ -302,18 +302,19 @@ function countIndenticalMentsuPairs(mentsus: [TileType, TileType, TileType][]) {
|
||||||
* 暗刻の数を数える (三暗刻なら3、四暗刻なら4)
|
* 暗刻の数を数える (三暗刻なら3、四暗刻なら4)
|
||||||
*/
|
*/
|
||||||
function countAnkos(state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait) {
|
function countAnkos(state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait) {
|
||||||
let ankans = state.huros.filter(huro => huro.type == 'ankan').length;
|
const ankans = state.huros.filter(huro => huro.type === 'ankan').length;
|
||||||
const handKotsus = fourMentsuOneJyantou.mentsus.filter(mentsu => isKotsu(mentsu)).length;
|
const handKotsus = fourMentsuOneJyantou.mentsus.filter(mentsu => isKotsu(mentsu)).length;
|
||||||
|
|
||||||
// ロンによりできた刻子は暗刻ではない
|
// ロンによりできた刻子は暗刻ではない
|
||||||
if (state.ronTile != null && fourMentsuOneJyantou.waitedFor == 'mentsu' && isToitsu(fourMentsuOneJyantou.waitedTaatsu)) {
|
if (state.ronTile != null && fourMentsuOneJyantou.waitedFor === 'mentsu' && isToitsu(fourMentsuOneJyantou.waitedTaatsu)) {
|
||||||
return ankans + handKotsus - 1;
|
return ankans + handKotsus - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ankans + handKotsus;
|
return ankans + handKotsus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NORMAL_YAKU_DEFINITIONS: NormalYakuDefinition[] = [{
|
export const NORMAL_YAKU_DEFINITIONS: NormalYakuDefinition[] = [
|
||||||
|
{
|
||||||
name: 'tsumo',
|
name: 'tsumo',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -323,61 +324,67 @@ export const NORMAL_YAKU_DEFINITIONS: NormalYakuDefinition[] = [{
|
||||||
|
|
||||||
return state.tsumoTile != null;
|
return state.tsumoTile != null;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'riichi',
|
name: 'riichi',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return !state.doubleRiichi && (state.riichi ?? false);
|
return !state.doubleRiichi && (state.riichi ?? false);
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'double-riichi',
|
name: 'double-riichi',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku) => {
|
calc: (state: EnvForCalcYaku) => {
|
||||||
return state.doubleRiichi ?? false;
|
return state.doubleRiichi ?? false;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'ippatsu',
|
name: 'ippatsu',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return state.ippatsu ?? false;
|
return state.ippatsu ?? false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'rinshan',
|
name: 'rinshan',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return (state.tsumoTile != null && state.rinshan) ?? false;
|
return (state.tsumoTile != null && state.rinshan) ?? false;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'haitei',
|
name: 'haitei',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return (state.tsumoTile != null && state.haitei) ?? false;
|
return (state.tsumoTile != null && state.haitei) ?? false;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'hotei',
|
name: 'hotei',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return (state.ronTile != null && state.hotei) ?? false;
|
return (state.ronTile != null && state.hotei) ?? false;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new Yakuhai('red', 'chun'),
|
new Yakuhai('red', 'chun'),
|
||||||
new Yakuhai('white', 'haku'),
|
new Yakuhai('white', 'haku'),
|
||||||
new Yakuhai('green', 'hatsu'),
|
new Yakuhai('green', 'hatsu'),
|
||||||
new FieldWind('field-wind-e', 'e'),
|
new FieldWind('field-wind-e', 'e'),
|
||||||
new FieldWind('field-wind-s', 's'),
|
new FieldWind('field-wind-s', 's'),
|
||||||
new FieldWind('field-wind-w', 'w'),
|
new FieldWind('field-wind-w', 'w'),
|
||||||
new FieldWind('field-wind-n', 'n'),
|
new FieldWind('field-wind-n', 'n'),
|
||||||
new SeatWind('seat-wind-e', 'e'),
|
new SeatWind('seat-wind-e', 'e'),
|
||||||
new SeatWind('seat-wind-s', 's'),
|
new SeatWind('seat-wind-s', 's'),
|
||||||
new SeatWind('seat-wind-w', 'w'),
|
new SeatWind('seat-wind-w', 'w'),
|
||||||
new SeatWind('seat-wind-n', 'n'),
|
new SeatWind('seat-wind-n', 'n'),
|
||||||
{
|
{
|
||||||
name: 'tanyao',
|
name: 'tanyao',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -392,7 +399,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
false).length === 0)
|
false).length === 0)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'pinfu',
|
name: 'pinfu',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -405,7 +413,7 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
if (state.handTiles.some(t => ['haku', 'hatsu', 'chun'].includes(t))) return false;
|
if (state.handTiles.some(t => ['haku', 'hatsu', 'chun'].includes(t))) return false;
|
||||||
|
|
||||||
// 両面待ちかどうか
|
// 両面待ちかどうか
|
||||||
if (!(fourMentsuOneJyantou != null && fourMentsuOneJyantou.waitedFor == 'mentsu' && isRyanmen(fourMentsuOneJyantou.waitedTaatsu))) return false;
|
if (!(fourMentsuOneJyantou != null && fourMentsuOneJyantou.waitedFor === 'mentsu' && isRyanmen(fourMentsuOneJyantou.waitedTaatsu))) return false;
|
||||||
|
|
||||||
// 風牌判定(役牌でなければOK)
|
// 風牌判定(役牌でなければOK)
|
||||||
if (fourMentsuOneJyantou.head === state.seatWind) return false;
|
if (fourMentsuOneJyantou.head === state.seatWind) return false;
|
||||||
|
@ -416,7 +424,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'honitsu',
|
name: 'honitsu',
|
||||||
fan: 3,
|
fan: 3,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -443,7 +452,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'chinitsu',
|
name: 'chinitsu',
|
||||||
fan: 6,
|
fan: 6,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -470,7 +480,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'iipeko',
|
name: 'iipeko',
|
||||||
fan: 1,
|
fan: 1,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -481,9 +492,10 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
if (state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type))) return false;
|
if (state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type))) return false;
|
||||||
|
|
||||||
// 同じ順子が2つあるか?
|
// 同じ順子が2つあるか?
|
||||||
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) == 1;
|
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) === 1;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'ryampeko',
|
name: 'ryampeko',
|
||||||
fan: 3,
|
fan: 3,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -494,9 +506,10 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
if (state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type))) return false;
|
if (state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type))) return false;
|
||||||
|
|
||||||
// 2つの同じ順子が2組あるか?
|
// 2つの同じ順子が2組あるか?
|
||||||
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) == 2;
|
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) === 2;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'toitoi',
|
name: 'toitoi',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -512,30 +525,34 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'sananko',
|
name: 'sananko',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
||||||
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) == 3;
|
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) === 3;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'honroto',
|
name: 'honroto',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku) => {
|
calc: (state: EnvForCalcYaku) => {
|
||||||
return state.huros.every(huro => huro.type != 'cii' && includes(YAOCHU_TILES, huro.tile)) &&
|
return state.huros.every(huro => huro.type !== 'cii' && includes(YAOCHU_TILES, huro.tile)) &&
|
||||||
state.handTiles.every(tile => includes(YAOCHU_TILES, tile));
|
state.handTiles.every(tile => includes(YAOCHU_TILES, tile));
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'sankantsu',
|
name: 'sankantsu',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return fourMentsuOneJyantou != null &&
|
return fourMentsuOneJyantou != null &&
|
||||||
state.huros.filter(huro => huro.type == 'ankan' || huro.type == 'minkan').length == 3;
|
state.huros.filter(huro => huro.type === 'ankan' || huro.type === 'minkan').length === 3;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'sanshoku-dojun',
|
name: 'sanshoku-dojun',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -569,7 +586,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'sanshoku-doko',
|
name: 'sanshoku-doko',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -603,7 +621,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'ittsu',
|
name: 'ittsu',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -612,7 +631,7 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
if (fourMentsuOneJyantou == null) return false;
|
if (fourMentsuOneJyantou == null) return false;
|
||||||
|
|
||||||
const shuntsus = fourMentsuOneJyantou.mentsus.filter(tiles => isShuntu(tiles));
|
const shuntsus = fourMentsuOneJyantou.mentsus.filter(tiles => isShuntu(tiles));
|
||||||
shuntsus.push(...state.huros.filter((huro): huro is Cii => huro.type == 'cii').map(huro => huro.tiles));
|
shuntsus.push(...state.huros.filter((huro): huro is Cii => huro.type === 'cii').map(huro => huro.tiles));
|
||||||
|
|
||||||
if (shuntsus.some(tiles => tiles[0] === 'm1' && tiles[1] === 'm2' && tiles[2] === 'm3')) {
|
if (shuntsus.some(tiles => tiles[0] === 'm1' && tiles[1] === 'm2' && tiles[2] === 'm3')) {
|
||||||
if (shuntsus.some(tiles => tiles[0] === 'm4' && tiles[1] === 'm5' && tiles[2] === 'm6')) {
|
if (shuntsus.some(tiles => tiles[0] === 'm4' && tiles[1] === 'm5' && tiles[2] === 'm6')) {
|
||||||
|
@ -638,7 +657,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'chanta',
|
name: 'chanta',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -658,15 +678,16 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
// いずれかの雀頭か面子に字牌を含まないとダメ
|
// いずれかの雀頭か面子に字牌を含まないとダメ
|
||||||
if (!(includes(CHAR_TILES, head) ||
|
if (!(includes(CHAR_TILES, head) ||
|
||||||
mentsus.some(mentsu => includes(CHAR_TILES, mentsu[0])) ||
|
mentsus.some(mentsu => includes(CHAR_TILES, mentsu[0])) ||
|
||||||
huros.some(huro => huro.type != 'cii' && includes(CHAR_TILES, huro.tile)))) return false;
|
huros.some(huro => huro.type !== 'cii' && includes(CHAR_TILES, huro.tile)))) return false;
|
||||||
|
|
||||||
// 全ての面子に幺九牌が含まれる
|
// 全ての面子に幺九牌が含まれる
|
||||||
return (mentsus.every(mentsu => mentsu.some(tile => includes(YAOCHU_TILES, tile))) &&
|
return (mentsus.every(mentsu => mentsu.some(tile => includes(YAOCHU_TILES, tile))) &&
|
||||||
huros.every(huro => huro.type == 'cii' ?
|
huros.every(huro => huro.type === 'cii' ?
|
||||||
huro.tiles.some(tile => includes(YAOCHU_TILES, tile)) :
|
huro.tiles.some(tile => includes(YAOCHU_TILES, tile)) :
|
||||||
includes(YAOCHU_TILES, huro.tile)));
|
includes(YAOCHU_TILES, huro.tile)));
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'junchan',
|
name: 'junchan',
|
||||||
fan: 3,
|
fan: 3,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -685,11 +706,12 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
// 全ての面子に老頭牌が含まれる
|
// 全ての面子に老頭牌が含まれる
|
||||||
return (mentsus.every(mentsu => mentsu.some(tile => includes(TERMINAL_TILES, tile))) &&
|
return (mentsus.every(mentsu => mentsu.some(tile => includes(TERMINAL_TILES, tile))) &&
|
||||||
huros.every(huro => huro.type == 'cii' ?
|
huros.every(huro => huro.type === 'cii' ?
|
||||||
huro.tiles.some(tile => includes(TERMINAL_TILES, tile)) :
|
huro.tiles.some(tile => includes(TERMINAL_TILES, tile)) :
|
||||||
includes(TERMINAL_TILES, huro.tile)));
|
includes(TERMINAL_TILES, huro.tile)));
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'chitoitsu',
|
name: 'chitoitsu',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -703,7 +725,8 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
}
|
}
|
||||||
return Array.from(countMap.values()).every(c => c === 2);
|
return Array.from(countMap.values()).every(c => c === 2);
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'shosangen',
|
name: 'shosangen',
|
||||||
fan: 2,
|
fan: 2,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
|
@ -730,23 +753,27 @@ new SeatWind('seat-wind-n', 'n'),
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [
|
||||||
|
{
|
||||||
name: 'suanko-tanki',
|
name: 'suanko-tanki',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
isDoubleYakuman: true,
|
isDoubleYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
||||||
return fourMentsuOneJyantou != null && fourMentsuOneJyantou.waitedFor == 'head' && countAnkos(state, fourMentsuOneJyantou) == 4;
|
return fourMentsuOneJyantou != null && fourMentsuOneJyantou.waitedFor === 'head' && countAnkos(state, fourMentsuOneJyantou) === 4;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'suanko',
|
name: 'suanko',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
upper: 'suanko-tanki',
|
upper: 'suanko-tanki',
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
||||||
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) == 4;
|
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) === 4;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'daisangen',
|
name: 'daisangen',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
|
@ -766,7 +793,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return kotsuTiles.includes('haku') && kotsuTiles.includes('hatsu') && kotsuTiles.includes('chun');
|
return kotsuTiles.includes('haku') && kotsuTiles.includes('hatsu') && kotsuTiles.includes('chun');
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'shosushi',
|
name: 'shosushi',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
|
@ -792,7 +820,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'daisushi',
|
name: 'daisushi',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
|
@ -812,7 +841,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return kotsuTiles.includes('e') && kotsuTiles.includes('s') && kotsuTiles.includes('w') && kotsuTiles.includes('n');
|
return kotsuTiles.includes('e') && kotsuTiles.includes('s') && kotsuTiles.includes('w') && kotsuTiles.includes('n');
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'tsuiso',
|
name: 'tsuiso',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku) => {
|
calc: (state: EnvForCalcYaku) => {
|
||||||
|
@ -832,7 +862,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'ryuiso',
|
name: 'ryuiso',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
|
@ -847,22 +878,25 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'chinroto',
|
name: 'chinroto',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return fourMentsuOneJyantou != null &&
|
return fourMentsuOneJyantou != null &&
|
||||||
state.huros.every(huro => huro.type != 'cii' && includes(TERMINAL_TILES, huro.tile)) &&
|
state.huros.every(huro => huro.type !== 'cii' && includes(TERMINAL_TILES, huro.tile)) &&
|
||||||
state.handTiles.every(tile => includes(TERMINAL_TILES, tile));
|
state.handTiles.every(tile => includes(TERMINAL_TILES, tile));
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'sukantsu',
|
name: 'sukantsu',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return fourMentsuOneJyantou != null &&
|
return fourMentsuOneJyantou != null &&
|
||||||
state.huros.filter(huro => huro.type == 'ankan' || huro.type == 'minkan').length == 4;
|
state.huros.filter(huro => huro.type === 'ankan' || huro.type === 'minkan').length === 4;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'churen-9',
|
name: 'churen-9',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
isDoubleYakuman: true,
|
isDoubleYakuman: true,
|
||||||
|
@ -901,7 +935,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'churen',
|
name: 'churen',
|
||||||
upper: 'churen-9',
|
upper: 'churen-9',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
|
@ -933,34 +968,39 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'kokushi-13',
|
name: 'kokushi-13',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
isDoubleYakuman: true,
|
isDoubleYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
const agariTile = state.tsumoTile ?? state.ronTile;
|
const agariTile = state.tsumoTile ?? state.ronTile;
|
||||||
return KOKUSHI_TILES.every(t => state.handTiles.includes(t)) && countTiles(state.handTiles, agariTile) == 2;
|
return KOKUSHI_TILES.every(t => state.handTiles.includes(t)) && countTiles(state.handTiles, agariTile) === 2;
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'kokushi',
|
name: 'kokushi',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
upper: 'kokushi-13',
|
upper: 'kokushi-13',
|
||||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||||
return KOKUSHI_TILES.every(t => state.handTiles.includes(t)) && KOKUSHI_TILES.some(t => countTiles(state.handTiles, t) == 2);
|
return KOKUSHI_TILES.every(t => state.handTiles.includes(t)) && KOKUSHI_TILES.some(t => countTiles(state.handTiles, t) === 2);
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'tenho',
|
name: 'tenho',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku) => {
|
calc: (state: EnvForCalcYaku) => {
|
||||||
return (state.firstTurn ?? false) && state.tsumoTile != null && state.seatWind == 'e';
|
return (state.firstTurn ?? false) && state.tsumoTile != null && state.seatWind === 'e';
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
name: 'chiho',
|
name: 'chiho',
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
calc: (state: EnvForCalcYaku) => {
|
calc: (state: EnvForCalcYaku) => {
|
||||||
return (state.firstTurn ?? false) && state.tsumoTile != null && state.seatWind != 'e';
|
return (state.firstTurn ?? false) && state.tsumoTile != null && state.seatWind !== 'e';
|
||||||
}
|
},
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export function convertHuroForCalcYaku(huro: Huro): HuroForCalcYaku {
|
export function convertHuroForCalcYaku(huro: Huro): HuroForCalcYaku {
|
||||||
switch (huro.type) {
|
switch (huro.type) {
|
||||||
|
@ -970,7 +1010,7 @@ export function convertHuroForCalcYaku(huro: Huro): HuroForCalcYaku {
|
||||||
return {
|
return {
|
||||||
type: huro.type,
|
type: huro.type,
|
||||||
tile: TILE_ID_MAP.get(huro.tiles[0])!.t,
|
tile: TILE_ID_MAP.get(huro.tiles[0])!.t,
|
||||||
}
|
};
|
||||||
case 'cii':
|
case 'cii':
|
||||||
return {
|
return {
|
||||||
type: 'cii',
|
type: 'cii',
|
||||||
|
@ -986,7 +1026,7 @@ const NORMAL_YAKU_DATA_MAP = new Map<NormalYakuName, Required<NormalYakuData>>(
|
||||||
fan: yaku.fan,
|
fan: yaku.fan,
|
||||||
isYakuman: false,
|
isYakuman: false,
|
||||||
kuisagari: yaku.kuisagari ?? false,
|
kuisagari: yaku.kuisagari ?? false,
|
||||||
}] as const)
|
}] as const),
|
||||||
);
|
);
|
||||||
|
|
||||||
const YAKUMAN_DATA_MAP = new Map<YakuName, Required<YakumanData>>(
|
const YAKUMAN_DATA_MAP = new Map<YakuName, Required<YakumanData>>(
|
||||||
|
@ -996,7 +1036,7 @@ const YAKUMAN_DATA_MAP = new Map<YakuName, Required<YakumanData>>(
|
||||||
fan: null,
|
fan: null,
|
||||||
isYakuman: true,
|
isYakuman: true,
|
||||||
isDoubleYakuman: yaku.isDoubleYakuman ?? false,
|
isDoubleYakuman: yaku.isDoubleYakuman ?? false,
|
||||||
}])
|
}]),
|
||||||
);
|
);
|
||||||
|
|
||||||
export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
||||||
|
@ -1009,7 +1049,7 @@ export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
||||||
throw new TypeError('Agari tile not included in hand tiles');
|
throw new TypeError('Agari tile not included in hand tiles');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.handTiles.length + state.huros.length * 3 != 14) {
|
if (state.handTiles.length + state.huros.length * 3 !== 14) {
|
||||||
throw new TypeError('Invalid tile count');
|
throw new TypeError('Invalid tile count');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,7 +1057,7 @@ export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
||||||
if (oneHeadFourMentsuPatterns.length === 0) oneHeadFourMentsuPatterns.push(null);
|
if (oneHeadFourMentsuPatterns.length === 0) oneHeadFourMentsuPatterns.push(null);
|
||||||
|
|
||||||
const waitPatterns = oneHeadFourMentsuPatterns.map(
|
const waitPatterns = oneHeadFourMentsuPatterns.map(
|
||||||
fourMentsuOneJyantou => calcWaitPatterns(fourMentsuOneJyantou, agariTile)
|
fourMentsuOneJyantou => calcWaitPatterns(fourMentsuOneJyantou, agariTile),
|
||||||
).flat();
|
).flat();
|
||||||
|
|
||||||
const yakumanPatterns = waitPatterns.map(fourMentsuOneJyantouWithWait => {
|
const yakumanPatterns = waitPatterns.map(fourMentsuOneJyantouWithWait => {
|
||||||
|
@ -1038,13 +1078,13 @@ export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
||||||
|
|
||||||
const yakuPatterns = waitPatterns.map(
|
const yakuPatterns = waitPatterns.map(
|
||||||
fourMentsuOneJyantouWithWait => NORMAL_YAKU_DEFINITIONS.filter(
|
fourMentsuOneJyantouWithWait => NORMAL_YAKU_DEFINITIONS.filter(
|
||||||
yakuDef => yakuDef.calc(state, fourMentsuOneJyantouWithWait)
|
yakuDef => yakuDef.calc(state, fourMentsuOneJyantouWithWait),
|
||||||
).map(yakuDef => NORMAL_YAKU_DATA_MAP.get(yakuDef.name)!)
|
).map(yakuDef => NORMAL_YAKU_DATA_MAP.get(yakuDef.name)!),
|
||||||
).filter(yakus => yakus.length > 0);
|
).filter(yakus => yakus.length > 0);
|
||||||
|
|
||||||
const isMenzen = state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type));
|
const isMenzen = state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type));
|
||||||
|
|
||||||
if (yakuPatterns.length == 0) {
|
if (yakuPatterns.length === 0) {
|
||||||
return new NormalYakuSet(isMenzen, []);
|
return new NormalYakuSet(isMenzen, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -613,7 +613,7 @@ export class MasterGameEngine {
|
||||||
public commit_kakan(house: House, tid: TileId) {
|
public commit_kakan(house: House, tid: TileId) {
|
||||||
const tx = this.startTransaction();
|
const tx = this.startTransaction();
|
||||||
|
|
||||||
const pon = tx.$state.huros[house].find(h => h.type === 'pon' && $type(h.tiles[0]) === $type(tid)) as Huro & {type: 'pon'};
|
const pon = tx.$state.huros[house].find(h => h.type === 'pon' && $type(h.tiles[0]) === $type(tid)) as Huro & { type: 'pon' };
|
||||||
if (pon == null) throw new Error('No such pon');
|
if (pon == null) throw new Error('No such pon');
|
||||||
tx.$state.handTiles[house].splice(tx.$state.handTiles[house].indexOf(tid), 1);
|
tx.$state.handTiles[house].splice(tx.$state.handTiles[house].indexOf(tid), 1);
|
||||||
const tiles = [tid, ...pon.tiles] as const;
|
const tiles = [tid, ...pon.tiles] as const;
|
||||||
|
@ -686,7 +686,7 @@ export class MasterGameEngine {
|
||||||
doubleRiichi: tx.$state.doubleRiichis[house],
|
doubleRiichi: tx.$state.doubleRiichis[house],
|
||||||
ippatsu: tx.$state.ippatsus[house],
|
ippatsu: tx.$state.ippatsus[house],
|
||||||
rinshan: tx.$state.rinshanFlags[house],
|
rinshan: tx.$state.rinshanFlags[house],
|
||||||
haitei: tx.$state.tiles.length == 0,
|
haitei: tx.$state.tiles.length === 0,
|
||||||
});
|
});
|
||||||
const doraCount =
|
const doraCount =
|
||||||
Common.calcOwnedDoraCount(tx.handTileTypes[house], tx.$state.huros[house], tx.doras) +
|
Common.calcOwnedDoraCount(tx.handTileTypes[house], tx.$state.huros[house], tx.doras) +
|
||||||
|
@ -743,7 +743,7 @@ export class MasterGameEngine {
|
||||||
riichi: tx.$state.riichis[house],
|
riichi: tx.$state.riichis[house],
|
||||||
doubleRiichi: tx.$state.doubleRiichis[house],
|
doubleRiichi: tx.$state.doubleRiichis[house],
|
||||||
ippatsu: tx.$state.ippatsus[house],
|
ippatsu: tx.$state.ippatsus[house],
|
||||||
hotei: tx.$state.tiles.length == 0,
|
hotei: tx.$state.tiles.length === 0,
|
||||||
});
|
});
|
||||||
const doraCount =
|
const doraCount =
|
||||||
Common.calcOwnedDoraCount(tx.handTileTypes[house], tx.$state.huros[house], tx.doras) +
|
Common.calcOwnedDoraCount(tx.handTileTypes[house], tx.$state.huros[house], tx.doras) +
|
||||||
|
|
|
@ -270,7 +270,7 @@ export class PlayerGameEngine {
|
||||||
doubleRiichi: this.state.doubleRiichis[house],
|
doubleRiichi: this.state.doubleRiichis[house],
|
||||||
ippatsu: this.state.ippatsus[house],
|
ippatsu: this.state.ippatsus[house],
|
||||||
rinshan: this.state.rinshanFlags[house],
|
rinshan: this.state.rinshanFlags[house],
|
||||||
haitei: this.state.tilesCount == 0,
|
haitei: this.state.tilesCount === 0,
|
||||||
});
|
});
|
||||||
const doraCount =
|
const doraCount =
|
||||||
Common.calcOwnedDoraCount(handTiles.map(id => $type(id)), this.state.huros[house], this.doras) +
|
Common.calcOwnedDoraCount(handTiles.map(id => $type(id)), this.state.huros[house], this.doras) +
|
||||||
|
@ -322,7 +322,7 @@ export class PlayerGameEngine {
|
||||||
riichi: this.state.riichis[house],
|
riichi: this.state.riichis[house],
|
||||||
doubleRiichi: this.state.doubleRiichis[house],
|
doubleRiichi: this.state.doubleRiichis[house],
|
||||||
ippatsu: this.state.ippatsus[house],
|
ippatsu: this.state.ippatsus[house],
|
||||||
hotei: this.state.tilesCount == 0,
|
hotei: this.state.tilesCount === 0,
|
||||||
});
|
});
|
||||||
const doraCount =
|
const doraCount =
|
||||||
Common.calcOwnedDoraCount(handTiles[house].map(id => $type(id)), this.state.huros[house], this.doras) +
|
Common.calcOwnedDoraCount(handTiles[house].map(id => $type(id)), this.state.huros[house], this.doras) +
|
||||||
|
|
Loading…
Reference in New Issue