Picking Maximum Variable Value From a Large List

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
AnnieDB
Regular
Posts: 40
Joined: Tue Dec 01, 2015 3:24 pm
Location: Seattle
Contact:

Picking Maximum Variable Value From a Large List

#1 Post by AnnieDB » Thu Mar 17, 2016 9:27 pm

Hey guys - I've been chewing this over in Python, and trying to figure out how to run this check without it being a snarl so insane that an Elder God would look at it and go "MAN that is a kludge of code, what IS that even," and so on.

Here's the nitty-gritty of the scenario.

* There are over 10 characters in the game that you get friendship points with. These are player-incremented values, so you can't just put in a flat one and call it a day.
* I'd like a situation where something comes up, and the character you have the most points with appears.
* We can be jerks here and go with alphabetical order in case of a time, because whatever.

EXAMPLE:
With these friends -
Louie: 8
Zanax: 10
Mimi: 7
Parp: 10

I'd want to find scripting that made sure the one with the most points appeared. (And I'm ok with that being Parp, here, even if Zanax has just as many points, because I want to vagely attempt to make it easier on myself)

I don't need anything printed as a result - I just need something the game can go "AH it's Parp," and I can likely figure out how to route the rest. (it might be a slightly less ugly snarl but I can do it, at least)

THE PROBLEM: every bit of Python I see on this just assumes that the values are static, which doesn't help me - and trying to search "Variable" with RenPy leads to a lot of stuff that's not applicable. Anyone got an idea about this madness?

THANKS! :)

philat
Eileen-Class Veteran
Posts: 1763
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Picking Maximum Variable Value From a Large List

#2 Post by philat » Fri Mar 18, 2016 12:49 am

I'm not sure I understand the question. What do you mean the methods you found assume the values are static? I assume most of the methods were just max(), using varying degrees of complexity.

The answer will depend on your structure anyway. Are you storing them in simple variables? Lists? Dictionaries? Class object fields?

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Picking Maximum Variable Value From a Large List

#3 Post by nyaatrap » Fri Mar 18, 2016 6:30 am

list = [1,2,3]
listindex = list.index(max(list))

dict = {"a":1, "b":2, "c":3}
dictkey = max((k,v) for (k,v) in dict.items())[0]

or something others?

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Picking Maximum Variable Value From a Large List

#4 Post by xela » Fri Mar 18, 2016 6:39 am

nyaatrap wrote:dict = {"a":1, "b":2, "c":3}
dictkey = max((k,v) for (k,v) in dict.items())[0]
This is bad advice assuming sorting by points is required. It'll try to get max off the keys as well as values.

More appropriate way for dicts can be found here:

http://stackoverflow.com/questions/6131 ... y-by-value

I linked the same yesterday to a different post.
Like what we're doing? Support us at:
Image

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Picking Maximum Variable Value From a Large List

#5 Post by nyaatrap » Fri Mar 18, 2016 6:45 am

Oh true. I've using operator on instances and why I didn't think to use it also on dicts.

User avatar
AnnieDB
Regular
Posts: 40
Joined: Tue Dec 01, 2015 3:24 pm
Location: Seattle
Contact:

Re: Picking Maximum Variable Value From a Large List

#6 Post by AnnieDB » Fri Mar 18, 2016 2:29 pm

The problem with the dictionary function is that it needs to know the values for the stuff in the list, and I don't HAVE those values. Since they're player-controlled, they can be a range of things. And so far, I've found nothing about how to put variables in a dictionary where I don't know their values.

Basically, I can't just do -

dict = {"a":1, "b":2, "c":3}

- because a, b, and c could be wildly different in multiple instances. For you, A = 3, B = 4, C = 1 - and later on A = 8, B = 4, C = 3 and so on. I need to check the current values of each variable for a max and know which one is highest at that time.


I've tried

list = ['$ t1', '$ t2', '$ t3']
but RenPy screeches at that and refused to make it work. (Curse my Python inexperience!)

The variables are set and stored on script.rpy (or an appropriate variable manager page). They're simple values incremented over time, like

menu:
"HEY I LIKE YOUR SHIRT"
$t +=1

...and so on.

As a design note, the goal of this is to provide a quick way for the player to see which of the people they have the most points with in a more natural and opaque way instead of just blurting out HEY YOU HAVE 10 POINTS WITH PARP on a menu somewhere. (Which is all fine and good of course, but not how I choose to roll in this occasion)

User avatar
Zetsubou
Veteran
Posts: 495
Joined: Wed Mar 05, 2014 1:00 am
Completed: See my signature
Github: koroshiya
itch: zetsuboushita
Contact:

Re: Picking Maximum Variable Value From a Large List

#7 Post by Zetsubou » Fri Mar 18, 2016 5:35 pm

Not as nice as using a dict, but two lists will achieve this.

Code: Select all

