Please check out Aarchon !

Member Discussions

terms



[Previous] [Next] [Post] [Reply] [Topics] [Summary] [Search]


1. Java mud design Sun Jul 18, 2004 [4:56 PM]
Relative
Email not supplied
member since: Apr 4, 2004
Reply
Evenin'.

By day i'm a software engineer, while at night i don a pair of tights and a cape.
I'm in the process of creating a codebase written in Java, and have been looking at other codebases such as CoffeeMud and JavaMud, etc. While i have been quite impressed with these, i have noticed a trend whereby classes are created for different gaming actions, such as 'Look', 'say', etc, whereas perhaps they might better fit the Object Oriented paradigm as methods of, for example, a Creature class, or whatever.
I can see how creating a class to handle each event would make the coding perhaps less complicated (depending on your perspective), but it seems odd to me to use an object oriented language like Java, with its overheads, to create a program in a manner which, essentially, equates to traditional functional programming.

I'm aware that the overheads involved with using Java are of little importance using modern, fast equipment, and am mainly interested if anyone has an opinion as to why creating a mud in this manner would be beneficial, as opposed to using Java purely because the creator preferes to do so (which is perfectly okay with me).

I'd guess i'm fairly inexperienced compared to many of you and would appreciate any insight that can be offered :)


2. RE: Java mud design Sun Jul 18, 2004 [10:04 PM]
cwac5
cwac5 at hotmail
member since: Jun 1, 2001
In Reply To
Reply
I am not familiar with the codebases you mentioned, but I assume you are refering to what is commonly known as the 'command pattern'. This is a design where each class extends an interface that specifies one method to call, so the class can be determined at runtime, and the behavior is determined by this. For example a Look class might extend the Action interface which calls for an execute() method. so if the player types 'look' a lookup in a hashmap might take place and the Look class is passed to a method that calls the execute() method. This way every action you add to the game simply has to extend the Action interface and be added to the hashmap and it is now usable by the game without modifying any other code.

This is a highly object oriented way of doing things, where the other approach you mentioned, of adding a new method per action, is certainly acceptable and probably faster, but not considered to be as OO of a design.

Let me know if this is unclear, it is often easier to write some simple code rather than to explain it.


3. RE: Java mud design Mon Jul 19, 2004 [4:38 AM]
fmike
Email not supplied
member since: Sep 17, 2003
In Reply To
Reply
For Java codebase I'm working on I'm also use functional way
(fuctional inheritance/dependency). I think the pure OOP
inheritance/polymorph is less convinient way to organize action
flow than low-level function where you can make a checks like 'if
(creature)... if (player)' several times in the same function.


4. RE: Java mud design Mon Jul 19, 2004 [10:32 AM]
Teelf
Email not supplied
member since: Apr 5, 2002
In Reply To
Reply
I don't think it's related to OOP. It's more of a way to get around the fact the functions are not first class objects as they are in other languages (ML, Lisp, etc). If Look becomes a class, then you can do inheritance on the action itself. If its a method of a class, you can't. See Bartle's series of articles on Skotos for this idea taken to the extreme.


5. RE: Java mud design Mon Jul 19, 2004 [11:17 AM]
Relative
Email not supplied
member since: Apr 4, 2004
In Reply To
Reply
Thanks for your replies. Some interesting ideas.
I thought that the main reason was probably convenience as fmike indicated (Pain mud was what i meant to say when i mentioned JavaMud in the original post).

I prefere to try to keep the propgram structure as 'real world' as possible and to make as best use of polymorphism as possible, hence 'look' being a method of classes implementing a 'Visual' interface etc. Of course this all comes down to personal preference; and while my code is still in it's infancy this works wonderfully, although im sure i may find things becoming more hairy as it progresses.

The way i currently have the system working (for anyone that feels inclined to pass comment) is as follows:

*My command interpreter class reads player input and tokenizes it.

*Possible valid commands are stored in arrays associated with the appropriate interface or class type.

*The arrays of commands are iterated through looking for a match with the first token of player input, starting with a full match going down to the first letter.

*if a match is found the MudObject object is cast to the appropriate type. If this cast is successful the functionality of the reflect package is used to invoke the method in the newly casted MudObject. Otherwise the iteration process continues.

* All physical entities within the mud extend MudObject, wiich defines most of the core methods.
MudObject-->Container-->MobileContainer-->Creature-->Humanoid-->Player-->Vampire etc.

* I simply add new or altered methods as the chain/s grows.
( + a few static helper methods here and there )
It all works fine at the moment. One thing i have found nesecary is to break down methods into fairly small 'sub-Methods' to avoid too much code repetition between functionaly similar classes.

