Clarify Sapho finite-bid timing and pending Nexus rulings
This commit is contained in:
1 parent
6df505f003
commit
41fd6fe173
8 files changed
+96
-13
No files matched your search
@@ -176,7 +176,29 @@ void test('Once Around last preserves prior bids and permits a final outbid afte
|
||||
assert.deepEqual(g.order, ['a', 'e', 'g']);
|
||||
});
|
||||
|
||||
void test('Once Around rejects late first, completed opportunity, no-op and stale event without card loss', () => {
|
||||
void test('Once Around first after a prior bid moves only unacted bidders and preserves the committed bid', () => {
|
||||
let g = auction('g');
|
||||
const first = g.richeseAuction!.active!;
|
||||
g = bid(g, first, 1);
|
||||
const before = reload(g);
|
||||
assert.ok(viewGame(g, 'g').saphoOptions.some((o) => o.scope === 'onceAround' && o.mode === 'first'));
|
||||
g = applyAction(reload(g), 'g', action(g, 'first'));
|
||||
assert.deepEqual(g.richeseAuction!.acted, [first]);
|
||||
assert.equal(g.richeseAuction!.bid, 1);
|
||||
assert.equal(g.richeseAuction!.bidder, first);
|
||||
assert.deepEqual(g.richeseAuction!.tieOrder, before.richeseAuction!.tieOrder);
|
||||
assert.equal(g.richeseAuction!.active, 'g');
|
||||
assert.equal(g.discard.filter((c) => c.id === card).length, 1);
|
||||
g = bid(reload(g), 'g', 2);
|
||||
assert.equal(g.richeseAuction!.active, 'e');
|
||||
assert.deepEqual(g.richeseAuction!.acted, [first, 'g']);
|
||||
const sold = g.richeseAuction!.cardId;
|
||||
g = bid(g, 'e', 3);
|
||||
assert.ok(g.players[1].hand.some((c) => c.id === sold));
|
||||
assert.equal(g.players[1].spice, 17);
|
||||
});
|
||||
|
||||
void test('Once Around rejects no-op first, completed opportunity, no-op last and stale event without card loss', () => {
|
||||
let g = auction();
|
||||
g = bid(g, g.richeseAuction!.active!, 1);
|
||||
reject(g, 'e', action(g, 'first'));
|
||||
|
||||
@@ -96,7 +96,7 @@ const clock: Rooms.RoomsClock = { now: () => 10000, sleep: async () => {} };
|
||||
|
||||
const SAPHO = 'richese-juice-of-sapho';
|
||||
type Scope = 'onceAround' | 'movement';
|
||||
async function fixture(scope: Scope, advanced = false) {
|
||||
async function fixture(scope: Scope, advanced = false, lateFirst = false) {
|
||||
const store = unitStore();
|
||||
const made = await store.rooms.createRoom(
|
||||
'First player',
|
||||
@@ -107,7 +107,7 @@ async function fixture(scope: Scope, advanced = false) {
|
||||
const code = made.view.code;
|
||||
const holder = await store.rooms.joinRoom(code, 'Sapho holder', 'emperor');
|
||||
const guild = await store.rooms.joinRoom(code, 'Guild', 'guild');
|
||||
const fourth = advanced
|
||||
const fourth = advanced || lateFirst
|
||||
? await store.rooms.joinRoom(code, 'Later player', 'harkonnen')
|
||||
: null;
|
||||
const seats = await Promise.all(
|
||||
@@ -165,7 +165,9 @@ async function fixture(scope: Scope, advanced = false) {
|
||||
'Roster',
|
||||
'richese',
|
||||
).leaders;
|
||||
initial.order = [seats[2].playerId, seats[1].playerId, seats[0].playerId];
|
||||
initial.order = lateFirst
|
||||
? [seats[2].playerId, seats[3].playerId, seats[1].playerId, seats[0].playerId]
|
||||
: [seats[2].playerId, seats[1].playerId, seats[0].playerId];
|
||||
}
|
||||
const save = (g: engine.Game) =>
|
||||
store.sqlite
|
||||
@@ -192,11 +194,9 @@ async function fixture(scope: Scope, advanced = false) {
|
||||
direction: 'clockwise',
|
||||
});
|
||||
g = await f.restart().readRoom(code);
|
||||
assert.deepEqual(g.richeseAuction!.order, [
|
||||
seats[2].playerId,
|
||||
seats[1].playerId,
|
||||
seats[0].playerId,
|
||||
]);
|
||||
assert.deepEqual(g.richeseAuction!.order, lateFirst
|
||||
? [seats[3].playerId, seats[2].playerId, seats[1].playerId, seats[0].playerId]
|
||||
: [seats[2].playerId, seats[1].playerId, seats[0].playerId]);
|
||||
} else if (advanced) {
|
||||
const g = await f.restart().readRoom(code);
|
||||
assert.equal(g.decision?.kind, 'guildTiming');
|
||||
@@ -398,6 +398,37 @@ void test('Once Around last survives duplicate cardplay and restart without repl
|
||||
}
|
||||
});
|
||||
|
||||
void test('a prior persisted bid survives duplicate Sapho first and the remaining one-bid order', async () => {
|
||||
const f = await fixture('onceAround', false, true);
|
||||
try {
|
||||
let g = await stable(f);
|
||||
const event = g.richeseAuction!.event;
|
||||
g = await act(f, 3, bid(g, 2));
|
||||
const previous = structuredClone(g.richeseAuction!);
|
||||
await privacy(f, 'onceAround', event, ['first', 'last']);
|
||||
g = await duplicate(f, action('onceAround', event, 'first'));
|
||||
assert.deepEqual(g.richeseAuction!.order, [
|
||||
f.seats[3].playerId, f.seats[1].playerId,
|
||||
f.seats[2].playerId, f.seats[0].playerId,
|
||||
]);
|
||||
assert.equal(g.richeseAuction!.active, f.seats[1].playerId);
|
||||
for (const key of ['acted', 'bid', 'bidder', 'tieOrder', 'sealed'] as const)
|
||||
assert.deepEqual(g.richeseAuction![key], previous[key]);
|
||||
await privacy(f, 'onceAround', event, []);
|
||||
g = await act(f, 1, bid(g, 3));
|
||||
assert.equal(g.richeseAuction!.active, f.seats[2].playerId);
|
||||
g = await act(f, 2, bid(g, null));
|
||||
assert.equal(g.richeseAuction!.active, f.seats[0].playerId);
|
||||
g = await act(f, 0, bid(g, null));
|
||||
assert.equal(g.players[1].spice, 17);
|
||||
assert.equal(g.discard.filter((card) => card.id === SAPHO).length, 1);
|
||||
await rejectsWithoutWrite(f, 1, action('onceAround', event, 'first'));
|
||||
} finally {
|
||||
f.hooks.beforeWrite = undefined;
|
||||
f.sqlite.close();
|
||||
}
|
||||
});
|
||||
|
||||
void test('Once Around first persists only within its lot and cannot be replayed after its first actual bid', async () => {
|
||||
const f = await fixture('onceAround');
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user