88 lines
4.1 KiB
TypeScript
88 lines
4.1 KiB
TypeScript
import assert from 'node:assert/strict';
|
||
import test from 'node:test';
|
||
import {
|
||
reorderSaphoMovementOrder, saphoMovementOrderEvent, SaphoMovementOrderError,
|
||
type SaphoMovementOrderContext,
|
||
} from '../game/sapho-movement-order';
|
||
|
||
function context(): SaphoMovementOrderContext {
|
||
return {
|
||
queue: {
|
||
event: 'movement:3', eligible: ['done', 'active', 'later', 'last'],
|
||
remaining: ['active', 'later', 'last'], completed: ['done'],
|
||
current: 'active', currentStarted: true, protectedLast: null,
|
||
},
|
||
started: ['done', 'active'], guild: null, allowStartedLast: true,
|
||
};
|
||
}
|
||
function request(input: SaphoMovementOrderContext, player = 'active', mode: 'first' | 'last' = 'last') {
|
||
return reorderSaphoMovementOrder(input, { event: saphoMovementOrderEvent(input), player, mode });
|
||
}
|
||
function reject(input: SaphoMovementOrderContext, player = 'active', mode: 'first' | 'last' = 'last', event?: string) {
|
||
const before = structuredClone(input);
|
||
assert.throws(() => reorderSaphoMovementOrder(input, {
|
||
event: event ?? saphoMovementOrderEvent(input), player, mode,
|
||
}), SaphoMovementOrderError);
|
||
assert.deepEqual(input, before);
|
||
}
|
||
|
||
void test('a Basic started actor suspends the same opportunity at a protected last position', () => {
|
||
const input = context(), before = structuredClone(input), event = saphoMovementOrderEvent(input);
|
||
const result = request(input);
|
||
assert.equal(result.event, event);
|
||
assert.equal(result.afterCurrent, null);
|
||
assert.equal(result.suspended, 'active');
|
||
assert.deepEqual(result.next, {
|
||
event: 'movement:3', eligible: ['done', 'active', 'later', 'last'],
|
||
remaining: ['later', 'last', 'active'], completed: ['done'],
|
||
current: 'later', currentStarted: false, protectedLast: 'active',
|
||
});
|
||
assert.deepEqual(input, before);
|
||
assert.notEqual(result.next.eligible, input.queue.eligible);
|
||
assert.notEqual(result.next.completed, input.queue.completed);
|
||
assert.notEqual(result.next.remaining, input.queue.remaining);
|
||
});
|
||
|
||
void test('started self-last needs explicit Basic admission and cannot create a first or duplicate turn', () => {
|
||
const input = context();
|
||
reject({ ...input, allowStartedLast: undefined });
|
||
reject({ ...input, allowStartedLast: false });
|
||
reject(input, 'active', 'first');
|
||
reject(input, 'done');
|
||
const alone = context();
|
||
alone.queue = { ...alone.queue, eligible: ['done', 'active'], remaining: ['active'], completed: ['done'] };
|
||
reject(alone);
|
||
const advanced = context();
|
||
advanced.guild = { player: 'last', granted: false, locked: false };
|
||
assert.equal(request(advanced).next.protectedLast, 'active');
|
||
const proposed = request(input);
|
||
const already = { ...input, queue: proposed.next, started: ['done', 'active'] };
|
||
assert.throws(() => saphoMovementOrderEvent(already), SaphoMovementOrderError);
|
||
});
|
||
|
||
void test('a started actor is bound to its current phase, actor and whole remaining tail', () => {
|
||
const input = context(), event = saphoMovementOrderEvent(input);
|
||
assert.notEqual(event, input.queue.event);
|
||
const changed = context();
|
||
changed.queue = { ...changed.queue, remaining: ['active', 'last', 'later'] };
|
||
reject(changed, 'active', 'last', event);
|
||
const nextPhase = context(); nextPhase.queue = { ...nextPhase.queue, event: 'movement:4' };
|
||
reject(nextPhase, 'active', 'last', event);
|
||
const changedActor = context();
|
||
changedActor.queue = { ...changedActor.queue, remaining: ['later', 'active', 'last'], current: 'later' };
|
||
changedActor.started = ['done', 'later'];
|
||
reject(changedActor, 'later', 'last', event);
|
||
const invalid = context(); invalid.started = ['active', 'later'];
|
||
assert.throws(() => saphoMovementOrderEvent(invalid), SaphoMovementOrderError);
|
||
});
|
||
|
||
void test('explicit admission does not change another player’s existing queued-turn reorder', () => {
|
||
const input = context(), before = structuredClone(input);
|
||
const result = request(input, 'last', 'first');
|
||
assert.equal(result.afterCurrent, 'active');
|
||
assert.equal(result.suspended, undefined);
|
||
assert.deepEqual(result.next.remaining, ['active', 'last', 'later']);
|
||
assert.equal(result.next.currentStarted, true);
|
||
assert.deepEqual(input, before);
|
||
});
|