14 Jul, 2009, Kayle wrote in the 1st comment:
Votes: 0
So with the decision to write a base from scratch, I've had to start looking at design issues from a different light. And one of the problems I've come across is how to handle the relationship between a socket and any form of "body" in the game world, be it a players body, or a mobs body that has been possessed or what have you. It was suggested since I'm using C++ as the core, to have a separate class that handles how to drive the body, and have the socket be part of that, kinda like a brain, and then if there's no socket it swaps from socket control to whatever handles mob control. So I'm gonna ask around and find out what other people have done with this kind of thing.

Does anyone have an original way of handling this? Or does most everyone follow the same route that Diku did?
14 Jul, 2009, David Haley wrote in the 2nd comment:
Votes: 0
I would go for the "brain" concept. In an idealized world, the "brain" is sent events regarding what happened to the actor; if the brain is in fact a player, those event messages get converted to text and sent down the socket, and if the brain is an AI, the events are left as-is in its machine-readable format. The brain drives the character by sending commands to be interpreted; if it's a player the source is text over the wire and if it's an AI, the source is, well, the AI.

This is interesting because it lets you do all kinds of things like driving a character from the web, very easy implementation of mind-control etc., and so on. You could even have multiple brains attached to a mob! This would let you mix-and-match various AIs, for instance you could create a city guard armed with a bow that has the "City Guard" AI attached in addition to the "Archer" AI.

There are some shortcuts that you can and probably should take, such as for example not having NPC AIs literally construct command strings to be parsed; your command infrastructure should take parsed arguments, such that AIs can just pass along the arguments directly. The command interpreter layer for players would be responsible for parsing arguments to this format.
14 Jul, 2009, Kayle wrote in the 3rd comment:
Votes: 0
The brain idea intrigues me, and I'm more than likely going to pursue that path, but my posting this was mainly a curiosity thing. I wanted to see what other people had done to handle it. And find out how it was working for them, if they'd had any drawbacks or whatever. These are the kind of things I find myself pondering now. Instead of just wondering how I should do something, now I find myself wondering how other people have done something. It's odd to be on this side of the fence, yet strangely fun. :P
14 Jul, 2009, KaVir wrote in the 4th comment:
Votes: 0
Kayle said:
It was suggested since I'm using C++ as the core, to have a separate class that handles how to drive the body, and have the socket be part of that, kinda like a brain, and then if there's no socket it swaps from socket control to whatever handles mob control. So I'm gonna ask around and find out what other people have done with this kind of thing.

Yeah, that's pretty much what I do - a Thing and a Brain can be connected to each other, with the latter controlling the former. Currently only the Creature class (derived from Thing) uses a Brain, but there's nothing stopping me from giving a World or an Object or whatever else a Brain. In fact at one point I was planning to create a WeatherBrain for Worlds, and I may still do so one of these days.

The HumanBrain is derived from Brain, and contains a socket object. If you go link-dead, your brain vanishes and your body will sit there like a lemon. If your body is destroyed while you are connected, your brain will still function as an account - allowing you to chat, reload a body, etc.

There's a MobileBrain for mobs which includes responses to certain actions, but primarily provides combat AI (because combat is manual). I also added a WarBrain for mobs who play the war minigame (based on poker, so it required a completely different set of logic).

Some years ago there was an amusing bug whereby players with the same name as mobs would kick off the MobileBrains when they connected, taking over the mobs' bodies.

One problem is that if I wanted a MobileBrain to control my body, my body would in fact be treated as a mob - for example, it wouldn't save. Thus I would probably add a different brain type if I wanted players to do stuff while link-dead.
14 Jul, 2009, Kayle wrote in the 5th comment:
Votes: 0
That's along the lines of what I was thinking of doing. But, forgive me if this seems ignorant, but what all would you put in the brain class? The Socket/AI controllers would be the only thing I could think of. I might be looking at things in too narrow a fashion, but what would be shared by both that inheritance could be used?
14 Jul, 2009, KaVir wrote in the 6th comment:
Votes: 0
Kayle said:
But, forgive me if this seems ignorant, but what all would you put in the brain class?

The brain base class is only there to provide a generic interface. The idea is that I can do things like this, without needing to know what sort of brain it is:

