Compare commits

...

7 Commits

Author SHA1 Message Date
Lemongrass3110
726f7ac07b Fixed different signedness 2024-06-13 01:40:23 +02:00
Lemongrass3110
15c6201d99 Removed accidentally committed test script 2024-06-13 01:33:18 +02:00
Lemongrass3110
e815efb565 Merge branch 'master' into feature/array_sort
# Conflicts:
#	src/map/script.cpp
2024-06-13 01:30:52 +02:00
Lemongrass3110
22debbe86b Merge branch 'master' into feature/array_sort
# Conflicts:
#	doc/script_commands.txt
#	src/map/script.cpp
2018-06-14 22:14:23 +02:00
Lemongrass3110
0bf92ab14f Merge branch 'master' into feature/array_sort 2018-02-02 17:31:05 +01:00
Jittapan Pluemsumran
9231262787 Added support for string array sorting 2018-01-11 00:06:51 +07:00
Jittapan Pluemsumran
12d5d99a4d Implemented array sorting utility script command 2018-01-10 23:13:41 +07:00
3 changed files with 220 additions and 0 deletions

View File

@ -2406,6 +2406,34 @@ For more details, see the sample in 'doc/sample/inarray.txt'.
---------------------------------------
*sortarray(<array name>);
This command will do an in-place sort on an array specified in <array name>.
Original ordering of the array before execution of this command will be lost.
Example:
setarray .@a,31, 44, 14, 18, 24, 42, 39, 47, 30, 17, 36, 45, 34, 21, 38, 41, 23, 25, 13, 20, 8, 5, 22, 9, 2, 12, 19, 35, 48, 37;
sortarray(.@a);
.@size = getarraysize(.@a);
for(.@i = 0; .@size; .@i++) {
.@msg$ = .@msg$ + .@a[.@i] + " ";
}
debugmes(.@msg$);
Output: 2 5 8 9 12 13 14 17 18 19 20 21 22 23 24 25 30 31 34 35 36 37 38 39 41 42 44 45 47 48
setarray .@text$, "Lemongrass", "Atemo", "Jey", "Lighta", "Nova", "MasterOfMuppets", "Aleos", "Cydh", "Playtester", "Stolao", "Nanakiwurtz", "Akkarin", "Secret";
sortarray(.@text$);
for(.@i = 0; .@i < getarraysize(.@text$); .@i++) {
.@msg$ = .@msg$ + .@text$[.@i] + " ";
}
debugmes(.@msg$);
Output: Akkarin Aleos Atemo Cydh Jey Lemongrass Lighta MasterOfMuppets Nanakiwurtz Nova Playtester Secret Stolao
---------------------------------------
======================================
|2.- Information-retrieving commands.|
======================================

18
npc/test/ci/2796.txt Normal file
View File

@ -0,0 +1,18 @@
- script PullRequest2796 -1,{
OnInit:
setarray .@actual, 31, 44, 14, 18, 24, 42, 39, 47, 30, 17, 36, 45, 34, 21, 38, 41, 23, 25, 13, 20, 8, 5, 22, 9, 2, 12, 19, 35, 48, 37;
sortarray( .@actual );
setarray .@expected, 2, 5, 8, 9, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 30, 31, 34, 35, 36, 37, 38, 39, 41, 42, 44, 45, 47, 48;
for( .@i = 0; .@i < getarraysize( .@expected ); .@i++ ){
AssertEquals( .@expected[.@i], .@actual[.@i], "Index " + .@i );
}
setarray .@actual$, "Lemongrass", "Atemo", "Jey", "Lighta", "Nova", "MasterOfMuppets", "Aleos", "Cydh", "Playtester", "Stolao", "Nanakiwurtz", "Akkarin", "Secret";
sortarray( .@actual$ );
setarray .@expected$, "Akkarin", "Aleos", "Atemo", "Cydh", "Jey", "Lemongrass", "Lighta", "MasterOfMuppets", "Nanakiwurtz", "Nova", "Playtester", "Secret", "Stolao";
for( .@i = 0; .@i < getarraysize( .@expected$ ); .@i++ ){
AssertEquals( .@expected$[.@i], .@actual$[.@i], "Index " + .@i );
}
}

View File

