Writing answers instead of choosing menu options [EDITED]

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Message
Author
User avatar
xavimat
Eileen-Class Veteran
Posts: 1460
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Writing answers instead of choosing menu options [EDITED]

#1 Post by xavimat »

EDITED CODE.

A simple function that recognizes the words written by the player and can be used as a substitute of the menus.
It's inspired in fiorica's "The Doll's Stories" and uses some code from SusanTheCat's "Thera'Py".

Simply add the file 'reply.rpy' to the game directory and use the 'reply()' function to make questions to the player.
The functions needs a question (a string) and a list of possible answers (only simple words), and returns one of the words given.
If the player doesn't respond any of the options, the function presents a warning message, and repeats itself.
The function reply2() returns the list of valid keywords found in the player's answer.

An example:

Code: Select all

$ r = reply("Where can we go?", "park, beach, home")
if r == 'park':
    # do something
elif r == 'beach':
    # do something
else:
    # do something

$ r2 = reply2("Where can we go?", "park, beach, home")
if "park" in r2:
    e "You have chosen park"
if "beach" in r2:
    e "You have chosen beach"
if "home" in r2:
    e "You have chosen home"

$ l = len(r2)   
if l > 2:
    e "You have chosen too much."   
    
#Note that with reply2() we don't use "elif" but separated "if" because all of the keywords can be found. With "len()" you have the total of keywords found in the user's reply.
Here the code of 'reply.rpy':

Code: Select all

# Reply and Reply2
# by xavimat (cc-by, 2013)
# inspired by fiorica's "The Doll's Stories" and SusanTheCat's "Thera'Py"
# improved with help of jw2pfd

init python:

    def reply(question = "Yes or no?",
        answers = "yes,no",
        invalid_character = None,
        invalid_answer = "(Invalid answer)",
        show_answers = True):

        thequestion = question
        found_it = ""
        ans = answers.replace(" ", "")
        ans = ans.split(",")
                       
        if show_answers:
            thequestion += " {size=-10}("
       
            for element in ans:
                thequestion += element + ', '
            thequestion = thequestion[:-2] + "){/size}"           
       
        while found_it == "":
           
            phrase = renpy.input(thequestion)
            phrase = phrase.lower()       

            for chara in ',.;:!?-+*()[]{}&%$':
                phrase = phrase.replace(chara, ' ')           
            phras = phrase.split()
       
            for element in ans:
                for theword in phras:
                    if found_it == '' and element == theword:
                        found_it = element
                       
            if found_it == "":
                renpy.say(invalid_character, invalid_answer)

        return found_it

    def reply2(question = "Yes or no?",
        answers = "yes,no",
        invalid_character = None,
        invalid_answer = "(Invalid answer)",
        show_answers = True):

        thequestion = question
        found_it = [ ]
        ans = answers.replace(" ", "")
        ans = ans.split(",")
                       
        if show_answers:
            thequestion += " {size=-10}("
       
            for element in ans:
                thequestion += element + ', '
            thequestion = thequestion[:-2] + "){/size}"           
       
        while found_it == [ ]:
           
            phrase = renpy.input(thequestion)
            phrase = phrase.lower()       

            for chara in ',.;:!?-+*()[]{}&%$':
                phrase = phrase.replace(chara, ' ')           
            phras = phrase.split()
       
            for element in ans:
                for theword in phras:
                    if element == theword and element not in found_it:
                        found_it.append(element)
                       
            if found_it == [  ]:
                renpy.say(invalid_character, invalid_answer)

        return found_it
The function takes five arguments. 'invalid_character' and 'invalid_answer' are used if the warning message is said by a character. In this example, we have Eileen (defined as the character 'e'), saying the warning message:

Code: Select all

$ r = reply("Where do you want to go?", "park, beach, home", e, "Can you repeat your answer, please?")
The code for 'reply.rpy' and an example of 'script.rpy' can be downloaded here. Put the two files in a newly created game:
reply.zip
reply.rpy, script.rpy. Edited code.
(2.6 KiB) Downloaded 275 times
Additionally, jw2pfd has made another code that does essentially the same thing, with some features added like synonyms recognition. You can found his code and explanation here: http://lemmasoft.renai.us/forums/viewto ... 45#p288203.

