Jump to content

Scripting question


steelfeathers

Recommended Posts

I'm working on a script for an ability, and I need to be able to find the actor's top 3 skills.

 

However, I can't seem to figure out a clean way to find the maximum of a set of numbers - there doesn't seem to be a generic "max/min" function for papyrus.

 

Has anyone worked out a method for taking more than 2 numbers and finding the maximum? There are 15 skills to look at, which quickly gets out of hand when trying to compare each skill to every other skill.

Link to comment
Share on other sites

The function is trivial:

int function maxIndex(float[] numbers)
    ; Indicate an error for an empty array.
    if numbers.length < 1
        return -1
    endif

    ; Set up variables to track current maximum.
    int maxIndex = 0
    float maxValue = numbers[0]

    ; Loop through all array elements.
    int i = 1
    while i < numbers.length
        ; Update maximum whenever we find a larger value
        if numbers[i] > maxValue
            maxIndex = i
            maxValue = numbers[i]
        endif
        i += 1
    endwhile

    ; maxIndex now contains the index of the max value in the input array.
    return maxIndex
endfunction

If you're not familiar with this algorithm, the idea is simple:

  1. Given an unsorted list of values, assume the first one is the largest value. This is called the candidate maximum.
  2. Starting with the second value, compare it with the current candidate. If the candidate is smaller, replace it with the new, larger value.
  3. When you get to the end of the list, the candidate is the maximum value.

This particular function returns the position in the array rather than the value itself, since "the 4th skill in the list" is what we want to know, not "that skill that's at 58, you know the one."

 

You'd want each position in the array to correspond to a particular skill. That way if you get 8 back, you can check that list and know 8 is One Handed or Destruction or Lockpicking or whatever.

 

But if you want to get the top three, then rather than running max() three times and checking most of the skills multiple times, what you really want is a sort.

 

And yes, you'll want to decide what you want to do for skills that have the same value.

 

Edit: I went ahead and wrote a Papyrus implementation of quicksort, mostly out of boredom. Maybe it'll help? I haven't tested it yet, though, so it might not even compile.

function fSwap(float[] a, int i, int k)
    float temp = a[i]
    a[i] = a[k]
    a[k] = temp
endfunction

function iSwap(int[] a, int i, int k)
    int temp = a[i]
    a[i] = a[k]
    a[k] = temp
endfunction

function quicksort(float[] numbers, int[] indexes, int start, int end)
    p = partition(numbers, indexes, start, end)
    quicksort(numbers, indexes, start, p - 1)
    quicksort(numbers, indexes, p + 1, end)
endfunction

int function partition(float[] numbers, int[] indexes, int start, int end)
    pivotIndex = start
    pivotValue = numbers[start]
    
    fSwap(numbers, pivotIndex, end)
    iSwap(indexes, pivotIndex, end)

    int storeIndex = start
    int i = start
    while i < end
        if numbers[i] < pivotValue
            fSwap(numbers, i, storeIndex)
            iSwap(indexes, i, storeIndex)
            storeIndex += 1
        endif
        i += 1
    endwhile

    fSwap(numbers, storeIndex, end)
    iSwap(indexes, storeIndex, end)
    return storeIndex
endfunction

int[] function indexSort(float[] numbers)
    int[] indexes = new int[numbers.length]
    float[] numCopy = new float[numbers.length]
    int i = 0
    while i < indexes.length
        indexes[i] = i
        numCopy[i] = numbers[i]
        i += 1
    endwhile

    quicksort(numCopy, indexes, 0, numbers.length)

    return indexes
endfunction

Note: the fSwap, iSwap, partition, quicksort, and indexSort functions are all required. The indexSort function is the one you want to actually call, and returns an array of integers containing the original order of the array, so if you put in [81, 4, 73] you'll get out [1, 2, 0]. That way if you had some other array in the same order like ["Lockpicking", "One Handed", "Speechcraft"], you could look up the skill.

Edited by rainbowhyphen
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...