09 Jun, 2014, Sorressean wrote in the 1st comment:
Votes: 0
Hello all:

I have recently released Aspen into the public after a lot of work in the hopes that the community might find it useful and even possibly feel like developing for it.

The goal of Aspen is to provide a light-weight barebones mud engine, which can easily be extended. Part of my issue with a lot of mudbases is that in order to implement many of my ideas, I would have had to rip out a lot of code to implement my system. I have decided, then to provide an engine which provides all of the tools and systems that allows one to build on it.

While there are other bases that might be like this, the only one I am aware of is Nakedmud; there are a few issues that prevented me from using it: firstly, it is no longer being developed; finally, it is written in c and can not take advantage of some of the c++ 11 features that we are using in Aspen, not to mention the stl.

Aspen's design is simple, though not quite to the point where I would like it. First, I believe that my idea for objects and components is fairly unique. Copmponents are a way to transform objects from a is-a to a has-a relationship. For example, lets say that you want to take an object and give it some features: you want to make a weapon, that can serve as a container as well as maybe a key. In order to achieve this with aspen, you would create the object, then attach the weapon, container and key component to the object. Objects are also themselves vastly different from that of most mudbases. In the case of NPCS and objects, objects are created and managed in a two-part setup. First, There are "virtual" objects and npcs. what this does is holds the name and description of the object, as well as other variables. These are variables that would be coppied to every object, but that would stay the same. This essentially makes object templates a possibility. When you create an object, you provide the vnum and the object is coppied and then assigned a UUID. This also serves the purpose of being able to trac statistics on an individual object.

If any of this is interesting to you, please have a look. Aspen is currently not ready for primetime; it has a ways to go, but I am working as much as I can to develop it to the point where it will be ready. Feedback, code contributions and ideas from others would also help to make this a better engine. We are located on github: https://github.com/sorressean/aspen and on irc on freenode in #aspenmud. I currently, as of yet do not have another method for communication, but if anyone has more ideas there, please let me know.

Thanks,
10 Jun, 2014, roguewombat wrote in the 2nd comment:
Votes: 0
Very cool, thanks for sharing.
12 Jun, 2014, Lyanic wrote in the 3rd comment:
Votes: 0
What is the purpose of the vnum if you're assigning UUIDs?
12 Jun, 2014, Idealiad wrote in the 4th comment:
Votes: 0
As a template identifier? I suppose you could identify it by vnum or uri, it doesn't matter too much.
12 Jun, 2014, quixadhal wrote in the 5th comment:
Votes: 0
First of all, thanks for sharing this! Anything that moves us away from antique C codebases is a good thing! :)

The very first thing I'd probably change would be to rip out vnums and replace them with useful text identifiers that actually tell you something about the object they're representing.

"/domain/Shylar/room/BehindTheInn" is so much more useful than 3037, in almost every way imaginable. A UUID is perfectly fine for having a identifier that's unique across all instances of all objects, but I find having to look up vnums to figure out what things are to be vulgar. They made sense in 1990, when RAM was limited and CPU speed mattered, but these days, a std::map<std::string> would be perfectly fine.
12 Jun, 2014, Lyanic wrote in the 6th comment:
Votes: 0
Sadly, I agree with Quix here. That was the point I was getting at, but he elaborated on it. UUIDs are sufficient to uniquely identify game objects. For humans to actually refer to them, descriptive strings work far better than vnums.
12 Jun, 2014, Sorressean wrote in the 7th comment:
Votes: 0
Hello:
Thanks for the advice. I may do that at some point, but it's going to take a bit of revamping. Shouldn't be to hard.

The UUIDS are assigned to objects that are already created. It doesn't apply to rooms, but to objects and NPCS. The VNUM just refers to the "template" that the object is created from.
Thanks,
12 Jun, 2014, Nathan wrote in the 8th comment:
Votes: 0
quixadhal said:
First of all, thanks for sharing this! Anything that moves us away from antique C codebases is a good thing! :)

The very first thing I'd probably change would be to rip out vnums and replace them with useful text identifiers that actually tell you something about the object they're representing.

"/domain/Shylar/room/BehindTheInn" is so much more useful than 3037, in almost every way imaginable. A UUID is perfectly fine for having a identifier that's unique across all instances of all objects, but I find having to look up vnums to figure out what things are to be vulgar. They made sense in 1990, when RAM was limited and CPU speed mattered, but these days, a std::map<std::string> would be perfectly fine.