void CmdTest( IBrain *apBrain, std::string &arCommand, std::string &arArgument )
{
IThing *pBody = apBrain->GetThing();

if ( pBody == NULL )
{
apBrain->PutOutput("Oh no! You've lost your body!\r\n");
return;
}



}
14 Jul, 2009, David Haley wrote in the 7th comment:
Votes: 0
So you do it with actual text messages rather than machine-readable event types with parameters? (or something similar)
15 Jul, 2009, KaVir wrote in the 8th comment:
Votes: 0
Not sure I follow…I send text messages to the player using actual text messages, yes…
15 Jul, 2009, David Haley wrote in the 9th comment:
Votes: 0
You said it was a generic interface, and the example you showed was sending a literal string to a 'brain' object. How does this work with NPCs? Do you send literal strings that must be parsed, instead of some kind of machine-readable message?
15 Jul, 2009, KaVir wrote in the 10th comment:
Votes: 0
I could, but no - there's a SetKnowledge() method I use for sending that sort of information. For example when you attack someone, the following code is executed:
if ( apTarget->GetBrain() != NULL )
{
// Inform the target that s/he has an attacker.
apTarget->GetBrain()->SetKnowledge( IBrain::eATTACKER, apHitter->GetID() );
}

SetKnowledge() is overloaded by each brain class. If it's a HumanBrain, they'll check whether the autotarget config option is on, and if so they'll target their attacker. If it's a MobileBrain, they'll draw an appropriate weapon and start fighting.
15 Jul, 2009, elanthis wrote in the 11th comment:
Votes: 0
My setup makes use of several different concepts to get the core functionality. There is a base Actor class that represents all the shared stuff a player or mob might have, includng inventory, skills, etc. Most of the class is just virtual methods, since NPCs don't actually store all that information on a per-NPC basis, but instead use shared blueprints. The Player class then includes all the additional player-only stuff (experience gain, etc.) and the NPC class includes all the NPC-only stuff (blueprint inheritance, and so on).

The actual network stuff is all covered by a Session class, which has a couple derived classes for different types of connections (TELNET, mudlink, HTTP, etc.). The class has Drivers to cover different modes, including login, character generation, the main menu, and game play. The PlayDriver links to the Actor and the Actor then links back to the Session when in a playing state.

All in all it's pretty similar to what KaVir has. The only real difference – and this isn't a feature I even care about – is that I can have a Session and an AI attached to an Actor simultaneously, in cases when you want a Player to be charmed or something, or if you want a player to have an out-of-body experience watching everything some NPC does.
15 Jul, 2009, Idealiad wrote in the 12th comment:
Votes: 0
This is an interesting discussion for me because while I'm not working on a mud right now I am writing a roguelike, and muds have influenced my design a great deal. Currently I have a Thing class, which I attach a Brain to when creating an item, a creature, or any world object (a level or a town as well). Then depending on the template of the object the Brain gets a number of handlers that implement functionality like AI or so on. However the player client interface with input and display is separate – I just keep a reference to the current player object in the client. So in theory the player could play as a fortress ;D.
15 Jul, 2009, quixadhal wrote in the 13th comment:
Votes: 0
elanthis said:
My setup makes use of several different concepts to get the core functionality. There is a base Actor class that represents all the shared stuff a player or mob might have, includng inventory, skills, etc. Most of the class is just virtual methods, since NPCs don't actually store all that information on a per-NPC basis, but instead use shared blueprints. The Player class then includes all the additional player-only stuff (experience gain, etc.) and the NPC class includes all the NPC-only stuff (blueprint inheritance, and so on).


The nice thing about that is you can easily make special NPC's which do save all their data, and which would gain experience and evolve… in other words, "boss" mobs which only reset to their blueprint if they are killed (if even then).

I do like the ability to mix session and AI's, for exactly the examples given. Having a party member be charmed and under the control of the enemy is a wonderful (frustrating, scary, evil!) thing to have… World of Warcraft does this, and the AI is smart (dumb) enough to "waste" all your long-cooldown spells for you.

The out-of-body thing would make the "switch" command easier to implement, since you could passively hook to a mob and then inject commands to it as you wanted.

Just as an afterthought, Kayle, this might be the point where you decide to place hooks for an account system. I know some people don't care about it, but if you build the data structures to support one, it's easier to make it a no-op than to kludge it in after the fact.