label script:
    python:
        lou = 8
        zan = 10
        mimi = 7
        parp = 10

        vals = [lou, zan, mimi, parp]
        keys = ['Louie', 'Zanax', 'Mimi', 'Parp']
        listindex = vals.index(max(vals))
        #You're most friendly with keys[listindex]
So you'd run the lines from "vals = ..." onwards inside a screen, a function, etc. depending on where and when you want to view this information.
Finished games
-My games: Sickness, Wander No More, Max Massacre, Humanity Must Perish, Tomboys Need Love Too, Sable's Grimoire, My Heart Grows Fonder, Man And Elf, A Dragon's Treasure
-Commissions: No One But You, Written In The Sky, Diamond Rose, To Libertad, Catch Canvas, Love Ribbon, Happy Campers, Wolf Tails

Working on:
Circadian Loop + VN writing commissions

Image

User avatar
AnnieDB
Regular
Posts: 40
Joined: Tue Dec 01, 2015 3:24 pm
Location: Seattle
Contact:

Re: Picking Maximum Variable Value From a Large List

#8 Post by AnnieDB » Fri Mar 18, 2016 6:24 pm

Apologies for having issues parsing this - but it seems like there's still a point where you're defining variables there. I've got them defined in the base script file - and their values all start at 0. In this example I don't know and will not be defining their values.

Would it work if I split this into two steps? Like one: get all the current values of each variable from the game. Two, use those CURRENT definitions to derive which is the max.

My nonsense idea that didn't work started like this:

# list = ['$ t1', '$ t2', '$ t3']

# if max(list) == t1:
# jump option_t1
# elif max(list) == t2:
# jump option_t2
# elif max(list) == t3:
# jump option_t3

(Wherein the "option_" would be different reactive chunks of script)

The earlier example was purely an example with junk numbers to show the sort of thing I was going for. The issue is not making a list or getting a maximum - it's getting a max from variables that CHANGE. It's a tricky beast.

User avatar
Zetsubou
Veteran
Posts: 495
Joined: Wed Mar 05, 2014 1:00 am
Completed: See my signature
Github: koroshiya
itch: zetsuboushita
Contact:

Re: Picking Maximum Variable Value From a Large List

#9 Post by Zetsubou » Fri Mar 18, 2016 6:45 pm

AnnieDB wrote:Apologies for having issues parsing this - but it seems like there's still a point where you're defining variables there.
I did, but that's purely to show how it all works.
If you've already defined your variables, you don't need to do so again.

Code: Select all

        vals = [t1, t2, t3]
        keys = ['Name 1', 'Name 2', 'Name 3']
        listindex = vals.index(max(vals))
        #You're most friendly with keys[listindex]
AnnieDB wrote: My nonsense idea that didn't work started like this:

# list = ['$ t1', '$ t2', '$ t3']

# if max(list) == t1:
# jump option_t1
# elif max(list) == t2:
# jump option_t2
# elif max(list) == t3:
# jump option_t3

(Wherein the "option_" would be different reactive chunks of script)
That's fine, you're just doing it wrong.
Dollar signs don't work line that. https://www.renpy.org/doc/html/python.html
Using your code instead:

Code: Select all

    $ list = ['$ t1', '$ t2', '$ t3']
    $ maxVal = max(list)

    if maxVal == t1:
        jump option_t1
    elif maxVal == t2:
        jump option_t2
    elif maxVal == t3:
        jump option_t3
Finished games
-My games: Sickness, Wander No More, Max Massacre, Humanity Must Perish, Tomboys Need Love Too, Sable's Grimoire, My Heart Grows Fonder, Man And Elf, A Dragon's Treasure
-Commissions: No One But You, Written In The Sky, Diamond Rose, To Libertad, Catch Canvas, Love Ribbon, Happy Campers, Wolf Tails

Working on:
Circadian Loop + VN writing commissions

Image

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Picking Maximum Variable Value From a Large List

#10 Post by trooper6 » Fri Mar 18, 2016 7:19 pm

Rather than a dict, you can use a counter (which is a sort of dict, that has a most common function).

You create your counter with default of 0 points for each element, then you add points to it whenever it is appropriate, and then you call most_common() to see who is the most popular. It would look like this:

Code: Select all

init python:
    from collections import Counter

define n = Character(None, color="#c8ffc8")
default friendspts = Counter({"Louie":0, "Zanax":0, "Mimi":0, "Parp":0})

