adventure-sim/src/sim/definitions.rs

117 lines
3.5 KiB
Rust

use parser::{SliceParseError, TagParseError};
use serde::{Deserialize, Serialize};
use self::parser::{FilePosition, ParseError, SliceParse};
pub mod parser;
#[derive(Debug)]
pub enum TopLevelTag {
Site,
Creature,
}
#[derive(Default, Debug, Clone)]
pub struct Tag {
pub name: String,
pub values: Vec<String>,
pub file_position: FilePosition,
}
impl Tag {
fn parse_value<T: SliceParse>(&self) -> Result<T, ParseError> {
T::parse(&self.values).map_err(|err| {
ParseError::TagParseError(match err {
SliceParseError::ParseError => TagParseError::ParseError(self.clone()),
SliceParseError::MissingValue => TagParseError::MissingValue(self.clone()),
})
})
}
}
#[derive(Clone, Default, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct SiteDef {
pub id: String,
pub min_size: i32,
pub max_size: i32,
pub is_underground: bool,
pub is_natural: bool,
}
impl SiteDef {
pub fn parse(header: Tag, tags: &[Tag]) -> Result<Self, ParseError> {
let mut result = Self {
id: header.parse_value::<String>().unwrap(),
..Default::default()
};
for tag in tags {
match tag.name.as_str() {
"SIZE" => (result.min_size, result.max_size) = tag.parse_value().unwrap(),
"NATURAL" => result.is_natural = true,
_ => {
eprintln!("Unknown tag '{}' in SITE defs", tag.name);
}
}
}
Ok(result)
}
}
#[derive(Clone, Default, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct CreatureDef {
pub id: String,
pub name_singular: String,
pub name_plural: String,
pub health: i32,
pub armor_class: i8,
pub to_hit_modifier: i8,
pub min_damage: i32,
pub max_damage: i32,
pub multiattack: Option<u32>,
pub is_humanoid: bool,
pub is_animal: bool,
pub is_intelligent: bool,
pub patrols: bool,
pub prefers_dark: bool,
pub invulnerable: bool,
}
impl CreatureDef {
pub fn parse(header: Tag, tags: &[Tag]) -> Result<Self, ParseError> {
let mut result = Self {
id: header.parse_value().unwrap(),
..Default::default()
};
for tag in tags {
match tag.name.as_str() {
"NAME" => (result.name_singular, result.name_plural) = tag.parse_value()?,
"HEALTH" => result.health = tag.parse_value()?,
"AC" => result.armor_class = tag.parse_value()?,
"ATTACK" => {
(result.to_hit_modifier, result.min_damage, result.max_damage) =
tag.parse_value()?
}
"MULTIATTACK" => result.multiattack = Some(tag.parse_value()?),
"HUMANOID" => result.is_humanoid = true,
"ANIMAL" => result.is_animal = true,
"INTELLIGENT" => result.is_intelligent = true,
"PATROL" => result.patrols = true,
"PREFER_DARK" => result.prefers_dark = true,
"INVULNERABLE" => result.invulnerable = true,
_ => {
eprintln!("Unknown tag '{}' in CREATURE defs", tag.name);
}
}
}
Ok(result)
}
pub fn attack_count(&self) -> u32 {
self.multiattack.unwrap_or(1)
}
pub fn damage_roll(&self) -> i32 {
fastrand::i32(self.min_damage..=self.max_damage)
}
}