so i'm planning on changing the input model of my mud so that i can have more control over the mobs and npcs
in my mud i have a base MudObject that i derive my other game objects from currently i have Player, Item, World, Area, Room and Wilderness
as i was thinking about mobs and npc with the logical conclusion that they are very similar to players in how they interact with the world and how they are represented to the player as other players, this is leading me to want to create an Actor class that derives from MudObject and the Player, NPC, and Mobs would then derive from the actor class. then each class would have some kind of controller
this brings me to the question of how i should then organize the input controller
right now as it stands the the PlayerObject has a Reference to the client object, where the client is basically in control until the player logs into his character then the PlayerObject takes over control of the input polling the client reference for new lines and then passing those off to the command interpreter ect…
what ideas and suggestions does everyone have, i've just been working on it and banging my head against the wall, and i would prefer not to have to take a month long break until i'm struck with some random stroke of genius
The code base is custom, written in the d programming language i know a lot of programming languages so an idea expressed in one language i can convert to another, i'm having trouble figuring out the path data should take to organize and pass the data around that is received from the client's socket, right now the client object handles the processing of protocols whether it needs to add, convert or reform data that is then sent/received over the socket
in addition to this when data is received from a client it can be setup to either poll the raw data or poll data on a per line basis
in the main loop handle new connections process clients get input process players handle playerstate if state wants input polls for input change state after input if needed send out buffer to clients that was generated during tick/pulse what ever you want to call it rinse and repeat
in the main loop handle new connections process clients get input process players handle playerstate if state wants input polls for input change state after input if needed send out buffer to clients that was generated during tick/pulse what ever you want to call it rinse and repeat
This looks fine, to be honest. It sounds like you're wanting to reduce the differences between NPCs and Players, though, so I have a suggestion. Rather than "process players", make it "process characters" (both NPCs and Players) and handle "input" from both of them. Let's suppose that there's no difference between NPCs and Players except that the latter has a connection to a remote host. Check this out:
for ch in characters: if not ch.brain: continue input_lines = ch.brain.process() # Perhaps: ["look", "say hello", "wield sword"] for line in input_lines: ch.handle_command(line)
Now in this example, ch.brain.process() returns a list of commands that the character has chosen to execute. In the case of a player, ch.brain is actually a wrapper for the connection, so ch.brain.process() retrieves whole lines of input from the connection and returns them as a list. In the case of an NPC, however, ch.brain might be None or it might be an object that generates and returns a list of commands for the NPC to execute when ch.brain.process() is called.
As for what happens in ch.handle_command(), it sounds like you have a command interpreter and so forth already complete. If you want more flexibility in this area, though, you could change the way your characters handle commands after retrieving them from the connection/brain. One way is to have a number of handlers that you can attach/detach from characters and pass input to all of these handlers in turn. In this way you can easily add and remove sets of commands to/from individual characters as needed.
Hope this gives you some food for thought - if you were after something more specific, go ahead and ask. :smirk:
The code base is custom, written in the d programming language i know a lot of programming languages so an idea expressed in one language i can convert to another, i'm having trouble figuring out the path data should take to organize and pass the data around that is received from the client's socket, right now the client object handles the processing of protocols whether it needs to add, convert or reform data that is then sent/received over the socket
in addition to this when data is received from a client it can be setup to either poll the raw data or poll data on a per line basis
in the main loop handle new connections process clients get input process players handle playerstate if state wants input polls for input change state after input if needed send out buffer to clients that was generated during tick/pulse what ever you want to call it rinse and repeat
Although you still haven't asked a clear question, I'm beginning to suspect you're thinking about how to support human input that actually controls npcs/mobiles. Let us know if that's the case. They say that phrasing the right question takes you half-way to an answer. This may be one of those cases.
@chrisd - > that is the type of system that i'm leaning towards, atm
@plamzi -> i am looking at how to control npc/mobs with the human input, i'm also trying to keep things fairly clean, though i am by no means a tidy person, my mind wanders a lot and it hard alot of the time for me to express my crazy little mind =p things that i think are obvious never turn out to be
also i'm trying to wrestle with the idea of what should own the client object should the client object own the reference to the actor(npc/mob/player) or should it be the other way around where the actor owns the client reference
@plamzi -> i am looking at how to control npc/mobs with the human input, i'm also trying to keep things fairly clean, though i am by no means a tidy person, my mind wanders a lot and it hard alot of the time for me to express my crazy little mind =p things that i think are obvious never turn out to be
also i'm trying to wrestle with the idea of what should own the client object should the client object own the reference to the actor(npc/mob/player) or should it be the other way around where the actor owns the client reference
I think I understand your quandary. On the one hand, you need to start with a client object prior to a player logging in with a character. This indicates the client object outranks the actor object. On the other hand, a mobile/npc, which is also an actor, exists with or without an active client object, which *seems* to suggest the opposite.
For this problem, I'd say there's nothing wrong with reading the classics. The way a DikuMUD codebase handles the hierarchy (implicitly, in classless C) is it assumes that a client (descriptor) has to have a non-npc object in a playing state before it can become a controller of NPC's (via the switch command). This makes sense because you need to know that, say, an immo has sufficient powers to possess NPC's directly (as opposed to controlling them "from the outside"). After 'switching', the client has a child player object in a pseudo-linkless state, and whatever input waits at the socket is being interpreted into actions for the NPC being possessed. The real lesson here is that the client object rules, since it contains two pointers to "actors":
struct char_data *character; /* linked to char */ struct char_data *original; /* original char if switched */
At switch time, the character pointer "plugs" into an existing NPC actor, and the original pointer maintains the link with the actual player actor so a 'return' is possible. In other words, a DikuMUD NPC is an auto-spawned and re-spawned client-less character ready to be possessed, automated in the meantime.
Direct possession of NPC's seems to me to be a "messy" but also undisputedly convenient feature, especially for QM's. There's probably a way to get the same end result with less messiness and at the same time make it possible for one human QM to control multiple NPCS. For instance, you could have a client object that holds an array of actor pointers. If the primary actor pointer (always a non-NPC) is in the "NPC control" state at the time you poll the client for input, you can interpret the input as direct control over all the other active actor pointers (let's say five death knights galloping towards a player-defended city). You'd need a small set of immo commands to handle adding and removing of controlled NPC's to the array, but that should be trivial.
05 Jan, 2011, quixadhal wrote in the 10th comment:
Votes: 0
My only suggestion here is.. stop treating npc/mob/players as seperate things. They all function the same way in the game world, so make them share the same data structures and thus have (the potential for) the same abilities. If you do that, you only need to plug in either a socket/command-parser for control, or an AI routine; and either a save routine for state information, or not.
It will also make life easier down the road if you choose to do polymorph/possession/reincarnation or any other mechanic that has you swapping bodies or losing control of your character.
My only suggestion here is.. stop treating npc/mob/players as seperate things. They all function the same way in the game world, so make them share the same data structures and thus have (the potential for) the same abilities. If you do that, you only need to plug in either a socket/command-parser for control, or an AI routine; and either a save routine for state information, or not.
I'll +1 Quixadhal here. It is more an object oriented way of looking at the mud, but you're using an object oriented language so it is easy enough once our human heads wrap around it.
Really…What's the difference between a npc, player, item, or room.
All have short and long descriptions? Yep.
All have attributes? Yep. They're different for each, but that's ok, I'd store attributes probably in a dictionary anyway.
All have action controls? Yep. an NPC has AI, a player has a brain. (Arguable sometimes, but hey.) An item and room hopefully have AI in whatever form. Progs/triggers and such.
These are just a few examples. So really, the only difference we have so far between our objects is the AI/brain. (Note I referred to in-game items as "items" not objects.) Helper methods implemented on the brains that inherit the base object should be doing any differentiation work.
Now, with that done, you should be able to poll any "brain" object (with a common api between them of course) and have it respond appropriately whatever kind of thing it represents.
as i was thinking about mobs and npc with the logical conclusion that they are very similar to players in how they interact with the world and how they are represented to the player as other players, this is leading me to want to create an Actor class that derives from MudObject and the Player, NPC, and Mobs would then derive from the actor class.
I believe his question has to do with how best to accommodate the differences between the two within the same object (Actor) and how best to handle Actors in the main loop.
in my mud i have a base MudObject that i derive my other game objects from
currently i have Player, Item, World, Area, Room and Wilderness
as i was thinking about mobs and npc with the logical conclusion that they are very similar to players in how they interact with the world and how they are represented to the player as other players, this is leading me to want to create an Actor class that derives from MudObject and the Player, NPC, and Mobs would then derive from the actor class. then each class would have some kind of controller
this brings me to the question of how i should then organize the input controller
right now as it stands the the PlayerObject has a Reference to the client object, where the client is basically in control until the player logs into his character then the PlayerObject takes over control of the input polling the client reference for new lines and then passing those off to the command interpreter ect…
what ideas and suggestions does everyone have, i've just been working on it and banging my head against the wall, and i would prefer not to have to take a month long break until i'm struck with some random stroke of genius