Every suggestion will be appreciated.
Last edited by xavimat on Thu Nov 14, 2013 11:52 am, edited 2 times in total.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#2 Post by TrickWithAKnife »

Do you use IRC? I'd been working on some ideas a few weeks ago (inspired by the same projects), and perhaps some of what I've done could be of use to you.

Some of the features I've got working include:
  • A thesaurus for understanding words with similar meanings.
    "I want to visit the seaside."
  • Being able to process the grammar a little more. For example, being able to recognise negative sentences.
    "I don't feel like going to the beach. Let's go somewhere else."
  • Assigning properties to objects.
    "I can't eat the beach, it's not food!"
What I have is pretty incomplete though, but it does work.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

User avatar
Jod
Regular
Posts: 51
Joined: Sat Nov 24, 2012 10:16 am
Projects: F.I.N.
Organization: JodCorp
Location: The Netherlands
Contact:

Re: Writing answers instead of choosing menu options

#3 Post by Jod »

Hey, this is pretty interesting! I´ve made something similar for my game myself, including:

-Timed input (x seconds to give input)
-Synonyms (punch equals jab, equals.... etc. etc. etc.)
-Story-specific things

My code is nowhere close to being easily exportable, I'm afraid. That was still on the to-do list :). If I have some free time I'm going to see how this runs and I'll let you know!

User avatar
xavimat
Eileen-Class Veteran
Posts: 1460
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Re: Writing answers instead of choosing menu options

#4 Post by xavimat »

Thanks TrickWithAKnife and Jod.

@TrickWithAKnife: I write in several languages, and I'm not sure if that grammar processing will be easy to "translate". Anyway, I'm interested in it. PM me, if you want. I'm not sure about IRC.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

animedaisuki
Regular
Posts: 129
Joined: Thu Jan 31, 2013 1:07 am
Completed: Zefii Beta 1.0
Projects: Zefii - A Transcendent Journey
Organization: Balibu Studios
Contact:

Re: Writing answers instead of choosing menu options

#5 Post by animedaisuki »

hi could you give an example of doing fuzzy matching (as opposed to exact matching) with this code? or is the function not included?

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#6 Post by TrickWithAKnife »

There are different methods for getting the "fuzziness".

Some possible ways could be:
1. Simplify vocabulary to their grammatical functions.
2. Use a thesaurus to change words to understood forms.
3. Completely ignore grammar, and hope you pick up enough keywords to get the general meaning.
4. Some bizarre combination of the above methods, or something else.

I think method 3 is generally the most common, but adding method 2 isn't so difficult, and greatly increases the chances of recognising words.

Method 1 is challenging, but would get the most accurate responses. I wouldn't recommend this method, especially with a messy language like English. And I'm saying this as an English teacher.

@xavimat: I'm not sure what to PM.
I generally avoid PMing people, because it kills the flow of conversation, and I'm unreliable at replying.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

animedaisuki
Regular
Posts: 129
Joined: Thu Jan 31, 2013 1:07 am
Completed: Zefii Beta 1.0
Projects: Zefii - A Transcendent Journey
Organization: Balibu Studios
Contact:

Re: Writing answers instead of choosing menu options

#7 Post by animedaisuki »

yeah, my plan was to do #3, since it's the simplest... but how do i do it with the code they have here? as u probably can see, i don't know how those codes work at all...

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#8 Post by TrickWithAKnife »

Sometimes you need to reverse-engineer sentences and their responses.
For example, think about what kind of sentences the user is likely to enter, and what kind of responses you want them to see. Figuring out the logic first is a lot better than trying to code it at the same time.
This kind of thing isn't the sort of thing people throw together in an afternoon, and being a proficient programmer isn't enough.

I hope Xavimat, Jod, anyone else who is working on something like this and I can put our heads together and combine our efforts.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

User avatar
xavimat
Eileen-Class Veteran
Posts: 1460
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Re: Writing answers instead of choosing menu options

