Inspecting entities

Once you have a creature, object, or room — as $self, $actor, or something pulled from an iterable — you usually need to ask questions about it before acting. This chapter covers reading an entity's attributes, sorting one kind from another, finding where an object sits, and guarding against references that are empty or stale.

Reading attributes

The accessor built-ins read a live entity's current state. They are read-only — they never change the entity (for that, see Changing the world).

Accessor Returns
name display name (string)
vnum vnum / room number (int; players error)
level level (int)
class class name (string)
alignment good / evil / neutral
gen remort generation (int)
position position name (standing, sleeping, …)
room the entity's room (or a vnum resolved to a room)
carrier the creature carrying an object, else null
after command (appraise) {
  echo $actor "[name $actor], a level [level $actor] [class $actor], standing [position $actor]."
  echo $actor "Your alignment reads [alignment $actor]; generation [gen $actor]."
}

room is the bridge between vnums and rooms: [room $self] is the owner's room, while [room 3001] resolves a room vnum. carrier goes the other way for an object — who is holding it:

after get {
  let who [carrier $self]
  unless [isnull $who]
  echo $who "The amulet grows warm in your grasp."
}

(That handler lives on the object: $self is the item, $actor the creature, and the get event fires when it is picked up.)

What kind of thing is this?

The type predicates let one handler treat players, mobs, and objects differently. They each return a bool:

after command (assess) {
  if [ismob $actor] {
    do "say Another of my kind."
  } elif [isfighting $actor] {
    do "say You are in the thick of it!"
  } else {
    do "say Welcome, [name $actor]."
  }
}

Where is this object?

Two questions come up constantly. "Does this creature/room hold an item of vnum N?" is answered by vnum predicates: isholding searches carried/contained objects, and iswearing searches worn gear and implants:

before command (enter) {
  require [isholding $actor 1]      # carrying the token?
  do "say The gate recognises your token."
}

before command (sanctum) {
  require [iswearing $actor 1]      # wearing the sigil?
  do "say The wards admit you."
}

"Where is this specific object right now?" is answered by location, which tests one known object against a place name (carried, container, worn, wielded, held, implanted, room):

after command (inspect) {
  let item [first [inventory $self]]
  require [isobj $item]              # resolves to a live object?
  do "say My [name $item] is carried: [location $item carried]."
}

isobj here doubles as the empty-inventory guard: when first returns null, isobj is false and the handler stops.

The world clock

A couple of accessors describe the world rather than an entity: hour gives the current game hour (0–23) and moonphase the lunar phase. They take no arguments and pair naturally with tick handlers:

handle tick {
  if [lt [hour] 6] {
    do "emote yawns in the pre-dawn gloom."
  }
  if [streqi [moonphase] "full"] {
    do "say The full moon stirs something in me."
  }
}

Presence and staleness

An entity reference resolves to the live thing each time it is read, so it always reflects current state — but the thing it points at can vanish (a mob is killed, an object is purged). A reference whose entity is gone is stale, and resolving it quietly stops the script. Two guards keep you safe:

after command (track) {
  let prey [first [select [creatures $self] &isplayer]]
  if [isnull $prey] {
    do "say No quarry in sight."
  }
  if [exists $prey] {
    do "hunt [name $prey]"
  }
}

Use isnull for "was there anything to begin with?" and exists for "is this remembered reference still valid?" — especially after a pause, when the world may have moved on.

A note on types

Every value has exactly one type: null, bool, int, string, iterable, block, list, and the entity references creature, object, room, mob_proto, and obj_proto. Accessors and predicates expect particular types and raise a run-time type error on a mismatch; convert explicitly when you need to (see Numbers, text, and logic). The prototype types come from mob and object, covered in Changing the world.

See also