07 Aug, 2011, Nich wrote in the 1st comment:
Votes: 0
I'm working on a MUD using Evennia (here) as a base.

For my requirements, I need Objects in my MUD to be fairly realistic, and highly mutable. Most of the gameplay will come from using/manipulating objects in interesting ways.

I also want to place a limited set of build tools in the hands of the players, so that they can (within reason) create new objects on the fly. This includes really fringe cases, like a stone statue that can be turned into a golem which can then attack, and be damaged like a mob, or a chair that can be animated an ridden like a horse (but not turn into a horse, just ridden like one). The goal is to have a MUD that's dynamic enough to create worlds such as Harry Potter, Full Metal Alchemist, Looney Toons, Fantasia, etc., with high levels of fidelity, not just skills that "look" like they're doing what they should, but actually have visible effects.

This means that somehow, every object needs to know how to react to every effect, if at all.

Evennia seems to assume a standard OO model (which makes sense, since we're dealing with python here). OO models have proven themselves useful in many MUDs, but I don't think they'd work here. Take for example, a rose. In a standard object model, the rose could be an instance of flower, which is a subclass of plant, inheriting from the base object. The properties of flower allow for the user's creation of roses, petunias, daffodils, or whatever kind of flower they want, as long as the flowers conform to the properties of flower that I have designed.

What if they wanted a venus flytrap, however? They could make a flower, call it a venus flytrap, and describe it prettily, but it wouldn't catch flies. There would be no reasonable way to make it catch flies, either. I wouldn't want to add a damage field to flower when it's going to be null 99% of the time.

Multiclassing could solve this, but this requires that I allow for creation and storage of dynamically generated python classes, and that seems messy and prone to bugs.

There are other options I considered. One was having components. Objects by themselves do almost nothing, but contain a list of components that handle the data they use and what they're capable of doing. Thus, a venus flytrap could have all the components a plant normally has, plus an attack component, and a targetting component to attack flies.

The other is giving the user some control of Evennia's scripting system. This should allow for almost anything to be done, but comes at the cost of needing to create some kind of user friendly python interface for people who don't know python (and a security system to stop people from crashing the game with arbitrary python code).

I was strongly considering developing an entity system (here), which behaves similarily to a component system, but is highly memory efficient (The component system described above would have an instance of a script for each object. This is probably ok, but doesn't scale well for large numbers of objects, and causes problems if a frequently used script (say, AI) is particularly intensive. In an entity system, there is only one instance of each script, which processes a list of objects that register with it. This would be excellent in a system with few scripts and lots of objects). The problem is that Evennia's object system is very tightly integrated with everything, so a redesign would have me changing just about everything about the codebase. I think I would almost be better off starting from scratch (something I don't want to do). Doing this, I think, is chasing performance gains where they might not be required.

Which of the ideas I listed do you think best fits my requirements? Are there any paradigms I'm missing that would allow for highly mutable objects? Am I barking up the wrong tree entirely? (too bad! Doing it anyways! :redface: :biggrin:)
07 Aug, 2011, Runter wrote in the 2nd comment:
Votes: 0
Quote
Am I barking up the wrong tree entirely?


Yes. There's nothing wrong with object oriented design to solve this problem. The inheritance model isn't totally indicative of object oriented design. A totally validly designed object in OOP doesn't have to have an inheritance tree. Furthermore, composition (imo) is a form of multiple inheritance. And composition is a good way to solve this very problem.

Quote
What if they wanted a venus flytrap, however? They could make a flower, call it a venus flytrap, and describe it prettily, but it wouldn't catch flies. There would be no reasonable way to make it catch flies, either. I wouldn't want to add a damage field to flower when it's going to be null 99% of the time.


But none-the-less, it *is* a flower that catches flies.

class Flower ;
end

# Flower that doesn't eat flies.
class Tulip < Flower
end

# inherit flower
class VenusFlytrap < Flower
def eat_flies
end
end


That's clearly modeled as a flower that has the eat_flies method. I suspect you have better examples than this, but I think this one didn't do us any good in explaining why inheritance wasn't good enough. What you really probably want is some type of composition that doesn't rely on an type of inheritance hierarchy.
07 Aug, 2011, Nich wrote in the 3rd comment:
Votes: 0
The problem is that that's on the developer side, when I want it accessible to players.

Unless I allow them to submit python classes as objects (and I think that's expecting a lot from players), then that method won't work.

That's why I said that a Rose would be an instance of the flower class. It probably wouldn't have a class of it's own, because it doesn't do much that an ordinary flower doesn't already.

Unless there's a way of attaching eat flies to flower at run time, simply creating a Venus Flytrap class won't be sufficient. The question is how to best to that attachment at run time.
07 Aug, 2011, Nich wrote in the 4th comment:
Votes: 0
Runter said:
Quote
Am I barking up the wrong tree entirely?


Yes. There's nothing wrong with object oriented design to solve this problem. The inheritance model isn't totally indicative of object oriented design. A totally validly designed object in OOP doesn't have to have an inheritance tree. Furthermore, composition (imo) is a form of multiple inheritance. And composition is a good way to solve this very problem.


This is fair. I don't think it will be impossible to do what I want within the OO model, I'm just having trouble seeing exactly how. The solution will definitely be some form of composition.

As for composition being multiple inheritance, I think you have it backwards. Multiple inheritance is definitely composition (of the N parents being inherited from), and you can implement composition as a form of inheritance, but there are other ways of doing it.

The main thing is that it has to be done at run time, which means that standard inheritance is (sort of) off limits as a means of creating composition (It's possible to create classes dynamically in python, but how do you persist them? As opposed to a list of component classes, which would be easier).
07 Aug, 2011, David Haley wrote in the 5th comment:
Votes: 0
Nich, you're going to have two layers of implementation here. One is how things look in the code; the other is what you present to players.

You don't see how to do this because you're thinking that you'll be using OOP only in the code, and are not sure how to present that to players. You're right, you won't easily be able to. But that doesn't mean that you can't use the concepts. This is why you believe that inheritance is off the table because it has to be at runtime. Why not implement dynamic inheritance? You'll be implementing inheritance within your language, that might already have its own inheritance. Remember: there are two layers, and you must not mix them up.

Note that Runter didn't say that composition == multiple inheritance, he said it was a form of it. In fact, that is likely to be the most successful way you'll have of implementing this system: allow an object to "inherit" from several others by letting the player compose functionality together. In the code, you will have components that are composed. What players see could be an inheritance tree.
07 Aug, 2011, Tyche wrote in the 6th comment:
Votes: 0
In the article on entity-components, the one (maybe only) thing that struck me as novel and interesting was the possible use of multi-threading by component.
Not compelling enough for me to attempt, but probably compelling for those designing games for more than a couple hundred players.

I favor using runtime dynamic object-oriented languages for user-free programming environments.
I'd recommend taking a look at [link=file]727[/link].

Just a brief summary. ColdC is a prototypical object oriented language. There are no classes. Every object is it's own instance. It implements multiple inheritance sort of the way Python does (at least the search chain is depth-first and left to right). I don't know Python, but I suspect that's where the similarity ends, because ColdC's inheritance is dynamic, all data is private (fully encapsulated) and uses a form of lazy copy on write for ancestor values. Now if you've been taught or believe in the "one true way" of design according to Eiffel, C++ and Java class-oriented programming you're going to have to do some unlearning. ;-)

Ruby gets you part of the way with the everything is an object and allowing you to inject class objects into the inheritance heirarchy. It doesn't let you insert them anywhere however, nor remove them (although there are extension patches to do so, nor rearrange the tree (which IMO is important)

* Forget the has-a/is-a class-oriented programming dogma
* Inheritance is composition
* Multiple inheritance is good design

Anyway the MI mechanism in ColdC is used similarly to the entity-component model, though it's not necessary to make a distinction between entities and components. For example in ColdCore…

A particular room/place like $the_pit has as its parents:
@ancestors here

$the_pit [*-mvc]
$place [*fmvcG] (MI)
$location [*fmvc] (MI)
$physical [*-mvc] (MI)
$described [*-mvc] (MI)
$has_name [*fmvc]
$foundation [*fmvc] (MI)
$root [*-mvc]
$has_commands [*fmvc]
$foundation [*fmvc] (MI)
$root [*-mvc]
$event_handler [*-mvc]
$foundation [*fmvc] (MI)
$root [*-mvc]
$command_cache [*-mvc]
$has_commands [*fmvc]
$foundation [*fmvc] (MI)
$root [*-mvc]
$realm_settings [*-mvc]
$foundation [*fmvc] (MI)
$root [*-mvc]


$location, $described, $has_name, $has_commands are "components" of a $place and instead of implementing a is_a or has_a inheritance model, instead it is a has_part or is_composed_of model. While there are many ways to implement composition, MI is not the favored approach in many other languages.

I'm sure one could implement a roll-your-own-language under python to implement the same concepts. Perhaps even make it look similar enough to regular python to leverage what you or your builders already know.
08 Aug, 2011, Nich wrote in the 7th comment:
Votes: 0
David Haley said:
Nich, you're going to have two layers of implementation here. One is how things look in the code; the other is what you present to players.

You don't see how to do this because you're thinking that you'll be using OOP only in the code, and are not sure how to present that to players. You're right, you won't easily be able to. But that doesn't mean that you can't use the concepts. This is why you believe that inheritance is off the table because it has to be at runtime. Why not implement dynamic inheritance? You'll be implementing inheritance within your language, that might already have its own inheritance. Remember: there are two layers, and you must not mix them up.

Note that Runter didn't say that composition == multiple inheritance, he said it was a form of it. In fact, that is likely to be the most successful way you'll have of implementing this system: allow an object to "inherit" from several others by letting the player compose functionality together. In the code, you will have components that are composed. What players see could be an inheritance tree.


Yeah, you're dead on. I'm confusing what I want the players to use with what's going on behind the scenes. In my mind, the players are doing in game interactions: casting spells, drawing magic circles, using hammer-space - the "language" they use will be MUD specific, object oriented (but really only because it's transformations on objects), and imperative (the user is just performing a sequence of actions to get the desired result). It shouldn't actually feel too much like programming, it should feel like magic.

I guess I more or less know what I need to do. I just need to code it, and worry about the details as they come up.

Tyche, I'll take a look at that. I probably won't need to roll my own language, except to help me test/debug at a lower level then my players would normally use.

And yeah, my first language was Java, so I tend to accidentally suck it's paradigms into the things I work on. It's a bad habit I need to fix :).
08 Aug, 2011, David Haley wrote in the 8th comment:
Votes: 0
In fairness, what you're talking about is really not that trivial; there's a reason why you don't see rich (in-game-)object composition interfaces that often. It's hard! :smile: It really does require some mental gymnastics to separate the coding structure you use behind the scenes from the "coding" you present your users to compose objects. It's like having one low-level type system that implements a type system on top of it.

Dynamic languages like Python, Ruby, Lua, etc., just make that distinction that much harder because the language itself allows what you want, so you need to be disciplined in mentally separating internal implementation from what players see.
08 Aug, 2011, Idealiad wrote in the 9th comment:
Votes: 0
Nich said:
The main thing is that it has to be done at run time, which means that standard inheritance is (sort of) off limits as a means of creating composition (It's possible to create classes dynamically in python, but how do you persist them? As opposed to a list of component classes, which would be easier).


I don't understand the problem here – if you dynamically change a class or instance at run-time, why couldn't that be persisted? Nevertheless I would favor a more data-oriented approach, i.e. the second option you're talking about.
08 Aug, 2011, Idealiad wrote in the 10th comment:
Votes: 0
Apologies as it's too late to edit my last post, but I thought this link was worth adding here:

http://stackoverflow.com/questions/10000...
08 Aug, 2011, Nich wrote in the 11th comment:
Votes: 0
Ah, the problem is that (by my understanding), the objects in Evennia are persisted on the fly. If I were designing the object system from scratch, I could design the DB structures to account for this, but I'm designing neither the DB nor the base object.

Since the DB is synchronized continuously, it becomes problematic to change the structure of the objects on the fly, since those changes will trickle down to the database. I'm uncomfortable with my code making major, frequent changes to Database structure. That sounds like a nightmare.

But it's a problem of conflicting designs. Evennia is flexible, but to an extent I'm constrained to do things "their way", and I don't think that dynamically modifying objects is possible without changes I don't want to make.

That's more or less why I'm here. I'm strongly debating starting from scratch (building on top of a network library) if I can't reconcile what I want vs what Evennia offers. But I would be losing a great deal of functionality in the process.
08 Aug, 2011, Runter wrote in the 12th comment:
Votes: 0
Not really useful when dealing with a base that doesn't support it, but object databases are pretty nice.

I like CounchDB.
08 Aug, 2011, plamzi wrote in the 13th comment:
Votes: 0
Nich said:
That's more or less why I'm here. I'm strongly debating starting from scratch (building on top of a network library) if I can't reconcile what I want vs what Evennia offers. But I would be losing a great deal of functionality in the process.


This is just an alternative POV from someone who has a strong non-technical background. Set aside for a moment the technical challenges and go back to questions of target audience and practicality:

If you assign a limited set of properties an object may adopt, it will make your life a lot easier, and it is very likely to please 99% of players/builders. If someone (let's say 1%) wants to be able to define an arbitrary object behavior, is it worth spending 99% of your time building a tool for just them, or do you tell them to learn some scripting skills and give them some extra powers when and if they ask?

And also, what if instead of a super-flexible object creator you create a super-easy way to extend a predefined set of object properties/behaviors? Why not build a tool with which your 1% of advanced users can add object scripts to a library and less advanced users can easily re-use them? That's a lot easier for you, and it could well serve the same end goal.

I believe you're striking gold with the idea that a game should encourage player contributions and creativity 'from the ground up'. But I also believe that 'start from scratch' is rarely the most practical answer to a problem, and this belief gets stronger as the days fly by. What usually happens to me is that even the ideas I thought of as most revolutionary can be realized by tweaking existing stuff in a new way.

Best of luck with this tough nut and please keep us posted on your progress.
08 Aug, 2011, Nich wrote in the 14th comment:
Votes: 0
plamzi said:
If you assign a limited set of properties an object may adopt, it will make your life a lot easier, and it is very likely to please 99% of players/builders. If someone (let's say 1%) wants to be able to define an arbitrary object behavior, is it worth spending 99% of your time building a tool for just them, or do you tell them to learn some scripting skills and give them some extra powers when and if they ask?


This is probably my fault, since I picked a pretty obscure example to begin with. The point I was trying to make with the Venus Fly trap example is that the user should be able to create something that I haven't thought of, not just within the spaces that I've carefully mapped out. In essence, though, what I do want to provide is a scripting language, but integrated with the experience. People who don't program might not realize that they're programming. People who do program might recognize the similarities behind what they're doing, and programming. But it should all be done through in-game interactions with things.

I plan to scale the levelling system to things that affect the world in a more permanent way. Ideally, at max level, the player is already a builder, since building is how they've been playing the game.

plamzi said:
And also, what if instead of a super-flexible object creator you create a super-easy way to extend a predefined set of object properties/behaviors? Why not build a tool with which your 1% of advanced users can add object scripts to a library and less advanced users can easily re-use them? That's a lot easier for you, and it could well serve the same end goal.


That's more or less where I'm going, with the additional goal of providing the tool in such a way that 100% of the players will be able to use/enjoy it (Lofty, but people who can't/don't want to use the tool probably aren't playing. It might just end up being a game for me :P). There won't be a beginner set of tools, and an advanced set of tools, but rather a big set of tools that the user can gain access to, and use at whatever skill level they choose. But, as rightfully pointed out before, how the user sees and interacts with the system is different from how the system is set up. How the system is set up will affect how easy/hard it is to make a reasonable user interface, but they aren't totally dependent on each other.

plamzi said:
I believe you're striking gold with the idea that a game should encourage player contributions and creativity 'from the ground up'. But I also believe that 'start from scratch' is rarely the most practical answer to a problem, and this belief gets stronger as the days fly by. What usually happens to me is that even the ideas I thought of as most revolutionary can be realized by tweaking existing stuff in a new way.

Best of luck with this tough nut and please keep us posted on your progress.


I'm coming to the same conclusion RE: building things from the ground up. My first prototype is languishing unfinished, because I tried to do it from the ground up, and realized that for a lot of components I spent weeks working on, there were not only implementations available, but better ones then mine. That's why this time I'm starting with Evennia as a base. They have a lot of things (Network, persistence) done nicely, and I would rather keep at this point, I think, then try to rebuild them from scratch.

Currently I'm trying to build a component object model on top of their object model. We'll see how it goes.
09 Aug, 2011, Kelvin wrote in the 15th comment:
Votes: 0
Original author of Evennia here. I only got 80% of the way to a "1.0" release with Evennia before I ran out of steam and ultimately passed the torch on to someone else. The from-scratch approach can be fun, just make sure that you're 100% OK with the fact that you're probably going to be working for many many months (years?) for even the simplest game. Evennia was an excuse to learn Python, Twisted, and Django better a good number of years ago, and I worked on it as an academic exercise of sorts. I didn't have a game design in mind of my own, so I mostly just looked at MUX/MUSH and tried to replicate things I liked, sans softcode.

You wouldn't need to be nearly as generic as Evennia if you're building just for your game's feature set, but you're still going to be looking at a huge amount of time. That's OK, and if you're up for it, attack it. But the selfish Pythonista in me wants to actually see some Python MUDs take root, ship, and succeed :)
09 Aug, 2011, Idealiad wrote in the 16th comment:
Votes: 0
Not to derail the thread too much, but if you're looking for something in between Evennia and from-scratch take a look at Pants, a networking library being worked on by a couple of MB members.
09 Aug, 2011, Nich wrote in the 17th comment:
Votes: 0
Kelvin said:
Original author of Evennia here. I only got 80% of the way to a "1.0" release with Evennia before I ran out of steam and ultimately passed the torch on to someone else. The from-scratch approach can be fun, just make sure that you're 100% OK with the fact that you're probably going to be working for many many months (years?) for even the simplest game. Evennia was an excuse to learn Python, Twisted, and Django better a good number of years ago, and I worked on it as an academic exercise of sorts. I didn't have a game design in mind of my own, so I mostly just looked at MUX/MUSH and tried to replicate things I liked, sans softcode.

You wouldn't need to be nearly as generic as Evennia if you're building just for your game's feature set, but you're still going to be looking at a huge amount of time. That's OK, and if you're up for it, attack it. But the selfish Pythonista in me wants to actually see some Python MUDs take root, ship, and succeed :)


I was kind of hoping you would post :). I really like Evennia, and I think it makes a fantastic base for a MUD. I like how it makes very few assumptions about what the implementing MUD will need. This adds work in making a nice MUD specific layer on top of the base, but saves the trouble of trying to strip anything that you didn't want out of the MUD. I think if I weren't trying to do something so strange, it would be really simple to make a MUD in evennia.

Idealiad said:
Not to derail the thread too much, but if you're looking for something in between Evennia and from-scratch take a look at Pants, a networking library being worked on by a couple of MB members.


That looks similar to building out of twisted. I'll consider it if building on top of Evennia really isn't possible.
09 Aug, 2011, Tyche wrote in the 18th comment:
Votes: 0
There's also POO, an implementation of MOO in Python.
10 Aug, 2011, Griatch wrote in the 19th comment:
Votes: 0
Hello, I'm the current maintainer of Evennia, checking in. :)
Quote
Ah, the problem is that (by my understanding), the objects in Evennia are persisted on the fly. If I were designing the object system from scratch, I could design the DB structures to account for this, but I'm designing neither the DB nor the base object.

Hm, Evennia uses an abstraction layer above the database for customizing all game entities. This allows for normal Python classes to be used mostly without needing to care about what happens with the database. That said, whereas you can choose to have e.g. Attributes saved to your object transfer into the database if you want, there is also nothing stopping you from keeping things in memory only, if you don't worry about losing things on a reboot. How do you suggest the db be designed to give you better flexibility for your design?

Quote
Since the DB is synchronized continuously, it becomes problematic to change the structure of the objects on the fly, since those changes will trickle down to the database. I'm uncomfortable with my code making major, frequent changes to Database structure. That sounds like a nightmare.
Again, I'm not really sure what problem you perceive here with respect to the code, so you probably need to expand a little more so I understand what it is you want to do that Evennia cannot. :)

Quote
But it's a problem of conflicting designs. Evennia is flexible, but to an extent I'm constrained to do things "their way", and I don't think that dynamically modifying objects is possible without changes I don't want to make.

This is certainly true, the only way to get 100% control is to build everything from scratch. Evennia does try hard to only offer you the basic building blocks to expand into whatever game you please, but at some common base level is indeed needed. We are however most interested in hearing what does and what doesn't work with that base level! :)
.
Griatch
10 Aug, 2011, Nich wrote in the 20th comment:
Votes: 0
Hi Griatch, thanks a lot for posting :).

If I were in your position, I probably wouldn't make any changes, since the use-case I require is probably not what you intend Evennia to be used for. However, the problem I'm running into is that the basic Object (which Evennia expects for many, many operations) is tied to the DB, so while it's true that you can avoid the DB and keep everything in memory, there doesn't seem to be a way to use a custom DB back-end without re-implementing Object.

The specific problem was that someone suggested using metaclasses to modify objects on the fly. My concern is that that either a) wouldn't work with the object serializer, or b) would work, but terribly (because it would either create a new table for each unique objects, of which there could be uncountable numbers of, or add the new fields to the db, putting a null for the objects that don't have that field

For example, I have a chair, which has a nice representation in the DB. I want it to turn into a mobile, so at run time, I add an attack and health attribute to it using metaclasses. What does the DB model look like now?

However, that's not a problem with Evennia, and I don't think I like that approach anyways. My current attempt creates a new base object under the base object, with a list of components (also objects), and a merge function which takes the commands and scripts registered to the component and applies it to the object. When a method is called on the object, the new object will also be programmed to check if the components have that method and call those. It's not finished, and I'm not sure yet if it will work, but that's my attempt. It shouldn't break serialization, since the components themselves will have their own representation in the DB, and will just be referenced by the objects that need them.

If I would make any change to Evennia as a base, though, it would be to add a layer between the DB and Typeclass so that someone wanting to dodge the serializer can subclass that level, rather then turning the serializer off. i.e. Typeclass should extend Object, not vice versa. That way you could have the other functionalities of Object without interfering with how the serialization works. I think that might just be a personal preference, though, since you can get a similar effect by using ndb and rolling your own persistence.

Edit: I should add that I probably haven't put enough time at looking at Evennia to know what exactly is or isn't possible, so I could be completely wrong about the persistence thing :)
0.0/23