You've said this before and I've commented before. I personally find the numbers a little easier to remember, at least for small groups of things and numbers below 10-20k (i.e. they only have 6 digits at most). I also don't see any reason why code couldn't support more than one way of doing that sort of thing. It might even be viable to some extent if you split things down by areas/zones/? like some games do, for both systems really. 0 or 1 being the first object in that area and so forth. It just gets really nasty when the number has to be unique across the entire world, which presumably why UUIDs exist in the first place – to provide completely unique identifiers for vast numbers of things.
12 Jun, 2014, Sorressean wrote in the 9th comment:
Votes: 0
I'm particularly partial to vnums as well, as they're easier to use. /domains/foo/rooms/square is really LPC-like. What I could do, and perhaps make it automagic somehow is to allow for aliases. so: addvnumalias object 3000 wand. so, you could access it like: zone.wand etc.
12 Jun, 2014, plamzi wrote in the 10th comment:
Votes: 0
Lyanic said:
UUIDs are sufficient to uniquely identify game objects.


Not exactly true, unless you are generating everything "from scratch", which can really get labor-intensive. UUID's are enough for instances, but if you use templates to produce multiples of instances, then naturally you will need some way to uniquely identify the templates. It is fashionable to slam good old Diku, but VNUMs are basically template identifiers, and RNUMs are instance identifiers.

Lyanic said:
For humans to actually refer to them, descriptive strings work far better than vnums.


The whole point is moot if your game, like any modern game, keeps world data in a database. You may never need to know or worry about what the unique id of an instance or a template is. You will not need "descriptive" strings because you will be able to access templates and instances based on any property or combination of properties you may wish to use (queries).

As I've shared before, I find the LPMud id's to be just as dated as the VNUM / RNUM system. They have the imprint of directory trees on them, and who uses flat files anymore? Also, once you get to the bottom level of the hierarchy, e. g. /domain/Shylar/room/LongCorridor001 - /domain/Shylar/room/LongCorridor101, you still have the same issues with how to pick out truly unique id's for new entities. A database will handle that for you.
12 Jun, 2014, quixadhal wrote in the 11th comment:
Votes: 0
Speaking from experience, good luck finding the place a builder accidentally cross-linked exits using vnums, making a room in the grasslands end up with a one-way exit to the mountains because they linked room 3301 to room 1330 instead of 3310, like they meant to.

A database won't "handle that for you". A database will obscure the issue, because you rely on the OLC code to be 100% bug free AND for no one to ever mess things up with an ad-hoc query.

And sure, Grassland13 and Grassland53 won't help much. But when you see Grassland53 link to Forest13, you at least know you've made a change of area without needing to go look up it up. Seeing vnum 3353 link to 2013 might be a hint of area change, but unless you personally built every single area in the game, are you going to remember what are 20** is?

Of course, if you actually were doing an overland map thing, wouldn't you use Grassland_03_13, where those numbers are coordinates? That way, if you don't have a more descriptive id, at least it directly tells you WHERE in the zone the room sits.

OTOH, in dense areas where each room is actually NOT filler space, Seeing BackRoom -> CommonRoom -> MainStreet_N3 -> MainStreet_N2 -> JewelryShop seems to tell me a lot more than 3001 -> 3003 -> 3022 -> 3023 -> 3030.

Same goes for npcs and objects. I'd rather have an id be GrasslandOrc or TinSword than vnums.

Maybe it's a moot point because no MUD being designed today is likely to ever have more than one builder… namely, the admin who sets it up. They days of new muds taking off and having a team to work on content seem to have vanished under the "I want to make my own unique snowflake" syndrome.
12 Jun, 2014, plamzi wrote in the 12th comment:
Votes: 0
quixadhal said:
Speaking from experience, good luck finding the place a builder accidentally cross-linked exits using vnums, making a room in the grasslands end up with a one-way exit to the mountains because they linked room 3301 to room 1330 instead of 3310, like they meant to.

A database won't "handle that for you". A database will obscure the issue, because you rely on the OLC code to be 100% bug free AND for no one to ever mess things up with an ad-hoc query.


