Ren'Py (Hopefully) simple Ren'py question regarding Python

seamanq

Well-Known Member
Game Developer
Aug 28, 2018
1,888
2,858
I grabbed some code from the Ren'py documentation to allow my player to enter their name and then use it as a variable in the game.

This is the code, in script lines 13-22:

Code:
define playername = Character("[playername]", color="#c8c8ff")

python:
    playername = renpy.input("What is your name?")
    playername = playername.strip()

    if not playername:
         playername = "Bob"

playername "My name is [playername]!"


# The game starts here.
label start:

playername "Phew!"
When I try to run the game, I get a runtime error of maximum recursion depth exceeded in __instancecheck__ on line 28, which is the first place I try to call that defined variable:

Code:
playername "Phew!"
Do I need to terminate the Python code somehow, or is there something else wrong here? I am absolutely a NooB in both Ren'py and Python, so I appreciate any help that can be rendered here.
 

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,480
6,973
I think your problem is that you've called the Character "playername", but then you're using a variable named "playername" as the name you want it to call. So the Character object calls itself, which calls itself, which calls itself.

Change the name of the character to something else:
Code:
    define player = Character("[playername]", color="#c8c8ff") 

    $ playername = renpy.input("What is your name?")
    $ playername = playername.strip()

    if not playername:
        $ playername = "Bob"

    player "My name is [playername]!"

    player "Phew!"
 
  • Like
Reactions: anne O'nymous

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,480
6,973
By the way, when you post code, it's important that the indenting gets preserved, because that's critical to Ren'py.

Insert it as code, not as text.


1545165638718.png
 

seamanq

Well-Known Member
Game Developer
Aug 28, 2018
1,888
2,858
Ok. I revised it as suggested. Here is how the code looks now.

Code:
define pn = Character("[playername]")

python:
    playername = renpy.input("What is your name?")
    playername = playername.strip()

    if not playername:
         playername = "Bob"

pn "My name is [playername]!"


# The game starts here.
label start:

pn "Phew!"
Now it is telling me for line 27 (the last line in the code above) that there is a KeyError: u'playername'. I tried moving the define pn line under the Python code, thinking that maybe because the pn variable wasn't set by input that it was throwing out the error, but that didn't change anything. And the game is not asking for the input "What is your name?"

Thanks.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,569
2,196
Quick view...

But I think you'll also run into trouble with most of your game code being before the "label start:"
If you move the "label start:" before the "python:" statement... and see if things behave better.

"start" is where things will pick up when you start the game from the main menu.

If I'm understanding what RenPy is trying to do with your existing code...
You've defined a static non-saved variable called "pn". It's value is dynamically set using another variable "playername".
The code from "python:" to "#the game starts here." is valid, but never executed.
When the game starts, it tries to do the "pn 'Phew!'"...
... realizes that "pn" is linked to "playername"
... tries to lookup the variable "playername" which doesn't exist (because it was never executed)
... and crashes.

Edit:

Do I need to terminate the Python code somehow, or is there something else wrong here? I am absolutely a NooB in both Ren'py and Python, so I appreciate any help that can be rendered here.
No.
RenPy is all about indentation.
The "python:" block of code is terminated when the lines below it are no longer indented more than the code block itself.

Something else to know, if you're new to RenPy...
$ {code}
-and-
python:
___ {code}

...are pretty much the same thing. "$" tends to be used if there is a single line of python code (or at least, very few) and "python:" blocks tend to be longer.

So your snippet of code could also be...
Python:
define pn = Character("[playername]", color="#c8c8ff")

# The game starts here.
label start:

    $ playername = renpy.input("What is your name?")
    $ playername = playername.strip()

    if not playername:
        $ playername = "Bob"

    pn "My name is [playername]!"
    pn "Phew!"
I tend to indent code below labels, but is entirely personal preference. If the same code were in column 1, it would work the same.
It's just I find it easier to navigate code, when I can quickly spot the label statements in the midst of all the other code.
 
  • Like
Reactions: anne O'nymous

seamanq

Well-Known Member
Game Developer
Aug 28, 2018
1,888
2,858
Thanks for catching that. I am brand new with Ren'py so I don't know the "rules" yet, but that is a helpful one to know. This will help me to work through my game (so far) and find any other bugs that may be lurking, but I think it will be pretty clean because I haven't done too many crazy things for a first time out.
 

seamanq

Well-Known Member
Game Developer
Aug 28, 2018
1,888
2,858
Quick view...

But I think you'll also run into trouble with most of your game code being before the "label start:"
If you move the "label start:" before the "python:" statement... and see if things behave better.

"start" is where things will pick up when you start the game from the main menu.

If I'm understanding what RenPy is trying to do with your existing code...
You've defined a static non-saved variable called "pn". It's value is dynamically set using another variable "playername".
The code from "python:" to "#the game starts here." is valid, but never executed.
When the game starts, it tries to do the "pn 'Phew!'"...
... realizes that "pn" is linked to "playername"
... tries to lookup the variable "playername" which doesn't exist (because it was never executed)
... and crashes.

Edit:


No.
RenPy is all about indentation.
The "python:" block of code is terminated when the lines below it are no longer indented more than the code block itself.

