Connect bounded Moritani Atomics Aftermath
This commit is contained in:
1 parent
b2603f6715
commit
66a427ab55
17 files changed
+1036
-68
No files matched your search
@@ -0,0 +1,71 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createElement } from 'react';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import { MoritaniEntry, MoritaniTerrorSupply } from '../components/moritani-terror';
|
||||
import { TerrorBoardMarkers } from '../components/terror-board-markers';
|
||||
import { createGame, joinGame, newPlayer, viewGame, type GameView } from '../game/engine';
|
||||
import { createTerrorState, placeTerror, revealTerror } from '../game/moritani-terror';
|
||||
|
||||
function fixture() {
|
||||
const game = createGame('ATOMICS-CONTROLS', newPlayer('m', 'Moritani', 'moritani'));
|
||||
joinGame(game, newPlayer('a', 'Atreides', 'atreides'));
|
||||
joinGame(game, newPlayer('f', 'Fremen', 'fremen'));
|
||||
game.players.find((player) => player.id === 'm')!.ally = 'a';
|
||||
game.players.find((player) => player.id === 'a')!.ally = 'm';
|
||||
game.moritaniTerror = createTerrorState(() => 0);
|
||||
const token = game.moritaniTerror.tokens.find((item) => item.kind === 'atomics')!;
|
||||
game.moritaniTerror = placeTerror(game.moritaniTerror, token.id, 'arrakeen', 1);
|
||||
return { game, token };
|
||||
}
|
||||
|
||||
const supply = (view: GameView) =>
|
||||
renderToStaticMarkup(createElement(MoritaniTerrorSupply, { game: view }));
|
||||
const markers = (view: GameView) =>
|
||||
renderToStaticMarkup(createElement('svg', null, createElement(TerrorBoardMarkers, {
|
||||
tokens: view.moritaniTerror?.tokens ?? [], atomics: view.moritaniAtomics,
|
||||
})));
|
||||
|
||||
void test('a placed hidden face stays private; only owner sees the Atomics reveal consequences', () => {
|
||||
const { game } = fixture();
|
||||
const owner = viewGame(game, 'm');
|
||||
owner.decision = { kind: 'moritaniTerror', player: 'm', entrant: 'f', territory: 'arrakeen' };
|
||||
owner.terrorEntry = {
|
||||
entrant: 'f', territory: 'arrakeen', sector: 10, cause: 'shipment', stage: 'offer',
|
||||
kind: 'atomics', canReveal: true, canOfferAlliance: false,
|
||||
};
|
||||
const offer = renderToStaticMarkup(createElement(MoritaniEntry, { game: owner, busy: false, act() {} }));
|
||||
assert.match(offer, /Reveal Atomics/);
|
||||
assert.match(offer, /every faction’s forces/);
|
||||
assert.match(offer, /including Fremen reinforcements/);
|
||||
assert.match(offer, /discards one random card per excess/);
|
||||
const rival = viewGame(game, 'f');
|
||||
assert.match(supply(rival), /Inspect Hidden Terror/);
|
||||
assert.doesNotMatch(supply(rival), /Inspect Atomics|Atomics Aftermath/);
|
||||
assert.match(markers(rival), /hidden Terror token in Arrakeen/);
|
||||
assert.doesNotMatch(markers(rival), /Atomics Aftermath/);
|
||||
assert.equal(renderToStaticMarkup(createElement(MoritaniEntry, { game: rival, busy: false, act() {} })), '');
|
||||
});
|
||||
|
||||
void test('after revelation all seats see persistent Aftermath and its exact shipment and hand-limit consequences', () => {
|
||||
const { game, token } = fixture();
|
||||
game.moritaniTerror = revealTerror(game.moritaniTerror!, token.id);
|
||||
game.moritaniAtomics = { territory: 'arrakeen', turn: 2, moritaniId: 'm',
|
||||
allyAtActivation: 'a', alliancePolicy: 'unresolved' };
|
||||
game.turn = 2;
|
||||
game.players.find((player) => player.id === 'm')!.atomicsHandLimitPenalty = true;
|
||||
game.players.find((player) => player.id === 'a')!.atomicsHandLimitPenalty = true;
|
||||
for (const id of ['m', 'a', 'f']) {
|
||||
const view = viewGame(game, id);
|
||||
const notice = supply(view);
|
||||
assert.match(notice, /Atomics Aftermath · Arrakeen/);
|
||||
assert.match(notice, /From turn 2, no faction may ship forces/);
|
||||
assert.match(notice, /including Fremen reinforcements/);
|
||||
assert.match(notice, /ordinary movement and Sneak Attack remain possible/);
|
||||
assert.match(notice, /Moritani and Atreides/);
|
||||
assert.match(notice, /lasting hand-limit reduction of one/);
|
||||
const board = markers(view);
|
||||
assert.match(board, /Atomics Aftermath in Arrakeen: permanent shipment ban/);
|
||||
assert.doesNotMatch(board, /hidden Terror token in Arrakeen/);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user