How to determine if something is the second highest stat?

Hello, I’m determining whether the player ends up getting the trickier to get endings for Don’t Wake Me Up (I know, DWMU is finally getting its endings)!

Basically, you can’t get a certain ending if OUAD is the highest stat.

There are four stats, referred to in short as ROTP/OUAD/FB/WC

It doesn’t matter if OUAD is the second highest stat, it’s more testing whether it was predominantly the highest.

Should I just go through and try and find a reasonable stat number instead, or is there an easier way for me to do this?

Basically I want to be able to write
*if OUAD = not the highest stat
*goto ending1
*else
*goto ending2

Finding the highest stat is fairly simple and finding the second highest is only slightly more complicated. I have modified a piece of code that I originally wrote for a different problem, but I think it will work.

The code below is a gosub routine. There are six variables (u, v, w, x, y, and z), so if you have fewer or more variables you will need to modify it to work for you, but the concept should be the same. It will make two cycles. In the first cycle it will determine the highest stat, and in the second cycle it will determine the second highest stat.

If you only need to know the highest stat, then the code needn’t be quite this complicated.

*temp u_test u
*temp v_test v
*temp w_test w
*temp x_test x
*temp y_test y
*temp z_test z

*label highest

*if ((((((u_test >= v_test) and (u_test >= w_test)) and (u_test >= x_test)) and (u_test >= y_test)) and (u_test >= z_test))
  *if (counter = 0)
    *set u_high true
    *set u_test 0
    *set counter +1
  *else
    *set u_2ndhigh true
    *return
*elseif ((((((v_test >= u_test) and (v_test >= w_test)) and (v_test >= x_test)) and (v_test >= y_test)) and (v_test >= z_test))
  *if (counter = 0)
    *set v_high true
    *set v_test 0
    *set counter +1
  *else
    *set v_2ndhigh true
    *return
*elseif ((((((w_test >= u_test) and (w_test >= v_test)) and (w_test >= x_test)) and (w_test >= y_test)) and (w_test >= z_test))
  *if (counter = 0)
    *set w_high true
    *set w_test 0
    *set counter +1
  *else
    *set w_2ndhigh true
    *return
*elseif ((((((x_test >= u_test) and (x_test >= v_test)) and (x_test >= w_test)) and (x_test >= y_test)) and (x_test >= z_test))
  *if (counter = 0)
    *set x_high true
    *set x_test 0
    *set counter +1
  *else
    *set x_2ndhigh true
    *return
*elseif ((((((y_test >= u_test) and (y_test >= v_test)) and (y_test >= w_test)) and (y_test >= x_test)) and (y_test >= z_test))
  *if (counter = 0)
    *set y_high true
    *set y_test 0
    *set counter +1
  *else
    *set y_2ndhigh true
    *return
*else
  *if (counter = 0)
    *set z_high true
    *set z_test 0
    *set counter +1
  *else
    *set z_2ndhigh true
    *return

*if (counter = 1)
  *goto highest
*else 
  *bug
  *comment I put a bug here because the code should automatically *return if the counter is > 1, but it never hurts to make sure that everything is working as intended

Note that you will need to implement *gotos in this code if you have not enabled implicit control flow.

Let me know if you have any questions and whether or not this works for you!

3 Likes

If you’re willing to use curly brace notation, you can work with the name of your skills in variables to determine the highest and second-highest. In this example, I have four skill variables: skill_labwork, skill_library_research, skill_rhetoric, and skill_reasoning. The following code will put the name of the highest skill in the variable max_skill and the second-highest skill in the variable second_max_skill:

*temp max_skill "skill_labwork"
*temp second_max_skill "skill_library_research"
*if {max_skill} < skill_library_research
    *set second_max_skill max_skill
    *set max_skill "skill_library_research"
*elseif {second_max_skill} < skill_library_research
    *set second_max_skill "skill_library_research"
*if {max_skill} < skill_rhetoric
    *set second_max_skill max_skill
    *set max_skill "skill_rhetoric"
*elseif {second_max_skill} < skill_rhetoric
    *set second_max_skill "skill_rhetoric"
*if {max_skill} < skill_reasoning
    *set second_max_skill max_skill
    *set max_skill "skill_reasoning"
*elseif {second_max_skill} < skill_reasoning
    *set second_max_skill "skill_reasoning"

In your case, use ROTP, OUAD, FB, and WC in place of the skill_whatever values. Then you can see if max_skill equals OUAD, or if second_max_skill equals OUAD.

3 Likes

There are two ways you can go about it:

  1. Find the highest stat and check if it is or isn’t the OUAD (moderately difficult);
  2. Compare all stats to OUAD and check if there’s one above it (easy).

For the first one you might want to do something like this:


*label check_highest_stat

*temp stat_1 "ROTP"
*temp stat_2 "OUAD"
*temp stat_3 "FB"
*temp stat_4 "WC"

*temp highest (0-1000)

*temp loop_counter = 1
*label check_highest_stat_begin_for_loop
*if {stat[loop_counter]} > {highest}
	*set highest stat[loop_counter]
	*goto check_highest_stat_continue_for_loop
*label check_highest_stat_continue_for_loop
*set loop_counter +1
*if loop_counter <= 4
	*goto check_highest_stat_begin_for_loop
*return

For the second one, something like this:


*label check_if_OUAD_is_highest

*temp is_highest true

*if ROTP > OUAD
	*set is_highest false
	*return
*elseif FB > OUAD
	*set is_highest false
	*return
*elseif WC > OUAD
	*set is_highest false
	*return
*else
	*return

6 Likes

Elegant solution.

You don’t actually need that first *goto/*label pair. Choicescript automatically falls out of simple *if blocks (those without corresponding *elseif or *else). And yes, that’s regardless of your implicit_control_flow setting. In fact, you’re already doing that in your second *if block.

*label check_highest_stat

*temp stat_1 "ROTP"
*temp stat_2 "OUAD"
*temp stat_3 "FB"
*temp stat_4 "WC"

*temp highest (0-1000)

*temp loop_counter = 1
*label check_highest_stat_begin_for_loop
*if {stat[loop_counter]} > {highest}
	*set highest stat[loop_counter]
*set loop_counter +1
*if loop_counter <= 4
	*goto check_highest_stat_begin_for_loop
*return

1 Like

Thanks! Normally I wouldn’t even use that many labels, because I do use implicit control. But when posting here I try to add as many as I can, cause I never remember when they’re mandatory without the implicit control.

1 Like