Renpy Replay error with character names

TheTypist

Active Member
Donor
Game Developer
Sep 7, 2017
694
4,185
Trying to take advantage of renpy's replay mode and I've gotten many errors, corrected few, and am down to what I believe may be the last one needing a fix.
Here is the traceback

Code:
[code]
I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 1642, in script
    "But what Claire was unaware of was the fact that just a moment ago, someone had entered the shower room."
KeyError: u'cname'

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 1642, in script
    "But what Claire was unaware of was the fact that just a moment ago, someone had entered the shower room."
  File "renpy/ast.py", line 715, in execute
    renpy.exports.say(who, what, *args, **kwargs)
  File "renpy/exports.py", line 1384, in say
    who(what, *args, **kwargs)
  File "renpy/character.py", line 1164, in __call__
    what = what_pattern.replace("[what]", sub(what, translate=True))
  File "renpy/character.py", line 1153, in sub
    return renpy.substitutions.substitute(s, scope=scope, force=force, translate=translate)[0]
  File "renpy/substitutions.py", line 270, in substitute
    s = formatter.vformat(s, (), kwargs)
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 563, in vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 596, in _vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 613, in format_field
  File "renpy/character.py", line 1049, in __format__
    return format(str(self), spec)
  File "renpy/character.py", line 1032, in __unicode__
    return renpy.substitutions.substitute(who)[0]
  File "renpy/substitutions.py", line 270, in substitute
    s = formatter.vformat(s, (), kwargs)
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 563, in vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 585, in _vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 646, in get_field
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 605, in get_value
KeyError: u'cname'

Windows-10-10.0.19041
Ren'Py 7.4.2.1292
Because I Love Her Version_1.0
Mon Sep 27 18:34:58 2021


At first, I was getting a Maximum Recursion Depth error, then I saw a post by anne O'nymous in regards to player name setup using text substitution and fixed that error.
However, now I am getting the one above.
Here is the code used for my character setup now.
Code:
init python:
    import re
    def word_replace(text):
        """
        take a text and replace words that match the key in a dictionary
        with the associated value, return the changed text
        """

        def translate(match):
            word = match.group(0)
            return replace_dict.get(word, word)

        return re.sub(r"\b[A-Za-z_]\w*\b", translate, text)
init python:
# create a dictionary of key_word:replace_with pairs
    replace_dict = {
        "John" : "[n]",
        "JOHN" : "[n]",
        "john" : "[n]",
        "Claire" : "[c]",
        "CLAIRE" : "[c]",
        "claire" : "[c]",

    }

define config.say_menu_text_filter =  word_replace

# Declare characters used by this game. The color argument colorizes the
# name of the character.
define n = Character("[nname]", color="#CCFFFF")
define c = Character("[cname]", color="#FF00CC")
define o = Character("Olivia", color="#FF0033")
define j = Character("Jenni", color="#6600FF")
define nar = Character("Narrator", color="#00FFCC")
define t = Character("Thinking")
define man1 = Character("Man")
define man2 = Character("Man2")
define man3 = Character("Man3")
define v = Character("Voice", color="#CC0033")
define s = Character("Server", color="#FFCCFF")
define a = Character("Abigail", color="#FF9933")
define d = Character("Damon", color="#CCCCCC")
define b = Character("Darryl")
define ct = Character("Claire's Thoughts", color="#FF00CC")
define k = Character("Krystal", color="#FF9933")
define r = Character("Rose", color="#CCCCCC")
define jas = Character("Jason",color="#CCCCCC")
define girl = Character("Woman",color="#FF0033")
define bt = Character("Bartender",color="#FF9933")
define g = Character("Autumn", color="#FF9933")
define anna = Character("Anna", color="#FF0033")
define king = Character("King", color="FFC48E")
define dust = Character("Dustin", color="#F4D2F4")
define h = Character("H", color="#F4D2F4")

label start:
    $ jennilust = 0
    $ jennilove = 0
    $ clairelove = 0
    $ clairelust = 0
    $ goodbf = 0
    $ badbf = 0








    scene downtown
    $ nname = renpy.input("What is your name?")
    $ nnname = nname.strip()
    if nname == "":
        $ nname="John"
    $ cname = renpy.input("What is your fiances name?")
    $ cname = cname.strip()
    if cname == "":
        $ cname="Claire"
Thank you all in advanced.
 

LightmanP

Well-Known Member
Modder
Game Developer
Oct 5, 2020
1,750
16,558
Trying to take advantage of renpy's replay mode and I've gotten many errors, corrected few, and am down to what I believe may be the last one needing a fix.
Here is the traceback

Code:
[code]
I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 1642, in script
    "But what Claire was unaware of was the fact that just a moment ago, someone had entered the shower room."
