e065cef529327563f30215da30880be57cc80a48
[capablanca.git] / lasker-2.2.3 / src / seekproc.c
1 /*
2    Copyright (c) 2000 Dan Papasian
3    Copyright (C) Andrew Tridgell 2002
4    
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "includes.h"
21
22 enum { SEEKOPEN = 0, SEEKCLOSED };
23
24 /* The values of the follwing enums cannot be changed as they will end up */
25 /* Being seen by the client- we can add values later but the ones */
26 /* Here, after being documented, have to be here forever */
27 enum { LIGHTNING = 0, STANDARD, BLITZ, UNTIMED };
28
29 #undef BLACK
30 #undef WHITE
31 enum { BLACK = 0, WHITE};
32
33
34 static int get_empty_seekslot(void);
35 static char *form_ad(struct pending * ad, int i);
36
37 int com_seek(int p, param_list param)
38 {
39         struct player *pp = &player_globals.parray[p];
40         int             p1, count = 0;
41         int             num;    /* sought ID */
42         char           *msgtxt;
43         char            board[1], category[1];
44
45         
46         srandom(time(0));
47 #if 0
48         if (!CheckPFlag(p, PFLAG_REG)) {
49                 pprintf(p, "Only registered players can use the seek command.\n");
50                 return COM_OK;
51         }
52 #endif
53
54         if ((pp->game >= 0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE) || (game_globals.garray[pp->game].status == GAME_SETUP))) {
55                 pprintf(p, "ERROR: You can't seek a game while you are examining one.\n");
56                 return COM_OK;
57         }
58         if (pp->game >= 0) {
59                 pprintf(p, "ERROR: You can't seek a game while you are playing one.\n");
60                 return COM_OK;
61         }
62         num = get_empty_seekslot();
63         if (num == -1) {
64                 pprintf(p, "ERROR: Sorry, all available slots for seek are closed.\n");
65                 return COM_OK;
66         }
67         seek_globals.ads[num].status = SEEKCLOSED;
68         seek_globals.ads[num].whofrom = p;
69
70         if (param[0].type == TYPE_INT)
71                 seek_globals.ads[num].wtime = param[0].val.integer;     /* White time */
72         else
73                 seek_globals.ads[num].wtime = pp->d_time;
74
75         if (param[1].type == TYPE_INT)
76                 seek_globals.ads[num].winc = param[1].val.integer;      /* White increment */
77         else
78                 seek_globals.ads[num].winc = pp->d_inc;
79
80         seek_globals.ads[num].btime = seek_globals.ads[num].wtime;      /* Black time */
81         seek_globals.ads[num].binc = seek_globals.ads[num].winc;        /* Black increment */
82
83         if (param[2].type == TYPE_INT) {
84                 if (param[2].val.integer == UNRATED || !CheckPFlag(p, PFLAG_REG) || seek_globals.ads[num].wtime == 0)
85                         seek_globals.ads[num].rated = UNRATED;  /* unrated */
86                 else if (param[2].val.integer == RATED)
87                         seek_globals.ads[num].rated = RATED;    /* rated */
88         } else
89                 seek_globals.ads[num].rated = BoolCheckPFlag(p, PFLAG_RATED);
90
91
92         if (param[3].type == TYPE_INT) {
93                 if (param[3].val.integer == WHITE)
94                         seek_globals.ads[num].seek_color = WHITE;
95                 else if (param[3].val.word[0] == BLACK)
96                         seek_globals.ads[num].seek_color = BLACK;
97         } else
98                 seek_globals.ads[num].seek_color = random() % 2;
99
100         category[0]='\0';
101         board[0]='\0';
102         /* FIXME- use proper values */
103         seek_globals.ads[num].category = strdup(category);
104         seek_globals.ads[num].board_type = strdup(board);
105
106         seek_globals.ads[num].next = NULL;
107
108         msgtxt = form_ad(&seek_globals.ads[num], num);
109
110         for (p1 = 0; p1 < player_globals.p_num; p1++) {
111                 if ((p1 == p) || !CheckPFlag(p1, PFLAG_ADS)
112                   || (player_globals.parray[p1].status != PLAYER_PROMPT)
113                   || (player_censored(p1, p)))
114                         continue;
115                 count++;
116                 pprintf(p1, "%s", msgtxt);
117         }
118         pprintf(p, "%s", msgtxt);
119         free(msgtxt);
120
121         return COM_OK;
122 }
123
124 int com_play(int p, param_list param)
125 {
126         int             game;
127
128         game = param[0].val.integer;
129
130         if (seek_globals.ads[game].status != SEEKCLOSED) {
131                 pprintf(p, "ERROR: Either that game has already started or "
132                         "it is no longer available.\n");
133                 return COM_OK;
134         }
135         if (!CheckPFlag(p, PFLAG_REG) && seek_globals.ads[game].rated == 1) {
136                 pprintf(p, "ERROR: Unregistred users cannot play rated games.\n");
137                 return COM_OK;
138         }
139         if (seek_globals.ads[game].whofrom == p) {
140                 pprintf(p, "ERROR: You cannot respond to your own seek ads\n");
141                 return COM_OK;
142         }
143         seek_globals.ads[game].whoto = p;
144
145         decline_withdraw_offers(p, -1, PEND_ALL, DO_DECLINE | DO_WITHDRAW); 
146         decline_withdraw_offers(seek_globals.ads[game].whofrom, -1, PEND_ALL, DO_DECLINE | DO_WITHDRAW);
147
148         accept_match(&seek_globals.ads[game], p, seek_globals.ads[game].whofrom);
149 #if 0
150         free(seek_globals.ads[game].category);
151         free(seek_globals.ads[game].board_type);
152 #endif
153 return 0;
154 }
155
156 int com_sought(int p, param_list param)
157 {
158         int             i;
159
160         for (i = 0; i < seek_globals.max_ads; i++) {
161                 if (seek_globals.ads[i].status == SEEKCLOSED) {
162                         char *msgtxt = form_ad(&seek_globals.ads[i], i);
163                         pprintf(p, "%s", msgtxt);
164                         free(msgtxt);
165                 }
166         }
167         return COM_OK;
168 }
169
170
171 int com_unseek(int p, param_list param)
172 {
173         /* TODO: need to add parameters */
174         withdraw_seeks(p);
175         return COM_OK;
176 }
177
178 void withdraw_seeks(int p)
179 {
180         int             i, p1;
181
182         for (i = 0; i < seek_globals.max_ads; i++) {
183                 if (seek_globals.ads[i].whofrom == p && 
184                     seek_globals.ads[i].status == SEEKCLOSED) {
185                         seek_globals.ads[i].status = SEEKOPEN;
186
187                         for (p1 = 0; p1 < player_globals.p_num; p1++) {
188                                 if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT) ||
189                                     (player_censored(p1, p)) || !CheckPFlag(p1,PFLAG_ADS))
190                                         continue;
191                                 pprintf_prompt(p1, "AD_DESTROY: %d\n", i);
192                         }
193                         pprintf(p, "AD_DESTROY: %d\n", i);
194                         FREE(seek_globals.ads[i].category);
195                         FREE(seek_globals.ads[i].board_type);
196                 }
197         }
198 }
199
200 static int get_empty_seekslot(void)
201 {
202         int i;
203
204         for (i = 0; i < seek_globals.max_ads; i++) {
205                 if (seek_globals.ads[i].status != SEEKCLOSED) 
206                         return i;
207         }
208
209         if (seek_globals.max_ads >= config_get_int("MAX_SOUGHT", DEFAULT_MAX_SOUGHT)) {
210                 d_printf("Too many seeks! please raise MAX_SOUGHT\n");
211                 return -1;
212         }
213
214         seek_globals.max_ads += 100;
215         seek_globals.ads = (struct pending *)realloc(seek_globals.ads,
216                                                      seek_globals.max_ads * sizeof(struct pending));
217         
218         ZERO_STRUCT(seek_globals.ads[i]);
219         return i;
220
221 }
222
223 static char *form_ad(struct pending * ad, int i)
224 {
225
226         char           *final;
227         int             rating, total, type;
228
229         total = ad->wtime * 60 + ad->winc * 40;
230
231         if(total == 0) {
232                 type = UNTIMED;
233                 rating = player_globals.parray[ad->whofrom].l_stats.rating;
234         } else if (total < 180) {
235                 type = LIGHTNING;
236                 rating = player_globals.parray[ad->whofrom].l_stats.rating;
237         } else if (total >= 900) {
238                 type = STANDARD; 
239                 rating = player_globals.parray[ad->whofrom].s_stats.rating;
240         } else {
241                 type = BLITZ;
242                 rating = player_globals.parray[ad->whofrom].b_stats.rating;
243         }
244
245         asprintf(&final, "%3u %4u %-17s %3u %3u %-7s %-10s\n",
246                  i, 
247                  rating,
248                  player_globals.parray[ad->whofrom].name, 
249                  ad->wtime, 
250                  ad->winc, 
251                  ad->rated?"rated":"unrated",
252                  TypeStrings[ad->seek_color]);
253
254         return final;
255 }