Check-in modifications made by HGM so far
[capablanca.git] / lasker-2.2.3 / src / variable.c
1 /*
2    Copyright (c) 1993 Richard V. Nash.
3    Copyright (c) 2000 Dan Papasian
4    Copyright (C) Andrew Tridgell 2002
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 static int set_boolean_flag(int p, char *val, unsigned long flag)
24 {
25   int v = -1;
26
27   if (val == NULL) {
28     TogglePFlag(p, flag);
29     v = BoolCheckPFlag(p, flag);
30     return (v);
31   }
32   if (sscanf(val, "%d", &v) != 1) {
33     stolower(val);
34     if (!strcmp(val, "off") || !strcmp(val, "false"))
35       v = 0;
36     else if (!strcmp(val, "on") || !strcmp(val, "true"))
37       v = 1;
38   }
39   SetPFlag(p, flag, v);
40   return v;
41 }
42
43 static int set_availinfo(int p, char *var, char *val)
44 {
45   int v = set_boolean_flag(p, val, PFLAG_AVAIL);
46
47   if (v < 0)
48     return VAR_BADVAL;
49    pprintf(p, "availinfo set to %d.\n", BoolCheckPFlag(p, PFLAG_AVAIL));
50
51   if (v > 0)
52     pprintf(p, "You will receive info on who is available to play.\n");
53   else
54     pprintf(p, "You are no longer receiving info on who is available to play.\n");
55   return VAR_OK;
56 }
57
58 static int set_availmax(int p, char *var, char *val)
59 {
60   struct player *pp = &player_globals.parray[p];
61   int v = -1;
62
63   if (!val)
64     return VAR_BADVAL;
65   if (sscanf(val, "%d", &v) != 1)
66     return VAR_BADVAL;
67   if ((v < 0) || (v > 9999))
68     return VAR_BADVAL;
69
70   if (v < pp->availmin) {
71     pprintf(p, "You can't set availmax to less than availmin.\n");
72     return VAR_OK;
73   }
74
75   if ((pp->availmax = v)) {
76     pprintf(p, "You will be notified of availability with blitz ratings %d - %d.\n",pp->availmin,v); 
77   } else
78     pprintf(p, "You will be notified of all available players.\n");
79   return VAR_OK;
80 }
81
82 static int set_availmin(int p, char *var, char *val)
83 {
84   struct player *pp = &player_globals.parray[p];
85   int v = -1;
86
87   if (!val)
88     return VAR_BADVAL;
89   if (sscanf(val, "%d", &v) != 1)
90     return VAR_BADVAL;
91   if ((v < 0) || (v > 9999))
92     return VAR_BADVAL;
93
94   if (v > pp->availmax) {
95     pprintf(p, "You can't set availmin to more than availmax.\n");
96     return VAR_OK;
97   }
98
99   pp->availmin = v;
100   pprintf(p, "You will be notified of availability with blitz ratings %d - %d.\n",v,pp->availmax);
101   return VAR_OK;
102 }
103
104 static int set_open(int p, char *var, char *val)
105 {
106   struct player *pp = &player_globals.parray[p];
107   int v = set_boolean_flag(p, val, PFLAG_OPEN);
108
109   if (v < 0)
110     return VAR_BADVAL;
111   if (v > 0) {
112     pprintf(p, "You are now open to receive match requests.\n");
113     announce_avail (p);
114   } else {
115     decline_withdraw_offers(p, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
116     pprintf(p, "You are no longer receiving match requests.\n");
117     if (pp->game < 0)
118       announce_notavail (p);
119   }
120   return VAR_OK;
121 }
122
123 static int set_tourney(int p, char *var, char *val)
124 {
125   struct player *pp = &player_globals.parray[p];
126   int v = set_boolean_flag(p, val, PFLAG_TOURNEY);
127
128   if (v < 0)
129     return VAR_BADVAL;
130   if (v > 0) {
131     decline_withdraw_offers(p, -1, PEND_MATCH,DO_DECLINE | DO_WITHDRAW);
132     pprintf(p, "Your tournament variable is now set.\n");
133     announce_notavail (p);
134   } else {
135     pprintf(p, "Your tournament variable is no longer set.\n");
136     if (pp->game < 0)
137       announce_avail (p);
138   }
139   return VAR_OK;
140 }
141
142 static int set_sopen(int p, char *var, char *val)
143 {
144   int v = set_boolean_flag(p, val, PFLAG_SIMOPEN);
145
146   if (v < 0)
147     return VAR_BADVAL;
148   pprintf(p, "sopen set to %d.\n", v);
149
150   if (v > 0)
151     pprintf(p, "You are now open to receive simul requests.\n");
152   else
153     pprintf(p, "You are no longer receiving simul requests.\n");
154   decline_withdraw_offers(p, -1, PEND_SIMUL,DO_DECLINE);
155   return VAR_OK;
156 }
157
158 static int set_ropen(int p, char *var, char *val)
159 {
160   if (set_boolean_flag(p, val, PFLAG_ROPEN) < 0)
161     return VAR_BADVAL;
162   pprintf(p, "ropen set to %d.\n", BoolCheckPFlag(p, PFLAG_ROPEN));
163   return VAR_OK;
164 }
165
166 static int set_rated(int p, char *var, char *val)
167 {
168   if (!CheckPFlag(p, PFLAG_REG)) {
169     pprintf(p, "You cannot change your rated status.\n");
170     return VAR_OK;
171   }
172   if (set_boolean_flag(p, val, PFLAG_RATED) < 0)
173     return VAR_BADVAL;
174   pprintf(p, "rated set to %d.\n", BoolCheckPFlag(p, PFLAG_RATED));
175   return VAR_OK;
176 }
177
178 static int set_shout(int p, char *var, char *val)
179 {
180   if (set_boolean_flag(p, val, PFLAG_SHOUT) < 0)
181     return VAR_BADVAL;
182   if (CheckPFlag(p, PFLAG_SHOUT))
183     pprintf(p, "You will now hear shouts.\n");
184   else
185     pprintf(p, "You will not hear shouts.\n");
186   return VAR_OK;
187 }
188
189 static int set_ads(int p, char *var, char *val)
190 {
191   if (set_boolean_flag(p, val, PFLAG_ADS) < 0)
192     return VAR_BADVAL;
193   if (CheckPFlag(p, PFLAG_ADS))
194     pprintf(p, "You will now hear ads.\n");
195   else
196     pprintf(p, "You will not hear ads.\n");
197   return VAR_OK;
198 }
199
200 static int set_cshout(int p, char *var, char *val)
201 {
202   if (set_boolean_flag(p, val, PFLAG_CSHOUT) < 0)
203     return VAR_BADVAL;
204   if (CheckPFlag(p, PFLAG_CSHOUT))
205     pprintf(p, "You will now hear cshouts.\n");
206   else
207     pprintf(p, "You will not hear cshouts.\n");
208   return VAR_OK;
209 }
210
211 static int set_kibitz(int p, char *var, char *val)
212 {
213   if (set_boolean_flag(p, val, PFLAG_KIBITZ) < 0)
214     return VAR_BADVAL;
215   if (CheckPFlag(p, PFLAG_KIBITZ))
216     pprintf(p, "You will now hear kibitzes.\n");
217   else
218     pprintf(p, "You will not hear kibitzes.\n");
219   return VAR_OK;
220 }
221 static int set_kiblevel(int p, char *var, char *val)
222 {
223   struct player *pp = &player_globals.parray[p];
224   int v = -1;
225
226   if (!val)
227     return VAR_BADVAL;
228   if (sscanf(val, "%d", &v) != 1)
229     return VAR_BADVAL;
230   if ((v < 0) || (v > 9999))
231     return VAR_BADVAL;
232   pp->kiblevel = v;
233   pprintf(p, "Kibitz level now set to: %d.\n", v);
234   return VAR_OK;
235 }
236
237 static int set_tell(int p, char *var, char *val)
238 {
239   if (set_boolean_flag(p, val, PFLAG_TELL) < 0)
240     return VAR_BADVAL;
241   if (CheckPFlag(p, PFLAG_TELL))
242     pprintf(p, "You will now hear tells from unregistered users.\n");
243   else
244     pprintf(p, "You will not hear tells from unregistered users.\n");
245   return VAR_OK;
246 }
247
248 static int set_notifiedby(int p, char *var, char *val)
249 {
250   if (set_boolean_flag(p, val, PFLAG_NOTIFYBY) < 0)
251     return VAR_BADVAL;
252   if (CheckPFlag(p, PFLAG_NOTIFYBY))
253     pprintf(p, "You will now hear if people notify you, but you don't notify them.\n");
254   else
255     pprintf(p, "You will not hear if people notify you, but you don't notify them.\n");
256   return VAR_OK;
257 }
258
259 static int set_pinform(int p, char *var, char *val)
260 {
261   if (set_boolean_flag(p, val, PFLAG_PIN) < 0)
262     return VAR_BADVAL;
263   if (CheckPFlag(p, PFLAG_PIN))
264     pprintf(p, "You will now hear logins/logouts.\n");
265   else
266     pprintf(p, "You will not hear logins/logouts.\n");
267   return VAR_OK;
268 }
269
270 static int set_ginform(int p, char *var, char *val)
271 {
272   if (set_boolean_flag(p, val, PFLAG_GIN) < 0)
273     return VAR_BADVAL;
274   if (CheckPFlag(p, PFLAG_GIN))
275     pprintf(p, "You will now hear game results.\n");
276   else
277     pprintf(p, "You will not hear game results.\n");
278   return VAR_OK;
279 }
280
281 static int set_private(int p, char *var, char *val)
282 {
283   if (set_boolean_flag(p, val, PFLAG_PRIVATE) < 0)
284     return VAR_BADVAL;
285   if (CheckPFlag(p, PFLAG_PRIVATE))
286     pprintf(p, "Your games will be private.\n");
287   else
288     pprintf(p, "Your games may not be private.\n");
289   return VAR_OK;
290 }
291
292 static int set_jprivate(int p, char *var, char *val)
293 {
294   if (!CheckPFlag(p, PFLAG_REG)) {
295     pprintf(p, "Unregistered players may not keep a journal.\n");
296     return VAR_OK;
297   }
298
299   if (set_boolean_flag(p, val, PFLAG_JPRIVATE) < 0)
300     return VAR_BADVAL;
301   if (CheckPFlag(p, PFLAG_JPRIVATE))
302     pprintf(p, "Your journal will be private.\n");
303   else
304     pprintf(p, "Your journal will not be private.\n");
305   return VAR_OK;
306 }
307
308 static int set_automail(int p, char *var, char *val)
309 {
310   if (set_boolean_flag(p, val, PFLAG_AUTOMAIL) < 0)
311     return VAR_BADVAL;
312   if (CheckPFlag(p, PFLAG_AUTOMAIL))
313     pprintf(p, "Your games will be mailed to you.\n");
314   else
315     pprintf(p, "Your games will not be mailed to you.\n");
316   return VAR_OK;
317 }
318
319 static int set_mailmess(int p, char *var, char *val)
320 {
321   if (!CheckPFlag(p, PFLAG_REG)) {
322     pprintf(p, "Unregistered players may not receive messages.\n");
323     return VAR_OK;
324   }
325   if (set_boolean_flag(p, val, PFLAG_MAILMESS) < 0)
326     return VAR_BADVAL;
327   if (CheckPFlag(p, PFLAG_MAILMESS))
328     pprintf(p, "Your messages will be mailed to you.\n");
329   else
330     pprintf(p, "Your messages will not be mailed to you.\n");
331   return VAR_OK;
332 }
333
334 static int set_pgn(int p, char *var, char *val)
335 {
336   if (set_boolean_flag(p, val, PFLAG_PGN) < 0)
337     return VAR_BADVAL;
338   if (CheckPFlag(p, PFLAG_PGN))
339     pprintf(p, "Games will now be mailed to you in PGN.\n");
340   else
341     pprintf(p, "Games will now be mailed to you in FICS format.\n");
342   return VAR_OK;
343 }
344
345 static int set_bell(int p, char *var, char *val)
346 {
347   if (set_boolean_flag(p, val, PFLAG_BELL) < 0)
348     return VAR_BADVAL;
349   if (CheckPFlag(p, PFLAG_BELL))
350     pprintf(p, "Bell on.\n");
351   else
352     pprintf(p, "Bell off.\n");
353   return VAR_OK;
354 }
355
356 static int set_highlight(int p, char *var, char *val)
357 {
358   struct player *pp = &player_globals.parray[p];
359   int v = -1;
360
361   if (!val)
362     return VAR_BADVAL;
363   if (sscanf(val, "%d", &v) != 1)
364     return VAR_BADVAL;
365   if ((v < 0) || (v > 15))
366     return VAR_BADVAL;
367
368   if ((pp->highlight = v)) {
369     pprintf(p, "Highlight is now style ");
370     pprintf_highlight(p, "%d", v);
371     pprintf(p, ".\n");
372   } else
373     pprintf(p, "Highlight is off.\n");
374   return VAR_OK;
375 }
376
377 static int set_style(int p, char *var, char *val)
378 {
379   struct player *pp = &player_globals.parray[p];
380   int v = -1;
381
382   if (!val)
383     return VAR_BADVAL;
384   if (sscanf(val, "%d", &v) != 1)
385     return VAR_BADVAL;
386   if ((v < 1) || (v > MAX_STYLES))
387     return VAR_BADVAL;
388   pp->style = v - 1;
389   pprintf(p, "Style %d set.\n", v);
390   return VAR_OK;
391 }
392
393 static int set_flip(int p, char *var, char *val)
394 {
395   if (set_boolean_flag(p, val, PFLAG_FLIP) < 0)
396     return VAR_BADVAL;
397   if (CheckPFlag(p, PFLAG_FLIP))
398     pprintf(p, "Flip on.\n");
399   else
400     pprintf(p, "Flip off.\n");
401   return VAR_OK;
402 }
403 /* Was pointless as this is what notes are for
404 static int set_uscf(int p, char *var, char *val)
405 {
406   int v = -1;
407
408   if (!val)
409     return VAR_BADVAL;
410   if (sscanf(val, "%d", &v) != 1)
411     return VAR_BADVAL;
412   if ((v < 0) || (v > 3000))
413     return VAR_BADVAL;
414   pp->uscfRating = v;
415   pprintf(p, "USCF Rating set to %d.\n", v);
416   return VAR_OK;
417 }
418 */
419 static int set_time(int p, char *var, char *val)
420 {
421   struct player *pp = &player_globals.parray[p];
422   int v = -1;
423
424   if (!val)
425     return VAR_BADVAL;
426   if (sscanf(val, "%d", &v) != 1)
427     return VAR_BADVAL;
428   if ((v < 0) || (v > 240))
429     return VAR_BADVAL;
430   pp->d_time = v;
431   pprintf(p, "Default time set to %d.\n", v);
432   return VAR_OK;
433 }
434
435 static int set_inc(int p, char *var, char *val)
436 {
437   struct player *pp = &player_globals.parray[p];
438   int v = -1;
439
440   if (!val)
441     return VAR_BADVAL;
442   if (sscanf(val, "%d", &v) != 1)
443     return VAR_BADVAL;
444   if ((v < 0) || (v > 300))
445     return VAR_BADVAL;
446   pp->d_inc = v;
447   pprintf(p, "Default increment set to %d.\n", v);
448   return VAR_OK;
449 }
450
451 static int set_height(int p, char *var, char *val)
452 {
453   struct player *pp = &player_globals.parray[p];
454   int v = -1;
455
456   if (!val)
457     return VAR_BADVAL;
458   if (sscanf(val, "%d", &v) != 1)
459     return VAR_BADVAL;
460   if ((v < 5) || (v > 240))
461     return VAR_BADVAL;
462   pp->d_height = v;
463   pprintf(p, "Height set to %d.\n", v);
464   return VAR_OK;
465 }
466
467 static int set_width(int p, char *var, char *val)
468 {
469         struct player *pp = &player_globals.parray[p];
470         int v = -1;
471
472         if (!val)
473                 return VAR_BADVAL;
474         if (sscanf(val, "%d", &v) != 1)
475                 return VAR_BADVAL;
476         if ((v < 32) || (v > 10000))
477                 return VAR_BADVAL;
478         pp->d_width = v;
479         pprintf(p, "Width set to %d.\n", v);
480         return VAR_OK;
481 }
482
483 const char *Language(int i)
484 {
485   static const char *Lang[NUM_LANGS] = {"English", "Spanish", "French", "Danish"};
486   return Lang[i];
487 }
488
489 static int set_language (int p, char *var, char *val)
490 {
491   struct player *pp = &player_globals.parray[p];
492   int i, len, gotIt = -1;
493
494   if (!val)
495     return VAR_BADVAL;
496   len = strlen(val);
497   for (i=0; i < NUM_LANGS; i++) {
498     if (strncasecmp(val, Language(i), len))
499       continue;
500     if (gotIt >= 0)
501       return VAR_BADVAL;
502     else gotIt = i;
503   }
504   if (gotIt < 0)
505     return VAR_BADVAL;
506   pp->language = gotIt;
507   pprintf(p, "Language set to %s.\n", Language(gotIt));
508   return VAR_OK;
509 }
510
511 static int set_promote(int p, char *var, char *val)
512 {
513   struct player *pp = &player_globals.parray[p];
514   if (!val)
515     return VAR_BADVAL;
516   stolower(val);
517   switch (val[0]) {
518   case 'q':
519     pp->promote = QUEEN;
520     pprintf(p, "Promotion piece set to QUEEN.\n");
521     break;
522   case 'r':
523     pp->promote = ROOK;
524     pprintf(p, "Promotion piece set to ROOK.\n");
525     break;
526   case 'b':
527     pp->promote = BISHOP;
528     pprintf(p, "Promotion piece set to BISHOP.\n");
529     break;
530   case 'n':
531   case 'k':
532     pp->promote = KNIGHT;
533     pprintf(p, "Promotion piece set to KNIGHT.\n");
534     break;
535   default:
536     return VAR_BADVAL;
537   }
538   return VAR_OK;
539 }
540
541
542 static int set_interface(int p, char *var, char *val)
543 {
544         struct player *pp = &player_globals.parray[p];
545         if (!val) {
546                 FREE(pp->interface);
547                 return VAR_OK;
548         }
549         if (!printablestring(val))
550                 return VAR_BADVAL;
551         FREE(pp->interface);
552         asprintf(&pp->interface, "%s", val);
553         return VAR_OK;
554 }
555
556 static int set_prompt(int p, char *var, char *val)
557 {
558         struct player *pp = &player_globals.parray[p];
559         char *prompt;
560         if (!val) {
561                 free(pp->prompt);
562                 pp->prompt = config_get("DEFAULT_PROMPT");
563                 return VAR_OK;
564         }
565         if (!printablestring(val))
566                 return VAR_BADVAL;
567         free(pp->prompt);
568         asprintf(&prompt, "%s", val);
569         pp->prompt = prompt;
570         return VAR_OK;
571 }
572
573 static int RePartner (int p, int new)
574 {
575   struct player *pp = &player_globals.parray[p];
576   int pOld;
577
578   if (p < 0)
579     return -1;
580   pOld = pp->partner;
581   if (pOld >= 0) {
582     if (player_globals.parray[pOld].partner == p) {
583       if (new >= 0)
584         pprintf_prompt (pOld, "Your partner has just chosen a new partner.\n");
585       else {
586         pprintf (pOld, "Your partner has unset his/her partner variable.\n");
587         pprintf_prompt (pOld, "You are no longer %s's partner.\n",pp->name);
588       }
589       decline_withdraw_offers (pOld, -1, PEND_BUGHOUSE,DO_DECLINE | DO_WITHDRAW);
590       player_globals.parray[pOld].partner = -1;
591     }
592   }
593   decline_withdraw_offers(p, -1, PEND_BUGHOUSE,DO_DECLINE | DO_WITHDRAW);
594   decline_withdraw_offers(p, -1, PEND_PARTNER,DO_DECLINE | DO_WITHDRAW);
595   pp->partner = new;
596   return new;
597 }
598
599 int com_partner(int p, param_list param)
600 {
601   struct player *pp = &player_globals.parray[p];
602   int pNew;
603   struct pending* pend;
604
605   if (param[0].type == TYPE_NULL) {
606     if (pp->partner >= 0)
607       pprintf (p, "You no longer have a bughouse partner.\n");
608     else pprintf (p, "You do not have a bughouse partner.\n");
609     RePartner(p, -1);
610     return COM_OK;
611   }
612   /* OK, we're trying to set a new partner. */
613   pNew = player_find_part_login(param[0].val.word);
614   if (pNew < 0 || player_globals.parray[pNew].status == PLAYER_PASSWORD
615       || player_globals.parray[pNew].status == PLAYER_LOGIN) {
616     pprintf(p, "No user named \"%s\" is logged in.\n", param[0].val.word);
617     return COM_OK;
618   }
619   if (pNew == p) {
620     pprintf(p, "You can't be your own bughouse partner.\n");
621     return COM_OK; 
622   }
623   /* Now we know a legit partner has been chosen.  Is an offer pending? */
624   if ((pend = find_pend(pNew, p, PEND_PARTNER)) != NULL) {
625     pprintf (p, "You agree to be %s's partner.\n", player_globals.parray[pNew].name);
626     Bell (pNew);
627     pprintf_prompt (pNew, "%s agrees to be your partner.\n", pp->name);
628
629     delete_pending (pend);
630
631     /* Make the switch. */
632     RePartner (p, pNew);
633     RePartner (pNew, p);
634     return COM_OK;
635   }
636   /* This is just an offer. Make sure a new partner is needed. */
637   if (player_globals.parray[pNew].partner >= 0) {
638     pprintf(p, "%s already has a partner.\n", player_globals.parray[pNew].name);
639     return COM_OK;
640   }
641   pprintf(pNew, "\n");
642   pprintf_highlight(pNew, "%s", pp->name);
643   Bell (pNew);
644   pprintf(pNew, " offers to be your bughouse partner; ");
645   pprintf_prompt(pNew, "type \"partner %s\" to accept.\n", pp->name);
646   pprintf(p, "Making a partnership offer to %s.\n", player_globals.parray[pNew].name);
647   add_request(p, pNew, PEND_PARTNER);
648
649   return COM_OK;
650 }
651
652 static int set_busy(int p, char *var, char *val)
653 {
654   struct player *pp = &player_globals.parray[p];
655   if (!val) {
656     if (pp->busy != NULL) {
657       free (pp->busy);
658       pp->busy = NULL;
659     }
660     pprintf(p, "Your \"busy\" string was cleared.\n");
661     return VAR_OK;
662   }
663   if ((val) && (!printablestring(val)))
664     return VAR_BADVAL;
665   pp->busy = strdup(val);
666   pprintf(p, "Your \"busy\" string was set to \" %s\"\n", pp->busy);
667   return VAR_OK;
668 }
669
670 /* this is really ugly */
671 static int set_plan(int p, char *var, char *val)
672 {
673   struct player *pp = &player_globals.parray[p];
674   int which;
675   int i;
676
677   if (val && !printablestring(val))
678     return VAR_BADVAL;
679   which = atoi(var);            /* Must be an integer, no test needed */
680
681   if (which > MAX_PLAN)
682     return VAR_BADVAL;
683
684   if (which > pp->num_plan)
685     which = pp->num_plan + 1;
686
687   if (which == 0) {  /* shove from top */
688     if (pp->num_plan >= MAX_PLAN) { /* free the bottom string */
689       if (pp->planLines[pp->num_plan - 1] != NULL)
690         free(pp->planLines[pp->num_plan - 1]);
691     }
692     if (pp->num_plan) {
693       for (i = (pp->num_plan >= MAX_PLAN) ? MAX_PLAN - 1 : pp->num_plan; i > 0; i--)
694         pp->planLines[i] = pp->planLines[i - 1];
695     }
696     if (pp->num_plan < MAX_PLAN)
697       pp->num_plan++;
698 /* kludged the next line: "" was NULL, but crashed on pprintf. fb 2.24.96 */
699     pp->planLines[0] = ((val == NULL) ? "": strdup(val));
700     pprintf(p, "\nPlan variable %d changed to '%s'.\n", which+1, pp->planLines[which]);
701     pprintf(p, "All other variables moved down.\n");
702     return VAR_OK;
703   }
704   if (which > pp->num_plan) {   /* new line at bottom */
705     if (pp->num_plan >= MAX_PLAN) {     /* shove the old lines up */
706       if (pp->planLines[0] != NULL)
707         free(pp->planLines[0]);
708       for (i = 0; i < pp->num_plan; i++)
709         pp->planLines[i] = pp->planLines[i + 1];
710     } else {
711       pp->num_plan++;
712     }
713 /* kludged the next line: "" was NULL, but crashed on pprintf. fb2.24.96 */
714     pp->planLines[which - 1] = ((val == NULL) ? "": strdup(val));
715     pprintf(p, "\nPlan variable %d changed to '%s'.\n", which, pp->planLines[which-1]);
716     return VAR_OK;
717   }
718   which--;
719   if (pp->planLines[which] != NULL) {
720     free(pp->planLines[which]);
721   }
722   if (val != NULL) {
723     pp->planLines[which] = strdup(val);
724     pprintf(p, "\nPlan variable %d changed to '%s'.\n", which+1, pp->planLines[which]);
725   } else {
726     pp->planLines[which] = NULL;
727     if (which == pp->num_plan - 1) {    /* clear nulls from bottom */
728       while ((pp->num_plan > 0) && (pp->planLines[pp->num_plan - 1] == NULL)) {
729         pp->num_plan--;
730     pprintf(p, "\nPlan variable %d cleared.\n", which+1);
731       }
732     } else if (which == 0) {    /* clear nulls from top */
733       while ((which < pp->num_plan) && (pp->planLines[which] == NULL)) {
734         which++;
735       }
736       if (which != pp->num_plan) {
737         for (i = which; i < pp->num_plan; i++)
738           pp->planLines[i - which] = pp->planLines[i];
739       }
740       pp->num_plan -= which;
741     }
742   }
743   return VAR_OK;
744 }
745
746 static int set_formula(int p, char *var, char *val)
747 {
748   int which;
749   struct player *me = &player_globals.parray[p];
750
751 #ifdef NO_FORMULAS
752   pprintf(p, "Sorry -- not available because of a bug\n");
753   return COM_OK;
754 #else
755   if (isdigit(var[1]))
756     which = var[1] - '1';
757   else
758     which = MAX_FORMULA;
759
760   if (val != NULL) {
761     val = eatwhite(val);
762     if (val[0] == '\0')
763       val = NULL;
764   }
765   if (!SetValidFormula(p, which, val))
766     return VAR_BADVAL;
767
768   if (which < MAX_FORMULA) {
769     if (val != NULL) {
770       while (me->num_formula < which) {
771         me->formulaLines[me->num_formula] = NULL;
772         (me->num_formula)++;
773       }
774       if (me->num_formula <= which)
775         me->num_formula = which + 1;
776       pprintf(p, "Formula variable f%d set to %s.\n",
777               which + 1, me->formulaLines[which]);
778       return VAR_OK;
779     }
780     pprintf(p, "Formula variable f%d unset.\n", which + 1);
781     if (which + 1 >= me->num_formula) {
782       while (which >= 0 && me->formulaLines[which] == NULL)
783         which--;
784       me->num_formula = which + 1;
785     }
786   } else {
787     if (me->formula != NULL)
788       pprintf(p, "Formula set to %s.\n", me->formula);
789     else
790       pprintf(p, "Formula unset.\n");
791   }
792   return VAR_OK;
793 #endif
794 }
795
796 var_list variables[] = {
797   {"ads", set_ads},
798   {"availinfo", set_availinfo},
799   {"availmax", set_availmax},
800   {"availmin", set_availmin},
801   {"open", set_open},
802   {"tourney", set_tourney},
803   {"simopen", set_sopen},
804   {"rated", set_rated},
805   {"ropen", set_ropen},
806   {"cshout", set_cshout},
807   {"shout", set_shout},
808   {"kibitz", set_kibitz},
809   {"kiblevel", set_kiblevel},
810   {"tell", set_tell},
811   {"notifiedby", set_notifiedby},
812   {"pinform", set_pinform},
813   {"i_login", set_pinform},
814   {"ginform", set_ginform},
815   {"i_game", set_ginform},
816   {"automail", set_automail},
817   {"mailmess", set_mailmess},
818   {"bell", set_bell},
819   {"pgn", set_pgn},
820   {"private", set_private},
821   {"jprivate", set_jprivate},
822   {"highlight", set_highlight},
823   {"style", set_style},
824   {"flip", set_flip},
825   {"prompt", set_prompt},
826   {"promote", set_promote},
827   {"time", set_time},
828   {"inc", set_inc},
829   {"height", set_height},
830   {"width", set_width},
831   {"language", set_language},
832   {"busy", set_busy},
833   {"0", set_plan},
834   {"1", set_plan},
835   {"2", set_plan},
836   {"3", set_plan},
837   {"4", set_plan},
838   {"5", set_plan},
839   {"6", set_plan},
840   {"7", set_plan},
841   {"8", set_plan},
842   {"9", set_plan},
843   {"10", set_plan},
844   {"f1", set_formula},
845   {"f2", set_formula},
846   {"f3", set_formula},
847   {"f4", set_formula},
848   {"f5", set_formula},
849   {"f6", set_formula},
850   {"f7", set_formula},
851   {"f8", set_formula},
852   {"f9", set_formula},
853   {"formula", set_formula},
854   {"interface", set_interface},
855   {NULL, NULL}
856 };
857
858 static int set_find(char *var)
859 {
860   int i = 0;
861   int gotIt = -1;
862   int len = strlen(var);
863
864   while (variables[i].name) {
865     if (!strncmp(variables[i].name, var, len)) {
866       if (len == strlen(variables[i].name)) {
867         return i;
868       } else if (gotIt >= 0) {
869         return -VAR_AMBIGUOUS;
870       }
871       gotIt = i;
872     }
873     i++;
874   }
875   if (gotIt >= 0) {
876     return gotIt;
877   }
878   return -VAR_NOSUCH;
879 }
880
881 int var_set(int p, char *var, char *val, int *wh)
882 {
883   int which;
884
885   if (!var)
886     return VAR_NOSUCH;
887   if ((which = set_find(var)) < 0) {
888     return -which;
889   }
890   *wh = which;
891   return variables[which].var_func(p, (isdigit(*variables[which].name) ? var : variables[which].name), val);
892 }
893
894 int com_variables(int p, param_list param)
895 {
896   int p1, connected;
897   int i;
898
899   if (param[0].type == TYPE_WORD) {
900     if (!FindPlayer(p, param[0].val.word, &p1, &connected))
901       return COM_OK;
902   } else {
903       p1 = p;
904       connected = 1;
905   }
906
907   pprintf(p, "Variable settings of %s:\n\n", player_globals.parray[p1].name);
908
909   pprintf(p, "time=%-3d    private=%d     shout=%d         pin=%d           style=%-3d\n",
910           player_globals.parray[p1].d_time, BoolCheckPFlag(p1, PFLAG_PRIVATE),
911           BoolCheckPFlag(p1, PFLAG_SHOUT), BoolCheckPFlag(p1, PFLAG_PIN),
912           player_globals.parray[p1].style + 1);
913   pprintf(p, "inc=%-3d     jprivate=%d    cshout=%d        notifiedby=%d    flip=%d\n",
914           player_globals.parray[p1].d_inc, BoolCheckPFlag(p1, PFLAG_JPRIVATE),
915           BoolCheckPFlag(p1, PFLAG_CSHOUT), BoolCheckPFlag(p1, PFLAG_NOTIFYBY),
916           BoolCheckPFlag(p1, PFLAG_FLIP));
917   pprintf(p, "                          kibitz=%d        availinfo=%d     highlight=%d\n", 
918           BoolCheckPFlag(p1, PFLAG_KIBITZ), BoolCheckPFlag(p1, PFLAG_AVAIL),
919           player_globals.parray[p1].highlight);
920   pprintf(p, "rated=%d     automail=%d    kiblevel=%-4d   availmin=%-4d   bell=%d\n",
921           BoolCheckPFlag(p1, PFLAG_RATED), BoolCheckPFlag(p1, PFLAG_AUTOMAIL),
922           player_globals.parray[p1].kiblevel, player_globals.parray[p1].availmin, 
923           BoolCheckPFlag(p1, PFLAG_BELL));
924   pprintf(p, "ropen=%d     pgn=%d         tell=%d          availmax=%-4d   width=%-3d\n",
925           BoolCheckPFlag(p1, PFLAG_ROPEN), BoolCheckPFlag(p1, PFLAG_PGN),
926           BoolCheckPFlag(p1, PFLAG_TELL), player_globals.parray[p1].availmax,
927           player_globals.parray[p1].d_width);
928   pprintf(p, "open=%d                    mailmess=%d      gin=%d           height=%-3d\n", 
929           BoolCheckPFlag(p1, PFLAG_OPEN), BoolCheckPFlag(p1, PFLAG_MAILMESS), 
930           BoolCheckPFlag(p1, PFLAG_GIN), player_globals.parray[p1].d_height);
931   pprintf(p, "simopen=%d   tourney=%d     Lang=%s", 
932           BoolCheckPFlag(p1, PFLAG_SIMOPEN), BoolCheckPFlag(p1, PFLAG_TOURNEY),
933           Language(player_globals.parray[p1].language));
934
935   if (player_globals.parray[p1].prompt)
936     pprintf(p, "                    Prompt: %s\n", player_globals.parray[p1].prompt);
937   else
938     pprintf(p, "\n");
939
940   if (player_globals.parray[p1].partner >= 0)
941     pprintf(p, "\nBughouse partner: %s\n", player_globals.parray[player_globals.parray[p1].partner].name);
942
943   if (player_globals.parray[p1].num_formula) {
944     pprintf(p, "\n");
945     for (i = 0; i < player_globals.parray[p1].num_formula; i++) {
946       if (player_globals.parray[p1].formulaLines[i] != NULL)
947         pprintf(p, " f%d: %s\n", i + 1, player_globals.parray[p1].formulaLines[i]);
948       else
949         pprintf(p, " f%d:\n", i + 1);
950     }
951   }
952   if (player_globals.parray[p1].formula != NULL)
953     pprintf(p, "\nFormula: %s\n", player_globals.parray[p1].formula);
954   else
955     pprintf(p, "\n");
956
957   if (!connected)
958     player_remove(p1);
959   return COM_OK;
960 }
961
962 /* tournset (cause settourney is BAD for set)
963  *   used by Tournament Director programs to set/unset the
964  *   tourney variable of another registered player.
965  * fics usage: tournset playername int   (int can be 0 or 1)
966  */
967 int com_tournset(int p, param_list param)
968 {
969   struct player *pp = &player_globals.parray[p];
970   int p1, v;
971
972   if (!in_list(p, L_TD, pp->name)) {
973     pprintf(p, "Only TD programs are allowed to use this command.\n");
974     return COM_OK;
975   }
976   if (((p1 = player_find_bylogin(param[0].val.word)) < 0)
977       || (!CheckPFlag(p1, PFLAG_REG))) {
978      return COM_OK;
979   }
980   v = BoolCheckPFlag(p1, PFLAG_TOURNEY);
981   if (param[1].val.integer == 0) {  /* set it to 0 */
982     if (v == 1) {
983       SetPFlag(p1, PFLAG_TOURNEY, 0);
984       pprintf_prompt(p1, "\n%s has set your tourney variable to OFF.\n",
985             pp->name);
986     }
987   } else {  /* set it to 1 */
988     if (v == 0) {
989       SetPFlag(p1, PFLAG_TOURNEY, 1);
990       pprintf_prompt(p1, "\n%s has set your tourney variable to ON.\n",
991             pp->name);
992     }
993   }
994   return COM_OK;
995 }
996
997