/** One labelled bond level on the opinion scale. */ export interface RelationshipMilestone { readonly id: string; readonly label: string; /** Opinion at which the pair reaches this level. */ readonly at: number; /** Familiarity the pair also needs; a bond wants time shared, not one good afternoon. */ readonly requiresFamiliarity?: number; } /** The pair levels every game starts from; a game overrides the words and the cut points. */ export declare const DEFAULT_RELATIONSHIP_MILESTONES: readonly RelationshipMilestone[]; /** How one pair stands: how much time they have shared, and what they think of each other. */ export interface Relationship { /** 0 (strangers) . 1 (they know each other well). */ readonly familiarity: number; /** The game's opinion scale, default -100 (rivals) . 100 (inseparable). */ readonly opinion: number; } /** Tunables a game owns, every one reachable through {@link RelationshipBook.retune}. */ export interface RelationshipPolicy { readonly opinionMin?: number; readonly opinionMax?: number; readonly familiarityMax?: number; readonly milestones?: readonly RelationshipMilestone[]; } /** Opinion and familiarity one interaction adds; a game passes its own for a hug, a row or a shift. */ export interface SocialContact { readonly familiarity?: number; readonly opinion?: number; } /** What one social action did to a pair. */ export interface SocialOutcome { readonly a: string; readonly b: string; readonly before: Relationship; readonly after: Relationship; /** Milestones newly crossed upward, lowest first - what a notice feed or a journal line reads. */ readonly crossed: readonly RelationshipMilestone[]; } /** Serializable relationship state: every known pair plus the dials in play. */ export interface RelationshipBookSnapshot { pairs: Record; policy: RelationshipPolicy; } /** What a plain social action adds: a shared moment nudges both dials, never maxes either. */ export declare const DEFAULT_SOCIAL_CONTACT: Required; /** * Everyone's view of everyone else: familiarity and opinion per pair, changed by social actions, * with the pair levels that make a friendship a preference and a bond a refusal to split. * * One book serves a whole world (a park, a household, a squad). Pairs are undirected, so * `opinion(a, b) === opinion(b, a)` and one interaction is enough for both sides. */ export interface RelationshipBook { /** How a pair stands; strangers read as `familiarity 0, opinion 0`. */ get(a: string, b: string): Relationship; familiarity(a: string, b: string): number; opinion(a: string, b: string): number; /** * Record one interaction between two agents. Defaults add a small amount of familiarity and * opinion; a game passes a larger or negative contact for a row or a rescue. An agent's own id is * ignored, so a wide query that includes the actor cannot self-bond. */ socialise(a: string, b: string, contact?: SocialContact): SocialOutcome; /** The highest milestone a pair has reached, or `null` for strangers. */ milestone(a: string, b: string): RelationshipMilestone | null; /** Id of the highest milestone reached, or `null`. */ label(a: string, b: string): string | null; friends(a: string, b: string): boolean; /** A bonded pair. */ bonded(a: string, b: string): boolean; /** The strongest bonded partner of `a`, or `null`. A tie keeps the first pair recorded. */ bondedWith(a: string): string | null; /** Friends or closer - the pair prefers each other's company when both are free. */ prefersCompanyOf(a: string, b: string): boolean; /** WHY: the rule that keeps a couple from being posted to opposite shifts is an opinion threshold, not a flag. */ refusesToSplit(a: string, b: string): boolean; /** Every agent this one has shared anything with, sorted by id. Allocates - UI and tests. */ partnersOf(a: string): readonly string[]; policy(): Required; retune(patch: RelationshipPolicy): void; snapshot(): RelationshipBookSnapshot; restore(next: RelationshipBookSnapshot): void; } /** * Create the shared book of pair state. Keys are undirected and delimiter-safe through * `createPairKeyCodec`, and milestone crossings come from `crossThresholds`, so a notice feed and a * journal both read the same event. * * @capability relationships familiarity and opinion between agents, with a bond that changes behaviour */ export declare function createRelationshipBook(policy?: RelationshipPolicy): RelationshipBook;