Module: Lich::DragonRealms::DRCI

Defined in:
documented/dragonrealms/commons/common-items.rb

Overview

DragonRealms Common Items - low-level, stateless methods for item manipulation.

DRCI provides the foundational API for getting, wearing, storing, and querying items in the game world. All methods are module-level (stateless) and operate on item nouns or Item objects. This module depends only on DRC (common) and should not depend on higher-level modules like crafting or combat.

Methods are organized by category: Retrieval, Storage, Wearing, Tying, Queries, Existence checks, Counting, Container operations, Trash disposal, Transfers, and Gem Pouch handling. See the module documentation for the full method index.

See Also:

Constant Summary collapse

TRASH_STORAGE =

How to add new trash receptacles https://github.com/elanthia-online/dr-scripts/wiki/Adding-new-trash-receptacles Default trash-receptacle nouns. Players extend this at runtime via the custom_trash_storage setting; see trash_storage and CustomSubstitutions.

%w[arms barrel basin basket bin birdbath bucket chamberpot gloop hole log puddle statue stump tangle tree turtle urn gelapod].freeze
DROP_TRASH_SUCCESS_PATTERNS =

Game response patterns indicating successful item disposal.

Matches when an item is dropped, put away, spread, smashed, fed to a gelapod, or naturally destroyed (e.g., moonblade crumbling). Used by dispose_trash and execute_dispose_command.

Examples:

Matches

"You drop the rock."
"You put the apple on the ground."
"You spread the flour on the ground."
"You feed the apple to the domesticated gelapod."

See Also:

[
  /^You drop/,
  /^You put/,
  /^You spread .* on the ground/,
  /smashing it to bits/,
  # The next message is when item crumbles when leaves your hand, like a moonblade.
  /^As you open your hand to release the/,
  /^You toss .* at the domesticated gelapod/,
  /^You feed .* a bit warily to the domesticated gelapod/
].freeze
DROP_TRASH_FAILURE_PATTERNS =

Game response patterns indicating item disposal failure.

Matches when disposal is not possible due to missing item, full hands, cursed state, guarded location, non-empty containers, or game restrictions. Used by dispose_trash and execute_dispose_command.

Examples:

Matches

"What were you referring to?"
"Perhaps you should be holding that first."
"No littering in the bank."
"You can't put that there."

See Also:

[
  /^What were you referring to/,
  /^I could not find/,
  /^But you aren't holding that/,
  /^Perhaps you should be holding that first/,
  /^You're kidding, right/,
  /^You can't do that/,
  /No littering/, # A guard steps over to you and says, "No littering in the bank."
  /^Where do you want to put that/,
  /^You really shouldn't be loitering/,
  /^You don't seem to be able to move/,
  # You may get the next message if you've been cursed and unable to let go of items.
  # Find a Cleric to uncurse you.
  /^Oddly, when you attempt to stash it away safely/,
  /^You need something in your right hand/,
  /^You can't put that there/,
  /^The domesticated gelapod glances warily at/, # deeds
  /^You should empty it out, first./ # container with items
].freeze
DROP_TRASH_RETRY_PATTERNS =

Messages that when trying to drop an item you're warned. To continue you must retry the command.

[
  # You may get the next message if the item would be damaged upon dropping.
  /^If you still wish to drop it/,
  /would damage it/,
  # You may get the next messages when an outdated item is updated upon use.
  # "Something appears different about the <item>, perhaps try doing that again."
  # Example: https://elanthipedia.play.net/Item:Leather_lotion
  /^Something appears different about/,
  /perhaps try doing that again/
].freeze
WORN_TRASHCAN_VERB_PATTERNS =

Game response patterns when activating a worn trashcan via verb (e.g., tap, drum).

Indicates the worn container (e.g., shroud, compactor) has been activated to process the item inside. Used by dispose_trash after putting item into a worn receptacle.

Examples:

Matches

"You drum your fingers along the shroud."
"You pull a lever on the compactor."
"You poke your finger around inside."

See Also:

[
  /^You drum your fingers/,
  /^You pull a lever/,
  /^You poke your finger around/
].freeze
GET_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item retrieval.

Matches when an item is picked up, drawn, plucked, or obtained by any method. Includes messages for items already held, for magically concealed retrieval, and for careful/deft removal. Used by get_item_unsafe and related methods.

Examples:

Matches

"You get the sword."
"You draw your shield."
"You pick up the key."
"You are already holding the amulet."

See Also:

