wip
|
@ -60,7 +60,7 @@ type Room = {
|
||||||
|
|
||||||
type CallingAnswers = {
|
type CallingAnswers = {
|
||||||
pon: null | boolean;
|
pon: null | boolean;
|
||||||
cii: null | false | [Mahjong.Tile, Mahjong.Tile, Mahjong.Tile];
|
cii: null | false | 'x__' | '_x_' | '__x';
|
||||||
kan: null | boolean;
|
kan: null | boolean;
|
||||||
ron: {
|
ron: {
|
||||||
e: null | boolean;
|
e: null | boolean;
|
||||||
|
@ -594,7 +594,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async commit_cii(roomId: MiMahjongGame['id'], user: MiUser, tiles: [Mahjong.Tile, Mahjong.Tile, Mahjong.Tile]) {
|
public async commit_cii(roomId: MiMahjongGame['id'], user: MiUser, pattern: 'x__' | '_x_' | '__x') {
|
||||||
const room = await this.getRoom(roomId);
|
const room = await this.getRoom(roomId);
|
||||||
if (room == null) return;
|
if (room == null) return;
|
||||||
if (room.gameState == null) return;
|
if (room.gameState == null) return;
|
||||||
|
@ -605,7 +605,7 @@ export class MahjongService implements OnApplicationShutdown, OnModuleInit {
|
||||||
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
|
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
|
||||||
if (current == null) throw new Error('no asking found');
|
if (current == null) throw new Error('no asking found');
|
||||||
const currentAnswers = JSON.parse(current) as CallingAnswers;
|
const currentAnswers = JSON.parse(current) as CallingAnswers;
|
||||||
currentAnswers.cii = tiles;
|
currentAnswers.cii = pattern;
|
||||||
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
|
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class MahjongRoomChannel extends Channel {
|
||||||
case 'tsumoHora': this.tsumoHora(); break;
|
case 'tsumoHora': this.tsumoHora(); break;
|
||||||
case 'ronHora': this.ronHora(); break;
|
case 'ronHora': this.ronHora(); break;
|
||||||
case 'pon': this.pon(); break;
|
case 'pon': this.pon(); break;
|
||||||
case 'cii': this.cii(body.tiles); break;
|
case 'cii': this.cii(body.pattern); break;
|
||||||
case 'kan': this.kan(); break;
|
case 'kan': this.kan(); break;
|
||||||
case 'ankan': this.ankan(body.tile); break;
|
case 'ankan': this.ankan(body.tile); break;
|
||||||
case 'kakan': this.kakan(body.tile); break;
|
case 'kakan': this.kakan(body.tile); break;
|
||||||
|
@ -122,10 +122,10 @@ class MahjongRoomChannel extends Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async cii(tiles: string[]) {
|
private async cii(pattern: string) {
|
||||||
if (this.user == null) return;
|
if (this.user == null) return;
|
||||||
|
|
||||||
this.mahjongService.commit_cii(this.roomId!, this.user, tiles);
|
this.mahjongService.commit_cii(this.roomId!, this.user, pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
|
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 7 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.7 KiB |
|
@ -781,7 +781,6 @@ onUnmounted(() => {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
box-shadow: 0px 8px 2px 0px #0003;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.handTilesOfKamitya {
|
.handTilesOfKamitya {
|
||||||
|
|
|
@ -101,6 +101,80 @@ export const NEXT_TILE_FOR_DORA_MAP: Record<Tile, Tile> = {
|
||||||
chun: 'haku',
|
chun: 'haku',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const NEXT_TILE_FOR_SHUNTSU: Record<Tile, Tile | null> = {
|
||||||
|
m1: 'm2',
|
||||||
|
m2: 'm3',
|
||||||
|
m3: 'm4',
|
||||||
|
m4: 'm5',
|
||||||
|
m5: 'm6',
|
||||||
|
m6: 'm7',
|
||||||
|
m7: 'm8',
|
||||||
|
m8: 'm9',
|
||||||
|
m9: null,
|
||||||
|
p1: 'p2',
|
||||||
|
p2: 'p3',
|
||||||
|
p3: 'p4',
|
||||||
|
p4: 'p5',
|
||||||
|
p5: 'p6',
|
||||||
|
p6: 'p7',
|
||||||
|
p7: 'p8',
|
||||||
|
p8: 'p9',
|
||||||
|
p9: null,
|
||||||
|
s1: 's2',
|
||||||
|
s2: 's3',
|
||||||
|
s3: 's4',
|
||||||
|
s4: 's5',
|
||||||
|
s5: 's6',
|
||||||
|
s6: 's7',
|
||||||
|
s7: 's8',
|
||||||
|
s8: 's9',
|
||||||
|
s9: null,
|
||||||
|
e: null,
|
||||||
|
s: null,
|
||||||
|
w: null,
|
||||||
|
n: null,
|
||||||
|
haku: null,
|
||||||
|
hatsu: null,
|
||||||
|
chun: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PREV_TILE_FOR_SHUNTSU: Record<Tile, Tile | null> = {
|
||||||
|
m1: null,
|
||||||
|
m2: 'm1',
|
||||||
|
m3: 'm2',
|
||||||
|
m4: 'm3',
|
||||||
|
m5: 'm4',
|
||||||
|
m6: 'm5',
|
||||||
|
m7: 'm6',
|
||||||
|
m8: 'm7',
|
||||||
|
m9: 'm8',
|
||||||
|
p1: null,
|
||||||
|
p2: 'p1',
|
||||||
|
p3: 'p2',
|
||||||
|
p4: 'p3',
|
||||||
|
p5: 'p4',
|
||||||
|
p6: 'p5',
|
||||||
|
p7: 'p6',
|
||||||
|
p8: 'p7',
|
||||||
|
p9: 'p8',
|
||||||
|
s1: null,
|
||||||
|
s2: 's1',
|
||||||
|
s3: 's2',
|
||||||
|
s4: 's3',
|
||||||
|
s5: 's4',
|
||||||
|
s6: 's5',
|
||||||
|
s7: 's6',
|
||||||
|
s8: 's7',
|
||||||
|
s9: 's8',
|
||||||
|
e: null,
|
||||||
|
s: null,
|
||||||
|
w: null,
|
||||||
|
n: null,
|
||||||
|
haku: null,
|
||||||
|
hatsu: null,
|
||||||
|
chun: null,
|
||||||
|
};
|
||||||
|
|
||||||
type EnvForCalcYaku = {
|
type EnvForCalcYaku = {
|
||||||
house: House;
|
house: House;
|
||||||
|
|
||||||
|
@ -627,3 +701,27 @@ export function getTilesForRiichi(handTiles: Tile[]): Tile[] {
|
||||||
export function nextTileForDora(tile: Tile): Tile {
|
export function nextTileForDora(tile: Tile): Tile {
|
||||||
return NEXT_TILE_FOR_DORA_MAP[tile];
|
return NEXT_TILE_FOR_DORA_MAP[tile];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAvailableCiiPatterns(handTiles: Tile[], targetTile: Tile): [Tile, Tile, Tile][] {
|
||||||
|
const patterns: [Tile, Tile, Tile][] = [];
|
||||||
|
const prev1 = PREV_TILE_FOR_SHUNTSU[targetTile];
|
||||||
|
const prev2 = prev1 != null ? PREV_TILE_FOR_SHUNTSU[prev1] : null;
|
||||||
|
const next1 = NEXT_TILE_FOR_SHUNTSU[targetTile];
|
||||||
|
const next2 = next1 != null ? NEXT_TILE_FOR_SHUNTSU[next1] : null;
|
||||||
|
if (prev2 != null && prev1 != null) {
|
||||||
|
if (handTiles.includes(prev2) && handTiles.includes(prev1)) {
|
||||||
|
patterns.push([prev2, prev1, targetTile]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prev1 != null && next1 != null) {
|
||||||
|
if (handTiles.includes(prev1) && handTiles.includes(next1)) {
|
||||||
|
patterns.push([prev1, targetTile, next1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (next1 != null && next2 != null) {
|
||||||
|
if (handTiles.includes(next1) && handTiles.includes(next2)) {
|
||||||
|
patterns.push([targetTile, next1, next2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return patterns;
|
||||||
|
}
|
||||||
|
|
|
@ -436,7 +436,7 @@ export class MasterGameEngine {
|
||||||
|
|
||||||
public commit_resolveCallingInterruption(answers: {
|
public commit_resolveCallingInterruption(answers: {
|
||||||
pon: boolean;
|
pon: boolean;
|
||||||
cii: false | [Tile, Tile, Tile];
|
cii: false | 'x__' | '_x_' | '__x';
|
||||||
kan: boolean;
|
kan: boolean;
|
||||||
ron: House[];
|
ron: House[];
|
||||||
}) {
|
}) {
|
||||||
|
@ -497,9 +497,42 @@ export class MasterGameEngine {
|
||||||
};
|
};
|
||||||
} else if (cii != null && answers.cii) {
|
} else if (cii != null && answers.cii) {
|
||||||
const tile = this.state.hoTiles[cii.callee].pop()!;
|
const tile = this.state.hoTiles[cii.callee].pop()!;
|
||||||
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(answers.cii[0]), 1);
|
let tiles: [Tile, Tile, Tile];
|
||||||
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(answers.cii[1]), 1);
|
|
||||||
this.state.huros[cii.caller].push({ type: 'cii', tiles: [tile, answers.cii[0], answers.cii[1]], from: cii.callee });
|
switch (answers.cii) {
|
||||||
|
case 'x__': {
|
||||||
|
const a = Common.NEXT_TILE_FOR_SHUNTSU[tile];
|
||||||
|
if (a == null) throw new Error();
|
||||||
|
const b = Common.NEXT_TILE_FOR_SHUNTSU[a];
|
||||||
|
if (b == null) throw new Error();
|
||||||
|
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(a), 1);
|
||||||
|
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(b), 1);
|
||||||
|
tiles = [tile, a, b];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '_x_': {
|
||||||
|
const a = Common.PREV_TILE_FOR_SHUNTSU[tile];
|
||||||
|
if (a == null) throw new Error();
|
||||||
|
const b = Common.NEXT_TILE_FOR_SHUNTSU[tile];
|
||||||
|
if (b == null) throw new Error();
|
||||||
|
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(a), 1);
|
||||||
|
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(b), 1);
|
||||||
|
tiles = [a, tile, b];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '__x': {
|
||||||
|
const a = Common.PREV_TILE_FOR_SHUNTSU[tile];
|
||||||
|
if (a == null) throw new Error();
|
||||||
|
const b = Common.PREV_TILE_FOR_SHUNTSU[a];
|
||||||
|
if (b == null) throw new Error();
|
||||||
|
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(a), 1);
|
||||||
|
this.state.handTiles[cii.caller].splice(this.state.handTiles[cii.caller].indexOf(b), 1);
|
||||||
|
tiles = [b, a, tile];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state.huros[cii.caller].push({ type: 'cii', tiles: tiles, from: cii.callee });
|
||||||
|
|
||||||
this.state.turn = cii.caller;
|
this.state.turn = cii.caller;
|
||||||
|
|
||||||
|
@ -507,7 +540,7 @@ export class MasterGameEngine {
|
||||||
type: 'ciied' as const,
|
type: 'ciied' as const,
|
||||||
caller: cii.caller,
|
caller: cii.caller,
|
||||||
callee: cii.callee,
|
callee: cii.callee,
|
||||||
tiles: [tile, answers.cii[0], answers.cii[1]],
|
tiles: tiles,
|
||||||
turn: this.state.turn,
|
turn: this.state.turn,
|
||||||
};
|
};
|
||||||
} else if (this.state.tiles.length === 0) {
|
} else if (this.state.tiles.length === 0) {
|
||||||
|
|