• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Trigger] Sort Real from Lowest to Highest

Status
Not open for further replies.
Level 19
Joined
Oct 29, 2007
Messages
1,184
I am making a custom targeting system. Each player has one hero. When a player presses Esc, the system should detect units nearby the hero and sort the distance between them and the hero from closest, to farthest. I have this part of the trigger now:

  • Select Unit Copy
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
      • Player - Player 2 (Blue) skips a cinematic sequence
      • Player - Player 3 (Teal) skips a cinematic sequence
      • Player - Player 4 (Purple) skips a cinematic sequence
    • Conditions
      • DetectTargeting[(Player number of (Triggering player))] Equal to 0
    • Actions
      • Custom script: local integer a
      • Custom script: local rect r
      • Custom script: set r = Rect ( 0, 0, 0, 0 )
      • Custom script: set a = 2048
      • Set tmp_loc = (Position of Player[(Player number of (Triggering player))])
      • Custom script: call SetRect ( r, GetLocationX(udg_tmp_loc) - (a * 0.5), GetLocationY(udg_tmp_loc) - (a * 0.5), GetLocationX(udg_tmp_loc) + (a * 0.5), GetLocationY(udg_tmp_loc) + (a * 0.5) )
      • Set tmp_group[1] = (Units in tmp_region matching ((Owner of (Picked unit)) Not equal to Player 5 (Yellow)))
      • Unit Group - Pick every unit in tmp_group[1] and do (Actions)
        • Loop - Actions
          • Set tmp_real_array[tmp_integer] = (Distance between (Position of Player[(Player number of (Triggering player))]) and (Position of (Picked unit)))
          • Set tmp_integer = (tmp_integer + 1)
I have now detected the distance between the hero and the picked unit and saved it as "tmp_real_array[array]". No comes the hard part. What I need to do now is sort the reals from lowest to highest. Does anyone have a good way to do that? : <
 
Make another temp array and loop through the tmp_real_array setting a different temp real to the value at that point if it is lower than temp real, when you've completed the loop, set the first value of the new temp real array to whatever the temp real is. Loop like that again until you've sorted it.

EDIT: Meh, ignore that. Call this JASS function:
JASS:
function SortAscending takes nothing returns nothing
    local real tmpReal
    local boolean finish = true
    local integer i
    
    loop
        set i = 0
        set finish = true
        loop
            exitwhen i >= udg_tmp_int - 1
            
            if udg_tmp_real_array[i] > udg_tmp_real_array[i+1] then
                set tmpReal = udg_tmp_real_array[i]
                set udg_tmp_real_array[i] = udg_tmp_real_array[i+1]
                set udg_tmp_real_array[i+1] = tmpReal
                
                set finish = false
            endif
            
            set i = i + 1
        endloop
        
        exitwhen finish
    endloop
        
endfunction
For it to work you need a global real array called tmp_real_array, the one which it will sort, and a global integer tmp_int, which should be the maximum index of the array. This function assumes you use the index 0. If you don't it might not work.

EDIT2: Fixed a syntax error in the function

EDIT3: Fixed it so the function actually works lol
 
Last edited:
Level 8
Joined
Aug 4, 2006
Messages
357
Use this. It's more efficient than EOW's and I'm sure it will work. It uses a selection sort. udg_tmp_int should be the size of the array.
JASS:
function SortAscending takes nothing returns nothing
    local integer min
    local real temp
    local integer i
    local integer j
    
    set i = 0
    loop
        exitwhen i >= udg_tmp_int - 1
        set min = i
        set j = i + 1
        loop
            exitwhen j >= udg_tmp_int
            if udg_tmp_real_array[j] < udg_tmp_real_array[min] then
                set min = j
            endif
            set j = j + 1
        endloop
        if i != min then
            set temp = udg_tmp_real_array[i]
            set udg_tmp_real_array[i] = udg_tmp_real_array[min]
            set udg_tmp_real_array[min] = temp
        endif
        set i = i + 1
    endloop
        
endfunction

Megafyr said:
So this function will make "udg_tmp_real_array[1]" lowest and "udg_tmp_real_array[MOAR]" highest? :>
Yes.
 
Level 8
Joined
Aug 4, 2006
Messages
357
Oh woops. Ya the element at 0 is lowest, and the reals increase from there.

I don't think your sort would work properly. To me it looks like it would do an infinite loop if it ever had to swap two values. It sets finish to false, but there's nowhere else it could be set to true so the outer loop will not exit.

Selection sort does basically the same thing as bubble sort, but in a more efficient manner. It's also really easy to understand. While bubble sort causes the biggest value to "bubble" to the top on each inner loop, selection sort simply finds the biggest value and waits till the end of the inner loop to swap that value to the top. Since this top value is now in the right place, we no longer need to loop through it. We loop through the rest of the elements looking for the next highest real, and swap that to the top. Repeat until there are no more values to compare.

In the selection sort I did above, I actually stored the minimum value instead of the maximum. It's basically the same thing as I just explained, but swapping to the bottom of the list instead of the top.
 
Status
Not open for further replies.
Top