mirror of
https://github.com/misskey-dev/misskey.git
synced 2025-02-06 04:58:02 +09:00
wip
This commit is contained in:
parent
084e9449dc
commit
bb042b46ac
@ -657,8 +657,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
|||||||
|
|
||||||
if (mj.riichis[house]) {
|
if (mj.riichis[house]) {
|
||||||
// リーチ時はアガリ牌でない限りツモ切り
|
// リーチ時はアガリ牌でない限りツモ切り
|
||||||
const horaSets = Mmj.getHoraSets(mj.handTileTypes[house]);
|
if (!Mmj.canHora(mj.handTileTypes[house])) {
|
||||||
if (horaSets.length === 0) {
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.dahai(room, mj, house, mj.handTiles[house].at(-1));
|
this.dahai(room, mj, house, mj.handTiles[house].at(-1));
|
||||||
}, 500);
|
}, 500);
|
||||||
|
@ -292,7 +292,7 @@ const isMyTurn = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const canHora = computed(() => {
|
const canHora = computed(() => {
|
||||||
return Mmj.getHoraSets(mj.value.myHandTileTypes).length > 0;
|
return Mmj.canHora(mj.value.myHandTileTypes).length;
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectableTiles = ref<Mmj.TileType[] | null>(null);
|
const selectableTiles = ref<Mmj.TileType[] | null>(null);
|
||||||
|
@ -237,6 +237,8 @@ export const PREV_TILE_FOR_SHUNTSU: Record<TileType, TileType | null> = {
|
|||||||
chun: null,
|
chun: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const KOKUSHI_TILES: TileType[] = ['m1', 'm9', 'p1', 'p9', 's1', 's9', 'e', 's', 'w', 'n', 'haku', 'hatsu', 'chun'];
|
||||||
|
|
||||||
type EnvForCalcYaku = {
|
type EnvForCalcYaku = {
|
||||||
house: House;
|
house: House;
|
||||||
|
|
||||||
@ -471,7 +473,7 @@ export const YAKU_DEFINITIONS = [{
|
|||||||
|
|
||||||
// TODO: 両面待ちかどうか
|
// TODO: 両面待ちかどうか
|
||||||
|
|
||||||
const horaSets = getHoraSets(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
const horaSets = analyze1head3mentsuSets(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
||||||
return horaSets.some(horaSet => {
|
return horaSets.some(horaSet => {
|
||||||
// 風牌判定(役牌でなければOK)
|
// 風牌判定(役牌でなければOK)
|
||||||
if (horaSet.head === state.seatWind) return false;
|
if (horaSet.head === state.seatWind) return false;
|
||||||
@ -489,7 +491,7 @@ export const YAKU_DEFINITIONS = [{
|
|||||||
// 面前じゃないとダメ
|
// 面前じゃないとダメ
|
||||||
if (state.huros.some(huro => CALL_HURO_TYPES.includes(huro.type))) return false;
|
if (state.huros.some(huro => CALL_HURO_TYPES.includes(huro.type))) return false;
|
||||||
|
|
||||||
const horaSets = getHoraSets(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
const horaSets = analyze1head3mentsuSets(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
||||||
return horaSets.some(horaSet => {
|
return horaSets.some(horaSet => {
|
||||||
// 同じ順子が2つあるか?
|
// 同じ順子が2つあるか?
|
||||||
return horaSet.mentsus.some((mentsu) =>
|
return horaSet.mentsus.some((mentsu) =>
|
||||||
@ -505,12 +507,26 @@ export const YAKU_DEFINITIONS = [{
|
|||||||
if (state.huros.length > 0) {
|
if (state.huros.length > 0) {
|
||||||
if (state.huros.some(huro => huro.type === 'cii')) return false;
|
if (state.huros.some(huro => huro.type === 'cii')) return false;
|
||||||
}
|
}
|
||||||
const horaSets = getHoraSets(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
const horaSets = analyze1head3mentsuSets(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
||||||
return horaSets.some(horaSet => {
|
return horaSets.some(horaSet => {
|
||||||
// 全て刻子か?
|
// 全て刻子か?
|
||||||
if (!horaSet.mentsus.every((mentsu) => mentsu[0] === mentsu[1])) return false;
|
if (!horaSet.mentsus.every((mentsu) => mentsu[0] === mentsu[1])) return false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
name: 'chitoitsu',
|
||||||
|
fan: 2,
|
||||||
|
isYakuman: false,
|
||||||
|
calc: (state: EnvForCalcYaku) => {
|
||||||
|
return isChitoitsu(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: 'kokushi',
|
||||||
|
fan: 13,
|
||||||
|
isYakuman: true,
|
||||||
|
calc: (state: EnvForCalcYaku) => {
|
||||||
|
return isKokushi(state.handTiles.concat(state.tsumoTile ?? state.ronTile));
|
||||||
|
},
|
||||||
}];
|
}];
|
||||||
|
|
||||||
export function fanToPoint(fan: number, isParent: boolean): number {
|
export function fanToPoint(fan: number, isParent: boolean): number {
|
||||||
@ -709,7 +725,7 @@ function extractShuntsus(tiles: TileType[]): [TileType, TileType, TileType][] {
|
|||||||
* @param handTiles ポン、チー、カンした牌を含まない手牌
|
* @param handTiles ポン、チー、カンした牌を含まない手牌
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function getHoraSets(handTiles: TileType[]): HoraSet[] {
|
function analyze1head3mentsuSets(handTiles: TileType[]): HoraSet[] {
|
||||||
const horaSets: HoraSet[] = [];
|
const horaSets: HoraSet[] = [];
|
||||||
|
|
||||||
const headSet: TileType[] = [];
|
const headSet: TileType[] = [];
|
||||||
@ -808,6 +824,14 @@ export function getHoraSets(handTiles: TileType[]): HoraSet[] {
|
|||||||
return horaSets;
|
return horaSets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canHora(handTiles: TileType[]): boolean {
|
||||||
|
if (isKokushi(handTiles)) return true;
|
||||||
|
if (isChitoitsu(handTiles)) return true;
|
||||||
|
|
||||||
|
const horaSets = analyze1head3mentsuSets(handTiles);
|
||||||
|
return horaSets.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* アガリ牌リストを取得
|
* アガリ牌リストを取得
|
||||||
* @param handTiles ポン、チー、カンした牌を含まない手牌
|
* @param handTiles ポン、チー、カンした牌を含まない手牌
|
||||||
@ -815,14 +839,23 @@ export function getHoraSets(handTiles: TileType[]): HoraSet[] {
|
|||||||
export function getHoraTiles(handTiles: TileType[]): TileType[] {
|
export function getHoraTiles(handTiles: TileType[]): TileType[] {
|
||||||
return TILE_TYPES.filter(tile => {
|
return TILE_TYPES.filter(tile => {
|
||||||
const tempHandTiles = [...handTiles, tile];
|
const tempHandTiles = [...handTiles, tile];
|
||||||
const horaSets = getHoraSets(tempHandTiles);
|
const horaSets = analyze1head3mentsuSets(tempHandTiles);
|
||||||
return horaSets.length > 0;
|
return horaSets.length > 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 国士無双判定関数
|
function isKokushi(handTiles: TileType[]): boolean {
|
||||||
|
return KOKUSHI_TILES.every(t => handTiles.includes(t));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 七対子判定関数
|
function isChitoitsu(handTiles: TileType[]): boolean {
|
||||||
|
const countMap = new Map<TileType, number>();
|
||||||
|
for (const tile of handTiles) {
|
||||||
|
const count = (countMap.get(tile) ?? 0) + 1;
|
||||||
|
countMap.set(tile, count);
|
||||||
|
}
|
||||||
|
return Array.from(countMap.values()).every(c => c === 2);
|
||||||
|
}
|
||||||
|
|
||||||
export function getTilesForRiichi(handTiles: TileType[]): TileType[] {
|
export function getTilesForRiichi(handTiles: TileType[]): TileType[] {
|
||||||
return handTiles.filter(tile => {
|
return handTiles.filter(tile => {
|
||||||
|
@ -108,8 +108,7 @@ class StateManager {
|
|||||||
// TODO: ポンされるなどして自分の河にない場合の考慮
|
// TODO: ポンされるなどして自分の河にない場合の考慮
|
||||||
if (this.hoTileTypes[house].includes($type(tid))) return false;
|
if (this.hoTileTypes[house].includes($type(tid))) return false;
|
||||||
|
|
||||||
const horaSets = Common.getHoraSets(this.handTileTypes[house].concat($type(tid)));
|
if (!Common.canHora(this.handTileTypes[house].concat($type(tid)))) return false; // 完成形じゃない
|
||||||
if (horaSets.length === 0) return false; // 完成形じゃない
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
//const yakus = YAKU_DEFINITIONS.filter(yaku => yaku.calc(this.state, { tsumoTile: null, ronTile: tile }));
|
//const yakus = YAKU_DEFINITIONS.filter(yaku => yaku.calc(this.state, { tsumoTile: null, ronTile: tile }));
|
||||||
|
@ -218,7 +218,7 @@ export class PlayerGameEngine {
|
|||||||
|
|
||||||
if (house === this.myHouse) {
|
if (house === this.myHouse) {
|
||||||
} else {
|
} else {
|
||||||
const canRon = Common.getHoraSets(this.myHandTiles.concat(tid).map(id => $type(id))).length > 0;
|
const canRon = Common.canHora(this.myHandTiles.concat(tid).map(id => $type(id)));
|
||||||
const canPon = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tid)).length === 2;
|
const canPon = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tid)).length === 2;
|
||||||
const canKan = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tid)).length === 3;
|
const canKan = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tid)).length === 3;
|
||||||
const canCii = !this.isMeRiichi && house === Common.prevHouse(this.myHouse) &&
|
const canCii = !this.isMeRiichi && house === Common.prevHouse(this.myHouse) &&
|
||||||
|
Loading…
Reference in New Issue
Block a user