Prototype named Ghola leader Truthtrance promises
Verify and publish checkpoint container / container (push) Successful in 10m45s
Verify and publish checkpoint container / container (push) Successful in 10m45s
This commit is contained in:
1 parent
f8078ed5e2
commit
c1ffa1c28a
16 files changed
+689
-9
No files matched your search
@@ -0,0 +1,120 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { viewGame, type Action, type Game } from '../game/engine';
|
||||
import { botActions } from '../game/bots';
|
||||
import { DIFFICULTIES } from '../game/bot-profiles';
|
||||
import {
|
||||
actTruthLeaderRevival as act, answerTruthLeaderRevival as answer,
|
||||
createTruthLeaderRevivalFixture as fixture, declareTruthLeaderRevival as declare,
|
||||
settleTruthLeaderRevival as settle, truthLeaderRevivalInventory as inventory,
|
||||
truthLeaderRevivalPlayer as player,
|
||||
} from './fixture-truth-leader-revival';
|
||||
|
||||
function rejected(game: Game, actor: string, action: Action) {
|
||||
const before = structuredClone(game);
|
||||
assert.throws(() => act(game, actor, action));
|
||||
assert.deepEqual(game, before);
|
||||
}
|
||||
|
||||
function askGhola(f: ReturnType<typeof fixture>) {
|
||||
const declared = declare(f);
|
||||
const game = act(declared.game, f.asker, { type: 'truthAsk', question: {
|
||||
kind: 'gholaLeader', target: f.target, turn: declared.game.turn, leader: f.leader,
|
||||
} });
|
||||
return game;
|
||||
}
|
||||
|
||||
for (const advanced of [false, true]) {
|
||||
void test(`${advanced ? 'Advanced' : 'Basic'} named Ghola Yes is fulfilled by an actual Ghola leader return`, () => {
|
||||
const f = fixture({ advanced, ghola: true });
|
||||
assert.ok(f.ghola);
|
||||
const asked = askGhola(f);
|
||||
assert.ok(viewGame(asked, f.target).truthGholaLeaderAnswers?.includes('yes'));
|
||||
let game = answer(asked, f.target, 'yes');
|
||||
const promise = game.gholaLeaderPromises!.find(row => row.player === f.target)!;
|
||||
assert.equal(promise.leader, f.leader);
|
||||
assert.ok(!promise.fulfilled);
|
||||
// Spending the only dealt Ghola on a force return cannot satisfy the named leader.
|
||||
rejected(game, f.target, { type: 'card', card: f.ghola, amount: 1, elite: 0 });
|
||||
game = settle(act(game, f.target, { type: 'card', card: f.ghola, leader: f.leader }));
|
||||
assert.equal(player(game, f.target).leaders.find(leader => leader.id === f.leader)!.dead, false);
|
||||
assert.equal(player(game, f.target).leaderRevived, false);
|
||||
assert.equal(game.gholaLeaderPromises!.find(row => row.event === promise.event)!.fulfilled, true);
|
||||
assert.equal(game.discard.filter(card => card.id === f.ghola).length, 1);
|
||||
assert.deepEqual(inventory(game), f.originalCards);
|
||||
});
|
||||
}
|
||||
|
||||
void test('named Ghola No rejects the matching leader return but allows its independent force return', () => {
|
||||
const f = fixture({ ghola: true });
|
||||
assert.ok(f.ghola);
|
||||
const asked = askGhola(f);
|
||||
assert.ok(viewGame(asked, f.target).truthGholaLeaderAnswers?.includes('no'));
|
||||
let game = answer(asked, f.target, 'no');
|
||||
const promise = game.gholaLeaderPromises!.find(row => row.player === f.target)!;
|
||||
rejected(game, f.target, { type: 'card', card: f.ghola, leader: f.leader });
|
||||
game = settle(act(game, f.target, { type: 'card', card: f.ghola, amount: 1, elite: 0 }));
|
||||
assert.equal(player(game, f.target).leaders.find(leader => leader.id === f.leader)!.dead, true);
|
||||
assert.ok(!game.gholaLeaderPromises!.find(row => row.event === promise.event)!.fulfilled);
|
||||
assert.equal(game.discard.filter(card => card.id === f.ghola).length, 1);
|
||||
assert.deepEqual(inventory(game), f.originalCards);
|
||||
});
|
||||
|
||||
void test('two Truthtrances cannot bind contradictory answers about the same Ghola leader', () => {
|
||||
const f = fixture({ ghola: true });
|
||||
let game = declare(f, f.game, { copies: 2 }).game;
|
||||
const question = { kind: 'gholaLeader', target: f.target, turn: game.turn, leader: f.leader };
|
||||
game = act(game, f.asker, { type: 'truthAsk', question });
|
||||
game = answer(game, f.target, 'yes');
|
||||
game = act(game, f.asker, { type: 'truthAsk', question });
|
||||
assert.ok(viewGame(game, f.target).truthGholaLeaderAnswers?.includes('yes'));
|
||||
assert.ok(!viewGame(game, f.target).truthGholaLeaderAnswers?.includes('no'));
|
||||
rejected(game, f.target, { type: 'truthAnswer', answer: 'no' });
|
||||
game = answer(game, f.target, 'yes');
|
||||
assert.equal(game.gholaLeaderPromises!.filter(row => row.player === f.target).length, 2);
|
||||
});
|
||||
|
||||
void test('prior ordinary-revival Yes prevents a conflicting Ghola leader Yes', () => {
|
||||
const f = fixture({ ghola: true });
|
||||
let game = declare(f, f.game, { copies: 2 }).game;
|
||||
game = act(game, f.asker, { type: 'truthAsk', question: {
|
||||
kind: 'leaderRevival', target: f.target, turn: game.turn, leader: f.leader,
|
||||
} });
|
||||
game = answer(game, f.target, 'yes');
|
||||
game = act(game, f.asker, { type: 'truthAsk', question: {
|
||||
kind: 'gholaLeader', target: f.target, turn: game.turn, leader: f.leader,
|
||||
} });
|
||||
assert.ok(!viewGame(game, f.target).truthGholaLeaderAnswers?.includes('yes'));
|
||||
assert.ok(viewGame(game, f.target).truthGholaLeaderAnswers?.includes('no'));
|
||||
rejected(game, f.target, { type: 'truthAnswer', answer: 'yes' });
|
||||
game = answer(game, f.target, 'no');
|
||||
assert.ok(game.leaderRevivalPromises!.some(row => row.player === f.target && row.answer));
|
||||
assert.ok(game.gholaLeaderPromises!.some(row => row.player === f.target && !row.answer));
|
||||
});
|
||||
|
||||
void test('all bot profiles choose the native named Ghola guide', () => {
|
||||
const f = fixture({ ghola: true });
|
||||
const game = answer(askGhola(f), f.target, 'yes');
|
||||
const view = viewGame(game, f.target);
|
||||
const guide = view.gholaLeaderPromiseGuide;
|
||||
assert.ok(guide);
|
||||
assert.equal(guide.action.type, 'card');
|
||||
assert.equal(guide.action.leader, f.leader);
|
||||
for (const difficulty of DIFFICULTIES) {
|
||||
const botView = viewGame(game, f.target);
|
||||
botView.players.find(seat => seat.id === f.target)!.bot = difficulty;
|
||||
assert.deepEqual(botActions(botView)[0], guide.action);
|
||||
}
|
||||
const after = settle(act(game, f.target, guide.action));
|
||||
assert.ok(after.gholaLeaderPromises!.find(row => row.player === f.target)?.fulfilled);
|
||||
});
|
||||
|
||||
for (const advanced of [false, true]) {
|
||||
void test(`${advanced ? 'Advanced' : 'Basic'} ordinary revival cannot consume the leader promised for Ghola`, () => {
|
||||
const f = fixture({ advanced, ghola: true });
|
||||
const game = answer(askGhola(f), f.target, 'yes');
|
||||
assert.ok(game.gholaLeaderPromises!.some(row => row.player === f.target && row.answer && !row.fulfilled));
|
||||
rejected(game, f.target, f.revivalAction);
|
||||
assert.ok(player(game, f.target).leaders.find(leader => leader.id === f.leader)!.dead);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user