[MUD-Dev] common server design

Chris Gray cg at ami-cg.GraySage.Edmonton.AB.CA
Sun Jun 22 11:35:21 New Zealand Standard Time 1997


[Caliban:]

:A lot of effort appears to be directed at locating the good algorithms
:and internal representations of the object model, rather than the
:high-level things which make a good game.

That's a result of designers wanting to push the limits of what a server
is capable of supporting. The straightforward approaches to some things
won't work because they are too horrendously expensive, or require a near
infinite amount of special-purpose code. So, designers look for ways to
provide desired results in a practical way, and look to very general
purpose structures which can, hopefully, automatically handle most of
the special cases that were not specifically addressed. The facilities
in existing servers are deemed to be entirely inadequate for this, hence
the discussion of new servers and techniques.

:					   What I'm looking at here is
:the general idea that people prefer certain things; we never seem to
:discuss the actual end-result, but the idea of how to represent a
:specific effect. I think in any system, there are several things that
:need to be handled, but rather than looking around and going "Let's use
:the socket code from Diku and the builder code from Mordor and the
:commands from TinyMUX and the database structure from Cold" -- which of
:course would be like using all the leftovers you have that aren't moldy
:to make a casserole -- let's look at what *makes* these things good (and
:I'm not saying any of the above are necessarily the best examples
:available), and see if we can't come up with something that would be as
:good or better.

First, that's a very uninteresting thing to do. Second, it wouldn't
answer any of the problems I mention above. And third, it would be a
lot of unpleasant drudgework, for a very questionable final result. I
wouldn't do it unless paid a considerable amount of money, mostly because
I have my own programming standards, and from what I've seen, very little
of that code would meet my standards, and my reaction would be to pick it
over for ideas, and then throw it away. My gut feeling tells me that most
of the server writers on this list would have a similar reaction, although
the various programming standards would vary *very* widely, especially
from mine :-)

:No, no, no, that's not what I'm proposing! I'm proposing that we look at
:what works, and use it as a guide -- with the aim being to take the good
:parts, see why they're good, and try to put them together into something
:better. There will of course be modifications, because there's nothing
:out there that's *perfect*; more to the point, what I'm looking at is
:the possibility that if we assume the people using the server know
:absolutely nothing about anything, how can we best provide them with
:something intuitive and easy to use? This means that none of the admins,
:imms, imps, gods, wizards, or whatever you call them have any
:preconception about how the MUD ought to work; let's assume they would
:spend a lot of time posting messages to mailing lists asking how to do
:very very simple things, and try to answer those questions in the
:documentation and help. Let's try to make a server that takes next to no
:effort to install, run, and use, and free up these people to actually
:improve the game itself by adding new spells and classes and races and
:let them do all of it without having to recompile or reimplement
:anything at all.

I agree with your end goals, but I don't think your method would work, in
practice. I think a better approach would be to look over the existing
servers (and scenarios/worlds/mudlibs) to determine what is deemed to be
good in them, and use that infomation to guide the building of new servers
and scenarios. Actual code re-use isn't likely to work very well. I can't
imagine any of it being able to plug into my server, for example. Something
we could do, is perhaps determine what is hard about writing a server, and
provide example code for doing that. Unfortunately, I haven't worked on my
server for quite a while (most recent stuff has been with the client), but
here is what I remember about it:

    - the database code took a lot of work, and had some nasty bugs, one
	of which took months to identify and fix. Much of that was because
	of the nature of database I decided to use.
    - the programming language generally was easy to do, but that could be
	because I've done that sort of thing several times before. There
	were a few tricky cases of getting reference counts to work right
	with temporary functions (created dynamically during the run of
	an input command, and deleted as part of that same execution).
	Those difficulties were likely fairly specific to my design.
    - getting all the caching I wanted to work properly took a while, but
	there was nothing earth-shattering about it.
    - I have a *lot* of built-in functions, and getting them all working
	right took a lot of work, but clearly that effort won't port to
	any other server.
    - getting the parsing tools working the way I wanted took a lot of work,
	but they are quite different from the parsing of anything else I've
	seen out there, certainly based on the discussions in this group.
	So, that effort would be difficult to share.
    - my current server doesn't deal with sockets directly - it just uses
	AmigaOS messages to talk with agent programs, some of which do use
	sockets, others of which do direct serial port connections. So, that
	code isn't likely to be of use to anyone else, even though it took
	a lot of work to get my asynchronous bi-directional reliable serial
	protocol to work as desired.
    - I have a lot of code dealing with the co-ordination of the server and
	the custom clients in regards to what "effects" (graphics, sound,
	etc.) are cached in the various clients. That's irrelevant to most
	other servers, if not all.
	
