From 514e18fff3e2c0bc6274e93281431a9da3fcd043 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 22 Sep 2020 22:39:28 -0600 Subject: [PATCH] armor shop --- data/shops/barrier.toml | 219 ++++++++++++++++++++++++++++ data/shops/frame.toml | 251 ++++++++++++++++++++++++++++++++ data/shops/unit.toml | 300 +++++++++++++++++++++++++++++++++++++++ src/ship/shops/armor.rs | 259 +++++++++++++++++++++++++++++++++ src/ship/shops/mod.rs | 1 + src/ship/shops/tool.rs | 8 ++ src/ship/shops/weapon.rs | 7 + 7 files changed, 1045 insertions(+) create mode 100644 data/shops/barrier.toml create mode 100644 data/shops/frame.toml create mode 100644 data/shops/unit.toml create mode 100644 src/ship/shops/armor.rs diff --git a/data/shops/barrier.toml b/data/shops/barrier.toml new file mode 100644 index 0000000..6d80c05 --- /dev/null +++ b/data/shops/barrier.toml @@ -0,0 +1,219 @@ +[[barrier]] +level = 0 +[[barrier.item]] +item = "Barrier" +probability = 34 + +[[barrier.item]] +item = "Shield" +probability = 34 + +[[barrier.item]] +item = "CoreShield" +probability = 15 + +[[barrier.item]] +item = "GigaShield" +probability = 15 + +[[barrier.item]] +item = "BraveBarrier" +probability = 2 + + +[[barrier]] +level = 10 +[[barrier.item]] +item = "Barrier" +probability = 5 + +[[barrier.item]] +item = "Shield" +probability = 10 + +[[barrier.item]] +item = "CoreShield" +probability = 14 + +[[barrier.item]] +item = "GigaShield" +probability = 18 + +[[barrier.item]] +item = "SoulBarrier" +probability = 18 + +[[barrier.item]] +item = "HardShield" +probability = 14 + +[[barrier.item]] +item = "BraveBarrier" +probability = 10 + +[[barrier.item]] +item = "SolidShield" +probability = 5 + +[[barrier.item]] +item = "FlameBarrier" +probability = 2 + +[[barrier.item]] +item = "PlasmaBarrier" +probability = 2 + +[[barrier.item]] +item = "FreezeBarrier" +probability = 2 + + +[[barrier]] +level = 25 +[[barrier.item]] +item = "GigaShield" +probability = 6 + +[[barrier.item]] +item = "SoulBarrier" +probability = 10 + +[[barrier.item]] +item = "HardShield" +probability = 15 + +[[barrier.item]] +item = "BraveBarrier" +probability = 19 + +[[barrier.item]] +item = "SolidShield" +probability = 18 + +[[barrier.item]] +item = "FlameBarrier" +probability = 14 + +[[barrier.item]] +item = "PlasmaBarrier" +probability = 9 + +[[barrier.item]] +item = "FreezeBarrier" +probability = 4 + +[[barrier.item]] +item = "PsychicBarrier" +probability = 3 + +[[barrier.item]] +item = "ProtectBarrier" +probability = 2 + + +[[barrier]] +level = 42 +[[barrier.item]] +item = "SoulBarrier" +probability = 5 + +[[barrier.item]] +item = "HardShield" +probability = 5 + +[[barrier.item]] +item = "BraveBarrier" +probability = 5 + +[[barrier.item]] +item = "SolidShield" +probability = 10 + +[[barrier.item]] +item = "FlameBarrier" +probability = 14 + +[[barrier.item]] +item = "PlasmaBarrier" +probability = 15 + +[[barrier.item]] +item = "FreezeBarrier" +probability = 14 + +[[barrier.item]] +item = "PsychicBarrier" +probability = 11 + +[[barrier.item]] +item = "GeneralShield" +probability = 9 + +[[barrier.item]] +item = "ProtectBarrier" +probability = 6 + +[[barrier.item]] +item = "GloriousShield" +probability = 4 + +[[barrier.item]] +item = "GuardianShield" +probability = 2 + + +[[barrier]] +level = 60 +[[barrier.item]] +item = "HardShield" +probability = 4 + +[[barrier.item]] +item = "BraveBarrier" +probability = 5 + +[[barrier.item]] +item = "SolidShield" +probability = 5 + +[[barrier.item]] +item = "FlameBarrier" +probability = 8 + +[[barrier.item]] +item = "PlasmaBarrier" +probability = 11 + +[[barrier.item]] +item = "FreezeBarrier" +probability = 13 + +[[barrier.item]] +item = "PsychicBarrier" +probability = 13 + +[[barrier.item]] +item = "GeneralShield" +probability = 14 + +[[barrier.item]] +item = "ProtectBarrier" +probability = 14 + +[[barrier.item]] +item = "GloriousShield" +probability = 9 + +[[barrier.item]] +item = "ImperialBarrier" +probability = 2 + +[[barrier.item]] +item = "GuardianShield" +probability = 1 + +[[barrier.item]] +item = "DivinityBarrier" +probability = 1 + + diff --git a/data/shops/frame.toml b/data/shops/frame.toml new file mode 100644 index 0000000..1f9d456 --- /dev/null +++ b/data/shops/frame.toml @@ -0,0 +1,251 @@ +[[frame]] +level = 0 +[[frame.item]] +item = "Frame" +probability = 33 + +[[frame.item]] +item = "Armor" +probability = 33 + +[[frame.item]] +item = "PsyArmor" +probability = 15 + +[[frame.item]] +item = "GigaFrame" +probability = 10 + +[[frame.item]] +item = "SoulFrame" +probability = 5 + +[[frame.item]] +item = "SolidFrame" +probability = 4 + + +[[frame]] +level = 10 +[[frame.item]] +item = "Frame" +probability = 5 + +[[frame.item]] +item = "Armor" +probability = 5 + +[[frame.item]] +item = "PsyArmor" +probability = 10 + +[[frame.item]] +item = "GigaFrame" +probability = 15 + +[[frame.item]] +item = "SoulFrame" +probability = 19 + +[[frame.item]] +item = "CrossArmor" +probability = 19 + +[[frame.item]] +item = "SolidFrame" +probability = 10 + +[[frame.item]] +item = "BraveArmor" +probability = 10 + +[[frame.item]] +item = "HyperFrame" +probability = 5 + +[[frame.item]] +item = "KingsFrame" +probability = 2 + + +[[frame]] +level = 25 +[[frame.item]] +item = "SoulFrame" +probability = 5 + +[[frame.item]] +item = "CrossArmor" +probability = 5 + +[[frame.item]] +item = "SolidFrame" +probability = 10 + +[[frame.item]] +item = "BraveArmor" +probability = 15 + +[[frame.item]] +item = "HyperFrame" +probability = 19 + +[[frame.item]] +item = "GrandArmor" +probability = 19 + +[[frame.item]] +item = "ShockFrame" +probability = 10 + +[[frame.item]] +item = "KingsFrame" +probability = 10 + +[[frame.item]] +item = "DragonFrame" +probability = 5 + +[[frame.item]] +item = "GeneralArmor" +probability = 2 + + +[[frame]] +level = 42 +[[frame.item]] +item = "SolidFrame" +probability = 2 + +[[frame.item]] +item = "BraveArmor" +probability = 4 + +[[frame.item]] +item = "HyperFrame" +probability = 5 + +[[frame.item]] +item = "GrandArmor" +probability = 5 + +[[frame.item]] +item = "ShockFrame" +probability = 10 + +[[frame.item]] +item = "KingsFrame" +probability = 12 + +[[frame.item]] +item = "DragonFrame" +probability = 14 + +[[frame.item]] +item = "AbsorbArmor" +probability = 14 + +[[frame.item]] +item = "ProtectFrame" +probability = 10 + +[[frame.item]] +item = "GeneralArmor" +probability = 9 + +[[frame.item]] +item = "PerfectFrame" +probability = 5 + +[[frame.item]] +item = "ValiantFrame" +probability = 5 + +[[frame.item]] +item = "ImperialArmor" +probability = 3 + +[[frame.item]] +item = "HolinessArmor" +probability = 2 + + +[[frame]] +level = 60 +[[frame.item]] +item = "BraveArmor" +probability = 2 + +[[frame.item]] +item = "HyperFrame" +probability = 5 + +[[frame.item]] +item = "GrandArmor" +probability = 5 + +[[frame.item]] +item = "ShockFrame" +probability = 5 + +[[frame.item]] +item = "KingsFrame" +probability = 6 + +[[frame.item]] +item = "DragonFrame" +probability = 10 + +[[frame.item]] +item = "AbsorbArmor" +probability = 13 + +[[frame.item]] +item = "ProtectFrame" +probability = 14 + +[[frame.item]] +item = "GeneralArmor" +probability = 14 + +[[frame.item]] +item = "PerfectFrame" +probability = 14 + +[[frame.item]] +item = "ValiantFrame" +probability = 7 + +[[frame.item]] +item = "ImperialArmor" +probability = 3 + +[[frame.item]] +item = "HolinessArmor" +probability = 1 + +[[frame.item]] +item = "GuardianArmor" +probability = 1 + + +[[slot_rate]] +slot = 0 +probability = 75 + +[[slot_rate]] +slot = 1 +probability = 18 + +[[slot_rate]] +slot = 2 +probability = 6 + +[[slot_rate]] +slot = 3 +probability = 1 + +[[slot_rate]] +slot = 4 +probability = 0 + diff --git a/data/shops/unit.toml b/data/shops/unit.toml new file mode 100644 index 0000000..4e71152 --- /dev/null +++ b/data/shops/unit.toml @@ -0,0 +1,300 @@ +[[unit]] +level = 10 +[[unit.item]] +item = "KnightPower" +probability = 10 + +[[unit.item]] +item = "PriestMind" +probability = 10 + +[[unit.item]] +item = "MarksmanArm" +probability = 10 + +[[unit.item]] +item = "ThiefLegs" +probability = 10 + +[[unit.item]] +item = "DiggerHp" +probability = 10 + +[[unit.item]] +item = "WarriorBody" +probability = 10 + +[[unit.item]] +item = "ResistFire" +probability = 10 + +[[unit.item]] +item = "ResistCold" +probability = 10 + +[[unit.item]] +item = "ResistShock" +probability = 10 + +[[unit.item]] +item = "ResistLight" +probability = 5 + +[[unit.item]] +item = "ResistDark" +probability = 5 + + +[[unit]] +level = 25 +[[unit.item]] +item = "KnightPower" +probability = 10 + +[[unit.item]] +item = "PriestMind" +probability = 10 + +[[unit.item]] +item = "MarksmanArm" +probability = 10 + +[[unit.item]] +item = "ThiefLegs" +probability = 10 + +[[unit.item]] +item = "DiggerHp" +probability = 10 + +[[unit.item]] +item = "WarriorBody" +probability = 10 + +[[unit.item]] +item = "ResistFire" +probability = 10 + +[[unit.item]] +item = "ResistCold" +probability = 10 + +[[unit.item]] +item = "ResistShock" +probability = 10 + +[[unit.item]] +item = "ResistLight" +probability = 5 + +[[unit.item]] +item = "ResistDark" +probability = 5 + + +[[unit]] +level = 42 +[[unit.item]] +item = "KnightPower" +probability = 4 + +[[unit.item]] +item = "PriestMind" +probability = 4 + +[[unit.item]] +item = "MarksmanArm" +probability = 4 + +[[unit.item]] +item = "ThiefLegs" +probability = 4 + +[[unit.item]] +item = "DiggerHp" +probability = 4 + +[[unit.item]] +item = "WarriorBody" +probability = 4 + +[[unit.item]] +item = "ResistFire" +probability = 4 + +[[unit.item]] +item = "ResistCold" +probability = 4 + +[[unit.item]] +item = "ResistShock" +probability = 4 + +[[unit.item]] +item = "ResistLight" +probability = 5 + +[[unit.item]] +item = "ResistDark" +probability = 5 + +[[unit.item]] +item = "GeneralPower" +probability = 5 + +[[unit.item]] +item = "GeneralMind" +probability = 5 + +[[unit.item]] +item = "GeneralArm" +probability = 5 + +[[unit.item]] +item = "GeneralLegs" +probability = 5 + +[[unit.item]] +item = "GeneralHp" +probability = 5 + +[[unit.item]] +item = "GeneralBody" +probability = 5 + +[[unit.item]] +item = "ResistFlame" +probability = 5 + +[[unit.item]] +item = "ResistFreeze" +probability = 5 + +[[unit.item]] +item = "ResistThunder" +probability = 5 + +[[unit.item]] +item = "ResistSaint" +probability = 3 + +[[unit.item]] +item = "ResistEvil" +probability = 3 + +[[unit.item]] +item = "HpRestorate" +probability = 1 + +[[unit.item]] +item = "TpRestorate" +probability = 1 + +[[unit.item]] +item = "PbAmplifier" +probability = 1 + + +[[unit]] +level = 60 +[[unit.item]] +item = "KnightPower" +probability = 3 + +[[unit.item]] +item = "PriestMind" +probability = 3 + +[[unit.item]] +item = "MarksmanArm" +probability = 3 + +[[unit.item]] +item = "ThiefLegs" +probability = 3 + +[[unit.item]] +item = "DiggerHp" +probability = 3 + +[[unit.item]] +item = "WarriorBody" +probability = 3 + +[[unit.item]] +item = "ResistFire" +probability = 4 + +[[unit.item]] +item = "ResistCold" +probability = 4 + +[[unit.item]] +item = "ResistShock" +probability = 4 + +[[unit.item]] +item = "ResistLight" +probability = 4 + +[[unit.item]] +item = "ResistDark" +probability = 5 + +[[unit.item]] +item = "GeneralPower" +probability = 5 + +[[unit.item]] +item = "GeneralMind" +probability = 5 + +[[unit.item]] +item = "GeneralArm" +probability = 5 + +[[unit.item]] +item = "GeneralLegs" +probability = 5 + +[[unit.item]] +item = "GeneralHp" +probability = 5 + +[[unit.item]] +item = "GeneralBody" +probability = 5 + +[[unit.item]] +item = "ResistFlame" +probability = 5 + +[[unit.item]] +item = "ResistFreeze" +probability = 5 + +[[unit.item]] +item = "ResistThunder" +probability = 5 + +[[unit.item]] +item = "ResistSaint" +probability = 5 + +[[unit.item]] +item = "ResistEvil" +probability = 5 + +[[unit.item]] +item = "HpRestorate" +probability = 2 + +[[unit.item]] +item = "TpRestorate" +probability = 2 + +[[unit.item]] +item = "PbAmplifier" +probability = 2 + + diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs new file mode 100644 index 0000000..8944350 --- /dev/null +++ b/src/ship/shops/armor.rs @@ -0,0 +1,259 @@ +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; +use serde::Deserialize; +use rand::{Rng, SeedableRng}; +use rand::distributions::{WeightedIndex, Distribution}; +use rand::seq::{SliceRandom, IteratorRandom}; +use crate::entity::character::SectionID; +use crate::ship::room::Difficulty; +use crate::entity::item::armor::ArmorType; +use crate::entity::item::shield::ShieldType; +use crate::entity::item::unit::UnitType; + + +enum ShopArmor { + Frame(ArmorType, usize), + Barrier(ShieldType), + Unit(UnitType), +} + + + +#[derive(Debug, Deserialize, Clone)] +struct FrameTierItem { + item: ArmorType, + probability: usize, +} + +#[derive(Debug, Deserialize, Clone)] +struct FrameTier { + level: usize, + item: Vec, +} + +#[derive(Debug, Deserialize)] +struct SlotRate { + slot: usize, + probability: usize, +} + +#[derive(Debug, Deserialize)] +struct FrameTable { + frame: Vec, + slot_rate: Vec, +} + + +#[derive(Debug, Deserialize, Clone)] +struct BarrierTierItem { + item: ShieldType, + probability: usize, +} + +#[derive(Debug, Deserialize, Clone)] +struct BarrierTier { + level: usize, + item: Vec, +} + +#[derive(Debug, Deserialize)] +struct BarrierTable { + barrier: Vec, +} + +#[derive(Debug, Deserialize, Clone)] +struct UnitTierItem { + item: UnitType, + probability: usize, +} + +#[derive(Debug, Deserialize, Clone)] +struct UnitTier { + level: usize, + item: Vec, +} + +#[derive(Debug, Deserialize)] +struct UnitTable { + unit: Vec, +} + + + +fn load_frame_table() -> FrameTable { + let path = PathBuf::from("data/shops/frame.toml"); + let mut f = File::open(path).unwrap(); + let mut s = String::new(); + f.read_to_string(&mut s).unwrap(); + + let table: FrameTable = toml::from_str(s.as_str()).unwrap(); + table +} + +fn load_barrier_table() -> BarrierTable { + let path = PathBuf::from("data/shops/barrier.toml"); + let mut f = File::open(path).unwrap(); + let mut s = String::new(); + f.read_to_string(&mut s).unwrap(); + + let table: BarrierTable = toml::from_str(s.as_str()).unwrap(); + table +} + +fn load_unit_table() -> UnitTable { + let path = PathBuf::from("data/shops/unit.toml"); + let mut f = File::open(path).unwrap(); + let mut s = String::new(); + f.read_to_string(&mut s).unwrap(); + + let table: UnitTable = toml::from_str(s.as_str()).unwrap(); + table +} + + +fn number_of_frames_to_generate(character_level: usize) -> usize { + if character_level <= 10 { + 4 + } + else if character_level <= 25 { + 6 + } + else if character_level <= 42 { + 7 + } + else { + 8 + } +} + +fn number_of_barriers_to_generate(character_level: usize) -> usize { + if character_level <= 10 { + 4 + } + else if character_level <= 25 { + 5 + } + else if character_level <= 42 { + 6 + } + else { + 7 + } +} + +fn number_of_units_to_generate(character_level: usize) -> usize { + if character_level <= 10 { + 0 + } + else if character_level <= 25 { + 3 + } + else if character_level <= 42 { + 5 + } + else { + 6 + } +} + +#[derive(Debug)] +struct ArmorShop { + frame: FrameTable, + barrier: BarrierTable, + unit: UnitTable, + rng: R, +} + +impl ArmorShop { + pub fn new() -> ArmorShop { + ArmorShop { + frame: load_frame_table(), + barrier: load_barrier_table(), + unit: load_unit_table(), + rng: R::from_entropy(), + } + } + + fn generate_frame_list(&mut self, character_level: usize) -> Vec { + let tier = self.frame.frame.iter() + .filter(|t| t.level <= character_level) + .last() + .cloned() + .unwrap(); + + let frame_choice = WeightedIndex::new(tier.item.iter().map(|f| f.probability)).unwrap(); + let slot_choice = WeightedIndex::new(self.frame.slot_rate.iter().map(|sr| sr.probability)).unwrap(); + (0..number_of_frames_to_generate(character_level)) + .map(|_| { + let frame_detail = tier.item.get(frame_choice.sample(&mut self.rng)).unwrap(); + let slot = self.frame.slot_rate.get(slot_choice.sample(&mut self.rng)).unwrap(); + + ShopArmor::Frame(frame_detail.item, slot.slot) + }) + .collect() + } + + fn generate_barrier_list(&mut self, character_level: usize) -> Vec { + let tier = self.barrier.barrier.iter() + .filter(|t| t.level <= character_level) + .last() + .cloned() + .unwrap(); + + let barrier_choice = WeightedIndex::new(tier.item.iter().map(|b| b.probability)).unwrap(); + (0..number_of_barriers_to_generate(character_level)) + .map(|_| { + let barrier_detail = tier.item.get(barrier_choice.sample(&mut self.rng)).unwrap(); + + ShopArmor::Barrier(barrier_detail.item) + }) + .collect() + } + + fn generate_unit_list(&mut self, character_level: usize) -> Vec { + self.unit.unit.iter() + .filter(|t| t.level <= character_level) + .last() + .cloned() + .map(|tier| { + let unit_choice = WeightedIndex::new(tier.item.iter().map(|u| u.probability)).unwrap(); + (0..number_of_units_to_generate(character_level)) + .map(|_| { + let unit_detail = tier.item.get(unit_choice.sample(&mut self.rng)).unwrap(); + + ShopArmor::Unit(unit_detail.item) + }) + .collect() + }) + .unwrap_or(Vec::new()) + } + + pub fn generate_armor_list(&mut self, character_level: usize) -> Vec { + self.generate_frame_list(character_level).into_iter() + .chain(self.generate_barrier_list(character_level).into_iter()) + .chain(self.generate_unit_list(character_level).into_iter()) + .collect() + } +} + + + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_loading_tool_shop() { + ArmorShop::::new(); + } + + #[test] + fn test_generating_some_armor() { + let mut fs = ArmorShop::::new(); + for i in 0..200 { + fs.generate_armor_list(i); + } + } +} diff --git a/src/ship/shops/mod.rs b/src/ship/shops/mod.rs index d24e7a1..e8753d1 100644 --- a/src/ship/shops/mod.rs +++ b/src/ship/shops/mod.rs @@ -1,2 +1,3 @@ pub mod weapon; pub mod tool; +pub mod armor; diff --git a/src/ship/shops/tool.rs b/src/ship/shops/tool.rs index e3a7534..1b3df5d 100644 --- a/src/ship/shops/tool.rs +++ b/src/ship/shops/tool.rs @@ -265,4 +265,12 @@ mod test { fn test_loading_tool_shop() { ToolShop::::new(); } + + #[test] + fn test_generating_some_tools() { + let mut ts = ToolShop::::new(); + for i in 0..200 { + ts.generate_tool_list(i); + } + } } diff --git a/src/ship/shops/weapon.rs b/src/ship/shops/weapon.rs index 723a980..f2aead2 100644 --- a/src/ship/shops/weapon.rs +++ b/src/ship/shops/weapon.rs @@ -401,4 +401,11 @@ mod test { fn test_loading_weapon_shop() { WeaponShop::::new(Difficulty::Ultimate, SectionID::Pinkal); } + #[test] + fn test_generating_some_weapons() { + let mut ws = WeaponShop::::new(Difficulty::Ultimate, SectionID::Pinkal); + for i in 0..200 { + ws.generate_weapon(i); + } + } }