fix: lint
This commit is contained in:
parent
131605070a
commit
977218bda5
|
@ -1,25 +1,25 @@
|
|||
import { build } from "esbuild";
|
||||
import { globSync } from "glob";
|
||||
import { build } from 'esbuild';
|
||||
import { globSync } from 'glob';
|
||||
|
||||
const entryPoints = globSync("./src/**/**.{ts,tsx}");
|
||||
const entryPoints = globSync('./src/**/**.{ts,tsx}');
|
||||
|
||||
/** @type {import('esbuild').BuildOptions} */
|
||||
const options = {
|
||||
entryPoints,
|
||||
minify: true,
|
||||
outdir: "./built/esm",
|
||||
target: "es2022",
|
||||
platform: "browser",
|
||||
format: "esm",
|
||||
outdir: './built/esm',
|
||||
target: 'es2022',
|
||||
platform: 'browser',
|
||||
format: 'esm',
|
||||
};
|
||||
|
||||
if (process.env.WATCH === "true") {
|
||||
if (process.env.WATCH === 'true') {
|
||||
options.watch = {
|
||||
onRebuild(error, result) {
|
||||
if (error) {
|
||||
console.error("watch build failed:", error);
|
||||
console.error('watch build failed:', error);
|
||||
} else {
|
||||
console.log("watch build succeeded:", result);
|
||||
console.log('watch build succeeded:', result);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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';
|
||||
|
||||
|
@ -24,7 +24,7 @@ export function calcWaitPatterns(fourMentsuOneJyantou: FourMentsuOneJyantou | nu
|
|||
|
||||
const result: FourMentsuOneJyantouWithWait[] = [];
|
||||
|
||||
if (fourMentsuOneJyantou.head == agariTile) {
|
||||
if (fourMentsuOneJyantou.head === agariTile) {
|
||||
result.push({
|
||||
head: fourMentsuOneJyantou.head,
|
||||
mentsus: fourMentsuOneJyantou.mentsus,
|
||||
|
@ -44,7 +44,7 @@ export function calcWaitPatterns(fourMentsuOneJyantou: FourMentsuOneJyantou | nu
|
|||
waitedFor: 'mentsu',
|
||||
agariTile,
|
||||
waitedTaatsu: mentsu.toSpliced(agariTileIndex, 1) as [TileType, TileType],
|
||||
})
|
||||
});
|
||||
checkedMentsus.push(mentsu);
|
||||
}
|
||||
|
||||
|
@ -55,9 +55,9 @@ export function isRyanmen(taatsu: [TileType, TileType]): boolean {
|
|||
const number1 = TILE_NUMBER_MAP[taatsu[0]];
|
||||
const number2 = TILE_NUMBER_MAP[taatsu[1]];
|
||||
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 {
|
||||
return taatsu[0] == taatsu[1];
|
||||
return taatsu[0] === taatsu[1];
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ export type TileId = number;
|
|||
|
||||
// NOTE: 0 は"不明"(他プレイヤーの手牌など)を表すものとして予約されている
|
||||
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' }],
|
||||
[5, { t: 'm2' }], [6, { t: 'm2' }], [7, { t: 'm2' }], [8, { t: 'm2' }],
|
||||
[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' }],
|
||||
[129, { t: 'hatsu' }], [130, { t: 'hatsu' }], [131, { t: 'hatsu' }], [132, { t: 'hatsu' }],
|
||||
[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 {
|
||||
|
@ -130,7 +130,7 @@ export type PointFactor = {
|
|||
} | {
|
||||
isYakuman: true;
|
||||
value: number;
|
||||
}
|
||||
};
|
||||
|
||||
export const CALL_HURO_TYPES = ['pon', 'cii', 'minkan'] as const;
|
||||
|
||||
|
@ -386,7 +386,7 @@ export function calcTsumoHoraPointDeltas(house: House, fansOrFactor: number | Po
|
|||
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;
|
||||
if (isParent) {
|
||||
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 {
|
||||
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][] = [
|
||||
|
|
|
@ -68,7 +68,7 @@ export const YAKUMAN_NAMES = [
|
|||
'chiho',
|
||||
] as const;
|
||||
|
||||
type NormalYakuName = typeof NORMAL_YAKU_NAMES[number]
|
||||
type NormalYakuName = typeof NORMAL_YAKU_NAMES[number];
|
||||
|
||||
type YakumanName = typeof YAKUMAN_NAMES[number];
|
||||
|
||||
|
@ -302,18 +302,19 @@ function countIndenticalMentsuPairs(mentsus: [TileType, TileType, TileType][]) {
|
|||
* 暗刻の数を数える (三暗刻なら3、四暗刻なら4)
|
||||
*/
|
||||
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;
|
||||
|
||||
// ロンによりできた刻子は暗刻ではない
|
||||
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;
|
||||
}
|
||||
|
||||
export const NORMAL_YAKU_DEFINITIONS: NormalYakuDefinition[] = [{
|
||||
export const NORMAL_YAKU_DEFINITIONS: NormalYakuDefinition[] = [
|
||||
{
|
||||
name: 'tsumo',
|
||||
fan: 1,
|
||||
isYakuman: false,
|
||||
|
@ -323,48 +324,54 @@ export const NORMAL_YAKU_DEFINITIONS: NormalYakuDefinition[] = [{
|
|||
|
||||
return state.tsumoTile != null;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'riichi',
|
||||
fan: 1,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
return !state.doubleRiichi && (state.riichi ?? false);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'double-riichi',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
return state.doubleRiichi ?? false;
|
||||
}
|
||||
}, {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ippatsu',
|
||||
fan: 1,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
return state.ippatsu ?? false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'rinshan',
|
||||
fan: 1,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
return (state.tsumoTile != null && state.rinshan) ?? false;
|
||||
}
|
||||
}, {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'haitei',
|
||||
fan: 1,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
return (state.tsumoTile != null && state.haitei) ?? false;
|
||||
}
|
||||
}, {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'hotei',
|
||||
fan: 1,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
return (state.ronTile != null && state.hotei) ?? false;
|
||||
}
|
||||
},
|
||||
},
|
||||
new Yakuhai('red', 'chun'),
|
||||
new Yakuhai('white', 'haku'),
|
||||
|
@ -392,7 +399,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
false).length === 0)
|
||||
);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'pinfu',
|
||||
fan: 1,
|
||||
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 (!(fourMentsuOneJyantou != null && fourMentsuOneJyantou.waitedFor == 'mentsu' && isRyanmen(fourMentsuOneJyantou.waitedTaatsu))) return false;
|
||||
if (!(fourMentsuOneJyantou != null && fourMentsuOneJyantou.waitedFor === 'mentsu' && isRyanmen(fourMentsuOneJyantou.waitedTaatsu))) return false;
|
||||
|
||||
// 風牌判定(役牌でなければOK)
|
||||
if (fourMentsuOneJyantou.head === state.seatWind) return false;
|
||||
|
@ -416,7 +424,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'honitsu',
|
||||
fan: 3,
|
||||
isYakuman: false,
|
||||
|
@ -443,7 +452,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'chinitsu',
|
||||
fan: 6,
|
||||
isYakuman: false,
|
||||
|
@ -470,7 +480,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'iipeko',
|
||||
fan: 1,
|
||||
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;
|
||||
|
||||
// 同じ順子が2つあるか?
|
||||
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) == 1;
|
||||
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) === 1;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'ryampeko',
|
||||
fan: 3,
|
||||
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;
|
||||
|
||||
// 2つの同じ順子が2組あるか?
|
||||
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) == 2;
|
||||
return countIndenticalMentsuPairs(fourMentsuOneJyantou.mentsus) === 2;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'toitoi',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -512,30 +525,34 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'sananko',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
||||
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) == 3;
|
||||
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) === 3;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'honroto',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
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));
|
||||
}
|
||||
}, {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sankantsu',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: 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',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -569,7 +586,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'sanshoku-doko',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -603,7 +621,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'ittsu',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -612,7 +631,7 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
if (fourMentsuOneJyantou == null) return false;
|
||||
|
||||
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] === 'm4' && tiles[1] === 'm5' && tiles[2] === 'm6')) {
|
||||
|
@ -638,7 +657,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'chanta',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -658,15 +678,16 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
// いずれかの雀頭か面子に字牌を含まないとダメ
|
||||
if (!(includes(CHAR_TILES, head) ||
|
||||
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))) &&
|
||||
huros.every(huro => huro.type == 'cii' ?
|
||||
huros.every(huro => huro.type === 'cii' ?
|
||||
huro.tiles.some(tile => includes(YAOCHU_TILES, tile)) :
|
||||
includes(YAOCHU_TILES, huro.tile)));
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'junchan',
|
||||
fan: 3,
|
||||
isYakuman: false,
|
||||
|
@ -685,11 +706,12 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
// 全ての面子に老頭牌が含まれる
|
||||
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)) :
|
||||
includes(TERMINAL_TILES, huro.tile)));
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'chitoitsu',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -703,7 +725,8 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
}
|
||||
return Array.from(countMap.values()).every(c => c === 2);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'shosangen',
|
||||
fan: 2,
|
||||
isYakuman: false,
|
||||
|
@ -730,23 +753,27 @@ new SeatWind('seat-wind-n', 'n'),
|
|||
|
||||
return false;
|
||||
},
|
||||
}];
|
||||
},
|
||||
];
|
||||
|
||||
export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
||||
export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [
|
||||
{
|
||||
name: 'suanko-tanki',
|
||||
isYakuman: true,
|
||||
isDoubleYakuman: true,
|
||||
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',
|
||||
isYakuman: true,
|
||||
upper: 'suanko-tanki',
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantouWithWait | null) => {
|
||||
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) == 4;
|
||||
}
|
||||
}, {
|
||||
return fourMentsuOneJyantou != null && countAnkos(state, fourMentsuOneJyantou) === 4;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'daisangen',
|
||||
isYakuman: true,
|
||||
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');
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'shosushi',
|
||||
isYakuman: true,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
|
@ -792,7 +820,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
|||
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'daisushi',
|
||||
isYakuman: true,
|
||||
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');
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'tsuiso',
|
||||
isYakuman: true,
|
||||
calc: (state: EnvForCalcYaku) => {
|
||||
|
@ -832,7 +862,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
|||
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'ryuiso',
|
||||
isYakuman: true,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
|
@ -847,22 +878,25 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
|||
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'chinroto',
|
||||
isYakuman: true,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: 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));
|
||||
}
|
||||
}, {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sukantsu',
|
||||
isYakuman: true,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: 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',
|
||||
isYakuman: true,
|
||||
isDoubleYakuman: true,
|
||||
|
@ -901,7 +935,8 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
|||
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'churen',
|
||||
upper: 'churen-9',
|
||||
isYakuman: true,
|
||||
|
@ -933,34 +968,39 @@ export const YAKUMAN_DEFINITIONS: YakumanDefinition[] = [{
|
|||
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'kokushi-13',
|
||||
isYakuman: true,
|
||||
isDoubleYakuman: true,
|
||||
calc: (state: EnvForCalcYaku, fourMentsuOneJyantou: FourMentsuOneJyantou | null) => {
|
||||
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',
|
||||
isYakuman: true,
|
||||
upper: 'kokushi-13',
|
||||
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',
|
||||
isYakuman: true,
|
||||
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',
|
||||
isYakuman: true,
|
||||
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 {
|
||||
switch (huro.type) {
|
||||
|
@ -970,7 +1010,7 @@ export function convertHuroForCalcYaku(huro: Huro): HuroForCalcYaku {
|
|||
return {
|
||||
type: huro.type,
|
||||
tile: TILE_ID_MAP.get(huro.tiles[0])!.t,
|
||||
}
|
||||
};
|
||||
case 'cii':
|
||||
return {
|
||||
type: 'cii',
|
||||
|
@ -986,7 +1026,7 @@ const NORMAL_YAKU_DATA_MAP = new Map<NormalYakuName, Required<NormalYakuData>>(
|
|||
fan: yaku.fan,
|
||||
isYakuman: false,
|
||||
kuisagari: yaku.kuisagari ?? false,
|
||||
}] as const)
|
||||
}] as const),
|
||||
);
|
||||
|
||||
const YAKUMAN_DATA_MAP = new Map<YakuName, Required<YakumanData>>(
|
||||
|
@ -996,7 +1036,7 @@ const YAKUMAN_DATA_MAP = new Map<YakuName, Required<YakumanData>>(
|
|||
fan: null,
|
||||
isYakuman: true,
|
||||
isDoubleYakuman: yaku.isDoubleYakuman ?? false,
|
||||
}])
|
||||
}]),
|
||||
);
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
if (state.handTiles.length + state.huros.length * 3 != 14) {
|
||||
if (state.handTiles.length + state.huros.length * 3 !== 14) {
|
||||
throw new TypeError('Invalid tile count');
|
||||
}
|
||||
|
||||
|
@ -1017,7 +1057,7 @@ export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
|||
if (oneHeadFourMentsuPatterns.length === 0) oneHeadFourMentsuPatterns.push(null);
|
||||
|
||||
const waitPatterns = oneHeadFourMentsuPatterns.map(
|
||||
fourMentsuOneJyantou => calcWaitPatterns(fourMentsuOneJyantou, agariTile)
|
||||
fourMentsuOneJyantou => calcWaitPatterns(fourMentsuOneJyantou, agariTile),
|
||||
).flat();
|
||||
|
||||
const yakumanPatterns = waitPatterns.map(fourMentsuOneJyantouWithWait => {
|
||||
|
@ -1038,13 +1078,13 @@ export function calcYakusWithDetail(state: EnvForCalcYaku): YakuSet {
|
|||
|
||||
const yakuPatterns = waitPatterns.map(
|
||||
fourMentsuOneJyantouWithWait => NORMAL_YAKU_DEFINITIONS.filter(
|
||||
yakuDef => yakuDef.calc(state, fourMentsuOneJyantouWithWait)
|
||||
).map(yakuDef => NORMAL_YAKU_DATA_MAP.get(yakuDef.name)!)
|
||||
yakuDef => yakuDef.calc(state, fourMentsuOneJyantouWithWait),
|
||||
).map(yakuDef => NORMAL_YAKU_DATA_MAP.get(yakuDef.name)!),
|
||||
).filter(yakus => yakus.length > 0);
|
||||
|
||||
const isMenzen = state.huros.some(huro => includes(CALL_HURO_TYPES, huro.type));
|
||||
|
||||
if (yakuPatterns.length == 0) {
|
||||
if (yakuPatterns.length === 0) {
|
||||
return new NormalYakuSet(isMenzen, []);
|
||||
}
|
||||
|
||||
|
|
|
@ -686,7 +686,7 @@ export class MasterGameEngine {
|
|||
doubleRiichi: tx.$state.doubleRiichis[house],
|
||||
ippatsu: tx.$state.ippatsus[house],
|
||||
rinshan: tx.$state.rinshanFlags[house],
|
||||
haitei: tx.$state.tiles.length == 0,
|
||||
haitei: tx.$state.tiles.length === 0,
|
||||
});
|
||||
const doraCount =
|
||||
Common.calcOwnedDoraCount(tx.handTileTypes[house], tx.$state.huros[house], tx.doras) +
|
||||
|
@ -743,7 +743,7 @@ export class MasterGameEngine {
|
|||
riichi: tx.$state.riichis[house],
|
||||
doubleRiichi: tx.$state.doubleRiichis[house],
|
||||
ippatsu: tx.$state.ippatsus[house],
|
||||
hotei: tx.$state.tiles.length == 0,
|
||||
hotei: tx.$state.tiles.length === 0,
|
||||
});
|
||||
const doraCount =
|
||||
Common.calcOwnedDoraCount(tx.handTileTypes[house], tx.$state.huros[house], tx.doras) +
|
||||
|
|
|
@ -270,7 +270,7 @@ export class PlayerGameEngine {
|
|||
doubleRiichi: this.state.doubleRiichis[house],
|
||||
ippatsu: this.state.ippatsus[house],
|
||||
rinshan: this.state.rinshanFlags[house],
|
||||
haitei: this.state.tilesCount == 0,
|
||||
haitei: this.state.tilesCount === 0,
|
||||
});
|
||||
const doraCount =
|
||||
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],
|
||||
doubleRiichi: this.state.doubleRiichis[house],
|
||||
ippatsu: this.state.ippatsus[house],
|
||||
hotei: this.state.tilesCount == 0,
|
||||
hotei: this.state.tilesCount === 0,
|
||||
});
|
||||
const doraCount =
|
||||
Common.calcOwnedDoraCount(handTiles[house].map(id => $type(id)), this.state.huros[house], this.doras) +
|
||||
|
|
Loading…
Reference in New Issue