Response Library

jaynabonne
What started out as that long "Conversations" thread back in April has now culminated in a Beta version of my "Response" library. The attached is the current beta version. The drop includes:
- The response library ResponseLib.aslx
- A sample game, in the Sample folder
- An Integrator's Guide, which describes the few steps needed to integrate the library and get up and running.
- A User's Guide, which describes the elements that can be used in responses.

The documentation is undoubtedly incomplete. It is in beta form as well.

What I would hope is that at least somebody wishes to try this out. :) And the more the merrier. What I'm looking for in terms of feedback is:
- Are the docs clear? What areas need improving?
- How easy is the library to integrate into a game?
- Are there cases that the response library doesn't handle well? I'm looking for new features to add for common and perhaps not-so-common cases.
- Do you like it? Does it make sense?

The basic idea behind this library is that of creating rich, dynamic responses for all the typical game events - commands, verbs, descriptions, conversation, etc. This a highly data-driven approach. In the sample game, beyond the minimal code needed to integrate the library, there are only handful of code lines in the responses, despite there being standard game mechanics like keys-in-holes, conversation, appearing exits, and a simple combat scene.

It is a different way of designing a game. I hope, at least for some, it will be a better way. There are capabilities of this library that the sample game does not exercise. I plan to show off some of those in later postings.

I hope this can be useful to someone. I'll be posting updates to this, as well as further samples. I was working on a game for IFComp that didn't come together in the end. So there is a bit of testing on the library in terms of the real-world case of my game. I may post that later as well.

(Why oh why does this forum not allow .PDF files? And a data size limit of 200-someodd K, and only three attachments...)

Edit: Version 0.6 (2013-09-12)
Updated Library and Sample
- Worked around a Quest issue with serializing Boolean values stored in dictionaries.
- Made isgroup not needed for top-level response set.
- Added handlers and corresponding topics to ResponseLib_Room for beforeenter, enter, onexit, beforefirstenter, and firstenter. Topics are upper-cased form of the attribute.
- Added ability to reset a response's use count, to allow recurring behavior (e.g. a traffic light). ResponseLib_ResetUseCount(response)
- Made required topics be "or" (fixed code).
- Added a command to the sample game for exercising the menu (a bit lame): "speak/talk to mirror". (I just saw the response has a typo. Ah well, a todo for next time.)

Edit: Version 0.7 (2013-09-27)
Updated Library
- Added support for modular response handling (support inheritance):
- Added "<includes>responseobjectname</includes>" attribute to allow sharing of response sets.
- "action" scripts are now passed the responding object as "responder". "this" still refers to the response itself.

The Pixie
Can you explain why this approach is better than what Quest already offers? I think it is this "big picture" overview that is missing from the docs. I had a quick look at the game, and all the functionality I saw looked pretty easy to code without your library, and probably with less typing too.

By the way, the readme says "To talk to the Janitor, use "ask janitor about XXX"." I tried talking about the bat and the mirror, the only obvious topics, and got no reply.

Also, the "show topic" command is misleading. I was expecting to see topics available for the player. I suggest another command phrase.

jaynabonne
Let's get the short ones out of the way first.

As far as talking to the Janitor, I can see how this simple game has design flaws. The mirror and bat were actually added in just so I could show how verbs and commands hook in. They're absolutely irrelevant to the completion of the game, which involves the machine in the room and its missing key. Try asking about those. :) I'll add in some response to mirror and bat in the next rev of the sample.

The "show topics" command is a debugging command that would not normally be part of a game (more "test app"-itis). It shows the topics sent to the engine for the commmands typed. It provides an easy way to determine what topic keywords a specific command will input, which should make creating responses easier. It could be called anything. (I just happened to pick that.)

Now on to the tougher question: why is it better? The answer varies - perhaps for some it isn't. And I don't really want to get into such comparisons in the docs, since it really all depends. I hope that if the library will work better for someone, they will see it and embrace it for that reason.

The test app does do things that a standard Quest game would do. That was intentional, in that I wanted to show how you do the things you normally do in Quest "the response way." Unfortunately, some things can be better done the way they currently are done. For example, the "bat" description can more easily be done by just typing in its "description" field than by creating a response. There are reasons *to* create a response if you're already using the library, two of them being consistency and ease of later expansion, but you're right - some things are better done the current way. And the library is designed to allow you to only use it for what you want.