I think i've forgotten the original intent of this post. My apologies :P
















6. RE: Java mud design Mon Jul 19, 2004 [11:56 AM]
Teelf
Email not supplied
member since: Apr 5, 2002
In Reply To
Reply
In particular, I'd read http://www.skotos.net/articles/dawnof05.shtml about some problems with designing a mud that way.


7. RE: Java mud design Mon Jul 19, 2004 [12:44 PM]
cwac5
cwac5 at hotmail
member since: Jun 1, 2001
In Reply To
Reply
A couple points/things to consider:

Unless I am misunderstanding your design you are going to end up with MudObject having hundreds if not thousands of methods.

You are losing any speed gains from method calls rather than command objects by using reflection. You are also losing the OO advantages of command objects.

How do you handle validating if a player should be able to use a method? I assume the method itself is doing this? For example all Vampires have the bite() method, but perhaps you only want lv 10+ vampires to be able to use the skill?

There is nothing wrong with your design, and if you are successfully using reflection I can only assume you know what you are doing. I only bring up these points because I am on my 4th iteration of my codebase and I initially took a similar path until I started having scalability and maintainability issues. It all depends on how ambitious of a project it is.


8. RE: Java mud design Mon Jul 19, 2004 [5:32 PM]
lindahlb
Email not supplied
member since: Mar 2, 2001
In Reply To
Reply
The point of the Skotos article is to argue for dynamic behavior inheritance. Classes don't exist (except for possibly initial instantiation of objects). Objects contains a set of reactions as well as a set of data (hidden - and used to calculate reactions). One would only instaniate objects from other objects, instead of classes, which not only copies data, but behavior as well. Overriding behaviors can then be done dynamically, which is well-suited for AI and MUDs (where builders are often hindered by lack of flexibility in templating). Copying behaviors from another object simply means asking for it's reaction object which is mapped to the event type in question. This lends itself well to NPC learning.

Example implementation of "dataspace inheritance":
http://www.codealchemy.org/phpBB2/viewtopic.php?p=142#142

Note that this approach is NOT necessarily better than static behavior inheritance, i.e. C++ classes. It often leads to very under-structured objects which one can hardly assert anything about (unpredictable) - hell to debug, but interesting from an interaction point of view.

A hybrid method would be using C++ class methods to fall back on, inheriting from strict C++ classes, but using a sinlge reaction map object (perhaps a list or array implementation) to override specific reactions. One must taken into account the back-end storage and typical coding style to determine what, if any, dataspace inheritance should be incorporated.


(Comment added by lindahlb on Mon Jul 19 18:34:34 2004)

Brian Lindahl
Development Director
The Cathyle Project

(Comment added by lindahlb on Mon Jul 19 18:49:18 2004)

Oops, bad link, here's the real one:

http://www.codealchemy.org/phpBB2/viewtopic.php?t=53


9. RE: Java mud design Tue Jul 20, 2004 [2:15 AM]
Teelf
Email not supplied
member since: Apr 5, 2002
In Reply To
Reply
Classes don't exist (except for possibly initial instantiation of objects)

