tool shop
This commit is contained in:
		
							parent
							
								
									65208cddba
								
							
						
					
					
						commit
						991a71e1ca
					
				
							
								
								
									
										299
									
								
								data/shops/techniques.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								data/shops/techniques.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,299 @@
 | 
			
		||||
[[techniques]]
 | 
			
		||||
level = 0
 | 
			
		||||
 | 
			
		||||
[techniques.techs.Foie]
 | 
			
		||||
probability = 18
 | 
			
		||||
level_divisor = 3
 | 
			
		||||
[techniques.techs.Barta]
 | 
			
		||||
probability = 18
 | 
			
		||||
level_divisor = 4
 | 
			
		||||
[techniques.techs.Zonde]
 | 
			
		||||
probability = 18
 | 
			
		||||
level_divisor = 6
 | 
			
		||||
[techniques.techs.Resta]
 | 
			
		||||
probability = 18
 | 
			
		||||
level_divisor = 3
 | 
			
		||||
[techniques.techs.Anti]
 | 
			
		||||
probability = 18
 | 
			
		||||
level_divisor = 35
 | 
			
		||||
[techniques.techs.Shifta]
 | 
			
		||||
probability = 2
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Deband]
 | 
			
		||||
probability = 3
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Jellen]
 | 
			
		||||
probability = 3
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Zalure]
 | 
			
		||||
probability = 2
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Gifoie]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Gibarta]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Gizonde]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Ryuker]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Reverser]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rafoie]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rabarta]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Razonde]
 | 
			
		||||
probability = 0
 | 
			
		||||
set_level = 1
 | 
			
		||||
[[techniques]]
 | 
			
		||||
level = 10
 | 
			
		||||
 | 
			
		||||
[techniques.techs.Foie]
 | 
			
		||||
probability = 7
 | 
			
		||||
level_divisor = 6
 | 
			
		||||
[techniques.techs.Barta]
 | 
			
		||||
probability = 7
 | 
			
		||||
level_divisor = 7
 | 
			
		||||
[techniques.techs.Zonde]
 | 
			
		||||
probability = 7
 | 
			
		||||
level_divisor = 8
 | 
			
		||||
[techniques.techs.Resta]
 | 
			
		||||
probability = 7
 | 
			
		||||
level_divisor = 6
 | 
			
		||||
[techniques.techs.Anti]
 | 
			
		||||
probability = 7
 | 
			
		||||
level_divisor = 35
 | 
			
		||||
[techniques.techs.Shifta]
 | 
			
		||||
probability = 6
 | 
			
		||||
level_divisor = 9
 | 
			
		||||
[techniques.techs.Deband]
 | 
			
		||||
probability = 6
 | 
			
		||||
level_divisor = 7
 | 
			
		||||
[techniques.techs.Jellen]
 | 
			
		||||
probability = 6
 | 
			
		||||
level_divisor = 6
 | 
			
		||||
[techniques.techs.Zalure]
 | 
			
		||||
probability = 7
 | 
			
		||||
level_divisor = 8
 | 
			
		||||
[techniques.techs.Gifoie]
 | 
			
		||||
probability = 8
 | 
			
		||||
level_divisor = 9
 | 
			
		||||
[techniques.techs.Gibarta]
 | 
			
		||||
probability = 8
 | 
			
		||||
level_divisor = 12
 | 
			
		||||
[techniques.techs.Gizonde]
 | 
			
		||||
probability = 8
 | 
			
		||||
level_divisor = 8
 | 
			
		||||
[techniques.techs.Ryuker]
 | 
			
		||||
probability = 5
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Reverser]
 | 
			
		||||
probability = 5
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rafoie]
 | 
			
		||||
probability = 2
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rabarta]
 | 
			
		||||
probability = 2
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Razonde]
 | 
			
		||||
probability = 2
 | 
			
		||||
set_level = 1
 | 
			
		||||
[[techniques]]
 | 
			
		||||
level = 25
 | 
			
		||||
 | 
			
		||||
[techniques.techs.Foie]
 | 
			
		||||
probability = 5
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Barta]
 | 
			
		||||
probability = 5
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Zonde]
 | 
			
		||||
probability = 5
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Resta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Anti]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 35
 | 
			
		||||
[techniques.techs.Shifta]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 8
 | 
			
		||||
[techniques.techs.Deband]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 7
 | 
			
		||||
[techniques.techs.Jellen]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 5
 | 
			
		||||
[techniques.techs.Zalure]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 6
 | 
			
		||||
[techniques.techs.Gifoie]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 8
 | 
			
		||||
[techniques.techs.Gibarta]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 9
 | 
			
		||||
