microscope_memory/
mental_sandbox.rs1use std::collections::HashMap;
5use std::sync::{Arc, RwLock};
6
7#[derive(Debug, Clone)]
9pub struct Scenario {
10 pub id: String,
11 pub description: String,
12 pub actions: Vec<String>,
13 pub outcome_probability: f32,
14 pub risk_score: f32,
15 pub reward_potential: f32,
16}
17
18const MAX_SCENARIOS: usize = 100;
20
21pub struct MentalSandbox {
23 scenarios: Arc<RwLock<HashMap<String, Scenario>>>,
24 current_simulation: Arc<RwLock<Option<String>>>,
25 long_term_goals: Vec<String>,
26}
27
28impl Default for MentalSandbox {
29 fn default() -> Self {
30 Self::new()
31 }
32}
33
34impl MentalSandbox {
35 pub fn new() -> Self {
37 Self {
38 scenarios: Arc::new(RwLock::new(HashMap::new())),
39 current_simulation: Arc::new(RwLock::new(None)),
40 long_term_goals: Vec::new(),
41 }
42 }
43
44 pub fn add_goal(&mut self, goal: &str) {
46 self.long_term_goals.push(goal.to_string());
47 }
48
49 pub fn simulate_scenario(&self, description: &str, actions: Vec<&str>) -> Scenario {
51 let id = format!("scenario_{}", rand::random::<u32>());
52
53 let goal_alignment = self.calculate_goal_alignment(description);
55 let complexity_factor = actions.len() as f32 * 0.1;
56
57 let scenario = Scenario {
58 id: id.clone(),
59 description: description.to_string(),
60 actions: actions.iter().map(|s| s.to_string()).collect(),
61 outcome_probability: 0.7, risk_score: (1.0 - goal_alignment) * complexity_factor,
63 reward_potential: goal_alignment * (1.0 - complexity_factor.min(1.0)),
64 };
65
66 let mut scenarios = crate::sync_guard::write_lock(&self.scenarios);
67 scenarios.insert(id.clone(), scenario.clone());
68
69 if scenarios.len() > MAX_SCENARIOS {
71 let excess = scenarios.len() - MAX_SCENARIOS;
72 let keys: Vec<String> = scenarios.keys().take(excess).cloned().collect();
73 for k in keys {
74 scenarios.remove(&k);
75 }
76 }
77
78 let mut current = crate::sync_guard::write_lock(&self.current_simulation);
79 *current = Some(id);
80
81 scenario
82 }
83
84 fn calculate_goal_alignment(&self, description: &str) -> f32 {
86 if self.long_term_goals.is_empty() {
87 return 0.5; }
89
90 let keywords = description.to_lowercase();
91 let mut matches = 0.0;
92
93 for goal in &self.long_term_goals {
94 let goal_lower = goal.to_lowercase();
95 if keywords.contains(&goal_lower) {
96 matches += 1.0;
97 }
98 }
99
100 matches / self.long_term_goals.len() as f32
101 }
102
103 pub fn get_best_scenario(&self) -> Option<Scenario> {
105 let scenarios = crate::sync_guard::read_lock(&self.scenarios);
106
107 scenarios
108 .values()
109 .max_by(|a, b| {
110 let a_score = a.reward_potential / (a.risk_score + 0.01);
111 let b_score = b.reward_potential / (b.risk_score + 0.01);
112 a_score.total_cmp(&b_score)
113 })
114 .cloned()
115 }
116
117 pub fn clear(&mut self) {
119 crate::sync_guard::write_lock(&self.scenarios).clear();
120 *crate::sync_guard::write_lock(&self.current_simulation) = None;
121 }
122}
123
124pub fn run_parallel_simulations(
126 sandbox: &MentalSandbox,
127 scenario_descriptions: &[(&str, Vec<&str>)],
128) -> Vec<Scenario> {
129 scenario_descriptions
130 .iter()
131 .map(|(desc, actions)| sandbox.simulate_scenario(desc, actions.clone()))
132 .collect()
133}