From ba1e827b6b4c17c35a163e6b55be8c122de632b8 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Sat, 10 Apr 2021 03:00:20 -0300 Subject: Add several convenience functions. Fix some bugs regarding misuse of readparam() --- npc/functions/array.txt | 464 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 npc/functions/array.txt (limited to 'npc/functions/array.txt') diff --git a/npc/functions/array.txt b/npc/functions/array.txt new file mode 100644 index 00000000..d433abd7 --- /dev/null +++ b/npc/functions/array.txt @@ -0,0 +1,464 @@ +// Evol Script +// Author: Gumi + +// array_pad(, , ) +// prepend or append until the array is of size +// returns the amount added on success, or false (0) if nothing changed + +function script array_pad { + .@index = getarrayindex(getarg(0)); // passed index + .@count = getarraysize(getarg(0)) - .@index; // actual size + .@size = getarg(1); // desired size + .@absolute = (.@size >= 0 ? .@size : -(.@size)); // |size| + .@delta = .@absolute - .@count; // amount to fill + + if (.@absolute <= .@count) { + return false; // nothing to do + } + + if (.@size < 0) { + copyarray(getelementofarray(getarg(0), .@index + .@delta), getarg(0), .@count); // shift to the right + cleararray(getarg(0), getarg(2), .@delta); // prepend + } else { + cleararray(getelementofarray(getarg(0), .@index + .@count), getarg(2), .@delta); // append + } + + return .@delta; +} + + + +// array_replace(, , {, }) +// replace every occurence of with +// returns the number of replaced elements + +function script array_replace { + .@size = getarraysize(getarg(0)); + .@neq = getarg(3, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + set(getelementofarray(getarg(0), .@i), getarg(2)); + ++.@count; + } + } + + freeloop(false); + return .@count; +} + + + +// array_find(, {, }) +// return the index of the first occurence of in +// if not found it returns -1 + +function script array_find { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + freeloop(false); + return .@i; + } + } + + freeloop(false); + return -1; +} + + + +// array_rfind(, {, }) +// return the index of the last occurence of in +// if not found it returns -1 + +function script array_rfind { + .@min = getarrayindex(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = (getarraysize(getarg(0)) - 1); .@i >= .@min; --.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + freeloop(false); + return .@i; + } + } + + freeloop(false); + return -1; +} + + + +// array_exists(, {, }) +// return true or false accordingly if is found in + +function script array_exists { + return array_find(getarg(0), getarg(1), getarg(2, false)) > -1; +} + + + +// array_count(, {, }) +// counts the number of occurrence of in the + +function script array_count { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + ++.@count; + } + } + + freeloop(false); + return .@count; +} + + + +// array_entries() +// returns the number of non-empty entries + +function script array_entries { + if (isstr(getarg(0)) == 1) { + return array_count(getarg(0), "", true); + } + return array_count(getarg(0), 0, true); +} + + + +// array_remove(, {, }) +// removes every occurrence of in the while shifting left + +function script array_remove { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + deletearray(getelementofarray(getarg(0), .@i), 1); // shift left + ++.@count; // increase the counter + --.@size; // reduce the size + --.@i; // step back + } + } + + freeloop(false); + return .@count; +} + + + +// array_reverse() +// reverses the array + +function script array_reverse { + .@index = getarrayindex(getarg(0)); + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = .@index; .@i < ((.@size + .@index) / 2); ++.@i) { + swap(getelementofarray(getarg(0), .@i), getelementofarray(getarg(0), .@size + .@index - 1 - .@i)); // a <> b + } + + freeloop(false); + return true; +} + + + +// array_sum() +// return the sum of every element of the array + +function script array_sum { + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@sum += getelementofarray(getarg(0), .@i); + } + + freeloop(false); + return .@sum; +} + + + +// array_difference() +// return the difference of every element of the array + +function script array_difference { + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@diff -= getelementofarray(getarg(0), .@i); + } + + freeloop(false); + return .@diff; +} + + + +// array_shift() +// returns the first element of the array and removes it, while shifting left + +function script array_shift { + if (isstr(getarg(0)) == 1) { + .@val$ = getarg(0); + } else { + .@int = true; + .@val = getarg(0); + } + + deletearray(getarg(0), 1); // shift left + + return .@int ? .@val : .@val$; +} + + + +// array_unshift(, ) +// adds to the start of the array, while shifting right +// returns the new size + +function script array_unshift { + .@size = getarraysize(getarg(0)) + 1; + array_pad(getarg(0), -(.@size - getarrayindex(getarg(0))), getarg(1)); + return .@size; +} + + + +// array_pop() +// returns the last element of the array and removes it + +function script array_pop { + .@last = getarraysize(getarg(0)) - 1; + + if (isstr(getelementofarray(getarg(0), .@last)) == 1) { + .@val$ = getelementofarray(getarg(0), .@last); + } else { + .@int = true; + .@val = getelementofarray(getarg(0), .@last); + } + + deletearray(getelementofarray(getarg(0), .@last), 1); + + return .@int ? .@val : .@val$; +} + + + +// TODO: Rename to array_append >.< +// array_push(, ) +// adds to the end of the array +// returns the new size + +function script array_push { + .@size = getarraysize(getarg(0)); + set(getelementofarray(getarg(0), .@size), getarg(1)); + return .@size + 1; +} + + + +// array_shuffle() +// shuffles the array + +function script array_shuffle { + .@index = getarrayindex(getarg(0)); + .@size = getarraysize(getarg(0)) - .@index; + freeloop(true); + + if (isstr(getarg(0)) == 1) { + copyarray(.@tmp$[0], getarg(0), .@size); + for (; .@size >= 1; --.@size) { + set(getelementofarray(getarg(0), .@index + .@size - 1), array_shift(.@tmp$[rand(.@size)])); + } + } else { + copyarray(.@tmp[0], getarg(0), .@size); + for (; .@size >= 1; --.@size) { + set(getelementofarray(getarg(0), .@index + .@size - 1), array_shift(.@tmp[rand(.@size)])); + } + } + + freeloop(false); + return true; +} + + + +// array_unique({, }) +// allows entries to appear up to in the array + +function script array_unique { + .@size = getarraysize(getarg(0)); + .@max = getarg(1, 1); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@count = 1; + for (.@e = .@i + 1; .@e < .@size; ++.@e) { + if (getelementofarray(getarg(0), .@i) == getelementofarray(getarg(0), .@e)) { + if (++.@count >= .@max) { + deletearray(getelementofarray(getarg(0), .@e), 1); + ++.@removed; // increase counter + --.@size; // reduce size + --.@e; // step back + } + } + } + } + + freeloop(false); + return .@removed; +} + + + +// array_diff(, {, ...}, ) +// compares array1 against one or more other arrays and fills the last array +// with the values in array1 that are not present in any of the other arrays +// returns the number of entries not matching + +function script array_diff { + .@size = getarraysize(getarg(0)); + .@index = getarrayindex(getarg(0)); + freeloop(true); + + for (.@a = 1; .@a < (getargcount() - 1); ++.@a) { + for (.@i = .@index; .@i < .@size; ++.@i) { + if (!array_exists(getarg(.@a), getelementofarray(getarg(0), .@i))) { + array_push(getarg(getargcount() - 1), getelementofarray(getarg(0), .@i)); + ++.@count; + } + } + } + + freeloop(false); + return .@count; +} + + + +// array_filter(, "") +// filters the array using a callback function + +function script array_filter { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@eq = callfunc(getarg(1), getelementofarray(getarg(0), .@i)) != false; + if ((.@neq && .@eq) || (!(.@neq) && !(.@eq))) { + deletearray(getelementofarray(getarg(0), .@i), 1); // shift left + ++.@count; // increase the counter + --.@size; // reduce the size + --.@i; // step back + } + } + + freeloop(false); + return .@count; +} + +// array_highest() +// Returns the index of the highest value in +// NOTE: Array must be an INT array! + +function script array_highest { + .@size = getarraysize(getarg(0)); + .@win=0; + .@idx=0; + .@dw=false; + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if (getelementofarray(getarg(0), .@i) > .@win) { + .@win=getelementofarray(getarg(0), .@i); + .@idx=.@i; + if (.@dw) { + deletearray .@draw; + .@dw=false; + } + } else if (getelementofarray(getarg(0), .@i) == .@win) { + if (!.@dw) + array_push(.@draw, .@idx); + array_push(.@draw, .@i); + .@dw=true; + } + } + + // Will we return .@idx or do we need to draw a loot? + freeloop(false); + if (.@dw) + return any_of(.@draw); + else + return .@idx; +} + +// relative_array_random() +// returns a random entry from the array, by relative probability +// the first key of the array should be 0 and every entries are a tuple +// of [value, probability] + +function script relative_array_random { + .@is_str = getdatatype(getarg(0)) & DATATYPE_STR; + .@total_prob = getelementofarray(getarg(0), 0); + .@initial_index = getarrayindex(getarg(0)); + .@initial_index = .@initial_index ? .@initial_index : 1; + freeloop(true); + + if (.@total_prob < 1 || getarg(1, false)) + { + // first calculation, or forced re-calculation + .@total_prob = 0; + .@size = getarraysize(getarg(0)); + + for (.@i = .@initial_index + 1; .@i < .@size; .@i += 2) { + if (.@is_str) { + .@total_prob += max(1, atoi(getelementofarray(getarg(0), .@i))); + } else { + .@total_prob += max(1, getelementofarray(getarg(0), .@i)); + } + } + + // we cache on the first key + set(getelementofarray(getarg(0), 0), .@total_prob); + } + + .@target_sum = rand(0, .@total_prob); + + for (.@i = .@initial_index; .@sum < .@target_sum; .@i += 2) { + if (.@is_str) { + .@sum += atoi(getelementofarray(getarg(0), .@i + 1)); + } else { + .@sum += getelementofarray(getarg(0), .@i + 1); + } + + if (.@sum >= .@target_sum) { + break; + } + } + + freeloop(false); + return getelementofarray(getarg(0), .@i); +} + -- cgit v1.2.3-60-g2f50