rust/mapgen/src/lib.rs
changeset 14127 0c5b9cfda9ab
child 14128 b04dac00e8e2
equal deleted inserted replaced
14126:32383b888309 14127:0c5b9cfda9ab
       
     1 use std::{
       
     2     collections::hash_map::HashMap,
       
     3     borrow::Borrow,
       
     4     mem::replace
       
     5 };
       
     6 use serde::{Deserialize};
       
     7 use serde_derive::{Deserialize};
       
     8 use serde_yaml;
       
     9 use integral_geometry::{Point, Size, Rect};
       
    10 use landgen::{
       
    11     outline_template::OutlineTemplate
       
    12 };
       
    13 use rand::{thread_rng, Rng};
       
    14 
       
    15 #[derive(Deserialize)]
       
    16 struct PointDesc {
       
    17     x: u32,
       
    18     y: u32
       
    19 }
       
    20 
       
    21 #[derive(Deserialize)]
       
    22 struct RectDesc {
       
    23     x: u32,
       
    24     y: u32,
       
    25     w: u32,
       
    26     h: u32
       
    27 }
       
    28 
       
    29 #[derive(Deserialize)]
       
    30 struct TemplateDesc {
       
    31     width: usize,
       
    32     height: usize,
       
    33     can_flip: bool,
       
    34     can_invert: bool,
       
    35     can_mirror: bool,
       
    36     is_negative: bool,
       
    37     put_girders: bool,
       
    38     max_hedgehogs: u8,
       
    39     outline_points: Vec<Vec<RectDesc>>,
       
    40     fill_points: Vec<PointDesc>
       
    41 }
       
    42 
       
    43 #[derive(Deserialize)]
       
    44 struct TemplateCollectionDesc {
       
    45     templates: Vec<TemplateDesc>,
       
    46     template_types: HashMap<String, Vec<usize>>
       
    47 }
       
    48 
       
    49 impl From<&TemplateDesc> for OutlineTemplate {
       
    50     fn from(desc: &TemplateDesc) -> Self {
       
    51         OutlineTemplate {
       
    52             islands: desc.outline_points.iter()
       
    53                 .map(|v| v.iter()
       
    54                     .map(|r| Rect::new(r.x as i32, r.y as i32, r.w, r.h))
       
    55                     .collect())
       
    56                 .collect(),
       
    57             fill_points: desc.fill_points.iter()
       
    58                 .map(|p| Point::new(p.x as i32, p.y as i32))
       
    59                 .collect(),
       
    60             size: Size::new(desc.width, desc.height),
       
    61             can_flip: desc.can_flip,
       
    62             can_invert: desc.can_invert,
       
    63             can_mirror: desc.can_mirror,
       
    64             is_negative: desc.is_negative
       
    65         }
       
    66     }
       
    67 }
       
    68 
       
    69 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
       
    70 struct TemplateType(String);
       
    71 
       
    72 impl Borrow<str> for TemplateType {
       
    73     fn borrow(&self) -> &str {
       
    74         self.0.as_str()
       
    75     }
       
    76 }
       
    77 
       
    78 #[derive(Debug)]
       
    79 pub struct MapGenerator {
       
    80     pub(crate) templates: HashMap<TemplateType, Vec<OutlineTemplate>>
       
    81 }
       
    82 
       
    83 impl MapGenerator {
       
    84     pub fn new() -> Self {
       
    85         Self { templates: HashMap::new() }
       
    86     }
       
    87 
       
    88     pub fn import_yaml_templates(&mut self, text: &str) {
       
    89         let mut desc: TemplateCollectionDesc = serde_yaml::from_str(text).unwrap();
       
    90         let templates = replace(&mut desc.templates, vec![]);
       
    91         self.templates = desc.template_types.into_iter()
       
    92             .map(|(size, indices)|
       
    93                 (TemplateType(size), indices.iter()
       
    94                     .map(|i| (&templates[*i]).into())
       
    95                     .collect()))
       
    96             .collect();
       
    97     }
       
    98 
       
    99     pub fn get_template(&self, template_type: &str) -> Option<&OutlineTemplate> {
       
   100         self.templates.get(template_type).and_then(|t| thread_rng().choose(t))
       
   101     }
       
   102 }
       
   103 
       
   104 #[cfg(test)]
       
   105 mod tests {
       
   106     use crate::{
       
   107         MapGenerator,
       
   108         TemplateType
       
   109     };
       
   110 
       
   111     #[test]
       
   112     fn simple_load() {
       
   113         let text = r#"
       
   114 templates:
       
   115   -
       
   116     width: 3072
       
   117     height: 1424
       
   118     can_flip: false
       
   119     can_invert: false
       
   120     can_mirror: true
       
   121     is_negative: false
       
   122     put_girders: true
       
   123     max_hedgehogs: 18
       
   124     outline_points:
       
   125       -
       
   126         - {x: 748, y: 1424, w: 1, h: 1}
       
   127         - {x: 636, y: 1252, w: 208, h: 72}
       
   128         - {x: 898, y: 1110, w: 308, h: 60}
       
   129         - {x: 1128, y: 1252, w: 434, h: 40}
       
   130         - {x: 1574, y: 1112, w: 332, h: 40}
       
   131         - {x: 1802, y: 1238, w: 226, h: 36}
       
   132         - {x: 1930, y: 1424, w: 1, h: 1}
       
   133     fill_points:
       
   134       - {x: 1023, y: 0}
       
   135 
       
   136 template_types:
       
   137     test: [0]
       
   138 
       
   139 "#;
       
   140 
       
   141         let mut generator = MapGenerator::new();
       
   142         generator.import_yaml_templates(&text);
       
   143 
       
   144         assert!(generator.templates.contains_key(&TemplateType("test".to_string())));
       
   145 
       
   146         let template = generator.get_template("test").unwrap();
       
   147 
       
   148         assert_eq!(template.islands[0].len(), 7);
       
   149     }
       
   150 }