The basic idea behind the library is that (if taken to the limit) your game would consist of responses to events that are occurring in the game world. I chose the word "call" for such an event (from "call and respond"), which is a bit weird at times, but I had to call it something... :) For each "call" that comes in, all the current responses are checked, and the highest scoring ones that match are processed. The library generalizes what happens in Quest, and that is one advantage for me - I can treat everything the same, whether it be an object description, a conversation topic, the processing of a verb or command, or background (idle turn script) processing. It's all the same thing. Once I know how to create responses, I can respond to anything, with all the same flexibility in all cases.

The library attempts to address all the common beginner questions that are posted in the forums by Quest game creators:
- How can I output random text?
- How can I output text that varies depending on game conditions?
- How can I output text that changes each time it is shown?
- How can I make things happen at certain times?
- How can I change what happens when a player tries to exit?
- and many more...

So far I have mentioned two advantages to the library: consistency and expandability. A third is that it hides messy details under the covers. Let's look at an example that I hope will show some of the problems I wanted to solve.

Let's say you have created a room that has a window. Let's focus on the window. You assign it a description, and all is well. Here is the same as a response.

<object name="WindowLook">
<topics>*LOOKAT</topics>
<text>You look out onto a sunny day.</text>
</object>


More typing for sure. And probably not worth it for that.

Now, let's say later in the game, you want to incorporate the passage of time - you want morning, afternoon and night, with corresponding changes to the window description. How do you do it? Well, in the standard Quest approach, now you have to switch - you have to convert your text description to a script one. Then you have to take the text you had in your description, and you have to put it into an "msg" command and wrap that in an "if" and then add the other cases. Now you're happy. You have morning, afternoon and evening descriptions.

As responses:
<object name="WindowLookMorning">
<topics>*LOOKAT</topics>
<needs>morning</needs>
<text>The ground outside is wet with the morning dew..</text>
</object>
<object name="WindowLookAfternoon">
<topics>*LOOKAT</topics>
<needs>afternoon</needs>
<text>You look out onto a sunny day.</text>
</object>
<object name="WindowLookNight">
<topics>*LOOKAT</topics>
<needs>night</needs>
<text>The sky is black and filled with stars.</text>
</object>