Something else to know, if you're new to RenPy...
$ {code}
-and-
python:
___ {code}

...are pretty much the same thing. "$" tends to be used if there is a single line of python code (or at least, very few) and "python:" blocks tend to be longer.

So your snippet of code could also be...
Python:
define pn = Character("[playername]", color="#c8c8ff")

# The game starts here.
label start:

    $ playername = renpy.input("What is your name?")
    $ playername = playername.strip()

    if not playername:
        $ playername = "Bob"

    pn "My name is [playername]!"
    pn "Phew!"
I tend to indent code below labels, but is entirely personal preference. If the same code were in column 1, it would work the same.
It's just I find it easier to navigate code, when I can quickly spot the label statements in the midst of all the other code.
These are good tips. I am actually trying to write the code while I write the actual script, so that when I am done, it's just a matter of pouring the script into Ren'py. For my first effort, I am going to do very limited menus and options, just to keep it simple. But next month will be a different story. I actually have over 10,000 words written so I am well along my way, but I needed to test them in Ren'py to make sure I didn't have any major errors. I'm doing that one scene at a time.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,294
15,156
These are good tips.
Here's another one : Don't care about the content/story before you effectively understood how to do the main mechanism of the game with Ren'py.

It's normal to struggle at first when you have no knowledge about codding, which seem to be your case view your question in another thread. But you'll struggle more and more as you'll advance in your project.
If you need to have in mind both the story writing and the code writing, you'll fail at both. So, first think about what you'll need as code, and learn how to do it. And I don't mean efficiently doing it, but at least doing it in a way that works.
By example, in your other thread, you struggle because you mixed :
Code:
   $ var = "true"
and
Code:
if var = true:
In fact, even if none is the way to use Boolean with Python/Ren'py, both are still something that can works, if you don't mix them :
Code:
  $ var = "true"
  [...]
  $ var = "false"
  [...]
  if var = "true":
or
Code:
define true = 1
define false = 0
[...]
label blabla:
  $ var = true
  [...]
  $ var = false
  [...]
  if var = true:
Then only, when you finally know how to write the code you'll need, you can think about the story and implement it.
 

seamanq

Well-Known Member
Game Developer
Aug 28, 2018
1,888
2,858
Thank you for your clear explanation of mixing types. This is very useful information.
 

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,480
6,973
I tend to indent code below labels, but is entirely personal preference. If the same code were in column 1, it would work the same.
It's just I find it easier to navigate code, when I can quickly spot the label statements in the midst of all the other code.
it actually goes a bit beyond that. The fact that the code would work in column one is a happy accident of Ren'py. Ren'py is based on Python, and if you're following strict Python conventions (which is always a good thing), any time there is a line that ends in a colon, you're introducing a new block, and the block needs to be indented more than the line with the colon.

Many other Ren'py constructs will NOT work correctly if you don't indent right after a colon. Labels just happen to be an exception - apparently PyTom loosens the rules for them somewhat, possibly for "backwards compatibility" or "make it easier for sloppy coders." (No insult to you intended.) Virtually anywhere else, if you have a colon and don't have something indented after it, you'll get an error. (There is a "pass" statement that exists specifically to handle the case where a block is required but needs to do nothing.)

As a side note, if you look at the code for the Tutorial or The Question, you'll see that code after a label is indented. Since this is code written by PyTom to show off Ren'py, you can probably assume that this is what he considers "correct", even if other indentation practices might work.

Some people will argue that "anything that works is obviously 'correct'", but indentation bites people new to Ren'py in the butt all the time. You will have far fewer problems with Ren'py in the long run if you're careful to follow the Python conventions everywhere, even in cases where you don't strictly have to.

That's just my $0.02. Others may disagree, and that's OK.
 
  • Like
Reactions: anne O'nymous

seamanq

Well-Known Member
Game Developer
Aug 28, 2018
1,888
2,858
Some people will argue that "anything that works is obviously 'correct'", but indentation bites people new to Ren'py in the butt all the time. You will have far fewer problems with Ren'py in the long run if you're careful to follow the Python conventions everywhere, even in cases where you don't strictly have to.
I appreciate the highly detailed response along with the reasoning included. I come from the world of typesetting and after that HTML, both of which were highly contextual and if mistakes were made, they could come back to bite one in the butt, so I get where you are coming from. I think it is better to be overly precise than underly, especially when the language can come back to bite you. Thank you for the insightful and helpful comments.
 
  • Like
Reactions: Rich

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,294
15,156
Labels just happen to be an exception - apparently PyTom loosens the rules for them somewhat, possibly for "backwards compatibility" or "make it easier for sloppy coders."
From what I remember of it, it's more the happy accident you mentioned above.
Look at how Ren'py will just continue with the following label if you don't ended the current one with a "jump", "call" or "return". Label are more to see like entry points in the AST, than like effective blocks. So, when you forgot to indent the content of the label block, what Ren'py see is more on the side of an empty label and some code that are weirdly on init level but will be played only after the game start.
This said, I agree with you for the reason why PyTom let it continue to works like this when he discovered it.
 
  • Like
Reactions: Rich