Fix crash after recursive aliasing
[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 { UNTIMED = 0, BLITZ, STANDARD, NONSTANDARD, WILD, LIGHTNING };
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[100], category[100];
44         int             wt, bt, winc, binc, rated, white;
45
46         
47         srandom(time(0));
48 #if 0
49         if (!CheckPFlag(p, PFLAG_REG)) {
50                 pprintf(p, "Only registered players can use the seek command.\n");
51                 return COM_OK;
52         }
53 #endif
54
55         if ((pp->game >= 0) && ((game_globals.garray[pp->game].status == GAME_EXAMINE) || (game_globals.garray[pp->game].status == GAME_SETUP))) {
56                 pprintf(p, "ERROR: You can't seek a game while you are examining one.\n");
57                 return COM_OK;
58         }
59         if (pp->game >= 0) {
60                 pprintf(p, "ERROR: You can't seek a game while you are playing one.\n");
61                 return COM_OK;
62         }
63         num = get_empty_seekslot();
64         if (num == -1) {
65                 pprintf(p, "ERROR: Sorry, all available slots for seek are closed.\n");
66                 return COM_OK;
67         }
68         seek_globals.ads[num].whofrom = p;
69
70 #if 1
71         // [HGM] attempt to make seek as powerful as match
72         wt = bt = winc = binc = -1;
73         board[0] = category[0] = '\0';
74         white = rated = -1;
75         if (param[0].type != TYPE_NULL) {
76               if (!parse_match_string(p, &wt,&bt,&winc,&binc,&white,&rated,category,
77                                                           board,param[0].val.string))
78               return COM_OK; /* couldn't parse */
79         }
80
81     if (category[0]) {
82       if (!board[0] && strcmp(category,"bughouse")) {
83         pprintf(p, "You must specify a board and a category.\n");
84         return COM_OK;
85
86       } else if (board[0]) { /* not bughouse */
87         char fname[MAX_FILENAME_SIZE];
88
89         sprintf(fname, "%s/%s/%s", BOARD_DIR, category, board);
90         if (!file_exists(fname)) {
91           pprintf(p, "No such category/board: %s/%s\n", category, board);
92           return COM_OK;
93         }
94       }
95     }
96
97         seek_globals.ads[num].status = SEEKCLOSED; // params are valid; create ad
98
99         if(wt < 0) wt = pp->d_time; if(bt < 0) bt = wt;
100         if(winc < 0) winc = pp->d_inc; if(binc < 0) binc = bt;
101         seek_globals.ads[num].wtime = wt;
102         seek_globals.ads[num].btime = bt;
103         seek_globals.ads[num].winc = winc;
104         seek_globals.ads[num].binc = binc;
105
106         if (rated != -1) {
107                 if (!rated || !CheckPFlag(p, PFLAG_REG) || seek_globals.ads[num].wtime == 0)
108                         seek_globals.ads[num].rated = UNRATED;  /* unrated */
109                 else if (rated)
110                         seek_globals.ads[num].rated = RATED;    /* rated */
111         } else
112                 seek_globals.ads[num].rated = BoolCheckPFlag(p, PFLAG_RATED);
113
114
115         if (white != -1) {
116                 seek_globals.ads[num].seek_color = white ? WHITE : BLACK;
117         } else
118                 seek_globals.ads[num].seek_color = random() % 2;
119
120 #else
121         seek_globals.ads[num].status = SEEKCLOSED;
122
123         if (param[0].type == TYPE_INT)
124                 seek_globals.ads[num].wtime = param[0].val.integer;     /* White time */
125         else
126                 seek_globals.ads[num].wtime = pp->d_time;
127
128         if (param[1].type == TYPE_INT)
129                 seek_globals.ads[num].winc = param[1].val.integer;      /* White increment */
130         else
131                 seek_globals.ads[num].winc = pp->d_inc;
132
133         seek_globals.ads[num].btime = seek_globals.ads[num].wtime;      /* Black time */
134         seek_globals.ads[num].binc = seek_globals.ads[num].winc;        /* Black increment */
135
136         if (param[2].type == TYPE_INT) {
137                 if (param[2].val.integer == UNRATED || !CheckPFlag(p, PFLAG_REG) || seek_globals.ads[num].wtime == 0)
138                         seek_globals.ads[num].rated = UNRATED;  /* unrated */
139                 else if (param[2].val.integer == RATED)
140                         seek_globals.ads[num].rated = RATED;    /* rated */
141         } else
142                 seek_globals.ads[num].rated = BoolCheckPFlag(p, PFLAG_RATED);
143
144
145         if (param[3].type == TYPE_INT) {
146                 if (param[3].val.integer == WHITE)
147                         seek_globals.ads[num].seek_color = WHITE;
148                 else if (param[3].val.word[0] == BLACK)
149                         seek_globals.ads[num].seek_color = BLACK;
150         } else
151                 seek_globals.ads[num].seek_color = random() % 2;
152
153         category[0]='\0';
154         board[0]='\0';
155         /* FIXME- use proper values */
156 #endif
157         seek_globals.ads[num].category = strdup(category);
158         seek_globals.ads[num].board_type = strdup(board);
159
160         seek_globals.ads[num].next = NULL;
161
162         msgtxt = form_ad(&seek_globals.ads[num], num);
163
164         for (p1 = 0; p1 < player_globals.p_num; p1++) {
165                 if ((p1 == p) || !CheckPFlag(p1, PFLAG_ADS)
166                   || (player_globals.parray[p1].status != PLAYER_PROMPT)
167                   || (player_censored(p1, p)))
168                         continue;
169                 count++;
170                 pprintf(p1, "%s", msgtxt);
171         }
172         pprintf(p, "%s", msgtxt);
173         free(msgtxt);
174
175         return COM_OK;
176 }
177
178 int com_play(int p, param_list param)
179 {
180         int             game;
181
182         game = param[0].val.integer;
183
184         if (seek_globals.ads[game].status != SEEKCLOSED) {
185                 pprintf(p, "ERROR: Either that game has already started or "
186                         "it is no longer available.\n");
187                 return COM_OK;
188         }
189         if (!CheckPFlag(p, PFLAG_REG) && seek_globals.ads[game].rated == 1) {
190                 pprintf(p, "ERROR: Unregistred users cannot play rated games.\n");
191                 return COM_OK;
192         }
193         if (seek_globals.ads[game].whofrom == p) {
194                 pprintf(p, "ERROR: You cannot respond to your own seek ads\n");
195                 return COM_OK;
196         }
197         seek_globals.ads[game].whoto = p;
198
199         decline_withdraw_offers(p, -1, PEND_ALL, DO_DECLINE | DO_WITHDRAW); 
200         decline_withdraw_offers(seek_globals.ads[game].whofrom, -1, PEND_ALL, DO_DECLINE | DO_WITHDRAW);
201
202         accept_match(&seek_globals.ads[game], p, seek_globals.ads[game].whofrom);
203 #if 0
204         free(seek_globals.ads[game].category);
205         free(seek_globals.ads[game].board_type);
206 #endif
207 return 0;
208 }
209
210 extern FILE *comlog;
211
212 int com_sought(int p, param_list param)
213 {
214         int             i;
215
216         for (i = 0; i < seek_globals.max_ads; i++) {
217                 if (seek_globals.ads[i].status == SEEKCLOSED) {
218                         char *msgtxt = form_ad(&seek_globals.ads[i], i);
219 if(comlog) fprintf(comlog, "msgtext = %s\n", msgtxt), fflush(comlog);
220                         pprintf(p, "%s", msgtxt);
221                         free(msgtxt);
222                 }
223         }
224         return COM_OK;
225 }
226
227
228 int com_unseek(int p, param_list param)
229 {
230         /* TODO: need to add parameters */
231         withdraw_seeks(p);
232         return COM_OK;
233 }
234
235 void withdraw_seeks(int p)
236 {
237         int             i, p1;
238
239         for (i = 0; i < seek_globals.max_ads; i++) {
240                 if (seek_globals.ads[i].whofrom == p && 
241                     seek_globals.ads[i].status == SEEKCLOSED) {
242                         seek_globals.ads[i].status = SEEKOPEN;
243
244                         for (p1 = 0; p1 < player_globals.p_num; p1++) {
245                                 if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT) ||
246                                     (player_censored(p1, p)) || !CheckPFlag(p1,PFLAG_ADS))
247                                         continue;
248                                 pprintf_prompt(p1, "AD_DESTROY: %d\n", i);
249                         }
250                         pprintf(p, "Ads removed: %d\n", i);
251                         FREE(seek_globals.ads[i].category);
252                         FREE(seek_globals.ads[i].board_type);
253                 }
254         }
255 }
256
257 static int get_empty_seekslot(void)
258 {
259         int i;
260
261         for (i = 0; i < seek_globals.max_ads; i++) {
262                 if (seek_globals.ads[i].status != SEEKCLOSED) 
263                         return i;
264         }
265
266         if (seek_globals.max_ads >= config_get_int("MAX_SOUGHT", DEFAULT_MAX_SOUGHT)) {
267                 d_printf("Too many seeks! please raise MAX_SOUGHT\n");
268                 return -1;
269         }
270
271         seek_globals.max_ads += 100;
272         seek_globals.ads = (struct pending *)realloc(seek_globals.ads,
273                                                      seek_globals.max_ads * sizeof(struct pending));
274         
275         ZERO_STRUCT(seek_globals.ads[i]);
276         return i;
277
278 }
279
280 static char *form_ad(struct pending * ad, int i)
281 {
282
283         char           *final, buf[100];
284         int             rating, total, type;
285
286         total = ad->wtime * 60 + ad->winc * 40;
287
288         if(total == 0) {
289                 type = UNTIMED;
290                 rating = player_globals.parray[ad->whofrom].l_stats.rating;
291         } else if (total < 180) {
292                 type = LIGHTNING;
293                 rating = player_globals.parray[ad->whofrom].l_stats.rating;
294         } else if (total >= 900) {
295                 type = STANDARD; 
296                 rating = player_globals.parray[ad->whofrom].s_stats.rating;
297         } else {
298                 type = BLITZ;
299                 rating = player_globals.parray[ad->whofrom].b_stats.rating;
300         }
301
302 if(comlog) fprintf(comlog, "seek %d type = %d\n", i, type), fflush(comlog);
303         if(ad->category[0]) { // [HGM] print category with seek ad
304                 sprintf(buf, " %s", ad->category);
305                 if(ad->board_type[0] && strcmp(ad->board_type, "0"))
306                         sprintf(buf + strlen(buf), " %s", ad->board_type);
307         } else strcpy(buf, TypeStrings[type]); // [HGM] replaced color by type here...
308
309         asprintf(&final, "%3u %4u %-17s %3u %3u %-7s %-10s\n",
310                  i, 
311                  rating,
312                  player_globals.parray[ad->whofrom].name, 
313                  ad->wtime, 
314                  ad->winc, 
315                  ad->rated?"rated":"unrated",
316                  buf);
317
318         return final;
319 }