I'd also suggest making a "Player" class that's distinct from a "Admin" class… that is, your account stores permissions and then can instantiate a player object or an admin object for your character. If you are a player object, you simply cannot do anything admin-related. That would save you some checks down the road, as the first check on any privledged operation is to see if you are an Admin. Note that I used "admin" to mean any kind of above-game character, including builders.
15 Jul, 2009, flumpy wrote in the 14th comment:
Votes: 0
Here's what I did in GroovyMud. You'll have to forgive me because I had no prior knowledge of how other muds handle this sort of thing, I just went off my instinct and knowledge.

I use the OO design pattern called the "Observer" patter. This pattern allows loosely coupled objects to send "events" to each other in much the same way as your GUI works. Every object (that I want) is Observable. All containers are Observers of all my objects. When something happens, and event is "fired" by the observable object and the observers are notified of something happening with an "update" method. This update decides what to do with the event, but mainly unless its a system event it gets distributed amongst the contents of the container.

Objects in the game (or even not in the game) can also be an event listener. The object can decide what to do with the event its self, as well as consume it so no one else gets it. The events get processed by sets of triggered behaviours that may or may not be added to the MOB object, which decide how to control the mob or player based on the type of the event. I have three methods on my listener interface, onBeforeMudEvent, onMudEvent and onAfterEvent. This gives me the ability to control what happens before, during and after an event has happened. E.g. when a player moves, a movement event is created, the mob in the room gets delivered the event before it happens and consumes it so the player cannot move. Or, when a player gets an object, an event happens, and afterwards it causes the room to shake and the player to be kicked out etc etc.

I also have an interface called Alive, which lets me get hold of the players "terminal" object and ultimately write things to their console. This just lets me get an easy handle on things that can be sent message events.

I don't have a "brain" encapsulating any of this, I suppose I could if I wanted, but it still gives me flexibility to have objects that observe others without being alive, or alive objects that don't react to events.

I think whatever you decide, remember to loosely couple the "things that happen" in your game from the "things that mobs do". This will give you the flexibility you need to create any kind of world you like.
15 Jul, 2009, KaVir wrote in the 15th comment:
Votes: 0
elanthis said:
All in all it's pretty similar to what KaVir has. The only real difference – and this isn't a feature I even care about – is that I can have a Session and an AI attached to an Actor simultaneously, in cases when you want a Player to be charmed or something, or if you want a player to have an out-of-body experience watching everything some NPC does.

Well I could add separate AI functionality to the HumanBrain easily enough, but I do like your idea of having the AI as a separate module that can be plugged in to a brain. My AI functionality tends to be highly coupled with the brain itself (which is why I created a different brain for mobs that play the 'war' minigame), although I can add triggers to anything, and they are usually used to handle non-generic activities.

For the out-of-body experience I think it might make more sense to allow multiple brains to be attached to each thing. That way you could also do things like:

* Allow admin to help out newbies by serving as backseat drivers, a bit like the Diku 'snoop' and 'force' commands rolled into one.

* Provide a 'switch' command which works in the same way as the previous example, except it would also supress the former brain.

* Allow two or more players to share the same character at the same time. For example a two-headed ettin, where each head is controlled by a different player.

* Admin or players could attach 'logging' brains for recording their activity. For admin this would work like the Diku 'log' command. For players it could allow them to automatically record PK matches, roleplaying sessions, etc.

* Players could invite other players to snoop on them in a sort of 'spectator mode', with private channels and non-essential data gagged. This could work much like the previous logging example, except it would be real-time, with newbies tuning in to PK tournaments to watch their favourite fighter in action.

* Allow players to add a helper brain which provides client-esk functionality such as aliases and scripting - the R2D2 to your X-Wing. It could also take over should you lose your connection.
15 Jul, 2009, flumpy wrote in the 16th comment:
Votes: 0
KaVir said:
* Allow two or more players to share the same character at the same time. For example a two-headed ettin, where each head is controlled by a different player.


ROFL i nearly wet myself at that idea. how cool :D

KaVir said:
* Admin or players could attach 'logging' brains for recording their activity. For admin this would work like the Diku 'log' command. For players it could allow them to automatically record PK matches, roleplaying sessions, etc.


Groovymud has this feature, although its not very flexible atm.


You always have fantastic ideas Kavir I am very envious :D
17 Jul, 2009, Kayle wrote in the 17th comment:
Votes: 0
Glad I posted this instead of just going at it, I got some good input and ideas out of this, Thanks. :)
0.0/17