| Attributes |
| Penn has no special-case restrictions on what
character can be the first one in an attribute
name. |
MUX does have a special restriction. It also has a
more restrictive set of what characters are valid in
attribute names in general. |
| Booleans |
| All functions on Penn that check a
'boolean value' (True/False) use the same rules,
described in HELP BOOLEAN VALUES. There are two
different sets of rules, controlled by the
tiny_booleans run-time config variable (Which doesn't
act like described in the help (Must fix)). |
Some boolean functions in MUX follow the
same rules as Penn with tiny_booleans off, while
others don't, but only consider non-zero numbers to be
true. Example: if(#-1, a, b) returns a on MUX, b on
Penn, no matter the state of tiny_booleans. Example:
and(#1, 1) returns 0 on MUX and Penn with
tiny_booleans=yes, 1 on Penn with
tiny_booleans=no. |
| @function |
| Penn's syntax for adding new global functions is
@function name=object, attribute |
MUX's syntax is @function
name=object/attribute. Penn, as of version
1.7.5p8, understands this syntax also. |
| When calling a @function, it is evaluated with the
permissions of the object the attribute is on. |
With MUX, this only happens when the @function was
added with @function/privileged. This is stupid. It should
always act that way. |
| If you use q-registers in the @function code, it
should be protected by ulocal(), uldefault() or
localize() unless you want the register changes to be
available to the calling code. |
While ulocal() and localize() exist on MUX, it
also has a /preserve switch to @function that does the
same thing. This seems silly. I assume it has to
predate ulocal(), since localize() is a fairly new
addition. |
| You can remove @functions on Penn, and replace
built-in functions with a @function. You can enable
and disable functions. You can change their access
permissions. '@function name' will display some
information about the given function. |
You can't do most of this on MUX, as far as I
know. There might be a way to do the access control
and enabling/disabling via @admin. |
| Locks |
| As of PennMUSH 1.7.5, Penn has new, extended
locks. Indirect lock keys can now refer to arbitrary lock
names on objects, not just the same lock name. A new
lock key for testing if a flag/power/type is set on
the object being tested is present. |
Mux doesn't have the extended lock keys. |
| Locks can be inherited as of 1.7.5, and a number
of lock flags like attribute flags have been added. |
MUX seems to store locks as attributes, so it
might support inheritable locks and lock flags. I
haven't tested this. |
| You can have arbitarily-named user defined locks
on Penn without touching hardcode, for use with
indirect lock keys and elock(). |
I think that to add a new lock type in MUX, you
have to change a table in the source. |
| Math |
| Penn uses double-precision floating point numbers
for all of its math functions but div() and the
bit-manipulation ones.. |
MUX also supports 64-bit integer math in addition
to floating-point. This can be useful and might show
up in Penn someday. |
| How many digits of precision are used when
converting the results back into a string is a
run-time configuration option. Exponential notation is
supported in literal floats (add(2.5e10, 2.6e10), but
not in output. |
MUX uses as many digits as neccessary to get the
exact number back when the string version is converted
to a double. This seems good. It supports exponential
notation for both input and output. This, too, seems
good. |
| Networking and Connections |
| Penn supports IPv6 networking (IPv6 is
the highest version of the Internet Protocol that
controls how information is sent around on the
net. Most programs and computers are still only using
IPv4.) and will use it if run on a computer that has
an IPv6 stack running. When this is the case, IP
addresses (Like in player's &LASTIP attribute) are
different than the IPv4 'dotted-quad' notation. For
IPv4 connections to a IPv6 server, it'll look like
::ffff:AAA.BBB.CCC.DDD where AAA.BBB.CCC.DDD
is the IPv4 address. |
On Windows NT-ish systems, MUX uses asynchronous
I/O "completion ports". Penn has a compile-time option
for this, but I don't think it's tested very well and
might be broken. Asynchronous stuff is usually better
when dealing with huge volumes of output on a
multiple-CPU machine, so I'm a bit dubious as to how
much of a benefit it is to mushes. But since it works,
I'm not complaining. |
| The admin command for locking out specific
addresses from being able to connect or create new
players or log in as guest is @sitelock, and works by
matching wildcard or regular-expression patterns
against hostname and IP addresses. |
The command is a form of @admin, and works by
doing a 'mask' against the numeric IP address. This is
much more confusing to people who aren't already
familiar with how masks work, and makes it harder to
do things like banning all of aol.com in one easy
step. |
| Penn doesn't keep track of things like the highest
number of connections. We think it's easy to do this
in softcode if wanted. |
MUX does keep track of it. |
| Parser |
| Penn has a completely different
function/substitution parser than MUX. They handle a
very similar language, but do some things
differently. |
In particular, the MUX parser strips escaping
backslashes even when not actually evaluating code so
you have to add more backslashes to get things to work
right, and it isn't as accepting of misplaced
parenthesis, brackets and braces as the Penn parser
is. |
| Regular Expressions |
| Penn uses perl-style regexps
courtesy of PCRE |
MUX still uses Henry Spencer's tradition
regexp code. Someday I'll port Penn/PCRE over to it. |
| Penn has a lot of functions and commands
that deal with regular expressions. The REGEXP
attribute flag applies to @listen, @filter and
@infilter as well as ^-patterns. Penn also has the
CASE attribute flag to control case-sensitive regexp
matching of these attributes. |
MUX only has regmatch() and
regexp-matched ^-patterns. See above about someday
porting Penn's stuff. |
| Time & Date
Functions |
| Penn uses the time and date routines of the system
it's running on, which means for most cases, dates
have to fall between 1970 and 2038. Its basic time
type is the number of seconds since the start of the
host's epoch (Usually the start of 1970), and supports
displaying this in human-readable format using UTC or
the server's time-zone, and complex formatting with
timefmt() |
Brazil wrote his own time and date routines for
MUX, and so it supports a much wider range of
dates. That's good. It too has the UTC/local time
zones and timefmt() in compatible ways. |
| When it comes to elapsed time, Penn has two basic
functions: timestring() and etimefmt(). |
MUX has neither, but has singletime(),
writetime(), exptime(), digittime(), exptime() (Like
Penn's timestring() with one argument), and
digittime(). These are all fairly easily softcoded on
Penn using its elapased time functions. |
| Time in Penn is handled at a minimum
resolution of 1 second. |
On MUX, you can use fractions of a
second in some cases. |
| Penn will, on some systems (Namely glibc-based
linux ones), support a variety of formats that
convtime() can understand as a valid date and time to
turn into a seconds count. |
MUX supports a variety of formats always, and
they're a different variety to go along with the
greater date range and sub-second time
resolution. It's not template-based like Penn's. |
| Wizard, Inherit, and Trust |
| Any object can have the wizard flag on Penn. Any
Wizard player can set the Wizard flag on objects they
own. |
Only #1 can set wizard flags on MUX, and they're
usually only set on players. |
| Penn has no way for an object to 'inherit' the
permissions and privileges of its owner. Each object
must be given the powers it needs. |
MUX has the INHERIT flag to do this. Penn used to
have a flag named INHERIT that does something else,
and it was renamed to TRUST a while back because
people were getting confused about the similarity in
names. |