wip
This commit is contained in:
parent
76cdb48a3e
commit
b302796e70
|
@ -345,8 +345,8 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
||||||
});
|
});
|
||||||
this.endKyoku(room, mj);
|
this.endKyoku(room, mj);
|
||||||
break;
|
break;
|
||||||
case 'ryukyoku':
|
case 'ryuukyoku':
|
||||||
this.globalEventService.publishMahjongRoomStream(room.id, 'ryukyoku', {
|
this.globalEventService.publishMahjongRoomStream(room.id, 'ryuukyoku', {
|
||||||
});
|
});
|
||||||
this.endKyoku(room, mj);
|
this.endKyoku(room, mj);
|
||||||
break;
|
break;
|
||||||
|
@ -387,7 +387,11 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
||||||
|
|
||||||
const aiHouses = [[1, room.user1Ai], [2, room.user2Ai], [3, room.user3Ai], [4, room.user4Ai]].filter(([id, ai]) => ai).map(([id, ai]) => mj.getHouse(id));
|
const aiHouses = [[1, room.user1Ai], [2, room.user2Ai], [3, room.user3Ai], [4, room.user4Ai]].filter(([id, ai]) => ai).map(([id, ai]) => mj.getHouse(id));
|
||||||
|
|
||||||
if (res.asking) {
|
if (res.ryuukyoku) {
|
||||||
|
this.endKyoku(room, mj);
|
||||||
|
this.globalEventService.publishMahjongRoomStream(room.id, 'ryuukyoku', {
|
||||||
|
});
|
||||||
|
} else if (res.asking) {
|
||||||
const answers: CallingAnswers = {
|
const answers: CallingAnswers = {
|
||||||
pon: null,
|
pon: null,
|
||||||
cii: null,
|
cii: null,
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
|
@ -168,6 +168,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div :class="$style.ryuukyokuContainer">
|
||||||
|
<Transition
|
||||||
|
:enterActiveClass="$style.transition_serif_enterActive"
|
||||||
|
:leaveActiveClass="$style.transition_serif_leaveActive"
|
||||||
|
:enterFromClass="$style.transition_serif_enterFrom"
|
||||||
|
:leaveToClass="$style.transition_serif_leaveTo"
|
||||||
|
>
|
||||||
|
<img v-if="ryuukyokued" :src="`/client-assets/mahjong/ryuukyoku.png`" style="display: block; width: 100%;"/>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div :class="$style.actions" class="_buttons">
|
<div :class="$style.actions" class="_buttons">
|
||||||
<MkButton v-if="mj.canRon != null" primary gradate @click="ron">Ron</MkButton>
|
<MkButton v-if="mj.canRon != null" primary gradate @click="ron">Ron</MkButton>
|
||||||
<MkButton v-if="mj.canPon != null" primary @click="pon">Pon</MkButton>
|
<MkButton v-if="mj.canPon != null" primary @click="pon">Pon</MkButton>
|
||||||
|
@ -259,6 +270,22 @@ const ponSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false
|
||||||
const kanSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false, w: false, n: false });
|
const kanSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||||
const tsumoSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false, w: false, n: false });
|
const tsumoSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||||
const riichiSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false, w: false, n: false });
|
const riichiSerifHouses = reactive<Record<Mmj.House, boolean>>({ e: false, s: false, w: false, n: false });
|
||||||
|
const iTsumoed = ref(false);
|
||||||
|
const showKyokuResults = ref(false);
|
||||||
|
const kyokuResults = ref<Record<Mmj.House, {
|
||||||
|
yakus: {
|
||||||
|
name: string;
|
||||||
|
fan: number;
|
||||||
|
}[];
|
||||||
|
doraCount: number;
|
||||||
|
pointDeltas: Record<Mmj.House, number>;
|
||||||
|
} | null>>({
|
||||||
|
e: null,
|
||||||
|
s: null,
|
||||||
|
w: null,
|
||||||
|
n: null,
|
||||||
|
});
|
||||||
|
const ryuukyokued = ref(false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (room.value.isStarted && !room.value.isEnded) {
|
if (room.value.isStarted && !room.value.isEnded) {
|
||||||
|
@ -387,7 +414,7 @@ function cii(ev: MouseEvent) {
|
||||||
os.popupMenu(patterns.map(pattern => ({
|
os.popupMenu(patterns.map(pattern => ({
|
||||||
text: pattern.join(' '),
|
text: pattern.join(' '),
|
||||||
action: () => {
|
action: () => {
|
||||||
const index = Mmj.sortTileTypes(pattern).indexOf(targetTile);
|
const index = Mmj.sortTileTypes(pattern).indexOf(mj$type(targetTile));
|
||||||
props.connection!.send('cii', {
|
props.connection!.send('cii', {
|
||||||
pattern: index === 0 ? 'x__' : index === 1 ? '_x_' : '__x',
|
pattern: index === 0 ? 'x__' : index === 1 ? '_x_' : '__x',
|
||||||
});
|
});
|
||||||
|
@ -407,26 +434,6 @@ function skip() {
|
||||||
props.connection!.send('nop', {});
|
props.connection!.send('nop', {});
|
||||||
}
|
}
|
||||||
|
|
||||||
const iTsumoed = ref(false);
|
|
||||||
const showKyokuResults = ref(false);
|
|
||||||
const kyokuResults = ref<Record<Mmj.House, {
|
|
||||||
yakus: {
|
|
||||||
name: string;
|
|
||||||
fan: number;
|
|
||||||
}[];
|
|
||||||
doraCount: number;
|
|
||||||
pointDeltas: Record<Mmj.House, number>;
|
|
||||||
} | null>>({
|
|
||||||
e: null,
|
|
||||||
s: null,
|
|
||||||
w: null,
|
|
||||||
n: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
function kyokuEnd() {
|
|
||||||
showKyokuResults.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onStreamDahai(log) {
|
function onStreamDahai(log) {
|
||||||
console.log('onStreamDahai', log);
|
console.log('onStreamDahai', log);
|
||||||
|
|
||||||
|
@ -617,6 +624,16 @@ function onStreamTsumoHora(log) {
|
||||||
console.log('tsumohora', res);
|
console.log('tsumohora', res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onStreamRyuukyoku(log) {
|
||||||
|
console.log('onStreamRyuukyoku', log);
|
||||||
|
|
||||||
|
ryuukyokued.value = true;
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
showKyokuResults.value = true;
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
function restoreRoom(_room) {
|
function restoreRoom(_room) {
|
||||||
room.value = deepClone(_room);
|
room.value = deepClone(_room);
|
||||||
|
|
||||||
|
@ -635,6 +652,7 @@ onMounted(() => {
|
||||||
props.connection.on('ciied', onStreamCiied);
|
props.connection.on('ciied', onStreamCiied);
|
||||||
props.connection.on('ronned', onStreamRonned);
|
props.connection.on('ronned', onStreamRonned);
|
||||||
props.connection.on('tsumoHora', onStreamTsumoHora);
|
props.connection.on('tsumoHora', onStreamTsumoHora);
|
||||||
|
props.connection.on('ryuukyoku', onStreamRyuukyoku);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -650,6 +668,7 @@ onActivated(() => {
|
||||||
props.connection.on('ciied', onStreamCiied);
|
props.connection.on('ciied', onStreamCiied);
|
||||||
props.connection.on('ronned', onStreamRonned);
|
props.connection.on('ronned', onStreamRonned);
|
||||||
props.connection.on('tsumoHora', onStreamTsumoHora);
|
props.connection.on('tsumoHora', onStreamTsumoHora);
|
||||||
|
props.connection.on('ryuukyoku', onStreamRyuukyoku);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -665,6 +684,7 @@ onDeactivated(() => {
|
||||||
props.connection.off('ciied', onStreamCiied);
|
props.connection.off('ciied', onStreamCiied);
|
||||||
props.connection.off('ronned', onStreamRonned);
|
props.connection.off('ronned', onStreamRonned);
|
||||||
props.connection.off('tsumoHora', onStreamTsumoHora);
|
props.connection.off('tsumoHora', onStreamTsumoHora);
|
||||||
|
props.connection.off('ryuukyoku', onStreamRyuukyoku);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -680,6 +700,7 @@ onUnmounted(() => {
|
||||||
props.connection.off('ciied', onStreamCiied);
|
props.connection.off('ciied', onStreamCiied);
|
||||||
props.connection.off('ronned', onStreamRonned);
|
props.connection.off('ronned', onStreamRonned);
|
||||||
props.connection.off('tsumoHora', onStreamTsumoHora);
|
props.connection.off('tsumoHora', onStreamTsumoHora);
|
||||||
|
props.connection.off('ryuukyoku', onStreamRyuukyoku);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -969,6 +990,19 @@ onUnmounted(() => {
|
||||||
height: min-content;
|
height: min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ryuukyokuContainer {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 200px;
|
||||||
|
height: min-content;
|
||||||
|
margin: auto;
|
||||||
|
z-index: 100;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.sideTile {
|
.sideTile {
|
||||||
margin-bottom: -26px;
|
margin-bottom: -26px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,12 +253,12 @@ export class MasterGameEngine {
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private canRon(house: House, tile: TileId): boolean {
|
private canRon(house: House, tileId: TileId): boolean {
|
||||||
// フリテン
|
// フリテン
|
||||||
// TODO: ポンされるなどして自分の河にない場合の考慮
|
// TODO: ポンされるなどして自分の河にない場合の考慮
|
||||||
if (this.hoTileTypes[house].includes($type(tile))) return false;
|
if (this.hoTileTypes[house].includes($type(tileId))) return false;
|
||||||
|
|
||||||
const horaSets = Common.getHoraSets(this.handTileTypes[house].concat($type(tile)));
|
const horaSets = Common.getHoraSets(this.handTileTypes[house].concat($type(tileId)));
|
||||||
if (horaSets.length === 0) return false; // 完成形じゃない
|
if (horaSets.length === 0) return false; // 完成形じゃない
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -268,15 +268,15 @@ export class MasterGameEngine {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private canPon(house: House, tile: TileId): boolean {
|
private canPon(house: House, tileId: TileId): boolean {
|
||||||
return this.handTileTypes[house].filter(t => t === $type(tile)).length === 2;
|
return this.handTileTypes[house].filter(t => t === $type(tileId)).length === 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private canCii(caller: House, callee: House, tile: TileId): boolean {
|
private canCii(caller: House, callee: House, tileId: TileId): boolean {
|
||||||
if (callee !== Common.prevHouse(caller)) return false;
|
if (callee !== Common.prevHouse(caller)) return false;
|
||||||
const hand = this.handTileTypes[caller];
|
const hand = this.handTileTypes[caller];
|
||||||
return Common.SHUNTU_PATTERNS.some(pattern =>
|
return Common.SHUNTU_PATTERNS.some(pattern =>
|
||||||
pattern.includes($type(tile)) &&
|
pattern.includes($type(tileId)) &&
|
||||||
pattern.filter(t => hand.includes(t)).length >= 2);
|
pattern.filter(t => hand.includes(t)).length >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,20 +325,20 @@ export class MasterGameEngine {
|
||||||
this.endKyoku();
|
this.endKyoku();
|
||||||
}
|
}
|
||||||
|
|
||||||
public commit_dahai(house: House, tile: TileId, riichi = false) {
|
public commit_dahai(house: House, tileId: TileId, riichi = false) {
|
||||||
if (this.state.turn !== house) throw new Error('Not your turn');
|
if (this.state.turn !== house) throw new Error('Not your turn');
|
||||||
|
|
||||||
if (riichi) {
|
if (riichi) {
|
||||||
const tempHandTiles = [...this.handTileTypes[house]];
|
const tempHandTiles = [...this.handTileTypes[house]];
|
||||||
tempHandTiles.splice(tempHandTiles.indexOf($type(tile)), 1);
|
tempHandTiles.splice(tempHandTiles.indexOf($type(tileId)), 1);
|
||||||
if (Common.getHoraTiles(tempHandTiles).length === 0) throw new Error('Not tenpai');
|
if (Common.getHoraTiles(tempHandTiles).length === 0) throw new Error('Not tenpai');
|
||||||
if (this.state.points[house] < 1000) throw new Error('Not enough points');
|
if (this.state.points[house] < 1000) throw new Error('Not enough points');
|
||||||
}
|
}
|
||||||
|
|
||||||
const handTiles = this.state.handTiles[house];
|
const handTiles = this.state.handTiles[house];
|
||||||
if (!handTiles.includes(tile)) throw new Error('No such tile in your hand');
|
if (!handTiles.includes(tileId)) throw new Error('No such tile in your hand');
|
||||||
handTiles.splice(handTiles.indexOf(tile), 1);
|
handTiles.splice(handTiles.indexOf(tileId), 1);
|
||||||
this.state.hoTiles[house].push(tile);
|
this.state.hoTiles[house].push(tileId);
|
||||||
|
|
||||||
if (riichi) {
|
if (riichi) {
|
||||||
this.state.riichis[house] = true;
|
this.state.riichis[house] = true;
|
||||||
|
@ -347,24 +347,24 @@ export class MasterGameEngine {
|
||||||
const canRonHouses: House[] = [];
|
const canRonHouses: House[] = [];
|
||||||
switch (house) {
|
switch (house) {
|
||||||
case 'e':
|
case 'e':
|
||||||
if (this.canRon('s', tile)) canRonHouses.push('s');
|
if (this.canRon('s', tileId)) canRonHouses.push('s');
|
||||||
if (this.canRon('w', tile)) canRonHouses.push('w');
|
if (this.canRon('w', tileId)) canRonHouses.push('w');
|
||||||
if (this.canRon('n', tile)) canRonHouses.push('n');
|
if (this.canRon('n', tileId)) canRonHouses.push('n');
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (this.canRon('e', tile)) canRonHouses.push('e');
|
if (this.canRon('e', tileId)) canRonHouses.push('e');
|
||||||
if (this.canRon('w', tile)) canRonHouses.push('w');
|
if (this.canRon('w', tileId)) canRonHouses.push('w');
|
||||||
if (this.canRon('n', tile)) canRonHouses.push('n');
|
if (this.canRon('n', tileId)) canRonHouses.push('n');
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
if (this.canRon('e', tile)) canRonHouses.push('e');
|
if (this.canRon('e', tileId)) canRonHouses.push('e');
|
||||||
if (this.canRon('s', tile)) canRonHouses.push('s');
|
if (this.canRon('s', tileId)) canRonHouses.push('s');
|
||||||
if (this.canRon('n', tile)) canRonHouses.push('n');
|
if (this.canRon('n', tileId)) canRonHouses.push('n');
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
if (this.canRon('e', tile)) canRonHouses.push('e');
|
if (this.canRon('e', tileId)) canRonHouses.push('e');
|
||||||
if (this.canRon('s', tile)) canRonHouses.push('s');
|
if (this.canRon('s', tileId)) canRonHouses.push('s');
|
||||||
if (this.canRon('w', tile)) canRonHouses.push('w');
|
if (this.canRon('w', tileId)) canRonHouses.push('w');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,18 +372,18 @@ export class MasterGameEngine {
|
||||||
|
|
||||||
let canPonHouse: House | null = null;
|
let canPonHouse: House | null = null;
|
||||||
switch (house) {
|
switch (house) {
|
||||||
case 'e': canPonHouse = this.canPon('s', tile) ? 's' : this.canPon('w', tile) ? 'w' : this.canPon('n', tile) ? 'n' : null; break;
|
case 'e': canPonHouse = this.canPon('s', tileId) ? 's' : this.canPon('w', tileId) ? 'w' : this.canPon('n', tileId) ? 'n' : null; break;
|
||||||
case 's': canPonHouse = this.canPon('e', tile) ? 'e' : this.canPon('w', tile) ? 'w' : this.canPon('n', tile) ? 'n' : null; break;
|
case 's': canPonHouse = this.canPon('e', tileId) ? 'e' : this.canPon('w', tileId) ? 'w' : this.canPon('n', tileId) ? 'n' : null; break;
|
||||||
case 'w': canPonHouse = this.canPon('e', tile) ? 'e' : this.canPon('s', tile) ? 's' : this.canPon('n', tile) ? 'n' : null; break;
|
case 'w': canPonHouse = this.canPon('e', tileId) ? 'e' : this.canPon('s', tileId) ? 's' : this.canPon('n', tileId) ? 'n' : null; break;
|
||||||
case 'n': canPonHouse = this.canPon('e', tile) ? 'e' : this.canPon('s', tile) ? 's' : this.canPon('w', tile) ? 'w' : null; break;
|
case 'n': canPonHouse = this.canPon('e', tileId) ? 'e' : this.canPon('s', tileId) ? 's' : this.canPon('w', tileId) ? 'w' : null; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let canCiiHouse: House | null = null;
|
let canCiiHouse: House | null = null;
|
||||||
switch (house) {
|
switch (house) {
|
||||||
case 'e': canCiiHouse = this.canCii('s', house, tile) ? 's' : this.canCii('w', house, tile) ? 'w' : this.canCii('n', house, tile) ? 'n' : null; break;
|
case 'e': canCiiHouse = this.canCii('s', house, tileId) ? 's' : this.canCii('w', house, tileId) ? 'w' : this.canCii('n', house, tileId) ? 'n' : null; break;
|
||||||
case 's': canCiiHouse = this.canCii('e', house, tile) ? 'e' : this.canCii('w', house, tile) ? 'w' : this.canCii('n', house, tile) ? 'n' : null; break;
|
case 's': canCiiHouse = this.canCii('e', house, tileId) ? 'e' : this.canCii('w', house, tileId) ? 'w' : this.canCii('n', house, tileId) ? 'n' : null; break;
|
||||||
case 'w': canCiiHouse = this.canCii('e', house, tile) ? 'e' : this.canCii('s', house, tile) ? 's' : this.canCii('n', house, tile) ? 'n' : null; break;
|
case 'w': canCiiHouse = this.canCii('e', house, tileId) ? 'e' : this.canCii('s', house, tileId) ? 's' : this.canCii('n', house, tileId) ? 'n' : null; break;
|
||||||
case 'n': canCiiHouse = this.canCii('e', house, tile) ? 'e' : this.canCii('s', house, tile) ? 's' : this.canCii('w', house, tile) ? 'w' : null; break;
|
case 'n': canCiiHouse = this.canCii('e', house, tileId) ? 'e' : this.canCii('s', house, tileId) ? 's' : this.canCii('w', house, tileId) ? 'w' : null; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canRonHouses.length > 0 || canPonHouse != null || canCiiHouse != null) {
|
if (canRonHouses.length > 0 || canPonHouse != null || canCiiHouse != null) {
|
||||||
|
@ -422,6 +422,18 @@ export class MasterGameEngine {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 流局
|
||||||
|
if (this.state.tiles.length === 0) {
|
||||||
|
this.state.turn = null;
|
||||||
|
|
||||||
|
this.endKyoku();
|
||||||
|
|
||||||
|
return {
|
||||||
|
asking: false as const,
|
||||||
|
ryuukyoku: true as const,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
this.state.turn = Common.nextHouse(house);
|
this.state.turn = Common.nextHouse(house);
|
||||||
|
|
||||||
const tsumoTile = this.tsumo();
|
const tsumoTile = this.tsumo();
|
||||||
|
@ -433,11 +445,11 @@ export class MasterGameEngine {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public commit_kakan(house: House, tile: TileId) {
|
public commit_kakan(house: House, tileId: TileId) {
|
||||||
const pon = this.state.huros[house].find(h => h.type === 'pon' && $type(h.tiles[0]) === $type(tile));
|
const pon = this.state.huros[house].find(h => h.type === 'pon' && $type(h.tiles[0]) === $type(tileId));
|
||||||
if (pon == null) throw new Error('No such pon');
|
if (pon == null) throw new Error('No such pon');
|
||||||
this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(tile), 1);
|
this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(tileId), 1);
|
||||||
const tiles = [tile, ...pon.tiles];
|
const tiles = [tileId, ...pon.tiles];
|
||||||
this.state.huros[house].push({ type: 'minkan', tiles: tiles, from: pon.from });
|
this.state.huros[house].push({ type: 'minkan', tiles: tiles, from: pon.from });
|
||||||
|
|
||||||
this.state.activatedDorasCount++;
|
this.state.activatedDorasCount++;
|
||||||
|
@ -451,14 +463,14 @@ export class MasterGameEngine {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public commit_ankan(house: House, tile: TileId) {
|
public commit_ankan(house: House, tileId: TileId) {
|
||||||
const t1 = this.state.handTiles[house].filter(t => $type(t) === $type(tile)).at(0);
|
const t1 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(0);
|
||||||
if (t1 == null) throw new Error('No such tile');
|
if (t1 == null) throw new Error('No such tile');
|
||||||
const t2 = this.state.handTiles[house].filter(t => $type(t) === $type(tile)).at(1);
|
const t2 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(1);
|
||||||
if (t2 == null) throw new Error('No such tile');
|
if (t2 == null) throw new Error('No such tile');
|
||||||
const t3 = this.state.handTiles[house].filter(t => $type(t) === $type(tile)).at(2);
|
const t3 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(2);
|
||||||
if (t3 == null) throw new Error('No such tile');
|
if (t3 == null) throw new Error('No such tile');
|
||||||
const t4 = this.state.handTiles[house].filter(t => $type(t) === $type(tile)).at(3);
|
const t4 = this.state.handTiles[house].filter(t => $type(t) === $type(tileId)).at(3);
|
||||||
if (t4 == null) throw new Error('No such tile');
|
if (t4 == null) throw new Error('No such tile');
|
||||||
this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(t1), 1);
|
this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(t1), 1);
|
||||||
this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(t2), 1);
|
this.state.handTiles[house].splice(this.state.handTiles[house].indexOf(t2), 1);
|
||||||
|
@ -660,7 +672,7 @@ export class MasterGameEngine {
|
||||||
this.endKyoku();
|
this.endKyoku();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'ryukyoku' as const,
|
type: 'ryuukyoku' as const,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
this.state.turn = this.state.nextTurnAfterAsking!;
|
this.state.turn = this.state.nextTurnAfterAsking!;
|
||||||
|
|
|
@ -152,19 +152,19 @@ export class PlayerGameEngine {
|
||||||
return this.state.riichis[this.myHouse];
|
return this.state.riichis[this.myHouse];
|
||||||
}
|
}
|
||||||
|
|
||||||
public commit_tsumo(house: House, tile: TileId) {
|
public commit_tsumo(house: House, tileId: TileId) {
|
||||||
console.log('commit_tsumo', this.state.turn, house, tile);
|
console.log('commit_tsumo', this.state.turn, house, tileId);
|
||||||
this.state.tilesCount--;
|
this.state.tilesCount--;
|
||||||
this.state.turn = house;
|
this.state.turn = house;
|
||||||
if (house === this.myHouse) {
|
if (house === this.myHouse) {
|
||||||
this.myHandTiles.push(tile);
|
this.myHandTiles.push(tileId);
|
||||||
} else {
|
} else {
|
||||||
this.state.handTiles[house].push(0);
|
this.state.handTiles[house].push(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public commit_dahai(house: House, tile: TileId, riichi = false) {
|
public commit_dahai(house: House, tileId: TileId, riichi = false) {
|
||||||
console.log('commit_dahai', this.state.turn, house, tile, riichi);
|
console.log('commit_dahai', this.state.turn, house, tileId, riichi);
|
||||||
if (this.state.turn !== house) throw new PlayerGameEngine.InvalidOperationError();
|
if (this.state.turn !== house) throw new PlayerGameEngine.InvalidOperationError();
|
||||||
|
|
||||||
if (riichi) {
|
if (riichi) {
|
||||||
|
@ -172,29 +172,29 @@ export class PlayerGameEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (house === this.myHouse) {
|
if (house === this.myHouse) {
|
||||||
this.myHandTiles.splice(this.myHandTiles.indexOf(tile), 1);
|
this.myHandTiles.splice(this.myHandTiles.indexOf(tileId), 1);
|
||||||
this.state.hoTiles[this.myHouse].push(tile);
|
this.state.hoTiles[this.myHouse].push(tileId);
|
||||||
} else {
|
} else {
|
||||||
this.state.handTiles[house].pop();
|
this.state.handTiles[house].pop();
|
||||||
this.state.hoTiles[house].push(tile);
|
this.state.hoTiles[house].push(tileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state.turn = null;
|
this.state.turn = null;
|
||||||
|
|
||||||
if (house === this.myHouse) {
|
if (house === this.myHouse) {
|
||||||
} else {
|
} else {
|
||||||
const canRon = Common.getHoraSets(this.myHandTiles.concat(tile).map(id => $type(id))).length > 0;
|
const canRon = Common.getHoraSets(this.myHandTiles.concat(tileId).map(id => $type(id))).length > 0;
|
||||||
const canPon = !this.isMeRiichi && this.myHandTiles.filter(t => t === tile).length === 2;
|
const canPon = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tileId)).length === 2;
|
||||||
const canKan = !this.isMeRiichi && this.myHandTiles.filter(t => t === tile).length === 3;
|
const canKan = !this.isMeRiichi && this.myHandTileTypes.filter(t => t === $type(tileId)).length === 3;
|
||||||
const canCii = !this.isMeRiichi && house === Common.prevHouse(this.myHouse) &&
|
const canCii = !this.isMeRiichi && house === Common.prevHouse(this.myHouse) &&
|
||||||
Common.SHUNTU_PATTERNS.some(pattern =>
|
Common.SHUNTU_PATTERNS.some(pattern =>
|
||||||
pattern.includes($type(tile)) &&
|
pattern.includes($type(tileId)) &&
|
||||||
pattern.filter(t => this.myHandTileTypes.includes(t)).length >= 2);
|
pattern.filter(t => this.myHandTileTypes.includes(t)).length >= 2);
|
||||||
|
|
||||||
if (canRon) this.state.canRon = { callee: house };
|
this.state.canRon = canRon ? { callee: house } : null;
|
||||||
if (canPon) this.state.canPon = { callee: house };
|
this.state.canPon = canPon ? { callee: house } : null;
|
||||||
if (canKan) this.state.canKan = { callee: house };
|
this.state.canKan = canKan ? { callee: house } : null;
|
||||||
if (canCii) this.state.canCii = { callee: house };
|
this.state.canCii = canCii ? { callee: house } : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue