2 Copyright (c) 2000 Dan Papasian
3 Copyright (C) Andrew Tridgell 2002
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.
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.
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.
22 enum { SEEKOPEN = 0, SEEKCLOSED };
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 };
31 enum { BLACK = 0, WHITE};
34 static int get_empty_seekslot(void);
35 static char *form_ad(struct pending * ad, int i);
37 int com_seek(int p, param_list param)
39 struct player *pp = &player_globals.parray[p];
41 int num; /* sought ID */
43 char board[100], category[100];
44 int wt, bt, winc, binc, rated, white;
49 if (!CheckPFlag(p, PFLAG_REG)) {
50 pprintf(p, "Only registered players can use the seek command.\n");
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");
60 pprintf(p, "ERROR: You can't seek a game while you are playing one.\n");
63 num = get_empty_seekslot();
65 pprintf(p, "ERROR: Sorry, all available slots for seek are closed.\n");
68 seek_globals.ads[num].whofrom = p;
71 // [HGM] attempt to make seek as powerful as match
72 wt = bt = winc = binc = -1;
73 board[0] = category[0] = '\0';
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 */
82 if (!board[0] && strcmp(category,"bughouse")) {
83 pprintf(p, "You must specify a board and a category.\n");
86 } else if (board[0]) { /* not bughouse */
87 char fname[MAX_FILENAME_SIZE];
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);
97 seek_globals.ads[num].status = SEEKCLOSED; // params are valid; create ad
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;
107 if (!rated || !CheckPFlag(p, PFLAG_REG) || seek_globals.ads[num].wtime == 0)
108 seek_globals.ads[num].rated = UNRATED; /* unrated */
110 seek_globals.ads[num].rated = RATED; /* rated */
112 seek_globals.ads[num].rated = BoolCheckPFlag(p, PFLAG_RATED);
116 seek_globals.ads[num].seek_color = white ? WHITE : BLACK;
118 seek_globals.ads[num].seek_color = random() % 2;
121 seek_globals.ads[num].status = SEEKCLOSED;
123 if (param[0].type == TYPE_INT)
124 seek_globals.ads[num].wtime = param[0].val.integer; /* White time */
126 seek_globals.ads[num].wtime = pp->d_time;
128 if (param[1].type == TYPE_INT)
129 seek_globals.ads[num].winc = param[1].val.integer; /* White increment */
131 seek_globals.ads[num].winc = pp->d_inc;
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 */
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 */
142 seek_globals.ads[num].rated = BoolCheckPFlag(p, PFLAG_RATED);
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;
151 seek_globals.ads[num].seek_color = random() % 2;
155 /* FIXME- use proper values */
157 seek_globals.ads[num].category = strdup(category);
158 seek_globals.ads[num].board_type = strdup(board);
160 seek_globals.ads[num].next = NULL;
162 msgtxt = form_ad(&seek_globals.ads[num], num);
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)))
170 pprintf(p1, "%s", msgtxt);
172 pprintf(p, "%s", msgtxt);
178 int com_play(int p, param_list param)
182 game = param[0].val.integer;
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");
189 if (!CheckPFlag(p, PFLAG_REG) && seek_globals.ads[game].rated == 1) {
190 pprintf(p, "ERROR: Unregistred users cannot play rated games.\n");
193 if (seek_globals.ads[game].whofrom == p) {
194 pprintf(p, "ERROR: You cannot respond to your own seek ads\n");
197 seek_globals.ads[game].whoto = p;
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);
202 accept_match(&seek_globals.ads[game], p, seek_globals.ads[game].whofrom);
204 free(seek_globals.ads[game].category);
205 free(seek_globals.ads[game].board_type);
212 int com_sought(int p, param_list param)
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);
228 int com_unseek(int p, param_list param)
230 /* TODO: need to add parameters */
235 void withdraw_seeks(int p)
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;
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))
248 pprintf_prompt(p1, "AD_DESTROY: %d\n", i);
250 pprintf(p, "Ads removed: %d\n", i);
251 FREE(seek_globals.ads[i].category);
252 FREE(seek_globals.ads[i].board_type);
257 static int get_empty_seekslot(void)
261 for (i = 0; i < seek_globals.max_ads; i++) {
262 if (seek_globals.ads[i].status != SEEKCLOSED)
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");
271 seek_globals.max_ads += 100;
272 seek_globals.ads = (struct pending *)realloc(seek_globals.ads,
273 seek_globals.max_ads * sizeof(struct pending));
275 ZERO_STRUCT(seek_globals.ads[i]);
280 static char *form_ad(struct pending * ad, int i)
283 char *final, buf[100];
284 int rating, total, type;
286 total = ad->wtime * 60 + ad->winc * 40;
290 rating = player_globals.parray[ad->whofrom].l_stats.rating;
291 } else if (total < 180) {
293 rating = player_globals.parray[ad->whofrom].l_stats.rating;
294 } else if (total >= 900) {
296 rating = player_globals.parray[ad->whofrom].s_stats.rating;
299 rating = player_globals.parray[ad->whofrom].b_stats.rating;
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...
309 asprintf(&final, "%3u %4u %-17s %3u %3u %-7s %-10s\n",
312 player_globals.parray[ad->whofrom].name,
315 ad->rated?"rated":"unrated",