A modern database will handle unique identifiers for you. And a modern content building tool can be created on top of that database so that a human being never has to worry about whether to type 1330 or 3310. The problem you are describing is a problem with the content creation tool being very old-fashioned and user-unfriendly, which is a common shortcoming of many LPMuds and Dikurivatives alike.

I really don't understand your comment about a database obscuring the issue. Of course, you can point an old-school, buggy, and/or human-error-prone OLC to a database, and it's not going to automatically debug your tool for you. But I don't see how it is actually going to make things worse than they already are… If anything, knowing where your tool is flawed, you could query your world data for conflicts and flag anything that is out of whack more easily. For example, if you care about Euclidean consistency, you can query and find any room links across your entire world that are not two-way links…
13 Jun, 2014, Nathan wrote in the 13th comment:
Votes: 0
I don't know LPC, but I assume "/domain/Shylar/room/BehindTheInn" is not a template per say. X.Y makes sense when referring to a particular instance, Y, inside of X unless you've got virtual/template objects only for use in/with X. Unless I misunderstand.

In any case, you may want to use the wiki for your github repo as a place to put documentation, such as explaining (in depth) the logic behind how the code works and stuff like your virtual objects. I am fairly sure most of us on here come from a particular background in some codebase or our own code or perhaps some particular programming language and so have preconceived notions of what a word means in that context. For instance I might call your virtual objects prototypes in the sense that it's a model that will be duplicated to get real objects that will be used.
13 Jun, 2014, Nathan wrote in the 14th comment:
Votes: 0
@Plamzi
Just because something is old doesn't make it user-unfriendly. While I suppose there is a least common denominator style of design that's not necessarily the best approach.

It's much easier to work with something existing and functional that you understand well than it is to switch to something that is new and complex, even if it might be better in some ways. It's also something new to learn that would be a hindrance, in a way, to actually getting around to build something. Probably in an ideal world you'd have something like what exist in Diku and LPMUDs, only it's a some kind of model/interface that is backed by a database so that you can have the comfort of what you know without it's shortcomings.

Creating new, good, useful software is hard.
13 Jun, 2014, quixadhal wrote in the 15th comment:
Votes: 0
Nathan said:
I don't know LPC, but I assume "/domain/Shylar/room/BehindTheInn" is not a template per say. X.Y makes sense when referring to a particular instance, Y, inside of X unless you've got virtual/template objects only for use in/with X. Unless I misunderstand.


Actually, in an LPMUD, everything is an object. In a sense, everything is also a template in the sense that by default, there is only a single instance of any given object. However, for npcs and in-game items, it's usual to have many instances of the same object. It's a pretty simple mechanic.

When you attempt to load (or call a function in) an object, the driver will look for an LPC file in the path given. If it finds one, it loads/tokenizes it into LPC stack code. If that works, it calls the create() function in that new object. LPC has inheritance, so an object can also inherit code from other objects, in which case those will also be loaded as part of the process.

The driver also provides a function called clone_object(), which does the same thing, but it creates a new instance of the object regardless of one existing already or not. To distinguish a clone from a template, the driver appends a number to the pathname of the object and returns the new identifier as the result of the clone_object() call succeeding.

So, the "template" for a given NPC might be "/d/Shylar/npc/orc.c", but if I clone one, it may create "/d/Shylar/npc/orc.c#13", which would be the 13th clone of that object.

If the disk file didn't exist, the driver will attempt to call compile_object() with that same path. If it returns a valid object, it then associates the newly created object with that identifier. So, you could make a virtual wilderness by making compile_object() construct room objects based on the pathname, where it might really be pulling data from some algorithm, or a graphic file's pixels, or anything else you can think of. You don't NEED to use a directory-like path for such things, but it fits nicely with the rest of the system if you do. An example might be "/d/Shylar/virtual/room_23_45_1.c", with x,y,z coordinates.

The clever part of that is, you could literally make an entire zone (or world) be all virtual rooms, and decide to hand-build something at a given point. Just make on-disk files with those same names and when you re-load the rooms in question, you're suddenly using disk-based rooms which you can customize as you like, and point to sensibly-named exits, etc, etc.

Sure, you can do that with a database too, but it's on you to code your OLC system to have all the right boxes to tick and drop-menus to select things from to make it work.

