Implemented @warp suggestions.
This will display map name suggestions when attempting to @warp to a non-existent map. To enable, turn on 'feature.warp_suggestions' in 'conf/battle/feature.conf'. Signed-off-by: Euphy <euphy.raliel@rathena.org>
This commit is contained in:
parent
222b773c20
commit
f3777cce0e
@ -19,6 +19,10 @@ feature.search_stores: on
|
||||
// Show suggestions when typing an incomplete command?
|
||||
feature.atcommand_suggestions: off
|
||||
|
||||
// Warp suggestions (Note 1)
|
||||
// Show suggestions when attempting to @warp to a non-existent map?
|
||||
feature.warp_suggestions: off
|
||||
|
||||
// Banking (Note 1)
|
||||
// Requires: 2013-07-24aRagexe or later
|
||||
feature.banking: on
|
||||
|
@ -324,3 +324,28 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B)
|
||||
|
||||
return (unsigned int)floor(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Levenshtein distance of two strings.
|
||||
* @author http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C
|
||||
*/
|
||||
int levenshtein(const char *s1, const char *s2) {
|
||||
unsigned int s1len, s2len, x, y, lastdiag, olddiag, i;
|
||||
unsigned int *column;
|
||||
s1len = strlen(s1);
|
||||
s2len = strlen(s2);
|
||||
column = malloc((s1len+1) * sizeof(unsigned int));
|
||||
for (y = 1; y <= s1len; y++)
|
||||
column[y] = y;
|
||||
for (x = 1; x <= s2len; x++) {
|
||||
column[0] = x;
|
||||
for (y = 1, lastdiag = x-1; y <= s1len; y++) {
|
||||
olddiag = column[y];
|
||||
column[y] = min(min(column[y] + 1, column[y-1] + 1), lastdiag + (s1[y-1] == s2[x-1] ? 0 : 1));
|
||||
lastdiag = olddiag;
|
||||
}
|
||||
}
|
||||
i = column[s1len];
|
||||
free(column);
|
||||
return i;
|
||||
}
|
||||
|
@ -31,4 +31,6 @@ extern uint32 MakeDWord(uint16 word0, uint16 word1);
|
||||
|
||||
uint32 date2version(int date);
|
||||
|
||||
int levenshtein(const char *s1, const char *s2);
|
||||
|
||||
#endif /* _UTILS_H_ */
|
||||
|
@ -11,7 +11,7 @@
|
||||
/// Max number of items on @autolootid list
|
||||
#define AUTOLOOTITEM_SIZE 10
|
||||
|
||||
/// The maximum number of atcommand suggestions
|
||||
/// The maximum number of atcommand and @warp suggestions
|
||||
#define MAX_SUGGESTIONS 10
|
||||
|
||||
/// Comment to disable the official walk path
|
||||
|
@ -87,6 +87,7 @@ static char atcmd_player_name[NAME_LENGTH];
|
||||
static AtCommandInfo* get_atcommandinfo_byname(const char *name); // @help
|
||||
static const char* atcommand_checkalias(const char *aliasname); // @help
|
||||
static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand); // @help
|
||||
static void warp_get_suggestions(struct map_session_data* sd, const char *name); // @rura, @warp, @mapmove
|
||||
|
||||
// @commands (script-based)
|
||||
struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
|
||||
@ -370,6 +371,77 @@ ACMD_FUNC(send)
|
||||
#undef GET_VALUE
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves map name suggestions for a given string.
|
||||
* This will first check if any map names contain the given string, and will
|
||||
* print out MAX_SUGGESTIONS results if any maps are found.
|
||||
* Otherwise, suggestions will be calculated through Levenshtein distance,
|
||||
* and up to 5 of the closest matches will be printed.
|
||||
*
|
||||
* @author Euphy
|
||||
*/
|
||||
static void warp_get_suggestions(struct map_session_data* sd, const char *name) {
|
||||
char buffer[512];
|
||||
int i, count = 0;
|
||||
|
||||
if (strlen(name) < 2)
|
||||
return;
|
||||
|
||||
// build the suggestion string
|
||||
strcpy(buffer, msg_txt(sd, 205)); // Maybe you meant:
|
||||
strcat(buffer, "\n");
|
||||
|
||||
// check for maps that contain string
|
||||
for (i = 0; i < MAX_MAP_PER_SERVER; i++) {
|
||||
if (count < MAX_SUGGESTIONS && strstr(map[i].name, name) != NULL) {
|
||||
strcat(buffer, map[i].name);
|
||||
strcat(buffer, " ");
|
||||
if (++count >= MAX_SUGGESTIONS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if no maps found, search by edit distance
|
||||
if (!count) {
|
||||
unsigned int distance[MAX_MAP_PER_SERVER][2];
|
||||
int j, min;
|
||||
|
||||
// calculate Levenshtein distance for all maps
|
||||
for (i = 0; i < MAX_MAP_PER_SERVER; i++) {
|
||||
if (strlen(map[i].name) < 4) // invalid map name?
|
||||
distance[i][0] = INT_MAX;
|
||||
else {
|
||||
distance[i][0] = levenshtein(map[i].name, name);
|
||||
distance[i][1] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// selection sort elements as needed
|
||||
count = min(MAX_SUGGESTIONS, 5); // results past 5 aren't worth showing
|
||||
for (i = 0; i < count; i++) {
|
||||
min = i;
|
||||
for (j = i+1; j < MAX_MAP_PER_SERVER; j++) {
|
||||
if (distance[j][0] < distance[min][0])
|
||||
min = j;
|
||||
}
|
||||
|
||||
// print map name
|
||||
if (distance[min][0] > 4) { // awful results, don't bother
|
||||
if (!i) return;
|
||||
break;
|
||||
}
|
||||
strcat(buffer, map[distance[min][1]].name);
|
||||
strcat(buffer, " ");
|
||||
|
||||
// swap elements
|
||||
swap(distance[i][0], distance[min][0]);
|
||||
swap(distance[i][1], distance[min][1]);
|
||||
}
|
||||
}
|
||||
|
||||
clif_displaymessage(sd->fd, buffer);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* @rura, @warp, @mapmove
|
||||
*------------------------------------------*/
|
||||
@ -397,6 +469,10 @@ ACMD_FUNC(mapmove)
|
||||
|
||||
if (!mapindex) { // m < 0 means on different server! [Kevin]
|
||||
clif_displaymessage(fd, msg_txt(sd,1)); // Map not found.
|
||||
|
||||
if (battle_config.warp_suggestions_enabled)
|
||||
warp_get_suggestions(sd, map_name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -7369,6 +7369,7 @@ static const struct _battle_data {
|
||||
{ "atcommand_enable_npc", &battle_config.atcommand_enable_npc, 0, 0, 100, },
|
||||
{ "path_blown_halt", &battle_config.path_blown_halt, 1, 0, 1, },
|
||||
{ "rental_mount_speed_boost", &battle_config.rental_mount_speed_boost, 25, 0, 100, },
|
||||
{ "feature.warp_suggestions", &battle_config.warp_suggestions_enabled, 0, 0, 1, },
|
||||
};
|
||||
#ifndef STATS_OPT_OUT
|
||||
/**
|
||||
|
@ -532,6 +532,7 @@ extern struct Battle_Config
|
||||
int atcommand_enable_npc;
|
||||
int path_blown_halt;
|
||||
int rental_mount_speed_boost;
|
||||
int warp_suggestions_enabled;
|
||||
} battle_config;
|
||||
|
||||
void do_init_battle(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user