package persona // Character is the aggregate root for a character definition. // It combines all DNA, psychology, and background information. type Character struct { // ID is the unique identifier for this character. ID string `json:"id" yaml:"id"` // Version is the schema version for forward compatibility. Version string `json:"version" yaml:"version"` // Species determines validation rules (human, humanoid, android). Species SpeciesType `json:"species" yaml:"species"` // DNA contains the biological characteristics. DNA *DNA `json:"dna" yaml:"dna"` // Name contains the character's name information. Name NameSpec `json:"name" yaml:"name"` // Psychology contains the psychological profile. Psychology Psychology `json:"psychology" yaml:"psychology"` // Background contains backstory and life history. Background *Background `json:"background,omitempty" yaml:"background,omitempty"` // MorphLevel controls creature transformation intensity (humanoid only). // 0 = human, 25 = subtle, 50 = demi-human, 75 = hybrid, 100 = creature MorphLevel int `json:"morph_level,omitempty" yaml:"morph_level,omitempty"` // Morphology contains non-human physical features (humanoid only). // Only applied when MorphLevel >= 25. Morphology *MorphologyHints `json:"morphology,omitempty" yaml:"morphology,omitempty"` } // DNA contains the complete biological DNA specification for a character. // This is the single source of truth for all physical characteristics. // Once generated during character creation, this is immutable. type DNA struct { // Identity contains demographic and heritage information. Identity IdentityDNA `json:"identity" yaml:"identity"` // Face contains all facial feature specifications. Face FaceDNA `json:"face" yaml:"face"` // Body contains all body specifications. Body BodyDNA `json:"body" yaml:"body"` // Voice contains all voice specifications for TTS. Voice VoiceDNA `json:"voice" yaml:"voice"` } // NameSpec contains the character's name information. type NameSpec struct { // First is the first/given name. First string `json:"first" yaml:"first"` // Last is the last/family name. Last string `json:"last,omitempty" yaml:"last,omitempty"` // Middle is the middle name (if any). Middle string `json:"middle,omitempty" yaml:"middle,omitempty"` // Nickname is a preferred nickname. Nickname string `json:"nickname,omitempty" yaml:"nickname,omitempty"` // DisplayName is the name to show in UIs. // If empty, defaults to First name. DisplayName string `json:"display_name,omitempty" yaml:"display_name,omitempty"` } // FullName returns the full name as "First Last". func (n NameSpec) FullName() string { if n.Last == "" { return n.First } return n.First + " " + n.Last } // Display returns the display name, falling back to First name. func (n NameSpec) Display() string { if n.DisplayName != "" { return n.DisplayName } if n.Nickname != "" { return n.Nickname } return n.First } // NewCharacter creates a new character with default values. func NewCharacter(id string) *Character { return &Character{ ID: id, Version: "1.0", Species: SpeciesHuman, DNA: &DNA{}, } } // NewHumanCharacter creates a new human character. func NewHumanCharacter(id string) *Character { c := NewCharacter(id) c.Species = SpeciesHuman return c } // NewHumanoidCharacter creates a new humanoid character. func NewHumanoidCharacter(id string, morphLevel int) *Character { c := NewCharacter(id) c.Species = SpeciesHumanoid c.MorphLevel = morphLevel return c } // NewAndroidCharacter creates a new android character. func NewAndroidCharacter(id string) *Character { c := NewCharacter(id) c.Species = SpeciesAndroid return c } // IsHuman returns true if this is a human character. func (c *Character) IsHuman() bool { return c.Species == SpeciesHuman } // IsHumanoid returns true if this is a humanoid character. func (c *Character) IsHumanoid() bool { return c.Species == SpeciesHumanoid } // IsAndroid returns true if this is an android character. func (c *Character) IsAndroid() bool { return c.Species == SpeciesAndroid } // HasMorphology returns true if the character has non-human features. func (c *Character) HasMorphology() bool { return c.Morphology != nil && c.Morphology.HasFeatures() } // MorphBand returns the morph level band name. func (c *Character) MorphBand() string { return MorphLevelBand(c.MorphLevel) }