This past two weeks I have been tinkering with a pair of mudlibs,
Lima-1.0a6 and TMI-2v1.4a. I should state that I have extensive
experience with the TMI 1.3 lib, and that will doubtless color my
questions.
And so, in no particular order, my questions:
1. In what ways is the TMI 1.4 lib different from the 1.3 release?
2. It seems that no changes have been made since Mid 1996, and that
there are no Muds remaining which support/use the TMI libs. If any work
is being done using this lib, who is doing it and where?
3. Would they be willing to share improvements/ideas?
4. There are numerous references in the Lima mudlib to its speed gains
over the TMI lib. These, as I understand them are gained in the removal
of the set() property function. I can understand that this would be the
case, but, I would like to ask just how much of an improvement there is?
5. I don't think I understand exactly what the difference between a verb
and a command. Would someone please explain it to me? Note: I did
read the help file on 'verbs/commands', which I didn't find too helpful
=)
6. What security problems remain in the TMI lib? Lima?
7. Since it was decided to not support the the add_action() in Lima, how
would one go about creating a facsimile? I understand the argument that
a universal parsing system is a a good thing (tm) and I agree.
Therefore, how would one create a brewery vat which reacted to, for
instance, 'stir'ing, after ingredients were placed into it?
8. Is there more documentation on the modules? Or, alternatively, are
there any admins using the Lima lib actively who would consent to a
wizard just reading through what they have done and asking questions
soas to get a handle on how the lib works?
Hmm...that may be it for tonoight. Doubtless any answers will bring to
mind more questions.
Thanks in advance,
Tiggy
While the point about mudlib efficiency is true in many cases, this
is not one of them, since the simulation of variables at the mudlib
level (which is what properties are) result in an order of magnitude
difference (yes, that's right, a factor of 10) in speed. This can
make a substantial difference on real MUDs, especially since query
and set will be involved in almost every snippet of code running,
so the 10x slow down will be everywhere, including wherever your
particular bottlenecks are. It can get ugly.
Properties introduce much more than an additional layer of function
calls since (for example) even variable name lookup is now defered
to runtime. And this is without even mentioning the shortcomings
of properties from a maintenance, type safety, and flexibility
standpoint.
-Beek
>One note, though: Lima and TMI are both huge and relatively boggy on
>most systems people run muds on. This is not a harsh criticism, because
>they also do things few if any other libs DO, but if you want to run
>an LP on a really slow system, go elsewhere for a lib.
If you want speed, you might try Heaven7. OTOH, this means you have to run
3.x, and 3.x is almost but not quite compatible with just about everything
else (even 2.4.5 compat mode is somewhat flakey).
I've given up with the current crop of libs and have resorted to writing my
own -- from Lil. Phew ;-)
Evergreen@icewind
skaidi.hifm.no 2021
--
Cameron Kaiser
cdkaiser at concentric dot net (it hasn't helped the spam yet though)
*** visit the Spectre Server at www.sserv.com
*** C64 software lives! www.computerworkshops.home.ml.org
I, too, have been comparing different versions of mudlibs recently,
including Lima, Foundation, and TMI. I'm happy to share what little I
know.
> 2. It seems that no changes have been made since Mid 1996, and that
> there are no Muds remaining which support/use the TMI libs. If any work
> is being done using this lib, who is doing it and where?
I did a rudimentary search at The Mud Connector
(http://www.mudconnect.com) and found seven MUDs using TMI, seven MUDs
using Lima, and 117 MUDs claming to be an LPMud code base. (These were,
unfortunately, disjoint sets.) I don't know if work is being done on
TMI now; I think it is being presented as a learning tool, rather than a
real starting point for a modern mudlib.
> 4. There are numerous references in the Lima mudlib to its speed gains
> over the TMI lib. These, as I understand them are gained in the removal
> of the set() property function. I can understand that this would be the
> case, but, I would like to ask just how much of an improvement there is?
It is my intention to do some real quantitative analysis of this. The
Lima documentation claims that using set() is seven times slower than
using a direct call (Lima
lib/help/wizard/design_decisions/properties:22). I don't know how this
translates into overall mudlib speed.
I happen to like the ability to set any attribute on an object. I use
the following code in my mudlib:
mapping attr;
string foo;
varargs string set_foo( string value )
{
if ( ! nullp( value ) )
foo = value;
return foo;
}
mixed set( string key , string value )
{
mixed result;
result = call_other( this_object() , "set_"+key , value );
if ( ! undefinedp(result) )
return result;
result = attr[key] = value;
return result;
}
My hope is that this gives me the best of both worlds...speed plus
flexibility. However, I have not analyzed this yet.
> 7. Since it was decided to not support the the add_action() in Lima, how
> would one go about creating a facsimile? I understand the argument that
> a universal parsing system is a a good thing (tm) and I agree.
> Therefore, how would one create a brewery vat which reacted to, for
> instance, 'stir'ing, after ingredients were placed into it?
As you probably know, Lima's standpoint is that if something is
'stir'able, *everything* must be stirable (Lima:
lib/help/wizard/design_desicions/add_action:14). I believe you would
have to add a new verb "lib/cmds/verbs/stir.c", a new module
"lib/std/modules/stirable.c", and an object "vat.c" which defined a
"do_stir" function. Any object which did not include the stirable
module would fail the stir command. (I have not yet decided if this is
the right approach for me. My mudlib continues to allow add_action;
however, its command system is still very primative.)
> Thanks in advance,
> Tiggy
I'm glad you asked these questions, because I would like to stimulate
discussion on these points.
-- Scott
>It is my intention to do some real quantitative analysis of this. The
>Lima documentation claims that using set() is seven times slower than
>using a direct call (Lima
>lib/help/wizard/design_decisions/properties:22). I don't know how this
>translates into overall mudlib speed.
I've got a copy of lima mudlib I examined when I was looking for a mudlib
to use (eventually decided to write one - what the heck, no rush after
all :). I'll have to rummage around because I'm not sure what they are
referring to re set().
>I happen to like the ability to set any attribute on an object. I use
>the following code in my mudlib:
As do I...
[snip some code]
> mixed set( string key , string value )
> {
> mixed result;
> result = call_other( this_object() , "set_"+key , value );
> if ( ! undefinedp(result) )
> return result;
> result = attr[key] = value;
> return result;
> }
I like that idea - neat and tidy. Coming from a "discworld" based lib I have
similar code. The difference being that the settings for things that aren't
real variables are referred to as properties and have to be set using a
different call.
I guess the only count against your set() is there is an extra call_other()
in every call but I wouldn't have expected set() to be called often enough
for it to make a noticeable slowdown?
>> 7. Since it was decided to not support the the add_action() in Lima, how
>> would one go about creating a facsimile? I understand the argument that
>> a universal parsing system is a a good thing (tm) and I agree.
>> Therefore, how would one create a brewery vat which reacted to, for
>> instance, 'stir'ing, after ingredients were placed into it?
>As you probably know, Lima's standpoint is that if something is
>'stir'able, *everything* must be stirable (Lima:
>lib/help/wizard/design_desicions/add_action:14).
This was one of the aspects of Lima that put me off it.
>I believe you would
>have to add a new verb "lib/cmds/verbs/stir.c", a new module
>"lib/std/modules/stirable.c", and an object "vat.c" which defined a
>"do_stir" function. Any object which did not include the stirable
>module would fail the stir command.
This seems to be a huge amount of overhead for the newbie creator who
just wants to have a "bingle" command for his object. I suppose (expect)
that Lima has practically every verb you can think of in there already by
now though.
There must be extra overhead though in a room full of objects, each time
you do a command with a name that matches multiple objects each must
be checked for the command function. Whereas with the command associated
to the object, it is found right away.
> (I have not yet decided if this is
>the right approach for me. My mudlib continues to allow add_action;
>however, its command system is still very primative.)
My mudlib also allows add_action, but it is not the driver (MudOS v22) add_action.
That is replaced by a simul_efun that hooks into my own command system. I'm
undecided as yet whether to go the whole hog and compile MudOS with
NO_ADD_ACTION though.
From memory my system for player commands goes:
1) check command server
2) check local commands
Local commands are the ones added by the add_action simul_efun. They are
associated with the object that added them, should that object cease to
exist then the command is lost, also if the object stops being "close" to the
player. To be "close" the object must either be the player, the environment
of the player, in the same environment of the player, in the player's inventory
or a shadow of the player.
>I'm glad you asked these questions, because I would like to stimulate
>discussion on these points.
Careful what you ask for... :)
--
Scatter ///\oo/\\\
: While the point about mudlib efficiency is true in many cases, this
: is not one of them, since the simulation of variables at the mudlib
: level (which is what properties are) result in an order of magnitude
: difference (yes, that's right, a factor of 10) in speed. This can
If it is in fact that large, which I assume you are correct about, I
stand corrected. How does this stack up if one lpc->c's the code?
: to runtime. And this is without even mentioning the shortcomings
: of properties from a maintenance, type safety, and flexibility
: standpoint.
The only one of these last that bothers me is maintenance, really, but
then, I'm so used to the utter lack of type safety that I never miss
it. Flexibility is a point, but then, one doesn't use nukes to do
quarry blasting, either. Personally, I find properties to be useful,
but only in certain contexts, and generally in situations that require
more complex properties(such as timed ones) than most libs have.
--
John J. Adelsberger III
j...@umr.edu
"Civilization is the process of setting man free from men."
- Ayn Rand
Maybe I missed a few discussions here - what shortcomings in maintenance
and flexibility?
(No, I don't intend to start a pro/anti-properties discussion here,
I'm just curious about the anti-arguments.)
--
Lars Duening; la...@cableinet.co.uk
>In <34CE21...@or.cadix.com>, "Scott G. Stewart" <sste...@or.cadix.com> writes:
>[snip some code]
>> mixed set( string key , string value )
>> {
>> mixed result;
>> result = call_other( this_object() , "set_"+key , value );
>> if ( ! undefinedp(result) )
>> return result;
>> result = attr[key] = value;
>> return result;
>> }
>I like that idea - neat and tidy. Coming from a "discworld" based lib I have
>similar code. The difference being that the settings for things that aren't
>real variables are referred to as properties and have to be set using a
>different call.
>I guess the only count against your set() is there is an extra call_other()
>in every call but I wouldn't have expected set() to be called often enough
>for it to make a noticeable slowdown?
Well. If you are looking at it solely from performance perspective, I would
actually think that the biggest inefficiency comes from using dynamically
'calculated' function name. It means that a new string has to be allocated
memory, string parts copied, call_other() being done, in which malloced
string (probably, not 100% sure here) has to be transformed into a shared
one (which are used by function name tables, to speed up comparisons
from there on), and after the call string will be free'd. So, depending
on how efficient memory allocation is being used, it might be the part
eating up most of the execution time.
This being said, it shouldn't really matter all that much, all in all.
Value-setting probably isn't the part that uses most CPU-time in any case.
>This seems to be a huge amount of overhead for the newbie creator who
>just wants to have a "bingle" command for his object. I suppose (expect)
Well. One can also ask whether it's really necessary to make
"bingle", "foobar" or "gobblegoo"-commands. The good old
guess-the-verb-game comes to mind.
>that Lima has practically every verb you can think of in there already by
>now though.
Not being very familiar with Lima (browsed through some version few months
ago), I think it did use some sort of event-passing. That is, once you
have defined the syntax(es) of a command, an event (function call to a
function of which name reflects which syntax was used, "take_with_obj()"
or something like that?) will be sent to the object(s) referred to,
parsing is done by a daemon and other actions taken by the object(s)
referred to. Now; it would seem that it should be fairly easy to just
define the syntax(es) for the new verb and then make an object react
to the event by defining the function(s) necessary? Sounds easier than
doing add_action() _and_ parsing in the command.
I use quite a similar system in the mudlib I've written, although the
events are defined bit differently. The basic idea is about the same however.
>There must be extra overhead though in a room full of objects, each time
>you do a command with a name that matches multiple objects each must
>be checked for the command function. Whereas with the command associated
>to the object, it is found right away.
Why should there be any more overhead? I would actually think it's exactly
the opposite (unless you are dealing with really simple, verb-only commands);
with add_action(), each object would have to make sure it is the one being
referred to. But if parsing is done by just one object (daemon), it can
just check which object(s) are referenced once and for all. In addition,
it's much easier to make parser understand pronouns ("him", "her", "it",
"them" etc) that way, as well as more general references like "all swords",
"third stone/"stone 3" and so on.
>From memory my system for player commands goes:
>1) check command server
>2) check local commands
Offhand, it would seem the order should be the other way, so that local
commands could override globals if need be? (That's one of the reasons
people want to have add_action()... and usually add_action() is the
wrong answer anyways)
>Local commands are the ones added by the add_action simul_efun. They are
>associated with the object that added them, should that object cease to
>exist then the command is lost, also if the object stops being "close" to the
>player. To be "close" the object must either be the player, the environment
>of the player, in the same environment of the player, in the player's inventory
>or a shadow of the player.
So how exactly are the commands linked to the player? Is there some central
object which item has to register the command to, or does the command parser
always ask each item carried (or present in the same room) about whether it
has defined the command?
>>I'm glad you asked these questions, because I would like to stimulate
>>discussion on these points.
>Careful what you ask for... :)
Indeed... :-)
--
Tatu Saloranta, aka Doomdark.
doom...@cc.hut.fi
>>I guess the only count against your set() is there is an extra call_other()
>>in every call but I wouldn't have expected set() to be called often enough
>>for it to make a noticeable slowdown?
>Well. If you are looking at it solely from performance perspective, I would
>actually think that the biggest inefficiency comes from using dynamically
>'calculated' function name.
Yes that's an interesting point. I have no generic set() function that calculates
the set_whatever function to call. Rather, things either call set_whatever
directly or they call add_property for a "virtual" variable.
I'd expect looking up the "virtual" variable name in the properties mapping
to be more time consuming than accessing a real variable, but this is IMO
outweighed by the flexibility in being able to tag an object with information
that needs to be preserved when the object saves and that cannot be
anticipated in advance. Anything that's either used often or can be thought
of at the design stage of the object should be implemented as a real variable.
Properties are intended to be used for things that affect a small number of
objects and are rarely checked.
>This being said, it shouldn't really matter all that much, all in all.
>Value-setting probably isn't the part that uses most CPU-time in any case.
I would expect that interogating an object to find the value of something
is a task that the mudlib performs quite often... A generic query() has the
same overhead problems as the generic set().
>>This seems to be a huge amount of overhead for the newbie creator who
>>just wants to have a "bingle" command for his object. I suppose (expect)
>Well. One can also ask whether it's really necessary to make
>"bingle", "foobar" or "gobblegoo"-commands. The good old
>guess-the-verb-game comes to mind.
Yes I know... that was a case of my mind going blank trying to think of
an example that wasn't something that would have been anticipated. :) I
wouldn't recommend actually using such commands, though I believe I do
have a 'bingle' soul implemented.
>Not being very familiar with Lima (browsed through some version few months
>ago), I think it did use some sort of event-passing. That is, once you
>have defined the syntax(es) of a command, an event (function call to a
>function of which name reflects which syntax was used, "take_with_obj()"
>or something like that?) will be sent to the object(s) referred to,
>parsing is done by a daemon and other actions taken by the object(s)
>referred to.
Let me see if I have that straight... Whatever handles the command parses
it to find which objects the command might refer to and then calls a
predefinied function in each of those objects to handle the command?
So if I was to type "stir all" in a room containing 100 boxes and one bucket
of paint, there would 101 calls to do_handle_stir() out of which 100 would
be worthless?
>Now; it would seem that it should be fairly easy to just
>define the syntax(es) for the new verb and then make an object react
>to the event by defining the function(s) necessary? Sounds easier than
>doing add_action() _and_ parsing in the command.
[note - all references to add_action() below should be taken to mean my
mudlib implementation of it, not the standard MudOS add_action handling]
That's one problem I have with add_action(), that it must parse the command
string itself. On the one hand this allows as much flexibility as you want in
the parsing, and the object itself can decide if the command really applies
to it. On the other hand it means everyone who codes an add_action() has
to write it's parser.
I might try a generic parser simul_efun, possibly using MudOS's parsing efuns
and see how feasable that is. Then the command handling could parse the
command arguments and call the function defined by add_action() with the
results of the parsing instead of with the unparsed string.
>Why should there be any more overhead? I would actually think it's exactly
>the opposite (unless you are dealing with really simple, verb-only commands);
>with add_action(), each object would have to make sure it is the one being
>referred to. But if parsing is done by just one object (daemon), it can
>just check which object(s) are referenced once and for all. In addition,
>it's much easier to make parser understand pronouns ("him", "her", "it",
>"them" etc) that way, as well as more general references like "all swords",
>"third stone/"stone 3" and so on.
Ok, suppose I have a two boxes and two buckets. One of the buckets contains
water, the other paint. The player types "stir paint".
The add_action system would mean the two boxes are ignored completely. The
buckets are cloned from an object which has add_action( "stir", do_stir ) or
equivalent. So the first bucket has do_stir( string arg ) called with arg = "paint".
It does it's parsing and since it isn't called "paint" and doesn't contain "paint", it
returns 0. The 0 return means that the command handler calls the next
possibility, the other bucket. The same process this time returns 1 as a match.
Now as I understand it, your system would mean that the handler parses "stir
paint" and finding no objects matching "paint" (assuming that the paint bucket
doesn't respond to "paint") it will try do_handle_stir() in box 1, and then in
box 2, and then in bucket 1, and then in bucket 2 before finding a match.
The add_action version only has to check the objects that have "stir" linked
to them whereas the other has to check all objects in the room so in fact it
found which objects were referred to twice as fast.
That's ignoring parsing costs, but a common parsing efun with the results of
the parse passed to the add_action routine would level the playing field I
think. Otherwise the add_action version above effectively parses the command
twice, and probably in a more simplistic fashion.
If you consider a room with 200 boxes in and the box object doesn't define
stir - your system will still try calling do_handle_stir in all 200 boxes, plus
the room itself, plus the player? The add_action system will abort right
away since it knows in advance that there is no object there that handles "stir".
>>From memory my system for player commands goes:
>>1) check command server
>>2) check local commands
>
>Offhand, it would seem the order should be the other way, so that local
>commands could override globals if need be? (That's one of the reasons
>people want to have add_action()... and usually add_action() is the
>wrong answer anyways)
Um, good question. I'll have to go back and have a look, it was a while ago
I wrote that bit. I can't remember offhand whether I decided add_action()s
should be able to override the command server or not. Generally player
commands are not the sort of thing you would want an object to
override in the first place. In the case of changing things like "look" or "go"
as a result of an object or spell, my intention is that this should be done
via a shadow on the player. The command server checks for player->cmd_blah()
to check for an override to the "blah" command for example.
This is a result of the way I intend the magic system to work. (I'll explain more
if you're really interested).
>>Local commands are the ones added by the add_action simul_efun. They are
>>associated with the object that added them, should that object cease to
>>exist then the command is lost, also if the object stops being "close" to the
>>player. To be "close" the object must either be the player, the environment
>>of the player, in the same environment of the player, in the player's inventory
>>or a shadow of the player.
>So how exactly are the commands linked to the player? Is there some central
>object which item has to register the command to, or does the command parser
>always ask each item carried (or present in the same room) about whether it
>has defined the command?
The player object stores the links in a mapping variable, something like
([ string command : ({ ({ object handling_object, string function }) }) ]).
That is, the command is mapped to a list of objects handling it and the appropriate
function to call for that object. The command handling simply goes through
the list for a command, calling each object's function in turn until one of them
returns 1 to say that the command has been taken care of. If the object no
longer exists or check_close() returns 0 for that object, the entry is removed
from the list.
The add_action( string cmd, string function) simul_efun generates a call of the
form this_player()->add_command_entry( cmd, function, previous_object() )
to add to the array.
Objects can happily call add_command_entry themselves rather than use
the simul_efun, it's a case of ease of coding and familiarity to have it.
Since the command server is checked first, the vast majority of commands
never even get as far as checking this list so I don't think it'll have much
impact on speed (my mudlib isn't far enough along to really test this yet).
Don't think that entering a room for example will add_action() for each of
the exits, or that "look" etc are add_action()s in the player object - all
these common commands are handled by the command server.
Add_action()s are like properties - for those little extra bits that are nice
to be able to put in easily but aren't done all the time.
--
Dan
///\oo/\\\
It does ... as long as you never use the set() method. If you do,
you incur an extra call_other overhead, which I think is a factor
of 2-15 slower depending on how likely it is that you hit the call_other
cache. In general, your hack doesn't gain much.
BTW, the factor of 7 figure comes from benchmarks. I.e. mine, about
five years ago now :-)
-Beek
: Maybe I missed a few discussions here - what shortcomings in maintenance
: and flexibility?
First of all, properties introduce the ability to write code that
compiles but is completely impossible to debug. The problem being the
misspelling of the properties. In addition, properties will accept
any data as their values, whether or not that data is valid for the
given property.
Then there is also the issue of encapsulation. You are making some
base object the master of data that has nothing to do with the
conceptual object you are building. That makes it difficult to
implement polymorphism relating to properties.
And you gain absolutely nothing if properties are used as your
fundamental attribute mechanism. They are useful, IMHO, only as
static temporary storage for realm specific data. They never should
be employed by the mudlib except for odd things like debugging.
--
George Reese (bo...@imaginary.com) http://www.imaginary.com/~borg
"In our fear, we make an image, and that image we call God."
Antonius Block in The Seventh Seal
PGP Key: http://www.imaginary.com/servlet/Finger?user=borg&verbose=yes
: Yes I know... that was a case of my mind going blank trying to think of
: an example that wasn't something that would have been anticipated. :) I
: wouldn't recommend actually using such commands, though I believe I do
: have a 'bingle' soul implemented.
The reason you have a problem coming up with an example is that there
is absolutely no circumstance under which the add_action() approach
actually is preferable to the MudOS verb parser.
:>Not being very familiar with Lima (browsed through some version few months
:>ago), I think it did use some sort of event-passing. That is, once you
:>have defined the syntax(es) of a command, an event (function call to a
:>function of which name reflects which syntax was used, "take_with_obj()"
:>or something like that?) will be sent to the object(s) referred to,
:>parsing is done by a daemon and other actions taken by the object(s)
:>referred to.
: Let me see if I have that straight... Whatever handles the command parses
: it to find which objects the command might refer to and then calls a
: predefinied function in each of those objects to handle the command?
: So if I was to type "stir all" in a room containing 100 boxes and one bucket
: of paint, there would 101 calls to do_handle_stir() out of which 100 would
: be worthless?
No. It would be:
number of calls to direct_stir_obs() == # of objects with
direct_stir_obs() functions
And further processing only occurs in objects for which the above
returns true (as a simplistic description).
:>Now; it would seem that it should be fairly easy to just
:>define the syntax(es) for the new verb and then make an object react
:>to the event by defining the function(s) necessary? Sounds easier than
:>doing add_action() _and_ parsing in the command.
: [note - all references to add_action() below should be taken to mean my
: mudlib implementation of it, not the standard MudOS add_action handling]
: That's one problem I have with add_action(), that it must parse the command
: string itself. On the one hand this allows as much flexibility as you want in
: the parsing, and the object itself can decide if the command really applies
: to it. On the other hand it means everyone who codes an add_action() has
: to write it's parser.
You should most definitely NOT have "as much flexibility as you want
in the parsing". Syntazes should be standardized across the mud and
well documented. Anything else is a pointless game.
: I might try a generic parser simul_efun, possibly using MudOS's parsing efuns
: and see how feasable that is. Then the command handling could parse the
: command arguments and call the function defined by add_action() with the
: results of the parsing instead of with the unparsed string.
How does it determine what the command arguments are? You are
oversimplifying the issue, much as add_action() does.
:>Why should there be any more overhead? I would actually think it's exactly
:>the opposite (unless you are dealing with really simple, verb-only commands);
:>with add_action(), each object would have to make sure it is the one being
:>referred to. But if parsing is done by just one object (daemon), it can
:>just check which object(s) are referenced once and for all. In addition,
:>it's much easier to make parser understand pronouns ("him", "her", "it",
:>"them" etc) that way, as well as more general references like "all swords",
:>"third stone/"stone 3" and so on.
: Ok, suppose I have a two boxes and two buckets. One of the buckets contains
: water, the other paint. The player types "stir paint".
: The add_action system would mean the two boxes are ignored completely. The
: buckets are cloned from an object which has add_action( "stir", do_stir ) or
: equivalent. So the first bucket has do_stir( string arg ) called with arg = "paint".
: It does it's parsing and since it isn't called "paint" and doesn't contain "paint", it
: returns 0. The 0 return means that the command handler calls the next
: possibility, the other bucket. The same process this time returns 1 as a match.
: Now as I understand it, your system would mean that the handler parses "stir
: paint" and finding no objects matching "paint" (assuming that the paint bucket
: doesn't respond to "paint") it will try do_handle_stir() in box 1, and then in
: box 2, and then in bucket 1, and then in bucket 2 before finding a match.
Nope, this is not how the MudOS system works. First, your command is
vague. It should be "stir paint in bucket". And it should respond
properly to such things as:
stir red paint in the bucket
stir the read paint in the blue bucket
stir the ugly red paint in the dirty blue bucket
mix the paint in the bucket
(assuming of course the paint is ugly and red and the bucket is dirty
and blue)
At this point, add_action() is already messing with your mind. Newbie
cres are unlikely to do the following:
* handle adjectives and articles properly
* handle synonyms
Failing to handle synonyms is only bad since cres for other areas who
are more savvy will handle them, thus creating an inconsistency across
the mud.
(Beek might want to correct any missing details here)
But let's say you actually want "stir paint" to work (bad form). You
should have a paint object that the bucket contains. Thus the parser
would respond to the "stir paint" command by checking every object to
see if it has an ID of "paint". For each paint object, it will then
check direct_stir_obj(). If none return true, an error occurs. If
any return true, it goes on processing by calling multiple trues as
vague or actually performing a stir on a singular match.
: The add_action version only has to check the objects that have "stir" linked
: to them whereas the other has to check all objects in the room so in fact it
: found which objects were referred to twice as fast.
And naming clashes are indeterminate. If there is paint (and thus
stir actions) in both the box and the bucket, which one is stirred is
simply the luck of the draw. Furthermore, if the box defines stir but
the target of the stirring is soup, the box will:
* have to perform an ID check on itself in LPC, meaning again that ID
checking will vary from creator to creator and be slower than driver
ID checking
* call notify_fail() properly so that processing can go on to the
bucket. Creators are notorious about failing to call notify_fail(),
thus causing a "What?" when the player has a bucket for stirring.
: That's ignoring parsing costs, but a common parsing efun with the results of
: the parse passed to the add_action routine would level the playing field I
: think. Otherwise the add_action version above effectively parses the command
: twice, and probably in a more simplistic fashion.
: If you consider a room with 200 boxes in and the box object doesn't define
: stir - your system will still try calling do_handle_stir in all 200 boxes, plus
: the room itself, plus the player? The add_action system will abort right
: away since it knows in advance that there is no object there that handles "stir".
Again, this is not the way it works. Even if it did, it is infinitely
preferable in terms of functionality. After all, isn't it faster not
to parse commands at all?
The most important benefit of the MudOS command parser that seems to
always go unnoticed is the fact that the MudOS command parser allows
for proper error handling. With add_action(), you are lucky to get
anything other than "What?". Is it that there is no "stir" command?
Or is the problem that the right syntax is "stir paint in bucket"? Or
is the problem that the command I want is "mix" and not stir? Or is
it that I can "stir bucket" but not "stir paint"? add_action() does
almost nothing to help you provide a good error message to the player.
Under the MudOS parser, the player always knows WHY the command they
just issued did not do what they expected. If no command called
"stir" exists, they are told so. Nightmare even goes so far as to
tell them where they can go to get a full list of commands. If the
command has a different syntax than they used, they are given the
proper syntaxes. If you cannot stir "paint", but you can stir other
things, it tells you that you cannot stir paint.
And about that list of full commands. With the MudOS parser, it is
easy to keep a full list. With add_action(), it is nearly impossible.
: The reason you have a problem coming up with an example is that there
: is absolutely no circumstance under which the add_action() approach
: actually is preferable to the MudOS verb parser.
In fact: the Lima method is _usually_ preferable, for a number of reasons,
but there are several key assumptions in this judgement, not all of which
will always hold true even though all of them usually do. For instance,
if you want to make a mud in which coherence is NOT a goal, the centralized
approach is unsuitable, and while mindless wordgames are silly, there COULD
be a reason to do something like this, even if I don't know what it is at
the moment.
The reason _I_ don't use the MudOS parsing stuff is that it requires the
MudOS containment stuff, which I refuse to use for other reasons. It is
certain that George will insist that as a result, nothing I will ever do
with my lib will be any good at all, and that I am demonstrably wrong,
and that the MudOS containment stuff ought to be good enough for any and
all purposes, but that's because he's a fucking idiot.
: You should most definitely NOT have "as much flexibility as you want
: in the parsing". Syntazes should be standardized across the mud and
: well documented. Anything else is a pointless game.
"Pointless." So did speak George Reese, who is a god in his own mind.
Please, George... could you do some melodrama for us?
: How does it determine what the command arguments are? You are
: oversimplifying the issue, much as add_action() does.
So since he didn't provide all the details down to the implementation
level in a discussion on a newsgroup, he's wrong?
: Nope, this is not how the MudOS system works. First, your command is
: vague. It should be "stir paint in bucket". And it should respond
: properly to such things as:
: stir red paint in the bucket
: stir the read paint in the blue bucket
: stir the ugly red paint in the dirty blue bucket
: mix the paint in the bucket
: (assuming of course the paint is ugly and red and the bucket is dirty
: and blue)
So basically, you're requiring levels of detail he doesn't want, simply
because you think it has to be there, even though its not your game?
You've got a serious deity complex going there, Georgy.
: At this point, add_action() is already messing with your mind. Newbie
: cres are unlikely to do the following:
: * handle adjectives and articles properly
: * handle synonyms
They do if you enforce standards. Of course, some people can't be
bothered, but thats hardly a code problem.
: But let's say you actually want "stir paint" to work (bad form). You
Since he most certainly DOES want it to work, this seems a reasonable
request. Imagine... a parser that, given a command that OBVIOUSLY
targets the ONLY paint in a room(his example, not mine,) one might
actually do the command, instead of playing dumb and making the player
type out needless verbiage.
: should have a paint object that the bucket contains. Thus the parser
So even if all he wants is a stirrable bucket of paint, he has to have
2 objects. One would suffice, and in fact would be better in most
respects, and would appear NO different to a player, but because you
have ordained it so, it must be so. Preach it, brother...
: And naming clashes are indeterminate. If there is paint (and thus
: stir actions) in both the box and the bucket, which one is stirred is
: simply the luck of the draw.
Unless, of course, you modify add_action so that it doesn't do that.
The facts that the current MudOS add_action() is braindead and the
current MudOS centralized parsing stuff is fairly workable doesn't
mean distributed parsing is always bad and centralized parsing is
always good, even if you're too dense to see this as two separate
issues.
: Furthermore, if the box defines stir but
: the target of the stirring is soup, the box will:
: * have to perform an ID check on itself in LPC, meaning again that ID
: checking will vary from creator to creator and be slower than driver
: ID checking
If you can't figure out how to do this sort of thing in mandated inherit
files, you're grossly incompetent. LPC->C can take care of the speed
problem nicely.
: * call notify_fail() properly so that processing can go on to the
: bucket. Creators are notorious about failing to call notify_fail(),
: thus causing a "What?" when the player has a bucket for stirring.
If you choose not to enforce QC standards, you're a moron. This has
nothing to do with one way or another of parsing, and should not be
confused with it.
: And about that list of full commands. With the MudOS parser, it is
: easy to keep a full list. With add_action(), it is nearly impossible.
Mmm... administrivia. Again, it is easy to keep a full list of commands
in play by doing QC and maintaining your list appropriately. This is
not to say it is desirable, but you make all kinds of wild claims that
are just OBVIOUSLY false, and someone really needs to point this out,
so I will.
Just to make sure we have the same understanding of 'polymorphism': you
mean
for example that object A simply stores the given value when confronted
with
a 'SetLong(text)', whereas object B massages the value a bit before storing
it?
> And you gain absolutely nothing if properties are used as your
> fundamental attribute mechanism. They are useful, IMHO, only as
> static temporary storage for realm specific data. They never should
> be employed by the mudlib except for odd things like debugging.
I just wish it would be easier to get the 'SetFoo()/QueryFoo()' methods if
the
only thing they do is to set/query a variable. Our wizards tend to forget
these
things on grounds of 'it won't be needed', making debugging sometimes quite
difficult.
--
Lars Duening; la...@cableinet.co.uk
>In <doomdark....@snakemail.hut.fi>, doom...@sitriini.hut.fi (Tatu P Saloranta) writes:
>>sca...@thevortex.com (Scatter ///\oo/\\\) writes:
>>>In <34CE21...@or.cadix.com>, "Scott G. Stewart" <sste...@or.cadix.com> writes:
>>Well. If you are looking at it solely from performance perspective, I would
>>actually think that the biggest inefficiency comes from using dynamically
>>'calculated' function name.
>Yes that's an interesting point. I have no generic set() function that calculates
>the set_whatever function to call. Rather, things either call set_whatever
>directly or they call add_property for a "virtual" variable.
>I'd expect looking up the "virtual" variable name in the properties mapping
>to be more time consuming than accessing a real variable, but this is IMO
>outweighed by the flexibility in being able to tag an object with information
>that needs to be preserved when the object saves and that cannot be
>anticipated in advance. Anything that's either used often or can be thought
>of at the design stage of the object should be implemented as a real variable.
>Properties are intended to be used for things that affect a small number of
>objects and are rarely checked.
Ok, I guess this is quite close to the way I did it on 'my' mudlib then.
And no, I don't think accessing a mapping member (with shared id string) is
significantly slower than doing a direct reference. Likewise, using a big
switch-case statement is (perhaps somewhat surprisingly) about as efficient
as using a mapping. It also has the advantage of being able to do checks
on value being set. Downside is that it probably looks ugly as hell... :-)
>>This being said, it shouldn't really matter all that much, all in all.
>>Value-setting probably isn't the part that uses most CPU-time in any case.
>I would expect that interogating an object to find the value of something
>is a task that the mudlib performs quite often... A generic query() has the
>same overhead problems as the generic set().
Yes, true.
>>>This seems to be a huge amount of overhead for the newbie creator who
>>>just wants to have a "bingle" command for his object. I suppose (expect)
>>Well. One can also ask whether it's really necessary to make
>>"bingle", "foobar" or "gobblegoo"-commands. The good old
>>guess-the-verb-game comes to mind.
>Yes I know... that was a case of my mind going blank trying to think of
>an example that wasn't something that would have been anticipated. :) I
>wouldn't recommend actually using such commands, though I believe I do
>have a 'bingle' soul implemented.
:-)
First, before commenting on command parsing, I'd like to note that what
George wrote about Lima-mudlib covers most of the issues I would have,
and I agree with about all in his reply. Besides, as I said, I'm not an
expert on Lima. Anyways, there are some points I'd like reiterate:
>>Not being very familiar with Lima (browsed through some version few months
>>ago), I think it did use some sort of event-passing. That is, once you
>>have defined the syntax(es) of a command, an event (function call to a
>>function of which name reflects which syntax was used, "take_with_obj()"
>>or something like that?) will be sent to the object(s) referred to,
>>parsing is done by a daemon and other actions taken by the object(s)
>>referred to.
>Let me see if I have that straight... Whatever handles the command parses
>it to find which objects the command might refer to and then calls a
>predefinied function in each of those objects to handle the command?
In the mudlib I've written and use, yes. There are few exceptions, for
some of the weirder commands, though, in case no item is found with
a matching id ("read 4" to access a mailbox is one example... Although,
"read 4 from mailbox" is a valid command, and would actually lead to
an event being sent straight to the mailbox object)
>So if I was to type "stir all" in a room containing 100 boxes and one bucket
>of paint, there would 101 calls to do_handle_stir() out of which 100 would
>be worthless?
Well, actually, the way I look at it is that the player has said he wants to
try to stir _all_ items present. So it means we'll be calling all items
(provided we want to allow that for stir-command, for example... but in
any case we do understand which object(s) he/she referred to), yes.
>>Why should there be any more overhead? I would actually think it's exactly
>>the opposite (unless you are dealing with really simple, verb-only commands);
>>with add_action(), each object would have to make sure it is the one being
>>referred to. But if parsing is done by just one object (daemon), it can
>>just check which object(s) are referenced once and for all. In addition,
>>it's much easier to make parser understand pronouns ("him", "her", "it",
>>"them" etc) that way, as well as more general references like "all swords",
>>"third stone/"stone 3" and so on.
>Ok, suppose I have a two boxes and two buckets. One of the buckets contains
>water, the other paint. The player types "stir paint".
And like George already mentioned, I'd say this command is too vague
to be understood. So, first check would reveal that there's no item
with id 'paint'. Or alternatively, someone has done a kludge and added
id 'paint' to the bucket... :-)
Now, mudlib could also try checking 'details' of items ("paint in bucket",
detail "paint") if it really wanted to do more work. And this would seem
to be something mudlib could easily do in a centralized way. (I have only
done this for examine/look; sometimes it makes sense to allow players to
use 'read writing' instead of 'read writing on the sword', as a shortcut).
In any case, after deciding which object(s) was/were referred to, it/they
would be sent an event notification of some form (function call), and the
object could react whatever the way it sees fit.
So, all in all, I guess what I try to say is that the example command
would most probably be considered an 'invalid command'.
>The add_action system would mean the two boxes are ignored completely. The
>buckets are cloned from an object which has add_action( "stir", do_stir ) or
>equivalent. So the first bucket has do_stir( string arg ) called with arg = "paint".
>It does it's parsing and since it isn't called "paint" and doesn't contain "paint", it
>returns 0. The 0 return means that the command handler calls the next
>possibility, the other bucket. The same process this time returns 1 as a match.
>Now as I understand it, your system would mean that the handler parses "stir
>paint" and finding no objects matching "paint" (assuming that the paint bucket
>doesn't respond to "paint") it will try do_handle_stir() in box 1, and then in
>box 2, and then in bucket 1, and then in bucket 2 before finding a match.
>The add_action version only has to check the objects that have "stir" linked
>to them whereas the other has to check all objects in the room so in fact it
>found which objects were referred to twice as fast.
However, how is the object to know whether it is "paint 2" or "paint 3"
("2nd paint", "3rd paint, whatever)? Id-handling should be done well;
all synonyms that are normally applicable should be used and so on.
Which probably means there'd often be (order of) n ^ 2 id-checks,
as opposed to n if it was done once and for all.
Also, one problem with add_action()s (and similar mechanisms) is really
that they have too little knowledge about global context/parsing. If more than
one item try to apply a command, and notice it wasn't directed to
them, both would try to define an error message, and which one is to be
used? Even worse, one of them might decide command was actually directed
to it, but had invalid arguments, printing out an error, returning 1,
and preventing other items from having a chance to handle the command.
>If you consider a room with 200 boxes in and the box object doesn't define
>stir - your system will still try calling do_handle_stir in all 200 boxes, plus
>the room itself, plus the player? The add_action system will abort right
>away since it knows in advance that there is no object there that handles "stir".
And which error message would be used? Infamous "what?"? (Well, actually,
it shouldn't be all that hard to have a catch-all error handling)
Add_action is indeed an efficient way of passing exotic commands, but
there the correctness is the bigger problem IMO.
>>>From memory my system for player commands goes:
>>>1) check command server
>>>2) check local commands
>>
>>Offhand, it would seem the order should be the other way, so that local
>>commands could override globals if need be? (That's one of the reasons
>>people want to have add_action()... and usually add_action() is the
>>wrong answer anyways)
>Um, good question. I'll have to go back and have a look, it was a while ago
>I wrote that bit. I can't remember offhand whether I decided add_action()s
>should be able to override the command server or not. Generally player
>commands are not the sort of thing you would want an object to
>override in the first place. In the case of changing things like "look" or "go"
>as a result of an object or spell, my intention is that this should be done
>via a shadow on the player. The command server checks for player->cmd_blah()
>to check for an override to the "blah" command for example.
Well, the way I allow 'overriding' is for the objects to redefine effects
events cause. So, parsing will still be done at global level, only the
effects will vary. So, to modify what is seen when a player is being looked
at, event EVENT_LOOKED_AT will be caught by some other object (which has
added an event handler for the object) and so on. And with plain "look",
event is sent to the surrounding room, which usually gives room descriptions
and so on.
You seldom (if ever?) really need to modify the way 'examine' or 'look'
is parsed I think.
>This is a result of the way I intend the magic system to work. (I'll explain more
>if you're really interested).
Sure?
>>So how exactly are the commands linked to the player? Is there some central
>>object which item has to register the command to, or does the command parser
>>always ask each item carried (or present in the same room) about whether it
>>has defined the command?
>The player object stores the links in a mapping variable, something like
>([ string command : ({ ({ object handling_object, string function }) }) ]).
>That is, the command is mapped to a list of objects handling it and the appropriate
>function to call for that object. The command handling simply goes through
>the list for a command, calling each object's function in turn until one of them
>returns 1 to say that the command has been taken care of. If the object no
>longer exists or check_close() returns 0 for that object, the entry is removed
>from the list.
Ah. How are the commands, then, removed from the mapping? Is it being kept
up-to-date all the time (ie. always remove a command when item is not
eligible any more to handle it, or lazy update, removing only when such a
command definition is found to be no longer valid). I mean, destructed
objects are removed ok, but how about items that only define commands
when carried by the player, and are dropped later on? Perhaps the item
removes old links when it has to add new ones (player has dropped the
item and someone else picks it up)?
>Since the command server is checked first, the vast majority of commands
>never even get as far as checking this list so I don't think it'll have much
>impact on speed (my mudlib isn't far enough along to really test this yet).
I guess the biggest issue (at least for me) isn't the performance.
Add_action() might well be the fastest way to handle certain commands...
But due to its problems it makes no difference to me.
>Add_action()s are like properties - for those little extra bits that are nice
>to be able to put in easily but aren't done all the time.
I haven't removed add_action() yet from my mud either...
Although the mudlib doesn't use it anywhere, and I'd strongly
discourage anyone to use it. =)
I guess it's same for both add_action() and shadow(); I consider
using either of them as either bad programming practice, or a sign of
some serious shortcoming in the mudlib. However, just in case,
they are there if someone can come up with some real use for them.
I did some tests for this on the latest Amylaar LP driver. The overhead for
the above solution is about factor 4, with the extra function call itself (not
the setup like "set"+name) accounting for factor 1.5 (interesting enough,
unresolved calls tend to be faster than resolved ones). It was a tight loop,
so 'real lib' usage would multiply another factor > 1 for cache misses.
Dunno how this compares to the latest MudOS driver, though.
--
Lars Duening; la...@cableinet.co.uk
: : The reason you have a problem coming up with an example is that there
: : is absolutely no circumstance under which the add_action() approach
: : actually is preferable to the MudOS verb parser.
: In fact: the Lima method is _usually_ preferable, for a number of reasons,
: but there are several key assumptions in this judgement, not all of which
: will always hold true even though all of them usually do. For instance,
: if you want to make a mud in which coherence is NOT a goal, the centralized
: approach is unsuitable, and while mindless wordgames are silly, there COULD
: be a reason to do something like this, even if I don't know what it is at
: the moment.
Let me requote myself:
"The reason you have a problem coming up with an example is that there
is absolutely no circumstance under which the add_action() approach
actually is preferable to the MudOS verb parser."
Note this statement compares the MudOS internal parsing system to
add_action() and comes to the conclusion that there is no situation in
which add_action() is preferable. It does not discuss or make any
claims about the Lima implementation. Furthermore, if you were
wanting a game in which coherence was not desired and mindless word
games were, there would be better tools than add_action(). You *can*
even use the MudOS parser to do both quite well if you want. The Lima
implementation urges (but does not force upon you) coherence and
centralization.
: The reason _I_ don't use the MudOS parsing stuff is that it requires the
: MudOS containment stuff, which I refuse to use for other reasons.
I believe that this has been addressed in the latest MudOS releases.
Regardless, it has no bearing on the central thesis: that the MudOS
parser is always better than add_action() (which, by the way, has the
containment restriction).
: It is
: certain that George will insist that as a result, nothing I will ever do
: with my lib will be any good at all, and that I am demonstrably wrong,
: and that the MudOS containment stuff ought to be good enough for any and
: all purposes, but that's because he's a fucking idiot.
I will let this statement speak for itself. Just note that I am not
saying nor have I ever said anything resembling this claim.
: : You should most definitely NOT have "as much flexibility as you want
: : in the parsing". Syntazes should be standardized across the mud and
: : well documented. Anything else is a pointless game.
: "Pointless." So did speak George Reese, who is a god in his own mind.
: Please, George... could you do some melodrama for us?
Guessing at syntax is pointless. I stand behind that in spite of your
irrelevant personal attack.
: : How does it determine what the command arguments are? You are
: : oversimplifying the issue, much as add_action() does.
: So since he didn't provide all the details down to the implementation
: level in a discussion on a newsgroup, he's wrong?
I said he oversimplified the issue.
: : Nope, this is not how the MudOS system works. First, your command is
: : vague. It should be "stir paint in bucket". And it should respond
: : properly to such things as:
: : stir red paint in the bucket
: : stir the read paint in the blue bucket
: : stir the ugly red paint in the dirty blue bucket
: : mix the paint in the bucket
: : (assuming of course the paint is ugly and red and the bucket is dirty
: : and blue)
: So basically, you're requiring levels of detail he doesn't want, simply
: because you think it has to be there, even though its not your game?
: You've got a serious deity complex going there, Georgy.
Level of details he does not want? These are levels of details that
are necessary for the game to run. That the game may or may not
accept articles is irrelevant. What is important is that it accept or
not accept articles consistently across the mud.
: : At this point, add_action() is already messing with your mind. Newbie
: : cres are unlikely to do the following:
: : * handle adjectives and articles properly
: : * handle synonyms
: They do if you enforce standards. Of course, some people can't be
: bothered, but thats hardly a code problem.
In my experience, enforcing this level of code detail runs close to
impossible on a large running mud. It requires way too much time and
effort on the part of QC arches who have a lot of other work to do.
Inconsistencies slip through. Why would you require all this work
when there is a way to guarantee consistency across the mud?
: : But let's say you actually want "stir paint" to work (bad form). You
: Since he most certainly DOES want it to work, this seems a reasonable
: request. Imagine... a parser that, given a command that OBVIOUSLY
: targets the ONLY paint in a room(his example, not mine,) one might
: actually do the command, instead of playing dumb and making the player
: type out needless verbiage.
Players should type out what the mean. But this is completely outside
of the topic at hand. If you want to argue it, start another thread.
: : should have a paint object that the bucket contains. Thus the parser
: So even if all he wants is a stirrable bucket of paint, he has to have
: 2 objects. One would suffice, and in fact would be better in most
: respects, and would appear NO different to a player, but because you
: have ordained it so, it must be so. Preach it, brother...
No, there are two conceptual objects and thus should be two actual
objects. There is an actual relationship between the bucket and the
paint, one which could change. Furthermore, the player should be able
to put the paint in other liquid containers. But you do not have this
sort of flexibility if you don't have a paint object.
The wonders of object-oriented design!
: : And naming clashes are indeterminate. If there is paint (and thus
: : stir actions) in both the box and the bucket, which one is stirred is
: : simply the luck of the draw.
: Unless, of course, you modify add_action so that it doesn't do that.
: The facts that the current MudOS add_action() is braindead and the
: current MudOS centralized parsing stuff is fairly workable doesn't
: mean distributed parsing is always bad and centralized parsing is
: always good, even if you're too dense to see this as two separate
: issues.
You are trying to change the argument. Let me quote yet again the
thesis of this post:
"The reason you have a problem coming up with an example is that there
is absolutely no circumstance under which the add_action() approach
actually is preferable to the MudOS verb parser."
As far as centralized vs. decentralized, I have made plenty of other
arguments to support that. Because some of my arguments actually
support my thesis here and not your pet discussion does not invalid
those arguments nor does it render the thesis behind your pet
discussion correct.
: : Furthermore, if the box defines stir but
: : the target of the stirring is soup, the box will:
: : * have to perform an ID check on itself in LPC, meaning again that ID
: : checking will vary from creator to creator and be slower than driver
: : ID checking
: If you can't figure out how to do this sort of thing in mandated inherit
: files, you're grossly incompetent. LPC->C can take care of the speed
: problem nicely.
I already addressed this issue. You are requiring extra effort on the
part of creators AND QC staff that is completely unnecessary.
Furthermore, you don't LPC->C everthing in the mud.
: : * call notify_fail() properly so that processing can go on to the
: : bucket. Creators are notorious about failing to call notify_fail(),
: : thus causing a "What?" when the player has a bucket for stirring.
: If you choose not to enforce QC standards, you're a moron. This has
: nothing to do with one way or another of parsing, and should not be
: confused with it.
Again, I have already discussed this issue.
: : And about that list of full commands. With the MudOS parser, it is
: : easy to keep a full list. With add_action(), it is nearly impossible.
: Mmm... administrivia. Again, it is easy to keep a full list of commands
: in play by doing QC and maintaining your list appropriately. This is
: not to say it is desirable, but you make all kinds of wild claims that
: are just OBVIOUSLY false, and someone really needs to point this out,
: so I will.
I stated: "With the MudOS parser, it is EASY to keep a full list.
With add_action(), it is NEARLY impossible." Maintaining by hand a
master list of add_action()'ed commands in the game is not easy. It
is a major pain in the ass, very prone to error, and likely to
constantly be out of date. Anyone who has ever attempted to maintain
by hand a master list of anything will tell you that.
It is also interesting to note you omitted the argument I deemed the
most important, the one about error handling.
This touches on an topic I have always wondered about. As an
implementor, I can understand the beauty of a system which handles such
verbose, real-language commands. However, as a player, I would very
rarely type such a string. I am much more likely to type "stir paint",
or "stir red" if I have more than one paint. I can see some advantages
to this minimalist command system:
* It is fast to type - expert users can be efficient
* It is easy to type - novice typers can be effective
* It is standard - users can get up to speed faster
I do not believe that "stir paint" is bad form...I think it is the
desired form, and that command parsing should be optimized around the
simple "<verb> <object>|<adjective>" syntax. More expressive syntax
should of course be available, but not as the primary language.
I came to LPMuds after being an Infocom player, then a Diku player. I
remember being frustrated when getting an error typing "look orc", and
having to re-type "look at orc". I think that we have to keep our users
in mind when we create parsers...most will prefer "stir paint" over
"stir red paint in the bucket"...especially in dangerous game situations
where expediency is needed.
-- Scott
In article <34D04B6B...@mdisystems.com>, Lars Duning <ldu...@mdisystems.com> writes:
> Tim Hollebeek wrote:
> [...]
> > Properties introduce much more than an additional layer of function
> > calls since (for example) even variable name lookup is now defered
> > to runtime. And this is without even mentioning the shortcomings
> > of properties from a maintenance, type safety, and flexibility
> > standpoint.
>
> Maybe I missed a few discussions here - what shortcomings in maintenance
> and flexibility?
>
> (No, I don't intend to start a pro/anti-properties discussion here,
> I'm just curious about the anti-arguments.)
The largest one is the complete inability to overload each query/set method
when you want to change the behavior without changing the API. In fact,
you usually can't even do:
mixed query(string key) { if (key == ...) ... }
since set is (for good reasons) usually nomask. You can add hacks to
allow you to solve these sorts of problems at the mudlib level (e.g.
a set_property_function() type thing) but that makes them even more
complex, and bumps your efficiency loss up again ...
---------------------------------------------------------------------------
Tim Hollebeek | "Everything above is a true
email: t...@wfn-shop.princeton.edu | statement, for sufficiently
URL: http://wfn-shop.princeton.edu/~tim | false values of true."
: Then there is also the issue of encapsulation. You are making some
: base object the master of data that has nothing to do with the
: conceptual object you are building. That makes it difficult to
: implement polymorphism relating to properties.
This argument goes as follows: 'Properties are a bad idea because it is
difficult to implement polymorphic properties.' Let's have a look here:
1) What if I want properties that aren't polymorphic?
2) What if I don't find it difficult(in point of fact, I don't.)
: And you gain absolutely nothing if properties are used as your
: fundamental attribute mechanism. They are useful, IMHO, only as
: static temporary storage for realm specific data. They never should
: be employed by the mudlib except for odd things like debugging.
Your opinion seems to be taken straight from the rationale files for Lima.
That said, there is a very good reason to minimize property usage, which
Beek already pointed out - speed. Why are you bothering to continue a
worthless discussion when your arguments aren't even meaningful?
That's a strong statement... I'm sure there must be at least one. Having
read the arguments below though, I'm starting to agree that there are
some very good arguments against the add_action system.
>:>ago), I think it did use some sort of event-passing. That is, once you
>:>have defined the syntax(es) of a command, an event (function call to a
>:>function of which name reflects which syntax was used, "take_with_obj()"
>:>or something like that?) will be sent to the object(s) referred to,
>: So if I was to type "stir all" in a room containing 100 boxes and one bucket
>: of paint, there would 101 calls to do_handle_stir() out of which 100 would
>: be worthless?
>
>No. It would be:
>number of calls to direct_stir_obs() == # of objects with
>direct_stir_obs() functions
There would need to be a function_exists check on each object then? Or
is there some sort of handler which registers which objects can do which
commands?
>: That's one problem I have with add_action(), that it must parse the command
>: string itself. On the one hand this allows as much flexibility as you want in
>: the parsing
>You should most definitely NOT have "as much flexibility as you want
>in the parsing".
Perhaps. However it is useful to be able to be flexible. In my experience
players will continuously complain about something that doesn't work
as expected and it is therefore nice to be able to fix objects to
accept technically incorrect syntax sometimes.
>Syntazes should be standardized across the mud and
>well documented.
That is a good point, I agree that all commands should follow a standard
syntax. That doesn't mean it has to be a horrifically complicated
"cope with anything" syntax though.
>: I might try a generic parser simul_efun, possibly using MudOS's parsing efuns
>: and see how feasable that is. Then the command handling could parse the
>: command arguments and call the function defined by add_action() with the
>: results of the parsing instead of with the unparsed string.
>How does it determine what the command arguments are? You are
>oversimplifying the issue, much as add_action() does.
I'm not sure I understand your question. The command arguments are the
things the player typed after the command itself. As in player types
"stir paint in bucket" then the arguments are "paint in bucket" which
the parser would examine and call the add_action's function with, say,
({ "paint", "bucket" }). I may well be oversimplifying things, but since
I haven't looked into actually coding it yet I haven't done much
investigation.
>: Now as I understand it, your system would mean that the handler parses "stir
>: paint" and finding no objects matching "paint" (assuming that the paint bucket
>: doesn't respond to "paint") it will try do_handle_stir() in box 1, and then in
>: box 2, and then in bucket 1, and then in bucket 2 before finding a match.
>Nope, this is not how the MudOS system works. First, your command is
>vague. It should be "stir paint in bucket".
Yes the command is vague. It's also the first thing I'd type if I can see
a bucket of paint and want to stir it. It's not technically correct perhaps
but it's the laziest way to get the action done and it's obvious what is
meant.
>And it should respond
>properly to such things as:
>
>stir red paint in the bucket
>stir the read paint in the blue bucket
>stir the ugly red paint in the dirty blue bucket
>mix the paint in the bucket
>
>(assuming of course the paint is ugly and red and the bucket is dirty
>and blue)
And, IMO, should also respond to "stir paint" and "stir bucket" etc.
>At this point, add_action() is already messing with your mind. Newbie
>cres are unlikely to do the following:
>* handle adjectives and articles properly
>* handle synonyms
They don't have to. My standard object has an id() function which handles
all that.
All the examples you gave would be handled by the add_action function
doing pretty simple parsing - "%s in %s" and then an id() check on
the latter to check the command refers to itself, and an id() check
on it's contents to make sure the former refers to it's contents.
If sscanf couldn't match that pattern (i.e. no " in ") then id() the
whole string against itself, if no match id() it against the contents.
If no match return 0.
>Failing to handle synonyms is only bad since cres for other areas who
>are more savvy will handle them, thus creating an inconsistency across
>the mud.
In my experience, add_action()s that don't handle aliases, adjectives
etc are very quickly reported by player-testers and thus get fixed. Plus
a responsible creator should be vetting newbie creator's code before it's
placed in the game until such time as he decides that newbie is reliable
etc.
>But let's say you actually want "stir paint" to work (bad form).
Bad form, but essential to have it work.
>You should have a paint object that the bucket contains.
Of course, since the bucket should be a container object capable
of having many different things put in it.
>Thus the parser
>would respond to the "stir paint" command by checking every object to
>see if it has an ID of "paint". For each paint object, it will then
>check direct_stir_obj(). If none return true, an error occurs. If
>any return true, it goes on processing by calling multiple trues as
>vague or actually performing a stir on a singular match.
Depends on your concept of paint. I would have expected the paint object
to have an attribute of "volume", and should a second paint object be
placed in the bucket it should merge with the original. Hence the multiple
matches problem wouldn't occur. But, we rapidly diverge from the point
here. :)
>: The add_action version only has to check the objects that have "stir" linked
>: to them whereas the other has to check all objects in the room so in fact it
>: found which objects were referred to twice as fast.
>And naming clashes are indeterminate. If there is paint (and thus
>stir actions) in both the box and the bucket, which one is stirred is
>simply the luck of the draw.
In the case of "stir paint" yes. In which case the player gets to think
"doh, should have told it to stir the one in the bucket" and berate
themselves for being lazy.
>Furthermore, if the box defines stir but the target of the stirring is
>soup, the box will:
>* have to perform an ID check on itself in LPC, meaning again that ID
>checking will vary from creator to creator
I fail to see how a call "id( arg )" can vary from creator to creator.
>and be slower than driver ID checking
Yes, that's true.
>* call notify_fail() properly so that processing can go on to the
>bucket. Creators are notorious about failing to call notify_fail(),
>thus causing a "What?" when the player has a bucket for stirring.
This is a quality control issue. Again this is something I've found players
quick to report in practice, so it gets fixed. The responsible creator
gets hit over the head with something and doesn't do it again.
>The most important benefit of the MudOS command parser that seems to
>always go unnoticed is the fact that the MudOS command parser allows
>for proper error handling.
That is a bonus...
>With add_action(), you are lucky to get
>anything other than "What?".
Not true, but we'll ignore that for now.
>Is it that there is no "stir" command?
>Or is the problem that the right syntax is "stir paint in bucket"? Or
>is the problem that the command I want is "mix" and not stir? Or is
>it that I can "stir bucket" but not "stir paint"? add_action() does
>almost nothing to help you provide a good error message to the player.
Again not true. The notify_fail() function provides a clear reason for
the command not working, and the syntax to make it work. If it doesn't,
it's bad code. It's not the responsibility of the mudlib in that case.
The problem with the notify_fail() system is that if several objects
are passed through searching for a match for the command then only the
very last notify_fail message gets given to the player. This can lead
to some very confusing "error" messages that are often impossible to
"debug".
>Under the MudOS parser, the player always knows WHY the command they
>just issued did not do what they expected. If no command called
>"stir" exists, they are told so. Nightmare even goes so far as to
>tell them where they can go to get a full list of commands. If the
>command has a different syntax than they used, they are given the
>proper syntaxes. If you cannot stir "paint", but you can stir other
>things, it tells you that you cannot stir paint.
I think this is probably the best reason to use it. I'm going to rethink
my command system with this in mind.
>And about that list of full commands. With the MudOS parser, it is
>easy to keep a full list. With add_action(), it is nearly impossible.
Why would you need a full list? There are far simpler ways to spam players.
--
Scatter ///\oo/\\\
>>Let me see if I have that straight... Whatever handles the command parses
>>it to find which objects the command might refer to and then calls a
>>predefinied function in each of those objects to handle the command?
>In the mudlib I've written and use, yes. There are few exceptions, for
>some of the weirder commands, though, in case no item is found with
>a matching id ("read 4" to access a mailbox is one example... Although,
>"read 4 from mailbox" is a valid command, and would actually lead to
>an event being sent straight to the mailbox object)
So would that be handled as a special case for parsing, or is the "weirdness"
simply described in the syntax for the command?
>>So if I was to type "stir all" in a room containing 100 boxes and one bucket
>>of paint, there would 101 calls to do_handle_stir() out of which 100 would
>>be worthless?
>Well, actually, the way I look at it is that the player has said he wants to
>try to stir _all_ items present. So it means we'll be calling all items
>(provided we want to allow that for stir-command, for example... but in
>any case we do understand which object(s) he/she referred to), yes.
I guess the point I was trying to make was that the add_action() method
would know already that only 1 object can actually be stirred and call
only that object, whereas your system has to assume that in theory
everything is stirrable.
>>Ok, suppose I have a two boxes and two buckets. One of the buckets contains
>>water, the other paint. The player types "stir paint".
>And like George already mentioned, I'd say this command is too vague
>to be understood.
I think you and he both mean "too vague for a centralised parser to work
out what it refers to" since both I, the player and the add_action()
method can understand it easily. It's also the sort of thing I consider
essential to handle to keep the mud user friendly.
>So, first check would reveal that there's no item
>with id 'paint'. Or alternatively, someone has done a kludge and added
>id 'paint' to the bucket... :-)
That's a cop out. :)
>Now, mudlib could also try checking 'details' of items ("paint in bucket",
>detail "paint") if it really wanted to do more work. And this would seem
>to be something mudlib could easily do in a centralized way. (I have only
>done this for examine/look; sometimes it makes sense to allow players to
>use 'read writing' instead of 'read writing on the sword', as a shortcut).
The mudlib shouldn't have to be doing that amount of work. If it's going
to check all details of all objects present for any command then it's
going to be sloooow.
>>The add_action version only has to check the objects that have "stir" linked
>>to them whereas the other has to check all objects in the room so in fact it
>>found which objects were referred to twice as fast.
>However, how is the object to know whether it is "paint 2" or "paint 3"
>("2nd paint", "3rd paint, whatever)? Id-handling should be done well;
>all synonyms that are normally applicable should be used and so on.
>Which probably means there'd often be (order of) n ^ 2 id-checks,
>as opposed to n if it was done once and for all.
My standard object's id() function does all that checking. However it does
mean that each applicable object has to do the id checks - so 100 buckets
of water and one of paint could end up with 202 id checks in a worst case
scenerio. That's actually pretty awful isn't it! :(
>Also, one problem with add_action()s (and similar mechanisms) is really
>that they have too little knowledge about global context/parsing. If more than
>one item try to apply a command, and notice it wasn't directed to
>them, both would try to define an error message, and which one is to be
>used?
Yes, these are real problems with add_action. The last defined message
would be used and this can be confusing.
>Even worse, one of them might decide command was actually directed
>to it, but had invalid arguments, printing out an error, returning 1,
>and preventing other items from having a chance to handle the command.
This is poor code and poor quality control - but usually this sort of
thing is picked up and corrected pretty fast (especially when you
have good player-testers!).
>>If you consider a room with 200 boxes in and the box object doesn't define
>>stir - your system will still try calling do_handle_stir in all 200 boxes, plus
>>the room itself, plus the player? The add_action system will abort right
>>away since it knows in advance that there is no object there that handles "stir".
>And which error message would be used? Infamous "what?"? (Well, actually,
>it shouldn't be all that hard to have a catch-all error handling)
At present yes, my system would say "What?" however since this is handled
by the mudlib itself rather than MudOS, it would be trivial to change it
to say, for example, "Nothing here to stir."
>Add_action is indeed an efficient way of passing exotic commands, but
>there the correctness is the bigger problem IMO.
Agreed.
>>override in the first place. In the case of changing things like "look" or "go"
>>as a result of an object or spell, my intention is that this should be done
>>via a shadow on the player. The command server checks for player->cmd_blah()
>>to check for an override to the "blah" command for example.
>Well, the way I allow 'overriding' is for the objects to redefine effects
>events cause. So, parsing will still be done at global level, only the
>effects will vary. So, to modify what is seen when a player is being looked
>at, event EVENT_LOOKED_AT will be caught by some other object (which has
>added an event handler for the object) and so on. And with plain "look",
>event is sent to the surrounding room, which usually gives room descriptions
>and so on.
So how would this handle a spell which prevents players using the command
at all? It sounds like you'd need objects to catch events for every object
in the game!?
>You seldom (if ever?) really need to modify the way 'examine' or 'look'
>is parsed I think.
Magic spells... :)
"cast 'weapon blindness' at Binglemonster"
>>This is a result of the way I intend the magic system to work. (I'll explain more
>>if you're really interested).
>Sure?
Anything (like magic, illness, etc) that has a lasting effect goes through
a common mechanism that classifies it, records levels, durations etc and
saves the information with the affected object. This makes all such effects
reversible, allowing a full implementation of anti-magic for example, and
sickness/curses/healing etc.
The effects on the object might be implemented by changing attributes of
the objects, or changing the way the object behaves by shadowing functions.
Hence to fit in with this system and be able to change the way command
server commands work I decided the simplest way would be to use the
existing shadow to handle the command.
>>>So how exactly are the commands linked to the player?
>
>>The player object stores the links in a mapping variable, something like
>>([ string command : ({ ({ object handling_object, string function }) }) ]).
>
>>That is, the command is mapped to a list of objects handling it and the appropriate
>>function to call for that object. The command handling simply goes through
>>the list for a command, calling each object's function in turn until one of them
>>returns 1 to say that the command has been taken care of. If the object no
>>longer exists or check_close() returns 0 for that object, the entry is removed
>>from the list.
>
>Ah. How are the commands, then, removed from the mapping? Is it being kept
>up-to-date all the time (ie. always remove a command when item is not
>eligible any more to handle it, or lazy update, removing only when such a
>command definition is found to be no longer valid). I mean, destructed
>objects are removed ok, but how about items that only define commands
>when carried by the player, and are dropped later on? Perhaps the item
>removes old links when it has to add new ones (player has dropped the
>item and someone else picks it up)?
A combination of both really. If an object no longer wants to handle the
command it can remove_action() (or player->remove_command_entry() ) to
delete it's entry. This is what a room would do for example, to remove
a command it had added.
When the player object is searching for a match for a command, any
entries matched for which the handling object no longer exists or is
no longer close to the player are deleted. Thus it's usually the player
object that zaps the entries when the object that added the command has
moved away or died.
>>Since the command server is checked first, the vast majority of commands
>>never even get as far as checking this list so I don't think it'll have much
>>impact on speed (my mudlib isn't far enough along to really test this yet).
>I guess the biggest issue (at least for me) isn't the performance.
>Add_action() might well be the fastest way to handle certain commands...
>But due to its problems it makes no difference to me.
Yes it does have some big problems... this discussion has opened my eyes
to that a bit more!
>>Add_action()s are like properties - for those little extra bits that are nice
>>to be able to put in easily but aren't done all the time.
>I haven't removed add_action() yet from my mud either...
>Although the mudlib doesn't use it anywhere, and I'd strongly
>discourage anyone to use it. =)
I'm beginning to think I will remove it. The mudlib doesn't use it at all
anyway.
>I guess it's same for both add_action() and shadow(); I consider
>using either of them as either bad programming practice, or a sign of
>some serious shortcoming in the mudlib. However, just in case,
>they are there if someone can come up with some real use for them.
What is the objection to shadows? Or is this another touchy subject
I should avoid? :)
--
Scatter ///\oo/\\\
[Others pondering potential situations where add_action might be
favourable]
> : The reason you have a problem coming up with an example is that there
> : is absolutely no circumstance under which the add_action() approach
> : actually is preferable to the MudOS verb parser.
>
> In fact: the Lima method is _usually_ preferable, for a number of reasons,
> but there are several key assumptions in this judgement, not all of which
> will always hold true even though all of them usually do. For instance,
> if you want to make a mud in which coherence is NOT a goal, the centralized
> approach is unsuitable, and while mindless wordgames are silly, there COULD
> be a reason to do something like this, even if I don't know what it is at
> the moment.
For a good MUD, coherence is NOT a goal. The real goal is avoiding
situations
where the parser doesn`t understand what you intend.
> : You should most definitely NOT have "as much flexibility as you want
> : in the parsing". Syntazes should be standardized across the mud and
> : well documented. Anything else is a pointless game.
>
> "Pointless." So did speak George Reese, who is a god in his own mind.
> Please, George... could you do some melodrama for us?
Disregarding religion ;-) the point actually is:
Syntax standardisation is a makeshift solution. It is still better than
suffering from "syntax quests", but a really good Mud would simply
recognize
what the player in fact wanted.
[...]
> : Nope, this is not how the MudOS system works. First, your command is
> : vague. It should be "stir paint in bucket". And it should respond
> : properly to such things as:
> : stir red paint in the bucket
> : stir the read paint in the blue bucket
> : stir the ugly red paint in the dirty blue bucket
> : mix the paint in the bucket
> : (assuming of course the paint is ugly and red and the bucket is dirty
> : and blue)
[Scott G Stewart, in another posting]
--- snipp ---
This touches on an topic I have always wondered about. As an
implementor, I can understand the beauty of a system which handles such
verbose, real-language commands. However, as a player, I would very
rarely type such a string. I am much more likely to type "stir paint",
or "stir red" if I have more than one paint. I can see some advantages
to this minimalist command system:
* It is fast to type - expert users can be efficient
* It is easy to type - novice typers can be effective
* It is standard - users can get up to speed faster
-------------
A good Mudlib should deal with all possibilities: minimalistic commands,
or explicit depictions. Typically, players will choose the least
necessary
effort, but demand complex possibilities for otherwise ambiguous
situations.
> : At this point, add_action() is already messing with your mind. Newbie
> : cres are unlikely to do the following:
> : * handle adjectives and articles properly
> : * handle synonyms
I don`t think so. You don`t need a central parser to provide an object
identification function that will
- handle id synonyms
- check optional extra words for valid adjectives
- handle positions (1st, second etc) and
- amounts (if applicable)
- stated environment (container)
All that a newbie coder has to do is apply this function, and supply
sufficient ids and adjectives to his objects. That is what you usually
teach him at the very first steps anyway.
> : And naming clashes are indeterminate. If there is paint (and thus
> : stir actions) in both the box and the bucket, which one is stirred is
> : simply the luck of the draw.
Nonsense. Whats wrong with having default rules for that? Meaning that
e.g.
"get sword" will be equivalent to "get first sword". Exaggerating name
clash problems is annoying... see example below.
[George about another possible point for central parsers]
---- snip ----
Under the MudOS parser, the player always knows WHY the command they
just issued did not do what they expected. If no command called
"stir" exists, they are told so. Nightmare even goes so far as to
tell them where they can go to get a full list of commands. If the
command has a different syntax than they used, they are given the
proper syntaxes. If you cannot stir "paint", but you can stir other
things, it tells you that you cannot stir paint.
--------------
I prefer the notorious "what?" to funny results like "you can`t swim in
the
ocean", "none of the apples is alive" of just wrong ones like "you can`t
get 2 apples".
The following example is from the Lima Bean visitor`s room. It also
shows how annoying a mudlib can be when it is over-protective against
name
clashes. :)
---- snip ----
Sandy beach [exits: none]
The waves lap happily onto this sandy beach, which ends here -- the
mountains
barely meet the water, leaving not even a grain of sand on which to
walk.
An intricate sand castle towers before you.
A small sign is here, trenched deeply in the sand.
2 red apples lie at your feet.
> look at water
There is nothing special about the ocean.
> swim in ocean
You can't swim in that!
> get 2 apples
You can't get 2 apples.
> get two red apples
You can't get two red apples.
> get all apples
You can't get all apples.
> get all
ocean: You aren't able to take it.
sand castle: You aren't able to take it.
sandy beach: You aren't able to take it.
red apple: Taken.
red apple: Taken.
> put apples on floor
There is no floor here.
> examine apple
Which red apple do you mean?
> examine my apple
There is no such apple here.
> examine my first apple
It's an ordinary red apple.
It is untouched.
> drop apple
Which red apple do you mean?
> drop 1 apple
You can't drop 1 apple.
> drop an apple
You can't drop an apple.
> drop my first apple
Done.
> examine apple
Which red apple do you mean?
> examine my apple
There is no such apple here.
> i
You are carrying:
a red apple
2 the Swords of Mercy
2 backpacks
> bite into apple
There is no into apple here.
> bite apple
None of the apples are alive.
> open backpack
Which backpack do you mean?
> open first backpack
You open a backpack.
> put sword in backpack
Which the Sword of Mercy do you mean?
> put first sword in second backpack
There is only one of them.
> i
You are carrying:
2 the Swords of Mercy
a red apple
a backpack
a backpack
--------------
That should do to illustrate what I mean. :)
One could find worse examples for Nightmare, but there is no use in
blaming ancient MUDs which do have their historical merits for not
matching the state of the technology.
>
> : And about that list of full commands. With the MudOS parser, it is
> : easy to keep a full list. With add_action(), it is nearly impossible.
True, but why the **** should I wish to keep such a record if I don`t
intend to use the Nightmare "thesaurus" approach anyway.
There is no way to play such a Mud in an 'intuitive' way. Yet, having to
study a command language first before you can start at all, because for
some wierd consistency reasons you can`t even "examine" anything, isn`t
really fun for a newbie player.
Now, how do actually centralized and local concepts compare if you are
actually going to build a MUD that will understand natural language to a
reasonable extent?
We have seen in the previous discussion that central parsing may have
some
advantages if your MUD is primitive:
- You can at least provide consistency of your command set even if it is
rudimentary and non-intuitive ( But exactly thats the point we want to
overcome)
- You have to check a command only once for multiple present stock
objects.
( But on the other hand, a good Mud will try to get away from simple
stock stuff, and objects without individual properties should be coded
as
a single "unit" object anyway.)
- You can parse a small set of commands comparatively fast using a
central
pattern database. Yet, the more you allow for natural language,
synonyms
and all that, your database will grow enormously, and slow down the
process. The same is the case if your MUD is growing. For every single
command pattern the overall Mud size will slow down the processing!
On the other hand, the local approach will be completely independent of
the
Mud size.
What are the concepts of natural language processing anyway?
A completely centralized approach will first try to analyze the
semantics
of the input, then assign it a suitable function to handle it. Most
prominent teams of coders have been working on this concept for many
years
now, and still the results are only fair.
Using a local approach, you just have to check the quite small number of
possible events for their trigger criteria. Thats by orders of magnitude
easier!
For example, you want to end a quest by letting a player cut a pentagram
in the
bark of a holy oak using a magic dagger. (No, don`t do this with a
Nightmare
lib! :-D Actually, I don`t even recommend such quests at all... ;)
The verb could be "use" or "cut" or "carve",
the magic tool could have a name, be described as "magic tool" or
"knife",
the user could try "surface" or "wood" instead of bark,
"oak" or "tree" or "oaktree",
"pentagram" or "magic sign" or "star"...
At least, you have to multiply the numbers of synonyms of each group,
not
to think of the permutations of the sequence ( Some Languages such as
German
allow even much more correct sequences than English).
Well, I can achieve that like this:
AddCmd("use | cut | carve & pentagram | sign | star & bark | surface |
wood
& tree | oak | oaktree & knife | dagger | tool ","quest_solved");
I just want to outline the idea... you might wish a different
implementation
using arrays for the synonyms, or adding an array of specific
notify_fails
according to the missing parameters. Its just to demonstrate you can
quite
easily implement support for natural language understanding when using
some
advanced version of local add_action.
Sure, you might try to implement a similiar approach in a central
parser.
Yet, the chance that several other items anywhere in the mud define
commands
with knives, trees, wood.... will make your analysis quite expensive.
signs and so on will require a lot of extra overhead.
Hence, I am still not convinced the central solution is superior if you
want to create a _better_ Mud.
:-)
Babs
>> Tim Hollebeek wrote:
>> [...]
>> > Properties introduce much more than an additional layer of function
>> > calls since (for example) even variable name lookup is now defered
>> > to runtime. And this is without even mentioning the shortcomings
>> > of properties from a maintenance, type safety, and flexibility
>> > standpoint.
>>
>The largest one is the complete inability to overload each query/set method
>when you want to change the behavior without changing the API. In fact,
>you usually can't even do:
>
>mixed query(string key) { if (key == ...) ... }
>
>since set is (for good reasons) usually nomask. You can add hacks to
>allow you to solve these sorts of problems at the mudlib level (e.g.
>a set_property_function() type thing) but that makes them even more
>complex, and bumps your efficiency loss up again ...
Why not take advantage of function pointers or lambda closures to create a fake
query_foo() function in the object when set() is called? That seems to solve
this particular problem. As for efficiency, I haven't measured it, but I'd
expect it to be not much slower than actually creating a query_foo() method.
Babs <eum...@hotmail.com> wrote:
: John Adelsberger wrote:
: >
: > George Reese (bo...@imaginary.com) wrote:
: For a good MUD, coherence is NOT a goal. The real goal is avoiding
: situations where the parser doesn`t understand what you intend.
Actually, I hold that coherence is a goal, to some extent, but that, as
the HILARIOUS Lima Bean example you showed demonstrates aptly, too much
is really, really annoying.
: Syntax standardisation is a makeshift solution. It is still better than
: suffering from "syntax quests", but a really good Mud would simply
: recognize what the player in fact wanted.
Unfortunately, if I could do this sort of thing consistently, instead of
writing muds, I'd be making hundreds of thousands a year in one of the
ergo research labs somewhere.
: A good Mudlib should deal with all possibilities: minimalistic commands,
: or explicit depictions. Typically, players will choose the least
: necessary effort, but demand complex possibilities for otherwise ambiguous
: situations.
This is my thought, too. add_action as is is insufficient to this purpose,
in some ways, but something similar could work well, I think.
: All that a newbie coder has to do is apply this function, and supply
: sufficient ids and adjectives to his objects. That is what you usually
: teach him at the very first steps anyway.
Yes, and thats how most people do it, but don't let the facts get in the
way of the Opinion of Reese.
: Nonsense. Whats wrong with having default rules for that? Meaning that
: e.g.
: "get sword" will be equivalent to "get first sword". Exaggerating name
: clash problems is annoying... see example below.
Again, the only thing wrong with your view is that Reese has decided
otherwise, and now expects your compliance. If you do not comply,
he will ridicule you, and if you continue not to comply, he'll eventually
start ignoring you. This is how all religions deal with nonbelievers;
if you don't acknowledge it, it doesn't exist, right?:-)
: ---- snip ----
Pretty much. I never really gave it much thought, because I don't use
it, but that's damned annoying. Much worse than most add_action systems
I've seen.
To be fair, if it had a notion of 'first is default' and a notion of
'if they're identical, just pick one,' it'd be much nicer.
: One could find worse examples for Nightmare, but there is no use in
: blaming ancient MUDs which do have their historical merits for not
: matching the state of the technology.
According to Reese, NMIV is modern and up to date, and is the best designed
mudlib out there, and apparently it performs oral sex, too:-)
: > : And about that list of full commands. With the MudOS parser, it is
: > : easy to keep a full list. With add_action(), it is nearly impossible.
: True, but why the **** should I wish to keep such a record if I don`t
: intend to use the Nightmare "thesaurus" approach anyway.
You're missing George's key idea - everything he chooses is the best, and
anything else is shit. Therefore, when he argues for centralized parsing,
he's really arguing for NMIV, as is, precisely, because why would you want
anything else?
: There is no way to play such a Mud in an 'intuitive' way. Yet, having to
: study a command language first before you can start at all, because for
: some wierd consistency reasons you can`t even "examine" anything, isn`t
: really fun for a newbie player.
No kidding.
: - You can parse a small set of commands comparatively fast using a
: central pattern database. Yet, the more you allow for natural language,
: synonyms and all that, your database will grow enormously, and slow
: down the process. The same is the case if your MUD is growing. For
: every single command pattern the overall Mud size will slow down the
: processing!
I'm sure they're counting on the speed of their hardcoded efuns here;
I'd be amused to see a mud like Realms of the Dragon convert a copy
of their lib, just to see if it would still run at all, myself. I
have my doubts.
: A completely centralized approach will first try to analyze the
: semantics of the input, then assign it a suitable function to handle
: it. Most prominent teams of coders have been working on this concept
: for many years now, and still the results are only fair.
Fair is being polite about it. The speech rec people gave up a long
time ago and just started searching for keywords and ignoring the
rest. This might be a good approach for a mud, too.
: At least, you have to multiply the numbers of synonyms of each group,
: not to think of the permutations of the sequence ( Some Languages such as
: German allow even much more correct sequences than English).
Given hashes for word matching, this is easy, but hashes consume memory
like it was going out of style...
: AddCmd("use | cut | carve & pentagram | sign | star & bark | surface |
: wood
: & tree | oak | oaktree & knife | dagger | tool ","quest_solved");
Actually, this really whomps the ass off centralized parsing, because in
fact, even though 'cut the frog with the dagger' makes sense to us, why
should we care if some twit types 'cut with frog the the dagger' or
some such nonsense? We know what he meant; just establish a rule stating
that direct objects always come after nouns and verbs always come first,
and you're set. No mud command imaginable is such that any player would
find this arrangement awkward. This also allows for 'cut frog dagger,'
which may as well work, or, if we have a default weapon for some reason,
(such as a combat system with a notion of 'equipped') even just 'cut frog.'
I think I may have to write me a new efun, because this is much nicer than
add_action, and much more player-friendly than the centralized 'which apple'
approach:-)
: That's a strong statement... I'm sure there must be at least one. Having
: read the arguments below though, I'm starting to agree that there are
: some very good arguments against the add_action system.
It is a strong statement, but it is true. In fact, if it is false, it
is easy to prove false since a single counter-example is sufficient to
make it false. So, please, argue a case in which add_action() is
better :)
:>:>ago), I think it did use some sort of event-passing. That is, once you
:>:>have defined the syntax(es) of a command, an event (function call to a
:>:>function of which name reflects which syntax was used, "take_with_obj()"
:>:>or something like that?) will be sent to the object(s) referred to,
:>: So if I was to type "stir all" in a room containing 100 boxes and one bucket
:>: of paint, there would 101 calls to do_handle_stir() out of which 100 would
:>: be worthless?
:>
:>No. It would be:
:>number of calls to direct_stir_obs() == # of objects with
:>direct_stir_obs() functions
: There would need to be a function_exists check on each object then? Or
: is there some sort of handler which registers which objects can do which
: commands?
This is a question best left to Beek. The bottom line is that while
there is more processing involved with the MudOS parser, that
processing is not nearly as much as you have claimed and it is dwarfed
by the gains in consistency and functionality.
:>: That's one problem I have with add_action(), that it must parse the command
:>: string itself. On the one hand this allows as much flexibility as you want in
:>: the parsing
:>You should most definitely NOT have "as much flexibility as you want
:>in the parsing".
: Perhaps. However it is useful to be able to be flexible. In my experience
: players will continuously complain about something that doesn't work
: as expected and it is therefore nice to be able to fix objects to
: accept technically incorrect syntax sometimes.
That is not the context of flexible you were using. Fixing bugs is
done much easier with a centralized scheme, since fixing the bug once
fixes it for all the mud. With add_action(), fixing it once generally
just fixes it locally.
:>Syntazes should be standardized across the mud and
:>well documented.
: That is a good point, I agree that all commands should follow a standard
: syntax. That doesn't mean it has to be a horrifically complicated
: "cope with anything" syntax though.
No one said it should be. The benefit of standardized syntax is that
you can account for anything. It does not mean you have to account
for anything.
With a non-standardized parser (add_action()), you don't realistically
even have the option.
:>: I might try a generic parser simul_efun, possibly using MudOS's parsing efuns
:>: and see how feasable that is. Then the command handling could parse the
:>: command arguments and call the function defined by add_action() with the
:>: results of the parsing instead of with the unparsed string.
:>How does it determine what the command arguments are? You are
:>oversimplifying the issue, much as add_action() does.
: I'm not sure I understand your question. The command arguments are the
: things the player typed after the command itself. As in player types
: "stir paint in bucket" then the arguments are "paint in bucket" which
: the parser would examine and call the add_action's function with, say,
: ({ "paint", "bucket" }). I may well be oversimplifying things, but since
: I haven't looked into actually coding it yet I haven't done much
: investigation.
I am saying that you are oversimplifying the issue because you are
breaking a command line into the command and arguments. In fact, a
command is a user-initiated event. A bucket is not a string argument
to a command, but an object in the user's world which may or may not
respond to certain user-initiated events. My point is that the
anatomy of an event is much more complex than you seem to be giving
credit to.
:>: Now as I understand it, your system would mean that the handler parses "stir
:>: paint" and finding no objects matching "paint" (assuming that the paint bucket
:>: doesn't respond to "paint") it will try do_handle_stir() in box 1, and then in
:>: box 2, and then in bucket 1, and then in bucket 2 before finding a match.
:>Nope, this is not how the MudOS system works. First, your command is
:>vague. It should be "stir paint in bucket".
: Yes the command is vague. It's also the first thing I'd type if I can see
: a bucket of paint and want to stir it. It's not technically correct perhaps
: but it's the laziest way to get the action done and it's obvious what is
: meant
That's a side issue. 'stir paint' is ok, and I don't really have that
much of a problem with it. I mostly wanted to convey how rich the
syntax can be, and that other users will think of it another way.
There is nothing about the MudOS parser that favours one syntax over
another.
:>And it should respond
:>properly to such things as:
:>
:>stir red paint in the bucket
:>stir the read paint in the blue bucket
:>stir the ugly red paint in the dirty blue bucket
:>mix the paint in the bucket
:>
:>(assuming of course the paint is ugly and red and the bucket is dirty
:>and blue)
: And, IMO, should also respond to "stir paint" and "stir bucket" etc.
No, not "stir bucket". But this has nothing to do with the point at
hand anyways.
:>At this point, add_action() is already messing with your mind. Newbie
:>cres are unlikely to do the following:
:>* handle adjectives and articles properly
:>* handle synonyms
: They don't have to. My standard object has an id() function which handles
: all that.
And you hope each cre remembers to call id(). I have seen a zillion
and one different creator initiated methods for testing an id.
Any solution for consistency which places the burden of consistency on
individual cres is a bad solution.
: All the examples you gave would be handled by the add_action function
: doing pretty simple parsing - "%s in %s" and then an id() check on
: the latter to check the command refers to itself, and an id() check
: on it's contents to make sure the former refers to it's contents.
That really is not very simple parsing. Keep in mind, sscanf() is one
of the hardest functions for cres to learn. So, to make a simpl area,
you have now required your newbies cres to become sscanf() gurus.
: If sscanf couldn't match that pattern (i.e. no " in ") then id() the
: whole string against itself, if no match id() it against the contents.
: If no match return 0.
Again, assuming they actually know id() is the proper check.
:>Failing to handle synonyms is only bad since cres for other areas who
:>are more savvy will handle them, thus creating an inconsistency across
:>the mud.
: In my experience, add_action()s that don't handle aliases, adjectives
: etc are very quickly reported by player-testers and thus get fixed. Plus
: a responsible creator should be vetting newbie creator's code before it's
: placed in the game until such time as he decides that newbie is reliable
: etc.
The ones you hear about are quickly reported. But this creates an air
where inconsistency is the rule. Why would you opt for catch the
problems when the area is in the game approach as apposed to the
guaranteed consistency of the parser?
[ a bunch of off-thread stuff about container stuff deleted ]
:>: The add_action version only has to check the objects that have "stir" linked
:>: to them whereas the other has to check all objects in the room so in fact it
:>: found which objects were referred to twice as fast.
:>And naming clashes are indeterminate. If there is paint (and thus
:>stir actions) in both the box and the bucket, which one is stirred is
:>simply the luck of the draw.
: In the case of "stir paint" yes. In which case the player gets to think
: "doh, should have told it to stir the one in the bucket" and berate
: themselves for being lazy.
That's not what I meant. What if you have two buckets of paint, one
red and one blue? Blue is life and red death. You mean to tell me
that the mud assuming which paint you meant is a good thing? I don't
think so.
:>Furthermore, if the box defines stir but the target of the stirring is
:>soup, the box will:
:>* have to perform an ID check on itself in LPC, meaning again that ID
:>checking will vary from creator to creator
: I fail to see how a call "id( arg )" can vary from creator to creator.
Whether or not they make it.
:>and be slower than driver ID checking
: Yes, that's true.
:>* call notify_fail() properly so that processing can go on to the
:>bucket. Creators are notorious about failing to call notify_fail(),
:>thus causing a "What?" when the player has a bucket for stirring.
: This is a quality control issue. Again this is something I've found players
: quick to report in practice, so it gets fixed. The responsible creator
: gets hit over the head with something and doesn't do it again.
I find this answer very, very disturbing.
:>The most important benefit of the MudOS command parser that seems to
:>always go unnoticed is the fact that the MudOS command parser allows
:>for proper error handling.
: That is a bonus...
:>With add_action(), you are lucky to get
:>anything other than "What?".
: Not true, but we'll ignore that for now.
Yes, it is true. The cres have to understand how notify_fail() works
and remember to use it. In my experience, cres don't do this well
until they have reached a certain level of coding sophistication.
:>Is it that there is no "stir" command?
:>Or is the problem that the right syntax is "stir paint in bucket"? Or
:>is the problem that the command I want is "mix" and not stir? Or is
:>it that I can "stir bucket" but not "stir paint"? add_action() does
:>almost nothing to help you provide a good error message to the player.
: Again not true. The notify_fail() function provides a clear reason for
: the command not working, and the syntax to make it work. If it doesn't,
: it's bad code. It's not the responsibility of the mudlib in that case.
: The problem with the notify_fail() system is that if several objects
: are passed through searching for a match for the command then only the
: very last notify_fail message gets given to the player. This can lead
: to some very confusing "error" messages that are often impossible to
: "debug".
Right. In fact, I have seen notify_fail() produce some really funny
and confusing error messages that simply could not be fixed. Why
would you want a system that sometimes helps you and sometimes spouts
nonsense at you?
Furthermore, are you going to tell me that if I login to your mud, I
will never see the expression "What?"
:>Under the MudOS parser, the player always knows WHY the command they
:>just issued did not do what they expected. If no command called
:>"stir" exists, they are told so. Nightmare even goes so far as to
:>tell them where they can go to get a full list of commands. If the
:>command has a different syntax than they used, they are given the
:>proper syntaxes. If you cannot stir "paint", but you can stir other
:>things, it tells you that you cannot stir paint.
: I think this is probably the best reason to use it. I'm going to rethink
: my command system with this in mind.
:>And about that list of full commands. With the MudOS parser, it is
:>easy to keep a full list. With add_action(), it is nearly impossible.
: Why would you need a full list? There are far simpler ways to spam players.
Huh? You consider "help commands" spam???? That is odd. You want a
full list of commands because a player should know what things are
possible in their world.
This is not always the case. In 'Real Life' you don't have a nice list of
commands to check through when you are trying to decide what you want to do.
While I agree that standardization of *almost* all commands is a good thing, I
still think there are some situations where a non-standard verb/command is
best in a certain situation.
Sometimes, the player shouldn't be able to learn something or get a hint by
running through the list of available commands. I dont mean you put them
in a 'guess the verb' scenario: what I mean is they might have to learn what
the 'magic' comand is from another location, an NPC, etc, and should have no
chance of just 'stumbling' upon it by referencing a list.
-Aristotle@Threshold
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
VISIT THRESHOLD ONLINE! High Fantasy Role Playing Game!
Player run clans, guilds, businesses, legal system, nobility, missile
combat, detailed religions, rich, detailed roleplaying environment.
http://www.threshold.counseltech.com
telnet://threshold.counseltech.com:23
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
George, there are a lot of reasons why I might want a certain command to work
ONLY in one room or ONLY on one object. One very simple example is a room
where you have to type some magic word to make something happen (door opens,
wall raises, etc) but there is nowhere else in the game where you will ever
type that magic word.
Why make a verb? Why have this magic word appear on a list of possible
commands?
Since a player would have to learn this magic word somewhere else (from a
scroll, an NPC, etc), it is actually WORSE if they can figure it out by
reading a list of verbs or playing trial and error with all available verbs.
Standardization is NOT the best thing in 100% of all situations. Further, you
should not assume that your own personal preferences are the same for all
people.
>In article <6asus4$o83$1...@darla.visi.com>, George Reese <bo...@imaginary.com> wrote:
>>Let me requote myself:
>>
>>"The reason you have a problem coming up with an example is that there
>>is absolutely no circumstance under which the add_action() approach
>>actually is preferable to the MudOS verb parser."
>George, there are a lot of reasons why I might want a certain command to work
>ONLY in one room or ONLY on one object. One very simple example is a room
>where you have to type some magic word to make something happen (door opens,
>wall raises, etc) but there is nowhere else in the game where you will ever
>type that magic word.
Umh. Even so, usually, it would seem you are trying to solve the problem
wrong way by making your own command. For traditional "Sesam open" - thing,
you would catch the say-event (ie. somehow 'hear' what player says - this
should NOT be done by making new local say-command, but by getting indication
from mudlib, IMO), for other verbs, why not just require more precise
command, understood by global parser ("force door open using rubber hammer",
"pry stone door with tin knife"... whatever).
I think dividing parsing from affecting the item is a good conceptual
division. Syntax seldom (if ever) should dictate the action caused by
the command (directly, that is).
>Why make a verb? Why have this magic word appear on a list of possible
>commands?
>Since a player would have to learn this magic word somewhere else (from a
>scroll, an NPC, etc), it is actually WORSE if they can figure it out by
>reading a list of verbs or playing trial and error with all available verbs.
Well, the list of all available verb for a ready (and well-made) mud
should be rather big. I wouldn't think players actually tried all
N hundred commands with they M different forms (but who knows; players
are the devious creatures there are). But if you really want to prevent
accidental success, perhaps use passwords. But not as commands, no
syntax-is-the-password - game...
>Standardization is NOT the best thing in 100% of all situations. Further, you
>should not assume that your own personal preferences are the same for all
>people.
Quite true. One size doesn't fit all it seems.
>Tatu P Saloranta intoned these words...
>>sca...@thevortex.com (Scatter ///\oo/\\\) writes:
>>
>[lots of snips in here]
>>In the mudlib I've written and use, yes. There are few exceptions, for
>>some of the weirder commands, though, in case no item is found with
>>a matching id ("read 4" to access a mailbox is one example... Although,
>So would that be handled as a special case for parsing, or is the "weirdness"
>simply described in the syntax for the command?
Well, unfortunately the lib I have does not just define syntax in some
config-file (it should, and will some day). However, yes, it's a special
case. Occasionally I find it easier to do a kludge than to thrive for
100% purity. I know I know, it's a weakness.. :-)
The particular addition is just extra check after seeing if there is a
matching item; if not, then it checks if the argument is a number, and
dispatches the event to the room in which player is, to which the mailbox
(or bboard) has registered itself to, as a certain type of readable
object.
>>>So if I was to type "stir all" in a room containing 100 boxes and one bucket
>>>of paint, there would 101 calls to do_handle_stir() out of which 100 would
>>>be worthless?
>>Well, actually, the way I look at it is that the player has said he wants to
>>try to stir _all_ items present. So it means we'll be calling all items
>>(provided we want to allow that for stir-command, for example... but in
>>any case we do understand which object(s) he/she referred to), yes.
>I guess the point I was trying to make was that the add_action() method
>would know already that only 1 object can actually be stirred and call
>only that object, whereas your system has to assume that in theory
>everything is stirrable.
Yes, true. However, one thing worth noting is that sending an event that
doesn't get handled (default: return EVENT_NOT_HANDLED) is very fast,
compared to handling of a 'succesful' event. In any case, add_action()
would (or a similar construct; directly linked command by any other name)
be faster here, no objections. =)
>I think you and he both mean "too vague for a centralised parser to work
>out what it refers to" since both I, the player and the add_action()
>method can understand it easily. It's also the sort of thing I consider
>essential to handle to keep the mud user friendly.
That's true. Players often prefer ultra-short commands with all extra
stuffing removed. However... I do think that command still has to check
for item(s) of which id is "paint". Your system probably does that check
first too, if I'm not mistaken? Also, some systems would just give an
error indicating "Which paint you want to stir: ....", if there were more
than one item with matching id.
However, knowing what does "paint" in this context mean, when there is
no object having that id needs quite smart handling from the global
parser. Player's local context would make it quite clear, and in a way,
I think my parser could be (for example) enhanced to make use of
object "it", object that was referred to by last succesful command
("examine bucket" -> sets 'him'-object, so you can now use
"stir paint in it" ok)... And first check if "it" contains "paint"
(a good idea actually... chatting in newsgroups isn't waste of time
after all).
All in all, I guess this is in a way good example of diffences between
global and local parsing.
>>Now, mudlib could also try checking 'details' of items ("paint in bucket",
>>detail "paint") if it really wanted to do more work. And this would seem
>>to be something mudlib could easily do in a centralized way. (I have only
>>done this for examine/look; sometimes it makes sense to allow players to
>>use 'read writing' instead of 'read writing on the sword', as a shortcut).
>The mudlib shouldn't have to be doing that amount of work. If it's going
>to check all details of all objects present for any command then it's
>going to be sloooow.
Then again, if mudlib actually wants to be 'friendly', and notices that so
far it hasn't really understood the command, it might want to try some
more reasoning. Checking for a matching detail should be as fast as
checking for a matching id (and it is on my mudlib at least). It'd
double the id-check cost for the command, but only on those occasions
this unqualified-detail-reference ("paint" instead of "paint in bucket").
I don't actually think it's an overkill, even though using add_action()
would make it faster, and even though it's seldom needed. But that's
just me.
>>However, how is the object to know whether it is "paint 2" or "paint 3"
>>("2nd paint", "3rd paint, whatever)? Id-handling should be done well;
>>all synonyms that are normally applicable should be used and so on.
>>Which probably means there'd often be (order of) n ^ 2 id-checks,
>>as opposed to n if it was done once and for all.
>My standard object's id() function does all that checking. However it does
>mean that each applicable object has to do the id checks - so 100 buckets
>of water and one of paint could end up with 202 id checks in a worst case
>scenerio. That's actually pretty awful isn't it! :(
Yes. :-)
>>Even worse, one of them might decide command was actually directed
>>to it, but had invalid arguments, printing out an error, returning 1,
>>and preventing other items from having a chance to handle the command.
>This is poor code and poor quality control - but usually this sort of
>thing is picked up and corrected pretty fast (especially when you
>have good player-testers!).
True, that's how it should work. Still, it's an extra problem often
created by add_action() (etc). I have had my share of these problems
in a mud I was coding earlier... ("open book" -> "It is locked"; player
trying to open the spellbook in one particular room were puzzled when
the door decided it wants to handle all "open"-commands... bad coding,
bad cq of course)
>>And which error message would be used? Infamous "what?"? (Well, actually,
>>it shouldn't be all that hard to have a catch-all error handling)
>At present yes, my system would say "What?" however since this is handled
>by the mudlib itself rather than MudOS, it would be trivial to change it
>to say, for example, "Nothing here to stir."
Nod. Although, for commands with wider variety of syntaxes, it would be
helpful to get more precise information about the reason of failure.
>>at, event EVENT_LOOKED_AT will be caught by some other object (which has
>>added an event handler for the object) and so on. And with plain "look",
>>event is sent to the surrounding room, which usually gives room descriptions
>>and so on.
>So how would this handle a spell which prevents players using the command
>at all? It sounds like you'd need objects to catch events for every object
>in the game!?
Heh. No, then one would have to resort to another mechanism. I use another
approach for condition 'hallucinating' (blindness is an easier thing,
it's checked by 'look'-command directly).
>>You seldom (if ever?) really need to modify the way 'examine' or 'look'
>>is parsed I think.
>Magic spells... :)
>"cast 'weapon blindness' at Binglemonster"
Perhaps so. I just dispatch 'cast'-command to the spell daemon as is...
It's not handled by default syntax (spell syntaxes are actually defined
by a config-file, so spell-parsing is more advanced on my mud than
normal commands... figures, as they were added after the normal
command parsing system).
>>>This is a result of the way I intend the magic system to work. (I'll explain more
>>>if you're really interested).
>>Sure?
>Anything (like magic, illness, etc) that has a lasting effect goes through
>a common mechanism that classifies it, records levels, durations etc and
>saves the information with the affected object. This makes all such effects
>reversible, allowing a full implementation of anti-magic for example, and
>sickness/curses/healing etc.
>The effects on the object might be implemented by changing attributes of
>the objects, or changing the way the object behaves by shadowing functions.
Ah. Sounds interesting.
>Hence to fit in with this system and be able to change the way command
>server commands work I decided the simplest way would be to use the
>existing shadow to handle the command.
Ok, as long as you know about (possible) problems and alternatives,
and still think it's the way to go, then that's how it should go.
>>Ah. How are the commands, then, removed from the mapping? Is it being kept
>>up-to-date all the time (ie. always remove a command when item is not
>A combination of both really. If an object no longer wants to handle the
>command it can remove_action() (or player->remove_command_entry() ) to
>delete it's entry. This is what a room would do for example, to remove
>a command it had added.
Ah. Makes sense (for the effect you want). Was just wondering about
how many invalid commands there would be stored after the player
had adventured for hours.
>When the player object is searching for a match for a command, any
>entries matched for which the handling object no longer exists or is
>no longer close to the player are deleted. Thus it's usually the player
>object that zaps the entries when the object that added the command has
>moved away or died.
Yes, assuming player makes use of the commands linked.
>>I guess the biggest issue (at least for me) isn't the performance.
>>Add_action() might well be the fastest way to handle certain commands...
>>But due to its problems it makes no difference to me.
>Yes it does have some big problems... this discussion has opened my eyes
>to that a bit more!
>>I guess it's same for both add_action() and shadow(); I consider
>>using either of them as either bad programming practice, or a sign of
>>some serious shortcoming in the mudlib. However, just in case,
>>they are there if someone can come up with some real use for them.
>What is the objection to shadows? Or is this another touchy subject
>I should avoid? :)
Heh. Well... There were wars between people who hate shadows and those
who need they are useful. Much like with add_action(). The main problem
I have is that when people use shadows, they tend to be used in a way
that makes it much more difficult to develop the mudlib. Shadows are
used at such a low level, by-passing many abstractions, that it seems
to make the mud (and mudlib) much more fragile. And most of the time
they could have been replaced by making few more general hooks
(like someone already pointed out on another thread). But if someone
wants to argue for or against shadows, perhaps start another thread,
this one is already getting bit long.
add_action allows you to be more flexible in checking for "technically
incorrect" command syntaxes because they enable you to check for
syntax in the context of the player's situation. Additionally, error messages
therefore don't have to take into account all the possibilities in the
entire game but only those that apply to this specific instance.
>This is a question best left to Beek. The bottom line is that while
>there is more processing involved with the MudOS parser, that
>processing is not nearly as much as you have claimed and it is dwarfed
>by the gains in consistency and functionality.
I've not been claiming more processing but enquiring about it since I have
no experience of the MudOS parser and there doesn't seem to be any
documentation of the parsing efuns in the MudOS packages. (If anyone knows
where there is some, please let me know - doesn't seem to be in the alpha,
beta, pre or doc tar.gz packages on ftp.imaginary.com).
>:>You should most definitely NOT have "as much flexibility as you want
>:>in the parsing".
>: Perhaps. However it is useful to be able to be flexible. In my experience
>: players will continuously complain about something that doesn't work
>: as expected and it is therefore nice to be able to fix objects to
>: accept technically incorrect syntax sometimes.
>That is not the context of flexible you were using.
Yes it's exactly what I meant. You only have to be as complicated as is
necessary in a particular context. That means you can accept a wider
range of ways players might want to do this specific action than if
the parser has to cope with every possible different action in the entire
game that happens to use the same verb.
>Fixing bugs is done much easier with a centralized scheme, since
>fixing the bug once fixes it for all the mud. With add_action(), fixing it
>once generally just fixes it locally.
But what if you don't want the fix to apply to the entire mud? What if
the "fix" allows syntax that is only correct in one particular instance?
Your central system ends up with a load of extra checks for specific
instances.
For example, you might want a player to be able to "climb halfway up ladder"
but you are unlikely to want the player to be able to "climb halfway up
mountain" in one command.
>: That is a good point, I agree that all commands should follow a standard
>: syntax. That doesn't mean it has to be a horrifically complicated
>: "cope with anything" syntax though.
>No one said it should be. The benefit of standardized syntax is that
>you can account for anything. It does not mean you have to account
>for anything.
By definition a central command parser must be able to account for
everything in the mud.
>With a non-standardized parser (add_action()), you don't realistically
>even have the option.
There is no reason a standardized syntax cannot be applied to an add_action
system. The difference is that it is not rigidly enforced by the mudlib and
thus can be flexible. The only downside is ensuring that people use it.
>:>How does it determine what the command arguments are? You are
>:>oversimplifying the issue, much as add_action() does.
>: I'm not sure I understand your question. The command arguments are the
>: things the player typed after the command itself.
>I am saying that you are oversimplifying the issue because you are
>breaking a command line into the command and arguments. In fact, a
>command is a user-initiated event.
Maybe we have a terminology misunderstanding. Ok, a command is
something the user typed. It is an instruction to the mud to do something.
As such it consists of a verb (imperative) and some arguments which
describe what the required action applies to and supply any additional
information necessary.
I don't think it's too much to insist that the players start their input with
the command verb?
>A bucket is not a string argument to a command, but an object in the
>user's world which may or may not respond to certain user-initiated
>events.
"bucket" is exactly a string argument until such time as whatever is doing
the parsing decides what it means. If my command is "say bucket" then
how is this an object that must respond to the command "say"? Only the
parser decides which string arguments refer to objects and then tries to
locate them. In the example above, the parser would decide that
"bucket" was simply a piece of text to send to objects in a certain way.
>: Yes the command is vague. It's also the first thing I'd type if I can see
>: a bucket of paint and want to stir it.
>That's a side issue. 'stir paint' is ok, and I don't really have that
>much of a problem with it. I mostly wanted to convey how rich the
>syntax can be, and that other users will think of it another way.
You can make the syntax as rich as it needs to be with add_action too. With
the advantage that you only need to make it rich with respect to the
exact situation it applies to.
>:>stir red paint in the bucket
>:>stir the read paint in the blue bucket
>:>stir the ugly red paint in the dirty blue bucket
>:>mix the paint in the bucket
>: And, IMO, should also respond to "stir paint" and "stir bucket" etc.
>No, not "stir bucket". But this has nothing to do with the point at
>hand anyways.
Yes, "stir bucket" too. If me and you can work out what is meant then there
is no reason the mud should not, unless user-friendliness is not a goal. It
is relevant to the point since the point is flexibility of syntax amongst other
things.
>:>Newbie cres are unlikely to do the following:
>:>* handle adjectives and articles properly
>:>* handle synonyms
>: They don't have to. My standard object has an id() function which handles that.
>And you hope each cre remembers to call id().
They will, or their code won't go in game. Just like they will follow all other
code guidelines if they want their code in game.
>I have seen a zillion and one different creator initiated methods for
>testing an id.
And chances are none of them were as simple and catch-all as a good id().
Hence the vast majority of creators will opt straight away for using id() as
this gives them the least work to do.
>Any solution for consistency which places the burden of consistency on
>individual cres is a bad solution.
Equally, any solution that enforces consistency even to the detriment of
user-friendliness in the interface is a bad solution.
>: All the examples you gave would be handled by the add_action function
>: doing pretty simple parsing - "%s in %s" and then an id() check on
>: the latter to check the command refers to itself, and an id() check
>: on it's contents to make sure the former refers to it's contents.
>That really is not very simple parsing. Keep in mind, sscanf() is one
>of the hardest functions for cres to learn. So, to make a simpl area,
>you have now required your newbies cres to become sscanf() gurus.
sscanf is as complicated as you want it to be. Ok I'm a long time coder
but I don't see anything necessarily complicated in
sscanf( str, "%s in %s", thing, container ); - it's not necessary for a cre
to learn all the possible ways sscanf could ever be used (i.e. become a guru
as you suggest) in order to use this level of functionality.
>: If sscanf couldn't match that pattern (i.e. no " in ") then id() the
>: whole string against itself, if no match id() it against the contents.
>: If no match return 0.
>Again, assuming they actually know id() is the proper check.
There is no reason for them not to know. By the time they've graduated
from apprentice to junior creator (an essential step before any code can
go in game) they will have already demonstrated they know this stuff.
>: In my experience, add_action()s that don't handle aliases, adjectives
>: etc are very quickly reported by player-testers and thus get fixed.
>The ones you hear about are quickly reported.
In my experience the onces that are not reported quickly are the ones
that are very rarely used, so this is less important a point than you make out.
>But this creates an air
>where inconsistency is the rule. Why would you opt for catch the
>problems when the area is in the game approach as apposed to the
>guaranteed consistency of the parser?
Because it seems to me that problems being put in the game in the first
place will be rare providing there are guidelines on how to do things and
any creator trusted to put things in the game has proven that they know
them. Plus I think rigidity of an enforced consistency can be detrimental
to the user interface - see Babs' example from Lima Bean.
>: In the case of "stir paint" yes. In which case the player gets to think
>: "doh, should have told it to stir the one in the bucket" and berate
>: themselves for being lazy.
>That's not what I meant. What if you have two buckets of paint, one
>red and one blue? Blue is life and red death. You mean to tell me
>that the mud assuming which paint you meant is a good thing? I don't
>think so.
You can't force the mudlib to cope with player stupidity. If there was such
as case where stirring the blue bucket kills you and stirring the red bucket
yields a reward then (a) the room/objects concerned should make this clear
and (b) any player who simply types "stir bucket" knowing that one of them
kills you is asking for trouble.
That said, your central parser will just say "Which bucket?" Now there is no
real reason why the stir command add_actions in the red and blue buckets
cannot also say "Which bucket?" in this circumstance. Add_action gives you
the flexibility to have a default object to simplify player's lives in the vast
majority of circumstances and AT THE SAME TIME it allows you to insist on
the player being precise where it is necessary to do so.
>:>With add_action(), you are lucky to get
>:>anything other than "What?".
>: Not true, but we'll ignore that for now.
>Yes, it is true. The cres have to understand how notify_fail() works
>and remember to use it. In my experience, cres don't do this well
>until they have reached a certain level of coding sophistication.
It isn't complicated to use it correctly, and a creator would already have
demonstrated that they know how to use it before being trusted to
place code in the game.
>: The problem with the notify_fail() system is that if several objects
>: are passed through searching for a match for the command then only the
>: very last notify_fail message gets given to the player. This can lead
>: to some very confusing "error" messages that are often impossible to
>: "debug".
>Right. In fact, I have seen notify_fail() produce some really funny
>and confusing error messages that simply could not be fixed. Why
>would you want a system that sometimes helps you and sometimes spouts
>nonsense at you?
I'm not particularly happy with the notify_fail system and this is the only
reason I'm considering dropping add_action in favour of another system.
That said I have enough disagreements with the central system you prefer
that I'm likely to put some effort into coming up with a better error system
for my add_action implementation instead - I'll let you know if I come up
with one.
>Furthermore, are you going to tell me that if I login to your mud, I
>will never see the expression "What?"
You'll see "What?" quite frequently because I expect there are a lot
of commands you'd try that haven't yet been implemented. However what
you won't ever see is MudOS's "didn't find anything to handle this command
message" which in my config file is defined to be not "What?" but rather
"Severe command system failure, please tell a creator."
Since the "What?" that you do see is produced by the mudlib, it can be
trivially changed as I mentioned in another post.
>:>And about that list of full commands. With the MudOS parser, it is
>:>easy to keep a full list. With add_action(), it is nearly impossible.
>: Why would you need a full list? There are far simpler ways to spam players.
>Huh? You consider "help commands" spam????
More or less. A list of potentially hundreds of commands that reels off when
you type "help commands" is not particularly friendly or particularly useful
to a player unless they know ahead of time what command they are looking
for - and in that case why view the list?
"help commands" should rather give a menu of types of command (communication,
combat, etc) which you could then browse further to find the command you
need. Much easier to find the command that lets you "emote" to a distant
player that way, than to view a list of everything and try and guess which
one it is.
--
Dan
///\oo/\\\
> say open sesame
Descartes says, "Open sesame."
The cave door opens wide.
>
What you are using below as an example of why you would want
add_action() is actually a bastardization of the concept of a
command. A command represents an ACTION the player wants to take.
Abracadabra is not an action.
Threshold RPG <thre...@counseltech.com> wrote:
: In article <6asus4$o83$1...@darla.visi.com>, George Reese <bo...@imaginary.com> wrote:
:>John Adelsberger <j...@ultra5.cc.umr.edu> wrote:
:>: In fact: the Lima method is _usually_ preferable, for a number of reasons,
:>: but there are several key assumptions in this judgement, not all of which
:>: will always hold true even though all of them usually do. For instance,
:>: if you want to make a mud in which coherence is NOT a goal, the centralized
:>: approach is unsuitable, and while mindless wordgames are silly, there COULD
:>: be a reason to do something like this, even if I don't know what it is at
:>: the moment.
:>
:>Let me requote myself:
:>
:>"The reason you have a problem coming up with an example is that there
:>is absolutely no circumstance under which the add_action() approach
:>actually is preferable to the MudOS verb parser."
: George, there are a lot of reasons why I might want a certain command to work
: ONLY in one room or ONLY on one object. One very simple example is a room
: where you have to type some magic word to make something happen (door opens,
: wall raises, etc) but there is nowhere else in the game where you will ever
: type that magic word.
: Why make a verb? Why have this magic word appear on a list of possible
: commands?
: Since a player would have to learn this magic word somewhere else (from a
: scroll, an NPC, etc), it is actually WORSE if they can figure it out by
: reading a list of verbs or playing trial and error with all available verbs.
: Standardization is NOT the best thing in 100% of all situations. Further, you
: should not assume that your own personal preferences are the same for all
: people.
: -Aristotle@Threshold
: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
: VISIT THRESHOLD ONLINE! High Fantasy Role Playing Game!
: Player run clans, guilds, businesses, legal system, nobility, missile
: combat, detailed religions, rich, detailed roleplaying environment.
: http://www.threshold.counseltech.com
: telnet://threshold.counseltech.com:23
: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
--
: This is not always the case. In 'Real Life' you don't have a nice list of
: commands to check through when you are trying to decide what you want to do.
No, in real life you do what you intend. You do not need to guess "is
this a wielding the sword action?" You know what you can do.
: While I agree that standardization of *almost* all commands is a good thing, I
: still think there are some situations where a non-standard verb/command is
: best in a certain situation.
: Sometimes, the player shouldn't be able to learn something or get a hint by
: running through the list of available commands. I dont mean you put them
: in a 'guess the verb' scenario: what I mean is they might have to learn what
: the 'magic' comand is from another location, an NPC, etc, and should have no
: chance of just 'stumbling' upon it by referencing a list.
Again, that is a propert of the magic system in question. It has
absolutely nothing to do with learning what actions they can perform.
query() isn't the problem; set() is the more troublesome one. Here's why:
query is easy: return evaluate(properties[key]);
in order to get the functionality for set, though, you need:
if (propfunc[key]) properties[key] = evaluate(propfunc[key], value);
else properties[key] = value;
which adds an extra mapping to maintain, support functions for it,
and adds an extra mapping lookup and test to EVERY time a property is
set, so you're adding an additional speed penalty to something that is
already rather slow. That hurts. Then, later, you decided you need
security for certain values, so the set() system acquires a set of
privileges and way to set/check them, adding Yet Another check, even
if it is just for the _existence_ of a privilege for that key, and
if the mudlib is really stupid (read TMI) they even have support
for nested keys and privilege levels, which interact badly, so that
bugs like: set("name", ...) being protected, but set("/name", ...),
which does the same thing, wasn't ... etc ...
If you do things the correct way, it is trivial to do the above without
any of that baggage.
int largest_xp_gain; // added later
int skills_sum; // program invariant, added in hindsight
void add_exp(int foo) {
if (!security_check()) return;
if (foo > largest_xp_gain) largest_xp_gain = foo;
xp += foo;
}
void set_str(int foo) {
skills_sum -= str;
str = foo; // or perhaps ::set_str(foo)
skills_sum += str; // preserve invariant
}
This demonstrates some things that even a newbie mudlib coder can do
easily with the query_foo() design. Doing the same thing if 'str'
and 'xp' are properties is much more difficult.
George, who said I wanted the command to be SPOKEN? You are assuming that
everyone wants to design their game the way YOU Like it designed.
Some people would rather just have someone type a single command word, rather
than have to say it.
I dont understand why you have to INSIST that your way is the *ONLY* way that
is good. There are lots of cases where it is totally logical for someone to
want a command word to work ONLY in that one room or on one object.
In MOST cases, a standardized system of commands is superior. I agree with you
on that much. However, you are really being pigheaded when you INSIST that
your way is the only way for all situations.
>What you are using below as an example of why you would want
>add_action() is actually a bastardization of the concept of a
>command. A command represents an ACTION the player wants to take.
>Abracadabra is not an action.
Why not? Why does everyone have to design things the way YOU want them
designed? What if MYXELPLIC *is* an action in one room?
Even better, what if MYXELPLIC is the button on a wand and you press it by
typing MYXELPLIC.
Sure, you can have them type: press myxelplic, but myxelplic is a lot easier
to type on its own. And since the only time that command wil EVER be used is
for that one wand, there is absolutely no need for a central command for it.
Okay George, list every possible action you can perform.
Sorry, but you don't *know* what you can do. You cant check a list of actions
whenever a problem in real life presents itself.
I'm now planning to construct a common parser/syntax for commands handled
by the command server (i.e. the non-add_actions), it's going to be fun
coming up with a way of specifying all the kinds of weirdness especially
in creator commands.
>Occasionally I find it easier to do a kludge than to thrive for
>100% purity. I know I know, it's a weakness.. :-)
I have this weakness too. I find it inevitably results in me having to
come back and rewrite later though. :(
>>I think you and he both mean "too vague for a centralised parser to work
>>out what it refers to" since both I, the player and the add_action()
>>method can understand it easily. It's also the sort of thing I consider
>>essential to handle to keep the mud user friendly.
>That's true. Players often prefer ultra-short commands with all extra
>stuffing removed.
It's a question of the minimum amount of typing needed to achieve the
intended goal. I just don't think it's necessary to make players type an
essay everytime they want to do something.
>However... I do think that command still has to check
>for item(s) of which id is "paint". Your system probably does that check
>first too, if I'm not mistaken
There doesn't need to be a check for items matching paint in the add_action
system. All that needs to happen is for the add_action function to check
am I "paint"? Do I contain "paint"? This is a different kettle of fish to
a central parser which needs to check all objects present to see if they
match "paint" before it can even start to handle the command.
>I think my parser could be (for example) enhanced to make use of
>object "it", object that was referred to by last succesful command
>("examine bucket" -> sets 'him'-object, so you can now use
>"stir paint in it" ok)... And first check if "it" contains "paint"
That would help since it would allow the player to
>pour paint in bucket
You pour the paint into the bucket.
>stir paint
You stir the paint in the bucket, it mixes nicely.
Instead of:
>pour paint in bucket
You pour the paint into the bucket.
>stir paint
There is no paint here.
(or something like "Usage: stir <liquid> in <container>).
>(a good idea actually... chatting in newsgroups isn't waste of time
>after all).
I'm posting too much - I have little time to write code now. :)
>>The mudlib shouldn't have to be doing that amount of work. If it's going
>>to check all details of all objects present for any command then it's
>>going to be sloooow.
>Then again, if mudlib actually wants to be 'friendly', and notices that so
>far it hasn't really understood the command, it might want to try some
>more reasoning.
Yes that's true, it wouldn't have to always do detail checks.
>>>And which error message would be used? Infamous "what?"? (Well, actually,
>>>it shouldn't be all that hard to have a catch-all error handling)
>>At present yes, my system would say "What?" however since this is handled
>>by the mudlib itself rather than MudOS, it would be trivial to change it
>>to say, for example, "Nothing here to stir."
>Nod. Although, for commands with wider variety of syntaxes, it would be
>helpful to get more precise information about the reason of failure.
Would it? In the case that we have dropped through to "What?" it means that
there is no object that could handle the player's command. In this instance
it is better to tell the player that there is no object there he can
possibly use that command on rather than say "Usage: stir <liquid> in
<container>" which would imply that he could do it to something if only
he types the right words.
>>So how would this handle a spell which prevents players using the command
>>at all?
>Heh. No, then one would have to resort to another mechanism. I use another
>approach for condition 'hallucinating' (blindness is an easier thing,
>it's checked by 'look'-command directly).
This is a point I disagree on. The look command shouldn't have to cope
with every possible spell affecting sight that someone might come up with.
Take:
>>"cast 'weapon blindness' at Binglemonster"
... a spell that would make "Binglemonster" unable to see any weapons.
Should the look command have an extra check added for this new spell?
Or, is it better to handle it by the magic system transparently?
[snip some magic discussion]
>>Hence to fit in with this system and be able to change the way command
>>server commands work I decided the simplest way would be to use the
>>existing shadow to handle the command.
>Ok, as long as you know about (possible) problems and alternatives,
>and still think it's the way to go, then that's how it should go.
I think the security system is clever enough to prevent anything
"naughty" being done by shadowing commands (bypassing checks in the
commands themselves doesn't gain you much if the security handler
knows you haven't got permission).
I'm not convinced (yet?) that the bad points of a system of hooks
don't outweigh the bad points of shadows if you see what I mean.
>>A combination of both really. If an object no longer wants to handle the
>>command it can remove_action() (or player->remove_command_entry() ) to
>>delete it's entry. This is what a room would do for example, to remove
>>a command it had added.
>Ah. Makes sense (for the effect you want). Was just wondering about
>how many invalid commands there would be stored after the player
>had adventured for hours.
I don't know - its not currently possible to test the system in that
sort of environment. I suppose in theory it could get quite large after
a long playing period. Perhaps I could put in a check on the number of
command entries such that if it passes a certain size then a
"garbage collection" occurs to purge all invalid entries.
>>What is the objection to shadows? Or is this another touchy subject
>>I should avoid? :)
>Heh. Well... There were wars between people who hate shadows and those
>who need they are useful. Much like with add_action(). The main problem
>I have is that when people use shadows, they tend to be used in a way
>that makes it much more difficult to develop the mudlib. Shadows are
>used at such a low level, by-passing many abstractions, that it seems
>to make the mud (and mudlib) much more fragile.
I can't see why it should do so - can you give a couple of examples? I
think possibly tighter control of the shadow() efun and a mudlib
"control mechanism" for adding shadows rather than simply allowing anyone
to define shadows how they wish would make most of the problems go
away and leave a system more flexible than hooks.
--
Scatter ///\oo/\\\
> All that having been said, I personally don't give a hoot what people use.
> You could do something like the mudOS parsing system in the mudlib.
> Heck, we *used* to have something like that back when what is now Lima
> was running on an Amylaar driver. When we switched to MudOS, we moved
> it into the driver for efficiency reasons.
I am having trouble getting a handle on the modules and verbs of the
lima mudlib.
It is for that reason that I originally started this thread... Now that
I am
back from being stationed in Korea and ready to get back into some
mudlib coding,
I wanted some help deciding whether to return to the TMI mudlib (which,
with Nightmare
gone, and a personal aversion to database based muds) or it's only
competition
Lima (or should I say, choose between Lima and the quickly fading TMI).
At what point did the parsing move into the driver? This ability is,
IMO, the most
attractive feature of Lima, in theory, except, perhaps that it hard for
an old dog like
myself to learn new tricks, and I am having severe trouble figuring out
how to cope
without properties, add_action() and I still don't grok verb()s... Feel
like
enlightening me?
I can see that there are serious security problems with the TMI lib,
which, if I am
not mistaken, no one knows how to fix without either bloating the lib
and slowing it
horribly, or ripping out so much code that it ceases to resemble the old
mudlib...
correct me if I'm wrong. My question would be: are these security
problems of a type
whre a malicious wizard wreaks havoc, or the type where a
player/outsider does? If
it is the former, primarily, this is no problem, as I have my own
machine on the local
gateway which serves two functions: serving my news/mail/ftp and
running
my mud toys, and I personnaly know the rest of my wizards (and have
since we went to
high school seven (wow time flies) years ago). So, what about external
threats?
A last question, and with luck, my question will be answered rather than
mutate into a
different thread: whatever happened to Leto and his TMI-1.4
initiative? Is that dead?
Thanks,
Tigycho
>
> If you want to use add_action, if you still like it better, that's
> fine. Go use it, I won't get offended at all.
>
> In fact, that's how most of the Lima crew feels about Lima in general.
> We wrote what we wanted to use for our own project(s). We put it out
> there for the people who want to do something similar, and can "hang"
> with our code. That isn't everybody. I would think it wouldn't be a
> whole lot of people at all. I'd prefer people use something that
> they're happy with, no matter what product that is. Certainly, it is
> frustrating to everyone involved if someone doesn't want to be using
> my software, and spends all their time bitching and moaning.
>
> Please CC any replies, I'm not a huge/frequent usenet reader.
>
> John
>
> -------------------------------------------------------------------------------
> |John Viega "The public at large tends to confuse the |
> |vi...@list.org composing of a symphony with the writing of |
> |http://list.org/~viega/ its score." |
> |University of Virginia -- Edsger Dijkstra |
> -------------------------------------------------------------------------------
In article <6b3lkt$t8f$2...@usenet88.supernews.com>, thre...@counseltech.com writes:
>
> George, there are a lot of reasons why I might want a certain command to work
> ONLY in one room or ONLY on one object. One very simple example is a room
> where you have to type some magic word to make something happen (door opens,
> wall raises, etc) but there is nowhere else in the game where you will ever
> type that magic word.
(1) it is trivially possible to emulate this behavior with a verb.
[Hint: all you have to do is pretend to ignore it elsewhere]
(2) This is a wonderful way to create "syntax quests", especially for things
that aren't magic words, but more like doing a certain special thing
with a certain object. If you insist on a nonstandard verb, you put
quite a few players in the "I know what I want to do, but can't figure
out how to tell the game how to do it" category. That really sucks.
(3) even if it is a magic word, be realistic, and make them _say_ it.
Adds to the realism for other people in the room as well. In addition,
if your mud has gags or silence spells, it is even more fun ...
---------------------------- begin transcript -----------------------------
> say a murpe is not a mud
You say, "A murpe is not a mud."
Your Sword of ShitMUDs flashes with a dark light.
> cast Killfile on aristotle
Done.
Aristotle tries to say something, but noone seems to be able to hear him.
> kill thread
Somehow, it refuses to die.
> kill me
Suicide is not the answer.
> end post
Smart move.
> >You mean like "open sesame"?
> >
> >> say open sesame
> >Descartes says, "Open sesame."
>
> George, who said I wanted the command to be SPOKEN? You are assuming that
> everyone wants to design their game the way YOU Like it designed.
Let's say you wanted to recreate "adventure" on a mud. So you really
do want xyzzy and plugh, etc... to be commands, but they only work in
one room.
So let's say in that one room, the behavior is:
> xyzzy
--> Pinkfish grovels at your feet, and offers you a cabbage!
With normal add_action usage, when you're NOT in that room, you see:
--> What?
Wouldn't you rather see:
--> Nothing happens here.
I would. If I were playing some game, and I typed 'xyzzy' and I saw,
'What?', unless I were experienced enough to know better, I would
assume that the game didn't accept xyzzy as a verb. Most people are
probably not going to be experienced enough to know better, even if
you put it in the docs, etc. People don't read documentation except
as a last resort, in general.
The way that every place I've ever seen has used add_action, if you
didn't guess the right syntax the first time, you'd get a 'What?'.
Let's say I typed: "flip off switch". The code is looking for "flip
switch", and when it doesn't see it, 0 is returned. 'What?'
discourages me from trying the flip verb. Or, I could say, "flip the
red switch". Is the wizard going to be sophisticated enough to parse
out articles and adjectives? Probably not. It isn't worth the
energy, especially when it can be automated by the game. Anyway,
"What?" is a far less helpful message than, "I don't see a red switch
here." And do you really think your wizard is going to bother
handling, "flip the switch with the screwdriver"? It might make sense
to someone trying to solve a puzzle...
People have big misconceptions about the MudOS parsing system. You
can respond to verbs differently based on the room, no problem,
although that does depend on how your mudlib uses the driver
functions.
What sort of interface would you prefer as a wizard?
1) You learn add_action() syntax and its precidence rules, etc...
and if you want even minimal parsing, you do it yourself in your own
function. You get passed a string of input beyond the first word.
2) You write a function called verb(). All the parsing is done for
you based on english grammar templates someone else wrote. If
there is a grammatical match that doesn't make sense, you don't
even worry about it. verb() only gets called when it "makes sense".
if there is a target, you get the right object passed to you,
instead of having to figure out what object the user is referring
to on your own.
Then, you can do whatever you want to handle things.
The person always gets a *useful* message based on what he typed,
and not 'What?' It could be, 'you used the verb "kick" in a way I
don't understand.' But at least that tells the player the game
knows a verb named 'kick'.
I'm not saying a mudlib will provide an interface as nice as #2. I
know they usually try to come close, depending on the mudlib.
The parser isn't trying to take control away from the area coder.
Generally, the mudlib will be set up to let him do whatever he wants
to respond to a verb. The parser is there to _be useful_. If you're
running a game where you're asking players to type in something close
to english, the parser is there to make your life better by:
- Doing *parsing* for the wizard, since he shouldn't have to do it,
probably doesn't want to do it, and probably won't do it if he
doesn't have to bother. It is a *hard* thing to do, is tedious,
and is error prone. The parser makes it all effortless for
the wizard, and garuntees consistancy.
- Giving the player appropriate feedback to let him know *why*
his actions didn't work, or whatever. Again, this is something
the wizard *could* do if he wanted, but it is easier on everybody
and more consistant for him to not even have to worry about it.
The "automation" factor is why any commercial, off the shelf game you
ever played, like Zork and Kings Quest, etc... used a centralized
parser. It is a waste of time and energy to write more of the same
all over the place.
All that having been said, I personally don't give a hoot what people use.
You could do something like the mudOS parsing system in the mudlib.
Heck, we *used* to have something like that back when what is now Lima
was running on an Amylaar driver. When we switched to MudOS, we moved
it into the driver for efficiency reasons.
If you want to use add_action, if you still like it better, that's
First of all, with respect to the example from Lima Bean poosted:
1) That code was written probably 2 years ago when the parser was in a
pretty nubile state in MudOS.
2) The parser still isn't done.
3) The mudlib isn't done, especially wrt. the parser.
4) The way we do tune it is wrt. our personal preferences.
For example:
> : > swim in ocean
> : You can't swim in that!
This should work, and I think did work about two years ago, but the
area needs to be updated.
> : > get 2 apples
> : You can't get 2 apples.
> : > get two red apples
> : You can't get two red apples.
These should work, and I think they used to, and I'd have to look to
see why they don't.
> : > get all apples
> : You can't get all apples.
All as an adjective hasn't been added to the driver, which is where it
belongs.
> : > get all
> : ocean: You aren't able to take it.
> : sand castle: You aren't able to take it.
> : sandy beach: You aren't able to take it.
I think these are artifacts of the rooms being old.
> : > put apples on floor
> : There is no floor here.
There shouldn't be a floor on a beach. There should be in indoor
rooms. There should be a ground, though.
> : > examine apple
> : Which red apple do you mean?
This is our personal preference at Lima. We'd prefer that you have to
say "an" or "any" apple for it to randomly choose one. Or, it should
give you a menu, or let you actually answer the question, none of
which is implemented.
Anyway, that should be pretty representative.
> To be fair, if it had a notion of 'first is default' and a notion of
> 'if they're identical, just pick one,' it'd be much nicer.
Not in my opinion. I think "my" should be the default for certain
verbs. We also feel that for the types of muds we want to write,
(in general, not always) objects should be unique enough that you'd
*want* to distinguish with an adjective if you have two w/ the same
id. I can't help it if some guy walks onto our mud and starts cloning
10 identical objects, that's not the way we want to see it go down.
> : There is no way to play such a Mud in an 'intuitive' way. Yet, having to
> : study a command language first before you can start at all, because for
> : some wierd consistency reasons you can`t even "examine" anything, isn`t
> : really fun for a newbie player.
>
> No kidding.
Huh? People who are used to certain LP muds might get used to certain
"two word" syntaxes, but people who don't have the same background are
used to the way they speak and write. For what we want to do,
omitting the article is acceptable to us, but omitting the preposition
is not. 'examine frog' I'll live with, 'look frog', I don't want. It
is easy to make that work if that's the way you want it, though. Like
I said in another post, Lima is more concerned with writing software
that the dev team wants to use than what you may want to use.
Although we do try to keep the door open for people to change anything
they don't like arbitrarily. Many of the features we provide are only
there as placeholders more or less, because we find everybody has
something different in mind, no one will ever be satisfied with what
you provide, etc... (e.g., combat).
If you've ever played Zork or any other infocom game, that's the sort
of thing we're slowly moving towards with the parser and the mudlib.
We know how to get there, it is just a lot of work, and we're all busy
with graduate school or real jobs.
Sure, it is perfectly acceptable to want a mud where people can't talk
in english, where you have to use these forced word orderings, where
adjectives don't count, or where you don't want to recognize complex
sets of words as a single object or a set of objects, where you don't
want "it" to refer to the last thing you talk about, or "my" to refer
to anything in your inventory. Heck, I've wanted something like that
for certain things, but when I want something like that, I usually
have something more GUI based in mind, because I'm not a huge fan of
guess the verb, and I am a big fan of lucasarts games like Monkey
Island, Indiana Jones, and Maniac Mansion.
You can build your own system to do less if you want less, and that's
cool. To each his own. You can also make the mudOS system do less if
you want it to do so, and that might cut some corners for you, I don't
know.
> : - You can parse a small set of commands comparatively fast using a
> : central pattern database. Yet, the more you allow for natural language,
> : synonyms and all that, your database will grow enormously, and slow
> : down the process. The same is the case if your MUD is growing. For
> : every single command pattern the overall Mud size will slow down the
> : processing!
You should really look at the implementation. Unlike a hardcoded game
like Zork, the mud always knows all the verbs, but it only deals with
the objects that are important at any given time. The mud size
doesn't really slow anything down. You'd have to put tons and tons
and tons of objects in your environment for it to even start to make a
difference. You'll hit a ton of walls before this happens.
> fact, even though 'cut the frog with the dagger' makes sense to us, why
> should we care if some twit types 'cut with frog the the dagger' or
> some such nonsense? We know what he meant; just establish a rule stating
> that direct objects always come after nouns and verbs always come first,
> and you're set.
Beyond the fact that a lot of people do care... There are places where
this will get ambiguous. Instead of 'frog', use 'sharp stick'. cut
with the sharp stick the dagger has a completely different meaning
from cut the sharp stick with the dagger. Prepositions are very
important, scanning for nouns isn't good enough for us, although if it
is for you, that's fine by us...
> find this arrangement awkward. This also allows for 'cut frog dagger,'
Anyway, you could make all this stuff work the way you want w/ a
centralized system too. There are even multiple ways to go about it.
Like I said, you can labotomize the system that is in the driver to
your heart's content.
Well, I wouldnt. Not as a player nor as a designer. If xyzzy only works in one
place, maybe I don't want them to type it somewhere else and get a message
that says "Nothing happens here". That is just a hint for later use.
Sometimes, if you want a command to work in only one room, or on only one
object, in the entire game, I think an add_action is better. For one, it keeps
all the code in that one place, so its easier to locate. Second, you dont have
to create a verb *and* hooks in the appropriate object. Third, there is no way
for people to 'guess' the command because they cant type it anywhere else and
get a hint when it gives a more specific fail message (and sometimes, I prefer
this because I dont want them having ANY chance of 'figuring out' the command
unless they have learned it elsewhere in the proper manner- from an npc,
scroll, research, etc).
For those reasons, I think there are many perfectly reasonable scenarios in
which one could use an add_action. Certainly, a system that allows for this is
not ridiculous or pointless as George originally asserted.
(NOTE: I am not saying add_actions are BETTER than a standardized system. I am
saying there are some situations where an add_action makes a lot of sense and
is very reasonable, logical, and simple to use).
>Tatu P Saloranta intoned these words...
>>>I think you and he both mean "too vague for a centralised parser to work
>>>out what it refers to" since both I, the player and the add_action()
>>>method can understand it easily. It's also the sort of thing I consider
>>>essential to handle to keep the mud user friendly.
Although the command is question has been snipped, and I can't off-hand
remember what it was, it is not easy for the add_action method to understand
it.
The add_action method will only understand vague messages if you specifically
instruct it to. And 99% of the time creators do not parse the input to an
add_action properly
The centralised parser can make just as much sense of it as the add_action
can, UNLESS you have the add_action make some huge assumptions that anything
that looks remotely sensible must be correct.
In which case you can parse vague message easily enough, but have no
certainty of achieving what was desired.
>It's a question of the minimum amount of typing needed to achieve the
>intended goal. I just don't think it's necessary to make players type an
>essay everytime they want to do something.
I think 90+% of players would prefer an essay to a syntax quest...
>>However... I do think that command still has to check
>>for item(s) of which id is "paint". Your system probably does that check
>>first too, if I'm not mistaken
>There doesn't need to be a check for items matching paint in the add_action
>system. All that needs to happen is for the add_action function to check
>am I "paint"? Do I contain "paint"? This is a different kettle of fish to
>a central parser which needs to check all objects present to see if they
>match "paint" before it can even start to handle the command.
If your add_action doesn't check for all object of "paint" then you will run
into a lot of trouble.
add_actions should always use present() not id() unless you have written your
own method for handling multiple items of the same id.
"stir paint 2" should be parsed properly (assuming you use "<ob> 2" in your
parsing method)
If you only check ids, then you have this problem:
Consider two potions, each with add_action( "drink_potion", "drink" ) ;
The first potions in my inventory:
int drink_potion( string str )
{
if( !id(str) )
{
notify_fail("You cannot drink that.\n" ) ;
/* NOTE 1 */
return 0;
}
if( this_player()->query_race() != "gnome" )
{
notify_fail("Only a gnome may drink this potion.\n" ) ;
return 0;
}
this_player()->add_hp( 100 ) ;
write("You quaff the potion and feel better.\n") ;
destruct( this_object() ) ;
return 1;
}
The 2nd potion:
int drink_potion( string str )
{
if( !id(str) )
{
notify_fail("You cannot drink that.\n" ) ;
/* NOTE 1 */
return 0;
}
write("You sip from the black liquid.\n") ;
this_player()->death() ;
destruct( this_object() ) ;
return 1;
}
If I try and "drink potion", expecting it to use my first potion (which is
probably a bad thing anyway, but is fairly common) but I'm an elf, then
I die.
id() is the culprit. I didn't want the 2nd potion.
You will need to replace the id() calls will present( str ) == this_object()
tests, which will mean every object is attempting to find out which object
is being referred to, and actually increases your work.
[ NOTE 1:
The notify_fail( "You cannot drink that.\n" ) ; is an example of a really
bad error message that you commonly get with add_actions.
This object doesn't know whether you can drink that. You might well be able
to, but be full. However it needs to set some sort of notify_fail() to
avoid ye olde "What?". If you insist on individual parsing, then you
will need two forms of notify_fail() or a priority on them, so a "guess"
message doesn't cancel out a detailed one ]
>>>The mudlib shouldn't have to be doing that amount of work. If it's going
>>>to check all details of all objects present for any command then it's
>>>going to be sloooow.
It is only going to check all objects present if you use a command that
takes an object a an argument.
If your parsing doesn't check all objects before "assuming" that they mean a
particular object, then you are going to run into a lot of problems, (see
above )
: Well, I wouldnt. Not as a player nor as a designer. If xyzzy only works in one
: place, maybe I don't want them to type it somewhere else and get a message
: that says "Nothing happens here". That is just a hint for later use.
: Sometimes, if you want a command to work in only one room, or on only one
: object, in the entire game, I think an add_action is better. For one, it keeps
: all the code in that one place, so its easier to locate. Second, you dont have
: to create a verb *and* hooks in the appropriate object. Third, there is no way
: for people to 'guess' the command because they cant type it anywhere else and
: get a hint when it gives a more specific fail message (and sometimes, I prefer
: this because I dont want them having ANY chance of 'figuring out' the command
: unless they have learned it elsewhere in the proper manner- from an npc,
: scroll, research, etc).
: For those reasons, I think there are many perfectly reasonable scenarios in
: which one could use an add_action. Certainly, a system that allows for this is
: not ridiculous or pointless as George originally asserted.
: (NOTE: I am not saying add_actions are BETTER than a standardized system. I am
: saying there are some situations where an add_action makes a lot of sense and
: is very reasonable, logical, and simple to use).
I am saying any place where anyone has to guess a command is plain
stupid. Again, a command represents an action you want to take. A
command is only an expression that the mud can understand of what you
want to do. 'xxyzy' is not an action. Any mud that requires a player
to guess to type that in as a command has made a serious mistake. Not
only have you designed the mud such that figuring out what to do in
this instance is hard, but you have made every single general action
on the mud hard. Other actions are hard simply because you never know
when the problem is that an action is not understood by the mud versus
not understood here.
The command in question was "stir paint" where the player can see a
bucket of paint in the room. It's an example I'm beginning to regret picking. :)
>The add_action method will only understand vague messages if you specifically
> instruct it to. And 99% of the time creators do not parse the input to an
> add_action properly
>The centralised parser can make just as much sense of it as the add_action
> can, UNLESS you have the add_action make some huge assumptions that anything
> that looks remotely sensible must be correct.
The point is that in the case of add_action, the command is being examined
by the bucket object. The bucket object knows it can contain things and
that the thing the player wants to stir might be in it, so in this context it
can check if it contains something that matches what the player wants
to stir. For your central parser to understand this it needs to know all about
buckets rather than simply having an acceptable syntax for the command.
>In which case you can parse vague message easily enough, but have no
>certainty of achieving what was desired.
It's not about generally parsing vague messages, but parsing messages that
are vague in a global context but actually quite specific in the context of
a particular situation.
>>It's a question of the minimum amount of typing needed to achieve the
>>intended goal. I just don't think it's necessary to make players type an
>>essay everytime they want to do something.
>I think 90+% of players would prefer an essay to a syntax quest...
Which is a syntax quest:
You see a bucket of paint here.
:stir paint
Usage: stir <liquid> in <container>
Or:
You see a bucket of paint here.
:stir paint
You stir the paint around a bit.
Obviously I don't speak for everyone but I get frustrated very quickly
with systems that require me to type natural languages sentences for
everything. It's faster, quicker and more convenient to type
"put sword backpack" than "put my red sword into my backpack".
There's no reason, IMO, why the mud shouldn't accept both methods.
>add_actions should always use present() not id() unless you have written your
> own method for handling multiple items of the same id.
>"stir paint 2" should be parsed properly (assuming you use "<ob> 2" in your
> parsing method)
That's a good point. Except that since the buckets won't respond to id("paint")
anyway (the paint is an object inside the bucket) then present() won't help
in this instance. The only reason "paint" is handled at all is as an added extra
to be more friendly, to make "stir paint" equivalent to "stir paint in bucket".
I guess you could make "stir paint 2" equivalent to "stir paint in bucket 2" and
parse it that way but now the parsing is getting tricky and the number of
id() checks needed is growing.
This is a nice example, and it took a few moments to spot the mistake in
the add_action coding:
>id() is the culprit. I didn't want the 2nd potion.
No, the culprit is:
> notify_fail("Only a gnome may drink this potion.\n" ) ;
> return 0;
These should be a write() and return 1 - at this point the add_action has
determined that the action _does_ apply to itself (it must do since the
id() check passed) and hence it should prevent the command being processed
by other actions.
The potions must have some way to tell them apart (else how will the player
know which will kill him anyway?) so if he really wants to drink the second
potion rather than the first, he'd have to "drink black potion" for example,
making the first potion fail its id() check.
>[ NOTE 1:
> The notify_fail( "You cannot drink that.\n" ) ; is an example of a really
> bad error message that you commonly get with add_actions.
> This object doesn't know whether you can drink that. You might well be able
> to, but be full. However it needs to set some sort of notify_fail() to
> avoid ye olde "What?". If you insist on individual parsing, then you
> will need two forms of notify_fail() or a priority on them, so a "guess"
> message doesn't cancel out a detailed one ]
Suppose notify_fail worked like:
int notify_fail( string error_msg, int reason );
Now the reason could be for example:
NOT_ME - as far as the function can tell, it is not the intended recipient
of the command.
SYNTAX - the function could have handled it but the syntax didn't make
sense.
NOT_POSS - the function could have handled it but the thing the player tried
to do isn't possible.
If a check for a command falls through all possible objects without getting a
'1' then it shows the first NOT_POSS message encountered. If there are none of
them show the first SYNTAX message that was returned. If none of them then
show the first NOT_ME message. Or ignore NOT_ME messages and print a
general error message of the form "Cannot find 'thing' to stir.\n" (assuming
the player typed "stir thing").
--
Scatter
///\oo/\\\
> The point is that in the case of add_action, the command is being examined
> by the bucket object. The bucket object knows it can contain things and
> that the thing the player wants to stir might be in it, so in this context it
> can check if it contains something that matches what the player wants
> to stir. For your central parser to understand this it needs to know all about
> buckets rather than simply having an acceptable syntax for the command.
No, you misunderstand what goes on with centralized parsing as
implemented in MudOS. I'll give an example here, and then please see
my other posting in this thread somewhere for some more detail.
Let's say for the sake of simplicity that the only "stir" rule your
mud understands is stir OBJ1 with OBJ2. The player types some input.
The driver figures out based on the input what OBJ1 and OBJ2 could
possibly be. The driver then starts talking to potential candidates,
trying to determine a best match. For example, let's say paint chips
also ID to paint. If you say stir the paint, the driver might ask the
paint chips if it makes sense, and the paint chips would return
something like "you can't stir paint chips!". So that isn't a
success, and the driver then tries the paint, which will basically
say, "It makes sense to me.".
So when the driver picks out its objects, it calls a function that
means essentially "here's the interpretation, now respond to what he
wants to do, mudlib!" In most mudlibs, the verb will get that call.
Most verbs will do some default checks, like make sure it isn't too
dark to use that verb, or make sure the player's hands aren't tied, or
whatever. Then, the verb will generally pass the ball to the direct
object, and let the direct object deal. For example, the paint would
probably get called as such: stir_with(OBJ2).
Now you can add any rule that tickles your pickle, such as:
stir OBJ
stir OBJ in OBJ2 (though honestly, I wouldn't expect to see this
one... most people aren't going to bother typing "in the bucket" there
unless they know they have to do so for whatever reason).
> Obviously I don't speak for everyone but I get frustrated very quickly
> with systems that require me to type natural languages sentences for
> everything. It's faster, quicker and more convenient to type
> "put sword backpack" than "put my red sword into my backpack".
> There's no reason, IMO, why the mud shouldn't accept both methods.
Right, you don't speak for everyone. You're more than welcome to
add a rule on your mud:
put OBJ1 OBJ2
Some muds do this sort of thing, and they can certainly do what they
want.
Or depending on your mudlib, you might alias p=put $1 into $2 if
you're stuck with real english and you really hate it.
> No, the culprit is:
>
> > notify_fail("Only a gnome may drink this potion.\n" ) ;
> > return 0;
>
> These should be a write() and return 1 - at this point the add_action has
> determined that the action _does_ apply to itself (it must do since the
> id() check passed) and hence it should prevent the command being processed
> by other actions.
? If you picked up the potion of death more recently, and they both id
to potion, the potion of death will get called first. That's just an
add_action problem, although you could make it into a qc problem,
making everyone add adjectives. But then again, what if they're both
"black potions"?
> [...] For one, it keeps
> all the code in that one place, so its easier to locate. Second, you dont have
> to create a verb *and* hooks in the appropriate object. Third, there is no way
> for people to 'guess' the command because they cant type it anywhere else and
> get a hint when it gives a more specific fail message (and sometimes, I prefer
> this because I dont want them having ANY chance of 'figuring out' the command
> unless they have learned it elsewhere in the proper manner- from an npc,
> scroll, research, etc).
I can do all of these things with the centralized parser in MudOS:
The object that wants to use a verb can register it and handle it, if
you really want. Then, when someone trys to use the verb elsewhere,
you can say, "What?" or "I don't understand that verb" or whatever.
Of course, I'd probably still put a verb in a central location, and
have the verb dispatch to the object if it understands xyzzy just for
regularity's sake. Then, you don't have to worry if you do want a
second object to respond to xyzzy.
OTOH, If you pick an obscure word out of a hat, and players try to use
it as a verb, then they probably have some inside knowlege. Like,
they got the clue, and now they're trying to find the right place to
use it. Or they've used it before, and they're trying to figure out
if there's someplace else where it works. Once the person has
"discovered" the verb (or has used it successfully, or whatever is
appropriate), it would be really easy with the centralized parser to
switch from giving a message like "What?" to giving a message like
"You can't do that here."
I'm not surprised... I've never used a system where it is used so I've been
making a lot of assumptions.
[snip explanation]
So have I got this straight? There's some code in the player object, linked
to process_input() and this picks up the string the player typed. It looks
up the set of syntax rules defined for the command the player has typed
(presumably based on assuming the actual verb is the first word?) and
calls the driver efun to match elements of what the player typed with
elements of the first syntax rule. If it can't match the first syntax
rule it moves on to the second etc.
When it matches a rule, it calls the command object telling it which
rule was matched and what objects the player could have been refering
to at each part of the string?
The command object then calls various predefined functions in the
objects the player wanted to do the thing to in order to handle the
command?
Another point I'm not entirely clear on is where it is best to do the
actual handling of the command (i.e. executing the parsed output). The
choices are the object being referred to (i.e. the paint in "stir paint")
or in the command object (i.e. the stir command itself).
An example that might explain better - I've recently finished writing
room.c and one of the things I've done is to take out the code that
generates what the player sees when they "look" in the room and put
all that processing into the "look" command. My reasoning being that
if this processing is in room.c then it's going to get loaded
potentially thousands of times in an average mud. Whereas if it is
in the command object it just gets loaded once.
I'm not sure if this can be extrapolated into a general rule either way
but it's one of the things I'm puzzling over.
>So when the driver picks out its objects, it calls a function that
>means essentially "here's the interpretation, now respond to what he
>wants to do, mudlib!" In most mudlibs, the verb will get that call.
How does the driver determine which object to call?
I've asked this before, but is there any documentation of the MudOS
parsing package anywhere? I've now located a description of the
"parse_command" efun (part of Nanvaent's man pages at aragorn.uio.no)
but it's dated 1994 and I'm not at all sure it's the same thing that
people are talking about here.
>> No, the culprit is:
>> > notify_fail("Only a gnome may drink this potion.\n" ) ;
>> > return 0;
>>
>> These should be a write() and return 1 - at this point the add_action has
>> determined that the action _does_ apply to itself (it must do since the
>> id() check passed) and hence it should prevent the command being processed
>> by other actions.
>? If you picked up the potion of death more recently, and they both id
>to potion, the potion of death will get called first. That's just an
>add_action problem, although you could make it into a qc problem,
>making everyone add adjectives. But then again, what if they're both
>"black potions"?
I have to say you've picked a very good example to demonstrate add_action's
failings. It's true that this is a problem with add_action, it's also
true that there are ways around it. My solution to this would probably
be to make it a QC issue and insist that since the potion of death is
a horrible thing to drink by accident it should check to see if there
is anything else that id()s to the string as well as itself, and if so
ask the player to be more specific.
I do appreciate however that this isn't necessarily what's going to
be implemented and put in game though, especially when at the time
the death potion went in the game there were no other black potions.
I keep wavering for & against add_action in this discussion, I think
I'm probably back in the against camp now.
In most cases I think it's helpful to have a "default to first object"
rule (I can imagine getting frustrated with a parser that kept telling
me "Which healing potion?" when I type "drink healing potion" in the middle
of combat and happen to be carrying four identical ones). The cases
where "default to first object" can be dangerous should therefore IMO be
checked for in the dangerous objects, rather than impose the unfriendliness
of always making the player be totally specific.
--
Scatter ///\oo/\\\
1) all commands go through a central command daemon, with list of available
commands. all this daemon would do is pass the verb and arguments to a
command object if possible. when a command comes in the 'verb' is checked
vs list regardless of syntax following.
2) when a player enters a room (or a given range from and object) the object
registers its event handlers with the player. this perhaps would create
a huge list of handlers since most objects will have 'get', 'examine', etc
handlers just from standard objects. This perhaps could be defaulted out
and those commands that should act on every object simply realize this and
default to all objects in the room.
2) the command is passed to the verb/command object which contains rules for
its possible syntaxes. the syntax set and verb/argument combo get sent to
a rule parser which has the job of determining which words in the argument
are direct objects, adjectives, etc based on the rule set (I envision
something much like Lima's rule sets here) and a standard grammar set.
4) if syntax matches any valid rules it checks the callers list of registered
handlers for a match. if there is no match it could check an object list
for objects with the corresponding handler. if the handler is found it is
called with the parsed arguments in the correct object. In the case of
multiple handlers there would be a way to determine based on the syntax
parse which (if any) of the objects to call (or all the objects if
applicable)
something roughly like:
player -> commands daemon -> command object -> target object(s)
^ | ^
| (handler info) (verb,arg) v | (parsed arg)
object parser
This would be different from the Lima command parser in that it has a little bit
more information about a users environment, and thus would go through a list of
200 boxes more intelligently (or just as inefficiently if all the boxes
registered
the same handler). It seems to me that this would at least address the
efficiency
question for the centralized parser some (it might violate the object oriented
nature though by volunteering what an object can handle). It would also only
check the syntax for the command used, not an entire verb list (though I'm not
sure Lima does this anyhow, I'm not even sure why it would).
Lima may already do this in a passive way, though my recollection is unclear. I
will go back and look through it though...
Any comments, or I am just reinventing the wheel?
I think Farmville has fried your brain...
[your scheme snipped...]
> This would be different from the Lima command parser in that it has a little bit
> more information about a users environment, and thus would go through a list of
> 200 boxes more intelligently (or just as inefficiently if all the boxes
> registered
> the same handler).
I addressed this in another post in this thread, but you have a
misconception here. The parsing which is used in Lima doesn't scan
through all boxes when it goes to match a box. Depending on the
context, the parser will never really concern itself with more objects
than are in the recursive all_inventory of the top level environment
you're in. That's a gross upper bound, really. The parser won't let
you manipulate things in closed containers, etc (stuff determined with
mudlib callbacks).
There is *no* efficiency question here. You would have to have one
hell of a lot of objects in the same room for it to even become an
issue. I've had rooms with 100 different objects in it that ran just
fine. Remember, all the processing is done at the driver level, and
that helps too.
Again, just to be crystal clear, although many people seem to be
assuming otherwise, Lima *already* limits itself as to what objects
get checked.
In fact, you can include as many or as few objects in a check as you
want. The efun parse_sentance() demands a list of what objects it
should check. If you really wanted to, you could pass objects(), but
that would normally be a bit daft.
> Any comments, or I am just reinventing the wheel?
You are just reinventing the wheel, you need to take a closer look at
the parsing package.
> In fact, you can include as many or as few objects in a check as you
> want. The efun parse_sentance() demands a list of what objects it
> should check. If you really wanted to, you could pass objects(), but
> that would normally be a bit daft.
To be a bit more accurate about what goes on for those who are
interested, you can pass mudOS a flat array, or you can give it a
hierarchy of nested arrays to clue the parser in on containment... ie,
so it knows what stuff is YOURS, what's in the room, what's in the
chest...
> John Viega intoned these words...
> >In article <6b7c2n$88k$1...@news.uk.ibm.com> sca...@thevortex.com (Scatter ///\oo/\\\) writes:
> So have I got this straight? There's some code in the player object, linked
> to process_input() and this picks up the string the player typed. It looks
> up the set of syntax rules defined for the command the player has typed
> (presumably based on assuming the actual verb is the first word?) and
> calls the driver efun to match elements of what the player typed with
> elements of the first syntax rule. If it can't match the first syntax
> rule it moves on to the second etc.
No, the mudlib takes the input, and calls parse_sentance() in the
driver. The driver then goes and figures out which rule is a best fit
if any, and calls the "action" if appropriate. If it calls the
action, then it also passes on which objects the player was talking
about, and the names the player used to identify those objects if you
care about that. If no verbs match the input, the mudlib gets told so,
and then the mudlib goes off and checks non-game commands, which are
stuff like who, finger and most wizard commands. Some other stuff can
go on, but that's the high level summary.
> Another point I'm not entirely clear on is where it is best to do the
> actual handling of the command (i.e. executing the parsed output). The
> choices are the object being referred to (i.e. the paint in "stir paint")
> or in the command object (i.e. the stir command itself).
Generally we find it is best to pass control into the verb, and then
have the verb call the object. This way, you can do default checks
you don't want to have the wizards bother coding over and over again:
Is it too dark to perform the action? Is the player blinded? Has he
lost his arms in combat? Is he dead? In fact, even when writing the
verbs this gets kind of redundant. So in Lima, such things (tho we
don't have limb combat) are checked for you by default_checks() in the
base class for verbs.
The verb *could* hardcode the behavior, as maybe it should with look
and get and stuff that should have consistant meaning everywhere. But
in most instances, after it does the default checks, the verb will
dispatch to the direct object.
> all that processing into the "look" command. My reasoning being that
> if this processing is in room.c then it's going to get loaded
> potentially thousands of times in an average mud. Whereas if it is
in the command object it just gets loaded once.
Be careful, *code* doesn't get duplicated when you clone stuff, only
variables do.
> How does the driver determine which object to call?
Well, essentially what usually happens, is do_<verb>_<rule> gets called in
the appropriate verb object. For example, do_look_at_OBJ() will get
called in the look command. This may differ when you have a synonym,
for example, do_examine_OBJ() might not get called, do_look_at_OBJ()
might get called instead. Also, if you have something like a Soul
Daemon which has registered hundreds of verbs, and only has one
handler, you can have your generic handler get called instead of a
specific callback. So if kick is a soul, the Soul Daemon only needs
to define do_verb_rule() and not do_kick_OBJ(), do_kick(), do_bork(), etc...
>
> I've asked this before, but is there any documentation of the MudOS
> parsing package anywhere? I've now located a description of the
> "parse_command" efun (part of Nanvaent's man pages at aragorn.uio.no)
> but it's dated 1994 and I'm not at all sure it's the same thing that
> people are talking about here.
parse_command() is old, buggy and awful. It has nothing to do w/ the
current parsing system and is only there for compat for people who
have been using it forever. It definitely is a good idea *not* to use
that.
As for documentation, like many of the more modern MudOS features, the
best documentation that is written down is currently the MudOS
changelog. Of course, the people on Lima are usually willing to
answer questions, especially if you post them to the newsgroups (type
news when you get there).
> >? If you picked up the potion of death more recently, and they both id
> >to potion, the potion of death will get called first. That's just an
> >add_action problem, although you could make it into a qc problem,
> >making everyone add adjectives. But then again, what if they're both
> >"black potions"?
>
> My solution to this would probably
> be to make it a QC issue and insist that since the potion of death is
> a horrible thing to drink by accident it should check to see if there
> is anything else that id()s to the string as well as itself, and if so
> ask the player to be more specific.
This isn't a very satisfying solution at all. What if the player
doesn't know that it's a potion of death? If it did, it'd probably
also have 'death' as a useful adjective, no?
> I keep wavering for & against add_action in this discussion, I think
> I'm probably back in the against camp now.
Ok.
> In most cases I think it's helpful to have a "default to first object"
> rule (I can imagine getting frustrated with a parser that kept telling
> me "Which healing potion?" when I type "drink healing potion" in the middle
> of combat and happen to be carrying four identical ones). The cases
> where "default to first object" can be dangerous should therefore IMO be
> checked for in the dangerous objects, rather than impose the unfriendliness
> of always making the player be totally specific.
You can do this with the MudOS parser if you so wish to do so.
I agree.. sometimes, an add_action is a simple and easy to use thing.
But every
wizard who uses it should at least try to keep it as "sophisticated" as
possible.
I mean, it's rather annoying if you have three posts in the game where
you want to
put a nail in, and thee different ways to do it, just because noone
thought about
putting in a good parsing.
So, while add_action definately has it's uses, it should be used only
when the
nonstandard command is what you want.
Axel.
I do realize this. I am not saying there are things an add_action system can
do that a standarized/centralized verb/command system CANNOT do. I am just
saying that the use of an add_action is not going to be 'foolish' or
'ridiculous' in 100% of all situations (as George was claiming)
The issue here is not that standardized commands are better than add_actions.
That is pretty clear I think. The argument here is that George said any
use of nonstandardized command words is foolish/ridiculous/something to that
extent.
There are in fact situations where an add_action makes sense, and it would not
be "stupid" to use one.
>(2) This is a wonderful way to create "syntax quests", especially for things
> that aren't magic words, but more like doing a certain special thing
> with a certain object. If you insist on a nonstandard verb, you put
> quite a few players in the "I know what I want to do, but can't figure
> out how to tell the game how to do it" category. That really sucks.
This is a bad use of an undocumented command word. I have never said this is a
smart way to do things.
>(3) even if it is a magic word, be realistic, and make them _say_ it.
> Adds to the realism for other people in the room as well. In addition,
> if your mud has gags or silence spells, it is even more fun ...
Like I said, it isnt always a magic word. Sometimes it is a button to push,
etc. Furthermore, if its a quest, you might not want someone to speak it
anyway so observers wont get the hint.
For most things, a standardized command is best. I agree with this, and that
is what I do on my game. However, there are still situations where it seems
much more logical to have the 'command' located on the object/room/NPC.
You gain simplicity in coding it, a single location for all the code for that
rare/unique command, and the inability for it to be 'guessed' by looking
through a list of commands.
Okay. I am not explaining my example well enough. I would never make someone
GUESS a command word. However, I might want them to ONLY be able to learn it
by talking to an NPC somewhere else, identifying the magic item, reading a
scroll/book found somewhere else, etc.
> Again, a command represents an action you want to take. A
>command is only an expression that the mud can understand of what you
>want to do. 'xxyzy' is not an action. Any mud that requires a player
>to guess to type that in as a command has made a serious mistake.
I'm repeating myself a couple times to make sure this is clear. I am not
advocating ever making someone have to GUESS the command. I am saying they
should have to LEARN the command from another location (NPC, scroll, book,
etc). In a situation like this, I want it to be virtually impossible to guess.
That means I dont want them to be using a standard command word that is on any
list.
Add to this need the fact that an add_action keeps *ALL* the code for this
unique command in one place, and I think there is definitely a REASONABLE
justification for using an add_action in this type of situation.
>Other actions are hard simply because you never know
>when the problem is that an action is not understood by the mud versus
>not understood here.
Not really. In the situations I am describing, if a 'known action' doesnt
work, that means you need to talk to NPCs, search rooms, etc. in order to find
something that will TELL you what you need to do.
I have never said the standarized/centralized system cant do the things that
an add_action can do. I am not saying add_actions are better than standard
verbs.
I am saying that there are SOME situations in which it is reasonable and
logical to use an add_action.
This debate started because George made some statement that basically asserted
that any use of non-standardized commands was foolish/ridiculous/etc.
However, I think there are in fact situations where it is reasonable to use an
add_action.
As a whole, a standardized/centralized command system is vastly superior. I
agree 100% and 95% of the player commands in my game are totally centralized.
However, there are a few things that I prefer to use add_actions for. The
basic reasons are usually:
1) I dont want there to be any way to guess the verb.
2) All the code is located within that one object
3) It is easy to code
Yes, I know I could do the exact same thing by centralizing even that unique
verb. However, I don't see any advantage to centralizing a verb that is only
used in ONE place in the game, when all I would end up doing was make it look
like what an add_action looks like (and I'd lose the fact that all the code
for that unique command was located in that single object).
Fortunately, I dont have this problem because I am the only programmer on my
game. This is another reason why add_actions are not a problem for me. In the
uncommon scenario that I use one, it functions in the same manner as a
verb/command would.
Also, if I did use an add_action'ed command in two different places, it would
function the same.
In the situation in question, either you have a valid action taking
place (which xxyzy most definitely is not) or you have a magic phrase
or you have a magic item. If it is a valid action, it should be a
command that a person can do anywhere. If it is a magic phrase, then
you use the say command. This in fact sounds like what you really
want in this case.
Finally, if it is some magic spell or somethign like that, you should
have a spell system that understands verbs like 'cast' or 'pray' or
something like that.
At no point should a mud make up non-existent actions.
Threshold RPG <thre...@counseltech.com> wrote:
: -Aristotle@Threshold
: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
: VISIT THRESHOLD ONLINE! High Fantasy Role Playing Game!
: Player run clans, guilds, businesses, legal system, nobility, missile
: combat, detailed religions, rich, detailed roleplaying environment.
: http://www.threshold.counseltech.com
: telnet://threshold.counseltech.com:23
: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
--
: The issue here is not that standardized commands are better than add_actions.
Actually, my claim was that there was no circumstance in which
add_action() was better than the MudOS parser.
I will nevertheless admit that I believe what you claim I was arguing.
:>(2) This is a wonderful way to create "syntax quests", especially for things
:> that aren't magic words, but more like doing a certain special thing
:> with a certain object. If you insist on a nonstandard verb, you put
:> quite a few players in the "I know what I want to do, but can't figure
:> out how to tell the game how to do it" category. That really sucks.
: This is a bad use of an undocumented command word. I have never said this is a
: smart way to do things.
:>(3) even if it is a magic word, be realistic, and make them _say_ it.
:> Adds to the realism for other people in the room as well. In addition,
:> if your mud has gags or silence spells, it is even more fun ...
: Like I said, it isnt always a magic word. Sometimes it is a button to push,
: etc. Furthermore, if its a quest, you might not want someone to speak it
: anyway so observers wont get the hint.
: For most things, a standardized command is best. I agree with this, and that
: is what I do on my game. However, there are still situations where it seems
: much more logical to have the 'command' located on the object/room/NPC.
: You gain simplicity in coding it, a single location for all the code for that
: rare/unique command, and the inability for it to be 'guessed' by looking
: through a list of commands.
This is a really bad sort of question for several reasons. First, if
observers cannot tell what is going on, it certainly lacks in any sort
of realism.
Second, yet again, COMMANDS REPRESENT ACTIONS, they are not game
entities of themselves.
You say it is a button they should push?
Then the command is 'push'. Make the button obscure, not the text
representation of the act of pushing.
You don't want them to speak it?
Have them whisper the word to something.
Command event handling should be local. Interpretation should be
global. In all circumstances. Period.
> I have never said the standarized/centralized system cant do the things that
> an add_action can do. I am not saying add_actions are better than standard
> verbs.
I know.
> However, there are a few things that I prefer to use add_actions for. The
> basic reasons are usually:
>
> 1) I dont want there to be any way to guess the verb.
> 2) All the code is located within that one object
> 3) It is easy to code
> Yes, I know I could do the exact same thing by centralizing even that unique
> verb. However, I don't see any advantage to centralizing a verb that is only
> used in ONE place in the game, when all I would end up doing was make it look
> like what an add_action looks like (and I'd lose the fact that all the code
> for that unique command was located in that single object).
I see advantages to centralizing the verb. Here are the pros for both sides:
Centralized parsing: regularity (since we both seem to agree
centralized parsing is far preferable in general), doesn't suffer from
potential precidence problems you could have with add_action, gives
more control (e.g., if the administrator wants to make sure there is 1
and only 1 place on the mud where your verb makes sense, he can't do
that with add_action), parsing is already automated so you don't have
to roll your own, probably some other reasons. You can still keep all
the code inside to the object, you don't have to put it anywhere else
(ie, you definitely do not lose the fact that all the code for the
command is just in that obj).
add_action: The only thing that really comes to mind is if you're
*not* worried about any parsing at all, it _might_ take me 30 seconds
less to write.
: I am saying any place where anyone has to guess a command is plain
: stupid. Again, a command represents an action you want to take. A
: command is only an expression that the mud can understand of what you
: want to do. 'xxyzy' is not an action. Any mud that requires a player
: to guess to type that in as a command has made a serious mistake.
He didn't say you had to guess. He said you'd be told somewhere, but that
you would have to do whatever quest he wanted in order to be told. Are
you really so dense that you missed this, or are you simply ignoring any
and all arguments you can't cope with and substituting straw men?
: Not only have you designed the mud such that figuring out what to do in
: this instance is hard, but you have made every single general action
: on the mud hard.
He also mentioned using a standardized system for most things. Another
honest mistake on your part, right?:-)
: Other actions are hard simply because you never know
: when the problem is that an action is not understood by the mud versus
: not understood here.
Never is a strong term when he's talking about just doing a few local
exceptions to a centralized system. The problem here is that he is
right and you are wrong: if he wants a verb that _really_ only works
in one place, local parsing makes sense. If, as is the case with most
things, he wants a verb that exists everywhere, but works only where
it makes sense, centralized parsing makes sense. Any other claim
is foolishness on its face. Your argument is 'there are no instances
where you want a truly local verb,' which is a moronic argument unless
you're only talking about yourself; he may WELL want a local verb and
use it in a non-syntax-quest manner.
--
John J. Adelsberger III
j...@umr.edu
"Civilization is the process of setting man free from men."
- Ayn Rand
: something roughly like:
: player -> commands daemon -> command object -> target object(s)
: ^ | ^
: | (handler info) (verb,arg) v | (parsed arg)
: object parser
My method is somewhat different, but you're getting close to what I'm working
on. The main difference is that I have two sets of commands. The first is
'non-rp' commands, which are mostly creator-only, but also include things like
'who,' 'finger,' and so forth. The second are 'rp' commands, which use
natural language parsing. Another difference is that my 'command object'
is the user's shell object, which is the first object on a stack of objects
from which to take input. This stack is similar in some ways to Lima. The
non-rp commands currently do their own parsing, although this will be
changing before long, and the rp command parser isn't even started yet, as
I'm still deciding what all I want it to be able to do. One notable is that
this is a semi-centralized semi-distributed system; you can do truly local
commands, which I probably won't need, but might use here and there, and
you can also get a list of all the globally available commands very easily.
In other words, the system provides a mechanism, but doesn't dictate
policy.
: Command event handling should be local. Interpretation should be
: global. In all circumstances. Period.
Someone else flame him. I'm getting tired of pointing out that the world
is bigger than George's imagination.
Aristotle did make the comment that he didn't want anyone to
SAY it lest others overhear it. OTOH, there is a good case for
global commands for these sorts of mental exercises with nonsense
words.
How about 'THINK xyzzy' or 'THINK plugh'?
--
--/*\ Jon A. Lambert - TychoMUD Email:jlsy...@nospam.ix.netcom.com /*\--
--/*\ Mud Server Developer's Page <http://www.netcom.com/~jlsysinc> /*\--
--/*\ "Everything that deceives may be said to enchant" - Plato /*\--
> Aristotle did make the comment that he didn't want anyone to
> SAY it lest others overhear it. OTOH, there is a good case for
> global commands for these sorts of mental exercises with nonsense
> words.
>
> How about 'THINK xyzzy' or 'THINK plugh'?
>
Even if you just make 'xyzzy' or 'plugh' commands, I think there is a
good case for using the mudOS parser for that sort of thing as an
alternative to add_action. I won't restate the arguments here, since
they're availible elsewhere in this already overly mammoth thread...
In article <6b4jgn$s0m$1...@news.uk.ibm.com>, sca...@thevortex.com writes:
>
> Because it seems to me that problems being put in the game in the first
> place will be rare providing there are guidelines on how to do things and
> any creator trusted to put things in the game has proven that they know
> them. Plus I think rigidity of an enforced consistency can be detrimental
> to the user interface - see Babs' example from Lima Bean.
I'm not going to read through this entire thread, but it should be pointed
out that reasoning based on examples from Lima Bean is an extremely bad
idea, for a number of reasons:
(1) Lima Bean (as a *development* site) is currently running on an alpha
driver which has several known bugs in the parsing code
(2) The mudlib itself has several known bugs in it's parsing code
(3) it is impossible for the casual user to tell which behaviors are
enforced by the parser, which are concious choices made on the
mudlib side, which are bugs, which are design decisions, etc
Most of this is because we at Lima Bean don't put gross hacks into the
code to fix small problems; we instead wait until it can be fixed
correctly.
---------------------------------------------------------------------------
Tim Hollebeek | "Everything above is a true
email: t...@wfn-shop.princeton.edu | statement, for sufficiently
URL: http://wfn-shop.princeton.edu/~tim | false values of true."
You restated:
: "The reason you have a problem coming up with an example is that there
: is absolutely no circumstance under which the add_action() approach
: actually is preferable to the MudOS verb parser."
And I probably agree, although I think distributed parsing in forms other
than add_action() has uses.
: : The reason _I_ don't use the MudOS parsing stuff is that it requires the
: : MudOS containment stuff, which I refuse to use for other reasons.
: I believe that this has been addressed in the latest MudOS releases.
So I've been told. I'll look into it and see; as of the beta my last
Lima download was running on, it wouldn't even compile the parser w/o
containment, but maybe there's something newer.
: : : You should most definitely NOT have "as much flexibility as you want
: : : in the parsing". Syntazes should be standardized across the mud and
: : : well documented. Anything else is a pointless game.
: : "Pointless." So did speak George Reese, who is a god in his own mind.
: : Please, George... could you do some melodrama for us?
: Guessing at syntax is pointless. I stand behind that in spite of your
: irrelevant personal attack.
The point behind what I admit was partially an irrelevant personal attack
was that flexibility has purposes, however rare, which have nothing to do
with syntax or verb guessing games.
: : They do if you enforce standards. Of course, some people can't be
: : bothered, but thats hardly a code problem.
: In my experience, enforcing this level of code detail runs close to
: impossible on a large running mud. It requires way too much time and
: effort on the part of QC arches who have a lot of other work to do.
Distributed QC can work on large muds, in connection with spot checks.
Granted, it probably isn't perfect in any given case, but if it bothers
people, you'll hear about it, and if it doesn't, then it doesn't matter.
: Inconsistencies slip through. Why would you require all this work
: when there is a way to guarantee consistency across the mud?
A compelling argument, but then, I gave up advocating add_action() awhile
ago in favor of other more robust distributed parsing models, and agree
without reservation that some things are best done centralized on most any
mud.
: : Since he most certainly DOES want it to work, this seems a reasonable
: : request. Imagine... a parser that, given a command that OBVIOUSLY
: : targets the ONLY paint in a room(his example, not mine,) one might
: : actually do the command, instead of playing dumb and making the player
: : type out needless verbiage.
: Players should type out what the mean. But this is completely outside
: of the topic at hand. If you want to argue it, start another thread.
I'll just say that I don't think you should ever, in any computer interface
issue, have to do more than is necessary for the computer to disambiguate
the result, and leave it at that. Computers are good at gruntwork, and
we are not.
: : So even if all he wants is a stirrable bucket of paint, he has to have
: : 2 objects. One would suffice, and in fact would be better in most
: : respects, and would appear NO different to a player, but because you
: : have ordained it so, it must be so. Preach it, brother...
: No, there are two conceptual objects and thus should be two actual
: objects. There is an actual relationship between the bucket and the
: paint, one which could change. Furthermore, the player should be able
: to put the paint in other liquid containers. But you do not have this
: sort of flexibility if you don't have a paint object.
Depending on the purpose the paint serves, this may be perfectly reasonable.
A mud is not reality. A mud is a game. In reality, we expect everything
to work sensibly, but in a game, some things can be props, in much the same
way they are in a movie, and as long as they look good when used as intended,
we don't care. Any other approach is unreasonable; no computer can possibly
simulate every detail of even a small room, much less a world. Mr. Yospe
most likely is the local authority on this one, given his mud's design...
I wonder if he might deign to comment?:-)
: : : Furthermore, if the box defines stir but
: : : the target of the stirring is soup, the box will:
: : : * have to perform an ID check on itself in LPC, meaning again that ID
: : : checking will vary from creator to creator and be slower than driver
: : : ID checking
: : If you can't figure out how to do this sort of thing in mandated inherit
: : files, you're grossly incompetent. LPC->C can take care of the speed
: : problem nicely.
: I already addressed this issue. You are requiring extra effort on the
: part of creators AND QC staff that is completely unnecessary.
Creators and QC staff? What part of 'mandated inherit' did you fail to
comprehend? Put the inherit statement into your global include file and
be done with it:-) I'm not saying it HAS to be this way; what I'm saying
is that there are reasonable and functional alternatives in solving most
any problem.
: Furthermore, you don't LPC->C everthing in the mud.
I don't? I'm glad you told me this, as I was unaware that I'd missed
any:-)
(As to that error handling bit, my honest opinion is that nobody, including
Lima, has solved this one to my satisfaction, and I'm still thinking about
it.)
So in life, you always know exactly what is going on? Nope.
>Second, yet again, COMMANDS REPRESENT ACTIONS, they are not game
>entities of themselves.
>
>You say it is a button they should push?
>Then the command is 'push'. Make the button obscure, not the text
>representation of the act of pushing.
That is totally personal preference. A lot of people don't like extraneous
words in a command. Many people, both as player and coder, would rather have a
wand that required: zap <target> rather than press zap <target> or press zap
<at> target.
>You don't want them to speak it?
>Have them whisper the word to something.
Again. That is personal preference. Many people would prefer avoiding the
extraneous typing to initiate the command.
>Command event handling should be local. Interpretation should be
>global. In all circumstances. Period.
This assumes everyone likes things to work the way you like them to work. That
is not the case. There are a number of situations where an add_action()
performs at least equally as well.
As I have noted before, for the vast majority of things, a centralized command
parsers is vastly superior. I have incorporated this into my mudlib because I
agree it is best.
But there are still situations where it is NOT the best. Despite being shown
many examples, you seem to insist your way is better because its the way you
like it that way.
That is your opinion George. Believe it or not, a lot of people do not agree.
>Finally, if it is some magic spell or somethign like that, you should
>have a spell system that understands verbs like 'cast' or 'pray' or
>something like that.
A lot of people do NOT LIKE a requirement of a cast/pray verb. Why is it that
you refuse to realize that not everyone likes to play muds the same way that
you think is best.
None of my mage spells use a 'cast' verb to initiate them. The players of my
game have often commented that they think this is such a relief. The
requirement of typing cast is such a waste and its just something people use
aliases and macros to avoid anyway.
You keep ignoring other benefits.
For one, you make it virtually impossible for the person to merely 'guess' the
verb. It wont be on a list anywhere.
Also, it centralizes all the code for a certain object. If a wand for example
is the only object in the game that uses a certain command verb, all code for
the wand and that verb is in one place. If you want to change something with
the wand, you only have to change things in one place.
And in those situations it is 'faster' to code.
I think these are benefits that make an add_action a useful tool in limited
situations.
Oh, here is another one. Sometimes I create objects that have very limited
use. For example, in an invasion, and on the fly quest, etc.
In situations like that, I do NOT want to add verbs to the parser. I just want
something that will work for a few hours, or whenever I run the quest. In this
situation, objects with add_actions are much better.
> In article <JTV2J.98F...@adder.cs.virginia.edu>, jt...@adder.cs.virginia.edu (John Viega) wrote:
> >add_action: The only thing that really comes to mind is if you're
> >*not* worried about any parsing at all, it _might_ take me 30 seconds
> >less to write.
>
> You keep ignoring other benefits.
No, I'm not, you're not listening :)
>
> For one, you make it virtually impossible for the person to merely 'guess' the
> verb. It wont be on a list anywhere.
Like I said, I can make it so that you won't be able to guess the
verb w/ the parsing package, and it isn't on a list that players can see.
> Also, it centralizes all the code for a certain object. If a wand for example
> is the only object in the game that uses a certain command verb, all code for
> the wand and that verb is in one place. If you want to change something with
> the wand, you only have to change things in one place.
Like I said, I can do this too, absolutely no problem.
>
> And in those situations it is 'faster' to code.
I can make it so this kind of thing is a *lot* faster with the parser,
because it _automates the parsing_. Imagine me removing add_action
but replacing it with a simul_efun or library funcion:
add_oneoff_action (it'd have the same signature as basic add_action).
Then you pass the simple template in, the driver worries 100% about
the parsing, and your callback just fires with the right objects/info
getting passed. You don't have to do any of the parsing work normally
associated w/ add_action at all.
> I think these are benefits that make an add_action a useful tool in limited
> situations.
Again, I see no advantages over the parser yet.
> Oh, here is another one. Sometimes I create objects that have very limited
> use. For example, in an invasion, and on the fly quest, etc.
>
> In situations like that, I do NOT want to add verbs to the parser. I just want
> something that will work for a few hours, or whenever I run the quest. In this
> situation, objects with add_actions are much better.
Why? You can remove stuff from the parser just as easily.
> As I have noted before, for the vast majority of things, a centralized command
> parsers is vastly superior. I have incorporated this into my mudlib because I
> agree it is best.
>
> But there are still situations where it is NOT the best. Despite being shown
> many examples, you seem to insist your way is better because its the way you
> like it that way.
I think the real reason he's insisting that, is that you've yet to
sufficiently convince us that there is a case where add_action is more
useful. Let's leave it at that for this branch of the thread, and
continue to debate it where the specific examples live.
: That is your opinion George. Believe it or not, a lot of people do not agree.
Who does not agree? How?
You have yet to describe an action that makes any sense as a
singleton.
:>Finally, if it is some magic spell or somethign like that, you should
:>have a spell system that understands verbs like 'cast' or 'pray' or
:>something like that.
: A lot of people do NOT LIKE a requirement of a cast/pray verb. Why is it that
: you refuse to realize that not everyone likes to play muds the same way that
: you think is best.
What is the issue with a cast/pray verb or something similar?
: None of my mage spells use a 'cast' verb to initiate them. The players of my
: game have often commented that they think this is such a relief. The
: requirement of typing cast is such a waste and its just something people use
: aliases and macros to avoid anyway.
Using aliases is completely irrelevant. Aliases are tools for the
advanced user. When writing any system, you should both make it so
that it is intuitive to the novice and so that the advanced user can
customize it to their playing style.
: So in life, you always know exactly what is going on? Nope.
In life, you see what other people are doing who are in your visual
range.
:>Second, yet again, COMMANDS REPRESENT ACTIONS, they are not game
:>entities of themselves.
:>
:>You say it is a button they should push?
:>Then the command is 'push'. Make the button obscure, not the text
:>representation of the act of pushing.
: That is totally personal preference. A lot of people don't like extraneous
: words in a command. Many people, both as player and coder, would rather have a
: wand that required: zap <target> rather than press zap <target> or press zap
: <at> target.
'zap' would be an appropriate global verb. Where did I suggest a
syntax of 'press zap <target>'?
:>You don't want them to speak it?
:>Have them whisper the word to something.
: Again. That is personal preference. Many people would prefer avoiding the
: extraneous typing to initiate the command.
Whisper is a command already on most muds. It indicates a type of
'say' where you don't want others to hear. What extraneous typing are
you talking about?
Even if there is some extraneous typing, it is not really an issue on
rarely used commands.
:>Command event handling should be local. Interpretation should be
:>global. In all circumstances. Period.
: This assumes everyone likes things to work the way you like them to work. That
: is not the case. There are a number of situations where an add_action()
: performs at least equally as well.
This is not an argument. You have created an assumption for me that
is not borne out by any evidence.
I have already described my justification, and it has nothing to do
with personal preferences. It has to do with this basic assumption
about the nature of muds:
a mud by definition involves the modeling some sort of world and,
whatever sort of world it is, it involves agents acting.
Given that assumption, centralized parsing is all that makes any
sense. With or without my assumption, add_action() is NEVER a good
idea.
: As I have noted before, for the vast majority of things, a centralized command
: parsers is vastly superior. I have incorporated this into my mudlib because I
: agree it is best.
: But there are still situations where it is NOT the best. Despite being shown
: many examples, you seem to insist your way is better because its the way you
: like it that way.
There are plenty of things I do that I do not insist are better than
different ways of doing things. I have provided ample justification
for my point of view. And for every example you have provided, I have
given a more coherent action-based modeling of the problem. Let's
take a moment to sum up the arguments for the using the magic wand to
open a cave door.
I suggest 'zap cave with wand' or 'zap cave'. You suggest 'zap' or
'zap cave'. The difference is that you think a person should only
ever 'zap' when they have the wand and they are by the cave. What is
your justification? You say openly it is because you prefer it that
way.
I, on the other hand, argue that it makes sense for them to stand on
the beach and type 'zap beach' and see nothing happen. Or, better
yet, if it is a magic beach that a creator built AFTER the wand was
built and the creator wanted it to be zappable, it can be zappable
such that something can happen if the cre wants it to. But the wand
also gets some control over that so that if the wand builder wants it
to be only a cave zapper, then it is only a cave zapper. The
advantage of this approach is:
* You have the flexibility to define zapping events in different ways
for different situations without doing any parsing.
* You have the ability to extend existing zappers to zap differently
in different environments.
* You have a consistent syntax across the entire mud for anything that
zaps or can be zapped.
* You can provide help for this command centrally, if desired
And what do you get by doing zap as an add_action()?
* You appease people who are comfortable with the traditional LP way
of doing things and are afraid to learn other ways.
But you do not get one single game-related tangible benefit.
How is that an opinion? Anything I can do in one room, as long as the objects
are there to allow the action to make sense, I should be able to do in another
room. I just ran to the restroom and flushed my toilet. I can 'flush'
anywhere there is an object that 'flushing' makes sense to. If I go to your
house, I don't wanna have to 'flooge' your toilet. Commands represent REAL
actions. Be they flushing, flooging, casting, praying, jumping, stabbing,
whatever...
xyzzy is not a command. What is the meaning of xyzzy'ing something? You can
define your mud to let you xyzzy something, but if xyzzy is something you can
DO, you should be able to attempt to do it anywhere. I can think xyzzy, I can
say it, I can VERB it...but if its something I can DO I should be able to
attempt anywhere.
The point is, you can define xyzzy to actually be something a player can DO,
but once they can DO it, once its something DOABLE, it makes no sense to
only let them do it, you can certainly only make it succeed in one place, in
one place.
-murmur
On The Two Towers, based on TMI mudlib, we have both add_actions and centralized
commands. We also have a large QC staff.
Our experiences:
Centralized commands present a unique problem for area coders. For if
the stress is on reallism, they find themselves having to provide a LOT of
flags or hooks in their area. Without the hooks, you change the fail
message from: "What?" to an unrealistic "You cannot swim in the ocean".
As a personal preference, I like getting a generic fail message over getting
a fail message which is, bluntly, a lie.
The example which 'babs' posted earlier was a great example - the amount
of work the coder must do to have their area actually "make sense" to the
players increases significantly. Otherwise you end up with this excellent
parsing that really makes no sense whatsoever.
Back to the swim example, the action is always contained within a room. You
are not going to have objects that players carry which are in any way
associated with the ability to 'swim'. And there are few checks to do,
there is no containment to worry about (like "take sword from bag"). Even
vision is not a problem, as you can swim with your eyes closed. So in
this example, the work done by the global parsing is really over-kill.
In closing, the game-related tangible benefits of using add_action() :
1. Less work for the QC staff. They have only to test the room's defined
add_actions and a small set of centralized often-used verbs. They do not
have to test that the room responds properly to rarely-used verbs.
"stir ocean", "mix water", "swim in the ocean" - while all possible,
are such a HUGE amount of work for the QC staff and the coders to ensure
these rarely used commands work realistically.
2. Better containment for room-specific actions. If a player wants to 'swim'
in other rooms without water (such as the air-guitar you mentioned), they
can do so via an emote.
The benefits of centralized parsing have been harped on, and I fully
support it and use it for player-carried and mobile objects. Too often
add_actions are coded without "friendly" parsing, that are carried to
other areas and break things.
David Rudy
Aule @ The Two Towers
dar...@eng.sun.com
: Be careful, *code* doesn't get duplicated when you clone stuff, only
: variables do.
I was under the impression what while it USUALLY worked this way, there
were circumstances in which code did get duplicated, at least partially.
Is this the case, is it mistaken, or was it true at one time but not now?
: As for documentation, like many of the more modern MudOS features, the
: best documentation that is written down is currently the MudOS
: changelog. Of course, the people on Lima are usually willing to
: answer questions, especially if you post them to the newsgroups (type
: news when you get there).
Which, for those of us who are doing things from scratch, is nigh on
useless unless those people want to do nothing but answer questions
all day. I know you guys are too busy to do things any faster than
you already are, and I respect it, because I am too, but meanwhile,
its a bit silly to tell us we ought to be USING this stuff... sure,
I could read the driver source and changelogs and figure it out, but
I could beat myself with a stick too...
David Rudy <dar...@inpg.eng.sun.com.nospam> wrote:
: In article 150...@ptah.visi.com, George Reese <bo...@imaginary.com> writes:
:>And what do you get by doing zap as an add_action()?
:>
:>* You appease people who are comfortable with the traditional LP way
:>of doing things and are afraid to learn other ways.
:>
:>But you do not get one single game-related tangible benefit.
: On The Two Towers, based on TMI mudlib, we have both add_actions and centralized
: commands. We also have a large QC staff.
I think noting the large QC staff is important here. More on that in
a bit.
: Our experiences:
: Centralized commands present a unique problem for area coders. For if
: the stress is on reallism, they find themselves having to provide a LOT of
: flags or hooks in their area. Without the hooks, you change the fail
: message from: "What?" to an unrealistic "You cannot swim in the ocean".
: As a personal preference, I like getting a generic fail message over getting
: a fail message which is, bluntly, a lie.
But it is not a lie. You cannot swim in THIS ocean. Telling the
player that is useful information. The actual problem here is that
the mud has incomplete support for swimming.
: The example which 'babs' posted earlier was a great example - the amount
: of work the coder must do to have their area actually "make sense" to the
: players increases significantly. Otherwise you end up with this excellent
: parsing that really makes no sense whatsoever.
I think Rust already pointed out why it was a problematic
example--things basically do not happen at all like the example showed
in a central processor, unless it is down exceptionally badly.
: Back to the swim example, the action is always contained within a room. You
: are not going to have objects that players carry which are in any way
: associated with the ability to 'swim'. And there are few checks to do,
: there is no containment to worry about (like "take sword from bag"). Even
: vision is not a problem, as you can swim with your eyes closed. So in
: this example, the work done by the global parsing is really over-kill.
In this example, there is no work being done by the global parser. So
there is no over-kill. Parsing work is only done when you have
complex rules and the user provides arguments to parse. For a simple
command like swim, no more parsing is done than for an add_action().
: In closing, the game-related tangible benefits of using add_action() :
: 1. Less work for the QC staff. They have only to test the room's defined
: add_actions and a small set of centralized often-used verbs. They do not
: have to test that the room responds properly to rarely-used verbs.
: "stir ocean", "mix water", "swim in the ocean" - while all possible,
: are such a HUGE amount of work for the QC staff and the coders to ensure
: these rarely used commands work realistically.
Actually, it is more work for QC. In a centralized parsing system, QC
does not worry about any issues related to parsing. They only worry
about issues like 'this room says it is an ocean, does it inherit
LIB_SEA'? That's easy, and can be handled in a QC wiztool.
On the other hand, add_action() requires the QC person to read code to
see if the person properly parsed complex syntaxes, such as 'take X
from Y'. That in addition to making sure the creator allowed for the
proper actions.
: 2. Better containment for room-specific actions. If a player wants to 'swim'
: in other rooms without water (such as the air-guitar you mentioned), they
: can do so via an emote.
There is no such thing as room specific actions. There is only
conceptually a such thing as room-specific handlings of actions a
person can perform anywhere.
My example was not about playing air-guitar. It was about making sure
that a player can 'play OBJ' on any object on the mud. Guitars can
then respond to that playing different from violins. Nevertheless,
the idea of playing the instrument and playing are global concepts.
The bottom line I am trying to communicate is:
* Centralized command parsing requires less work on everyone's part,
QC and cre alike. QC has less work because there is a guaranteed
level of standardization for all command parsing. There is no more
need to proof command handling. Cres, on the other hand, can
benefit from never having to write command parsing code and a
central library of common command handlers, such as a sea room, a
pressable inheritable, etc.
* Centralized command parsing enhances room-specific uses of commands,
it does not diminish them. All that is global is the syntax. What
happens when a player issues a specific command is entirely
dependent on how the room or object in question handles it. In that
sense, it is no different from add_action().
or 'whisper'.
Occasionally, during discussions with people on Lima Bean, we would
ask them what sort of things HAD to be a global verb, and noone ever
came up with a decent example; most people actually just weren't used
to thinking this way, and liked it after it was gently pointed out to
them that there is no reason why MUD commands should be nonsense, other
than that that is how things are usually done.
All you have to do is think about what is really going on. In
Adventure, when I typed 'xyzzy' I must admit I have no idea what went
on; the game simply isn't that "rich". I tend to think it was spoken,
and would be audible to others in the room (c.f. the hollow voice and
"plugh"), so if I was reimping that today, I'd do it with 'say'.
Probably allow whisper as well; put a nice system of hooks for magic
words into all the communication functions, so EVERYONE can benefit
from it. People who want others to hear can 'say'; others can
'whisper' or 'mumble', etc. It makes for a much more realistic
environment. If you want something boring with stock areas and
monsters, sentences without prepositions, and commands that make no
sense, wander over to r.g.m.diku.
(btw, shorthand for things like boards and mailers can be an
exception, but anything that changes parsing that radically should
push an input handler and change the prompt)
In article <34d8d...@news.cc.umr.edu>, j...@ultra4.cc.umr.edu writes:
> George Reese (bo...@imaginary.com) wrote:
>
> : I am saying any place where anyone has to guess a command is plain
> : stupid. Again, a command represents an action you want to take. A
> : command is only an expression that the mud can understand of what you
> : want to do. 'xxyzy' is not an action. Any mud that requires a player
> : to guess to type that in as a command has made a serious mistake.
>
> He didn't say you had to guess. He said you'd be told somewhere, but that
> you would have to do whatever quest he wanted in order to be told.
> [typical pointless and irrelevant personal slam snipped]
Nope, you still have to guess. The clue will be something like 'use xyzzy'
or 'the magic word is xyzzy', etc. If it wasn't for the fact that MUDs
have traditionally done it the old way, the first thing most people think
to try would NOT be just typing the word as if it were a verb.
The syntactic nightmares that existing MUDs are is why you get lovely
descriptions like:
This is a ring. You can 'twist' it. You can also 'frobnicate <monster>'
and 'lizardvomit'.
If traditional MUD syntax is so intuitive and obvious, why is it that
EVERY room and object feels compelled to explain what to type (complete
with single quotes to make it obvious) ? That sort of crap really ruins
any sort of consistent textual style, mood, or atmosphere.
I dont have to show examples where add_action is better. He said all uses of
it are stupid/idiotic/absurd/etc. Thus, all I have to show is that there are
times where use of an add_action is equally as good, or nearly as good.
Further, I have given a number of Pros to add_action use. Thus, there are
logical reasons someone might choose to utilize an add_action.
Designing a game is filled with personal preferences. To attempt to make
blanket statements that one method is absolutely "better" than another in all
situations is generally flawed at its core.
> In article <JTV2J.98F...@adder.cs.virginia.edu>, jt...@adder.cs.virginia.edu (John Viega) wrote:
> >I think the real reason he's insisting that, is that you've yet to
> >sufficiently convince us that there is a case where add_action is more
> >useful. Let's leave it at that for this branch of the thread, and
> >continue to debate it where the specific examples live.
>
> I dont have to show examples where add_action is better. He said all uses of
> it are stupid/idiotic/absurd/etc. Thus, all I have to show is that there are
> times where use of an add_action is equally as good, or nearly as good.
I think you are arguing the wrong side of the coin. You're giving a
contrived example where it is slightly closer to as good as a
centralized system than most examples you could give. For reasons
I've pointed out elsewhere in this thread and I would prefer you to
argue elsewhere in the thread so I don't have to repeat myself
everywhere, your examples are not equally as good, nor are they nearly
as good. In short, they're not very convincing at all. If you have a
centralized system, I don't think it would be very reasonable or
logical to suddenly switch over to add_action. A good argument
someone else made that you could have is that it is not always
worthwhile to change an old mudlib to use new methods. That is a case
where add_action is probably better because it is already working, and
would be too much effort to change. However, I know George Reese
would not argue this one, either. The thread is really about if you're
starting from scratch, what kind of system you should add.
>
> Further, I have given a number of Pros to add_action use. Thus, there are
> logical reasons someone might choose to utilize an add_action.
Like I said, you have yet to provide one that stood up under my
scrutiny. If you'd like to argue my responses, please argue them on
that part of the thread, not here.
> Designing a game is filled with personal preferences. To attempt to make
> blanket statements that one method is absolutely "better" than another in all
> situations is generally flawed at its core.
Personal preference is a reason I can respect for choosing add_action
over a centralized system, but that is a subjective reason, and not
based on the objective advantages and disadvantages of each
system. Objectively, a centralized system can clearly be
better. Again, we're not talking about subjective preferences,
here. For example, that the halting problem is undecidable is a
mathematical fact. However, I know at least one person who doesn't
believe it nonetheless. Is it 'flawed at its core' to talk about the
halting problem as fact just because people don't believe in
mathematics enough to accept the proof? Hopefully you will agree with
me when I say that I think the answer is pretty obviously no.
In this thread, as far as I can tell, what George Reese is arguing is
the objective facts of the matter, given a tabula rasa for a mudlib.
John
Hmm, deciding what is nonsense and what not is partly a matter of taste.
For example it would be no problem devising a MUD around a world where 'say'
is nonsense because the player-bodies communicate non-verbally.
> cast say Hi!
The air around you vibrates shortly.
Oh well, people will alias away the 'cast' anyway[1].
[1] This could make a nice feature for guilds, e.g. magicians. Newly learnt
spells are, well, new, you explicitely have to 'cast' them. After a long
while, you get so used to them that they become natural like breathing.
Hence, no explicit 'cast'ing necessary.
--
Lars Duening; la...@cableinet.co.uk (Home)
: Hmm, deciding what is nonsense and what not is partly a matter of taste.
: For example it would be no problem devising a MUD around a world where 'say'
: is nonsense because the player-bodies communicate non-verbally.
The nonsense will flow in that direction, but not in the other. What
I mean is, it is easy to say that "in this world, the idea of 'saying'
things makes no sense since people in this world have no voices." The
thing is, you can imagine a world in which 'say' makes sense.
Similarly, it is not possible to imagine a world in which 'xyzzy'
makes any sense, because it describes nothing.
Now, there are certain people who will say 'George is such an arrogant
absolutist, how can he say it makes no sense in my world?'. These
idiots are missing the point. If you can describe the action to me,
that is what qualifies it as making sense. It has nothing to do with
whether I have blessed your 'xyzzy' command as making sense.
And if the command makes sense, it should be global.
It is possible, I just did. Maybe I'm the only one who can, but it is
possible.
> Now, there are certain people who will say 'George is such an arrogant
> absolutist, how can he say it makes no sense in my world?'.
I'd say 'George has a limited imagination', if this were our mud :-)
But this isn't, and things like that are design decisions which are up
to the mud makers to decide. You and I are just presenting different
points of view.
> And if the command makes sense, it should be global.
Yup. _If_ someone decides that 'xyzzy' makes sense as command, it should
be global. And all other similar magic words as well. If.
--
Lars Duening; la...@cableinet.co.uk
: It is possible, I just did. Maybe I'm the only one who can, but it is
: possible.
Then please describe what it is to xyzzy.
:> Now, there are certain people who will say 'George is such an arrogant
:> absolutist, how can he say it makes no sense in my world?'.
: I'd say 'George has a limited imagination', if this were our mud :-)
: But this isn't, and things like that are design decisions which are up
: to the mud makers to decide. You and I are just presenting different
: points of view.
You are missing the point. It is not a question of point of view.
Either xyzzy is the act of doing some thing or another, or it is not.
If it is, you should be able to describe what it is to do xyzzy. It
has absolutely nothing to do with points of view.
:> And if the command makes sense, it should be global.
: Yup. _If_ someone decides that 'xyzzy' makes sense as command, it should
: be global. And all other similar magic words as well. If.
Any word you cannot describe, should not be a command.
: Parsing through a very large number of verbs takes time, and that time
: is needed whenever anyone enters any command. Unless you run on a
: machine where lag is no problem at all, that can be bad. I'd rather use
: the cpu capacity for more intelligent npc's ect.
: Frankly, i think that a generalized system is a good idea in general,
: but it is not, as you put it, inherently "better" than a mixed system
: that also uses add_actions().
You argument seems to be based entirely on efficiency. I certainly do
not know enough to comment on the internal details of the parser, but
I do know that I have used both systems and there is no practical efficiency
issue.
Yes, thanks to the man.
[big snip]
>
> There is no such thing as room specific actions. There is only
> conceptually a such thing as room-specific handlings of actions a
> person can perform anywhere.
>
> My example was not about playing air-guitar. It was about making sure
> that a player can 'play OBJ' on any object on the mud. Guitars can
> then respond to that playing different from violins. Nevertheless,
> the idea of playing the instrument and playing are global concepts.
>
> The bottom line I am trying to communicate is:
> * Centralized command parsing requires less work on everyone's part,
> QC and cre alike. QC has less work because there is a guaranteed
> level of standardization for all command parsing. There is no more
> need to proof command handling. Cres, on the other hand, can
> benefit from never having to write command parsing code and a
> central library of common command handlers, such as a sea room, a
> pressable inheritable, etc.
> * Centralized command parsing enhances room-specific uses of commands,
> it does not diminish them. All that is global is the syntax. What
> happens when a player issues a specific command is entirely
> dependent on how the room or object in question handles it. In that
> sense, it is no different from add_action().
>
[snipped off the signature]
There is some truth in this, but, for a mud with a very rich command
structure, a centralized parsing which parses for ALL avialable verbs
can present quite a problem. Especially when one wishes to offer as
many alternative verbs for a given action as possible, so that there
is always a "natural" command that works for each action, even for
those who are not that good speaking english.
Parsing through a very large number of verbs takes time, and that time
is needed whenever anyone enters any command. Unless you run on a
machine where lag is no problem at all, that can be bad. I'd rather use
the cpu capacity for more intelligent npc's ect.
Frankly, i think that a generalized system is a good idea in general,
but it is not, as you put it, inherently "better" than a mixed system
that also uses add_actions().
Axel.
> There is some truth in this, but, for a mud with a very rich command
> structure, a centralized parsing which parses for ALL avialable verbs
> can present quite a problem. Especially when one wishes to offer as
> many alternative verbs for a given action as possible, so that there
> is always a "natural" command that works for each action, even for
> those who are not that good speaking english.
>
> Parsing through a very large number of verbs takes time, and that time
> is needed whenever anyone enters any command. Unless you run on a
> machine where lag is no problem at all, that can be bad. I'd rather use
> the cpu capacity for more intelligent npc's ect.
This is certainly not the case. It uses a hashed lookup, so when you
look at the first word in the user's input, it takes you CONSTANT TIME
to find it in the parser info.
The same thing is not true of add_action(). First, you're keeping them
in a list, which you are traversing. That is potentially linear
time. I am not sure if *all* actions are kept in a linear list, but I
believe that is the case. If so, that's a pretty poor lookup time in
comparison. If they're hashed by verb and then kept in a list, that
is certainly better, and essentially as good as verbs in practice.
The second consideration is memory. Each player has his own list of
actions he can perform. If you have a lot of actions (e.g., very
rich, with a lot of synonyms) in a lot of places on your mud, you can
waste a lot of memory by having all of those verbs showing up in data
structures multiple times over hundreds of players.
> Frankly, i think that a generalized system is a good idea in general,
> but it is not, as you put it, inherently "better" than a mixed system
> that also uses add_actions().
I think you'd have to show me a case where I'd rather have an
add_action.
World 1: A player race has, in addition to verbal means, the capability to
communicate with optical signals.[1]
> xyzzy Ohoh, humans again.
World 2: Another player race has a natural teleport capability.[2]
> xyzzy home
World 3: What a guildmaster does with an obnoxious apprentice.[3]
> xyzzy junior with big bat
(In this case the exact meaning of xyzzy is left unspecified, except
that it is not pleasant for the victim.)
Just because a word has no meaning in the real world does not mean that
I can't give it a meaning in a fantasy mud world.
Note that I don't argue for 'xyzzy' as an one-place-out-of-the-blue
command, as in merging Adventure into an existing mud world.
The world examples are based on ideas by:
[1] Charles Sheffield
[2] Alfred Bester
[3] alt.sysadmin.recovery;
note also the use of "plonk" meaning "adding someone to one's killfile"
Lars Duning <ldu...@mdisystems.com> wrote:
: George Reese wrote:
:>
:> Lars Duening <la...@cableinet.co.uk> wrote:
:> : George Reese <bo...@imaginary.com> wrote:
: [...]
:> :> Similarly, it is not possible to imagine a world in which 'xyzzy'
:> :> makes any sense, because it describes nothing.
:>
:> : It is possible, I just did. Maybe I'm the only one who can, but it is
:> : possible.
:>
:> Then please describe what it is to xyzzy.
: World 1: A player race has, in addition to verbal means, the capability to
: communicate with optical signals.[1]
: > xyzzy Ohoh, humans again.
: World 2: Another player race has a natural teleport capability.[2]
: > xyzzy home
: World 3: What a guildmaster does with an obnoxious apprentice.[3]
: > xyzzy junior with big bat
: (In this case the exact meaning of xyzzy is left unspecified, except
: that it is not pleasant for the victim.)
You are mixing up the concepts of language and action. If 'xyzzy' is
the English word to describe [1], then that is what it is to xyzzy.
Instead, you are using xyzzy to mean three completely unrelated
things, which is an abuse of language. If a person wants to try
communicating with their eyes, they should be able to:
> 'xyzzy I hate snow'
You bat your eyelashes like a lunatic.
Because xyzzy *means* to communicate with your eyes.
: Just because a word has no meaning in the real world does not mean that
: I can't give it a meaning in a fantasy mud world.
: Note that I don't argue for 'xyzzy' as an one-place-out-of-the-blue
: command, as in merging Adventure into an existing mud world.
: The world examples are based on ideas by:
: [1] Charles Sheffield
: [2] Alfred Bester
: [3] alt.sysadmin.recovery;
: note also the use of "plonk" meaning "adding someone to one's killfile"
None of this has anything to do with what I am arguing. Certainly
muds are filled with examples of things that make no sense in the real
world. But you are still able to give them meaning.
Furthermore, all of this has been presented in terms of how you
process user input... globally with centralized syntax or locally with
local syntax. You are not even arguing that point :)
George Reese wrote:
> You are mixing up the concepts of language and action. If 'xyzzy' is
> the English word to describe [1], then that is what it is to xyzzy.
>
Um, well, language and actions DO have some relationships, in BOTH directions. And
what about secret languages of guilds / clans / whatever ? What about different
languages for races ? I think this 'xyzzy' example isn't a good one at all for
your real topic.
: George Reese wrote:
That language and action are related does not mean one cannot confuse
them. In fact, being related often lends itself to confusion.
Yes, guilds, clans, etc. very likely have their own secret language
and customs. That has nothing to do with what it is to be the events
their language is describing. A command interpreter is not about
being cutesy. It is about providing the user with an interface for
communicating to the mud the action that user wishes to take. The
perfect user interface involves no language whatsoever--the user
simply thinks an action and the mud understands that thought
(Wittgensteinian discussions about the relationship between language
and thought aside). Unfortunately, computers are not that advanced.
So we need to provide the user with a way to *describe* what it is
that user wants to do. How the user describes it is not important;
the mud should make every effort to be able to interpret the
description without ambiguity. Once the mud understands what it is
the user wants to do, the mud should model that action.
People who want to make 'xyzzy' matter are people who wish to make the
describing of an action one of the challenges of playing a mud.
'xyzzy' is so esoteric. Let's get down to something more tangible.
Requiring 'xyzzy' as the verb to open just this cave instead of 'say
xyzzy' or 'whisper xyzzy' (or, more important, instead of any action
that allows the user to utter the phrase where it can be heard by the
magic forces of the cave), is the same as requiring a user to say
'look at cave' instead of 'look cave' in just a single room. In
either case, the user knows exactly what they want to do, but they are
being challenged to *describe* what they want to do. That's not a
part of mudding.
Haha, I love language discussions. They get so *religious*.
This argument of object portability is a fun one. It crops up in many
languages in many forms. You're almost right here, but I think you're
confusing the linguistic instance you're dealing with.
Specifically, an action is applied to an object. It is not intrensic to
the object. Properties are intrensic to objects. An action can query or
modify a property, and an action itself can be modified by the object's
context, but the action is not a property of the object.
Let me give you a simple simple example to make my point clear:
Addition is an action. Given two objects, '4' and '5', it is nonsensical
to say that '4' knows anything about addition operator. If '4' knows
about addition, why not '5'? Can you decide which one should have the
addition method called? '4' should impose an integer context on the
addition action, but it doesn't know how that addition will be carried
out. Why is this important? Well, because you might also have two
objects '4' and 'foo', and want to add them. '4' should not have to know
about the string context to be added to a string. Also, it makes no
sense for both '4' and 'foo' to somehow be in contention for an addition
method they would both contain in your system. No, addition has to be
external to the system, so that it can resolve that the integer context
is superceded by a string context, and the product is '4foo', not
something else that would make no sense.
James
> Addition is an action. Given two objects, '4' and '5', it is nonsensical
> to say that '4' knows anything about addition operator. If '4' knows
> about addition, why not '5'? Can you decide which one should have the
> addition method called? '4' should impose an integer context on the
> addition action, but it doesn't know how that addition will be carried
> out. Why is this important? Well, because you might also have two
> objects '4' and 'foo', and want to add them. '4' should not have to know
> about the string context to be added to a string. Also, it makes no
> sense for both '4' and 'foo' to somehow be in contention for an addition
> method they would both contain in your system. No, addition has to be
> external to the system, so that it can resolve that the integer context
> is superceded by a string context, and the product is '4foo', not
> something else that would make no sense.
Hey, James, why don't you just add multimethods to LPC and solve the
problem? ;-)
Oh, yes! multimethods! Conceptually cool, but a usability nightmare!
That sounds pretty appropriate for LisPC in particular (3.2.x) :)
Seriously now, I doubt this problem will ever have a practical
solution in LPC that pleases everyone. The only reasonable conjecture
for a solution to the problem for OOP I've heard to date involves
multimethods and a smart environment, but of course, that's less
substantial than vaporware.
backtracking a bit:
> Specifically, an action is applied to an object. It is not intrensic to
> the object. Properties are intrensic to objects. An action can query or
> modify a property, and an action itself can be modified by the object's
> context, but the action is not a property of the object.
"actions are applied to objects" isn't quite right. Objects can be
acted upon, and they can act. An object's visible interface defines
the ways it can be acted upon by others. Of course, this isn't a
perfect view of the world, and it isn't even a wholly accurate view of
what's really going on in many programs. But as I suggested above, we
don't really know how to make it perfect...
> I think you have misunderstood what I have said...
Then explain it again in different words.
Anyway, I re-read the thread and my main point is to argue
> >At no point should a mud make up non-existent actions.
because it's my impression that people see 'non-existent' actions
too strictly.
[lots of examples]
> You are mixing up the concepts of language and action. If 'xyzzy' is
> the English word to describe [1], then that is what it is to xyzzy.
> Instead, you are using xyzzy to mean three completely unrelated
> things, which is an abuse of language.
Within one world, 'xyzzy'[1] of course has to mean just one thing.
It'd be nice if 'xyzzy' meant the same in every mud, but that's what
help files are for.
> If a person wants to try communicating with their eyes, they should be
> able to:
>
> > 'xyzzy I hate snow'
> You bat your eyelashes like a lunatic.
...I thought more along the lines of displaying colored points on one's
chest...
> Furthermore, all of this has been presented in terms of how you
> process user input... globally with centralized syntax or locally with
> local syntax. You are not even arguing that point :)
Global vs. local parsing? Nope, I don't argue that.
[1] 'xyzzy' used here as placeholder for invented command names.
The proper response to the command 'xyzzy' itself should be 'Nothing
happens.' or 'This is MegaMud, not Zork.'
--
Lars Duening; la...@cableinet.co.uk
George Reese <bo...@imaginary.com> wrote:
: perfect user interface involves no language whatsoever--the user
: simply thinks an action and the mud understands that thought
: (Wittgensteinian discussions about the relationship between language
: and thought aside). Unfortunately, computers are not that advanced.
They never will be. Even if they could 'read' nervous system impulses
directly, you'd still have to form those impulses in a given manner to
get a given result, and this would still be language, albeit a very
natural one. I don't know much about Wittgenstein(sp) but I know that
communication requires a medium and a signalling method(language.)
: George Reese <bo...@imaginary.com> wrote:
: : perfect user interface involves no language whatsoever--the user
: : simply thinks an action and the mud understands that thought
: : (Wittgensteinian discussions about the relationship between language
: : and thought aside). Unfortunately, computers are not that advanced.
: They never will be. Even if they could 'read' nervous system impulses
: directly, you'd still have to form those impulses in a given manner to
: get a given result, and this would still be language, albeit a very
: natural one. I don't know much about Wittgenstein(sp) but I know that
: communication requires a medium and a signalling method(language.)
Is talking out of your ass something you just can't help?
: : They never will be. Even if they could 'read' nervous system impulses
: : directly, you'd still have to form those impulses in a given manner to
: : get a given result, and this would still be language, albeit a very
: : natural one. I don't know much about Wittgenstein(sp) but I know that
: : communication requires a medium and a signalling method(language.)
: Is talking out of your ass something you just can't help?
Pot? Kettle? Black? At least what I said was _true._