Not a member yet? Register for full benefits!

Coding by Example: +where

Create a command which lists all users on the game and the room they are in if they do not have the UNFINDABLE flag set.
TinyMUSH 2.2.4
Command and Function List:
@pemit, ljust(), repeat(), list(), objeval(), lwho(), name(), switch(), hasflag(), and room().
SUBSTITUTIONS (%r, %#, ##)

Step #1: Set up the object.

@create +where
@set +where=COMMANDS

Step #2: The Command

The command has two parts:

  1. First we use @pemit to send the formatted header to the player. I seperate this from the actually list of players and locations to ensure it is evaluated first.
  2. Using the list() function we send a formatted line for each player connected to the enactor (the person typing +where).
    Here is how the command appears (layout is done for reability only):
&CMD-WHERE +where=$+where: @pemit %#=[ljust(Name,20)][ljust(Room,40)]%r[repeat(-,78)];
[list( [objeval(%#,lwho())], [ljust([name(##)],20)] [switch(hasflag(##,unfind),1,[ljust(-- Unfindable --,40)],
[ljust([name(room(##))],40)] )] )]

The Logic:

I've decided I only want two elements listed for each player connected to the game -- the name and the name of the room they are in. Thus, I set up my header information with two justifications and a line to separate the header from the data. I assign the name region to have 20 spaces and the room name to have 40 spaces. To do this, the ljust() function is utilized. Ljust() is merely the function call for left justification.

The @pemit %#=[ljust(Name,18)][ljust(Room,40)] outputs a line which appears like:

Name              Room              

To separate it, I place a line feed (%r) after the second ljust call and then put in a repeat to write a line of dashes. This section is @pemit %#=[ljust(Name,18)][ljust(Room,40)]%r[repeat(-,78)];

Evaluation of this appears as:

Name              Room

Now we need to start working on the list of players remembering that we have allocated 20 spaces to the player name and 40 spaces to the room name. Since we want one line per player as output we will make use of the list() function rather than using iter(). This allows easier control of formatted outputs.

The first step is to produce the first argument for the list() function. The historical method would be just lwho(). However, since +where is commonly used on privileged objects as a global command, we want to make sure that lwho() is processed as the enactor. That eliminates the case of dark wizards being returned in the lwho() list. To do this, we make use of the objeval() function which evaluates a set of code like a specific user rather than based on the privileges of the object it is on.

The list portion of the list() function will be:


Next we want to write the formatted text for each player as the second argument for the list() function. Remember, as list() processes each element in its first argument, that value is passed as ## to the second argument. The first half of the outputed text will be the player name left justified in a 20 space section:


The processing for this starts with ## which is a dbref from the lwho() listing. It then calls the name() function which returns the name associated with that dbref and finally left justifiies the returned name over 20 spaces.

The second half of the outputed text is the room name where the player player is located. However, if the player has the Unfindable flag set, we do not want to return that players location. To do this we will be using switch() combined with the hasflag() function. There are several alternate ways to do this but hasflag() is sufficient for our purpose.

The code for the room string looks like this:

[switch(hasflag(##,unfind), 1,[ljust(-- Unfindable --,40)], [ljust([name(room(##))],40)] )]

The logic flow is as follows:

Does the player have the unfind flag?
If yes (1), we return a the string -- Unfindable -- justified
Else (default) we return the room name.
To get the room name, you will notice I selected the room() function to find the room the player is in. Room() was chosen
rather than loc() because the specifications called for the Room Name, not the Location Name. Had we used loc() and were
the player in an object, that object's name would have been returned rather than the room name.

Here is how the ouput looks once the full system is working:

Name              Room
Wizard            -- Unfindable --
Mark              Limbo

The @decompile of the object is: 
@create +where
@set +where=COMMANDS
&CMD-WHERE +where=$+where:@pemit %#=[ljust(Name,18)][ljust(Room,40)]%r[repeat(-,78)];
[ljust(-- Unfindable --,40)],[ljust([name(room(##))],24)])])]

Suggested Projects

  1. Change the hasflag() usage to findable()
  2. Using controls() and flags() add in the room dbref and flags behind the room name if the enactor controls the room.
    Keep in mind that they should not get information for rooms they do not control and not for unfindable players.
  3. Use the left() function to ensure that the room name does not go beyond 40 characters.
  4. Using left() and get(), put in a column indicating the first letter of the player's @sex
Staff Comments


Untitled Document .