diff --git a/components/coalition-nexus.tsx b/components/coalition-nexus.tsx index a88261dd..09b09fd9 100644 --- a/components/coalition-nexus.tsx +++ b/components/coalition-nexus.tsx @@ -10,6 +10,8 @@ export type CoalitionNexusView = { groups: readonly CoalitionGroup[]; proposal: CoalitionAdmission | null; revision: number; + /** Absent preserves the original, at-most-three alliance prototype. */ + variant?: 'unlimited'; }; export type CoalitionNexusIntent = @@ -28,7 +30,7 @@ export function coalitionNexusOptions(view: CoalitionNexusView): { const ownGroup = view.groups.find(group => group.members.includes(view.me)); const occupied = new Set(view.groups.flatMap(group => group.members)); const invitations = !seated || view.proposal ? [] : view.groups.flatMap(group => - group.members.length !== 2 ? [] : view.players + (group.members.length < 2 || group.members.length >= (view.variant === 'unlimited' ? 6 : 3)) ? [] : view.players .filter(player => !occupied.has(player.id) && (player.id === view.me || group.members.includes(view.me))) .map(player => ({ groupId: group.id, entrant: player.id, members: group.members }))); @@ -57,8 +59,10 @@ export function CoalitionNexus({ view, disabled = false, onIntent }: { const submit = (intent: CoalitionNexusIntent) => { if (!disabled) onIntent(intent); }; return

Group alliance negotiations

-

All three players must agree before an invitation forms an alliance. - The existing pair remains allied while an invitation is pending.

+ {view.variant === 'unlimited' ?

Every current member and the invited player must agree. + The existing alliance remains in place while an invitation is pending.

: +

All three players must agree before an invitation forms an alliance. + The existing pair remains allied while an invitation is pending.

} {view.groups.length ? :

There are no alliances yet.

} {proposal ?
@@ -77,7 +81,9 @@ export function CoalitionNexus({ view, disabled = false, onIntent }: { proposal.approvals.includes(view.me) ? 'Withdraw approval and cancel invitation' : 'Decline and cancel invitation'}}
:
- {options.invitations.length > 0 &&

Invite an unallied player to an existing pair, or ask to join a pair.

} + {options.invitations.length > 0 &&

{view.variant === 'unlimited' + ? 'Invite an unallied player to an existing alliance, or ask to join one.' + : 'Invite an unallied player to an existing pair, or ask to join a pair.'}

} {options.invitations.map(option => } {ownGroup?.members.length === 3 &&

Leaving keeps the other two players allied under the provisional online policy.

} + {view.variant === 'unlimited' && (ownGroup?.members.length ?? 0) > 3 && +

Leaving keeps the other players allied under the provisional online policy.

}
}
; } diff --git a/components/game-table.tsx b/components/game-table.tsx index 66f8c919..24cc91d8 100644 --- a/components/game-table.tsx +++ b/components/game-table.tsx @@ -306,7 +306,7 @@ export function GameTable({ }) { const me = g.players.find((p) => p.id === g.me)!; const groupNexus = g.coalitionNexus; - const inGroup = groupNexus?.groups.some(group => group.members.length === 3 && group.members.includes(me.id)); + const inGroup = groupNexus?.groups.some(group => group.members.length >= 3 && group.members.includes(me.id)); const outgoingAlliance = g.allianceOffers[me.id]; const outgoingAllianceName = g.players.find((p) => p.id === outgoingAlliance)?.name; const shipmentAvailable = nexusGuildShipmentAvailable(g); @@ -4395,7 +4395,7 @@ export function GameTable({ {g.players .filter((p) => p.id !== me.id && !groupNexus?.groups.some(group => - group.members.length === 3 && group.members.includes(p.id))) + group.members.length >= 3 && group.members.includes(p.id))) .map((p) => (