rust/mapgen/src/lib.rs
changeset 14148 0c5b9cfda9ab
child 14149 b04dac00e8e2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/mapgen/src/lib.rs	Sun Nov 04 04:43:30 2018 +0300
@@ -0,0 +1,150 @@
+use std::{
+    collections::hash_map::HashMap,
+    borrow::Borrow,
+    mem::replace
+};
+use serde::{Deserialize};
+use serde_derive::{Deserialize};
+use serde_yaml;
+use integral_geometry::{Point, Size, Rect};
+use landgen::{
+    outline_template::OutlineTemplate
+};
+use rand::{thread_rng, Rng};
+
+#[derive(Deserialize)]
+struct PointDesc {
+    x: u32,
+    y: u32
+}
+
+#[derive(Deserialize)]
+struct RectDesc {
+    x: u32,
+    y: u32,
+    w: u32,
+    h: u32
+}
+
+#[derive(Deserialize)]
+struct TemplateDesc {
+    width: usize,
+    height: usize,
+    can_flip: bool,
+    can_invert: bool,
+    can_mirror: bool,
+    is_negative: bool,
+    put_girders: bool,
+    max_hedgehogs: u8,
+    outline_points: Vec<Vec<RectDesc>>,
+    fill_points: Vec<PointDesc>
+}
+
+#[derive(Deserialize)]
+struct TemplateCollectionDesc {
+    templates: Vec<TemplateDesc>,
+    template_types: HashMap<String, Vec<usize>>
+}
+
+impl From<&TemplateDesc> for OutlineTemplate {
+    fn from(desc: &TemplateDesc) -> Self {
+        OutlineTemplate {
+            islands: desc.outline_points.iter()
+                .map(|v| v.iter()
+                    .map(|r| Rect::new(r.x as i32, r.y as i32, r.w, r.h))
+                    .collect())
+                .collect(),
+            fill_points: desc.fill_points.iter()
+                .map(|p| Point::new(p.x as i32, p.y as i32))
+                .collect(),
+            size: Size::new(desc.width, desc.height),
+            can_flip: desc.can_flip,
+            can_invert: desc.can_invert,
+            can_mirror: desc.can_mirror,
+            is_negative: desc.is_negative
+        }
+    }
+}
+
+#[derive(PartialEq, Eq, Hash, Clone, Debug)]
+struct TemplateType(String);
+
+impl Borrow<str> for TemplateType {
+    fn borrow(&self) -> &str {
+        self.0.as_str()
+    }
+}
+
+#[derive(Debug)]
+pub struct MapGenerator {
+    pub(crate) templates: HashMap<TemplateType, Vec<OutlineTemplate>>
+}
+
+impl MapGenerator {
+    pub fn new() -> Self {
+        Self { templates: HashMap::new() }
+    }
+
+    pub fn import_yaml_templates(&mut self, text: &str) {
+        let mut desc: TemplateCollectionDesc = serde_yaml::from_str(text).unwrap();
+        let templates = replace(&mut desc.templates, vec![]);
+        self.templates = desc.template_types.into_iter()
+            .map(|(size, indices)|
+                (TemplateType(size), indices.iter()
+                    .map(|i| (&templates[*i]).into())
+                    .collect()))
+            .collect();
+    }
+
+    pub fn get_template(&self, template_type: &str) -> Option<&OutlineTemplate> {
+        self.templates.get(template_type).and_then(|t| thread_rng().choose(t))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::{
+        MapGenerator,
+        TemplateType
+    };
+
+    #[test]
+    fn simple_load() {
+        let text = r#"
+templates:
+  -
+    width: 3072
+    height: 1424
+    can_flip: false
+    can_invert: false
+    can_mirror: true
+    is_negative: false
+    put_girders: true
+    max_hedgehogs: 18
+    outline_points:
+      -
+        - {x: 748, y: 1424, w: 1, h: 1}
+        - {x: 636, y: 1252, w: 208, h: 72}
+        - {x: 898, y: 1110, w: 308, h: 60}
+        - {x: 1128, y: 1252, w: 434, h: 40}
+        - {x: 1574, y: 1112, w: 332, h: 40}
+        - {x: 1802, y: 1238, w: 226, h: 36}
+        - {x: 1930, y: 1424, w: 1, h: 1}
+    fill_points:
+      - {x: 1023, y: 0}
+
+template_types:
+    test: [0]
+
+"#;
+
+        let mut generator = MapGenerator::new();
+        generator.import_yaml_templates(&text);
+
+        assert!(generator.templates.contains_key(&TemplateType("test".to_string())));
+
+        let template = generator.get_template("test").unwrap();
+
+        assert_eq!(template.islands[0].len(), 7);
+    }
+}