package races import ( "fmt" ) // RaceAware interface for entities that have race information type RaceAware interface { GetRace() int8 SetRace(int8) } // EntityWithRace interface extends RaceAware with additional entity properties type EntityWithRace interface { RaceAware GetID() int32 GetName() string } // RaceIntegration provides race-related functionality for other systems type RaceIntegration struct { races *Races utils *RaceUtils } // NewRaceIntegration creates a new race integration helper func NewRaceIntegration() *RaceIntegration { return &RaceIntegration{ races: GetGlobalRaces(), utils: NewRaceUtils(), } } // ValidateEntityRace validates an entity's race and provides detailed information func (ri *RaceIntegration) ValidateEntityRace(entity RaceAware) (bool, string, map[string]any) { raceID := entity.GetRace() if !ri.races.IsValidRaceID(raceID) { return false, fmt.Sprintf("Invalid race ID: %d", raceID), nil } raceInfo := ri.races.GetRaceInfo(raceID) return true, "Valid race", raceInfo } // ApplyRacialBonuses applies racial stat bonuses to an entity // This would integrate with the stat system when available func (ri *RaceIntegration) ApplyRacialBonuses(entity RaceAware, stats map[string]*int16) { raceID := entity.GetRace() if !ri.races.IsValidRaceID(raceID) { return } // Get racial modifiers modifiers := ri.utils.GetRaceStatModifiers(raceID) // Apply modifiers to stats for statName, modifier := range modifiers { if statPtr, exists := stats[statName]; exists && statPtr != nil { *statPtr += int16(modifier) } } } // GetEntityRaceInfo returns comprehensive race information for an entity func (ri *RaceIntegration) GetEntityRaceInfo(entity EntityWithRace) map[string]any { info := make(map[string]any) // Basic entity info info["entity_id"] = entity.GetID() info["entity_name"] = entity.GetName() // Race information raceID := entity.GetRace() raceInfo := ri.races.GetRaceInfo(raceID) info["race"] = raceInfo // Additional race-specific info info["description"] = ri.utils.GetRaceDescription(raceID) info["starting_location"] = ri.utils.GetRaceStartingLocation(raceID) info["stat_modifiers"] = ri.utils.GetRaceStatModifiers(raceID) info["aliases"] = ri.utils.GetRaceAliases(raceID) info["compatible_races"] = ri.utils.GetCompatibleRaces(raceID) return info } // ChangeEntityRace changes an entity's race with validation func (ri *RaceIntegration) ChangeEntityRace(entity RaceAware, newRaceID int8) error { if !ri.races.IsValidRaceID(newRaceID) { return fmt.Errorf("invalid race ID: %d", newRaceID) } oldRaceID := entity.GetRace() // Validate the race transition if valid, reason := ri.utils.ValidateRaceTransition(oldRaceID, newRaceID); !valid { return fmt.Errorf("race change not allowed: %s", reason) } // Perform the race change entity.SetRace(newRaceID) return nil } // GetRandomRaceForEntity returns a random race appropriate for an entity func (ri *RaceIntegration) GetRandomRaceForEntity(alignment string) int8 { return ri.utils.GetRandomRaceByAlignment(alignment) } // CheckRaceCompatibility checks if two entities' races are compatible func (ri *RaceIntegration) CheckRaceCompatibility(entity1, entity2 RaceAware) bool { race1 := entity1.GetRace() race2 := entity2.GetRace() if !ri.races.IsValidRaceID(race1) || !ri.races.IsValidRaceID(race2) { return false } // Same race is always compatible if race1 == race2 { return true } // Check alignment compatibility alignment1 := ri.races.GetRaceAlignment(race1) alignment2 := ri.races.GetRaceAlignment(race2) // Neutral races are compatible with everyone if alignment1 == AlignmentNeutral || alignment2 == AlignmentNeutral { return true } // Same alignment races are compatible return alignment1 == alignment2 } // FormatEntityRace returns a formatted race name for an entity func (ri *RaceIntegration) FormatEntityRace(entity RaceAware, format string) string { raceID := entity.GetRace() return ri.utils.FormatRaceName(raceID, format) } // GetEntityRaceAlignment returns an entity's race alignment func (ri *RaceIntegration) GetEntityRaceAlignment(entity RaceAware) string { raceID := entity.GetRace() return ri.races.GetRaceAlignment(raceID) } // IsEntityGoodRace checks if an entity is a good-aligned race func (ri *RaceIntegration) IsEntityGoodRace(entity RaceAware) bool { raceID := entity.GetRace() return ri.races.IsGoodRace(raceID) } // IsEntityEvilRace checks if an entity is an evil-aligned race func (ri *RaceIntegration) IsEntityEvilRace(entity RaceAware) bool { raceID := entity.GetRace() return ri.races.IsEvilRace(raceID) } // IsEntityNeutralRace checks if an entity is a neutral race func (ri *RaceIntegration) IsEntityNeutralRace(entity RaceAware) bool { raceID := entity.GetRace() return ri.races.IsNeutralRace(raceID) } // GetEntitiesByRace filters entities by race func (ri *RaceIntegration) GetEntitiesByRace(entities []RaceAware, raceID int8) []RaceAware { result := make([]RaceAware, 0) for _, entity := range entities { if entity.GetRace() == raceID { result = append(result, entity) } } return result } // GetEntitiesByAlignment filters entities by race alignment func (ri *RaceIntegration) GetEntitiesByAlignment(entities []RaceAware, alignment string) []RaceAware { result := make([]RaceAware, 0) for _, entity := range entities { entityAlignment := ri.GetEntityRaceAlignment(entity) if entityAlignment == alignment { result = append(result, entity) } } return result } // ValidateRaceForClass checks if a race/class combination is valid func (ri *RaceIntegration) ValidateRaceForClass(raceID, classID int8) (bool, string) { if !ri.races.IsValidRaceID(raceID) { return false, "Invalid race" } // Use the utility function (which currently allows all combinations) if ri.utils.ValidateRaceForClass(raceID, classID) { return true, "" } raceName := ri.races.GetRaceNameCase(raceID) return false, fmt.Sprintf("Race %s cannot be class %d", raceName, classID) } // GetRaceStartingStats returns the starting stats for a race func (ri *RaceIntegration) GetRaceStartingStats(raceID int8) map[string]int16 { baseStats := map[string]int16{ "strength": 50, "stamina": 50, "agility": 50, "wisdom": 50, "intelligence": 50, } // Apply racial modifiers modifiers := ri.utils.GetRaceStatModifiers(raceID) for statName, modifier := range modifiers { if baseStat, exists := baseStats[statName]; exists { baseStats[statName] = baseStat + int16(modifier) } } return baseStats } // CreateRaceSpecificEntity creates entity data with race-specific properties func (ri *RaceIntegration) CreateRaceSpecificEntity(raceID int8) map[string]any { if !ri.races.IsValidRaceID(raceID) { return nil } entityData := make(map[string]any) // Basic race info entityData["race_id"] = raceID entityData["race_name"] = ri.races.GetRaceNameCase(raceID) entityData["alignment"] = ri.races.GetRaceAlignment(raceID) // Starting stats entityData["starting_stats"] = ri.GetRaceStartingStats(raceID) // Starting location entityData["starting_location"] = ri.utils.GetRaceStartingLocation(raceID) // Race description entityData["description"] = ri.utils.GetRaceDescription(raceID) return entityData } // GetRaceSelectionData returns data for race selection UI func (ri *RaceIntegration) GetRaceSelectionData() map[string]any { data := make(map[string]any) // All available races allRaces := ri.races.GetAllRaces() raceList := make([]map[string]any, 0, len(allRaces)) for raceID, friendlyName := range allRaces { raceData := map[string]any{ "id": raceID, "name": friendlyName, "alignment": ri.races.GetRaceAlignment(raceID), "description": ri.utils.GetRaceDescription(raceID), "stats": ri.GetRaceStartingStats(raceID), } raceList = append(raceList, raceData) } data["races"] = raceList data["statistics"] = ri.utils.GetRaceStatistics() return data } // Global race integration instance var globalRaceIntegration *RaceIntegration // GetGlobalRaceIntegration returns the global race integration helper func GetGlobalRaceIntegration() *RaceIntegration { if globalRaceIntegration == nil { globalRaceIntegration = NewRaceIntegration() } return globalRaceIntegration }