:display_message(preamble,msg) --- prints msg to player.
:parse_message_seq from_msg_seq %from_msg_seq to_msg_seq %to_msg_seq subject_msg_seq body_msg_seq kept_msg_seq unkept_msg_seq display_seq_headers display_seq_full messages_in_seq list_rmm new_message_num length_num_le length_date_le length_date_gt length_all_msgs exists_num_eq msg_seq_to_msg_num_list msg_seq_to_msg_num_string rm_message_seq undo_rmm expunge_rmm renumber keep_message_seq - parse_message_seq(strings,cur) => msg_seq
:msg_text(@msg) => list of strings.
:notify_mail(from,recipients[,msgnums])
:current_message([recipient])
:get_current_message([recipient])
:set_current_message(recipient[,number[,date]])
:make_current_message(recipient[,index])
:kill_current_message(recipient)
:current_folder() => default folder to use, always an object, usually `this'
:parse_folder_spec(verb,args,expected_preposition[,allow_trailing_args_p])
:parse_mailread_cmd(verb,args,default,prep[,trailer])
@mail - @mail <msg-sequence> --- as in help @mail
@read @peek - @read <msg>... -- as in help @read
@rmm*ail - @rmm <message-sequence> [from <recipient>]. Use @unrmm if you screw up.
@unrmm*ail - @unrmm [on <recipient>] -- undoes the previous @rmm on that recipient.
@answer @repl*y - @answer <msg> [on *<recipient>] [<flags>...]
@forward - @forward <msg> [on *<recipient>] to <recipient> [<recipient>...]
@skip - @skip [*<folder/mailing_list>...]
@subscribe*-quick @unsubscribed*-quick - @subscribe *<folder/mailing_list> [with notification] [before|after *<folder>]
:mail_option(name)
@unsub*scribe - @unsubscribe [*<folder/mailing_list> ...]
:send_self_netmail(msg [ ,from ])
@netforw*ard - @netforward <msg>... -- as in help on @netforward
@@sendmail - Syntax: @@sendmail
@keep-m*ail @keepm*ail - @keep-mail [<msg-sequence>|none] [on <recipient>]
:my_match_recipient(string) => matches string against player's private mailing lists.
:msg_full_text(@msg) => list of strings.
@resend - @resend <msg> [on *<recipient>] to <recipient> [<recipient>...]
:expirable_msg_seq - Return a sequence indicating the expirable messages for this player.
:format_for_netforward - Takes a message sequence (the actual messages, not just the sequence describing it) and grovels over it filling text etc. Returns a two valued list: {formatted message, header for same}
:format_for_netforward_debug - Takes a message sequence (the actual messages, not just the sequence describing it) and grovels over it filling text etc. Returns a two valued list: {formatted message, header for same} @nn - @nn -- reads the first new message on the first mail_recipient (in .current_message) where new mail exists.
@unread - @unread <msg> [on *<recipient>] -- resets last-read-date for recipient to just before the first of the indicated messages.
@refile @copym*ail - @refile/@copym*ail <msg-sequence> [on <recipient>] to <recipient>
@quickr*eply @qreply - @qreply <msg> [on *<recipient>] [<flags>...]
@mail-all-new*-mail - @mail-all-new-mail
@read-all-new*-mail @ranm - @read-all-new-mail [yes]
@quick*send @qsend - Syntax: @quicksend <recipients(s)> [subj=<text>] [<message>]
@add-notify - Ideally, in order for one person to be notified that another person has new mail, both the mail recipient and the notification recipient should agree that this is an OK transfer of information.
@unsend - USAGE: @unsend [message-sequence] from <player>
:do_unsend(seq) -> Remove the specified messages. Used by @unsend. Cannot be overridden by players or player classes; @unsend won't bother to call the verb.
:my_huh - Extra parsing of player commands. Called by $command_utils:do_huh.
:last_huh(verb,args) final attempt to parse a command...
:my_match_object(string [,location])
:linesplit(line,len) => list of substrings of line
@pagelen*gth - @pagelength number -- sets page buffering to that many lines (or 0 to turn off page buffering)
:set_gaglist(@newlist) => this.gaglist = newlist
:receive_page - called by $player:page. Two args, the page header and the text, all pre-processed by the page command. Could be extended to provide haven abilities, multiline pages, etc. Indeed, at the moment it just does :tell_lines, so we already do have multiline pages, if someone wants to take advantage of it.
:page_origin_msg page_echo_msg page_absent_msg away_msg oaway_msg back_msg oback_msg away_absent_msg - set_task_perms(this.owner)
:display_option(name) => returns the value of the specified @display option
:edit_option(name) => returns the value of the specified edit option
:set_edit_option(oname,value)
:set_name - set_name(newname) attempts to change this.name to newname
:set_aliases - set_aliases(alias_list)
:set_gender - set_gender(newgender) attempts to change this.gender to newgender
:set_brief - set_brief(value)
@mode - @mode <mode>
:add_feature - Add a feature to this player's features list. Caller must be this or have suitable permissions (this or wizardly).
:remove_feature - Remove a feature from this player's features list. Caller must be this, or have permissions of this, a wizard, or feature.owner.
:is_listening - return true if player is active.
:linewrap - Return a true value if this needs linewrapping.
@set-note-string @set-note-text - Usage: @set-note-{string | text} {#xx | #xx.pname}
:set_linelength - Set linelength. Linelength must be an integer >= 10.
:set_pagelength - Set pagelength. Must be an integer >= 5, or 0 to turn pagelength off.
:set_home - set_home(newhome) attempts to change this.home to newhome
@registerme - @registerme as <email-address> -- update your account email address
:ctime([INT time]) => STR as the function.
news - Usage: news [contents] [articles]
@password - Last modified Sun Dec 7 01:44:07 2025 UTC by Claude (#13505@Mongoose).
:title - random april fools jokes :)
@remove-feature @rmfeature - Copied from generic player (#6):@rmfeature [verb author Daiverd (#2)] at Sun Jul 23 09:34:27 2006 PDT
:you - What should this object be replaced with when printing messages about itself to itself?
@sgag*! - Copied from generic player (#6):@gag [verb author Q (#249)] at Fri Jul 14 16:58:44 2023 UTC
:set_sgaglist - Copied from generic player (#6):set_gaglist [verb author daiverd (#2)] at Fri Jul 14 17:03:52 2023 UTC
@listsgag - Copied from generic player (#6):@listgag [verb author daiverd (#2)] at Fri Jul 14 17:05:08 2023 UTC
:sgag_p - Copied from generic player (#6):gag_p [verb author daiverd (#2)] at Fri Jul 14 17:09:09 2023 UTC
@sungag - Copied from generic player (#6):@ungag [verb author daiverd (#2)] at Sat Jul 15 05:01:26 2023 UTC
rps - rps <player> - Challenge another player to rock-paper-scissors
:test_receive_page_gmcp_perms - Property: Comm.Channel send_channel_text accepts $player as a caller for page delivery.
:test_receive_page_gmcp_text - Property: receive_page still returns 1 for listening players after GMCP page emit is added.
:facing_angle - Canonical accessor for player listener facing angle in radians.
:orientation - Canonical accessor for orientation in MOO world coords (east=+x, north=+y, up=+z). Returns forward + up unit vectors; the CLIENT converts to Web Audio. MOO yaw: south=0, east=pi/2, north=pi, west=3pi/2.
:face - Canonical mutator for player listener facing.
:test_orientation_basics - Verify facing_angle stored prop, orientation derivation, face() mutator (not traveling). Vectors are asserted in the CANONICAL MOO frame (east=+x, north=+y, up=+z); the client converts to Web Audio once, on its side. Do NOT reintroduce Web-Audio-frame (+Y up) expectations here.
:test_facing_angle_during_travel - Verify facing_angle returns the current segment angle during a journey.
:face - Canonical mutator for player listener facing.
:test_face_updates_property - Verify face() updates .facing_angle and orientation reflects it (not traveling).
turn - Player command: turn <left|right|around|degrees>
:turn_to - turn_to(target_angle_radians) -> the turn DURATION in seconds (0.0 if negligible/instant). Eases facing to target by driving :face over a duration proportional to the angular distance; supersedes any in-progress turn. Callers may suspend(duration) to await it.
:face_object(target) -> turn to face another object in this room. Returns the new yaw.
:test_face_object_points_at_target - face_object(target) must turn the player toward the target's coordinates, in the canonical yaw frame (south=0, east=pi/2, north=pi, west=3pi/2).
:my_match_object_menu(string [,location]) => like :my_match_object, but when 'string' is GENUINELY ambiguous among the objects you can see (per $string_utils:match), present an interactive menu ($command_utils:menu) of the tied candidates and return the chosen one. Otherwise resolves exactly as :my_match_object. Any command can call this in place of :my_match_object to get disambiguation for free; it never returns $ambiguous_match.
:test_sound_origin_head - $player:sound_origin() -> HEAD height, not box centre. A voice comes from a head, and your own head is where your ears are (the listener position the scene sends). Guards the vertical bug: coordinates() is the min-corner with z=0, so a player's ears sat on the FLOOR and every sound in the room arrived from above.
:sound_origin() -> {x,y,z} at HEAD height. Overrides $gpo's box-centre origin: a voice comes from a head, not a navel, and your own head is where your ears are -- this is the listener position Client.Spatial sends. x,y still centre the footprint (pass()); z is a fraction of stature (ears sit at ~93% of height) so it scales with the body rather than a fixed drop that would go negative on a small one.
:mass - Copied from Root Class (#1):mass [verb author Daiverd (#2)] at Mon Nov 10 23:04:48 2008 CET
:coord*inates coords - coordinates() -> this object's position {x,y,z}. coordinates(list) or coordinates(x,y,z) sets it.
:cube - Copied from Root Class (#1):cube [verb author Daiverd (#2)] at Mon Nov 10 23:12:50 2008 CET
:weight - Copied from Root Class (#1):weight [verb author Daiverd (#2)] at Thu Nov 13 07:04:56 2008 CET
:test_interpolated_coordinates - Position interpolation along a path, via an inert $journey fixture. Segment angles are YAW, exactly as find_path emits them: south=0, east=pi/2, north=pi, west=3pi/2. Do NOT write math-convention angles (0=east) here -- doing so encodes a fiction and hides real bugs in $journey::position.
:test_interpolated_coords_multiseg - Multi-segment interpolation (east 5m then north 5m), via an inert $journey fixture. Segment angles are YAW as find_path emits them: east=pi/2, north=pi. See $journey::position.
:test_stop_travel - Stop freezes coords at the interpolated position and clears the journey. Segment angles are YAW as find_path emits them (east=pi/2); see $journey::position.
:test_arrive - Arrival sets coords to destination and clears the journey.
:test_travel_to - travel_to returns E_INVARG with no path, and clears any prior journey even on failure.
:interpolated_coordinates() -> DEPRECATED alias. coordinates() is now the one canonical live accessor (interpolated during a journey, stored at rest). Kept so existing callers keep working; new code calls :coordinates().
:interact_with(target) - suspends until nearby, kills task if can't reach
:_arrive_and_interact() - Arrival callback that resumes suspended task
:movement_velocity() -> movement speed in m/s
:scene_sounds - Base: a physical object has no replayable sound scene. Rooms ($room #2700) override with the emitter-based scene. Keeps :listen/:stop_listen uniform across all $gpo.
:media_scene_for - Base media scene for scene_source-capable places. Non-room physical objects expose no replayable media scene by default.
:test_cancel_travel_kills_pending - cancel_travel kills the active journey's task AND the suspended walk/interact task, clears pending_interaction, WITHOUT touching coords.
:cancel_travel() - Kill the active journey's task and clear it (and any pending_interaction waiter). Does NOT change coords -- callers that already set a final position (teleport, exit) rely on this. stop_travel adds the freeze-at-interpolated behavior on top.
:test_interact_with_approaches_without_overlap - interact_with should approach into interaction range without overlapping the target.
:test_travel_to_supersede_uses_live_position - test_travel_to_supersede_uses_live_position - a travel_to issued while a journey is in flight must compute start_coords from the LIVE interpolated position, not the stale stored .coords anchor. Regression: travel_to cleared this.journey before reading this:coordinates(), so the live position was already gone. Segment angles are YAW (east=pi/2).
:test_position_honors_find_path_angles - test_position_honors_find_path_angles - $journey::position must interpolate along the SAME angle convention find_path emits (yaw: south=0, east=pi/2, north=pi). Regression: position() used {cos(a),sin(a)} (math convention), so a due-north walk interpolated due WEST for its whole duration; arrive() snapped coords to the destination at the end and hid it. This test derives its path from find_path itself rather than hand-writing angles -- do not replace it with a literal path.
:test_walk_approach_point_avoids_target - approach_point returns an in-bounds point off the target footprint that find_path can route to.
:approach_point(my_coords, my_dims, target_coords, target_dims, ?gap) -> nearest in-bounds point off the target footprint, or {} if none. Shared by walk/run/interact_with so you stop ADJACENT to a target, never on top of it.
:placement([new]) -> the object's canonical allocentric-location anchor. Verb is truth; .placement is storage/cache. With an argument, validate via $spatial_utils and store it. {} means 'free' (raw coords, no anchor). See [[allocentric-location]].
:test_sound_origin - sound_origin() -> the point a sound emanates FROM: the centre of the object's box, not its min-corner. coordinates() stays the min-corner (load-bearing for collision/pathing/bounds); sound_origin is the derived acoustic origin the GMCP scene sends. Regression guard for: every sound in a room arriving from its object's west/south/floor corner.
:sound_origin() -> {x,y,z}, the point sound emanates from for this object: the CENTRE of its box. coordinates() is the canonical live position (interpolated mid-journey) but it is the MIN-CORNER, which is load-bearing for collision/pathing/bounds and must not change. A panner needs a POINT, so without this a big object's audio arrives from its west/south/floor corner. $player overrides this to head height. Pure geometry: it knows nothing about audio.
:test_set_ambience - set_ambience(file) attaches ONE looping ambience to this object and is IDEMPOTENT: calling it repeatedly must leave exactly one sound and one emitter. The key is owner-derived ('ambience'+tostr(this)), so ensure_emitter_for_sound reuses the emitter with that id and the previous sound under the key is stopped first. Room-owned ambience is anonymous and has no key to collide with, which is how #8608 accumulated 167 orphan emitters. An object-owned sound has an identity, so it replaces instead of stacking.
:set_ambience(file, ?volume) -> attach ONE looping ambience sound to this object; returns the sound. IDEMPOTENT by construction: the handle is derived from the owner ('ambience'+tostr(this)), so ensure_emitter_for_sound finds and REUSES the emitter with that id rather than registering another, and any previous sound under the key is stopped first. Anonymous room-owned ambience has no key to collide with and therefore piles up -- #8608 holds 167 orphan emitters from exactly that. Bind sound to the thing that makes it: it gets an identity, so it replaces instead of stacking, and you can look at what you hear. Position comes from this:sound_origin() (the centre), not the min-corner. Pass a falsy file to just stop.
:test_approach_point_skips_blocked_candidate - approach_point must skip a candidate that something else is standing on, and pick one find_path can actually route to.
:footfall_origin() -> {x,y,z}, the point where this body meets the ground: its footprint CENTRE, at floor level.
:test_footfall_origin - footfall_origin() -> where a body meets the ground: the footprint CENTRE, at FLOOR level. It shares x and y with sound_origin, which centres the box, and z with coordinates, which is the min-corner. Regression guard for: footsteps emitted at the raw min-corner, half a body-width off in +x and +y from the same body's published position, a fixed diagonal displacement that followed the walker around no matter which way they faced.
:add_option(<description>, <default value>)
:set_name - set_name(newname) attempts to change this.name to newname
:set_aliases - set_aliases(alias_list) attempts to change this.aliases to alias_list
:set_description - set_description(newdesc) attempts to change this.description to newdesc
:eject eject_nice eject_basic - eject(victim) --- usable by the owner of this to remove victim from this.contents. victim goes to its home if different from here, or $unclaimed or $player_start according as victim is a player.
:set_message(msg_name,new_value)
:do_examine - do_examine(examiner)
:examine_key - examine_key(examiner)
:examine_names - examine_names(examiner)
:examine_desc - examine_desc(who) - return the description, probably
:examine_contents - examine_contents(examiner)
:examine_verbs - Return a list of strings to be told to the player. Standard format says "Obvious verbs:" followed by a series of lines explaining syntax for each usable verb.
:get_message(msg_name)
:contents objects_for_match - Returns a list of the objects that are apparently inside this one. Don't confuse this with .contents, which is a property kept consistent with .location by the server. This verb should be used in `VR' situations, for instance when looking in a room, and does not necessarily have anything to do with the value of .contents (although the default implementation does). `Non-VR' commands (like @contents) should look directly at .contents.
:examine_verb_ok - examine_verb_ok(loc, index, info, syntax, commands_ok, hidden_verbs)
:is_listening - return 1 if the object can hear a :tell, or cares. Useful for active objects that want to stop when nothing is listening.
:hidden_verbs - hidden_verbs(who)
:examine_owner - examine_owner(examiner)
commands cmd*s - This verb allows players to see commands for an object.
:loc_enter loc_exit - syntax: what, where, levels from original
:integrate_room_msg integrate_container_msg - Select this object's integration message for the given verb (integrate_room_msg / integrate_container_msg) and pronoun_sub it.
:empty_message - Usage: :empty_msg(msgname)
:ps*c po*c pr*c pp*c pq*c psu pou pru ppu pqu - Get the appropriate pronoun.
:vitals - Pass vitals upwards, towards vehicles/ships/etc
:clone - clone(?deep=false) -> copy of this object; copies all properties. If deep, also clones each clonable content via content:clone(deep) into the copy.
:match_targets() => Returns a list of objects used for matching code. Child implementations should probably call pass() before overriding.
:visible([viewer]) - canonical visibility (verb-is-truth). Returns base .visible AND not under an invisibility effect the viewer can't pierce. .visible remains inherent/base storage; magical invisibility is an $effect ("invisibility"), pierced by the viewer's "detect_invis". NOTE: has_effect returns a waif (falsy) or 0, so compare != 0.
- - - - -
See "help mail-system" for a description of the programming interface to the mail system.
In particular, see "help $mail_recipient" for information on creating new mail collections.