import type { FactionRelation } from "../faction/factions.js"; /** * A rank within a group's hierarchy. Higher `level` means more authority: a member can only * manage (kick, re-rank) members strictly below their own level, and cannot promote anyone to a * level at or above their own. `permissions` are opaque, genre-agnostic capability slugs the game * checks with {@link Tribe.can} (e.g. `"build"`, `"demolish"`, `"invite"`, `"kick"`, `"manage-ranks"`, * plus the {@link AssetAction} slugs `"inventory"`, `"use"`, `"command"` for group-owned assets). * A `bypass` rank (an admin) skips every permission check, exactly like the founder. */ export interface TribeRankDef { id: string; name: string; /** Higher = more authority. Determines who can manage/promote whom. */ level: number; /** Capability slugs this rank grants; checked by {@link Tribe.can} and {@link Tribe.canAccess}. */ permissions?: readonly string[]; /** Admin rank — bypasses all permission and hierarchy checks (like the founder). */ bypass?: boolean; } /** Per-asset action gated by rank on group-owned assets. */ export type AssetAction = "inventory" | "use" | "command"; /** Opaque reference to a shared thing (structure, creature, container) by kind + id. */ export interface AssetRef { kind: string; id: string; } /** Who inside the group owns an asset: the group as a whole, or a specific member personally. */ export type AssetOwnership = { scope: "group"; } | { scope: "personal"; memberId: string; }; /** The kind of change recorded in a tribe's event log (membership, ownership, or alliance). */ export type TribeEventType = "member-added" | "member-removed" | "member-left" | "rank-changed" | "founder-transferred" | "asset-registered" | "asset-unregistered" | "alliance-formed" | "alliance-broken"; /** One entry in a tribe's bounded event log. Optional fields present only when meaningful. */ export interface TribeEvent { seq: number; type: TribeEventType; at: number; /** Member who performed the action, when applicable. */ actor?: string; /** Member the action targets (added/removed/re-ranked). */ subject?: string; /** Other tribe id, for alliance events. */ tribeId?: string; rankId?: string; assetKind?: string; assetId?: string; } /** A member of a tribe and the rank id that governs their permissions. */ export interface TribeMemberRecord { id: string; rankId: string; joinedAt: number; } /** An asset (structure/creature) owned within a tribe — group-shared or held by one member. */ export interface TribeAssetRecord { kind: string; id: string; /** `null` marks a group-owned asset; otherwise the member who owns it personally. */ ownerId: string | null; } /** Full serializable state of one tribe — the save/replication baseline. */ export interface TribeSnapshot { id: string; founderId: string; ranks: TribeRankDef[]; defaultRankId: string; founderRankId: string; logCap: number; members: TribeMemberRecord[]; assets: TribeAssetRecord[]; allies: string[]; events: TribeEvent[]; eventSeq: number; } /** Construction options for {@link createTribe}: id, founder, rank ladder, and log cap. */ export interface TribeConfig { id: string; founderId: string; /** At least one rank. */ ranks: readonly TribeRankDef[]; /** Rank new members receive; defaults to the lowest-level rank. */ defaultRankId?: string; /** Rank the founder holds; defaults to the highest-level rank. */ founderRankId?: string; /** Max events retained in the ring buffer (default 128). */ logCap?: number; /** Injected clock for deterministic timestamps; defaults to `Date.now`. */ now?: () => number; } /** Standard `{ reason }`-on-failure / `null`-on-success result for authorized mutations. */ export type TribeResult = { reason: string; } | null; /** * A shared-ownership group — a tribe, guild, clan, or company — as one first-class aggregate. * Unifies ranked membership, group-vs-personal asset ownership, mutual alliances, and a bounded * event log that otherwise have to be hand-assembled from parties, factions, build permissions, * and per-owner rosters. */ export interface Tribe { readonly id: string; founderId(): string; hasMember(memberId: string): boolean; memberIds(): readonly string[]; rankOf(memberId: string): TribeRankDef | null; /** True if the member's rank grants `permission`, or they are the founder / an admin rank. */ can(memberId: string, permission: string): boolean; /** Founder or a `bypass` rank — skips every permission check. */ isAdmin(memberId: string): boolean; addMember(actorId: string, memberId: string, rankId?: string): TribeResult; removeMember(actorId: string, memberId: string): TribeResult; leave(memberId: string): TribeResult; setMemberRank(actorId: string, memberId: string, rankId: string): TribeResult; transferFounder(actorId: string, memberId: string): TribeResult; registerAsset(actorId: string, ref: AssetRef, ownership: AssetOwnership): TribeResult; unregisterAsset(actorId: string, ref: AssetRef): TribeResult; ownerOfAsset(ref: AssetRef): AssetOwnership | null; /** Personal assets a member holds inside this group (they keep these on leaving). */ assetsOf(memberId: string): readonly AssetRef[]; /** Resolve access to an asset: rank permission for group assets, ownership for personal ones. */ canAccess(memberId: string, ref: AssetRef, action: AssetAction): boolean; addAlly(tribeId: string): void; removeAlly(tribeId: string): void; isAllied(tribeId: string): boolean; allyIds(): readonly string[]; /** `"friendly"` for self and allies, else `"neutral"` — never hostile by default. */ relationTo(tribeId: string): FactionRelation; events(): readonly TribeEvent[]; snapshot(): TribeSnapshot; hydrate(snapshot: TribeSnapshot): void; } /** * Create a shared-ownership group aggregate (tribe / guild / clan / company). Members hold a * {@link TribeRankDef rank} whose configurable permission slugs gate management actions and access * to group-owned assets, while personally-owned assets stay with their member — and follow them out * when they leave. Group↔group {@link Tribe.addAlly alliances} resolve allied tribes as friendly, and * every membership / ownership / alliance change lands in a bounded ring-buffer {@link Tribe.events log}. * All state is plain JSON via {@link Tribe.snapshot}/{@link Tribe.hydrate}; timestamps come from an * injected clock for determinism. Compose many tribes with {@link createTribeRegistry} for mutual * alliances and cross-member relation lookups. * * @capability tribe-group shared-ownership group (tribe/guild/clan) with ranked permissions, group vs personal assets, alliances, and a bounded event log */ export declare function createTribe(config: TribeConfig): Tribe; /** Injected dependencies for {@link createTribeRegistry} (e.g. a `now()` clock for event timestamps). */ export interface TribeRegistryDeps { now?: () => number; defaultLogCap?: number; } /** Full serializable state of a tribe registry — every tribe's snapshot in one payload. */ export interface TribeRegistrySnapshot { tribes: TribeSnapshot[]; } /** * A collection of {@link Tribe tribes} with mutual alliance management and cross-member relation * lookups. Alliances are kept symmetric here (both sides updated together), and member-to-member * relations resolve through tribe membership + alliances, mirroring the `faction` graph vocabulary. */ export interface TribeRegistry { create(config: TribeConfig): Tribe; get(id: string): Tribe | null; all(): readonly Tribe[]; remove(id: string): void; /** Form a mutual alliance, updating and logging both tribes. */ formAlliance(tribeA: string, tribeB: string): TribeResult; /** Break a mutual alliance on both sides. */ breakAlliance(tribeA: string, tribeB: string): void; areAllied(tribeA: string, tribeB: string): boolean; relationBetweenTribes(tribeA: string, tribeB: string): FactionRelation; tribeOfMember(memberId: string): Tribe | null; relationBetweenMembers(memberA: string, memberB: string): FactionRelation; isFriendly(memberA: string, memberB: string): boolean; snapshot(): TribeRegistrySnapshot; hydrate(snapshot: TribeRegistrySnapshot): void; } /** * Create a registry that owns many tribes, keeps alliances mutual, and resolves member relations. * * @capability tribe-registry registry of tribes with mutual alliances and cross-tribe relation lookup */ export declare function createTribeRegistry(deps?: TribeRegistryDeps): TribeRegistry;