Fix bug in setting up w3 and w4 games
[capablanca.git] / lasker-2.2.3 / src / comproc.c
1 /*
2    Copyright (c) 1993 Richard V. Nash.
3    Copyright (c) 2000 Dan Papasian
4    Copyright (C) Andrew Tridgell 2002
5    
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.
10    
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.
15    
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.
19 */
20
21
22 #include "includes.h"
23
24 const int none = 0;
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;
30
31 int com_more(int p, param_list param)
32 {
33         pmore_text(p);
34         return COM_OK;
35 }
36
37 int com_quit(int p, param_list param)
38 {
39         struct player *pp = &player_globals.parray[p];
40
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");
46                 return COM_OK;
47         }
48
49         psend_logoutfile(p, MESS_DIR, MESS_LOGOUT);
50         return COM_LOGOUT;
51 }
52
53 int com_set(int p, param_list param)
54 {
55   int result;
56   int which;
57   char *val;
58
59   if (param[1].type == TYPE_NULL)
60     val = NULL;
61   else
62     val = param[1].val.string;
63   result = var_set(p, param[0].val.word, val, &which);
64   switch (result) {
65   case VAR_OK:
66     break;
67   case VAR_BADVAL:
68     pprintf(p, "Bad value given for variable %s.\n", param[0].val.word);
69     break;
70   case VAR_NOSUCH:
71     pprintf(p, "No such variable name %s.\n", param[0].val.word);
72     break;
73   case VAR_AMBIGUOUS:
74     pprintf(p, "Ambiguous variable name %s.\n", param[0].val.word);
75     break;
76   }
77   /* player_save(p); */
78   return COM_OK;
79 }
80
81 int FindPlayer(int p, char* name, int *p1, int *connected)
82 {
83   *p1 = player_search(p, name);
84   if (*p1 == 0)
85     return 0;
86   if (*p1 < 0) {                /* player had to be connected and will be
87                            removed later */
88     *connected = 0;
89     *p1 = (-*p1) - 1;
90   } else {
91     *connected = 1;
92     *p1 = *p1 - 1;
93   }
94   return 1;
95 }
96
97 static void com_stats_andify(int *numbers, int howmany, char *dest)
98 {
99   char tmp[10];
100
101   *dest = '\0';
102   while (howmany--) {
103     sprintf(tmp, "%d", numbers[howmany]);
104     strcat(dest, tmp);
105     if (howmany > 1)
106       sprintf(tmp, ", ");
107     else if (howmany == 1)
108       sprintf(tmp, " and ");
109     else
110       sprintf(tmp, ".\n");
111     strcat(dest, tmp);
112   }
113   return;
114 }
115
116 static void com_stats_rating(char *hdr, struct statistics * stats, char *dest, long now)
117 {
118   char tmp[100];
119
120   *dest = 0;
121
122   if (stats->num == 0) return;
123
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);
129     strcat(dest, tmp);
130     strftime(tmp, sizeof(tmp), " (%d-%b-%Y)", localtime((time_t *) & stats->whenbest));
131     strcat(dest, tmp);
132   }
133   strcat(dest, "\n");
134   return;
135 }
136
137 int com_stats(int p, param_list param)
138 {
139   int g, i;
140   time_t t;
141   int p1, connected;
142   char line[255], tmp[255], tmp2[255];
143   int numbers[MAX_OBSERVE > MAX_SIMUL ? MAX_OBSERVE : MAX_SIMUL];
144   int onTime;
145   int showRatingsFlag, showNotesFlag;
146   int showCommentsFlag = 0;
147   long now;
148
149   showRatingsFlag = showNotesFlag = 1; /* everything on by default */
150
151   if (param[0].type == TYPE_WORD) {
152     if (!FindPlayer(p, param[0].val.word, &p1, &connected))
153       return COM_OK;
154     if (param[1].type == TYPE_WORD) { /* optional second parameter */
155       char *c = param[1].val.word;
156        showRatingsFlag = showNotesFlag = 0;
157       while (*c != '\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++; }
162         else {
163           if (!connected)
164             player_remove(p1);
165           return COM_BADPARAMETERS;
166         }
167       }
168     }
169   } else {
170       p1 = p;
171       connected = 1;
172   }
173
174   strcpy(tmp2, player_globals.parray[p1].name);
175   AddPlayerLists(p1, tmp2);
176   tmp2[17] = '\0';
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)));
180     strcat(line, tmp);
181     sprintf(tmp, "   Idle: %s\n", hms_desc(player_idle(p1)));
182   } else {
183     if ((t = player_lastdisconnect(p1)))
184       sprintf(tmp, "(Last disconnected %s):\n", strltime(&t));
185     else
186       sprintf(tmp, "(Never connected.)\n");
187   }
188   strcat(line, tmp);
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)
193         t++;
194     }
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);
197     pprintf(p, 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);
206     } else {
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);
213       }
214     }
215   }
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;
221     }
222     if (t) {
223       pprintf(p, "%s is observing game%s ", player_globals.parray[p1].name, ((t > 1) ? "s" : ""));
224       com_stats_andify(numbers, t, tmp);
225       pprintf(p, tmp);
226     }
227   }
228   if (player_globals.parray[p1].busy != NULL) {
229     pprintf(p, "(%s %s)\n", player_globals.parray[p1].name, player_globals.parray[p1].busy);
230   }
231   if (!CheckPFlag(p1, PFLAG_REG)) {
232     pprintf(p, "%s is NOT a registered player.\n\n", player_globals.parray[p1].name);
233   } else {
234     if (showRatingsFlag > 0) {
235       now = time(NULL);
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);
247     }
248   }
249   pprintf(p, "\n");
250   if (player_globals.parray[p1].adminLevel > 0) {
251     pprintf(p, "Admin Level: ");
252     switch (5*(player_globals.parray[p1].adminLevel/5)) {
253     case 5:
254       pprintf(p, "Authorized Helper Person\n");
255       break;
256     case 10:
257       pprintf(p, "Administrator\n");
258       break;
259     case 15:
260       pprintf(p, "Help File Librarian/Administrator\n");
261       break;
262     case 20:
263       pprintf(p, "Master Administrator\n");
264       break;
265     case 50:
266       pprintf(p, "Master Help File Librarian/Administrator\n");
267       break;
268     case 60:
269       pprintf(p, "Assistant Super User\n");
270       break;
271     case 100:
272       pprintf(p, "Super User\n");
273       break;
274     default:
275       pprintf(p, "%d\n", player_globals.parray[p1].adminLevel);
276       break;
277     }
278   }
279
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)"));
290
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");
293   }
294   
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);
298
299     timeToStr[strlen(timeToStr)-1]='\0';
300     pprintf(p, "\n");
301     onTime = (time(0) - player_globals.parray[p1].logon_time) + player_globals.parray[p1].totalTime;
302
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)),
306            timeToStr);
307   }
308
309   if (player_globals.parray[p1].num_plan && (showNotesFlag > 0)) {
310     pprintf(p, "\n");
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] : "");
313   }
314   if (showCommentsFlag) {
315     pprintf(p, "\n");
316     pprintf(p, "Comments for %s:\n",player_globals.parray[p1].name);
317     player_show_comments(p, p1); 
318   }
319   if (!connected)
320     player_remove(p1);
321   return COM_OK;
322 }
323
324 int com_password(int p, param_list param)
325 {
326         struct player *pp = &player_globals.parray[p];
327         char *oldpassword = param[0].val.word;
328         char *newpassword = param[1].val.word;
329         char salt[3];
330
331         if (!CheckPFlag(p, PFLAG_REG)) {
332                 pprintf(p, "Setting a password is only for registered players.\n");
333                 return COM_OK;
334         }
335         if (pp->passwd) {
336                 salt[0] = pp->passwd[3];
337                 salt[1] = pp->passwd[4];
338                 salt[2] = '\0';
339                 if (strcmp(chessd_crypt(oldpassword,salt), pp->passwd)) {
340                         pprintf(p, "Incorrect password, password not changed!\n");
341                         return COM_OK;
342                 }
343                 free(pp->passwd);
344                 pp->passwd = NULL;
345         }
346         salt[0] = 'a' + random() % 26;
347         salt[1] = 'a' + random() % 26;
348         salt[2] = '\0';
349         pp->passwd = strdup(chessd_crypt(newpassword,salt));
350         pprintf(p, "Password changed to \"%s\".\n", newpassword);
351         return COM_OK;
352 }
353
354 int com_uptime(int p, param_list param)
355 {
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);
361
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));
365
366   pprintf(p,"Up for");
367
368   if(days)
369     pprintf(p," %d day%s", days, (days == 1) ? "" : "s");
370
371   if(hours)
372     pprintf(p," %d hour%s", hours, (hours == 1) ? "" : "s");
373
374   if(mins)
375     pprintf(p," %d minute%s", mins, (mins == 1) ? "" : "s");
376
377   if(secs)
378     pprintf(p," %d second%s", secs, (secs == 1) ? "" : "s");
379
380   pprintf(p,".\n");
381
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);
386   return COM_OK;
387 }
388
389 int com_date(int p, param_list param)
390 {
391         time_t t = time(0);
392         pprintf(p, "Local time     - %s\n", strltime(&t));
393         pprintf(p, "Greenwich time - %s\n", strgtime(&t));
394         return COM_OK;
395 }
396
397 static const char *inout_string[] = {
398   "login", "logout"
399 };
400
401 static int plogins(int p, char *fname)
402 {
403         FILE *fp;
404         int inout, registered;
405         time_t thetime;
406         char loginName[MAX_LOGIN_NAME + 1];
407         char ipstr[20];
408         
409         fp = fopen_p("%s", "r", fname);
410         if (!fp) {
411                 pprintf(p, "Sorry, no login information available.\n");
412                 return COM_OK;
413         }
414         while (!feof(fp)) {
415                 unsigned t;
416                 if (fscanf(fp, "%d %s %u %d %s\n", &inout, loginName, &t,
417                            &registered, ipstr) != 5) {
418                         d_printf( "CHESSD: Error in login info format. %s\n", 
419                                 fname);
420                         fclose(fp);
421                         return COM_OK;
422                 }
423                 thetime = (time_t)t;
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);
428                 } else
429                         pprintf(p, "\n");
430         }
431         fclose(fp);
432         return COM_OK;
433 }
434
435 int com_llogons(int p, param_list param)
436 {
437         int result;
438         if (!CheckPFlag(p, PFLAG_REG)) {
439                 pprintf(p,"Sorry, guest users may not use this command\n");
440                 return COM_OK;
441         }
442         result = plogins(p, STATS_DIR "/" STATS_LOGONS);
443         return result;
444 }
445
446 int com_logons(int p, param_list param)
447 {
448         struct player *pp = &player_globals.parray[p];
449         char fname[MAX_FILENAME_SIZE];
450
451         if (param[0].type == TYPE_WORD) {
452                 int p1, connected;
453                 if (!FindPlayer(p, param[0].val.word, &p1, &connected))
454                         return COM_OK;
455                 sprintf(fname, "%s/player_data/%c/%s.%s", 
456                         STATS_DIR, 
457                         player_globals.parray[p1].login[0], 
458                         player_globals.parray[p1].login, STATS_LOGONS);
459                 if (!connected)
460                         player_remove(p1);
461         } else {
462                 sprintf(fname, "%s/player_data/%c/%s.%s", 
463                         STATS_DIR, 
464                         pp->login[0], 
465                         pp->login, 
466                         STATS_LOGONS);
467         }
468         return plogins(p, fname);
469 }
470
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
480
481 #define WHO_ALL 0xff
482
483 void AddPlayerLists (int p1, char *ptmp)
484 {
485         if (check_admin(p1, ADMIN_ADMIN) && CheckPFlag(p1, PFLAG_ADMINLIGHT))
486                 strcat(ptmp, "(*)");
487         if (in_list(p1, L_COMPUTER, player_globals.parray[p1].name))
488                 strcat(ptmp, "(C)");
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))
500                 strcat(ptmp, "(T)");
501         if (in_list(p1, L_BLIND, player_globals.parray[p1].name))
502                 strcat(ptmp, "(B)");
503 }
504
505 static void who_terse(int p, int num, int *plist, int type)
506 {
507   struct player *pp = &player_globals.parray[p];
508   char ptmp[80 + 20];           /* for highlight */
509   multicol *m = multicol_start(player_globals.parray_size);
510   int i;
511   int p1;
512   int rat = 0;
513
514   /* altered DAV 3/15/95 */
515
516   for (i = 0; i < num; i++) {
517     p1 = plist[i];
518
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;
529
530     if (type == none) {
531       sprintf(ptmp, "     ");
532     } else {
533       sprintf(ptmp, "%-4s", ratstrii(rat, p1));
534       if ((player_globals.parray[p1].simul_info != NULL) && (player_globals.parray[p1].simul_info->numBoards))
535           strcat(ptmp, "~");
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)))
537         strcat(ptmp, "#");
538       else if (player_globals.parray[p1].game >= 0)
539         strcat(ptmp, "^");
540       else if (!CheckPFlag(p1, PFLAG_OPEN))
541         strcat(ptmp, ":");
542       else if (player_idle(p1) > 300)
543         strcat(ptmp, ".");
544       else
545         strcat(ptmp, " ");
546     }
547
548     if (p == p1) {
549       psprintf_highlight(p, ptmp + strlen(ptmp), "%s", player_globals.parray[p1].name);
550     } else {
551       strcat(ptmp, player_globals.parray[p1].name);
552     }
553
554     AddPlayerLists(p1, ptmp);
555     multicol_store(m, ptmp);
556   }
557   multicol_pprint(m, p, pp->d_width, 2);
558   multicol_end(m);
559   pprintf(p, "\n %d players displayed (of %d). (*) indicates system administrator.\n", num, player_count(1));
560 }
561
562 static void who_verbose(p, num, plist)
563 int p;
564 int num;
565 int plist[];
566 {
567   int i, p1;
568   char playerLine[255], tmp[255];       /* +8 for highlight */
569   char p1WithAttrs[255];
570
571   pprintf(p,
572       " +---------------------------------------------------------------+\n"
573     );
574   pprintf(p,
575       " |      User              Standard    Blitz        On for   Idle |\n"
576     );
577   pprintf(p,
578       " +---------------------------------------------------------------+\n"
579     );
580
581   for (i = 0; i < num; i++) {
582     p1 = plist[i];
583
584     strcpy(playerLine, " |");
585
586     if (player_globals.parray[p1].game >= 0)
587       sprintf(tmp, "%3d", player_globals.parray[p1].game + 1);
588     else
589       sprintf(tmp, "   ");
590     strcat(playerLine, tmp);
591
592     if (!CheckPFlag(p1, PFLAG_OPEN))
593       sprintf(tmp, "X");
594     else
595       sprintf(tmp, " ");
596     strcat(playerLine, tmp);
597
598     if (CheckPFlag(p1, PFLAG_REG))
599       if (CheckPFlag(p1, PFLAG_RATED)) {
600         sprintf(tmp, " ");
601       } else {
602         sprintf(tmp, "u");
603       }
604     else
605       sprintf(tmp, "U");
606     strcat(playerLine, tmp);
607
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';
612
613     /* Modified by DAV 3/15/95 */
614     if (p == p1) {
615       strcpy(tmp, " ");
616       psprintf_highlight(p, tmp + strlen(tmp), "%-17s", p1WithAttrs);
617     } else {
618       sprintf(tmp, " %-17s", p1WithAttrs);
619     }
620     strcat(playerLine, tmp);
621
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);
627
628     if (player_idle(p1) >= 60) {
629       sprintf(tmp, "%5s   |\n", hms(player_idle(p1), 0, 0, 0));
630     } else {
631       sprintf(tmp, "        |\n");
632     }
633     strcat(playerLine, tmp);
634     pprintf(p, "%s", playerLine);
635   }
636
637   pprintf(p,
638       " |                                                               |\n"
639     );
640   pprintf(p,
641      " |    %3d Players Displayed                                      |\n",
642           num
643     );
644   pprintf(p,
645       " +---------------------------------------------------------------+\n"
646     );
647 }
648
649 static void who_winloss(p, num, plist)
650 int p;
651 int num;
652 int plist[];
653 {
654   int i, p1;
655   char playerLine[255], tmp[255];       /* for highlight */
656   char p1WithAttrs[255];
657
658   pprintf(p,
659           "Name               Stand     win loss draw   Blitz    win loss draw    idle\n"
660     );
661   pprintf(p,
662           "----------------   -----     -------------   -----    -------------    ----\n"
663     );
664
665   for (i = 0; i < num; i++) {
666     playerLine[0] = '\0';
667     p1 = plist[i];
668
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';
673
674     if (p1 == p) {
675       psprintf_highlight(p, playerLine, "%-17s", p1WithAttrs);
676     } else {
677       sprintf(playerLine, "%-17s", p1WithAttrs);
678     }
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);
685
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);
692
693     if (player_idle(p1) >= 60) {
694       sprintf(tmp, "%5s\n", hms(player_idle(p1), 0, 0, 0));
695     } else {
696       sprintf(tmp, "     \n");
697     }
698     strcat(playerLine, tmp);
699
700     pprintf(p, "%s", playerLine);
701   }
702   pprintf(p, "    %3d Players Displayed.\n", num);
703 }
704
705 static int who_ok(int p, unsigned int sel_bits)
706 {
707   struct player *pp = &player_globals.parray[p];
708   int p2;
709   if (pp->status != PLAYER_PROMPT)
710     return 0;
711   if (sel_bits == WHO_ALL)
712     return 1;
713   if (sel_bits & WHO_OPEN)
714     if (!CheckPFlag(p, PFLAG_OPEN) || CheckPFlag(p, PFLAG_TOURNEY))
715       return 0;
716   if (sel_bits & WHO_CLOSED)
717     if (CheckPFlag(p, PFLAG_OPEN))
718       return 0;
719   if (sel_bits & WHO_RATED)
720     if (!CheckPFlag(p, PFLAG_RATED))
721       return 0;
722   if (sel_bits & WHO_UNRATED)
723     if (CheckPFlag(p, PFLAG_RATED))
724       return 0;
725   if (sel_bits & WHO_FREE)
726     if (pp->game >= 0)
727       return 0;
728   if (sel_bits & WHO_PLAYING)
729     if (pp->game < 0)
730       return 0;
731   if (sel_bits & WHO_REGISTERED)
732     if (!CheckPFlag(p, PFLAG_REG))
733       return 0;
734   if (sel_bits & WHO_UNREGISTERED)
735     if (CheckPFlag(p, PFLAG_REG))
736       return 0;
737   if (sel_bits & WHO_BUGTEAM) {
738     p2 = pp->partner;
739     if (p2 < 0 || player_globals.parray[p2].partner != p)
740       return 0;
741     }  
742   return 1;
743 }
744
745
746 static int blitz_cmp(const void *pp1, const void *pp2)
747 {
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)
752       return 0;
753     else
754       return -1;
755   }
756   if (player_globals.parray[p2].status != PLAYER_PROMPT)
757     return 1;
758   if (player_globals.parray[p1].b_stats.rating > player_globals.parray[p2].b_stats.rating)
759     return -1;
760   if (player_globals.parray[p1].b_stats.rating < player_globals.parray[p2].b_stats.rating)
761     return 1;
762   if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
763     return -1;
764   if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
765     return 1;
766   return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
767 }
768
769 static int light_cmp(const void *pp1, const void *pp2)
770 {         
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)
775       return 0; 
776     else
777       return -1;
778   }       
779   if (player_globals.parray[p2].status != PLAYER_PROMPT)
780     return 1;
781   if (player_globals.parray[p1].l_stats.rating > player_globals.parray[p2].l_stats.rating)
782     return -1;
783   if (player_globals.parray[p1].l_stats.rating < player_globals.parray[p2].l_stats.rating)
784     return 1;
785   if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
786     return -1;
787   if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
788     return 1;
789   return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
790 }
791
792 static int bug_cmp(const void *pp1, const void *pp2)
793 {  
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)
798       return 0;
799     else
800       return -1;
801   }
802   if (player_globals.parray[p2].status != PLAYER_PROMPT)
803     return 1;
804   if (player_globals.parray[p1].bug_stats.rating > player_globals.parray[p2].bug_stats.rating)
805     return -1;
806   if (player_globals.parray[p1].bug_stats.rating < player_globals.parray[p2].bug_stats.rating)
807     return 1;
808   if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
809     return -1;
810   if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
811     return 1;
812   return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
813 }
814
815 static int stand_cmp(const void *pp1, const void *pp2)
816 {
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)
821       return 0;
822     else
823       return -1;
824   }
825   if (player_globals.parray[p2].status != PLAYER_PROMPT)
826     return 1;
827   if (player_globals.parray[p1].s_stats.rating > player_globals.parray[p2].s_stats.rating)
828     return -1;
829   if (player_globals.parray[p1].s_stats.rating < player_globals.parray[p2].s_stats.rating)
830     return 1;
831   if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
832     return -1;
833   if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
834     return 1;
835   return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
836 }
837
838 static int wild_cmp(const void *pp1, const void *pp2)
839 {
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)
844       return 0;
845     else
846       return -1;
847   }
848   if (player_globals.parray[p2].status != PLAYER_PROMPT)
849     return 1;
850   if (player_globals.parray[p1].w_stats.rating > player_globals.parray[p2].w_stats.rating)
851     return -1;
852   if (player_globals.parray[p1].w_stats.rating < player_globals.parray[p2].w_stats.rating)
853     return 1;
854   if (CheckPFlag(p1, PFLAG_REG) && !CheckPFlag(p2, PFLAG_REG))
855     return -1;
856   if (!CheckPFlag(p1, PFLAG_REG) && CheckPFlag(p2, PFLAG_REG))
857     return 1;
858   return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
859 }
860
861 static int alpha_cmp(const void *pp1, const void *pp2)
862 {
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)
867       return 0;
868     else
869       return -1;
870   }
871   if (player_globals.parray[p2].status != PLAYER_PROMPT)
872     return 1;
873   return strcmp(player_globals.parray[p1].login, player_globals.parray[p2].login);
874 }
875
876 static void sort_players(int *players,
877                          int ((*cmp_func) (const void *, const void *)))
878 {
879         int i;
880
881         for (i = 0; i < player_globals.p_num; i++) {
882                 players[i] = i;
883         }
884         qsort(players, player_globals.p_num, sizeof(int), cmp_func);
885 }
886
887 /* This is the of the most compliclicated commands in terms of parameters */
888 int com_who(int p, param_list param)
889 {
890         struct player *pp = &player_globals.parray[p];
891         int style = 0;
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 *));
897         int startpoint;
898         int stoppoint;
899         int i, len;
900         int tmpI, tmpJ;
901         char c;
902         int p1, count, num_who;
903         int sort_type;
904         int total;
905
906         sortlist = malloc(sizeof(int) * player_globals.p_num);
907         plist = malloc(sizeof(int) * player_globals.p_num);
908         
909         total = pp->d_time * 60 + pp->d_inc * 40;
910         if (total < 180) {
911                 sort_type = light_rat;
912                 cmp_func = light_cmp;
913         } else if (total >= 900) {
914                 sort_type = std_rat;
915                 cmp_func = stand_cmp;
916         } else {
917                 sort_type = blitz_rat;
918                 cmp_func = blitz_cmp;
919         }
920         
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];
925                         if (isdigit(c)) {
926                                 if (i == 0 || !isdigit(param[0].val.string[i - 1])) {
927                                         tmpI = c - '0';
928                                         if (tmpI == 1) {
929                                                 start_perc = 0.0;
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;
936                                                 stop_perc = 1.0;
937                                         } else if ((i == len - 1) || (!isdigit(param[0].val.string[i + 1])))
938                                                 goto bad_parameters;
939                                 } else {
940                                         tmpI = c - '0';
941                                         tmpJ = param[0].val.string[i - 1] - '0';
942                                         if (tmpI == 0)
943                                                 goto bad_parameters;
944                                         if (tmpJ > tmpI)
945                                                 goto bad_parameters;
946                                         start_perc = ((float) tmpJ - 1.0) / (float) tmpI;
947                                         stop_perc = ((float) tmpJ) / (float) tmpI;
948                                 }
949                         } else {
950                                 switch (c) {
951                                 case ' ':
952                                 case '\n':
953                                 case '\t':
954                                         break;
955                                 case 'o':
956                                         if (sel_bits == WHO_ALL)
957                                                 sel_bits = WHO_OPEN;
958                                         else
959                                                 sel_bits |= WHO_OPEN;
960                                         break;
961                                 case 'r':
962                                         if (sel_bits == WHO_ALL)
963                                                 sel_bits = WHO_RATED;
964                                         else
965                                                 sel_bits |= WHO_RATED;
966                                         break;
967                                 case 'f':
968                                         if (sel_bits == WHO_ALL)
969                                                 sel_bits = WHO_FREE;
970                                         else
971                                                 sel_bits |= WHO_FREE;
972                                         break;
973                                 case 'a':
974                                         if (sel_bits == WHO_ALL)
975                                                 sel_bits = WHO_FREE | WHO_OPEN;
976                                         else
977                                                 sel_bits |= (WHO_FREE | WHO_OPEN);
978                                         break;
979                                 case 'R':
980                                         if (sel_bits == WHO_ALL)
981                                                 sel_bits = WHO_REGISTERED;
982                                         else
983                                                 sel_bits |= WHO_REGISTERED;
984                                         break;
985                                 case 'l':               /* Sort order */
986                                         cmp_func = alpha_cmp;
987                                         sort_type = none;
988                                         break;
989                                 case 'A':               /* Sort order */
990                                         cmp_func = alpha_cmp;
991                                         break;
992                                 case 'w':               /* Sort order */
993                                         cmp_func = wild_cmp;
994                                         sort_type = wild_rat;
995                                         break;
996                                 case 's':               /* Sort order */
997                                         cmp_func = stand_cmp;
998                                         sort_type = std_rat;
999                                         break;
1000                                 case 'b':               /* Sort order */
1001                                         cmp_func = blitz_cmp;
1002                                         sort_type = blitz_rat;
1003                                         break;
1004                                 case 'L':               /* Sort order */
1005                                         cmp_func = light_cmp;
1006                                         sort_type = light_rat;
1007                                         break;
1008                                 case 't':               /* format */
1009                                         style = 0;
1010                                         break;
1011                                 case 'v':               /* format */
1012                                         style = 1;
1013                                         break;
1014                                 case 'n':               /* format */
1015                                         style = 2;
1016                                         break;
1017                                 case 'U':
1018                                         if (sel_bits == WHO_ALL)
1019                                                 sel_bits = WHO_UNREGISTERED;
1020                                         else
1021                                                 sel_bits |= WHO_UNREGISTERED;
1022                                         break;
1023                                 case 'B':
1024                                         if (sel_bits == WHO_ALL)
1025                                                 sel_bits = WHO_BUGTEAM;
1026                                         else
1027                                                 sel_bits |= WHO_BUGTEAM;
1028                                         cmp_func = bug_cmp;
1029                                         sort_type = bug_rat;
1030                                         break;
1031                                 default:
1032                                         goto bad_parameters;
1033                                 }
1034                         }
1035                 }
1036         }
1037         sort_players(sortlist, cmp_func);
1038         count = 0;
1039         for (p1 = 0; p1 < player_globals.p_num; p1++) {
1040                 if (!who_ok(sortlist[p1], sel_bits))
1041                         continue;
1042                 count++;
1043         }
1044         startpoint = floor((float) count * start_perc);
1045         stoppoint = ceil((float) count * stop_perc) - 1;
1046         num_who = 0;
1047         count = 0;
1048         for (p1 = 0; p1 < player_globals.p_num; p1++) {
1049                 if (!who_ok(sortlist[p1], sel_bits))
1050                         continue;
1051                 if ((count >= startpoint) && (count <= stoppoint)) {
1052                         plist[num_who++] = sortlist[p1];
1053                 }
1054                 count++;
1055         }
1056         
1057         if (num_who == 0) {
1058                 pprintf(p, "No logged in players match the flags in your who request.\n");
1059                 return COM_OK;
1060         }
1061         
1062         switch (style) {
1063         case 0:                 /* terse */
1064                 who_terse(p, num_who, plist, sort_type);
1065                 break;
1066         case 1:                 /* verbose */
1067                 who_verbose(p, num_who, plist);
1068                 break;
1069         case 2:                 /* win-loss */
1070                 who_winloss(p, num_who, plist);
1071                 break;
1072         default:
1073                 goto bad_parameters;
1074         }
1075         
1076         return COM_OK;
1077
1078 bad_parameters:
1079         return COM_BADPARAMETERS;
1080 }
1081
1082 int com_open(int p, param_list param)
1083 {
1084   int retval;
1085   if ((retval = pcommand(p, "set open")) != COM_OK)
1086     return retval;
1087   else
1088     return COM_OK_NOPROMPT;
1089 }
1090
1091 int com_simopen(int p, param_list param)
1092 {
1093   int retval;
1094   if ((retval = pcommand(p, "set simopen")) != COM_OK)
1095     return retval;
1096   else
1097     return COM_OK_NOPROMPT;
1098 }
1099
1100 int com_bell(int p, param_list param)
1101 {
1102   int retval;
1103   if ((retval = pcommand(p, "set bell")) != COM_OK)
1104     return retval;
1105   else
1106     return COM_OK_NOPROMPT;
1107 }
1108
1109 int com_flip(int p, param_list param)
1110 {
1111   int retval;
1112   if ((retval = pcommand(p, "set flip")) != COM_OK)
1113     return retval;
1114   else
1115     return COM_OK_NOPROMPT;
1116 }
1117
1118 int com_style(int p, param_list param)
1119 {
1120   int retval;
1121   if ((retval = pcommand(p, "set style %d", param[0].val.integer)) != COM_OK)
1122     return retval;
1123   else
1124     return COM_OK_NOPROMPT;
1125 }
1126
1127 int com_promote(int p, param_list param)
1128 {
1129   int retval;
1130   if ((retval = pcommand(p, "set promote %s", param[0].val.word)) != COM_OK)
1131     return retval;
1132   else
1133     return COM_OK_NOPROMPT;
1134 }
1135
1136 void alias_add(int p, const char *name, const char *value)
1137 {
1138         struct player *pp = &player_globals.parray[p];
1139
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);
1144         pp->numAlias++;
1145 }
1146
1147
1148 int com_alias(int p, param_list param)
1149 {
1150         struct player *pp = &player_globals.parray[p];
1151         int al, i;
1152         const char *noalias[] = {"quit", "unalias", NULL};
1153
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);
1159                 }
1160                 return COM_OK;
1161         }
1162
1163         al = alias_lookup(param[0].val.word, pp->alias_list, pp->numAlias);
1164         if (param[1].type == TYPE_NULL) {
1165                 if (al < 0) {
1166                         pprintf(p, "You have no alias named '%s'.\n", param[0].val.word);
1167                 } else {
1168                         pprintf(p, "%s -> %s\n", 
1169                                 pp->alias_list[al].comm_name,
1170                                 pp->alias_list[al].alias);
1171                 }
1172                 return COM_OK;
1173         } 
1174
1175         if (al >= 0) {
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);
1179                 return COM_OK;
1180         }
1181
1182         if (pp->numAlias >= config_get_int("MAX_ALIASES", DEFAULT_MAX_ALIASES)) {
1183                 pprintf(p, "You have your maximum number of aliases.\n");
1184                 return COM_OK;
1185         } 
1186
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");
1190                         return COM_OK;
1191                 }
1192         }
1193
1194         alias_add(p, param[0].val.word, param[1].val.string);
1195
1196         pprintf(p, "Alias set.\n");
1197
1198         return COM_OK;
1199 }
1200
1201 int com_unalias(int p, param_list param)
1202 {
1203         struct player *pp = &player_globals.parray[p];
1204         int al;
1205         int i;
1206         
1207         al = alias_lookup(param[0].val.word, pp->alias_list, pp->numAlias);
1208         if (al < 0) {
1209                 pprintf(p, "You have no alias named '%s'.\n", param[0].val.word);
1210                 return COM_OK;
1211         } 
1212
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;
1218         }
1219         pp->numAlias--;
1220         pp->alias_list = (struct alias_type *)realloc(pp->alias_list, 
1221                                                       sizeof(struct alias_type) * pp->numAlias);
1222         pprintf(p,"Alias removed.\n");
1223
1224         return COM_OK;
1225 }
1226
1227
1228 int com_handles(int p, param_list param)
1229 {
1230         char *buffer[1000];
1231         char pdir[MAX_FILENAME_SIZE];
1232         int count;
1233         
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);
1237         if (count > 0)
1238                 display_directory(p, buffer, count);
1239         return COM_OK;
1240 }
1241
1242 int com_getgi(int p, param_list param)
1243 {
1244   int p1, g;
1245   struct player *pp = &player_globals.parray[p];
1246
1247   if (!in_list(p, L_TD, pp->name)) {
1248     pprintf(p, "Only TD programs are allowed to use this command.\n");
1249     return COM_OK;
1250   }
1251   if (((p1 = player_find_bylogin(param[0].val.word)) < 0)
1252       || (!CheckPFlag(p1, PFLAG_REG))) {
1253     /* Darkside suggested not to return anything */
1254     return COM_OK;
1255   }
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,
1265               g + 1,
1266               game_globals.garray[g].wInitTime,
1267               game_globals.garray[g].wIncrement,
1268               game_globals.garray[g].rated,
1269               game_globals.garray[g].private);
1270     } else {
1271       pprintf(p, "%s is not playing a game.\n", player_globals.parray[p1].name);
1272     }
1273   } else {
1274     pprintf(p, "%s is not playing a game.\n", player_globals.parray[p1].name);
1275   }
1276   return COM_OK;
1277 }
1278
1279 int com_getpi(int p, param_list param)
1280 {
1281   struct player *pp = &player_globals.parray[p];
1282   int p1;
1283
1284   if (!in_list(p, L_TD, pp->name)) {
1285     pprintf(p, "Only TD programs are allowed to use this command.\n");
1286     return COM_OK;
1287   }
1288   if (((p1 = player_find_bylogin(param[0].val.word)) < 0)
1289       || (!CheckPFlag(p1, PFLAG_REG))) {
1290     /* Darkside suggested not to return anything */
1291     return COM_OK;
1292   }
1293   if (!CheckPFlag(p1, PFLAG_REG)) {
1294     pprintf(p, "*getpi %s -1 -1 -1*\n", player_globals.parray[p1].name);
1295   } else {
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);    
1301   }
1302   return COM_OK;
1303 }
1304
1305 int com_limits(int p, param_list param)
1306 {
1307         struct player *pp = &player_globals.parray[p];
1308
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);
1320         } else {
1321                 pprintf(p, "  Size of journal (entries): 26\n");
1322         }
1323         pprintf(p, "\nAdmin settable limits:\n");
1324         pprintf(p, "  Shout quota gives two shouts per %d seconds.\n", seek_globals.quota_time);
1325         return COM_OK;
1326 }
1327
1328
1329 int com_remote(int p, param_list param)
1330 {
1331         int p1;
1332
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);
1335                 return COM_OK;
1336         }
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);
1340                 return COM_OK;
1341         }
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);
1346         return COM_OK;
1347 }