This depends on your definition of a class. I would argue each atom in the hierarchy is a class and an object because they can have other atoms(classes) derive from them (you could argue the leaves aren't classes because nothing derives from them).

Objects contains a set of reactions as well as a set of data

Objects contain nothing. Everything is contained within the functions only. Objects exists solely for thier type.

Example implementation of 'dataspace inheritance':

Any implementation of Bartle's design would require multimethods, something C++ can't simulate directly. However you can do dataspace inheritance as a separate feature.


10. RE: Java mud design Tue Jul 20, 2004 [9:43 AM]
lindahlb
Email not supplied
member since: Mar 2, 2001
In Reply To
Reply
This depends on your definition of a class. I would argue each atom in the hierarchy is a class and an object because they can have other atoms(classes) derive from them (you could argue the leaves aren't classes because nothing derives from them).

True, I should have mentioned that I meant classes in the sense of being seperate from objects, as C++ and many others (if not all, but definately most) OO languages define them.


Objects contain nothing. Everything is contained within the functions only. Objects exists solely for thier type.

Any implementation of Bartle's design would require multimethods, something C++ can't simulate directly. However you can do dataspace inheritance as a separate feature.


Sorry, I got off topic and moved from talking about how I got from reading Richard's article on multimethods (he doesn't use this term, but this a standard term for what he describes) and turned it into a discussion about dataspace inheritance. I guess the best explanation for this deviation would be the long hours I'm working - I'm completely wiped by the end of the day, whoops.

Anyhow, multimethods can be implemented using my example, quite easily. In the event code, we process the interaction between all involved objects, and then dispatch events to respond to for each object. Objects then respond to an event in their own fashion.

For example, in the swing event, we mediate the collision, and calculate the results. We then tell the target to react to damage, the actor to react to the energy expent and damage to itself and the audience to react to seeing the collision. The event decides what events each object should react to (or what happens to each object) - multimethods, it is then up to the object to react to the event in the manner implemented by it's own dataspace based upon dataspace inheritance.

So, the topics are loosely related, but still, I'm surprised I moved from one topic to another without even realizing it - especially considering the topics were not closely related.

An extra blurb on dataspace inheritance:
Objects would need the knowledge of what reactions they have, some sort of binding - in this case the binding is done as data, since it must be dynamically inherited - which requires a deviation from seperating, entirely, the code from the object. The object asks it's reaction map to react upon an event - but it needs to know what it's reaction map is.


11. RE: Java mud design Tue Jul 20, 2004 [2:12 PM]
Teelf
Email not supplied
member since: Apr 5, 2002
In Reply To
Reply
Anyhow, multimethods can be implemented using my example, quite easily.

I'm not seeing it... can you give an example of how it's equivalent to multimethods?


12. RE: Java mud design Tue Jul 20, 2004 [4:42 PM]
lindahlb
Email not supplied
member since: Mar 2, 2001
In Reply To
Reply
class Event {
protected:
  class Fn {
    virtual void operator()(...) = 0;

  class Map {
  virtual Fn& operator()(ClassType) = 0;
  virtual Fn& operator()(ClassType,ClassType) = 0;
  // one for each mapping you'll need
  };
};

class SomeEvent : public Event {
public:
  virtual void execute() {
    sExcuteSomeEvent(actor.class(),target.class())(target,class);
  }
protected:
  static Map& sExecuteSomeEvent;
};

(Comment added by lindahlb on Tue Jul 20 18:07:47 2004)

I never said it was equivalent. I said it was pretty easy to implement. What gets complicated is lookup and matching algorithms that are actually efficient. Caching along with hybrid-lookup mechanisms tend to be most efficient from what I've read.

In C++, we have multimethod programming with a reverse lookup with the first iteration being a table lookup:
  someObject[function] (and then delegate further lookups)
and the second to nth iteration being done explicitly by the programmer.

So basically C++ does the first level lookup for you, but its up to the programmer to do deeper argument lookups. At the second level, you can choose to use multimethod programming techniques to delegate what code is executed for the rest of the arguments (beyond the first).

Consider a two argument multimethod lookup, is there any substantial difference between the following:?
someFunction[object] (multimethod programming)
someObject[function] (C++ virtual functions)

I would answer no. All it comes down to is whether you want to attatch code to a function or to an object. Attaching code to an object works better in practice because it supports locality of reference, because functions typically don't have data.

Basically, what it comes down to is, do you want good locality of reference, or do you want modularized code?

Trick question, with declarations being seperate from definitions, you can define all your virtual functions called 'swing' in the same file - if you really want to.


13. RE: Java mud design Tue Jul 20, 2004 [4:57 PM]
cwac5
cwac5 at hotmail
member since: Jun 1, 2001
In Reply To
Reply
Very interesting... but we have certainly gotten off topic, unless you have a code example in Java of something equivelant...


14. RE: Java mud design Tue Jul 20, 2004 [10:26 PM]
Teelf
Email not supplied
member since: Apr 5, 2002
In Reply To
Reply
Very interesting... but we have certainly gotten off topic, unless you have a code example in Java of something equivelant...

Not really. Even though the OP put the word 'Java' in the title, mud design is not confined to Java. And the specific question asked transcends any one language.


15. RE: Java mud design Wed Jul 21, 2004 [9:19 AM]
datroof
Email not supplied
member since: Jun 9, 2001
In Reply To
Reply
This topic drew my interest because Bartle's Notes from the Dawn of Time series had a profound effect on me while I was designing my current codebase. Although I didn't adhere strictly to his concept of atoms, it inspired my design for managing character actions. My codebase is written in C++, but the ideas are not language-dependent.

Most actions that characters can perform are based on skills. (The few exceptions are behaviors that are crucial to the game engine's operability, such as movement, communication, and object manipulation.) The Skill class has a Use() function that takes three arguments: User, Target, and Tool. Using Bartle's syntax, every action takes the form of {SKILL USER TARGET TOOL}, like so:

{PUNCH PLAYER ORC NONE}
{ARCHERY PLAYER ORC LONGBOW}
{COOKING PLAYER MEAT STOVE}
{LOOK PLAYER ORC NONE}
{LOOK PLAYER ORC TELESCOPE}

There are several Skill classes that derive from the base Skill class to handle common types of skills, such as Attack skills. I added these skill types to the codebase itself to simplify the builder's job and to boost performance. If I were so inclined, I could implement each unique Skill as its own derived class, but I use an embedded script interpreter to much the same effect.

Every skill can have an onuse script associated with it which accepts the same arguments as the skill->use() function. Whenever a skill is used, it triggers the script. This provides a handy method for providing specialized functionality.

Using my codebase, even simple activities like eating and drinking are implemented as skills. If it's something that anyone should be able to do, I simply give it zero prerequisites.

A crude script for the Look skill might look like this (in pseudocode):

look.onuse($user, $target, $tool) {
    $max_distance = $user->vision
    if ($tool->type == "eyeglass") {
        $max_distance += $tool->bonus
    }
    if (distance($user, $target) < $max_distance) {
        tell($user, "$target->description")
    } else {
        tell($user, "You can't see $target->name from here.")
    }
}


The system allows for much more powerful scripts, but that's the general idea.

So far, this design has proven robust enough to handle any skill or behavior I've wanted to add. If a skill is too specialized to be implemented as an existing derived skill type, its onuse script can override the inherent skill behavior.


16. RE: Java mud design Thu Jul 22, 2004 [12:00 PM]
Relative
Email not supplied
member since: Apr 4, 2004
In Reply To
Reply
Thanks for your input guys.

The replies have gotten me thinking and i am considering creating a version using the command objects as most of you suggested. Having not looked at any Mud code until recently i have only just started to realise that the nature of a Mud means that i cannot always do things the way i think they 'should' be done.
Although i think that Mr Bartles points are greatly exagerated, and avoidable to a certain degree, they have made me realise that my initial model is just as non-ideal as they method he proposes, while his offers some distinct advantages.
Another factor in my change of opinion results from some very brief research into the overheads involved in using the reflect package's functionality. If i'm going to code my mud in a way that i'm not entirely comfortable with, i may as well do it the most efficient way.

Cheers :)


17. RE: Java mud design Tue Jul 27, 2004 [7:02 AM]
Skarsnik
Email not supplied
member since: Nov 14, 2002
In Reply To
Reply
"If i'm going to code my mud in a way that i'm not entirely comfortable with, i may as well do it the most efficient way."

When coding (almost) anything the last thing you should consider is efficiency. Write the code and then perform some analysis on its efficiency and then fix up the slow bits the analysis identified.

I think commands fits fine into OO, it just requires you take a different view of things when modeling your heirarchy.

And finally I suggest you go and buy "Design Patterns" by Erich Gamma, Richard Helm, Ralph Johnson, John Vlisside. Without a mentor you might not gain much out of it, but its worth the gamble!

Skarsnik


18. RE: Java mud design Fri Aug 13, 2004 [11:06 PM]
tvaananen_
Email not supplied
member since: Aug 13, 2004
In Reply To
Reply

Java is a fair choice for creating a MUD. I have been programming with C, C++, Java, and others for quite a while, and I think Java strikes a good balance between productivity, easiness and performance.

People have this persisting idea that Java is slow - have you compared it? Modern JVMs compile the byte code to machine language and run Java like any native application, so why would it be considerably slower? There is certain overhead penalty in the carbage collector, but then again, you do not want to bother with memory management yourself, right?

About MUD design... I would concentrate on a bit larger issues than intricasies of the command pattern. First off the bat you need a good lightweight framework to support your MUD. You do not want to concern yourself with all kinds of crud code that really has no direct function from the game perspective. You want all that necessary plumbing done for you before you even start your library.

I would take a look at some of the light containers available, such as Spring, Pico, Avalon, etc. I have personally used Spring, and it really is a life saver (look at www.springframework.org). It can really make management, and configuration of objects/components easy. Better yet, you reduce dependencies and crud code you normally get stuck with on your own. Spring supports all sorts of popular Java libraries and frameworks right out of the box. Spring even has support for very advanced programming concepts like aspect oriented programming (AOP).

I hope this helps you get started and makes the whole ordeal easier to approach, when the biggest basic design decisions of your library are already taken care of by the professionals. You can't beat that.


19. RE: Java mud design Wed Sep 22, 2004 [1:24 PM]
tandonmiir
Email not supplied
member since: Nov 5, 2002
In Reply To
Reply
I'd advise that book as well. Just today in my programming class, we learned all about how many ideas are expressed in Gamma/Helm/Johnson/Vlisside (aka the Gang of Four.)

If you're interested in developing any sort of multi-layered program, pick it up.
-----------------------------
catch(Exception ex)
{
// oh crap!
}

-TandonMiir




[Previous] [Next] [Post] [Reply] [Topics] [Summary] [Search]