(There are other ways to group this, such that the LOOKAT topic is checked first with nested children, and that would reduce the amount of text, but that's not essential for this example.)

As you can see, the case above is just more of the same - we now have three responses instead of one, each with its own condition. We did not need to shift gears from text to script. We're doing the same thing now we did before.

You also need to somehow advance time. There are libraries for that, but it's not necessarily a simple drop in. You would (minimally) need to create a turn script and then set up the varible(s) to use and then advance them. For this example, let's assume that time will be turn-based. Let's say after 50 turns, it's afternoon, and after 100 it's night. In the standard case, you need to dip down into variables, initializing them, creating a turn script to increment them. It's not a big deal for someone who codes, but for math-phobes, it can be imposing.

Here is the response for handling the passage of time. Assume that "morning" is initially set.

<object name="TimePassage">
<topics>IDLE</topics>
<sets50>afternoon !morning</sets50>
<sets100>night !afternoon</sets100>
</object>


That's it. We say "on the 50th time, set afternoon and clear morning. On the 100th set night and clear afternoon." No need to learn about turn scripts, no math to set and increment variables, no scripts whatsoever.

Now we do have a conceptual shift. Now we need to think about things like "When should this response happen? What are the conditions? What should it do?" as opposed to "How do I code a script? How do I work with variables?"

Let's say we're getting adventurous now. We want to have random events occur when we look out the window, but only in the afternoon. How do we do it? In the standard Quest case, we would need to dive into GetRandomInt. More math (well, numbers, but it's all the same for some). The author is saying, "I just want to randomly choose between some things." Those are words, but they need to be translated into numbers. They would need to call GetRandomInt and then either use a switch statement or an "if-then-else" to choose different paths based on that number. Let's look at the response for this:

<object name="WindowLookAfternoon">
<topics>*LOOKAT</topics>
<needs>afternoon</needs>
<usechildren>random</usechildren>
<object name="WindowLookAfternoon_Normal">
<text>You look out onto a sunny day.</text>
</object>
<object name="WindowLookAfternoon_ManComing">
<text>You see a man coming up the walkway.</text>
<sets>mancoming</sets>
</object>
</object>


Some things to note: we now have nested responses, but the concepts are all the same. And we just said "choose a random child". No need to learn how random numbers are generated; no need to get into if/then/else or switches. Just "choose randomly between these two." And we could add more choices, and it would just work. Note was well that the response need not only have text - it can set variables, it can call scripts ("action" fields), it can make "calls" out to other objects for other responses.

I could go on, and perhaps I should, in some sort of design document or a tutorial. I'd love to put the latter together. But for now, I hope at least some of the flavor is coming through.

There are also more advanced uses that the sample game didn't show. I kept it simple to not overwhelm people, but in the game I was working on, I had features like:

- If you look at the holes in the wall, the first time (only) the old man would say, "Don't put your hand in the hole. You might not get it back." This required having the old man *know* that you were looking at the holes. That would be tricky to do with standard Quest scripting. In the response library, all you had to do was add "<suggests>holes</suggests>" to the description (LOOKAT) for the holes and then add a response for the old man during IDLE time for that topic.
- The old man would initiate conversation. There is a part of the library that allows for "callers". These are object/characters that call their own topics out into the world. In my game, the old man would offer you a cigarette or inquire about why you're in the prison. You could, in theory, have two NPCs engaging in a conversation with each other! Each would call topics that the other would respond to.
- Different output styles. The sample game shows some of this - you can assign classes to the responses and then handle them differently at output time, to show them in different order, in different styles.
- Advanced class usage. I wanted the old man to ask you questions, but only at quiet times. If you were conversing with the old man, asking him questions, etc I didn't want him to suddenly shift topics to something else. So I wanted him to only initiate during reflective times, not interactive times. I did this by having two classes for response, "reflect" and "interact". (A reponse could also be neither.) Then during output, I would manage the counts, bumping the "reflect" count each time I got one of those (e.g. looking at the room, sitting, standing) and setting it back to 0 when you interacted (e.g. asked the old man a question or got a response from him). Then the <cond> for my calls would require a reflect count of at least 1. Otherwise, you were interacting, and he waited. Again, you could do this in Quest (I mean, my library does, and it's written in Quest), but trying to do it with standard scripts might end up being a bit clumsy.
- Referencing responses within other responses. There is a simple text markup wherein one response can incorporate other responses in. This allows you to break your text up into common piece and then thread them together at output time. This is especially useful if you're trying to have a variable narrative depending on the path the player takes. And it keeps you from duplicating text, actions, etc. The sample game shows this a little with the SMASH_MIRROR common piece.

A final advantage to me is the ability to consolidate everything together and make it all uniform. I can handle everything about a character or object in one spot. I don't have some in the object, some in a turn script, some in verbs or commands. It allows for a nice modular design.

Perhaps more than you wanted to know (and I could probably ramble on much longer), but I hope that helps somewhat.

I would love to see if the *concepts* of the response library - having a rule-based approach to at least some of what goes on in a game - could be incorporated into future versions of Quest more naturally in the UI. Then, in addition to a script editor, you'd have a response editor...

In standard Quest, it's easy to add text to objects. If you want to do anything beyond simple text, you have to learn how to code scripts. So it's either simple (boring) text, or you must be a coder. This library allows you to do almost everything you can do in Quest now, with minimal dives into script. It's a bit clunky to set up in the GUI editor (but not impossible - it's designed to be "editor friendly), but the *concepts* (I believe) are clean.

This library might not be for everyone or even for many. But for those for whom it works, it can be very powerful, liberating and a heck of a lot of fun. :)

The Pixie

As far as talking to the Janitor, I can see how this simple game has design flaws. The mirror and bat were actually added in just so I could show how verbs and commands hook in. They're absolutely irrelevant to the completion of the game, which involves the machine in the room and its missing key. Try asking about those. :) I'll add in some response to mirror and bat in the next rev of the sample.


Okay. I happened to look at the wrong things.

The "show topics" command is a debugging command that would not normally be part of a game (more "test app"-itis). It shows the topics sent to the engine for the commmands typed. It provides an easy way to determine what topic keywords a specific command will input, which should make creating responses easier. It could be called anything. (I just happened to pick that.)


I realised it was a debugging command - the problem is that it does not sound like one.

