diff --git a/Cargo.lock b/Cargo.lock index 1b0c372..3529034 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,10 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "argh" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca1877e24cecacd700d469066e0160c4f8497cc5635367163f50c8beec820154" +checksum = "f023c76cd7975f9969f8e29f0e461decbdc7f51048ce43427107a3d192f1c9bf" dependencies = [ "argh_derive", "argh_shared", @@ -12,9 +14,9 @@ dependencies = [ [[package]] name = "argh_derive" -version = "0.1.1" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e742194e0f43fc932bcb801708c2b279d3ec8f527e3acda05a6a9f342c5ef764" +checksum = "48ad219abc0c06ca788aface2e3a1970587e3413ab70acd20e54b6ec524c1f8f" dependencies = [ "argh_shared", "heck", @@ -25,19 +27,19 @@ dependencies = [ [[package]] name = "argh_shared" -version = "0.1.1" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1ba68f4276a778591e36a0c348a269888f3a177c8d2054969389e3b59611ff5" +checksum = "38de00daab4eac7d753e97697066238d67ce9d7e2d823ab4f72fe14af29f3f33" [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "dsmsg" -version = "1.7.0-dev0" +version = "1.7.0" dependencies = [ "argh", "lazy_static", @@ -47,9 +49,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", "libc", @@ -58,9 +60,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" dependencies = [ "unicode-segmentation", ] @@ -73,30 +75,30 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.77" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] @@ -150,9 +152,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "1.0.42" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" +checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" dependencies = [ "proc-macro2", "quote", @@ -161,15 +163,15 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "wasi" diff --git a/Cargo.toml b/Cargo.toml index 9b35af1..136a08c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dsmsg" -description = "Randomly generate online messages from Dark Souls, Demon's Souls, Bloodborne, and Sekiro." -version = "1.7.0-dev0" +description = "Randomly generate online messages from Dark Souls, Demon's Souls, Bloodborne, Sekiro, and Elden Ring." +version = "1.7.0" authors = ["Yaulendil "] repository = "https://github.com/yaulendil/dsmsg" @@ -23,20 +23,22 @@ panic = "abort" [dependencies] -argh = "0.1.3" -lazy_static = "1.4.0" +argh = "0.1" +lazy_static = "1.4" rand = "0.7" -static_assertions = "1.1.0" +static_assertions = "1.1" [features] -default = ["ds1", "ds2", "ds3"] +default = ["darksouls"] # NewLine Feature inserts a Line Break between parts of a Compound Message. newline = [] # Include messages from Demon's Souls. demons = [] +# Include messages from the entire Dark Souls series. +darksouls = ["ds1", "ds2", "ds3"] # Include messages from Dark Souls 1. ds1 = [] # Include messages from Dark Souls 2. @@ -47,6 +49,8 @@ ds3 = [] bloodborne = [] # Include messages from Sekiro. sekiro = [] +# Include messages from Elden Ring. +eldenring = [] # Include all available message sets. -all-sets = ["ds1", "ds2", "ds3", "bloodborne", "demons", "sekiro"] +all-sets = ["darksouls", "bloodborne", "demons", "sekiro", "eldenring"] diff --git a/README.md b/README.md index d587430..5158b3e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ![docs.rs](https://docs.rs/dsmsg/badge.svg?style=for-the-badge) ](https://docs.rs/dsmsg) -##### Random generator for online messages from Dark Souls, Demon's Souls, Bloodborne, and Sekiro. +##### Random generator for online messages from Dark Souls, Demon's Souls, Bloodborne, Sekiro, and Elden Ring. Generates messages in the format of one of any game in the series, chosen randomly. Messages from the more recent titles may have a second part, in which case the two parts will be joined by a conjunction. @@ -39,7 +39,7 @@ cargo install dsmsg --features "newline" ## Optional Message Sets -Messages from Bloodborne, Demon's Souls, and Sekiro are also available via compile options. To enable output from all available message groups: +Messages from Bloodborne, Demon's Souls, Sekiro, and Elden Ring are also available via compile options. To enable output from all available message groups: ``` cargo install dsmsg --features "all-sets" @@ -58,6 +58,7 @@ This will first **disable** all three Dark Souls message groups (including `ds3` - `ds2` - `ds3` - `sekiro` +- `eldenring` --- diff --git a/src/er1/data.rs b/src/er1/data.rs new file mode 100644 index 0000000..65d588e --- /dev/null +++ b/src/er1/data.rs @@ -0,0 +1,454 @@ +// TODO: Decide whether to replicate typos from in-game conjunctions. They may +// be patched and corrected. + +/// Templates: Base strings, into which nouns can be inserted. +pub const TEMPLATES: &[&str] = &[ + "\x1F ahead", + "No \x1F ahead", + "\x1F required ahead", + "Be wary of \x1F", + "Try \x1F", + "Likely \x1F", + "First off, \x1F", + "Seek \x1F", + "Still no \x1F...", + "Why is it always \x1F?", + "If only I had a \x1F...", + "Didn't expect \x1F...", + "Visions of \x1F...", + "Could this be a \x1F?", + "Time for \x1F", + "\x1F, O \x1F", + "Behold, \x1F!", + "Offer \x1F", + "Huh. It's a \x1F...", + "Praise the \x1F!", + "Let there be \x1F", + "Ahh, \x1F...", + "\x1F", + "\x1F!", + "\x1F?", + "\x1F...", +]; + +/// Conjunctions: Phrases which can be used to combine two Templates. +#[cfg(not(feature = "newline"))] +pub const CONJUNCTIONS: &[&str] = &[ + " and then ", + " or ", + // " or", // Typo exists in game. + " but ", + " therefore ", + " in short ", + // " in short", // Typo exists in game. + " except ", + // " except", // Typo exists in game. + " by the way ", + " so to speak ", + " all the more ", + ", ", +]; + +/// Conjunctions: Phrases which can be used to combine two Templates, onto +/// multiple lines. +#[cfg(feature = "newline")] +pub const CONJUNCTIONS: &[&str] = &[ + "\nand then ", + "\nor ", + // "\nor", // Typo exists in game. + "\nbut ", + "\ntherefore ", + "\nin short ", + // "\nin short", // Typo exists in game. + "\nexcept ", + // "\nexcept", // Typo exists in game. + "\nby the way ", + "\nso to speak ", + "\nall the more ", + ",\n", +]; + +/// Words: Nouns, tactics, concepts, and anything else which can be inserted +/// into a Template to form a Message. +pub const WORDS: &[&str] = &[ + // Enemies + "enemy", + "weak foe", + "strong foe", + "monster", + "dragon", + "boss", + "sentry", + "group", + "pack", + "decoy", + "undead", + "soldier", + "knight", + "cavalier", + "archer", + "sniper", + "mage", + "ordnance", + "monarch", + "lord", + "demi-human", + "outsider", + "giant", + "horse", + "dog", + "wolf", + "rat", + "beast", + "bird", + "raptor", + "snake", + "crab", + "prawn", + "octopus", + "bug", + "scarab", + "slug", + "wraith", + "skeleton", + "monstrosity", + "ill-omened creature", + // People + "Tarnished", + "warrior", + "swordfighter", + "knight", + "samurai", + "sorcerer", + "cleric", + "sage", + "merchant", + "teacher", + "master", + "friend", + "lover", + "old dear", + "old codger", + "angel", + "fat coinpurse", + "pauper", + "good sort", + "wicked sort", + "plump sort", + "skinny sort", + "lovable sort", + "pathetic sort", + "strange sort", + "nimble sort", + "laggardly sort", + "invisible sort", + "unfathomable sort", + "giant sort", + "sinner", + "thief", + "liar", + "dastard", + "traitor", + "pair", + "trio", + "noble", + "aristocrat", + "hero", + "champion", + "monarch", + "lord", + "god", + // Things + "item", + "necessary item", + "precious item", + "something", + "something incredible", + "treasure chest", + "corpse", + "coffin", + "trap", + "armament", + "shield", + "bow", + "projectile weapon", + "armor", + "talisman", + "skill", + "sorcery", + "incantation", + "map", + "material", + "flower", + "grass", + "tree", + "fruit", + "seed", + "mushroom", + "tear", + "crystal", + "butterfly", + "bug", + "dung", + "grace", + "door", + "key", + "ladder", + "lever", + "lift", + "spiritspring", + "sending gate", + "stone astrolabe", + "Birdseye Telescope", + "message", + "bloodstain", + "Erdtree", + "Elden Ring", + // Battle Tactics + "close-quarters battle", + "ranged battle", + "horseback battle", + "luring out", + "defeating one-by-one", + "taking on all at once", + "rushing in", + "stealth", + "mimicry", + "confusion", + "pursuit", + "fleeing", + "summoning", + "circling around", + "jumping off", + "dashing through", + "brief respite", + // Action + "attacking", + "jump attack", + "running attack", + "critical hit", + "two-handing", + "blocking", + "parrying", + "guard counter", + "sorcery", + "incantation", + "skill", + // "summoning", // Duplicate. + "throwing", + "healing", + "running", + "rolling", + "backstepping", + "jumping", + "crouching", + "target lock", + "item crafting", + "gesturing", + // Situations + "morning", + "noon", + "evening", + "night", + "clear sky", + "overcast", + "rain", + "storm", + "mist", + "snow", + "patrolling", + "procession", + "crowd", + "surprise attack", + "ambush", + "pincer attack", + "beating to a pulp", + "battle", + "reinforcements", + "ritual", + "explosion", + "high spot", + "defensible spot", + "climbable spot", + "crossable spot", + "bright spot", + "dark spot", + "open area", + "cramped area", + "hiding place", + "sniping spot", + "recon spot", + "safety", + "danger", + "gorgeous view", + "detour", + "hidden path", + "secret passage", + "shortcut", + "dead end", + "looking away", + "unnoticed", + "out of stamina", + // Places + "high road", + "checkpoint", + "bridge", + "castle", + "fort", + "city", + "ruins", + "church", + "tower", + "camp site", + "house", + "cemetary", + "underground tomb", + "tunnel", + "cave", + "evergaol", + "great tree", + "cellar", + "surface", + "underground", + "forest", + "river", + "lake", + "bog", + "mountain", + "valley", + "cliff", + "waterside", + "nest", + "hole", + // Directions + "east", + "west", + "south", + "north", + "ahead", + "behind", + "left", + "right", + "center", + "up", + "down", + "edge", + // Body Parts + "head", + "stomach", + "back", + "arms", + "legs", + "rump", + "tail", + "core", + "fingers", + // Affinities + "physical", + "standard", + "striking", + "slashing", + "piercing", + "fire", + "lightning", + "magic", + "holy", + "poison", + "toxic", + "scarlet rot", + "blood loss", + "frost", + "sleep", + "madness", + "death", + // Concepts + "life", + "Death", + "light", + "dark", + "stars", + "fire", + "Order", + "chaos", + "joy", + "wrath", + "suffering", + "sadness", + "comfort", + "bliss", + "misfortune", + "good fortune", + "bad luck", + "hope", + "despair", + "victory", + "defeat", + "research", + "faith", + "abundance", + "rot", + "loyalty", + "injustice", + "secret", + "opportunity", + "pickle", + "clue", + "friendship", + "love", + "bravery", + "vigor", + "fortitude", + "confidence", + "distracted", + "unguarded", + "introspection", + "regret", + "resignation", + "futility", + "on the brink", + "betrayal", + "revenge", + "destruction", + "recklessness", + "calmness", + "vigilance", + "tranquility", + "sound", + "tears", + "sleep", + "depths", + "dregs", + "fear", + "sacrifice", + "ruin", + // Phrases + "good luck", + "look carefully", + "listen carefully", + "think carefully", + "well done", + "I did it!", + "I've failed...", + "here!", + "not here!", + "don't you dare!", + "do it!", + "I can't take this...", + "don't think", + "so lonely...", + "here again...", + "just getting started", + "stay calm", + "keep moving", + "turn back", + "give up", + "don't give up", + "help me...", + "I don't believe it...", + "too high up", + "I want to go home...", + "it's like a dream...", + "seems familiar...", + "beautiful...", + "you don't have the right", +]; diff --git a/src/er1/mod.rs b/src/er1/mod.rs new file mode 100644 index 0000000..75b0bd5 --- /dev/null +++ b/src/er1/mod.rs @@ -0,0 +1,69 @@ +//! Generate Messages from Elden Ring. + +mod data; + +use data::{CONJUNCTIONS, TEMPLATES, WORDS}; +use rand::prelude::{SliceRandom, ThreadRng}; +use std::fmt::{Display, Formatter, Result}; +use super::DsMulti; + + +/// A template, combined with a phrase to be inserted into it. Represents a +/// single complete thought. +struct Segment { main: &'static str, word: &'static str } + +impl Segment { + /// Create a new `Segment`, with a random Template and a random Word. + pub fn random(rng: &mut ThreadRng) -> Self { + Self { + main: TEMPLATES.choose(rng).unwrap(), + word: WORDS.choose(rng).unwrap(), + } + } +} + +impl Display for Segment { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + if self.main == "\x1F" { + self.word.fmt(f) + } else { + self.main.replace('\x1F', self.word).fmt(f) + } + } +} + + +/// A complete Hint Message that could be found in Elden Ring. Consists of +/// either one or two parts. If there are two, there will also be a +/// Conjunction string to join them. +pub struct MessageEr1 { + p1: Segment, + p2: Option<(&'static str, Segment)>, +} + +impl DsMulti for MessageEr1 { + /// Create a `MessageEr1` with two parts. + fn double(rng: &mut ThreadRng) -> Self { + Self { + p1: Segment::random(rng), + p2: Some((CONJUNCTIONS.choose(rng).unwrap(), Segment::random(rng))), + } + } + + /// Create a `MessageEr1` with one part. + fn single(rng: &mut ThreadRng) -> Self { + Self { + p1: Segment::random(rng), + p2: None, + } + } +} + +impl Display for MessageEr1 { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match &self.p2 { + Some((conj, second)) => write!(f, "{}{}{}", &self.p1, conj, second), + None => self.p1.fmt(f), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 8055cb6..0cd1027 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,11 +4,12 @@ #[cfg(not(any( feature = "bloodborne", feature = "demons", feature = "ds1", feature = "ds2", feature = "ds3", + feature = "eldenring", feature = "sekiro", )))] compile_error!("Cannot compile without any Message Sets enabled. Enable \ at least one of the following Features:\ -\n- bloodborne\n- demons\n- ds1\n- ds2\n- ds3\n- sekiro"); +\n- bloodborne\n- demons\n- ds1\n- ds2\n- ds3\n- eldenring\n- sekiro"); #[cfg(feature = "ds2")] #[macro_use] @@ -29,6 +30,8 @@ mod ds2; mod ds3; #[cfg(feature = "sekiro")] mod sek; +#[cfg(feature = "eldenring")] +mod er1; #[cfg(feature = "bloodborne")] pub use bb::MessageBB; @@ -42,6 +45,8 @@ pub use ds2::MessageDkS2; pub use ds3::MessageDkS3; #[cfg(feature = "sekiro")] pub use sek::MessageSek; +#[cfg(feature = "eldenring")] +pub use er1::MessageEr1; use rand::prelude::{Rng, SliceRandom, thread_rng, ThreadRng}; use std::fmt::Display; @@ -100,6 +105,7 @@ pub const GENERATORS: &[fn(&mut ThreadRng) -> Box] = &[ #[cfg(feature = "ds2")] |r| Box::new(MessageDkS2::random(r)), #[cfg(feature = "ds3")] |r| Box::new(MessageDkS3::random(r)), #[cfg(feature = "sekiro")] |r| Box::new(MessageSek::random(r)), + #[cfg(feature = "eldenring")] |r| Box::new(MessageEr1::random(r)), ]; diff --git a/src/main.rs b/src/main.rs index f51d164..e5c86d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,6 +43,11 @@ struct CommandOpts { #[argh(switch)] ds3: bool, + /// generate a message from Elden Ring + #[cfg(feature = "eldenring")] + #[argh(switch)] + er1: bool, + /// generate a message from Sekiro #[cfg(feature = "sekiro")] #[argh(switch)] @@ -58,6 +63,7 @@ impl From for Vec { #[cfg(feature = "ds1")] opt.ds1, #[cfg(feature = "ds2")] opt.ds2, #[cfg(feature = "ds3")] opt.ds3, + #[cfg(feature = "eldenring")] opt.er1, #[cfg(feature = "sekiro")] opt.sek, ] } diff --git a/tests/test.rs b/tests/test.rs index ee1e21f..8a7c0d9 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -77,6 +77,18 @@ fn test_bb() { } +#[cfg(feature = "eldenring")] +#[test] +fn test_er1() { + for i in 1..=ITERS { + println!( + "E-{i:0d$}: {txt}", + i = i, d = DIGIT, txt = MessageEr1::random(&mut thread_rng()), + ); + } +} + + #[cfg(feature = "sekiro")] #[test] fn test_sek() {