The two major forms of programming, Procedural and Object Oriented, approach the problem of programming from opposite directions; those directions being a code centric view (“verb oriented” if you will) and a data type centric view (“noun oriented”).
Procedural, being the older of the two, is code centric, since that's the primary view of computers when they were first built—how do we get this expensive box of electronics to do something? Procedural is more concerned with the steps of solving a problem—step one, step two, step three. Actions. Verbs. When you have very few data types, it's easier to program the nouns to the verbs (if you will). That is, a program will tend to look like:
add(one,two) if one and two are ints, then do the add this way if one and two are floats, then do the add this way if one and two are strings, then do the add this way sub(one,two) if one and two are ints, then do the sub this way if one and two are floats, then do the sub this way if one and two are strings, then it's an error, bub!
Adding a new verb is easy, given the limited number of nouns present. But, as the number of nouns (remember, in this rather twisted metaphore, a noun is a data type) increases in a program, this starts to get unwieldy, which leads us to—
Object Oriented, developed in the 70s and gained industry wide acceptance during the 80s, is a more data-type centric view of programming. If you have lots of data types, but relatively few verbs, it then becomes more convenient to program the verbs to the nouns, something like:
int(op) if op is add, do this if op is sub, do this float(op) if op is add, do this if op is sub, do this string(op) if op is add, do this if op is sub, then it's an error, bub!
Sure, there's still a sequence of steps done to do anything, but it's the nouns that do the work themselves (if you care to view it that way). You simply tell the datatype, “do this.” And if it can, it does.
But as the number of verbs increase, then this too become unwieldly which leads us to—
Nothing that I know of.
Granted, if the number of verbs is significantly large to the number of nouns, then a Procedural method works well, while the opposite, if the number of nouns is significantly large to the number of verbs, then Object Oriented is the way to go. But what if both nouns and verbs are significantly large? What if you have a hundred different data types and a hundred different actions that can be applied? (One hundred of each ever after you tried reducing the number of both?)
Either approach will lead to a mess.
And when will you even have a large number of nouns and verbs in a program?
Well, think of the Massively-Multiuser Online Role Playing Games, like EverQuest or Star Wars Galaxies. Thousands of objects, and possibly thousands of different actions. A player can walk, run, skip, jump, jog, crawl, skulk, stumble, dance, turn, parry, dodge, spin, thrust (thwack! ouch!). That's just movement, and I'm sure I'm leaving out plenty of other movement actions. They can also carry, throw, chuck, up-chuck, heave, shoot, fling, place and lay items.
Sure, you can cut the number of actions down by making some of them more abstract, like “use” an object (the “use” of an object like a camera being different than the “use” of an object like a key) but we humans are creative (or stupid, take your pick) and while you can't use a key to take a picture, you can attempt to use a camera to open a lock (although you may end up with a mangled camera and a still locked lock) and it would be nice if the program would allow us to attempt this (even if it is stupid).
It'd be nice if there was a way to manage both a large number of nouns and verbs within a program, but as of yet, there doesn't seem to be a way to do this.
But even with this limitation, I think one can still build programs with tons of objects with tons of actions.
Or it may end up being one large mess.
I'd be interesting to see.
While sleeping last night [which was actually Thursday night/Friday morning—Sean] I had a rather odd thought pop through my head—a WikiMUD. I then spent some time pondering that and how one would go about implementing such a thing.
I can hear you blinking out there.
Okay, for those who might otherwise not know, a WikiWikiWeb (or “Wiki” for short) is a website where every page is editable by anyone. See a typo? Fix it. See a mispelling? Fix it. Don't agree with what you read? Add your two zorkmids. A very egalitarian approach to web content, and it can lead to some wonderful things.
A MUD, which stands for “Multi-User Dungeon” or “Multi-User Domain” (take your pick) is a multiplayer verion of a text adventure, where instead of you just walking through a twisty little maze of passages all alike, there are scores of people all waking through a twisty little maze of passages all alike. Just as Adventure was the single player forerunner of a MUD, a MUD (and there are still plenty around) was the forerunner of todays MMORPG, or “Massively-Multiuser Online Role Playing Game” like EverQuest or Star Wars Galaxies (these tend to be graphical in nature).
So, a WikiMUD is a MUD where anyone can edit anything and even change the nature of the game play as it's being played.
The WikiNature scares some people; not only can anyone edit anything, they can also delete anything. MUDs scare others; people (often college students) emersing themselves into a game 10, 12, 16 hours per day to the detriment of living in the real world (this has happened to friends of mine—the results are not pretty). A WikiMUD should therefore be downright horrifying!
Now, besides the potentially horrifying nature of a WikiMUD, how could one implement such a beast? Obviously there is going to be a programming language available, and some form of online editor so that on-the-fly changes can be made to the game. But the underlying implementation? The framework that can support such a thing? That's challenging.
In the few MUDs I've looked at, source code wise (and yes, I did toy with them briefly in college but I was more interested in writing a MUD, not in playing a MUD; I never did get around to writing one though) is usually structured around rooms, objects, monsters (or mobile-object, aka MOB) and players, which generally lend themselves to being written in a object-oriented manner, even if that ultimately may limit them.
Some thought on this lead me to a possible implementation. It may not be a good implementation, but it's more than nothing. And it allows great freedom to the users to extend the game in ways the game designer (or implementor) might not have thought otherwise.
Everything in a MUD can be broken down into two things: objects and actions. We'll go into actions later. An object can be something like a room, which may have a name, and have a list of items it has—an inventory if you will. Or an object can be something like a player, which may have a name, and have a list of items it has—an inventory if you will, and a location within the game map. Now, in a traditional object oriented design, one might then be tempted to make a person a subclass of room, but that doesn't really work here since a person ISnotA room, even if they share some commonality. It gets even worse if you want to include a bag-like object, which may have a name, and have a list of items it has—an inventory if you will, and a location, either a room or a person; a bag is a kind of portable room, but again, a bag ISnotA room.
[I'm making a rather bad pun in the previous paragraph. The ISA Principle of OOP states that a relationship between an object A, and a derived (or based off of) object B, is that object B ISA object A. What I'm saying here is that even though the implementation of object B is similar to (or the same as) object A, that does not mean that object B is derived, nor should it be derived, from object A.]
[I also suspect I'm loosing more and more of my readers at this point … ah well.]
So we have three objects so far, all of which are similar (name, inventory, a location in two of the three objects) but none of which really follow the ISA principle of OOP, although they certainly have plenty of HASA relationships between them all. And we haven't even gotten to monster objects yet. But each of these objects do have one thing in common—they all have some form of attribute. Be it a name, or a list if things it has, or its location, these are all attributes of the object.
[A HASA relationship between object A and object B, such that object B HASA object A, does not mean that object B is derived from object A, but that it uses or contains within its definition an instantiation (or “fully initialized and ready to use”) of object A. Sorry for the digression.]
So what, instead of having distinct objects we simply attach attributes to objects as we need them? You create (or “instantiate” in OOPspeak) an object. This object is … well … there is no real metaphore for what this object is, other than … an inherent object with … objectness to it. It is an object with which anything else can be created. It is the urObject in our WikiMUDian universe and is nothing until one attaches attributes to it.
Want a person? At a minimum, it's an object with a name and a location. Want a room? At a minimum, it's an object with things in it, and exits to other room-like objects. Want a bag? Again, just an object with things in it, and a possible location (even if that location happens to be a person object, or another bag object). A minimal WikiMUDian universe may look something like:
# this is a comment # numbers represent object ids object-id: 0 south: 1 inventory: 2 object-id: 1 inventory: 3 north: 0 object-id: 2 name: bag location: 0 object-id: 3 name: Sean location: 1
When I move (as object #3, “Sean”) north, the location attribute would change from a 1 to 0, and the inventory list of object 0 would change to now include object 3—me. When I pick up the bag, the bag's location would change from object 0 (a room) to object 3 (me) and I would then gain a new attribute, inventory, with the object-id of the bag.
Simplistic yes. Flexible yes. And it can certainly lead to very surreal things, where as it stands now, I can “pick up” room 0 and “drop it” in room 1. There really isn't anything built into the code to prevent such wierd occurances as this.
And I'm not sure if there should be. Yes, as people add objects and actions (which we'll get to) certain conventions will probably come out, and code added to prevent people from picking up rooms and dropping them here and there. But it certainly will allow someone to create, say, a dollhouse that can be carried about, but that also contain actual rooms that people can move about in, if they were so sized (which is just another attribute one can add, after all).
And speaking of picking up rooms … we need actions. We've already mentioned a few, such as creating an object (or “urObject” as the case may be), adding and modifying attributes, moving ourselves around, picking up bags and rooms. While we're at it, we might also want to remove attributes, destroy objects, and even copy objects (because you can never have too many bags, or zorkmids once someone gets around to creating one). Now, while I've been currently envisioning objects as being global (in the programming sense, which makes sense to me but explaining why it makes sense would take as long as a semester of Philosophy 101, which I'm not about to do here), actions on the other hand, can be global (available to be applied to all objects whether it makes sense or not) or local to just an object (and copying an object will copy those actions local to the object).
[In thinking this through, I may have inadvertantly reinvented SmallTalk.]
So, the action of going “north” would be applied to the player, and the code may look something like this:
(to north (target) (let room (object-by-id target/location)) (if (object-by-id room/north) ( (modify target/location (object-by-id room/north)) (say target "You move north.") (say (allbut room target) target/name " moves away to the north.") ) ( (say target "You silly git! There's no way to move north!") (say (allbut room target) target/name " stumbles into the north wall.") ) ) )
[Yes, the code looks like Lisp. Since Greenspun's 10th Law of Programming states that any sufficiently complicated program will contain an ad-hoc, informally-specified, bug-ridden, slow implementation of half of CommonLisp, I thought I'd go ahead and cut to the chase—besides, it's dead simple to write a Lisp-like parser.]
And it would be a global action, available to all objects (or all players). An example of a localized action might be:
(to stick-head-in-bag (bag target) (modify target/description (+ target/description " Plus there's this " "rather large and unsightly bag over the person's head, for " "some unearthly reason." ) (to target/see (target) (say target "You silly git! You can't see! You " "have a large and unsightly bag over your head!") ) )
Basically, we modify the description attribute of the target (in this case, the idiot putting the bag on their head) to indicate such, and also add a local action to the target—in this case the “see” action, to say to the player that they can't see because they have a bag over their head.
The attributes and actions I've described so far are not cast into stone—in fact, except for a few actions that manipulate objects and actions, there are no baked in commands. There are no baked in objects either (with the possible exception of a minimal, if even that, player object). Everything (and I mean everything) is up to the players. The rules (or lack thereof). The rooms. The genre.
What are the implications of this?
Well, dup bugs (that allow the duplication of objects that shouldn't be duplicated) aren't a problem. Heck, duplication of objects is a feature; I find a zorkmid, it's easy enough for me to duplicate it a thousand times (“Look at me! I'm a counterfeiter!”). Heck, I could duplicate myself a thousand times if I wanted to. Sustaining an economy in such an environment is … interesting, to say the least.
Leveling? What's that? Oh, you're level 40? Well, let me just modify my level attribute to 70! No wait, 1,000! No, how about 50,000! Take that you puny 40th level … player … you. Here, let me throw this Ninja zorkmid at you! Oh wait! No throw action. Hold on … <hack> <hack> <hack> … there we go! Ninja zorkmid throwing action! Which leads to interesting combat when I can make anything a weapon that does a hundred points of damage. Or a thousand. Or a million. Or instant destruction.
The Ninja Dandelion of Instant and Utter Death, anyone?
Drat! Your Shield of Formica +1 blocks it!
If there's no leveling, nor any meaningful concept of an economy, and everyone can cheat by changing things they don't like (if you can call it cheating if the system allows it), then why would anyone actually want to play one?
Because of the creativity that would ensue. A certain class of people would play just to create experiences that others can enjoy, and another class of people would play just to experience those experiences. Over time, I'm sure, conventions will be developed over what is allowed and what isn't, but that still doesn't prevent someone from creating their own “world” within the WikiMUD universe. I can see people creating multiply different worlds within a single WikiMUD. Some open to all, some open by invite only, some good, most probably horribly bad (Sturgeon's Law: 90% of everything is crap). Much like what happened in Roger Williams' novel, The Metamorphosis of Prime Intellect (where a computer gains self-sentience and enough power to literally create worlds to anyone's design, although I don't see the WikiMUD actually gaining sentience).
I for one would love to see something like this—to see what people would do with such an open ended and extensible system where anyone can add to it. While I'm sure there are MUDs out there that allow people to extend them, I suspect the additions are mostly limited to rooms and maybe objects. To allow the editing of everything though …
Would definitely be interesting.