As for the rest, I will think more on it, but your explanation does help. And I think that that is what is missing from the documentation. A tutorial will be useful too.

So how stable is it? If I use the library to create a game now, how likely is it to work in six months?

jaynabonne
I would consider it very stable, especially in terms of the definitions of things and expected behaviors. I happen to consider it stable code-wise as well, since I've been evolving and using it myself in a real-world game situation, but I know that bugs always exist. At this point, for me it's particularly a question of whether I have covered the sorts of things people would want covered. For example, "use children - first" was a more recent addition, since I began running into cases where the definitions were getting a bit unwieldy. So... I'm happy to take feature suggestions and feedback on where things work and where they don't. I believe the current set is a good starting point, so it should just be forward motion from here.

One area I haven't used much (strange as it sounds) is the Quest integration - the hooked verbs and commands. The game I was working on was using the library as the entire parser. While that gave me lots of insight into how well the library was working in different situations, it ended up not being very viable in terms of user experience (it would match too much when it shouldn't). So getting it integrated with the more rigid (relatively speaking) Quest parser is a good thing, but I haven't used it much in that way. There may be issues there.

I want to work up a sample with more conversation in it. Another thought is to take the game I was working on and convert it to using the new Quest parser integration. That should fix a number of things in the game and will give me experience with how well that works.

If you give it a try and have any problems or questions, please let me know. I look forward to what you'll discover. :)

The Pixie
More comments and questions.

In the Integrator's guide, you say it is a good idea to inherit from response library types, but you do not do that in the demo (because the demo is not integrated?), or in the examples later in that doc.



In the demo, you have this:
    <object name="RoomLook">
<topics>LOOK</topics>
<usechildren>first</usechildren>
<object name="RoomLook_MachineOn">
<needs>machine_on</needs>
<text>The room is a bit less depressing now.</text>
</object>
<object name="RoomLook_MachineOff">
<text>The room is quiet and depressing.</text>
</object>
</object>

This seems to assume that a certain order is preserved, that RoomLook_MachineOn is always before RoomLook_MachineOff (as only the former has the condition). Is that a sagfe assumption? I considered doing something similar some time ago, but got the impression it was not. In particular, when you save the game and reload it, can you be sure the order is preserved?



For topics, I see LOOk and LOOKAT used as examples. Are these topics hardcoded into Quest/ResponseLib? If so, is there a full list of topics somewhere? Or does response lib actually send this value to the Quest parser?



Is "isgroup" ever false? Would it save typing if group is the default (so the flag is "issingle")?



You have:
<needs>!mirror_smashed</needs>

Quest uses "not", might be better as <needs>not mirror_smashed</needs>



Any GUI support? Looks like the answer is no; would be good, even for coders, as it saves typing the XML tags.

jaynabonne

In the Integrator's guide, you say it is a good idea to inherit from response library types, but you do not do that in the demo (because the demo is not integrated?), or in the examples later in that doc.


Actually all standard Quest objects in the demo aslx do: the room inherits from ResponseLib_Room, the bat inherits from ResponseLib_Object, the player inherits from ResponseLib_Player, etc. The responses themselves have no base types. They're just pure data objects. (For some reason, in the demo, I inherited "machine" from ResponseLib_Responder. That's actually wrong. It should be ResponseLib_Object.)

This seems to assume that a certain order is preserved, that RoomLook_MachineOn is always before RoomLook_MachineOff (as only the former has the condition). Is that a safe assumption?


I really hope so. If not, then everything falls apart. I will do a "save" test. I'll also ask Alex.

For topics, I see LOOk and LOOKAT used as examples. Are these topics hardcoded into Quest/ResponseLib? If so, is there a full list of topics somewhere? Or does response lib actually send this value to the Quest parser?


I'll have to make that stand out more in the Integrator's Guide. For verbs, the topic that comes in is the verb's "property" attribute upper-cased. For commands, it's the upper-case form of the command's name. I decided to go with upper-cased forms of verbs/commands and lower-cased forms of verb/command *text* (e.g. the text value for "ask/tell") as a canonical form. That actually causes a conflict with "sit" and "siton" (why the property for "siton" is "sit" is a mystery to me). I had contemplated going through each of the standard Quest verbs and listing what that would be in the doc. I think I'll still do that. I had figured that if people could figure out what attribute to use for a verb, they could work out the corresponding topic, but why not be comprehensive? :) As a fallback, you can use "show topics" to see what the verb or command causes to be injected.

