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