@Planzi, the reason I say a database can obscure the issue is that if you hand-link one room to the WRONG room, there's no way to notice that unless you go and edit it in OLC again, or you happen to notice that going north-south-north doesn't put you in the same room the second time. With vnums, you also can't easily see the mistake, since vnum 3301 and vnum 3331 both look reasonable for a zone whose rooms are 33xx. A pathname is slightly better, since if you're standing in "/d/Shylar/room/CommonRoom.c" and you see an exit pointing to "/d/Shylar/room/GoblinCave.c", you might wonder. MORE importantly, when building and creating those links, they are different enough that you aren't likely to make the mistake in the first place. A typo on a meaningful id usually results in an error, not a valid but incorrect link.
13 Jun, 2014, plamzi wrote in the 16th comment:
Votes: 0
Nathan said:
@Plamzi
Just because something is old doesn't make it user-unfriendly.


Absolutely right. If today you design an interface that requires human beings to keep track of numbers, or strings, in their heads that they then have to type later on, or to somehow have to divine what kind of number or string to put in that hasn't been used before, it will still be user-unfriendly :)

Nathan said:
It's much easier to work with something existing and functional that you understand well than it is to switch to something that is new and complex, even if it might be better in some ways. It's also something new to learn that would be a hindrance, in a way, to actually getting around to build something.


That's true. But what about switching from something user-unfriendly to something user-friendly? For instance, a couple of years ago I made a modern UI for content creation. Under the hood, it's still generating VNUMs, but at no point is it asking the builder to remember to plug the correct number. When you place two rooms next to each other, it links them up, with 0 chance of entering the wrong unique id's.

There is no comfort I can see in using a tool that slows you down and allows for human errors that then create more work.

Nathan said:
Probably in an ideal world you'd have something like what exist in Diku and LPMUDs, only it's a some kind of model/interface that is backed by a database so that you can have the comfort of what you know without it's shortcomings.


We have this, but it would have been significantly easier to build if I could let the database take care of the unique id generation and book-keeping. As it is now, game servers that predate modern databases are doing a shoddy work of something that is the bread and butter of databases.
13 Jun, 2014, Scandum wrote in the 17th comment:
Votes: 0
Sorressean said:
For example, lets say that you want to take an object and give it some features: you want to make a weapon, that can serve as a container as well as maybe a key. In order to achieve this with aspen, you would create the object, then attach the weapon, container and key component to the object.

That's a dead end as far as I'm concerned. You want behavior to be innate and subsequently inherited. If done properly any object can be used as a weapon or a key. Doing things the other way around results in very little synergy.

In the model I propose a door with a keyhole would be a container. A player could stick something in the keyhole to jam it, which would be an innate characteristic of any container so this wouldn't require additional code as it would be handled by the container handling routines. You get added features without having to add additional code.
13 Jun, 2014, Kelvin wrote in the 18th comment:
Votes: 0
I like how this thread about a new C++ MUD codebase has been hijacked with such a pointless, petty discussion. Sometimes I get the feeling that we're on here to compare e-peens and always "win" arguments.

Thanks for sharing this, Sorressean. Good to see more MU* codebase work being done.
13 Jun, 2014, Lyanic wrote in the 19th comment:
Votes: 0
I feel the need to point out a flaw in the underlying assumptions of plamzi's responses, which is rather relevant here. While I agree with the general assumption that more modern building tools can help prevent user error and the necessity to keep up with strings and numbers, the ones plamzi refers to are graphical building tools. The flaw is assuming that graphical building tools are and should be the preferred choice. Alas, many members of our community are visually impaired, perhaps including some in this thread.
13 Jun, 2014, Sorressean wrote in the 20th comment:
Votes: 0
@kelvin: <3

@lyanic: Because we are blind, it doesn't prevent us from using graphical building tools, as long as the underlying GUI is accessible. One eventual goal for Aspen is to make OLC web based. OLC is slightly confusing in its current form, but it's really easy to do something like that with.

Scandum: You should hate multiple inheritance, as should everyone. Sure everything could be a weapon and food and a container and a key and everything else, but that requires that objects are huge and have all of this extra crap you don't want. With my component system, you have a has-a relationship as opposed to an is-a relationship. So you write the code -once- for a component and if you have an object that you want to be all of those things, you just attach the component to it (eventually through OLC, perhaps today if I get a lot done). This lets objects be -only- what they need to be and not have a ton of multiple/huge inheritance chains going on.
0.0/27