Enable Basic Kull by default and suspend Sapho turns

This commit is contained in:
Quintine committed 2026-10-27 21:51:43 +11:00
1 parent f96183f350
commit e9154a90f1
20 files changed
+669 -27

No files matched your search

+87
View File
@@ -0,0 +1,87 @@
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 };
reject(advanced);
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);
});