Add CLI option for two player game, and associated framework to hook it all together.
[sgk-go] / interface / main.c
CommitLineData
7eeb782e
AT
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
3 * http://www.gnu.org/software/gnugo/ for more information. *
4 * *
5 * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
6 * 2008 and 2009 by the Free Software Foundation. *
7 * *
8 * This program is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU General Public License as *
10 * published by the Free Software Foundation - version 3 or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License in file COPYING for more details. *
17 * *
18 * You should have received a copy of the GNU General Public *
19 * License along with this program; if not, write to the Free *
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
21 * Boston, MA 02111, USA. *
22\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23
24#include "gnugo.h"
25
c150f57c 26#include <ctype.h>
3ebb0002 27#include <stdbool.h>
7eeb782e
AT
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
7eeb782e
AT
31
32#ifdef HAVE_UNISTD_H
33/* For isatty(). */
34#include <unistd.h>
35#else
36#include <io.h>
37#endif
38
39#if TIME_WITH_SYS_TIME
c150f57c
AT
40#include <sys/time.h>
41#include <time.h>
42#else
43#if HAVE_SYS_TIME_H
44#include <sys/time.h>
7eeb782e 45#else
c150f57c
AT
46#include <time.h>
47#endif
7eeb782e
AT
48#endif
49
50#include "liberty.h"
51
52#include "gg-getopt.h"
53#include "gg_utils.h"
54#include "winsocket.h"
55
56#include "interface.h"
7eeb782e 57#include "random.h"
c150f57c 58#include "sgftree.h"
7eeb782e
AT
59
60static void show_copyright(void);
61static void show_version(void);
62static void show_help(void);
63static void show_debug_help(void);
64static void show_debug_flags(void);
65
c150f57c
AT
66static void socket_connect_to(const char* host_name, unsigned int port,
67 FILE** input_file, FILE** output_file);
68static void socket_listen_at(const char* host_name, unsigned int port,
69 FILE** input_file, FILE** output_file);
70static void socket_close_connection(FILE* input_file, FILE* output_file);
71static void socket_stop_listening(FILE* input_file, FILE* output_file);
7eeb782e
AT
72
73/* long options which have no short form */
c150f57c
AT
74enum { OPT_BOARDSIZE = 127,
75 OPT_HANDICAPSTONES,
76 OPT_COLOR,
77 OPT_KOMI,
78 OPT_CLOCK_TIME,
79 OPT_CLOCK_BYO_TIME,
80 OPT_CLOCK_BYO_PERIOD,
81 OPT_AUTOLEVEL,
82 OPT_MODE,
83 OPT_INFILE,
84 OPT_OUTFILE,
85 OPT_QUIET,
86 OPT_GTP_INPUT,
87 OPT_GTP_CONNECT,
88 OPT_GTP_LISTEN,
89 OPT_GTP_DUMP_COMMANDS,
90 OPT_GTP_INITIAL_ORIENTATION,
91 OPT_GTP_VERSION,
92 OPT_SHOWCOPYRIGHT,
93 OPT_REPLAY_GAME,
94 OPT_DECIDE_STRING,
95 OPT_DECIDE_CONNECTION,
96 OPT_DECIDE_OWL,
97 OPT_DECIDE_DRAGON_DATA,
98 OPT_DECIDE_SEMEAI,
99 OPT_DECIDE_SURROUNDED,
100 OPT_DECIDE_TACTICAL_SEMEAI,
101 OPT_DECIDE_ORACLE,
102 OPT_EXPERIMENTAL_SEMEAI,
103 OPT_EXPERIMENTAL_OWL_EXT,
104 OPT_SEMEAI_NODE_LIMIT,
105 OPT_EXPERIMENTAL_CONNECTIONS,
106 OPT_ALTERNATE_CONNECTIONS,
107 OPT_WITH_BREAK_IN,
108 OPT_WITHOUT_BREAK_IN,
109 OPT_COSMIC_GNUGO,
110 OPT_NO_COSMIC_GNUGO,
111 OPT_LARGE_SCALE,
112 OPT_NO_LARGE_SCALE,
113 OPT_OPTIONS,
114 OPT_STANDARD_SEMEAI,
115 OPT_STANDARD_CONNECTIONS,
116 OPT_PRINT_LEVELS,
117 OPT_DECIDE_POSITION,
118 OPT_DECIDE_EYE,
119 OPT_DECIDE_COMBINATION,
120 OPT_BRANCH_DEPTH,
121 OPT_BACKFILL2_DEPTH,
122 OPT_BREAK_CHAIN_DEPTH,
123 OPT_SUPERSTRING_DEPTH,
124 OPT_AA_DEPTH,
125 OPT_DEBUG_FLAGS,
126 OPT_OWL_DISTRUST,
127 OPT_OWL_BRANCH,
128 OPT_OWL_READING,
129 OPT_OWL_NODE_LIMIT,
130 OPT_NOFUSEKIDB,
131 OPT_NOFUSEKI,
132 OPT_NOJOSEKIDB,
133 OPT_LEVEL,
134 OPT_MIN_LEVEL,
135 OPT_MAX_LEVEL,
136 OPT_LIMIT_SEARCH,
137 OPT_SHOWTIME,
138 OPT_SHOWSCORE,
139 OPT_DEBUG_INFLUENCE,
140 OPT_SCORE,
141 OPT_PRINTSGF,
142 OPT_PROFILE_PATTERNS,
143 OPT_CHINESE_RULES,
144 OPT_OWL_THREATS,
145 OPT_NO_OWL_THREATS,
146 OPT_JAPANESE_RULES,
147 OPT_FORBID_SUICIDE,
148 OPT_ALLOW_SUICIDE,
149 OPT_ALLOW_ALL_SUICIDE,
150 OPT_SIMPLE_KO,
151 OPT_NO_KO,
152 OPT_POSITIONAL_SUPERKO,
153 OPT_SITUATIONAL_SUPERKO,
154 OPT_CAPTURE_ALL_DEAD,
155 OPT_PLAY_OUT_AFTERMATH,
156 OPT_MIRROR,
157 OPT_MIRROR_LIMIT,
158 OPT_METAMACHINE,
159 OPT_RESIGN_ALLOWED,
160 OPT_NEVER_RESIGN,
161 OPT_MONTE_CARLO,
162 OPT_MC_GAMES_PER_LEVEL,
163 OPT_MC_PATTERNS,
164 OPT_MC_LIST_PATTERNS,
165 OPT_MC_LOAD_PATTERNS
7eeb782e
AT
166};
167
168/* names of playing modes */
169
170enum mode {
c150f57c
AT
171 MODE_UNKNOWN = 0,
172 MODE_ASCII,
3ebb0002
AT
173 MODE_ANSI,
174 MODE_STRICTANSI,
de03db18 175 MODE_TWOPLAYER,
c150f57c
AT
176 MODE_GTP,
177 MODE_GMP,
178 MODE_SGMP,
179 MODE_SGF,
180 MODE_LOAD_AND_ANALYZE,
181 MODE_LOAD_AND_SCORE,
182 MODE_LOAD_AND_PRINT,
183 MODE_SOLO,
184 MODE_REPLAY,
185 MODE_DECIDE_STRING,
186 MODE_DECIDE_CONNECTION,
187 MODE_DECIDE_OWL,
188 MODE_DECIDE_DRAGON_DATA,
189 MODE_DECIDE_SEMEAI,
190 MODE_DECIDE_TACTICAL_SEMEAI,
191 MODE_DECIDE_POSITION,
192 MODE_DECIDE_EYE,
193 MODE_DECIDE_COMBINATION,
194 MODE_DECIDE_SURROUNDED,
195 MODE_DECIDE_ORACLE
7eeb782e
AT
196};
197
7eeb782e
AT
198/* Definitions of the --long options. Final column is
199 * either an OPT_ as defined in the enum above, or it
200 * is the equivalent single-letter option.
201 * It is useful to keep them in the same order as the
202 * help string, for maintenance purposes only.
203 */
204
c150f57c
AT
205static struct gg_option const long_options[] = {
206 { "mode", required_argument, 0, OPT_MODE },
207 { "replay", required_argument, 0, OPT_REPLAY_GAME },
208 { "quiet", no_argument, 0, OPT_QUIET },
209 { "silent", no_argument, 0, OPT_QUIET },
210 { "gtp-input", required_argument, 0, OPT_GTP_INPUT },
211 { "gtp-connect", required_argument, 0, OPT_GTP_CONNECT },
212 { "gtp-listen", required_argument, 0, OPT_GTP_LISTEN },
213 { "gtp-dump-commands", required_argument, 0, OPT_GTP_DUMP_COMMANDS },
214 { "orientation", required_argument, 0, OPT_GTP_INITIAL_ORIENTATION },
215 { "gtp-initial-orientation",
216 required_argument, 0, OPT_GTP_INITIAL_ORIENTATION },
217 { "gtp-version", required_argument, 0, OPT_GTP_VERSION },
218 { "infile", required_argument, 0, 'l' },
219 { "until", required_argument, 0, 'L' },
220 { "outfile", required_argument, 0, 'o' },
221 { "output-flags", required_argument, 0, 'O' },
222 { "boardsize", required_argument, 0, OPT_BOARDSIZE },
223 { "color", required_argument, 0, OPT_COLOR },
224 { "handicap", required_argument, 0, OPT_HANDICAPSTONES },
225 { "komi", required_argument, 0, OPT_KOMI },
226 { "help", optional_argument, 0, 'h' },
227 { "copyright", no_argument, 0, OPT_SHOWCOPYRIGHT },
228 { "version", no_argument, 0, 'v' },
229 { "allpats", no_argument, 0, 'a' },
230 { "printboard", no_argument, 0, 'T' },
231 { "printeyes", no_argument, 0, 'E' },
232 { "debug", required_argument, 0, 'd' },
233 { "debug-flags", no_argument, 0, OPT_DEBUG_FLAGS },
234 { "depth", required_argument, 0, 'D' },
235 { "backfill-depth", required_argument, 0, 'B' },
236 { "branch-depth", required_argument, 0, OPT_BRANCH_DEPTH },
237 { "backfill2-depth", required_argument, 0, OPT_BACKFILL2_DEPTH },
238 { "break-chain-depth", required_argument, 0, OPT_BREAK_CHAIN_DEPTH },
239 { "superstring-depth", required_argument, 0, OPT_SUPERSTRING_DEPTH },
240 { "fourlib-depth", required_argument, 0, 'F' },
241 { "ko-depth", required_argument, 0, 'K' },
242 { "aa-depth", required_argument, 0, OPT_AA_DEPTH },
243 { "owl-distrust", required_argument, 0, OPT_OWL_DISTRUST },
244 { "owl-branch", required_argument, 0, OPT_OWL_BRANCH },
245 { "owl-reading", required_argument, 0, OPT_OWL_READING },
246 { "owl-node-limit", required_argument, 0, OPT_OWL_NODE_LIMIT },
247 { "print-levels", no_argument, 0, OPT_PRINT_LEVELS },
248 { "level", required_argument, 0, OPT_LEVEL },
249 { "min-level", required_argument, 0, OPT_MIN_LEVEL },
250 { "max-level", required_argument, 0, OPT_MAX_LEVEL },
251 { "limit-search", required_argument, 0, OPT_LIMIT_SEARCH },
252 { "clock", required_argument, 0, OPT_CLOCK_TIME },
253 { "byo-time", required_argument, 0, OPT_CLOCK_BYO_TIME },
254 { "byo-period", required_argument, 0, OPT_CLOCK_BYO_PERIOD },
255 { "autolevel", no_argument, 0, OPT_AUTOLEVEL },
256 { "chinese-rules", no_argument, 0, OPT_CHINESE_RULES },
257 { "japanese-rules", no_argument, 0, OPT_JAPANESE_RULES },
258 { "experimental-semeai", no_argument, 0, OPT_EXPERIMENTAL_SEMEAI },
259 { "experimental-owl-ext", no_argument, 0, OPT_EXPERIMENTAL_OWL_EXT },
260 { "semeai-node-limit", required_argument, 0, OPT_SEMEAI_NODE_LIMIT },
261 { "experimental-connections", no_argument, 0, OPT_EXPERIMENTAL_CONNECTIONS },
262 { "standard-connections", no_argument, 0, OPT_STANDARD_CONNECTIONS },
263 { "standard-semeai", no_argument, 0, OPT_STANDARD_SEMEAI },
264 { "alternate-connections", no_argument, 0, OPT_ALTERNATE_CONNECTIONS },
265 { "with-break-in", no_argument, 0, OPT_WITH_BREAK_IN },
266 { "without-break-in", no_argument, 0, OPT_WITHOUT_BREAK_IN },
267 { "cosmic-gnugo", no_argument, 0, OPT_COSMIC_GNUGO },
268 { "no-cosmic-gnugo", no_argument, 0, OPT_NO_COSMIC_GNUGO },
269 { "large-scale", no_argument, 0, OPT_LARGE_SCALE },
270 { "no-large-scale", no_argument, 0, OPT_NO_LARGE_SCALE },
271 { "options", no_argument, 0, OPT_OPTIONS },
272 { "forbid-suicide", no_argument, 0, OPT_FORBID_SUICIDE },
273 { "allow-suicide", no_argument, 0, OPT_ALLOW_SUICIDE },
274 { "allow-all-suicide", no_argument, 0, OPT_ALLOW_ALL_SUICIDE },
275 { "simple-ko", no_argument, 0, OPT_SIMPLE_KO },
276 { "no-ko", no_argument, 0, OPT_NO_KO },
277 { "positional-superko", no_argument, 0, OPT_POSITIONAL_SUPERKO },
278 { "situational-superko", no_argument, 0, OPT_SITUATIONAL_SUPERKO },
279 { "capture-all-dead", no_argument, 0, OPT_CAPTURE_ALL_DEAD },
280 { "play-out-aftermath", no_argument, 0, OPT_PLAY_OUT_AFTERMATH },
281 { "cache-size", required_argument, 0, 'M' },
282 { "worms", no_argument, 0, 'w' },
283 { "moyo", required_argument, 0, 'm' },
284 { "benchmark", required_argument, 0, 'b' },
285 { "statistics", no_argument, 0, 'S' },
286 { "trace", no_argument, 0, 't' },
287 { "seed", required_argument, 0, 'r' },
288 { "decide-string", required_argument, 0, OPT_DECIDE_STRING },
289 { "decide-connection", required_argument, 0, OPT_DECIDE_CONNECTION },
290 { "decide-dragon", required_argument, 0, OPT_DECIDE_OWL },
291 { "decide-owl", required_argument, 0, OPT_DECIDE_OWL },
292 { "decide-dragon-data", required_argument, 0, OPT_DECIDE_DRAGON_DATA },
293 { "decide-semeai", required_argument, 0, OPT_DECIDE_SEMEAI },
294 { "decide-tactical-semeai", required_argument, 0, OPT_DECIDE_TACTICAL_SEMEAI },
295 { "decide-position", no_argument, 0, OPT_DECIDE_POSITION },
296 { "decide-surrounded", required_argument, 0, OPT_DECIDE_SURROUNDED },
297 { "decide-eye", required_argument, 0, OPT_DECIDE_EYE },
298 { "decide-combination", no_argument, 0, OPT_DECIDE_COMBINATION },
299 { "decide-oracle", no_argument, 0, OPT_DECIDE_ORACLE },
300 { "nofusekidb", no_argument, 0, OPT_NOFUSEKIDB },
301 { "nofuseki", no_argument, 0, OPT_NOFUSEKI },
302 { "nojosekidb", no_argument, 0, OPT_NOJOSEKIDB },
303 { "debug-influence", required_argument, 0, OPT_DEBUG_INFLUENCE },
304 { "showtime", no_argument, 0, OPT_SHOWTIME },
305 { "showscore", no_argument, 0, OPT_SHOWSCORE },
306 { "score", required_argument, 0, OPT_SCORE },
307 { "printsgf", required_argument, 0, OPT_PRINTSGF },
308 { "profile-patterns", no_argument, 0, OPT_PROFILE_PATTERNS },
309 { "mirror", no_argument, 0, OPT_MIRROR },
310 { "mirror-limit", required_argument, 0, OPT_MIRROR_LIMIT },
311 { "metamachine", no_argument, 0, OPT_METAMACHINE },
312 { "resign-allowed", no_argument, 0, OPT_RESIGN_ALLOWED },
313 { "never-resign", no_argument, 0, OPT_NEVER_RESIGN },
314 { "monte-carlo", no_argument, 0, OPT_MONTE_CARLO },
315 { "mc-games-per-level", required_argument, 0, OPT_MC_GAMES_PER_LEVEL },
316 { "mc-patterns", required_argument, 0, OPT_MC_PATTERNS },
317 { "mc-list-patterns", no_argument, 0, OPT_MC_LIST_PATTERNS },
318 { "mc-load-patterns", required_argument, 0, OPT_MC_LOAD_PATTERNS },
319 { NULL, 0, NULL, 0 }
7eeb782e
AT
320};
321
c150f57c 322int main(int argc, char* argv[])
7eeb782e 323{
c150f57c
AT
324 Gameinfo gameinfo;
325 SGFTree sgftree;
326
327 int i;
328 int mandated_color = EMPTY;
329 enum mode playmode = MODE_UNKNOWN;
330 int replay_color = EMPTY;
331
332 char* infilename = NULL;
333 char* untilstring = NULL;
334 char* scoringmode = NULL;
335 char* outfile = NULL;
336 char* outflags = NULL;
337 char* gtpfile = NULL;
338 char* gtp_dump_commands_file = NULL;
339 int gtp_tcp_ip_mode = 0;
340 char* gtp_tcp_ip_address = NULL;
341
342 char* printsgffile = NULL;
343
344 char decide_this[8];
345 char* decide_that = NULL;
346 char debuginfluence_move[4] = "\0";
347
348 int benchmark = 0; /* benchmarking mode (-b) */
349 FILE* output_check;
350 int orientation = 0;
351
352 char mc_pattern_name[40] = "";
353 char mc_pattern_filename[320] = "";
354
355 float memory = (float)DEFAULT_MEMORY; /* Megabytes used for hash table. */
356
357 /* If seed is zero, GNU Go will play a different game each time. If
7eeb782e
AT
358 * it is set using -r, GNU Go will play the same game each time.
359 * (Change seed to get a different game).
360 */
c150f57c
AT
361 int seed = 0;
362 int seed_specified = 0;
363
364 int requested_boardsize = -1;
365
366 sgftree_clear(&sgftree);
367 gameinfo_clear(&gameinfo);
368
369 /* Weed through all of the command line options. */
370 while ((i = gg_getopt_long(argc, argv,
371 "-ab:B:d:D:EF:gh::K:l:L:M:m:o:O:p:r:fsStTvw",
372 long_options, NULL))
373 != EOF) {
374 switch (i) {
375 case 'T':
376 printboard++;
377 break;
378 case 't':
379 ++verbose;
380 break;
381 case 'a':
382 allpats = 1;
383 break;
384
385 case 1:
386 case 'l':
387 infilename = gg_optarg;
388 break;
389
390 case 'b':
391 benchmark = atoi(gg_optarg);
392 playmode = MODE_SOLO;
393 break;
394 case 'r':
395 seed = atoi(gg_optarg);
396 seed_specified = 1;
397 break;
398 case 'S':
399 showstatistics = 1;
400 break;
401 case 'w':
402 printworms = 1;
403 break;
404 case 'm':
405 printmoyo = strtol(gg_optarg, NULL, 0); /* allows 0x... */
406 break;
407 case 'd':
408 debug ^= strtol(gg_optarg, NULL, 0); /* allows 0x... */
409 break;
410 case 'D':
411 mandated_depth = atoi(gg_optarg);
412 break;
413 case 'M':
414 memory = atof(gg_optarg);
415 break; /* floating point number */
416 case 'E':
417 printboard = 2;
418 break;
419 case 'B':
420 mandated_backfill_depth = atoi(gg_optarg);
421 break;
422 case 'F':
423 mandated_fourlib_depth = atoi(gg_optarg);
424 break;
425 case 'K':
426 mandated_ko_depth = atoi(gg_optarg);
427 break;
428
429 case 'L':
430 untilstring = gg_optarg;
431 break;
432
433 case 'o':
434 if (strlen(gg_optarg) >= sizeof(outfilename)) {
435 fprintf(stderr, "Too long filename given as value to -o option.\n");
436 exit(EXIT_FAILURE);
437 }
438 outfile = gg_optarg;
439 strcpy(outfilename, gg_optarg);
440 break;
441
442 case 'O':
443 outflags = gg_optarg;
444 output_flags = 0;
445 if (outflags)
446 while (*outflags) {
447 switch (*outflags) {
448 case 'd':
449 output_flags |= OUTPUT_MARKDRAGONS;
450 break;
451 case 'v':
452 output_flags |= OUTPUT_MOVEVALUES;
453 break;
454 }
455 outflags++;
456 }
457 break;
458
459 case OPT_QUIET:
460 quiet = 1;
461 break;
462
463 case OPT_GTP_INPUT:
464 case OPT_GTP_CONNECT:
465 case OPT_GTP_LISTEN:
466 if (gtp_tcp_ip_mode != 0 || gtpfile != NULL) {
467 fprintf(stderr, ("Options `--gtp-input', `--gtp-connect' and `--gtp-listen' "
468 "are mutually-exclusive\n"));
469 exit(EXIT_FAILURE);
470 }
471
472 if (i == OPT_GTP_INPUT)
473 gtpfile = gg_optarg;
474 else {
475 gtp_tcp_ip_mode = i;
476 gtp_tcp_ip_address = gg_optarg;
477 }
478
479 break;
480
481 case OPT_GTP_DUMP_COMMANDS:
482 gtp_dump_commands_file = gg_optarg;
483 break;
484
485 case OPT_GTP_INITIAL_ORIENTATION:
486 orientation = atoi(gg_optarg);
487 if (orientation < 0 || orientation > 7) {
488 fprintf(stderr, "Invalid orientation: %d.\n", orientation);
489 fprintf(stderr, "Try `gnugo --help' for more information.\n");
490 exit(EXIT_FAILURE);
491 }
492 break;
493
494 case OPT_GTP_VERSION:
495 gtp_version = atoi(gg_optarg);
496 break;
497
498 case OPT_OPTIONS:
499 if (USE_BREAK_IN)
500 fprintf(stdout,
501 "configure option enabled: experimental break-ins\n");
502 if (COSMIC_GNUGO)
503 fprintf(stdout,
504 "configure option enabled: cosmic GNU Go \n");
505 if (LARGE_SCALE)
506 fprintf(stdout,
507 "configure option enabled: large scale captures \n");
508 if (EXPERIMENTAL_CONNECTIONS)
509 fprintf(stdout,
510 "configure option enabled: experimental connections\n");
511 if (ALTERNATE_CONNECTIONS)
512 fprintf(stdout,
513 "configure option enabled: alternate connections\n");
514 if (EXPERIMENTAL_OWL_EXT)
515 fprintf(stdout,
516 "configure option enabled: experimental GAIN/LOSS codes\n");
517 if (OWL_THREATS)
518 fprintf(stdout,
519 "configure option enabled: owl threats\n");
520 if (RESIGNATION_ALLOWED)
521 fprintf(stdout,
522 "configure option enabled: resignation allowed\n");
523 if (ORACLE)
524 fprintf(stdout,
525 "configure option enabled: oracle\n");
526 fprintf(stdout,
527 "Owl node limit: %d\n", OWL_NODE_LIMIT);
528 fprintf(stdout,
529 "Semeai node limit: %d\n", SEMEAI_NODE_LIMIT);
530 if (DEFAULT_MEMORY == -1)
531 fprintf(stdout, "Cache size: %d MB (special default value)\n",
532 DEFAULT_MEMORY);
533 else
534 fprintf(stdout, "Cache size: %d MB\n", DEFAULT_MEMORY);
535
536 return EXIT_SUCCESS;
537 break;
538
539 case OPT_SHOWTIME:
540 showtime = 1;
541 break;
542
543 case OPT_SHOWSCORE:
544 showscore = 1;
545 break;
546
547 case OPT_HANDICAPSTONES: {
548 int requested_handicap = atoi(gg_optarg);
549
550 if (requested_handicap < 0 || requested_handicap > MAX_HANDICAP) {
551 fprintf(stderr, "Unsupported handicap: %d.\n", requested_handicap);
552 fprintf(stderr, "Try `gnugo --help' for more information.\n");
553 exit(EXIT_FAILURE);
554 }
555 gameinfo.handicap = requested_handicap;
556 } break;
557
558 case OPT_BOARDSIZE:
559 requested_boardsize = atoi(gg_optarg);
560 break;
561
562 case OPT_KOMI:
563 if (sscanf(gg_optarg, "%f", &komi) != 1) {
564 fprintf(stderr, "Invalid komi selection: %s\n", gg_optarg);
565 fprintf(stderr, "Try `gnugo --help' for more information.\n");
566 exit(EXIT_FAILURE);
567 }
568 break;
569
570 case OPT_CHINESE_RULES:
571 chinese_rules = 1;
572 break;
573
574 case OPT_OWL_THREATS:
575 owl_threats = 1;
576 break;
577
578 case OPT_NO_OWL_THREATS:
579 owl_threats = 0;
580 break;
581
582 case OPT_METAMACHINE:
583 metamachine = 1;
584 break;
585
586 case OPT_JAPANESE_RULES:
587 chinese_rules = 0;
588 break;
589
590 case OPT_EXPERIMENTAL_OWL_EXT:
591 experimental_owl_ext = 1;
592 break;
593
594 case OPT_SEMEAI_NODE_LIMIT:
595 mandated_semeai_node_limit = atoi(gg_optarg);
596 break;
597
598 case OPT_EXPERIMENTAL_CONNECTIONS:
599 experimental_connections = 1;
600 break;
601
602 case OPT_STANDARD_CONNECTIONS:
603 experimental_connections = 0;
604 break;
605
606 case OPT_ALTERNATE_CONNECTIONS:
607 alternate_connections = !alternate_connections;
608 break;
609
610 case OPT_WITH_BREAK_IN:
611 experimental_break_in = 1;
612 break;
613
614 case OPT_WITHOUT_BREAK_IN:
615 experimental_break_in = 0;
616 break;
617
618 case OPT_COSMIC_GNUGO:
619 cosmic_gnugo = 1;
620 break;
621
622 case OPT_NO_COSMIC_GNUGO:
623 cosmic_gnugo = 0;
624 break;
625
626 case OPT_LARGE_SCALE:
627 large_scale = 1;
628 break;
629
630 case OPT_NO_LARGE_SCALE:
631 large_scale = 0;
632 break;
633
634 case OPT_FORBID_SUICIDE:
635 suicide_rule = FORBIDDEN;
636 break;
637
638 case OPT_ALLOW_SUICIDE:
639 suicide_rule = ALLOWED;
640 break;
641
642 case OPT_ALLOW_ALL_SUICIDE:
643 suicide_rule = ALL_ALLOWED;
644 break;
645
646 case OPT_SIMPLE_KO:
647 ko_rule = SIMPLE;
648 break;
649
650 case OPT_NO_KO:
651 ko_rule = NONE;
652 break;
653
654 case OPT_POSITIONAL_SUPERKO:
655 ko_rule = PSK;
656 break;
657
658 case OPT_SITUATIONAL_SUPERKO:
659 ko_rule = SSK;
660 break;
661
662 case OPT_CAPTURE_ALL_DEAD:
663 capture_all_dead = 1;
664 break;
665
666 case OPT_PLAY_OUT_AFTERMATH:
667 play_out_aftermath = 1;
668 break;
669
670 case OPT_RESIGN_ALLOWED:
671 resign_allowed = 1;
672 break;
673
674 case OPT_NEVER_RESIGN:
675 resign_allowed = 0;
676 break;
677
678 case OPT_MONTE_CARLO:
679 use_monte_carlo_genmove = 1;
680 break;
681
682 case OPT_MC_GAMES_PER_LEVEL:
683 mc_games_per_level = atoi(gg_optarg);
684 break;
685
686 case OPT_MC_PATTERNS:
687 if (strlen(gg_optarg) >= sizeof(mc_pattern_name)) {
688 fprintf(stderr, "Too long name given as value to --mc-patterns option.\n");
689 exit(EXIT_FAILURE);
690 }
691 strcpy(mc_pattern_name, gg_optarg);
692 break;
693
694 case OPT_MC_LIST_PATTERNS:
695 list_mc_patterns();
696 return EXIT_SUCCESS;
697 break;
698
699 case OPT_MC_LOAD_PATTERNS:
700 if (strlen(gg_optarg) >= sizeof(mc_pattern_filename)) {
701 fprintf(stderr, "Too long name given as value to --mc-load-patterns option.\n");
702 exit(EXIT_FAILURE);
703 }
704 strcpy(mc_pattern_filename, gg_optarg);
705 break;
706
707 case OPT_MODE:
708 if (strcmp(gg_optarg, "ascii") == 0)
709 playmode = MODE_ASCII;
3ebb0002
AT
710 else if (strcmp(gg_optarg, "ansi") == 0)
711 playmode = MODE_ANSI;
712 else if (strcmp(gg_optarg, "strictansi") == 0)
713 playmode = MODE_STRICTANSI;
de03db18
AT
714 else if (strcmp(gg_optarg, "twoplayer") == 0)
715 playmode = MODE_TWOPLAYER;
c150f57c
AT
716 else if (strcmp(gg_optarg, "gtp") == 0)
717 playmode = MODE_GTP;
718 else if (strcmp(gg_optarg, "gmp") == 0)
719 playmode = MODE_GMP;
720 else if (strcmp(gg_optarg, "sgmp") == 0)
721 playmode = MODE_SGMP;
722 else {
723 fprintf(stderr, "Invalid mode selection: %s\n", gg_optarg);
724 fprintf(stderr, "Try `gnugo --help' for more information.\n");
725
726 exit(EXIT_FAILURE);
727 }
728 break;
729
730 case OPT_DECIDE_STRING:
731 if (strlen(gg_optarg) > 3) {
732 fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
733 exit(EXIT_FAILURE);
734 }
735 strcpy(decide_this, gg_optarg);
736 playmode = MODE_DECIDE_STRING;
737 break;
738
739 case OPT_DECIDE_CONNECTION:
740 if (strlen(gg_optarg) > 7) {
741 fprintf(stderr,
742 "usage: --decide-connection [first string]/[second string]\n");
743 return EXIT_FAILURE;
744 }
745 strcpy(decide_this, gg_optarg);
746 strtok(decide_this, "/");
747 decide_that = strtok(NULL, "/");
748 if (!decide_that) {
749 fprintf(stderr,
750 "usage: --decide-connection [first string]/[second string]\n");
751 return EXIT_FAILURE;
752 }
753
754 playmode = MODE_DECIDE_CONNECTION;
755 break;
756
757 case OPT_DECIDE_OWL:
758 if (strlen(gg_optarg) > 3) {
759 fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
760 exit(EXIT_FAILURE);
761 }
762 strcpy(decide_this, gg_optarg);
763 playmode = MODE_DECIDE_OWL;
764 break;
765
766 case OPT_DECIDE_DRAGON_DATA:
767 if (strlen(gg_optarg) > 3) {
768 fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
769 exit(EXIT_FAILURE);
770 }
771 strcpy(decide_this, gg_optarg);
772 playmode = MODE_DECIDE_DRAGON_DATA;
773 break;
774
775 case OPT_DECIDE_SEMEAI:
776 if (strlen(gg_optarg) > 7) {
777 fprintf(stderr,
778 "usage: --decide-semeai [first dragon]/[second dragon]\n");
779 return EXIT_FAILURE;
780 }
781 strcpy(decide_this, gg_optarg);
782 strtok(decide_this, "/");
783 decide_that = strtok(NULL, "/");
784 if (!decide_that) {
785 fprintf(stderr,
786 "usage: --decide-semeai [first dragon]/[second dragon]\n");
787 return EXIT_FAILURE;
788 }
789
790 playmode = MODE_DECIDE_SEMEAI;
791 break;
792
793 case OPT_DECIDE_TACTICAL_SEMEAI:
794 if (strlen(gg_optarg) > 7) {
795 fprintf(stderr,
796 "usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
797 return EXIT_FAILURE;
798 }
799 strcpy(decide_this, gg_optarg);
800 strtok(decide_this, "/");
801 decide_that = strtok(NULL, "/");
802 if (!decide_that) {
803 fprintf(stderr,
804 "usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
805 return EXIT_FAILURE;
806 }
807 playmode = MODE_DECIDE_TACTICAL_SEMEAI;
808 break;
809
810 case OPT_DECIDE_POSITION:
811 playmode = MODE_DECIDE_POSITION;
812 break;
813
814 case OPT_DECIDE_EYE:
815 if (strlen(gg_optarg) > 3) {
816 fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
817 exit(EXIT_FAILURE);
818 }
819 strcpy(decide_this, gg_optarg);
820 playmode = MODE_DECIDE_EYE;
821 break;
822
823 case OPT_DECIDE_COMBINATION:
824 playmode = MODE_DECIDE_COMBINATION;
825 break;
826
827 case OPT_DECIDE_SURROUNDED:
828 if (strlen(gg_optarg) > 3) {
829 fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
830 exit(EXIT_FAILURE);
831 }
832 strcpy(decide_this, gg_optarg);
833 playmode = MODE_DECIDE_SURROUNDED;
834 break;
835
836 case OPT_DECIDE_ORACLE:
837 playmode = MODE_DECIDE_ORACLE;
838 break;
839
840 case OPT_BRANCH_DEPTH:
841 mandated_branch_depth = atoi(gg_optarg);
842 break;
843
844 case OPT_BACKFILL2_DEPTH:
845 mandated_backfill2_depth = atoi(gg_optarg);
846 break;
847
848 case OPT_BREAK_CHAIN_DEPTH:
849 mandated_break_chain_depth = atoi(gg_optarg);
850 break;
851
852 case OPT_SUPERSTRING_DEPTH:
853 mandated_superstring_depth = atoi(gg_optarg);
854 break;
855
856 case OPT_AA_DEPTH:
857 mandated_aa_depth = atoi(gg_optarg);
858 break;
859
860 case OPT_OWL_DISTRUST:
861 mandated_owl_distrust_depth = atoi(gg_optarg);
862 break;
863
864 case OPT_OWL_BRANCH:
865 mandated_owl_branch_depth = atoi(gg_optarg);
866 break;
867
868 case OPT_OWL_READING:
869 mandated_owl_reading_depth = atoi(gg_optarg);
870 break;
871
872 case OPT_OWL_NODE_LIMIT:
873 mandated_owl_node_limit = atoi(gg_optarg);
874 break;
875
876 case OPT_NOFUSEKIDB:
877 fusekidb = 0;
878 break;
879
880 case OPT_NOFUSEKI:
881 disable_fuseki = 1;
882 break;
883
884 case OPT_NOJOSEKIDB:
885 josekidb = 0;
886 break;
887
888 case OPT_LEVEL:
889 set_level(atoi(gg_optarg));
890 break;
891
892 case OPT_MIN_LEVEL:
893 set_min_level(atoi(gg_optarg));
894 break;
895
896 case OPT_MAX_LEVEL:
897 set_max_level(atoi(gg_optarg));
898 break;
899
900 case OPT_LIMIT_SEARCH: {
901 int pos = string_to_location(board_size, gg_optarg);
902 if (pos == NO_MOVE) {
903 fprintf(stderr, "gnugo: use --limit-search <pos>\n");
904 return EXIT_FAILURE;
905 }
906 set_search_diamond(pos);
907 } break;
908
909 case OPT_CLOCK_TIME:
910 clock_settings(atoi(gg_optarg), -1, -1);
911 break;
912
913 case OPT_CLOCK_BYO_TIME:
914 clock_settings(-1, atoi(gg_optarg), -1);
915 break;
916
917 case OPT_CLOCK_BYO_PERIOD:
918 clock_settings(-1, -1, atoi(gg_optarg));
919 break;
920
921 case OPT_AUTOLEVEL:
922 autolevel_on = 1;
923 break;
924
925 case OPT_DEBUG_INFLUENCE:
926 if (strlen(gg_optarg) > 3) {
927 fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
928 exit(EXIT_FAILURE);
929 }
930 strcpy(debuginfluence_move, gg_optarg);
931 break;
932
933 case OPT_REPLAY_GAME:
934 playmode = MODE_REPLAY;
935 if (strcmp(gg_optarg, "white") == 0)
936 replay_color = WHITE;
937 else if (strcmp(gg_optarg, "black") == 0)
938 replay_color = BLACK;
939 else if (strcmp(gg_optarg, "both") == 0)
940 replay_color = GRAY;
941 else {
942 fprintf(stderr, "Invalid replay color: %s\n", gg_optarg);
943 fprintf(stderr, "Try `gnugo --help' for more information.\n");
944 exit(EXIT_FAILURE);
945 }
946 break;
947
948 case OPT_SCORE:
949 scoringmode = gg_optarg;
950 if (playmode == MODE_UNKNOWN)
951 playmode = MODE_LOAD_AND_SCORE;
952 break;
953
954 case OPT_PRINTSGF:
955 playmode = MODE_LOAD_AND_PRINT;
956 printsgffile = gg_optarg;
957 break;
958
959 case OPT_PROFILE_PATTERNS:
960 profile_patterns = 1;
961 prepare_pattern_profiling();
962 break;
963
964 case OPT_COLOR:
965 if (strcmp(gg_optarg, "white") == 0)
966 mandated_color = WHITE;
967 else if (strcmp(gg_optarg, "black") == 0)
968 mandated_color = BLACK;
969 else {
970 fprintf(stderr, "Invalid color selection: %s\n", gg_optarg);
971 fprintf(stderr, "Try `gnugo --help' for more information.\n");
972 exit(EXIT_FAILURE);
973 }
974 break;
975
976 case OPT_SHOWCOPYRIGHT:
977 show_copyright();
978 return EXIT_SUCCESS;
979 break;
980
981 case OPT_MIRROR:
982 play_mirror_go = 1;
983 break;
984
985 case OPT_MIRROR_LIMIT:
986 mirror_stones_limit = atoi(gg_optarg);
987 break;
988
989 case 'v':
990 show_version();
991 show_copyright();
992 return EXIT_SUCCESS;
993 break;
994
995 case 'h':
996 show_version();
997 if (gg_optarg) {
998 /* In the default behavior of getopt_long with optional args
7eeb782e
AT
999 * you need to type "-hdebug"
1000 * I can't get long options "--helpdebug" to work at all
1001 */
c150f57c
AT
1002 if (strncmp(gg_optarg, "debug", 5) == 0)
1003 show_debug_help();
1004 } else {
1005 /* This is the trick to get "--help debug" and "-h debug" to work*/
1006 if (gg_optind < argc) {
1007 if (strncmp(argv[gg_optind], "debug", 5) == 0)
1008 show_debug_help();
1009 } else
1010 show_help();
1011 }
1012 return EXIT_SUCCESS;
1013 break;
1014
1015 case OPT_DEBUG_FLAGS:
1016 show_debug_flags();
1017 return EXIT_SUCCESS;
1018 break;
1019
1020 case OPT_PRINT_LEVELS: {
1021 int lev;
1022 for (lev = 12; lev >= 0; lev--)
1023 set_depth_values(lev, 1);
1024 }
1025 return EXIT_SUCCESS;
1026 break;
1027
1028 /* NOTE: getopt returns '?' if an illegal option is supplied. */
1029
1030 case '?':
1031 default:
1032 fprintf(stderr, "Try `gnugo --help' for more information.\n");
1033 exit(EXIT_FAILURE);
1034 }
1035 }
1036
1037 if (requested_boardsize != -1) {
1038 if (!check_boardsize(requested_boardsize, stderr))
1039 exit(EXIT_FAILURE);
1040 gnugo_clear_board(requested_boardsize);
7eeb782e
AT
1041 }
1042
c150f57c
AT
1043 /* Start random number seed. */
1044 if (!seed_specified)
1045 seed = time(0);
1046
1047 /* Initialize the GNU Go engine. */
1048 init_gnugo(memory, seed);
1049
1050 /* Load Monte Carlo patterns if one has been specified. Either
7eeb782e
AT
1051 * choose one of the compiled in ones or load directly from a
1052 * database file.
1053 */
c150f57c
AT
1054 if (strlen(mc_pattern_filename) > 0) {
1055 if (!mc_load_patterns_from_db(mc_pattern_filename, NULL))
1056 return EXIT_FAILURE;
1057 } else if (strlen(mc_pattern_name) > 0) {
1058 if (!choose_mc_patterns(mc_pattern_name)) {
1059 fprintf(stderr, "Unknown Monte Carlo pattern database name %s.\n",
1060 mc_pattern_name);
1061 fprintf(stderr, "Use \"--mc-list-patterns\" to list the available databases.\n");
1062 return EXIT_FAILURE;
1063 }
7eeb782e 1064 }
7eeb782e 1065
c150f57c
AT
1066 /* Read the infile if there is one. Also play up the position. */
1067 if (infilename) {
1068 if (!sgftree_readfile(&sgftree, infilename)) {
1069 fprintf(stderr, "Cannot open or parse '%s'\n", infilename);
1070 exit(EXIT_FAILURE);
1071 }
1072
1073 if (gameinfo_play_sgftree_rot(&gameinfo, &sgftree, untilstring,
1074 orientation)
1075 == EMPTY) {
1076 fprintf(stderr, "Cannot load '%s'\n", infilename);
1077 exit(EXIT_FAILURE);
1078 }
1079 } else
1080 /* Initialize and empty sgf tree if there was no infile. */
1081 sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap);
1082
1083 /* Set the game_record to be identical to the loaded one or the
7eeb782e
AT
1084 * newly created empty sgf tree.
1085 */
c150f57c
AT
1086 gameinfo.game_record = sgftree;
1087
1088 /* Notice that we need to know the board size before we can do this.
7eeb782e 1089 */
c150f57c
AT
1090 if (debuginfluence_move[0]) {
1091 int pos = string_to_location(board_size, debuginfluence_move);
1092 debug_influence_move(pos);
1093 }
1094
1095 /* Figure out a default mode if there was no explicit one. */
1096 if (playmode == MODE_UNKNOWN) {
1097 if (infilename)
1098 playmode = MODE_LOAD_AND_ANALYZE;
1099 else
3ebb0002 1100 playmode = (isatty(0)) ? MODE_ANSI : MODE_GMP;
c150f57c
AT
1101 }
1102
1103 if (outfile && playmode != MODE_LOAD_AND_PRINT) {
1104 output_check = fopen(outfile, "w");
1105 if (!output_check) {
1106 fprintf(stderr, "Error: could not open '%s' for writing\n", outfile);
1107 exit(EXIT_FAILURE);
1108 }
1109 fclose(output_check);
7eeb782e 1110 }
7eeb782e 1111
c150f57c
AT
1112 switch (playmode) {
1113 case MODE_GMP:
1114 case MODE_SGMP:
7eeb782e 1115
c150f57c
AT
1116 /* not supported by the protocol */
1117 resign_allowed = 0;
7eeb782e
AT
1118
1119#if ORACLE
c150f57c
AT
1120 if (metamachine)
1121 summon_oracle();
7eeb782e
AT
1122#endif
1123
c150f57c
AT
1124 /* EMPTY is valid for play_gmp.c. */
1125 gameinfo.computer_player = mandated_color;
1126 play_gmp(&gameinfo, playmode == MODE_SGMP);
7eeb782e
AT
1127
1128#if ORACLE
c150f57c
AT
1129 if (metamachine)
1130 dismiss_oracle();
7eeb782e
AT
1131#endif
1132
c150f57c
AT
1133 break;
1134
1135 case MODE_SOLO:
1136 play_solo(&gameinfo, benchmark);
1137 break;
1138
1139 case MODE_REPLAY:
1140 if (!infilename) {
1141 fprintf(stderr, "You must use -l infile with replay mode.\n");
1142 exit(EXIT_FAILURE);
1143 }
1144 play_replay(&sgftree, replay_color);
1145 break;
1146
1147 case MODE_LOAD_AND_ANALYZE:
1148 if (mandated_color != EMPTY)
1149 gameinfo.to_move = mandated_color;
1150
1151 if (!infilename) {
1152 fprintf(stderr, "You must use -l infile with load and analyze mode.\n");
1153 exit(EXIT_FAILURE);
1154 }
7eeb782e
AT
1155
1156#if ORACLE
c150f57c
AT
1157 if (metamachine) {
1158 summon_oracle();
1159 oracle_loadsgf(infilename, untilstring);
1160 }
7eeb782e
AT
1161#endif
1162
c150f57c 1163 load_and_analyze_sgf_file(&gameinfo);
7eeb782e
AT
1164
1165#if ORACLE
c150f57c 1166 dismiss_oracle();
7eeb782e
AT
1167#endif
1168
c150f57c 1169 break;
7eeb782e 1170
c150f57c
AT
1171 case MODE_LOAD_AND_SCORE:
1172 if (mandated_color != EMPTY)
1173 gameinfo.to_move = mandated_color;
7eeb782e 1174
c150f57c
AT
1175 if (!infilename) {
1176 fprintf(stderr, "gnugo: --score must be used with -l\n");
1177 exit(EXIT_FAILURE);
1178 }
1179 load_and_score_sgf_file(&sgftree, &gameinfo, scoringmode);
1180 break;
1181
1182 case MODE_LOAD_AND_PRINT:
1183 if (!infilename) {
1184 fprintf(stderr, "gnugo: --printsgf must be used with -l\n");
1185 exit(EXIT_FAILURE);
1186 }
1187
1188 else {
1189 if (mandated_color != EMPTY)
1190 gameinfo.to_move = mandated_color;
1191
1192 sgffile_printsgf(gameinfo.to_move, printsgffile);
1193 }
1194 break;
1195
1196 case MODE_DECIDE_STRING: {
1197 int str;
1198
1199 if (!infilename) {
1200 fprintf(stderr, "gnugo: --decide-string must be used with -l\n");
1201 return EXIT_FAILURE;
1202 }
1203
1204 str = string_to_location(board_size, decide_this);
1205 if (str == NO_MOVE) {
1206 fprintf(stderr, "gnugo: --decide-string: strange coordinate \n");
1207 return EXIT_FAILURE;
1208 }
1209
1210 decide_string(str);
1211 } break;
1212
1213 case MODE_DECIDE_CONNECTION: {
1214 int str1, str2;
1215
1216 if (!infilename) {
1217 fprintf(stderr, "gnugo: --decide-connection must be used with -l\n");
1218 return EXIT_FAILURE;
1219 }
1220
1221 str1 = string_to_location(board_size, decide_this);
1222 if (str1 == NO_MOVE) {
1223 fprintf(stderr,
1224 "usage: --decide-connection [first string]/[second string]\n");
1225 return EXIT_FAILURE;
1226 }
1227
1228 str2 = string_to_location(board_size, decide_that);
1229 if (str2 == NO_MOVE) {
1230 fprintf(stderr,
1231 "usage: --decide-connection [first string]/[second string]\n");
1232 return EXIT_FAILURE;
1233 }
1234
1235 decide_connection(str1, str2);
1236 } break;
1237
1238 case MODE_DECIDE_OWL: {
1239 int pos;
1240
1241 if (!infilename) {
1242 fprintf(stderr, "gnugo: --decide-dragon must be used with -l\n");
1243 return EXIT_FAILURE;
1244 }
1245
1246 pos = string_to_location(board_size, decide_this);
1247 if (pos == NO_MOVE) {
1248 fprintf(stderr, "gnugo: --decide-dragon: strange coordinate \n");
1249 return EXIT_FAILURE;
1250 }
1251
1252 decide_owl(pos);
1253 } break;
1254
1255 case MODE_DECIDE_DRAGON_DATA: {
1256 int pos;
1257
1258 if (!infilename) {
1259 fprintf(stderr, "gnugo: --decide-dragon-data must be used with -l\n");
1260 return EXIT_FAILURE;
1261 }
1262
1263 pos = string_to_location(board_size, decide_this);
1264 if (pos == NO_MOVE) {
1265 fprintf(stderr, "gnugo: --decide-dragon-data: strange coordinate \n");
1266 return EXIT_FAILURE;
1267 }
1268
1269 decide_dragon_data(pos);
1270 } break;
1271
1272 case MODE_DECIDE_SEMEAI: {
1273 int pos1, pos2;
1274
1275 if (!infilename) {
1276 fprintf(stderr, "gnugo: --decide-semeai must be used with -l\n");
1277 return EXIT_FAILURE;
1278 }
1279
1280 pos1 = string_to_location(board_size, decide_this);
1281 if (pos1 == NO_MOVE) {
1282 fprintf(stderr,
1283 "usage: --decide-semeai [first dragon]/[second dragon]\n");
1284 return EXIT_FAILURE;
1285 }
1286
1287 pos2 = string_to_location(board_size, decide_that);
1288 if (pos2 == NO_MOVE) {
1289 fprintf(stderr,
1290 "usage: --decide-semeai [first dragon]/[second dragon]\n");
1291 return EXIT_FAILURE;
1292 }
1293
1294 decide_semeai(pos1, pos2);
1295 } break;
1296
1297 case MODE_DECIDE_TACTICAL_SEMEAI: {
1298 int pos1, pos2;
1299
1300 if (!infilename) {
1301 fprintf(stderr, "gnugo: --decide-tactical-semeai must be used with -l\n");
1302 return EXIT_FAILURE;
1303 }
1304
1305 pos1 = string_to_location(board_size, decide_this);
1306 if (pos1 == NO_MOVE) {
1307 fprintf(stderr,
1308 "usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
1309 return EXIT_FAILURE;
1310 }
1311
1312 pos2 = string_to_location(board_size, decide_that);
1313 if (pos2 == NO_MOVE) {
1314 fprintf(stderr,
1315 "usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
1316 return EXIT_FAILURE;
1317 }
1318
1319 decide_tactical_semeai(pos1, pos2);
1320 } break;
1321
1322 case MODE_DECIDE_POSITION: {
1323 if (!infilename) {
1324 fprintf(stderr, "gnugo: --decide-position must be used with -l\n");
1325 return EXIT_FAILURE;
1326 }
1327 decide_position();
1328 } break;
1329
1330 case MODE_DECIDE_EYE: {
1331 int pos;
1332
1333 if (!infilename) {
1334 fprintf(stderr, "gnugo: --decide-eye must be used with -l\n");
1335 return EXIT_FAILURE;
1336 }
1337
1338 pos = string_to_location(board_size, decide_this);
1339 if (pos == NO_MOVE) {
1340 fprintf(stderr, "gnugo: --decide-eye: strange coordinate \n");
1341 return EXIT_FAILURE;
1342 }
1343
1344 decide_eye(pos);
1345 } break;
1346
1347 case MODE_DECIDE_COMBINATION: {
1348 int color;
1349 if (!infilename) {
1350 fprintf(stderr, "gnugo: --decide-combination must be used with -l\n");
1351 return EXIT_FAILURE;
1352 }
1353 color = gameinfo.to_move;
1354 if (mandated_color != EMPTY)
1355 color = mandated_color;
1356 decide_combination(color);
1357 } break;
1358
1359 case MODE_DECIDE_SURROUNDED: {
1360 int pos = string_to_location(board_size, decide_this);
1361
1362 if (pos == NO_MOVE) {
1363 fprintf(stderr,
1364 "usage: --decide-surrounded [pos]\n");
1365 return EXIT_FAILURE;
1366 }
1367
1368 decide_surrounded(pos);
1369 break;
7eeb782e
AT
1370 }
1371
1372#if ORACLE
c150f57c
AT
1373 case MODE_DECIDE_ORACLE: {
1374 if (mandated_color != EMPTY)
1375 gameinfo.to_move = mandated_color;
1376
1377 if (!infilename) {
1378 fprintf(stderr, "You must use -l infile with load and analyze mode.\n");
1379 exit(EXIT_FAILURE);
1380 }
1381
1382 decide_oracle(&gameinfo, infilename, untilstring);
1383 break;
7eeb782e
AT
1384 }
1385#endif
1386
c150f57c
AT
1387 case MODE_GTP: {
1388 FILE* gtp_input_FILE = stdin;
1389 FILE* gtp_output_FILE = stdout;
1390 FILE* gtp_dump_commands_FILE = NULL;
1391
1392 if (gtpfile != NULL) {
1393 gtp_input_FILE = fopen(gtpfile, "r");
1394 if (gtp_input_FILE == NULL) {
1395 fprintf(stderr, "gnugo: Cannot open file %s\n", gtpfile);
1396 return EXIT_FAILURE;
1397 }
1398 } else if (gtp_tcp_ip_mode != 0) {
1399 unsigned int port = 65536;
1400 char* port_string = strchr(gtp_tcp_ip_address, ':');
1401 const char* host_name = NULL;
1402
1403 if (port_string) {
1404 host_name = gtp_tcp_ip_address;
1405
1406 *port_string++ = 0;
1407 sscanf(port_string, "%u", &port);
1408 } else
1409 sscanf(gtp_tcp_ip_address, "%u", &port);
1410
1411 if (port > 65535) {
1412 fprintf(stderr, "A valid TCP/IP port number expected\n");
1413 exit(EXIT_FAILURE);
1414 }
1415
1416 if (gtp_tcp_ip_mode == OPT_GTP_CONNECT) {
1417 socket_connect_to(host_name, port,
1418 &gtp_input_FILE, &gtp_output_FILE);
1419 } else {
1420 socket_listen_at(host_name, port,
1421 &gtp_input_FILE, &gtp_output_FILE);
1422 }
1423 }
1424
1425 if (gtp_dump_commands_file != NULL) {
1426 gtp_dump_commands_FILE = fopen(gtp_dump_commands_file, "w");
1427 if (gtp_dump_commands_FILE == NULL) {
1428 fprintf(stderr, "gnugo: Cannot open file %s\n",
1429 gtp_dump_commands_file);
1430 return EXIT_FAILURE;
1431 }
1432 }
1433
1434 play_gtp(gtp_input_FILE, gtp_output_FILE, gtp_dump_commands_FILE,
1435 orientation);
1436
1437 if (gtp_dump_commands_FILE)
1438 fclose(gtp_dump_commands_FILE);
1439
1440 if (gtp_tcp_ip_mode == OPT_GTP_CONNECT)
1441 socket_close_connection(gtp_input_FILE, gtp_output_FILE);
1442 else if (gtp_tcp_ip_mode == OPT_GTP_LISTEN)
1443 socket_stop_listening(gtp_input_FILE, gtp_output_FILE);
7eeb782e
AT
1444 }
1445
1446 break;
1447
de03db18
AT
1448 case MODE_TWOPLAYER:
1449 play_twoplayer(&sgftree, &gameinfo, infilename, untilstring);
1450 break;
1451
3ebb0002
AT
1452 case MODE_STRICTANSI:
1453 if (mandated_color != EMPTY) gameinfo.computer_player = OTHER_COLOR(mandated_color);
1454#if ORACLE
1455 if (metamachine) {
1456 summon_oracle();
1457 oracle_loadsgf(infilename, untilstring);
1458 }
1459#endif
1460 play_ansi(&sgftree, &gameinfo, infilename, untilstring, true);
1461 break;
1462
1463 case MODE_ANSI:
1464 if (mandated_color != EMPTY) gameinfo.computer_player = OTHER_COLOR(mandated_color);
1465#if ORACLE
1466 if (metamachine) {
1467 summon_oracle();
1468 oracle_loadsgf(infilename, untilstring);
1469 }
1470#endif
1471 play_ansi(&sgftree, &gameinfo, infilename, untilstring, false);
1472 break;
1473
c150f57c
AT
1474 case MODE_ASCII:
1475 default:
1476 if (mandated_color != EMPTY)
1477 gameinfo.computer_player = OTHER_COLOR(mandated_color);
7eeb782e 1478
c150f57c
AT
1479 /* Display copyright message in ASCII mode unless --quiet option used. */
1480 if (!quiet) {
3ebb0002
AT
1481 show_version();
1482 show_copyright();
c150f57c 1483 }
7eeb782e
AT
1484
1485#if ORACLE
c150f57c
AT
1486 if (metamachine) {
1487 summon_oracle();
1488 oracle_loadsgf(infilename, untilstring);
1489 }
7eeb782e
AT
1490#endif
1491
c150f57c
AT
1492 play_ascii(&sgftree, &gameinfo, infilename, untilstring);
1493 break;
1494 }
7eeb782e 1495
c150f57c
AT
1496 if (profile_patterns)
1497 report_pattern_profiling();
7eeb782e 1498
c150f57c 1499 sgfFreeNode(sgftree.root);
7eeb782e 1500
c150f57c
AT
1501 return 0;
1502} /* end main */
7eeb782e
AT
1503
1504static void
1505show_version(void)
1506{
3ebb0002 1507 printf("GNU Go %s\n with SGK modifications", VERSION);
7eeb782e
AT
1508}
1509
7eeb782e
AT
1510/* Set the parameters which determine the depth to which
1511 * the reading and owl code carries its calculations.
1512 */
1513
7eeb782e
AT
1514/*
1515 * This string is modelled after the GNU tar --help output.
1516 * Since the maximum string length is 2048 bytes in VC++ we
1517 * split the help string.
1518 */
1519
7eeb782e
AT
1520#define USAGE "\n\
1521Usage: gnugo [-opts]\n\
1522\n\
1523Examples:\n\
1524 gnugo --mode gtp --level 5\n\
1525 To play against gnugo in level 5 from a GTP client\n\
1526 gnugo --mode ascii -l game.sgf -L 123\n\
1527 Resume game at move 123 in ASCII mode\n\
1528 gnugo --score estimate -l game.sgf\n\
1529 Give a rough score estimate of the end position in game.sgf\n\
1530\n\
1531Main Options:\n\
1532 --mode <mode> Force the playing mode ('ascii', 'gmp', 'sgmp',\n\
1533 or 'gtp'). Default is ASCII.\n\
1534 If no terminal is detected GMP (Go Modem Protocol)\n\
1535 will be assumed.\n\
1536 --quiet --silent Don't print copyright and informational messages\n\
1537 --level <amount> strength (default %d)\n\
1538 --never-resign Forbid GNU Go to resign\n\
1539 --resign-allowed Allow resignation (default)\n\
1540 -l, --infile <file> Load name sgf file\n\
1541 -L, --until <move> Stop loading just before move is played. <move>\n\
1542 can be the move number or location (eg L10).\n\
1543 -o, --outfile <file> Write sgf output to file\n\
1544 --printsgf <file> Write position as a diagram to file (use with -l)\n\
1545\n\
1546Scoring:\n\
1547 --score estimate estimate score at loaded position\n\
1548 --score finish generate moves to finish game, then score\n\
1549 --score aftermath generate moves to finish, use best algorithm\n\
1550\n\
1551"
1552
1553#define USAGE1 "\
1554Game Options:\n\
1555Used with --mode ascii (or other modes for non-interactive settings)\n\
1556 --boardsize num Set the board size to use (%d--%d)\n\
1557 --color <color> Choose your color ('black' or 'white')\n\
1558 --handicap <num> Set the number of handicap stones (0--%d)\n\
1559 --komi <num> Set the komi\n\
1560 --clock <sec> Initialize the timer.\n\
1561 --byo-time <sec> Initialize the byo-yomi timer.\n\
1562 --byo-period <stones> Initialize the byo-yomi period.\n\
1563\n\
1564 --japanese-rules (default)\n\
1565 --chinese-rules\n\
1566 --forbid-suicide Forbid suicide. (default)\n\
1567 --allow-suicide Allow suicide except single-stone suicide.\n\
1568 --allow-all-suicide Allow all suicide moves.\n\
1569 --simple-ko Forbid simple ko recapture. (default)\n\
1570 --no-ko Allow any ko recapture.\n\
1571 --positional-superko Positional superko restrictions.\n\
1572 --situational-superko Situational superko restrictions.\n\
1573\n\
1574 --play-out-aftermath\n\
1575 --capture-all-dead\n\
1576\n\
1577 --min-level <amount> minimum level for adjustment schemes\n\
1578 --max-level <amount> maximum level for adjustment schemes\n\
1579 --autolevel adapt gnugo level during game to respect\n\
1580 the time specified by --clock <sec>.\n\
1581\n\
1582Connection options\n\
1583 --gtp-input <file>Read gtp commands from file instead of stdin\n\
1584 --gtp-connect [HOST:]PORT\n\
1585 Connect to given host (127.0.0.1 if omitted) and port\n\
1586 and receive GTP commands on the established connection\n\
1587 --gtp-listen [HOST:]PORT\n\
1588 Wait for the first TCP/IP connection on the given port\n\
1589 (if HOST is specified, only to that host)\n\
1590 --gtp-version\n\
1591\n\
1592"
1593
1594#define USAGE2 "\
1595Experimental options:\n\
1596 --with-break-in use the break-in code (on at level 10 by default)\n\
1597 --without-break-in do not use the break-in code\n\
1598 --cosmic-gnugo use center oriented influence\n\
1599 --no-cosmic-gnugo don't use center oriented influence (default)\n\
1600 --large-scale look for large scale captures\n\
1601 --no-large-scale don't seek large scale captures (default)\n\
1602 --nofusekidb turn off fuseki database\n\
1603 --nofuseki turn off fuseki moves entirely\n\
1604 --nojosekidb turn off joseki database\n\
1605 --mirror try to play mirror go\n\
1606 --mirror-limit <n> stop mirroring when n stones on board\n\n\
1607 --monte-carlo enable Monte Carlo move generation (9x9 or smaller)\n\
1608 --mc-games-per-level <n> number of Monte Carlo simulations per level\n\
1609 --mc-list-patterns list names of builtin Monte Carlo patterns\n\
1610 --mc-patterns <name> choose a built in Monte Carlo pattern database\n\
1611 --mc-load-patterns <filename> read Monte Carlo patterns from file\n\
1612 --alternate-connections\n\
1613 --experimental-connections\n\
1614 --experimental-owl-ext\n\
1615 --experimental-semeai\n\
1616 --standard-connections\n\
1617 --standard-semeai\n\
1618 --oracle Read the documentation\n\
1619\n\
1620Cache size (higher=more memory usage, faster unless swapping occurs):\n\
1621 -M, --cache-size <megabytes> RAM cache for read results (default %4.1f Mb)\n\
1622\n\
1623Informative Output:\n\
1624 -v, --version Display the version and copyright of GNU Go\n\
1625 --options Display configure options\n\
1626 -h, --help Display this help message\n\
1627 --help debug Display help about debugging options\n\
1628 --copyright Display copyright notice\n\
1629\n\
1630"
1631
1632#define COPYRIGHT \
c150f57c 1633 "Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007\n\
7eeb782e
AT
16342008 and 2009 by the Free Software Foundation, Inc.\n\
1635See http://www.gnu.org/software/gnugo/ or contact\n\
1636gnugo@gnu.org for information about GNU Go. GNU Go comes with NO WARRANTY to\n\
1637the extent permitted by law. This program is free software; you can\n\
1638redistribute it and/or modify it under the terms of the GNU General Public\n\
1639License as published by the Free Software Foundation - version 3 or\n\
1640(at your option) any later version. For more\n\
1641information about these matters, see the files named COPYING.\n"
1642
1643/* USAGE_DEBUG Split in half because of VC limit on constant string
1644 * length of 2048 characters!*/
1645#define USAGE_DEBUG "\n\
1646Debugging Options:\n\
1647\n\
1648 --replay <color> replay the moves in a game for color.\n\
1649 (requires -l)\n\
1650 white: replay only white moves\n\
1651 black: replay only black moves\n\
1652 both: replay all moves\n\
1653 -a, --allpats test all patterns\n\
1654 -T, --printboard colored display of dragons\n\
1655 -E, --printeyes colored display of eye spaces\n\
1656 -d, --debug <flags> debugging output (see next item for bits)\n\
1657 --debug-flags print the debug flags for previous item\n\
1658 -w, --worms print worm and dragon data and move reasons\n\
1659 -m, --moyo <level> moyo debugging, show moyo board\n\
1660 --debug-influence <move> print influence map after making a move\n\
1661 -b, --benchmark num benchmarking mode - can be used with -l\n\
1662 -S, --statistics print statistics (for debugging purposes)\n\n\
1663 --profile-patterns print statistics for pattern usage\n\
1664 --showtime print timing diagnostic\n\
1665 -t, --trace verbose tracing\n\
1666 -O, --output-flags <flags> optional output (use with -o)\n\
1667 d: mark dead and critical dragons\n\
1668 v: show values of considered moves\n\
1669 specify either 'd', 'v' or 'dv' (nothing by default)\n\
1670 --showscore print estimated score\n\
1671 -r, --seed number set random number seed\n\
1672 --gtp-dump-commands <file>dump commands received in GTP mode\n\
1673 --gtp-initial-orientation\n\
1674 --orientation\n\
1675\n\
1676"
1677
1678#define USAGE_DEBUG2 "\
1679Options affecting depth settings and playing strength:\n\
1680 --print-levels shows all this values for levels 12 to 0\n\
1681\n\
1682 Default values for the default level (%d):\n\
1683 -D, --depth <depth> deep reading cutoff (default %d)\n\
1684 -B, --backfill-depth <depth> deep reading cutoff (default %d)\n\
1685 -F, --fourlib-depth <depth> deep reading cutoff (default %d)\n\
1686 -K, --ko-depth <depth> deep reading cutoff (default %d)\n\
1687 --branch-depth <depth> deep reading cutoff (default %d)\n\
1688 --backfill2-depth <depth> deep reading cutoff (default %d)\n\
1689 --break_chain-depth <depth> deep reading cutoff (default %d)\n\
1690 --superstring-depth <depth> deep reading cutoff (default %d)\n\
1691 --aa-depth <depth> deep reading cutoff (default %d)\n\
1692 --owl-distrust <depth> owl distrust depth (default %d)\n\
1693 --owl-branch <depth> owl branching depth (default %d)\n\
1694 --owl-reading <depth> owl reading depth (default %d)\n\
1695 --owl-node-limit <limit> max nodes for owl reading (default %d)\n\
1696 --semeai-node-limit <limit> max nodes for semeai reading (default %d)\n\
1697\n\
1698Options providing detailed reading results etc.:\n\
1699 --decide-string <string> can this string live? (try with -o)\n\
1700 --decide-connection <str/str> can these strings connect? (try with -o)\n\
1701 --decide-dragon <dragon> can this dragon live? (try with -o or -t)\n\
1702 --decide-dragon-data\n\
1703 --decide-owl\n\
1704 --decide-position evaluate all dragons (try with -o or -t)\n\
1705 --decide-eye <string> evaluate the eye\n\
1706 --decide-combination search for combination attack (try with -o)\n\
1707 --decide-oracle\n\
1708 --decide-semeai\n\
1709 --decide-tactical-semeai\n\
1710 --decide-surrounded\n\
1711 --limit-search\n\
1712\n\
1713"
1714
7eeb782e
AT
1715/*
1716 * Since the maximum string length is 2048 bytes in VC++ we
1717 * split the help string.
1718 */
1719static void
1720show_help(void)
1721{
c150f57c
AT
1722 printf(USAGE, DEFAULT_LEVEL);
1723 printf(USAGE1, MIN_BOARD, MAX_BOARD, MAX_HANDICAP);
1724 printf(USAGE2, DEFAULT_MEMORY <= 0 ? reading_cache_default_size() : (float)DEFAULT_MEMORY);
7eeb782e
AT
1725}
1726
7eeb782e
AT
1727static void
1728show_debug_help(void)
1729{
c150f57c
AT
1730 set_depth_values(DEFAULT_LEVEL, 0);
1731 printf(USAGE_DEBUG USAGE_DEBUG2,
1732 DEFAULT_LEVEL, depth, backfill_depth, fourlib_depth, ko_depth, branch_depth,
1733 backfill2_depth, break_chain_depth, superstring_depth, aa_depth,
1734 owl_distrust_depth, owl_branch_depth,
1735 owl_reading_depth, owl_node_limit, semeai_node_limit);
7eeb782e
AT
1736}
1737
c150f57c 1738static void
7eeb782e
AT
1739show_debug_flags(void)
1740{
c150f57c 1741 printf(DEBUG_FLAGS);
7eeb782e
AT
1742}
1743
1744static void
1745show_copyright(void)
1746{
c150f57c 1747 printf(COPYRIGHT);
7eeb782e
AT
1748}
1749
7eeb782e
AT
1750#ifdef ENABLE_SOCKET_SUPPORT
1751
7eeb782e
AT
1752#if !defined(_WIN32) && !defined(_WIN32_WCE)
1753
7eeb782e
AT
1754#include <arpa/inet.h>
1755#include <netdb.h>
c150f57c
AT
1756#include <netinet/in.h>
1757#include <sys/socket.h>
7eeb782e 1758
c150f57c 1759#define closesocket close
7eeb782e
AT
1760#define init_sockets()
1761
c150f57c 1762#else /* on Windows */
7eeb782e
AT
1763
1764#include <winsocket.h>
1765
7eeb782e
AT
1766static void
1767init_sockets(void)
1768{
c150f57c
AT
1769 WSADATA data;
1770 WORD version = MAKEWORD(1, 1);
7eeb782e 1771
c150f57c
AT
1772 if (WSAStartup(version, &data) != NO_ERROR) {
1773 fprintf(stderr, "WSAStartup() failed with error %d\n", WSAGetLastError());
1774 exit(EXIT_FAILURE);
1775 }
7eeb782e
AT
1776}
1777
c150f57c 1778#endif /* on Windows */
7eeb782e
AT
1779
1780static void
c150f57c
AT
1781socket_connect_to(const char* host_name, unsigned int port,
1782 FILE** input_file, FILE** output_file)
7eeb782e 1783{
c150f57c
AT
1784 struct sockaddr_in address;
1785 int connection_socket;
1786 struct hostent* host_data;
1787 char** address_pointer;
7eeb782e 1788
c150f57c 1789 init_sockets();
7eeb782e 1790
c150f57c
AT
1791 if (!host_name)
1792 host_name = "127.0.0.1";
7eeb782e 1793
c150f57c
AT
1794 host_data = gethostbyname(host_name);
1795 if (!host_data
1796 || host_data->h_addrtype != AF_INET
1797 || host_data->h_length != sizeof address.sin_addr) {
1798 fprintf(stderr, "Failed to resolve host name `%s'\n", host_name);
1799 exit(EXIT_FAILURE);
1800 }
7eeb782e 1801
c150f57c
AT
1802 connection_socket = socket(PF_INET, SOCK_STREAM, 0);
1803 if (connection_socket == -1) {
1804 fprintf(stderr, "Unexpected error: failed to create a socket\n");
1805 exit(EXIT_FAILURE);
1806 }
1807
1808 address.sin_family = AF_INET;
1809 address.sin_port = htons((unsigned short)port);
1810
1811 for (address_pointer = host_data->h_addr_list; *address_pointer;
1812 address_pointer++) {
1813 memcpy(&address.sin_addr, *address_pointer, sizeof address.sin_addr);
1814 if (connect(connection_socket, (struct sockaddr*)&address,
1815 sizeof address)
1816 != -1)
1817 break;
1818 }
1819
1820 if (!*address_pointer) {
1821 fprintf(stderr, "Failed to connect to %s:%u\n", host_data->h_name, port);
1822 closesocket(connection_socket);
1823 exit(EXIT_FAILURE);
1824 }
7eeb782e
AT
1825
1826#if !USE_WINDOWS_SOCKET_CLUDGE
1827
c150f57c
AT
1828 *input_file = fdopen(connection_socket, "r");
1829 *output_file = fdopen(dup(connection_socket), "w");
7eeb782e 1830
c150f57c 1831#else /* USE_WINDOWS_SOCKET_CLUDGE */
7eeb782e 1832
c150f57c 1833 winsocket_activate(connection_socket);
7eeb782e 1834
c150f57c
AT
1835 *input_file = NULL;
1836 *output_file = NULL;
7eeb782e 1837
c150f57c 1838#endif /* USE_WINDOWS_SOCKET_CLUDGE */
7eeb782e
AT
1839}
1840
7eeb782e 1841static void
c150f57c
AT
1842socket_listen_at(const char* host_name, unsigned int port,
1843 FILE** input_file, FILE** output_file)
7eeb782e 1844{
c150f57c
AT
1845 struct sockaddr_in address;
1846 int listening_socket;
1847 int connection_socket;
7eeb782e 1848
c150f57c 1849 init_sockets();
7eeb782e 1850
c150f57c
AT
1851 if (host_name) {
1852 struct hostent* host_data;
1853
1854 host_data = gethostbyname(host_name);
1855 if (!host_data
1856 || host_data->h_addrtype != AF_INET
1857 || host_data->h_length != sizeof address.sin_addr) {
1858 fprintf(stderr, "Failed to resolve host name `%s'\n", host_name);
1859 exit(EXIT_FAILURE);
1860 }
1861
1862 host_name = host_data->h_name;
1863 memcpy(&address.sin_addr, host_data->h_addr_list[0],
1864 sizeof address.sin_addr);
1865 } else
1866 address.sin_addr.s_addr = htonl(INADDR_ANY);
1867
1868 listening_socket = socket(PF_INET, SOCK_STREAM, 0);
1869 if (listening_socket == -1) {
1870 fprintf(stderr, "Unexpected error: failed to create a socket\n");
1871 exit(EXIT_FAILURE);
7eeb782e
AT
1872 }
1873
c150f57c
AT
1874 address.sin_family = AF_INET;
1875 address.sin_port = htons((unsigned short)port);
7eeb782e 1876
c150f57c
AT
1877 if (verbose) {
1878 if (host_name) {
1879 fprintf(stderr, "Waiting for a connection on %s:%u...\n",
1880 host_name, port);
1881 } else
1882 fprintf(stderr, "Waiting for a connection on port %u...\n", port);
1883 }
7eeb782e 1884
c150f57c
AT
1885 if (bind(listening_socket,
1886 (struct sockaddr*)&address, sizeof address)
1887 == -1
1888 || listen(listening_socket, 0) == -1
1889 || (connection_socket = accept(listening_socket, NULL, NULL)) == -1) {
1890 if (host_name)
1891 fprintf(stderr, "Failed to listen on %s:%u\n", host_name, port);
1892 else
1893 fprintf(stderr, "Failed to listen on port %u\n", port);
1894
1895 closesocket(listening_socket);
1896 exit(EXIT_FAILURE);
7eeb782e 1897 }
7eeb782e
AT
1898
1899 closesocket(listening_socket);
7eeb782e
AT
1900
1901#if !USE_WINDOWS_SOCKET_CLUDGE
1902
c150f57c
AT
1903 *input_file = fdopen(connection_socket, "r");
1904 *output_file = fdopen(dup(connection_socket), "w");
7eeb782e 1905
c150f57c 1906#else /* USE_WINDOWS_SOCKET_CLUDGE */
7eeb782e 1907
c150f57c 1908 winsocket_activate(connection_socket);
7eeb782e 1909
c150f57c
AT
1910 *input_file = NULL;
1911 *output_file = NULL;
7eeb782e 1912
c150f57c 1913#endif /* USE_WINDOWS_SOCKET_CLUDGE */
7eeb782e
AT
1914}
1915
7eeb782e 1916static void
c150f57c 1917socket_close_connection(FILE* input_file, FILE* output_file)
7eeb782e 1918{
c150f57c
AT
1919 /* When connecting, we close the socket first. */
1920 fclose(input_file);
1921 fclose(output_file);
7eeb782e
AT
1922}
1923
7eeb782e 1924static void
c150f57c 1925socket_stop_listening(FILE* input_file, FILE* output_file)
7eeb782e 1926{
c150f57c 1927 int buffer[0x1000];
7eeb782e 1928
c150f57c
AT
1929 if (verbose)
1930 fprintf(stderr, "Waiting for the client to disconnect...\n");
7eeb782e 1931
c150f57c 1932 /* When listening, we wait for the client to disconnect first.
7eeb782e
AT
1933 * Otherwise, socket doesn't get released properly.
1934 */
c150f57c
AT
1935 do
1936 fread(buffer, sizeof buffer, 1, input_file);
1937 while (!feof(input_file));
7eeb782e 1938
c150f57c
AT
1939 fclose(input_file);
1940 fclose(output_file);
7eeb782e
AT
1941}
1942
c150f57c 1943#else /* not ENABLE_SOCKET_SUPPORT */
7eeb782e
AT
1944
1945static void
c150f57c
AT
1946socket_connect_to(const char* host_name, unsigned int port,
1947 FILE** input_file, FILE** output_file)
7eeb782e 1948{
c150f57c
AT
1949 UNUSED(host_name);
1950 UNUSED(port);
1951 UNUSED(input_file);
1952 UNUSED(output_file);
7eeb782e 1953
c150f57c
AT
1954 fprintf(stderr, "GNU Go was compiled without socket support, unable to connect\n");
1955 exit(EXIT_FAILURE);
7eeb782e
AT
1956}
1957
7eeb782e 1958static void
c150f57c
AT
1959socket_listen_at(const char* host_name, unsigned int port,
1960 FILE** input_file, FILE** output_file)
7eeb782e 1961{
c150f57c
AT
1962 UNUSED(host_name);
1963 UNUSED(port);
1964 UNUSED(input_file);
1965 UNUSED(output_file);
7eeb782e 1966
c150f57c
AT
1967 fprintf(stderr, "GNU Go was compiled without socket support, unable to listen\n");
1968 exit(EXIT_FAILURE);
7eeb782e
AT
1969}
1970
7eeb782e 1971static void
c150f57c 1972socket_close_connection(FILE* input_file, FILE* output_file)
7eeb782e 1973{
c150f57c
AT
1974 UNUSED(input_file);
1975 UNUSED(output_file);
7eeb782e
AT
1976}
1977
7eeb782e 1978static void
c150f57c 1979socket_stop_listening(FILE* input_file, FILE* output_file)
7eeb782e 1980{
c150f57c
AT
1981 UNUSED(input_file);
1982 UNUSED(output_file);
7eeb782e
AT
1983}
1984
c150f57c 1985#endif /* not ENABLE_SOCKET_SUPPORT */
7eeb782e
AT
1986
1987/*
1988 * Local Variables:
c150f57c
AT
1989 * tab-width: 4
1990 * c-basic-offset: 4
7eeb782e
AT
1991 * End:
1992 */