#9 Post by xavimat »

@animedaisuki: The code I posted is really really simple. It's only a loop:
1. When the 'reply()' function is called, you must include the possible answers that will be recognized. These must be simple words (can't be expressions with spaces). You can include as many words as you want.
2. The function asks the user for an input, and the user writes something.
3. And finally, the function makes a loop: For any word in the 'possible answers list' searches if that word is found in the users' input. If it's found, then that will be the return of the reply() function. And all the other words will be ignored. If not, it tries with the next possible answer.
4. If none of the 'possible answers' is found, the reply() function starts again, asking for a new input.

There is, though, no grammar involved. It's a simple 'find the first word that match' function.

The story can continue with an if-elif-else statement (as shown in the OP). The reply() function will repeat itself forever while no correct word is found in the input (because of that, the possible answers should be given as a hint to the user).

@TrickWithAKnife: Can you show us (or PM me) the code that recognizes negative sentences? Thanks.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#10 Post by TrickWithAKnife »

I just have a list of negative words that can be run through a thesaurus. If they are found in the sentence, a variable named is_the_sentence_negative changes. Then this is referenced when generating responses. There's no reason why it can't check the position of the negative words in the sentence though, for more exact understanding.

I'll post part of the code when I get home, anyway. I have no problems sharing all my code, but as its all WiP, it's probably unreadable to other people.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#11 Post by TrickWithAKnife »

I took the liberty of messing a little with your code, to crowbar in checking for negative words. I haven't actually tested this new code (or your original), so if it doesn't work, it's because I'm lazy.

Also, it doesn't actually change the responses (although that is easy to do). It just changes the value of one variable.

Also, unless I'm mistaken, it looks like your function stops processing the user's input the moment it finds a keyword. That might be okay in some cases, but not if the coder wants to check for more than one particular word, or checking the sentence's meaning. For example "The beach is okay, but the park is best" would show up as "beach" being the desired destination. But again, perhaps I misread.

I'm also curious about whether your code changes
,.;:!?-+*()[]{}&%$
into spaces. If so, that could cause problems with apostrophes, so may be safer to just remove them entirely.

Code: Select all

# Reply
# by xavimat (cc-by, 2013)
# inspired by fiorica's "The Doll's Stories" and SusanTheCat's "Thera'Py"

init python:
    
    def reply(question = "Yes or no?", 
        answers = ["yes", "no"], 
        invalid_character = None, 
        invalid_answer = "(Invalid answer)", 
        show_answers = True):

        ## Change this to whatever the thesaurus is called ##
        definitions = english_thesaurus ##
        was_the_sentence_positive_or_negative = "+" ##

        
        thequestion = question        
        if show_answers:
            thequestion += " {size=-10}("
            for element in answers:
                thequestion += element + ', '
            thequestion = thequestion[:-2] + "){/size}"            
        phrase = renpy.input(thequestion)
        phrase = phrase.lower()        

        for chara in ',.;:!?-+*()[]{}&%$':
            phrase = phrase.replace(chara, ' ')            
        pre_phras = phrase.split() ##
        ## This next line checks the thesaurus for matching words, and changes them. ##
        phras = [ definitions[word] if word in definitions else word for word in pre_phras] ##
        found_it = ''
        for element in answers:
            for theword in phras:

                ## Just to make a note if there is a negative word in the sentence. Do with that whatever you like. ##
                if element == "NEGATIVE": ##
                    was_the_sentence_positive_or_negative = "-" ##

                if found_it == '' and element == theword:
                    found_it = element   
   

              
        while found_it == '':
            renpy.say(invalid_character, invalid_answer)
            found_it = reply(question, answers, invalid_character, invalid_answer, show_answers)            
            
        return found_it
Also, this bad boy is an example of a very short thesaurus:

Code: Select all

   
    english_thesaurus = {
        "isnt" : "NEGATIVE", 
        "not" : "NEGATIVE", 
        "dont" : "NEGATIVE", 
        "cant" : "NEGATIVE", 
        "wont" : "NEGATIVE", 
        "shouldnt" : "NEGATIVE", 
        "mustnt" : "NEGATIVE", 
        "wouldnt" : "NEGATIVE", 
        "couldnt" : "NEGATIVE", 
        "didnt" : "NEGATIVE", 
        "no" : "NEGATIVE", 
        "arent" : "NEGATIVE", 
        "wasnt" : "NEGATIVE", 
        "banned" : "NEGATIVE", 
        "prohibited" : "NEGATIVE", 
        "disallowed" : "NEGATIVE"}
Hope you don't mind me posting this here (can move it if you prefer).
Last edited by TrickWithAKnife on Tue May 07, 2013 3:26 pm, edited 1 time in total.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

User avatar
xavimat
Eileen-Class Veteran
Posts: 1460
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Re: Writing answers instead of choosing menu options

#12 Post by xavimat »

Thanks for the suggestions, TrickWithAKnife.
TrickWithAKnife wrote:Also, unless I'm mistaken, it looks like your function stops processing the user's input the moment it finds a keyword. That might be okay in some cases, but not if the coder wants to check for more than one particular word, or checking the sentence's meaning. For example "The beach is okay, but the park is best" would show up as "beach" being the desired destination. But again, perhaps I misread.
You are right. The function only checks for the first word that match, and then returns it. It wouldn't be difficult to check for more than one word and then complain about "ambiguity" and ask the user for a new answer. (For example, in a game with the user talking to a dump computer.)
TrickWithAKnife wrote:I'm also curious about whether your code changes
,.;:!?-+*()[]{}&%$
into spaces. If so, that could cause problems with apostrophes, so may be safer to just remove them entirely.
I didn't include the quotes in this line (single neither double) to avoid problems with apostrophe. I've made the test and it works with answers with apostrophes ("don't", etc.)
TrickWithAKnife wrote:Hope you don't mind me posting this here (can move it if you prefer).
It's OK. I'm learning a lot.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#13 Post by TrickWithAKnife »

I noticed in your example, you check for certain words, and have pre-defined responses each time.

I wonder if it would be useful to include some set responses in addition. For example, if someone uses an offensive word, the response could be something about not using offensive language, or if the user's input starts with a question word and contains a question mark, then say something like "Hey, I'm asking the questions here."

I should be careful. I have loads of ideas, but each one makes things more complicated.
Also different methods are better for different situations. I don't think there is a best way for all situations.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

User avatar
xavimat
Eileen-Class Veteran
Posts: 1460
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Re: Writing answers instead of choosing menu options

#14 Post by xavimat »

My first idea was inspired by fiorica's "The Doll's Stories" where the user can write (as 'speaking' to the dolls characters), but that doesn't change the path (it doesn't work as a menu). I'm not sure if the responses that the user writes have an actual influence in the game (do they raise stats or something?). Anyway, I enjoyed a lot the possibilities of that as a game.

That was the initial purpose of this function, a simulation game were the user "simulates" saying something instead of "clicking" a box with a word written in it, as in the usual menus.

Of course, that can be extended with many possibilities (thesaurus, negation recognition, grammar processing, offensive language detection...), so, they are welcome. :)
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

TrickWithAKnife
Eileen-Class Veteran
Posts: 1261
Joined: Fri Mar 16, 2012 11:38 am
Projects: Rika
Organization: Solo (for now)
IRC Nick: Trick
Location: Tokyo, Japan
Contact:

Re: Writing answers instead of choosing menu options

#15 Post by TrickWithAKnife »

I talked with Fiorica quite a bit about Dolls' text system while I was messing around with my own, and I think we seemed quite keen on a more flexible system too.

I actually have 2 or 3 different methods that I was working with, but each has disadvantages.
"We must teach them through the tools with which they are comfortable."
The #renpy IRC channel is a great place to chat with other devs. Due to the nature of IRC and timezone differences, people probably won't reply right away.

If you'd like to view or use any code from my VN PM me. All code is freely available without restriction, but also without warranty or (much) support.

Post Reply

Who is online

Users browsing this forum: No registered users