Is "isgroup" ever false? Would it save typing if group is the default (so the flag is "issingle")?


Actually, out of the 60 response objects in that file, only 7 are groups. But this does raise a point: the "isgroup" is more or less typically necessary for the top level set of responses that an object refers to. Hmm... Originally, that top level set of objects was just an object list of responses. So you didn't need "isgroup", since it wasn't the same thing as a response; it was just a list of responses. For some reason, I eventually realized I could make the top level object a response in its own right, to make it all consistent. But then you had to mark it as "isgroup" unless you just wanted a single response at the top (but who would?). Let me think about that. I could easily change it back to where the top level object is just a container for the responses, where "isgroup" is no longer needed at the top. It will be a data structure inconsistency, but it will make it simpler. Or perhaps I can work out a way to special-case the top-level set. Thanks!

Quest uses "not", might be better as <needs>not mirror_smashed</needs>


The reason for this is that it might not be a single word. For example, if a topic has multiple needs, then you just list them there:

<needs>sawfigure !conversing<needs>

means "needs sawfigure and not conversing". I just do a split on the string and then check each word, with "!" being a convenient first character to look for. If I wanted to switch to "not", I'd have to parse the words more to look for words to pair up. Let me think about that. I do understand what you mean. I was also contemplating allowing things like "and" and "or", as the default now is always "and", but then you need to get into parentheses to really be full-featured, and it felt more complicated. But... the ability to have "or" might be handy.

Any GUI support? Looks like the answer is no; would be good, even for coders, as it saves typing the XML tags.


The only real GUI support is via the Attributes tab of the object. Fortunately, Quest puts the object-defined attributes up front (as opposed to the inherited ones), so you don't have to paw through the list. You could, in theory, do it all in the GUI that way. At least you wouldn't have to type the XML! I had initially considered showing in the doc both the GUI and non-GUI ways to set up objects, especially in the Integrator's Guide for the top-level object inheritance and the response attributes. Perhaps there can be a separate "Using the GUI" section.

This is great feedback. I really appreciate it.

jaynabonne
I did a Save test, and it seems to work fine as far as object order goes.

I did run into a Save problem that Alex has reported as bug - that Boolean values in dictionaries don't serialize properly. I have made a change to the library to work around this, and the new version is attached.

Edit: Attachment deleted as the initial posting now has the latest version.

jaynabonne
A further update: I asked Alex about object order, and he said the order should be preserved across saves. He even went so far as to say that if the order was not preserved, it should be considered a bug to be fixed. (Whew!)

jaynabonne
Todo list:

The Pixie
Thinking about this further, I would be inclined to use "!" rather than "not". It feels better when you have <sets> as well. And saves typing.


You could have a <needsone> tag to indicate an OR situation; the response just needs one flag to be set from those given.


"Selection phase: Only the responses with the top score are selected. There may be more than one response selected if they have equal scores."
I cannot imagine when I would want more than one response. Always giving a prompt is a way around thas however.


"In the following example, “HIT” is marked as a required keyword. If that keyword does not exist in the call, then the response is discarded during the eligibility phase. Its score it not even computed."
I am uncertain how well this would work. I can see requiring something for my response, but I would want to allow a number of synonyms. What if the player types "strike" or "attack"? I want them handled with the same response. But I still only want that response to be seen if one of those is present. Can you have multiple words flagged with *, and only one is required?

jaynabonne

Thinking about this further, I would be inclined to use "!" rather than "not". It feels better when you have <sets> as well. And saves typing.



Ok, good. Less work for me. :)

"Selection phase: Only the responses with the top score are selected. There may be more than one response selected if they have equal scores." I cannot imagine when I would want more than one response.



I have encountered some uses for that. One is in the case of the room description. The sample game shows this (the machine adds its own description into the room description).

The other case is when using prompts as multiple choice options (like a menu):

<object name="GenderLeadin">
<topics>GENDER_QUERY</topics>
<text>The elf leans in closer. "Be ye male or be ye female?"</text>
</object>

<object name="GenderMale">
<topics>GENDER_QUERY</topics>
<prompt>I'm a red-blooded male</prompt>
<sets>male</sets>
<calls>GENDER_SET</calls>
</object>

