diff --git a/Cargo.lock b/Cargo.lock
index 6e4774f5..bc70071b 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 fcffe903..a504f2e8 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 cd2edf9d..4f44a06a 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 8fc0c404..2f107b23 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 293e05ea..f7a45813 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