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