Softcode

Softcode javelin Sun, 2012-02-12 22:02

Herein find answers to frequently-asked questions about softcode on PennMUSH.

$commands

$commands javelin Sun, 2012-02-12 22:21

$commands

How can I make +who, who, and wh all run the same code?

How can I make +who, who, and wh all run the same code? javelin Sun, 2012-02-12 22:26

How can I make +who, who, and wh all run the same code?

Regular expression (regexp) command matching is a very efficient way to do this. One can write code like this:

  &DO_WHO obj = $^\\+?who?$: @pemit %#=...who code here...
  @set obj/DO_WHO=regexp

The regular expression "\\+?who?$" means "an optional + sign", a "w", an "h", and an optional "o", which nicely describes +who, who, wh (and also +wh)

More detail about regexps is available in the Penn help or the book Mastering Regular Expressions, published by O\'Reilly. (Note that Penn\'s regexps are essentially the same as perl 5, but often require extra \\ escapes when used in contexts where they\'ll be evaluated by the Penn parser first (like regmatch))

2001-Apr-01 5:01pm dunemush

Note that the pattern part of attributes with $-commands on them aren\'t evaluated, so the only thing that needs extra escaping here is any colons (:)\'s in the pattern, so they aren\'t taken as the end of the pattern. It\'s only in functions that the extra escapes are needed. The + is escaped in the regexp above because + is a special regexp character. The backslash turns it into something matching a literal +.

2001-Jun-11 8:12pm shawnw

How do I lock the commands on an object to only things inside it?

How do I lock the commands on an object to only things inside it? javelin Sun, 2012-02-12 22:38

How do I lock the commands on an object to only things inside it?

&location <object>=%L
@lock/use <object>=location/<object\'s dbref>

How this works: %L is a substitution that evaluates to the location of %#. So, when the use lock is checked, the location attribute on <object> is evaluated, returning the location of %# (The object trying to pass the use lock). If that matches the second part of the eval-lock, %# is in the object, and it passes the lock. Otherwise, it fails.

2001-Jul-27 7:16pm shawnw

What good are global exits in the master room?

What good are global exits in the master room? javelin Sun, 2012-02-12 22:36

What good are global exits in the master room?

Exits in the master room can be used from any place in the mush, if not overridden by something else. See HELP EVALUATION for details on the order commands are checked against things.

These global exits are good for use as commands that move their user to another location -- for example, a +ooc command that takes people to an OOC area of the mush. Using a global exit for this is simpler than writing a command that displays the needed messages and does a @teleport, because it acts in all respects like a normal exit.

Globals exits can\'t, of course, be used to emulate commands that take arguments, and as a matter of style and efficiency, shouldn\'t really be used for things that don\'t involve moving objects around.

2001-Jun-11 8:09pm shawnw

Global locked exits are also useful in the master room if you have a lot of cardinal directions on your MUSH and don\'t want people to see \"Huh?\" when they try to go east in a room with no east exit:

In the master room:

@open East;e;north;n;west;w;south;s;up;u;down;d=here
@lock east=#0
@fail east=You can\'t go that way.

produces a nicer error message.

2001-Aug-01 8:38pm dunemush

What\'s the best way to have a vehicle moved by someone inside it?

What\'s the best way to have a vehicle moved by someone inside it? javelin Sun, 2012-02-12 22:37

What\'s the best way to have a vehicle moved by someone inside it?

Something along the lines of

&drive_cmd car=$drive *:go %0

In particular, you do not need to use @force, nor do you want to.
Both of these

&drive_cmd car=$drive *:@force me=%0
&drive_cmd car=$drive *:@force me=go %0

will allow anyone to effectively control the car. They can make it do anything at all with the drive command.

Imagine someone typing: \'drive @nuke me\'.

2001-Jul-26 8:27pm shawnw

What\'s wrong with &DO_IT obj=$do_it: [pemit(%#,You did it)]

What\'s wrong with &DO_IT obj=$do_it: [pemit(%#,You did it)] javelin Sun, 2012-02-12 22:24

What\'s wrong with &DO_IT obj=$do_it: [pemit(%#,You did it)]

MUSHcode makes a distinction between commands and functions. @pemit, for example, is a command that notifies a player with a message. pemit() is a function that, as a side effect, notifies a player with a message.

There are some places where commands are expected, and others where functions are expected. The code triggered by a $command, a ^pattern, or @trigger must be a command (or set of commands). So this is ok:

  $do_it: @pemit %#=You did it

