Implement S-Chess
[capablanca.git] / lasker-2.2.3 / src / pending.c
1 /*
2    This program is free software; you can redistribute it and/or modify
3    it under the terms of the GNU General Public License as published by
4    the Free Software Foundation; either version 2 of the License, or
5    (at your option) any later version.
6    
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11    
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17 /* 
18   pending.c
19
20   Sat Feb 10 - created - DAV
21
22 */
23 #include "includes.h"
24
25 extern const char *colorstr[];
26
27 /* iterator for player p */
28 static struct pending* next_pending(struct pending* current)
29 {
30
31  if (current == NULL) {
32    d_printf("NULL pointer passed to next_pending\n");
33    return NULL;
34  } else return current->next;
35 }
36  
37 /* deletor for pending - returns next item*/
38 struct pending *delete_pending(struct pending *current)
39 {
40         struct pending *p;
41
42         if (current == NULL) { 
43                 d_printf("NULL pointer passed to delete_pending\n");
44                 return NULL;
45         }
46  
47         player_globals.parray[current->whofrom].number_pend_from--;
48         player_globals.parray[current->whoto].number_pend_to--;
49
50         if (current->category != NULL) {
51                 free(current->category);
52         }
53         if (current->board_type != NULL) {
54                 free(current->board_type);
55         }
56         
57         if (current == seek_globals.pendlist) {
58                 seek_globals.pendlist = current->next;
59                 free(current);
60                 return seek_globals.pendlist;
61         }
62
63         for (p=seek_globals.pendlist; p && p->next != current; p=p->next) ;
64
65         if (!p) {
66                 d_printf("current not on pending list??");
67                 return NULL;
68         }
69
70         p->next = current->next;
71         free(current);
72         return p->next;
73 }
74
75 /* kills the whole pending list on shutdown */
76 void destruct_pending(void)
77 {
78         struct pending* current = seek_globals.pendlist;
79         
80         while (current != NULL)
81                 current = delete_pending(current); 
82
83
84 struct pending *add_pending(int from,int to,int type)
85 {
86         struct pending* new = (struct pending*) malloc(sizeof(struct pending));
87
88         new->whofrom = from;
89         new->whoto = to;
90         new->type = type;
91         new->next = seek_globals.pendlist;
92         new->category = NULL;
93         new->board_type = NULL;
94         
95         player_globals.parray[from].number_pend_from++;
96         player_globals.parray[to].number_pend_to++;
97         
98         seek_globals.pendlist = new;
99
100         return new;
101 }
102
103 static int check_current_pend(struct pending* current, int p, int p1, int type)
104 {
105     if ((p != -1) && ((current->whofrom) != p))
106       return 0;
107     if (current->whoto != p1 && p1 != -1)
108       return 0;
109     if ((type == PEND_ALL) || (current->type == type))
110       return 1;
111     if ((type < 0) && (current->type != -type))
112       return 1;
113 /* The above "if" allows a type of -PEND_SIMUL to match every request
114     EXCEPT simuls, for example.  I'm doing this because Heringer does
115     not want to decline simul requests when he makes a move in a sumul.
116     -- hersco. */
117
118     return 0;
119 }
120
121 /* from p to p1 */
122 struct pending *find_pend(int p, int p1, int type)
123 {
124         struct player *pp = &player_globals.parray[p];
125         /* -ve type can be used to decline all but that type */
126         struct pending* current = seek_globals.pendlist;
127         
128         if (((p != -1) && (!pp->number_pend_from)) || 
129             ((p1 != -1) && (!player_globals.parray[p1].number_pend_to)))
130                 return NULL;
131         
132         while (current != NULL) {
133                 if (check_current_pend(current,p,p1, type))
134                         return current;
135                 current = next_pending(current);
136         }
137         return NULL;
138 }
139
140 /* from p to p1 */
141 struct pending *add_request(int p, int p1, int type)
142 {
143         struct player *pp = &player_globals.parray[p];
144         struct pending* new = NULL;
145
146         if ((pp->number_pend_from) && 
147             (player_globals.parray[p1].number_pend_to)) {
148                 if ((new = find_pend(p, p1, type)) != NULL)
149                         return new;                  /* Already exists */
150         }
151
152         if ((new = add_pending(p,p1,type)) == NULL)
153                 return NULL;
154         return new;
155 }
156
157 /* removes all requests from p to p1 */
158 void remove_request(int p, int p1, int type)
159 {
160         struct pending* next;
161         struct pending* current = seek_globals.pendlist;
162
163         while (current != NULL) {
164                 next = next_pending(current);
165                 if (check_current_pend(current,p,p1,type))
166                         delete_pending(current);
167                 current = next;
168         }
169 }
170
171 /* made into 1 functions for speed */
172
173 /* decline offers to p and withdraw offers from p */
174 static void do_decline_withdraw_offers(int p,int p1, int offers, int partners, int wd)
175 {
176   struct player *pp = &player_globals.parray[p];
177   struct pending* offer = seek_globals.pendlist;
178   int type, p2;
179   char *pName = pp->name, *p2Name;
180   int decline;
181
182   if ((wd & DO_DECLINE) && (wd & DO_WITHDRAW)) { /* cut search times */
183     if (((p != -1)  && (!pp->number_pend_to)
184                     && (!pp->number_pend_from))
185         || ((p1 != -1) && (!player_globals.parray[p1].number_pend_to)
186                        && (!player_globals.parray[p1].number_pend_from)))
187       return;
188   }
189
190   if ((wd & DO_DECLINE) && (!(wd & DO_WITHDRAW))) { /* cut search times */
191     if (((p != -1) && (!pp->number_pend_to)) ||
192       ((p1 != -1) && (!player_globals.parray[p1].number_pend_from)))
193       return;
194   }
195
196   if ((!(wd & DO_DECLINE)) && (wd & DO_WITHDRAW)) { /* cut search times */
197     if (((p != -1) && (!pp->number_pend_from)) ||
198       ((p1 != -1) && (!player_globals.parray[p1].number_pend_to)))
199       return;
200   }
201
202   while (offer != NULL) {
203
204     decline = 0;
205     if ((wd & DO_DECLINE) && (check_current_pend(offer, p1, p, offers))) {
206       p2 = offer->whofrom;
207       decline = 1;
208     } else if ((wd & DO_WITHDRAW) && (check_current_pend(offer,p, p1, offers))) {
209       p2 = offer->whoto;
210     } else {
211       offer = offer->next;
212       continue;
213     }
214     
215     type = offer->type;
216     p2Name = player_globals.parray[p2].name;
217
218     switch (type) {
219       case PEND_MATCH:
220         if (partners) {
221           if (offer->game_type != TYPE_BUGHOUSE) {
222             offer = offer->next;
223             continue;
224           } else if (decline) {
225             if (offer->whoto == p) {
226               pprintf(p,
227                 "Either your opponent's partner or your partner has joined another match.\n");
228               pprintf_prompt(p,
229                 "Removing the bughouse offer from %s.\n",
230                 p2Name);
231
232               pprintf(p2,
233                 "Either your opponent's partner or your partner has joined another match.\n");
234               pprintf_prompt(p2,
235                 "Removing the bughouse offer to %s.\n",
236                 pName);
237
238             } else {
239               pprintf_prompt(p,
240                 "Your partner declines the bughouse offer from %s.\n",
241                 p2Name);
242               pprintf_prompt(p2,
243                 "%s declines the bughouse offer from your partner.\n",
244                 pName);
245             }
246
247           } else {
248             if (offer->whofrom == p) {
249               pprintf(p,
250                 "Either your opponent's partner or your partner has joined another match.\n");
251               pprintf_prompt(p,
252                 "Removing the bughouse offer to %s.\n",
253                 p2Name);
254
255               pprintf(p2,
256                 "Either your opponent's partner or your partner has joined another match.\n");
257               pprintf_prompt(p2,
258                 "Removing the bughouse offer from %s.\n",
259                 pName);
260
261             } else {
262               pprintf_prompt(p,
263                 "Your partner withdraws the bughouse offer to %s.\n",
264                 p2Name);
265               pprintf_prompt(p2,
266                 "%s withdraws the bughouse offer to your partner.\n",
267                 pName);
268             }
269           }
270         } else {
271
272           if (decline) {
273             pprintf_prompt(p2, "\n%s declines the match offer.\n", pName);
274             pprintf(p, "You decline the match offer from %s.\n", p2Name);
275           } else {
276             pprintf_prompt(p2, "\n%s withdraws the match offer.\n", pName);
277             pprintf(p, "You withdraw the match offer to %s.\n", p2Name);
278           }
279         }
280         break;
281       case PEND_DRAW:
282         if (decline) {
283           pprintf_prompt(p2, "\n%s declines draw request.\n", pName);
284           pprintf(p, "You decline the draw request from %s.\n", p2Name);
285         } else {
286           pprintf_prompt(p2, "\n%s withdraws draw request.\n", pName);
287           pprintf(p, "You withdraw the draw request to %s.\n", p2Name);
288         }
289         break;
290
291       case PEND_PAUSE:
292         if (decline) {
293           pprintf_prompt(p2, "\n%s declines pause request.\n", pName);
294           pprintf(p, "You decline the pause request from %s.\n", p2Name);
295         } else {
296           pprintf_prompt(p2, "\n%s withdraws pause request.\n", pName);
297           pprintf(p, "You withdraw the pause request to %s.\n", p2Name);
298         }
299         break;
300
301       case PEND_UNPAUSE:
302         if (decline) {
303           pprintf_prompt(p2, "\n%s declines unpause request.\n", pName);
304           pprintf(p, "You decline the unpause request from %s.\n", p2Name);
305         } else {
306           pprintf_prompt(p2, "\n%s withdraws unpause request.\n", pName);
307           pprintf(p, "You withdraw the unpause request to %s.\n", p2Name);
308         }
309         break;
310
311       case PEND_ABORT:
312         if (decline) {
313           pprintf_prompt(p2, "\n%s declines abort request.\n", pName);
314           pprintf(p, "You decline the abort request from %s.\n", p2Name);
315         } else {
316           pprintf_prompt(p2, "\n%s withdraws abort request.\n", pName);
317           pprintf(p, "You withdraw the abort request to %s.\n", p2Name);
318         }
319         break;
320
321       case PEND_TAKEBACK:
322         if (decline) {
323           pprintf_prompt(p2, "\n%s declines the takeback request.\n", pName);
324           pprintf(p, "You decline the takeback request from %s.\n", p2Name);
325         } else {
326           pprintf_prompt(p2, "\n%s withdraws the takeback request.\n", pName);
327           pprintf(p, "You withdraw the takeback request to %s.\n", p2Name);
328         }
329         break;
330
331       case PEND_ADJOURN:
332         if (decline) {
333           pprintf_prompt(p2, "\n%s declines the adjourn request.\n", pName);
334           pprintf(p, "You decline the adjourn request from %s.\n", p2Name);
335         } else {
336           pprintf_prompt(p2, "\n%s withdraws the adjourn request.\n", pName);
337           pprintf(p, "You withdraw the adjourn request to %s.\n", p2Name);
338         }
339         break;
340
341       case PEND_SWITCH:
342         if (decline) {
343           pprintf_prompt(p2, "\n%s declines the switch sides request.\n", pName);
344           pprintf(p, "You decline the switch sides request from %s.\n", p2Name);
345         } else {
346           pprintf_prompt(p2, "\n%s withdraws the switch sides request.\n", pName);
347           pprintf(p, "You withdraw the switch sides request to %s.\n", p2Name);
348         }
349         break;
350
351       case PEND_SIMUL:
352         if (decline) {
353           pprintf_prompt(p2, "\n%s declines the simul offer.\n", pName);
354           pprintf(p, "You decline the simul offer from %s.\n", p2Name);
355         } else { 
356           pprintf_prompt(p2, "\n%s withdraws the simul offer.\n", pName);
357           pprintf(p, "You withdraw the simul offer to %s.\n", p2Name);
358         }
359         break;
360
361       case PEND_PARTNER:
362         if (decline) {
363           pprintf_prompt(p2, "\n%s declines your partnership request.\n", pName);
364           pprintf(p, "You decline the partnership request from %s.\n", p2Name);
365         } else {
366           pprintf_prompt(p2, "\n%s withdraws partnership request.\n", pName);
367           pprintf(p, "You withdraw the partnership request to %s.\n", p2Name);
368         }
369         break;
370     }
371     offer = delete_pending(offer);
372   }
373 }
374
375 /* wd is DO_DECLINE to decline DO_WITHDRAW to withdraw  and both for mutual */
376 void decline_withdraw_offers(int p, int p1, int offerType,int wd)
377 {
378   struct player *pp = &player_globals.parray[p];
379   /* First get rid of bughouse offers from partner. */
380   /* last param in if is a safety check - shouldn't happen */
381
382  int partner;
383
384   if (p1 == -1)
385     partner = -1;
386   else
387     partner = player_globals.parray[p1].partner;
388
389   if ((offerType == PEND_MATCH || offerType == PEND_ALL)
390       && pp->partner >= 0 && player_globals.parray[pp->partner].partner == p)
391     do_decline_withdraw_offers(pp->partner, partner , PEND_MATCH,1,wd);
392
393
394   do_decline_withdraw_offers(p, p1, offerType,0,wd);
395 }
396
397 /* find nth offer from p */
398 static struct pending* find_nth_pendfrom(int p,int num)
399 {
400   struct pending* current = seek_globals.pendlist;
401
402   while (num) {
403     if (check_current_pend(current,p,-1,PEND_ALL))
404       num--;
405     if (num > 0)
406       current = next_pending(current);
407   }
408   return current;
409 }
410
411 /* find nth offer to p */
412 static struct pending* find_nth_pendto(int p,int num)
413 {
414   struct pending* current = seek_globals.pendlist;
415
416   while (num) {
417     if (check_current_pend(current,-1,p,PEND_ALL))
418       num--;
419     if (num > 0)
420       current = next_pending(current);
421   }
422   return current;
423 }
424
425 static int WordToOffer (int p, char *Word, int *type, int *p1)
426 {
427   /* Convert draw adjourn match takeback abort pause
428      simmatch switch partner or <name> to offer type. */
429   *p1 = -1;
430   if (!strcmp(Word, "match")) {
431     *type = PEND_MATCH;
432   } else if (!strcmp(Word, "draw")) {
433     *type = PEND_DRAW;
434   } else if (!strcmp(Word, "pause")) {
435     *type = PEND_PAUSE;
436   } else if (!strcmp(Word, "unpause")) {
437     *type = PEND_UNPAUSE;
438   } else if (!strcmp(Word, "abort")) {
439     *type = PEND_ABORT;
440   } else if (!strcmp(Word, "takeback")) {
441     *type = PEND_TAKEBACK;
442   } else if (!strcmp(Word, "adjourn")) {
443     *type = PEND_ADJOURN;
444   } else if (!strcmp(Word, "switch")) {
445     *type = PEND_SWITCH;
446   } else if (!strcmp(Word, "simul")) {
447     *type = PEND_SIMUL;
448   } else if (!strcmp(Word, "partner")) {
449     *type = PEND_PARTNER;
450   } else if (!strcmp(Word, "all")) {
451   } else {
452     *p1 = player_find_part_login(Word);
453     if (*p1 < 0) {
454       pprintf(p, "No user named \"%s\" is logged in.\n", Word);
455       return 0;
456     }
457   }
458   return 1;
459 }
460
461 int com_accept(int p, param_list param)
462 {
463   struct player *pp = &player_globals.parray[p];
464   int type = -1;
465   int p1;
466   int number; 
467   struct pending* current = NULL;
468
469   if (!(number = pp->number_pend_to)) {
470     pprintf(p, "You have no offers to accept.\n");
471     return COM_OK;
472   }
473
474   if (param[0].type == TYPE_NULL) {
475     if (number != 1) {
476       pprintf(p, "You have more than one offer to accept.\nUse \"pending\" to see them and \"accept n\" to choose which one.\n");
477       return COM_OK;
478     }
479     current = find_pend(-1,p,PEND_ALL);
480
481   } else if (param[0].type == TYPE_INT) {
482     if ((param[0].val.integer < 1) || (param[0].val.integer > number)) {
483       pprintf(p, "Out of range. Use \"pending\" to see the list of offers.\n");
484       return COM_OK;
485     }
486
487     current = find_nth_pendto(p,param[0].val.integer);
488
489   } else if (param[0].type == TYPE_WORD) {
490     if (!WordToOffer (p,param[0].val.word,&type,&p1))
491       return COM_OK;
492     if ((p1 < 0) && ((current = find_pend(-1, p, type)) == NULL)) {
493       pprintf(p, "There are no pending %s offers.\n", param[0].val.word);
494       return COM_OK;
495     } else if ((p1 >= 0) && (current = find_pend(p1, p, PEND_ALL)) == NULL) {
496       pprintf(p, "There are no pending offers from %s.\n", player_globals.parray[p1].name);
497       return COM_OK;
498     }
499   }
500
501   switch (current->type) {
502     case PEND_MATCH:
503       accept_match(current, p, current->whofrom);
504       return (COM_OK);
505       break;
506     case PEND_DRAW:
507       pcommand(p, "draw");
508       break;
509     case PEND_PAUSE:
510       pcommand(p, "pause");
511       break;
512     case PEND_UNPAUSE:
513       pcommand(p, "unpause");
514       break;
515     case PEND_ABORT:
516       pcommand(p, "abort");
517       break;
518     case PEND_TAKEBACK:
519       pcommand(p, "takeback %d", current->wtime);
520       break;
521     case PEND_SIMUL:
522       pcommand(p, "simmatch %s", player_globals.parray[current->whofrom].name);
523       break;
524     case PEND_SWITCH:
525       pcommand(p, "switch");
526       break;
527     case PEND_ADJOURN:
528       pcommand(p, "adjourn");
529       break;
530     case PEND_PARTNER:
531       pcommand(p, "partner %s", player_globals.parray[current->whofrom].name);
532       break;
533   }
534   return COM_OK_NOPROMPT;
535 }
536
537 static int com_decline_withdraw(int p, param_list param,int wd)
538 {
539   struct player *pp = &player_globals.parray[p];
540   int type = -1;
541   int p1;
542   int number;
543   struct pending* current = seek_globals.pendlist;
544
545   if (wd & DO_DECLINE) {
546     if (!(number = pp->number_pend_to)) {
547       pprintf(p, "You have no pending offers from other players.\n");
548       return COM_OK;
549     }
550   } else {
551     if (!(number = pp->number_pend_from)) {
552       pprintf(p, "You have no pending offers to other players.\n");
553       return COM_OK;
554     }
555   }
556
557
558   if (param[0].type == TYPE_NULL) {
559     if (number == 1) {
560       if (wd & DO_DECLINE) {
561         current = find_pend(-1,p,PEND_ALL);
562         p1 = current->whofrom;
563       } else {
564         current = find_pend(p,-1,PEND_ALL);
565         p1 = current->whoto;
566       }
567        type = current->type;
568     } else { 
569       if (wd & DO_DECLINE)
570         pprintf(p, "You have more than one pending offer.\nUse \"pending\" to see them and \"decline n\" to choose which one.\n");
571       else 
572         pprintf(p, "You have more than one pending offer.\nUse \"pending\" to see them and \"withdraw n\" to choose which one.\n");
573       return COM_OK;
574     }
575
576   } else if (param[0].type == TYPE_INT) {
577     if ((param[0].val.integer < 1) || (param[0].val.integer > number)) {
578       pprintf(p, "Out of range. Use \"pending\" to see the list of offers.\n");
579       return COM_OK;
580     }
581     if (wd & DO_DECLINE) {
582       current = find_nth_pendto(p,param[0].val.integer);
583       p1 = current->whofrom;
584     } else {
585       current = find_nth_pendfrom(p,param[0].val.integer);
586       p1 = current->whoto;
587     }
588     type = current->type;
589
590   } else if (!WordToOffer (p, param[0].val.word, &type, &p1))
591     return COM_OK;
592
593   decline_withdraw_offers(p, p1, type,wd);
594   return COM_OK;
595 }
596
597 int com_decline(int p, param_list param)
598 {
599  return com_decline_withdraw(p,param,DO_DECLINE);
600 }
601
602 int com_withdraw(int p, param_list param)
603 {
604  return com_decline_withdraw(p,param,DO_WITHDRAW);
605 }
606
607 static void pend_print(int p, struct pending *pend)
608 {
609
610   if (p == pend->whofrom) {
611     pprintf(p, "You are offering %s ", player_globals.parray[pend->whoto].name);
612   } else {
613     pprintf(p, "%s is offering ", player_globals.parray[pend->whofrom].name);
614   }
615
616   switch (pend->type) {
617   case PEND_MATCH:
618     pprintf(p, "a challenge: %s (%s) %s%s (%s) %s.\n",
619           player_globals.parray[pend->whofrom].name,
620           ratstrii(GetRating(&player_globals.parray[pend->whofrom], pend->game_type),
621                    pend->whofrom),
622           colorstr[pend->seek_color + 1], 
623           player_globals.parray[pend->whoto].name,
624           ratstrii(GetRating(&player_globals.parray[pend->whoto], pend->game_type),
625                    pend->whoto),
626           game_str(pend->rated, pend->wtime * 60, pend->winc,
627                    pend->btime * 60, pend->binc, pend->category, pend->board_type));
628     break;
629   case PEND_DRAW:
630     pprintf(p, "a draw.\n");
631     break;
632   case PEND_PAUSE:
633     pprintf(p, "to pause the clock.\n");
634     break;
635   case PEND_UNPAUSE:
636     pprintf(p, "to unpause the clock.\n");
637     break;
638   case PEND_ABORT:
639     pprintf(p, "to abort the game.\n");
640     break;
641   case PEND_TAKEBACK:
642     pprintf(p, "to takeback the last %d half moves.\n", pend->wtime);
643     break;
644   case PEND_SIMUL:
645     pprintf(p, "to play a simul match.\n");
646     break;
647   case PEND_SWITCH:
648     pprintf(p, "to switch sides.\n");
649     break;
650   case PEND_ADJOURN:
651     pprintf(p, "an adjournment.\n");
652     break;
653   case PEND_PARTNER:
654     pprintf(p, "to be bughouse partners.\n");
655     break;
656   }
657 }
658
659 int com_pending(int p, param_list param)
660 {
661   struct player *pp = &player_globals.parray[p];
662   struct pending* current = seek_globals.pendlist;
663   int num = 0;
664   int num2 = 0; 
665   int total = 0;
666
667   if ((total = pp->number_pend_from)) {
668     while ((current != NULL) && (num != total)) {
669       if (check_current_pend(current,p,-1,PEND_ALL)) {
670         if (!num)
671           pprintf(p, "Offers TO other players:\n");
672         num++;
673         pprintf(p, " %d: ",num);
674         pend_print(p, current); 
675       }
676       current = next_pending(current);
677     }
678     pprintf(p, "\nIf you wish to withdraw any of these offers type 'withdraw n'\nor just 'withdraw' if there is only one offer.\n\n");
679   } else
680     pprintf(p, "There are no offers pending TO other players.\n\n");
681
682   current = seek_globals.pendlist;
683
684   if ((total = pp->number_pend_to)) {
685     while ((current != NULL) && (num2 != total)) {
686       if (check_current_pend(current,-1,p,PEND_ALL)) {
687         if (!num2)
688           pprintf(p, "Offers FROM other players:\n");
689         num2++;
690         pprintf(p, " %d: ",num2);
691         pend_print(p, current);
692       }
693       current = next_pending(current);
694     }
695     pprintf(p, "\nIf you wish to accept any of these offers type 'accept n'\nor just 'accept' if there is only one offer.\n");
696   } else 
697     pprintf(p, "There are no offers pending FROM other players.\n");
698
699   return COM_OK;
700 }
701
702 void pend_join_match (int p, int p1)
703 {
704   struct player *pp = &player_globals.parray[p];
705   struct pending* current;
706   struct pending* next = seek_globals.pendlist; 
707
708   if ((pp->number_pend_from == 0) && (pp->number_pend_to == 0)
709       && (player_globals.parray[p1].number_pend_from == 0) && (player_globals.parray[p1].number_pend_to == 0))
710     return;
711
712   while (next != NULL) {
713     current = next;
714     next = next_pending(current);
715     if (check_current_pend(current,p,-1,-PEND_PARTNER)) {
716       pprintf_prompt(current->whoto, "\n%s, who was challenging you, has joined a match with %s.\n", pp->name, player_globals.parray[p1].name); 
717       pprintf(p, "Challenge to %s withdrawn.\n", player_globals.parray[current->whoto].name);
718       delete_pending(current);
719       continue;
720     }
721
722     if (check_current_pend(current,p1,-1,-PEND_PARTNER)) {
723       pprintf_prompt(current->whoto, "\n%s, who was challenging you, has joined a match with %s.\n", player_globals.parray[p1].name, pp->name);
724       pprintf(p1, "Challenge to %s withdrawn.\n", player_globals.parray[current->whoto].name);
725       delete_pending(current);
726       continue;
727     }
728
729     if (check_current_pend(current,-1,p,-PEND_PARTNER)) {
730       pprintf_prompt(current->whofrom, "\n%s, whom you were challenging, has joined a match with %s.\n", pp->name, player_globals.parray[p1].name);
731       pprintf(p, "Challenge from %s removed.\n", player_globals.parray[current->whofrom].name);
732       delete_pending(current);
733       continue;
734     }
735
736     if (check_current_pend(current,-1,p1,-PEND_PARTNER)) {
737       pprintf_prompt(current->whofrom, "\n%s, whom you were challenging, has joined a match with %s.\n", player_globals.parray[p1].name, pp->name);
738       pprintf(p1, "Challenge from %s removed.\n",
739               player_globals.parray[current->whofrom].name);
740       delete_pending(current);
741       continue;
742     }
743   }
744 }