Prototype two-player four-faction setup
This commit is contained in:
1 parent
70ef142577
commit
24255905ed
28 files changed
+1091
-73
No files matched your search
@@ -0,0 +1,98 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
TwoPlayerControllersError,
|
||||
addTwoPlayerControlledSeat as add,
|
||||
controllerStrongholdTarget as target,
|
||||
createTwoPlayerControllers as create,
|
||||
physicalControllerCount as count,
|
||||
validateTwoPlayerControllersComplete as complete,
|
||||
validateTwoPlayerControllersLobby as lobby,
|
||||
type TwoPlayerControllers,
|
||||
} from '../game/two-player-controllers';
|
||||
|
||||
const seats = ['atreides', 'harkonnen', 'fremen', 'guild'];
|
||||
function assembled(): TwoPlayerControllers {
|
||||
let state = create();
|
||||
state = add(state, seats, 'atreides', 'atreides');
|
||||
state = add(state, seats, 'atreides', 'fremen');
|
||||
state = add(state, seats, 'harkonnen', 'harkonnen');
|
||||
return add(state, seats, 'harkonnen', 'guild');
|
||||
}
|
||||
|
||||
void test('lobby additions create two distinct primary controllers without mutating inputs', () => {
|
||||
const empty = create(), first = add(empty, seats, 'atreides', 'atreides');
|
||||
const prior = structuredClone(first);
|
||||
const second = add(first, seats, 'atreides', 'fremen');
|
||||
assert.deepEqual(empty, { version: 1, controllers: [] });
|
||||
assert.deepEqual(first, prior);
|
||||
assert.notEqual(second.controllers, first.controllers);
|
||||
assert.notEqual(second.controllers[0].seats, first.controllers[0].seats);
|
||||
lobby(second, seats);
|
||||
assert.throws(() => complete(second, seats), TwoPlayerControllersError);
|
||||
const ready = assembled();
|
||||
complete(ready, seats);
|
||||
assert.deepEqual(ready.controllers, [
|
||||
{ id: 'atreides', seats: ['atreides', 'fremen'] },
|
||||
{ id: 'harkonnen', seats: ['harkonnen', 'guild'] },
|
||||
]);
|
||||
});
|
||||
|
||||
void test('full mapping counts two people and keeps faction alliances separate', () => {
|
||||
const state = assembled();
|
||||
assert.equal(count(seats, state), 2);
|
||||
assert.equal(target(seats, state, false), 4);
|
||||
assert.equal(target(seats, state, true), 4);
|
||||
assert.deepEqual(state.controllers[0].seats, ['atreides', 'fremen']);
|
||||
// Without the explicit mode, four faction seats remain four players.
|
||||
assert.equal(count(seats), 4);
|
||||
assert.equal(target(seats, undefined, false), 3);
|
||||
assert.equal(target(seats, undefined, true), 4);
|
||||
assert.equal(target(seats.slice(0, 2), null, false), 4);
|
||||
assert.equal(count(['a', 'b', 'c', 'd', 'e', 'f']), 6);
|
||||
});
|
||||
|
||||
void test('lobby mapping rejects duplicate, foreign, missing and forged primary assignments', () => {
|
||||
for (const value of [
|
||||
{ version: 1, controllers: [{ id: 'atreides', seats: ['atreides', 'atreides'] }] },
|
||||
{ version: 1, controllers: [{ id: 'atreides', seats: ['fremen'] }] },
|
||||
{ version: 1, controllers: [{ id: 'atreides', seats: ['atreides', 'foreign'] }] },
|
||||
{ version: 1, controllers: [
|
||||
{ id: 'atreides', seats: ['atreides', 'fremen'] },
|
||||
{ id: 'harkonnen', seats: ['harkonnen', 'fremen'] },
|
||||
] },
|
||||
{ version: 1, controllers: [{ id: 'atreides', seats: [] }] },
|
||||
{ version: 1, controllers: [{ id: 'atreides', seats: ['atreides'], secret: 'x' }] },
|
||||
{ version: 2, controllers: [] },
|
||||
{ version: 1, controllers: [], extra: true },
|
||||
]) assert.throws(() => lobby(value, seats), TwoPlayerControllersError);
|
||||
const state = assembled(), snapshot = structuredClone(state);
|
||||
assert.throws(() => lobby(state, seats.slice(0, 3)), TwoPlayerControllersError);
|
||||
assert.throws(() => lobby(state, ['atreides', 'atreides']), TwoPlayerControllersError);
|
||||
assert.deepEqual(state, snapshot);
|
||||
});
|
||||
|
||||
void test('incremental additions cannot steal, duplicate or exceed a controller seat', () => {
|
||||
let state = add(create(), seats, 'atreides', 'atreides');
|
||||
const before = structuredClone(state);
|
||||
assert.throws(() => add(state, seats, 'atreides', 'atreides'), TwoPlayerControllersError);
|
||||
assert.throws(() => add(state, seats, 'harkonnen', 'guild'), TwoPlayerControllersError);
|
||||
assert.throws(() => add(state, seats, 'atreides', 'unknown'), TwoPlayerControllersError);
|
||||
assert.deepEqual(state, before);
|
||||
state = add(state, seats, 'atreides', 'fremen');
|
||||
assert.throws(() => add(state, seats, 'atreides', 'guild'), TwoPlayerControllersError);
|
||||
state = add(state, seats, 'harkonnen', 'harkonnen');
|
||||
assert.throws(() => add(state, seats, 'guild', 'guild'), TwoPlayerControllersError);
|
||||
});
|
||||
|
||||
void test('a partial or malformed mapping cannot alter victory calculations', () => {
|
||||
const partial = add(create(), seats, 'atreides', 'atreides');
|
||||
assert.throws(() => count(seats, partial), TwoPlayerControllersError);
|
||||
assert.throws(() => target(seats, partial, false), TwoPlayerControllersError);
|
||||
assert.throws(() => target(seats, partial, true), TwoPlayerControllersError);
|
||||
assert.throws(() => count([], undefined), TwoPlayerControllersError);
|
||||
assert.throws(() => count(['a', 'a'], undefined), TwoPlayerControllersError);
|
||||
const restored = JSON.parse(JSON.stringify(assembled())) as TwoPlayerControllers;
|
||||
complete(restored, seats);
|
||||
assert.equal(target(seats, restored, false), 4);
|
||||
});
|
||||
Reference in new issue
Block a user