28 Apr, 2014, hitsuzen wrote in the 1st comment:
Votes: 0
Hi,

I've played around with CoffeeMud for a little bit, made a basic world, modified the code some, etc. But I'm not so sure it's the right codebase for what I want to make. It's got a log of garbage and baggage, especially for creating new races and player skills. It also doesn't feel very object-oriented, at least from playing with its internal object-creator, but then again, I don't have a lot to compare it to… And I didn't get too familiar with it.

Anyway….

I'm inclined to make a "proper" World of Darkness MUD. As you may or may not be aware, there are a couple WoD MUDs out there, but they are basically just chatrooms. Players will congregate in OOC rooms and organize sterile RP in the small static city-world. I want to create something that is more like a happy union between 'traditional' roleplaying and cRPGs/Roguelikes. I'm talking about a game where players are motivated to explore the game world, to comb over every nook and cranny, and maybe make some small corner of the world their home. Players can amass wealth and status by doing things for AI-controlled agencies, but at the same time, roleplay is encouraged (and not brainless rat-farming).

I'm looking for a platform which has a reputation for not being a hassle to develop and world build for. CoffeeMUD's HTML-based world creator thing was pretty nice (it would have been difficult to build a world purely using raw XML files I think), though I can manage with something more low level I think if there are benefits to it. I'm looking for a codebase which can accommodate a lot shenanigans - I mean, I'm not exactly looking for vehicle-support or anything really ridiculous, but I'd like players to be able to modify the world, start businesses and build hangouts as well as leave cryptic marks on the world (like create their own magical artifacts). The codebase shouldn't make it too hard for me to write some WoD-inspired active/passive skills, as well as determine each of the supernatural races and their specialties.

What sounds like a good codebase for something like this? What language it's in or what OS the server requires doesn't really matter.
01 May, 2014, Nathan wrote in the 2nd comment:
Votes: 0
I'm not sure what that would be. Plenty of games/codebases have some kind of online creation system, but most are inside the game not outside and can take getting used to. It would be fair to say that almost any mud server has it's own variety of baggage. If you could expand on specific hassles that you are bothered by that would help. You should also keep in mind that many games subdivide the world into rooms and/or areas rather than say an open world sort of think like modern, graphical games have (see Skyrim, Minecraft, etc).

I think CoffeeMUD is somewhat unique in having a substantial web-based game administration interface

For any codebase you are going to have to deal with certain quirks of it's design and the thought that went into it. You probably want to stay largely away from Diku and Circle as codebases and any derivatives of them which will significantly limit your options in my opinion. They tend to have hardcoded stuff for skills/classes/races/etc which will mean you'll spend a lot of time ripping out existing code and writing your own to suit your needs. If you're willing to put a ton of work in, the LPMud family (http://en.wikipedia.org/wiki/LPMud) apparently has a lot of potential, but as to whether there is a mudlib that will work for you out of the box I don't really know.

You should check out the following and see if they are anything like what you're after:

