feat: allow three cumulative selection timeouts per match

This commit is contained in:
2026-10-15 11:51:08 +09:00
parent fc5e475f24
commit 293ed7bcc4
14 changed files with 228 additions and 37 deletions
+23 -1
View File
@@ -39,10 +39,15 @@ test('a turn resolves once and a hit ends the game', () => {
test('only verified missing choices count as timeouts; technical abort leaves outcome separate', () => {
const { engine, at } = setup(); engine.start(1000); at(4000); engine.beginTurn(); at(8000);
engine.resolve([null, 'charge']);
assert.equal(engine.view().phase, 'selecting');
assert.deepEqual(engine.view().timeouts, [1, 0]);
at(engine.view().deadline); engine.resolve([null, 'charge']);
assert.equal(engine.view().phase, 'selecting');
at(engine.view().deadline); engine.resolve([null, 'charge']);
assert.equal(engine.view().finished?.winnerIndex, 1);
assert.equal(engine.view().finished?.reason, 'timeout');
const other = setup(); other.engine.start(1000); other.at(4000); other.engine.beginTurn(); other.at(8000);
other.engine.resolve([null, null]);
for (let i = 0; i < 3; i++) { other.at(other.engine.view().deadline); other.engine.resolve([null, null]); }
assert.equal(other.engine.view().finished?.reason, 'double_timeout');
const aborted = setup(); aborted.engine.abort('connection_failed');
assert.equal(aborted.engine.view().aborted, true);
@@ -86,3 +91,20 @@ test('rollback and recovery keep published revisions increasing so the view acce
other.engine.resumeTurn(start, 5000);
assert.ok(other.engine.view().version > previous);
});
test('timeout chances persist across turns and restore while locked actions stay locked', () => {
const { engine, at } = setup(); engine.start(1000); at(4000); engine.beginTurn(); engine.lockAction('guard');
at(engine.view().deadline); engine.resolve(['guard', null]);
assert.equal(engine.view().ownAction, 'guard');
assert.equal(engine.lockAction('charge'), false);
assert.deepEqual(engine.view().timeouts, [0, 1]);
engine.resolve(['guard', 'charge']);
at(engine.view().reveal!.revealEndsAt); engine.beginTurn();
const saved = engine.checkpoint(); engine.restore(saved);
assert.deepEqual(engine.view().timeouts, [0, 1]);
at(engine.view().deadline); engine.resolve([null, null]);
assert.deepEqual(engine.view().timeouts, [1, 2]);
at(engine.view().deadline); engine.resolve([null, null]);
assert.deepEqual(engine.view().timeouts, [2, 3]);
assert.equal(engine.view().finished?.winnerIndex, 0);
});