[techniques.techs.Gizonde]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 10
 | 
			
		||||
[techniques.techs.Ryuker]
 | 
			
		||||
probability = 6
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Reverser]
 | 
			
		||||
probability = 6
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rafoie]
 | 
			
		||||
probability = 9
 | 
			
		||||
level_divisor = 10
 | 
			
		||||
[techniques.techs.Rabarta]
 | 
			
		||||
probability = 9
 | 
			
		||||
level_divisor = 11
 | 
			
		||||
[techniques.techs.Razonde]
 | 
			
		||||
probability = 9
 | 
			
		||||
level_divisor = 12
 | 
			
		||||
[[techniques]]
 | 
			
		||||
level = 42
 | 
			
		||||
 | 
			
		||||
[techniques.techs.Foie]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Barta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Zonde]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Resta]
 | 
			
		||||
probability = 5
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Anti]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 35
 | 
			
		||||
[techniques.techs.Shifta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Deband]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Jellen]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Zalure]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 12
 | 
			
		||||
[techniques.techs.Gifoie]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Gibarta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Gizonde]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 10
 | 
			
		||||
[techniques.techs.Ryuker]
 | 
			
		||||
probability = 6
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Reverser]
 | 
			
		||||
probability = 6
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rafoie]
 | 
			
		||||
probability = 6
 | 
			
		||||
level_divisor = 12
 | 
			
		||||
[techniques.techs.Rabarta]
 | 
			
		||||
probability = 6
 | 
			
		||||
level_divisor = 13
 | 
			
		||||
[techniques.techs.Razonde]
 | 
			
		||||
probability = 6
 | 
			
		||||
level_divisor = 11
 | 
			
		||||
[[techniques]]
 | 
			
		||||
level = 60
 | 
			
		||||
 | 
			
		||||
[techniques.techs.Foie]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Barta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Zonde]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Resta]
 | 
			
		||||
probability = 5
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Anti]
 | 
			
		||||
probability = 5
 | 
			
		||||
level_divisor = 35
 | 
			
		||||
[techniques.techs.Shifta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Deband]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Jellen]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Zalure]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 5
 | 
			
		||||
max = 14
 | 
			
		||||
[techniques.techs.Gifoie]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 13
 | 
			
		||||
[techniques.techs.Gibarta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 13
 | 
			
		||||
[techniques.techs.Gizonde]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 4
 | 
			
		||||
max = 13
 | 
			
		||||
[techniques.techs.Ryuker]
 | 
			
		||||
probability = 6
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Reverser]
 | 
			
		||||
probability = 6
 | 
			
		||||
set_level = 1
 | 
			
		||||
[techniques.techs.Rafoie]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 13
 | 
			
		||||
[techniques.techs.Rabarta]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 13
 | 
			
		||||
[techniques.techs.Razonde]
 | 
			
		||||
probability = 6
 | 
			
		||||
min = 3
 | 
			
		||||
max = 13
 | 
			
		||||
							
								
								
									
										1
									
								
								data/shops/tools.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/shops/tools.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
tools = [ "Monomate", "Dimate", "Trimate", "Monofluid", "Difluid", "Trifluid", "Antidote", "Antiparalysis", "SolAtomizer", "MoonAtomizer", "StarAtomizer", "Telepipe",]
 | 
			
		||||
@ -1 +1,2 @@
 | 
			
		||||
pub mod weapon;
 | 
			
		||||
pub mod tool;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										268
									
								
								src/ship/shops/tool.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								src/ship/shops/tool.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,268 @@
 | 
			
		||||
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::tool::{Tool, ToolType};
 | 
			
		||||