label start: 
    "Let's just see what is currently in our counter."
    python:
        for k,v in friendspts.items():
            n("[k] has [v] points.")
        else:
            n("End of list")
    "Now lets add some points to those values and then look at the counter again."
    $ friendspts["Louie"] += 8
    $ friendspts["Zanax"] += 10
    $ friendspts["Mimi"] += 7
    $ friendspts["Parp"] += 10
    python:
        for k,v in friendspts.items():
            n("[k] has [v] points.")
        else:
            n("End of list.") 
    
    "You can print out the most friendly in two ways, the long way:"
    $ name = friendspts2.most_common()[0][0]
    "The most friendly is [name]"
    "Or the short way:"
    $n("Our Most friendly? {0}".format(friendspts2.most_common()[0][0]))
    
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Fox Lee
Veteran
Posts: 213
Joined: Sat Oct 18, 2008 1:46 am
Completed: Where Ages Go [NaNo2015]
Projects: Swan x Swan [YuriJam/NaNo16], ♥ON, Guilded Age
Organization: Invincible Ink
Deviantart: foxlee
Location: Australia
Contact:

Re: Picking Maximum Variable Value From a Large List

#11 Post by Fox Lee » Fri Mar 18, 2016 7:29 pm

AnnieDB wrote:The problem with the dictionary function is that it needs to know the values for the stuff in the list, and I don't HAVE those values. Since they're player-controlled, they can be a range of things. And so far, I've found nothing about how to put variables in a dictionary where I don't know their values.

Basically, I can't just do -

dict = {"a":1, "b":2, "c":3}

- because a, b, and c could be wildly different in multiple instances. For you, A = 3, B = 4, C = 1 - and later on A = 8, B = 4, C = 3 and so on. I need to check the current values of each variable for a max and know which one is highest at that time.
Could you just store the variables in a dictionary to begin with, rather than trying to place them in later? If you need to sort the values often, it seems like that would be more convenient to just make a dictionary of 0-values at the start, and update those by their keys during play.

(Or is there some reason that couldn't work? I could be missing something - I've done very little with Python so far ^^; But I just got through making a dictionary-based loop for my weird composite sprite loader, and it seems to work as expected.)
Fox Lee: The Girl Your Mother Warned You About
CleanDirtyFurryPro
Image
Image
Image

User avatar
AnnieDB
Regular
Posts: 40
Joined: Tue Dec 01, 2015 3:24 pm
Location: Seattle
Contact:

Re: Picking Maximum Variable Value From a Large List

#12 Post by AnnieDB » Fri Mar 18, 2016 8:25 pm

trooper6 - That gets me pretty close, thank you! The issue now is not having something print, but routing it correctly, ideally through an if statement that jumps me to a section that can feature that character. Like if you and I both played, but you were peeps with Mimi and I were with Parp - you'd see the scene with Mimi, while I'd see one with Parp.

To clarify: I don't need printouts, but raw values. I can run checks on those and get where I need to go! :)

User avatar
AnnieDB
Regular
Posts: 40
Joined: Tue Dec 01, 2015 3:24 pm
Location: Seattle
Contact:

Re: Picking Maximum Variable Value From a Large List

#13 Post by AnnieDB » Fri Mar 18, 2016 9:37 pm

FIXED! Not by me, but by my friend Jake (credit where due!)

In case anyone wants to know how it was done:

Jake - "I'm creating an array that holds all of the character variables, and another array that holds all of the names we want. Then I find the biggest thing in the character array, grab it's index, and compare it to the second array to get the name I want."

According to him, the trick was creating the array inside the file that contained the subject of the search - because it needs to be a freshly summoned array each time the check is run.

Code: Select all

label SCENE:

    $incident = "NAME"

python:
    char_house = [variable1,variable2,etc]
    char_names = ["variable1","variable2",etc]
    char_best = char_house.index(max(char_house))

CHECK:

Code: Select all

    $ highest_friend = "_" + char_names[char_best]
    $ target_label = "SCENENAME_"+incident+highest_friend
    $ renpy.jump(target_label)

Then boom - if you name the scenes after your characters in this scenario, it should jump there automatically.

Ex.

Code: Select all

    char_house = [char_mimi,char_parp,char_louie,char_zanax]
    char_names = ["mimi","parp","louie","zanax"]
    char_best = char_house.index(max(char_house))
If $ char_mimi was the highest value and
"SCENENAME" = something like "friend"
"incident" = something like "dinner" (defined by the scene it fires in)
you'd end up at friend_dinner_mimi


Thanks everyone for your hard work and good advice - it helped us throw a lot of stuff at the wall in a short time to find the right path to take. Hopefully this discussion will help folks! :)

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Picking Maximum Variable Value From a Large List

#14 Post by xela » Fri Mar 18, 2016 9:54 pm

Zetsubou suggested the same thing couple of posts back... but as long as you got it working.
Like what we're doing? Support us at:
Image

User avatar
AnnieDB
Regular
Posts: 40
Joined: Tue Dec 01, 2015 3:24 pm
Location: Seattle
Contact:

Re: Picking Maximum Variable Value From a Large List

#15 Post by AnnieDB » Fri Mar 18, 2016 10:26 pm

Got it! It was harder to parse in context - and the additional script doo-dads is just fancier routing. Also, their input helped shape where we were going as well. It's very much appreciated!

Post Reply

Who is online

Users browsing this forum: No registered users