A query to other game developers out there.

Do people do anything interesting for authoring conversations for RPGs?

I want to be able to just edit a conversation as a text file, but it starts getting a little hairy because I don’t want the conversation to be structured as a strict tree. (At a point in the dialogue, there are some things you can talk about, but for example other things you can always ask about no matter where you are in talking to this person, and a lot of options that are hidden but triggered by variables, etc).

Add to this the fact that I want to support some markup in the text (bold, italics, and such) and it’s looking like I want to go all XML.

Which kind of pains me, because I dislike XML. But, that is obviously one way to go — just make my own markup tags that mean things like “conditional based on a variable”, or whatever, and go from there.

But before I do that, I thought I’d check and see if anyone pursues alternatives. Even if they rely on some huge proprietary in-house thing that took man-years to make, it’d at least be interesting to hear about what the approach is.

Thanks!

-Jonathan.

61 thoughts on “A query to other game developers out there.”

  1. I’ve tried a few approaches for things of this sort. For a while I was using a custom language I wrote, but I kept having to add new features and conditionals and things.

    I think the right solution – and note that I haven’t actually done this yet – is just to use an easily-embeddable language like Lua. Use coroutines and yield() whenever the user is being prompted. Simple discussions end up looking like:

    response = Query(“Hello, fair traveler! There is a dungeon. Do you want to know where?”, {“Yes”, “No”})

    while response == “No” do response = Query(“There is a lot of treasure in it! I think you really want to know. Let me tell you where it is.”, {“Yes”, “No”}) end

    response = Query(“It’s beyond the hills! Over there, where the burning is. There is almost certainly a dragon inhabiting it.”, {“Oh no!”, “No problem.”})

    if response == “No problem.” do
    local text = “You seem extremely confident! Do you think the dragon will be an issue for you?”
    if player:averageEquipmentLevel() < 30 then text = text .. ” You don’t seem very well-equipped.” end
    Query(text, {“Yes”, “No”}) — ignore the response, we just don’t care
    end

    Query(“Well, good luck! Try not to get eaten.”)

    . . . and I really can’t imagine any possible XML or tag-based system that can make a dialog “tree” of that form even remotely as readable as that is. Obviously, that’s a simple example compared to what you can do in theory, there’s no reason you couldn’t plug far more complicated functions, conversation paths, minigames, etc in.

    The downside, of course, is that you have to add Lua (or something similar) into your codebase, but I think it’s what I’m going to try next time.

    Color/font/bold/italic markup is, in my experience, now usually done through the use of escape codes of one sort or another. Something like: “The last word is |bbold|b.” or “The last word is |b(bold).” It’s just incredibly convenient to be able to plug that sort of thing directly into the string, and if you just write the color-tag into Query() then it All Just Works.

  2. Neverwinter Nights exposed a lot of tools to end users to develop their own quests, so you could look at that. I believe dialog was done through their C-like scripting language.

    AGS (adventure game studio) is another one that’s easy to look at; it has a hybrid script/gui system.

  3. Although this is not precisely made for what you have in mind, I’ve been using FreeMind lately to organize key concepts in one of our prototypes. It’s fairly easy to structure a flow of ideas with it, so I guess it could be fairly useful for structuring a flow of dialogue as well.

    Pretty ghetto, but how can we be creative about our ideas if we’re not creative about our tools? 😉

  4. You could throw a fair bit of logic (beyond simple branching stuff) into your conversations if you used something like Lua to script them.

  5. Well, another concern is that I probably want to deploy this on consoles at some point. I know someone who tried to use Lua in a game for the original xbox, and regretted it. How is that sort of thing now? Is it possible to make the Lua interpreter behave and be reasonable about memory and other such things?

  6. I don’t know how hackable it is, but I’ve heard that the Lua interpreter is intentionally built to be a small amount of code, and relatively easily maintainable/modifiable.

    From there, though, I couldn’t tell you. If you find anything more concrete I’d love to hear about it, since I’m considering using Lua in a game that I would also like to deploy on consoles 🙂

  7. I never actually made a game or a dialogue tree type of thing (though you say you don’t want a tree), but I think you might want to look into a technique called continuation passing style. The basic idea of that is that you parameterize each function with a similar one, that is called after the function is done. This basically sets up a chain of calls.

    In this case you can use a set of answer/continuation pairs, then have the function give a question and the list of answers, and when one is chosen, call the corresponding continuation. This allows for any type of structure including loops. And you can define the functions in any order. If you set it up right it should be very easy to maintain and require only a minimum of programming when actually building the conversations (although you will have the power of the fulll language available if you want it).

    I myself use Haskell for most of my programming which is very well suited for this. You can really just make a higher-order function that is parameterized by the aforementioned question and answers/continuations, and have that do all the work (like showing it in your game and allowing to pick answers and such). You can even make some combinators to easily adapt one of these functions into a multi-page question, or to insert emotes from the character you are talking too, or give or take items from the character’s inventory.

    I’m not sure how well this would work in other languages, and it sure isn’t a tried and true method. But you could at least look into it for a few hours, at worst you’ll learn a new programming technique.

  8. On EverQuest II, we have a network of Dialog Node files that have various (Lua) scripted predicates to check things like completed quests or inventory items. The Dialog Nodes then link to other Dialog Nodes to form a graph of dialog. NPC characters in the game have what we call a ‘Hail Handler’ which is a tree of data-driven predicates (again, checking items, quest progression, completed quests, etc) and “handlers” (which can call script, open Dialog Nodes, give items, offer quests, etc). The Hail Handlers are executed whenever a player initiates communication with an NPC.

    It’s a very complicated system and becomes difficult to traverse at runtime to provide UI feedback such as if an NPC has a quest to offer you, but it works well as far as providing data for conversations.

    We use Lua on EQII for our server-side scripting. We’ve hacked it to give us better control over when the GC runs and to enforce a bytecode limit of 10000 instructions per event call (so that our designers can’t write infinite loops). Aside from Lua being extremely raw (roll-your-own Object Orientation), we’ve found it very effective. It does do a lot of dynamic allocation though, so you might want to pool memory for it if heap alloc is a worry with the console.

    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

    Switching gears, another game that I worked on was Ultima Online (which had a very unique conversation engine). The Convo system in UO classified NPCs by profession as well as varying degrees of basic stats (i.e. intellect and bravery) and provided phrases based on keywords and interpretation of their stats. For instance, a Convo region for a city might be something like this:
    Type: Peasant
    Keyword: bank
    Low Int: “Well, I dunno where the bank might be.”
    Med Int: “I can’t help you find the bank.”
    High Int: “I’m sorry, perhaps you should seek the local Cartographer.”

    As you can no doubt imaging, this system would be very difficult to localize and was disabled when UO started requiring translation.

  9. hi, i am from the chair in artificial intelligence and applied computer science of the university of Würzburg (Germany). we develop an second-opinion-system (d3web) where a user answers some questions posed by the system and the system finally comes up with the best matching solutions to the problem. one important module of this system is the dialog controller: as the system can pose lots and lots of questions (hundreds), only a few of them are typically needed. the rule based module makes sure that only relevant questions are posed to the user. for this there are different queues of questions with different priorities and actions to put questions on these queues (either at last position or at first position).

    example: if (“makes your motor funny noises?” = “yes”) then (activate question “what type of noise?”)

    it’s pretty complex but it’s open source, so you may check it out at http://d3web.sourceforge.net – if you can make any use of it we’d like to hear from you 🙂

  10. If you don’t want to use XML …. you can use YAML … it’s like a very simple XML, very handy, and there are much libraries to parse it. In this way you can store structured data very easily, and maybe you can also structure the conversation logic. Have a nice day!

  11. I’ll post a more detailed response later but it seems to me exactly what you need to do is study the various japanese “Ren-Ai” engines. They are exactly what you are describing. They are also known as “Visual Novels”. There are a few free engines out there that you can study to give you some ideas in your own implementation, check out http://www.renpy.org/ for starters.

  12. Take a look at the syntax to develop MS Live Agent.

    http://agents.live.com/

    It was developped to have a free form text conversation, but can also force some sort of guided chat as well, and permit jumping to other subject. And it could output full html if needed.

    The chat definition code is relatively easy to parse, and was designed to use a standard text editor, not doing xml pushups. I don’t think you can use the engine for a game, but the syntax might give you some good ideas.

    -Mathieu

    ps: full disclosure, I used to work on that project before it got acquired by MS.

  13. I have a custom narrative scripting language that I have worked on as a hobby for a few years. It is designed to encapsulate a majority of the narrative aspects of an interactive story, not just the dialog (it can, of course, do dialog, using the syntax SPEAKER:”things I am saying”). It is designed to call “gameplay” sections of the narrative that may be written in another language, much like how renpy allows you to write or call python functions that implement minigames. This is in line with an interest I have had for several years in toying with narrative-game hybrids, games where success and failure is not as important as narrative immersion, though skill-based mechanics can still be found. This language is similar to xml, and is mostly declarative, with square brackets instead of angled brackets and a few specialized semantic modifications geared toward scripting. As far as keeping a clean tree-structure, you can call “blocks” (like one would call methods in a procedural language). These “blocks” contain executable commands and can be placed in the current file or in other files. Blocks can be nested with a scope based resolution for organization. Files don’t need to be explicitly imported; at runtime, all files in the base directory and its subdirectories are loaded at the same scope level, so deciding to reorganize and move a block from one file to another does not require the grunt work of adding import statements. Files can be imported anywhere in a script via an import command, but they must be named with a special extension to prevent them from being automatically loaded into the global scope.

    A chunk of text followed by two end lines represents the end of a narrative chunk where the user will have to press a button to progress. If this post was a script file in my language (and it is legal syntax in its entirety, as plain text is considered output by default similar to html), you would have had to hit a progress button (such as the enter key in my runtime) to bring up this paragraph once you got to the end of the previous paragraph. I have also implemented timers to automate progress if it is so desired. The user can be presented with choices, and these choices can have conditions based on variables or based on what other choices/events have occured. At the end of a choice block, progress automatically continues until the end of the current block, similar to an if/else or switch construct.

    One of the most useful block types that I implemented is a “situation”. A situation is basically a set of events. A situation will try to play an event, either randomly or prioritized (this can get pretty complex), until it runs out of events or is explicitly told to end via the endSituation instruction. Situations can also contain actions instead of events. An action is basically something the player chooses to do whereas an event is something that the storyworld causes to happen, often “randomly” from the player’s point of view. If a situation contains only actions, it will pool together any that have their conditions met and ask the player which one they want to execute. Actions (and almost any element, for that matter) can have “occurance limits”. I find this a very natural way to implement those dialogs where the player has n choices and must select each one once before continuing. Or if you want to give an “I get it, let me leave” option, just add it as an action that contains an endSituation command.

    All elements in a script can be named and referred to by name, so you can have choices that don’t open up until a particular dialog branch in another part of the script (or in another script) has occured. Naturally there are variables for state-based branching, and basic math functions and string concatenation operations for embedding variables into dialog output. As far as mark up, I have an engine for executing storyworlds that are written in this language and it uses basic (and some not-so-basic) html tags for markup. This is one of the reasons I used square brackets for my declarative tree structure.

    Since this post is getting long and I’m not sure how it would be formatted, I will refrain from posting example code here unless anyone would explicitly like to see it. This is technology that I plan on pursuing as a hobby again someday, so if you have questions or feedback I would be very interested to hear. Jonathan, it sounds pretty in line with what you need, so if you are interested in using it for prototyping (or just inspiration for your own engine) let me know and I will try to get you example scripts or even dig up and brush off the source.

  14. Regarding lua, we used it on the last shipped project I worked on and had relatively few memory problems embedding it into a 3D sandbox game (on the Wii even!). I can not vouch firsthand for its usability as a scripting language as the closest I came to using it was implementing C++ hooks for when the designers called certain methods, but it still seems to have positive support in the industry. This seems like a reasonable approach.

    Regarding renpy, I would call it a reasonable approach by the same logic. I have actually used it and liked it despite not being a fan of python. Having to maintain a 6000+ line python build script where type errors might not be caught until any point in the multiple hour execution makes static analysis of types and variable declaration look quite desirable, but I don’t have such an issue with small, mostly-linear scripting in python.

    Regarding facade, while it is a fascinating case study worthy of examining by its own right, it seems like overhaul for what was described here. It uses the ABL language, which is geared more toward letting agents communicate dynamically in real time and would probably be difficult to implement a dialog tree in.

  15. “it” what is “it” in this context.You know Jonathan u said October for pc version and we are at the middle of November now. So what is “it”, not that we in any way are demanding anything or that you in any way ow us (the pc people with no 360) anything. But come on, you have crated (one of the) the highest rated (indie) game of all time, so please can you give us an update.

    It is something, anyone can see it. The way you never respond to any pc questions anymore, relax im a doctor, you can tell me anything.

    See what i did there, I mad a funny, to take focus of the ass licking part you just read.

  16. Hey, Jonathon.

    This has nothing to do with your arcane issues with programing that I one day wish to learn but I heard World of Goo an indie game has reported a 90% piracy rate. It makes me think that for you, it might have been beneficial to launch your game on XBLA first, then very much later in the year you put out the PC version. I think that, because the people who would have wanted to play Braid have already paid the $15 to do so. Instead of launching it simultaneously where the people who would want to play Braid would be in a split of paid and illegally downloaded.

    Right now, I believe the PC version will launch for the purpose of anyone that couldn’t experience (what in my opinion is a contender for 2008 GOTY) game, to be able to play it. I cannot prove the pirating will be minimal for you, because I cannot prove who didn’t pirate it because XBLA was the only place to get it. But I bet dollars to doughnuts that the number of people who would have pirated your game be less, because they already bought it on XBLA.

    Whats your thoughts on this? Did you dodge a bullet here?

  17. Neverwinter Nights used a tree approach.

    If you want a “flatter” system, consider looking at Spiderweb Software’s RPGs (esp. Blades of Avernum, Geneforge series). Many of the conversation nodes are available at all times, and the scripts are ASCII and easily inspected.

  18. To avoid XML conversation trees you’re probably going to end up making something custom that acts just like XML or something a little more script-oriented.

    Personally I’d go with XML but I guess I’m a fan. :p

    As mentioned above, parametered predicates are a clean and easy way to toss in any quest/item/story/attribute/etc checking to control the dialog flow. Then there’s custom parsing for embedding colors, fonts, pictures, his/her gender recognition, etc. With XML you could get a system that emulates whatever features people liked from Morrowind/Ultima/NWN pretty easy.

    Now permit me to spin 180 degrees here.

    If you’re looking for alternatives to dialog trees, you’re probably bored with the status quo for the way dialog is being written in RPGs anyway. And I gotta say there’s a lot to be bored about. Why are complicated dialog trees so popular anyway? What is the point? Are they more realistic than linear dialog? I would say not, because people respond well to dialog in books and movies and those are completely non-interactive. Do they make the characters more believable? Of course not, the guard would have remembered saying “Oh, the mayor’s house is at the end of the yellow road.” 60 times when you wouldn’t stop clicking on him. These dialog constructs serve to remind us that we’re not talking to people, we’re talking to dressed-up quest and information dispensers. They might as well be sign posts.

    The most entertaining game dialog I can think of would be from the Metal Gear Solid series when you radio in a support character. And that’s from an action game, think of how that technique could evolve in an RPG!

    But if you’re looking for an alternative to dialog trees, I say look for an alternative to dialog entirely. Seek to convey as much of the story as possible using visual cues. A burned out cottage might imply an accident, but finding the door jammed from the outside and two bodies in the ashes points to an Arsonist killer.

    After exhausting all the possible stories that can be told without dialog, maybe we can learn something about what kind of stories we actually do need words for?

  19. “Are they more realistic than linear dialog? I would say not, because people respond well to dialog in books and movies and those are completely non-interactive.”

    People respond well to linear visuals in movies as well! By this line of thought, why make the game interactive at all?

    In other words, your evaluative criteria here is nonsensical. We don’t put in player control to be ‘realistic’ — you can almost always make something more ‘realistic’ by completely removing interactivity.

    Your guard example is odd, since it’s obviously not necessary for dialog to work that way — you can avoid having a guard who repeats the same thing 60 times. In fact, the guard conversations could go just like the radio conversations you apparently enjoyed; aren’t those user-triggerable as well? But the game design with the self-repeating guard has chosen instead to trade away realism for something else — perhaps for accessibility, or a gamer-friendly predictable world. I’m not convinced that is always a bad choice.

    “After exhausting all the possible stories that can be told without dialog, maybe we can learn something about what kind of stories we actually do need words for?”

    To me this sounds roughly equivalent to: “After randomly sampling all the real numbers between 0 and 1, perhaps we can learn something about the reals outside that range” …

  20. If you need help testing the PC version I’m your man. Porting it to Mac? Count me in. Linux? Sure! No, I don’t actually expect that to happen, but I want to play this game and don’t have xbox. And I’d be a good tester. 😉

  21. How about before you start working on an rpg you release the pc version of braid. 2008 is running out, don’t you want my money? I kid, but seriously, been waiting on braid for a while. You programmed it in xna. so umm, whats the hold up?

  22. Well, in all honesty I didn’t take the time to really understand what it is you are actually looking for, but some interesting work on conversations was at AIIDE this year that may be of interest to you:

    “Talking with NPCs: Towards Dynamic Generation of Discourse Structures”
    Christina R. Strong, Michael Mateas

  23. I am really impressed with the answers to the original question so far, and to me it’s obvious there are two main schools of thought on the issue. If you go with lua or any related scripting language (python, etc) then you have a lot of flexibility, because what you are doing is combining your data with your logic. You trade flexibility for ease of reading, and ease of debugging. It also requires your writer and editor (which may be yourself) to be able to read and follow (and craft) script-form prose. This can often be a problem. Debugging conversations is also often a problem, esp. With mistyped variable names.

    The alternative (which I advocate) is XML or a derivative format. In other words, a strict parseable declarative format. This has a lot of advantages. For a start, your formatting becomes dead simple, you just use tags. Secondly, it’s easy to read, because you can just xslt it to html (and vice versa) and use any existing wysiwyg web or desktop editor. It means there is no technical requirements on your writer or editor. This is a big deal if your game has a lot of text and having well written prose is important to you.

    Your conversation logic can then simply be gated based on attributes (metadata) you apply to the conversation blocks and fragments. While I have personally used highly sophisticated branching engines declared in XML, rich metadata eliminates most of that need. The biggest advantage of this is the ease of debugging. Since no functions are declared in script, you simply build and test your parsing/display engine and then the only logic errors you encounter from that point on should be declarative in nature.

    Admitedly, you lose the flexibility of the scripting solution, but I would argue that if your dialog engine is built with a robust collection of rules, the extra flexibility is unnecessary, and ultimately more trouble than it’s worth.

    A final note: storytron and facade are unsuitable for this purpose. They are game engines in themselves and not designed to be tacked on purely to manage dialog trees. They bring considerable overhead (dev time, memory, content creation) with themselves.

  24. First, about Lua: all the thumbs in the world up for Lua can’t express how awesome it is. Srsly. We’re shipping a game written entirely in Lua above the “render this mesh here” level, gameplay logic, UI, network code, missions, everything. Don’t worry about memory usage. Don’t worry about performance. Do worry about undetected typos killing you when the source gets huge (60k+ lines in our case).

    We store our conversations in Lua files, which can be anywhere between XML (pure declaration) and full scripting (pure imperative), you choose where to place the slider.
    We let designers type the conversations directly in Lua in a text editor, but this was a bit too fidgety for them, with too much attention going into typing/pasting the exact conversation/actor/item/quest/phrase IDs; now they use a primitive data-entry GUI built in FileMaker which exports Lua files, and still has fields like “type extra script here” for simple things like CountItems(“apple”) + CountItems(“pear”) > 10. The conversations are structured like bunch of phrases with predefined transition rules (graph, not tree) with paths taken based on conditions or random numbers and actions; the most common conditions (check for item in inventory, add item to inventory) are predefined as higher-level blocks, and arbitrary ones can be implemented by typing some Lua code (which sometimes needs a programmer to come and help).

  25. For fast, customizable scripting, XML will be regrettable. You can look at Unreal Tournament’s scripts and see that for the most part, 90% of the time they use bare-bones modifications of plain-text (not counting their automated or unreal scripts).

    I tried to create an XML programming language. It would handle commands, scopes, variables, control-flow including loops and branching, etc, but I found this to be a TON of work.

    With scripting, the quicker and dirtier, the better. Scripting shouldn’t be just a hack, but I wouldn’t spend weeks prototyping obsessively just to find a scripting format you’re comfortable with. The trade-off between development time and development progress is way, way too severe in scripting to do that.

    My two cents,
    Pritchard

  26. Inform 7 [http://www.inform-fiction.org/I7/Inform%207.html] is certainly the most advanced textual interaction mechanism for games I’ve seen anywhere. While it was designed with text adventures in mind, you might find it interesting.

  27. @ corinne: I was going to suggest Freemind too, if only for planning/writing. No idea if their file format is easily parsable to then use it for implementation. Still, the mind-mapping SW seems to conceptually meet the need for these conversation fragments.

    @insanejedi: This is pretty typical conspiracy theory that is oft cited for big retail games having PC skus that lag. It’s bunk, IMHO. (a) There’s overlap between formats, but only so much. PC pirated copies cost PC sales, but less so console sales. (b) There’s also a cost to not simul-shipping from the marketing side, and (c) often, the do-or-don’t PC sku decision is the one most on the bubble, and so seeing how the console sku does lets the publisher make that call.

    All that aside, I really doubt this was the issue in Jon’s case. He’s just one guy writing the code, so simul-shipping would have required the growth of extra fingers, etc.

    My 2c.

  28. Regarding Lua memory usage: Lua uses an incremental garbage collector, so that every step some GC is done. If this default behavior isn’t sufficient, you can manually alter its aggressiveness (suspending collection or forcing mark-and-sweep at certain times) from either Lua or C.

  29. Store all the dialog in an sqlite database. Each line of text should be a separate record in a table. You can have as many additional fields as you need on the table to figure out when the dialog should be said. You should also create another table to join it with to make it easier to filter down base on character, area, etc.

  30. My guess would be to go with an event driven NLP. This gives you the benefit of (i) using a look-up response table which can be in any format – least of all XML (ii) an unprecedented – and automated – control over the conversation flow (iii) automated conversation branching you don’t have to babysit.

    It would of course be quite a bit of work but the end result would be more control – and all without having to touch a third party scripting system.

    If you do want to use a scripting system – even with your own grown language parser – you have quite a few choices including the following:

    AngelScript, Spirit (part of the peer reviewed Boost suite) and maybe Squirrel.

    If you’re going with Lua (the recommended path of least resistance), then you need a suite of complimentary tools which includes some of the following:

    – CPB: http://www.thomasandamy.com/projects/CPB/

    – Decoda: http://www.unknownworlds.com/decoda

    – VSLua: http://www.itrango.com/vslua/index.html

    Then there’s AnaGram or ProGrammar if you do decide to take the long road.

  31. You might want to get in touch with the Planeshift team. They’ve recently spoke at google talks (easily found on youtube) and part of the presentation was about conversation files.

  32. My guess would be to go with an event driven NLP. This gives you the benefit of (i) using a look-up response table which can be in any format – least of all XML (ii) an unprecedented – and automated – control over the conversation flow (iii) automated conversation branching you don’t have to babysit.

    It would of course be quite a bit of work but the end result would be more control – and all without having to touch a third party scripting system.

    If you do want to use a scripting system – even with your own grown language parser – you have quite a few choices including the following:

    AngelScript, Spirit (part of the peer reviewed Boost suite) and maybe Squirrel.

    If you’re going with Lua (the recommended path of least resistance), then you need a suite of complimentary tools which includes some of the following:

  33. If you are set on XML, though, here’s strange approach, and I have no idea how practical it might be:

    questid(100).complete() = False
    Watch your back, there be dragons!
    192,193

    questID(100).complete = True
    There no longer be dragons!
    0

    Ah HA! Soon, there won’t be dragons!
    0

    Indeed there are.
    0

    questID(100).started = TRUE
    I’m on my way to take care of the problem, actually.
    107

    And so on. You’d basically have an NPC that can start conversations 106,105. It’d pick the first one in that list (ID doesn’t matter) that meets all of the COND conditions, and display it. The responses are similar, displaying only the responses that meet the proper conditions (although for responses, you wouldn’t stop at just the first one). JUMPTO just starts a new conversation entirely if it’s picked, possibly with its own responses.

    If JUMPTO is 0, it obviously just closes the conversation – maybe a simple “Thanks for your help” line that you could select to close the convo.

    I guess the biggest hassle is making sure your responses are in the proper order, since in this approach it’ll only pick the first one that meets all if its conditions (or doesn’t have a COND at all). Well, that and actually scripting something to parse the thing.

    Of course, this is an odd way to do it, but hey, maybe it’ll give you some ideas.

  34. We shipped a PS2 game with Lua as the scripting language. It’s not so bad on memory, just don’t get crazy with it and start doing what should be C++ code-level work. Most of the trick to getting reasonable memory footprint and performance out of any scripting language is KEEPING IT A SCRIPTING LANGUAGE. I’m looking at you, UnrealScript. 🙂

    @kim, I think that PC games simship tend to cannibalize more than you might realize from console sales. I can imagine this being even more of the case with casual games; the system requirements are lower so you’ll see more overlap of the people who don’t have ubermachines (but do own a 360) being able to play it, so they just bittorrent instead of XBLA/PSN.

    On the ACTUAL topic of conversation engines, XML is likely overkill if you’re just looking to read in data. With a couple of commercial exceptions all of the XML reader engines that I’ve looked at are going to be slow and clunky (or you’ll have license lockups going to consoles). If you’re not doing something clever and over-the-top with commands embedded in your conversations and you just want markup, take a look at what some of the web-based editing solutions are doing for bloggers; I would suggest Markdown or Textile as a starting point. You can even find open source reference implementations of scripts to read and parse.

    http://daringfireball.net/projects/markdown/
    http://en.wikipedia.org/wiki/Markdown
    http://hobix.com/textile/
    http://en.wikipedia.org/wiki/Textile_(markup_language)

    As for the conversation end of it, a number of people are recommending solutions that aren’t quite in line with what it sounds like you want, even though they’re really powerful (i.e. NLP-ish ones like Inform or Façade). I think Kriegshauser’s description of his work is a good jumping off point… you’re probably going to benefit a lot more in the “state machine that makes it easy to manage large conversations from script” arena than in the “understanding human speech” arena. 🙂

    -jf

  35. If we’re talking about conversation systems for particularly lengthy or nuanced conversations, there are two games that you should study. First off, there’s “Planescape: Torment”, which contains more conversational options than the conventional WRPG. RPGs in general tend to be very combat-heavy, both computer and pen-and-paper ones (open up any RPG primer, and 90% will most likely be about combat feats), but “Torment” includes a lot ways for the player to talk his way out of various situations, provided his character is smart enough. Some characters can be greatly influenced through conversations, even to the point of acquiring new skills through a quick application of logic. There’s a lot of dialogue in there, so it’s definitely worth a case study.

    The other one is Bioware’s “Mass Effect”, which uses a sophisticated dialogue system, much like the one you’ve described above (there are some things you can talk about, other things you can always ask about no matter where you are in the conversation, options that are hidden but triggered by variables). A conversation typically moves in a decided direction, but often the player has the choice of an “Investigate” option, which brings up a sub-menu, through which he or she can pick from different subjects they wish to inquire about. Lastly, there are conversational options (and small, subtle beats), that don’t occur unless the player has already performed a certain task, or spoken with another person about a given subject. In addition, some conversations are greatly altered by the order in which the player completes the game’s tasks.

    For example, picking a reaction to a suggestion might look something like this:

    -> Good idea
    Investigate Perhaps
    -> No way

    Choose the “Investigate” option, and you’ll see this sub-menu:

    Cargo History
    Crew BACK
    Captain Culture

    Choosing an option from the sub-menu might lead to a quick explanation, but can also lead to further dialogue options being made available in the main menu. Let’s say that the player picks “Captain”. First, he gets a response, after which the main conversation wheel re-appears, but now it looks like this:

    Captain’s drinking habit Good idea
    Investigate Perhaps
    Shady activities No way

    It’s pretty nuanced, so it might take more than one play-through to properly absorb the system’s strengths and shortcomings, but it’ll be well worth it. Some conversations are shorter and simpler than others. Some can go a dozen different ways, depending on your choices.

    Another thing is that the game does not spell out the actual line of dialogue, but rather gives a sort of “emotional reaction shorthand”. The player picks an option, and then his avatar provides the actual reaction as a piece of dialogue. Every line in the game is voiced, both the player’s own and that of the NPCs. Also, players don’t actually wait until the other character has said their piece. Rather, they are provided with the option to respond just before the other character finishes.

    This is essentially done to help with the “flow” of the conversation, so there aren’t as many awkward pauses in the dialogue. This all adds up to the creation of natural-sounding conversations, rather than characters reading off blocks of text or, (and this is much to my chagrin, personally, when a game does this) the feeling that a character is “talking at you”, rather than talking *with* you. Simply put, the “Mass Effect” series is the one to watch in terms of the development of conversations and dialogue in video games.

    So, I definitely recommend you play these two, if you haven’t already, because there’s a lot to be learned from them, and simply because they’re great games.

    Anyway, I wish you luck on your next project. Cheers.

  36. Here’s what one of my lua-based conversation trees looks like:

    conversation = {
    “init” = Monologue{
    “Hello. Listen to me.”,
    “It’s not safe here. We should get out of here as soon as possible!”,
    “Please follow me.”,
    “screw you” = Execute(function(this, data)
    if (data[“insultcounter”] == nil) then
    data[“insultcounter”] = 1;
    return Respond(“insult”);
    else
    return Respond(“insult2”);
    end),
    “who are you?” = Monologue{
    “There’s no time to explain now!”,
    “screw you” = Respond(“insult”)
    },
    “insult” = Monologue{
    “There’s no need to get offensive!”
    “screw you!” = Respond(“insult2”)
    },
    “insult2” = Monologue{
    “Fine. Suit yourself!”,
    done = Abort
    }

    It’s purely lua, parsed automatically to a usable tree when the script is loaded for the first time, and this is done through some lua magic that allows you to run the “Monologue” function with as first argument a table by calling something as Monologue{…}.

    This is quite a powerful approach, as it allows for dynamic rerouting based on the environment (through the Execute function), dynamic responses, complex trees with “goto” possibilities (through Respond), and so on. It’s also easy to read and comprehend, even for people with no coding experience. It’s working great in my game, so I can definitely recommend this approach.

  37. Okay, I added spaces in front of the lines of code to make the entire thing readable, but apparently the posting script removed them. How silly. Without indentation it definitely is much less readable.

  38. As someone noted above, take a look at Inform 7 and current Interactive Fiction games. Since IF is all text, the way you design conversations is vital because there are no pretty graphics to distract you from a crappy conversational system. And the IF scene is pretty old, so people have been tackling this issue for a while.

    One of the best designers in this respect is Emily Short, whose game Galatea was focused entirely on one conversation with one character. Best of Three, a more recent game, features her conversational system again. The nice thing about it is, like Mass Effect’s combat system, you select topics to talk about, without knowing exactly what your character is going to say. So you as the player get to choose a conversational path to navigate, while still being rewarded by how it plays out.

    The other conversational system that intrigued me in recent years was the one in Indigo Prophecy, where you had to select an option in a limited amount of time, or else your character would give a default response that may not be optimal. This overcomes one of the problems with branching conversation trees in games like The Longest Journey, where you feel that you must drain every ounce of information out of the conversation by making sure you’ve hit every conversation branch. Indigo Prophecy made that impossible, and therefore made every conversational choice important, while maintaing pacing and tension.

    Anyway, Inform 7 is a very exciting design language (especially for a non-programmer like me, it’s very intuitive), but there’s no reason to use the actual language – I’m sure you could adapt Emily Short’s approach to your own uses.

  39. I once worked on a chatbot which was extremely successful. People could talk with her for hours. Some people believed it was a real person.

    We used XML files, but it wasn’t structured as a tree. It was simply a huge database of keywords and responses, which some notion of “context”.

    What made a real difference was to have some talented people writing the dialogs. And, also, some kind a feedback — since it was a web based application, it was possible to collect actual conversations and extend her vocabulary.

    So, my advice would be:

    1) Use xml, but don’t make it like a tree. It should be simple and flat.

    2) Hire a talented writer to write the scripts. That will make a *huge* difference.

    3) Allow players to type questions (at least in beta versions of the game), and collect this material to improve your database.

    Just my 2 cents.

  40. A few more comments.

    Take a look on AIML – It provides some hints on how to:

    Resolve Synonyms: Map inputs “Hello”, “Hi there”, “Howdy” etc. onto “Hi”.

    Simplify Inputs: Convert “I am feeling very happy right now” to “I am happy”.

    Divide and Conquer: Split “Yes my name is Jim” into “Yes” and “My name is Jim”.

    http://alicebot.blogspot.com/

    You don’t have to use the same markup — but use that as a model.

    And, finally — by all means, use Lua or some sort of scripting language to make everything easier. 🙂

  41. Undecided; I have been working on other parts of that game. However, it’s going to be something simple, not any kind of natural language conversation system, because that does not fit the game design.

  42. A recent blog about moving beyond Inform 7 might spark some fresh ideas for you. It proposed a rules based system. Very interesting proposal, but he’s still trying to get it to work:

    http://www.eblong.com/zarf/essays/rule-based-if/index.html

    For The Witch’s Yarn, I cobbled a language together to allow theatrical conversations, dialog between multiple characters per user choice. It took about three days to write the compiler in Python. Basic structure was:

    BLOCK name
    ADD choices of blockNames to list after dialog finishes.
    REMOVE choices
    IF pythonExpr THEN
    ELSE
    ENDIF

    0 What is that dog doing here? [player is char 0. limit one 0 line per block]
    1 Woof woof!
    2 No way! Timmy’s trapped in the old well?
    1 whimper
    3 Do you really believe he is talking with that dog?

    [] comment delimiters

    (there were other useful keyword commands, but those were the work horses)
    ENDBLOCK

    ASSIGN 1 TheDog
    ASSIGN 2 Bill
    ASSIGN 3 Ted

    This language made it very easy and natural to write conversations. That’s a big win when you’re writing thousands of lines of dialog, keeping formatting tags to a minimum.

    By leveraging the compiler, you can spit out a spreadsheet for translation and a format that will merge with the translated versions. You can also add incredibly useful (game design specific) tests to a compiler.

  43. I’m delighted that you found my post interesting!

    The IF post you want to look at, though, is Emily’s GSW column from yesterday ( http://www.gamesetwatch.com/2009/05/column_homer_in_silicon_the_co_1.php ). It’s specifically about a rule-based conversation architecture, and it has the distinct advantage that it’s usable in real life. 🙂 Alabaster ( http://emshort.home.mindspring.com/Alabaster/ ) is a conversation-centered I7 game that uses this model.

Leave a Reply

Your email address will not be published. Required fields are marked *