<object name="GenderFemale">
<topics>GENDER_QUERY</topics>
<prompt>I'm all woman</prompt>
<sets>female</sets>
<calls>GENDER_SET</calls>
</object>

This will print out the lead-in and then the two menu choices.

(You can invoke this by either calling ResponseLib_Call("GENDER_QUERY") in a script, or by using:

<calls>GENDER_QUERY</calls>

in a response.)

Can you have multiple words flagged with *, and only one is required?


I was going to answer that it is that way, but then I looked at the code and realized I had done it the other way. I actually do want it to be an "or" situation, since topics are already non-exclusive. So I'll change the code.

jaynabonne
Thinking about it, I guess you could also do my menu example as:

<object name="GenderQuery">
<topics>*GENDER_QUERY</topics>
<isgroup/>
<object name="GenderLeadin">
<text>The elf leans in closer. "Be ye male or be ye female?"</text>
</object>
<object name="GenderMale">
<prompt>I'm a red-blooded male</prompt>
<text>"I'm a man, thank you."</text>
<sets>male</sets>
<calls>GENDER_SET</calls>
</object>
<object name="GenderFemale">
<prompt>I'm all woman</prompt>
<text>"I'm a woman, you twit."</text>
<sets>female</sets>
<calls>GENDER_SET</calls>
</object>
</object>


It's still invoking multiple responses, but they're more nicely grouped.

jaynabonne
Here's something to ponder... Given the above "menu" (the second one with text), if you add this to the GenderMale:

<needs>!female</needs>

and this to the GenderFemale

<needs>!male</needs>

then something interesting happens if "male" or "female" is already defined: the "other" response doesn't match, you end up with only a single response with a prompt, and that single response will just be executed directly.

So if "male" were already set, you'd just see:

The elf leans in closer. "Be ye male or be ye female?"
"I'm a man, thank you."


The Pixie

I have encountered some uses for that. One is in the case of the room description. The sample game shows this (the machine adds its own description into the room description).

The other case is when using prompts as multiple choice options (like a menu):


I was guessing the machine adding its own description was a recursive call back to the response library, rather than two competing responses.

With regards to menus, it would be good to put that in the demo. It is an aspect that appeals and is not at all obvious.

I would like to have a play around. Do you intend to release a new version in the near future?

jaynabonne
Let me update it by this weekend with the changes we've discussed. It may be sooner (perhaps even tonight), but it depends on work.

jaynabonne
New version of Library and Sample uploaded to initial posting. Changes listed in initial posting.

jaynabonne
New library posted (docs to come later). Support added to allow for inheritance via "includes" of common responses as well as the responder object being passed into action scripts so that shared actions can apply to different objects.

george
This is probably a dumb question, but I didn't see it stated explicitly in the docs -- if you're writing a response, say like this,


<object name="BatLook">
<topics>LOOKAT</topics>
<text>Louisville never made a slugger like this.</text>
</object>


Does the QRL know to call this response because you've named it 'BatLook'? For example naming it 'Bat_Look' wouldn't work?

jaynabonne
The only object names that are critical are the top-level response sets: for example, "bat responses" for the "bat" object, "room responses" for the "room" object, etc. All the other object names can be anything you like, and I wish, in fact, that you didn't have to give them at all, as they're not used by the library. But every object in Quest needs a name, so you have to provide one.

In the example you gave, fleshing out a bit more, you have:

  <object name="bat responses">
<object name="BatLook">
<topics>LOOKAT</topics>
<text>Louisville never made a slugger like this.</text>
</object>
...
</object>


It's part of the "bat responses" set, so it will be looked up whenever "bat" is the target (e.g. "look bat", "use bat", etc). And the LOOKAT topic means it will be the response when "x bat" or "look at bat" are input. The "BatLook" name could be anything.

george
Thanks Jay, that makes much more sense!

Really cool work on the library by the way, I'm going to use it in my game.

jaynabonne
Great! If you have any questions at all, drop me a PM. I'm curious to see where there may be holes or things not so easily understood. Also, I might have thought of ways of doing things that weren't made clear in the examples.

Silver
I'm interested in this for what I think it might do.