Dead Souls (http://dead-souls.net/) – an LPMUD driver and mudlib (at least I think it's both) [C/LPC]
Evennia (http://www.evennia.com/) – A custom codebase (i.e. not directly derived from a previous one afaik), the main website isn't working when I just checked, so go look at the github repository for it (https://github.com/evennia/evennia) [Python]

P.S.
You're probably in for some not insignificant coding regardless of what you end up with, it's just a question of whether you have to modify the main code or if you can modify parts of it without messing with the primary functionality.

P.P.S
According to these results -> http://mudstats.com/Genre/WorldofDarknes... at least one of them is using some kind of variant of the GodWars codebase, so perhaps it's worth looking at even though it is a Diku/Merc derivative (or at least that's how it's categorized in the code section here).
01 May, 2014, quixadhal wrote in the 3rd comment:
Votes: 0
Rather than trying to find a codebase that has lots of built-in stuff, you'll have more luck picking a codebase you like, reading the code to understand the world file format, and writing (or adapting) an editor to use it.

My old MUD is a DikuMUD which predates OLC. We built the world (4500 rooms) using graph paper and a text editor (vi tinyworld.wld). At one point, there was some interest in moving to an LPMUD for the far more flexible system. In an LPMUD, everything is an object described via LPC code, while a DikuMUD uses a data template format, and all code is in the server.

It wasn't super-difficult to write a converter program to take the DikuMUD world files and emite LPC room code. I never fully finished the project, because the team lost interest and people drifted off… but the basic world was done and functional.

That's why I would suggest finding a codebase that you like first, since finding ways to make world building easier is just a matter of learning your codebase and writing some code. It's not hard, it's just a lot of tedius work to get all the format details right. Picking a codebase that has neat OLC, but that makes you want to change half the systems is a LOT more work in the long run.
02 May, 2014, hitsuzen wrote in the 4th comment:
Votes: 0
Thanks for your feedback.

I guess I can't afford to be too picky, there aren't too many mud engines around. I'll examine your suggestions, so thanks for offering them up.

Doing rooms on graph paper sounds really difficult, don't know how you stayed sane with a method like that - though maybe I'm just lazy.
02 May, 2014, Ssolvarain wrote in the 5th comment:
Votes: 0
It really does suck to work with only a text editor.
02 May, 2014, quixadhal wrote in the 6th comment:
Votes: 0
It's not so bad with an LPMUD. A DikuMUD was horrible, because the entire world was in a single giant file, and the format is obscure and not well documented…. for example:

#3001
Griffin's Tale~
The warm candlelight emanates a soft glow throughout this chamber revealing
the many tables and chairs that fill this large congregational. Near the
southern wall sits a longer table that must serve as the bar, several bottles
sit upon it. There are a few pictures near a fireplace which glow dimly,
only adding to the simple elegance of this Inn. Just past a large picture
stands a arch which seems to lead into a back room which is deathly silent.
A door leads to the west while to the east lies an archway opening into a
long hall with many doors lining it.
~
30 124 1
D1
A sign over the entrance reads, "Inn, bread and brothel".
~
archway~
0 -1 3008
D2
A sign over the archway reads, "Quests".
~
~
0 -1 3038
D3
A door made of fine ironwood.
~
door~
1 -1 3000
S


The rough equivalent in LPC would be:

// Automated conversion of WileyMUD by Quixadhal
// Original: WileyMUD III, Room [#3001]
// Target: Dead Souls 3.6, /domains/Shylar_30/rooms/GriffinsTale_3001.c
// Performed: 1140502.025911.589

#include <lib.h>
inherit LIB_ROOM;
static void create() {
room::create();
SetClimate("indoors");

SetAmbientLight(80);
SetShort("Griffin's Tale");
SetLong( " The warm candlelight emanates a soft glow throughout this chamber revealing"
" the many tables and chairs that fill this large congregational. Near the"
" southern wall sits a longer table that must serve as the bar, several bottles"
" sit upon it. There are a few pictures near a fireplace which glow dimly,"
" only adding to the simple elegance of this Inn. Just past a large picture"
" stands a arch which seems to lead into a back room which is deathly silent."
"\n A door leads to the west while to the east lies an archway opening into a"
" long hall with many doors lining it."
"\n" );


add_exit( "east", "/domains/Shylar_30/rooms/GriffinsInn_3008", "road" );
add_alias( "east", "archway" );
add_item( ({ "east", "archway" }),
"A sign over the entrance reads, \"Inn, bread and brothel\"."
"\n" );
add_exit( "south", "/domains/Shylar_30/rooms/Backroom_3038", "road" );
add_item( "south" ,
"A sign over the archway reads, \"Quests\"."
"\n" );
add_exit( "west", "/domains/Shylar_30/rooms/Travelersroad_3000", "door" );
add_alias( "west", "door" );
add_item( ({ "west", "door" }),
"A door made of fine ironwood."
"\n" );
}
02 May, 2014, Nathan wrote in the 7th comment:
Votes: 0
I don't think either is terrible, but making five rooms is different than making fifty or five hundred. Just writing room descriptions (preferably on the computer) and drawing a map on paper helps a lot I imagine, because once you have the pieces, synthesizing the necessary data file is less tedious than typing it all into a data file a line at a time.

Having a nice gui editor like this -> http://www.gammon.com.au/smaugeditor/sma... for a game can take away some of the tedium. Alas, they are usually tied to a particular game due to differences in data format.
02 May, 2014, Tyche wrote in the 8th comment:
Votes: 0
hitsuzen said:
… but I'd like players to be able to modify the world, start businesses and build hangouts as well as leave cryptic marks on the world (like create their own magical artifacts)

LambdaMOO supports user free programming.
The driver is written in C, but you need only get it compiled onn your patform.
All the building of the game and all objects is done in MOO code.
Here's a tutorial
02 May, 2014, quixadhal wrote in the 9th comment:
Votes: 0
Nathan said:
I don't think either is terrible, but making five rooms is different than making fifty or five hundred. Just writing room descriptions (preferably on the computer) and drawing a map on paper helps a lot I imagine, because once you have the pieces, synthesizing the necessary data file is less tedious than typing it all into a data file a line at a time.


The terrible part is the line containing "30 124 1", since that includes the wonderful bitflag fields. Typically, if you take more than a day off from working on such things, you then have to go back to looking up each bit to figure out WTF they are.

While I understand the need for them back in 1989 when you had to cram the whole game into 4MB of RAM… the fact that people STILL cling to them is horrible. Looking them up in my notes… 124 is "NO_MOB + INDOORS + PEACEFUL + NO_STEAL + NO_SUMMON". The problem was even more nasty for NPC and objects, since they often repurpose the same flags or values for different things, depending on the TYPE of object or mob.

At least the LPC version never does that. If there's an equivalent to PEACEFUL, it would likely be something like SetAllowCombat(0).

Considering that most Dikurivatives have OLC these days, it's a shame they still cling to such cryptic file formats. Even the "key'd" formats still seem to use bitflags and magic numbers quite often. If I were still working on an active codebase, I'd probably scrap the whole system and change it to just dump to JSON (or pick your favorite lightweight data transport) and then remove all that old legacy file parsing code.
02 May, 2014, Tyche wrote in the 10th comment:
Votes: 0
quixadhal said:
Considering that most Dikurivatives have OLC these days, it's a shame they still cling to such cryptic file formats.

The use of OLC makes the file format irrelevant.
03 May, 2014, quixadhal wrote in the 11th comment:
Votes: 0
Tyche said:
quixadhal said:
Considering that most Dikurivatives have OLC these days, it's a shame they still cling to such cryptic file formats.

The use of OLC makes the file format irrelevant.


It makes it irrelevant except that when you add a new flag/feature/whatever you now have to not only edit the code that uses it, and the OLC code, but also the loading and saving code… which is overly complex to accomodate a format which was designed to be hand-edited in a text editor.
03 May, 2014, Nathan wrote in the 12th comment:
Votes: 0
quixadhal said:
Nathan said:
I don't think either is terrible, but making five rooms is different than making fifty or five hundred. Just writing room descriptions (preferably on the computer) and drawing a map on paper helps a lot I imagine, because once you have the pieces, synthesizing the necessary data file is less tedious than typing it all into a data file a line at a time.


The terrible part is the line containing "30 124 1", since that includes the wonderful bitflag fields. Typically, if you take more than a day off from working on such things, you then have to go back to looking up each bit to figure out WTF they are.

While I understand the need for them back in 1989 when you had to cram the whole game into 4MB of RAM… the fact that people STILL cling to them is horrible. Looking them up in my notes… 124 is "NO_MOB + INDOORS + PEACEFUL + NO_STEAL + NO_SUMMON". The problem was even more nasty for NPC and objects, since they often repurpose the same flags or values for different things, depending on the TYPE of object or mob.

At least the LPC version never does that. If there's an equivalent to PEACEFUL, it would likely be something like SetAllowCombat(0).

Considering that most Dikurivatives have OLC these days, it's a shame they still cling to such cryptic file formats. Even the "key'd" formats still seem to use bitflags and magic numbers quite often. If I were still working on an active codebase, I'd probably scrap the whole system and change it to just dump to JSON (or pick your favorite lightweight data transport) and then remove all that old legacy file parsing code.


You could change your saving/loading stuff to take in text like "NO_MOB" and translate them to the appropriate internal data. I expect they won't ever go away because hand-editing JSON is just as bad, no OLC is perfect, and JSON is one more library that you have to deal with. Honestly I kind of dislike the notion you describe with LPC of objects basically consisting of the script to recreate the object rather than just the data. It just seems odd to have code in a data file, even if it does have the minor advantage of being somewhat more clear what each piece of information is for.
03 May, 2014, quixadhal wrote in the 13th comment:
Votes: 0
Nathan said:
You could change your saving/loading stuff to take in text like "NO_MOB" and translate them to the appropriate internal data. I expect they won't ever go away because hand-editing JSON is just as bad, no OLC is perfect, and JSON is one more library that you have to deal with. Honestly I kind of dislike the notion you describe with LPC of objects basically consisting of the script to recreate the object rather than just the data. It just seems odd to have code in a data file, even if it does have the minor advantage of being somewhat more clear what each piece of information is for.


You misunderstand how an LPMUD works. The entire game is coded in LPC, not just a few scripted objects. The driver handles socket connections, filesystem I/O, and running LPC code with appropriate limits to prevent deadlocks and infinite loops. That's it. Everything else is softcode in LPC. So, it's not that I'm using a little script to fill in a template for a room… the LPC code in that file plus the inherited code defines how that room works. I could override stuff in the inherited code so I could reverse gravity, or make the room only let you leave when someone else enters, for example.

As for JSON, it's a very simple and lightweight library. In 2014, it's silly to avoid using libraries when it's trivial for anyone to just download and install them. It's not as nice to use in C as other languages, but it's still easier to write a few lines to read/write each structure than parse a bunch of text.
03 May, 2014, Tyche wrote in the 14th comment:
Votes: 0
quixadhal said:
Tyche said:
quixadhal said:
Considering that most Dikurivatives have OLC these days, it's a shame they still cling to such cryptic file formats.

The use of OLC makes the file format irrelevant.


It makes it irrelevant except that when you add a new flag/feature/whatever you now have to not only edit the code that uses it, and the OLC code, but also the loading and saving code… which is overly complex to accomodate a format which was designed to be hand-edited in a text editor.

Surely you would also have edit all those things even if you use JSON when you are adding a new field or flag to the structures in your Dikumud.
The same would be true when using XML or YAML or SQL or "your own special" format.

Some muds have made the format more friendly by accepting the same words that their OLC uses in its tables.
04 May, 2014, quixadhal wrote in the 15th comment:
Votes: 0
Tyche said:
Surely you would also have edit all those things even if you use JSON when you are adding a new field or flag to the structures in your Dikumud.
The same would be true when using XML or YAML or SQL or "your own special" format.


The entire point of using a serializer (JSON, XML, whatever) is that you hand it a data structure and it returns a string which can be used to restore that data structure. Even in a non-dynamic language like C, the most you should have to do is save that string along with (maybe) a hint of the kind of structure to allocate when you want to load it back again.

Considering that C lacks any useful kind of self-inspection capability, I could see you needing an extra step of using a utility program to auto-generate loading/saving code from a given struct definition, if the library can't figure it out… but that could be automated as part of the Makefile driven process.

In perl, if you have a data structure like this:

$self = {
_time_daemon => $time_daemon,
_pressure => 960,
_change => 0,
_sky => 'clear',
_wind_speed => 0,
_wind_direction => 'calm',
_category_shift => 0,
};


saving that to disk is literally two lines of code that never has to change, no matter how many fields you add or remove…

my $json = JSON->new->allow_blessed(1)->convert_blessed(1);
my $data = $json->encode($self) or die "Invalid JSON conversion: $!";


Restoring that to a brand new object is one line of code

$self = decode_json $data;


It handles any level of nested data types. The only special handling you might need to do is for function pointers, which
you'd likely have to omit and restore by hand, since the pointers won't be valid between executable runs. In this example,
that's actually the time_daemon, which adds three more lines of code to the above process.

But, my point was, if I had a bunch of flags and decided to add a new one, by using JSON I don't need to rewrite the loading and saving code
to accommodate that new value.

Maybe there isn't a C library that can do this automatically. If that's the case, the only benefits you gain from using a standardized serializer would be easy interoperability with other systems (IE: a web page), and not having to do error checking unless you let humans edit the files.
04 May, 2014, Nathan wrote in the 16th comment:
Votes: 0
quixadhal said:
Nathan said:
You could change your saving/loading stuff to take in text like "NO_MOB" and translate them to the appropriate internal data. I expect they won't ever go away because hand-editing JSON is just as bad, no OLC is perfect, and JSON is one more library that you have to deal with. Honestly I kind of dislike the notion you describe with LPC of objects basically consisting of the script to recreate the object rather than just the data. It just seems odd to have code in a data file, even if it does have the minor advantage of being somewhat more clear what each piece of information is for.


You misunderstand how an LPMUD works. The entire game is coded in LPC, not just a few scripted objects. The driver handles socket connections, filesystem I/O, and running LPC code with appropriate limits to prevent deadlocks and infinite loops. That's it. Everything else is softcode in LPC. So, it's not that I'm using a little script to fill in a template for a room… the LPC code in that file plus the inherited code defines how that room works. I could override stuff in the inherited code so I could reverse gravity, or make the room only let you leave when someone else enters, for example.

As for JSON, it's a very simple and lightweight library. In 2014, it's silly to avoid using libraries when it's trivial for anyone to just download and install them. It's not as nice to use in C as other languages, but it's still easier to write a few lines to read/write each structure than parse a bunch of text.


Perhaps, but it's looks a lot like that room file is read once to load the room as a script of sorts that constructs and object? Is that not true? I don't see how a method like 'setDescription' can be anything other modifying an object in memory, unless you hand back a *new* representation of the room every time someone looks at it which seems bad in code performance sort of way. I suppose I find the notion the of the whole game being softcode a little distressing. It just seems like it'd be too easy to break something. With regard to libraries it's not about someone having the libraries, but about having to use them as the programmer/coder. Libraries can be "perfectly" functional and badly documented at the same time. It's more comfortable, if more painful, to handle stuff yourself than trust someone else's code to do it.

I believe it's more work in Java if you want to reconstruct objects, if they contain non-primitive types. C only has structs, which only contain primitives or other structs. I can't imagine serialization plays nicely with any sort of pointer. I could be wrong, but if, in Java, you have a Class with a List inside I don't think you can't just serialize it nicely to json OR perhaps the not nice is getting the list back, rather than just an array. Maybe you could use java's raw serialization, but that depends heavily, I expect, on uncorrupted data to work properly. Feel free to explain if you know otherwise (web links are nice).
05 May, 2014, quixadhal wrote in the 17th comment:
Votes: 0
Nathan said:
Perhaps, but it's looks a lot like that room file is read once to load the room as a script of sorts that constructs and object? Is that not true? I don't see how a method like 'setDescription' can be anything other modifying an object in memory, unless you hand back a *new* representation of the room every time someone looks at it which seems bad in code performance sort of way. I suppose I find the notion the of the whole game being softcode a little distressing. It just seems like it'd be too easy to break something.


Let me take a moment to explain the way that code works. In an LPMUD, everything is an object. When an object is loaded by the driver, it calls a method in that object called create(), which is only ever called by the driver at the time the object is instantiated. That create() function usually sets up various properties and values on the object itself, and may also call functions in other objects.

So, SetLong() is technically modifying an object in memory… but it's modifying itself… the object that's being created at that point. It won't ever do so again, unless the room is unloaded and reloaded, which happens either when someone edits the code and uses the update command, or if the room is unloaded by the driver for being "idle" for too long (to save memory).

This is different from the DikuMUD concept of trigger-based softcode, where the code is run every time someone walks into the room. We have that too, but it's not defined as different or special code… it's a function of the mudlib design, not the driver.

When a player moves into a room, the softcode of the mudlib is what moves the player. The driver neither knows nor cares, it simply runs lpc code. The mudlib itself handles the movement, and calls this_player()->eventLook() once the move is complete. That bit of code will likely call environment(this_player())->getLong() to fetch the room description and present it to the player.

The one thing the driver does… when the move code accesses the room by doing something like "/domains/town/room/hall.c"->canEnter(this_player()), is if that room object doesn't exist yet, it will load it, calling create() on it first. If it already exists, nothing else happens.

I'm simplifying a little, as there are a few other cases where stuff gets called… but hopefully I described how it works well enough.

As for being fragile, quite the opposite. LPC code is interepreted by the game driver, and as such no error in LPC can crash the driver itself (unless you find a bug in the driver code, which is rare these days). Furthermore, because the mudlib has a security system, builders can't just edit any file they want… they can only modify things they have permission to modify. Always their own workroom area. Often a domain or area they're working on. Sometimes a game system they're adding or improving. But if anything gets broken, it stays isolated in those systems.

If you break a room, only that room is inaccessible until fixed. If you break the "fireball" spell, "lightning bolt" and "cure" still work fine. If you break the "elf" class, players who play elves will be unhappy, but others can still login and are not affected. Obviously, if you break the player or login objects, it makes a mess… but it still doesn't crash the game.

—-

I can't speak for Java, as I don't know it very well. I can say that Perl allows you to serialize objects with other arbitrary objects nested, with the caveat that you have to provide a TO_JSON method to "unbless" the objects. In Perl, an object is really just an associative array of data with a bunch of methods in a namespace. When you "bless" the array, it gains the magic of being able to call the methods on it. Usually a TO_JSON function just makes an empty mapping and copies all the data from the blessed version to it, omitting fields that don't make sense like pointers to other objects.

When you serialize an object, it calls the TO_JSON method on it first, then it serializes each element in the thing returned. If your object has an object that you want to keep, you can have the parent's TO_JSON serialize that inner object the same way, instead of ignoring it.

This makes sense when you have a player with an inventory, for example… you want to keep the inventory nested in the player. However, if you had a room with a list of players, you might want to skip those objects, since they may not come back to the same room when you reboot.
05 May, 2014, Nathan wrote in the 18th comment:
Votes: 0
I wasn't suggesting it would break the game, just that it seems unpleasant to be able to break even a small part of the system while it's live. Coding bugs are one thing, but letting live editing break things…

It just seems like it could be bad in Java, it might be perfectly fine if the library neatly handles all primitives and their Object equivalents (Integer, Boolean). In theory everything ought to boil down to some primitive eventually. Reconstituting it, however, might be tricky. I'm guessing that's why Google-Gson has what they call a TypeAdapter so you can specify how to translate all the data back into an object. It's just be nice if you didn't have to do that. No fun to convert everything over since you might have to write a type adapter for any given class if you want any of the benefits of using different list types. At some level this is mostly speculation as I've only used a TypeAdapter setup where you specify how to populate the fields of an instance of the class from the data and have no idea what is does without any customization.
05 May, 2014, quixadhal wrote in the 19th comment:
Votes: 0
*nod*

There are a lot of people with mostly DikuMUD experience on this forum (and others I read), so I wanted to be sure I was clear about each code segment being isolated. In truth, many LPMUD's run a live game and a test port, just like other MUD types.

The main difference is that you can allow your builders to create new areas and code new objects or NPC's on the live game without any fear of things breaking for players. Generally speaking, you might still want a test copy to work on systems code, where breaking it will affect more things that just the one you're working on. :)

The way I've envisioned serialization working may or may not actually be implemented for any given language. If the language allows for self-inspection, there's no reason your serializer can't look at the object and note the types as properties in the JSON encoding, and then use those notes when restoring the object hierarchy to allocate objects of the correct type. Even without google's extensions, it's just looking at the object and saying Oh, that has a struct foo reference… { "object":"bar", { "light_level":3, "doors":[ {"__type":"foo", "__value":{ "another nested":"json object" }}]}}.

It would require the deserialize code recognize such hints and do the right thing, but it doesn't seem totally unreasonable.

In language with soft typing, you have it easy (perl).. since objects don't have rigid structures. But even there, if I have nested objects and want to restore them, either my restore code has to know how to do it, or I have to leave such hints so I can bless the raw data into the right kind of object reference.
05 May, 2014, Viriato wrote in the 20th comment:
Votes: 0
Hello.
Java has it's own serializing format, and you can use libraries to do it in other formats, like JSON. For Java serialization you need to implement Serializable in your classes, basically, and be aware that a serialized class cannot be de-serialized if you make changes in the class code meanwhile (you can do some changes, like add a new variable, but can't do others, like change a variable datatype from string to int).
There are some more details about it, so if you are interested, PM me and I'll be glad to share what I know.
0.0/30