// Evol Script
// Author: Gumi
// array_pad(<array>, <size>, <value>)
// prepend or append <value> until the array is of <size> 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(<array>, <needle>, <replace>{, <neq>})
// replace every occurence of <needle> with <replace>
// 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(<array>, <needle>{, <neq>})
// return the index of the first occurence of <needle> in <array>
// 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(<array>, <needle>{, <neq>})
// return the index of the last occurence of <needle> in <array>
// 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(<array>, <needle>{, <neq>})
// return true or false accordingly if <needle> is found in <array>
function script array_exists {
return array_find(getarg(0), getarg(1), getarg(2, false)) > -1;
}
// array_count(<array>, <needle>{, <neq>})
// counts the number of occurrence of <needle> in the <array>
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(<array>)
// 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(<array>, <needle>{, <neq>})
// removes every occurrence of <needle> in the <array> 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(<array>)
// 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(<array>)
// 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(<array>)
// 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(<array>)
// 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(<array>, <value>)
// adds <value> 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(<array>)
// 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(<array>, <value>)
// adds <value> 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(<array>)
// 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(<array>{, <threshold>})
// allows entries to appear up to <threshold> 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(<array1>, <array2>{, <array>...}, <array>)
// 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(<array>, "<function>")
// 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(<array>)
// Returns the index of the highest value in <array>
// 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(<array: 0, {[value, probability]..}>)
// 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);
}