diff --git a/Cargo.lock b/Cargo.lock index 6e4774f..bc70071 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,6 @@ dependencies = [ "nom", "once_cell", "ouroboros", - "phf", "rand", "rand_distr", "ring", @@ -1246,33 +1245,9 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros", "phf_shared", ] -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.52", -] - [[package]] name = "phf_shared" version = "0.11.2" diff --git a/blastmud_game/Cargo.toml b/blastmud_game/Cargo.toml index fcffe90..a504f2e 100644 --- a/blastmud_game/Cargo.toml +++ b/blastmud_game/Cargo.toml @@ -26,7 +26,6 @@ tokio-stream = "0.1.14" tokio-util = { version = "0.7.10", features = ["codec"] } uuid = { version = "1.7.0", features = ["v4", "serde", "rng"] } serde_json = "1.0.114" -phf = { version = "0.11.2", features = ["macros"] } async-trait = "0.1.77" nom = "7.1.3" ouroboros = "0.18.3" diff --git a/blastmud_game/src/message_handler/user_commands.rs b/blastmud_game/src/message_handler/user_commands.rs index cd2edf9..4f44a06 100644 --- a/blastmud_game/src/message_handler/user_commands.rs +++ b/blastmud_game/src/message_handler/user_commands.rs @@ -14,7 +14,7 @@ use async_trait::async_trait; use log::warn; use mockall_double::double; use once_cell::sync::OnceCell; -use phf::phf_map; +use std::collections::BTreeMap; use std::sync::Arc; mod agree; @@ -124,195 +124,195 @@ pub fn user_error(msg: String) -> UResult { /* Verb registries list types of commands available in different circumstances. */ pub type UserVerbRef = &'static (dyn UserVerb + Sync + Send); -type UserVerbRegistry = phf::Map<&'static str, UserVerbRef>; -static ALWAYS_AVAILABLE_COMMANDS: UserVerbRegistry = phf_map! { - "" => ignore::VERB, - "help" => help::VERB, - "quit" => quit::VERB, -}; +pub fn always_available_commands() -> &'static BTreeMap<&'static str, UserVerbRef> { + static V: OnceCell> = OnceCell::new(); + V.get_or_init(|| { + vec![ + ("", ignore::VERB), + ("help", help::VERB), + ("quit", quit::VERB), + ] + .into_iter() + .collect() + }) +} -static UNREGISTERED_COMMANDS: UserVerbRegistry = phf_map! { - "agree" => agree::VERB, - "connect" => login::VERB, - "login" => login::VERB, - "register" => register::VERB, -}; +pub fn unregistered_commands() -> &'static BTreeMap<&'static str, UserVerbRef> { + static V: OnceCell> = OnceCell::new(); + V.get_or_init(|| { + vec![ + ("agree", agree::VERB), + ("connect", login::VERB), + ("login", login::VERB), + ("register", register::VERB), + ] + .into_iter() + .collect() + }) +} -static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! { - // Movement comments first: - "north" => movement::VERB, - "n" => movement::VERB, - "northeast" => movement::VERB, - "ne" => movement::VERB, - "east" => movement::VERB, - "e" => movement::VERB, - "southeast" => movement::VERB, - "se" => movement::VERB, - "south" => movement::VERB, - "s" => movement::VERB, - "southwest" => movement::VERB, - "sw" => movement::VERB, - "west" => movement::VERB, - "w" => movement::VERB, - "northwest" => movement::VERB, - "nw" => movement::VERB, - "up" => movement::VERB, - "down" => movement::VERB, - "in" => movement::VERB, +pub fn registered_commands() -> &'static BTreeMap<&'static str, UserVerbRef> { + static V: OnceCell> = OnceCell::new(); + V.get_or_init(|| { + vec![ + // Movement comments first: + ("north", movement::VERB), + ("n", movement::VERB), + ("northeast", movement::VERB), + ("ne", movement::VERB), + ("east", movement::VERB), + ("e", movement::VERB), + ("southeast", movement::VERB), + ("se", movement::VERB), + ("south", movement::VERB), + ("s", movement::VERB), + ("southwest", movement::VERB), + ("sw", movement::VERB), + ("west", movement::VERB), + ("w", movement::VERB), + ("northwest", movement::VERB), + ("nw", movement::VERB), + ("up", movement::VERB), + ("down", movement::VERB), + ("in", movement::VERB), + // Other commands (alphabetical except aliases grouped): + ("allow", allow::VERB), + ("disallow", allow::VERB), + ("attack", attack::VERB), + ("butcher", butcher::VERB), + ("buy", buy::VERB), + ("c", c::VERB), + ("close", close::VERB), + ("corp", corp::VERB), + ("cut", cut::VERB), + ("delete", delete::VERB), + ("drink", drink::VERB), + ("drop", drop::VERB), + ("eat", eat::VERB), + ("fill", fill::VERB), + ("fire", fire::VERB), + ("follow", follow::VERB), + ("unfollow", follow::VERB), + ("gear", gear::VERB), + ("get", get::VERB), + ("hack", hack::VERB), + ("hire", hire::VERB), + ("improv", improvise::VERB), + ("improvise", improvise::VERB), + ("improvize", improvise::VERB), + ("install", install::VERB), + ("inventory", inventory::VERB), + ("inv", inventory::VERB), + ("i", inventory::VERB), + ("kill", attack::VERB), + ("k", attack::VERB), + ("describe", describe::VERB), + ("l", look::VERB), + ("look", look::VERB), + ("read", look::VERB), + ("examine", look::VERB), + ("ex", look::VERB), + ("feint", feint::VERB), + ("list", list::VERB), + ("load", load::VERB), + ("unload", load::VERB), + ("lm", map::VERB), + ("lmap", map::VERB), + ("gm", map::VERB), + ("gmap", map::VERB), + ("make", make::VERB), + ("open", open::VERB), + ("p", page::VERB), + ("page", page::VERB), + ("pg", page::VERB), + ("rep", page::VERB), + ("repl", page::VERB), + ("reply", page::VERB), + ("pay", pay::VERB), + ("plug", plug::VERB), + ("pow", pow::VERB), + ("power", pow::VERB), + ("powerattack", pow::VERB), + ("put", put::VERB), + ("recline", recline::VERB), + ("remove", remove::VERB), + ("rent", rent::VERB), + ("report", report::VERB), + (("\'", say::VERB)), + ("say", say::VERB), + ("scan", scan::VERB), + ("scavenge", scavenge::VERB), + ("search", scavenge::VERB), + ("sc", score::VERB), + ("score", score::VERB), + ("sell", sell::VERB), + ("share", share::VERB), + ("serious", share::VERB), + ("amicable", share::VERB), + ("joking", share::VERB), + ("parody", share::VERB), + ("play", share::VERB), + ("thoughts", share::VERB), + ("exploring", share::VERB), + ("roaming", share::VERB), + ("fishing", share::VERB), + ("good", share::VERB), + ("surviving", share::VERB), + ("slow", share::VERB), + ("normal", share::VERB), + ("intense", share::VERB), + ("sign", sign::VERB), + ("sit", sit::VERB), + ("stand", stand::VERB), + ("st", status::VERB), + ("stat", status::VERB), + ("stats", status::VERB), + ("status", status::VERB), + ("stop", stop::VERB), + ("turn", turn::VERB), + ("uninstall", uninstall::VERB), + ("use", use_cmd::VERB), + ("vacate", vacate::VERB), + ("-", whisper::VERB), + ("whisper", whisper::VERB), + ("tell", whisper::VERB), + ("wear", wear::VERB), + ("wield", wield::VERB), + ("who", who::VERB), + ("write", write::VERB), + ] + .into_iter() + .collect() + }) +} - // Other commands (alphabetical except aliases grouped): - "allow" => allow::VERB, - "disallow" => allow::VERB, - - "attack" => attack::VERB, - "butcher" => butcher::VERB, - "buy" => buy::VERB, - "c" => c::VERB, - "close" => close::VERB, - "corp" => corp::VERB, - "cut" => cut::VERB, - "delete" => delete::VERB, - "drink" => drink::VERB, - "drop" => drop::VERB, - "eat" => eat::VERB, - "fill" => fill::VERB, - "fire" => fire::VERB, - - "follow" => follow::VERB, - "unfollow" => follow::VERB, - - "gear" => gear::VERB, - "get" => get::VERB, - "hack" => hack::VERB, - "hire" => hire::VERB, - - "improv" => improvise::VERB, - "improvise" => improvise::VERB, - "improvize" => improvise::VERB, - - "install" => install::VERB, - "inventory" => inventory::VERB, - "inv" => inventory::VERB, - "i" => inventory::VERB, - "kill" => attack::VERB, - "k" => attack::VERB, - - "describe" => describe::VERB, - "l" => look::VERB, - "look" => look::VERB, - "read" => look::VERB, - "examine" => look::VERB, - "ex" => look::VERB, - - "feint" => feint::VERB, - "list" => list::VERB, - - "load" => load::VERB, - "unload" => load::VERB, - - "lm" => map::VERB, - "lmap" => map::VERB, - "gm" => map::VERB, - "gmap" => map::VERB, - - "make" => make::VERB, - "open" => open::VERB, - - "p" => page::VERB, - "page" => page::VERB, - "pg" => page::VERB, - "rep" => page::VERB, - "repl" => page::VERB, - "reply" => page::VERB, - - "pay" => pay::VERB, - "plug" => plug::VERB, - - "pow" => pow::VERB, - "power" => pow::VERB, - "powerattack" => pow::VERB, - - "put" => put::VERB, - - "recline" => recline::VERB, - "remove" => remove::VERB, - "rent" => rent::VERB, - "report" => report::VERB, - - "\'" => say::VERB, - "say" => say::VERB, - - "scan" => scan::VERB, - - "scavenge" => scavenge::VERB, - "search" => scavenge::VERB, - - "sc" => score::VERB, - "score" => score::VERB, - - "sell" => sell::VERB, - - "share" => share::VERB, - "serious" => share::VERB, - "amicable" => share::VERB, - "joking" => share::VERB, - "parody" => share::VERB, - "play" => share::VERB, - "thoughts" => share::VERB, - "exploring" => share::VERB, - "roaming" => share::VERB, - "fishing" => share::VERB, - "good" => share::VERB, - "surviving" => share::VERB, - "slow" => share::VERB, - "normal" => share::VERB, - "intense" => share::VERB, - - "sign" => sign::VERB, - "sit" => sit::VERB, - "stand" => stand::VERB, - - "st" => status::VERB, - "stat" => status::VERB, - "stats" => status::VERB, - "status" => status::VERB, - - "stop" => stop::VERB, - "turn" => turn::VERB, - "uninstall" => uninstall::VERB, - "use" => use_cmd::VERB, - "vacate" => vacate::VERB, - - "-" => whisper::VERB, - "whisper" => whisper::VERB, - "tell" => whisper::VERB, - - "wear" => wear::VERB, - "wield" => wield::VERB, - "who" => who::VERB, - "write" => write::VERB, -}; - -static STAFF_COMMANDS: UserVerbRegistry = phf_map! { - "staff_invincible" => invincible::VERB, - "staff_reset_spawns" => reset_spawns::VERB, - "staff_show" => staff_show::VERB, -}; +pub fn staff_commands() -> &'static BTreeMap<&'static str, UserVerbRef> { + static V: OnceCell> = OnceCell::new(); + V.get_or_init(|| { + vec![ + ("staff_invincible", invincible::VERB), + ("staff_reset_spawns", reset_spawns::VERB), + ("staff_show", staff_show::VERB), + ] + .into_iter() + .collect() + }) +} fn resolve_handler(ctx: &VerbContext, cmd: &str) -> Option<&'static UserVerbRef> { - let mut result = ALWAYS_AVAILABLE_COMMANDS.get(cmd); + let mut result = always_available_commands().get(cmd); match &ctx.user_dat { None => { - result = result.or_else(|| UNREGISTERED_COMMANDS.get(cmd)); + result = result.or_else(|| unregistered_commands().get(cmd)); } Some(user_dat) => { if user_dat.terms.terms_complete { - result = result.or_else(|| REGISTERED_COMMANDS.get(cmd)); + result = result.or_else(|| registered_commands().get(cmd)); if user_dat.user_flags.contains(&UserFlag::Staff) { - result = result.or_else(|| STAFF_COMMANDS.get(cmd)); + result = result.or_else(|| staff_commands().get(cmd)); } } else if cmd == "agree" { result = Some(&agree::VERB); diff --git a/blastmud_game/src/message_handler/user_commands/help.rs b/blastmud_game/src/message_handler/user_commands/help.rs index 8fc0c40..2f107b2 100644 --- a/blastmud_game/src/message_handler/user_commands/help.rs +++ b/blastmud_game/src/message_handler/user_commands/help.rs @@ -65,6 +65,10 @@ pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef; #[cfg(test)] mod tests { + use std::collections::BTreeSet; + + use crate::message_handler::user_commands::registered_commands; + use super::*; #[test] @@ -81,4 +85,18 @@ mod tests { fn always_help_ok() { always_help_pages(); } + + #[test] + fn all_registered_user_commands_documented() { + let help_keys: BTreeSet = + registered_help_pages().keys().map(|k| k.clone()).collect(); + let cmds: BTreeSet = registered_commands() + .keys() + .map(|k| k.to_string()) + .collect(); + assert_eq!( + cmds.difference(&help_keys).collect::>(), + BTreeSet::<&String>::new() + ); + } } diff --git a/blastmud_game/src/message_handler/user_commands/help/registered.yaml b/blastmud_game/src/message_handler/user_commands/help/registered.yaml index 293e05e..f7a4581 100644 --- a/blastmud_game/src/message_handler/user_commands/help/registered.yaml +++ b/blastmud_game/src/message_handler/user_commands/help/registered.yaml @@ -26,12 +26,37 @@ newbie: |- Also try the map commands - lmap for a local map including exits, and gmap for a giant map to let you see the broader context. -movement: |- +movement: &movement |- Once you know what direction to move, you can type the direction, using either the full name of the direction (e.g. northeast or south, or a short form (n, e, s, w, ne, nw, se, sw, up, down). -look: Try look or l to look at the current room. Follow it with the name of an exit to look at an adjacent room. Or name an object or player in the room to look at that. -combat: >- +n: *movement +north: *movement +ne: *movement +northeast: *movement +e: *movement +east: *movement +se: *movement +southeast: *movement +s: *movement +south: *movement +sw: *movement +southwest: *movement +w: *movement +west: *movement +nw: *movement +northwest: *movement +up: *movement +down: *movement +in: *movement +look: &look Try look, l, examine or ex to look at the current room. Follow it with the name of an exit to look at an adjacent room. Or name an object or player in the room to look at that. +l: *look +ex: *look +read: *look +examine: *look +describe: Use describe me as description to set how you appear when people look at you. +who: Use who to see what players are online. +combat: &combat >- Type kill character or k character to attack a character. If their health points hits zero, they die. If your health points hit zero, you die. Note that characters can reclone so death isn't fully permanent (see help death). @@ -46,6 +71,20 @@ combat: >- Remember, you can always (at least while you are not dead) try to run away from combat by just by using movement commands (see help movement - but if your dodge skill isn't high enough, it might fail. +k: *combat +kill: *combat +attack: *combat +pow: &pow >- + Type powerattack or pow while you are in combat to make your + next move a powerattack. For weapons where it is possible, a powerattack takes longer + to do, but hits harder, and has a higher chance of inflicting critical damage on the + enemy. +power: *pow +powerattack: *pow +feint: >- + Use feint while you are in combat to make your next move a feint. This + will pit your intelligence against your opponent, and confuse them if you win. But + beware, if they win, you might end up confused! death: >- In Blastmud, you can die if your health points reach zero. While you are dead, you can't move or talk! Unless someone quickly comes and uses a defibrilator on you, your current @@ -59,40 +98,55 @@ skills: >- and some from your raws. Raw skill is how much you have improved by learning the skill as you play the game. Your raw skill caps out at 15 per skill, and adds on to the contribution from your stats, and any temporary buffs or debuffs caused by your character's state. -information: |- +information: &info |- Commands to examine the world: look (or l) to look around - follow it with an exit or a character / item name for detail on that. lmap - get a map showing exits and places. + gmap - see a larger (giant) map. +lmap: *info +lm: *info +gmap: *info +gm: *info talk: &talk |- Use: 'message to send message to the room. -user message to whisper to someone. p user message to page someone on your wristpad. - reply message to page back the last person to page you. + reply message (or rep message) to page back the last person to page you. say: *talk whisper: *talk page: *talk reply: *talk +"'": *talk +"-": *talk +rep: *talk +repl: *talk +tell: *talk +p: *talk +pg: *talk possessions: &possessions |- Use: get item to pick something up from the ground. drop item to drop something from your inventory. inv to see what you are holding. buy item to buy something from the shop you are in. + sell item to sell something to the shop you are in. list to see the price list for the stop. wield to hold a weapon in your inventory for use when you attack. gear to see what you are wearing, and how much protection it offers. Hint: get and drop support an item name, but you can also prefix it with a number - e.g. get 2 whip. Instead of a number, you can use all. You can also omit the item name to match any possession, e.g. drop all will drop everything you have. get: *possessions drop: *possessions +i: *possessions inv: *possessions inventory: *possessions buy: *possessions +sell: *possessions list: *possessions wield: *possessions gear: *possessions -allow: |- +allow: &consent |- allow is the corner-stone of Blastmud's consent system. Consents in Blastmud let you choose how you want to play with other players (it only affects players, not NPCs). There are 5 types of consent: fight (for hostile actions like attack or pick), medicine (for medical actions, including those that might crit fail and do harm), gifts (lets them give you things), visit (lets them on to a tile owned by you legally), and share (lets them local share knowledge with you, making both parties stronger). To allow, as an individual, use the syntax allow type from player options @@ -113,6 +167,8 @@ allow: |- disallow action from player Consent for fight can be revoked similarly if the consent used the allow revoke option. Otherwise, attempting to revoke informs the other player, and it is revoked when they also issue a disallow command. +consent: *consent +disallow: *consent corp: |- corp is the entry point to commands related to corps. It supports the following subcommands: corp hire username into corpname @@ -193,6 +249,10 @@ corp: |- death - Deaths of players in the corp. consent - Changes to corp consents (war declarations). "corp order": "corp order corpname as number Set the position of the corp in your list." +c: >- + c sends a message to one of your corporations. Use it as c message to send message to your + first corp (use corp order to choose which corp is first). Or explicitly name a corp like this: + corp @corpname message "install": "install item on door to direction Installs hardware such as a lock on a door." "uninstall": "uninstall item from door to direction Removes installed hardware such as a lock on a door." "gear": "gear See equipment you have on, and what protection it offers you." @@ -210,7 +270,7 @@ put: |- You can put something in a container using a command like put thing in container. See also help get to learn how to get them back out. get: |- You can get something out of a container using a command like get thing from container. -sharing: |- +sharing: &sharing |- Sharing lets you share knowledge with another player. Because knowledge is power, sharing will increase the stats of both players for a little while (10 minutes); the better a job you do at sharing, the greater the impact on your stats (up to a maximum of two points of increase to every stat). If you share twice, you will forget what you from the first sharing, and the more recent one will affect your stats. Sharing is therefore a great way to collaborate with another player to temporarily become more capable. However, sharing effectively takes great skill [both player skill, and share skill in the game]. Type share knowledge with player to start a sharing session. You will immediately begin sharing, and if you type share status, you'll start to see growth in certain interest types. Sharing stops when the pair sharing get to 100% on any interest level and get bored - so you'll want to change topics to avoid that. To get the best score, try to get all interest levels balanced to just below the maximum before you go over on any. However, there are a couple of catches: firstly, changing anything about the conversation is going to be awkward (might fail) if you try too soon after the last change - the higher your Share skill, the faster you can change with a high chance of success. Secondly, to discuss some topics, you need to switch to an appropriate conversation style (amicable, playful, or serious) for the topic first - which could take even longer if your skill level is low. It is a lot easier if yyou work with your conversational partner - they might be able to change earlier. @@ -218,3 +278,123 @@ sharing: |- Throughout the conversation, the game will tell you what styles you can change to, and what topics you can change to under the current style. Just type the name of the topic or style to switch. Each topic has a different rate at which it increases or decreases different interest types. If you find the pace of the conversation too fast or slow, you can also change the pace with share slowly, share normally or share quickly. Keep in mind changing the pace counts as a change, like changing topics - but once you have set the pace, it scales how fast conversational interest levels grow. +amicable: *sharing +exploring: *sharing +fishing: *sharing +good: *sharing +joking: *sharing +parody: *sharing +play: *sharing +serious: *sharing +share: *sharing +slow: *sharing +normal: *sharing +intense: *sharing +surviving: *sharing +thoughts: *sharing +roaming: *sharing +butcher: &butcher >- + Use the butcher command to cut everything possible out of a corpse. + Alternatively, you can cut one part from a corpse by doing something like: + cut steak from dead dog + This typically requires craft skill. +cut: *butcher +hire: &hiring >- + Use hire npc to hire an NPC (e.g. a Roboporter) into your personal employment. + Use fire npc to fire them and terminate their employment. + Please note that these commands hire them personally. See also corp hire + and corp fire to learn about hiring into corps. +fire: *hiring +follow: &follow >- + Use follow player to start following a player around. + Use unfollow to stop following. +unfollow: *follow +open: &doors >- + Use open direction to open a door (and attempting to unlock). + Doors will auto-open just by moving through them, but opening lets you look first, + or let someone else in. + Use close direction to close the door in that direction (and lock if applicable). +doors: *doors +close: *doors +hack: >- + If you've found a room where you can install a wristpad hack, use + hack hackname to install that hack on your wristpad. + The room description will generally tell you what hackname to use. +improvise: &improvise >- + If you don't have a crafting bench or instructions, you might still be able to make something. + Try improv with item to explore what you can make with item. + Once you know what to make, try improv output from item1, item2, ... + This will let you use as many items as you need. +improv: *improvise +improvize: *improvise +make: &craft >- + To craft, you generally need some form of instructions, a craft bench of some form (which might be a stove, specialised workbench, etc...), and some ingredients. + To start crafting, firstly put the instructions (or the entire book) into the craft bench. See help put for help on putting. Likewise put the ingredients in the bench + Then use make thing on bench, where thing is the thing the instructions describe how to + make. The thing will end up in the craft bench. Pay attention to make sure you get it out, and not the recipe. +craft: *craft +crafting: *craft +load: &loading >- + To load an item onto an NPC such as a roboporter (so it will carry your stuff around for you), try: + load item onto npc + You can unload with unload item from npc +unload: *loading +pay: >- + Use pay $amount [from corp] to recipient + Leave off the from corp part if it is from you. + Recipient can be a corp or a user. + You must have finance privileges in the corp you are paying from. +plug: >- + Use plug in equipment to plug something electrical in to charge. + It needs to be on the ground (not in inventory), and you need to do it where there is power. +recline: &posture >- + Use sit to sit down. + Use recline to recline (lie down). + Use stand to stand up. +sit: *posture +stand: *posture +stand up: *posture +rent: &rent >- + Renting property gives you somewhere to stay, or gives your corp an HQ. + To rent, go to the place where property is on offer (usually the lobby), and use + rent roomtype + To rent for a corp, use: + rent roomtype for corpname + To stop renting, use: + vacate roomtype [for corpname] +vacate: *rent +renting: *rent +property: *rent +report abuse: &report + If someone breaks the rules (for example, by posting content that isn't allowed, or by harassing another user), + immediately type report abuse to record the last 80 things the MUD sent to you, and give you a report + ID. Once you have a report ID, send it to staff@blastmud.org with a description of the problem. We'll be able to + look up the report ID to see what you are referring to. +report: *report +abuse: *report +harassment: *report +scan: >- + Use the scan command to scan a QR code found in the game with your wristpad. +score: &score >- + Use the score command to see your stats, skills, experience, and hacks. +sc: *score +scavenge: &scavenge >- + Use the scavenge or search command to look for hidden treasure (or junk) at the current location. +search: *scavenge +sign: Use sign thing to sign a contract. +status: &stats >- + Use stats to see your character's basic stats and credits. +st: *stats +stat: *stats +stats: *stats +stop: Use stop to stop any queued actions, and reverse the current one if possible. +turn: &turn >- + Use turn on thing to turn something on. + Use turn off thing to turn something off. +use: Use use item [on character] to use something on someone (optional). +wear: &clothes >- + Use wear clothing to wear something. + Use remove clothing to remove some clothing. + Clothing must be removed in the opposite order it is layered on. +remove: *clothes +write: Use write message on item to write on something. diff --git a/blastmud_game/src/static_content/room.rs b/blastmud_game/src/static_content/room.rs index 0f61aca..763102e 100644 --- a/blastmud_game/src/static_content/room.rs +++ b/blastmud_game/src/static_content/room.rs @@ -890,6 +890,7 @@ pub async fn check_for_enter_action(ctx: &mut QueuedCommandContext<'_>) -> UResu mod test { use super::super::scavtable::scavtable_map; use super::*; + use ansi::ansi; use itertools::Itertools; #[test] @@ -1002,4 +1003,16 @@ mod test { .collect::>(); assert_eq!(unresolved_exits, Vec::::new()); } + + #[test] + fn rooms_with_stock_list_have_help() { + let stock_rooms_without_help: Vec<&'static str> = room_list() + .iter() + .filter(|r| { + !r.stock_list.is_empty() && !r.description.contains(ansi!("list")) + }) + .map(|r| r.code.as_str()) + .collect(); + assert_eq!(stock_rooms_without_help, Vec::<&'static str>::new()); + } } diff --git a/blastmud_game/src/static_content/room/melbs.yaml b/blastmud_game/src/static_content/room/melbs.yaml index 49684b6..a15ef25 100644 --- a/blastmud_game/src/static_content/room/melbs.yaml +++ b/blastmud_game/src/static_content/room/melbs.yaml @@ -78,7 +78,7 @@ x: 2 y: -2 z: 0 - description: A dated looking eatery that looks like it has existed long before the collapse. Inside the diner is speckled white linoleum floors that run up to the walls. The smell of bacon grease pervades the air, reminding you of the purpose of this venue with every breath you take. Tables of various sizes are set out for diners to sit at, and at the back is a kitchen. The kitchen whirs with stainless steel exhaust pans, as cooks appear to do nothing but frying. Separating the kitchen from the dining area, and running the width of the restaurant, runs a counter. Hanging signs convey a menu in hand-painted black on white. A middle-aged woman sits behind the counter, looking eager to take your order. + description: A dated looking eatery that looks like it has existed long before the collapse. Inside the diner is speckled white linoleum floors that run up to the walls. The smell of bacon grease pervades the air, reminding you of the purpose of this venue with every breath you take. Tables of various sizes are set out for diners to sit at, and at the back is a kitchen. The kitchen whirs with stainless steel exhaust pans, as cooks appear to do nothing but frying. Separating the kitchen from the dining area, and running the width of the restaurant, runs a counter. Hanging signs convey a menu in hand-painted black on white. A middle-aged woman sits behind the counter, looking eager to take your order. [Try list to see what is for sale here] exits: - direction: west should_caption: false @@ -330,7 +330,7 @@ A warm and inviting atmosphere surrounds you as you explore the meticulously arranged space. Rich, reclaimed hardwood floors stretch out beneath your feet, bearing the echoes of countless stories from the past. Worn yet sturdy, the wooden furniture exudes an enduring charm that captivates the eye, while the kitchen and bathroom sections of the store harbour more modern furniture. - A seasoned storekeeper stands ready to assist shoppers + A seasoned storekeeper stands ready to assist shoppers [Try list to see what is for sale here] exits: - direction: west stock_list: @@ -1511,7 +1511,7 @@ It smells slightly acrid here. - Behind a counter, a serious looking tall man clad in a labcoat stands behind a counter, waiting patiently for you to select your equipment and pay him + Behind a counter, a serious looking tall man clad in a labcoat stands behind a counter, waiting patiently for you to select your equipment and pay him [Try list to see what is for sale here] exits: - direction: east stock_list: @@ -1533,7 +1533,7 @@ The inhabitants of this forsaken land gather here, seeking solace and hope within the forgotten stories and practical guides that line the shelves. - The Dusty Pages stands as a beacon of intellectual survival, a sanctuary where survivors can momentarily escape the harsh realities of their existence + The Dusty Pages stands as a beacon of intellectual survival, a sanctuary where survivors can momentarily escape the harsh realities of their existence [Try list to see what is for sale here] exits: - direction: west stock_list: @@ -1737,7 +1737,7 @@ code: oorans_testing name: OORANS Testing Centre description: |- - A room, painted completely white. The room has rows of desks, each with a pen attached by a string. Stern looking invigilators pace up and down the room ensuring that no one cheats on the test. At the front, it looks like you can buy test papers from the head invigilator to sit the test for a permit to access fallout contaminated areas + A room, painted completely white. The room has rows of desks, each with a pen attached by a string. Stern looking invigilators pace up and down the room ensuring that no one cheats on the test. At the front, it looks like you can buy test papers from the head invigilator to sit the test for a permit to access fallout contaminated areas. [Try list to see what is for sale here] short: TE grid_coords: x: 1 @@ -1752,7 +1752,7 @@ code: oorans_gift name: OORANS Gift Shop description: |- - A brightly coloured room, each wall a different primary colour. Rows of merchandise hang neatly on racks, while a shop keeper stands near the front, his hands clasped in anticipation of a sale + A brightly coloured room, each wall a different primary colour. Rows of merchandise hang neatly on racks, while a shop keeper stands near the front, his hands clasped in anticipation of a sale. [Try list to see what is for sale here] short: G$ grid_coords: x: 1 @@ -1894,7 +1894,7 @@ x: 3 y: 2 z: 0 - description: A store full of beeping gadgets locked in glass display cabinets, all of which seem to be focused around health and medicine. A tall male technician in a white lab coat stands behind a counter, his eyes following you hoping that you are going to buy something + description: A store full of beeping gadgets locked in glass display cabinets, all of which seem to be focused around health and medicine. A tall male technician in a white lab coat stands behind a counter, his eyes following you hoping that you are going to buy something. [Try list to see what is for sale here] exits: - direction: south stock_list: @@ -1909,7 +1909,7 @@ x: 3 y: 4 z: 0 - description: A shop that looks like it once helped people camp for fun, its clientele now days are probably more focused on just surviving! A weary looking woman with calloused, grease covered hands paces the shop floor, prepared to spring on you and hype up whatever merchandise you look at as the best thing ever + description: A shop that looks like it once helped people camp for fun, its clientele now days are probably more focused on just surviving! A weary looking woman with calloused, grease covered hands paces the shop floor, prepared to spring on you and hype up whatever merchandise you look at as the best thing ever. [Try list to see what is for sale here] exits: - direction: north stock_list: @@ -2382,7 +2382,7 @@ x: 7 y: 8 z: 0 - description: This seems to be some kind of security shop, selling locks from super high-tech to primitive. Behind a counter sits a grizzled old man, who appears eager to sell you something + description: This seems to be some kind of security shop, selling locks from super high-tech to primitive. Behind a counter sits a grizzled old man, who appears eager to sell you something. [Try list to see what is for sale here] exits: - direction: northwest stock_list: diff --git a/blastmud_game/src/static_content/room/melbs_sewers.yaml b/blastmud_game/src/static_content/room/melbs_sewers.yaml index 44a9257..11cf979 100644 --- a/blastmud_game/src/static_content/room/melbs_sewers.yaml +++ b/blastmud_game/src/static_content/room/melbs_sewers.yaml @@ -1024,7 +1024,7 @@ x: 9 y: 1 z: -3 - description: A large room that has been carved into the bedrock, its walls, floor formed of grey stone. A gentle fresh breeze blows in through cracks in the rock. The room is dimly lit by yellow glowing light bulbs, suspended by cables, and apparently powered by cables that snake across the stone ceiling and up through a hole in the rock. Some of the cables snake down to power points on the wall. The room is stacked with unlabelled crates. In the northeast corner of the room, a woman sits in an office chair behind a basic wooden desk. Above her head, afixed to the wall, is a banner that says "Welcome the Josephine's Shop!" + description: A large room that has been carved into the bedrock, its walls, floor formed of grey stone. A gentle fresh breeze blows in through cracks in the rock. The room is dimly lit by yellow glowing light bulbs, suspended by cables, and apparently powered by cables that snake across the stone ceiling and up through a hole in the rock. Some of the cables snake down to power points on the wall. The room is stacked with unlabelled crates. In the northeast corner of the room, a woman sits in an office chair behind a basic wooden desk. Above her head, afixed to the wall, is a banner that says "Welcome the Josephine's Shop!". [Try list to see what is for sale here] has_power: true exits: - direction: south