Wait for the host to press "next hand" on every table

Previously only the review CPU table paused after each hand; cash-only,
friends and CPU tables moved on automatically after a short delay. Now
every table keeps the result on screen until the host presses 次のハンドへ,
and the next hand is dealt right away. If the host has left, the new host
presses it; with no human seated the table still advances on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
野口煌陽andClaude Opus 5.5 committed 2026-10-30 22:56:37 +09:00
1 parent 22ee28ba03
commit f64c502086
8 files changed
+103 -31

No files matched your search

+54 -1
View File
@@ -232,6 +232,7 @@ test('離席中の人の手番は自動でチェック/フォールド、次の
assert.notEqual(h.toAct, first);
t.act(tk(t, h.toAct), 'fold', 0); // 残り1人で終了
assert.ok(h.finished);
assert.equal(t.nextHand(T(0), 0), null);
t.tick(10 ** 6);
t.tick(10 ** 7);
assert.equal(t.hand.number, 2);
@@ -253,15 +254,60 @@ test('一時停止中はアクションも勝者の決定も次のハンドも
t.togglePause(T(0), 4000);
assert.equal(t.award(T(0), [[h.order[0]]]), null);
t.togglePause(T(0), 5000);
assert.equal(t.nextHand(T(0), 5000), '一時停止中です');
t.tick(10 ** 7);
t.tick(10 ** 8);
assert.equal(t.hand.number, 1); // 止まっている
t.togglePause(T(0), 10 ** 8);
assert.equal(t.nextHand(T(0), 10 ** 8), null);
t.tick(10 ** 8 + 10 ** 5);
t.tick(10 ** 8 + 10 ** 6);
assert.equal(t.hand.number, 2);
});
test('次のハンドはホストが「次のハンドへ」を押すまで始まらない', () => {
for (const mode of ['chips', 'friends']) {
const t = makeTable([1000, 1000, 1000], { mode });
t.start(T(0), 0);
assert.equal(t.nextHand(T(0), 0), 'ハンドが終わっていません');
const h = t.hand;
for (let i = 0; i < 10 && !h.finished; i++) t.act(tk(t, h.toAct), 'fold', 0);
assert.ok(h.finished);
assert.equal(t.publicState(T(1), new Set()).awaitingNext, true);
for (let k = 1; k <= 5; k++) t.tick(k * 10 ** 6);
assert.equal(t.hand, h); // 待っている
assert.equal(t.nextHand(T(1), 10 ** 7), 'ホストのみ操作できます');
assert.equal(t.nextHand(T(0), 10 ** 7), null);
assert.equal(t.awaitingNext, false);
t.tick(10 ** 7);
assert.equal(t.hand.number, 2);
}
});
test('ホストが退席したら、次のホストが押す。人間がいなければ待たずに進む', () => {
const t = makeTable([1000, 1000, 1000], { mode: 'friends' });
t.start(T(0), 0);
const h = t.hand;
for (let i = 0; i < 10 && !h.finished; i++) t.act(tk(t, h.toAct), 'fold', 0);
assert.ok(t.leave(T(0)));
assert.ok(t.awaitingNext);
assert.equal(t.nextHand(T(0), 0), 'ホストのみ操作できます');
assert.ok(t.isHost(T(1)));
assert.equal(t.nextHand(T(1), 0), null);
t.tick(1);
assert.equal(t.hand.number, 2);
// CPU戦で人間が退席すると、ボタンを待たずに片付けへ進む
const c = makeTable([1000], { mode: 'cpu', cpuCount: 2 });
c.start(T(0), 0);
const ch = c.hand;
c.leave(T(0));
let now = 0;
for (let k = 0; k < 400 && !ch.finished; k++) c.tick((now += 5000));
assert.ok(ch.finished);
assert.equal(c.awaitingNext, false);
});
test('ハンド中の退席: フォールド扱いで席はハンド終了まで予約', () => {
const t = makeTable([1000, 1000, 1000]);
t.start(T(0), 0);
@@ -380,6 +426,7 @@ test('ランダムに遊んでもチップの合計が変わらず、必ず終
});
assert.equal(t.award(T(0), winners), null);
} else {
if (t.awaitingNext) assert.equal(t.nextHand(T(0), now), null);
t.tick((now += 10 ** 5));
}
for (const s of t.seats) if (s) assert.ok(s.stack >= 0);
@@ -623,6 +670,7 @@ test('カードあり: ランダムに遊んでもチップの合計が変わら
} else {
assert.equal(h.awaitingWinners, false);
if (h.runout && t.runoutAt == null) runouts++;
if (t.awaitingNext) assert.equal(t.nextHand(T(0), now), null);
t.tick((now += 10 ** 5));
}
for (const s of t.seats) if (s) assert.ok(s.stack >= 0);
@@ -703,6 +751,7 @@ test('CPU: どんな状況でも正しいアクションを返す', () => {
assert.equal(h.act(h.toAct, d.type, d.amount), null, JSON.stringify(d));
actions++;
} else {
if (t.awaitingNext) assert.equal(t.nextHand(T(0), now), null);
t.tick((now += 10 ** 5));
}
const inPot = t.hand && !t.hand.finished ? t.hand.potTotal : 0;
@@ -736,6 +785,7 @@ test('CPU: どの思考(ライブラリ)も自分で正しいアクション
assert.equal(h.act(h.toAct, d.type, d.amount), null, `${brain} ${JSON.stringify(d)}`);
decisions++;
} else {
if (t.awaitingNext) assert.equal(t.nextHand(T(0), now), null);
t.tick((now += 10 ** 5));
}
}
@@ -818,7 +868,10 @@ test('CPU戦: CPU が席に着き、ホストは人間のまま、CPU は自動
// 人間が離席すると CPU だけで次のハンドは始まらない
t.setSittingOut(T(0), true);
for (let k = 0; k < 400 && t.hand; k++) t.tick((now += 5000));
for (let k = 0; k < 400 && t.hand; k++) {
if (t.awaitingNext) assert.equal(t.nextHand(T(0), now), null);
t.tick((now += 5000));
}
assert.equal(t.hand, null);
t.setSittingOut(T(0), false);
+3 -3
View File
@@ -342,7 +342,7 @@ test('レビュー付きCPU戦: 作成者だけが座れ、ハンドごとにレ
assert.ok(t.hand.finished);
t.tick((now += 5000));
const v = t.publicState(T(0), new Set([T(0)]));
assert.ok(v.review && v.review.last && v.review.waiting);
assert.ok(v.review && v.review.last && v.awaitingNext);
assert.equal(v.review.hands, 1);
assert.equal(t.publicState(T(5), new Set()).review, null); // 作成者以外には送らない
@@ -350,8 +350,8 @@ test('レビュー付きCPU戦: 作成者だけが座れ、ハンドごとにレ
const number = t.hand.number;
for (let k = 0; k < 10; k++) t.tick((now += 60000));
assert.equal(t.hand.number, number);
assert.equal(t.reviewNext(T(5)), '操作できません');
assert.equal(t.reviewNext(T(0)), null);
assert.equal(t.nextHand(T(5), now), 'ホストのみ操作できます');
assert.equal(t.nextHand(T(0), now), null);
for (let k = 0; k < 10 && t.hand.number === number; k++) t.tick((now += 5000));
assert.equal(t.hand.number, number + 1);
+2
View File
@@ -61,6 +61,7 @@ test('席順: ハンド中は次のハンドの始めに並べ替え、ボタン
// 全員降りてハンドを終わらせ、次のハンドへ
for (let i = 0; i < 10 && !h.finished; i++) t.act(t.seats[h.toAct].token, 'fold', 0);
assert.ok(h.finished);
assert.equal(t.nextHand(T(0), 0), null);
t.tick(10 ** 6);
t.tick(10 ** 7);
assert.equal(t.hand.number, 2);
@@ -84,6 +85,7 @@ test('席順: 決めた後に座った人は最後に加え、いなくなった
t.join(T(5), 'p5'); // ハンド中に新しく座る
t.leave(T(1)); // ハンド中に退席
for (let i = 0; i < 10 && !h.finished; i++) t.act(t.seats[h.toAct].token, 'fold', 0);
assert.equal(t.nextHand(T(0), 0), null);
t.tick(10 ** 6);
t.tick(10 ** 7);
assert.deepEqual(names(t), ['p2', 'p0', 'p5']);