Branching paths in a text adventure.

Discussion in 'NDS - Emulation and Homebrew' started by Rydian, Feb 18, 2011.

Feb 18, 2011
  1. Rydian
    OP

    Member Rydian Resident Furvert™

    Joined:
    Feb 4, 2010
    Messages:
    27,883
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    I intend to make a choose-your-own adventure game purely in text. The thing is I've never worked in a compiled language before (or even one that accepts user input while running), only interpreted/web (run-once) languages. I'm unsure how to properly make branching paths of choices. Not simply a choice and then continuing along the same path, but branching paths.

    For something simple (say a 3-step story) you could just keep a path number in a variable and use conditionals to display the right path, as in this pseudocode.
    Code:
    displaytext("hello");
    givechoice("cake","pudding");
    if ("cake") {path=1;}
    if ("pudding") {path=2;}
    
    if (path==1) {
    displaytext("Do you eat the icing or cake first?");
    givechoice("icing","cake");
    if ("icing") {path=3;}
    if ("cake") {path=4;}
    
    }
    if (path==2) {
    displaytext("What flavor pudding?");
    givechoice("vanilla","caramel");
    if ("vanilla") {path=5;}
    if ("caramel") {path=6;}
    }
    
    if (path==3) { displaytext("That's not the way I eat cake."); }
    if (path==4) { displaytext("That's the way I eat cake."); }
    if (path==5) { displaytext("Nothing special?"); }
    if (path==6) { displaytext("That's one of my favorites."); }
    Thing is as more and more choices become available within the story that can get rather messy, so I'm curious to know if there's any better way to do this, or if I'm on the right (basic) track.

    As for keeping track of the paths and such I'll be using an external program, FreeMind.
     
  2. FAST6191

    Reporter FAST6191 Techromancer

    pip
    Joined:
    Nov 21, 2005
    Messages:
    21,706
    Country:
    United Kingdom
    Well there are reasons very few games ever have true branching* and this would probably be one of the big ones alongside it is very difficult to write (see exponential growth- even for your simple two choice "demo" 8 choices in you have 256 possibilities just at choice level 8, at 7 you have 128 and the sum of that whole sequence is 510 or 511 depending of whether you have a 0 power in there- this is where procedural generation comes into play).

    *much like all approximations and most computer modelling it is all about reuse and other tricks- different entry points (with different characters- Resident evil games are especially fond of this), texture/level/layout reuse and the like. This is not necessarily a bad thing either.

    Likewise it might also depend on what language you are using- object oriented probably being easier than a procedural (which is arguably what your pseudocode is doing), it is not impossible if you lack object oriented or even that much harder just not as nice to look at and will take more lines. On that subject it being text only affords several niceties with regards to amount of speed and optimisation needed.

    I would counsel against numbering your paths like that- instead I would opt for a probability tree approach and tack on/flip a bit somewhere along the way and keep a counter of the number of choices so you can easily decode where something is and if necessary reverse and replay it.
    Do it properly and you can have it all as a database type program with a simple thread running the lot- a similar idea to CSS and PHP in website building.

    General idea, I am not a fan of pseudocode so I will not be using it (much).

    Have a database, for something simple I would opt for a simple CSV or XML thing with rows as choice values (the 3rd choice, the 5th choice .......) and the columns as the actual choices (all possible instances for this- my logic hopefully will become clear in a few moments)

    Have the program/language gain the relevant lookup code, if you have a library great you should use that.
    Code:
    declare variable "choicenumber" variable type="unsigned byte"ÂÂ"initial value =0x0"
    declare variable "choice counter" variable type="number" "initial value= 0x0"
    
    If you wanted you could combine the two into a 16 bit value with the upper and lower bytes being either the counter or the values. 
    
    function(main program)
    displaytext("hello");
    determinevalue "choice counter"
    determinevalue "choice number"
    
    Lookup (row=choicecounter, values=choice number)
    Lookup2 (row=choicecounter, values=choice number +1)
    display the lookup text for the value and the following value (assuming a two choice system)
    
    givechoice("lookup"," lookup2");
    
    if givechoice=("lookup") set relevant bit 0//relevant bit is bit associated with choice counter - first choice is the least significant bit, second choice is the next most and so on.
    if givechoice=("lookup2") set relevant bit 1// doing it this way means you can simply read your choice values as a straight up number
    
    if "choice counter"=8 set final bit and call "end game function"
    else choice counter +1 call "main program"
    
    If you wanted to have a responses table then add another line to the database with them on too, it is now a simple lookup (or more likely lookup a pointer in the database and grab the data from another file using the pointer.
    
    function(replay choices)
    
    end game function
    displaytext("Congratulation you finished the game")
    displaytext("Your choices were as follows:")
    // If you wanted you could add some nice error catching here.
    Now you lookup the binary thing for each choice-
    
    
    if you had say 0101 1110 you would look up 0 for choice counter 0
    You then look up 10 for choice counter 1
    You then look up 110 for choice counter 2
    You then look up 1110 for choice counter 3
    Rinse and repeat until you looked up the whole byte. Personally I would NOR it with The choice counter value amount of 1's so as to only get the value you need.
    Hopefully you will agree this is far more elegant than burying text within code not to mention ignoring any database access penalties probably quite a lot quicker and smaller.

    Of course I could be wrong but that is the great thing about programming- a million ways to skin a cat.
     
  3. Rydian
    OP

    Member Rydian Resident Furvert™

    Joined:
    Feb 4, 2010
    Messages:
    27,883
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    I guess I didn't give enough info, but it's not going to be that many choices (I'm aware of exponential growth and will be limiting the paths appropriately).

    I've never actually used CSV/XML or outside storage like that, I might just stick with the if branching and keep things simpler or CSV parsing takes too much time for me to work out properly.
     
  4. saviorkross

    Newcomer saviorkross Advanced Member

    Joined:
    Mar 16, 2008
    Messages:
    78
    Country:
    United States
    Threw this together real quick, so be gentle. [​IMG]

    I've read a few "choose your own adventure/scare" books over the years, and they're indeed quite interesting. Basically a block of text, and then a few text choices followed by a page number for each. Some led to other choices, some to previous paths, others to death, etc. I'm not sure if that's what you were thinking of exactly, but that's the picture I had in my head while messing with this.

    Basically, I have each "page" as a separate text file. Then they're all combined into one file and read from the filesystem.
    Example of 000.txt:
    Code:
    "Hello kind sir. Would you like cake or pudding with your meal this evening?"
    Cake.~1
    Pudding.~2
    #
    The first line is the block of text. Each line thereafter is a choice; up to 4. As you'll notice between Cake and 1, there's a ~. This is used to separate the choice name and the "page" it leads to. Lastly, it ends with either a # or a 0. # is just to stop it from reading farther than it's supposed to. 0 represents an "ending" to a path. All these script .txt files are then combined into one file named "scripts.sc" with 'combiner.exe'. Combiner.exe gathers all files in the 'texts' folder, writes their locations to the beginning of the file, and combines them. You then drag the scripts.sc file over to your nitrofiles directory, and you're all set. In the program, it loads the first page automatically with LoadPage(0). From there, it gives you the choices for each of the 4 buttons on the right face.(ABYX)

    I wasn't sure if you used pure libnds, PaLib, etc, so I decided to play it safe and compile it with just libnds. It's slightly commented.
    Example with source code.

    If you decide this is the way you wanna do it, I can explain further.
     
  5. Rydian
    OP

    Member Rydian Resident Furvert™

    Joined:
    Feb 4, 2010
    Messages:
    27,883
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    Yes, that is the type of thing I was aiming for, and that's a great way of doing it that will help keep track of which choices lead to which, but as before I think it's a bit too overholding for what I planned on (a small project), and while I thank you for the work I'm a little iffy on using somebody else's source for the base (as this is partially a project for me to fiddle around and learn). Perhaps upload it somewhere where other people can use it?

    As for the libraries, I'm attempting to stay away from NitroFS after hearing issues about it with multiple flash cards and projects (and as a way to keep this small and simplistic), I want to make sure it runs on as many people's carts as it can, 'ya know? Just going with PAlib and text (will be using simplistic ASCII art).
     
  6. relminator

    Member relminator GBAtemp Fan

    Joined:
    May 28, 2010
    Messages:
    333
    Country:
    Philippines
    Rydian: Why not use straight libNDS and have all the bangs and whistles even if it's just a text game.

    Imagine a scrolling BG, with nice fonts, translucent dialog boxes without much effort.

    I'm not going to post a link until you tell me lest I be accused of spamming.
     
  7. chintoi

    Newcomer chintoi Advanced Member

    Joined:
    Oct 9, 2008
    Messages:
    51
    Country:
    Russia
    First of all, you don't need ready solutions, you need general knowlege. At your level textbooks are going to be a great help. Second, you need practice. Judging from your code you haven't had much. Third, you should accept criticism. For example, here's a bit refactored version of your peudocode:
    Code:
    enum {first, second};
    
    print("hello");ÂÂÂÂ// TODO: that's all?
    bool result = simpleChoice("cake", "pudding");
    
    if(result == first) {ÂÂ// cake
    ÂÂÂÂprint("Do you eat the icing or cake first?");
    ÂÂÂÂbool subres = simpleChoice("icing", "cake");
    ÂÂÂÂstring respones[2] = {"That's not the way I eat cake.", "That's the way I eat cake."};
    ÂÂÂÂprint (responses[subres]);
    }
    else {ÂÂ// pudding
    ÂÂÂÂprint("What flavor pudding?");
    ÂÂÂÂbool subres = simpleChoice("vanilla", "caramel");
    ÂÂÂÂstring respones[2] = {"Nothing special?", "That's one of my favorites."};
    ÂÂÂÂprint (responses[subres]);
    }
     
  8. Rydian
    OP

    Member Rydian Resident Furvert™

    Joined:
    Feb 4, 2010
    Messages:
    27,883
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    http://en.wikipedia.org/wiki/Pseudocode
    The human-readable definition of pseudocode is what I was using. The point not being actual usable code, but a basic outline for other people to understand. You know, it's the "concept art" of a program.
     
  9. chintoi

    Newcomer chintoi Advanced Member

    Joined:
    Oct 9, 2008
    Messages:
    51
    Country:
    Russia
    That's what I called it. And if you give it a moment, you'll find out that my version is a lot cleaner. You didn't even indent your code.
     
  10. Rydian
    OP

    Member Rydian Resident Furvert™

    Joined:
    Feb 4, 2010
    Messages:
    27,883
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    That's... Guh.

    The point of pseudocode is to be a rough draft to convey an idea. There's no need to declare variable types or to use proper syntax for commands, and it's often typed up on-the-spot. Most browsers don't let you directly input tabs to fields, you'd need to insert them via copy-pasting from another program, which is not something that normally needs to be bothered with when it's not even going to be used as a basis for any actual code, just the draft.

    You want an example of some actual coding?

    CODEThat's my signature here.

    You'll notice it's indented, sections are commented, proper syntax is used, the works. This is because it's actual code which is meant to be run.

    Contrast this with pseudocode (as in my first post), which is not meant to ever be run in a compiler/interpreter, and has very little work put into being syntaxically-correct because it's not a requirement.
     
  11. relminator

    Member relminator GBAtemp Fan

    Joined:
    May 28, 2010
    Messages:
    333
    Country:
    Philippines
    Chintoi: The guy was asking for help. Not criticism. Let's just help Rydian and have peace here.
    ;*)
     
  12. chintoi

    Newcomer chintoi Advanced Member

    Joined:
    Oct 9, 2008
    Messages:
    51
    Country:
    Russia
    When something is wrong something is wrong.

    Rydian You are missing the point. I'm not trying to prove anything about code vs pseucode or something. I'm trying to open new helpful concepts to you. Having no indentation is like a bad habit, like smoking. It just stinks.
    Another example: You have over ten conditional operators while I have only one for doing the same job. Having too much conditional operators was one of the reasons of your confusion.
     
  13. Rydian
    OP

    Member Rydian Resident Furvert™

    Joined:
    Feb 4, 2010
    Messages:
    27,883
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    vdajkgjaddgajk;

    That's not the actual code!
     

Share This Page