And this is ok, if (to my mind) uglier:

  
  $do_it: think [pemit(%#,You did it)]

But this is wrong:

  
  $do_it: [pemit(%#,You did it)]

because there is no command to run. If this code works, you\'re just lucky - there is no assurance it will work in the future -- it is simply wrong code.

Similarly, only functions can be called from within functions. This code doesn\'t do what a naive coder might expect:

  
  $do_it: think [switch(%#,#7,@emit hi,@emit hello)]

The object will think "@emit hi" or "@emit hello", but it won\'t do the emit. This is what\'s probably meant:

  $do_it: @switch %#=#7, { @emit hi }, { @emit hello }

or (usually best):

  $do_it: @emit [switch(%#,#7,hi,hello)]

or, if you must, one of these:

  $do_it: think [switch(%#,#7,emit(hi),emit(hello))]
  $do_it: think [emit(switch(%#,#7,hi,hello))]

2001-Mar-29 6:17pm dunemush

Why aren\'t exits matched for $commands?

Why aren\'t exits matched for $commands? javelin Sun, 2012-02-12 22:22

Why aren\'t exits matched for $commands?

For largely historical reasons, exits are considered to have their \'home\' in the room in which they originate, but their \'location\' is their destination room. So while it wouldn\'t be hard to have $command checking performed on all exits in the player\'s location, when the exit ran the command, it would do so as if it were located in the destination room, rather than where the player is.

There used to be some sense to this; the current structure for objects in the db tries to be highly memory-efficient by overloading fields like \'location\', and back in the day of low RAM, that was a good thing. Nowadays, it\'s less sensible, and this may change one day if the database internals are rewritten.

2001-Mar-28 1:58pm dunemush

Working with lists

Working with lists javelin Sun, 2012-02-12 22:03

Working with lists

How can I explode a string into a list of characters?

How can I explode a string into a list of characters? javelin Sun, 2012-02-12 22:12

How can I explode a string into a list of characters?

trim(edit(mystring,,%b))

2001-Apr-01 4:54pm dunemush

How can I get every other item of a list (Or every 3rd, 4th, etc.)?

How can I get every other item of a list (Or every 3rd, 4th, etc.)? javelin Sun, 2012-02-12 22:17

How can I get every other item of a list (Or every 3rd, 4th, etc.)?

Up to every 10th item can be gotten very easily, with the help of step().

For example:

&every_other foo=%1

think step(foo/every_other, a b c d e f, 2) 

=> b d f

If you want every other element starting with the first, use
%0 instead of %1.

Alternatively, you can use elements() and build the list of
positions using lnum() and vmul().

For example:

think elements(a b c d e f, vmul(lnum(0, 6), 2))

2001-Nov-13 6:44pm shawnw

How can I remove all spaces from a list?

How can I remove all spaces from a list? javelin Sun, 2012-02-12 22:11

How can I remove all spaces from a list?

edit(list of elements,%b,)

2001-Apr-01 4:52pm dunemush

How do I convert a list into a list of arguments?

How do I convert a list into a list of arguments? javelin Sun, 2012-02-12 22:20

How can I convert a standard space-separated list of integer values into a list of arguments that can be passed to a function that accepts an indeterminate number arguments, such as add() or max()?

2006-Jun-29 12:29pm misfit815

The answer is in Section 14.5 of Amberyl\'s MUSH manual. The use of fold() is necessary.

2006-Jun-29 1:23pm misfit815

If you want to pass a space-separated list of numbers to a math function, lmath() can be used instead of fold().

2007-Jan-29 12:05pm shawnw

How do I get a list of all the characters/letters the mush accepts?

How do I get a list of all the characters/letters the mush accepts? javelin Sun, 2012-02-12 22:19

How do I get a list of all the characters/letters the mush accepts?

Many mushes can work with non-ASCII accented letters and other special characters. The @nameaccent attribute, and the accent(), chr() and ord() functions can be used to generate some of them in softcode, and you can send others through your client if you can type them, or cut&paste. But what about seeing exactly what characters the mush will handle in a better way than trial and error?

With the regraball() function, you can generate lists of every character the mush considers "printable" and thus accepts, or the characters that meet stricter restrictions, like "every lower-case letter".

To do this, call regraball() like so:

regraball(iter(lnum(1, 255), chr(##)), ^\\[\\[:FOO:\\]\\]$)

FOO is one of the following classes:

 upper, for upper-case letters,
 lower, for lower-case letters,
 alpha, for letters,
 digit, for digits,
 alnum, for letters and digits,
 word, for letters, digits and _,
 xdigit, for digits in base-16 numbers,
 ascii, for characters in the ASCII set only,
 punct, for punctuation characters,
 space, for white-space characters
 graph, for non-white-space characters,
 print, for all characters

There\'s also cntrl, but none of the characters that can match it can be
generated by chr().

If you want to get just characters that also fall into a certain range (Like, from A to Z), you can fiddle with the lnum() bit as needed.

2004-Jul-24 10:50am shawnw

Here\'s a line of code you can just paste to make it list all the printable characters:

th edit(iter(lnum(1,255), switch(chr(##), #-1*,,#$)),%b,)

2003-Apr-23 7:28am pmak

I have a list of attributes named FOO1, FOO2,...FOO100. How do I sort them so the numbers are in the right order?

I have a list of attributes named FOO1, FOO2,...FOO100. How do I sort them so the numbers are in the right order? javelin Sun, 2012-02-12 22:09

I have a list of attributes named FOO1, FOO2,...FOO100. How do I sort them so the numbers are in the right order?

The default PennMUSH sort() is lexicographic, which means that FOO2 will be sorted after FOO100.
For simple lists of numbers, you could do sort(1 2 ... 100,n) and get a numeric sort, but that won\'t work for attribute names with text before the numbers. Here\'s a few things that will:

&HELPER obj=[sub(after(%0,FOO),after(%1,FOO))]

sortby(obj/HELPER,FOO1 FOO2 ... FOO100)


&NUMSORT obj=[sort(%0,n)]

munge(obj/numsort, edit(FOO1 FOO2 ...,FOO,), FOO1 FOO2 ...)

The first version works by comparing the numbers after "FOO" in a given pair of attribute names, and returns a negative number when %0 should be before %1, a positive number when %1 should be before %0, and 0 when they\'re the same. This is exactly what sortby() needs to sort the list.
The second version uses edit() to build a list of just the numerical parts of the attributes, and munge sorts this list numerically and then returns the corresponding elements out of the original list.

2001-Mar-28 10:02am dunemush

Or, you could have named them as FOO001, FOO002, ..., FOO100 in the first place, thus allowing you to sort lexographically. You can generate zero-padded numbers this way:

> think iter(lnum(1, 100), rjust(##, 3, 0))

001 002 003 ... 100

2003-Apr-23 7:32am pmak

List X contains element W. How do I get the corresponding element from list Y of the same length?

List X contains element W. How do I get the corresponding element from list Y of the same length? javelin Sun, 2012-02-12 22:05

List X contains element W. How do I get the corresponding element from list Y of the same length?

Take your pick:

extract(Y,member(X,W),1)
elements(Y,member(X,W))

2001-Mar-28 9:55am dunemush

This also works:

  
[set(me,uh_temp:W)][munge(uh_temp,X,Y)]

This can be useful when W is produced by a u() call w/o arguments (you can get rid of the set() and just use the name of the u()\\\\\\\\\\\\\\\'d attribute in place of uh_temp).

2001-Mar-28 11:05am popiel

What\\\'s the difference between match(), member() and strmatch()?

What\\\'s the difference between match(), member() and strmatch()? javelin Sun, 2012-02-12 22:15

What\\\'s the difference between match(), member() and strmatch()?

match(list, wildcard pattern[, delimiter])
member(list, element[, delimiter])
strmatch(string, wildcardpattern)

match() and member() are list functions that look for a matching element in a list and return its position in the list, or 0 if it\\\'s not found. member() does case-sensitive exact matches, which makes it good for things like dbrefs. match() is case-insensitive, and does wildcard matching (* and ?), so it can be used to find things like the first element of the list starting with the letter F (or f).

strmatch(), on the other hand, is a string function. Instead of treating its first argument as a list to be broken up into individual elements to look at, it compares the entire argument at once against the wildcard pattern, and returns 1 if it matches, 0 if not.

2001-Oct-22 6:52pm shawnw

Why is this code that uses iter() adding spaces I don\\\'t want?

Why is this code that uses iter() adding spaces I don\\\'t want? javelin Sun, 2012-02-12 22:13

Why is this code that uses iter() adding spaces I don\\\'t want?

The spaces are probably coming from the default output seperator of iter(), which happens to be a space. An empty fourth argument to iter() will eliminate the output seperator.

For example:

iter(#1 #2 #3, complex formatting code, %b, )

2001-Jun-11 8:16pm shawnw

Does an object have to be set PUPPET to be @forced?

Does an object have to be set PUPPET to be @forced? javelin Sun, 2012-02-12 22:54

Does an object have to be set PUPPET to be @forced?

No. Any thing or player-type object can be @forced by other objects that control it. The puppet flag is not involved.

2001-Jul-26 8:21pm shawnw

How can I make a room display objects and exits in two side-by-side columns?

How can I make a room display objects and exits in two side-by-side columns? javelin Sun, 2012-02-12 22:41

How can I make a room display objects and exits in two side-by-side columns?

By default, rooms display their contents list and then their exit list. The @conformat and @exitformat attributes on the room control the appearance of these lists. The easiest way to get a side-by-side display is to have @conformat do nothing but store the list of objects the player can see, and to have @exitformat display both contents and exits in two columns:

  &CONFORMAT here=[set(me,VISIBLE:%0)]
  &EXITFORMAT here=
     [ljust(Contents:,40)] Exits: [iter(lnum(1,max(words(v(VISIBLE)),words(%0))),
      %r[ljust(name(extract(v(VISIBLE),#@,1)),40)] [name(extract(%0,#@,1))])]

The CONFORMAT, which is evaluated first, stores the list of contents visible to the looker in the VISIBLE attribute. The EXITFORMAT iterates through the elements of VISIBLE and its %0 (the list of visible exits) and displays them in two columns.

(You may want to truncate the names at 40 chars, etc., as well)

2001-Mar-28 10:44am dunemush

Instead of using extract() to get at the elements of one of the lists, you can also use the mix() function to pass the corresponding elements of two (Or more) lists to an attribute. For example:

 &format_line object=[ljust(name(%0), 30)][name(%1)]
 @conformat object=
 @exitformat object=[ljust(Contents, 30)]
     Exits%r[mix(format_lines, lvcon(me), %0, %b, %r)]

This code also uses the lvcon() function to get the list of visible contents, rather than saving the list in the @conformat. An empty @conformat is needed so you don\\\\\\\'t get the default contents list and your custom one generated in the @exitformat.
2004-Jul-24 10:47am shawnw

In recent versions of Penn(), align() allows for separation of code logic for either columns.

@conformat  here=
@exitformat here=align(<30 >30,Exits:%r[iter(%0,name(##),%b,%r)],
     Things:%r[iter(lvcon(me),name(##),%b,%r)])

Note that the >30 in align will right-align the Things list. This can easily be changed to <30 to left-align it.

2004-Jul-24 10:57am walker

How can you tell if a player is hidden by @hide?

How can you tell if a player is hidden by @hide? javelin Sun, 2012-02-12 23:03

In the help, it says to use @hide over the dark flag, but how do you tell via code that a player is using it?

Examining myself, I could not figure out any means to detect if a player is hidden.

2004-Jan-04 5:59pm strolfey

The hidden() function is used to tell if a player is hidden or not.

2004-Jan-16 1:02pm shawnw

How do I automatically add new players to an in-game channel such as \'help\' or \'newbie\'?

How do I automatically add new players to an in-game channel such as \'help\' or \'newbie\'? javelin Sun, 2012-02-12 23:06

How do I automatically add new players to an in-game channel such as \'help\' or \'newbie\'?

I\'m only asking about this because I keep misplacing the documentation that I get from the helpful folks on the M*U*S*H +softcode channel.
From what I remember though, I had to:
1. create an object and set it in the room where new players connect,
2. set that object wizard,
3. set a command on that object to add the new player to \'help\' or \'newbie\',
3. set the @aconnect on the room to trigger the command on the object.
Is this correct because I can\'t seem to get it to work. Any help would be appreciated.
Thanks,
Skaven

You\'re on the right track.
The easiest way is to @set the room new players are created in (#0 by default) Wizard and add an @aconnect to it that does a \'@channel/on Newbie=%#\'.
If the room isn\'t Wizard, I don\'t think it can trigger anything on an object that is.

Anonymous

How do I colorize exit names?

How do I colorize exit names? javelin Sun, 2012-02-12 23:00

As an example, here\'s a parent object that will, given exits following the common naming
pattern of : Name <Alias>;Alias, highlight the <Alias> bit. (It requires Penn 1.7.5).

 @create Color Exit Parent
 @exitformat Color Exit Parent=Obvious Exits:%r[map(format_exit, %0, %b, %r)]
 &format_exit Color Exit Parent=regedit(name(%0), <\\\\w+>$, setq(E, $0)[ansi(h, %qE)])

It\'s easy to extend the format_exit attribute to do transparent-room checks and any other features
desired.

2004-Jul-24 10:55am shawnw

I have done this, though I don\'t understand how to use the color exit parent once created. Please help.

2007-Jan-20 2:49am violetallure

How do I create an attribute on a player, when they pass through an exit?

How do I create an attribute on a player, when they pass through an exit? javelin Sun, 2012-02-12 22:56

How do I create an attribute on a player, when they pass through an exit?

  @asuccess exit=&attr %#=value

The exit also has to be set WIZARD, so it has permission to set attributes on players.
2001-Sep-09 3:34pm shawnw

How do I destroy an object immediately?

How do I destroy an object immediately? javelin Sun, 2012-02-12 23:02

How do I destroy an object immediately?

Normally, when you @recycle an object, it doesn\'t get destroyed for a while. This is handy for those times when you realize just after you do it that you really wanted to keep it, and can safely @unrecycle it. But what if you really do want it gone at once? Just use @recycle on it twice in a row.

2003-Jun-23 7:49pm shawnw

How do I find all objects @parented to a given object?

How do I find all objects @parented to a given object? javelin Sun, 2012-02-12 22:51

How do I find all objects @parented to a given object?

The easiest way to find all children of a given object is to use @search:

  @search all parent=#1234

If you want to find all descendants of an object (including objects
which are @parented to the object\'s children, or its children\'s
children, etc.), then you can use:

  @search all eval=member(lparent(##), #1234)

Of course, you can also use the lsearch() function similarly.

In future, PennMUSH may add a children(X) function as syntactic
sugar for lsearch(all, parent, X), but it will cost the same and
be subject to exactly the same restrictions as the lsearch().

2001-Apr-16 11:58am popiel

children() was added in 1.7.7p13

2003-Apr-29 8:23pm shawnw

How do I get a list of all the connected players in a room or object?

How do I get a list of all the connected players in a room or object? javelin Sun, 2012-02-12 22:57

How do I get a list of all the connected players in a room or object?

&is_connected room=gte(conn(%0), 0)
&list_players room=filter(is_connected, lcon(me))

... or something along similar lines. 

2001-Oct-22 7:16pm shawnw

In Penn 1.7.5, you can use lvplayers() instead. There\'s also lplayers(), which doesn\'t check for connection status.

2001-Nov-13 6:49pm shawnw

How do I get around &quot;I don\'t know which you mean&quot;?

How do I get around &quot;I don\'t know which you mean&quot;? javelin Sun, 2012-02-12 22:52

How do I get around "I don\'t know which you mean"?

In versions of PennMUSH before 1.7.4p2 or so, when you have multiple objects with the same name, and you try to match one (by using \'get thing\', \'look thing\' or any other command), the command will work, but on an arbitrarily chosen one of the objects (sometimes randomly chosen, sometimes the first one in the room\'s contents).
As of 1.7.2p2, the parser correctly interprets this situation as one of ambiguity, and instead of choosing for you, reports "I don\'t know which you mean" or similar, functions return #-2, etc.
But what do you do if you need to write code that acts on one of the objects? How can you choose a particular one?
The solution is English matching. Since 1.7.3, PennMUSH has supported the following adjectives before object names:

  1st/2nd/3rd/4th/etc.  -- to specify the xth object visible to you
  my 1st/2nd/3rd/etc.   -- the xth object in your inventory
  this here 1st/2nd/etc. - the xth object in the room with you

(\'this here\' may be abbreviated \'here\')
So if you write a vendor that creates identical objects and gives them away, rather than have it \'give %#=object\', use \'give %#=my 1st object\' and you can be sure it will work, even if your vendor somehow comes to contain multiple \'object\' objects.
Of course, if you know dbrefs, you can always work by dbrefs as well.
(And if you have side-effect functions, write your vendors to use create(),
and keep the dbref, and operate that way!) You can often get dbrefs using the locate() function, which can be instructed to treat ambiguous cases in the old style (returning an arbitrary matching object), as well as to use english matching.

2001-May-19 12:33pm dunemush

In recent versions, there is also "toward" for exits. For example, if there\'s two exits going east, "toward 1st east" will reference the first east exit.

2003-Apr-23 7:22am pmak

How do I get the dbref of a room dug by a hotel vendor?

How do I get the dbref of a room dug by a hotel vendor? javelin Sun, 2012-02-12 23:11

How do I get the dbref of a room dug by a hotel vendor?

I have a wizard device that digs rooms for rental. The rented rooms are connected to the room in which the device sits.
How do I programmatically find out the dbref of the newly created room so that the device can either set descriptive text for the new room (desc, succ, osucc, ofail; etc) from its remote location, or [guarantee to] teleport the user to the room and force him/her to set these things? Room names are "1", "2" and so on.
Thanks in advance.
EricT.

2008-May-09 9:52am eric.twose

>The main issue is that the vendor needs to be able to transfer ownership of the new room to the new tenant so that when we programmatically get him/her to move to the new room and set up desc, etc, we don\'t get permission denied errors. But without a dbref, the vendor cannot see the new room.

2008-May-09 10:35am eric.twose

Of course, the function dig() returns a dbref unlike @dig.
2008-May-09 2:12pm eric.twose

How do I lock an object for one person at a time?

How do I lock an object for one person at a time? javelin Sun, 2012-02-12 23:16

How do I lock an object for one person at a time?

The following prevents a second user coming along and being built a room by a vendor whilst still processing a previous user request:
&INUSE Room Digger<rd>=0
In the Room Digger object\'s dig command:
@switch v(INUSE)=<1,{v(INUSE)=1;{build the room};v(INUSE)=0},{@pemit %#=Sorry but the clerk is busy dealing with another client. Wait a few seconds.}


2008-May-09 3:51pm eric.twose

Actually, that code\'s wrong in several ways. v(INUSE)=.. should probably be &INUSE me=..., because commands are expected there, not function. But the more serious problem is that there\'s a race condition. @switch queues its action lists, so you\'ll find that you can very quickly trigger that command twice. For real protection, you could use a semaphore, but the easiest modern approach involves @break:

$build: @break [v(INUSE)]=@pemit%#=Sorry but the clerk is busy; 
   &INUSE me=1; 
   @@ Build the room;
   &INUSE me=0

This assumes your room-building commands don\'t use the queue (that is, don\'t involve @wait, @force, @trigger, @switch). If they do, semaphores are your friend:

&build vendor=
    $build: @wait me={ @@ Room building commands; 
        @notify me }
@drain vendor
@notify vendor

2012-Feb-10 javelin

How do I send guests home to room 0 when they QUIT?

How do I send guests home to room 0 when they QUIT? javelin Sun, 2012-02-12 23:10

How do I send guests home to room 0 when they QUIT?

Q: When guests are used, the user very rarely returns the guest to the start room 0, so the next time someone comes along, they may find their guest character at the bottom of a dark pit. How can I automatically send them home when they QUIT?

2008-Apr-29 10:17am eric.twose

@aconnect #1234=home

2008-May-01 5:22am eric.twose

The @aconnect will send them home when they next connect (and will show the new guest a message as they are sent home right after connecting). You might prefer to send the guest player object home after its user disconnects. Just use @adisconnect in place of @aconnect.

2012-Feb-10 javelin

How do I tell if a player is connected?

How do I tell if a player is connected? javelin Sun, 2012-02-12 22:55

How do I tell if a player is connected?

With something like this:
gte(conn(*player), 0)

You shouldn\'t use hasflag(*player, connected). That will only work for see_all objects, because the connected flag is hidden to mortals. This might change in the future, but don\'t depend on it. Stick to conn().

2001-Jul-27 8:37pm shawnw

I am having trouble using Zones

I am having trouble using Zones javelin Sun, 2012-02-12 23:01

I wish to use zones in the Mush that i am creating, but am instead having terrible difficulty.
I am trying to make it so that each empire has it\'s own zone, and in turn all rooms and exits and objects become apart of it. The main usage that i want to use an exit with a zone is so that only people with authorisation and/or is apart of that empire can enter through it.
I have as such tried, but with no luck, if anyone could help i would be gratefully appreciated.
Thankyou.

2002-Jan-11 7:08pm FishHerring73864

This is for when you have different places on a MUSH grid (like 4 cities), and rather than have everything be in the Master Room, you want to have city-specific codes for each section of the grid. For the sake of ease, we\'ll call the zone-specific code Local Globals and the zone-master will be Zone Master Room.
1) Make sure that the room you are going to put the Local Globals in is @lock/zone <db #>==<whoever\'s in charge>. The double = is needed, otherwise someone can carry the person in charge and pass the lock.
2) @chzone <the room you want in the zone>=<db # of the Zone Master Room>
3) Drop all the Local Global objects into the Zone Master Room.
That should do it.

2002-Sep-20 9:43am ellis1138

Large Ansi Output Cutoff

Large Ansi Output Cutoff javelin Sun, 2012-02-12 22:50

Alright.. I don\'t think my question got added right the first time, so here goes. Anyways, I have a function that is outputting a lot of ansified text (a grid of characters), but after a certain number, it just cuts off and stops displaying the characters. I checked the function invocation limit, and that isn\'t the problem. When I remove the ansi(), it outputs fine.. I\'m thinking it may have something to do with the output buffer, but I\'d be unsure in how to change that. Any suggestions?

2001-Apr-05 8:17pm twpage

As you suggest, the cutoff is likely due to limited buffer size and
the way that the MUSH stores ANSI codes. Each ANSI transition takes
up between 4 and 7 bytes in the fixed-size (usually 8K) evaluation
buffer... so if you\'re doing color transitions with every character,
you\'ll only be able to fit around 1000 visible characters into the
buffer. Possibly less if you\'re combining foreground, background,
and highlight in each change (that\'s 3 separate transitions, when
stored).
One way to deal with this would be to generate (and @pemit or whatever)
each line of output separately. It\'s very unlikely you\'ll have so much
ANSI stuff that you won\'t be able to fit 80 visible characters into the
buffer.
Alternatively, if you have hardcode access to the server you\'re doing
this on, you can increase the BUFFER_LEN above 8K. I really don\'t
encourage this, however.
PennMUSH may start dealing more economically with ANSI in future... but
I wouldn\'t wait for it.

2001-Apr-06 4:39pm popiel

My Parent Room object isn\'t working.

My Parent Room object isn\'t working. javelin Sun, 2012-02-12 22:58

I Found some softcode on the Net, that creates a fancier version for displaying objects and exits, the only problem is that it didn\'t display them in two side by side columns, so i attempted to join the example from this FAQ site with the other, it sort of works but the columns aren\'t displaying properly.
Any help would be greatly appreciated. The code is as follows:

@create Room Parent v.04
@link Room Parent v.04 = here
@set Room Parent v.04 = INHERIT
@set Room Parent v.04 = NO_COMMAND
@CONFORMAT Room Parent v.04=[ansi(gh,[ljust(Contents:,43)] Obvious Exits:%r)]
@set Room Parent v.04/CONFORMAT=no_command
&CREDITS Room Parent v.04=Coded by Jamie. For permission to use email jamie@dj-tech.org.
@DESCRIBE Room Parent v.04=[ansi(hb,[repeat(=,76)])]%r[u(me/inf_desc)]%r[ansi(hb,[repeat(=,76)])]
@set Room Parent v.04/DESCRIBE=no_command visual
@EXITFORMAT Room Parent v.04=[ljust([iter(lcon(me),[switch(##,%#,,[switch(hasflag(##,DARK),0,[switch(type(##),PLAYER,[switch(idle(##),-1,,%r[ansi(hc,[name(##)])])],THING,%r[ansi(c,[name(##)])])])])])],44)][iter(lexits(me),[switch(hasflag(##,DARK),0,{[ansi(c,<)][ansi(hc,[ucstr([extract([fullname(##)],2,1,;)])])][ansi(c,>)][ansi(r,-)][ansi(c,name(##))%r]},{})],)]
@set Room Parent v.04/EXITFORMAT=no_command
&INF_DESC Room Parent v.04=%tThis is the default description for the room parent by Jamie. You can set your own description with the inf_desc attribute. You can customize your top describe border with inf_desc_border_t and the bottom one with inf_desc_border_b. Also you can customize the headers for the contents and exits using inf_contents_header and inf_exits_header. Changing the color that objects and players show up in can be done with the inf_player_color and inf_obj_color. Changing the colors for the exits can be done with inf_exit_c. Further the exit alias color can be set with inf_alias_c and the brackets around the alias with inf_alias_bra.
@dolist [lattr(Room Parent v.04)] credits=@set Room Parent v.04/##=no_command
@set Room Parent v.04/credits=visual
@wait me/10=@pe/silent %#=[ansi(hr,INSTALLATION COMPLETE.)]%r[ansi(hc,Email jamie@dj-tech.org with comments/feedback/questions)]

2001-Dec-22 3:43pm FishHerring73864

This is a good example of the wrong way to put questions up on the FAQ. Huge code-dumps usually don\'t go over well, especially when they\'re mangled into one big unreadable block. Fixing specific broken pieces of code is probably better left to mushes with code-help channels or other resources. What the code is doing instead of what\'s expected isn\'t even mentioned. At least what is expected is.

The idea is to have exits and contents in two columns, with colors in the exit names. There\'s a FAQ entry on both bits of it, and it\'s fairly easy to combine them. Take the format_exit attribute from the colorizing-exits FAQ, and plug it in where the two-columns FAQ gets the exit names.

Examples of good questions: How do I do SOMETHING? What\'s wrong with APPROACH? Why does THIS happen?

2002-Jan-04 9:13pm shawnw

The problems with ## in iter() and @dolist

The problems with ## in iter() and @dolist javelin Sun, 2012-02-12 22:54

Using ## in iter() and @dolist (And #$ in switch()) can be dangerous if not treated with care. The problem is that the ## token is replaced /before/ evaluation of the code, not during, as with %-substitutions. This means that if the current list item that takes the place of ## has anything resembling code in it, it will get evaluated. In badly-written code, this can provide a malicious attacker with the ability to run any functions as the object the iter() is on. Obviously, this is bad.
There are several measures you can take to avoid these security holes. The first is to use itext() instead of ## when the list being itered over might contain arbitrary text and code (The results of things like lnum() and lcon() don\'t usually need this, because numbers and dbrefs are safe). The second is to use escape() or secure() on the list argument, (not around the ##\'s). This will escape or remove the special characters that indicate code as opposed to plain text (Brackets, percent signs, etc.).

2001-Jun-11 7:48pm shawnw

Using ascii2mush and figlet for easy beautification

Using ascii2mush and figlet for easy beautification javelin Sun, 2012-02-12 22:49

If you ever wanted nice, large text, or complex maps on MUSH, and have had a flag day doing it (like me), you might want to take a look at ascii2mush.
Ascii2mush (http://ftp.pennmush.org/Scripts/ascii2mush.pl) is a nifty perl script made by Javelin@M*U*S*H, that converts spaces to %b or to [repeat(%b,number)], escapes "\\"s, and generally makes ascii art and the like display the way you want it to.

To use it, you must have PERL installed. The next steps assume you use *nix, but if you use PERL regularly on another OS, you should be able to figure out how it works.
Download the script, modify the path in the #! line (first line) to the path where perl lives (to find out, type whereis perl), save it, and place it somewhere in your path (or if you are root and want other users to be able to use it, place it in /usr/local/bin for example).

You can now either type ascii2mush <file>, in which case it will convert the contents of <file> to MUSH format, or use pipes to it, like with figlet.

For example, if you want to display \'Hello!\' in big letters in a certain room, you can use figlet (for information on figlet and how to get it, see http://st-www.cs.uiuc.edu/users/chai/figlet.html) in combination with ascii2mush like this: figlet Hello! |ascii2mush, and copy and paste the result to the MUSH. For more information on how to use figlet, read the documents packaged with figlet, available on the above URL, or type \'man figlet\' if it\'s installed.

If you want to create a visual map, you can draw the map in a text file (pico -w map, then draw and save it), and then type ascii2mush map, and it will convert the map to MUSH format.
Ascii2mush can save you a lot of time when creating graphical things on a MUSH, so if you don\'t want to spend a lot of time perfecting your maps etc, I recommend using it.

Cheetah@M*U*S*H
2001-Apr-01 4:47pm aiviru

Using regrep

Using regrep javelin Sun, 2012-02-12 23:05

I\'ve run into the limit of my knowledge with regrep. I have a \'media article archive\' object containing attributes which are formatted as -
<date>|<source>|<title>|<text>
I want to search the attributes for a keyword in <title>. regrepi() looks to be the way to do this
regrepi(<dbref>,ART_*,<what goes here???>
but I can\'t work out what I need as a regexp expression to do the search. I have tried many combinations but simply don\'t know enough about regular expressions to make it work. Regexp experts, please help. (Argon@CM2)

wildgrepi() might be a better choice.

wildgrepi(<dbref>, ART_*, *|*|*%0*|*)

Anonymous

What is &quot;the queue&quot;?

What is &quot;the queue&quot;? javelin Sun, 2012-02-12 22:48

What is "the queue"?

For a probably better answer, see the collaborative book \"Enough to be Dangerous\" on this site.

2012-Feb-10 javelin
In PennMUSH, there are actually 4 kinds of queues that are important in softcode: the player queue, the object queue, the wait queue, and the semaphore queue. Usually people who talk about \"the queue\" mean the object queue.

  • The player queue is a line of commands that have been typed by players directly to the MUSH from their connection. These get their own queue because the MUSH prefers to run commands from this queue when it can, so that it feels more responsive to players\' direct actions.
  • The object queue is a line of commands to be run by objects (anything other than a player typing directly from their connection)
  • The wait queue is a line of commands that are to be run at some time in the future (commands that have been enqueued using @wait =)
  • The semaphore queue is a line of commands that are to be run at some time in the future and are controlled by a semaphore (commands that have been enqueued using @wait me/=)

Here\'s an example of the object queue in operation. Imagine that you\'re in a room with an object like this in it:


Toaster(#100)
POP [#3]: @emit The toast pops!
START [#3]: $start: @emit %N starts the toaster; @tr me/POP

When you type \'start\', the object queues up this command set:

@emit %N starts the toaster; @tr me/POP

along with some information about who %N was at the time.
When this command set is at the front of the queue, the MUSH server executes it, \"Javelin starts the toaster\" is emitted, and the @trigger command is run, which puts the contents of the POP attribute onto the back of the queue.

In the meantime, of course, other things may be ahead of this and run from the queue, but eventually \"@emit The toast pops!\" is at the front of the queue, and is executed.

The @trigger command, @force command, and @switch/@select commands result in a new command-set being queued up. This is why code using these commands can feel slower -- you have to wait until the newly-queued command set is at the front of the queue before it runs. Of course, if speed isn\'t important, using the queue is a good thing -- it lets the MUSH server share its time between commands of all the objects, and reduces overall lag.

2001-Mar-29 6:33pm dunemush

Where can I get a softcoded chargen system?

Where can I get a softcoded chargen system? javelin Sun, 2012-02-12 22:46

Where can I get a softcoded chargen system?

There are few released softcoded chargen systems, as these systems are usually highly specific to the individual MUSH\'s notion of what a "character" should include (stats? skills? virtues and flaws?) and how they should be generated (roll dice? spend points? choose from lists?)

The good news is that there *is* a program that *generates* chargen systems, based on a rather simple specification. It\'s called \'gengen\' and you can try it out online (http://javelin.pennmush.org/gengen.html) and download it if you want to run it locally. It\'s written in perl, and produces output in quickbuild format (quickbuild\'s another perl script that speeds up offline building of areas, and is at http://javelin.pennmush.org/quickbuild.html).

gengen can produce chargen areas that are either linear (you go through them in order) or spoke-topology (you go through the facets in any order), and can create rooms for attributes to be set by dice rolling, point spending, choosing from a list, or entering arbitrary text. gengen-produced chargen systems are functional, but you\'ll often want to use them as a starting point for further customization.

2007-Mar-18 12:41pm dunemush

The Sandbox Globals Project also has a chargen system. See http://sgp.erisian.net/cgen/ for details.

2002-Jan-04 8:49pm shawnw

Which is better: @pemit or think pemit()?

Which is better: @pemit or think pemit()? javelin Sun, 2012-02-12 23:02

Which is better: @pemit or think pemit()?

@pemit foo=bar

versus

think pemit(foo, bar)

The former case, using @pemit, is preferrable. In both cases, the parser has to find the command, and evaluate its argument(s). Using @pemit directly means there is one fewer function to evaluate in the argument than when using think pemit(), and it\'s thus more efficient.
The only times think X() is normally to be preferred over @X is when the function version returns a value and you need to do something with that value. A vendor object, for example, is more likely to use create() than @create so it can easily reference the newly created object by dbref.
Of course, there are also times where X() is the only option (Like when it\'s in an attribute being evaluated by u()). But for action list elements, remember @pemit over think pemit().

2002-May-18 12:36am shawnw

Will there ever be wait(), trigger() or force() functions?

Will there ever be wait(), trigger() or force() functions? javelin Sun, 2012-02-12 22:45

Will there ever be wait(), trigger() or force() functions?

No. The exploits made possible by side-effect functions pale in comparison to what can be done with functions that add commands to the queue. Imagine someone exploiting badly-written code on a wizard object that lets them evaluate arbitrary code as that wizard object. (It happens. A lot. Especially with people who don\'t know how to make iter() safe writing code). They could use it to do a @shutdown, or @nuke most of the database, or other nasty things. This is not desirable.

2001-Mar-28 11:02am shawnw

They could already cause this much damage using the set() function.

I thought the real reason wait(), trigger() and force() won\'t be implemented is that allowing functions to add entries to the queue is very difficult to implement without introducing denial of service vulnerabilities.

2003-Apr-23 7:17am pmak

These functions appear to have been implemented since the original author wrote this. I actually believe that this is not a bad thing since it adds a lot of power. I take the same attitude to mush object security as computer security. I would never intentionally try to do harm myself, but I presume that others will. I personally use regex matching on all commands to ensure safety. I have very little sympathy for wizards who fail to take basic precautions.

2005-Jul-23 6:53am interfecus