Connect Richese final-cache and provisional full-hand acquisition

This commit is contained in:
Quintine committed 2026-10-08 20:29:45 +11:00
1 parent 451ecc950c
commit 66e061ccca
10 files changed
+83 -45

No files matched your search

+1 -4
View File
@@ -90,7 +90,7 @@ void test('all four profiles acquire only usable canonical Karama and settle onc
}
});
void test('all profiles decline unavailable, used, basic, full-hand and low-budget purchases', () => {
void test('all profiles decline unavailable, used, basic and low-budget purchases', () => {
for (const difficulty of DIFFICULTIES) {
for (const change of [
(g: Game) => {
@@ -102,9 +102,6 @@ void test('all profiles decline unavailable, used, basic, full-hand and low-budg
(g: Game) => {
g.players[0].spice = 3;
},
(g: Game) => {
g.players[0].hand.push(...g.deck.splice(0, 3));
},
(g: Game) => {
g.players[0].hand = [];
},
+2 -10
View File
@@ -279,16 +279,8 @@ void test('special purchase cannot spend sealed bid funds or take the already of
rejected(g, { ...action, acquire: offered }, /offered for auction/);
});
void test('full-hand, final-cache and noncanonical selections remain explicit atomic unsupported or invalid cases', () => {
let g = fixture();
const action = command(g);
g.players[0].hand.push(...g.deck.splice(0, 3));
rejected(g, action, /full hand.*ruling/);
g = fixture();
const last = command(g);
g.richeseCache = g.richeseCache!.filter((c) => c.id === last.acquire);
rejected(g, last, /final cache.*implementation/);
g = fixture();
void test('noncanonical cache selections remain invalid before any purchase cost', () => {
const g = fixture();
const fake = command(g);
g.richeseCache!.find((c) => c.id === fake.acquire)!.name =
'Invented replacement';
+18 -13
View File
@@ -156,19 +156,24 @@ void test('private options validate exactly and do not mutate state or expose ca
g.richeseCache![0].name = 'Forged face';
assert.throws(() => purchase(g), /verified card/);
});
void test('full-hand and last-cache capacity edges remain explicit atomic implementation guards', () => {
const g = fixture();
g.players[0].hand.push(...g.deck.splice(0, 3));
const before = JSON.stringify(g);
assert.throws(() => purchase(g), /awaits a ruling/);
assert.equal(JSON.stringify(g), before);
assert.match(
viewGame(g, 'r').richeseSpecialKarama!.blocked!,
/awaits a ruling/,
);
g.players[0].hand.splice(1);
g.richeseCache = g.richeseCache!.slice(0, 1);
assert.throws(() => purchase(g), /empty-cache/);
void test('full-hand special purchase exchanges the spent Karama and may exhaust the cache under the resolved auction rule', () => {
const start = fixture();
start.players[0].hand.push(...start.deck.splice(0, 3));
const spent = start.players[0].hand.find(card => card.effect === 'karama')!.id;
const chosen = start.richeseCache!.find(card => card.id === 'richese-ornithopter')!;
start.richeseRemoved!.push(...start.richeseCache!.filter(card => card.id !== chosen.id));
start.richeseCache = [chosen];
const held = start.players[0].hand.filter(card => card.id !== spent).map(card => card.id);
const result = purchase(start, chosen.id);
assert.equal(result.players[0].hand.length, 4);
assert.ok(held.every(id => result.players[0].hand.some(card => card.id === id)));
assert.ok(result.players[0].hand.some(card => card.id === chosen.id));
assert.equal(result.discard.filter(card => card.id === spent).length, 1);
assert.equal(result.richeseCache!.length, 0);
assert.equal(result.players[0].spice, 7);
assert.equal(result.players[2].spice, 13);
assert.equal(result.players[0].specialKaramaUsed, true);
});
void test('insufficient or pledged spice, Basic mode, used power and committed Karama are rejected atomically', () => {
for (const configure of [