Add forbids, update description colors, names

This commit is contained in:
asonix 2020-10-31 18:02:24 -05:00
parent faec338d57
commit 5b02cbec16
5 changed files with 131 additions and 41 deletions

2
Cargo.lock generated
View File

@ -1072,7 +1072,7 @@ dependencies = [
[[package]]
name = "warriors-names"
version = "0.1.4"
version = "0.1.5"
dependencies = [
"anyhow",
"rand",

View File

@ -1,6 +1,6 @@
[package]
name = "warriors-names"
version = "0.1.4"
version = "0.1.5"
authors = ["asonix <asonix@asonix.dog>"]
edition = "2018"

View File

@ -153,27 +153,12 @@
"ginger",
"brown",
"reddish-brown",
"golden",
"golden-brown",
"dusky-brown",
"white"
],
"depends": [{
"variants": [
"black",
"gray",
"silver",
"blue-gray",
"ginger",
"brown",
"reddish-brown",
"golden-brown",
"dusky-brown",
"white"
],
"depends": "solid",
"chance": 0.2,
"order": "{solid} {base}"
}, {
"variants": ["black"],
"depends": "color-modifier",
"chance": 0.3,
@ -189,12 +174,14 @@
"ginger",
"brown",
"reddish-brown",
"golden",
"golden-brown"
],
"depends": "color-modifier",
"chance": 0.3,
"order": "{color-modifier} {base}",
"weights": [
[1, "dark"],
[1, "light"],
[1, "pale"],
[1, "bright"]
@ -207,6 +194,23 @@
"weights": [
[1, "bright"]
]
}, {
"variants": [
"black",
"gray",
"silver",
"blue-gray",
"ginger",
"brown",
"reddish-brown",
"golden",
"golden-brown",
"dusky-brown",
"white"
],
"depends": "solid",
"chance": 0.2,
"order": "{solid} {base}"
}]
}, {
"name": "gembder",
@ -229,6 +233,10 @@
"tabby"
],
"depends": "pelt-color",
"forbids": [{
"name": "solid",
"variants": ["solid"]
}],
"chance": 0.5,
"order": "{pelt-color} {base}"
}, {
@ -258,7 +266,19 @@
"order": "{base} {gembder}",
"default": "cat"
}, {
"variants": "any",
"variants": [
"tabby",
"tortoiseshell"
],
"depends": "descriptor",
"forbids": [{
"name": "descriptor",
"variants": ["mottled"]
}],
"chance": 0.5,
"order": "{descriptor} {base}"
}, {
"variants": ["cat"],
"depends": "descriptor",
"chance": 0.5,
"order": "{descriptor} {base}"

View File

@ -110,7 +110,9 @@
"minnow",
"pounce",
"pebble",
"ripple"
"ripple",
"ice",
"fox"
],
"suffix": [
"kit",
@ -146,7 +148,8 @@
"wing",
"fall",
"bird",
"feather"
"feather",
"mist"
]
}

View File

@ -46,19 +46,37 @@ struct Entry {
}
impl Entry {
fn gen(
&self,
fn gen<'a, 'b>(
&'a self,
weights: Option<&[(u64, String)]>,
entries: &[Entry],
entries: &'a [Entry],
forbids: &'b mut Vec<Vec<&'a Forbid>>,
rng: &mut impl Rng,
) -> String {
) -> String
where
'a: 'b,
{
let variant = self.gen_variant(weights, rng);
let building = self.gen_depends(&variant, entries, rng);
if forbids
.iter()
.find(|f| {
f.iter()
.find(|f| f.name == self.name && f.variants.contains(&variant))
.is_some()
})
.is_some()
{
return String::new();
}
let building = self.gen_depends(&variant, entries, forbids, rng);
let mut seen = HashSet::new();
seen.insert(variant.clone());
self.gen_next(building, &variant, weights, entries, &mut seen, rng)
self.gen_next(
building, &variant, weights, entries, forbids, &mut seen, rng,
)
}
fn gen_variant(&self, weights: Option<&[(u64, String)]>, rng: &mut impl Rng) -> String {
@ -74,27 +92,40 @@ impl Entry {
.to_string()
}
fn gen_depends(&self, variant: &str, entries: &[Entry], rng: &mut impl Rng) -> String {
fn gen_depends<'a, 'b>(
&'a self,
variant: &str,
entries: &'a [Entry],
forbids: &'b mut Vec<Vec<&'a Forbid>>,
rng: &mut impl Rng,
) -> String
where
'a: 'b,
{
let base = if self.silent.contains(variant) {
String::new()
} else {
variant.to_string()
};
self.depends
.iter()
.fold(base, |acc, depend| depend.gen(acc, variant, entries, rng))
self.depends.iter().fold(base, |acc, depend| {
depend.gen(acc, variant, entries, forbids, rng)
})
}
fn gen_next(
&self,
fn gen_next<'a, 'b>(
&'a self,
building: String,
variant: &str,
weights: Option<&[(u64, String)]>,
entries: &[Entry],
entries: &'a [Entry],
forbids: &'b mut Vec<Vec<&'a Forbid>>,
seen: &mut HashSet<String>,
rng: &mut impl Rng,
) -> String {
) -> String
where
'a: 'b,
{
let (s, _, _) = self.next.iter().fold(
(building, variant.to_string(), seen),
|(acc, v, seen), next| {
@ -103,11 +134,11 @@ impl Entry {
return (acc, variant, seen);
}
seen.insert(variant.clone());
let depends = self.gen_depends(&variant, entries, rng);
let depends = self.gen_depends(&variant, entries, forbids, rng);
let building = next.join(acc, &depends);
let building = self.gen_next(building, &variant, weights, entries, seen, rng);
let building =
self.gen_next(building, &variant, weights, entries, forbids, seen, rng);
return (building, variant, seen);
}
@ -120,6 +151,12 @@ impl Entry {
}
}
#[derive(serde::Deserialize)]
struct Forbid {
name: String,
variants: Anyable,
}
#[derive(serde::Deserialize)]
struct Next {
from: Anyable,
@ -206,10 +243,23 @@ struct Depend {
order: String,
weights: Option<Vec<(u64, String)>>,
default: Option<String>,
#[serde(default)]
forbids: Vec<Forbid>,
}
impl Depend {
fn gen(&self, acc: String, variant: &str, entries: &[Entry], rng: &mut impl Rng) -> String {
fn gen<'a, 'b>(
&'a self,
acc: String,
variant: &str,
entries: &'a [Entry],
forbids: &'b mut Vec<Vec<&'a Forbid>>,
rng: &mut impl Rng,
) -> String
where
'a: 'b,
{
if !self.variants.contains(variant) {
return acc;
}
@ -225,17 +275,32 @@ impl Depend {
return acc;
}
let local_forbids = self.forbids.iter().collect();
forbids.push(local_forbids);
let entry = entries
.into_iter()
.find(|entry| entry.name == self.depends)
.expect(&format!("Missing entry for {}", self.depends));
let value = entry.gen(self.weights.as_ref().map(Vec::as_slice), entries, rng);
let value = entry.gen(
self.weights.as_ref().map(Vec::as_slice),
entries,
forbids,
rng,
);
forbids.pop();
if acc.is_empty() {
return value;
}
if value.is_empty() {
return acc;
}
self.join(acc, &value)
}
@ -260,7 +325,9 @@ impl Config {
.find(|entry| entry.name == self.root)
.expect(&format!("Invalid config: no entry called {}", self.root));
root.gen(None, &self.entries, rng)
let mut forbids = Vec::new();
root.gen(None, &self.entries, &mut forbids, rng)
}
}