:If we operate from the assumption that no one is going to need to bring
:a database or area in from any other server, and leave any desired
:conversion utilities to standalone programs designed by people who need
:to do that sort of thing... that could free up our ability to define
:what really needs to be in the server. If we work from the idea of
:making the player happy, rather than the builder and the programmer,
:then we could possibly come out of this with something really great
:that's long overdue.

The basic representations and standards are going to vary a lot between
servers, so it would be difficult to convert anything other than the most
basic of properties. Certainly you could bring over the interconnections
of rooms, their descriptions and contents, along with object descriptions.
But, are you planning on automatically translating the chicken scratches
that substitute for a programming language in, say, TinyMUSH? Not to
mention MUF code! I'm aware that there are some conventions for inter-MUD
motion (e.g. Marcus Ranum's Unter), but my understanding is that only
very basic stuff can be moved from system to system, and that requires
advance planning and co-ordination. With a lot of effort, those of us with
fully programmable servers could probably write code to bring "area files"
into our worlds, but I'm not convinced it would be worth it.

:It's not the question of technical versus nontechnical; it's more a
:question of directed effort. The server developer is obviously concerned
:more with the code that runs the server than he is with the command set
:it results in. We end up with an interface and command structure that
:happens almost as a side effect.

I disagree. I was quite concerned with the commands that would be available.
The parsing stuff in my server was one of the first things I designed. In
my (humble?) opinion, stuff like the syntactic mess that passes for commands
in Tiny's, and things modelled on them (even some in MOO's!) should never
have happened - its just too unfriendly to a non computer person. However,
my gut can certainly see the attraction of a universe which is as dynamic
and changeable as those provided by the Tiny's and MOO. That's why I spent
several months adding my "builder commands" to my scenario (note that they
are in the scenario, and not the server), so that those who want to, can
type icky commands like:

    @o new mytable newvase vase;large,glass

But, I made sure that those not so inclined never have to worry about
funny syntaxes.

:But the question is whether you're allowing new people who WOULD like to
:play these same kinds of games an appropriate opportunity to learn the
:game. No game is going to make *everyone* happy, but to create an
:interface targeted at people with a specific area of knowledge can
:unfairly lock out some very promising players.

I agree. However, when people are writing servers for fun, they are more
likely to *want* to spend time on what they consider interesting. Making
their system into a real live usable system for the masses may not be of
much interest. It so happens it is for me, and (hopefully!) for the
commercial folks on the list, but I doubt it is for all.

:						A related problem area is
:the all-too-common lack of documentation in servers; as should be
:evident in this post, I have four major problems with the majority of
:servers available.
:
:	1. Lack of documentation.

Yep. The other problem is the quality of whatever documentation exists.
I can work around poor grammar and overall structure, but when the stuff
is actually wrong, with examples that won't work...

:	2. Nonintuitive command structure.

What particular commands are you thinking of here? Things like "look rock"
are not terribly hard, I hope. Certainly any command that requires the
user to be aware of special syntax characters should be stamped out, except
in rare cases. Paging someone should *not* require an '=' sign!

:	3. Complex and difficult building interface.

It isn't hard to make simple building simple. Its the more complicated
stuff that is ... more complicated. You can add a zillion special cases
that try to handle everything you can think of, but you're going to end
up with a mess that is very hard to expand. In the end, I think interesting
building is going to require that the builder do some kind of programming.
You want the builder to be able to define new properties, and manipulate
them in whatever way is appropriate for the effect they are trying to
achieve. You want them to be able to cause delayed and repeating actions.
You want them to be able to save arbitrary state. Etc.

:	4. Lack of system flexibility.

You definitely want flexibility. There are many ways to achieve it however.
This is where arguments about things like single versus multiple inheritance
come in. Similar for strong versus weak typing in the server language.

:What all of this comes down to, in my opinion, is a lack of proper
:planning and design. I think what happens is that the developer has a
:really cool idea, and just jumps in and starts writing code. (I've been
:guilty of this myself.) When he hits a snag, he ducks and weaves around
:the problem. At the end of the process, there's this huge mess of code
:that could have been a lot better; and it's so tightly integrated, the
:problems are now difficult if not impossible to fix.

That can certainly happen. It is often related to the experience of the
programmer - experienced people have a better intuition of when it is
time to step back and redo things. They also have a better intuition of
how things ought to be done in the first place. That's what experience
is all about.