@ -13,6 +13,7 @@
#include <cmath>
#include <csetjmp>
#include <cstdlib> // atoi, strtol, strtoll, exit
#include <stack>
#ifdef PCRE_SUPPORT
#include <pcre.h> // preg_match
@ -27263,6 +27264,178 @@ BUILDIN_FUNC(setdialogpospercent){
return SCRIPT_CMD_SUCCESS;
}
/**
* Partition a string array to be used in quick sort with Hoare's partitioning
* This function does not guarantee that the string array is accessible, so the burden fall to the caller.
* @param st Current script state
* @param sd The player owning the variable, can be nullptr
* @param array_ The string array to be partitioned
* @param start Starting index
* @param end Ending index
*/
int32 partition_array_str(script_state *st, map_session_data *sd, script_data *array_, int32 start, int32 end) {
struct reg_db* ref = reference_getref(array_);
int32 id = reference_getid(array_);
const char* name = reference_getname(array_);
int32 i = start, j = end;
int32 pivotidx = rnd() % (end - start);
const char* pivot = get_val2_str(st, reference_uid(id, start + pivotidx), ref);
while (i < j) {
const char* tmp_i;
int64 uid_i;
while (true) {
uid_i = reference_uid(id, i);
tmp_i = get_val2_str(st, uid_i, ref);
if (strcmp( tmp_i, pivot) >= 0)
break;
// Pop tmp_i
script_removetop(st, -1, 0);
i++;
}
const char* tmp_j;
int64 uid_j;
while (true) {
uid_j = reference_uid(id, j);
tmp_j = get_val2_str(st, uid_j, ref);
if (strcmp( tmp_j, pivot) <= 0)
break;
// Pop tmp_j
script_removetop(st, -1, 0);
j--;
}
// Swap
set_reg_str( st, sd, uid_j, name, tmp_i, ref );
set_reg_str( st, sd, uid_i, name, tmp_j, ref );
// Pop tmp_i and tmp_j
script_removetop(st, -2, 0);
}
// Pop pivot
script_removetop(st, -1, 0);
return j;
}
/**
* Partition an integer array to be used in quick sort with Hoare's partitioning
* This function does not guarantee that the integer array is accessible, so the burden fall to the caller.
* @param st Current script state
* @param sd The player owning the variable, can be nullptr
* @param array_ The integer array to be partitioned
* @param start Starting index
* @param end Ending index
*/
int32 partition_array_num(script_state *st, map_session_data *sd, script_data *array_, int32 start, int32 end) {
struct reg_db* ref = reference_getref(array_);
int32 id = reference_getid(array_);
const char* name = reference_getname(array_);
int32 i = start, j = end;
int32 pivotidx = rnd() % (end - start);
int64 pivot = get_val2_num(st, reference_uid(id, start + pivotidx), ref);
while (i < j) {
int64 tmp_i;
int64 uid_i;
while (true) {
uid_i = reference_uid(id, i);
tmp_i = get_val2_num(st, uid_i, ref);
if (tmp_i >= pivot)
break;
i++;
}
int64 tmp_j;
int64 uid_j;
while (true) {
uid_j = reference_uid(id, j);
tmp_j = get_val2_num(st, uid_j, ref);
if (tmp_j <= pivot)
break;
j--;
}
// Swap
set_reg_num( st, sd, uid_j, name, tmp_i, ref );
set_reg_num( st, sd, uid_i, name, tmp_j, ref );
}
return j;
}
/**
* Sort an array
* sortarray(<array>);
*/
BUILDIN_FUNC(sortarray) {
map_session_data *sd = nullptr;
script_data *array_ = script_getdata(st, 2);
if (!data_isreference(array_)) {
ShowError("buildin_sortarray: Not a variable!\n");
script_reportdata(array_);
st->state = END;
return SCRIPT_CMD_FAILURE;
}
char* name = reference_getname(array_);
reg_db* ref = reference_getref(array_);
if( not_server_variable( name[0] ) && !script_rid2sd( sd ) ){
return SCRIPT_CMD_FAILURE;
}
bool is_string = is_string_variable(name);
std::stack<int32> stack;
int32 size = script_array_highest_key(st, sd, name, ref);
// Push initial indices
stack.push(0);
stack.push(size - 1);
while (!stack.empty()) {
int32 end = stack.top();
stack.pop();
int32 start = stack.top();
stack.pop();
int32 p;
if( is_string ){
p = partition_array_str(st, sd, array_, start, end);
}else{
p = partition_array_num(st, sd, array_, start, end);
}
if(p - 1 > start) {
stack.push(start);
stack.push(p - 1);
}
if(p + 1 < end) {
stack.push(p + 1);
stack.push(end);
}
}
return SCRIPT_CMD_SUCCESS;
}
#include <custom/script.inc>
// declarations that were supposed to be exported from npc_chat.cpp
@ -28027,6 +28200,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(setdialogsize, "ii"),
BUILDIN_DEF(setdialogpos, "ii"),
BUILDIN_DEF(setdialogpospercent, "ii"),
BUILDIN_DEF(sortarray, "r"),
#include <custom/script_def.inc>