Add optional short alliance victory
Verify and publish checkpoint container / container (push) Successful in 11m2s

This commit is contained in:
Quintine committed 2026-10-28 21:40:24 +11:00
1 parent 8fb9f59106
commit e896570f07
25 files changed
+632 -27

No files matched your search

+3 -2
View File
@@ -10,11 +10,11 @@ const keys = (value: Record<string, unknown>, names: string[]) => Object.keys(va
const integer = (value: unknown): value is number => Number.isSafeInteger(value) && Number(value) >= 0;
export function validAdminLobbyView(value: unknown): value is AdminLobbyView {
if (!object(value) || !keys(value, ['code', 'version', 'status', 'editable', 'blockedReason', 'host', 'advanced', 'techTokens', 'strongholdCards', 'players', 'control']) ||
if (!object(value) || !keys(value, ['code', 'version', 'status', 'editable', 'blockedReason', 'host', 'advanced', 'techTokens', 'strongholdCards', 'shortAllianceVictory', 'players', 'control']) ||
typeof value.code !== 'string' || value.code.length !== 8 || !/^[A-Z2-9]{8}$/.test(value.code) || !integer(value.version) ||
!['lobby', 'setup', 'playing', 'finished', 'unreadable'].includes(String(value.status)) || typeof value.editable !== 'boolean' ||
!(value.blockedReason === null || typeof value.blockedReason === 'string') || !(value.host === null || typeof value.host === 'string') ||
typeof value.advanced !== 'boolean' || typeof value.techTokens !== 'boolean' || typeof value.strongholdCards !== 'boolean' ||
typeof value.advanced !== 'boolean' || typeof value.techTokens !== 'boolean' || typeof value.strongholdCards !== 'boolean' || typeof value.shortAllianceVictory !== 'boolean' ||
!Array.isArray(value.players) || value.players.length > 6 || !object(value.control)) return false;
const control = value.control;
return keys(control, ['paused', 'joinLocked', 'revision', 'updatedAt', ...(control.closed === true ? ['closed'] : [])]) && typeof control.paused === 'boolean' && typeof control.joinLocked === 'boolean' &&
@@ -74,6 +74,7 @@ export function describeAdminLobbyAction(action: AdminLobbyAction, view: AdminLo
case 'rules': return `Select ${action.advanced ? 'Advanced preview' : 'Basic'} rules`;
case 'techTokens': return `${action.enabled ? 'Enable' : 'Disable'} Tech Tokens`;
case 'strongholdCards': return `${action.enabled ? 'Enable' : 'Disable'} Stronghold Cards`;
case 'shortAllianceVictory': return `${action.enabled ? 'Enable' : 'Disable'} the optional three-stronghold alliance victory`;
case 'addBot': return `Add ${faction} AI at ${action.difficulty}`;
case 'removeBot': return `Remove AI player ${player}`;
case 'configureBot': return `Configure ${player}: ${faction}, ${action.difficulty}, circle ${action.position}`;
+3 -2
View File
@@ -4,7 +4,7 @@ import type { RoomControl } from './room-control';
export type AdminLobbyAction =
| { type: 'rules'; advanced: boolean }
| { type: 'techTokens' | 'strongholdCards'; enabled: boolean }
| { type: 'techTokens' | 'strongholdCards' | 'shortAllianceVictory'; enabled: boolean }
| { type: 'addBot'; faction: FactionId; difficulty: Difficulty }
| { type: 'removeBot' | 'assignHost'; target: string }
| {
@@ -30,6 +30,7 @@ export type AdminLobbyView = {
advanced: boolean;
techTokens: boolean;
strongholdCards: boolean;
shortAllianceVictory: boolean;
players: {
id: string;
name: string;
@@ -84,7 +85,7 @@ export function validAdminLobbyInput(value: unknown): value is AdminLobbyInput {
return (
keys(action, ['type', 'advanced']) && typeof action.advanced === 'boolean'
);
if (action.type === 'techTokens' || action.type === 'strongholdCards')
if (action.type === 'techTokens' || action.type === 'strongholdCards' || action.type === 'shortAllianceVictory')
return (
keys(action, ['type', 'enabled']) && typeof action.enabled === 'boolean'
);