KeyError: u'cname'

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 1642, in script
    "But what Claire was unaware of was the fact that just a moment ago, someone had entered the shower room."
  File "renpy/ast.py", line 715, in execute
    renpy.exports.say(who, what, *args, **kwargs)
  File "renpy/exports.py", line 1384, in say
    who(what, *args, **kwargs)
  File "renpy/character.py", line 1164, in __call__
    what = what_pattern.replace("[what]", sub(what, translate=True))
  File "renpy/character.py", line 1153, in sub
    return renpy.substitutions.substitute(s, scope=scope, force=force, translate=translate)[0]
  File "renpy/substitutions.py", line 270, in substitute
    s = formatter.vformat(s, (), kwargs)
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 563, in vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 596, in _vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 613, in format_field
  File "renpy/character.py", line 1049, in __format__
    return format(str(self), spec)
  File "renpy/character.py", line 1032, in __unicode__
    return renpy.substitutions.substitute(who)[0]
  File "renpy/substitutions.py", line 270, in substitute
    s = formatter.vformat(s, (), kwargs)
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 563, in vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 585, in _vformat
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 646, in get_field
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python2.7/string.py", line 605, in get_value
KeyError: u'cname'

Windows-10-10.0.19041
Ren'Py 7.4.2.1292
Because I Love Her Version_1.0
Mon Sep 27 18:34:58 2021


At first, I was getting a Maximum Recursion Depth error, then I saw a post by anne O'nymous in regards to player name setup using text substitution and fixed that error.
However, now I am getting the one above.
Here is the code used for my character setup now.
Code:
init python:
    import re
    def word_replace(text):
        """
        take a text and replace words that match the key in a dictionary
        with the associated value, return the changed text
        """

        def translate(match):
            word = match.group(0)
            return replace_dict.get(word, word)

        return re.sub(r"\b[A-Za-z_]\w*\b", translate, text)
init python:
# create a dictionary of key_word:replace_with pairs
    replace_dict = {
        "John" : "[n]",
        "JOHN" : "[n]",
        "john" : "[n]",
        "Claire" : "[c]",
        "CLAIRE" : "[c]",
        "claire" : "[c]",

    }

define config.say_menu_text_filter =  word_replace

# Declare characters used by this game. The color argument colorizes the
# name of the character.
define n = Character("[nname]", color="#CCFFFF")
define c = Character("[cname]", color="#FF00CC")
define o = Character("Olivia", color="#FF0033")
define j = Character("Jenni", color="#6600FF")
define nar = Character("Narrator", color="#00FFCC")
define t = Character("Thinking")
define man1 = Character("Man")
define man2 = Character("Man2")
define man3 = Character("Man3")
define v = Character("Voice", color="#CC0033")
define s = Character("Server", color="#FFCCFF")
define a = Character("Abigail", color="#FF9933")
define d = Character("Damon", color="#CCCCCC")
define b = Character("Darryl")
define ct = Character("Claire's Thoughts", color="#FF00CC")
define k = Character("Krystal", color="#FF9933")
define r = Character("Rose", color="#CCCCCC")
define jas = Character("Jason",color="#CCCCCC")
define girl = Character("Woman",color="#FF0033")
define bt = Character("Bartender",color="#FF9933")
define g = Character("Autumn", color="#FF9933")
define anna = Character("Anna", color="#FF0033")
define king = Character("King", color="FFC48E")
define dust = Character("Dustin", color="#F4D2F4")
define h = Character("H", color="#F4D2F4")

label start:
    $ jennilust = 0
    $ jennilove = 0
    $ clairelove = 0
    $ clairelust = 0
    $ goodbf = 0
    $ badbf = 0








    scene downtown
    $ nname = renpy.input("What is your name?")
    $ nnname = nname.strip()
    if nname == "":
        $ nname="John"
    $ cname = renpy.input("What is your fiances name?")
    $ cname = cname.strip()
    if cname == "":
        $ cname="Claire"
Thank you all in advanced.
Replay can't read variables that were set outside of defines and defaults. Basically, it's like starting the game in the place your replay starts. Since it seems like you're hardcoding "Claire" in the dialogue, I think the easiest solution would be to have a default for cname, e.g. default cname = "Claire".

The other way you can pass variable values to replays is by using the scope in the Replay statement.
Python:
action Replay("day13tammylewdscene", scope={"day13praisedtammy" : persistent.tammyep13})
For this to work, you also need to actually give "persistent.tammyep13" a value at some point.

If you want nname and cname to actually have custom values a player inputs, you can set up those names when a gallery is first opened with something like this:
Python:
label gallery_name_set:
    default persistent.nname = ""
    default persistent.cname = ""

    if persistent.nname == "":
        $ persistent.nname = renpy.input("What is your name?", default="DEFAULT NAME").strip() or "DEFAULT NAME"
    if persistent.cname == "":
        $ persistent.cname = renpy.input("What is your wife's name?", default="DEFAULT NAME").strip() or "DEFAULT NAME"

    return
And then open your gallery like this and have the following in your replay statements:
Python:
action (ui.callsinnewcontext("gallery_name_set"), Show("scene_gallery"))

Replay("replay_scene", scope={"nname" : persistent.nname, "cname" : persistent.cname})
This could be simplified by using a dictionary in the scope or something like that.

Hope that helps :)
 
Last edited:
  • Like
Reactions: TheTypist

TheTypist

Active Member
Donor
Game Developer
Sep 7, 2017
694
4,185
I went with changing the nname and cname to their default values just to finally get a working gallery, I appreciate you :)
 
  • Like