For instance, if I look at the monkey in the cage it might be eating an apple. If I look again ten seconds later it will still be eating the apple. But if I leave the room and come back it might be swinging off the rope or have gone to bed. Is this the sort of thing the code deals with?

Also, does this then replace quest's code completely? If so is there an interface or are coding skills needed in order to use this?

jaynabonne
Silver wrote:I'm interested in this for what I think it might do.

For instance, if I look at the monkey in the cage it might be eating an apple. If I look again ten seconds later it will still be eating the apple. But if I leave the room and come back it might be swinging off the rope or have gone to bed. Is this the sort of thing the code deals with?


That is the idea, yes. A general purpose way to have responses to user input that vary depending on game state, etc. :)

Silver wrote:Also, does this then replace quest's code completely? If so is there an interface or are coding skills needed in order to use this?


The latest code has been integrated with the Quest object model. So you can define responses for objects easily and set up the responses to handle verbs and commands without having to write script for most things.

The only downside is that it's based around response data definitions, which use Quest objects as responses - and it's not so easy to do that through the GUI interface, since the attributes edit mechanism doesn't lend itself well for this. You can use it, but I prefer looking at the raw text myself. If you do give it a try, I'm curious to see if the GUI would work for you. (I keep meaning to find out if I can create custom editor pages.)

I'm actually using this library in my own current game work. I have a game in development that I'm desperate to get done, but it's that last 20% that seems to take the longest. I'm hoping to submit it for IFComp, but it's looking a bit grim at the moment. (I missed last year's IFComp as well. Then I gave up on it, then I came back to it, then I eventually came up with a new way of looking at the UI that solved a number of problems, and now I'm working on it again. lol)

If you'd like to try the library out, I'd be happy to help. I don't know if it will work for you or not, but you never know!

Silver
Well I'm in a position where I've started writing two games (literally the opening scenes, the easiest bit lol) but have plotted them out on paper and looking at having a good overall grasp of the software before hammering them down. So I'll have a play with your script but I really am a complete newbie when it comes to coding (even more than I am IF, but at least I understand the basic principles of that) but maybe now is a good time to learn? I'm in no hurry to get anything finished. I'm a perfectionist (nothing ever gets finished but they would have been good).

jdpjdpjdp
I'm interested in downloading these and seeing what they can do, but all the zip files are reading as corrupted and won't open. Could someone please check and see if they are working right, so at least I'll know if the problem is on my end or not?

Alex
Thanks for pointing that out - I moved the forum to a different server over the weekend and this was one of the casualties. It is fixed now, so please try again!

jdpjdpjdp
Works fine now, thank you!

I've only played with it a bit... will return later with questions/comments.

jaynabonne
If you want to see it in action, you can look at the "spondre" source as well. The game was written using the library. (In fact, the library in that game source is more up-to-date than this one.)

jdpjdpjdp
Well, I've only just started with the most preliminary aspects of the library and I've encountered a problem. When you take or drop an object, it does it successfully, but not without displaying the following:

Error running script: Error compiling expression 'value': Unknown object or variable 'value'

I even tried dropping the bat in the included demo, just to make sure it wasn't something I'd messed up... same result. Am I missing something? I want to make sure there's some easy fix for this before I delve any deeper...

jaynabonne
It was fixed but not uploaded as part of the sample. You can either grab the response library from the spondre source or I have attached the latest response library as a separate attachment in the first posting in this thread. Sorry about that!

If you wish to manually fix the version you have, search for the function "ResponseLib_AddObjectParam" and change:

foreach (obj, value)

to

foreach (obj, o)


The new version gives you some nifty new features, though (like being able to have numeric values and use "needs" with some small set of expressions, so you can have value-based responses in addition to binary "is this set" sort of conditions), so you might want to switch to it anyway! :)

jdpjdpjdp
I had already downloaded the spondre source -- which you told me had a newer, better version of the library -- but I was using the older one! My bad. I'll make the switch. Thanks!

jaynabonne
The response library can be used for either parser-based games (like the demo) or hypertext-type games (like spondre). If you're going parser-based, then the demo is a good start. If you'd like a setup like spondre, let me know. I could provide a stripped-down "starter kit".

jdpjdpjdp
I'm going the parser route, for now. I was actually working on a hypertext sort of thing, but I've put it on the backburner. Maybe if I can get a proper handle on this library I'll give it a go after all!

