Page 1 of 1

Picking Maximum Variable Value From a Large List

Posted: Thu Mar 17, 2016 9:27 pm
by AnnieTiamat
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! :)

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 12:49 am
by philat
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?

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 6:30 am
by nyaatrap
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?

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 6:39 am
by xela
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.

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 6:45 am
by nyaatrap
Oh true. I've using operator on instances and why I didn't think to use it also on dicts.

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 2:29 pm
by AnnieTiamat
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)

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 5:35 pm
by Zetsubou
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.

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 6:24 pm
by AnnieTiamat
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.

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 6:45 pm
by Zetsubou
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

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 7:19 pm
by trooper6
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]))
    

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 7:29 pm
by Fox Lee
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.)

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 8:25 pm
by AnnieTiamat
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! :)

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 9:37 pm
by AnnieTiamat
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! :)

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 9:54 pm
by xela
Zetsubou suggested the same thing couple of posts back... but as long as you got it working.

Re: Picking Maximum Variable Value From a Large List

Posted: Fri Mar 18, 2016 10:26 pm
by AnnieTiamat
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!