Reactions: LightmanP

Llamamann

Engaged Member
Game Developer
Feb 26, 2018
2,553
10,748
Replay can't read variables that were set outside of defines and defaults. Basically, it's like starting the game in the place your replay starts. Since it seems like you're hardcoding "Claire" in the dialogue, I think the easiest solution would be to have a default for cname, e.g. default cname = "Claire".

The other way you can pass variable values to replays is by using the scope in the Replay statement.
Python:
action Replay("day13tammylewdscene", scope={"day13praisedtammy" : persistent.tammyep13})
For this to work, you also need to actually give "persistent.tammyep13" a value at some point.

If you want nname and cname to actually have custom values a player inputs, you can set up those names when a gallery is first opened with something like this:
Python:
label gallery_name_set:
    default persistent.nname = ""
    default persistent.cname = ""

    if persistent.nname == "":
        $ persistent.nname = renpy.input("What is your name?", default="DEFAULT NAME").strip() or "DEFAULT NAME"
    if persistent.cname == "":
        $ persistent.cname = renpy.input("What is your wife's name?", default="DEFAULT NAME").strip() or "DEFAULT NAME"

    return
And then open your gallery like this and have the following in your replay statements:
Python:
action (ui.callsinnewcontext("gallery_name_set"), Show("scene_gallery"))

Replay("replay_scene", scope={"nname" : persistent.nname, "cname" : persistent.cname})
This could be simplified by using a dictionary in the scope or something like that.

Hope that helps :)
Hey, would you mind expanding on how to use a dictionary in the scope? I have more variables than the scope will allow on a replay button. So id love to have a nice list for it to reference for names and relationships.

Thanks!
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
Your other potential solution would be to use if _in_replay:.

Something like:

Python:
    if _in_replay:
        $ cname = "Claire"
        # other variables that might not be available within the replay.

# -or-

    # if you've saved a copy of the latest values in the persistent store...
    if _in_replay:
        $ cname = persistent.cname

You'd normally use _in_replay: for anything that relies on variables. Not just character names, but also places where you might check a value (I'm thinking something like if c_affection >= 15:)...


The scope thing is documented .

In effect, you create your own dictionary (using define) and pass that dictionary to the replay to use instead of the normal store storage area.

Something like (and I haven't testing this):

Python:
define replay_vars = {
    "cname": "Claire",
    "clove": 100,
    "chate": 0
    }

#somewhere else...

    action Replay("some-label-somewhere, scope=replay_vars)

You can do it with without pre-defining things by specifying the dictionary values at the scope= level, something like:

Python:
    action Replay("some-label-somewhere, scope={"cname": "Claire", "clove": 100, "chate": 0})

It might not be that exact code, but it'll be close enough to work it out.
 

Llamamann

Engaged Member
Game Developer
Feb 26, 2018
2,553
10,748
Your other potential solution would be to use if _in_replay:.

Something like:

Python:
    if _in_replay:
        $ cname = "Claire"
        # other variables that might not be available within the replay.

# -or-

    # if you've saved a copy of the latest values in the persistent store...
    if _in_replay:
        $ cname = persistent.cname

You'd normally use _in_replay: for anything that relies on variables. Not just character names, but also places where you might check a value (I'm thinking something like if c_affection >= 15:)...


The scope thing is documented .

In effect, you create your own dictionary (using define) and pass that dictionary to the replay to use instead of the normal store storage area.

Something like (and I haven't testing this):

Python:
define replay_vars = {
    "cname": "Claire",
    "clove": 100,
    "chate": 0
    }

#somewhere else...

    action Replay("some-label-somewhere, scope=replay_vars)

You can do it with without pre-defining things by specifying the dictionary values at the scope= level, something like:

Python:
    action Replay("some-label-somewhere, scope={"cname": "Claire", "clove": 100, "chate": 0})

It might not be that exact code, but it'll be close enough to work it out.
Thats great, thank you very much. I will test it out
 

peterppp

Active Member
Mar 5, 2020
763
1,349
After 10, it didnt highlight the text the same way, so it seems like thats all i could put in a single Action on an image button
i doubt your editor/extension (whatever you use) is advanced enough to know possible renpy code limitations like that. more likely, something went wrong with the parsing of the text, but then it's just a visual thing in the editor
 
  • Like
Reactions: gojira667

Llamamann

Engaged Member
Game Developer
Feb 26, 2018
2,553
10,748
i doubt your editor/extension (whatever you use) is advanced enough to know possible renpy code limitations like that. more likely, something went wrong with the parsing of the text, but then it's just a visual thing in the editor
Maybe so. I’m certainly no expert. But, putting 20+ scope items for each replay would still be tedious.

I settled on making the names and relationships persistent, and calling a list of them when replaying. Seems to be good so far, and should be good going forward
 

gojira667

Member
Sep 9, 2019
325
320
Maybe so. I’m certainly no expert. But, putting 20+ scope items for each replay would still be tedious.
Besides defining the dict as above, if they are all the same there's . I want to say that the Replay() scope dict is merged with the config.replay_scope one.
 
  • Like
Reactions: Llamamann