[
  /you draw (?!\w+'s wounds)/i,
  /^You get/,
  /^You pick/,
  /^You pluck/,
  /^You slip/,
  /^You scoop/,
  /^You deftly remove/,
  /^You are already holding/,
  /^You fade in for a moment as you/,
  /^You carefully lift/,
  /^You carefully remove .* from the bundle/,
  /^With a flick of your wrist, you stealthily unsheath/
].freeze
GET_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item retrieval failure.

Matches when retrieval is impossible due to magical force, full hands, injured limbs, item capacity, cursed state, decay, or game restrictions. Used by get_item_unsafe to determine if an item was successfully obtained.

Examples:

Matches

"You need both hands free."
"A magical force keeps you from grasping it."
"Your left hand is too injured."
"That would push you over the item limit."

See Also:

[
  /^A magical force keeps you from grasping/,
  /^You'll need both hands free/,
  /^You need both hands free/,
  /^You need a free hand/,
  /^You can't pick that up with your hand that damaged/,
  /^Your (left|right) hand is too injured/,
  /^You just can't/,
  /^You stop as you realize the .* is not yours/,
  /^You can't reach that from here/, # on a mount like a flying carpet
  /^You don't seem to be able to move/,
  /^You should untie/,
  /^You can't do that/,
  /^Get what/,
  /^I could not/,
  /^What were you/,
  /already in your inventory/, # wearing it
  /needs to be tended to be removed/, # ammo lodged in you
  /push you over the item limit/, # you're at item capacity
  /rapidly decays away/, # item disappears when try to get it
  /cracks and rots away/, # item disappears when try to get it
  /^You should stop practicing your Athletics skill before you do that/
].freeze
WEAR_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item donning.

Matches when an item is worn, put on, attached, strapped, slipped, placed, or worn by any verb. Includes messages for items already worn, complex items (boots, gloves), and special enchanted items (ice-veined leather, bearskin). Used by wear_item_unsafe?.

Examples:

Matches

"You put on the cloak."
"You pull the amulet around your neck."
"You are already wearing the boots."
"You slip your feet into the boots."

See Also:

[
  /^You put/,
  /^You pull/,
  /^You sling/,
  /^You attach/,
  /^You strap/,
  /^You slide/,
  /^You spin/,
  /^You slip/,
  /^You place/,
  /^You hang/,
  /^You tug/,
  /^You struggle/,
  /^You squeeze/,
  /^You manage/,
  /^You gently place/,
  /^You toss one strap/,
  /^You carefully loop/,
  /^You work your way into/,
  /^You are already wearing/,
  /^Gritting your teeth, you grip/,
  /^You expertly sling the/,
  /put it on/, # weird clerical collar thing, trying to make it a bit generic
  /slide effortlessly onto your/,
  /^You carefully arrange/,
  /^A brisk chill rushes through you as you wear/, # some hiro bearskin gloves interlaced with strips of ice-veined leather
  /^You drape/,
  /You lean over and slip your feet into the boots./, # a pair of weathered barkcloth boots lined in flannel,
  /^You reach down and step into/, # pair of enaada boots clasped by asharsh'dai
  /Gritting your teeth/ # Gritting your teeth, you grip each of your heavy combat boots in turn by the straps, and drive your feet into them for a secure fit.
].freeze
WEAR_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item donning failure.

Matches when an item cannot be worn due to unloaded container, game restrictions, or invalid target. Used by wear_item_unsafe?.

Examples:

Matches

"You can't wear that."
"You should unload it first."
"Wear what?"

See Also:

[
  /^You can't wear/,
  /^You (need to|should) unload/,
  /close the fan/,
  /^You don't seem to be able to move/,
  /^Wear what/,
  /^I could not/,
  /^What were you/
].freeze
TIE_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item tying.

Matches when an item (typically a container or bag) is tied, attached, or already tied. Used by tie_item?.

Examples:

Matches

"You tie the pouch to your belt."
"You attach the cord to the bag."
"The pouch has already been tied off."

See Also:

[
  /^You .*tie/,
  /^You attach/,
  /has already been tied off/,
  /Tie it off when it's empty\?/
].freeze
TIE_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item tying failure.

Matches when an item cannot be tied due to lack of ties, busy state, injured limbs, or fit issues. Used by tie_item?.

Examples:

Matches

"There's no more free ties."
"You don't seem to be able to move."
"This doesn't seem to fit."

See Also:

[
  /^There's no more free ties/,
  /^Tie what/,
  /^You are a little too busy/,
  /^You don't seem to be able to move/,
  /^You must be holding/,
  /^Your wounds hinder your ability to do that/,
  /close the fan/,
  /doesn't seem to fit/
].freeze
UNTIE_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item untying.

Matches when a tied item is removed or untied. Used by untie_item?.

Examples:

Matches

"You remove the pouch from your belt."
"You untie the cord."

See Also:

[
  /^You remove/,
  /You untie/i
].freeze
UNTIE_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item untying failure.

Matches when an item cannot be untied due to busy state, fumbled attempt, or invalid target. Used by untie_item?.

Examples:

Matches

"You fumble with the ties."
"You don't seem to be able to move."
"Untie what?"

See Also:

[
  /^You don't seem to be able to move/,
  /^You fumble with the ties/,
  /^You are a little too busy/,
  /^You are a bit too busy/,
  /^Untie what/,
  /^What were you referring/
].freeze
REMOVE_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item removal from worn slots.

Matches when a worn item is taken off, detached, loosened, slipped, untied, or pulled from the body. Includes messages for complex items (boots, gloves) and enchanted items. Used by remove_item_unsafe?.

Examples:

Matches

"You slip off the gloves."
"You detach the amulet."
"You pull off the boots."
"Grunting, you pull off your combat boots."

See Also:

[
  /^Dropping your shoulder/,
  /^The .* slide/,
  /^Without any effort/,
  /^You .* slide/,
  /^You detach/,
  /^You loosen/,
  /^You pull/,
  /^You.*remove/,
  /^You slide/,
  /^You sling/,
  /^You slip/,
  /^You struggle/,
  /^You take/,
  /you tug/i,
  /^You untie/,
  /as you remove/,
  /slide themselves off of your/,
  /you manage to loosen/,
  /you unlace/,
  /^You slam the heels/,
  /^You work your way out/,
  /^Grunting with momentary exertion/, # Grunting with momentary exertion, you grip each of your heavy combat boots in turn by the heel, and pull them off.
  /^With masterful grace, you ready/,
  /^A brisk chill leaves you as you/ # cold-enchanted items (e.g., ice-veined leather gloves)
].freeze
REMOVE_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item removal failure.

Matches when an item cannot be removed due to full hands, injured limbs, item not worn, or movement restriction. Used by remove_item_unsafe?.

Examples:

Matches

"You aren't wearing that."
"You need a free hand."
"You don't seem to be able to move."

See Also:

[
  /^You'll need both hands free/,
  /^You need a free hand/,
  /^You aren't wearing/,
  /^You don't seem to be able to move/,
  /^Remove what/,
  /^I could not/,
  /^What were you/
].freeze
SHEATH_ITEM_SUCCESS_PATTERNS =

Success patterns for the SHEATH verb.

Matches game output when a weapon is successfully sheathed into a scabbard, sheath, or harness. Also splatted into PUT_AWAY_ITEM_SUCCESS_PATTERNS because STOW can trigger sheath responses when the default storage is a sheath.

Examples:

Matches

"Sheathing your sword, you put it away."
"You sheath your sword in your scabbard."
"With fluid and stealthy movements you slip the sabre into your harness."

See Also:

[
  /^Sheathing/,
  /^You sheath/,
  /^You secure your/,
  /^You slip/,
  /^You hang/,
  /^You (easily )?strap/,
  /^With a flick of your wrist,? you stealthily sheath/,
  /^With fluid and stealthy movements you slip/,
  /^The .* slides easily/
].freeze
SHEATH_ITEM_FAILURE_PATTERNS =

Failure patterns for the SHEATH verb.

Examples:

Matches

"Sheath your sword where?"
"There's no room for that."

See Also:

[
  /^Sheath your .* where/,
  /^There's no room/,
  /is too small to hold that/,
  /is too wide to fit/,
  /^Your (left|right) hand is too injured/
].freeze
PUT_AWAY_ITEM_SUCCESS_PATTERNS =

Success patterns for putting an item away via PUT or STOW.

Includes SHEATH_ITEM_SUCCESS_PATTERNS because STOW can trigger sheath responses when the default storage is a sheath/harness.

[
  /^You put your .* in/,
  /^You hold out/,
  /^You stuff/,
  /^You tuck/,
  /^You open your pouch and put/,
  /^You guide your/i, # puppy storage
  /^You nudge your/i, # monkey storage
  # The next message is when item crumbles when stowed, like a moonblade.
  /^As you open your hand to release the/,
  # You're a thief and you binned a stolen item.
  /nods toward you as your .* falls into the .* bin/,
  /^You add/,
  /^You rearrange/,
  /^You combine the stacks/,
  /^You secure/,
  # The following are success messages for putting an item in a container OFF your person.
  /^You drop/i,
  /^You set/i,
  /^You put/i,
  /^You carefully fit .* into your bundle/,
  /^You gently set/,
  # Sheath patterns included because STOW can trigger sheath responses.
  *SHEATH_ITEM_SUCCESS_PATTERNS,
  /^You toss .* into/ # You toss the alcohol into the bowl and mix it in thoroughly
].freeze
PUT_AWAY_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item storage failure.

Matches when an item cannot be stowed or put into a container due to capacity, container design, cursed state, or game restrictions. Includes messages for items too large, too heavy, or incompatible with container. Used by put_away_item_unsafe?.

Examples:

Matches

"There isn't any more room in that."
"That's too heavy to go in there."
"The backpack is not designed to carry anything."
"Containers can't be placed in containers."

See Also:

[
  /^Stow what/,
  /^I can't find your container for stowing things in/,
  /^Please rephrase that command/,
  /^What were you referring to/,
  /^I could not find what you were referring to/,
  /^There isn't any more room in/,
  /^There's no room/,
  /^(The|That).* too heavy to go in there/,
  /^You (need to|should) unload/,
  /^You can't do that/,
  /^You just can't get/,
  /^You can't put items/,
  /^You can only take items out/,
  /^You don't seem to be able to move/,
  /^Perhaps you should be holding that first/,
  /^Containers can't be placed in/,
  /^The .* is not designed to carry anything/,
  /^You can't put that.*there/,
  /^Weirdly, you can't manage .* to fit/,
  /^\[Containers can't be placed in/,
  /even after stuffing it/,
  /is too .* to (fit|hold)/,
  /no matter how you arrange it/,
  /close the fan/,
  /to fit in the/,
  /doesn't seem to want to leave you/, # trying to put a pet in a home within a container
  # You may get the next message if you've been cursed and unable to let go of items.
  # Find a Cleric to uncurse you.
  /Oddly, when you attempt to stash it away safely/,
  /completely full/,
  /That doesn't belong in there!/,
  /exerts a steady force preventing/
].freeze
PUT_AWAY_ITEM_RETRY_PATTERNS =

Messages that when trying to put away an item you're warned. To continue you must retry the command.

[
  # You may get the next messages when an outdated item is updated upon use.
  # "Something appears different about the <item>, perhaps try doing that again."
  # Example: https://elanthipedia.play.net/Item:Leather_lotion
  /Something appears different about/,
  /perhaps try doing that again/
].freeze
STOW_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item stowing.

Combines GET_ITEM_SUCCESS_PATTERNS and PUT_AWAY_ITEM_SUCCESS_PATTERNS to match both retrieval and storage phases of the STOW command. Used by stow_item_unsafe? and stow_hand.

[
  *GET_ITEM_SUCCESS_PATTERNS,
  *PUT_AWAY_ITEM_SUCCESS_PATTERNS
].freeze
STOW_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item stowing failure.

Combines GET_ITEM_FAILURE_PATTERNS and PUT_AWAY_ITEM_FAILURE_PATTERNS to match failures in either retrieval or storage phases of the STOW command. Used by stow_item_unsafe? and stow_hand.

[
  *GET_ITEM_FAILURE_PATTERNS,
  *PUT_AWAY_ITEM_FAILURE_PATTERNS
].freeze
STOW_ITEM_RETRY_PATTERNS =

Game response patterns that warrant retry during item stowing.

Combines PUT_AWAY_ITEM_RETRY_PATTERNS for messages that indicate transient conditions (item updates, game state changes) where retry should succeed. Used by stow_item_unsafe? and stow_hand.

[
  *PUT_AWAY_ITEM_RETRY_PATTERNS
].freeze
WIELD_ITEM_SUCCESS_PATTERNS =

Success patterns for the WIELD verb.

Matches game output when a weapon is successfully drawn from a sheath, scabbard, or harness.

Examples:

Matches

"You draw your sword from your scabbard."
"You deftly remove a dagger from your thigh sheath."
"With a flick of your wrist, you stealthily unsheath your weapon."

See Also:

[
  /you draw (?!\w+'s wounds)/i,
  /^You deftly remove/,
  /^You slip/,
  /^With a flick of your wrist,? you stealthily unsheath/,
  /^With fluid and stealthy movements you draw/,
  /^The .* slides easily out/
].freeze
WIELD_ITEM_FAILURE_PATTERNS =

Failure patterns for the WIELD verb.

[
  /^Wield what/,
  /^Your (left|right) hand is too injured/
].freeze
SWAP_HANDS_SUCCESS_PATTERNS =

Success patterns for the SWAP verb (hand swap).

Matches game output when items are successfully swapped between left and right hands.

Examples:

Matches

"You move a steel sword to your left hand."

See Also:

[
  /^You move/
].freeze
SWAP_HANDS_FAILURE_PATTERNS =

Failure patterns for the SWAP verb (hand swap).

[
  /^Will alone cannot conquer the paralysis/
].freeze
UNLOAD_WEAPON_SUCCESS_PATTERNS =

Success patterns for the UNLOAD verb.

Matches game output when a ranged weapon is successfully unloaded. Includes both visible and hidden unloading messages, as well as the case where ammo falls to the ground (hands full).

The game may prepend an aim/firing timer tag to the unload line, e.g. " You unload the shortbow." The optional (?:<dialogData.*?<\/dialogData>)? prefix lets the patterns match whether or not the tag is present, without assuming its inner values.

Examples:

Matches

"You unload the crossbow."
"Your bolt falls from your crossbow to your feet."
"As you release the string, the arrow tumbles to the ground."
"You remain concealed by your surroundings, convinced that your unloading of the crossbow went unobserved."

See Also:

[
  /^(?:<dialogData.*?<\/dialogData>)?You unload/,
  /^Your .* fall.*to your feet\.$/,
  /As you release the string/,
  /^(?:<dialogData.*?<\/dialogData>)?You .* unloading/
].freeze
UNLOAD_WEAPON_FAILURE_PATTERNS =

Failure patterns for the UNLOAD verb.

[
  /But your .* isn't loaded/,
  /You can't unload such a weapon/,
  /You don't have a ranged weapon to unload/,
  /You must be holding the weapon to do that/
].freeze
RUMMAGE_SUCCESS_PATTERNS =

Game response patterns indicating successful container rummage.

Matches when container contents are successfully listed via RUMMAGE, including empty containers. Used by rummage_container and list_container_contents.

Examples:

Matches

"You rummage through the backpack and see a sword, shield, and amulet."
"In the pouch you see three gems."
"There is nothing interesting in there."

See Also:

[
  /^You rummage through .* and see (.*)\./,
  /^In the .* you see (.*)\./,
  /there is nothing/i
].freeze
RUMMAGE_FAILURE_PATTERNS =

Game response patterns indicating rummage failure.

Matches when container contents cannot be accessed due to inability to move, missing container, or invalid reference. Used by rummage_container and list_container_contents.

Examples:

Matches

"I could not find what you were referring to."
"You don't seem to be able to move."
"What were you referring to?"

See Also:

[
  /^You don't seem to be able to move/,
  /^I could not find/,
  /^I don't know what you are referring to/,
  /^What were you referring to/
].freeze
TAP_SUCCESS_PATTERNS =

Game response patterns indicating successful item tap.

Matches when tapping an item returns information about its location (worn, stowed, inside container) or other status. Response text is parsed by wearing?, inside?, and exists?. Used by tap.

Examples:

Matches

"You tap a steel sword (wearing)."
"You tap a shield (inside your backpack)."
"You tap a key."
"You tap a person on the shoulder."

See Also:

[
  /^You tap\s(?!into).*/, # The `.*` is needed to capture entire phrase. Methods parse it to know if an item is worn, stowed, etc.
  /^You (thump|drum) your finger/, # You tapped an item with fancy verbiage, ohh la la!
  /^As you tap/, # As you tap a large ice-veined leather and flamewood surveyor's case
  /^The orb is delicate/, # You tapped a favor orb
  /^You .* on the shoulder/, # You tapped someone
  /^You suddenly forget what you were doing/ # "tap my tessera" messaging when hands are full
].freeze
TAP_FAILURE_PATTERNS =

Game response patterns indicating item tap failure.

Matches when an item cannot be tapped due to inability to move, missing item, or invalid reference. Used by tap.

Examples:

Matches

"I could not find what you were referring to."
"You don't seem to be able to move."
"What were you referring to?"

See Also:

[
  /^You don't seem to be able to move/,
  /^I could not find/,
  /^I don't know what you are referring to/,
  /^What were you referring to/
].freeze
OPEN_CONTAINER_SUCCESS_PATTERNS =

Game response patterns indicating successful container opening.

Matches when a container is opened or is already open. Used by open_container?.

Examples:

Matches

"You open the backpack."
"The chest is already open."
"You unbutton the pouch."

See Also:

[
  /^You open/,
  /^You slowly open/,
  /^The .* opens/,
  /^You unbutton/,
  /([Ii]t's|is) already open/,
  /^You spread your arms, carefully holding your bag well away from your body/
].freeze
OPEN_CONTAINER_FAILURE_PATTERNS =

Game response patterns indicating container opening failure.

Matches when a container cannot be opened due to magical/spell interference, location restrictions, busy state, or game restrictions. Used by open_container?.

Examples:

Matches

"You don't want to ruin your spell just for that."
"This is probably not the time nor place for that."
"Open what?"

See Also:

[
  /^Please rephrase that command/,
  /^What were you referring to/,
  /^I could not find what you were referring to/,
  /^You don't want to ruin your spell just for that do you/,
  /^It would be a shame to disturb the silence of this place for that/,
  /^This is probably not the time nor place for that/,
  /^You don't seem to be able to move/,
  /^There is no way to do that/,
  /^You can't do that/,
  /^Open what/
].freeze
CLOSE_CONTAINER_SUCCESS_PATTERNS =

Game response patterns indicating successful container closing.

Matches when a container is closed or is already closed. Used by close_container?.

Examples:

Matches

"You close the backpack."
"The chest is already closed."
"You quickly close the pouch."

See Also:

[
  /^You close/,
  /^You quickly close/,
  /^You pull/,
  /is already closed/
].freeze
CLOSE_CONTAINER_FAILURE_PATTERNS =

Game response patterns indicating container closing failure.

Matches when a container cannot be closed due to magical/spell interference, location restrictions, busy state, or game restrictions. Used by close_container?.

Examples:

Matches

"You don't want to ruin your spell just for that."
"This is probably not the time nor place for that."

See Also:

[
  /^Please rephrase that command/,
  /^What were you referring to/,
  /^I could not find what you were referring to/,
  /^You don't want to ruin your spell just for that do you/,
  /^It would be a shame to disturb the silence of this place for that/,
  /^This is probably not the time nor place for that/,
  /^You don't seem to be able to move/,
  /^There is no way to do that/,
  /^You can't do that/
].freeze
CONTAINER_IS_CLOSED_PATTERNS =

Game response patterns indicating a container is closed.

Matches messages that indicate an operation cannot proceed because the target container is closed. Used by retry logic in put_away_item_unsafe?, stow_hand, and list_container_contents.

Examples:

Matches

"But that's closed."
"While it's closed, you can't do that."

See Also:

[
  /^But that's closed/,
  /^That is closed/,
  /^While it's closed/
].freeze
LOWER_SUCCESS_PATTERNS =

Game response patterns indicating successful item lowering to ground.

Matches when a held item is lowered to the feet slot. Includes messages for items that crumble during lowering (e.g., moonblade). Used by lower_item?.

Examples:

Matches

"You lower the sword to the ground."
"As you open your hand to release the moonblade, it crumbles."

See Also:

[
  /^You lower/,
  # The next message is when item crumbles when leaves your hand, like a moonblade.
  /^As you open your hand to release the/
].freeze
LOWER_FAILURE_PATTERNS =

Game response patterns indicating item lowering failure.

Matches when an item cannot be lowered due to empty hands, movement restriction, or invalid reference. Used by lower_item?.

Examples:

Matches

"But you aren't holding anything."
"You don't seem to be able to move."
"What were you referring to?"

See Also:

[
  /^You don't seem to be able to move/,
  /^But you aren't holding anything/,
  /^Please rephrase that command/,
  /^What were you referring to/,
  /^I could not find what you were referring to/
].freeze
LIFT_SUCCESS_PATTERNS =

Game response patterns indicating successful item lifting from ground.

Matches when an item is picked up from the ground/feet slot. Used by lift?.

Examples:

Matches

"You pick up the sword."

See Also:

[
  /^You pick up/
].freeze
LIFT_FAILURE_PATTERNS =

Game response patterns indicating item lifting failure.

Matches when an item cannot be lifted from the ground due to missing items, weakness, or movement restriction. Used by lift?.

Examples:

Matches

"There are no items lying at your feet."
"You are not strong enough to pick that up."
"What did you want to try and lift?"

See Also:

[
  /^There are no items lying at your feet/,
  /^What did you want to try and lift/,
  /can't quite lift it/,
  /^You are not strong enough to pick that up/
].freeze
GIVE_ITEM_SUCCESS_PATTERNS =

Game response patterns indicating successful item giving/trade.

Matches when an NPC or player accepts an offered item, typically during repairs, trades, or quests. Used by give_item?.

Examples:

Matches

"Ragge has accepted your offer."
"You hand Ragge your ticket and are handed back a sword."

See Also:

[
  /has accepted your offer/,
  /your ticket and are handed back/,
  /Please don't lose this ticket!/,
  /^You hand .* gives you back a repair ticket/,
  /^You hand .* your ticket and are handed back/
].freeze
GIVE_ITEM_FAILURE_PATTERNS =

Game response patterns indicating item giving failure.

Matches when an NPC or player declines the offer, is unavailable, or the item is not in the required state for the transaction. Used by give_item?.

Examples:

Matches

"I don't repair those here."
"has declined the offer."
"Your offer has expired."
"That isn't damaged!"

See Also:

[
  /I don't repair those here/,
  /There isn't a scratch on that/,
  /give me a few more moments/,
  /I will not repair something that isn't broken/,
  /I can't fix those/,
  /has declined the offer/,
  /^Your offer to .* has expired/,
  /^You may only have one outstanding offer at a time/,
  /^What is it you're trying to give/,
  /Lucky for you!  That isn't damaged!/
].freeze
FILL_POUCH_SUCCESS_PATTERNS =

Game response patterns indicating successful gem pouch filling.

Matches when gems are transferred from a container into a pouch, or when the pouch contains no gems to transfer. Used by fill_gem_pouch_with_container.

Examples:

Matches

"You open the pouch."
"You fill your black gem pouch with the gems from the container."
"There aren't any gems to fill with."

See Also:

[
  /^You open/,
  /^You fill your/,
  /^There aren't any gems/
].freeze
FILL_POUCH_NEEDS_TIE_PATTERNS =

Game response patterns indicating pouch must be tied before filling.

Matches when a gem pouch requires tying before additional gems can be added. Used by fill_gem_pouch_with_container to trigger tying or treating the pouch as full and swapping it out.

Examples:

Matches

"You'd better tie it up before putting more gems in."
"You'll need to tie it up before we can continue."

See Also:

[
  /^You'd better tie it up before putting/,
  /^You'll need to tie it up before/
].freeze
FILL_POUCH_FULL_PATTERN =

Game response pattern indicating gem pouch is at capacity.

Matches when a gem pouch cannot hold more gems. Triggers swapping out the full pouch for a spare in fill_gem_pouch_with_container.

Examples:

Matches

"The pouch is too full to fit another gem."

See Also:

/is too full to fit/.freeze
FILL_POUCH_FAILURE_PATTERNS =

Game response patterns indicating gem pouch filling failure.

Matches when gems cannot be transferred due to invalid command or reference. Used by fill_gem_pouch_with_container.

Examples:

Matches

"Please rephrase that command."
"What were you referring to?"

See Also:

[
  /^Please rephrase that command/,
  /^What were you referring to/
].freeze
INV_BELT_START_PATTERN =

Game response pattern marking the start of INVENTORY BELT output.

Used as the start marker in check_belt_for_pouch? to parse belt contents via Util.issue_command.

/^All of your items worn attached to the belt:/.freeze
INV_BELT_END_PATTERN =

Game response pattern marking the end of INVENTORY BELT output.

Used as the end marker in check_belt_for_pouch? to parse belt contents via Util.issue_command.

/^\[Use INVENTORY HELP/.freeze
COUNT_PART_PATTERNS =

Game response patterns for parsing COUNT command output.

Matches when counting parts/uses/scrolls remaining in an item. Captures the numeric count value via named group count. Used by count_item_parts to sum parts across multiple stacks.

Examples:

Matches

"There are 45 parts left."
"The leather has 10 uses remaining."
"There are enough left to create 3 more items."
"You count out 20 pieces of material there."

See Also:

[
  /and see there (?:is|are) (?<count>.+) left\./,
  /There (?:is|are) (?:only )?(?<count>.+) parts? left/,
  /There's (?:only )?(?<count>.+) parts? left/,
  /The (?:.+) has (?<count>.+) uses remaining./,
  /There are enough left to create (?<count>.+) more/,
  /You count out (?<count>.+) pieces? of material there/,
  /There (?:is|are) (?<count>.+) scrolls? left for use with crafting/
].freeze
BRAID_TOO_LONG_PATTERN =

Game response pattern indicating a braided item is too long to stow.

Matches when a braid (hairstyle) is too long to fit in the default stow container. Captures the braid name via named group braid_name for disposal. Used by stow_hand to detect and dispose of oversized braids.

Examples:

Matches

"The braided rope is too long."

See Also:

/The braided (?<braid_name>.+) is too long/.freeze
ACCEPT_SUCCESS_PATTERN =

Game response pattern indicating successful item offer acceptance.

Matches when a player accepts another player's item offer. Captures the offering player's name via named group name. Used by accept_item?.

Examples:

Matches

"You accept Thorgrim's offer and are now holding a sword."

See Also:

/You accept (?<name>\w+)'s offer and are now holding/.freeze

Class Method Summary collapse

Class Method Details

.accept_item? ⇒ String, false

Accepts a pending item offer from another player.

Returns:

  • (String, false) —

    name of the person whose offer was accepted, or false if no offer pending or hands full

See Also:



2360
2361
2362
2363
2364
# File 'documented/dragonrealms/commons/common-items.rb', line 2360

def accept_item?
  result = DRC.bput("accept", ACCEPT_SUCCESS_PATTERN, "You have no offers", "Both of your hands are full", "would push you over your item limit")
  match = result&.match(ACCEPT_SUCCESS_PATTERN)
  match ? match[:name] : false
end

.check_belt_for_pouch?(gem_pouch_adjective, gem_pouch_noun) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if a gem pouch is already attached to the belt.

Uses INV BELT to inspect belt contents and matches against the pouch adjective and noun.

Parameters:

  • gem_pouch_adjective (String) —

    pouch adjective (e.g., "black")

  • gem_pouch_noun (String) —

    pouch noun (e.g., "pouch")

Returns:

  • (Boolean) —

    true if a matching pouch is found on the belt



2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
# File 'documented/dragonrealms/commons/common-items.rb', line 2379

def check_belt_for_pouch?(gem_pouch_adjective, gem_pouch_noun)
  belt_contents = Lich::Util.issue_command(
    "inv belt",
    INV_BELT_START_PATTERN,
    INV_BELT_END_PATTERN,
    timeout: 3,
    silent: true,
    quiet: true,
    usexml: false,
    include_end: false
  )

  return false if belt_contents.nil? || belt_contents.empty?

  pouch_pattern = /#{gem_pouch_adjective}.*gem.*#{gem_pouch_noun}/i
  belt_contents.any? { |line| line.match?(pouch_pattern) }
end

.close_container?(container) ⇒ Boolean

Closes a container.

Parameters:

  • container (String) —

    container noun to close

Returns:

  • (Boolean) —

    true if container was closed (or already closed)

See Also:



2279
2280
2281
2282
2283
2284
2285
# File 'documented/dragonrealms/commons/common-items.rb', line 2279

def close_container?(container)
  case DRC.bput("close #{container}", CLOSE_CONTAINER_SUCCESS_PATTERNS, CLOSE_CONTAINER_FAILURE_PATTERNS)
  when *CLOSE_CONTAINER_SUCCESS_PATTERNS
    return true
  end
  return false
end

.container_is_empty?(container) ⇒ Boolean?

Checks if a container is empty by looking inside it.

Parameters:

  • container (String) —

    container noun to check

Returns:

  • (Boolean, nil) —

    true if empty, false if not empty, nil if unable to determine (e.g., cannot open or look in container)



2033
2034
2035
# File 'documented/dragonrealms/commons/common-items.rb', line 2033

def container_is_empty?(container)
  look_in_container(container)&.empty?
end

.count_all_boxes(settings) ⇒ Integer

Counts all lockpick boxes across configured containers.

Checks the picking_box_source, picking_box_sources, blacklist, and too_hard containers from settings.

Parameters:

  • settings (OpenStruct) —

    user settings from get_settings

Returns:

  • (Integer) —

    total number of boxes across all containers



1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
# File 'documented/dragonrealms/commons/common-items.rb', line 1554

def count_all_boxes(settings)
  current_box_count = 0

  [
    settings.picking_box_source,
    settings.pick['picking_box_sources'],
    settings.pick['blacklist_container'],
    settings.pick['too_hard_container']
  ].flatten.uniq.reject { |container|
    container.to_s.empty?
  }.each { |container|
    current_box_count += get_box_list_in_container(container).size
  }

  current_box_count
end

.count_item_parts(item) ⇒ Integer

Counts the remaining parts/uses of a stackable item.

Iterates through ordinals (first, second, ...) to count across multiple stacks. Falls back to count_items if the item is not stackable.

Examples:

DRCI.count_item_parts("leather")  #=> 45

Parameters:

  • item (String) —

    item noun to count

Returns:

  • (Integer) —

    total number of parts across all stacks



1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
# File 'documented/dragonrealms/commons/common-items.rb', line 1444

def count_item_parts(item)
  count = 0
  # Item IDs (starting with #) are unique, so we count once without ordinals
  items_to_count = item&.start_with?('#') ? [item] : $ORDINALS.map { |ord| "#{ord} #{item}" }

  items_to_count.each do |item_with_ordinal|
    result = DRC.bput("count #{item_ref(item_with_ordinal)}",
                      'I could not find what you were referring to.',
                      'tell you much of anything.',
                      *COUNT_PART_PATTERNS)
    if result == 'I could not find what you were referring to.'
      break
    elsif result == 'tell you much of anything.'
      Lich::Messaging.msg("bold", "DRCI: count_item_parts called on non-stackable item: #{item}")
      count = count_items(item)
      break
    else
      # Try to match against our count patterns
      match = COUNT_PART_PATTERNS.lazy.filter_map { |pat| result.match(pat) }.first
      if match
        countval = match[:count].tr('-', ' ')
        if countval.match?(/\A\d+\z/)
          count += Integer(countval)
        else
          count += DRC.text2num(countval)
        end
      end
    end
    waitrt?
  end
  count
end

.count_items(item) ⇒ Integer

Counts matching items in the container inferred by tapping the item.

Taps the item to determine which container it is in, then delegates to count_items_in_container.

Parameters:

  • item (String) —

    item noun to count

Returns:

  • (Integer) —

    number of matching items in the inferred container

See Also:



1486
1487
1488
1489
1490
1491
1492
# File 'documented/dragonrealms/commons/common-items.rb', line 1486

def count_items(item)
  tap_result = tap(item)
  match = tap_result&.match(/inside your (?<container>.*)/)
  return 0 unless match

  count_items_in_container(item, match[:container])
end

.count_items_in_container(item, container) ⇒ Integer

Counts matching items in a specific container via RUMMAGE.

Parameters:

  • item (String) —

    item noun to count

  • container (String) —

    container noun to rummage

Returns:

  • (Integer) —

    number of matching items found

See Also:



1501
1502
1503
1504
1505
1506
# File 'documented/dragonrealms/commons/common-items.rb', line 1501

def count_items_in_container(item, container)
  contents = DRC.bput("rummage /C #{item.split.last} in #{item_ref(container)}", /^You rummage .*/, /That would accomplish nothing/)
  # This regexp avoids counting the quoted item name in the message, as
  # well as avoiding finding the item as a substring of other items.
  contents.scan(/ #{item}\W/).size
end

.count_lockpick_container(container) ⇒ Integer

Counts how many more lockpicks a lockpick stacker can hold.

Uses APPRAISE QUICK to determine remaining capacity.

Parameters:

  • container (String) —

    lockpick ring/stacker noun

Returns:

  • (Integer) —

    number of additional lockpicks that can fit

See Also:



1516
1517
1518
1519
1520
# File 'documented/dragonrealms/commons/common-items.rb', line 1516

def count_lockpick_container(container)
  result = DRC.bput("appraise #{item_ref(container)} quick", /it appears to be full/, /it might hold an additional \d+/, /\d+ lockpicks would probably fit/)
  waitrt?
  result.scan(/\d+/).first.to_i
end

.count_necro_stacker(necro_stacker) ⇒ Integer

Counts items in a Necromancer material stacker via STUDY.

Parameters:

  • necro_stacker (String) —

    stacker noun

Returns:

  • (Integer) —

    number of items currently held



1542
1543
1544
1545
# File 'documented/dragonrealms/commons/common-items.rb', line 1542

def count_necro_stacker(necro_stacker)
  result = DRC.bput("study #{item_ref(necro_stacker)}", /currently holds \d+ items/)
  result.scan(/\d+/).first.to_i
end

.dispose_trash(item, worn_trashcan = nil, worn_trashcan_verb = nil, retries: 3) ⇒ Boolean?

Disposes of an item by putting it in a trash receptacle.

Tries multiple disposal strategies in order: worn trashcan, room meta-tagged trashcan, room objects matching known trash receptacles, and finally drops the item on the ground.

Examples:

Dispose using room trash bins

DRCI.dispose_trash("rock")

Dispose into a worn trashcan

DRCI.dispose_trash("rock", "shroud", "tap")

Parameters:

  • item (String) —

    item noun to dispose of

  • worn_trashcan (String, nil) (defaults to: nil) —

    worn container for trash (e.g., "shroud")

  • worn_trashcan_verb (String, nil) (defaults to: nil) —

    verb to activate the worn trashcan after use

  • retries (Integer) (defaults to: 3) —

    remaining retry attempts before giving up (default 3)

Returns:

  • (Boolean, nil) —

    true if disposed, false if failed, nil if item is nil or not held



1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
# File 'documented/dragonrealms/commons/common-items.rb', line 1127

def dispose_trash(item, worn_trashcan = nil, worn_trashcan_verb = nil, retries: 3)
  return unless item

  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: dispose_trash exceeded max retries")
    return false
  end

  return unless DRCI.get_item_if_not_held?(item)

  if worn_trashcan
    result = execute_dispose_command("put #{item_ref(item)} in #{item_ref(worn_trashcan)}", item, retries, worn_trashcan, worn_trashcan_verb)
    if result == :success
      if worn_trashcan_verb
        DRC.bput("#{worn_trashcan_verb} #{item_ref(worn_trashcan)}", *WORN_TRASHCAN_VERB_PATTERNS)
        DRC.bput("#{worn_trashcan_verb} #{item_ref(worn_trashcan)}", *WORN_TRASHCAN_VERB_PATTERNS)
      end
      return true
    end
    return result unless result == :failure
  end

  # Check for meta:trashcan tag on the room to identify a specific trashcan to use.
  metatag_match = Room.current.tags.find { |t| t =~ /meta:trashcan:(?<trashcan>.*)/ }&.match(/meta:trashcan:(?<trashcan>.*)/)
  if metatag_match
    metatag_trashcan = metatag_match[:trashcan]

    # Gelapod needs special handling since you feed it, and it disappears in winter
    metatag_trash_command = nil
    if metatag_trashcan == 'gelapod'
      metatag_trash_command = "feed #{item_ref(item)} to gelapod" if DRRoom.room_objs.include?('gelapod')
    else
      metatag_trash_command = "put #{item_ref(item)} in #{metatag_trashcan}"
    end

    # gelapod is not here - probably winter move on to next attempt to get rid of
    unless metatag_trash_command.nil?
      result = execute_dispose_command(metatag_trash_command, item, retries)
      return true if result == :success
      return result unless result == :failure
    end
  end

  recognized_trash = trash_storage
  trashcans = DRRoom.room_objs
                    .reject { |obj| obj =~ /azure \w+ tree/ }
                    .map { |long_name| DRC.get_noun(long_name) }
                    .select { |obj| recognized_trash.include?(obj) }

  trashcans.each do |trashcan|
    if trashcan == 'gloop'
      trashcan = 'bucket' if DRRoom.room_objs.include?('bucket of viscous gloop')
      trashcan = 'cauldron' if DRRoom.room_objs.include?('small bubbling cauldron of viscous gloop')
    elsif trashcan == 'bucket'
      trashcan = 'sturdy bucket' if DRRoom.room_objs.include?('sturdy bucket')
    elsif trashcan == 'basket'
      trashcan = 'waste basket' if DRRoom.room_objs.include?('waste basket')
    elsif trashcan == 'bin'
      trashcan = 'waste bin' if DRRoom.room_objs.include?('waste bin')
      trashcan = 'small bin' if DRRoom.room_objs.include?('small bin concealed with some nearby brush')
    elsif trashcan == 'arms'
      trashcan = 'statue'
    elsif trashcan == 'birdbath'
      trashcan = 'alabaster birdbath'
    elsif trashcan == 'turtle'
      trashcan = 'stone turtle'
    elsif trashcan == 'tree'
      trashcan = 'hollow' if DRRoom.room_objs.include?('dead tree with a darkened hollow near its base')
    elsif trashcan == 'basin'
      trashcan = 'stone basin' if DRRoom.room_objs.include?('hollow stone basin')
    elsif trashcan == 'tangle'
      trashcan = 'dark gap' if DRRoom.room_objs.include?('tangle of thick roots forming a dark gap')
    elsif XMLData.room_title == '[[A Junk Yard]]'
      trashcan = 'bin'
    elsif trashcan == 'gelapod'
      trash_command = "feed #{item_ref(item)} to gelapod"
    end

    trash_command = "put #{item_ref(item)} in #{trashcan}" unless trashcan == 'gelapod'

    result = execute_dispose_command(trash_command, item, retries)
    return true if result == :success
    return true if result && result != :failure
  end

  # No trash bins or not able to put item in a bin, just drop it.
  result = execute_dispose_command("drop #{item_ref(item)}", item, retries)
  case result
  when :success
    true
  when :failure
    Lich::Messaging.msg("bold", "DRCI: Failed to dispose of '#{item}'.")
    false
  when false, nil
    Lich::Messaging.msg("bold", "DRCI: Unexpected response when dropping '#{item}'.")
    false
  else
    result
  end
end

.execute_dispose_command(command, item, retries, *retry_args) ⇒ Symbol, Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Executes a dispose command and handles common retry/recovery patterns.

Parameters:

  • command (String) —

    game command to execute

  • item (String) —

    item being disposed

  • retries (Integer) —

    remaining retry attempts

  • retry_args (Array) —

    extra args to pass to dispose_trash on retry

Returns:

  • (Symbol, Boolean) —

    :success, :failure, or the boolean result of a retry



1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
# File 'documented/dragonrealms/commons/common-items.rb', line 1237

def execute_dispose_command(command, item, retries, *retry_args)
  case DRC.bput(command, DROP_TRASH_SUCCESS_PATTERNS, DROP_TRASH_FAILURE_PATTERNS, DROP_TRASH_RETRY_PATTERNS, /^Perhaps you should be holding that first/, /^But you aren't holding that/)
  when *DROP_TRASH_SUCCESS_PATTERNS
    :success
  when /^Perhaps you should be holding that first/, /^But you aren't holding that/
    DRCI.get_item?(item) && dispose_trash(item, *retry_args, retries: retries - 1)
  when *DROP_TRASH_FAILURE_PATTERNS
    :failure
  when *DROP_TRASH_RETRY_PATTERNS
    dispose_trash(item, *retry_args, retries: retries - 1)
  end
end

.exists?(item, container = nil) ⇒ Boolean

Checks if an item exists in inventory or a container by tapping it.

Examples:

DRCI.exists?("deed")
DRCI.exists?("sword", "backpack")

Parameters:

  • item (String) —

    item noun to check

  • container (String, nil) (defaults to: nil) —

    container to check in, or nil for general inventory

Returns:

  • (Boolean) —

    true if the item exists



1291
1292
1293
1294
1295
1296
1297
1298
# File 'documented/dragonrealms/commons/common-items.rb', line 1291

def exists?(item, container = nil)
  case tap(item, container)
  when *TAP_SUCCESS_PATTERNS
    true
  else
    false
  end
end

.fill_gem_pouch_with_container(gem_pouch_adjective, gem_pouch_noun, source_container, full_pouch_container = nil, spare_gem_pouch_container = nil, should_tie_gem_pouches = false, retries: 10) ⇒ void

This method returns an undefined value.

Fills a gem pouch from a source container.

Handles full pouches by swapping them out for spares via swap_out_full_gempouch?. Handles untied pouches by tying them when requested.

Examples:

DRCI.fill_gem_pouch_with_container("black", "pouch", "lootbag",
  "backpack", "trunk", true)

Parameters:

  • gem_pouch_adjective (String) —

    pouch adjective (e.g., "black")

  • gem_pouch_noun (String) —

    pouch noun (e.g., "pouch")

  • source_container (String) —

    container holding gems to transfer

  • full_pouch_container (String, nil) (defaults to: nil) —

    container for full pouches

  • spare_gem_pouch_container (String, nil) (defaults to: nil) —

    container holding spare pouches

  • should_tie_gem_pouches (Boolean) (defaults to: false) —

    whether to tie pouches after filling

  • retries (Integer) (defaults to: 10) —

    remaining retry attempts before giving up (default 10)



2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
# File 'documented/dragonrealms/commons/common-items.rb', line 2497

def fill_gem_pouch_with_container(gem_pouch_adjective, gem_pouch_noun, source_container, full_pouch_container = nil, spare_gem_pouch_container = nil, should_tie_gem_pouches = false, retries: 10)
  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: fill_gem_pouch_with_container exceeded max retries")
    return
  end

  Flags.add("pouch-full", FILL_POUCH_FULL_PATTERN)
  begin
    pouch = "#{gem_pouch_adjective} #{gem_pouch_noun}"
    result = DRC.bput(
      "fill #{item_ref(pouch)} with #{item_ref(source_container)}",
      *FILL_POUCH_SUCCESS_PATTERNS,
      FILL_POUCH_FULL_PATTERN,
      *FILL_POUCH_NEEDS_TIE_PATTERNS,
      *FILL_POUCH_FAILURE_PATTERNS
    )

    case result
    when *FILL_POUCH_FAILURE_PATTERNS
      Lich::Messaging.msg("bold", "DRCI: Fill failed - #{result}")
      return
    when *FILL_POUCH_NEEDS_TIE_PATTERNS
      # Pouch needs to be tied before more gems can be added
      if should_tie_gem_pouches
        # Tie the pouch and retry
        unless tie_gem_pouch?(gem_pouch_adjective, gem_pouch_noun)
          Lich::Messaging.msg("bold", "DRCI: Could not tie #{gem_pouch_adjective} #{gem_pouch_noun}.")
          return
        end
        return fill_gem_pouch_with_container(gem_pouch_adjective, gem_pouch_noun, source_container, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches, retries: retries - 1)
      else
        # Treat as full - swap out the pouch
        unless swap_out_full_gempouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches)
          Lich::Messaging.msg("bold", "DRCI: Could not swap gem pouches.")
          return
        end
        return fill_gem_pouch_with_container(gem_pouch_adjective, gem_pouch_noun, source_container, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches, retries: retries - 1)
      end
    when FILL_POUCH_FULL_PATTERN
      # Pouch is full, swap it out
      unless swap_out_full_gempouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches)
        Lich::Messaging.msg("bold", "DRCI: Could not swap gem pouches.")
        return
      end
      return fill_gem_pouch_with_container(gem_pouch_adjective, gem_pouch_noun, source_container, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches, retries: retries - 1)
    end

    # Check flag for mid-fill full pouch (when pouch fills up during the fill operation)
    if Flags["pouch-full"]
      Flags.reset("pouch-full")
      unless swap_out_full_gempouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches)
        Lich::Messaging.msg("bold", "DRCI: Could not swap gem pouches.")
        return
      end
      return fill_gem_pouch_with_container(gem_pouch_adjective, gem_pouch_noun, source_container, full_pouch_container, spare_gem_pouch_container, should_tie_gem_pouches, retries: retries - 1)
    end

    # Optionally tie the pouch after successful fill
    tie_gem_pouch?(gem_pouch_adjective, gem_pouch_noun) if should_tie_gem_pouches
  ensure
    Flags.delete("pouch-full")
  end
end

.get_box_list_in_container(container) ⇒ Array<String>

Lists boxes in a container via RUMMAGE /B.

Parameters:

  • container (String) —

    container noun to rummage

Returns:

  • (Array<String>) —

    list of box descriptions



1526
1527
1528
# File 'documented/dragonrealms/commons/common-items.rb', line 1526

def get_box_list_in_container(container)
  DRC.rummage('B', container)
end

.get_inventory_by_type(type = 'combat') ⇒ Array<String>

Returns a list of item descriptions from the INVENTORY <type|slot> verb output.

Examples:

DRCI.get_inventory_by_type('combat')
#=> ["steel plate helm", "dark leather jerkin with reinforced seams"]

Parameters:

  • type (String) (defaults to: 'combat') —

    inventory type: armor, weapon, fluff, container, combat, or any slot from INVENTORY SLOTS LIST

Returns:

  • (Array<String>) —

    item descriptions with articles stripped

See Also:



2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
# File 'documented/dragonrealms/commons/common-items.rb', line 2048

def get_inventory_by_type(type = 'combat')
  start_pattern = /^All of your |^You aren't wearing anything like that|^Both of your hands are empty/
  end_pattern = /^\[Use INVENTORY HELP/

  snapshot = Lich::Util.issue_command(
    "inventory #{type}",
    start_pattern,
    end_pattern,
    timeout: 5,
    usexml: false,
    include_end: false
  )

  if snapshot.nil? || snapshot.empty?
    Lich::Messaging.msg("bold", "DRCI: No inventory data for type '#{type}'. Valid options: ARMOR, WEAPON, FLUFF, CONTAINER, COMBAT, or any slot from INVENTORY SLOTS LIST.")
    return []
  end

  items_at_feet = snapshot.any? { |line| line.strip.start_with?('Lying at your feet') }

  snapshot
    .map(&:strip)
    .reject { |line| start_pattern.match?(line) || line.empty? }
    .take_while { |line| !items_at_feet || !line.start_with?('Lying at your feet') }
    .map { |item| item.gsub(/^(a|an|some)\s+/, '').gsub(/\s+\(closed\)/, '') }
end

.get_item(item, container = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets an item, optionally from a specific container.

Accepts a single container or an array of containers to try in order. Delegates to get_item_safe with "my " prefix qualification.

Parameters:

  • item (String) —

    item noun to get

  • container (String, Array<String>, nil) (defaults to: nil) —

    container(s) to try, or nil for default

Returns:

  • (Boolean) —

    true if item was retrieved successfully



1681
1682
1683
1684
1685
1686
1687
1688
1689
# File 'documented/dragonrealms/commons/common-items.rb', line 1681

def get_item(item, container = nil)
  if container.is_a?(Array)
    container.each do |c|
      return true if get_item_safe(item, c)
    end
    return false
  end
  get_item_safe(item, container)
end

.get_item?(item, container = nil) ⇒ Boolean

Gets an item, optionally from a specific container.

Predicate-named convenience wrapper for get_item.

Examples:

Get from default storage

DRCI.get_item?("sword")

Get from specific container

DRCI.get_item?("bandages", "backpack")

Parameters:

  • item (String) —

    item noun to get

  • container (String, Array<String>, nil) (defaults to: nil) —

    container noun, array of containers to try, or nil

Returns:

  • (Boolean) —

    true if item was retrieved successfully

See Also:



1668
1669
1670
# File 'documented/dragonrealms/commons/common-items.rb', line 1668

def get_item?(item, container = nil)
  get_item(item, container)
end

.get_item_from_eddy_portal?(item, container) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets an item from an eddy portal after forcing a content refresh.

Workaround for a game change where you must LOOK in the portal before its contents are available for retrieval.

Parameters:

  • item (String) —

    item name to get

  • container (String) —

    portal container reference

Returns:

  • (Boolean) —

    true if item was retrieved successfully

See Also:



1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
# File 'documented/dragonrealms/commons/common-items.rb', line 1772

def get_item_from_eddy_portal?(item, container)
  # Ensure the eddy is open then look in it to force the contents to be loaded.
  return false unless DRCI.open_container?('my eddy') && DRCI.look_in_container('portal in my eddy')

  from = container
  from = "from #{container}" if container && !(container =~ /^(in|on|under|behind|from) /i)
  case DRC.bput("get #{item} #{from}", GET_ITEM_SUCCESS_PATTERNS, GET_ITEM_FAILURE_PATTERNS)
  when *GET_ITEM_SUCCESS_PATTERNS
    return true
  else
    return false
  end
end

.get_item_if_not_held?(item, container = nil) ⇒ Boolean

Gets an item only if not already held in either hand.

Avoids getting a duplicate when you already have the item. Returns true if the item is already in hand or was successfully retrieved.

Examples:

DRCI.get_item_if_not_held?("almanac")
DRCI.get_item_if_not_held?("sword", "backpack")

Parameters:

  • item (String) —

    item noun to get

  • container (String, nil) (defaults to: nil) —

    container to get from, or nil for default

Returns:

  • (Boolean) —

    true if item is now in hand

See Also:



1646
1647
1648
1649
1650
1651
# File 'documented/dragonrealms/commons/common-items.rb', line 1646

def get_item_if_not_held?(item, container = nil)
  return false unless item
  return true if in_hands?(item)

  return get_item(item, container)
end

.get_item_list(container, verb = 'rummage') ⇒ Array<String>?

Lists items in a container using RUMMAGE or LOOK.

RUMMAGE returns full tap descriptions (e.g., "grey ice skates with black laces"). LOOK returns short names (e.g., "grey ice skates"), which is easier to parse.

Examples:

DRCI.get_item_list("backpack", "look")

Parameters:

  • container (String) —

    container noun to inspect

  • verb (String) (defaults to: 'rummage') —

    "rummage" or "look"

Returns:

  • (Array<String>, nil) —

    list of item descriptions, or nil on failure

See Also:



2089
2090
2091
2092
2093
2094
2095
2096
# File 'documented/dragonrealms/commons/common-items.rb', line 2089

def get_item_list(container, verb = 'rummage')
  case verb
  when /^(r|rummage)$/i
    rummage_container(container)
  when /^(l|look)$/i
    look_in_container(container)
  end
end

.get_item_safe(item, container = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets an item with "my " prefix on item and container names.

Predicate-named convenience wrapper for get_item_safe?.

Parameters:

  • item (String) —

    item noun to get

  • container (String, nil) (defaults to: nil) —

    container noun, or nil for default

Returns:

  • (Boolean) —

    true if item was retrieved successfully



1711
1712
1713
# File 'documented/dragonrealms/commons/common-items.rb', line 1711

def get_item_safe(item, container = nil)
  get_item_safe?(item, container)
end

.get_item_safe?(item, container = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets an item with "my " prefix on item and container names.

Parameters:

  • item (String) —

    item noun to get

  • container (String, nil) (defaults to: nil) —

    container noun, or nil for default

Returns:

  • (Boolean) —

    true if item was retrieved successfully



1697
1698
1699
1700
1701
# File 'documented/dragonrealms/commons/common-items.rb', line 1697

def get_item_safe?(item, container = nil)
  item = item_ref(item)
  container = item_ref(container) if container && !(container =~ /^(in|on|under|behind|from) /i)
  get_item_unsafe(item, container)
end

.get_item_unsafe(item, container = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets an item without "my " prefix qualification.

Issues the GET command, then verifies success by checking whether the item's noun appears in either hand via the XML game-object feed (+in_hands?+) rather than relying on text-pattern matching of the game response. This avoids false positives from combat messages (e.g. "You get a startling sensation" matching /^You get/).

The success and failure patterns are still passed to bput so it returns promptly once the game has responded, but the return value of bput is not used to determine success.

A short polling loop (up to 1 second) accommodates XML feed lag between the text response and the GameObj update.

Examples:

Basic retrieval

get_item_unsafe("backpack")  #=> true (if backpack is now in hand)

With container

get_item_unsafe("sword", "chest")  #=> true

Parameters:

  • item (String) —

    item name (unqualified)

  • container (String, nil) (defaults to: nil) —

    container name (unqualified), or nil

Returns:

  • (Boolean) —

    true if item was retrieved successfully

See Also:



1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
# File 'documented/dragonrealms/commons/common-items.rb', line 1743

def get_item_unsafe(item, container = nil)
  from = container
  from = "from #{container}" if container && !(container =~ /^(in|on|under|behind|from) /i)

  noun = DRC.get_noun(item)
  DRC.bput("get #{item} #{from}", GET_ITEM_FAILURE_PATTERNS, GET_ITEM_SUCCESS_PATTERNS)

  10.times do
    break if in_hands?(noun)
    sleep 0.1
  end

  return true if in_hands?(noun)
  return get_item_from_eddy_portal?(item, container) if container =~ /\bportal\b/i

  false
end

.get_scroll_list_in_container(container) ⇒ Array<String>

Lists scrolls in a container via RUMMAGE /SC.

Parameters:

  • container (String) —

    container noun to rummage

Returns:

  • (Array<String>) —

    list of scroll descriptions



1534
1535
1536
# File 'documented/dragonrealms/commons/common-items.rb', line 1534

def get_scroll_list_in_container(container)
  DRC.rummage('SC', container)
end

.give_item?(target, item = nil, retries: 5) ⇒ Boolean?

Gives a held item to a target (player or NPC).

Handles retry prompts, expired offers, and hand-swap scenarios. Uses a 35-second timeout to allow the target time to accept.

Examples:

Give to NPC for repair

DRCI.give_item?("Ragge", "sword")

Parameters:

  • target (String) —

    player name or NPC noun to give to

  • item (String, nil) (defaults to: nil) —

    item noun, or nil to give whatever is held

  • retries (Integer) (defaults to: 5) —

    remaining retry attempts before giving up (default 5)

Returns:

  • (Boolean, nil) —

    true if accepted, false if declined/failed, nil on edge cases

See Also:



2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
# File 'documented/dragonrealms/commons/common-items.rb', line 2305

def give_item?(target, item = nil, retries: 5)
  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: give_item? exceeded max retries")
    return false
  end

  command = item ? "give #{item_ref(item)} to #{target}" : "give #{target}"
  case DRC.bput(command, { 'timeout' => 35 }, /GIVE it again/, /give it to me again/, /^You don't need to specify the object/, /already has an outstanding offer/, GIVE_ITEM_SUCCESS_PATTERNS, GIVE_ITEM_FAILURE_PATTERNS)
  when *GIVE_ITEM_SUCCESS_PATTERNS
    true
  when *GIVE_ITEM_FAILURE_PATTERNS
    false
  when /give it to me again/
    give_item?(target, item, retries: retries - 1)
  when /already has an outstanding offer/
    pause 5
    give_item?(target, item, retries: retries - 1)
  when /GIVE it again/
    waitrt
    give_item?(target, item, retries: retries - 1)
  when /You don't need to specify the object/
    if in_right_hand?(item)
      give_item?(target, retries: retries - 1)
    elsif in_left_hand?(item)
      case DRC.bput('swap', *SWAP_HANDS_SUCCESS_PATTERNS, *SWAP_HANDS_FAILURE_PATTERNS)
      when *SWAP_HANDS_SUCCESS_PATTERNS
        give_item?(target, retries: retries - 1)
      else
        false
      end
    else
      Lich::Messaging.msg("bold", "DRCI: give_item? could not find '#{item}' in either hand")
      false
    end
  end
end

.have_item_by_look?(item, container) ⇒ Boolean

Checks if an item exists in a container by LOOKing at it.

Unlike exists? which uses TAP, this uses LOOK AT which can find items inside containers that TAP cannot reach.

Parameters:

  • item (String) —

    item noun to look for

  • container (String) —

    container noun to look in

Returns:

  • (Boolean) —

    true if item is found in the container



1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
# File 'documented/dragonrealms/commons/common-items.rb', line 1387

def have_item_by_look?(item, container)
  return false unless item

  item = item.delete_prefix('my ')
  # For item IDs, don't add preposition with 'my' - just use 'in' for the container
  if container&.start_with?('#')
    preposition = 'in' if container && !(container =~ /^(in|on|under|behind|from) /i)
  else
    preposition = 'in my' if container && !(container =~ /^((in|on|under|behind|from) )?my /i)
  end

  case DRC.bput("look at #{item_ref(item)} #{preposition} #{container}", item, /^You see nothing unusual/, /^I could not find/, /^What were you referring to/)
  when /You see nothing unusual/, item
    true
  else
    false
  end
end

.in_hand?(item, which_hand = 'either') ⇒ Boolean

Checks if an item is in one or more hands.

Accepts a string noun or a Lich::DragonRealms::DRC::Item object. Strings are converted to Item objects for regex matching against hand contents.

Examples:

Check either hand

DRCI.in_hand?("sword")

Check specific hand

DRCI.in_hand?("shield", "left")

Parameters:

  • item (String, DRC::Item) —

    item noun or Item object

  • which_hand (String) (defaults to: 'either') —

    "left", "right", "either", or "both"

Returns:

  • (Boolean) —

    true if item is in the specified hand(s)



1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
# File 'documented/dragonrealms/commons/common-items.rb', line 1360

def in_hand?(item, which_hand = 'either')
  return false unless item

  item = DRC::Item.from_text(item) if item.is_a?(String)
  case which_hand.downcase
  when 'left'
    !!(DRC.left_hand =~ item.short_regex)
  when 'right'
    !!(DRC.right_hand =~ item.short_regex)
  when 'either'
    in_left_hand?(item) || in_right_hand?(item)
  when 'both'
    in_left_hand?(item) && in_right_hand?(item)
  else
    Lich::Messaging.msg("bold", "DRCI: Unknown hand: #{which_hand}. Valid options are: left, right, either, both")
    false
  end
end

.in_hands?(item) ⇒ Boolean

Checks if the item is in either hand.

Parameters:

Returns:

  • (Boolean) —

    true if item is in either hand

See Also:



1322
1323
1324
# File 'documented/dragonrealms/commons/common-items.rb', line 1322

def in_hands?(item)
  in_hand?(item, 'either')
end

.in_left_hand?(item) ⇒ Boolean

Checks if the item is in the left hand.

Parameters:

Returns:

  • (Boolean) —

    true if item is in the left hand

See Also:



1332
1333
1334
# File 'documented/dragonrealms/commons/common-items.rb', line 1332

def in_left_hand?(item)
  in_hand?(item, 'left')
end

.in_right_hand?(item) ⇒ Boolean

Checks if the item is in the right hand.

Parameters:

Returns:

  • (Boolean) —

    true if item is in the right hand

See Also:



1342
1343
1344
# File 'documented/dragonrealms/commons/common-items.rb', line 1342

def in_right_hand?(item)
  in_hand?(item, 'right')
end

.inside?(item, container = nil) ⇒ Boolean

Checks if an item is inside a container by tapping it.

Parameters:

  • item (String) —

    item noun to check

  • container (String, nil) (defaults to: nil) —

    container noun to check, or nil for any

Returns:

  • (Boolean) —

    true if item is inside a container



1278
1279
1280
# File 'documented/dragonrealms/commons/common-items.rb', line 1278

def inside?(item, container = nil)
  !!(tap(item, container) =~ /inside/)
end

.item_ref(value) ⇒ String?

Prepends "my " to an item or container name for ownership qualification.

Skips the prefix when the value is nil, already starts with "my ", or uses item ID syntax (starts with "#").

Examples:

DRCI.item_ref("sword")       #=> "my sword"
DRCI.item_ref("my sword")    #=> "my sword"
DRCI.item_ref("#12345")       #=> "#12345"
DRCI.item_ref(nil)            #=> nil

Parameters:

  • value (String, nil) —

    item or container noun

Returns:

  • (String, nil) —

    qualified name, or nil if value was nil



65
66
67
68
69
# File 'documented/dragonrealms/commons/common-items.rb', line 65

def item_ref(value)
  return value if value.nil? || value =~ /^(my |#)/i

  "my #{value}"
end

.lift?(item = nil, stow = nil) ⇒ Boolean

Lifts an item from the ground, optionally stowing it afterward.

Examples:

Lift only

DRCI.lift?("sword")

Lift and stow to default

DRCI.lift?("sword", true)

Lift and put in specific container

DRCI.lift?("sword", "backpack")

Parameters:

  • item (String, nil) (defaults to: nil) —

    item noun to lift (uses last word only)

  • stow (String, Boolean, nil) (defaults to: nil) —

    if a String, puts item in that container; if true, stows to default container; if nil/false, just lifts

Returns:

  • (Boolean) —

    true if lifted (and optionally stowed) successfully



2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
# File 'documented/dragonrealms/commons/common-items.rb', line 2006

def lift?(item = nil, stow = nil)
  return false unless item

  item = item.split.last # Necessary until adjectives are implemented for lift
  case DRC.bput("lift #{item}", LIFT_SUCCESS_PATTERNS, LIFT_FAILURE_PATTERNS)
  when *LIFT_SUCCESS_PATTERNS
    if stow.is_a?(String)
      put_away_item?(item, stow)
    elsif stow
      stow_item?(item)
    else
      true
    end
  else
    false
  end
end

.list_container_contents(verb, container, retries: 2) {|String| ... } ⇒ Array<String>?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Shared implementation for listing container contents with retry and closed-container recovery. Callers provide a block to parse the game response into an item list.

Parameters:

  • verb (String) —

    command verb ("rummage" or "look in")

  • container (String) —

    container noun

  • retries (Integer) (defaults to: 2) —

    remaining retry attempts

Yields:

  • (String) —

    game response text for parsing

Yield Returns:

  • (Array<String>) —

    parsed item list

Returns:

  • (Array<String>, nil) —

    parsed items, empty array if empty, nil on failure



2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
# File 'documented/dragonrealms/commons/common-items.rb', line 2148

def list_container_contents(verb, container, retries: 2, &parse_block)
  container = item_ref(container)

  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: #{verb} exceeded max retries")
    return nil
  end

  contents = DRC.bput("#{verb} #{container}", CONTAINER_IS_CLOSED_PATTERNS, RUMMAGE_SUCCESS_PATTERNS, RUMMAGE_FAILURE_PATTERNS)
  case contents
  when *RUMMAGE_FAILURE_PATTERNS
    Lich::Messaging.msg("bold", "DRCI: Unable to #{verb} '#{container}'.")
    nil
  when *CONTAINER_IS_CLOSED_PATTERNS
    unless open_container?(container)
      Lich::Messaging.msg("bold", "DRCI: Unable to open '#{container}' for #{verb}.")
      return nil
    end

    list_container_contents(verb, container, retries: retries - 1, &parse_block)
  when /there is nothing/i
    []
  else
    parse_block.call(contents)
  end
end

.look_in_container(container, retries: 2) ⇒ Array<String>?

Lists items in a container via LOOK IN.

Returns short item names. Automatically opens closed containers before looking.

Parameters:

  • container (String) —

    container noun to look in

  • retries (Integer) (defaults to: 2) —

    remaining retry attempts before giving up (default 2)

Returns:

  • (Array<String>, nil) —

    list of item descriptions, or nil if cannot access container



2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
# File 'documented/dragonrealms/commons/common-items.rb', line 2125

def look_in_container(container, retries: 2)
  list_container_contents("look in", container, retries: retries) do |contents|
    match = contents.match(/In the .* you see (?:some|an|a) (?<items>.*)\./)
    next [] unless match

    match[:items]
      .split(/(?:,|and) (?:some|an|a)/)
      .map(&:strip)
  end
end

.lower_item?(item) ⇒ Boolean

Lowers a held item to the ground (feet slot).

Determines which hand holds the item, then issues LOWER GROUND.

Examples:

DRCI.lower_item?("sword")

Parameters:

  • item (String) —

    item noun to lower

Returns:

  • (Boolean) —

    true if item was lowered successfully, false if not held or failed



1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
# File 'documented/dragonrealms/commons/common-items.rb', line 1978

def lower_item?(item)
  return false unless in_hands?(item)

  item_regex = /\b#{item}\b/
  hand = (DRC.left_hand =~ item_regex) ? 'left' : 'right'
  case DRC.bput("lower ground #{hand}", *LOWER_SUCCESS_PATTERNS, *LOWER_FAILURE_PATTERNS)
  when *LOWER_SUCCESS_PATTERNS
    true
  else
    false
  end
end

.open_container?(container) ⇒ Boolean

Opens a container.

Parameters:

  • container (String) —

    container noun to open

Returns:

  • (Boolean) —

    true if container was opened (or already open)

See Also:



2265
2266
2267
2268
2269
2270
2271
# File 'documented/dragonrealms/commons/common-items.rb', line 2265

def open_container?(container)
  case DRC.bput("open #{container}", OPEN_CONTAINER_SUCCESS_PATTERNS, OPEN_CONTAINER_FAILURE_PATTERNS)
  when *OPEN_CONTAINER_SUCCESS_PATTERNS
    return true
  end
  return false
end

.put_away_item?(item, container = nil) ⇒ Boolean

Puts away a held item, optionally into a specific container.

If no container is specified, uses the default stow location. Accepts an array of containers to try in order (useful when some may be full).

Examples:

Stow to default location

DRCI.put_away_item?("sword")

Put in specific container

DRCI.put_away_item?("sword", "backpack")

Try multiple containers

DRCI.put_away_item?("gem", ["pouch", "sack", "backpack"])

Parameters:

  • item (String) —

    item noun to put away

  • container (String, Array<String>, nil) (defaults to: nil) —

    container noun, array of containers, or nil

Returns:

  • (Boolean) —

    true if item was put away successfully

See Also:



2199
2200
2201
2202
2203
2204
2205
2206
2207
# File 'documented/dragonrealms/commons/common-items.rb', line 2199

def put_away_item?(item, container = nil)
  if container.is_a?(Array)
    container.each do |c|
      return true if put_away_item_safe?(item, c)
    end
    return false
  end
  put_away_item_safe?(item, container)
end

.put_away_item_safe?(item, container = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Puts away an item with "my " prefix on item and container names.

Parameters:

  • item (String) —

    item noun to put away

  • container (String, nil) (defaults to: nil) —

    container noun, or nil for default

Returns:

  • (Boolean) —

    true if item was put away successfully



2215
2216
2217
# File 'documented/dragonrealms/commons/common-items.rb', line 2215

def put_away_item_safe?(item, container = nil)
  put_away_item_unsafe?(item_ref(item), item_ref(container))
end

.put_away_item_unsafe?(item, container = nil, preposition = "in", retries: 3) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Puts away an item without "my " prefix qualification.

Supports custom prepositions (e.g., "on", "under") and retries on closed containers or retry-pattern responses.

Parameters:

  • item (String) —

    item name (unqualified)

  • container (String, nil) (defaults to: nil) —

    container name (unqualified), or nil for default stow

  • preposition (String) (defaults to: "in") —

    container preposition ("in", "on", "under", etc.)

  • retries (Integer) (defaults to: 3) —

    remaining retry attempts before giving up (default 3)

Returns:

  • (Boolean) —

    true if item was put away successfully



2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
# File 'documented/dragonrealms/commons/common-items.rb', line 2230

def put_away_item_unsafe?(item, container = nil, preposition = "in", retries: 3)
  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: put_away_item_unsafe? exceeded max retries")
    return false
  end

  command = "put #{item} #{preposition} #{container}" if container
  command = "stow #{item}" unless container
  result = DRC.bput(command, CONTAINER_IS_CLOSED_PATTERNS, PUT_AWAY_ITEM_SUCCESS_PATTERNS, PUT_AWAY_ITEM_FAILURE_PATTERNS, PUT_AWAY_ITEM_RETRY_PATTERNS)
  case result
  when *CONTAINER_IS_CLOSED_PATTERNS
    return false unless container && open_container?(container)

    return put_away_item_unsafe?(item, container, preposition, retries: retries - 1)
  when *PUT_AWAY_ITEM_RETRY_PATTERNS
    return put_away_item_unsafe?(item, container, preposition, retries: retries - 1)
  when *PUT_AWAY_ITEM_SUCCESS_PATTERNS
    return true
  when *PUT_AWAY_ITEM_FAILURE_PATTERNS
    return false
  else
    return false
  end
end

.remove_and_stow_pouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container = nil) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Removes the current gem pouch and stows it in a container.

Parameters:

  • gem_pouch_adjective (String) —

    pouch adjective (e.g., "black")

  • gem_pouch_noun (String) —

    pouch noun (e.g., "pouch")

  • full_pouch_container (String, nil) (defaults to: nil) —

    container for the full pouch, or nil for default

Returns:

  • (Boolean) —

    true if removed and stowed successfully



2421
2422
2423
2424
2425
2426
2427
2428
# File 'documented/dragonrealms/commons/common-items.rb', line 2421

def remove_and_stow_pouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container = nil)
  pouch = "#{gem_pouch_adjective} #{gem_pouch_noun}"
  unless remove_item?(pouch)
    Lich::Messaging.msg("bold", "DRCI: Unable to remove existing pouch.")
    return false
  end
  put_away_item?(pouch, full_pouch_container) || stow_item?(pouch)
end

.remove_item?(item) ⇒ Boolean

Removes a worn item into your hands.

Issues the REMOVE command with "my " prefix qualification.

Examples:

DRCI.remove_item?("cloak")

Parameters:

  • item (String) —

    item noun to remove

Returns:

  • (Boolean) —

    true if item was removed successfully

See Also:



1884
1885
1886
# File 'documented/dragonrealms/commons/common-items.rb', line 1884

def remove_item?(item)
  remove_item_safe?(item)
end

.remove_item_safe?(item) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Removes a worn item with "my " prefix qualification.

Parameters:

  • item (String) —

    item noun to remove

Returns:

  • (Boolean) —

    true if item was removed successfully



1893
1894
1895
# File 'documented/dragonrealms/commons/common-items.rb', line 1893

def remove_item_safe?(item)
  remove_item_unsafe?(item_ref(item))
end

.remove_item_unsafe?(item) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Removes a worn item without "my " prefix qualification.

Parameters:

  • item (String) —

    item name (unqualified)

Returns:

  • (Boolean) —

    true if item was removed successfully



1902
1903
1904
1905
1906
1907
1908
1909
# File 'documented/dragonrealms/commons/common-items.rb', line 1902

def remove_item_unsafe?(item)
  case DRC.bput("remove #{item}", REMOVE_ITEM_SUCCESS_PATTERNS, REMOVE_ITEM_FAILURE_PATTERNS)
  when *REMOVE_ITEM_SUCCESS_PATTERNS
    return true
  else
    return false
  end
end

.rummage_container(container, retries: 2) ⇒ Array<String>?

Lists items in a container via RUMMAGE.

Returns full tap descriptions. Automatically opens closed containers before rummaging.

Parameters:

  • container (String) —

    container noun to rummage

  • retries (Integer) (defaults to: 2) —

    remaining retry attempts before giving up (default 2)

Returns:

  • (Array<String>, nil) —

    list of item descriptions, or nil if cannot access container



2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
# File 'documented/dragonrealms/commons/common-items.rb', line 2106

def rummage_container(container, retries: 2)
  list_container_contents("rummage", container, retries: retries) do |contents|
    match = contents.match(/You rummage through .* and see (?:a|an|some) (?<items>.*)\./)
    next [] unless match

    match[:items] # Get string of just the comma separated item list
      .sub(/ and (?=a|an|some)/, ", ") # replace " and " for the last item into " , "
      .split(/, (?:a|an|some) /) # Split at a, an, or some, but only when it follows a comma
  end
end

.search?(item) ⇒ Boolean

Searches inventory for an item using the INV SEARCH command.

Examples:

DRCI.search?("deed")  #=> true if found

Parameters:

  • item (String) —

    item noun to search for

Returns:

  • (Boolean) —

    true if item is found in inventory



1261
1262
1263
# File 'documented/dragonrealms/commons/common-items.rb', line 1261

def search?(item)
  !!(DRC.bput("inv search #{item}", /^You can't seem to find anything/, /(?:An?|Some) .+ is (?:in|being)/) =~ /(?:An?|Some) .+ is (?:in|being)/)
end

.stow_hand(hand, retries: 3) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Stows whatever is in the specified hand.

Handles braids that are too long by disposing them as trash.

Parameters:

  • hand (String) —

    "right" or "left"

  • retries (Integer) (defaults to: 3) —

    remaining retry attempts before giving up (default 3)

Returns:

  • (Boolean) —

    true if the hand is now empty



1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
# File 'documented/dragonrealms/commons/common-items.rb', line 1608

def stow_hand(hand, retries: 3)
  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: stow_hand exceeded max retries")
    return false
  end

  result = DRC.bput("stow #{hand}", BRAID_TOO_LONG_PATTERN, CONTAINER_IS_CLOSED_PATTERNS, STOW_ITEM_SUCCESS_PATTERNS, STOW_ITEM_FAILURE_PATTERNS, STOW_ITEM_RETRY_PATTERNS)
  braid_match = result&.match(BRAID_TOO_LONG_PATTERN)
  if braid_match
    dispose_trash(DRC.get_noun(braid_match[:braid_name]))
  elsif STOW_ITEM_RETRY_PATTERNS.any? { |pat| pat.match?(result) }
    stow_hand(hand, retries: retries - 1)
  elsif STOW_ITEM_SUCCESS_PATTERNS.any? { |pat| pat.match?(result) }
    true
  else
    false
  end
end

.stow_hands ⇒ Boolean

Stows whatever is held in both hands.

Skips empty hands. Returns true only if both hands are empty or successfully stowed.

Returns:

  • (Boolean) —

    true if both hands are now empty

See Also:



1583
1584
1585
1586
# File 'documented/dragonrealms/commons/common-items.rb', line 1583

def stow_hands
  (!DRC.left_hand || stow_hand('left')) &&
    (!DRC.right_hand || stow_hand('right'))
end

.stow_item?(item) ⇒ Boolean

Stows an item into its default container (per STORE HELP settings).

Issues the STOW command with "my " prefix qualification. Retries automatically on retry-pattern responses.

Examples:

DRCI.stow_item?("sword")

Parameters:

  • item (String) —

    item noun to stow

Returns:

  • (Boolean) —

    true if item was stowed successfully

See Also:



1927
1928
1929
# File 'documented/dragonrealms/commons/common-items.rb', line 1927

def stow_item?(item)
  stow_item_safe?(item)
end

.stow_item_safe?(item) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Stows an item with "my " prefix qualification.

Parameters:

  • item (String) —

    item noun to stow

Returns:

  • (Boolean) —

    true if item was stowed successfully



1936
1937
1938
# File 'documented/dragonrealms/commons/common-items.rb', line 1936

def stow_item_safe?(item)
  stow_item_unsafe?(item_ref(item))
end

.stow_item_unsafe?(item, retries: 3) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Without "my " prefix, may attempt to stow an item on the ground rather than one in your inventory.

Stows an item without "my " prefix qualification.

Parameters:

  • item (String) —

    item name (unqualified)

  • retries (Integer) (defaults to: 3) —

    remaining retry attempts before giving up (default 3)

Returns:

  • (Boolean) —

    true if item was stowed successfully



1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
# File 'documented/dragonrealms/commons/common-items.rb', line 1949

def stow_item_unsafe?(item, retries: 3)
  if retries <= 0
    Lich::Messaging.msg("bold", "DRCI: stow_item_unsafe? exceeded max retries")
    return false
  end

  case DRC.bput("stow #{item}", CONTAINER_IS_CLOSED_PATTERNS, STOW_ITEM_SUCCESS_PATTERNS, STOW_ITEM_FAILURE_PATTERNS, STOW_ITEM_RETRY_PATTERNS)
  when *STOW_ITEM_RETRY_PATTERNS
    return stow_item_unsafe?(item, retries: retries - 1)
  when *STOW_ITEM_SUCCESS_PATTERNS
    return true
  else
    return false
  end
end

.swap_out_full_gempouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container = nil, spare_gem_pouch_container = nil, should_tie_gem_pouches = false) ⇒ Boolean

Swaps a full gem pouch for a spare one.

Removes and stows the current pouch, then checks the belt for an existing spare before getting one from the spare container.

Parameters:

  • gem_pouch_adjective (String) —

    pouch adjective (e.g., "black")

  • gem_pouch_noun (String) —

    pouch noun (e.g., "pouch")

  • full_pouch_container (String, nil) (defaults to: nil) —

    container for the full pouch

  • spare_gem_pouch_container (String, nil) (defaults to: nil) —

    container holding spare pouches

  • should_tie_gem_pouches (Boolean) (defaults to: false) —

    whether to tie the new pouch

Returns:

  • (Boolean) —

    true if swap completed successfully



2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
# File 'documented/dragonrealms/commons/common-items.rb', line 2441

def swap_out_full_gempouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container = nil, spare_gem_pouch_container = nil, should_tie_gem_pouches = false)
  unless DRC.left_hand.nil? || DRC.right_hand.nil?
    Lich::Messaging.msg("bold", "DRCI: No free hand. Not swapping pouches now.")
    return false
  end

  unless remove_and_stow_pouch?(gem_pouch_adjective, gem_pouch_noun, full_pouch_container)
    Lich::Messaging.msg("bold", "DRCI: Remove and stow pouch routine failed.")
    return false
  end

  pouch = "#{gem_pouch_adjective} #{gem_pouch_noun}"

  # Check if there's already another pouch on the belt before getting from spare container
  if check_belt_for_pouch?(gem_pouch_adjective, gem_pouch_noun)
    Lich::Messaging.msg("plain", "DRCI: Found existing #{pouch} on belt, using that.")
    unless untie_item?(pouch)
      Lich::Messaging.msg("bold", "DRCI: Could not untie existing pouch on belt.")
      return false
    end
  elsif !get_item?(pouch, spare_gem_pouch_container)
    Lich::Messaging.msg("bold", "DRCI: No spare pouch found in #{spare_gem_pouch_container || 'default container'}.")
    return false
  end

  unless wear_item?(pouch)
    Lich::Messaging.msg("bold", "DRCI: Could not wear new pouch.")
    return false
  end

  if should_tie_gem_pouches && !tie_gem_pouch?(gem_pouch_adjective, gem_pouch_noun)
    Lich::Messaging.msg("bold", "DRCI: Could not tie new pouch.")
    # Not a fatal error - pouch is worn, just not tied
  end

  true
end

.tap(item, container = nil) ⇒ String?

Taps an item and returns the game response string.

The tap response indicates whether the item is worn, inside a container, etc. Used by wearing?, inside?, and exists?.

Parameters:

  • item (String) —

    item noun to tap

  • container (String, nil) (defaults to: nil) —

    container to qualify the tap, or nil for general inventory

Returns:

  • (String, nil) —

    game response text, or nil if item is nil



1308
1309
1310
1311
1312
1313
1314
# File 'documented/dragonrealms/commons/common-items.rb', line 1308

def tap(item, container = nil)
  return nil unless item

  from = container
  from = "from #{item_ref(container)}" if container && !(container =~ /^(in|on|under|behind|from) /i)
  DRC.bput("tap #{item_ref(item)} #{from}", *TAP_SUCCESS_PATTERNS, *TAP_FAILURE_PATTERNS)
end

.tie_gem_pouch(gem_pouch_adjective, gem_pouch_noun) ⇒ Object

Deprecated.

Use tie_gem_pouch? instead for boolean return value.



2408
2409
2410
2411
2412
# File 'documented/dragonrealms/commons/common-items.rb', line 2408

def tie_gem_pouch(gem_pouch_adjective, gem_pouch_noun)
  unless tie_gem_pouch?(gem_pouch_adjective, gem_pouch_noun)
    Lich::Messaging.msg("bold", "DRCI: Failed to tie #{gem_pouch_adjective} #{gem_pouch_noun}.")
  end
end

.tie_gem_pouch?(gem_pouch_adjective, gem_pouch_noun) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Ties a gem pouch.

Parameters:

  • gem_pouch_adjective (String) —

    pouch adjective (e.g., "black")

  • gem_pouch_noun (String) —

    pouch noun (e.g., "pouch")

Returns:

  • (Boolean) —

    true if tied successfully or already tied



2403
2404
2405
# File 'documented/dragonrealms/commons/common-items.rb', line 2403

def tie_gem_pouch?(gem_pouch_adjective, gem_pouch_noun)
  tie_item?("#{gem_pouch_adjective} #{gem_pouch_noun}")
end

.tie_item?(item, container = nil) ⇒ Boolean

Ties an item, optionally to a specific container.

Examples:

Tie to belt

DRCI.tie_item?("pouch", "belt")

Parameters:

  • item (String) —

    item noun to tie

  • container (String, nil) (defaults to: nil) —

    container to tie to, or nil for default

Returns:

  • (Boolean) —

    true if item was tied successfully

See Also:



1800
1801
1802
1803
1804
1805
1806
1807
1808
# File 'documented/dragonrealms/commons/common-items.rb', line 1800

def tie_item?(item, container = nil)
  place = container ? "to #{item_ref(container)}" : nil
  case DRC.bput("tie #{item_ref(item)} #{place}", TIE_ITEM_SUCCESS_PATTERNS, TIE_ITEM_FAILURE_PATTERNS)
  when *TIE_ITEM_SUCCESS_PATTERNS
    true
  else
    false
  end
end

.trash_storage ⇒ Array<String>

Recognized trash-receptacle nouns: the built-in TRASH_STORAGE defaults merged with the player's custom_trash_storage additions. Lets a player teach dispose_trash about a receptacle their town has that Lich does not yet know, without a Lich release.

Returns:

  • (Array<String>) —

    recognized trash-receptacle nouns

See Also:



84
85
86
# File 'documented/dragonrealms/commons/common-items.rb', line 84

def trash_storage
  CustomSubstitutions.resolve(:custom_trash_storage, TRASH_STORAGE, type: :names)
end

.untie_item?(item, container = nil) ⇒ Boolean

Unties an item, optionally from a specific container.

Parameters:

  • item (String) —

    item noun to untie

  • container (String, nil) (defaults to: nil) —

    container to untie from, or nil for default

Returns:

  • (Boolean) —

    true if item was untied successfully

See Also:



1817
1818
1819
1820
1821
1822
1823
1824
1825
# File 'documented/dragonrealms/commons/common-items.rb', line 1817

def untie_item?(item, container = nil)
  place = container ? "from #{item_ref(container)}" : nil
  case DRC.bput("untie #{item_ref(item)} #{place}", UNTIE_ITEM_SUCCESS_PATTERNS, UNTIE_ITEM_FAILURE_PATTERNS)
  when *UNTIE_ITEM_SUCCESS_PATTERNS
    true
  else
    false
  end
end

.wear_item?(item) ⇒ Boolean

Wears an item from your hands.

Issues the WEAR command with "my " prefix qualification.

Examples:

DRCI.wear_item?("cloak")

Parameters:

  • item (String) —

    item noun to wear

Returns:

  • (Boolean) —

    true if item was worn successfully

See Also:



1842
1843
1844
# File 'documented/dragonrealms/commons/common-items.rb', line 1842

def wear_item?(item)
  wear_item_safe?(item)
end

.wear_item_safe?(item) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Wears an item with "my " prefix qualification.

Parameters:

  • item (String) —

    item noun to wear

Returns:

  • (Boolean) —

    true if item was worn successfully



1851
1852
1853
# File 'documented/dragonrealms/commons/common-items.rb', line 1851

def wear_item_safe?(item)
  wear_item_unsafe?(item_ref(item))
end

.wear_item_unsafe?(item) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Wears an item without "my " prefix qualification.

Parameters:

  • item (String) —

    item name (unqualified)

Returns:

  • (Boolean) —

    true if item was worn successfully



1860
1861
1862
1863
1864
1865
1866
1867
# File 'documented/dragonrealms/commons/common-items.rb', line 1860

def wear_item_unsafe?(item)
  case DRC.bput("wear #{item}", WEAR_ITEM_SUCCESS_PATTERNS, WEAR_ITEM_FAILURE_PATTERNS)
  when *WEAR_ITEM_SUCCESS_PATTERNS
    return true
  else
    return false
  end
end

.wearing?(item) ⇒ Boolean

Checks if an item is currently worn by tapping it.

Parameters:

  • item (String) —

    item noun to check

Returns:

  • (Boolean) —

    true if item is currently worn



1269
1270
1271
# File 'documented/dragonrealms/commons/common-items.rb', line 1269

def wearing?(item)
  !!(tap(item) =~ /wearing/)
end