1use super::Rng;
5use super::history::{Civilization, EventType};
6use super::language::Language;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum MythType {
11 Creation, Flood, HeroJourney, Prophecy, Trickster, War,
12 Origin, Apocalypse, Romance, Curse, Gift, Transformation,
13}
14
15#[derive(Debug, Clone)]
17pub struct Myth {
18 pub id: u32,
19 pub myth_type: MythType,
20 pub title: String,
21 pub narrative: String,
22 pub source_civ: u32,
23 pub characters: Vec<MythCharacter>,
24 pub moral: String,
25 pub related_events: Vec<i32>,
26}
27
28#[derive(Debug, Clone)]
30pub struct MythCharacter {
31 pub name: String,
32 pub role: MythRole,
33 pub epithet: String,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum MythRole {
38 Creator, Destroyer, Hero, Trickster, Monster, Lover, Sage, Martyr, King, Prophet,
39}
40
41pub fn generate(civs: &[Civilization], languages: &[Language], rng: &mut Rng) -> Vec<Myth> {
43 let mut myths = Vec::new();
44 let mut next_id = 0u32;
45
46 for civ in civs {
47 let lang = languages.iter().find(|l| l.owner_civ == civ.id)
48 .or_else(|| languages.first());
49
50 myths.push(generate_creation_myth(next_id, civ, lang, rng));
52 next_id += 1;
53
54 for event in &civ.historical_events {
56 if matches!(event.event_type, EventType::War | EventType::HeroRise | EventType::GoldenAge) {
57 if rng.coin(0.4) {
58 myths.push(generate_hero_myth(next_id, civ, event, lang, rng));
59 next_id += 1;
60 }
61 }
62 }
63
64 if rng.coin(0.6) {
66 myths.push(generate_prophecy(next_id, civ, lang, rng));
67 next_id += 1;
68 }
69 }
70
71 myths
72}
73
74fn generate_creation_myth(id: u32, civ: &Civilization, lang: Option<&Language>, rng: &mut Rng) -> Myth {
75 let creator_name = myth_name(lang, rng);
76 let world_name = myth_name(lang, rng);
77
78 let templates = [
79 format!("In the beginning, {} shaped {} from the void. From chaos came order, and from order came life.", creator_name, world_name),
80 format!("{} dreamed, and the dream became {}. The mountains are {} sleeping thoughts, and the rivers are tears of joy.", creator_name, world_name, creator_name),
81 format!("Two forces clashed: {} the maker and the void. Where they met, {} was born — imperfect but alive.", creator_name, world_name),
82 format!("{} spoke a single word, and {} erupted from silence. Each syllable became a mountain, each pause a valley.", creator_name, world_name),
83 format!("From the death of the old world, {} gathered the fragments and forged {}. We are the children of destruction reborn.", creator_name, world_name),
84 ];
85
86 let narrative = templates[rng.next_u64() as usize % templates.len()].clone();
87
88 Myth {
89 id,
90 myth_type: MythType::Creation,
91 title: format!("The Making of {}", world_name),
92 narrative,
93 source_civ: civ.id,
94 characters: vec![MythCharacter {
95 name: creator_name,
96 role: MythRole::Creator,
97 epithet: "the First".to_string(),
98 }],
99 moral: "From nothing, all things come.".to_string(),
100 related_events: Vec::new(),
101 }
102}
103
104fn generate_hero_myth(id: u32, civ: &Civilization, event: &super::history::HistoricalEvent, lang: Option<&Language>, rng: &mut Rng) -> Myth {
105 let hero_name = myth_name(lang, rng);
106 let villain_name = myth_name(lang, rng);
107
108 let narrative = format!(
109 "In the year of {}, {} rose from humble origins. Armed with nothing but courage, \
110 {} faced the terrible {} and prevailed through {}. The people of {} remember this deed in song.",
111 event.year, hero_name, hero_name, villain_name,
112 if rng.coin(0.5) { "wisdom" } else { "strength" },
113 civ.name
114 );
115
116 Myth {
117 id,
118 myth_type: MythType::HeroJourney,
119 title: format!("The Saga of {}", hero_name),
120 narrative,
121 source_civ: civ.id,
122 characters: vec![
123 MythCharacter { name: hero_name, role: MythRole::Hero, epithet: "the Brave".to_string() },
124 MythCharacter { name: villain_name, role: MythRole::Monster, epithet: "the Terrible".to_string() },
125 ],
126 moral: "Even the smallest can change the fate of the world.".to_string(),
127 related_events: vec![event.year],
128 }
129}
130
131fn generate_prophecy(id: u32, civ: &Civilization, lang: Option<&Language>, rng: &mut Rng) -> Myth {
132 let prophet_name = myth_name(lang, rng);
133 let harbinger = myth_name(lang, rng);
134
135 let templates = [
136 format!("When {} walks the earth again, the old order shall crumble and a new age shall dawn.", harbinger),
137 format!("{} foretold: 'Three signs shall mark the end — a star that bleeds, a king who weeps, and a door that opens into nothing.'", prophet_name),
138 format!("The scrolls of {} speak of a convergence, when all rivers flow backward and the dead remember their names.", prophet_name),
139 ];
140
141 let narrative = templates[rng.next_u64() as usize % templates.len()].clone();
142
143 Myth {
144 id,
145 myth_type: MythType::Prophecy,
146 title: format!("The Prophecy of {}", prophet_name),
147 narrative,
148 source_civ: civ.id,
149 characters: vec![
150 MythCharacter { name: prophet_name, role: MythRole::Prophet, epithet: "the Seer".to_string() },
151 ],
152 moral: "The future is written but never read clearly.".to_string(),
153 related_events: Vec::new(),
154 }
155}
156
157fn myth_name(lang: Option<&Language>, rng: &mut Rng) -> String {
158 if let Some(lang) = lang {
159 let syllables = rng.range_usize(2, 4);
160 let word = lang.generate_word(rng, syllables);
161 capitalize(&word)
162 } else {
163 let syllables = ["Zar", "Keth", "Mor", "Ael", "Vor", "Thi", "Dra", "Nym"];
164 let s1 = syllables[rng.next_u64() as usize % syllables.len()];
165 let s2 = syllables[rng.next_u64() as usize % syllables.len()];
166 format!("{}{}", s1, s2.to_lowercase())
167 }
168}
169
170fn capitalize(s: &str) -> String {
171 let mut c = s.chars();
172 match c.next() {
173 None => String::new(),
174 Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_generate_myths() {
184 let mut rng = Rng::new(42);
185 let civs = vec![Civilization {
186 id: 0, name: "TestCiv".to_string(), founding_year: -1000,
187 collapse_year: None, capital_settlement: 0, settlements: vec![0],
188 population: 10000, technology_level: 0.5, military_strength: 0.3,
189 culture_score: 0.5, trade_score: 0.3,
190 government: super::super::history::GovernmentType::Monarchy,
191 religion: super::super::history::ReligionType::Polytheism,
192 relations: Vec::new(),
193 historical_events: vec![super::super::history::HistoricalEvent {
194 year: -500, event_type: EventType::War,
195 description: "War".to_string(), participants: vec![0],
196 }],
197 traits: Vec::new(),
198 }];
199 let langs = super::super::language::generate(1, &civs, &mut rng);
200 let myths = generate(&civs, &langs, &mut rng);
201 assert!(!myths.is_empty());
202 assert!(myths.iter().any(|m| m.myth_type == MythType::Creation));
203 }
204}