Command table

MadROM dispatches every player command through the global cmd_table defined in src/interp.c. Each entry uses the struct cmd_type layout declared in src/interp.h so that the interpreter can discover the handler function, the positions and trust levels that may execute it, and whether immortals should see it in command listings.

Entry layout

The fields of struct cmd_type describe both how a command is invoked and how it is presented:

Field Declared in Purpose
name src/interp.h Text players type at the prompt. Abbreviations work so long as they are unique.
do_fun src/interp.h Function pointer to the implementation, usually defined in one of the act_*.c files.
position src/interp.h Minimum character position (for example POS_DEAD, POS_STANDING) required before the interpreter will call the handler.
level src/interp.h Minimum level or trust that may use the command.
wizbit[WIZ_BITS] src/interp.h Optional wizard flag requirements. The stock table leaves these as zero but they can gate commands behind custom wiznet-style permissions.
log src/interp.c Controls logging with the LOG_NORMAL, LOG_ALWAYS, and LOG_NEVER constants. Entries flagged LOG_ALWAYS are written to the immortal log even without fLogAll.
show src/interp.c When set to FALSE the command is hidden from the commands listing, though it still works when typed directly.

Because the interpreter checks commands in the order they appear in cmd_table, related entries are commonly grouped together in the source file.

Adding a command

To wire a new command into the game:

  1. Declare the handler – Add a DECLARE_DO_FUN(do_yourcommand); prototype to src/interp.h so the table can reference it.
  2. Register the entry – Insert a row into cmd_table in src/interp.c with the command name, handler, required position, level, wizard bits, logging mode, and visibility flag.
  3. Implement the behavior – Provide the do_yourcommand function in an appropriate source file (often one of the act_*.c modules). Make sure it follows the standard signature so the interpreter can invoke it.

Immortal commands should set the level field to the appropriate trust threshold and toggle log or show to control auditing and visibility. Mortals-only commands typically leave wizbit at zero.

Social commands

Emotes and socials bypass the command table and instead use the social_table array that load_socials populates in src/db2.c. Each entry is a struct social_type with fields such as name, char_no_arg, others_no_arg, char_found, others_found, vict_found, and optional self-targeted strings. To add a social, append the new definition to the socials data file read by load_socials; the loader handles $ sentinels for empty strings and # markers that terminate each definition.

Logging and snooping

When the interpreter dispatches a command it calls the handler after running the logging and snoop hooks in src/interp.c. Commands that set log to LOG_ALWAYS, characters flagged with PLR_LOG, or a server with fLogAll enabled generate entries in the immortal log and on the secure wiznet channel. The snoop system also echoes the final command line to any administrators snooping the player before the handler executes.