civ_map_generator 0.1.6

A civilization map generator
Documentation
use std::sync::LazyLock;

use regex::Regex;
use serde::{Deserialize, Serialize};

use crate::tile_component::{BaseTerrain, Feature, TerrainType};

pub trait Name {
    fn name(&self) -> String;
}

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Yields {
    #[serde(default)]
    pub food: i8,
    #[serde(default)]
    pub production: i8,
    #[serde(default)]
    pub science: i8,
    #[serde(default)]
    pub gold: i8,
    #[serde(default)]
    pub culture: i8,
    #[serde(default)]
    pub faith: i8,
    #[serde(default)]
    pub happiness: i8,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RequiredTerrain {
    #[serde(default = "default_terrain_type")]
    pub terrain_type: Vec<TerrainType>,
    #[serde(default = "default_base_terrain")]
    pub base_terrain: Vec<BaseTerrain>,
    /// When it's `None`, it means the required terrain will ignore this value,
    /// which means it can be any feature or no feature.
    pub feature: Option<Vec<Feature>>,
    /// When it's `None`, it means the required terrain will ignore this value,
    /// which means it has a river or not.
    river: Option<bool>,
    /// When it's `None`, it means the required terrain will ignore this value,
    /// which means the required terrain can be freshwater or not.
    #[serde(default)]
    pub freshwater: Option<bool>,
    #[serde(default)]
    pub extra_conditions: Vec<String>,
}

impl Default for RequiredTerrain {
    fn default() -> Self {
        Self {
            terrain_type: vec![TerrainType::Flatland, TerrainType::Hill],
            base_terrain: vec![
                BaseTerrain::Grassland,
                BaseTerrain::Plain,
                BaseTerrain::Desert,
                BaseTerrain::Tundra,
                BaseTerrain::Snow,
            ],
            feature: None,
            river: None,
            freshwater: None,
            extra_conditions: Vec::new(),
        }
    }
}

fn default_terrain_type() -> Vec<TerrainType> {
    vec![TerrainType::Flatland, TerrainType::Hill]
}

fn default_base_terrain() -> Vec<BaseTerrain> {
    vec![
        BaseTerrain::Grassland,
        BaseTerrain::Plain,
        BaseTerrain::Desert,
        BaseTerrain::Tundra,
        BaseTerrain::Snow,
    ]
}

#[derive(Debug)]
pub struct Unique {
    pub placeholder_text: String,
    pub params: Vec<String>,
    pub conditionals: Vec<Unique>,
}

impl Unique {
    pub fn new(unique: &str) -> Self {
        static PARAMS_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\[(.+?)\]").unwrap());
        static CONDITION_REGEX: LazyLock<Regex> =
            LazyLock::new(|| Regex::new(r"<([^>]*)>").unwrap());

        let unique_without_conditionals = CONDITION_REGEX.replace_all(unique, "");
        let unique_without_conditionals = unique_without_conditionals.trim();

        let placeholder_text = PARAMS_REGEX
            .replace_all(unique_without_conditionals, "[]")
            .to_string();

        let params = PARAMS_REGEX
            .captures_iter(unique_without_conditionals)
            .map(|cap| cap[1].to_owned())
            .collect();

        let conditionals = CONDITION_REGEX
            .captures_iter(unique)
            .map(|cap| Self::new(&cap[1]))
            .collect();

        Self {
            placeholder_text,
            params,
            conditionals,
        }
    }
}