:It's been mentioned on this list before that the planning phase and the
:documentation phase just aren't fun. I think that's a good point, but I
:also think that we have a large enough community that we could possibly
:get the planning done in a sort of open forum, even before the code is
:actually being written. If we create something that has clear and
:compelling advantages, then people will *want* to write to the standard,
:and it won't be a question of my project and his project. If we build a
:set of 'desirable' server qualities, and put forth a little work here
:and there toward implementing those qualities, we can end up with a
:project that really doesn't *belong* to anyone. It would be something
:that is a property of the community, like it should be. It would reflect
:the wants, needs, and opinions of the people who are actually expected
:to use it.

This is an admirable goal, but it will be difficult to pull off. The folks
involved in commercial projects would find it hard to get involved, both
because their time is not all their own, and because they would have to
be very careful not to let out stuff they aren't supposed to. Others who
are already deep into their own projects could be extremely reluctant to
abandon those projects (understandably so!). Working in parallel on two
different, but similar, projects can be very confusing. If there are
folks on this list that aren't deep into their own stuff, and interested
in doing this, then I say "go for it!". Those of us who can't directly
contribute in terms of programming, etc., are likely to be interested
in watching and offering comments and suggestions.

:I think complexity is something we should be trying to minimise. The
:more complicated the game gets, the harder it is to add a new feature or
:enhance an existing one.

>From what I've seen on this list, some folks, as players, *want* complexity
in the game they play. Can that complexity be done without some similar
complexity in the server? As someone with 25+ years of programming
experience, I believe that a good, efficient, general server *is* a
complex piece of code. Certainly it is good to do some advanced planning
and design, but that is just a normal part of good programming. (I have
to be honest here, however, and admit that conscious design is something
that I don't recall ever doing - I let my subconscious do that sort of
thing for me, and I'm willing to redo lots of stuff if it is wrong.)

:			  Tight integration for speed and power is a good
:thing until you want to build on it; there's no place to slot your
:changes and concepts in, and when you try to shift things around, you
:break things that you thought weren't even related. One of the things
:I've been looking at is trying to separate the four sections of the
:server I mentioned previously on this list; basically, setting them up
:so there is a very simple API in between them and anything that conforms
:to that API can replace a section. Sort of like FOSSIL drivers for
:serial interfaces; a FOSSIL driver abstracted the serial communications
:required for a program into a simple interrupt-driven API which nearly
:anyone could support. Any DOS programmer could learn the API in a matter
:of minutes, and add serial support to an application with a few hours of
:work.

Again, I'm not sure how this can be done in a practical way. Scratching
my head a bit, I'll suggest a few obvious interface points... hmm -
rather than try to remember and invent, I'll just cheat and ram in some
parts of the external declarations for my system (much easier for me!):

Database:
    log(*char message)void,
    logX(*char m1; ulong n; *char m2)void,
    logN(*char m1; ulong n; *char m2)void,
    logXNL(*char m1; ulong n)void,
    log2NL(*char m1, m2)void,
    ioShutDown(*char message)void,
    ioInitialize(*char path; ulong cacheSize)bool,
    ioRead(ulong key)arbptr,
    ioCreate(uint typ; arbptr p; uint len)ulong,
    ioDirty(ulong key)void,
    ioExpand(ulong key; uint newLen)arbptr,
    ioShrink(ulong key; uint newLen)void,
    ioReplace(ulong key; arbptr p; uint newLen)void,
    ioFlush(bool doIndex)void,
    ioTerminate()void,
    ioDelete(ulong key)void,
    ioWrite(ulong key)void,

Interpreter: (the count is the parameter count to pass to the code)
    doProc0(ulong key)ulong,
    doProc0Top(ulong key)ulong,
    doProc1(ulong key; *char par1)ulong,
    doProc1Top(ulong key; *char par1)ulong,
    doProc2(ulong key; *char par1, par2)ulong,
    doProc2Top(ulong key; *char par1, par2)ulong,
    doProc3(ulong key; *char par1, par2, par3)ulong,
    doProc3Top(ulong key; *char par1, par2, par3)ulong,

Nope, this isn't working. Too many of the key routines (e.g. the parser)
are not exported to other server code, since it doesn't use them - they
are only exported as builtin functions to MUD code.

Looking at the few hundred routines exported across pieces of my server,
I'd say that its not a good example. :-)

:I think we could do the same general thing with a MUD, allowing someone
:to easily plug a new command set or builder interface or programming
:language or server core into the game. In other words, we could make it
:modular, with any and all of the modules interchangeable within their
:own function set. Working to this sort of standard would allow us to
:write whatever weird and wonderful things we want, with the assurance
:that as long as it conforms to the API it's going to work well with
:other pieces.

Lets just say I'm quite sceptical. I'm interested in seeing this sort
of thing tried, mostly to see how far it can be taken, but in real life,
something of this complexity is going to grow some warts.

--
Chris Gray   cg at ami-cg.GraySage.Edmonton.AB.CA



More information about the MUD-Dev mailing list