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.
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.
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.
20 Sat Feb 10 - created - DAV
25 extern const char *colorstr[];
27 /* iterator for player p */
28 static struct pending* next_pending(struct pending* current)
31 if (current == NULL) {
32 d_printf("NULL pointer passed to next_pending\n");
34 } else return current->next;
37 /* deletor for pending - returns next item*/
38 struct pending *delete_pending(struct pending *current)
42 if (current == NULL) {
43 d_printf("NULL pointer passed to delete_pending\n");
47 player_globals.parray[current->whofrom].number_pend_from--;
48 player_globals.parray[current->whoto].number_pend_to--;
50 if (current->category != NULL) {
51 free(current->category);
53 if (current->board_type != NULL) {
54 free(current->board_type);
57 if (current == seek_globals.pendlist) {
58 seek_globals.pendlist = current->next;
60 return seek_globals.pendlist;
63 for (p=seek_globals.pendlist; p && p->next != current; p=p->next) ;
66 d_printf("current not on pending list??");
70 p->next = current->next;
75 /* kills the whole pending list on shutdown */
76 void destruct_pending(void)
78 struct pending* current = seek_globals.pendlist;
80 while (current != NULL)
81 current = delete_pending(current);
84 struct pending *add_pending(int from,int to,int type)
86 struct pending* new = (struct pending*) malloc(sizeof(struct pending));
91 new->next = seek_globals.pendlist;
93 new->board_type = NULL;
95 player_globals.parray[from].number_pend_from++;
96 player_globals.parray[to].number_pend_to++;
98 seek_globals.pendlist = new;
103 static int check_current_pend(struct pending* current, int p, int p1, int type)
105 if ((p != -1) && ((current->whofrom) != p))
107 if (current->whoto != p1 && p1 != -1)
109 if ((type == PEND_ALL) || (current->type == type))
111 if ((type < 0) && (current->type != -type))
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.
122 struct pending *find_pend(int p, int p1, int type)
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;
128 if (((p != -1) && (!pp->number_pend_from)) ||
129 ((p1 != -1) && (!player_globals.parray[p1].number_pend_to)))
132 while (current != NULL) {
133 if (check_current_pend(current,p,p1, type))
135 current = next_pending(current);
141 struct pending *add_request(int p, int p1, int type)
143 struct player *pp = &player_globals.parray[p];
144 struct pending* new = NULL;
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 */
152 if ((new = add_pending(p,p1,type)) == NULL)
157 /* removes all requests from p to p1 */
158 void remove_request(int p, int p1, int type)
160 struct pending* next;
161 struct pending* current = seek_globals.pendlist;
163 while (current != NULL) {
164 next = next_pending(current);
165 if (check_current_pend(current,p,p1,type))
166 delete_pending(current);
171 /* made into 1 functions for speed */
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)
176 struct player *pp = &player_globals.parray[p];
177 struct pending* offer = seek_globals.pendlist;
179 char *pName = pp->name, *p2Name;
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)))
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)))
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)))
202 while (offer != NULL) {
205 if ((wd & DO_DECLINE) && (check_current_pend(offer, p1, p, offers))) {
208 } else if ((wd & DO_WITHDRAW) && (check_current_pend(offer,p, p1, offers))) {
216 p2Name = player_globals.parray[p2].name;
221 if (offer->game_type != TYPE_BUGHOUSE) {
224 } else if (decline) {
225 if (offer->whoto == p) {
227 "Either your opponent's partner or your partner has joined another match.\n");
229 "Removing the bughouse offer from %s.\n",
233 "Either your opponent's partner or your partner has joined another match.\n");
235 "Removing the bughouse offer to %s.\n",
240 "Your partner declines the bughouse offer from %s.\n",
243 "%s declines the bughouse offer from your partner.\n",
248 if (offer->whofrom == p) {
250 "Either your opponent's partner or your partner has joined another match.\n");
252 "Removing the bughouse offer to %s.\n",
256 "Either your opponent's partner or your partner has joined another match.\n");
258 "Removing the bughouse offer from %s.\n",
263 "Your partner withdraws the bughouse offer to %s.\n",
266 "%s withdraws the bughouse offer to your partner.\n",
273 pprintf_prompt(p2, "\n%s declines the match offer.\n", pName);
274 pprintf(p, "You decline the match offer from %s.\n", p2Name);
276 pprintf_prompt(p2, "\n%s withdraws the match offer.\n", pName);
277 pprintf(p, "You withdraw the match offer to %s.\n", p2Name);
283 pprintf_prompt(p2, "\n%s declines draw request.\n", pName);
284 pprintf(p, "You decline the draw request from %s.\n", p2Name);
286 pprintf_prompt(p2, "\n%s withdraws draw request.\n", pName);
287 pprintf(p, "You withdraw the draw request to %s.\n", p2Name);
293 pprintf_prompt(p2, "\n%s declines pause request.\n", pName);
294 pprintf(p, "You decline the pause request from %s.\n", p2Name);
296 pprintf_prompt(p2, "\n%s withdraws pause request.\n", pName);
297 pprintf(p, "You withdraw the pause request to %s.\n", p2Name);
303 pprintf_prompt(p2, "\n%s declines unpause request.\n", pName);
304 pprintf(p, "You decline the unpause request from %s.\n", p2Name);
306 pprintf_prompt(p2, "\n%s withdraws unpause request.\n", pName);
307 pprintf(p, "You withdraw the unpause request to %s.\n", p2Name);
313 pprintf_prompt(p2, "\n%s declines abort request.\n", pName);
314 pprintf(p, "You decline the abort request from %s.\n", p2Name);
316 pprintf_prompt(p2, "\n%s withdraws abort request.\n", pName);
317 pprintf(p, "You withdraw the abort request to %s.\n", p2Name);
323 pprintf_prompt(p2, "\n%s declines the takeback request.\n", pName);
324 pprintf(p, "You decline the takeback request from %s.\n", p2Name);
326 pprintf_prompt(p2, "\n%s withdraws the takeback request.\n", pName);
327 pprintf(p, "You withdraw the takeback request to %s.\n", p2Name);
333 pprintf_prompt(p2, "\n%s declines the adjourn request.\n", pName);
334 pprintf(p, "You decline the adjourn request from %s.\n", p2Name);
336 pprintf_prompt(p2, "\n%s withdraws the adjourn request.\n", pName);
337 pprintf(p, "You withdraw the adjourn request to %s.\n", p2Name);
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);
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);
353 pprintf_prompt(p2, "\n%s declines the simul offer.\n", pName);
354 pprintf(p, "You decline the simul offer from %s.\n", p2Name);
356 pprintf_prompt(p2, "\n%s withdraws the simul offer.\n", pName);
357 pprintf(p, "You withdraw the simul offer to %s.\n", p2Name);
363 pprintf_prompt(p2, "\n%s declines your partnership request.\n", pName);
364 pprintf(p, "You decline the partnership request from %s.\n", p2Name);
366 pprintf_prompt(p2, "\n%s withdraws partnership request.\n", pName);
367 pprintf(p, "You withdraw the partnership request to %s.\n", p2Name);
371 offer = delete_pending(offer);
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)
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 */
387 partner = player_globals.parray[p1].partner;
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);
394 do_decline_withdraw_offers(p, p1, offerType,0,wd);
397 /* find nth offer from p */
398 static struct pending* find_nth_pendfrom(int p,int num)
400 struct pending* current = seek_globals.pendlist;
403 if (check_current_pend(current,p,-1,PEND_ALL))
406 current = next_pending(current);
411 /* find nth offer to p */
412 static struct pending* find_nth_pendto(int p,int num)
414 struct pending* current = seek_globals.pendlist;
417 if (check_current_pend(current,-1,p,PEND_ALL))
420 current = next_pending(current);
425 static int WordToOffer (int p, char *Word, int *type, int *p1)
427 /* Convert draw adjourn match takeback abort pause
428 simmatch switch partner or <name> to offer type. */
430 if (!strcmp(Word, "match")) {
432 } else if (!strcmp(Word, "draw")) {
434 } else if (!strcmp(Word, "pause")) {
436 } else if (!strcmp(Word, "unpause")) {
437 *type = PEND_UNPAUSE;
438 } else if (!strcmp(Word, "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")) {
446 } else if (!strcmp(Word, "simul")) {
448 } else if (!strcmp(Word, "partner")) {
449 *type = PEND_PARTNER;
450 } else if (!strcmp(Word, "all")) {
452 *p1 = player_find_part_login(Word);
454 pprintf(p, "No user named \"%s\" is logged in.\n", Word);
461 int com_accept(int p, param_list param)
463 struct player *pp = &player_globals.parray[p];
467 struct pending* current = NULL;
469 if (!(number = pp->number_pend_to)) {
470 pprintf(p, "You have no offers to accept.\n");
474 if (param[0].type == TYPE_NULL) {
476 pprintf(p, "You have more than one offer to accept.\nUse \"pending\" to see them and \"accept n\" to choose which one.\n");
479 current = find_pend(-1,p,PEND_ALL);
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");
487 current = find_nth_pendto(p,param[0].val.integer);
489 } else if (param[0].type == TYPE_WORD) {
490 if (!WordToOffer (p,param[0].val.word,&type,&p1))
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);
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);
501 switch (current->type) {
503 accept_match(current, p, current->whofrom);
510 pcommand(p, "pause");
513 pcommand(p, "unpause");
516 pcommand(p, "abort");
519 pcommand(p, "takeback %d", current->wtime);
522 pcommand(p, "simmatch %s", player_globals.parray[current->whofrom].name);
525 pcommand(p, "switch");
528 pcommand(p, "adjourn");
531 pcommand(p, "partner %s", player_globals.parray[current->whofrom].name);
534 return COM_OK_NOPROMPT;
537 static int com_decline_withdraw(int p, param_list param,int wd)
539 struct player *pp = &player_globals.parray[p];
543 struct pending* current = seek_globals.pendlist;
545 if (wd & DO_DECLINE) {
546 if (!(number = pp->number_pend_to)) {
547 pprintf(p, "You have no pending offers from other players.\n");
551 if (!(number = pp->number_pend_from)) {
552 pprintf(p, "You have no pending offers to other players.\n");
558 if (param[0].type == TYPE_NULL) {
560 if (wd & DO_DECLINE) {
561 current = find_pend(-1,p,PEND_ALL);
562 p1 = current->whofrom;
564 current = find_pend(p,-1,PEND_ALL);
567 type = current->type;
570 pprintf(p, "You have more than one pending offer.\nUse \"pending\" to see them and \"decline n\" to choose which one.\n");
572 pprintf(p, "You have more than one pending offer.\nUse \"pending\" to see them and \"withdraw n\" to choose which one.\n");
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");
581 if (wd & DO_DECLINE) {
582 current = find_nth_pendto(p,param[0].val.integer);
583 p1 = current->whofrom;
585 current = find_nth_pendfrom(p,param[0].val.integer);
588 type = current->type;
590 } else if (!WordToOffer (p, param[0].val.word, &type, &p1))
593 decline_withdraw_offers(p, p1, type,wd);
597 int com_decline(int p, param_list param)
599 return com_decline_withdraw(p,param,DO_DECLINE);
602 int com_withdraw(int p, param_list param)
604 return com_decline_withdraw(p,param,DO_WITHDRAW);
607 static void pend_print(int p, struct pending *pend)
610 if (p == pend->whofrom) {
611 pprintf(p, "You are offering %s ", player_globals.parray[pend->whoto].name);
613 pprintf(p, "%s is offering ", player_globals.parray[pend->whofrom].name);
616 switch (pend->type) {
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),
622 colorstr[pend->seek_color + 1],
623 player_globals.parray[pend->whoto].name,
624 ratstrii(GetRating(&player_globals.parray[pend->whoto], pend->game_type),
626 game_str(pend->rated, pend->wtime * 60, pend->winc,
627 pend->btime * 60, pend->binc, pend->category, pend->board_type));
630 pprintf(p, "a draw.\n");
633 pprintf(p, "to pause the clock.\n");
636 pprintf(p, "to unpause the clock.\n");
639 pprintf(p, "to abort the game.\n");
642 pprintf(p, "to takeback the last %d half moves.\n", pend->wtime);
645 pprintf(p, "to play a simul match.\n");
648 pprintf(p, "to switch sides.\n");
651 pprintf(p, "an adjournment.\n");
654 pprintf(p, "to be bughouse partners.\n");
659 int com_pending(int p, param_list param)
661 struct player *pp = &player_globals.parray[p];
662 struct pending* current = seek_globals.pendlist;
667 if ((total = pp->number_pend_from)) {
668 while ((current != NULL) && (num != total)) {
669 if (check_current_pend(current,p,-1,PEND_ALL)) {
671 pprintf(p, "Offers TO other players:\n");
673 pprintf(p, " %d: ",num);
674 pend_print(p, current);
676 current = next_pending(current);
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");
680 pprintf(p, "There are no offers pending TO other players.\n\n");
682 current = seek_globals.pendlist;
684 if ((total = pp->number_pend_to)) {
685 while ((current != NULL) && (num2 != total)) {
686 if (check_current_pend(current,-1,p,PEND_ALL)) {
688 pprintf(p, "Offers FROM other players:\n");
690 pprintf(p, " %d: ",num2);
691 pend_print(p, current);
693 current = next_pending(current);
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");
697 pprintf(p, "There are no offers pending FROM other players.\n");
702 void pend_join_match (int p, int p1)
704 struct player *pp = &player_globals.parray[p];
705 struct pending* current;
706 struct pending* next = seek_globals.pendlist;
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))
712 while (next != NULL) {
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);
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);
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);
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);