Handling movement in text-adventures.

This is a discussion on Handling movement in text-adventures. within the Game Programming forums, part of the General Programming Boards category; Originally Posted by GamingMarvel another way to do items is int he class or struct you use reference a boolean ...

  1. #16
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by GamingMarvel
    another way to do items is int he class or struct you use reference a boolean to each room its in if you are in the room and the item is also pick it up and then at that time turn the boolean into false and then the program if coded right can give the error

    object is not here

    or sometthing similar
    That's a horrible idea. And I'm not just picking on you because I think you're an idiot. Rather, I truely think that's a horrible idea. Let's say you have 500 rooms, which would be considered a very small mud (Yeah, it's a text adventure, but for all intents and purposes, it's the same as a mud.). Now for every single object, you want to add 500 booleans to mark what room it's in?

    If that's not what you meant, please clarify. And when you do so, please try to use full sentences, some capitalization, and perhaps punctuation. I'd rather pour ground glass in my eye than decypher your post.

    Quzah.
    Hope is the first step on the road to disappointment.

  2. #17
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Code:
    struct object *object_from_room( struct object *o )
    {
        struct room *r;
        r = o->in_room;
    Wait, what are you doing here? I'm not overy familiar with the struct syntax, so, er, what's with "Struct object *o" in the parentheses? Also, why are you having r point at o->in_room?

    Code:
        /* First we unhook it from the room itself... */
        if( r->objects_here == o )
    Ah, so do I need to establish a seperate if for each object I'm using, or is o a special object?

  3. #18
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Actually, I think I see what you're doing.

    Would it be okay to have a third item_list class to handle all the linking? With that, I could basically point all of the items to the list and do the next/prev linkup you suggested, and then have the room pointing back at the list. This would also allow for a very generic and flexible item searching function which I just thought of. My only real concern is that I'd have to make an item_list paralleling each room. WEll, actually, I wouldn't. Thre's something easy I could do with pointers. I just don't really see it right now, but after I mess around with it, I'll figure it out more. Beh.

    Right. Stick the item_list in the room class itself. Then I can just... uh... item_at -> room -> item_list, and then handle linking up from there.

    By the way, do I really need to keep everything linked into a master list? That looks like it'd be more of a thing for MUDs, where item permanence is a bit shakier.

  4. #19
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well it depends on what you want to do. If you keep a master list, you can do things llike:

    "cast 'locate item' 'sword of doom'"

    And search through the entire object list spitting out results of where every 'sword of doom' is located. Or what not. It just really depends on what you want to do.

    The reason there's a main list of items is in part that most MUDs are written in C, so they don't use classes. Mainly it's for things like searching through all objects for a given item or what not. It's easier to just walk through the item list, then it is to go through every creature, and every player, and every room, looking for all of a given item or what not.

    If you have lists of every given type (room, item, creature, etc), and you need to do something to one, such as find, destroy, whatever, it's easier to loop through one big list of that type, than it is to hunt it down from various small lists.
    Code:
    struct object *object_from_room( struct object *o )
    {
        struct room *r;
        r = o->in_room;
    Wait, what are you doing here? I'm not overy familiar with the struct syntax, so, er, what's with "Struct object *o" in the parentheses? Also, why are you having r point at o->in_room?
    This is a function. This function:
    a) returns a pointer to a 'struct object'.
    b) has the name of 'object_from_room'.
    c) takes a pointer of type 'struct object' as an argument.

    Here in this function we declare a pointer to type 'struct room', and assign it the room that the passed object resides in. You could get away without that, but it looks cleaner in my opinion to do it that way.
    Code:
    if( o->in_room && o->in_room->objects_here == o )
        o->in_room->objects_here = o->next_in_room;
    There's how you'd do it without declaring that pointer. Basicly these are all just linked lists, and I'm shuffling pointers around to remove and add items to the list.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #20
    Self-Taught Noob
    Join Date
    Jan 2005
    Location
    Ohio
    Posts
    38
    Quote Originally Posted by quzah
    That's a horrible idea. And I'm not just picking on you because I think you're an idiot. Rather, I truely think that's a horrible idea. Let's say you have 500 rooms, which would be considered a very small mud (Yeah, it's a text adventure, but for all intents and purposes, it's the same as a mud.). Now for every single object, you want to add 500 booleans to mark what room it's in?

    If that's not what you meant, please clarify. And when you do so, please try to use full sentences, some capitalization, and perhaps punctuation. I'd rather pour ground glass in my eye than decypher your post.
    Yes that's is pretty much what i meant but you could also set it up with a switch if i am thinking right.

    Have a code you create for the rooms then use a switch in the item. that will run through the room possibilities and then give the item to the person in that room.

    Set a default also so that if the room is not specified it says that the item is not there. One problem i forsee is you'd have to debug the information so that if the player drops an item you add the room and once the character takes the item he can't get it again.


    There is that easier to read?
    No one died when Clinton lied.

    Compiler: Borland C++ Builder
    OS: Windows XP

  6. #21
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Yes. Much easier to read. It's still a horrible idea though. You don't want to waste space for 500 booleans on every single object just to see what room it's in. For one, you'd still have to loop through them all just to see if it's in the same room as the current one you're in. I suppose you could use an array of booleans, where the array has the same number of elements as there are rooms, but this, like the origional boolean idea is horrible too.

    While it would allow easy lookup:
    Code:
    if( object.inroom[ player.roomnumber ] == true )
        ...the object is here with you...
    It's still horrible for the fact that if you ever add more rooms, you've got to resize all of these. Sure, you could use a constant/#define some place to keep track of how many rooms you have, but it's still horribly inefficient. Why store 500 booleans per object when you can simply use an integer or a pointer to the room it's in? Why store 50,000 booleans per object when your world gets large, when one single integer or pointer will work just as well?

    Another benifit of the pointer method is as I previously described, you have access to the room itself immediately for checks of its contents, if the room is dark, or whatever. It saves you seeking through yet another list just to find the room it's in.

    Basicly, with the pointer method, you can, given an object, a player, a room, whatever, immediately find what is here with it:
    Code:
    void show_otherobjects( struct object *withme )
    {
        struct room *r;
        struct object *o;
    
        r = withme->in_room;
        if( r )
        {
            for( o = r->next_object; o; o = o->next_object )
                ...display this object...
        }
    }
    You can do basicly the same thing with player, room, whatever, just by having a pointer to one instance of nearly anything.

    Quzah.
    Hope is the first step on the road to disappointment.

  7. #22
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,598
    At the start of the game you can assign objects to rooms using ID's and keep a pointer to track them from that point on. Using pointers from the outset it will be harder to do the initial setup of the world. So I'm suggesting using both. Start off with ID's and then use pointers to track them for the rest of the game. That way in your scripted setup file or cfg file you simply need to store object and roomID.

  8. #23
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Actually, that whole thing with a seperate class item_list thing was stupid. I should just have an item pointer in the room class.

    Actually, in retrospect, I think I'm doing exactly what you're doing, only somehow the struct-related syntax threw me off (Even though it isn't THAT different).

    My main issue is that I'm still slogging through how to add and remove stuff to the list, but something like that's sort of hard to describe, and I'm certain it will become bleedingly obvious as soon as a crack open a can of soda and drink it. And then proceed to program the code in something else.

    Anyway, I had this idea involving checking currant_object's name variable to see if it matched the players input object. If it does, EXECUTE CODE. If not, have currant_object (What IS my obsession with those little red berries anyway?) or rather current_object point at whatever it's point at's *at_next object in the list.

    My problem with this is that I either end and start the list with NULLs/special unusuable bookending objects and resetting to the first non-null position in the list after each search, or, on the start of the search, set some arbitrary test string to the first item's name to mark the start position and use that later to check to make sure nothing is repeated, and hook all of the items in the list up end-to-end.

    I'm wondering if this would be too slow to do.

    Actually, if items are defined before rooms, and items have room objects in their class, and vice versa, how do I preload all this stuff without getting, "WTF ROOM DOESN'T EXIST" errors?

  9. #24
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Bubba
    At the start of the game you can assign objects to rooms using ID's and keep a pointer to track them from that point on. Using pointers from the outset it will be harder to do the initial setup of the world. So I'm suggesting using both. Start off with ID's and then use pointers to track them for the rest of the game. That way in your scripted setup file or cfg file you simply need to store object and roomID.
    That's basicly what I was talking about when I mentioned muds use "templates" earlier. The file for a room might look like this:
    Code:
    ROOM
    vnum 200
    description <some text here>~
    north 201
    south 202
    END
    
    ROOM
    vnum 201
    description <some text here>~
    south 200
    END
    
    ROOM
    vnum 202
    description <you know the drill>~
    north 200
    east 203
    END
    
    ...and so on...
    This is a common DIKU method for dealing with it. Though their files look a bit different, they take that basic format. The "template" is never changed in memory, and it's only used for reference purposes. For example, at MUD boot to link the rooms after it's loaded them all. You run through the template list and link all the actual instances together, which use pointers to point to the other rooms.

    This way you have actual "instances" of everything which can be effected by various things, and you still have the origional template to work from if you need to repop a new one (ie: mobs and objects, or to reset an area or what not).

    But yeah, the vnum / pointer combination is used frequently in MUDs. (Think every DIKU child in existance, and probably many other variants.)

    Quzah.
    Hope is the first step on the road to disappointment.

  10. #25
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Well, I think I got the get code working, and the drop code... will come later, because the game I'm working on doesn't really use it, and if I can get get working, drop shouldn't be bad.

    Eventually, I plan on finding a way to implement the list thing, but that can wait.

    Just curious, but would making the inventory a room object be a bad idea? It seems mostly coherent and logical with what I'm doing.

    So, I guess I should move onto doing the parser, so that I can figure out a useful method of properly testing get. Anyway, as I previously stated, my original method worked on the principal of hashing apart the users input string. However, y'all've said that tokenization is more useful.

    Now, I've been told that tolkenizing is breaking down the input into reasonable chunks based on spaces or something. I doubt I'm saying this rigth, but whatever. Any suggestions on how I'd go about implementing this? Is it a matter of checking what the first word is, and if word1 = something, then check word2 for a certain condition?

  11. #26
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Sure, you just set up the way you want commands to work when you teach users how to play. For example, a help entry may look like this:
    Command: get

    Syntax:
    get <object name>
    get <object name> <location>
    Examples:
    get sword
    get sword bag
    The first example tries to get a "sword" from "here". The second example tries to get a "sword" from a "bag". If no location is provided, "here" will be used. "Here" would be wherever the user is at at the time.
    Or if you wanted it more complex, then you just tell them the way that it needs to be done, and you just chop things up and compare them to the expect syntax.

    "get the 'glowing sword' from the 'dark brown bag'"

    Regarding making the inventory a room, that's an interesting thought. You could then allow for people to be inside the inventory of another person. You would need to set up a special case so that when they climbed out of the inventory it would take them to wherever the person whose inventory you were in was. For example, a giant could pick you up and put you in its pocket or backpack, or whatever, and wander off with you. Might be fun.

    Quzah.
    Hope is the first step on the road to disappointment.

  12. #27
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Okay, so yeah, that doesn't sound so bad. If I can't figure that out, I could always default to my old hash-apart method. Sort of limited, but it works.

    Anyway, case sensitivity is something I don't want. Is there a better method for this than defaulting everything to either lower or uppercase, or should I just... well, someone game me this &tolower function and the associated code, and I don't really know how it works and they said don't try to understand it, but is that the best approach?

  13. #28
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Hm. Alternatiely, instead of processing entire strings, I could present the player with a list of options, which would take either a single letter, number, or word. These would open up sub-menues. I think for an *RPG* this migth be preferable to a more traditional parser. Alternatively, I could implement the key-getting functions from... whatever library/API/whatever that was and use THOSE.

    Anyway, my next major concern was NPCs, and how to handle dialogue. I figure I'll use a single-word/phrase keyword input system. I'll treat dialogue topics like items -- string them together in a list, and have the NPC point at them. This is how morrowind handles dialogue, sort of.

    Or, I could adopt an even MORE morrowind-esque system, in which the keywords, instead of being pointed at by the person who has them, will all be contained in a master list. They'll have numerous conditions which will be met. If any of these fail, you get an "invalid word" thinger. It's sort of hard to describe.

    Basically, it all comes down to whether or not I have a lot of conditions to meet and a lot of text which is shared by NPCs.

  14. #29
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Hm. Well, I can't find where I edit my posts at, so...

    I've further broken down dialogue. There are two classes -- keywords and responses. Both function like items. Anyway, the keyword object contains a pointer to a number of response. When you input text, it searches through the "list" for a keyword. When it find its, it searched through the keyword's list of responses, and checks to make sure all possible conditionals match or are irrelevant. I'm working on making my description make sense.

    Anyway, my next two problems were these.

    One-time-only events in certain rooms. I'm guessing that the only way to do this is to run some sort of if statement each time that room is entered or something. Any easier ways to do this?

    Second, how would I go about creating multiple instances of the same object?

  15. #30
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,598
    All of what you want to do with NPCs and with rooms can be accomplished via messages.

    Think Windows programming. Windows passes messages to your window and the LPARAM and WPARAM meanings are relative to the message being passed. You could do the same thing with characters, rooms, etc. Read the global script and translate it. Then when an event needs to be fired...send a message to the event to tell it to fire. When a character is supposed to talk simply throw the message to all players involved in the dialogue. When the player is done talking, send a message indicating this to all players involved in the dialogue. This would mean that each dialogue would be an object and each player might have to 'register' with the conversation or dialogue to receive messages from it.

    This structure would allow you to 'know' when one player is done talking or should start talking.

    Your script commands for dialogue could be kept to a minimum:

    Here are some examples:

    $ - string
    # - number (DWORD) - usually refers to the ID of an object

    NPCTalk(#,$)
    NPCTalk_ID(#,#)

    Desc: Instructs NPC # to talk using string $ or string resource ID #
    Talking is not directed at anyone.


    NPCTalkTo(#,$,#)
    NPCTalkTo_ID(#,#,#)

    Desc: Instructs NPC # to talk to # using string $ or string resource ID #

    NPCShutup(#)
    Desc: Instructs NPC # to stop talking

    NPCInterrupt(#,#,$,$)
    NPCInterrupt_ID(#,#,$,#)

    Desc: Instructs NPC # to interrupt NPC/Player # at word $ in string $ or string resource ID #

    NPCTalkToPlayer(#,$,#)
    NPCTalkToPlayer_ID(#,#,#)

    Desc: Instructs NPC # to talk using string $ or string resource ID # and direct conversation to player #

    Those are just examples of what you could do.
    Last edited by VirtualAce; 02-11-2005 at 04:59 AM.

Page 2 of 3 FirstFirst 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. DirectX | Drawing text
    By gavra in forum Game Programming
    Replies: 4
    Last Post: 06-08-2009, 01:23 AM
  2. event handling is serialized in MS Visual Studio C++ 2005 ??
    By mynickmynick in forum Windows Programming
    Replies: 3
    Last Post: 08-07-2008, 05:47 AM
  3. Scrolling The Text
    By GaPe in forum C Programming
    Replies: 3
    Last Post: 07-14-2002, 05:33 PM
  4. Replies: 1
    Last Post: 07-13-2002, 06:45 PM
  5. Ok, Structs, I need help I am not familiar with them
    By incognito in forum C++ Programming
    Replies: 7
    Last Post: 06-29-2002, 10:45 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21