cannot win without yaku
This commit is contained in:
parent
e82cc8fc7a
commit
3333dbd011
1 changed files with 42 additions and 13 deletions
53
src/game.ts
53
src/game.ts
|
|
@ -138,7 +138,7 @@ export class Game {
|
|||
if (this.chooseChii) {
|
||||
drawChiis(ctx, this.getChii(0));
|
||||
} else {
|
||||
const canTsumoLocal = this.hasPicked && this.hasWin(0);
|
||||
const canTsumoLocal = this.hasPicked && this.hasWin(0) && (!this.enableYakus || this.handHasAnyYaku(this.hands[0], this.groups[0]));
|
||||
let canRonLocal = false;
|
||||
if (this.lastDiscard !== undefined && this.lastDiscard !== 0) {
|
||||
if (this.canRonCache.lastDiscard === this.lastDiscard && this.canRonCache.handVer === this.handVersion[0]) {
|
||||
|
|
@ -153,7 +153,9 @@ export class Game {
|
|||
}
|
||||
sim.push(new Tile(last.getFamily(), last.getValue(), last.isRed()));
|
||||
sim.sort();
|
||||
canRonLocal = sim.toGroup() !== undefined;
|
||||
const simGroups = sim.toGroup() as Array<Group> | undefined;
|
||||
const combinedGroups = this.groups[0].concat(simGroups ? simGroups : []);
|
||||
canRonLocal = sim.toGroup() !== undefined && (!this.enableYakus || this.handHasAnyYaku(sim, combinedGroups));
|
||||
} else {
|
||||
canRonLocal = false;
|
||||
}
|
||||
|
|
@ -227,6 +229,27 @@ export class Game {
|
|||
this.staticDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given hand (possibly simulated) yields at least one yaku.
|
||||
* Does not modify `lastYakus`/`lastTotalHan` — only inspects using yakus detectors.
|
||||
*/
|
||||
private handHasAnyYaku(hand: Hand, groups: Array<Group> = []): boolean {
|
||||
try {
|
||||
for (const k of Object.keys(yakus)) {
|
||||
const fn = (yakus as any)[k];
|
||||
try {
|
||||
const han = fn(hand, groups, this.windPlayer);
|
||||
if (han && han > 0) return true;
|
||||
} catch (e) {
|
||||
// ignore detector errors
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private initializeGame(): void {
|
||||
this.deck.shuffle();
|
||||
|
||||
|
|
@ -350,7 +373,7 @@ export class Game {
|
|||
public click(mp: MousePos): void {
|
||||
const rect = this.cv.getBoundingClientRect();
|
||||
|
||||
if (this.hasWin(0)) {
|
||||
if (this.hasWin(0) && (!this.enableYakus || this.handHasAnyYaku(this.hands[0], this.groups[0]))) {
|
||||
this.resolveWin(0, 1);
|
||||
return;
|
||||
}
|
||||
|
|
@ -361,7 +384,7 @@ export class Game {
|
|||
}
|
||||
|
||||
// Determine if Ron/Tsumo should be available for player 0
|
||||
const canTsumo = this.hasPicked && this.hasWin(0);
|
||||
const canTsumo = this.hasPicked && this.hasWin(0) && (!this.enableYakus || this.handHasAnyYaku(this.hands[0], this.groups[0]));
|
||||
let canRon = false;
|
||||
if (this.lastDiscard !== undefined && this.lastDiscard !== 0) {
|
||||
const d = this.discards[this.lastDiscard];
|
||||
|
|
@ -373,7 +396,9 @@ export class Game {
|
|||
}
|
||||
sim.push(new Tile(last.getFamily(), last.getValue(), last.isRed()));
|
||||
sim.sort();
|
||||
canRon = sim.toGroup() !== undefined;
|
||||
const simGroups = sim.toGroup() as Array<Group> | undefined;
|
||||
const combinedGroups = this.groups[0].concat(simGroups ? simGroups : []);
|
||||
canRon = sim.toGroup() !== undefined && (!this.enableYakus || this.handHasAnyYaku(sim, combinedGroups));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +539,7 @@ export class Game {
|
|||
}
|
||||
|
||||
private handleBotTurn(): void {
|
||||
if (this.hasWin(this.turn)) {
|
||||
if (this.hasWin(this.turn) && (!this.enableYakus || this.handHasAnyYaku(this.hands[this.turn], this.groups[this.turn]))) {
|
||||
this.resolveWin(this.turn, 2);
|
||||
return;
|
||||
}
|
||||
|
|
@ -567,7 +592,9 @@ export class Game {
|
|||
}
|
||||
sim.push(new Tile(last.getFamily(), last.getValue(), last.isRed()));
|
||||
sim.sort();
|
||||
if (sim.toGroup() !== undefined) return true;
|
||||
const simGroups = sim.toGroup() as Array<Group> | undefined;
|
||||
const combinedGroups = this.groups[p].concat(simGroups ? simGroups : []);
|
||||
if (sim.toGroup() !== undefined && (!this.enableYakus || this.handHasAnyYaku(sim, combinedGroups))) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -589,7 +616,7 @@ export class Game {
|
|||
if (this.turn === 3) {
|
||||
this.turn = 0;
|
||||
this.pick(0);
|
||||
if (this.hasWin(0)) {
|
||||
if (this.hasWin(0) && (!this.enableYakus || this.handHasAnyYaku(this.hands[0], this.groups[0]))) {
|
||||
this.resolveWin(0, 1);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -696,7 +723,7 @@ export class Game {
|
|||
this.tenpaiCacheVersion[p] = -1;
|
||||
this.canRonCache = { result: false };
|
||||
|
||||
if (this.hasWin(p)) {
|
||||
if (this.hasWin(p) && (!this.enableYakus || this.handHasAnyYaku(this.hands[p], this.groups[p]))) {
|
||||
this.resolveWin(p, p === 0 ? 1 : 2);
|
||||
}
|
||||
|
||||
|
|
@ -865,7 +892,7 @@ export class Game {
|
|||
this.tenpaiCacheVersion[thief] = -1;
|
||||
this.canRonCache = { result: false };
|
||||
|
||||
if (this.hasWin(thief)) {
|
||||
if (this.hasWin(thief) && (!this.enableYakus || this.handHasAnyYaku(this.hands[thief], this.groups[thief]))) {
|
||||
this.resolveWin(thief, thief === 0 ? 1 : 2);
|
||||
}
|
||||
|
||||
|
|
@ -903,7 +930,7 @@ export class Game {
|
|||
drawChiis(this.staticCtx, this.getChii(0));
|
||||
} else {
|
||||
// Compute availability of ron/tsumo for player 0
|
||||
const canTsumoLocal = this.hasPicked && this.hasWin(0);
|
||||
const canTsumoLocal = this.hasPicked && this.hasWin(0) && (!this.enableYakus || this.handHasAnyYaku(this.hands[0], this.groups[0]));
|
||||
let canRonLocal = false;
|
||||
if (this.lastDiscard !== undefined && this.lastDiscard !== 0) {
|
||||
// Use cache when lastDiscard and player's hand version are unchanged
|
||||
|
|
@ -919,7 +946,9 @@ export class Game {
|
|||
}
|
||||
sim.push(new Tile(last.getFamily(), last.getValue(), last.isRed()));
|
||||
sim.sort();
|
||||
canRonLocal = sim.toGroup() !== undefined;
|
||||
const simGroups = sim.toGroup() as Array<Group> | undefined;
|
||||
const combinedGroups = this.groups[0].concat(simGroups ? simGroups : []);
|
||||
canRonLocal = sim.toGroup() !== undefined && (!this.enableYakus || this.handHasAnyYaku(sim, combinedGroups));
|
||||
} else {
|
||||
canRonLocal = false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue