Crossfire Server, Branch 1.12  R12190
c_misc.c
Go to the documentation of this file.
00001 /*
00002  * static char *rcsid_c_misc_c =
00003  *   "$Id: c_misc.c 11869 2009-06-14 14:32:45Z akirschbaum $";
00004  */
00005 
00006 /*
00007     CrossFire, A Multiplayer game for X-windows
00008 
00009     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
00010     Copyright (C) 1992 Frank Tore Johansen
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00025 
00026     The authors can be reached via e-mail at crossfire-devel@real-time.com
00027 */
00028 
00035 #include <global.h>
00036 #include <loader.h>
00037 
00038 #undef SS_STATISTICS
00039 #include <shstr.h>
00040 
00041 #ifndef __CEXTRACT__
00042 #include <sproto.h>
00043 #endif
00044 #include <assert.h>
00045 #include <sounds.h>
00046 
00055 void map_info(object *op, char *search) {
00056     mapstruct *m;
00057     char map_path[MAX_BUF];
00058     long sec = seconds();
00059 
00060     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
00061                          i18n_translate(get_language(op), I18N_MSG_CMISC_000),
00062                          i18n_translate(get_language(op), I18N_MSG_CMISC_000),
00063                          (sec%86400)/3600, (sec%3600)/60, sec%60);
00064 
00065     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
00066                   i18n_translate(get_language(op), I18N_MSG_CMISC_001),
00067                   i18n_translate(get_language(op), I18N_MSG_CMISC_002));
00068 
00069     for (m = first_map; m != NULL; m = m->next) {
00070         if (search && strstr(m->path, search) == NULL)
00071             continue;   /* Skip unwanted maps */
00072 
00073         /* Print out the last 18 characters of the map name... */
00074         if (strlen(m->path) <= 18)
00075             strcpy(map_path, m->path);
00076         else
00077             strcpy(map_path, m->path+strlen(m->path)-18);
00078 
00079         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
00080                              i18n_translate(get_language(op), I18N_MSG_CMISC_003),
00081                              i18n_translate(get_language(op), I18N_MSG_CMISC_004),
00082                              map_path, m->players, players_on_map(m, FALSE),
00083                              m->in_memory, m->timeout, m->difficulty,
00084                              (MAP_WHEN_RESET(m)%86400)/3600, (MAP_WHEN_RESET(m)%3600)/60,
00085                              MAP_WHEN_RESET(m)%60);
00086     }
00087 }
00088 
00097 int command_language(object *op, char *params) {
00098     const char *language_str;
00099     int language;
00100     int i;
00101 
00102     if (!op->contr)
00103         return 0;
00104 
00105     language_str = language_names[get_language(op)];
00106 
00107     if (!params || (!strcmp(params, ""))) {
00108         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00109                              i18n_translate(get_language(op), I18N_MSG_CMISC_005),
00110                              i18n_translate(get_language(op), I18N_MSG_CMISC_005),
00111                              language_str);
00112         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00113                              i18n_translate(get_language(op), I18N_MSG_CMISC_051),
00114                              i18n_translate(get_language(op), I18N_MSG_CMISC_051),
00115                              language_str);
00116         for (i = 0; i < NUM_LANGUAGES; i++) {
00117             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00118                                  "[fixed]%s: %s",
00119                                  "%s: %s",
00120                                  language_codes[i],
00121                                  language_names[i]);
00122         }
00123         return 0;
00124     } else {
00125         for (i = 0; i < NUM_LANGUAGES; i++) {
00126             if (!strcmp(language_codes[i], params)) {
00127                 language = i;
00128                 i = NUM_LANGUAGES;
00129             }
00130         }
00131         op->contr->language = language;
00132         language_str = language_names[language];
00133 
00134         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00135                              i18n_translate(language, I18N_MSG_CMISC_006),
00136                              i18n_translate(language, I18N_MSG_CMISC_006),
00137                              language_str);
00138         return 0;
00139     }
00140 }
00141 
00157 int command_body(object *op, char *params) {
00158     int i;
00159 
00160     /* Too hard to try and make a header that lines everything up, so just
00161      * give a description.
00162      */
00163     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_BODY,
00164                   i18n_translate(get_language(op), I18N_MSG_CMISC_007), NULL);
00165 
00166     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_BODY,
00167                   i18n_translate(get_language(op), I18N_MSG_CMISC_008), NULL);
00168 
00169     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_BODY,
00170                   i18n_translate(get_language(op), I18N_MSG_CMISC_009), NULL);
00171 
00172     for (i = 0; i < NUM_BODY_LOCATIONS; i++) {
00173         /* really debugging - normally body_used should not be set to anything
00174          * if body_info isn't also set.
00175          */
00176         if (op->body_info[i] || op->body_used[i]) {
00177             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_BODY,
00178                                  i18n_translate(get_language(op), I18N_MSG_CMISC_010),
00179                                  i18n_translate(get_language(op), I18N_MSG_CMISC_011),
00180                                  body_locations[i].use_name, op->body_info[i], op->body_used[i]);
00181         }
00182     }
00183     if (!QUERY_FLAG(op, FLAG_USE_ARMOUR))
00184         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_BODY,
00185                       i18n_translate(get_language(op), I18N_MSG_CMISC_012), NULL);
00186     if (!QUERY_FLAG(op, FLAG_USE_WEAPON))
00187         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_BODY,
00188                       i18n_translate(get_language(op), I18N_MSG_CMISC_013), NULL);
00189 
00190     return 1;
00191 }
00192 
00203 int command_motd(object *op, char *params) {
00204     display_motd(op);
00205     return 1;
00206 }
00207 
00218 int command_rules(object *op, char *params) {
00219     send_rules(op);
00220     return 1;
00221 }
00222 
00233 int command_news(object *op, char *params) {
00234     send_news(op);
00235     return 1;
00236 }
00237 
00244 void malloc_info(object *op) {
00245     int ob_used = count_used(), ob_free = count_free(), players, nrofmaps;
00246     int nrm = 0, mapmem = 0, anr, anims, sum_alloc = 0, sum_used = 0, i, tlnr, alnr;
00247     treasurelist *tl;
00248     player *pl;
00249     mapstruct *m;
00250     archetype *at;
00251     artifactlist *al;
00252 
00253     for (tl = first_treasurelist, tlnr = 0; tl != NULL; tl = tl->next, tlnr++)
00254         ;
00255     for (al = first_artifactlist, alnr = 0; al != NULL; al = al->next, alnr++)
00256         ;
00257 
00258     for (at = first_archetype, anr = 0, anims = 0; at != NULL; at = at->more == NULL ? at->next : at->more, anr++)
00259         ;
00260 
00261     for (i = 1; i < num_animations; i++)
00262         anims += animations[i].num_animations;
00263 
00264     for (pl = first_player, players = 0; pl != NULL; pl = pl->next, players++)
00265         ;
00266 
00267     for (m = first_map, nrofmaps = 0; m != NULL; m = m->next, nrofmaps++)
00268         if (m->in_memory == MAP_IN_MEMORY) {
00269             mapmem += MAP_WIDTH(m)*MAP_HEIGHT(m)*(sizeof(object *)+sizeof(MapSpace));
00270             nrm++;
00271         }
00272 
00273     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00274                          i18n_translate(get_language(op), I18N_MSG_CMISC_014),
00275                          i18n_translate(get_language(op), I18N_MSG_CMISC_014),
00276                          sizeof(object), sizeof(player), sizeof(mapstruct));
00277 
00278     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00279                          i18n_translate(get_language(op), I18N_MSG_CMISC_015),
00280                          i18n_translate(get_language(op), I18N_MSG_CMISC_016),
00281                          ob_used, i = (ob_used*sizeof(object)));
00282 
00283     sum_used += i;
00284     sum_alloc += i;
00285     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00286                          i18n_translate(get_language(op), I18N_MSG_CMISC_017),
00287                          i18n_translate(get_language(op), I18N_MSG_CMISC_018),
00288                          ob_free, i = (ob_free*sizeof(object)));
00289 
00290     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00291                          i18n_translate(get_language(op), I18N_MSG_CMISC_019),
00292                          i18n_translate(get_language(op), I18N_MSG_CMISC_020),
00293                          count_active(), 0);
00294 
00295     sum_alloc += i;
00296     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00297                          i18n_translate(get_language(op), I18N_MSG_CMISC_021),
00298                          i18n_translate(get_language(op), I18N_MSG_CMISC_022),
00299                          players, i = (players*sizeof(player)));
00300 
00301     sum_alloc += i;
00302     sum_used += i;
00303 
00304     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00305                          i18n_translate(get_language(op), I18N_MSG_CMISC_023),
00306                          i18n_translate(get_language(op), I18N_MSG_CMISC_024),
00307                          nrofmaps, i = (nrofmaps*sizeof(mapstruct)));
00308 
00309     sum_alloc += i;
00310     sum_used += nrm*sizeof(mapstruct);
00311 
00312     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00313                          i18n_translate(get_language(op), I18N_MSG_CMISC_025),
00314                          i18n_translate(get_language(op), I18N_MSG_CMISC_026),
00315                          nrm, mapmem);
00316 
00317     sum_alloc += mapmem;
00318     sum_used += mapmem;
00319 
00320     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00321                          i18n_translate(get_language(op), I18N_MSG_CMISC_027),
00322                          i18n_translate(get_language(op), I18N_MSG_CMISC_028),
00323                          anr, i = (anr*sizeof(archetype)));
00324 
00325     sum_alloc += i;
00326     sum_used += i;
00327 
00328     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00329                          i18n_translate(get_language(op), I18N_MSG_CMISC_029),
00330                          i18n_translate(get_language(op), I18N_MSG_CMISC_030),
00331                          anims, i = (anims*sizeof(Fontindex)));
00332 
00333     sum_alloc += i;
00334     sum_used += i;
00335 
00336     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00337                          i18n_translate(get_language(op), I18N_MSG_CMISC_031),
00338                          i18n_translate(get_language(op), I18N_MSG_CMISC_032),
00339                          tlnr, i = (tlnr*sizeof(treasurelist)));
00340 
00341     sum_alloc += i;
00342     sum_used += i;
00343 
00344     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00345                          i18n_translate(get_language(op), I18N_MSG_CMISC_033),
00346                          i18n_translate(get_language(op), I18N_MSG_CMISC_034),
00347                          nroftreasures, i = (nroftreasures*sizeof(treasure)));
00348 
00349     sum_alloc += i;
00350     sum_used += i;
00351 
00352     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00353                          i18n_translate(get_language(op), I18N_MSG_CMISC_035),
00354                          i18n_translate(get_language(op), I18N_MSG_CMISC_036),
00355                          nrofartifacts, i = (nrofartifacts*sizeof(artifact)));
00356 
00357     sum_alloc += i;
00358     sum_used += i;
00359 
00360     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00361                          i18n_translate(get_language(op), I18N_MSG_CMISC_037),
00362                          i18n_translate(get_language(op), I18N_MSG_CMISC_038),
00363                          nrofallowedstr, i = (nrofallowedstr*sizeof(linked_char)));
00364 
00365     sum_alloc += i;
00366     sum_used += i;
00367 
00368     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00369                          i18n_translate(get_language(op), I18N_MSG_CMISC_039),
00370                          i18n_translate(get_language(op), I18N_MSG_CMISC_040),
00371                          alnr, i = (alnr*sizeof(artifactlist)));
00372 
00373     sum_alloc += i;
00374     sum_used += i;
00375 
00376     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00377                          i18n_translate(get_language(op), I18N_MSG_CMISC_041),
00378                          i18n_translate(get_language(op), I18N_MSG_CMISC_042),
00379                          sum_alloc);
00380 
00381     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MALLOC,
00382                          i18n_translate(get_language(op), I18N_MSG_CMISC_043),
00383                          i18n_translate(get_language(op), I18N_MSG_CMISC_044),
00384                          sum_used);
00385 }
00386 
00398 void current_region_info(object *op) {
00399     /*
00400      * Ok I /suppose/ I should write a seperate function for this, but it isn't
00401      * going to be /that/ slow, and won't get called much
00402      */
00403     region *r = get_region_by_name(get_name_of_region_for_map(op->map));
00404 
00405     /* This should only be possible if regions are not operating on this server. */
00406     if (!r)
00407         return;
00408 
00409     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00410                          i18n_translate(get_language(op), I18N_MSG_CMISC_045),
00411                          i18n_translate(get_language(op), I18N_MSG_CMISC_045),
00412                          get_region_longname(r), get_region_msg(r));
00413 }
00414 
00421 void current_map_info(object *op) {
00422     mapstruct *m = op->map;
00423 
00424     if (!m)
00425         return;
00426 
00427     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00428                          "%s (%s) in %s",
00429                          "%s (%s) in %s",
00430                          m->name, m->path, get_region_longname(get_region_by_map(m)));
00431 
00432     if (QUERY_FLAG(op, FLAG_WIZ)) {
00433         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00434                              i18n_translate(get_language(op), I18N_MSG_CMISC_046),
00435                              i18n_translate(get_language(op), I18N_MSG_CMISC_046),
00436                              m->players, m->difficulty,
00437                              MAP_WIDTH(m), MAP_HEIGHT(m),
00438                              MAP_ENTER_X(m), MAP_ENTER_Y(m),
00439                              MAP_TIMEOUT(m));
00440 
00441     }
00442     if (m->msg)
00443         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE, m->msg, NULL);
00444 }
00445 
00446 #ifdef DEBUG_MALLOC_LEVEL
00447 
00456 int command_malloc_verify(object *op, char *parms) {
00457     extern int malloc_verify(void);
00458 
00459     if (!malloc_verify())
00460         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00461                       i18n_translate(get_language(op), I18N_MSG_CMISC_047), NULL);
00462     else
00463         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00464                       i18n_translate(get_language(op), I18N_MSG_CMISC_048), NULL);
00465 
00466     return 1;
00467 }
00468 #endif
00469 
00482 int command_whereabouts(object *op, char *params) {
00483     region *reg;
00484     player *pl;
00485 
00486     /*
00487      * reset the counter on the region, then use it to store the number of
00488      * players there.
00489      * I don't know how thread-safe this would be, I suspect not very....
00490      */
00491     for (reg = first_region; reg != NULL; reg = reg->next) {
00492         reg->counter = 0;
00493     }
00494     for (pl = first_player; pl != NULL; pl = pl->next)
00495         if (pl->ob->map != NULL)
00496             get_region_by_map(pl->ob->map)->counter++;
00497 
00498     /* we only want to print out by places with a 'longname' field...*/
00499     for (reg = first_region; reg != NULL; reg = reg->next) {
00500         if (reg->longname == NULL && reg->counter > 0) {
00501             if (reg->parent != NULL) {
00502                 reg->parent->counter += reg->counter;
00503                 reg->counter = 0;
00504             } else /*uh oh, we shouldn't be here. */
00505                 LOG(llevError, "command_whereabouts() Region %s with no longname has no parent\n", reg->name);
00506         }
00507     }
00508     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00509                   i18n_translate(get_language(op), I18N_MSG_CMISC_049), NULL);
00510 
00511     for (reg = first_region; reg != NULL; reg = reg->next)
00512         if (reg->counter > 0) {
00513             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00514                                  i18n_translate(get_language(op), I18N_MSG_CMISC_050),
00515                                  i18n_translate(get_language(op), I18N_MSG_CMISC_050),
00516                                  reg->counter, get_region_longname(reg));
00517         }
00518     return 1;
00519 }
00520 
00522 typedef struct {
00523     char namebuf[MAX_BUF];
00524     int login_order;
00525 } chars_names;
00526 
00536 static int name_cmp(const chars_names *c1, const chars_names *c2) {
00537     return strcasecmp(c1->namebuf, c2->namebuf);
00538 }
00539 
00550 void list_players(object *op, region *reg, partylist *party) {
00551     player *pl;
00552     uint16 i;
00553     char *format;
00554     int num_players = 0, num_wiz = 0, num_afk = 0, num_bot = 0;
00555     chars_names *chars = NULL;
00556 
00557     if (op == NULL || QUERY_FLAG(op, FLAG_WIZ))
00558         format = settings.who_wiz_format;
00559     else
00560         format = settings.who_format;
00561 
00562     for (pl = first_player; pl != NULL; pl = pl->next) {
00563         if (pl->ob->map == NULL)
00564             continue;
00565         if (pl->hidden && !QUERY_FLAG(op, FLAG_WIZ))
00566             continue;
00567 
00568         if (reg && !region_is_child_of_region(get_region_by_map(pl->ob->map), reg))
00569             continue;
00570         if (party && pl->party != party)
00571             continue;
00572 
00573         if (pl->state == ST_PLAYING || pl->state == ST_GET_PARTY_PASSWORD) {
00574 
00575             num_players++;
00576             chars = (chars_names *)realloc(chars, num_players*sizeof(chars_names));
00577             if (chars == NULL) {
00578                 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_WHO,
00579                               i18n_translate(get_language(op), I18N_MSG_CMISC_052), NULL);
00580                 return;
00581             }
00582             sprintf(chars[num_players-1].namebuf, "%s", pl->ob->name);
00583             chars[num_players-1].login_order = num_players;
00584 
00585             /* Check for WIZ's & AFK's*/
00586             if (QUERY_FLAG(pl->ob, FLAG_WIZ))
00587                 num_wiz++;
00588 
00589             if (QUERY_FLAG(pl->ob, FLAG_AFK))
00590                 num_afk++;
00591 
00592             if (pl->socket.is_bot)
00593                 num_bot++;
00594         }
00595     }
00596     if (first_player != (player *)NULL) {
00597         if (reg == NULL && party == NULL)
00598             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_WHO,
00599                                  i18n_translate(get_language(op), I18N_MSG_CMISC_053),
00600                                  i18n_translate(get_language(op), I18N_MSG_CMISC_053),
00601                                  num_players, num_wiz, num_afk, num_bot);
00602         else if (party == NULL)
00603             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_WHO,
00604                                  i18n_translate(get_language(op), I18N_MSG_CMISC_054),
00605                                  i18n_translate(get_language(op), I18N_MSG_CMISC_054),
00606                                  reg->longname ? reg->longname : reg->name, num_players, num_wiz, num_afk, num_bot);
00607         else
00608             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_WHO,
00609                                  i18n_translate(get_language(op), I18N_MSG_CMISC_055),
00610                                  i18n_translate(get_language(op), I18N_MSG_CMISC_055),
00611                                  party->partyname, num_players, num_wiz, num_afk, num_bot);
00612     }
00613     qsort(chars, num_players, sizeof(chars_names), (int (*)(const void *, const void *))name_cmp);
00614     for (i = 0; i < num_players; i++)
00615         display_who_entry(op, find_player(chars[i].namebuf), format);
00616     free(chars);
00617 }
00618 
00629 int command_who(object *op, char *params) {
00630     region *reg;
00631 
00632     reg = get_region_from_string(params);
00633     list_players(op, reg, NULL);
00634 
00635     return 1;
00636 }
00637 
00648 void display_who_entry(object *op, player *pl, const char *format) {
00649     char tmpbuf[MAX_BUF];
00650     char outbuf[MAX_BUF], outbuf1[MAX_BUF];
00651     size_t i;
00652 
00653     strcpy(outbuf, "[fixed]");
00654     outbuf1[0] = '\0';
00655 
00656     if (pl == NULL) {
00657         LOG(llevError, "display_who_entry(): I was passed a null player\n");
00658         return;
00659     }
00660     for (i = 0; i <= strlen(format); i++) {
00661         if (format[i] == '%') {
00662             i++;
00663             get_who_escape_code_value(tmpbuf, sizeof(tmpbuf), format[i], pl);
00664             strcat(outbuf, tmpbuf);
00665             strcat(outbuf1, tmpbuf);
00666         } else if (format[i] == '_') {
00667             strcat(outbuf, " "); /* allow '_' to be used in place of spaces */
00668             strcat(outbuf1, " "); /* allow '_' to be used in place of spaces */
00669         } else {
00670             snprintf(tmpbuf, sizeof(tmpbuf), "%c", format[i]);
00671             strcat(outbuf, tmpbuf);
00672             strcat(outbuf1, tmpbuf);
00673         }
00674     }
00675     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_WHO, outbuf, outbuf1);
00676 }
00677 
00709 void get_who_escape_code_value(char *return_val, int size, const char letter, player *pl) {
00710 
00711     switch (letter) {
00712     case 'N':
00713         snprintf(return_val, size, "%s", pl->ob->name);
00714         break;
00715 
00716     case 't':
00717         snprintf(return_val, size, "%s", (pl->own_title[0] == '\0' ? pl->title : pl->own_title));
00718         break;
00719 
00720     case 'T':
00721         if (pl->own_title[0] == '\0')
00722             snprintf(return_val, size, "the ");
00723         else
00724             *return_val = '\0';
00725         break;
00726 
00727     case 'c':
00728         snprintf(return_val, size, "%u", pl->ob->count);
00729         break;
00730 
00731     case 'n':
00732         snprintf(return_val, size, "\n");
00733         break;
00734 
00735     case 'h':
00736         snprintf(return_val, size, "%s", pl->peaceful ? "" : " <Hostile>");
00737         break;
00738 
00739     case 'l':
00740         snprintf(return_val, size, "%d", pl->ob->level);
00741         break;
00742 
00743     case 'd':
00744         snprintf(return_val, size, "%s", (QUERY_FLAG(pl->ob, FLAG_WIZ) ? " <WIZ>" : ""));
00745         break;
00746 
00747     case 'a':
00748         snprintf(return_val, size, "%s", (QUERY_FLAG(pl->ob, FLAG_AFK) ? " <AFK>" : ""));
00749         break;
00750 
00751     case 'b':
00752         snprintf(return_val, size, "%s", (pl->socket.is_bot == 1) ? " <BOT>" : "");
00753         break;
00754 
00755     case 'm':
00756         snprintf(return_val, size, "%s", pl->ob->map->path);
00757         break;
00758 
00759     case 'M':
00760         snprintf(return_val, size, "%s", pl->ob->map->name ? pl->ob->map->name : "Untitled");
00761         break;
00762 
00763     case 'r':
00764         snprintf(return_val, size, "%s", get_name_of_region_for_map(pl->ob->map));
00765             break;
00766 
00767     case 'R':
00768         snprintf(return_val, size, "%s", get_region_longname(get_region_by_map(pl->ob->map)));
00769         break;
00770 
00771     case 'i':
00772         snprintf(return_val, size, "%s", pl->socket.host);
00773         break;
00774 
00775     case '%':
00776         snprintf(return_val, size, "%%");
00777         break;
00778 
00779     case '_':
00780         snprintf(return_val, size, "_");
00781         break;
00782     }
00783 }
00784 
00795 int command_afk(object *op, char *params) {
00796     if QUERY_FLAG(op, FLAG_AFK) {
00797         CLEAR_FLAG(op, FLAG_AFK);
00798         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00799                       i18n_translate(get_language(op), I18N_MSG_CMISC_056), NULL);
00800     } else {
00801         SET_FLAG(op, FLAG_AFK);
00802         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00803                       i18n_translate(get_language(op), I18N_MSG_CMISC_057), NULL);
00804     }
00805     return 1;
00806 }
00807 
00818 int command_malloc(object *op, char *params) {
00819     malloc_info(op);
00820     return 1;
00821 }
00822 
00833 int command_mapinfo(object *op, char *params) {
00834     current_map_info(op);
00835     return 1;
00836 }
00837 
00848 int command_whereami(object *op, char *params) {
00849     current_region_info(op);
00850     return 1;
00851 }
00852 
00861 int command_maps(object *op, char *params) {
00862     map_info(op, params);
00863     return 1;
00864 }
00865 
00876 int command_strings(object *op, char *params) {
00877     char stats[HUGE_BUF];
00878 
00879     ss_dump_statistics(stats, sizeof(stats));
00880     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_LAST,
00881                          "[fixed]%s\n",
00882                          "%s",
00883                          stats);
00884 
00885     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_LAST,
00886                   ss_dump_table(SS_DUMP_TOTALS, stats, sizeof(stats)), NULL);
00887     return 1;
00888 }
00889 
00900 int command_time(object *op, char *params) {
00901     time_info(op);
00902     return 1;
00903 }
00904 
00915 int command_archs(object *op, char *params) {
00916     arch_info(op);
00917     return 1;
00918 }
00919 
00930 int command_hiscore(object *op, char *params) {
00931     display_high_score(op, op == NULL ? 9999 : 50, params);
00932     return 1;
00933 }
00934 
00945 int command_debug(object *op, char *params) {
00946     int i;
00947 
00948     if (params == NULL || !sscanf(params, "%d", &i)) {
00949         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00950                              i18n_translate(get_language(op), I18N_MSG_CMISC_092),
00951                              i18n_translate(get_language(op), I18N_MSG_CMISC_092),
00952                              settings.debug);
00953         return 1;
00954     }
00955     if (op != NULL && !QUERY_FLAG(op, FLAG_WIZ)) {
00956         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00957                       i18n_translate(get_language(op), I18N_MSG_CMISC_093), NULL);
00958         return 1;
00959     }
00960     settings.debug = (enum LogLevel)FABS(i);
00961     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
00962                          i18n_translate(get_language(op), I18N_MSG_CMISC_094),
00963                          i18n_translate(get_language(op), I18N_MSG_CMISC_094),
00964                          i);
00965     return 1;
00966 }
00967 
00968 
00979 int command_dumpbelow(object *op, char *params) {
00980     if (op && op->below) {
00981         StringBuffer *sb;
00982         char *diff;
00983 
00984         sb = stringbuffer_new();
00985         dump_object(op->below, sb);
00986         diff = stringbuffer_finish(sb);
00987         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE, diff, NULL);
00988         free(diff);
00989 
00990         /* Let's push that item on the dm's stack */
00991         dm_stack_push(op->contr, op->below->count);
00992     }
00993     return 0;
00994 }
00995 
01006 int command_wizpass(object *op, char *params) {
01007     int i;
01008 
01009     if (!op)
01010         return 0;
01011 
01012     if (!params)
01013         i = (QUERY_FLAG(op, FLAG_WIZPASS)) ? 0 : 1;
01014     else
01015         i = onoff_value(params);
01016 
01017     if (i) {
01018         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01019                       i18n_translate(get_language(op), I18N_MSG_CMISC_095), NULL);
01020         SET_FLAG(op, FLAG_WIZPASS);
01021     } else {
01022         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01023                       i18n_translate(get_language(op), I18N_MSG_CMISC_096), NULL);
01024         CLEAR_FLAG(op, FLAG_WIZPASS);
01025     }
01026     return 0;
01027 }
01028 
01039 int command_wizcast(object *op, char *params) {
01040     int i;
01041 
01042     if (!op)
01043         return 0;
01044 
01045     if (!params)
01046         i = (QUERY_FLAG(op, FLAG_WIZCAST)) ? 0 : 1;
01047     else
01048         i = onoff_value(params);
01049 
01050     if (i) {
01051         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01052                       i18n_translate(get_language(op), I18N_MSG_CMISC_097), NULL);
01053         SET_FLAG(op, FLAG_WIZCAST);
01054     } else {
01055         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01056                       i18n_translate(get_language(op), I18N_MSG_CMISC_098), NULL);
01057         CLEAR_FLAG(op, FLAG_WIZCAST);
01058     }
01059     return 0;
01060 }
01061 
01072 int command_dumpallobjects(object *op, char *params) {
01073     dump_all_objects();
01074     return 0;
01075 }
01076 
01087 int command_dumpfriendlyobjects(object *op, char *params) {
01088     dump_friendly_objects();
01089     return 0;
01090 }
01091 
01102 int command_dumpallarchetypes(object *op, char *params) {
01103     dump_all_archetypes();
01104     return 0;
01105 }
01106 
01117 int command_ssdumptable(object *op, char *params) {
01118     ss_dump_table(SS_DUMP_TABLE, NULL, 0);
01119     return 0;
01120 }
01121 
01132 int command_dumpmap(object *op, char *params) {
01133     if (op)
01134         dump_map(op->map);
01135     return 0;
01136 }
01137 
01148 int command_dumpallmaps(object *op, char *params) {
01149     dump_all_maps();
01150     return 0;
01151 }
01152 
01163 int command_printlos(object *op, char *params) {
01164     if (op)
01165         print_los(op);
01166     return 0;
01167 }
01168 
01169 
01180 int command_version(object *op, char *params) {
01181     version(op);
01182     return 0;
01183 }
01184 
01185 
01196 int command_output_sync(object *op, char *params) {
01197     int val;
01198 
01199     if (!params) {
01200         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01201                              i18n_translate(get_language(op), I18N_MSG_CMISC_099),
01202                              i18n_translate(get_language(op), I18N_MSG_CMISC_099),
01203                              op->contr->outputs_sync);
01204         return 1;
01205     }
01206     val = atoi(params);
01207     if (val > 0) {
01208         op->contr->outputs_sync = val;
01209         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01210                              i18n_translate(get_language(op), I18N_MSG_CMISC_100),
01211                              i18n_translate(get_language(op), I18N_MSG_CMISC_100),
01212                              op->contr->outputs_sync);
01213     } else
01214         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01215                       i18n_translate(get_language(op), I18N_MSG_CMISC_101), NULL);
01216 
01217     return 1;
01218 }
01219 
01230 int command_output_count(object *op, char *params) {
01231     int val;
01232 
01233     if (!params) {
01234         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01235                              i18n_translate(get_language(op), I18N_MSG_CMISC_102),
01236                              i18n_translate(get_language(op), I18N_MSG_CMISC_102),
01237                              op->contr->outputs_count);
01238         return 1;
01239     }
01240     val = atoi(params);
01241     if (val > 0) {
01242         op->contr->outputs_count = val;
01243         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01244                              i18n_translate(get_language(op), I18N_MSG_CMISC_103),
01245                              i18n_translate(get_language(op), I18N_MSG_CMISC_103),
01246                              op->contr->outputs_count);
01247     } else
01248         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01249                       i18n_translate(get_language(op), I18N_MSG_CMISC_104), NULL);
01250 
01251     return 1;
01252 }
01253 
01264 int command_listen(object *op, char *params) {
01265     int i;
01266 
01267     if (params == NULL || !sscanf(params, "%d", &i)) {
01268         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01269                              i18n_translate(get_language(op), I18N_MSG_CMISC_105),
01270                              i18n_translate(get_language(op), I18N_MSG_CMISC_105),
01271                              op->contr->listening);
01272         return 1;
01273     }
01274     if (i < 0) {
01275         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01276                              i18n_translate(get_language(op), I18N_MSG_CMISC_106), NULL);
01277         return 1;
01278     }
01279     op->contr->listening = (char)i;
01280     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01281                          i18n_translate(get_language(op), I18N_MSG_CMISC_107),
01282                          i18n_translate(get_language(op), I18N_MSG_CMISC_107),
01283                          i);
01284     return 1;
01285 }
01286 
01300 int command_statistics(object *pl, char *params) {
01301     char buf[MAX_BUF];
01302     char buf2[MAX_BUF];
01303 
01304     if (!pl->contr)
01305         return 1;
01306     strcpy(buf, i18n_translate(get_language(pl), I18N_MSG_CMISC_108));
01307     strcpy(buf2, i18n_translate(get_language(pl), I18N_MSG_CMISC_109));
01308     strcat(buf, FMT64);
01309     strcat(buf2, FMT64);
01310     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01311                          buf,
01312                          buf2,
01313                          pl->stats.exp);
01314     strcpy(buf, i18n_translate(get_language(pl), I18N_MSG_CMISC_110));
01315     strcpy(buf2, i18n_translate(get_language(pl), I18N_MSG_CMISC_111));
01316     strcat(buf, FMT64);
01317     strcat(buf2, FMT64);
01318     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01319                          buf,
01320                          buf2,
01321                          level_exp(pl->level+1, pl->expmul));
01322 
01323     draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01324                   i18n_translate(get_language(pl), I18N_MSG_CMISC_112),
01325                   i18n_translate(get_language(pl), I18N_MSG_CMISC_113));
01326 
01327     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01328                          i18n_translate(get_language(pl), I18N_MSG_CMISC_114),
01329                          i18n_translate(get_language(pl), I18N_MSG_CMISC_115),
01330                          pl->contr->orig_stats.Str, pl->stats.Str, 20+pl->arch->clone.stats.Str);
01331     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01332                          i18n_translate(get_language(pl), I18N_MSG_CMISC_116),
01333                          i18n_translate(get_language(pl), I18N_MSG_CMISC_117),
01334                          pl->contr->orig_stats.Dex, pl->stats.Dex, 20+pl->arch->clone.stats.Dex);
01335     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01336                          i18n_translate(get_language(pl), I18N_MSG_CMISC_118),
01337                          i18n_translate(get_language(pl), I18N_MSG_CMISC_119),
01338                          pl->contr->orig_stats.Con, pl->stats.Con, 20+pl->arch->clone.stats.Con);
01339     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01340                          i18n_translate(get_language(pl), I18N_MSG_CMISC_120),
01341                          i18n_translate(get_language(pl), I18N_MSG_CMISC_121),
01342                          pl->contr->orig_stats.Int, pl->stats.Int, 20+pl->arch->clone.stats.Int);
01343     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01344                          i18n_translate(get_language(pl), I18N_MSG_CMISC_122),
01345                          i18n_translate(get_language(pl), I18N_MSG_CMISC_123),
01346                          pl->contr->orig_stats.Wis, pl->stats.Wis, 20+pl->arch->clone.stats.Wis);
01347     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01348                          i18n_translate(get_language(pl), I18N_MSG_CMISC_124),
01349                          i18n_translate(get_language(pl), I18N_MSG_CMISC_125),
01350                          pl->contr->orig_stats.Pow, pl->stats.Pow, 20+pl->arch->clone.stats.Pow);
01351     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01352                          i18n_translate(get_language(pl), I18N_MSG_CMISC_126),
01353                          i18n_translate(get_language(pl), I18N_MSG_CMISC_127),
01354                          pl->contr->orig_stats.Cha, pl->stats.Cha, 20+pl->arch->clone.stats.Cha);
01355     draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_STATISTICS,
01356                          i18n_translate(get_language(pl), I18N_MSG_CMISC_128),
01357                          i18n_translate(get_language(pl), I18N_MSG_CMISC_129),
01358                          pl->contr->peaceful ?  "Peaceful" : "Hostile");
01359 
01360     /* Can't think of anything else to print right now */
01361     return 0;
01362 }
01363 
01374 int command_fix_me(object *op, char *params) {
01375     sum_weight(op);
01376     fix_object(op);
01377     return 1;
01378 }
01379 
01390 int command_players(object *op, char *params) {
01391     char buf[MAX_BUF];
01392     char *t;
01393     DIR *Dir;
01394 
01395     snprintf(buf, sizeof(buf), "%s/%s/", settings.localdir, settings.playerdir);
01396     t = buf+strlen(buf);
01397     if ((Dir = opendir(buf)) != NULL) {
01398         const struct dirent *Entry;
01399 
01400         while ((Entry = readdir(Dir)) != NULL) {
01401             /* skip '.' , '..' */
01402             if (!((Entry->d_name[0] == '.' && Entry->d_name[1] == '\0')
01403                 || (Entry->d_name[0] == '.' && Entry->d_name[1] == '.' && Entry->d_name[2] == '\0'))) {
01404                 struct stat Stat;
01405 
01406                 strcpy(t, Entry->d_name);
01407                 if (stat(buf, &Stat) == 0) {
01408                     /* This was not posix compatible
01409                      * if ((Stat.st_mode & S_IFMT)==S_IFDIR) {
01410                      */
01411                     if (S_ISDIR(Stat.st_mode)) {
01412                         struct tm *tm = localtime(&Stat.st_mtime);
01413 
01414                         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01415                                              i18n_translate(get_language(op), I18N_MSG_CMISC_130),
01416                                              i18n_translate(get_language(op), I18N_MSG_CMISC_131),
01417                                              Entry->d_name,
01418                                              1900+tm->tm_year,
01419                                              1+tm->tm_mon,
01420                                              tm->tm_mday,
01421                                              tm->tm_hour,
01422                                              tm->tm_min,
01423                                              tm->tm_sec);
01424                     }
01425                 }
01426             }
01427         }
01428     }
01429     closedir(Dir);
01430     return 0;
01431 }
01432 
01443 int command_applymode(object *op, char *params) {
01444     unapplymode unapply = op->contr->unapply;
01445     static const char *const types[] = {
01446         "nochoice",
01447         "never",
01448         "always"
01449     };
01450 
01451     if (!params) {
01452         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01453                              i18n_translate(get_language(op), I18N_MSG_CMISC_132),
01454                              i18n_translate(get_language(op), I18N_MSG_CMISC_133),
01455                              types[op->contr->unapply]);
01456         return 1;
01457     }
01458 
01459     if (!strcmp(params, "nochoice"))
01460         op->contr->unapply = unapply_nochoice;
01461     else if (!strcmp(params, "never"))
01462         op->contr->unapply = unapply_never;
01463     else if (!strcmp(params, "always"))
01464         op->contr->unapply = unapply_always;
01465     else {
01466         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01467                              i18n_translate(get_language(op), I18N_MSG_CMISC_134),
01468                              i18n_translate(get_language(op), I18N_MSG_CMISC_134),
01469                              params);
01470         return 0;
01471     }
01472     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01473                          i18n_translate(get_language(op), I18N_MSG_CMISC_135),
01474                          i18n_translate(get_language(op), I18N_MSG_CMISC_135),
01475                          (unapply == op->contr->unapply ? "" : " now"),
01476                          types[op->contr->unapply]);
01477 
01478     return 1;
01479 }
01480 
01491 int command_bowmode(object *op, char *params) {
01492     bowtype_t oldtype = op->contr->bowtype;
01493     static const char *const types[] = {
01494         "normal",
01495         "threewide",
01496         "spreadshot",
01497         "firenorth",
01498         "firene",
01499         "fireeast",
01500         "firese",
01501         "firesouth",
01502         "firesw",
01503         "firewest",
01504         "firenw",
01505         "bestarrow"
01506     };
01507     char buf[MAX_BUF];
01508     int i, found;
01509 
01510     if (!params) {
01511         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01512                              i18n_translate(get_language(op), I18N_MSG_CMISC_136),
01513                              i18n_translate(get_language(op), I18N_MSG_CMISC_136),
01514                              types[op->contr->bowtype]);
01515         return 1;
01516     }
01517 
01518     for (i = 0, found = 0; i <= bow_bestarrow; i++) {
01519         if (!strcmp(params, types[i])) {
01520             found++;
01521             op->contr->bowtype = i;
01522             break;
01523         }
01524     }
01525     if (!found) {
01526         snprintf(buf, sizeof(buf), "bowmode: Unknown options %s, valid options are:", params);
01527         for (i = 0; i <= bow_bestarrow; i++) {
01528             strcat(buf, " ");
01529             strcat(buf, types[i]);
01530             if (i < bow_nw)
01531                 strcat(buf, ",");
01532             else
01533                 strcat(buf, ".");
01534         }
01535         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG, buf, NULL);
01536         return 0;
01537     }
01538     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01539                          i18n_translate(get_language(op), I18N_MSG_CMISC_137),
01540                          i18n_translate(get_language(op), I18N_MSG_CMISC_137),
01541                          (oldtype == op->contr->bowtype ? "" : "now"),
01542                          types[op->contr->bowtype]);
01543     return 1;
01544 }
01545 
01556 int command_petmode(object *op, char *params) {
01557     petmode_t oldtype = op->contr->petmode;
01558     static const char *const types[] = {
01559         "normal",
01560         "sad",
01561         "defend",
01562         "arena"
01563     };
01564 
01565     if (!params) {
01566         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01567                              i18n_translate(get_language(op), I18N_MSG_CMISC_138),
01568                              i18n_translate(get_language(op), I18N_MSG_CMISC_138),
01569                              types[op->contr->petmode]);
01570         return 1;
01571     }
01572 
01573     if (!strcmp(params, "normal"))
01574         op->contr->petmode = pet_normal;
01575     else if (!strcmp(params, "sad"))
01576         op->contr->petmode = pet_sad;
01577     else if (!strcmp(params, "defend"))
01578         op->contr->petmode = pet_defend;
01579     else if (!strcmp(params, "arena"))
01580         op->contr->petmode = pet_arena;
01581     else {
01582         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01583                              i18n_translate(get_language(op), I18N_MSG_CMISC_139),
01584                              i18n_translate(get_language(op), I18N_MSG_CMISC_139),
01585                              params);
01586         return 0;
01587     }
01588     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01589                          i18n_translate(get_language(op), I18N_MSG_CMISC_140),
01590                          i18n_translate(get_language(op), I18N_MSG_CMISC_140),
01591                          (oldtype == op->contr->petmode ? "" : "now"),
01592                          types[op->contr->petmode]);
01593     return 1;
01594 }
01595 
01606 int command_showpets(object *op, char *params) {
01607     objectlink *obl, *next;
01608     int counter = 0, target = 0;
01609     int have_shown_pet = 0;
01610     if (params != NULL)
01611         target = atoi(params);
01612 
01613     for (obl = first_friendly_object; obl != NULL; obl = next) {
01614         object *ob = obl->ob;
01615 
01616         next = obl->next;
01617         if (get_owner(ob) == op) {
01618             if (target == 0) {
01619                 if (counter == 0)
01620                     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01621                                   i18n_translate(get_language(op), I18N_MSG_CMISC_141), NULL);
01622                 draw_ext_info_format(NDI_UNIQUE, 0, op,  MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01623                                      i18n_translate(get_language(op), I18N_MSG_CMISC_142),
01624                                      i18n_translate(get_language(op), I18N_MSG_CMISC_142),
01625                                      ++counter, ob->name, ob->level);
01626             } else if (!have_shown_pet && ++counter == target) {
01627                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01628                                      i18n_translate(get_language(op), I18N_MSG_CMISC_143),
01629                                      i18n_translate(get_language(op), I18N_MSG_CMISC_144),
01630                                      ob->level, ob->name);
01631                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01632                                      i18n_translate(get_language(op), I18N_MSG_CMISC_145),
01633                                      i18n_translate(get_language(op), I18N_MSG_CMISC_146),
01634                                      ob->stats.hp, ob->stats.maxhp, ob->stats.sp, ob->stats.maxsp);
01635 
01636                 /* this is not a nice way to do this, it should be made to be more like the statistics command */
01637                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01638                                      i18n_translate(get_language(op), I18N_MSG_CMISC_147),
01639                                      i18n_translate(get_language(op), I18N_MSG_CMISC_148),
01640                                      ob->stats.Str);
01641                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01642                                      i18n_translate(get_language(op), I18N_MSG_CMISC_149),
01643                                      i18n_translate(get_language(op), I18N_MSG_CMISC_150),
01644                                      ob->stats.Dex);
01645                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01646                                      i18n_translate(get_language(op), I18N_MSG_CMISC_151),
01647                                      i18n_translate(get_language(op), I18N_MSG_CMISC_152),
01648                                      ob->stats.Con);
01649                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01650                                      i18n_translate(get_language(op), I18N_MSG_CMISC_153),
01651                                      i18n_translate(get_language(op), I18N_MSG_CMISC_154),
01652                                      ob->stats.Int);
01653                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01654                                      i18n_translate(get_language(op), I18N_MSG_CMISC_155),
01655                                      i18n_translate(get_language(op), I18N_MSG_CMISC_156),
01656                                      ob->stats.Wis);
01657                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01658                                      i18n_translate(get_language(op), I18N_MSG_CMISC_157),
01659                                      i18n_translate(get_language(op), I18N_MSG_CMISC_158),
01660                                      ob->stats.Cha);
01661                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01662                                      i18n_translate(get_language(op), I18N_MSG_CMISC_159),
01663                                      i18n_translate(get_language(op), I18N_MSG_CMISC_160),
01664                                      ob->stats.Pow);
01665                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01666                                      i18n_translate(get_language(op), I18N_MSG_CMISC_161),
01667                                      i18n_translate(get_language(op), I18N_MSG_CMISC_162),
01668                                      ob->stats.wc, ob->stats.dam, ob->stats.ac);
01669                 have_shown_pet = 1;
01670             }
01671         }
01672     }
01673     if (counter == 0)
01674         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01675                       i18n_translate(get_language(op), I18N_MSG_CMISC_163), NULL);
01676     else if (target != 0 && have_shown_pet == 0)
01677         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
01678                       i18n_translate(get_language(op), I18N_MSG_CMISC_164), NULL);
01679     return 0;
01680 }
01681 
01692 int command_usekeys(object *op, char *params) {
01693     usekeytype oldtype = op->contr->usekeys;
01694     static const char *const types[] = {
01695         "inventory",
01696         "keyrings",
01697         "containers"
01698     };
01699 
01700     if (!params) {
01701         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01702                              i18n_translate(get_language(op), I18N_MSG_CMISC_165),
01703                              i18n_translate(get_language(op), I18N_MSG_CMISC_165),
01704                              types[op->contr->usekeys]);
01705         return 1;
01706     }
01707 
01708     if (!strcmp(params, "inventory"))
01709         op->contr->usekeys = key_inventory;
01710     else if (!strcmp(params, "keyrings"))
01711         op->contr->usekeys = keyrings;
01712     else if (!strcmp(params, "containers"))
01713         op->contr->usekeys = containers;
01714     else {
01715         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01716                              i18n_translate(get_language(op), I18N_MSG_CMISC_166),
01717                              i18n_translate(get_language(op), I18N_MSG_CMISC_166),
01718                              params);
01719         return 0;
01720     }
01721     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
01722                          i18n_translate(get_language(op), I18N_MSG_CMISC_167),
01723                          i18n_translate(get_language(op), I18N_MSG_CMISC_167),
01724                          (oldtype == op->contr->usekeys ? "" : "now"),
01725                          types[op->contr->usekeys]);
01726 
01727     return 1;
01728 }
01729 
01740 int command_resistances(object *op, char *params) {
01741     int i;
01742     if (!op)
01743         return 0;
01744 
01745     for (i = 0; i < NROFATTACKS; i++) {
01746         if (i == ATNR_INTERNAL)
01747             continue;
01748 
01749         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01750                              i18n_translate(get_language(op), I18N_MSG_CMISC_168),
01751                              i18n_translate(get_language(op), I18N_MSG_CMISC_169),
01752                              attacktype_desc[i], op->resist[i]);
01753     }
01754 
01755     /* If dragon player, let's display natural resistances */
01756     if (is_dragon_pl(op)) {
01757         int attack;
01758         object *tmp;
01759 
01760         for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
01761             if ((tmp->type == FORCE) && (strcmp(tmp->arch->name, "dragon_skin_force") == 0)) {
01762                 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01763                               i18n_translate(get_language(op), I18N_MSG_CMISC_170), NULL);
01764 
01765                 for (attack = 0; attack < NROFATTACKS; attack++) {
01766                     if (atnr_is_dragon_enabled(attack)) {
01767                         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01768                                              i18n_translate(get_language(op), I18N_MSG_CMISC_171),
01769                                              i18n_translate(get_language(op), I18N_MSG_CMISC_171),
01770                                              change_resist_msg[attack], tmp->resist[attack]);
01771                     }
01772                 }
01773                 break;
01774             }
01775         }
01776     }
01777 
01778     return 0;
01779 }
01780 
01791 static void help_topics(object *op, int what) {
01792     DIR *dirp;
01793     struct dirent *de;
01794     char filename[MAX_BUF], line[HUGE_BUF];
01795     char suffix[MAX_BUF];
01796     int namelen;
01797     const char *language;
01798 
01799     language = language_codes[get_language(op)];
01800     snprintf(suffix, sizeof(suffix), ".%s", language);
01801 
01802     switch (what) {
01803     case 1:
01804         snprintf(filename, sizeof(filename), "%s/wizhelp", settings.datadir);
01805         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01806                       i18n_translate(get_language(op), I18N_MSG_CMISC_172), NULL);
01807         break;
01808 
01809     case 3:
01810         snprintf(filename, sizeof(filename), "%s/mischelp", settings.datadir);
01811         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01812                       i18n_translate(get_language(op), I18N_MSG_CMISC_173), NULL);
01813         break;
01814 
01815     default:
01816         snprintf(filename, sizeof(filename), "%s/help", settings.datadir);
01817         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01818                       i18n_translate(get_language(op), I18N_MSG_CMISC_174), NULL);
01819         break;
01820     }
01821     if (!(dirp = opendir(filename)))
01822         return;
01823 
01824     line[0] = '\0';
01825     for (de = readdir(dirp); de; de = readdir(dirp)) {
01826         namelen = NAMLEN(de);
01827 
01828         if (namelen <= 2
01829         && *de->d_name == '.'
01830         && (namelen == 1 || de->d_name[1] == '.'))
01831             continue;
01832         if (strstr(de->d_name, suffix)) {
01833             strcat(line, strtok(de->d_name, "."));
01834             strcat(line, " ");
01835         }
01836     }
01837     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01838                   line, line);
01839     closedir(dirp);
01840 }
01841 
01852 static void show_commands(object *op, int what) {
01853     char line[HUGE_BUF];
01854     int i, size, namelen;
01855     command_array_struct *ap;
01856 
01857     switch (what) {
01858     case 1:
01859         ap = WizCommands;
01860         size = WizCommandsSize;
01861         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01862                       i18n_translate(get_language(op), I18N_MSG_CMISC_175), NULL);
01863         break;
01864 
01865     case 2:
01866         ap = CommunicationCommands;
01867         size = CommunicationCommandSize;
01868         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01869                       i18n_translate(get_language(op), I18N_MSG_CMISC_176), NULL);
01870         break;
01871 
01872     default:
01873         ap = Commands;
01874         size = CommandsSize;
01875         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01876                       i18n_translate(get_language(op), I18N_MSG_CMISC_177), NULL);
01877         break;
01878     }
01879 
01880     line[0] = '\0';
01881     for (i = 0; i < size; i++) {
01882         namelen = strlen(ap[i].name);
01883 
01884         strcat(line, ap[i].name);
01885         strcat(line, " ");
01886     }
01887     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, line, line);
01888 }
01889 
01900 int command_help(object *op, char *params) {
01901     struct stat st;
01902     FILE *fp;
01903     char filename[MAX_BUF], line[MAX_BUF];
01904     int len;
01905     const char *language;
01906 
01907     language = language_codes[get_language(op)];
01908 
01909     /*
01910      * Main help page?
01911      */
01912     if (!params) {
01913         snprintf(filename, sizeof(filename), "%s/def_help", settings.datadir);
01914         if ((fp = fopen(filename, "r")) == NULL) {
01915             LOG(llevError, "Cannot open help file %s: %s\n", filename, strerror_local(errno, line, sizeof(line)));
01916             return 0;
01917         }
01918         while (fgets(line, MAX_BUF, fp)) {
01919             line[MAX_BUF-1] = '\0';
01920             len = strlen(line)-1;
01921             if (line[len] == '\n')
01922                 line[len] = '\0';
01923             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, line, NULL);
01924         }
01925         fclose(fp);
01926         return 0;
01927     }
01928 
01929     /*
01930      * Topics list
01931      */
01932     if (!strcmp(params, "topics")) {
01933         help_topics(op, 3);
01934         help_topics(op, 0);
01935         if (QUERY_FLAG(op, FLAG_WIZ))
01936             help_topics(op, 1);
01937         return 0;
01938     }
01939 
01940     /*
01941      * Commands list
01942      */
01943     if (!strcmp(params, "commands")) {
01944         show_commands(op, 0);
01945         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "\n", NULL);
01946         show_commands(op, 2); /* show comm commands */
01947         if (QUERY_FLAG(op, FLAG_WIZ)) {
01948             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "\n", NULL);
01949             show_commands(op, 1);
01950         }
01951         return 0;
01952     }
01953 
01954     /*
01955      * User wants info about command
01956      */
01957     if (strchr(params, '.') || strchr(params, ' ') || strchr(params, '/')) {
01958         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01959                              i18n_translate(get_language(op), I18N_MSG_CMISC_178),
01960                              i18n_translate(get_language(op), I18N_MSG_CMISC_178),
01961                              params);
01962         return 0;
01963     }
01964 
01965     snprintf(filename, sizeof(filename), "%s/mischelp/%s.%s", settings.datadir, params, language);
01966     if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
01967         if (op) {
01968             snprintf(filename, sizeof(filename), "%s/help/%s.%s", settings.datadir, params, language);
01969             if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
01970                 if (QUERY_FLAG(op, FLAG_WIZ)) {
01971                     snprintf(filename, sizeof(filename), "%s/wizhelp/%s.%s", settings.datadir, params, language);
01972                     if (stat(filename, &st) || !S_ISREG(st.st_mode))
01973                         goto nohelp;
01974                 } else
01975                     goto nohelp;
01976             }
01977         }
01978     }
01979 
01980     /*
01981      * Found that. Just cat it to screen.
01982      */
01983     if ((fp = fopen(filename, "r")) == NULL) {
01984         LOG(llevError, "Cannot open help file %s: %s\n", filename, strerror_local(errno, line, sizeof(line)));
01985         return 0;
01986     }
01987 
01988     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
01989                          i18n_translate(get_language(op), I18N_MSG_CMISC_179),
01990                          i18n_translate(get_language(op), I18N_MSG_CMISC_179),
01991                          params);
01992 
01993     while (fgets(line, MAX_BUF, fp)) {
01994         line[MAX_BUF-1] = '\0';
01995         len = strlen(line)-1;
01996         if (line[len] == '\n')
01997             line[len] = '\0';
01998         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, line, NULL);
01999     }
02000     fclose(fp);
02001     return 0;
02002 
02003     /*
02004      * No_help -escape
02005      */
02006 
02007 nohelp:
02008     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO,
02009                          i18n_translate(get_language(op), I18N_MSG_CMISC_180),
02010                          i18n_translate(get_language(op), I18N_MSG_CMISC_180),
02011                          params);
02012 
02013     return 0;
02014 }
02015 
02026 int onoff_value(const char *line) {
02027     int i;
02028 
02029     if (sscanf(line, "%d", &i))
02030         return (i != 0);
02031 
02032     switch (line[0]) {
02033     case 'o':
02034         switch (line[1]) {
02035         case 'n':
02036             return 1;  /* on */
02037         default:
02038             return 0;  /* o[ff] */
02039         }
02040 
02041     case 'y':   /* y[es] */
02042     case 'k':   /* k[ylla] */
02043     case 's':
02044     case 'd':
02045         return 1;
02046 
02047     case 'n':   /* n[o] */
02048     case 'e':   /* e[i] */
02049     case 'u':
02050     default:
02051         return 0;
02052     }
02053 }
02054 
02065 int command_quit(object *op, char *params) {
02066     send_query(&op->contr->socket, CS_QUERY_SINGLECHAR,
02067                i18n_translate(get_language(op), I18N_MSG_CMISC_181));
02068 
02069     op->contr->state = ST_CONFIRM_QUIT;
02070     return 1;
02071 }
02072 
02086 int command_explore(object *op, char *params) {
02087     if (settings.explore_mode == FALSE) {
02088         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02089                       i18n_translate(get_language(op), I18N_MSG_CMISC_182), NULL);
02090         return 1;
02091     }
02092     /*
02093      * I guess this is the best way to see if we are solo or not.  Actually,
02094      * are there any cases when first_player->next==NULL and we are not solo?
02095      */
02096     if ((first_player != op->contr) || (first_player->next != NULL)) {
02097         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02098                       i18n_translate(get_language(op), I18N_MSG_CMISC_183), NULL);
02099     } else if (op->contr->explore)
02100         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02101                       i18n_translate(get_language(op), I18N_MSG_CMISC_184), NULL);
02102     else {
02103         op->contr->explore = 1;
02104         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02105                       i18n_translate(get_language(op), I18N_MSG_CMISC_185), NULL);
02106     }
02107     return 1;
02108 }
02109 
02120 int command_sound(object *op, char *params) {
02121     if (!(op->contr->socket.sound&SND_MUTE)) {
02122         op->contr->socket.sound = op->contr->socket.sound|SND_MUTE;
02123         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02124                       i18n_translate(get_language(op), I18N_MSG_CMISC_186), NULL);
02125     } else {
02126         op->contr->socket.sound = op->contr->socket.sound&~SND_MUTE;
02127         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02128                       i18n_translate(get_language(op), I18N_MSG_CMISC_187), NULL);
02129     }
02130     return 1;
02131 }
02132 
02142 void receive_player_name(object *op) {
02143     if (!check_name(op->contr, op->contr->write_buf+1)) {
02144         get_name(op);
02145         return;
02146     }
02147     FREE_AND_COPY(op->name, op->contr->write_buf+1);
02148     FREE_AND_COPY(op->name_pl, op->contr->write_buf+1);
02149     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE, op->contr->write_buf, NULL);
02150     op->contr->name_changed = 1;
02151     get_password(op);
02152 }
02153 
02160 void receive_player_password(object *op) {
02161     unsigned int pwd_len = strlen(op->contr->write_buf);
02162 
02163     if (pwd_len <= 1 || pwd_len > 17) {
02164         if (op->contr->state == ST_CHANGE_PASSWORD_OLD
02165         || op->contr->state == ST_CHANGE_PASSWORD_NEW
02166         || op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
02167             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02168                           i18n_translate(get_language(op), I18N_MSG_CMISC_188), NULL);
02169             op->contr->state = ST_PLAYING;
02170         } else
02171             get_name(op);
02172         return;
02173     }
02174     /* To hide the password better */
02175     /* With currently clients, not sure if this is really the case - MSW */
02176     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE, "          ", NULL);
02177 
02178     if (checkbanned(op->name, op->contr->socket.host)) {
02179         LOG(llevInfo, "Banned player tried to add: [%s@%s]\n", op->name, op->contr->socket.host);
02180         draw_ext_info(NDI_UNIQUE|NDI_RED, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02181                       i18n_translate(get_language(op), I18N_MSG_CMISC_189), NULL);
02182         get_name(op);
02183         return;
02184     }
02185 
02186     if (op->contr->state == ST_CONFIRM_PASSWORD) {
02187         if (!check_password(op->contr->write_buf+1, op->contr->password)) {
02188             draw_ext_info(NDI_UNIQUE, 0, op,  MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02189                           i18n_translate(get_language(op), I18N_MSG_CMISC_190), NULL);
02190             get_name(op);
02191             return;
02192         }
02193         LOG(llevInfo, "LOGIN: New player named %s from ip %s\n", op->name, op->contr->socket.host);
02194         display_motd(op);
02195         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02196                       i18n_translate(get_language(op), I18N_MSG_CMISC_191), NULL);
02197         roll_again(op);
02198         op->contr->state = ST_ROLL_STAT;
02199         return;
02200     }
02201 
02202     if (op->contr->state == ST_CHANGE_PASSWORD_OLD) {
02203         if (!check_password(op->contr->write_buf+1, op->contr->password)) {
02204             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02205                           i18n_translate(get_language(op), I18N_MSG_CMISC_192), NULL);
02206             op->contr->state = ST_PLAYING;
02207         } else {
02208             send_query(&op->contr->socket, CS_QUERY_HIDEINPUT, i18n_translate(get_language(op), I18N_MSG_CMISC_193));
02209             op->contr->state = ST_CHANGE_PASSWORD_NEW;
02210         }
02211         return;
02212     }
02213 
02214     if (op->contr->state == ST_CHANGE_PASSWORD_NEW) {
02215         strcpy(op->contr->new_password, crypt_string(op->contr->write_buf+1, NULL));
02216         send_query(&op->contr->socket, CS_QUERY_HIDEINPUT, i18n_translate(get_language(op), I18N_MSG_CMISC_194));
02217         op->contr->state = ST_CHANGE_PASSWORD_CONFIRM;
02218         return;
02219     }
02220 
02221     if (op->contr->state == ST_CHANGE_PASSWORD_CONFIRM) {
02222         if (strcmp(crypt_string(op->contr->write_buf+1, op->contr->new_password), op->contr->new_password)) {
02223             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02224                           i18n_translate(get_language(op), I18N_MSG_CMISC_195), NULL);
02225         } else {
02226             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02227                           i18n_translate(get_language(op), I18N_MSG_CMISC_196), NULL);
02228             strncpy(op->contr->password, op->contr->new_password, 13);
02229         }
02230         op->contr->state = ST_PLAYING;
02231         return;
02232     }
02233 
02234     strcpy(op->contr->password, crypt_string(op->contr->write_buf+1, NULL));
02235     op->contr->state = ST_ROLL_STAT;
02236     check_login(op);
02237     return;
02238 }
02239 
02250 int command_title(object *op, char *params) {
02251     char buf[MAX_BUF];
02252 
02253     if (settings.set_title == FALSE) {
02254         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02255                       i18n_translate(get_language(op), I18N_MSG_CMISC_197), NULL);
02256         return 1;
02257     }
02258 
02259     /* dragon players cannot change titles */
02260     if (is_dragon_pl(op)) {
02261         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02262                       i18n_translate(get_language(op), I18N_MSG_CMISC_198), NULL);
02263         return 1;
02264     }
02265 
02266     if (params == NULL) {
02267         if (op->contr->own_title[0] == '\0')
02268             snprintf(buf, sizeof(buf), i18n_translate(get_language(op), I18N_MSG_CMISC_199), op->contr->title);
02269         else
02270             snprintf(buf, sizeof(buf), i18n_translate(get_language(op), I18N_MSG_CMISC_200), op->contr->own_title);
02271         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG, buf, NULL);
02272         return 1;
02273     }
02274     if (strcmp(params, "clear") == 0 || strcmp(params, "default") == 0) {
02275         if (op->contr->own_title[0] == '\0')
02276             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02277                           i18n_translate(get_language(op), I18N_MSG_CMISC_201), NULL);
02278         else
02279             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02280                           i18n_translate(get_language(op), I18N_MSG_CMISC_202), NULL);
02281         op->contr->own_title[0] = '\0';
02282         return 1;
02283     }
02284 
02285     if ((int)strlen(params) >= MAX_NAME) {
02286         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02287                       i18n_translate(get_language(op), I18N_MSG_CMISC_203), NULL);
02288         return 1;
02289     }
02290     strcpy(op->contr->own_title, params);
02291     replace_unprintable_chars(op->contr->own_title);
02292     return 1;
02293 }
02294 
02305 int command_save(object *op, char *params) {
02306     if (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL)&P_NO_CLERIC) {
02307         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02308                       i18n_translate(get_language(op), I18N_MSG_CMISC_204), NULL);
02309     } else if (!op->stats.exp) {
02310         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02311                       i18n_translate(get_language(op), I18N_MSG_CMISC_205), NULL);
02312     } else {
02313         if (save_player(op, 1))
02314             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02315                           i18n_translate(get_language(op), I18N_MSG_CMISC_206), NULL);
02316         else
02317             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02318                           i18n_translate(get_language(op), I18N_MSG_CMISC_207), NULL);
02319     }
02320     return 1;
02321 }
02322 
02333 int command_peaceful(object *op, char *params) {
02334     if ((op->contr->peaceful = !op->contr->peaceful))
02335         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02336                       i18n_translate(get_language(op), I18N_MSG_CMISC_208), NULL);
02337     else
02338         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02339                       i18n_translate(get_language(op), I18N_MSG_CMISC_209), NULL);
02340     return 1;
02341 }
02342 
02353 int command_wimpy(object *op, char *params) {
02354     int i;
02355 
02356     if (params == NULL || !sscanf(params, "%d", &i)) {
02357         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02358                              i18n_translate(get_language(op), I18N_MSG_CMISC_210),
02359                              i18n_translate(get_language(op), I18N_MSG_CMISC_210),
02360                              op->run_away);
02361         return 1;
02362     }
02363 
02364     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_CONFIG,
02365                          i18n_translate(get_language(op), I18N_MSG_CMISC_211),
02366                          i18n_translate(get_language(op), I18N_MSG_CMISC_211),
02367                          i);
02368     op->run_away = i;
02369     return 1;
02370 }
02371 
02382 int command_brace(object *op, char *params) {
02383     if (!params)
02384         op->contr->braced = !op->contr->braced;
02385     else
02386         op->contr->braced = onoff_value(params);
02387 
02388     if (op->contr->braced)
02389         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02390                       i18n_translate(get_language(op), I18N_MSG_CMISC_212), NULL);
02391     else
02392         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02393                       i18n_translate(get_language(op), I18N_MSG_CMISC_213), NULL);
02394 
02395     fix_object(op);
02396 
02397     return 0;
02398 }
02399 
02410 int command_kill_pets(object *op, char *params) {
02411     objectlink *obl, *next;
02412     int counter = 0, removecount = 0;
02413 
02414     if (params == NULL) {
02415         terminate_all_pets(op);
02416         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02417                       i18n_translate(get_language(op), I18N_MSG_CMISC_214), NULL);
02418     } else {
02419         int target = atoi(params);
02420         for (obl = first_friendly_object; obl != NULL; obl = next) {
02421             object *ob = obl->ob;
02422             next = obl->next;
02423             if (get_owner(ob) == op)
02424                 if (++counter == target || (target == 0 && !strcasecmp(ob->name, params)))  {
02425                     if (!QUERY_FLAG(ob, FLAG_REMOVED))
02426                         remove_ob(ob);
02427                     remove_friendly_object(ob);
02428                     free_object(ob);
02429                     removecount++;
02430                 }
02431         }
02432         if (removecount != 0)
02433             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02434                                  i18n_translate(get_language(op), I18N_MSG_CMISC_215),
02435                                  i18n_translate(get_language(op), I18N_MSG_CMISC_215),
02436                                  removecount);
02437         else
02438             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_SUBTYPE_NONE,
02439                           i18n_translate(get_language(op), I18N_MSG_CMISC_216), NULL);
02440     }
02441     return 0;
02442 }
02443 
02454 int command_passwd(object *pl, char *params) {
02455     send_query(&pl->contr->socket, CS_QUERY_HIDEINPUT, i18n_translate(get_language(pl), I18N_MSG_CMISC_217));
02456 
02457     pl->contr->state = ST_CHANGE_PASSWORD_OLD;
02458     return 1;
02459 }
02460 
02472 int do_harvest(object *pl, int dir, object *skill) {
02473     sint16 x, y;
02474     int count = 0, proba; /* Probability to get the item, 100 based. */
02475     int level, exp;
02476     object *found[10]; /* Found items that can be harvested. */
02477     mapstruct *map;
02478     object *item, *inv;
02479     sstring trace, ttool, tspeed, race, tool, slevel, sexp;
02480     float speed;
02481 
02482     x = pl->x+freearr_x[dir];
02483     y = pl->y+freearr_y[dir];
02484     map = pl->map;
02485 
02486     if (!pl->type == PLAYER)
02487         return 0;
02488 
02489     if (!map)
02490         return 0;
02491 
02492     if (get_map_flags(map, &map, x, y, &x, &y)&P_OUT_OF_MAP) {
02493         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You can't %s anything here.", NULL, skill->slaying);
02494         return 0;
02495     }
02496 
02497     if (!pl->chosen_skill || pl->chosen_skill->skill != skill->skill)
02498         return 0;
02499 
02500     trace = get_ob_key_value(pl->chosen_skill, "harvest_race");
02501     ttool = get_ob_key_value(pl->chosen_skill, "harvest_tool");
02502     tspeed = get_ob_key_value(pl->chosen_skill, "harvest_speed");
02503     if (!trace || strcmp(trace, "") == 0 || !ttool || strcmp(ttool, "") == 0 || !tspeed || strcmp(tspeed, "") == 0) {
02504         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You can't %s anything here.", NULL, skill->slaying);
02505         LOG(llevError, "do_harvest: tool %s without harvest_[race|tool|speed]\n", pl->chosen_skill->name);
02506         return 0;
02507     }
02508 
02509     item = GET_MAP_OB(map, x, y);
02510     while (item && count < 10) {
02511         for (inv = item->inv; inv; inv = inv->below) {
02512             if (get_ob_key_value(inv, "harvestable") == NULL)
02513                 continue;
02514             race = get_ob_key_value(inv, "harvest_race");
02515             tool = get_ob_key_value(inv, "harvest_tool");
02516             slevel = get_ob_key_value(inv, "harvest_level");
02517             sexp = get_ob_key_value(inv, "harvest_exp");
02518             if (race && (!slevel || !sexp)) {
02519                 LOG(llevError, "do_harvest: item %s without harvest_[level|exp]\n", inv->name);
02520                 continue;
02521             }
02522             if (race == trace && (!tool || tool == ttool))
02523                 found[count++] = inv;
02524         }
02525         item = item->above;
02526     }
02527     if (count == 0) {
02528         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You can't %s anything here.", NULL, skill->slaying);
02529         return 0;
02530     }
02531 
02532     inv = found[rndm(0, count-1)];
02533     assert(inv);
02534 
02535     slevel = get_ob_key_value(inv, "harvest_level");
02536     sexp = get_ob_key_value(inv, "harvest_exp");
02537     level = atoi(slevel);
02538     exp = atoi(sexp);
02539 
02540     speed = atof(tspeed);
02541     if (speed < 0)
02542         speed = -speed*pl->speed;
02543     pl->speed_left -= speed;
02544 
02545 
02546     /* Now we found something to harvest, randomly try to get it. */
02547     if (level > skill->level+10) {
02548         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You fail to %s anything.", NULL, skill->slaying);
02549         return 0;
02550     }
02551 
02552     if (level >= skill->level)
02553         /* Up to 10 more levels, 1 to 11 percent probability. */
02554         proba = 10+skill->level-level;
02555     else if (skill->level <= level+10)
02556         proba = 10+(skill->level-level)*2;
02557     else
02558         proba = 30;
02559 
02560     if (proba <= random_roll(0, 100, pl, 1)) {
02561         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You fail to %s anything.", NULL, skill->slaying);
02562         return 0;
02563     }
02564 
02565     /* Ok, got it. */
02566     item = get_object();
02567     copy_object_with_inv(inv, item);
02568     set_ob_key_value(item, "harvestable", NULL, 0);
02569     if (QUERY_FLAG(item, FLAG_MONSTER)) {
02570         int spot = find_free_spot(item, pl->map, pl->x, pl->y, 0, SIZEOFFREE);
02571         if (spot == -1) {
02572             /* Better luck next time...*/
02573             remove_ob(item);
02574             draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You fail to %s anything.", NULL, skill->slaying);
02575             return 0;
02576         }
02577         item->x = pl->x+freearr_x[spot];
02578         item->y = pl->y+freearr_y[spot];
02579         insert_ob_in_map(item, pl->map, NULL, 0);
02580         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s a %s!", NULL, skill->slaying, item->name);
02581     } else {
02582         item = insert_ob_in_ob(item, pl);
02583         draw_ext_info_format(NDI_WHITE, 0, pl, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, "You %s some %s", NULL, skill->slaying, item->name);
02584     }
02585 
02586     /* Get exp */
02587     change_exp(pl, exp, skill->name, SK_EXP_ADD_SKILL);
02588 
02589     return 0;
02590 }