Implement mixed Planetologist advisor gather continuation

This commit is contained in:
Quintine committed 2026-10-18 00:35:36 +11:00
1 parent bc37cd38fe
commit c265f0638e
16 files changed
+512 -171

No files matched your search

+2 -89
View File
@@ -1,7 +1,5 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import {
applyAction,
createGame,
@@ -9,10 +7,7 @@ import {
viewGame,
type Game,
} from '../game/engine';
import {
PlanetologistMovement,
planetologistMoveDraft,
} from '../components/planetologist-movement';
import { planetologistMoveDraft } from '../components/planetologist-movement';
import { LEADER_SKILL_CARDS } from '../game/leader-skill-cards';
import { location } from '../game/board';
@@ -74,34 +69,8 @@ function fixture(): Game {
return g;
}
function markup(g: Game, viewer = 'p', busy = false) {
return renderToStaticMarkup(
createElement(PlanetologistMovement, {
game: viewGame(g, viewer),
act() {},
busy,
destination,
sector: 0,
}),
);
}
void test('the owner sees both modes, physical source controls and the shared board destination', () => {
const g = fixture();
const html = markup(g);
assert.match(html, /Planetologist movement/);
assert.match(html, /One territory farther, maximum three/);
assert.match(html, /Gather from two territories/);
assert.match(html, /Destination: Polar Sink, sector 0/);
assert.match(html, /False Wall West, sector 16 · 2 forces/);
assert.match(html, /Elite from this group · 1 available/);
assert.match(html, /Select forces from one territory/);
assert.match(html, /disabled=""/);
assert.equal(markup(g, 'o'), '');
assert.ok((markup(g, 'p', true).match(/disabled=""/g) ?? []).length >= 2);
});
void test('drafts send only the public mode and exact physical counts, and both settle through the engine', () => {
void test('range and gather controls settle the selected physical normal and elite counters through the engine', () => {
const g = fixture();
const view = viewGame(g, 'p');
const range = planetologistMoveDraft(
@@ -113,15 +82,6 @@ void test('drafts send only the public mode and exact physical counts, and both
{ [rangeSource]: 1 },
);
assert.equal(range.blocked, null);
assert.deepEqual(range.action, {
type: 'move',
planetologist: 'range',
forces: { [rangeSource]: 2 },
eliteForces: { [rangeSource]: 1 },
territory: destination,
sector: 0,
});
assert.equal(Object.hasOwn(range.action!, 'leader'), false);
const ranged = applyAction(structuredClone(g), 'p', range.action!);
assert.equal(ranged.players[0].forces[`${destination}:0`], 2);
assert.equal(ranged.players[0].elites!.forces[`${destination}:0`], 1);
@@ -135,55 +95,8 @@ void test('drafts send only the public mode and exact physical counts, and both
{ [gatherSources[0]]: 1, [gatherSources[1]]: 2 },
);
assert.equal(gather.blocked, null);
assert.deepEqual(gather.action, {
type: 'move',
planetologist: 'gather',
forces: { [gatherSources[0]]: 2, [gatherSources[1]]: 3 },
eliteForces: { [gatherSources[0]]: 1, [gatherSources[1]]: 2 },
territory: destination,
sector: 0,
});
assert.equal(Object.hasOwn(gather.action!, 'leader'), false);
const gathered = applyAction(structuredClone(g), 'p', gather.action!);
assert.equal(gathered.players[0].forces[`${destination}:0`], 5);
assert.equal(gathered.players[0].elites!.forces[`${destination}:0`], 3);
});
void test('the client rejects wrong origin counts and unavailable elite custody before sending', () => {
const view = viewGame(fixture(), 'p');
assert.match(
planetologistMoveDraft(
view,
'gather',
destination,
0,
{ [gatherSources[0]]: 1 },
{ [gatherSources[0]]: 0 },
).blocked!,
/exactly two different territories/,
);
assert.match(
planetologistMoveDraft(
view,
'range',
destination,
0,
{ [rangeSource]: 2 },
{ [rangeSource]: 0 },
).blocked!,
/normal and elite mix/,
);
const expansion = fixture();
expansion.players[1].faction = 'ixians';
assert.match(
planetologistMoveDraft(
viewGame(expansion, 'p'),
'range',
destination,
0,
{ [rangeSource]: 2 },
{ [rangeSource]: 1 },
).blocked!,
/expansion factions awaits/,
);
});