/ src / systems / ltl.go
ltl.go
  1  // Package systems implements advanced cellular interactions
  2  package systems
  3  
  4  import (
  5  	"creature/src/models"
  6  	"math"
  7  	"sort"
  8  
  9  	"github.com/google/uuid"
 10  )
 11  
 12  // ExtendedNeighborhood manages cell interaction relationships
 13  type ExtendedNeighborhood struct {
 14  	Neighbors    map[uuid.UUID]NeighborInfo
 15  	Radius       float64
 16  	MaxNeighbors int
 17  }
 18  
 19  // NeighborInfo stores interaction data
 20  type NeighborInfo struct {
 21  	Distance float64
 22  	Weight   float64
 23  }
 24  
 25  // NewExtendedNeighborhood creates a new neighborhood configuration
 26  func NewExtendedNeighborhood(radius float64, maxNeighbors int) *ExtendedNeighborhood {
 27  	return &ExtendedNeighborhood{
 28  		Neighbors:    make(map[uuid.UUID]NeighborInfo),
 29  		Radius:       radius,
 30  		MaxNeighbors: maxNeighbors,
 31  	}
 32  }
 33  
 34  // CalculateInfluence computes interaction strength between cells
 35  func (en *ExtendedNeighborhood) CalculateInfluence(distance, sourcePhase, targetPhase float64) float64 {
 36  	spatial := 1 / (1 + math.Exp(-4*(en.Radius-distance)/en.Radius))
 37  	phaseSync := 0.5 * (1 + math.Cos(sourcePhase-targetPhase))
 38  	return spatial * (0.7 + 0.3*phaseSync)
 39  }
 40  
 41  // UpdateNeighbors refreshes the neighbor list based on current positions
 42  func (en *ExtendedNeighborhood) UpdateNeighbors(cellPos *models.Coordinates, others []CellEntry) {
 43  	type neighbor struct {
 44  		id       uuid.UUID
 45  		distance float64
 46  	}
 47  
 48  	var neighbors []neighbor
 49  	for _, entry := range others {
 50  		dist := Calculate3DDistance(cellPos, &entry.Position)
 51  		if dist <= en.Radius && dist > 0 {
 52  			neighbors = append(neighbors, neighbor{entry.ID, dist})
 53  		}
 54  	}
 55  
 56  	sort.Slice(neighbors, func(i, j int) bool {
 57  		return neighbors[i].distance < neighbors[j].distance
 58  	})
 59  
 60  	if len(neighbors) > en.MaxNeighbors {
 61  		neighbors = neighbors[:en.MaxNeighbors]
 62  	}
 63  
 64  	en.Neighbors = make(map[uuid.UUID]NeighborInfo)
 65  	for _, n := range neighbors {
 66  		en.Neighbors[n.id] = NeighborInfo{
 67  			Distance: n.distance,
 68  			Weight:   en.CalculateInfluence(n.distance, 0, 0), // Default phases
 69  		}
 70  	}
 71  }
 72  
 73  // EnhancedCellState represents advanced cell properties
 74  type EnhancedCellState struct {
 75  	Energy           float64
 76  	ActivityLevel    float64
 77  	Stability        float64
 78  	Phase            float64
 79  	PhaseVelocity    float64
 80  	CouplingStrength float64
 81  	AdaptationRate   float64
 82  }
 83  
 84  // NewEnhancedCellState creates a default initialized cell state
 85  func NewEnhancedCellState() *EnhancedCellState {
 86  	return &EnhancedCellState{
 87  		Energy:           100.0,
 88  		CouplingStrength: 0.5,
 89  		AdaptationRate:   0.1,
 90  	}
 91  }
 92  
 93  // CalculatePhaseCoupling updates synchronization dynamics
 94  func (ecs *EnhancedCellState) CalculatePhaseCoupling(phases, weights []float64) {
 95  	var phaseDiffSum, totalWeight float64
 96  
 97  	for i := range phases {
 98  		if i >= len(weights) {
 99  			break
100  		}
101  		phaseDiffSum += weights[i] * math.Sin(phases[i]-ecs.Phase)
102  		totalWeight += weights[i]
103  	}
104  
105  	if totalWeight > 0 {
106  		ecs.PhaseVelocity += ecs.CouplingStrength * phaseDiffSum / totalWeight
107  		ecs.Phase += ecs.PhaseVelocity * ecs.AdaptationRate
108  		ecs.Phase = math.Mod(ecs.Phase, 2*math.Pi)
109  		ecs.PhaseVelocity *= 0.9 // Damping
110  	}
111  }
112  
113  // UpdateState refreshes cell properties based on neighbors
114  func (ecs *EnhancedCellState) UpdateState(nh *ExtendedNeighborhood, neighbors map[uuid.UUID]*EnhancedCellState) {
115  	var (
116  		weightedEnergy, weightedActivity float64
117  		totalWeight                      float64
118  	)
119  
120  	for id, info := range nh.Neighbors {
121  		if neighbor, exists := neighbors[id]; exists {
122  			weightedEnergy += neighbor.Energy * info.Weight
123  			weightedActivity += neighbor.ActivityLevel * info.Weight
124  			totalWeight += info.Weight
125  		}
126  	}
127  
128  	if totalWeight > 0 {
129  		ecs.Energy = ecs.Energy*0.8 + (weightedEnergy/totalWeight)*0.2
130  		ecs.ActivityLevel = ecs.ActivityLevel*0.7 + (weightedActivity/totalWeight)*0.3
131  		ecs.Stability = ecs.calculateStability(nh, neighbors)
132  		ecs.Phase = math.Mod(ecs.Phase+0.1, 2*math.Pi)
133  	}
134  }
135  
136  func (ecs *EnhancedCellState) calculateStability(nh *ExtendedNeighborhood, neighbors map[uuid.UUID]*EnhancedCellState) float64 {
137  	var variance, count float64
138  
139  	for id, info := range nh.Neighbors {
140  		if neighbor, exists := neighbors[id]; exists {
141  			diff := ecs.Energy - neighbor.Energy
142  			variance += info.Weight * diff * diff
143  			count += 1
144  		}
145  	}
146  
147  	if count > 0 {
148  		return 1 / (1 + math.Sqrt(variance/count))
149  	}
150  	return 1.0
151  }
152  
153  // CellEntry combines ID and position for neighbor calculations
154  type CellEntry struct {
155  	ID       uuid.UUID
156  	Position models.Coordinates
157  }
158  
159  // InteractionEffect types
160  type InteractionEffect struct {
161  	Type  string
162  	Value float64
163  }
164  
165  var (
166  	EnergyBoost        = "EnergyBoost"
167  	Synchronization    = "SynchronizationBonus"
168  	SpawnConditionsMet = "SpawnConditionsMet"
169  )
170  
171  // Calculate3DDistance computes Euclidean distance in 3D space
172  func Calculate3DDistance(a, b *models.Coordinates) float64 {
173  	dx := a.X - b.X
174  	dy := a.Y - b.Y
175  	dz := a.Z - b.Z
176  	return math.Sqrt(dx*dx + dy*dy + dz*dz)
177  }