Implement Moritani Nexus placement and preserve later Terror custody
This commit is contained in:
1 parent
290259bac2
commit
ae66668e2e
27 files changed
+2208
-73
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { applyAction, viewGame } from '../game/engine';
|
||||
import { botActions } from '../game/bots';
|
||||
import { nexusMoritaniBotActions } from '../game/nexus-moritani-options';
|
||||
import {
|
||||
nexusMoritaniFixture,
|
||||
nexusMoritaniInventory,
|
||||
} from './fixture-nexus-moritani';
|
||||
|
||||
void test('all four Moritani profiles use Cunning for a public opposing Arrakis group and keep token custody until allowance', () => {
|
||||
for (const profile of ['Easy', 'Medium', 'Hard', 'Brutal'] as const) {
|
||||
const f = nexusMoritaniFixture();
|
||||
// Conserved public target position, staged before the real declaration.
|
||||
const target = f.g.players.find((player) => player.id === f.target)!;
|
||||
target.reserves -= 3;
|
||||
target.forces['red_chasm:7'] = 3;
|
||||
const v = viewGame(f.g, f.owner);
|
||||
v.players.find((player) => player.id === f.owner)!.bot = profile;
|
||||
const before = structuredClone(v);
|
||||
const action = botActions(v)[0];
|
||||
assert.deepEqual([action], nexusMoritaniBotActions(v));
|
||||
assert.equal(action.territory, 'red_chasm');
|
||||
assert.equal(action.nexus, v.nexusMoritani!.event);
|
||||
const pending = applyAction(f.g, f.owner, action);
|
||||
assert.equal(pending.response?.kind, 'moritaniPlacement');
|
||||
assert.deepEqual(pending.moritaniTerror, f.g.moritaniTerror);
|
||||
nexusMoritaniInventory(pending);
|
||||
assert.deepEqual(v, before);
|
||||
}
|
||||
});
|
||||
|
||||
void test('Cunning policy reads only public opposing armies, supports an existing stack and retains ordinary fallback', () => {
|
||||
const f = nexusMoritaniFixture({ stack: true });
|
||||
const target = f.g.players.find((player) => player.id === f.target)!;
|
||||
target.reserves -= 2;
|
||||
target.forces['arrakeen:10'] = 2;
|
||||
const v = viewGame(f.g, f.owner);
|
||||
for (const p of v.players.filter((player) => player.id !== f.owner))
|
||||
for (const key of ['hand', 'traitors', 'spice'])
|
||||
Object.defineProperty(p, key, {
|
||||
get() {
|
||||
throw new Error('Private opponent data read');
|
||||
},
|
||||
});
|
||||
assert.equal(nexusMoritaniBotActions(v)[0].territory, 'arrakeen');
|
||||
v.nexusMoritani!.blocked = 'Not available now';
|
||||
assert.deepEqual(nexusMoritaniBotActions(v), []);
|
||||
const ordinary = viewGame(f.g, f.owner);
|
||||
ordinary.nexusMoritani = null;
|
||||
for (const profile of ['Easy', 'Medium', 'Hard', 'Brutal'] as const) {
|
||||
ordinary.players.find((player) => player.id === f.owner)!.bot = profile;
|
||||
const action = botActions(ordinary)[0];
|
||||
assert.equal(action.type, 'decision');
|
||||
assert.equal(action.nexus, undefined);
|
||||
nexusMoritaniInventory(applyAction(f.g, f.owner, action));
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user