Fix crash after recursive aliasing
[capablanca.git] / lasker-2.2.3 / src / talkproc.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 #include "includes.h"
22
23 static int on_channel(int ch, int p);
24
25 static int CheckShoutQuota(int p)
26 {
27         struct player *pp = &player_globals.parray[p];
28         int timeleft = time(0) - pp->lastshout_a;
29         
30         if ((timeleft < seek_globals.quota_time) && (pp->adminLevel == 0))
31                 return (seek_globals.quota_time - timeleft);
32
33         return 0;
34 }
35
36 int com_shout(int p, param_list param)
37 {
38   int p1, count = 0, timeleft = CheckShoutQuota(p);     
39   struct player *pp = &player_globals.parray[p];
40
41   if (!CheckPFlag(p, PFLAG_REG)) {
42     pprintf(p, "Only registered players can use the shout command.\n");
43     return COM_OK;
44   }
45   if (in_list(p, L_MUZZLE, pp->login)) {
46     pprintf(p, "You are muzzled.\n");
47     return COM_OK;
48   }
49   if (param[0].type == TYPE_NULL) {
50     if (timeleft)
51       pprintf(p, "Next shout available in %d seconds.\n", timeleft);
52     else
53       pprintf(p, "Your next shout is ready for use.\n");
54     return COM_OK;
55   }
56   if (timeleft) {
57     pprintf(p, "Shout not sent. Next shout in %d seconds.\n", timeleft);
58     return COM_OK;
59   }
60
61   pp->lastshout_a = pp->lastshout_b;
62   pp->lastshout_b = time(0);
63   if (!printablestring(param[0].val.string)) {
64     pprintf(p, "Your message contains some unprintable character(s).\n");
65     return COM_OK;
66   }
67
68   for (p1 = 0; p1 < player_globals.p_num; p1++) {
69     if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT) ||
70         (!CheckPFlag(p1, PFLAG_SHOUT)) || (player_censored(p1, p)))
71       continue;
72     count++;
73     pprintf_prompt(p1, "\n%s shouts: %s\n",pp->name,param[0].val.string);
74   }
75
76   pprintf(p, "(%d) %s shouts: %s\n", count, pp->name, 
77           param[0].val.string);
78
79   if (!CheckPFlag(p, PFLAG_SHOUT))
80     pprintf (p, "You are not listening to shouts.\n");
81   if ((timeleft = CheckShoutQuota(p))) 
82     pprintf(p, "Next shout in %d second(s).\n", timeleft);
83   
84   return COM_OK;
85 }
86
87 int com_cshout(int p, param_list param)
88 {
89   struct player *pp = &player_globals.parray[p];
90   int p1, count = 0;
91
92   if (!CheckPFlag(p, PFLAG_REG)) {
93     pprintf(p, "Only registered players can use the cshout command.\n");
94     return COM_OK;
95   }
96   if (in_list(p, L_CMUZZLE, pp->login)) {
97     pprintf(p, "You are c-muzzled.\n");
98     return COM_OK;
99   }
100   if (!printablestring(param[0].val.string)) {
101     pprintf(p, "Your message contains some unprintable character(s).\n");
102     return COM_OK;
103   }
104
105   for (p1 = 0; p1 < player_globals.p_num; p1++) {
106     if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT) || 
107         (!CheckPFlag(p1, PFLAG_CSHOUT)) || (player_censored(p1, p)))
108       continue;
109     count++;
110     pprintf_prompt(p1, "\n%s c-shouts: %s\n", pp->name,
111                    param[0].val.string);
112   }
113   pprintf(p, "(%d) %s c-shouts: %s\n", count, pp->name,
114           param[0].val.string);
115   if (!CheckPFlag(p, PFLAG_CSHOUT))
116     pprintf (p, "You are not listening to c-shouts.\n");
117   
118   return COM_OK;
119 }
120
121 int com_it(int p, param_list param)
122 {
123   struct player *pp = &player_globals.parray[p];
124   int p1, count = 0, timeleft = CheckShoutQuota(p);
125
126   if (!CheckPFlag(p, PFLAG_REG)) {
127     pprintf(p, "Only registered players can use the it command.\n");
128     return COM_OK;
129   }
130   if (in_list(p, L_MUZZLE, pp->login)) {
131     pprintf(p, "You are muzzled.\n");
132     return COM_OK;
133   }
134   if (param[0].type == TYPE_NULL) {
135     if (timeleft)
136       pprintf(p, "Next shout available in %d seconds.\n", timeleft);
137     else
138       pprintf(p, "Your next shout is ready for use.\n");
139
140     return COM_OK;
141   }
142   if (timeleft) {
143     pprintf(p, "Shout not sent. Next shout in %d seconds.\n", timeleft);
144     return COM_OK;
145   }
146   pp->lastshout_a = pp->lastshout_b;
147   pp->lastshout_b = time(0);
148
149   if (!printablestring(param[0].val.string)) {
150     pprintf(p, "Your message contains some unprintable character(s).\n");
151     return COM_OK;
152   }
153
154   for (p1 = 0; p1 < player_globals.p_num; p1++) {
155     if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT) || 
156         (!CheckPFlag(p1, PFLAG_SHOUT)) || (player_censored(p1, p)))
157       continue;
158     count++;
159     if ((!strncmp(param[0].val.string, "\'", 1)) ||
160         (!strncmp(param[0].val.string, ",", 1)) ||
161         (!strncmp(param[0].val.string, ".", 1)))
162       pprintf_prompt(p1, "\n--> %s%s\n", pp->name,
163                      param[0].val.string);
164     else
165       pprintf_prompt(p1, "\n--> %s %s\n", pp->name,
166                      param[0].val.string);
167   }
168   if ((!strncmp(param[0].val.string, "\'", 1)) ||
169       (!strncmp(param[0].val.string, ",", 1)) ||
170       (!strncmp(param[0].val.string, ".", 1))) 
171     pprintf(p, "--> %s%s\n", pp->name, param[0].val.string);
172   else
173     pprintf(p, "--> %s %s\n", pp->name, param[0].val.string);
174   
175   if ((timeleft = CheckShoutQuota(p)))
176     pprintf(p, "Next shout in %d second(s).\n", timeleft);
177
178   return COM_OK;
179 }
180
181 static int tell(int p, int p1, const char *msg, int why, int ch)
182 {
183   struct player *pp = &player_globals.parray[p];
184   char tmp[MAX_LINE_SIZE];
185   int rating, rating1, p2;
186
187   if (!printablestring(msg)) {
188     pprintf(p, "Your message contains some unprintable character(s).\n");
189     return COM_OK;
190   }
191
192   if (!CheckPFlag(p1, PFLAG_TELL) && !CheckPFlag(p, PFLAG_REG)) {
193     pprintf(p, "Player \"%s\" isn't listening to unregistered tells.\n",
194             player_globals.parray[p1].name);
195     return COM_OK;
196   }
197   if (player_censored(p1, p)) {
198     if (pp->adminLevel == 0) {
199       if (why != TELL_KIBITZ && why != TELL_WHISPER && why != TELL_CHANNEL)
200         pprintf(p, "Player \"%s\" is censoring you.\n", player_globals.parray[p1].name);
201       return COM_OK;
202     } else
203       pprintf(p, "Told \"%s\", who is censoring you.\n", player_globals.parray[p1].name);
204   }
205
206   switch (why) {
207   case TELL_SAY:
208     pprintf_highlight(p1, "\n%s", pp->name);
209     pprintf_prompt(p1, " says: %s\n", msg);
210     break;
211   case TELL_WHISPER:
212   case TELL_KIBITZ:
213     rating = GetRating(&player_globals.parray[p], TYPE_BLITZ);
214     if (rating < (rating1 = (GetRating(&player_globals.parray[p], TYPE_STAND))))
215       rating = rating1;
216     if (in_list(p, L_FM, pp->name))
217       pprintf(p1, "\n%s(FM)", pp->name);
218     else if (in_list(p, L_IM, pp->name))
219       pprintf(p1, "\n%s(IM)", pp->name);
220     else if (in_list(p, L_GM, pp->name))
221       pprintf(p1, "\n%s(GM)", pp->name);
222     else if (in_list(p, L_WGM, pp->name))
223       pprintf(p1, "\n%s(WGM)", pp->name);
224     else if ((pp->adminLevel >= 10)
225              && CheckPFlag(p, PFLAG_ADMINLIGHT))
226       pprintf(p1, "\n%s(*)", pp->name);
227     else if ((rating >= player_globals.parray[p1].kiblevel) || 
228              ((pp->adminLevel >= 10)
229               && CheckPFlag(p, PFLAG_ADMINLIGHT)))
230       if (!CheckPFlag(p, PFLAG_REG))
231         pprintf(p1, "\n%s(++++)", pp->name);
232       else if (rating != 0)
233         if (in_list(p, L_COMPUTER, pp->name))
234           pprintf(p1, "\n%s(%d)(C)", pp->name, rating);
235         else
236           pprintf(p1, "\n%s(%d)", pp->name, rating);
237       else 
238         pprintf(p1, "\n%s(----)", pp->name);
239     else break;
240     
241     if (why == TELL_WHISPER) 
242       pprintf_prompt(p1, " whispers: %s\n", msg);
243     else 
244       pprintf_prompt(p1, " kibitzes: %s\n", msg);
245
246     break;
247   case TELL_CHANNEL:
248     pprintf(p1, "\n%s", pp->name);
249     if ((pp->adminLevel >= 10)
250         && CheckPFlag(p, PFLAG_ADMINLIGHT) && (ch == 1))
251       pprintf(p1, "(*)");
252     pprintf_prompt(p1, "(%d): %s\n", ch, msg);
253     break;
254   case TELL_LTELL:
255       pprintf_prompt(p1, "\n%s tells you: %s\n", pp->name, msg);
256       break;
257
258   case TELL_TELL:
259   default:
260     if (player_globals.parray[p1].highlight)
261       pprintf_highlight(p1, "\n%s", pp->name);
262     else
263       pprintf(p1, "\n%s", pp->name);
264     
265     if ((pp->adminLevel >= 10) && CheckPFlag(p, PFLAG_ADMINLIGHT))
266       pprintf(p1,"(*)");
267     
268     pprintf_prompt(p1, " tells you: %s\n", msg);
269
270 /* let's test for forwarding of tells */
271
272     if ((pp->ftell == p1) || (player_globals.parray[p1].ftell == p)) {
273       for (p2 = 0; p2 < player_globals.p_num; p2++) {
274         if ((p2 == p) || (p2 == p1) || (player_globals.parray[p2].status != PLAYER_PROMPT))
275           continue;
276         if (on_channel(0, p2))
277           pprintf (p2,"\nFwd tell: %s told %s: %s\n", pp->name,
278                  player_globals.parray[p1].name, msg);
279       }
280     }
281
282     break;
283   }
284   
285   tmp[0] = '\0';
286   
287   if (!(player_globals.parray[p1].busy == NULL))
288     sprintf(tmp, ", who %s (idle: %s)", player_globals.parray[p1].busy, 
289             hms_desc(player_idle(p1)));
290   else
291     if (((player_idle(p1) % 3600) / 60) > 2)
292       sprintf(tmp, ", who has been idle %s", hms_desc(player_idle(p1)));
293   
294   if ((why == TELL_SAY) || (why == TELL_TELL) || (why == TELL_LTELL)) {
295     pprintf(p, "(told %s%s)\n", player_globals.parray[p1].name,
296             (((player_globals.parray[p1].game>=0) && (game_globals.garray[player_globals.parray[p1].game].status == GAME_EXAMINE)) 
297              ? ", who is examining a game" : 
298              ((player_globals.parray[p1].game>=0) && (game_globals.garray[player_globals.parray[p1].game].status == GAME_SETUP))
299              ? ", who is setting up a position" :
300              (player_globals.parray[p1].game >= 0 && (player_globals.parray[p1].game != pp->game))
301              ? ", who is playing" : tmp));
302   }
303
304   if (why == TELL_TELL || why == TELL_SAY) {
305           FREE(pp->last_tell);
306           pp->last_tell = strdup(player_globals.parray[p1].login);
307   }
308   
309   return COM_OK;
310 }
311
312 int com_ptell(int p, param_list param)
313 {
314   struct player *pp = &player_globals.parray[p];
315   char tmp[MAX_LINE_SIZE];
316   int p1;
317
318    if (pp->partner < 0) {
319      pprintf (p, "You do not have a partner at present.\n");
320      return COM_OK;
321    }
322
323    p1 = pp->partner;
324    if ((p1 < 0) || (player_globals.parray[p1].status == PLAYER_PASSWORD)
325        || (player_globals.parray[p1].status == PLAYER_LOGIN)) {
326      pprintf(p, "Your partner is not logged in.\n");
327      return COM_OK;
328    }
329
330    if (player_globals.parray[p1].highlight)
331      pprintf_highlight(p1, "\n%s", pp->name);
332    else
333      pprintf(p1, "\n%s", pp->name);
334    
335    pprintf_prompt(p1, " (your partner) tells you: %s\n", param[0].val.string);
336    tmp[0] = '\0';
337    if (!(player_globals.parray[p1].busy == NULL))
338      sprintf(tmp, ", who %s (idle: %s)", player_globals.parray[p1].busy,
339              hms_desc(player_idle(p1)));
340    else
341      if (((player_idle(p1) % 3600) / 60) > 2) 
342        sprintf(tmp, ", who has been idle %s", hms_desc(player_idle(p1)));
343    
344    pprintf(p, "(told %s%s)\n", player_globals.parray[p1].name,
345            (((player_globals.parray[p1].game>=0) && (game_globals.garray[player_globals.parray[p1].game].status == GAME_EXAMINE))
346             ? ", who is examining a game" :
347             ((player_globals.parray[p1].game>=0) && (game_globals.garray[player_globals.parray[p1].game].status == GAME_SETUP))
348             ? ", who is setting up a position" :
349             (player_globals.parray[p1].game >= 0 && (player_globals.parray[p1].game != pp->game))
350             ? ", who is playing" : tmp));
351    
352    return COM_OK;
353 }
354
355 static int chtell(int p, int ch, char *msg)
356 {
357   struct player *pp = &player_globals.parray[p];
358   int p1, count = 0;
359
360   if ((ch == 0) && (pp->adminLevel < ADMIN_ADMIN)) {
361     pprintf(p, "Only admins may send tells to channel 0.\n");
362     return COM_OK;
363   }
364
365   if (ch < 0) {
366     pprintf(p, "The lowest channel number is 0.\n");
367     return COM_OK;
368   }
369
370   if (ch >= MAX_CHANNELS) {
371     pprintf(p, "The maximum channel number is %d.\n", MAX_CHANNELS - 1);
372     return COM_OK;
373   }
374
375   if ((ch == 1) && (in_list(p, L_C1MUZZLE, pp->login))) {
376     pprintf (p, "You have been prevented from sending tells to channel 1.\n");
377     return COM_OK;
378   }
379
380   if ((ch == 24) && (in_list(p, L_C24MUZZLE, pp->login))) {
381     pprintf (p, "You have been prevented from sending tells to channel 24.\n");
382     return COM_OK;
383   }
384
385   if ((ch == 46) && (in_list(p, L_C46MUZZLE, pp->login))) {
386     pprintf (p, "You have been prevented from sending tells to channel 46.\n");
387     return COM_OK;
388   }
389
390   if ((ch == 49) && (in_list(p, L_C49MUZZLE, pp->login))) {
391     pprintf (p, "You have been prevented from sending tells to channel 49.\n");
392     return COM_OK;
393   }
394
395   if ((ch == 50) && (in_list(p, L_C50MUZZLE, pp->login))) {
396     pprintf (p, "You have been prevented from sending tells to channel 50.\n");
397     return COM_OK;
398   }
399
400   if ((ch == 51) && (in_list(p, L_C51MUZZLE, pp->login))) {
401     pprintf (p, "You have been prevented from sending tells to channel 51.\n");
402     return COM_OK;
403   }
404
405   for (p1 = 0; p1 < player_globals.p_num; p1++) {
406     if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT)) 
407       continue;
408     if ((on_channel(ch, p1)) && (!player_censored(p1, p))
409         && (CheckPFlag(p, PFLAG_REG) || CheckPFlag(p1, PFLAG_TELL))) {
410       tell(p, p1, msg, TELL_CHANNEL, ch);
411       if (!player_censored(p1, p))
412         count++;
413     }
414   }
415
416   if (count) 
417     pp->last_channel = ch;
418   
419   pprintf(p, "%s(%d): %s\n", pp->name, ch, msg);
420   if (!on_channel(ch, p))
421     pprintf(p, " (You're not listening to channel %d.)\n", ch);
422   
423   return COM_OK;
424 }
425
426 int com_whisper(int p, param_list param)
427 {
428   struct player *pp = &player_globals.parray[p];
429   int g, p1, count = 0;
430
431   if (!pp->num_observe && pp->game < 0) {
432     pprintf(p, "You are not playing or observing a game.\n");
433     return COM_OK;
434   }
435   if (!CheckPFlag(p, PFLAG_REG) && (pp->game == -1)) {
436     pprintf(p, "You must be registered to whisper other people's games.\n");
437     return COM_OK;
438   }
439   if (pp->game >= 0)
440     g = pp->game;
441   else
442     g = pp->observe_list[0];
443   for (p1 = 0; p1 < player_globals.p_num; p1++) {
444     if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT))
445       continue;
446     if (player_is_observe(p1, g) ||
447         (game_globals.garray[g].link >= 0 && player_is_observe(p1, game_globals.garray[g].link)
448          && player_globals.parray[p1].game != game_globals.garray[g].link)) {
449       tell(p, p1, param[0].val.string, TELL_WHISPER, 0);
450       if ((pp->adminLevel >= ADMIN_ADMIN) || !game_globals.garray[g].private || !player_censored(p1, p))
451         count++;
452     }
453   }
454   pprintf(p, "whispered to %d.\n", count);
455   return COM_OK;
456 }
457
458 int com_kibitz(int p, param_list param)
459 {
460   struct player *pp = &player_globals.parray[p];
461   int g, p1, count = 0;
462
463   if (!pp->num_observe && pp->game < 0) {
464     pprintf(p, "You are not playing or observing a game.\n");
465     return COM_OK;
466   }
467   if (!CheckPFlag(p, PFLAG_REG) && (pp->game == -1)) {
468     pprintf(p, "You must be registered to kibitz other people's games.\n");
469     return COM_OK;
470   }
471   if (pp->game >= 0)
472     g = pp->game;
473   else
474     g = pp->observe_list[0];
475   if(pp->game == g) { // [HGM] capture engine kibitz of player
476     float score; int depth;
477     if(sscanf(param[0].val.string, "!!! %f/%d", &score, &depth) == 2) {
478       struct game *gg = &game_globals.garray[g];
479       if(gg->numHalfMoves && gg->status == GAME_ACTIVE) {
480         int n = gg->numHalfMoves-1;
481         if(n && (gg->game_state.onMove == WHITE && gg->black != p ||
482                  gg->game_state.onMove == BLACK && gg->white != p   )) n--;
483         gg->moveList[n].score = score;
484         gg->moveList[n].depth = depth;
485       }
486     }
487   }
488   for (p1 = 0; p1 < player_globals.p_num; p1++) {
489     if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT))
490       continue;
491     if ((player_is_observe(p1, g) || player_globals.parray[p1].game == g
492          || (game_globals.garray[g].link >= 0
493              && (player_is_observe(p1, game_globals.garray[g].link)
494                  || player_globals.parray[p1].game == game_globals.garray[g].link)))
495         && CheckPFlag(p1, PFLAG_KIBITZ)) {
496       tell(p, p1, param[0].val.string, TELL_KIBITZ, 0);
497       if ((pp->adminLevel >= ADMIN_ADMIN) || 
498           !game_globals.garray[g].private || (player_globals.parray[p1].game == g) || !player_censored(p1, p))
499         count++;
500     }
501   }
502   pprintf(p, "kibitzed to %d.\n", count);
503   return COM_OK;
504 }
505
506 /* 
507    like tell() but takes a player name
508 */
509 static int tell_s(int p, const char *who, const char *msg, int why, int ch)
510 {
511         int p1;
512
513         p1 = player_find_part_login(who);
514         if ((p1 < 0) || (player_globals.parray[p1].status == PLAYER_PASSWORD)
515             || (player_globals.parray[p1].status == PLAYER_LOGIN)) {
516                 if (why != TELL_LTELL) {
517                         pprintf(p, "No user named '%s' is logged in.\n", who);
518                 }
519                 return COM_OK;
520         }
521
522         return tell(p, p1, msg, why, ch);
523 }
524
525 int com_tell(int p, param_list param)
526 {
527         struct player *pp = &player_globals.parray[p];
528         char *who;
529
530         if (param[0].type == TYPE_NULL)
531                 return COM_BADPARAMETERS;
532         if (param[0].type != TYPE_WORD) {
533                 return chtell(p, param[0].val.integer, param[1].val.string);
534         }
535
536         who = param[0].val.word;
537         stolower(who);
538
539         if (strcmp(who, ".") == 0) {
540                 if (!pp->last_tell) {
541                         pprintf(p, "No previous tell.\n");
542                         return COM_OK;
543                 }
544                 who = pp->last_tell;
545         }
546
547         if (strcmp(who, ",") == 0) {
548                 if (pp->last_channel == -1) {
549                         pprintf(p, "No previous channel.\n");
550                         return COM_OK;
551                 }
552                 return chtell(p, pp->last_channel, param[1].val.string);
553         }
554
555         return tell_s(p, who, param[1].val.string, TELL_TELL, 0);
556 }
557
558
559 /* tell all players in a named list */
560 int com_ltell(int p, param_list param)
561 {
562         struct List *gl;
563         int i;
564
565         gl = list_findpartial(p, param[0].val.word, 0);
566         if (!gl) {
567                 pprintf(p,"Can't find that list\n");
568                 return COM_OK;
569         }
570         
571         for (i=0;i<gl->numMembers;i++) {
572                 tell_s(p, gl->m_member[i], param[1].val.string, TELL_LTELL, 0);
573         }
574         
575         return COM_OK;
576 }
577
578
579 int com_xtell(int p, param_list param)
580 {
581   struct player *pp = &player_globals.parray[p];
582   int p1;
583   char *msg, tmp[2048];
584   
585   msg = param[1].val.string;
586   p1 = player_find_part_login(param[0].val.word);
587   if ((p1 < 0) || (player_globals.parray[p1].status == PLAYER_PASSWORD)
588       || (player_globals.parray[p1].status == PLAYER_LOGIN)) {
589     pprintf(p, "No user named \"%s\" is logged in.\n", param[0].val.word);
590     return COM_OK;
591   }
592   if (!printablestring(msg)) {
593     pprintf(p, "Your message contains some unprintable character(s).\n");
594     return COM_OK;
595   }
596   if (!CheckPFlag(p1, PFLAG_TELL) && !CheckPFlag(p, PFLAG_REG)) {
597     pprintf(p, "Player \"%s\" isn't listening to unregistered tells.\n",
598             player_globals.parray[p1].name);
599     return COM_OK;
600   }
601   if ((player_censored(p1, p)) && (pp->adminLevel == 0)) {
602     pprintf(p, "Player \"%s\" is censoring you.\n", player_globals.parray[p1].name);
603     return COM_OK;
604   }
605   if (player_globals.parray[p1].highlight)
606     pprintf_highlight(p1, "\n%s", pp->name);
607   else
608     pprintf(p1, "\n%s", pp->name);
609   
610   pprintf_prompt(p1, " tells you: %s\n", msg);
611
612   tmp[0] = '\0';
613   if (!(player_globals.parray[p1].busy == NULL))
614     sprintf(tmp, ", who %s (idle: %s)", player_globals.parray[p1].busy,
615             hms_desc(player_idle(p1)));
616   else
617     if (((player_idle(p1) % 3600) / 60) > 2)
618       sprintf(tmp, ", who has been idle %s", hms_desc(player_idle(p1)));
619   
620   pprintf(p, "(told %s%s)\n", player_globals.parray[p1].name,
621           (((player_globals.parray[p1].game>=0) && (game_globals.garray[player_globals.parray[p1].game].status == GAME_EXAMINE)) 
622            ? ", who is examining a game" : 
623            ((player_globals.parray[p1].game>=0) && (game_globals.garray[player_globals.parray[p1].game].status == GAME_SETUP))
624            ? ", who is setting up a position" :
625            (player_globals.parray[p1].game >= 0 && (player_globals.parray[p1].game != pp->game))
626            ? ", who is playing" : tmp));
627   return COM_OK;
628 }
629
630 int com_say(int p, param_list param)
631 {
632         struct player *pp = &player_globals.parray[p];
633         if (pp->opponent < 0) {
634                 if (!pp->last_opponent) {
635                         pprintf(p, "No one to say anything to, try tell.\n");
636                         return COM_OK;
637                 }
638                 return tell_s(p, pp->last_opponent, param[0].val.string, TELL_SAY, 0);
639         }
640         return tell(p, pp->opponent, param[0].val.string, TELL_SAY, 0);
641 }
642
643 int com_inchannel(int p, param_list param)
644 {
645   int p1,count = 0;
646   char tmp[18];
647
648   if (param[0].type == TYPE_NULL) {
649     pprintf (p,"inchannel [no params] has been removed\n");
650     pprintf (p,"Please use inchannel [name] or inchannel [number]\n");
651     return COM_OK;
652   }
653
654   if (param[0].type == TYPE_WORD) {
655     p1 = player_find_part_login(param[0].val.word);
656     if ((p1 < 0) || (player_globals.parray[p1].status != PLAYER_PROMPT)) {
657       pprintf(p, "No user named \"%s\" is logged in.\n", param[0].val.word);
658       return COM_OK;
659     }
660     pprintf (p,"%s is in the following channels:",player_globals.parray[p1].name); 
661     if (list_channels (p,p1))
662       pprintf (p," No channels found for %s.\n",player_globals.parray[p1].name);
663     return COM_OK;
664   } else if (param[0].val.integer >= MAX_CHANNELS) {
665     pprintf (p, "No such channel; the largest channel number is %d.\n",
666                  MAX_CHANNELS - 1);
667     return COM_OK;
668   } else {
669     sprintf (tmp,"%d",param[0].val.integer);
670     for (p1 = 0; p1 < player_globals.p_num; p1++) {
671       if (player_globals.parray[p1].status != PLAYER_PROMPT)
672         continue;
673       if (in_list(p1,L_CHANNEL,tmp)) {
674         if (!count)
675           pprintf(p,"Channel %d:",param[0].val.integer);
676         pprintf (p," %s", player_globals.parray[p1].name);
677         if ((player_globals.parray[p1].adminLevel >= 10)
678             && CheckPFlag(p1, PFLAG_ADMINLIGHT)
679             && (param[0].val.integer < 2))
680           pprintf(p, "(*)");
681         count++;
682       } 
683     }
684     if (!count)
685       pprintf(p,"Channel %d is empty.\n",param[0].val.integer);
686     else
687       pprintf (p,"\n%d %s in channel %d.\n",count,(count == 1 ? "person is" : "people are"),param[0].val.integer);
688     return COM_OK;
689   }
690 }
691
692 static int com_sendmessage(int p, param_list param)
693 {
694   struct player *pp = &player_globals.parray[p];
695   int p1, connected = 1;
696   
697   if (!CheckPFlag(p, PFLAG_REG)) {
698     pprintf(p, "You are not registered and cannot send messages.\n");
699     return COM_OK;
700   }
701   
702   if (!FindPlayer(p, param[0].val.word, &p1, &connected))
703     return COM_OK;
704   
705   if (!CheckPFlag(p1, PFLAG_REG)) {
706     pprintf(p, "Player \"%s\" is unregistered and cannot receive messages.\n",
707             player_globals.parray[p1].name);
708     return COM_OK;
709   }
710   
711   if ((player_censored(p1, p)) && (pp->adminLevel == 0)) {
712     pprintf(p, "Player \"%s\" is censoring you.\n", player_globals.parray[p1].name);
713     if (!connected)
714       player_remove(p1);
715     return COM_OK;
716   }
717   if (player_add_message(p1, p, param[1].val.string)) {
718     pprintf(p, "Couldn't send message to %s. Message buffer full.\n",
719             player_globals.parray[p1].name);
720   } else {
721     if (connected) {
722       pprintf(p1, "\n%s just sent you a message:\n", pp->name);
723       pprintf_prompt(p1, "    %s\n", param[1].val.string);
724     } 
725   }
726   if (!connected)
727     player_remove(p1);
728   return COM_OK;
729 }
730
731 int com_messages(int p, param_list param)
732 {
733   int start;
734   
735   if (!CheckPFlag(p, PFLAG_REG)) {
736     pprintf (p, "Unregistered players may not send or receive messages.\n");
737     return COM_OK;
738   }
739   if (param[0].type == TYPE_NULL) {
740     player_show_messages (p);
741   } else if (param[0].type == TYPE_WORD) {
742     if (param[1].type != TYPE_NULL)
743       return com_sendmessage(p, param);
744     else ShowMsgsBySender(p, param);
745   } else {
746     start = param[0].val.integer;
747     ShowMsgRange (p, start, start);
748   }
749   return COM_OK;
750 }
751
752 int com_forwardmess(int p, param_list param)
753 {
754   if (!CheckPFlag(p, PFLAG_REG)) {
755     pprintf (p, "Unregistered players may not send or receive messages.\n");
756     return COM_OK;
757   }
758   
759   ForwardMsgRange(param[0].val.word, p, param[1].val.integer, param[1].val.integer);
760
761   return COM_OK;
762 }
763
764 int com_clearmessages(int p, param_list param)
765 {
766   if (player_num_messages(p) <= 0) {
767     pprintf(p, "You have no messages.\n");
768     return COM_OK;
769   }
770   if (param[0].type == TYPE_NULL) {
771     pprintf(p, "Messages cleared.\n");
772     player_clear_messages(p);
773   } else if (param[0].type == TYPE_WORD)
774     ClearMsgsBySender(p, param);
775   else if (param[0].type == TYPE_INT)
776     ClrMsgRange (p, param[0].val.integer, param[0].val.integer);
777
778   return COM_OK;
779 }
780
781 int com_znotify(int p, param_list param)
782 {
783   int p1, count = 0;
784   
785   for (p1 = 0; p1 < player_globals.p_num; p1++) {
786     if (player_notified(p, p1) && player_globals.parray[p1].status == PLAYER_PROMPT) {
787       if (!count)
788         pprintf(p, "Present company on your notify list:\n  ");
789       pprintf(p, " %s", player_globals.parray[p1].name);
790       count++;
791     }
792   }
793   if (!count)
794     pprintf(p, "No one from your notify list is logged on.");
795   pprintf(p, "\n");
796   
797   count = 0;
798   for (p1 = 0; p1 < player_globals.p_num; p1++) {
799     if (player_notified(p1, p) && player_globals.parray[p1].status == PLAYER_PROMPT) {
800       if (!count)
801         pprintf(p,
802                 "The following players have you on their notify list:\n  ");
803       pprintf(p, " %s", player_globals.parray[p1].name);
804       count++;
805     }
806   }
807   if (!count)
808     pprintf(p, "No one logged in has you on their notify list.");
809   pprintf(p, "\n");
810
811   return COM_OK;
812 }
813
814 int com_qtell(int p, param_list param)
815 {
816   struct player *pp = &player_globals.parray[p];
817   int p1;
818   char tmp[MAX_STRING_LENGTH];
819   char dummy[2];
820   char buffer1[MAX_STRING_LENGTH];      /* no highlight and no bell */
821   char buffer2[MAX_STRING_LENGTH];      /* no highlight and bell */
822   char buffer3[MAX_STRING_LENGTH];      /* highlight and no bell */
823   char buffer4[MAX_STRING_LENGTH];      /* highlight and and bell */
824   int i,count;
825   
826   if (!in_list(p, L_TD, pp->name)) {
827     pprintf(p, "Only TD programs are allowed to use this command.\n");
828     return COM_OK;
829   }
830   strcpy(buffer1, ":\0");
831   strcpy(buffer2, ":\0");
832   strcpy(buffer3, ":\0");
833   strcpy(buffer4, ":\0");
834   
835   sprintf(tmp, "%s", param[1].val.string);
836   for (i = 0, count = 0; ((tmp[i] != '\0') && (count < 1029));) {
837     if ((tmp[i] == '\\') && (tmp[i + 1] == 'n')) {
838       strcat(buffer1, "\n:");
839       strcat(buffer2, "\n:");
840       strcat(buffer3, "\n:");
841       strcat(buffer4, "\n:");
842       count += 2;
843       i += 2;
844     } else if ((tmp[i] == '\\') && (tmp[i + 1] == 'b')) {
845       strcat(buffer2, "\007");
846       strcat(buffer4, "\007");
847       count++;
848       i += 2;
849     } else if ((tmp[i] == '\\') && (tmp[i + 1] == 'H')) {
850       strcat(buffer3, "\033[7m");
851       strcat(buffer4, "\033[7m");
852       count += 4;
853       i += 2;
854     } else if ((tmp[i] == '\\') && (tmp[i + 1] == 'h')) {
855       strcat(buffer3, "\033[0m");
856       strcat(buffer4, "\033[0m");
857       count += 4;
858       i += 2;
859     } else {
860       dummy[0] = tmp[i];
861       dummy[1] = '\0';
862       strcat(buffer1, dummy);
863       strcat(buffer2, dummy);
864       strcat(buffer3, dummy);
865       strcat(buffer4, dummy);
866       count++;
867       i++;
868     }
869   }
870
871   if (param[0].type == TYPE_WORD) {
872     if ((p1 = player_find_bylogin(param[0].val.word)) < 0) {
873       pprintf(p, "*qtell %s 1*\n", param[0].val.word);
874       return COM_OK;
875     }
876     pprintf_prompt(p1, "\n%s\n", (player_globals.parray[p1].highlight && CheckPFlag(p1, PFLAG_BELL)) ? buffer4 :
877                    (player_globals.parray[p1].highlight && !CheckPFlag(p1, PFLAG_BELL)) ? buffer3 :
878                    (!player_globals.parray[p1].highlight && CheckPFlag(p1, PFLAG_BELL)) ? buffer2 :
879                    buffer1);
880     pprintf(p, "*qtell %s 0*\n", player_globals.parray[p1].name);
881
882   } else {
883     int p1;
884     int ch = param[0].val.integer;
885
886     if (ch == 0) {
887       pprintf(p, "*qtell %d 1*\n", param[0].val.integer);
888       return COM_OK;
889     }
890     if (ch < 0) {
891       pprintf(p, "*qtell %d 1*\n", param[0].val.integer);
892       return COM_OK;
893     }
894     if (ch >= MAX_CHANNELS) {
895       pprintf(p, "*qtell %d 1*\n", param[0].val.integer);
896       return COM_OK;
897     }
898     sprintf (tmp,"%d",param[0].val.integer);
899     for (p1 = 0; p1 < player_globals.p_num ; p1++) {
900       if ((p1 == p) || (player_censored(p1, p)) || (player_globals.parray[p1].status != PLAYER_PROMPT))
901         continue;
902       if (in_list(p1,L_CHANNEL,tmp))
903         pprintf_prompt(p1, "\n%s\n", (player_globals.parray[p1].highlight && CheckPFlag(p1, PFLAG_BELL)) ? buffer4 :
904                      (player_globals.parray[p1].highlight && !CheckPFlag(p1, PFLAG_BELL)) ? buffer3 :
905                      (!player_globals.parray[p1].highlight && CheckPFlag(p1, PFLAG_BELL)) ? buffer2 :
906                      buffer1);
907     }
908     pprintf(p, "*qtell %d 0*\n", param[0].val.integer);
909   }
910   return COM_OK;
911 }
912
913 static int on_channel(int ch, int p)
914 {
915         char tmp[10];  /* 9 digits ought to be enough :) */
916
917         sprintf (tmp,"%d",ch);
918         return in_list(p, L_CHANNEL,tmp);  /* since needs ch converted to a string
919                                               kept hidden from view */
920 }