diff --git a/src/ship/map/enemy.rs b/src/ship/map/enemy.rs index b5efd7c..70964a1 100644 --- a/src/ship/map/enemy.rs +++ b/src/ship/map/enemy.rs @@ -87,10 +87,9 @@ impl RareMonsterAppearTable { let appear_rates: HashMap = cfg .into_iter() - .map(|(monster, rate)| { - let monster: MonsterType = monster.parse().unwrap(); // TODO: don't unwrap! - let appear_rate = rate; - (monster, appear_rate) + .filter_map(|(monster, rate)| { + let monster: MonsterType = monster.parse().ok()?; + Some((monster, rate)) }) .collect(); @@ -99,7 +98,7 @@ impl RareMonsterAppearTable { } } - pub fn roll_appearance(&self, monster: &MonsterType) -> bool { + pub fn roll_is_rare(&self, monster: &MonsterType) -> bool { if rand_chacha::ChaChaRng::from_entropy().gen::() < *self.appear_rate.get(monster).unwrap_or(&0.0f32) { return true } @@ -324,7 +323,7 @@ impl MapEnemy { } } - pub fn has_rare_appearance(self) -> bool { + pub fn can_be_rare(&self) -> bool { matches!(self.monster, MonsterType::RagRappy | MonsterType::Hildebear | MonsterType::PoisonLily | MonsterType::PofuillySlime | @@ -339,10 +338,10 @@ impl MapEnemy { guaranteed rare monsters don't count towards the limit */ #[must_use] - pub fn set_rare_appearance(self) -> MapEnemy { + pub fn into_rare(self) -> MapEnemy { match (self.monster, self.map_area.to_episode()) { (MonsterType::RagRappy, Episode::One) => {MapEnemy {monster: MonsterType::AlRappy, shiny:true, ..self}}, - (MonsterType::RagRappy, Episode::Two) => {MapEnemy {monster: MonsterType::EventRappy, shiny:true, ..self}}, + (MonsterType::RagRappy, Episode::Two) => {MapEnemy {monster: MonsterType::LoveRappy, shiny:true, ..self}}, (MonsterType::Hildebear, _) => {MapEnemy {monster: MonsterType::Hildeblue, shiny:true, ..self}}, (MonsterType::PoisonLily, _) => {MapEnemy {monster: MonsterType::NarLily, shiny:true, ..self}}, (MonsterType::PofuillySlime, _) => {MapEnemy {monster: MonsterType::PouillySlime, shiny:true, ..self}}, @@ -357,14 +356,5 @@ impl MapEnemy { _ => {self}, } } - - // in theory this should only be called on monsters we know can have rare types - #[must_use] - pub fn roll_appearance_for_mission(self, rare_monster_table: &RareMonsterAppearTable) -> MapEnemy { - if rare_monster_table.roll_appearance(&self.monster) { - return self.set_rare_appearance() - } - self - } } diff --git a/src/ship/map/maps.rs b/src/ship/map/maps.rs index 6c971fc..febfa44 100644 --- a/src/ship/map/maps.rs +++ b/src/ship/map/maps.rs @@ -278,20 +278,20 @@ impl Maps { _ => unreachable!() }; - let mut maps = Maps { + Maps { enemy_data: map_variants.iter() - .fold(Vec::new(), |mut enemy_data, map_variant| { - enemy_data.append(&mut enemy_data_from_map_data(map_variant, &room_mode.episode())); - enemy_data - }), + .map(|map_variant| { + enemy_data_from_map_data(map_variant, &room_mode.episode()) + }) + .flatten() + .map(|enemy| apply_rare_enemy(enemy, rare_monster_table)) + .collect(), object_data: map_variants.iter() - .flat_map(|map_variant| { - objects_from_map_data(map_variant.obj_file().into(), &room_mode.episode(), &map_variant.map) - }).collect(), - map_variants, - }; - maps.roll_monster_appearance(rare_monster_table); - maps + .flat_map(|map_variant| { + objects_from_map_data(map_variant.obj_file().into(), &room_mode.episode(), &map_variant.map) + }).collect(), + map_variants, + } } pub fn enemy_by_id(&self, id: usize) -> Result { @@ -314,9 +314,11 @@ impl Maps { }) } - pub fn set_quest_data(&mut self, enemies: Vec>, objects: Vec>, rare_monster_appear_table: &RareMonsterAppearTable) { - self.enemy_data = enemies; - self.roll_monster_appearance(rare_monster_appear_table); + pub fn set_quest_data(&mut self, enemies: Vec>, objects: Vec>, rare_monster_table: &RareMonsterAppearTable) { + self.enemy_data = enemies + .into_iter() + .map(|enemy| apply_rare_enemy(enemy, rare_monster_table)) + .collect(); self.object_data = objects; } @@ -325,10 +327,11 @@ impl Maps { let shiny: Vec<(usize, &Option)> = self.enemy_data.iter() .enumerate() .filter(|(_,m)| { - if m.is_some() { - m.unwrap().shiny - } else { - false + match m { + Some(m) => { + m.shiny + }, + None => false, } }) .collect(); @@ -341,21 +344,15 @@ impl Maps { } rare_monsters } +} - pub fn roll_monster_appearance(&mut self, rare_monster_table: &RareMonsterAppearTable) { - self.enemy_data = self.enemy_data - .iter() - .map(|&x| - if let Some(monster) = x { - if monster.has_rare_appearance() { - Some(monster.roll_appearance_for_mission(rare_monster_table)) - } else { - Some(monster) - } - } else { - x - } - ) - .collect(); - } +fn apply_rare_enemy(enemy: Option, rare_enemy_table: &RareMonsterAppearTable) -> Option { + enemy.map(|enemy| { + if enemy.can_be_rare() && rare_enemy_table.roll_is_rare(&enemy.monster) { + enemy.into_rare() + } + else { + enemy + } + }) }