Add CLI option for two player game, and associated framework to hook it all together.
[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 <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 "random.h"
#include "sgftree.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_ANSI,
MODE_STRICTANSI,
MODE_TWOPLAYER,
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, "ansi") == 0)
playmode = MODE_ANSI;
else if (strcmp(gg_optarg, "strictansi") == 0)
playmode = MODE_STRICTANSI;
else if (strcmp(gg_optarg, "twoplayer") == 0)
playmode = MODE_TWOPLAYER;
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_ANSI : 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_TWOPLAYER:
play_twoplayer(&sgftree, &gameinfo, infilename, untilstring);
break;
case MODE_STRICTANSI:
if (mandated_color != EMPTY) gameinfo.computer_player = OTHER_COLOR(mandated_color);
#if ORACLE
if (metamachine) {
summon_oracle();
oracle_loadsgf(infilename, untilstring);
}
#endif
play_ansi(&sgftree, &gameinfo, infilename, untilstring, true);
break;
case MODE_ANSI:
if (mandated_color != EMPTY) gameinfo.computer_player = OTHER_COLOR(mandated_color);
#if ORACLE
if (metamachine) {
summon_oracle();
oracle_loadsgf(infilename, untilstring);
}
#endif
play_ansi(&sgftree, &gameinfo, infilename, untilstring, false);
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 with SGK modifications", 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 <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.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: 4
* c-basic-offset: 4
* End:
*/