1 /* Command line parsing for Xconq.
2 Copyright (C) 1987-1989, 1991-2000 Stanley T. Shebs.
3
4 Xconq is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version. See the file COPYING. */
8
9 /* This is a command-line parser that may be used in implementations
10 that get a command line from somewhere. */
11
12 /* Command lines get parsed in several stages, since for instance the
13 choice of game module will decide which variants are available. */
14
15 #include "conq.h"
16 extern short initially_no_ai;
17 #include "kpublic.h"
18 #include "cmdline.h"
19
20 static void add_a_raw_player_spec(char *specstr);
21 static void version_info(void);
22 static void general_usage_info(void);
23 static void game_usage_info(void);
24 static void player_usage_info(void);
25 static void parse_world_option(char *str);
26 static void parse_realtime_option(char *subopt, char *arg);
27 static void parse_variant(char *str);
28 static int find_variant_from_name(Module *module, char *name);
29
30 /* The startup-settable options. */
31
32 static int option_width;
33 static int option_height;
34 static int option_circumference;
35 static int option_total_game_time;
36 static int option_per_side_time;
37 static int option_per_turn_time;
38 static int option_add_default_player;
39
40 char *option_game_to_host = NULL;
41
42 char *option_game_to_join = NULL;
43
44 int option_num_to_wait_for = 0;
45
46 static char *default_ai_type = ",mplayer";
47
48 /* Use this to record the options used to set up a game, so it can be
49 reported to users. */
50 /* (should flush? better to display in intelligible form) */
51
52 char *args_used;
53
54 /* The list of asked-for players. */
55
56 struct raw_spec {
57 char *spec;
58 struct raw_spec *next;
59 } *raw_player_specs, *last_raw_player_spec;
60
61 char *raw_default_player_spec;
62
63 /* The list of accumulated variant choices. */
64
65 static Obj *variant_settings;
66
67 static char *program_name = "";
68
69 static int help_wanted = FALSE;
70
71 static int variant_help_wanted = FALSE;
72
73 static int version_wanted = FALSE;
74
75 static int had_error = FALSE;
76
77 /* Set the most basic of defaults on the dynamically-settable
78 options. */
79
80 /* (need flags to indicate which options were actually used, so
81 variant handling can warn about improper use) */
82
83 void
init_options(void)84 init_options(void)
85 {
86 option_add_default_player = TRUE;
87 variant_settings = lispnil;
88 }
89
90 /* Generic command line parsing. This is used by several different
91 programs, so it just collects info, doesn't process it much. This
92 is called several times, because the validity of some args depends
93 on which game modules are loaded and which players are to be in the
94 game, and interfaces may need to do some of their own processing in
95 between. */
96
97 void
parse_command_line(int argc,char * argv[],int spec)98 parse_command_line(int argc, char *argv[], int spec)
99 {
100 char *arg, *aispec, tmpspec[100], tmpargbuf[CLIBUFSIZE], blurb[BLURBSIZE];
101 int i, n, numused, total_arg_space, tmpargbuflen = 0;
102
103 /* This macro just checks that a required next argument is actually
104 there. */
105
106 #define REQUIRE_ONE_ARG \
107 if (i + 1 >= argc) { \
108 fprintf(stderr, "Error: `%s' requires an argument, exiting now\n", argv[i]); \
109 had_error = TRUE; \
110 continue; \
111 } \
112 numused = 2;
113
114 /* Each of these causes argument parsing to skip over the option if
115 it's not the right time to look at it. */
116
117 #define GENERAL_OPTION if (spec != general_options) continue;
118 #define VARIANT_OPTION if (spec != variant_options) continue;
119 #define PLAYER_OPTION if (spec != player_options) continue;
120
121 /* (should peel off any path stuff) */
122 program_name = argv[0];
123
124 if (spec == general_options)
125 init_options();
126
127 total_arg_space = 0;
128 for (i = 0; i < argc; ++i) {
129 if (!empty_string(argv[i])) {
130 strncpy(tmpargbuf, argv[i], CLIBUFSIZE);
131 tmpargbuf[CLIBUFSIZE - 1] = 0;
132 tmpargbuflen = strlen(tmpargbuf);
133 total_arg_space += tmpargbuflen + 2;
134 (argv[i])[tmpargbuflen] = 0;
135 }
136 }
137 if (args_used == NULL)
138 args_used = (char *)xmalloc (total_arg_space);
139
140 for (i = 1; i < argc; ++i) {
141 if (argv[i] == NULL || (argv[i])[0] == '\0') {
142 /* Empty or already munched, nothing to do. */
143 } else if ((argv[i])[0] == '-') {
144 arg = argv[i];
145 Dprintf("%s\n", arg);
146 numused = 1;
147 if (strcmp(arg, "-c") == 0) {
148 REQUIRE_ONE_ARG;
149 GENERAL_OPTION;
150 checkpoint_interval = atoi(argv[i+1]);
151 } else if (strcmp(arg, "-design") == 0) {
152 GENERAL_OPTION;
153 #ifdef DESIGNERS
154 allbedesigners = TRUE;
155 #else
156 fprintf(stderr,
157 "No designing available, ignoring option `%s'\n", arg);
158 #endif /* DESIGNERS */
159 } else if (strncmp(arg, "-D", 2) == 0) {
160 GENERAL_OPTION;
161 #ifdef DEBUGGING
162 Debug = TRUE;
163 if (strchr(arg+2, '-'))
164 Debug = FALSE;
165 if (strchr(arg+2, 'M'))
166 DebugM = TRUE;
167 if (strchr(arg+2, 'G'))
168 DebugG = TRUE;
169 #else
170 fprintf(stderr,
171 "No debugging available, ignoring option `%s'\n", arg);
172 #endif /* DEBUGGING */
173 } else if (strncmp(arg, "-e", 2) == 0) {
174 REQUIRE_ONE_ARG;
175 PLAYER_OPTION;
176 n = atoi(argv[i+1]);
177 /* A comma indicates that the name of a particular
178 desired AI type follows. */
179 if (strlen(arg) > 2) {
180 aispec = arg + 2;
181 if (*aispec != ',') {
182 sprintf(tmpspec, "%s%s", default_ai_type, aispec);
183 aispec = tmpspec;
184 }
185 } else {
186 aispec = default_ai_type;
187 }
188 while (n-- > 0)
189 add_a_raw_player_spec(aispec);
190 } else if (strcmp(arg, "-f") == 0) {
191 REQUIRE_ONE_ARG;
192 GENERAL_OPTION;
193 add_a_module(NULL, argv[i+1]);
194 } else if (strcmp(arg, "-g") == 0) {
195 REQUIRE_ONE_ARG;
196 GENERAL_OPTION;
197 add_a_module(copy_string(argv[i+1]), NULL);
198 } else if (strcmp(arg, "-h") == 0) {
199 REQUIRE_ONE_ARG;
200 PLAYER_OPTION;
201 n = atoi(argv[i+1]);
202 option_num_to_wait_for += n;
203 while (n-- > 0)
204 add_a_raw_player_spec("?@");
205 } else if (strcmp(arg, "-help") == 0) {
206 GENERAL_OPTION;
207 help_wanted = TRUE;
208 /* Will display help info later. */
209 } else if (strcmp(arg, "-host") == 0) {
210 REQUIRE_ONE_ARG;
211 GENERAL_OPTION;
212 option_game_to_host = copy_string(argv[i+1]);
213 } else if (strcmp(arg, "-join") == 0) {
214 REQUIRE_ONE_ARG;
215 GENERAL_OPTION;
216 option_game_to_join = copy_string(argv[i+1]);
217 } else if (strcmp(arg, "-L") == 0) {
218 REQUIRE_ONE_ARG;
219 GENERAL_OPTION;
220 if (strcmp(argv[i+1], "-") == 0)
221 add_library_path(NULL);
222 else
223 add_library_path(argv[i+1]);
224 } else if (strcmp(arg, "-M") == 0) {
225 REQUIRE_ONE_ARG;
226 VARIANT_OPTION;
227 parse_world_option(argv[i+1]);
228 } else if (strcmp(arg, "-noai") == 0) {
229 PLAYER_OPTION;
230 initially_no_ai = TRUE;
231 } else if (strcmp(arg, "-r") == 0) {
232 PLAYER_OPTION;
233 option_add_default_player = FALSE;
234 } else if (strcmp(arg, "-R") == 0) {
235 REQUIRE_ONE_ARG;
236 GENERAL_OPTION;
237 #ifdef DEBUGGING
238 init_xrandom(atoi(argv[i+1]));
239 #else
240 fprintf(stderr,
241 "No debugging available, ignoring option `%s'\n", arg);
242 #endif /* DEBUGGING */
243 } else if (strcmp(arg, "-seq") == 0) {
244 VARIANT_OPTION;
245 push_key_int_binding(&variant_settings, K_SEQUENTIAL, 1);
246 } else if (strcmp(arg, "-sim") == 0) {
247 VARIANT_OPTION;
248 push_key_int_binding(&variant_settings, K_SEQUENTIAL, 0);
249 } else if (strncmp(arg, "-t", 2) == 0) {
250 REQUIRE_ONE_ARG;
251 VARIANT_OPTION;
252 parse_realtime_option(arg, argv[i+1]);
253 } else if (strncmp(arg, "-v", 2) == 0) {
254 VARIANT_OPTION;
255 parse_variant(arg + 2);
256 } else if (strcmp(arg, "-V") == 0) {
257 VARIANT_OPTION;
258 push_key_int_binding(&variant_settings, K_SEE_ALL, 1);
259 } else if (strcmp(arg, "-V0") == 0) {
260 VARIANT_OPTION;
261 push_key_int_binding(&variant_settings, K_SEE_ALL, 0);
262 } else if (strcmp(arg, "-Vfalse") == 0) {
263 VARIANT_OPTION;
264 push_key_int_binding(&variant_settings, K_SEE_ALL, 0);
265 } else if (strcmp(arg, "-w") == 0) {
266 GENERAL_OPTION;
267 warnings_suppressed = TRUE;
268 } else if (strcmp(arg, "-x") == 0) {
269 GENERAL_OPTION;
270 option_popup_new_game_dialog = TRUE;
271 } else if (strcmp(arg, "--help") == 0) {
272 GENERAL_OPTION;
273 help_wanted = TRUE;
274 /* Will display help info later. */
275 } else if (strcmp(arg, "--version") == 0) {
276 GENERAL_OPTION;
277 version_wanted = TRUE;
278 } else {
279 numused = 0;
280 /* Anything unrecognized during the last parse is an error. */
281 if (spec >= leftover_options) {
282 fprintf(stderr, "Unrecognized option `%s'\n", arg);
283 had_error = TRUE;
284 }
285 }
286 if (numused >= 1) {
287 strcat(args_used, " ");
288 strcat(args_used, argv[i]);
289 argv[i] = "";
290 }
291 if (numused >= 2) {
292 strcat(args_used, " ");
293 strcat(args_used, argv[i+1]);
294 argv[i+1] = "";
295 }
296 if (numused >= 1)
297 i += (numused - 1);
298 } else {
299 if (spec == player_options) {
300 if (*(argv[i]) == '+' || *(argv[i]) == '@') {
301 raw_default_player_spec = argv[i];
302 } else {
303 add_a_raw_player_spec(argv[i]);
304 }
305 strcat(args_used, " ");
306 strcat(args_used, argv[i]);
307 argv[i] = NULL;
308 }
309 }
310 }
311 if (version_wanted) {
312 version_info();
313 }
314 if (had_error || help_wanted || variant_help_wanted) {
315 /* If we want to get help about a particular game, have to
316 load it first. */
317 if (help_wanted || variant_help_wanted)
318 load_all_modules();
319 if (had_error || help_wanted)
320 general_usage_info();
321 if (had_error || help_wanted)
322 player_usage_info();
323 if (help_wanted && mainmodule != NULL) {
324 printf("\nGame info:\n\n");
325 if (!empty_string(mainmodule->title))
326 printf("%s (%s)\n", mainmodule->title, mainmodule->name);
327 else
328 printf("%s\n", mainmodule->name);
329 printf(" %s\n");
330 if (mainmodule->blurb != lispnil) {
331 append_blurb_strings(blurb, mainmodule->blurb);
332 printf("%s", blurb);
333 } else {
334 printf("(no description)");
335 }
336 }
337 /* Display variant info here so it comes after basic info
338 about the game module. */
339 if (had_error || help_wanted || variant_help_wanted)
340 game_usage_info();
341 }
342 if (had_error || help_wanted || variant_help_wanted || version_wanted) {
343 exit(had_error);
344 }
345 }
346
347 /* Given a module name and/or filename, add it to the list of modules
348 to load. */
349
350 void
add_a_module(char * name,char * filename)351 add_a_module(char *name, char *filename)
352 {
353 Module *module;
354
355 module = get_game_module(name);
356 if (module == NULL)
357 exit(1); /* bad error if happens */
358 if (filename)
359 module->filename = copy_string(filename);
360 if (mainmodule != NULL)
361 printf("Warning: game module already specified, will replace");
362 mainmodule = module;
363 }
364
365 /* Glue an unprocessed player spec onto the list of other specs found
366 on the command line. */
367
368 static void
add_a_raw_player_spec(char * specstr)369 add_a_raw_player_spec(char *specstr)
370 {
371 struct raw_spec *spec =
372 (struct raw_spec *) xmalloc (sizeof(struct raw_spec));
373
374 spec->spec = copy_string(specstr);
375 if (raw_player_specs == NULL)
376 raw_player_specs = spec;
377 else
378 last_raw_player_spec->next = spec;
379 last_raw_player_spec = spec;
380 }
381
382 static void
version_info(void)383 version_info(void)
384 {
385 printf("Xconq (%s) version %s\n", program_name, version_string());
386 }
387
388 /* This routine prints out help info about all the possible arguments. */
389
390 static void
general_usage_info(void)391 general_usage_info(void)
392 {
393 printf("Usage:\n\t%s [ -options ... ]\n\n", program_name);
394 printf("General options:\n\n");
395 printf(" -c n\t\tcheckpoint every <n> turns\n");
396 printf(" -f filename\t\trun <filename> as a game\n");
397 printf(" -g gamename\t\tfind <gamename> in library and run it\n");
398 printf(" -help\t\tdisplay this help info\n");
399 printf(" -host <game@host>\thost the given game\n");
400 printf(" -join <game@host>\tconnect to the given game\n");
401 printf(" -L pathname\t\tset <pathname> to be library location\n");
402 printf(" -w\t\t\tsuppress warnings\n");
403 printf(" -x\t\t\tuse game setup dialogs to choose game and options\n");
404 printf(" -design\t\tmake every player a designer");
405 #ifndef DESIGNERS
406 printf(" (not available)");
407 #endif
408 printf("\n");
409 /* We don't display the debugging options -D* and -R, on the
410 theory that only hackers should try to use them. */
411 /* Group the long options together, but don't identify them
412 specially. */
413 printf(" --help\t\tdisplay this help info\n");
414 printf(" --version\t\tdisplay version info\n");
415 }
416
417 /* Describe the available variants for a game. */
418
419 static void
game_usage_info(void)420 game_usage_info(void)
421 {
422 int i, wid, hgt, circumf, lat, lon, pergame, perside, perturn;
423 char *varid;
424 char buf[BUFSIZE];
425 Variant *var;
426 Obj *vardflt;
427
428 printf("\nGame variant options");
429 if (mainmodule == NULL) {
430 printf(":\n\n No game loaded, no information available.\n\n");
431 return;
432 }
433 printf(" for \"%s\":\n\n", mainmodule->name);
434 if (mainmodule->variants == NULL) {
435 printf(" No variants available.\n\n");
436 return;
437 }
438 for (i = 0; mainmodule->variants[i].id != lispnil; ++i) {
439 var = &(mainmodule->variants[i]);
440 varid = c_string(var->id);
441 vardflt = var->dflt;
442 switch (keyword_code(varid)) {
443 case K_SEE_ALL:
444 printf(" -V\t\t\t%s (default %s)\n",
445 var->help,
446 (vardflt == lispnil ? "true" :
447 (c_number(eval(vardflt)) ? "true" : "false")));
448 break;
449 case K_SEQUENTIAL:
450 printf(" -seq\t\t%s (default %s)\n",
451 var->help,
452 (vardflt == lispnil ? "false" :
453 (c_number(eval(vardflt)) ? "false" : "true")));
454 printf(" -sim\t\tSides move simultaneously (opposite of -seq)\n");
455 break;
456 case K_WORLD_SEEN:
457 printf(" -v\t\t\t%s (default %s)\n",
458 var->help,
459 (vardflt == lispnil ? "true" :
460 (c_number(eval(vardflt)) ? "true" : "false")));
461 break;
462 case K_WORLD_SIZE:
463 printf(" -M wid[xhgt][Wcircumf][+lat][+long]\tset world size (default ");
464 /* Note that if the game definition sets these values
465 directly using world or area forms, this is misleading;
466 but that's the fault of the game designer for including
467 both preset values and a variant whose defaults don't
468 match those presets. */
469 circumf = DEFAULTCIRCUMFERENCE;
470 wid = DEFAULTWIDTH; hgt = DEFAULTHEIGHT;
471 lat = lon = 0;
472 /* Pick the width and height out of the list. */
473 if (vardflt != lispnil) {
474 wid = c_number(eval(car(vardflt)));
475 vardflt = cdr(vardflt);
476 }
477 if (vardflt != lispnil) {
478 hgt = c_number(eval(car(vardflt)));
479 vardflt = cdr(vardflt);
480 } else {
481 hgt = wid;
482 }
483 /* Pick up a circumference etc if given. */
484 if (vardflt != lispnil) {
485 circumf = c_number(eval(car(vardflt)));
486 vardflt = cdr(vardflt);
487 }
488 if (vardflt != lispnil) {
489 lat = c_number(eval(car(vardflt)));
490 vardflt = cdr(vardflt);
491 }
492 if (vardflt != lispnil) {
493 lon = c_number(eval(car(vardflt)));
494 }
495 printf("%dx%dW%d", wid, hgt, circumf);
496 if (lat != 0 || lon != 0)
497 printf("+%d+%d", lat, lon);
498 printf(")\n");
499 break;
500 case K_REAL_TIME:
501 pergame = perside = perturn = 0;
502 if (vardflt != lispnil) {
503 pergame = c_number(eval(car(vardflt)));
504 vardflt = cdr(vardflt);
505 }
506 if (vardflt != lispnil) {
507 perside = c_number(eval(car(vardflt)));
508 vardflt = cdr(vardflt);
509 }
510 if (vardflt != lispnil) {
511 perturn = c_number(eval(car(vardflt)));
512 }
513 printf(" -tgame mins\t\tlimit game time to <mins> minutes (default %d)\n",
514 pergame);
515 printf(" -tside mins\t\tlimit each player <mins> minutes in all (default %d)\n",
516 perside);
517 printf(" -tturn mins\t\tlimit each turn to <mins> minutes (default %d)\n",
518 perturn);
519 break;
520 default:
521 printf(" -v%s[=value]\t%s (default ", varid, var->help);
522 if (vardflt == lispnil
523 || (numberp(vardflt) && c_number(vardflt) == 0)) {
524 printf("false");
525 } else if (numberp(vardflt) && c_number(vardflt) == 1) {
526 printf("true");
527 } else {
528 sprintlisp(buf, vardflt, BUFSIZE);
529 printf("%s", buf);
530 }
531 printf(")\n");
532 break;
533 }
534 }
535 }
536
537 /* Dump info about player setup options. These can only get used when
538 the game has been loaded and variants chosen. */
539
540 static void
player_usage_info(void)541 player_usage_info(void)
542 {
543 printf("\nPlayer setup options:\n\n");
544 printf(" [[name][,ai][/config]@]host[+advantage]\tadd player\n");
545 printf(" ai\t\t= name of AI type or \"ai\" for default type\n");
546 printf(" config\t\t= name of config file\n");
547 printf(" host\t\t= name of player's host machine or display\n");
548 printf(" advantage\t= numerical initial advantage (default 1)\n");
549 printf(" -e number[,ai]\tadd <number> computer players\n");
550 printf(" -h number[,ai]\tadd <number> human players\n");
551 printf(" -noai\t\tsuppress all AIs\n");
552 printf(" -r\t\t\tno default player on local display\n");
553 /* (should available AI types here) */
554 }
555
556 /* Given a string representing world dimensions, extract various
557 components. */
558
559 static void
parse_world_option(char * str)560 parse_world_option(char *str)
561 {
562 char *str2;
563
564 option_width = atoi(str);
565 option_height = option_width;
566 str2 = strchr(str, 'x');
567 if (str2 != NULL)
568 option_height = atoi(str2 + 1);
569 /* Add a world circumference setting if present. */
570 str2 = strchr(str, 'W');
571 if (str2 != NULL)
572 option_circumference = atoi(str2 + 1);
573 }
574
575 static void
parse_realtime_option(char * subopt,char * arg)576 parse_realtime_option(char *subopt, char *arg)
577 {
578 if (strcmp(subopt, "-tgame") == 0) {
579 option_total_game_time = 60 * atoi(arg);
580 } else if (strcmp(subopt, "-tside") == 0) {
581 option_per_side_time = 60 * atoi(arg);
582 } else if (strcmp(subopt, "-tturn") == 0) {
583 option_per_turn_time = 60 * atoi(arg);
584 } else {
585 fprintf(stderr, "Realtime option not one of -tgame, -tside, -tturn, ignoring\n");
586 }
587 }
588
589 /* Given a variant, turn it into a list "(name val)". */
590
591 static void
parse_variant(char * str)592 parse_variant(char *str)
593 {
594 char *varname = NULL, *str2;
595 Obj *varval = lispnil;
596
597 if (strcmp(str, "") == 0) {
598 push_key_int_binding(&variant_settings, K_WORLD_SEEN, 1);
599 } else if (strcmp(str, "help") == 0) {
600 variant_help_wanted = TRUE;
601 } else {
602 str2 = strchr(str, '=');
603 if (str2 != NULL && str2 != str) {
604 /* (should interp val as string or number) */
605 varval = new_number(atoi(str2 + 1));
606 varname = copy_string(str);
607 varname[str2 - str] = '\0';
608 } else {
609 /* Assume varname by itself means "enable" (set to value of 1). */
610 varname = str;
611 varval = new_number(1);
612 }
613 if (varname)
614 push_binding(&variant_settings, intern_symbol(varname), varval);
615 }
616 }
617
618 /* Load the game module asked for on the cmd line, or else the
619 default. */
620
621 void
load_all_modules(void)622 load_all_modules(void)
623 {
624 if (mainmodule != NULL) {
625 load_game_module(mainmodule, TRUE);
626 } else {
627 /* If we've got absolutely no files to load, the standard game
628 is the one to go for. It will direct the remainder of
629 random generation. */
630 load_default_game();
631 }
632 }
633
634 /* Set module variants from command line options. */
635
636 void
set_variants_from_options(void)637 set_variants_from_options(void)
638 {
639 int which;
640 char *varname;
641 Obj *varrest, *varset;
642
643 /* Only the host of a networked game can set variants. */
644 if (option_game_to_join != NULL) {
645 if (variant_settings != lispnil
646 || option_width > 0)
647 fprintf(stderr, "Not the host, ignoring variant settings\n");
648 return;
649 }
650 if (option_width > 0) {
651 which = find_variant_from_name(mainmodule, keyword_name(K_WORLD_SIZE));
652 if (which >= 0)
653 net_set_variant_value(which, option_width, option_height,
654 option_circumference);
655 else
656 fprintf(stderr, "World size variant not available, -M ignored\n");
657 }
658 /* Set the real-time variant if any times were supplied. */
659 if (option_total_game_time != 0
660 || option_per_side_time != 0
661 || option_per_turn_time != 0) {
662 which = find_variant_from_name(mainmodule, keyword_name(K_REAL_TIME));
663 if (which >= 0)
664 net_set_variant_value(which, option_total_game_time,
665 option_per_side_time, option_per_turn_time);
666 else
667 fprintf(stderr, "Real time variants not available, ignored\n");
668 }
669 for_all_list(variant_settings, varrest) {
670 varset = car(varrest);
671 varname = c_string(car(varset));
672 which = find_variant_from_name(mainmodule, varname);
673 if (which >= 0)
674 net_set_variant_value(which, c_number(cadr(varset)), 0, 0);
675 else
676 fprintf(stderr, "No variant `%s' known, ignored\n", varname);
677 }
678 do_module_variants(mainmodule, lispnil);
679 }
680
681 /* Given a string, return the index of the variant for the module, or
682 -1 to indicate that it is not the name of a valid variant. */
683
684 static int
find_variant_from_name(Module * module,char * name)685 find_variant_from_name(Module *module, char *name)
686 {
687 int i;
688 Variant *var;
689
690 if (module->variants == NULL)
691 return -1;
692 for (i = 0; module->variants[i].id != lispnil; ++i) {
693 var = &(module->variants[i]);
694 if (strcmp(name, c_string(var->id)) == 0)
695 return i;
696 }
697 return -1;
698 }
699
700 /* Set player characteristics from command-line options. */
701
702 void
set_players_from_options(void)703 set_players_from_options(void)
704 {
705 int mergespecs;
706 Player *player;
707 struct raw_spec *spec;
708
709 /* Only the host of a networked game can set up players. */
710 if (option_game_to_join != NULL) {
711 make_default_player_spec();
712 return;
713 }
714 player = NULL;
715 /* Assume that if any players exist already, then this is a restored
716 game of some sort, and merge instead of adding new players. */
717 mergespecs = (numplayers > 0);
718 /* Add a player for the indepside if none found. */
719 if (indepside_needed() && find_player(0) == NULL)
720 player = add_player();
721 /* If we're merging specs, skip over the indepside player. */
722 if (mergespecs)
723 player = playerlist->next;
724 /* Add the default player. */
725 if (option_game_to_host == NULL
726 && (raw_player_specs == NULL || option_add_default_player)) {
727 if (!mergespecs)
728 player = add_default_player();
729 parse_player_spec(player, raw_default_player_spec);
730 canonicalize_player(player);
731 if (player)
732 player = player->next;
733 }
734 /* Add the explicitly listed players. */
735 for (spec = raw_player_specs; spec != NULL; spec = spec->next) {
736 if (mergespecs) {
737 if (player == NULL) {
738 fprintf(stderr, "Excess player spec `%s', ignoring\n",
739 spec->spec);
740 continue;
741 }
742 } else {
743 player = add_player();
744 }
745 parse_player_spec(player, spec->spec);
746 canonicalize_player(player);
747 player = player->next;
748 }
749 /* If we made a special request to suppress AIs, go through all
750 players existing at this time. */
751 if (initially_no_ai) {
752 for_all_players(player) {
753 player->aitypename = NULL;
754 }
755 }
756 /* Transmit the official list of players to everybody else. */
757 if (my_rid > 0 && my_rid == master_rid) {
758 for_all_players(player) {
759 net_update_player(player);
760 }
761 }
762 }
763
764 /* This is not, strictly speaking, part of command line processing,
765 but command-line programs are also the ones for which stdio is
766 useful. */
767
768 void
print_instructions(void)769 print_instructions(void)
770 {
771 Obj *instructions, *rest;
772
773 printf("\n");
774 if (mainmodule != NULL
775 && (instructions = mainmodule->instructions) != lispnil) {
776 if (stringp(instructions)) {
777 printf("%s\n", c_string(instructions));
778 } else if (consp(instructions)) {
779 for_all_list(instructions, rest) {
780 if (stringp(car(rest))) {
781 printf("%s\n", c_string(car(rest)));
782 } else {
783 run_warning("Instructions are of wrong type");
784 }
785 }
786 } else {
787 run_warning("Instructions are of wrong type");
788 }
789 } else {
790 printf("(no instructions supplied)\n");
791 }
792 }
793