Initial commit of GNU Go v3.8.
[sgk-go] / interface / main.c
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
* http://www.gnu.org/software/gnugo/ for more information. *
* *
* Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008 and 2009 by the Free Software Foundation. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation - version 3 or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License in file COPYING for more details. *
* *
* You should have received a copy of the GNU General Public *
* License along with this program; if not, write to the Free *
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02111, USA. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "gnugo.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
/* For isatty(). */
#include <unistd.h>
#else
#include <io.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include "liberty.h"
#include "gg-getopt.h"
#include "gg_utils.h"
#include "winsocket.h"
#include "interface.h"
#include "sgftree.h"
#include "random.h"
static void show_copyright(void);
static void show_version(void);
static void show_help(void);
static void show_debug_help(void);
static void show_debug_flags(void);
static void socket_connect_to(const char *host_name, unsigned int port,
FILE **input_file, FILE **output_file);
static void socket_listen_at(const char *host_name, unsigned int port,
FILE **input_file, FILE **output_file);
static void socket_close_connection(FILE *input_file, FILE *output_file);
static void socket_stop_listening(FILE *input_file, FILE *output_file);
/* long options which have no short form */
enum {OPT_BOARDSIZE = 127,
OPT_HANDICAPSTONES,
OPT_COLOR,
OPT_KOMI,
OPT_CLOCK_TIME,
OPT_CLOCK_BYO_TIME,
OPT_CLOCK_BYO_PERIOD,
OPT_AUTOLEVEL,
OPT_MODE,
OPT_INFILE,
OPT_OUTFILE,
OPT_QUIET,
OPT_GTP_INPUT,
OPT_GTP_CONNECT,
OPT_GTP_LISTEN,
OPT_GTP_DUMP_COMMANDS,
OPT_GTP_INITIAL_ORIENTATION,
OPT_GTP_VERSION,
OPT_SHOWCOPYRIGHT,
OPT_REPLAY_GAME,
OPT_DECIDE_STRING,
OPT_DECIDE_CONNECTION,
OPT_DECIDE_OWL,
OPT_DECIDE_DRAGON_DATA,
OPT_DECIDE_SEMEAI,
OPT_DECIDE_SURROUNDED,
OPT_DECIDE_TACTICAL_SEMEAI,
OPT_DECIDE_ORACLE,
OPT_EXPERIMENTAL_SEMEAI,
OPT_EXPERIMENTAL_OWL_EXT,
OPT_SEMEAI_NODE_LIMIT,
OPT_EXPERIMENTAL_CONNECTIONS,
OPT_ALTERNATE_CONNECTIONS,
OPT_WITH_BREAK_IN,
OPT_WITHOUT_BREAK_IN,
OPT_COSMIC_GNUGO,
OPT_NO_COSMIC_GNUGO,
OPT_LARGE_SCALE,
OPT_NO_LARGE_SCALE,
OPT_OPTIONS,
OPT_STANDARD_SEMEAI,
OPT_STANDARD_CONNECTIONS,
OPT_PRINT_LEVELS,
OPT_DECIDE_POSITION,
OPT_DECIDE_EYE,
OPT_DECIDE_COMBINATION,
OPT_BRANCH_DEPTH,
OPT_BACKFILL2_DEPTH,
OPT_BREAK_CHAIN_DEPTH,
OPT_SUPERSTRING_DEPTH,
OPT_AA_DEPTH,
OPT_DEBUG_FLAGS,
OPT_OWL_DISTRUST,
OPT_OWL_BRANCH,
OPT_OWL_READING,
OPT_OWL_NODE_LIMIT,
OPT_NOFUSEKIDB,
OPT_NOFUSEKI,
OPT_NOJOSEKIDB,
OPT_LEVEL,
OPT_MIN_LEVEL,
OPT_MAX_LEVEL,
OPT_LIMIT_SEARCH,
OPT_SHOWTIME,
OPT_SHOWSCORE,
OPT_DEBUG_INFLUENCE,
OPT_SCORE,
OPT_PRINTSGF,
OPT_PROFILE_PATTERNS,
OPT_CHINESE_RULES,
OPT_OWL_THREATS,
OPT_NO_OWL_THREATS,
OPT_JAPANESE_RULES,
OPT_FORBID_SUICIDE,
OPT_ALLOW_SUICIDE,
OPT_ALLOW_ALL_SUICIDE,
OPT_SIMPLE_KO,
OPT_NO_KO,
OPT_POSITIONAL_SUPERKO,
OPT_SITUATIONAL_SUPERKO,
OPT_CAPTURE_ALL_DEAD,
OPT_PLAY_OUT_AFTERMATH,
OPT_MIRROR,
OPT_MIRROR_LIMIT,
OPT_METAMACHINE,
OPT_RESIGN_ALLOWED,
OPT_NEVER_RESIGN,
OPT_MONTE_CARLO,
OPT_MC_GAMES_PER_LEVEL,
OPT_MC_PATTERNS,
OPT_MC_LIST_PATTERNS,
OPT_MC_LOAD_PATTERNS
};
/* names of playing modes */
enum mode {
MODE_UNKNOWN = 0,
MODE_ASCII,
MODE_GTP,
MODE_GMP,
MODE_SGMP,
MODE_SGF,
MODE_LOAD_AND_ANALYZE,
MODE_LOAD_AND_SCORE,
MODE_LOAD_AND_PRINT,
MODE_SOLO,
MODE_REPLAY,
MODE_DECIDE_STRING,
MODE_DECIDE_CONNECTION,
MODE_DECIDE_OWL,
MODE_DECIDE_DRAGON_DATA,
MODE_DECIDE_SEMEAI,
MODE_DECIDE_TACTICAL_SEMEAI,
MODE_DECIDE_POSITION,
MODE_DECIDE_EYE,
MODE_DECIDE_COMBINATION,
MODE_DECIDE_SURROUNDED,
MODE_DECIDE_ORACLE
};
/* Definitions of the --long options. Final column is
* either an OPT_ as defined in the enum above, or it
* is the equivalent single-letter option.
* It is useful to keep them in the same order as the
* help string, for maintenance purposes only.
*/
static struct gg_option const long_options[] =
{
{"mode", required_argument, 0, OPT_MODE},
{"replay", required_argument, 0, OPT_REPLAY_GAME},
{"quiet", no_argument, 0, OPT_QUIET},
{"silent", no_argument, 0, OPT_QUIET},
{"gtp-input", required_argument, 0, OPT_GTP_INPUT},
{"gtp-connect", required_argument, 0, OPT_GTP_CONNECT},
{"gtp-listen", required_argument, 0, OPT_GTP_LISTEN},
{"gtp-dump-commands", required_argument, 0, OPT_GTP_DUMP_COMMANDS},
{"orientation", required_argument, 0, OPT_GTP_INITIAL_ORIENTATION},
{"gtp-initial-orientation",
required_argument, 0, OPT_GTP_INITIAL_ORIENTATION},
{"gtp-version", required_argument, 0, OPT_GTP_VERSION},
{"infile", required_argument, 0, 'l'},
{"until", required_argument, 0, 'L'},
{"outfile", required_argument, 0, 'o'},
{"output-flags", required_argument, 0, 'O'},
{"boardsize", required_argument, 0, OPT_BOARDSIZE},
{"color", required_argument, 0, OPT_COLOR},
{"handicap", required_argument, 0, OPT_HANDICAPSTONES},
{"komi", required_argument, 0, OPT_KOMI},
{"help", optional_argument, 0, 'h'},
{"copyright", no_argument, 0, OPT_SHOWCOPYRIGHT},
{"version", no_argument, 0, 'v'},
{"allpats", no_argument, 0, 'a'},
{"printboard", no_argument, 0, 'T'},
{"printeyes", no_argument, 0, 'E'},
{"debug", required_argument, 0, 'd'},
{"debug-flags", no_argument, 0, OPT_DEBUG_FLAGS},
{"depth", required_argument, 0, 'D'},
{"backfill-depth", required_argument, 0, 'B'},
{"branch-depth", required_argument, 0, OPT_BRANCH_DEPTH},
{"backfill2-depth", required_argument, 0, OPT_BACKFILL2_DEPTH},
{"break-chain-depth", required_argument, 0, OPT_BREAK_CHAIN_DEPTH},
{"superstring-depth", required_argument, 0, OPT_SUPERSTRING_DEPTH},
{"fourlib-depth", required_argument, 0, 'F'},
{"ko-depth", required_argument, 0, 'K'},
{"aa-depth", required_argument, 0, OPT_AA_DEPTH},
{"owl-distrust", required_argument, 0, OPT_OWL_DISTRUST},
{"owl-branch", required_argument, 0, OPT_OWL_BRANCH},
{"owl-reading", required_argument, 0, OPT_OWL_READING},
{"owl-node-limit", required_argument, 0, OPT_OWL_NODE_LIMIT},
{"print-levels", no_argument, 0, OPT_PRINT_LEVELS},
{"level", required_argument, 0, OPT_LEVEL},
{"min-level", required_argument, 0, OPT_MIN_LEVEL},
{"max-level", required_argument, 0, OPT_MAX_LEVEL},
{"limit-search", required_argument, 0, OPT_LIMIT_SEARCH},
{"clock", required_argument, 0, OPT_CLOCK_TIME},
{"byo-time", required_argument, 0, OPT_CLOCK_BYO_TIME},
{"byo-period", required_argument, 0, OPT_CLOCK_BYO_PERIOD},
{"autolevel", no_argument, 0, OPT_AUTOLEVEL},
{"chinese-rules", no_argument, 0, OPT_CHINESE_RULES},
{"japanese-rules", no_argument, 0, OPT_JAPANESE_RULES},
{"experimental-semeai", no_argument, 0, OPT_EXPERIMENTAL_SEMEAI},
{"experimental-owl-ext", no_argument, 0, OPT_EXPERIMENTAL_OWL_EXT},
{"semeai-node-limit", required_argument, 0, OPT_SEMEAI_NODE_LIMIT},
{"experimental-connections", no_argument, 0, OPT_EXPERIMENTAL_CONNECTIONS},
{"standard-connections", no_argument, 0, OPT_STANDARD_CONNECTIONS},
{"standard-semeai", no_argument, 0, OPT_STANDARD_SEMEAI},
{"alternate-connections", no_argument, 0, OPT_ALTERNATE_CONNECTIONS},
{"with-break-in", no_argument, 0, OPT_WITH_BREAK_IN},
{"without-break-in", no_argument, 0, OPT_WITHOUT_BREAK_IN},
{"cosmic-gnugo", no_argument, 0, OPT_COSMIC_GNUGO},
{"no-cosmic-gnugo", no_argument, 0, OPT_NO_COSMIC_GNUGO},
{"large-scale", no_argument, 0, OPT_LARGE_SCALE},
{"no-large-scale", no_argument, 0, OPT_NO_LARGE_SCALE},
{"options", no_argument, 0, OPT_OPTIONS},
{"forbid-suicide", no_argument, 0, OPT_FORBID_SUICIDE},
{"allow-suicide", no_argument, 0, OPT_ALLOW_SUICIDE},
{"allow-all-suicide", no_argument, 0, OPT_ALLOW_ALL_SUICIDE},
{"simple-ko", no_argument, 0, OPT_SIMPLE_KO},
{"no-ko", no_argument, 0, OPT_NO_KO},
{"positional-superko", no_argument, 0, OPT_POSITIONAL_SUPERKO},
{"situational-superko", no_argument, 0, OPT_SITUATIONAL_SUPERKO},
{"capture-all-dead", no_argument, 0, OPT_CAPTURE_ALL_DEAD},
{"play-out-aftermath", no_argument, 0, OPT_PLAY_OUT_AFTERMATH},
{"cache-size", required_argument, 0, 'M'},
{"worms", no_argument, 0, 'w'},
{"moyo", required_argument, 0, 'm'},
{"benchmark", required_argument, 0, 'b'},
{"statistics", no_argument, 0, 'S'},
{"trace", no_argument, 0, 't'},
{"seed", required_argument, 0, 'r'},
{"decide-string", required_argument, 0, OPT_DECIDE_STRING},
{"decide-connection", required_argument, 0, OPT_DECIDE_CONNECTION},
{"decide-dragon", required_argument, 0, OPT_DECIDE_OWL},
{"decide-owl", required_argument, 0, OPT_DECIDE_OWL},
{"decide-dragon-data", required_argument, 0, OPT_DECIDE_DRAGON_DATA},
{"decide-semeai", required_argument, 0, OPT_DECIDE_SEMEAI},
{"decide-tactical-semeai", required_argument, 0, OPT_DECIDE_TACTICAL_SEMEAI},
{"decide-position", no_argument, 0, OPT_DECIDE_POSITION},
{"decide-surrounded", required_argument, 0, OPT_DECIDE_SURROUNDED},
{"decide-eye", required_argument, 0, OPT_DECIDE_EYE},
{"decide-combination", no_argument, 0, OPT_DECIDE_COMBINATION},
{"decide-oracle", no_argument, 0, OPT_DECIDE_ORACLE},
{"nofusekidb", no_argument, 0, OPT_NOFUSEKIDB},
{"nofuseki", no_argument, 0, OPT_NOFUSEKI},
{"nojosekidb", no_argument, 0, OPT_NOJOSEKIDB},
{"debug-influence", required_argument, 0, OPT_DEBUG_INFLUENCE},
{"showtime", no_argument, 0, OPT_SHOWTIME},
{"showscore", no_argument, 0, OPT_SHOWSCORE},
{"score", required_argument, 0, OPT_SCORE},
{"printsgf", required_argument, 0, OPT_PRINTSGF},
{"profile-patterns", no_argument, 0, OPT_PROFILE_PATTERNS},
{"mirror", no_argument, 0, OPT_MIRROR},
{"mirror-limit", required_argument, 0, OPT_MIRROR_LIMIT},
{"metamachine", no_argument, 0, OPT_METAMACHINE},
{"resign-allowed", no_argument, 0, OPT_RESIGN_ALLOWED},
{"never-resign", no_argument, 0, OPT_NEVER_RESIGN},
{"monte-carlo", no_argument, 0, OPT_MONTE_CARLO},
{"mc-games-per-level", required_argument, 0, OPT_MC_GAMES_PER_LEVEL},
{"mc-patterns", required_argument, 0, OPT_MC_PATTERNS},
{"mc-list-patterns", no_argument, 0, OPT_MC_LIST_PATTERNS},
{"mc-load-patterns", required_argument, 0, OPT_MC_LOAD_PATTERNS},
{NULL, 0, NULL, 0}
};
int
main(int argc, char *argv[])
{
Gameinfo gameinfo;
SGFTree sgftree;
int i;
int mandated_color = EMPTY;
enum mode playmode = MODE_UNKNOWN;
int replay_color = EMPTY;
char *infilename = NULL;
char *untilstring = NULL;
char *scoringmode = NULL;
char *outfile = NULL;
char *outflags = NULL;
char *gtpfile = NULL;
char *gtp_dump_commands_file = NULL;
int gtp_tcp_ip_mode = 0;
char *gtp_tcp_ip_address = NULL;
char *printsgffile = NULL;
char decide_this[8];
char *decide_that = NULL;
char debuginfluence_move[4] = "\0";
int benchmark = 0; /* benchmarking mode (-b) */
FILE *output_check;
int orientation = 0;
char mc_pattern_name[40] = "";
char mc_pattern_filename[320] = "";
float memory = (float) DEFAULT_MEMORY; /* Megabytes used for hash table. */
/* If seed is zero, GNU Go will play a different game each time. If
* it is set using -r, GNU Go will play the same game each time.
* (Change seed to get a different game).
*/
int seed = 0;
int seed_specified = 0;
int requested_boardsize = -1;
sgftree_clear(&sgftree);
gameinfo_clear(&gameinfo);
/* Weed through all of the command line options. */
while ((i = gg_getopt_long(argc, argv,
"-ab:B:d:D:EF:gh::K:l:L:M:m:o:O:p:r:fsStTvw",
long_options, NULL)) != EOF)
{
switch (i) {
case 'T': printboard++; break;
case 't': ++verbose; break;
case 'a': allpats = 1; break;
case 1 :
case 'l': infilename = gg_optarg;
break;
case 'b': benchmark = atoi(gg_optarg); playmode = MODE_SOLO; break;
case 'r': seed = atoi(gg_optarg); seed_specified = 1; break;
case 'S': showstatistics = 1; break;
case 'w': printworms = 1; break;
case 'm': printmoyo = strtol(gg_optarg, NULL, 0); /* allows 0x... */
break;
case 'd': debug ^= strtol(gg_optarg, NULL, 0); /* allows 0x... */ break;
case 'D': mandated_depth = atoi(gg_optarg); break;
case 'M': memory = atof(gg_optarg); break; /* floating point number */
case 'E': printboard = 2; break;
case 'B': mandated_backfill_depth = atoi(gg_optarg); break;
case 'F': mandated_fourlib_depth = atoi(gg_optarg); break;
case 'K': mandated_ko_depth = atoi(gg_optarg); break;
case 'L':
untilstring = gg_optarg;
break;
case 'o':
if (strlen(gg_optarg) >= sizeof(outfilename)) {
fprintf(stderr, "Too long filename given as value to -o option.\n");
exit(EXIT_FAILURE);
}
outfile = gg_optarg;
strcpy(outfilename, gg_optarg);
break;
case 'O':
outflags = gg_optarg;
output_flags = 0;
if (outflags)
while (*outflags) {
switch (*outflags) {
case 'd':
output_flags |= OUTPUT_MARKDRAGONS;
break;
case 'v':
output_flags |= OUTPUT_MOVEVALUES;
break;
}
outflags++;
}
break;
case OPT_QUIET:
quiet = 1;
break;
case OPT_GTP_INPUT:
case OPT_GTP_CONNECT:
case OPT_GTP_LISTEN:
if (gtp_tcp_ip_mode != 0 || gtpfile != NULL) {
fprintf(stderr, ("Options `--gtp-input', `--gtp-connect' and `--gtp-listen' "
"are mutually-exclusive\n"));
exit(EXIT_FAILURE);
}
if (i == OPT_GTP_INPUT)
gtpfile = gg_optarg;
else {
gtp_tcp_ip_mode = i;
gtp_tcp_ip_address = gg_optarg;
}
break;
case OPT_GTP_DUMP_COMMANDS:
gtp_dump_commands_file = gg_optarg;
break;
case OPT_GTP_INITIAL_ORIENTATION:
orientation = atoi(gg_optarg);
if (orientation < 0 || orientation > 7) {
fprintf(stderr, "Invalid orientation: %d.\n", orientation);
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
break;
case OPT_GTP_VERSION:
gtp_version = atoi(gg_optarg);
break;
case OPT_OPTIONS:
if (USE_BREAK_IN)
fprintf(stdout,
"configure option enabled: experimental break-ins\n");
if (COSMIC_GNUGO)
fprintf(stdout,
"configure option enabled: cosmic GNU Go \n");
if (LARGE_SCALE)
fprintf(stdout,
"configure option enabled: large scale captures \n");
if (EXPERIMENTAL_CONNECTIONS)
fprintf(stdout,
"configure option enabled: experimental connections\n");
if (ALTERNATE_CONNECTIONS)
fprintf(stdout,
"configure option enabled: alternate connections\n");
if (EXPERIMENTAL_OWL_EXT)
fprintf(stdout,
"configure option enabled: experimental GAIN/LOSS codes\n");
if (OWL_THREATS)
fprintf(stdout,
"configure option enabled: owl threats\n");
if (RESIGNATION_ALLOWED)
fprintf(stdout,
"configure option enabled: resignation allowed\n");
if (ORACLE)
fprintf(stdout,
"configure option enabled: oracle\n");
fprintf(stdout,
"Owl node limit: %d\n", OWL_NODE_LIMIT);
fprintf(stdout,
"Semeai node limit: %d\n", SEMEAI_NODE_LIMIT);
if (DEFAULT_MEMORY == -1)
fprintf(stdout, "Cache size: %d MB (special default value)\n",
DEFAULT_MEMORY);
else
fprintf(stdout, "Cache size: %d MB\n", DEFAULT_MEMORY);
return EXIT_SUCCESS;
break;
case OPT_SHOWTIME:
showtime = 1;
break;
case OPT_SHOWSCORE:
showscore = 1;
break;
case OPT_HANDICAPSTONES:
{
int requested_handicap = atoi(gg_optarg);
if (requested_handicap < 0 || requested_handicap > MAX_HANDICAP) {
fprintf(stderr, "Unsupported handicap: %d.\n", requested_handicap);
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
gameinfo.handicap = requested_handicap;
}
break;
case OPT_BOARDSIZE:
requested_boardsize = atoi(gg_optarg);
break;
case OPT_KOMI:
if (sscanf(gg_optarg, "%f", &komi) != 1) {
fprintf(stderr, "Invalid komi selection: %s\n", gg_optarg);
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
break;
case OPT_CHINESE_RULES:
chinese_rules = 1;
break;
case OPT_OWL_THREATS:
owl_threats = 1;
break;
case OPT_NO_OWL_THREATS:
owl_threats = 0;
break;
case OPT_METAMACHINE:
metamachine = 1;
break;
case OPT_JAPANESE_RULES:
chinese_rules = 0;
break;
case OPT_EXPERIMENTAL_OWL_EXT:
experimental_owl_ext = 1;
break;
case OPT_SEMEAI_NODE_LIMIT:
mandated_semeai_node_limit = atoi(gg_optarg);
break;
case OPT_EXPERIMENTAL_CONNECTIONS:
experimental_connections = 1;
break;
case OPT_STANDARD_CONNECTIONS:
experimental_connections = 0;
break;
case OPT_ALTERNATE_CONNECTIONS:
alternate_connections = !alternate_connections;
break;
case OPT_WITH_BREAK_IN:
experimental_break_in = 1;
break;
case OPT_WITHOUT_BREAK_IN:
experimental_break_in = 0;
break;
case OPT_COSMIC_GNUGO:
cosmic_gnugo = 1;
break;
case OPT_NO_COSMIC_GNUGO:
cosmic_gnugo = 0;
break;
case OPT_LARGE_SCALE:
large_scale = 1;
break;
case OPT_NO_LARGE_SCALE:
large_scale = 0;
break;
case OPT_FORBID_SUICIDE:
suicide_rule = FORBIDDEN;
break;
case OPT_ALLOW_SUICIDE:
suicide_rule = ALLOWED;
break;
case OPT_ALLOW_ALL_SUICIDE:
suicide_rule = ALL_ALLOWED;
break;
case OPT_SIMPLE_KO:
ko_rule = SIMPLE;
break;
case OPT_NO_KO:
ko_rule = NONE;
break;
case OPT_POSITIONAL_SUPERKO:
ko_rule = PSK;
break;
case OPT_SITUATIONAL_SUPERKO:
ko_rule = SSK;
break;
case OPT_CAPTURE_ALL_DEAD:
capture_all_dead = 1;
break;
case OPT_PLAY_OUT_AFTERMATH:
play_out_aftermath = 1;
break;
case OPT_RESIGN_ALLOWED:
resign_allowed = 1;
break;
case OPT_NEVER_RESIGN:
resign_allowed = 0;
break;
case OPT_MONTE_CARLO:
use_monte_carlo_genmove = 1;
break;
case OPT_MC_GAMES_PER_LEVEL:
mc_games_per_level = atoi(gg_optarg);
break;
case OPT_MC_PATTERNS:
if (strlen(gg_optarg) >= sizeof(mc_pattern_name)) {
fprintf(stderr, "Too long name given as value to --mc-patterns option.\n");
exit(EXIT_FAILURE);
}
strcpy(mc_pattern_name, gg_optarg);
break;
case OPT_MC_LIST_PATTERNS:
list_mc_patterns();
return EXIT_SUCCESS;
break;
case OPT_MC_LOAD_PATTERNS:
if (strlen(gg_optarg) >= sizeof(mc_pattern_filename)) {
fprintf(stderr, "Too long name given as value to --mc-load-patterns option.\n");
exit(EXIT_FAILURE);
}
strcpy(mc_pattern_filename, gg_optarg);
break;
case OPT_MODE:
if (strcmp(gg_optarg, "ascii") == 0)
playmode = MODE_ASCII;
else if (strcmp(gg_optarg, "gtp") == 0)
playmode = MODE_GTP;
else if (strcmp(gg_optarg, "gmp") == 0)
playmode = MODE_GMP;
else if (strcmp(gg_optarg, "sgmp") == 0)
playmode = MODE_SGMP;
else {
fprintf(stderr, "Invalid mode selection: %s\n", gg_optarg);
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
break;
case OPT_DECIDE_STRING:
if (strlen(gg_optarg) > 3) {
fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
exit(EXIT_FAILURE);
}
strcpy(decide_this, gg_optarg);
playmode = MODE_DECIDE_STRING;
break;
case OPT_DECIDE_CONNECTION:
if (strlen(gg_optarg) > 7) {
fprintf(stderr,
"usage: --decide-connection [first string]/[second string]\n");
return EXIT_FAILURE;
}
strcpy(decide_this, gg_optarg);
strtok(decide_this, "/");
decide_that = strtok(NULL, "/");
if (!decide_that) {
fprintf(stderr,
"usage: --decide-connection [first string]/[second string]\n");
return EXIT_FAILURE;
}
playmode = MODE_DECIDE_CONNECTION;
break;
case OPT_DECIDE_OWL:
if (strlen(gg_optarg) > 3) {
fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
exit(EXIT_FAILURE);
}
strcpy(decide_this, gg_optarg);
playmode = MODE_DECIDE_OWL;
break;
case OPT_DECIDE_DRAGON_DATA:
if (strlen(gg_optarg) > 3) {
fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
exit(EXIT_FAILURE);
}
strcpy(decide_this, gg_optarg);
playmode = MODE_DECIDE_DRAGON_DATA;
break;
case OPT_DECIDE_SEMEAI:
if (strlen(gg_optarg) > 7) {
fprintf(stderr,
"usage: --decide-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
strcpy(decide_this, gg_optarg);
strtok(decide_this, "/");
decide_that = strtok(NULL, "/");
if (!decide_that) {
fprintf(stderr,
"usage: --decide-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
playmode = MODE_DECIDE_SEMEAI;
break;
case OPT_DECIDE_TACTICAL_SEMEAI:
if (strlen(gg_optarg) > 7) {
fprintf(stderr,
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
strcpy(decide_this, gg_optarg);
strtok(decide_this, "/");
decide_that = strtok(NULL, "/");
if (!decide_that) {
fprintf(stderr,
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
playmode = MODE_DECIDE_TACTICAL_SEMEAI;
break;
case OPT_DECIDE_POSITION:
playmode = MODE_DECIDE_POSITION;
break;
case OPT_DECIDE_EYE:
if (strlen(gg_optarg) > 3) {
fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
exit(EXIT_FAILURE);
}
strcpy(decide_this, gg_optarg);
playmode = MODE_DECIDE_EYE;
break;
case OPT_DECIDE_COMBINATION:
playmode = MODE_DECIDE_COMBINATION;
break;
case OPT_DECIDE_SURROUNDED:
if (strlen(gg_optarg) > 3) {
fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
exit(EXIT_FAILURE);
}
strcpy(decide_this, gg_optarg);
playmode = MODE_DECIDE_SURROUNDED;
break;
case OPT_DECIDE_ORACLE:
playmode = MODE_DECIDE_ORACLE;
break;
case OPT_BRANCH_DEPTH:
mandated_branch_depth = atoi(gg_optarg);
break;
case OPT_BACKFILL2_DEPTH:
mandated_backfill2_depth = atoi(gg_optarg);
break;
case OPT_BREAK_CHAIN_DEPTH:
mandated_break_chain_depth = atoi(gg_optarg);
break;
case OPT_SUPERSTRING_DEPTH:
mandated_superstring_depth = atoi(gg_optarg);
break;
case OPT_AA_DEPTH:
mandated_aa_depth = atoi(gg_optarg);
break;
case OPT_OWL_DISTRUST:
mandated_owl_distrust_depth = atoi(gg_optarg);
break;
case OPT_OWL_BRANCH:
mandated_owl_branch_depth = atoi(gg_optarg);
break;
case OPT_OWL_READING:
mandated_owl_reading_depth = atoi(gg_optarg);
break;
case OPT_OWL_NODE_LIMIT:
mandated_owl_node_limit = atoi(gg_optarg);
break;
case OPT_NOFUSEKIDB:
fusekidb = 0;
break;
case OPT_NOFUSEKI:
disable_fuseki = 1;
break;
case OPT_NOJOSEKIDB:
josekidb = 0;
break;
case OPT_LEVEL:
set_level(atoi(gg_optarg));
break;
case OPT_MIN_LEVEL:
set_min_level(atoi(gg_optarg));
break;
case OPT_MAX_LEVEL:
set_max_level(atoi(gg_optarg));
break;
case OPT_LIMIT_SEARCH:
{
int pos = string_to_location(board_size, gg_optarg);
if (pos == NO_MOVE) {
fprintf(stderr, "gnugo: use --limit-search <pos>\n");
return EXIT_FAILURE;
}
set_search_diamond(pos);
}
break;
case OPT_CLOCK_TIME:
clock_settings(atoi(gg_optarg), -1, -1);
break;
case OPT_CLOCK_BYO_TIME:
clock_settings(-1, atoi(gg_optarg), -1);
break;
case OPT_CLOCK_BYO_PERIOD:
clock_settings(-1, -1, atoi(gg_optarg));
break;
case OPT_AUTOLEVEL:
autolevel_on = 1;
break;
case OPT_DEBUG_INFLUENCE:
if (strlen(gg_optarg) > 3) {
fprintf(stderr, "Invalid board coordinate: %s\n", gg_optarg);
exit(EXIT_FAILURE);
}
strcpy(debuginfluence_move, gg_optarg);
break;
case OPT_REPLAY_GAME:
playmode = MODE_REPLAY;
if (strcmp(gg_optarg, "white") == 0)
replay_color = WHITE;
else if (strcmp(gg_optarg, "black") == 0)
replay_color = BLACK;
else if (strcmp(gg_optarg, "both") == 0)
replay_color = GRAY;
else {
fprintf(stderr, "Invalid replay color: %s\n", gg_optarg);
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
break;
case OPT_SCORE:
scoringmode = gg_optarg;
if (playmode == MODE_UNKNOWN)
playmode = MODE_LOAD_AND_SCORE;
break;
case OPT_PRINTSGF:
playmode = MODE_LOAD_AND_PRINT;
printsgffile = gg_optarg;
break;
case OPT_PROFILE_PATTERNS:
profile_patterns = 1;
prepare_pattern_profiling();
break;
case OPT_COLOR:
if (strcmp(gg_optarg, "white") == 0)
mandated_color = WHITE;
else if (strcmp(gg_optarg, "black") == 0)
mandated_color = BLACK;
else {
fprintf(stderr, "Invalid color selection: %s\n", gg_optarg);
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
break;
case OPT_SHOWCOPYRIGHT:
show_copyright();
return EXIT_SUCCESS;
break;
case OPT_MIRROR:
play_mirror_go = 1;
break;
case OPT_MIRROR_LIMIT:
mirror_stones_limit = atoi(gg_optarg);
break;
case 'v':
show_version();
show_copyright();
return EXIT_SUCCESS;
break;
case 'h':
show_version();
if (gg_optarg) {
/* In the default behavior of getopt_long with optional args
* you need to type "-hdebug"
* I can't get long options "--helpdebug" to work at all
*/
if (strncmp(gg_optarg, "debug", 5) == 0)
show_debug_help();
}
else {
/* This is the trick to get "--help debug" and "-h debug" to work*/
if (gg_optind < argc) {
if (strncmp(argv[gg_optind], "debug", 5) == 0)
show_debug_help();
}
else
show_help();
}
return EXIT_SUCCESS;
break;
case OPT_DEBUG_FLAGS:
show_debug_flags();
return EXIT_SUCCESS;
break;
case OPT_PRINT_LEVELS:
{
int lev;
for (lev = 12; lev >= 0; lev--)
set_depth_values(lev, 1);
}
return EXIT_SUCCESS;
break;
/* NOTE: getopt returns '?' if an illegal option is supplied. */
case '?':
default:
fprintf(stderr, "Try `gnugo --help' for more information.\n");
exit(EXIT_FAILURE);
}
}
if (requested_boardsize != -1) {
if (!check_boardsize(requested_boardsize, stderr))
exit(EXIT_FAILURE);
gnugo_clear_board(requested_boardsize);
}
/* Start random number seed. */
if (!seed_specified)
seed = time(0);
/* Initialize the GNU Go engine. */
init_gnugo(memory, seed);
/* Load Monte Carlo patterns if one has been specified. Either
* choose one of the compiled in ones or load directly from a
* database file.
*/
if (strlen(mc_pattern_filename) > 0) {
if (!mc_load_patterns_from_db(mc_pattern_filename, NULL))
return EXIT_FAILURE;
}
else if (strlen(mc_pattern_name) > 0) {
if (!choose_mc_patterns(mc_pattern_name)) {
fprintf(stderr, "Unknown Monte Carlo pattern database name %s.\n",
mc_pattern_name);
fprintf(stderr, "Use \"--mc-list-patterns\" to list the available databases.\n");
return EXIT_FAILURE;
}
}
/* Read the infile if there is one. Also play up the position. */
if (infilename) {
if (!sgftree_readfile(&sgftree, infilename)) {
fprintf(stderr, "Cannot open or parse '%s'\n", infilename);
exit(EXIT_FAILURE);
}
if (gameinfo_play_sgftree_rot(&gameinfo, &sgftree, untilstring,
orientation) == EMPTY) {
fprintf(stderr, "Cannot load '%s'\n", infilename);
exit(EXIT_FAILURE);
}
}
else
/* Initialize and empty sgf tree if there was no infile. */
sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap);
/* Set the game_record to be identical to the loaded one or the
* newly created empty sgf tree.
*/
gameinfo.game_record = sgftree;
/* Notice that we need to know the board size before we can do this.
*/
if (debuginfluence_move[0]) {
int pos = string_to_location(board_size, debuginfluence_move);
debug_influence_move(pos);
}
/* Figure out a default mode if there was no explicit one. */
if (playmode == MODE_UNKNOWN) {
if (infilename)
playmode = MODE_LOAD_AND_ANALYZE;
else
playmode = (isatty(0)) ? MODE_ASCII : MODE_GMP;
}
if (outfile && playmode != MODE_LOAD_AND_PRINT) {
output_check = fopen(outfile, "w");
if (!output_check) {
fprintf(stderr, "Error: could not open '%s' for writing\n", outfile);
exit(EXIT_FAILURE);
}
fclose(output_check);
}
switch (playmode) {
case MODE_GMP:
case MODE_SGMP:
/* not supported by the protocol */
resign_allowed = 0;
#if ORACLE
if (metamachine)
summon_oracle();
#endif
/* EMPTY is valid for play_gmp.c. */
gameinfo.computer_player = mandated_color;
play_gmp(&gameinfo, playmode == MODE_SGMP);
#if ORACLE
if (metamachine)
dismiss_oracle();
#endif
break;
case MODE_SOLO:
play_solo(&gameinfo, benchmark);
break;
case MODE_REPLAY:
if (!infilename) {
fprintf(stderr, "You must use -l infile with replay mode.\n");
exit(EXIT_FAILURE);
}
play_replay(&sgftree, replay_color);
break;
case MODE_LOAD_AND_ANALYZE:
if (mandated_color != EMPTY)
gameinfo.to_move = mandated_color;
if (!infilename) {
fprintf(stderr, "You must use -l infile with load and analyze mode.\n");
exit(EXIT_FAILURE);
}
#if ORACLE
if (metamachine) {
summon_oracle();
oracle_loadsgf(infilename, untilstring);
}
#endif
load_and_analyze_sgf_file(&gameinfo);
#if ORACLE
dismiss_oracle();
#endif
break;
case MODE_LOAD_AND_SCORE:
if (mandated_color != EMPTY)
gameinfo.to_move = mandated_color;
if (!infilename) {
fprintf(stderr, "gnugo: --score must be used with -l\n");
exit(EXIT_FAILURE);
}
load_and_score_sgf_file(&sgftree, &gameinfo, scoringmode);
break;
case MODE_LOAD_AND_PRINT:
if (!infilename) {
fprintf(stderr, "gnugo: --printsgf must be used with -l\n");
exit(EXIT_FAILURE);
}
else {
if (mandated_color != EMPTY)
gameinfo.to_move = mandated_color;
sgffile_printsgf(gameinfo.to_move, printsgffile);
}
break;
case MODE_DECIDE_STRING:
{
int str;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-string must be used with -l\n");
return EXIT_FAILURE;
}
str = string_to_location(board_size, decide_this);
if (str == NO_MOVE) {
fprintf(stderr, "gnugo: --decide-string: strange coordinate \n");
return EXIT_FAILURE;
}
decide_string(str);
}
break;
case MODE_DECIDE_CONNECTION:
{
int str1, str2;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-connection must be used with -l\n");
return EXIT_FAILURE;
}
str1 = string_to_location(board_size, decide_this);
if (str1 == NO_MOVE) {
fprintf(stderr,
"usage: --decide-connection [first string]/[second string]\n");
return EXIT_FAILURE;
}
str2 = string_to_location(board_size, decide_that);
if (str2 == NO_MOVE) {
fprintf(stderr,
"usage: --decide-connection [first string]/[second string]\n");
return EXIT_FAILURE;
}
decide_connection(str1, str2);
}
break;
case MODE_DECIDE_OWL:
{
int pos;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-dragon must be used with -l\n");
return EXIT_FAILURE;
}
pos = string_to_location(board_size, decide_this);
if (pos == NO_MOVE) {
fprintf(stderr, "gnugo: --decide-dragon: strange coordinate \n");
return EXIT_FAILURE;
}
decide_owl(pos);
}
break;
case MODE_DECIDE_DRAGON_DATA:
{
int pos;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-dragon-data must be used with -l\n");
return EXIT_FAILURE;
}
pos = string_to_location(board_size, decide_this);
if (pos == NO_MOVE) {
fprintf(stderr, "gnugo: --decide-dragon-data: strange coordinate \n");
return EXIT_FAILURE;
}
decide_dragon_data(pos);
}
break;
case MODE_DECIDE_SEMEAI:
{
int pos1, pos2;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-semeai must be used with -l\n");
return EXIT_FAILURE;
}
pos1 = string_to_location(board_size, decide_this);
if (pos1 == NO_MOVE) {
fprintf(stderr,
"usage: --decide-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
pos2 = string_to_location(board_size, decide_that);
if (pos2 == NO_MOVE) {
fprintf(stderr,
"usage: --decide-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
decide_semeai(pos1, pos2);
}
break;
case MODE_DECIDE_TACTICAL_SEMEAI:
{
int pos1, pos2;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-tactical-semeai must be used with -l\n");
return EXIT_FAILURE;
}
pos1 = string_to_location(board_size, decide_this);
if (pos1 == NO_MOVE) {
fprintf(stderr,
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
pos2 = string_to_location(board_size, decide_that);
if (pos2 == NO_MOVE) {
fprintf(stderr,
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
return EXIT_FAILURE;
}
decide_tactical_semeai(pos1, pos2);
}
break;
case MODE_DECIDE_POSITION:
{
if (!infilename) {
fprintf(stderr, "gnugo: --decide-position must be used with -l\n");
return EXIT_FAILURE;
}
decide_position();
}
break;
case MODE_DECIDE_EYE:
{
int pos;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-eye must be used with -l\n");
return EXIT_FAILURE;
}
pos = string_to_location(board_size, decide_this);
if (pos == NO_MOVE) {
fprintf(stderr, "gnugo: --decide-eye: strange coordinate \n");
return EXIT_FAILURE;
}
decide_eye(pos);
}
break;
case MODE_DECIDE_COMBINATION:
{
int color;
if (!infilename) {
fprintf(stderr, "gnugo: --decide-combination must be used with -l\n");
return EXIT_FAILURE;
}
color = gameinfo.to_move;
if (mandated_color != EMPTY)
color = mandated_color;
decide_combination(color);
}
break;
case MODE_DECIDE_SURROUNDED:
{
int pos = string_to_location(board_size, decide_this);
if (pos == NO_MOVE) {
fprintf(stderr,
"usage: --decide-surrounded [pos]\n");
return EXIT_FAILURE;
}
decide_surrounded(pos);
break;
}
#if ORACLE
case MODE_DECIDE_ORACLE:
{
if (mandated_color != EMPTY)
gameinfo.to_move = mandated_color;
if (!infilename) {
fprintf(stderr, "You must use -l infile with load and analyze mode.\n");
exit(EXIT_FAILURE);
}
decide_oracle(&gameinfo, infilename, untilstring);
break;
}
#endif
case MODE_GTP:
{
FILE *gtp_input_FILE = stdin;
FILE *gtp_output_FILE = stdout;
FILE *gtp_dump_commands_FILE = NULL;
if (gtpfile != NULL) {
gtp_input_FILE = fopen(gtpfile, "r");
if (gtp_input_FILE == NULL) {
fprintf(stderr, "gnugo: Cannot open file %s\n", gtpfile);
return EXIT_FAILURE;
}
}
else if (gtp_tcp_ip_mode != 0) {
unsigned int port = 65536;
char *port_string = strchr(gtp_tcp_ip_address, ':');
const char *host_name = NULL;
if (port_string) {
host_name = gtp_tcp_ip_address;
*port_string++ = 0;
sscanf(port_string, "%u", &port);
}
else
sscanf(gtp_tcp_ip_address, "%u", &port);
if (port > 65535) {
fprintf(stderr, "A valid TCP/IP port number expected\n");
exit(EXIT_FAILURE);
}
if (gtp_tcp_ip_mode == OPT_GTP_CONNECT) {
socket_connect_to(host_name, port,
&gtp_input_FILE, &gtp_output_FILE);
}
else {
socket_listen_at(host_name, port,
&gtp_input_FILE, &gtp_output_FILE);
}
}
if (gtp_dump_commands_file != NULL) {
gtp_dump_commands_FILE = fopen(gtp_dump_commands_file, "w");
if (gtp_dump_commands_FILE == NULL) {
fprintf(stderr, "gnugo: Cannot open file %s\n",
gtp_dump_commands_file);
return EXIT_FAILURE;
}
}
play_gtp(gtp_input_FILE, gtp_output_FILE, gtp_dump_commands_FILE,
orientation);
if (gtp_dump_commands_FILE)
fclose(gtp_dump_commands_FILE);
if (gtp_tcp_ip_mode == OPT_GTP_CONNECT)
socket_close_connection(gtp_input_FILE, gtp_output_FILE);
else if (gtp_tcp_ip_mode == OPT_GTP_LISTEN)
socket_stop_listening(gtp_input_FILE, gtp_output_FILE);
}
break;
case MODE_ASCII:
default:
if (mandated_color != EMPTY)
gameinfo.computer_player = OTHER_COLOR(mandated_color);
/* Display copyright message in ASCII mode unless --quiet option used. */
if (!quiet) {
show_version();
show_copyright();
}
#if ORACLE
if (metamachine) {
summon_oracle();
oracle_loadsgf(infilename, untilstring);
}
#endif
play_ascii(&sgftree, &gameinfo, infilename, untilstring);
break;
}
if (profile_patterns)
report_pattern_profiling();
sgfFreeNode(sgftree.root);
return 0;
} /* end main */
static void
show_version(void)
{
printf("GNU Go %s\n", VERSION);
}
/* Set the parameters which determine the depth to which
* the reading and owl code carries its calculations.
*/
/*
* This string is modelled after the GNU tar --help output.
* Since the maximum string length is 2048 bytes in VC++ we
* split the help string.
*/
#define USAGE "\n\
Usage: gnugo [-opts]\n\
\n\
Examples:\n\
gnugo --mode gtp --level 5\n\
To play against gnugo in level 5 from a GTP client\n\
gnugo --mode ascii -l game.sgf -L 123\n\
Resume game at move 123 in ASCII mode\n\
gnugo --score estimate -l game.sgf\n\
Give a rough score estimate of the end position in game.sgf\n\
\n\
Main Options:\n\
--mode <mode> Force the playing mode ('ascii', 'gmp', 'sgmp',\n\
or 'gtp'). Default is ASCII.\n\
If no terminal is detected GMP (Go Modem Protocol)\n\
will be assumed.\n\
--quiet --silent Don't print copyright and informational messages\n\
--level <amount> strength (default %d)\n\
--never-resign Forbid GNU Go to resign\n\
--resign-allowed Allow resignation (default)\n\
-l, --infile <file> Load name sgf file\n\
-L, --until <move> Stop loading just before move is played. <move>\n\
can be the move number or location (eg L10).\n\
-o, --outfile <file> Write sgf output to file\n\
--printsgf <file> Write position as a diagram to file (use with -l)\n\
\n\
Scoring:\n\
--score estimate estimate score at loaded position\n\
--score finish generate moves to finish game, then score\n\
--score aftermath generate moves to finish, use best algorithm\n\
\n\
"
#define USAGE1 "\
Game Options:\n\
Used with --mode ascii (or other modes for non-interactive settings)\n\
--boardsize num Set the board size to use (%d--%d)\n\
--color <color> Choose your color ('black' or 'white')\n\
--handicap <num> Set the number of handicap stones (0--%d)\n\
--komi <num> Set the komi\n\
--clock <sec> Initialize the timer.\n\
--byo-time <sec> Initialize the byo-yomi timer.\n\
--byo-period <stones> Initialize the byo-yomi period.\n\
\n\
--japanese-rules (default)\n\
--chinese-rules\n\
--forbid-suicide Forbid suicide. (default)\n\
--allow-suicide Allow suicide except single-stone suicide.\n\
--allow-all-suicide Allow all suicide moves.\n\
--simple-ko Forbid simple ko recapture. (default)\n\
--no-ko Allow any ko recapture.\n\
--positional-superko Positional superko restrictions.\n\
--situational-superko Situational superko restrictions.\n\
\n\
--play-out-aftermath\n\
--capture-all-dead\n\
\n\
--min-level <amount> minimum level for adjustment schemes\n\
--max-level <amount> maximum level for adjustment schemes\n\
--autolevel adapt gnugo level during game to respect\n\
the time specified by --clock <sec>.\n\
\n\
Connection options\n\
--gtp-input <file>Read gtp commands from file instead of stdin\n\
--gtp-connect [HOST:]PORT\n\
Connect to given host (127.0.0.1 if omitted) and port\n\
and receive GTP commands on the established connection\n\
--gtp-listen [HOST:]PORT\n\
Wait for the first TCP/IP connection on the given port\n\
(if HOST is specified, only to that host)\n\
--gtp-version\n\
\n\
"
#define USAGE2 "\
Experimental options:\n\
--with-break-in use the break-in code (on at level 10 by default)\n\
--without-break-in do not use the break-in code\n\
--cosmic-gnugo use center oriented influence\n\
--no-cosmic-gnugo don't use center oriented influence (default)\n\
--large-scale look for large scale captures\n\
--no-large-scale don't seek large scale captures (default)\n\
--nofusekidb turn off fuseki database\n\
--nofuseki turn off fuseki moves entirely\n\
--nojosekidb turn off joseki database\n\
--mirror try to play mirror go\n\
--mirror-limit <n> stop mirroring when n stones on board\n\n\
--monte-carlo enable Monte Carlo move generation (9x9 or smaller)\n\
--mc-games-per-level <n> number of Monte Carlo simulations per level\n\
--mc-list-patterns list names of builtin Monte Carlo patterns\n\
--mc-patterns <name> choose a built in Monte Carlo pattern database\n\
--mc-load-patterns <filename> read Monte Carlo patterns from file\n\
--alternate-connections\n\
--experimental-connections\n\
--experimental-owl-ext\n\
--experimental-semeai\n\
--standard-connections\n\
--standard-semeai\n\
--oracle Read the documentation\n\
\n\
Cache size (higher=more memory usage, faster unless swapping occurs):\n\
-M, --cache-size <megabytes> RAM cache for read results (default %4.1f Mb)\n\
\n\
Informative Output:\n\
-v, --version Display the version and copyright of GNU Go\n\
--options Display configure options\n\
-h, --help Display this help message\n\
--help debug Display help about debugging options\n\
--copyright Display copyright notice\n\
\n\
"
#define COPYRIGHT \
"Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007\n\
2008 and 2009 by the Free Software Foundation, Inc.\n\
See http://www.gnu.org/software/gnugo/ or contact\n\
gnugo@gnu.org for information about GNU Go. GNU Go comes with NO WARRANTY to\n\
the extent permitted by law. This program is free software; you can\n\
redistribute it and/or modify it under the terms of the GNU General Public\n\
License as published by the Free Software Foundation - version 3 or\n\
(at your option) any later version. For more\n\
information about these matters, see the files named COPYING.\n"
/* USAGE_DEBUG Split in half because of VC limit on constant string
* length of 2048 characters!*/
#define USAGE_DEBUG "\n\
Debugging Options:\n\
\n\
--replay <color> replay the moves in a game for color.\n\
(requires -l)\n\
white: replay only white moves\n\
black: replay only black moves\n\
both: replay all moves\n\
-a, --allpats test all patterns\n\
-T, --printboard colored display of dragons\n\
-E, --printeyes colored display of eye spaces\n\
-d, --debug <flags> debugging output (see next item for bits)\n\
--debug-flags print the debug flags for previous item\n\
-w, --worms print worm and dragon data and move reasons\n\
-m, --moyo <level> moyo debugging, show moyo board\n\
--debug-influence <move> print influence map after making a move\n\
-b, --benchmark num benchmarking mode - can be used with -l\n\
-S, --statistics print statistics (for debugging purposes)\n\n\
--profile-patterns print statistics for pattern usage\n\
--showtime print timing diagnostic\n\
-t, --trace verbose tracing\n\
-O, --output-flags <flags> optional output (use with -o)\n\
d: mark dead and critical dragons\n\
v: show values of considered moves\n\
specify either 'd', 'v' or 'dv' (nothing by default)\n\
--showscore print estimated score\n\
-r, --seed number set random number seed\n\
--gtp-dump-commands <file>dump commands received in GTP mode\n\
--gtp-initial-orientation\n\
--orientation\n\
\n\
"
#define USAGE_DEBUG2 "\
Options affecting depth settings and playing strength:\n\
--print-levels shows all this values for levels 12 to 0\n\
\n\
Default values for the default level (%d):\n\
-D, --depth <depth> deep reading cutoff (default %d)\n\
-B, --backfill-depth <depth> deep reading cutoff (default %d)\n\
-F, --fourlib-depth <depth> deep reading cutoff (default %d)\n\
-K, --ko-depth <depth> deep reading cutoff (default %d)\n\
--branch-depth <depth> deep reading cutoff (default %d)\n\
--backfill2-depth <depth> deep reading cutoff (default %d)\n\
--break_chain-depth <depth> deep reading cutoff (default %d)\n\
--superstring-depth <depth> deep reading cutoff (default %d)\n\
--aa-depth <depth> deep reading cutoff (default %d)\n\
--owl-distrust <depth> owl distrust depth (default %d)\n\
--owl-branch <depth> owl branching depth (default %d)\n\
--owl-reading <depth> owl reading depth (default %d)\n\
--owl-node-limit <limit> max nodes for owl reading (default %d)\n\
--semeai-node-limit <limit> max nodes for semeai reading (default %d)\n\
\n\
Options providing detailed reading results etc.:\n\
--decide-string <string> can this string live? (try with -o)\n\
--decide-connection <str/str> can these strings connect? (try with -o)\n\
--decide-dragon <dragon> can this dragon live? (try with -o or -t)\n\
--decide-dragon-data\n\
--decide-owl\n\
--decide-position evaluate all dragons (try with -o or -t)\n\
--decide-eye <string> evaluate the eye\n\
--decide-combination search for combination attack (try with -o)\n\
--decide-oracle\n\
--decide-semeai\n\
--decide-tactical-semeai\n\
--decide-surrounded\n\
--limit-search\n\
\n\
"
/*
* Since the maximum string length is 2048 bytes in VC++ we
* split the help string.
*/
static void
show_help(void)
{
printf(USAGE, DEFAULT_LEVEL);
printf(USAGE1, MIN_BOARD, MAX_BOARD, MAX_HANDICAP);
printf(USAGE2, DEFAULT_MEMORY <= 0 ? reading_cache_default_size() :
(float) DEFAULT_MEMORY);
}
static void
show_debug_help(void)
{
set_depth_values(DEFAULT_LEVEL,0);
printf(USAGE_DEBUG USAGE_DEBUG2,
DEFAULT_LEVEL, depth, backfill_depth, fourlib_depth, ko_depth, branch_depth,
backfill2_depth, break_chain_depth, superstring_depth, aa_depth,
owl_distrust_depth, owl_branch_depth,
owl_reading_depth, owl_node_limit, semeai_node_limit);
}
static void
show_debug_flags(void)
{
printf(DEBUG_FLAGS);
}
static void
show_copyright(void)
{
printf(COPYRIGHT);
}
#ifdef ENABLE_SOCKET_SUPPORT
#if !defined(_WIN32) && !defined(_WIN32_WCE)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define closesocket close
#define init_sockets()
#else /* on Windows */
#include <winsocket.h>
static void
init_sockets(void)
{
WSADATA data;
WORD version = MAKEWORD(1, 1);
if (WSAStartup(version, &data) != NO_ERROR) {
fprintf(stderr, "WSAStartup() failed with error %d\n", WSAGetLastError());
exit(EXIT_FAILURE);
}
}
#endif /* on Windows */
static void
socket_connect_to(const char *host_name, unsigned int port,
FILE **input_file, FILE **output_file)
{
struct sockaddr_in address;
int connection_socket;
struct hostent *host_data;
char **address_pointer;
init_sockets();
if (!host_name)
host_name = "127.0.0.1";
host_data = gethostbyname(host_name);
if (!host_data
|| host_data->h_addrtype != AF_INET
|| host_data->h_length != sizeof address.sin_addr) {
fprintf(stderr, "Failed to resolve host name `%s'\n", host_name);
exit(EXIT_FAILURE);
}
connection_socket = socket(PF_INET, SOCK_STREAM, 0);
if (connection_socket == -1) {
fprintf(stderr, "Unexpected error: failed to create a socket\n");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_port = htons((unsigned short) port);
for (address_pointer = host_data->h_addr_list; *address_pointer;
address_pointer++) {
memcpy(&address.sin_addr, *address_pointer, sizeof address.sin_addr);
if (connect(connection_socket, (struct sockaddr *) &address,
sizeof address) != -1)
break;
}
if (! *address_pointer) {
fprintf(stderr, "Failed to connect to %s:%u\n", host_data->h_name, port);
closesocket(connection_socket);
exit(EXIT_FAILURE);
}
#if !USE_WINDOWS_SOCKET_CLUDGE
*input_file = fdopen(connection_socket, "r");
*output_file = fdopen(dup(connection_socket), "w");
#else /* USE_WINDOWS_SOCKET_CLUDGE */
winsocket_activate(connection_socket);
*input_file = NULL;
*output_file = NULL;
#endif /* USE_WINDOWS_SOCKET_CLUDGE */
}
static void
socket_listen_at(const char *host_name, unsigned int port,
FILE **input_file, FILE **output_file)
{
struct sockaddr_in address;
int listening_socket;
int connection_socket;
init_sockets();
if (host_name) {
struct hostent *host_data;
host_data = gethostbyname(host_name);
if (!host_data
|| host_data->h_addrtype != AF_INET
|| host_data->h_length != sizeof address.sin_addr) {
fprintf(stderr, "Failed to resolve host name `%s'\n", host_name);
exit(EXIT_FAILURE);
}
host_name = host_data->h_name;
memcpy(&address.sin_addr, host_data->h_addr_list[0],
sizeof address.sin_addr);
}
else
address.sin_addr.s_addr = htonl(INADDR_ANY);
listening_socket = socket(PF_INET, SOCK_STREAM, 0);
if (listening_socket == -1) {
fprintf(stderr, "Unexpected error: failed to create a socket\n");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_port = htons((unsigned short) port);
if (verbose) {
if (host_name) {
fprintf(stderr, "Waiting for a connection on %s:%u...\n",
host_name, port);
}
else
fprintf(stderr, "Waiting for a connection on port %u...\n", port);
}
if (bind(listening_socket,
(struct sockaddr *) &address, sizeof address) == -1
|| listen(listening_socket, 0) == -1
|| (connection_socket = accept(listening_socket, NULL, NULL)) == -1) {
if (host_name)
fprintf(stderr, "Failed to listen on %s:%u\n", host_name, port);
else
fprintf(stderr, "Failed to listen on port %u\n", port);
closesocket(listening_socket);
exit(EXIT_FAILURE);
}
closesocket(listening_socket);
#if !USE_WINDOWS_SOCKET_CLUDGE
*input_file = fdopen(connection_socket, "r");
*output_file = fdopen(dup(connection_socket), "w");
#else /* USE_WINDOWS_SOCKET_CLUDGE */
winsocket_activate(connection_socket);
*input_file = NULL;
*output_file = NULL;
#endif /* USE_WINDOWS_SOCKET_CLUDGE */
}
static void
socket_close_connection(FILE *input_file, FILE *output_file)
{
/* When connecting, we close the socket first. */
fclose(input_file);
fclose(output_file);
}
static void
socket_stop_listening(FILE *input_file, FILE *output_file)
{
int buffer[0x1000];
if (verbose)
fprintf(stderr, "Waiting for the client to disconnect...\n");
/* When listening, we wait for the client to disconnect first.
* Otherwise, socket doesn't get released properly.
*/
do
fread(buffer, sizeof buffer, 1, input_file);
while (!feof(input_file));
fclose(input_file);
fclose(output_file);
}
#else /* not ENABLE_SOCKET_SUPPORT */
static void
socket_connect_to(const char *host_name, unsigned int port,
FILE **input_file, FILE **output_file)
{
UNUSED(host_name);
UNUSED(port);
UNUSED(input_file);
UNUSED(output_file);
fprintf(stderr, "GNU Go was compiled without socket support, unable to connect\n");
exit(EXIT_FAILURE);
}
static void
socket_listen_at(const char *host_name, unsigned int port,
FILE **input_file, FILE **output_file)
{
UNUSED(host_name);
UNUSED(port);
UNUSED(input_file);
UNUSED(output_file);
fprintf(stderr, "GNU Go was compiled without socket support, unable to listen\n");
exit(EXIT_FAILURE);
}
static void
socket_close_connection(FILE *input_file, FILE *output_file)
{
UNUSED(input_file);
UNUSED(output_file);
}
static void
socket_stop_listening(FILE *input_file, FILE *output_file)
{
UNUSED(input_file);
UNUSED(output_file);
}
#endif /* not ENABLE_SOCKET_SUPPORT */
/*
* Local Variables:
* tab-width: 8
* c-basic-offset: 2
* End:
*/