//! Agent strategy patterns for simulation. //! //! Defines different agent behaviors (Scientist, Troll, Believer) and //! the framework for strategy-driven simulation. use stemedb_core::types::{Hash, ObjectValue}; /// Specification for creating agents with a particular strategy. #[derive(Debug, Clone, Copy)] pub struct AgentSpec { /// Number of agents to create with this strategy. pub count: usize, /// The strategy type for these agents. pub strategy: StrategyType, } /// Available strategy types for agents. #[derive(Debug, Clone, Copy)] pub enum StrategyType { /// Scientific agent: creates high-confidence assertions. Scientist, /// Troll agent: creates low-confidence contradictions. Troll, /// Believer agent: primarily votes, occasionally creates assertions. Believer, } /// Metrics tracking for a strategy. #[derive(Debug, Clone, Default)] pub struct StrategyMetrics { /// Number of assertions created. pub assertions_created: usize, /// Number of votes cast. pub votes_cast: usize, /// Number of queries executed. pub queries_executed: usize, /// Number of skip actions taken. pub skips: usize, } /// World state visible to agents when making decisions. #[derive(Debug, Clone)] pub struct WorldState { /// Current simulation tick. pub tick: usize, /// Existing assertions (hash, subject, predicate, object, confidence). pub existing_assertions: Vec<(Hash, String, String, ObjectValue, f32)>, /// Vote summaries (assertion_hash, total_weight). pub vote_summaries: Vec<(Hash, f32)>, /// Total number of agents in the simulation. pub agent_count: usize, } /// Actions an agent can take in a simulation tick. #[derive(Debug, Clone)] pub enum AgentAction { /// Create a new assertion. Assert { /// The subject entity. subject: String, /// The predicate/relation. predicate: String, /// The object value. object: ObjectValue, }, /// Cast a vote for an assertion. Vote { /// Hash of the assertion to vote on. assertion_hash: Hash, /// Vote weight (0.0 to 1.0). weight: f32, }, /// Execute a query. Query { /// The subject to query. subject: String, /// The predicate to query. predicate: String, }, /// Skip this turn. Skip, } /// Trait defining agent strategy behavior. pub trait AgentStrategy: Send { /// Human-readable strategy name. fn name(&self) -> &str; /// Base confidence level for assertions created by this strategy. fn base_confidence(&self) -> f32; /// Decide what action to take given the current world state. fn decide_action(&self, world: &WorldState) -> AgentAction; } /// Scientist strategy: creates high-confidence assertions. struct ScientistStrategy; impl AgentStrategy for ScientistStrategy { fn name(&self) -> &str { "Scientist" } fn base_confidence(&self) -> f32 { 0.9 } fn decide_action(&self, world: &WorldState) -> AgentAction { let subject = format!("Entity_{}", world.tick); let predicate = "has_property".to_string(); let object = ObjectValue::Text(format!("value_{}", world.tick)); AgentAction::Assert { subject, predicate, object } } } /// Troll strategy: creates low-confidence contradictions. struct TrollStrategy; impl AgentStrategy for TrollStrategy { fn name(&self) -> &str { "Troll" } fn base_confidence(&self) -> f32 { 0.3 } fn decide_action(&self, world: &WorldState) -> AgentAction { // If there are existing assertions, contradict one if !world.existing_assertions.is_empty() { let target = &world.existing_assertions[world.tick % world.existing_assertions.len()]; return AgentAction::Assert { subject: target.1.clone(), predicate: target.2.clone(), object: ObjectValue::Text(format!("fake_value_{}", world.tick)), }; } // Otherwise create a generic low-confidence assertion AgentAction::Assert { subject: format!("TrollEntity_{}", world.tick), predicate: "dubious_claim".to_string(), object: ObjectValue::Text("unverified".to_string()), } } } /// Believer strategy: primarily votes, occasionally creates assertions. struct BelieverStrategy; impl AgentStrategy for BelieverStrategy { fn name(&self) -> &str { "Believer" } fn base_confidence(&self) -> f32 { 0.7 } fn decide_action(&self, world: &WorldState) -> AgentAction { // Believers prefer to vote on existing high-confidence assertions if !world.existing_assertions.is_empty() { // Find highest confidence assertion if let Some((hash, _, _, _, confidence)) = world .existing_assertions .iter() .max_by(|a, b| a.4.partial_cmp(&b.4).unwrap_or(std::cmp::Ordering::Equal)) { if *confidence > 0.5 { return AgentAction::Vote { assertion_hash: *hash, weight: 1.0 }; } } } // Occasionally create an assertion or skip if world.tick % 3 == 0 { AgentAction::Assert { subject: format!("BeliefEntity_{}", world.tick), predicate: "trusted_fact".to_string(), object: ObjectValue::Text(format!("trusted_value_{}", world.tick)), } } else { AgentAction::Skip } } } /// Create a strategy instance for the given type. pub fn create_strategy(strategy_type: StrategyType) -> Box { match strategy_type { StrategyType::Scientist => Box::new(ScientistStrategy), StrategyType::Troll => Box::new(TrollStrategy), StrategyType::Believer => Box::new(BelieverStrategy), } }