TinyMUX

Object Matching

Hardcode

When a player types get sword or look here, the server must resolve that text into an internal database reference number (dbref). This translation—from human-readable names to dbrefs—is object matching. The implementation lives in match.cpp and follows a precise sequence of checks, each with a defined confidence level.

The Confidence Hierarchy

Every candidate match is assigned a confidence score built from these flags, which combine as a bitmask:

FlagValueMeaning
CON_LOCAL0x01Object is near the player
CON_TYPE0x02Object is the preferred type
CON_LOCK0x04Player passes the object’s lock
CON_COMPLETE0x08Input is the object’s full name
CON_TOKEN0x10Input is a special keyword (me, here, *player)
CON_DBREF0x20Input is a direct dbref (#123)

A higher confidence always wins. When two candidates share the same confidence, one is chosen at random. Once a CON_DBREF-level match is found, most match functions return immediately without searching further.

Match Order

The function match_everything() drives the standard search. It checks sources in this order:

  1. me – The literal word me resolves to the player’s own dbref.
  2. here – The literal word here resolves to the player’s location. The location’s actual name is also checked.
  3. Absolute dbrefs – Input beginning with # is parsed as a number. Named references (#_name) are also resolved here.
  4. Bare numbers – If the MAT_NUMERIC flag is set, a plain number without # is treated as a dbref.
  5. home – If the MAT_HOME flag is set, the literal word home matches the special HOME dbref.
  6. Player names – Input beginning with * triggers a player-name lookup (e.g., *Bob).

If any of these produce a CON_TOKEN-level match or better, the search stops. Otherwise it continues to name-based searching:

  1. Exits – Exits carried by the player, then exits in the player’s location. If MAT_EXIT_PARENTS is set, parent chains are walked.
  2. Neighbors – Objects in the contents list of the player’s location.
  3. Inventory – Objects in the player’s own contents list.

For neighbors and inventory, both exact and partial name matches are attempted. An exact match earns CON_COMPLETE; a partial (substring) match earns a lower base confidence.

Exit Matching

Exit names use a special convention: a single exit can have multiple aliases separated by semicolons. The name North;n;no defines three ways to refer to one exit. The function matches_exit_from_list() walks the semicolon-delimited list and compares the player’s input against each alias individually. The comparison is case-insensitive and Unicode-aware.

Exit matching also walks parent chains when MAT_EXIT_PARENTS is active. The master room’s exits provide global commands available everywhere. Zone exits offer a similar facility scoped to a zone.

The locate() Function

Softcode accesses matching through locate(<looker>, <string>, <where>). The <where> argument is a string of single-character flags controlling which search scopes are active:

FlagScope
aAbsolute references (#number)
cExits carried by the looker (with parents)
eExits in the looker’s location (with parents)
hThe keyword here
iThe looker’s inventory
mThe keyword me
nNeighbors (other objects in the same room)
pPlayer names prefixed by *
sPossessive matching (e.g., bob's sword)
*All of the above

Qualifier flags resolve ambiguity: E, P, R, and T prefer exits, players, rooms, or things respectively. L prefers unlocked exits over locked ones. X picks randomly among equal matches instead of returning #-2. V sends error messages to the looker.

Return Values

DbrefMeaning
#-1 (NOTHING)No match found. The player sees “I don’t see that here.”
#-2 (AMBIGUOUS)Multiple objects match with equal confidence. The player sees “I don’t know which one you mean!”

In softcode, locate() returns #-1 for no match and #-2 for ambiguity (unless the X qualifier selects randomly).

The MAT_ Flags

These flags control match_everything() behavior:

FlagValueEffect
MAT_NO_EXITS1Skip all exit matching
MAT_EXIT_PARENTS2Walk parent chains when matching exits
MAT_NUMERIC4Accept bare numbers as dbrefs (without #)
MAT_HOME8Recognize the keyword home

Most commands use MAT_EXIT_PARENTS. The @open command uses MAT_NO_EXITS since it creates exits rather than matching them.

Lock Key Matching

When @lock keys are parsed in boolexp.cpp, the lock compiler calls init_match() and match_everything(MAT_EXIT_PARENTS) to resolve each token in the lock expression. If the result is NOTHING, the player is told “I don’t see X here.” If the result is AMBIGUOUS, the player is told “I don’t know which X you mean!” In either failure case, the lock expression falls back to TRUE_BOOLEXP (always fails to pass).

The init_match_check_keys() variant also evaluates the @lock on each candidate during matching, adding CON_LOCK confidence to objects the player can pass.

Common Pitfalls

  • Ambiguity. If two objects named “sword” are in the same room and no exact-match tiebreaker applies, the server returns #-2. Use dbrefs in softcode to avoid this.
  • Recycled dbrefs. A dbref like #47 is stable only while the object exists. After @destroy, the number can be reused. Hardcoded dbref references in attributes can silently refer to the wrong object.
  • Partial matches are weak. A partial name match has lower confidence than an exact match. If the room contains “red ball” and “red car,” typing red is ambiguous. Typing the full name resolves it.
  • Exit alias order does not matter. All semicolon-separated aliases are equally valid. The first matching alias wins for a given exit, but among multiple exits, equal-confidence matches are chosen randomly.
  • Scope matters. A command that uses MAT_NO_EXITS will never find an exit by name. Conversely, locate() with only i will never check the room’s contents.