Ren'Py How to refer to a string as if it was a variable? [RESOLVED]

obsessionau

Member
Game Developer
Sep 27, 2018
270
376
Hi all,

I have a player clicking on a number of images.
Depending on the image clicked it will modify a variable.
At the moment I am using a if statement to process this:

Code:
if dungeon[cardClicked][2] == 0:
            if dungeon[cardClicked][0][:3] == "m01":
                $ m01score += 1
            if dungeon[cardClicked][0][:3] == "m02":
                $ m02score += 1
            if dungeon[cardClicked][0][:3] == "m03":
                $ m03score += 1
            if dungeon[cardClicked][0][:3] == "m04":
                $ m04score += 1
However I want to change this so that I can drastically reduce the amount of code and if statements by concatenating 'score' onto the end of the value and modify that variable:

While the below statement won't work (I am not using buttons), this is similar to what I am after...

Code:
if dungeon[cardClicked][2] == 0:
        SetVariable(dungeon[cardClicked][0][:3]+"score", +1)
It is probably painfully simple, I just can't find any examples of it anywhere.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Code:
if dungeon[cardClicked][2] == 0:
        SetVariable(dungeon[cardClicked][0][:3]+"score", +1)
It is probably painfully simple, I just can't find any examples of it anywhere.
What are you searching to do exactly ? Because is a screen action, therefore it have no effective meaning outside of the action property of a screen statement.
It can still be used outside of it :
Code:
if dungeon[cardClicked][2] == 0:
        SetVariable(dungeon[cardClicked][0][:3]+"score", 1)()
but it make really few sense to use such syntax.

What you are looking for is the Python function:
Code:
if dungeon[cardClicked][2] == 0:
        $ setattr( dungeon[cardClicked][0][:3]+"score", 1 )
 
  • Like
Reactions: obsessionau

obsessionau

Member
Game Developer
Sep 27, 2018
270
376
$ setattr( dungeon[cardClicked][0][:3]+"score", 1 )

setattr requires the variable to be an attribute of an object.

I thought putting them in classes might work...

Code:
    class m01:
        def __init__(self, service, love, score):
            self.service = service
            self.love = love
            self.cost = cost

    class m02:
and then...

Code:
         $ setattr( dungeon[cardClicked][0][:3], "love" , playerLove)

but it is saying unicode object has no attribute love.
 
Last edited:

obsessionau

Member
Game Developer
Sep 27, 2018
270
376
Code:
SetVariable(dungeon[cardClicked][0][:3]+"score", 1)()
Does appear to work however it makes the value 1 and not increments by 1

I can't use
Code:
SetVariable("x",  x + 1)()
as I don't know x.

I have a feeling it should all go into a dictionary?

It appears there is multiple ways to go about what I am doing, and I am not doing it correctly in any of these ways hahaha
 
Last edited:

obsessionau

Member
Game Developer
Sep 27, 2018
270
376
Ok so the method I went with (ie. the first one I got to work) was...

create a dictionary of the variables...
Code:
    maidVar = {}
    maidVar["m01service"] = 0
    maidVar["m01love"] = 0
    maidVar["m01type"] = 0
    maidVar["m02service"] = 0
    maidVar["m02love"] = 0
    maidVar["m02type"] = 0
    maidVar["m03service"] = 0
    maidVar["m03love"] = 0
    maidVar["m03type"] = 0
    maidVar["m04service"] = 0
    maidVar["m04love"] = 0
    maidVar["m04type"] = 0
and then edit the dictionary as I can pass strings as variable names easily.

Code:
    $ maidVar[dungeon[cardClicked][0][:3]+"service"] = maidVar[dungeon[cardClicked][0][:3]+"service"] + 1
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Alright... I had a hard day yesterday, it was past midnight when I answered, and I'm sick as hell :( Not a great combination, sorry. I stupidly mimicked what you wrote with SetVariable, which was a double error.


$ setattr( dungeon[cardClicked][0][:3]+"score", 1 )

setattr requires the variable to be an attribute of an object.
The link to the setattr documentation, and Ren'py documentation should have gave you the answer for this one.

Like all variables are stored by Ren'py in an object named , you already have the missing object and just need to correct the syntax according to the setattr documentation : setattr( store, dungeon[cardClicked][0][:3]+"score", VALUE_TO_ASSIGN )


Code:
SetVariable(dungeon[cardClicked][0][:3]+"score", 1)()
Does appear to work however it makes the value 1 and not increments by 1
Here again, the answer where on the link I provided yesterday, SetVariable "causes the variable with name to be set to value".
And the documentation for setattr tell you how to correct this : "This is the counterpart of " ; the name of the counterpart being explicit enough to understand what it do.

Therefore, the correct syntax is setattr( store, dungeon[cardClicked][0][:3]+"score", getattr( store, dungeon[cardClicked][0][:3]+"score" ) + 1 )


On a side note, a search for "setattr" on the forum give you more than 40 answers, among them few in a thread named "Dynamically determining variables" (a title explicit enough to know that the answer can be there). Between this thread and the other talking about this function, you could have been able to find what you needed to correct my messed initial answer.


Code:
    class m01:
        def __init__(self, service, love, score):
            self.service = service
            self.love = love
            self.cost = cost

    class m02:
and then...

Code:
         $ setattr( dungeon[cardClicked][0][:3], "love" , playerLove)
but it is saying unicode object has no attribute love.
Many problems here :

Firstly, it's absolutely not how you use objects. You are creating named "m01", "m02", when you should have created a master class, then objects named "m01", "m02" depending of this said "master class".

Secondly, setattr need to be given an object, and you provide it a class.

Thirdly, there's still the store problem ; more on this subject can be found here.
 

obsessionau

Member
Game Developer
Sep 27, 2018
270
376
Thank you for taking the time to explain it!

I often see people saying "read the documentation it explains it all". But unfortunately the documentation is more obvious for some than others. Especially when the documentation is not written for use with Renpy and even if it is Renpy documentation I can't remember what I read a month ago or the nuances of how it relates to what I am reading now!

That isn't to say that I didn't look at the documentation, because I did. Just didn't realise Renpy had it's variables in an object store.
I think I had tried "None" and a few other things.

I can't remember why I tried to use classes as objects. Hmmm.

All my searches have been for "using strings as variables" and although some of my searches did bring up "dynamically creating variables" I was honestly thinking it was going to be a simple encapsulation thing. ie Put a special character in front of it and Renpy will reference the string as a variable type thing.

Thank you again! :)
 
Last edited:

Echox2

Newbie
Oct 6, 2017
59
113
Zombie-ing this post. I also was looking for how to set a variable by referring to a string just now. Figured it out thanks to this three-year-old post.

I found the hardest thing about programming is learning how to ask the right questions. I spent much too long searching "call a variable with a variable", "variables inside strings", "assign variable based on information taken from string" etc. Until finally I found the problem I was looking for.

Thank you for solving this problem in a way an idiot like me can understand.