Seeking simple code to rank a series of stats


#1

I have four stats, all numeric, and I’ll be using their rankings fairly regularly. I need to know all four stats’ positions, so I was going to code a sequence that would set the best, second best, and worst (so then I’ve found the third-ranked stat by default). I’m planning to put this code in a subscene, since I’ll need it frequently.

The method I’m using now takes about a hundred lines, and it looks like this, only four times over in different iterations:

Code

*if (((stat_a >= stat_b) and (stat_a >= stat_c)) and (stat_a >= stat_d))
  *set best_stat "stat_a"
  *if ((stat_b >= stat_c) and (stat_b >= stat_d))
    *set second_stat "stat_b"
    *if (stat_c >= stat_d)
      *set worst_stat "stat_d"
      *goto all_done
    *else
      *set worst_stat "stat_c"
      *goto all_done
  *elseif (stat_c >= stat_d)
    *set second_stat "stat_c"
    *if (stat_b >= stat_d)
      *set worst_stat "stat_d"
      *goto all_done
    *else
      *set worst_stat "stat_b"
      *goto all_done
  *else
    *set second_stat "stat_d"
    *if (stat_b >= stat_c)
      *set worst_stat "stat_c"
      *goto all_done
    *else
      *set worst_stat "stat_b"
      *goto all_done

And so forth for stat_b and stat_c and stat_d, with a few minor variations to account for previous code.

I was just wondering if anyone had suggestions for how to code a simpler version? I feel like there must be a quicker solution, but after some tinkering, I’m still not sure what. I did have a hunt for a topic on this, but I didn’t find anything (apologies if I’ve just missed them).

Thanks!


#2

I remember having to do this for 20 items back in 1999 for a football management game I was trying to make. Needless to say the code was very long!

For 4… let’s see. There are 4! possible combinations but you also have to take into account ties (two stats the same). 100 lines isn’t bad. I’ll get to a PC in a few hours and see if I can do any better.


#3

I just decided which stats would take priority in the case of ties (mostly based on whimsy what might be most narratively interesting, or possibly less-often the highest), as I’m not using these for scores, like I have up in that wee sample.

Fabulous! I look forward to seeing the results of your coding wizardry.


#4

This is 71 lines with declarations. I didn’t try with arrays yet which would simplify it.

*temp stat_a 60
*temp stat_b 90
*temp stat_c 70
*temp stat_d 50
*temp temp_stat ""
*temp best_stat ""
*temp second_instrument ""
*temp third_instrument ""
*temp worst_stat ""

*comment find best stat
*set best_stat "stat_a"
*set temp_stat "stat_b"
*gosub CompareBestStats
*set temp_stat "stat_c"
*gosub CompareBestStats
*set temp_stat "stat_d"
*gosub CompareBestStats

*comment second best stat
*set second_instrument "stat_a"
*set temp_stat "stat_b"
*gosub Compare2ndBestStats
*set temp_stat "stat_c"
*gosub Compare2ndBestStats
*set temp_stat "stat_d"
*gosub Compare2ndBestStats

*comment third stat
*set third_instrument "stat_a"
*set temp_stat "stat_b"
*gosub Compare3rdBestStats
*set temp_stat "stat_c"
*gosub Compare3rdBestStats
*set temp_stat "stat_d"
*gosub Compare3rdBestStats

*comment worst stat
*set worst_stat "stat_a"
*if worst_stat = best_stat
  *set worst_stat "stat_b"
*if worst_stat = second_instrument
  *set worst_stat "stat_c"
*if worst_stat = third_instrument
  *set worst_stat "stat_d"
  
best stat: ${best_stat}
*line_break
2nd best stat: ${second_instrument}
*line_break
3rd best stat: ${third_instrument}
*line_break
worst stat: ${worst_stat}
*finish

*label CompareBestStats
*if {temp_stat} > {best_stat}
  *set best_stat temp_stat
*return

*label Compare2ndBestStats
*if best_stat != temp_stat
  *if {temp_stat} > {second_instrument}
    *set second_instrument temp_stat
*return

*label Compare3rdBestStats
*if (best_stat != temp_stat) and (second_instrument != temp_stat)
  *if {temp_stat} > {third_instrument}
    *set third_instrument temp_stat
*return

#5

Hmmm… I see 1st, 2nd, and worse ranking.
Is our 3rd champion is intentionally missed out there?


#6

I asked a similar question a few weeks ago. Still haven’t solved the problem of ties, though.


#7

Yes; I don’t think I’ll need it, actually, but if I do I’ve already found it by default.

I did see that, but you were just looking for the highest stat, correct? And not a system for ranking, which adds other steps too…

That looks brilliant, thank you.

I thought arrays would likely assist, but they’re still quite new to me so I’ve done very limited meddling. I should probably meddle more. Thank you though, much obliged!


#8

I’m afraid I don’t have a lot of time, but this is what I’ve come up with.

Note: this will get you the four numbers in the correct order but it doesn’t tell you the name of what each stat represents… I’m assuming you will match them again afterwards or that doesn’t matter? :confused:

Summary
*create stat_a 0
*create stat_b 0
*create stat_c 0
*create stat_d 0
*create temp_stat 0
*create first stat_a
*create second stat_c
*create third stat_b
*create fourth stat_d

*comment compare 2 pairs to get highest (first and second) and lowest (third and fourth)
*if stat_b >= stat_a
  *set first stat_b
  *set third stat_a
*if stat_d >= stat_c
  *set second stat_d
  *set fourth stat_c

*comment cross check the lower numbers with the higher numbers
*if fourth >= first
  *set temp_stat fourth
  *set fourth first
  *set first temp_stat
*if third >= second
  *set temp_stat third
  *set third second
  *set second temp_stat

*comment compare top1 and top2 - for first and second place
*if second > first
  *set temp_stat first
  *set first second
  *set second temp_stat

*comment compare third and fourth - swap if necessary.
*label third_fourth
*if fourth > third
  *set temp_stat third
  *set third fourth
  *fourth temp_stat
*goto all_done

Edit: down to 33 lines if you remove the comments and spaces.


#9

It’s fabulous; thank you!

I actually mostly need to know which stat is in which position, not which number value is the highest…now to see what would be the quickest way to do that, and if I can sneak it in and still keep the total under the 42 lines of code @JimD’s algorithm compressed into. :D

@JimD and @andymwhy I’ll be using one or the other of your samples as the basis for my code…would you mind terribly if I credit you in the scene file via *comment as the originator of your code routine? And thanks so much!

Edit: @JimD I was playing about with the code and discovered that it doesn’t work properly if the stats happen to be in descending order. I tried (without changing anything save the names of the stats) and ended up like so:

I’ve managed to change the problem by tinkering but I’ve not been eliminate it entirely…still trying, though.


#10

@JimD is missing a check on the occasion that best_stat = temp_stat (which happens if stat_a is the highest). In which case, stat_a is found as the best in all 4 slots, I believe.

In this situation, I’d recommend using my code as you only have 4 numbers to order. My code will give you the four numbers in the correct order. Jim’s style, with a little tweaking, would be better for a general case (5, 10, X items to order).

There’s no need to place a credit but if you wish to in the code as a comment, that’s fine :slight_smile:


#11

Insert Sort using arrays, for giggles:

*title Insert Sort Test
*author RTWojick
*scene_list
	startup

*create leadership 50
*create strength 50
*create intellect 50
*create agility 50

*create stat_0 ""
*create stat_1 ""
*create stat_2 ""
*create stat_3 ""

*create val_0 0
*create val_1 0
*create val_2 0
*create val_3 0

*label reset

*set stat_0 "leadership"
*set stat_1 "strength"
*set stat_2 "intellect"
*set stat_3 "agility"

*rand leadership 1 100
*rand strength 1 100
*rand intellect 1 100
*rand agility 1 100

*set val_0 leadership
*set val_1 strength
*set val_2 intellect
*set val_3 agility

Insert Sort Test

*page_break

*gosub insert_sort

Unsorted:
*stat_chart
	text Leadership
	text Strength
	text Intellect
	text Agility
*line_break
Sorted:
*line_break
${stat_0}: ${val_0}
*line_break
${stat_1}: ${val_1}
*line_break
${stat_2}: ${val_2}
*line_break
${stat_3}: ${val_3}

*page_break

*goto reset

*label insert_sort

*temp i 1
*temp j 0
*temp curr_stat ""
*temp curr_val 0

*label sort_start

*set curr_stat stat[i]
*set curr_val val[i]
*set j (i - 1)

*label shift_vals
*if (j >= 0)
	*if (val[j] < curr_val)
		*set val[j + 1] val[j]
		*set stat[j + 1] stat[j]
		*set j -1
		*goto shift_vals
*set val[j + 1] curr_val
*set stat[j + 1] curr_stat
*set i +1
*if (i < 4)
	*goto sort_start

*return

#12

Update! More efficient version using references:

*title Insert Sort Test
*author RTWojick
*scene_list
	startup

*create leadership 50
*create strength 50
*create intellect 50
*create agility 50

*create stat_0 "leadership"
*create stat_1 "strength"
*create stat_2 "intellect"
*create stat_3 "agility"

*label reset

*rand leadership 1 100
*rand strength 1 100
*rand intellect 1 100
*rand agility 1 100

Insert Sort Test

*page_break

*gosub insert_sort

Unsorted:
*stat_chart
	text Leadership
	text Strength
	text Intellect
	text Agility
*line_break
Sorted:
*line_break
$!{stat_0}: ${{stat_0}}
*line_break
$!{stat_1}: ${{stat_1}}
*line_break
$!{stat_2}: ${{stat_2}}
*line_break
$!{stat_3}: ${{stat_3}}

*page_break

*goto reset

*label insert_sort

*temp i 1
*temp j 0
*temp curr ""

*label sort_start

*set curr stat[i]
*set j (i - 1)

*label shift_vals
*if (j >= 0)
	*if ({stat[j]} < {curr})
		*set stat[j + 1] stat[j]
		*set j -1
		*goto shift_vals
*set stat[j + 1] curr
*set i +1
*if (i < 4)
	*goto sort_start

*return