use crate::entity::item::tech::{Technique, TechniqueDisk};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum ShopTool {
 | 
			
		||||
    Tool(ToolType),
 | 
			
		||||
    Tech(TechniqueDisk),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Ord for ShopTool {
 | 
			
		||||
    fn cmp(&self, other: &ShopTool) -> std::cmp::Ordering {
 | 
			
		||||
        let a = match self {
 | 
			
		||||
            ShopTool::Tool(t) => Tool{tool : *t}.as_individual_bytes(),
 | 
			
		||||
            ShopTool::Tech(t) => t.as_bytes(),
 | 
			
		||||
        };
 | 
			
		||||
        let b = match other {
 | 
			
		||||
            ShopTool::Tool(t) => Tool{tool : *t}.as_individual_bytes(),
 | 
			
		||||
            ShopTool::Tech(t) => t.as_bytes(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        a.cmp(&b)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PartialOrd for ShopTool {
 | 
			
		||||
    fn partial_cmp(&self, other: &ShopTool) -> Option<std::cmp::Ordering> {
 | 
			
		||||
        let a = match self {
 | 
			
		||||
            ShopTool::Tool(t) => Tool{tool : *t}.as_individual_bytes(),
 | 
			
		||||
            ShopTool::Tech(t) => t.as_bytes(),
 | 
			
		||||
        };
 | 
			
		||||
        let b = match other {
 | 
			
		||||
            ShopTool::Tool(t) => Tool{tool : *t}.as_individual_bytes(),
 | 
			
		||||
            ShopTool::Tech(t) => t.as_bytes(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        a.partial_cmp(&b)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize)]
 | 
			
		||||
struct ToolTable(Vec<ToolType>);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize, Clone)]
 | 
			
		||||
#[serde(untagged)]
 | 
			
		||||
enum TechLevel {
 | 
			
		||||
    Set {
 | 
			
		||||
        set_level: usize,
 | 
			
		||||
    },
 | 
			
		||||
    Level {
 | 
			
		||||
        level_divisor: usize,
 | 
			
		||||
    },
 | 
			
		||||
    Range {
 | 
			
		||||
        min: usize,
 | 
			
		||||
        max: usize,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize, Clone)]
 | 
			
		||||
struct TechEntry {
 | 
			
		||||
    probability: usize,
 | 
			
		||||
    #[serde(flatten)]
 | 
			
		||||
    level: TechLevel,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize)]
 | 
			
		||||
struct TechTierDeserialize {
 | 
			
		||||
    level: usize,
 | 
			
		||||
    techs: HashMap<String, TechEntry>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
struct TechTier {
 | 
			
		||||
    level: usize,
 | 
			
		||||
    techs: HashMap<Technique, TechEntry>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct TechTable(Vec<TechTier>);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn load_tool_table() -> ToolTable {
 | 
			
		||||
    let path = PathBuf::from("data/shops/tools.toml");
 | 
			
		||||
    let mut f = File::open(path).unwrap();
 | 
			
		||||
    let mut s = String::new();
 | 
			
		||||
    f.read_to_string(&mut s).unwrap();
 | 
			
		||||
 | 
			
		||||
    let mut table: HashMap<String, Vec<ToolType>> = toml::from_str(s.as_str()).unwrap();
 | 
			
		||||
 | 
			
		||||
    ToolTable(table.remove("tools".into()).unwrap())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn load_tech_table() -> TechTable {
 | 
			
		||||
    let path = PathBuf::from("data/shops/techniques.toml");
 | 
			
		||||
    let mut f = File::open(path).unwrap();
 | 
			
		||||
    let mut s = String::new();
 | 
			
		||||
    f.read_to_string(&mut s).unwrap();
 | 
			
		||||
 | 
			
		||||
    let mut table: HashMap<String, Vec<TechTierDeserialize>> = toml::from_str(s.as_str()).unwrap();
 | 
			
		||||
    let techniques = table.remove("techniques".into()).unwrap();
 | 
			
		||||
    let techniques = techniques.into_iter()
 | 
			
		||||
        .map(|tech_tier| {
 | 
			
		||||
            TechTier {
 | 
			
		||||
                level: tech_tier.level,
 | 
			
		||||
                techs: tech_tier.techs.into_iter()
 | 
			
		||||
                    .map(|(tech_name, tech_entry)| {
 | 
			
		||||
                        (tech_name.parse().unwrap(), tech_entry)
 | 
			
		||||
                    }).collect()
 | 
			
		||||
            }
 | 
			
		||||
        }).collect();
 | 
			
		||||
 | 
			
		||||
    TechTable(techniques)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn number_of_techs_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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct ToolShop<R: Rng + SeedableRng> {
 | 
			
		||||
    tools: ToolTable,
 | 
			
		||||
    techs: TechTable,
 | 
			
		||||
    rng: R,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<R: Rng + SeedableRng> ToolShop<R> {
 | 
			
		||||
    pub fn new() -> ToolShop<R> {
 | 
			
		||||
        ToolShop {
 | 
			
		||||
            tools: load_tool_table(),
 | 
			
		||||
            techs: load_tech_table(),
 | 
			
		||||
            rng: R::from_entropy(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn generate_tech(&mut self, character_level: usize) -> ShopTool {
 | 
			
		||||
        let tier = self.techs.0.iter()
 | 
			
		||||
            .filter(|t| t.level <= character_level)
 | 
			
		||||
            .last()
 | 
			
		||||
            .unwrap();
 | 
			
		||||
 | 
			
		||||
        let mut tier = tier.techs.iter()
 | 
			
		||||
            .map(|(tech, entry)| {
 | 
			
		||||
                (tech, entry)
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        let tech_choice = WeightedIndex::new(tier.clone().map(|(_, e)| e.probability)).unwrap();
 | 
			
		||||
        let tech_detail = tier.nth(tech_choice.sample(&mut self.rng)).unwrap();
 | 
			
		||||
        let tech_level = match tech_detail.1.level {
 | 
			
		||||
            TechLevel::Set{set_level} => set_level,
 | 
			
		||||
            TechLevel::Level{level_divisor} => std::cmp::max(std::cmp::min(character_level, 99)/level_divisor, 1),
 | 
			
		||||
            TechLevel::Range{min, max} => self.rng.gen_range(min, max+1),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        ShopTool::Tech(
 | 
			
		||||
            TechniqueDisk {
 | 
			
		||||
                tech: *tech_detail.0,
 | 
			
		||||
                level: tech_level as u32,
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn generate_tech_types(&mut self, character_level: usize) -> Vec<Technique> {
 | 
			
		||||
        let tier = self.techs.0.iter()
 | 
			
		||||
            .filter(|t| t.level <= character_level)
 | 
			
		||||
            .last()
 | 
			
		||||
            .unwrap();
 | 
			
		||||
 | 
			
		||||
        let possible_techs = tier.techs.iter()
 | 
			
		||||
            .filter(|(_, entry)| entry.probability > 0)
 | 
			
		||||
            .collect::<Vec<_>>();
 | 
			
		||||
 | 
			
		||||
        let number_of_techs = std::cmp::min(possible_techs.len(), number_of_techs_to_generate(character_level));
 | 
			
		||||
        if number_of_techs == possible_techs.len() {
 | 
			
		||||
            possible_techs.into_iter()
 | 
			
		||||
                .map(|(tech, _entry)| {
 | 
			
		||||
                    tech
 | 
			
		||||
                })
 | 
			
		||||
                .cloned()
 | 
			
		||||
                .collect()
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            let mut techs = Vec::new();
 | 
			
		||||
            let tier = tier.techs.iter()
 | 
			
		||||
                .map(|(tech, entry)| {
 | 
			
		||||
                    (tech, entry)
 | 
			
		||||
                })
 | 
			
		||||
                .collect::<Vec<_>>();
 | 
			
		||||
 | 
			
		||||
            let tech_choice = WeightedIndex::new(tier.iter().map(|(_, e)| e.probability)).unwrap();
 | 
			
		||||
            while techs.len() < number_of_techs {
 | 
			
		||||
                let tech_detail = tier.get(tech_choice.sample(&mut self.rng)).unwrap();
 | 
			
		||||
                if techs.iter().find(|t| *t == tech_detail.0).is_none() {
 | 
			
		||||
                    techs.push(*tech_detail.0);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            techs
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn generate_techs(&mut self, character_level: usize) -> Vec<ShopTool> {
 | 
			
		||||
        let tier = self.techs.0.iter()
 | 
			
		||||
            .filter(|t| t.level <= character_level)
 | 
			
		||||
            .last()
 | 
			
		||||
            .cloned()
 | 
			
		||||
            .unwrap();
 | 
			
		||||
 | 
			
		||||
        let tech_types = self.generate_tech_types(character_level);
 | 
			
		||||
        tech_types.into_iter()
 | 
			
		||||
            .map(|tech| {
 | 
			
		||||
                let tech_detail = tier.techs.get(&tech).unwrap().clone();
 | 
			
		||||
                let level = match tech_detail.level {
 | 
			
		||||
                    TechLevel::Set{set_level} => set_level,
 | 
			
		||||
                    TechLevel::Level{level_divisor} => std::cmp::max(std::cmp::min(character_level, 99)/level_divisor, 1),
 | 
			
		||||
                    TechLevel::Range{min, max} => self.rng.gen_range(min, max+1),
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                ShopTool::Tech(TechniqueDisk {
 | 
			
		||||
                    tech: tech,
 | 
			
		||||
                    level: level as u32,
 | 
			
		||||
                })
 | 
			
		||||
            })
 | 
			
		||||
            .collect()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn generate_tool_list(&mut self, character_level: usize) -> Vec<ShopTool> {
 | 
			
		||||
        let mut tools = Vec::new().into_iter()
 | 
			
		||||
            .chain(self.tools.0.clone().into_iter().map(|t| ShopTool::Tool(t)))
 | 
			
		||||
            .chain(self.generate_techs(character_level).into_iter())
 | 
			
		||||
            .collect::<Vec<_>>();
 | 
			
		||||
        tools.sort();
 | 
			
		||||
        tools
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod test {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_loading_tool_shop() {
 | 
			
		||||
        ToolShop::<rand_chacha::ChaCha20Rng>::new();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user