use failure;
use rrecutils;
/// A `Card` always has a name, an icon, and some miscellaneous other information
#[derive(Debug)]
pub struct Card<'a> {
pub name: &'a str,
pub icon: String,
pub card_type: CardType<'a>,
}
/// Different card types have different miscellaneous other pieces of
/// information, but most of them are kept in a catch-all "Generic"
/// case
#[derive(Debug)]
pub enum CardType<'a> {
Monster {
hp: &'a str,
melee: Option<&'a str>,
ranged: Option<&'a str>,
arcane: Option<&'a str>,
defense: Option<&'a str>,
action: &'a str,
effect: &'a str,
},
Weapon {
weapon_type: WeaponType,
ability: &'a str,
effect: &'a str,
},
Generic {
kind: Kind,
effect: &'a str,
},
}
#[derive(Debug, Clone, Copy)]
pub enum Kind { Ability, Equipment, Item, Plant, Treasure }
#[derive(Debug, Clone, Copy)]
pub enum WeaponType { Melee, Ranged, Arcane }
impl<'a> Card<'a> {
/// Here we parse out our in-program `Card` type from the recutils
/// storage format of the card
pub fn from_record(rec: &'a rrecutils::Record)
-> Result<Card<'a>, failure::Error>
{
let name = rec.get("Name")?;
// If this doesn't have a Type set by the Recutils parser,
// then that's a problem!
let typ = rec.get_type()?;
let card_type = match typ {
"Weapon" => CardType::Weapon {
weapon_type: match rec.get("Type")? {
"melee" => WeaponType::Melee,
"ranged" => WeaponType::Ranged,
// XXX FIXME IN THE FILE (but for ease of writing
// this assumes that we might keep using the old
// "magic" terminology instead of "arcane")
"magic" | "arcane" => WeaponType::Arcane,
t => bail!("Unknown weapon type: {}", t),
},
ability: rec.get("Ability")?,
effect: rec.get("Effect")?,
},
"Monster" => CardType::Monster {
hp: rec.get("HP")?,
melee: rec.get("Melee").ok(),
ranged: rec.get("Ranged").ok(),
arcane: rec.get("Arcane").ok(),
defense: rec.get("Defense").ok(),
action: rec.get("Action")?,
effect: rec.get("Effect")?,
},
t => CardType::Generic {
kind: match t {
"Ability" => Kind::Ability,
"Item" => Kind::Item,
"Equipment" => Kind::Equipment,
"Plant" => Kind::Plant,
"Treasure" => Kind::Treasure,
_ => bail!("Unknown card type: {}", t),
},
effect: rec.get("Effect")?,
}
};
let lower_type = typ.to_lowercase();
let icon = format!(
"../icons/{}-icon.svg",
rec.get("Icon").unwrap_or(
match typ {
"Weapon" => rec.get("Type")?,
_ => &lower_type,
}
),
);
Ok(Card { name, icon, card_type })
}
pub fn type_name(&self) -> &'static str {
match self.card_type {
CardType::Weapon { .. } => "weapon",
CardType::Monster { .. } => "monster",
CardType::Generic { kind, .. } => match kind {
Kind::Ability => "ability",
Kind::Item => "item",
Kind::Equipment => "equipment",
Kind::Plant => "plant",
Kind::Treasure => "treasure",
},
}
}
pub fn card_name(&self) -> String {
self.name.chars().filter_map(|c| {
if c == ' '{
Some('_')
} else if c.is_alphabetic() {
Some(c.to_ascii_lowercase())
} else {
None
}
}).collect()
}
}