Anyway, I like what I'm seeing, in particular the fact that I can utilize the functions I want but use the editor for things it does easier (like basic, unconditional verb/object pairings).

One thing has me confused, and that's "suggests" and "listeners". How I think it works, and PLEASE correct me if I'm wrong: a response is given a "suggests" attribute. This is a keyword or words that have now been "suggested" to any listeners in the current context. If the player inputs one of those keywords subsequently, the listener will produce a particular response. Is that the basic idea? And, if so, how do you create the response the listener will produce? Is it just a regular response keyed to that word? If so, then why do you need "suggests" at all?

As you can see I'm a little turned around. Sorry if my questions are a bit dense, my understanding of code is minimal. I greatly appreciate the willingness to help me out, though.

jaynabonne
I don't know how I missed this before, but apologies for not responding sooner. :)

You have the right idea in general. Topics suggested by responses are broadcast to all available listeners. The default behavior for a listener is to add the received topics to its "short term topics" list. Short term topics differ from long term topics in that short term topics fade away over time. They're meant to be contextual, representing the current topics of discussion or activity, as opposed to long term topics which are meant to be more permanent. (The italicized topics shown in spondre in the bottom bar are short term topics.)

Right now, short term topics are used by "callers". These are responders that can trigger their own topic queries (the same as the player does either by clicking links or typing at the prompt). The Spon character is a caller - he has his own actions, prompts his own conversation, asks questions, etc based on long and short term topics. For example, if you have looked at the holes once you've begun speaking to him, then he'll say "Be sure you don't put your hand in those. You might not get it back." Stuff like that. It's supposed to allow characters that have their own independent actions to track the conversation to inject their own relevant topics.

Callers have their own set of responses. If you look in the spondre source, in spondre.aslx, you'll see that "TheOther" character looks like this:

    <object name="TheOther">
<inherit name="editor_object" />
<inherit name="ResponseLib_Caller" />
<alias>the strange figure</alias>
<capalias>The strange figure</capalias>
<longtermtopics type="dictionary" />
<reflectcount type="int">0</reflectcount>
<responses type="object">TheOtherResponses</responses>
<calls type="object">TheOtherCalls</calls>
<changedalias type="script">
this.capalias = CapFirst(this.alias)
</changedalias>
</object>

It has both "responses" (which are the responses to the player's queries, etc) and "calls", which are what it prompts on its own based on its own internal long- and short-term topics.

Callers are triggered to "do their thing" by a custom topic called "CALL". You don't need to worry about matching that topic - it's used internally. You just need to provide caller responses. This caller topic is sent via a turn script, after the IDLE topic is sent. So callers get a chance to contribute to things on each turn. :) So you could have a caller response with topics of "cat", and if the topic "cat" comes up via a suggests, then the next time the calls are requested, it will trigger that response (if it's eligible). That way the "caller" NPC can appear to respond to the current conversation - or whatever the player happens to be doing, if the response suggests the appropriate thing.

jaynabonne
And the reason why I put this in (as opposed to just having the responders respond directly) is that the suggested topics might not be what the player has initiated. For example, asking a character where they're from might elicit a response like "I lived with my family on a farm in Foobiebush.", which might then suggest topics like "family father farm Foobiebush". Later, during a post-turn call, the NPC (depending on design) could pick up on any of those topics, depending on strength (the more you suggest a topic, the higher priority it is) and generate subsequent conversation. Continuing our example, the NPC might on its own then later prompt (as you look at the apple on the table), "Our farm was quite small, but I always loved it there" based on the short term topic "farm" still being in the list, injected by the response suggestion two turns back.

jaynabonne
And if it's not clear, the whole calling/suggesting thing is more advanced. You could probably get away with a fairly complex game without using it at all. It really has specific uses as far as having NPCs having more autonomous actions and reactions.

jdpjdpjdp
jaynabonne wrote:And if it's not clear, the whole calling/suggesting thing is more advanced.


Yeah it's pretty clear. :lol:

I think I've got a better handle on some of it. Gonna move forward on my current game plans without implementing that, but I've got a test game set up with it installed so I can keep playing with it and (hopefully) figure more of it out. I've never made a game before, so this entire thing is one big learning experience. Thanks for the library and the help... it's great to see people around here are so willing to offer their wisdom to those of us who need it!

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums