It was recently observed to me that I'm spending a lot of my time
responding to others posts without making mention of my own
project(s). 'Tis true.
A preface on MUD game design:
The largest failure of MUDs is that they have generally never, and
never stabley, been able to assemble large simultaneous populations.
What is "large" in this context? I would start at 500 as still being
on the verges of small.
Raph, Sellers: Can you provide context from UOL and M59 here?
Why is this important? Large populations allow cultural and social
dymanics to form which are not possible with smaller groups. For a
viable society to form there must be something from which it can
extract itself, against which it can compare. It must form and define
the "other". Smaller populations cannot form stable societies in this
manner -- they miss the grouping imperitive and there is not enough
need or social context -- and before anyone here raises the issue of
the society formed by this list's membership, this list exists against
the greater backdrop of the MUDding field and USENET.
The below design is predisposed on the concept of a large simultaneous
(ie concurrently logged in) population. My hope in that score is that
500 will be a very small number.
Project name: MURKLE
I'll let you figure out what that is an acronym for. If its rude,
you're getting close. If its terribly irreverent you've got it. No,
I won't answer queries on it.
Murkle is of course a MUD server. At the lowest level its merely a
generic programmable network server. You could make it into quite a
nice little web server, a front-end to a database, or whatever, but
its primary purpose is to serve games, specifically virtual
environments. and to be very scalable at doing that.
In the beginning Murkle's only purpose was to act as a test bed for
teaching myself various programming concepts and techniques, and to
act as a proof-of-concept for various ideas I had for what could be
done with MUD servers and worlds. Coding started in 1985.
There have been many changes since then, in platform, implementation
language, design goals, etc.
The early designs were almost direct rip-offs of Shades. "If you
haven't died in Shades, you haven't lived." I still consider Shades
the most utterly playable of all the MUDs, bar none. Unsurprisingly
it also happens to fit Dr Cat's entry requirements and "fun" criteria.
I've since come to the conclusion that the best homage I can pay to
Shades is to honour it, not copy it. I certainly can't pretend to
best it. Shades is architectually spare, lean to the point of
anorexia. There's nothing wasted, or extra in there.
"The most beautiful things in the world are those from which all
excess weight has been removed." -- Henry Ford
Technically it is of coursea hodge-podge, but that barely if at all
impacts playability.
Note that in what follows the distinction between the server and the
game world is fuzzy. The server contains no game or game-world code.
It merely provides a tool set which *could* be used to present a
game-world, and merely happens to be used for a very particular form
of game in this instance.
My current plans are more ambitious than the early Shades re-cap.
Murkle is intended to serve worlds where the players can create
virtual realities, and then enforce those realities on each other.
"Enjoin" might be a better word than "enforce" in the above sentence,
but it also loses much of the possibility inherent in the system. The
enforcement can of course be co-operative, concensual, or in the
nature of conquest or virtual rape. The only difference between them
at the server or world level is that of interpretation and viewpoint.
What does it mean to create a reality? Free user programming where
users can create and program objects, castles, worlds, animals, magic
etc, but all limited by base physical model restrictions of the game
world. The server and the base game world working together as
*system* preserves data security and logical consistency (of a very
perverse form) of the resultant presented game world.
Yes, the players are truly gods of near infinitely varied and
ranging power -- only bound by chains and restrictions which even they
cannot shift.
At one level the game is a challenge and a race for the individual
conquest and control of resources, at another an acknowledgment that
the whole is greater than the sum of its parts (an organisation of
mice can master any dragon if they work well enough).
However realities also have histories. Commonly only the human, and
especially the emotive aspects of history are concetrated upon (that's
what sells newspapers). Murkle attempts to do one better than that:
time travel.
In essence this is logging, with the difference that this time
everything is logged, and those logs are available to everybody. This
is transparency and exposure to the N'th degree. The base model is
that any player can select an object or location and travel "back in
time" to see exactly what happened to that object, or at that
location, exactly as if he had been there at that past time.
Unsurprisingly it is the technical aspects of this bit that are
proving the most challenging, and currently have me stymied. A brief
examination of the bandwidth concerns should indicate why.
Other interesting aspects of the game world:
Body stealing, multi-body characters: This has been discussed here
at length, so I won't recap much. Briefly, a single character can
control multiple bodies ("character" is almost equal to "soul", but
without much of the connotative baggage). Some bodies are swarm
bodies (like a swarm of bees). Additionally characters can steal
bodies from mobiles and other characters, adding to the total set of
bodies controlled by that character and gaining the advantages imbued
in that body.
High magic: The world runs on a zero-sum particle based economy,
where magic (mana) is one of the particle types, and (loosely)
operates on the faucet-drain principle. Any creation results in two
products, each identical except for sign. Such matching pairs are
mutually attractive and self-destruct when they do. The cost of
creation is proportional to the square of the current resouces'
deviation from zero.
Additionally there are mana particle faucets and drains in the
world, with a careful mechanical model applied (like particles of
opposite sign attract inversely proportional to the square of the
seperating distance, like particles of similar sig repell when at
rest, but attract proportional the square of their absolute velocity
and the distance seperating. As such mana particles tend to move in
packs and waves, and at speed).
Outside of this the magic system (at the user presentation level)
attempts to be an ambitious mutation of Mage2Mage with a bit of
Bartle's Waving Hands thrown in (Mage2Mage to add the aggregate and
scripting ability, WavingHands for the algebra, with the Mage2Mage
resultant spell names being the main public face).
The result is a split level scripting language, with a very very
simple magical scripting language at the surface (equivalent to DOS
batch files), a full Mage2Mage style next down, and the internal
server programming language (see below) under that.
Object destruction: Objects (generally, and especially magical
objects) consume resources during their life. If they are unable to
satisfy their hungers they self-destruct.
Private namespaces: There are no global namespaces. There is no WHO
list or command. There is no seeing other's names floating above
their heads when first meeting them. Names are assigned by the
individual character, private to that characters, and bear no relation
to the preferred or requested name of the object or character in
question.
Universe seperation: The game-world is fractured into three:
physical, spiritual, and character. All exist in parallel, and any
character has a presence in all simultaneously. While the character
level is strictly for OOC concerns (it has no relevance to the other
universes, only to the human player), attacks, conversations,
coordination, etc can occur seperately or in concert across the
physical or spiritual worlds.
Its worth noting that the physical and spiritual universes are
otherwise disjoint. While the character, and all other characters
exist in both, there is no geographic relationship between, say,
position in the physical world, and position in the spiritual world.
Similarly the namespaces do not map between the universes. A name
assigned to something in the physical universe binds to that physical
object, and in the case of a body, not to the character controlling
that body. Thus it is left to the player to resolve spiritual
identity against physical presence (as well as character identity).
Given the fact that body-stealing is anonymous (exactly who is
controlling any given body at any instant is difficult to determine),
this can and will make for identity problems.
Combat: Yes, I have perma-death. Combat is intended to be fatal,
messy, and highly risky even to the experts. The underdog is expected
to win or do serious damage an appreciable percentage of the time.
Currently I have no working satisfactory design for the combat model.
Whatever combat model I end up with must be able to commonly support
fights ala:
--<cut>--
UggUgg slashes at you with his Sword of Instant Beheading
and minor discomfort!
> cast soakhole on uggugg
You cast the dreaded mana eater soakhole on UggUgg!
UggUgg sneezes and buries your in green snot!
Your armour suddenly dissappears!
Your spell of magical summon protection fails!
Your spell of magical sight fails!
UggUgg's Nose Ring of Killer Snot dissappears!
UggUgg's Belt of Gas Containment dissappears! Phew!
UggUgg's dagger of wart removal dissappears!
> cast create mana
You create 5,000 units of mana!
Your mana stores are now empty.
>cast $my_protections
You are now magically potected from summons.
You can now see all magically hidden objects.
UggUgg thows a blade of painful castration at you!
> jump!
You leap mightily.
The blade misses! You are still a baritone.
> attack uggugg with spear
You ram UggUgg through with the spear of Icy Death!
UggUgg now has the flu and looks a bit watery about the eyes.
UggUgg picks up a rock.
UggUgg bashs you with a rock! Ouch! That hurt!
> throw TC at uggugg
You throw the charmed trash collector at UggUgg.
The TC englobes UggUgg!
UggUgg gives you the Sword of Instant Beheading and minor
discomfort.
UggUgg gives you the Boots of Mighty Chilblains,
UggUgg gives you the Goggles of Big Farts.
UggUgg gives you Super Nose Hair Puller.
The TC has eaten everything UggUgg was carrying! Yech!
UggUgg is naked!
Your spell of magical summon protection fails!
Your spell of magical sight fails!
Your spell of magical tummy tuck fails!
Your spell of power voice fails!
Your spell of land control fails!
Your spell of bowel control fails!
Your spell of toe cheese protection fails!
> stat spells
You have no spells.
> stat mana
There is no mana here.
> strangle uggugg
You wrap your hands about UggUgg's neck and begin to squeeze!
UggUgg prays to the Great God GooGoo!
GooGoo mana blesses the area!
There is a LOT of mana here! You skin prickles!
> i
You have a mana shielding sack
> l in sack
There are 5,000,000 TC spores in the sack.
>empty sack on UggUgg
The spores eat all the mana!
There are 5,000,000 TC's here! Wow.
All the mana is gone!
...
--<cut>--
Unstable feedback systems: I'm a fan of unstable positive feedback
systems for internal game systems and ecology simulators. I'm also
conviced that very complex and interesting systems can be built from
the interactions between very simple and internally unstable systems.
I use this model a lot. The result is an often chaotic and volatile
world. Good examples are the Trash Collectors and the Orc
Breeder/Fighter/Nobles:
--<cut>--
Essentially the TC's would wander the land in slightly overwhelming
numbers, finding and collecting any loose odd objects that happen to
be laying about (eg torches, dropped EQ, weapons, newly programmed and
abandoned user objects etc). How the TC's handle that junk comes in a
number of flavours:
-- If the object is small they pick it up and continue on.
-- If a larger object they englobe the object and decay it and any
carried objects at an accellerated pace. Once the object(s) have
destructed, the TC will move on, having grown slightly. This process
produces considerable mana.
-- If the object is too large to englobe, it will suck its own thumb
and grow until it is large enough to englobe the object(s). Once the
object(s) have destructed, the TC will split into multiple new TC's.
This process consumes considerable mana. Should there be insufficient
local mana, the TC consumes the mana, dies, and scatters a spore for
each unborn TC.
-- If the object is a TC corpse, the TC will eat it and grow by a
factor smaller than the size of the TC eaten.
-- If the object is another TC, a small percentage of the time one TC
will eat the other, and both will die, producing four TC spores in the
process.
-- If the object is in some way special/wanted the TC picks up the
object, drops anything else it is carrying, and attempts to convey it
back to a (special characteristic specific) dumping group. (This
makes TC's preferred hunting targets for players)
-- The TC will spoof the object found, and disappear. The action of
the spoof is to speed the delay of the object, and to drop a TC spore
(that will grown into a new TC) into a percentage of rooms it passes
thru which don't contain TC's or TC spores. In the mean time the base
object continues to behave as normal until it destructs.
-- If the object is a TC spore, the TC will eat the spore and
increment the count of the number of spores it will release when it
dies.
Once a TC has grown past a specified size, or if it successfully
consumes more than X objects, it will split into two otherwise
identical TC's. A TC in normal operation (moving, whatever),
continually and slowly produces mana. However, very high mana levels
are quickly fatal to TC's _unless_ they find an object to englobe.
TC's have a set (short) lifespan. They are born from spores, grow on
objects found, move quickly, and produce spores when they die.
As far as resets are concerned, should a TC find an object with a
reset() method, with a set RESET_ME flag, the TC will call the reset()
method a percentage of the time (percentage depending on age of
requested reset, plus object-specific fudge factor).
A TC spore will consume all mana in its area. The rate of development
of a TC spore is porportional to the rate of mana consumption. Should
their be no mana, the spore will lay dormant.
--<cut>--
Note: The above TC model is far too unstable. The currently
implemented version is considerably moderated.
and for the Orc Breeder/Fighter/Nobles:
--<cut>--
The OrcCaves:
-- There is a set of underground caves and tunnels.
-- A certain (small) set of those caves have no entrances, and cannot
be teleported to.
-- Such caves contain "breeders".
-- Breeders produce new baby Orcs at a rate proportional to the
current Orc population.
-- New Orcs "appear" in the accessable caverns.
-- Baby Orcs produced fall into one of four types: grunts, new
breeders, fighters, and nobles.
-- The ration of the types produced is based on the current general
mortality rate, mortality rate in the caverns, total population
(crowding) etc.
-- An Orc of any type can and will mutate into an Orc of the next
higher or lower type should the current environment request i. (eg
caverns under attack, breeders start turning into fighters to defend
their spawn).
-- Individuals of any type will tend to group with individuals of the
same type, breeders with breeders, fighters with fighters, nobles with
nobles.
-- If nothing else is around, another type is better than nothing.
-- A single noble will preferentially group with a sufficiently large
group of fighters. Should their already be a noble in residence, the
nobles will fight for control (one dies). (And thus there were clans)
-- A noble/fighter group will generally ignore all other groups --
except for noble-less fighter groups, which will attempt to join it.
-- Noble groups are unstable, and will tend to split up every so
often.
-- One noble per cavern will become a "King".
-- If the King dies, then noble groups will congregate and mutually
annihilate until a surviving Orc is tagged as King.
Result: Normally the Orcs breed like rabbits. Once the population
builds up enough to get crowded they start producting more fighters.
Fighters are wanderers, and tend to both group and attack a lot
(slight preference for grouping).
Thusly, left alone the Orcs wil overrun their caverns and start
boiling out upon the outside land with hordes of nasty unpleasant
types that chew on the wrong ends of fair maidens.
Should such a doughty band find a new set of caverns, they may decay
to breeders, with their keys set to the new cavern system. (ie a new
colony which _can_ be eradicated))
Should the caverns in any state be invaded by slaughtering players or
mobiles, the breeders will start producing more and more fighters to
repell the invasion.
Etc.
A simple enough system that provokes all sorts of interesting patterns.
Take the same base and extend it with a few twists and extra
behaviours and now you have mining dwarves, elves in the forest, the
human King's castle and outlieing farms etc. Rool a bunch of theese
all into a shared land, and you start getting an active animated
universe which runs itself.
--<cut>--
Rank system: This is mostly a variation of the influence trees
concept, but with my Rank Points idea mixed in:
--<cut>--
A simple model:
Player characters can award each other "rank points" (RP).
Each player character is given (free) 1RP per day.
A player character with sufficient RPs can be automagically
promoted to a high status position.
Maintaining a high status position costs a player character
XXX RPs per day (automatic debit).
A player caharacter can promote other player characters to other
(lower) status positions.
Such a promotion costs the appointing player a one time cost of
YYY RPs.
The promoted player has his own daily RP cost for his position.
Should the high ranking player lose his position thru lack of
RP's, all appointees will also lose their position as it they
had failed to acquire enough RPs to maintain their own position.
A junior ranked player can still appoint sub-juniours with the
same mapping as above.
Ergo: To survive a high ranking player must persaude many many other
players to give him their daily RPs so he can keep his position. A
high ranking player may appoint juniours who are then also in the same
position, but can be required to funnel some portion of their
collections to their appointer.
--<cut>--
An extension to the above is that Rank Points will be initially
"unflavoured". A character can then however "flavour" his RP's as per
any of the selected flavours of a society of which he is a member
(player-created society and geogrpahically defined flavours). The
expectation is that RP's will form a political currency.
Justice System: I've recently (prompted by a telephone coversation
with Raph), to implement justice code. There will be several disjoint
parts in that the definition and scoping of a crime will be
greographically controlled and defined by each society within the
game, and the magicall summoning etc of the below will only occur if
the target is within the geographic reach of the titular society.
However the basis will be something along the line of:
--<cut>--
Were I to do a legal system I suspect it would be something as
follows:
"Crimes" would be deliberately vaguely defined.
The system would erraticly and unpredictably cycle between
ultra-strict enforcement and ultra-relaxed enforcement of crime
detection.
An increased percentage of guilty verdicts would tend to sway the
system towards stricter enforcement.
Users can report crimes to the system.
Depending on the above, not all reports would be acted upon.
The system would internally detect crimes. This would take place
via mobiles or other similar coded systems viewing a crime in progress
or the results of a crime.
Again, not all would be acted upon.
All crimes would be recorded and tagged against the assumed perp (DB
rollbacks are wonderful).
Upon a crime handling being started, the assumed perpetrator would
be charged with all the unresolved and unhandled crimes against his
name.
Crime handling would be specific to various societies.
Societies would be user defined, but system administered (membership
primarily).
Upon a criminal handling commencing, a random selection of the
currently logged in members of the society in question would be tagged
as jurors.
The jurors would be told that the system will teleport them to a
court room at a pre-defined time (30 RL mins later) in the future to
stand judgement.
The juror list is openly published at the same time.
The accused is informed that he is accused and when the trial will
be.
Jurors may sell or transfer their juror position to any other
society member, including the accused, prior to the trial.
Death or non-attendance of all jurors prior to a trial defaults to a
not-guilty verdict.
The case of all the jurors being the accused defaults to a
non-guilty verdict.
Non-attending jurors are tagged with the crime of non-attendance,
and may or may not be called to stand trial for that crime.
The courtroom consists of a room containing four areas:
1) A exitless pen which contains the accused, suitably immobilised
(ie he has no control over his character other than speech).
2) An open pen marked "Guilty".
3) An open pen marked "Innocent".
4) A free space surrounding the guilty/innocent pens.
The guilty and innocent pens each contain a single button marked,
"Verdict".
The courtroom has no entrances and no exits. There is no possiblity
to view an in-progress court case unless one of the jurors brings in a
remote camera object.
Shortly before the trial commences all jurors are so warned.
Upon the trial commencement all jurors are teleported to the open
free area of the courtroom, and the accused is immobilised and put in
the pen.
Jurors are teleported with everything they happen to be carrying at
that time.
There are no controls and no supervision of what happens in the
courtroom.
Crimes in the courtroom are not recorded.
The verdict is determined by all surviving jurors gathering in a
single pen, guilty or innocent, and the verdict button being pushed.
If the verdict is innocent, the accused is freed, and the jurors
returned to the locations they were summoned from. Any dead/injured
jurors remain dead/injured etc. EQ is left where it was at the
instant the button was pushed.
Any EQ left in the courtroom is given to the accused.
If the verdict is guilty the innocent pen dissappears, and the guilt
pen is renamed "penalised". The accused's EQ is made available to the
jurors to do with as they wish (ie everything he is carrying or in a
location he controls). If one of the crimes is deemed suitably
serious, the accused stats are made available to the jurors for
editing as they wish.
Guilty processing terminates when all surviving jurors enter the
penalised pen and the button is pressed.
Any EQ left in the courtroom when the button is pressed and all
jurors teleported back is given to the accused.
............................................
It should be amusing at the least, wonderfully chaotic at best, and
intensely unfair and primitive at its ideal scene.
--<cut>--
Technically the game is implemented as a persistant store (cf Texas
Persistant Store, Persist++, Object Store, Arjuna) with an internal
MUD programming language. The internal programming language is
deliberately simplistic, borrows most heavily from C and Python, and
is message passing and exception based. The language is not
inherently object oriented -- objects and the object model is treated
as structural at a level largely outside the language. Language is
used to codify behaviour inside objects, not to define objects. In
this manner the internal language is somewhat similar to ColdC, MOO
etc.
The guiding principle for the security and internal model is:
Any feature must be able to be implemented on any object without
requiring source access to any other objects.
Please take a moment to think about that. Its quite a bit more
incisive than many seem to notice, and is the primary source of the
Spoofs and Watchers concept (see the archives and search for the
Castle Krak, the Sceptre, and the the Elven Forest scenario, as well
as the Great God GooGoo, Demon Wroth, magic bag etc scenario which
were the test cases for the models.)
Internally the server is massively threaded. Resting state has
something like 50 threads, with more added as activity grows
(non-linearly of course!). The internal structure is that of
Database/Dispatchor/Executor, where the DB is responsible for
maintaining data integrity and access, the Dispatchor for timing of
processing (in parallel), and the Executor the execution and
(re-)scheduling of processes across a thread pool. The data model is
the by now famous/classical lockless C&C model. Please see the list
archives for details.
Of course there is more, but it is Friday, I am tired, and the wife
and kids are at home and I'm not...
--
J C Lawrence Internet: claw@null.net
(Contractor) Internet: coder@ibm.net
---------(*) Internet: claw@under.engr.sgi.com
...Honourary Member of Clan McFud -- Teamer's Avenging Monolith...
--
MUD-Dev: Advancing an unrealised future.