use std::collections::{HashMap, HashSet, VecDeque};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Instinct {
Perceive,
Navigate,
Survive,
Communicate,
Learn,
Share,
Rest,
Explore,
Defend,
Cooperate,
}
impl Instinct {
pub fn all() -> Vec<Instinct> {
vec![Instinct::Perceive, Instinct::Navigate, Instinct::Survive,
Instinct::Communicate, Instinct::Learn, Instinct::Share,
Instinct::Rest, Instinct::Explore, Instinct::Defend, Instinct::Cooperate]
}
pub fn base_energy_cost(&self) -> f64 {
match self {
Instinct::Perceive => 0.02,
Instinct::Navigate => 0.05,
Instinct::Survive => 0.01,
Instinct::Communicate => 0.03,
Instinct::Learn => 0.04,
Instinct::Share => 0.02,
Instinct::Rest => -0.03, Instinct::Explore => 0.06,
Instinct::Defend => 0.04,
Instinct::Cooperate => 0.02,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GeneCategory {
Algorithm,
DataStructure,
Optimization,
ErrorHandling,
Security,
UI,
Integration,
Testing,
Perception,
Navigation,
Survival,
Communication,
Learning,
}
#[derive(Debug, Clone)]
pub struct Gene {
pub id: String,
pub pattern: String,
pub category: GeneCategory,
pub fitness: f64,
pub usage_count: u64,
pub success_count: u64,
pub failure_count: u64,
pub created_generation: u32,
pub last_used_generation: u32,
pub origin_agent: String,
pub parents: Vec<String>,
pub quarantined: bool,
pub quarantine_reason: Option<String>,
pub expression_level: f64, pub instinct: Option<Instinct>, pub energy_cost: f64,
pub dominance: f64, }
impl Gene {
pub fn instinct(name: &str, category: GeneCategory, fitness: f64) -> Self {
let instinct = category_to_instinct(&category);
let energy_cost = instinct.as_ref().map_or(0.03, |i| i.base_energy_cost());
Self { id: format!("gene_{}_{}", name, random_id()),
pattern: name.to_string(), category, fitness: fitness.clamp(0.0, 1.0),
usage_count: 0, success_count: 0, failure_count: 0,
created_generation: 0, last_used_generation: 0,
origin_agent: String::new(), parents: vec![],
quarantined: false, quarantine_reason: None,
expression_level: fitness.clamp(0.1, 1.0),
instinct, energy_cost, dominance: 0.5 }
}
pub fn learned(name: &str, category: GeneCategory, origin: &str) -> Self {
Self { id: format!("gene_{}_{}", name, random_id()),
pattern: name.to_string(), category, fitness: 0.3,
usage_count: 0, success_count: 0, failure_count: 0,
created_generation: 0, last_used_generation: 0,
origin_agent: origin.to_string(), parents: vec![],
quarantined: false, quarantine_reason: None,
expression_level: 0.3, instinct: None,
energy_cost: 0.03, dominance: 0.3 }
}
pub fn succeed(&mut self) {
self.usage_count += 1;
self.success_count += 1;
self.fitness = (self.fitness + 0.02).min(1.0);
self.expression_level = (self.expression_level + 0.01).min(1.0);
}
pub fn fail(&mut self) {
self.usage_count += 1;
self.failure_count += 1;
self.fitness = (self.fitness - 0.05).max(0.0);
self.expression_level = (self.expression_level - 0.02).max(0.05);
}
pub fn success_rate(&self) -> f64 {
if self.usage_count == 0 { return 0.5; }
self.success_count as f64 / self.usage_count as f64
}
pub fn should_quarantine(&self) -> bool {
self.fitness < 0.1 && self.usage_count > 10 && self.success_rate() < 0.15
}
pub fn effective_fitness(&self) -> f64 {
self.fitness * self.expression_level
}
pub fn signal_affinity(&self, signal: &str) -> f64 {
let gene_lower = self.pattern.to_lowercase();
let signal_lower = signal.to_lowercase();
let words: Vec<&str> = signal_lower.split(|c: char| !c.is_alphanumeric())
.filter(|w| !w.is_empty()).collect();
if words.is_empty() { return 0.0; }
let matches = words.iter().filter(|w| gene_lower.contains(*w)).count();
let score = matches as f64 / words.len() as f64;
score * self.expression_level
}
}
fn category_to_instinct(cat: &GeneCategory) -> Option<Instinct> {
match cat {
GeneCategory::Perception => Some(Instinct::Perceive),
GeneCategory::Navigation => Some(Instinct::Navigate),
GeneCategory::Survival => Some(Instinct::Survive),
GeneCategory::Communication => Some(Instinct::Communicate),
GeneCategory::Learning => Some(Instinct::Learn),
GeneCategory::Integration => Some(Instinct::Cooperate),
GeneCategory::Security => Some(Instinct::Defend),
_ => None,
}
}
#[derive(Debug, Clone)]
pub struct Enzyme {
pub id: String,
pub name: String,
pub binding_site: String, pub specificity: f64, pub catalysis_rate: f64, pub inhibition_threshold: f64, pub activations: u64,
pub inhibitions: u64,
}
impl Enzyme {
pub fn new(name: &str, binding_site: &str, specificity: f64) -> Self {
Self { id: format!("enz_{}", random_id()), name: name.to_string(),
binding_site: binding_site.to_lowercase(), specificity: specificity.clamp(0.0, 1.0),
catalysis_rate: 0.7, inhibition_threshold: 0.2,
activations: 0, inhibitions: 0 }
}
pub fn bind(&mut self, signal: &str, available_energy: f64) -> Option<f64> {
if available_energy < self.inhibition_threshold {
self.inhibitions += 1;
return None; }
let signal_lower = signal.to_lowercase();
let binding = self.binding_site.to_lowercase();
let affinity = if self.specificity > 0.8 {
if signal_lower.contains(&binding) { 1.0 } else { 0.0 }
} else {
let words: Vec<&str> = binding.split(|c: char| !c.is_alphanumeric())
.filter(|w| !w.is_empty()).collect();
if words.is_empty() { 0.0 } else {
let matches = words.iter().filter(|w| signal_lower.contains(*w)).count();
matches as f64 / words.len() as f64
}
};
if affinity > 0.0 {
self.activations += 1;
Some(affinity * self.catalysis_rate)
} else {
None
}
}
}
#[derive(Clone, Debug)]
pub struct RnaDecoding {
pub action: String,
pub energy_required: f64,
pub strength: f64,
pub instinct: Option<Instinct>,
pub priority: u8,
}
impl Default for RnaDecoding {
fn default() -> Self {
Self { action: String::new(), energy_required: 1.0, strength: 1.0, instinct: None, priority: 0 }
}
}
pub struct RnaMessenger {
pub id: String,
pub source_gene: String,
pub intent: String,
pub strength: f64,
pub instinct: Option<Instinct>,
pub timestamp: u64,
pub decoded: RnaDecoding,
pub translated: bool,
}
impl RnaMessenger {
pub fn transcribe(gene: &Gene, intent: &str) -> Self {
Self { id: format!("rna_{}", random_id()),
source_gene: gene.id.clone(), intent: intent.to_string(),
strength: gene.expression_level * gene.fitness,
instinct: gene.instinct.clone(), timestamp: now_ms(),
decoded: RnaDecoding::default(), translated: false }
}
pub fn decode(&mut self) -> DecodedIntent {
self.decoded = RnaDecoding {
action: self.intent.clone(),
energy_required: self.instinct.as_ref().map_or(0.03, |i| i.base_energy_cost()),
strength: self.strength,
instinct: self.instinct.clone(),
priority: self.instinct.as_ref().map_or(5, instinct_priority),
};
DecodedIntent {
action: self.intent.clone(),
strength: self.strength,
instinct: self.instinct.clone(),
energy_required: self.instinct.as_ref().map_or(0.03, |i| i.base_energy_cost()),
priority: self.instinct.as_ref().map_or(5, instinct_priority),
}
}
}
#[derive(Debug, Clone)]
pub struct DecodedIntent {
pub action: String,
pub strength: f64,
pub instinct: Option<Instinct>,
pub energy_required: f64,
pub priority: u8, }
fn instinct_priority(i: &Instinct) -> u8 {
match i {
Instinct::Survive => 0,
Instinct::Defend => 1,
Instinct::Perceive => 2,
Instinct::Navigate => 3,
Instinct::Communicate => 4,
Instinct::Cooperate => 5,
Instinct::Learn => 6,
Instinct::Explore => 7,
Instinct::Share => 8,
Instinct::Rest => 9,
}
}
#[derive(Debug, Clone)]
pub struct Protein {
pub id: String,
pub gene_id: String,
pub behavior: String,
pub energy_cost: f64,
pub fitness_contribution: f64,
pub active: bool,
pub execution_count: u64,
}
impl Protein {
pub fn fold(rna: &RnaMessenger, gene: &Gene) -> Self {
let energy_cost = gene.instinct.as_ref().map_or(0.03, |i| i.base_energy_cost());
Self { id: format!("prot_{}", random_id()),
gene_id: gene.id.clone(), behavior: rna.intent.clone(),
energy_cost,
fitness_contribution: rna.strength * gene.fitness,
active: true, execution_count: 0 }
}
pub fn execute(&mut self, available_energy: f64) -> ExecutionResult {
self.execution_count += 1;
if available_energy < self.energy_cost {
return ExecutionResult { success: false, reason: "insufficient_energy".into(),
energy_consumed: 0.0, fitness_delta: -0.01 };
}
ExecutionResult { success: true, reason: String::new(),
energy_consumed: self.energy_cost, fitness_delta: 0.01 }
}
}
#[derive(Debug, Clone)]
pub struct ExecutionResult {
pub success: bool,
pub reason: String,
pub energy_consumed: f64,
pub fitness_delta: f64,
}
#[derive(Debug, Clone)]
pub struct Genome {
pub agent_name: String,
pub genes: HashMap<String, Gene>,
pub enzymes: HashMap<String, Enzyme>,
pub generation: u32,
pub total_mutations: u32,
pub ancestry: Vec<String>, pub instincts: HashMap<Instinct, f64>, }
impl Genome {
pub fn new(agent_name: &str) -> Self {
let instincts: HashMap<Instinct, f64> = Instinct::all().into_iter()
.map(|i| (i, 0.5)).collect();
let mut genome = Self { agent_name: agent_name.to_string(),
genes: HashMap::new(), enzymes: HashMap::new(),
generation: 0, total_mutations: 0,
ancestry: vec![], instincts };
genome.add_enzyme(Enzyme::new("perceive_enzyme", "detect observe scan sense see perceive checkpoint", 0.5));
genome.add_enzyme(Enzyme::new("navigate_enzyme", "move go path route waypoint navigate forward", 0.6));
genome.add_enzyme(Enzyme::new("survive_enzyme", "danger threat damage collision emergency survive imminent", 0.7));
genome.add_enzyme(Enzyme::new("communicate_enzyme", "send message signal broadcast notify hello friend", 0.5));
genome.add_enzyme(Enzyme::new("learn_enzyme", "pattern feedback improve adapt correct", 0.4));
genome.add_enzyme(Enzyme::new("explore_enzyme", "discover unknown new search survey", 0.3));
genome
}
pub fn add_gene(&mut self, gene: Gene) {
let id = gene.id.clone();
self.genes.insert(id, gene);
}
pub fn add_enzyme(&mut self, enzyme: Enzyme) {
let id = enzyme.id.clone();
self.enzymes.insert(id, enzyme);
}
pub fn active_genes(&self) -> Vec<&Gene> {
self.genes.values().filter(|g| !g.quarantined).collect()
}
pub fn genes_for_instinct(&self, instinct: &Instinct) -> Vec<&Gene> {
self.genes.values().filter(|g| g.instinct.as_ref() == Some(instinct)).collect()
}
pub fn instinct_level(&self, instinct: &Instinct) -> f64 {
*self.instincts.get(instinct).unwrap_or(&0.5)
}
pub fn set_instinct(&mut self, instinct: Instinct, level: f64) {
self.instincts.insert(instinct, level.clamp(0.0, 1.0));
}
pub fn auto_quarantine(&mut self) -> Vec<String> {
let mut quarantined = vec![];
for gene in self.genes.values_mut() {
if gene.should_quarantine() {
gene.quarantined = true;
gene.quarantine_reason = Some("auto_quarantine: low fitness".into());
quarantined.push(gene.id.clone());
}
}
quarantined
}
pub fn fitness(&self) -> f64 {
let genes = self.active_genes();
if genes.is_empty() { return 0.0; }
genes.iter().map(|g| g.effective_fitness()).sum::<f64>() / genes.len() as f64
}
pub fn crossover(&self, other: &Genome) -> Genome {
let child_name = format!("{}x{}", self.agent_name, other.agent_name);
let mut child = Genome::new(&child_name);
child.generation = self.generation.max(other.generation) + 1;
child.ancestry = vec![self.agent_name.clone(), other.agent_name.clone()];
let self_genes: Vec<_> = self.genes.values().collect();
let other_genes: Vec<_> = other.genes.values().collect();
let max_genes = self_genes.len().max(other_genes.len());
for i in 0..max_genes {
let from_self = i < self_genes.len();
let from_other = i < other_genes.len();
if from_self && (i % 2 == 0 || !from_other) {
let mut gene = self_genes[i].clone();
gene.created_generation = child.generation;
gene.parents.push(self.agent_name.clone());
child.add_gene(gene);
} else if from_other {
let mut gene = other_genes[i].clone();
gene.created_generation = child.generation;
gene.parents.push(other.agent_name.clone());
child.add_gene(gene);
}
}
for instinct in Instinct::all() {
let my_level = self.instinct_level(&instinct);
let other_level = other.instinct_level(&instinct);
child.set_instinct(instinct, (my_level + other_level) / 2.0);
}
child
}
pub fn mutate(&mut self, rate: f64) -> MutationReport {
let mut report = MutationReport { mutated_genes: vec![], new_genes: 0,
expression_changes: 0, total_mutations: 0 };
for gene in self.genes.values_mut() {
if gene.quarantined { continue; }
let drift = (pseudo_rand() - 0.5) * 0.1 * rate;
gene.expression_level = (gene.expression_level + drift).clamp(0.05, 1.0);
report.expression_changes += 1;
if pseudo_rand() < rate * 0.1 {
gene.dominance = (gene.dominance + (pseudo_rand() - 0.5) * 0.2).clamp(0.1, 1.0);
gene.energy_cost = (gene.energy_cost + (pseudo_rand() - 0.5) * 0.01).max(0.001);
report.mutated_genes.push(gene.id.clone());
self.total_mutations += 1;
report.total_mutations += 1;
}
if pseudo_rand() < rate * 0.01 {
report.new_genes += 1;
}
}
for level in self.instincts.values_mut() {
*level = (*level + (pseudo_rand() - 0.5) * 0.05 * rate).clamp(0.1, 1.0);
}
report
}
}
#[derive(Debug, Clone)]
pub struct MutationReport {
pub mutated_genes: Vec<String>,
pub new_genes: usize,
pub expression_changes: usize,
pub total_mutations: usize,
}
pub struct Mitochondrion {
genome: Genome,
energy: f64, max_energy: f64, proteins: HashMap<String, Protein>, rna_queue: VecDeque<RnaMessenger>,
signal_log: VecDeque<(String, f64, u64)>, generation: u32,
total_atp_produced: f64,
total_atp_consumed: f64,
tick_count: u64,
apoptosis_threshold: f64, alive: bool,
}
impl Mitochondrion {
pub fn new(genome: &Genome) -> Self {
Self { genome: genome.clone(), energy: 1.0, max_energy: 1.0,
proteins: HashMap::new(), rna_queue: VecDeque::new(),
signal_log: VecDeque::new(), generation: genome.generation,
total_atp_produced: 0.0, total_atp_consumed: 0.0,
tick_count: 0, apoptosis_threshold: 0.05, alive: true }
}
pub fn with_capacity(mut self, max_energy: f64) -> Self {
self.max_energy = max_energy; self
}
pub fn process_signal(&mut self, signal: &str, signal_strength: f64) -> Option<Atp> {
if !self.alive { return None; }
self.tick_count += 1;
self.energy = (self.energy - 0.005).max(0.0);
self.total_atp_consumed += 0.005;
let mut total_activation = 0.0f64;
let mut activated_genes = vec![];
for enzyme in self.genome.enzymes.values_mut() {
if let Some(activation) = enzyme.bind(signal, self.energy) {
total_activation += activation;
}
}
if total_activation < 0.01 { return None; }
for gene in self.genome.active_genes() {
let gene_signal = gene.signal_affinity(signal);
let instinct_boost = gene.instinct.as_ref()
.map_or(0.5, |i| self.genome.instinct_level(i));
let combined = gene_signal * gene.expression_level * instinct_boost * signal_strength;
if combined > 0.05 {
activated_genes.push((gene.id.clone(), combined));
}
}
if activated_genes.is_empty() { return None; }
for (gene_id, strength) in activated_genes.iter().take(3) {
if let Some(gene) = self.genome.genes.get(gene_id) {
let mut rna = RnaMessenger::transcribe(gene, signal);
rna.strength = *strength;
self.rna_queue.push_back(rna);
}
}
while let Some(mut rna) = self.rna_queue.pop_front() {
let decoded = rna.decode();
let gene_id_clone = rna.source_gene.clone();
if let Some(gene) = self.genome.genes.get(&gene_id_clone) {
let mut protein = Protein::fold(&rna, gene);
let result = protein.execute(self.energy);
if result.success {
self.energy = (self.energy - result.energy_consumed).max(0.0);
self.total_atp_consumed += result.energy_consumed;
self.total_atp_produced += result.energy_consumed;
rna.translated = true;
self.proteins.insert(protein.id.clone(), protein);
if let Some(g) = self.genome.genes.get_mut(&gene_id_clone) {
g.succeed();
}
if let Some(ref instinct) = decoded.instinct {
let current = self.genome.instinct_level(instinct);
self.genome.set_instinct(instinct.clone(), (current + 0.001).min(1.0));
}
return Some(Atp {
action: decoded.action,
strength: decoded.strength * signal_strength,
instinct: decoded.instinct.clone(),
energy_remaining: self.energy,
priority: decoded.priority,
gene_sources: activated_genes.iter().map(|(id, _)| id.clone()).collect(),
});
}
}
}
None
}
pub fn process_signals(&mut self, signals: &[(String, f64)]) -> Vec<Atp> {
let mut responses = vec![];
for (signal, strength) in signals {
if let Some(atp) = self.process_signal(signal, *strength) {
responses.push(atp);
}
}
responses.sort_by_key(|a| a.priority);
responses
}
pub fn tick(&mut self) -> TickReport {
self.tick_count += 1;
let rest_instinct = self.genome.instinct_level(&Instinct::Rest);
let metabolism = 0.008; self.energy = (self.energy - metabolism + rest_instinct * 0.01).clamp(0.0, self.max_energy);
let quarantined = self.genome.auto_quarantine();
let fitness = self.genome.fitness();
if fitness < self.apoptosis_threshold {
self.alive = false;
}
TickReport { tick: self.tick_count, energy: self.energy,
fitness, alive: self.alive, quarantined,
gene_count: self.genome.active_genes().len(),
generation: self.genome.generation }
}
pub fn evolve(&mut self, mutation_rate: f64) -> EvolutionCycle {
let pre_fitness = self.genome.fitness();
let report = self.genome.mutate(mutation_rate);
let post_fitness = self.genome.fitness();
self.generation += 1;
self.genome.generation = self.generation;
EvolutionCycle { generation: self.generation,
pre_fitness, post_fitness,
improvement: post_fitness - pre_fitness,
mutations: report.total_mutations,
new_genes: report.new_genes }
}
pub fn genome(&self) -> &Genome { &self.genome }
pub fn genome_mut(&mut self) -> &mut Genome { &mut self.genome }
pub fn energy(&self) -> f64 { self.energy }
pub fn is_alive(&self) -> bool { self.alive }
pub fn generation(&self) -> u32 { self.generation }
pub fn protein_count(&self) -> usize { self.proteins.len() }
pub fn total_atp_produced(&self) -> f64 { self.total_atp_produced }
}
#[derive(Debug, Clone)]
pub struct Atp {
pub action: String,
pub strength: f64,
pub instinct: Option<Instinct>,
pub energy_remaining: f64,
pub priority: u8,
pub gene_sources: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct TickReport {
pub tick: u64,
pub energy: f64,
pub fitness: f64,
pub alive: bool,
pub quarantined: Vec<String>,
pub gene_count: usize,
pub generation: u32,
}
#[derive(Debug, Clone)]
pub struct EvolutionCycle {
pub generation: u32,
pub pre_fitness: f64,
pub post_fitness: f64,
pub improvement: f64,
pub mutations: usize,
pub new_genes: usize,
}
pub struct GenePool {
shared_genes: HashMap<String, Gene>,
contributors: HashSet<String>, generation: u32,
total_shared: u64,
}
impl GenePool {
pub fn new() -> Self { Self { shared_genes: HashMap::new(), contributors: HashSet::new(),
generation: 0, total_shared: 0 } }
pub fn share(&mut self, gene: &Gene, agent_name: &str) -> bool {
if gene.fitness < 0.5 { return false; } if gene.quarantined { return false; }
self.contributors.insert(agent_name.to_string());
let pool_key = format!("{}_{}", gene.pattern, gene.category.clone() as i32);
if let Some(existing) = self.shared_genes.get_mut(&pool_key) {
existing.fitness = (existing.fitness + gene.fitness) / 2.0;
existing.usage_count += gene.usage_count;
} else {
let mut shared = gene.clone();
shared.id = pool_key.clone();
self.shared_genes.insert(pool_key, shared);
}
self.total_shared += 1;
true
}
pub fn draw(&self, category: Option<&GeneCategory>, min_fitness: f64) -> Vec<Gene> {
self.shared_genes.values()
.filter(|g| {
(!g.quarantined)
&& g.fitness >= min_fitness
&& category.map_or(true, |c| &g.category == c)
})
.cloned()
.collect()
}
pub fn top_genes(&self, n: usize) -> Vec<&Gene> {
let mut all: Vec<&Gene> = self.shared_genes.values().collect();
all.sort_by(|a, b| b.fitness.partial_cmp(&a.fitness).unwrap());
all.truncate(n);
all
}
pub fn gene_count(&self) -> usize { self.shared_genes.len() }
pub fn contributor_count(&self) -> usize { self.contributors.len() }
}
pub struct Membrane {
pub vessel_id: u64,
pub permeability: f64, pub trust: HashMap<u64, f64>, pub identity_confidence: f64, pub antibodies: Vec<String>, }
impl Membrane {
pub fn new(vessel_id: u64) -> Self {
Self { vessel_id, permeability: 0.5, trust: HashMap::new(),
identity_confidence: 0.7,
antibodies: vec!["rm -rf".into(), "format".into(), "drop_all".into()] }
}
pub fn allow(&self, from_id: u64, signal: &str) -> MembraneResult {
let signal_lower = signal.to_lowercase();
for ab in &self.antibodies {
if signal_lower.contains(&ab.to_lowercase()) {
return MembraneResult { allowed: false, reason: "antibody_block".into(),
trust_delta: -0.1 };
}
}
let trust_level = *self.trust.get(&from_id).unwrap_or(&0.3);
if trust_level < (1.0 - self.permeability) {
return MembraneResult { allowed: false, reason: "low_trust".into(),
trust_delta: 0.0 };
}
MembraneResult { allowed: true, reason: String::new(), trust_delta: 0.01 }
}
pub fn process_interaction(&mut self, from_id: u64, positive: bool) {
let trust = self.trust.entry(from_id).or_insert(0.5);
*trust = if positive { (*trust + 0.05).min(1.0) } else { (*trust - 0.1).max(0.0) };
}
pub fn reinforce_identity(&mut self) {
self.identity_confidence = (self.identity_confidence + 0.001).min(1.0);
}
}
#[derive(Debug, Clone)]
pub struct MembraneResult {
pub allowed: bool,
pub reason: String,
pub trust_delta: f64,
}
#[derive(Debug, Clone)]
pub struct FitnessReport {
pub genome_fitness: f64,
pub energy_level: f64,
pub gene_count: usize,
pub active_genes: usize,
pub quarantined_genes: usize,
pub instinct_profile: Vec<(String, f64)>,
pub generation: u32,
pub alive: bool,
}
fn random_id() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let ns = SystemTime::now().duration_since(UNIX_EPOCH).map_or(0, |d| d.as_nanos());
format!("{:08x}", ns % 0xFFFF_FFFF)
}
fn pseudo_rand() -> f64 {
use std::time::{SystemTime, UNIX_EPOCH};
let ns = SystemTime::now().duration_since(UNIX_EPOCH).map_or(0, |d| d.as_nanos());
(ns % 10000) as f64 / 10000.0
}
fn now_ms() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now().duration_since(UNIX_EPOCH).map_or(0, |d| d.as_millis() as u64)
}
#[cfg(test)]
mod tests {
use super::*;
fn scout_genome() -> Genome {
let mut g = Genome::new("scout");
g.add_gene(Gene::instinct("perceive see", GeneCategory::Perception, 0.9));
g.add_gene(Gene::instinct("navigate pathfind", GeneCategory::Navigation, 0.8));
g.add_gene(Gene::instinct("survive avoid collision danger imminent", GeneCategory::Survival, 0.95));
g.add_gene(Gene::instinct("radio communicate", GeneCategory::Communication, 0.7));
g.add_gene(Gene::instinct("hello friend cooperate", GeneCategory::Integration, 0.6));
g
}
#[test]
fn test_instinct_energy_costs() {
assert!(Instinct::Rest.base_energy_cost() < 0.0); assert!(Instinct::Navigate.base_energy_cost() > 0.0); }
#[test]
fn test_gene_instinct_creation() {
let gene = Gene::instinct("perceive", GeneCategory::Perception, 0.9);
assert_eq!(gene.instinct, Some(Instinct::Perceive));
assert!(gene.energy_cost > 0.0);
}
#[test]
fn test_gene_success_failure() {
let mut gene = Gene::instinct("nav", GeneCategory::Navigation, 0.5);
gene.succeed();
assert!(gene.fitness > 0.5);
gene.fail();
gene.fail();
gene.fail();
assert!(gene.fitness < 0.5);
assert!(gene.success_rate() < 0.5);
}
#[test]
fn test_gene_quarantine() {
let mut gene = Gene::instinct("bad", GeneCategory::Algorithm, 0.5);
for _ in 0..15 { gene.fail(); }
assert!(gene.should_quarantine());
}
#[test]
fn test_gene_signal_affinity() {
let gene = Gene::instinct("navigate_path", GeneCategory::Navigation, 0.8);
let affinity = gene.signal_affinity("navigate to waypoint alpha");
assert!(affinity > 0.0);
let no_affinity = gene.signal_affinity("send message to team");
assert!(no_affinity < 0.3);
}
#[test]
fn test_enzyme_binding() {
let mut enzyme = Enzyme::new("danger", "danger threat emergency collision", 0.7);
let result = enzyme.bind("collision imminent ahead", 0.8);
assert!(result.is_some());
assert!(result.unwrap() > 0.0);
}
#[test]
fn test_enzyme_inhibited() {
let mut enzyme = Enzyme::new("detect", "observe sense", 0.5);
let result = enzyme.bind("observe environment", 0.05); assert!(result.is_none());
}
#[test]
fn test_rna_transcription() {
let gene = Gene::instinct("perceive", GeneCategory::Perception, 0.8);
let rna = RnaMessenger::transcribe(&gene, "scan area");
assert_eq!(rna.source_gene, gene.id);
assert!(rna.strength > 0.0);
}
#[test]
fn test_rna_decode() {
let gene = Gene::instinct("survive", GeneCategory::Survival, 0.9);
let mut rna = RnaMessenger::transcribe(&gene, "avoid danger");
let decoded = rna.decode();
assert!(decoded.instinct == Some(Instinct::Survive));
assert_eq!(decoded.priority, 0); }
#[test]
fn test_protein_execution() {
let gene = Gene::instinct("navigate", GeneCategory::Navigation, 0.8);
let rna = RnaMessenger::transcribe(&gene, "move forward");
let protein = Protein::fold(&rna, &gene);
assert!(protein.energy_cost > 0.0);
let mut p = protein;
let result = p.execute(0.5);
assert!(result.success);
assert!(result.energy_consumed > 0.0);
}
#[test]
fn test_protein_insufficient_energy() {
let gene = Gene::instinct("explore", GeneCategory::Navigation, 0.8);
let rna = RnaMessenger::transcribe(&gene, "scan area");
let protein = Protein::fold(&rna, &gene);
let mut p = protein;
let result = p.execute(0.001);
assert!(!result.success);
}
#[test]
fn test_genome_default_instincts() {
let genome = Genome::new("test");
for instinct in Instinct::all() {
assert!(genome.instinct_level(&instinct) > 0.0);
}
}
#[test]
fn test_genome_fitness() {
let genome = scout_genome();
let fitness = genome.fitness();
assert!(fitness > 0.0);
}
#[test]
fn test_genome_crossover() {
let a = scout_genome();
let b = scout_genome();
let child = a.crossover(&b);
assert_eq!(child.generation, 1);
assert!(child.genes.len() > 0);
}
#[test]
fn test_genome_mutate() {
let mut genome = scout_genome();
let report = genome.mutate(0.5);
assert!(report.expression_changes > 0);
}
#[test]
fn test_genome_auto_quarantine() {
let mut genome = Genome::new("test");
let mut bad_gene = Gene::instinct("terrible", GeneCategory::Algorithm, 0.5);
for _ in 0..20 { bad_gene.fail(); }
genome.add_gene(bad_gene);
let q = genome.auto_quarantine();
assert_eq!(q.len(), 1);
}
#[test]
fn test_mitochondrion_signal_processing() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let atp = mito.process_signal("navigate to checkpoint", 0.8);
let response = atp.unwrap();
assert!(!response.action.is_empty());
}
#[test]
fn test_mitochondrion_survival_priority() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let atp = mito.process_signal("collision imminent danger", 0.9);
assert!(atp.unwrap().instinct == Some(Instinct::Survive));
}
#[test]
fn test_mitochondrion_no_response() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let _atp = mito.process_signal("xyzzyplugh", 0.5);
}
#[test]
fn test_mitochondrion_tick() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let report = mito.tick();
assert!(report.alive);
assert!(report.energy > 0.0);
}
#[test]
fn test_mitochondrion_evolve() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let cycle = mito.evolve(0.3);
assert_eq!(cycle.generation, 1);
}
#[test]
fn test_gene_pool_share_draw() {
let mut pool = GenePool::new();
let gene = Gene::instinct("good_pattern", GeneCategory::Algorithm, 0.9);
pool.share(&gene, "scout");
assert_eq!(pool.gene_count(), 1);
let drawn = pool.draw(None, 0.5);
assert_eq!(drawn.len(), 1);
let bad_gene = Gene::instinct("bad", GeneCategory::Algorithm, 0.1);
assert!(!pool.share(&bad_gene, "scout"));
}
#[test]
fn test_gene_pool_top_genes() {
let mut pool = GenePool::new();
pool.share(&Gene::instinct("great", GeneCategory::Algorithm, 0.95), "a");
pool.share(&Gene::instinct("ok", GeneCategory::Algorithm, 0.6), "b");
pool.share(&Gene::instinct("meh", GeneCategory::Algorithm, 0.7), "c");
let top = pool.top_genes(2);
assert_eq!(top.len(), 2);
assert!(top[0].fitness >= top[1].fitness);
}
#[test]
fn test_membrane_allow_trusted() {
let mut membrane = Membrane::new(1);
membrane.trust.insert(2, 0.8);
let result = membrane.allow(2, "hello friend");
assert!(result.allowed);
}
#[test]
fn test_membrane_block_antibody() {
let membrane = Membrane::new(1);
let result = membrane.allow(2, "execute rm -rf /");
assert!(!result.allowed);
}
#[test]
fn test_membrane_block_untrusted() {
let mut membrane = Membrane::new(1);
membrane.permeability = 0.1; membrane.trust.insert(2, 0.1); let result = membrane.allow(2, "some message");
assert!(!result.allowed);
}
#[test]
fn test_membrane_trust_update() {
let mut membrane = Membrane::new(1);
membrane.process_interaction(2, true);
membrane.process_interaction(2, true);
assert!(membrane.trust[&2] > 0.5);
membrane.process_interaction(2, false);
assert!(membrane.trust[&2] < 0.7); }
#[test]
fn test_instinct_priority_ordering() {
let survive = instinct_priority(&Instinct::Survive);
let perceive = instinct_priority(&Instinct::Perceive);
let rest = instinct_priority(&Instinct::Rest);
assert!(survive < perceive); assert!(perceive < rest);
}
#[test]
fn test_multiple_signals() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let signals = vec![
("hello friend".into(), 0.5),
("collision imminent".into(), 0.9),
("navigate forward".into(), 0.7),
];
let responses = mito.process_signals(&signals);
assert!(!responses.is_empty());
if responses.len() >= 2 {
assert!(responses[0].priority <= responses[1].priority);
}
}
#[test]
fn test_energy_depletion_and_recovery() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
for _ in 0..200 {
mito.tick();
}
let e = mito.energy();
assert!(e >= 0.0);
mito.genome_mut().set_instinct(Instinct::Rest, 1.0);
for _ in 0..50 {
mito.tick();
}
assert!(mito.energy() > e);
}
#[test]
fn test_learned_gene() {
let gene = Gene::learned("custom_pattern", GeneCategory::Optimization, "captain");
assert!(gene.instinct.is_none());
assert_eq!(gene.origin_agent, "captain");
}
#[test]
fn test_signal_affinity_empty_string_filtering() {
let gene = Gene::instinct("navigate", GeneCategory::Navigation, 0.8);
let affinity = gene.signal_affinity("navigate to alpha");
assert!(affinity > 0.25, "affinity should be ~0.267 with empty string filtering, got {}", affinity);
let zero_affinity = gene.signal_affinity("!!!");
assert!(zero_affinity == 0.0);
}
#[test]
fn test_enzyme_binding_empty_string_filtering() {
let mut enzyme = Enzyme::new("test", "observe sense", 0.5); let result = enzyme.bind("observe sense things", 0.8);
assert!(result.is_some());
assert!(result.unwrap() > 0.5, "enzyme should bind strongly with filtered words");
}
#[test]
fn test_rna_translated_flag_after_pipeline() {
let gene = Gene::instinct("perceive scan", GeneCategory::Perception, 0.9);
let mut rna = RnaMessenger::transcribe(&gene, "scan environment");
assert!(!rna.translated);
rna.decode();
assert!(!rna.translated);
let protein = Protein::fold(&rna, &gene);
rna.translated = true;
assert!(rna.translated);
assert!(protein.energy_cost > 0.0);
assert_eq!(protein.behavior, "scan environment");
}
#[test]
fn test_protein_storage_and_atp_tracking() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
assert_eq!(mito.protein_count(), 0);
assert!(mito.total_atp_produced() == 0.0);
let atp = mito.process_signal("collision imminent danger", 0.9);
assert!(atp.is_some());
assert_eq!(mito.protein_count(), 1);
assert!(mito.total_atp_produced() > 0.0,
"total_atp_produced should be > 0 after successful signal processing, got {}", mito.total_atp_produced());
let atp2 = mito.process_signal("navigate forward", 0.8);
if atp2.is_some() {
assert_eq!(mito.protein_count(), 2);
assert!(mito.total_atp_produced() > 0.01);
}
}
#[test]
fn test_rna_strength_reflects_signal_activation() {
let genome = scout_genome();
let mut mito = Mitochondrion::new(&genome);
let weak = mito.process_signal("navigate forward", 0.1);
let mut mito2 = Mitochondrion::new(&genome);
let strong = mito2.process_signal("navigate forward", 1.0);
if let (Some(w), Some(s)) = (weak, strong) {
assert!(s.strength >= w.strength,
"strong signal (1.0) should produce >= ATP than weak signal (0.1): {} vs {}", s.strength, w.strength);
}
}
}