2 Copyright (c) 1993 Richard V. Nash.
3 Copyright (c) 2000 Dan Papasian
4 Copyright (C) Andrew Tridgell 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 const int blitz_rat = 1;
26 const int std_rat = 2;
27 const int wild_rat = 3;
28 const int light_rat = 4;
29 const int bug_rat = 5;
31 int com_more(int p, param_list param)
37 int com_quit(int p, param_list param)
39 struct player *pp = &player_globals.parray[p];
41 /* Examined games are killed on logout */
42 if ((pp->game >= 0) &&
43 ((game_globals.garray[pp->game].status != GAME_EXAMINE) &&
44 (game_globals.garray[pp->game].status != GAME_SETUP))) {
45 pprintf(p, "You can't quit while you are playing a game.\nType 'resign' to resign the game, or you can request an abort with 'abort'.\n");
49 psend_logoutfile(p, MESS_DIR, MESS_LOGOUT);
53 int com_set(int p, param_list param)
59 if (param[1].type == TYPE_NULL)
62 val = param[1].val.string;
63 result = var_set(p, param[0].val.word, val, &which);
68 pprintf(p, "Bad value given for variable %s.\n", param[0].val.word);
71 pprintf(p, "No such variable name %s.\n", param[0].val.word);
74 pprintf(p, "Ambiguous variable name %s.\n", param[0].val.word);
81 int FindPlayer(int p, char* name, int *p1, int *connected)
83 *p1 = player_search(p, name);
86 if (*p1 < 0) { /* player had to be connected and will be
97 static void com_stats_andify(int *numbers, int howmany, char *dest)
103 sprintf(tmp, "%d", numbers[howmany]);
107 else if (howmany == 1)
108 sprintf(tmp, " and ");
116 static void com_stats_rating(char *hdr, struct statistics * stats, char *dest, long now)
122 if (stats->num == 0) return;
124 sprintf(dest, "%-10s%4s %5.1f %4d %4d %4d %4d", hdr,
125 ratstr(stats->rating), current_sterr(stats->sterr, now-stats->ltime),
126 stats->win, stats->los, stats->dra, stats->num);
127 if (stats->whenbest) {
128 sprintf(tmp, " %d", stats->best);
130 strftime(tmp, sizeof(tmp), " (%d-%b-%Y)", localtime((time_t *) & stats->whenbest));
137 int com_stats(int p, param_list param)
142 char line[255], tmp[255], tmp2[255];
143 int numbers[MAX_OBSERVE > MAX_SIMUL ? MAX_OBSERVE : MAX_SIMUL];
145 int showRatingsFlag, showNotesFlag;
146 int showCommentsFlag = 0;
149 showRatingsFlag = showNotesFlag = 1; /* everything on by default */
151 if (param[0].type == TYPE_WORD) {
152 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
154 if (param[1].type == TYPE_WORD) { /* optional second parameter */
155 char *c = param[1].val.word;
156 showRatingsFlag = showNotesFlag = 0;
158 if (*c == 'r') { showRatingsFlag = 1; c++; }
159 else if (*c == 'n') { showNotesFlag = 1; c++; }
160 else if ((*c == 'c') && check_admin(p, ADMIN_ADMIN)) {
161 showCommentsFlag = 1; c++; }
165 return COM_BADPARAMETERS;
174 strcpy(tmp2, player_globals.parray[p1].name);
175 AddPlayerLists(p1, tmp2);
177 sprintf(line, "\nStatistics for %-17s", tmp2);
178 if ((connected) && (player_globals.parray[p1].status == PLAYER_PROMPT)) {
179 sprintf(tmp, "On for: %s", hms_desc(player_ontime(p1)));
181 sprintf(tmp, " Idle: %s\n", hms_desc(player_idle(p1)));
183 if ((t = player_lastdisconnect(p1)))
184 sprintf(tmp, "(Last disconnected %s):\n", strltime(&t));
186 sprintf(tmp, "(Never connected.)\n");
189 pprintf(p, "%s", line);
190 if (((player_globals.parray[p1].simul_info) != NULL) && (player_globals.parray[p1].simul_info->numBoards)) {
191 for (i = 0, t = 0; i < player_globals.parray[p1].simul_info->numBoards; i++) {
192 if ((numbers[t] = player_globals.parray[p1].simul_info->boards[i] + 1) != 0)
195 pprintf(p, "%s is giving a simul: game%s ", player_globals.parray[p1].name, ((t > 1) ? "s" : ""));
196 com_stats_andify(numbers, t, tmp);
198 } else if (player_globals.parray[p1].game >= 0) {
199 g = player_globals.parray[p1].game;
200 if (game_globals.garray[g].status == GAME_EXAMINE) {
201 pprintf(p, "(Examining game %d: %s vs. %s)\n", g + 1,
202 game_globals.garray[g].white_name, game_globals.garray[g].black_name);
203 } else if (game_globals.garray[g].status == GAME_SETUP) {
204 pprintf(p, "(Setting up game %d: %s vs. %s)\n", g + 1,
205 game_globals.garray[g].white_name, game_globals.garray[g].black_name);
207 pprintf(p, "(playing game %d: %s vs. %s)\n", g + 1,
208 player_globals.parray[game_globals.garray[g].white].name, player_globals.parray[game_globals.garray[g].black].name);
209 if (game_globals.garray[g].link >= 0) {
210 pprintf(p, "(partner is playing game %d: %s vs. %s)\n", game_globals.garray[g].link + 1,
211 player_globals.parray[game_globals.garray[game_globals.garray[g].link].white].name,
212 player_globals.parray[game_globals.garray[game_globals.garray[g].link].black].name);
216 if (player_globals.parray[p1].num_observe) {
217 for (i = 0, t = 0; i < player_globals.parray[p1].num_observe; i++) {
218 g = player_globals.parray[p1].observe_list[i];
219 if ((g != -1) && (check_admin(p, ADMIN_ADMIN) || (game_globals.garray[g].private == 0)))
220 numbers[t++] = g + 1;
223 pprintf(p, "%s is observing game%s ", player_globals.parray[p1].name, ((t > 1) ? "s" : ""));
224 com_stats_andify(numbers, t, tmp);
228 if (player_globals.parray[p1].busy != NULL) {
229 pprintf(p, "(%s %s)\n", player_globals.parray[p1].name, player_globals.parray[p1].busy);
231 if (!CheckPFlag(p1, PFLAG_REG)) {
232 pprintf(p, "%s is NOT a registered player.\n\n", player_globals.parray[p1].name);
234 if (showRatingsFlag > 0) {
236 pprintf(p, "\n rating RD win loss draw total best\n");
237 com_stats_rating("Blitz", &player_globals.parray[p1].b_stats, tmp, now);
238 if (*tmp) pprintf(p, tmp);
239 com_stats_rating("Standard", &player_globals.parray[p1].s_stats, tmp, now);
240 if (*tmp) pprintf(p, tmp);
241 com_stats_rating("Lightning", &player_globals.parray[p1].l_stats, tmp, now);
242 if (*tmp) pprintf(p, tmp);
243 com_stats_rating("Wild", &player_globals.parray[p1].w_stats, tmp, now);
244 if (*tmp) pprintf(p, tmp);
245 com_stats_rating("Bughouse", &player_globals.parray[p1].bug_stats, tmp, now);
246 if (*tmp) pprintf(p, tmp);
250 if (player_globals.parray[p1].adminLevel > 0) {
251 pprintf(p, "Admin Level: ");
252 switch (5*(player_globals.parray[p1].adminLevel/5)) {
254 pprintf(p, "Authorized Helper Person\n");
257 pprintf(p, "Administrator\n");
260 pprintf(p, "Help File Librarian/Administrator\n");
263 pprintf(p, "Master Administrator\n");
266 pprintf(p, "Master Help File Librarian/Administrator\n");
269 pprintf(p, "Assistant Super User\n");
272 pprintf(p, "Super User\n");
275 pprintf(p, "%d\n", player_globals.parray[p1].adminLevel);
280 if (check_admin(p, 1) && !CheckPFlag(p, PFLAG_HIDEINFO)) {
281 pprintf(p, "Full Name : %s\n", (player_globals.parray[p1].fullName ? player_globals.parray[p1].fullName : "(none)"));
282 pprintf(p, "Address : %s\n", (player_globals.parray[p1].emailAddress ? player_globals.parray[p1].emailAddress : "(none)"));
283 pprintf(p, "Host : %s\n",
284 dotQuad(connected ? player_globals.parray[p1].thisHost : player_globals.parray[p1].lastHost));
285 if (CheckPFlag(p1, PFLAG_REG))
286 if (player_globals.parray[p1].num_comments)
287 pprintf(p, "Comments : %d\n", player_globals.parray[p1].num_comments);
288 } else if ((p1 == p) && CheckPFlag(p1, PFLAG_REG))
289 pprintf(p, "Address : %s\n", (player_globals.parray[p1].emailAddress ? player_globals.parray[p1].emailAddress : "(none)"));
291 if (player_globals.parray[p1].socket != -1) {
292 pprintf(p, "\nTimeseal: %s\n", net_globals.con[player_globals.parray[p1].socket]->timeseal ? "yes" : "no");
295 if (connected && CheckPFlag(p1, PFLAG_REG)
296 && (p==p1 || (check_admin(p, 1) && !CheckPFlag(p, PFLAG_HIDEINFO)))) {
297 char *timeToStr = ctime((time_t *) &player_globals.parray[p1].timeOfReg);
299 timeToStr[strlen(timeToStr)-1]='\0';
301 onTime = (time(0) - player_globals.parray[p1].logon_time) + player_globals.parray[p1].totalTime;
303 pprintf(p, "Total time on-line: %s\n", hms_desc(onTime) );
304 pprintf(p, "%% of life on-line: %3.1f (since %s)\n",
305 (double)((onTime*100)/(double)(time(0)-player_globals.parray[p1].timeOfReg)),
309 if (player_globals.parray[p1].num_plan && (showNotesFlag > 0)) {
311 for (i = 0; i < player_globals.parray[p1].num_plan; i++)
312 pprintf(p, "%2d: %s\n", i + 1, (player_globals.parray[p1].planLines[i] != NULL) ? player_globals.parray[p1].planLines[i] : "");
314 if (showCommentsFlag) {
316 pprintf(p, "Comments for %s:\n",player_globals.parray[p1].name);
317 player_show_comments(p, p1);
324 int com_password(int p, param_list param)
326 struct player *pp = &player_globals.parray[p];
327 char *oldpassword = param[0].val.word;
328 char *newpassword = param[1].val.word;
331 if (!CheckPFlag(p, PFLAG_REG)) {
332 pprintf(p, "Setting a password is only for registered players.\n");
336 salt[0] = pp->passwd[3];
337 salt[1] = pp->passwd[4];
339 if (strcmp(chessd_crypt(oldpassword,salt), pp->passwd)) {
340 pprintf(p, "Incorrect password, password not changed!\n");
346 salt[0] = 'a' + random() % 26;
347 salt[1] = 'a' + random() % 26;
349 pp->passwd = strdup(chessd_crypt(newpassword,salt));
350 pprintf(p, "Password changed to \"%s\".\n", newpassword);
354 int com_uptime(int p, param_list param)
356 time_t uptime = time(0) - command_globals.startuptime;
357 int days = (uptime / (60*60*24));
358 int hours = ((uptime % (60*60*24)) / (60*60));
359 int mins = (((uptime % (60*60*24)) % (60*60)) / 60);
360 int secs = (((uptime % (60*60*24)) % (60*60)) % 60);
362 pprintf(p, "Server location: %s Server version : %s\n",
363 config_get_tmp("SERVER_HOSTNAME"), VERS_NUM);
364 pprintf(p, "The server has been up since %s.\n", strltime(&command_globals.startuptime));
369 pprintf(p," %d day%s", days, (days == 1) ? "" : "s");
372 pprintf(p," %d hour%s", hours, (hours == 1) ? "" : "s");
375 pprintf(p," %d minute%s", mins, (mins == 1) ? "" : "s");
378 pprintf(p," %d second%s", secs, (secs == 1) ? "" : "s");
382 pprintf(p, "\nPlayer limit: %d\n", config_get_int("MAX_PLAYER", DEFAULT_MAX_PLAYER));
383 pprintf(p, "\nThere are currently %d players, with a high of %d since last restart.\n", player_count(1), command_globals.player_high);
384 pprintf(p, "There are currently %d games, with a high of %d since last restart.\n", game_count(), command_globals.game_high);
385 pprintf(p, "\nCompiled on %s\n", COMP_DATE);
389 int com_date(int p, param_list param)
392 pprintf(p, "Local time - %s\n", strltime(&t));
393 pprintf(p, "Greenwich time - %s\n", strgtime(&t));
397 static const char *inout_string[] = {
401 static int plogins(int p, char *fname)
404 int inout, registered;
406 char loginName[MAX_LOGIN_NAME + 1];
409 fp = fopen_p("%s", "r", fname);
411 pprintf(p, "Sorry, no login information available.\n");
416 if (fscanf(fp, "%d %s %u %d %s\n", &inout, loginName, &t,
417 ®istered, ipstr) != 5) {
418 d_printf( "CHESSD: Error in login info format. %s\n",
424 pprintf(p, "%s: %-17s %-6s", strltime(&thetime), loginName,
425 inout_string[inout]);
426 if (check_admin(p, 1) && !CheckPFlag(p, PFLAG_HIDEINFO)) {
427 pprintf(p, " from %s\n", ipstr);
435 int com_llogons(int p, param_list param)
438 if (!CheckPFlag(p, PFLAG_REG)) {
439 pprintf(p,"Sorry, guest users may not use this command\n");
442 result = plogins(p, STATS_DIR "/" STATS_LOGONS);
446 int com_logons(int p, param_list param)
448 struct player *pp = &player_globals.parray[p];
449 char fname[MAX_FILENAME_SIZE];
451 if (param[0].type == TYPE_WORD) {
453 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
455 sprintf(fname, "%s/player_data/%c/%s.%s",
457 player_globals.parray[p1].login[0],
458 player_globals.parray[p1].login, STATS_LOGONS);
462 sprintf(fname, "%s/player_data/%c/%s.%s",
468 return plogins(p, fname);
471 #define WHO_OPEN 0x01
472 #define WHO_CLOSED 0x02
473 #define WHO_RATED 0x04
474 #define WHO_UNRATED 0x08
475 #define WHO_FREE 0x10
476 #define WHO_PLAYING 0x20
477 #define WHO_REGISTERED 0x40
478 #define WHO_UNREGISTERED 0x80
479 #define WHO_BUGTEAM 0x100
483 void AddPlayerLists (int p1, char *ptmp)
485 if (check_admin(p1, ADMIN_ADMIN) && CheckPFlag(p1, PFLAG_ADMINLIGHT))
487 if (in_list(p1, L_COMPUTER, player_globals.parray[p1].name))
489 if (in_list(p1, L_FM, player_globals.parray[p1].name))
490 strcat(ptmp, "(FM)");
491 if (in_list(p1, L_IM, player_globals.parray[p1].name))
492 strcat(ptmp, "(IM)");
493 if (in_list(p1, L_GM, player_globals.parray[p1].name))
494 strcat(ptmp, "(GM)");
495 if (in_list(p1, L_WGM, player_globals.parray[p1].name))
496 strcat(ptmp, "(WGM)");
497 if (in_list(p1, L_TD, player_globals.parray[p1].name))
498 strcat(ptmp, "(TD)");
499 if (in_list(p1, L_TEAMS, player_globals.parray[p1].name))
501 if (in_list(p1, L_BLIND, player_globals.parray[p1].name))
505 static void who_terse(int p, int num, int *plist, int type)
507 struct player *pp = &player_globals.parray[p];
508 char ptmp[80 + 20]; /* for highlight */
509 multicol *m = multicol_start(player_globals.parray_size);
514 /* altered DAV 3/15/95 */
516 for (i = 0; i < num; i++) {
519 if (type == blitz_rat)
520 rat = player_globals.parray[p1].b_stats.rating;
521 else if (type == wild_rat)
522 rat = player_globals.parray[p1].w_stats.rating;
523 else if (type == std_rat)
524 rat = player_globals.parray[p1].s_stats.rating;
525 else if (type == light_rat)
526 rat = player_globals.parray[p1].l_stats.rating;
527 else if (type == bug_rat)
528 rat = player_globals.parray[p1].bug_stats.rating;
533 sprintf(ptmp, "%-4s", ratstrii(rat, p1));
534 if ((player_globals.parray[p1].simul_info != NULL) && (player_globals.parray[p1].simul_info->numBoards))
536 else if ((player_globals.parray[p1].game >= 0) && ((game_globals.garray[player_globals.parray[p1].game].status == GAME_EXAMINE) || (game_globals.garray[player_globals.parray[p1].game].status == GAME_SETUP)))
538 else if (player_globals.parray[p1].game >= 0)
540 else if (!CheckPFlag(p1, PFLAG_OPEN))
542 else if (player_idle(p1) > 300)
549 psprintf_highlight(p, ptmp + strlen(ptmp), "%s", player_globals.parray[p1].name);
551 strcat(ptmp, player_globals.parray[p1].name);
554 AddPlayerLists(p1, ptmp);
555 multicol_store(m, ptmp);
557 multicol_pprint(m, p, pp->d_width, 2);
559 pprintf(p, "\n %d players displayed (of %d). (*) indicates system administrator.\n", num, player_count(1));
562 static void who_verbose(p, num, plist)
568 char playerLine[255], tmp[255]; /* +8 for highlight */
569 char p1WithAttrs[255];
572 " +---------------------------------------------------------------+\n"
575 " | User Standard Blitz On for Idle |\n"
578 " +---------------------------------------------------------------+\n"
581 for (i = 0; i < num; i++) {
584 strcpy(playerLine, " |");
586 if (player_globals.parray[p1].game >= 0)
587 sprintf(tmp, "%3d", player_globals.parray[p1].game + 1);
590 strcat(playerLine, tmp);
592 if (!CheckPFlag(p1, PFLAG_OPEN))
596 strcat(playerLine, tmp);
598 if (CheckPFlag(p1, PFLAG_REG))
599 if (CheckPFlag(p1, PFLAG_RATED)) {
606 strcat(playerLine, tmp);
608 /* Modified by hersco to include lists in 'who v.' */
609 strcpy (p1WithAttrs, player_globals.parray[p1].name);
610 AddPlayerLists(p1, p1WithAttrs);
611 p1WithAttrs[17] = '\0';
613 /* Modified by DAV 3/15/95 */
616 psprintf_highlight(p, tmp + strlen(tmp), "%-17s", p1WithAttrs);
618 sprintf(tmp, " %-17s", p1WithAttrs);
620 strcat(playerLine, tmp);
622 sprintf(tmp, " %4s %-4s %5s ",
623 ratstrii(player_globals.parray[p1].s_stats.rating, p1),
624 ratstrii(player_globals.parray[p1].b_stats.rating, p1),
625 hms(player_ontime(p1), 0, 0, 0));
626 strcat(playerLine, tmp);
628 if (player_idle(p1) >= 60) {
629 sprintf(tmp, "%5s |\n", hms(player_idle(p1), 0, 0, 0));
631 sprintf(tmp, " |\n");
633 strcat(playerLine, tmp);
634 pprintf(p, "%s", playerLine);
641 " | %3d Players Displayed |\n",
645 " +---------------------------------------------------------------+\n"
649 static void who_winloss(p, num, plist)
655 char playerLine[255], tmp[255]; /* for highlight */
656 char p1WithAttrs[255];
659 "Name Stand win loss draw Blitz win loss draw idle\n"
662 "---------------- ----- ------------- ----- ------------- ----\n"
665 for (i = 0; i < num; i++) {
666 playerLine[0] = '\0';
669 /* Modified by hersco to include lists in 'who n.' */
670 strcpy (p1WithAttrs, player_globals.parray[p1].name);
671 AddPlayerLists(p1, p1WithAttrs);
672 p1WithAttrs[17] = '\0';
675 psprintf_highlight(p, playerLine, "%-17s", p1WithAttrs);
677 sprintf(playerLine, "%-17s", p1WithAttrs);
679 sprintf(tmp, " %4s %4d %4d %4d ",
680 ratstrii(player_globals.parray[p1].s_stats.rating, p1),
681 (int) player_globals.parray[p1].s_stats.win,
682 (int) player_globals.parray[p1].s_stats.los,
683 (int) player_globals.parray[p1].s_stats.dra);
684 strcat(playerLine, tmp);
686 sprintf(tmp, "%4s %4d %4d %4d ",
687 ratstrii(player_globals.parray[p1].b_stats.rating, p1),
688 (int) player_globals.parray[p1].b_stats.win,
689 (int) player_globals.parray[p1].b_stats.los,
690 (int) player_globals.parray[p1].b_stats.dra);
691 strcat(playerLine, tmp);
693 if (player_idle(p1) >= 60) {
694 sprintf(tmp, "%5s\n", hms(player_idle(p1), 0, 0, 0));
698 strcat(playerLine, tmp);
700 pprintf(p, "%s", playerLine);
702 pprintf(p, " %3d Players Displayed.\n", num);
705 static int who_ok(int p, unsigned int sel_bits)
707 struct player *pp = &player_globals.parray[p];
709 if (pp->status != PLAYER_PROMPT)
711 if (sel_bits == WHO_ALL)
713 if (sel_bits & WHO_OPEN)
714 if (!CheckPFlag(p, PFLAG_OPEN) || CheckPFlag(p, PFLAG_TOURNEY))
716 if (sel_bits & WHO_CLOSED)
717 if (CheckPFlag(p, PFLAG_OPEN))
719 if (sel_bits & WHO_RATED)
720 if (!CheckPFlag(p, PFLAG_RATED))
722 if (sel_bits & WHO_UNRATED)
723 if (CheckPFlag(p, PFLAG_RATED))
725 if (sel_bits & WHO_FREE)
728 if (sel_bits & WHO_PLAYING)
731 if (sel_bits & WHO_REGISTERED)
732 if (!CheckPFlag(p, PFLAG_REG))
734 if (sel_bits & WHO_UNREGISTERED)
735 if (CheckPFlag(p, PFLAG_REG))
737 if (sel_bits & WHO_BUGTEAM) {
739 if (p2 < 0 || player_globals.parray[p2].partner != p)
746 static int blitz_cmp(const void *pp1, const void *pp2)
748 register int p1 = *(int *) pp1;
749 register int p2 = *(int *) pp2;
750 if (player_globals.parray[p1].status != PLAYER_PROMPT) {
751 if (player_globals.parray[p2].status != PLAYER_PROMPT)
756 if (player_globals.parray[p2].status != PLAYER_PROMPT)
758 if (player_globals.parray[p1].b_stats.rating > player_globals.parray[p2].b_stats.rating)
760 if (player_globals.parray[p1].b_stats.rating < player_globals.parray[p2].b_stats.rating)
762 if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
764 if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
766 return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
769 static int light_cmp(const void *pp1, const void *pp2)
771 register int p1 = *(int *) pp1;
772 register int p2 = *(int *) pp2;
773 if (player_globals.parray[p1].status != PLAYER_PROMPT) {
774 if (player_globals.parray[p2].status != PLAYER_PROMPT)
779 if (player_globals.parray[p2].status != PLAYER_PROMPT)
781 if (player_globals.parray[p1].l_stats.rating > player_globals.parray[p2].l_stats.rating)
783 if (player_globals.parray[p1].l_stats.rating < player_globals.parray[p2].l_stats.rating)
785 if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
787 if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
789 return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
792 static int bug_cmp(const void *pp1, const void *pp2)
794 register int p1 = *(int *) pp1;
795 register int p2 = *(int *) pp2;
796 if (player_globals.parray[p1].status != PLAYER_PROMPT) {
797 if (player_globals.parray[p2].status != PLAYER_PROMPT)
802 if (player_globals.parray[p2].status != PLAYER_PROMPT)
804 if (player_globals.parray[p1].bug_stats.rating > player_globals.parray[p2].bug_stats.rating)
806 if (player_globals.parray[p1].bug_stats.rating < player_globals.parray[p2].bug_stats.rating)
808 if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
810 if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
812 return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
815 static int stand_cmp(const void *pp1, const void *pp2)
817 register int p1 = *(int *) pp1;
818 register int p2 = *(int *) pp2;
819 if (player_globals.parray[p1].status != PLAYER_PROMPT) {
820 if (player_globals.parray[p2].status != PLAYER_PROMPT)
825 if (player_globals.parray[p2].status != PLAYER_PROMPT)
827 if (player_globals.parray[p1].s_stats.rating > player_globals.parray[p2].s_stats.rating)
829 if (player_globals.parray[p1].s_stats.rating < player_globals.parray[p2].s_stats.rating)
831 if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
833 if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
835 return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
838 static int wild_cmp(const void *pp1, const void *pp2)
840 register int p1 = *(int *) pp1;
841 register int p2 = *(int *) pp2;
842 if (player_globals.parray[p1].status != PLAYER_PROMPT) {
843 if (player_globals.parray[p2].status != PLAYER_PROMPT)
848 if (player_globals.parray[p2].status != PLAYER_PROMPT)
850 if (player_globals.parray[p1].w_stats.rating > player_globals.parray[p2].w_stats.rating)
852 if (player_globals.parray[p1].w_stats.rating < player_globals.parray[p2].w_stats.rating)
854 if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
856 if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
858 return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
861 static int alpha_cmp(const void *pp1, const void *pp2)
863 register int p1 = *(int *) pp1;
864 register int p2 = *(int *) pp2;
865 if (player_globals.parray[p1].status != PLAYER_PROMPT) {
866 if (player_globals.parray[p2].status != PLAYER_PROMPT)
871 if (player_globals.parray[p2].status != PLAYER_PROMPT)
873 return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
876 static void sort_players(int *players,
877 int ((*cmp_func) (const void *, const void *)))
881 for (i = 0; i < player_globals.p_num; i++) {
884 qsort(players, player_globals.p_num, sizeof(int), cmp_func);
887 /* This is the of the most compliclicated commands in terms of parameters */
888 int com_who(int p, param_list param)
890 struct player *pp = &player_globals.parray[p];
892 float stop_perc = 1.0;
893 float start_perc = 0;
894 unsigned int sel_bits = WHO_ALL;
895 int *sortlist, *plist;
896 int ((*cmp_func) (const void *, const void *));
902 int p1, count, num_who;
906 sortlist = malloc(sizeof(int) * player_globals.p_num);
907 plist = malloc(sizeof(int) * player_globals.p_num);
909 total = pp->d_time * 60 + pp->d_inc * 40;
911 sort_type = light_rat;
912 cmp_func = light_cmp;
913 } else if (total >= 900) {
915 cmp_func = stand_cmp;
917 sort_type = blitz_rat;
918 cmp_func = blitz_cmp;
921 if (param[0].type != TYPE_NULL) {
922 len = strlen(param[0].val.string);
923 for (i = 0; i < len; i++) {
924 c = param[0].val.string[i];
926 if (i == 0 || !isdigit(param[0].val.string[i - 1])) {
930 stop_perc = 0.333333;
931 } else if (tmpI == 2) {
932 start_perc = 0.333333;
933 stop_perc = 0.6666667;
934 } else if (tmpI == 3) {
935 start_perc = 0.6666667;
937 } else if ((i == len - 1) || (!isdigit(param[0].val.string[i + 1])))
941 tmpJ = param[0].val.string[i - 1] - '0';
946 start_perc = ((float) tmpJ - 1.0) / (float) tmpI;
947 stop_perc = ((float) tmpJ) / (float) tmpI;
956 if (sel_bits == WHO_ALL)
959 sel_bits |= WHO_OPEN;
962 if (sel_bits == WHO_ALL)
963 sel_bits = WHO_RATED;
965 sel_bits |= WHO_RATED;
968 if (sel_bits == WHO_ALL)
971 sel_bits |= WHO_FREE;
974 if (sel_bits == WHO_ALL)
975 sel_bits = WHO_FREE | WHO_OPEN;
977 sel_bits |= (WHO_FREE | WHO_OPEN);
980 if (sel_bits == WHO_ALL)
981 sel_bits = WHO_REGISTERED;
983 sel_bits |= WHO_REGISTERED;
985 case 'l': /* Sort order */
986 cmp_func = alpha_cmp;
989 case 'A': /* Sort order */
990 cmp_func = alpha_cmp;
992 case 'w': /* Sort order */
994 sort_type = wild_rat;
996 case 's': /* Sort order */
997 cmp_func = stand_cmp;
1000 case 'b': /* Sort order */
1001 cmp_func = blitz_cmp;
1002 sort_type = blitz_rat;
1004 case 'L': /* Sort order */
1005 cmp_func = light_cmp;
1006 sort_type = light_rat;
1008 case 't': /* format */
1011 case 'v': /* format */
1014 case 'n': /* format */
1018 if (sel_bits == WHO_ALL)
1019 sel_bits = WHO_UNREGISTERED;
1021 sel_bits |= WHO_UNREGISTERED;
1024 if (sel_bits == WHO_ALL)
1025 sel_bits = WHO_BUGTEAM;
1027 sel_bits |= WHO_BUGTEAM;
1029 sort_type = bug_rat;
1032 goto bad_parameters;
1037 sort_players(sortlist, cmp_func);
1039 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1040 if (!who_ok(sortlist[p1], sel_bits))
1044 startpoint = floor((float) count * start_perc);
1045 stoppoint = ceil((float) count * stop_perc) - 1;
1048 for (p1 = 0; p1 < player_globals.p_num; p1++) {
1049 if (!who_ok(sortlist[p1], sel_bits))
1051 if ((count >= startpoint) && (count <= stoppoint)) {
1052 plist[num_who++] = sortlist[p1];
1058 pprintf(p, "No logged in players match the flags in your who request.\n");
1064 who_terse(p, num_who, plist, sort_type);
1066 case 1: /* verbose */
1067 who_verbose(p, num_who, plist);
1069 case 2: /* win-loss */
1070 who_winloss(p, num_who, plist);
1073 goto bad_parameters;
1079 return COM_BADPARAMETERS;
1082 int com_open(int p, param_list param)
1085 if ((retval = pcommand(p, "set open")) != COM_OK)
1088 return COM_OK_NOPROMPT;
1091 int com_simopen(int p, param_list param)
1094 if ((retval = pcommand(p, "set simopen")) != COM_OK)
1097 return COM_OK_NOPROMPT;
1100 int com_bell(int p, param_list param)
1103 if ((retval = pcommand(p, "set bell")) != COM_OK)
1106 return COM_OK_NOPROMPT;
1109 int com_flip(int p, param_list param)
1112 if ((retval = pcommand(p, "set flip")) != COM_OK)
1115 return COM_OK_NOPROMPT;
1118 int com_style(int p, param_list param)
1121 if ((retval = pcommand(p, "set style %d", param[0].val.integer)) != COM_OK)
1124 return COM_OK_NOPROMPT;
1127 int com_promote(int p, param_list param)
1130 if ((retval = pcommand(p, "set promote %s", param[0].val.word)) != COM_OK)
1133 return COM_OK_NOPROMPT;
1136 void alias_add(int p, const char *name, const char *value)
1138 struct player *pp = &player_globals.parray[p];
1140 pp->alias_list = (struct alias_type *)realloc(pp->alias_list,
1141 sizeof(struct alias_type) * (pp->numAlias+1));
1142 pp->alias_list[pp->numAlias].comm_name = strdup(name);
1143 pp->alias_list[pp->numAlias].alias = strdup(value);
1148 int com_alias(int p, param_list param)
1150 struct player *pp = &player_globals.parray[p];
1152 const char *noalias[] = {"quit", "unalias", NULL};
1154 if (param[0].type == TYPE_NULL) {
1155 for (al = 0; al < pp->numAlias; al++) {
1156 pprintf(p, "%s -> %s\n",
1157 pp->alias_list[al].comm_name,
1158 pp->alias_list[al].alias);
1163 al = alias_lookup(param[0].val.word, pp->alias_list, pp->numAlias);
1164 if (param[1].type == TYPE_NULL) {
1166 pprintf(p, "You have no alias named '%s'.\n", param[0].val.word);
1168 pprintf(p, "%s -> %s\n",
1169 pp->alias_list[al].comm_name,
1170 pp->alias_list[al].alias);
1176 FREE(pp->alias_list[al].alias);
1177 pp->alias_list[al].alias = strdup(param[1].val.string);
1178 pprintf(p, "Alias %s replaced.\n", param[0].val.string);
1182 if (pp->numAlias >= config_get_int("MAX_ALIASES", DEFAULT_MAX_ALIASES)) {
1183 pprintf(p, "You have your maximum number of aliases.\n");
1187 for (i=0;noalias[i];i++) {
1188 if (strcasecmp(param[0].val.string, noalias[i]) == 0) {
1189 pprintf(p, "Sorry, you can't alias this command.\n");
1194 alias_add(p, param[0].val.word, param[1].val.string);
1196 pprintf(p, "Alias set.\n");
1201 int com_unalias(int p, param_list param)
1203 struct player *pp = &player_globals.parray[p];
1207 al = alias_lookup(param[0].val.word, pp->alias_list, pp->numAlias);
1209 pprintf(p, "You have no alias named '%s'.\n", param[0].val.word);
1213 FREE(pp->alias_list[al].comm_name);
1214 FREE(pp->alias_list[al].alias);
1215 for (i = al; i < pp->numAlias-1; i++) {
1216 pp->alias_list[i].comm_name = pp->alias_list[i+1].comm_name;
1217 pp->alias_list[i].alias = pp->alias_list[i+1].alias;
1220 pp->alias_list = (struct alias_type *)realloc(pp->alias_list,
1221 sizeof(struct alias_type) * pp->numAlias);
1222 pprintf(p,"Alias removed.\n");
1228 int com_handles(int p, param_list param)
1231 char pdir[MAX_FILENAME_SIZE];
1234 sprintf(pdir, "%s/%c", PLAYER_DIR, param[0].val.word[0]);
1235 count = search_directory(pdir, param[0].val.word, buffer, 1000);
1236 pprintf(p, "Found %d names.\n", count);
1238 display_directory(p, buffer, count);
1242 int com_getgi(int p, param_list param)
1245 struct player *pp = &player_globals.parray[p];
1247 if (!in_list(p, L_TD, pp->name)) {
1248 pprintf(p, "Only TD programs are allowed to use this command.\n");
1251 if (((p1 = player_find_bylogin(param[0].val.word)) < 0)
1252 || (!CheckPFlag(p1, PFLAG_REG))) {
1253 /* Darkside suggested not to return anything */
1256 if (!CheckPFlag(p1, PFLAG_REG)) {
1257 pprintf(p, "*getgi %s none none -1 -1 -1 -1 -1*\n", player_globals.parray[p1].name);
1258 } else if (player_globals.parray[p1].game >= 0) {
1259 g = player_globals.parray[p1].game;
1260 if (game_globals.garray[g].status == GAME_ACTIVE) {
1261 pprintf(p, "*getgi %s %s %s %d %d %d %d %d*\n",
1262 player_globals.parray[p1].name,
1263 game_globals.garray[g].white_name,
1264 game_globals.garray[g].black_name,
1266 game_globals.garray[g].wInitTime,
1267 game_globals.garray[g].wIncrement,
1268 game_globals.garray[g].rated,
1269 game_globals.garray[g].private);
1271 pprintf(p, "%s is not playing a game.\n", player_globals.parray[p1].name);
1274 pprintf(p, "%s is not playing a game.\n", player_globals.parray[p1].name);
1279 int com_getpi(int p, param_list param)
1281 struct player *pp = &player_globals.parray[p];
1284 if (!in_list(p, L_TD, pp->name)) {
1285 pprintf(p, "Only TD programs are allowed to use this command.\n");
1288 if (((p1 = player_find_bylogin(param[0].val.word)) < 0)
1289 || (!CheckPFlag(p1, PFLAG_REG))) {
1290 /* Darkside suggested not to return anything */
1293 if (!CheckPFlag(p1, PFLAG_REG)) {
1294 pprintf(p, "*getpi %s -1 -1 -1*\n", player_globals.parray[p1].name);
1296 pprintf(p, "*getpi %s %d %d %d %d*\n", player_globals.parray[p1].name,
1297 player_globals.parray[p1].w_stats.rating,
1298 player_globals.parray[p1].b_stats.rating,
1299 player_globals.parray[p1].s_stats.rating,
1300 player_globals.parray[p1].l_stats.rating);
1305 int com_limits(int p, param_list param)
1307 struct player *pp = &player_globals.parray[p];
1309 pprintf(p, "\nCurrent hardcoded limits:\n");
1310 pprintf(p, " Max number of channels and max capacity: %d\n", MAX_CHANNELS);
1311 pprintf(p, " Max number of channels one can be in: %d\n", MAX_INCHANNELS);
1312 pprintf(p, " Max number of people on the notify list: %d\n", MAX_NOTIFY);
1313 pprintf(p, " Max number of people on the censor list: %d\n", MAX_CENSOR);
1314 pprintf(p, " Max number of people in a simul game: %d\n", MAX_SIMUL);
1315 pprintf(p, " Max number of messages one can receive: %d\n", MAX_MESSAGES);
1316 pprintf(p, " Min number of games to be active: %d\n", PROVISIONAL);
1317 if (!check_admin(p, ADMIN_ADMIN) &&
1318 !titled_player(p,pp->login)) {
1319 pprintf(p, " Size of journal (entries): %d\n", MAX_JOURNAL);
1321 pprintf(p, " Size of journal (entries): 26\n");
1323 pprintf(p, "\nAdmin settable limits:\n");
1324 pprintf(p, " Shout quota gives two shouts per %d seconds.\n", seek_globals.quota_time);
1329 int com_remote(int p, param_list param)
1333 if ((p1 = player_find_part_login(param[0].val.word)) < 0) {
1334 pprintf(p, "%s is not logged in.\n", param[0].val.word);
1337 if (!in_list(p1, L_REMOTE, player_globals.parray[p].login)) {
1338 pprintf(p, "You are not in the remote list for %s\n",
1339 player_globals.parray[p1].login);
1342 pprintf(p, "Command issued as %s\n", player_globals.parray[p1].name);
1343 pprintf(p1, "Remote command [%s] issued by %s\n",
1344 param[1].val.string, player_globals.parray[p].name);
1345 pcommand(p1, "%s\n", param[1].val.string);