Response Library
jaynabonne
09 Sept 2013, 22:38- 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
10 Sept 2013, 10:53By 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
10 Sept 2013, 15:12As 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
10 Sept 2013, 21:20As 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
10 Sept 2013, 23:05One 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
11 Sept 2013, 08:01In 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
11 Sept 2013, 09:04In 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
11 Sept 2013, 09:57I 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
11 Sept 2013, 11:00jaynabonne
11 Sept 2013, 11:14The Pixie
11 Sept 2013, 15:00You 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
11 Sept 2013, 19:16Thinking 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
11 Sept 2013, 19:34<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
11 Sept 2013, 19:50<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
12 Sept 2013, 07:26I 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
12 Sept 2013, 08:05jaynabonne
12 Sept 2013, 22:16jaynabonne
27 Sept 2013, 10:17george
11 Feb 2014, 02:51
<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
11 Feb 2014, 06:46In 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
11 Feb 2014, 15:39Really cool work on the library by the way, I'm going to use it in my game.
jaynabonne
12 Feb 2014, 20:54Silver
26 Aug 2014, 18:25For 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
26 Aug 2014, 20:23Silver 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
26 Aug 2014, 20:58jdpjdpjdp
22 Dec 2014, 06:01Alex
22 Dec 2014, 09:27jdpjdpjdp
22 Dec 2014, 22:43I've only played with it a bit... will return later with questions/comments.
jaynabonne
22 Dec 2014, 22:58jdpjdpjdp
23 Dec 2014, 05:33Error 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
23 Dec 2014, 09:39If 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
23 Dec 2014, 18:11jaynabonne
23 Dec 2014, 20:34jdpjdpjdp
23 Dec 2014, 21:18Anyway, 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
24 Dec 2014, 22:04You 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
24 Dec 2014, 22:10jaynabonne
24 Dec 2014, 22:22jdpjdpjdp
25 Dec 2014, 00:23jaynabonne wrote:And if it's not clear, the whole calling/suggesting thing is more advanced.
Yeah it's pretty clear.
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!