/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* 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. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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_GTP_INITIAL_ORIENTATION
,
OPT_DECIDE_TACTICAL_SEMEAI
,
OPT_EXPERIMENTAL_OWL_EXT
,
OPT_EXPERIMENTAL_CONNECTIONS
,
OPT_ALTERNATE_CONNECTIONS
,
OPT_STANDARD_CONNECTIONS
,
/* names of playing modes */
MODE_DECIDE_TACTICAL_SEMEAI
,
/* 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
},
int main(int argc
, char* argv
[])
int mandated_color
= EMPTY
;
enum mode playmode
= MODE_UNKNOWN
;
int replay_color
= EMPTY
;
char* untilstring
= NULL
;
char* scoringmode
= NULL
;
char* gtp_dump_commands_file
= NULL
;
char* gtp_tcp_ip_address
= NULL
;
char* printsgffile
= NULL
;
char* decide_that
= NULL
;
char debuginfluence_move
[4] = "\0";
int benchmark
= 0; /* benchmarking mode (-b) */
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 requested_boardsize
= -1;
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",
benchmark
= atoi(gg_optarg
);
printmoyo
= strtol(gg_optarg
, NULL
, 0); /* allows 0x... */
debug
^= strtol(gg_optarg
, NULL
, 0); /* allows 0x... */
mandated_depth
= atoi(gg_optarg
);
memory
= atof(gg_optarg
);
break; /* floating point number */
mandated_backfill_depth
= atoi(gg_optarg
);
mandated_fourlib_depth
= atoi(gg_optarg
);
mandated_ko_depth
= atoi(gg_optarg
);
if (strlen(gg_optarg
) >= sizeof(outfilename
)) {
fprintf(stderr
, "Too long filename given as value to -o option.\n");
strcpy(outfilename
, gg_optarg
);
output_flags
|= OUTPUT_MARKDRAGONS
;
output_flags
|= OUTPUT_MOVEVALUES
;
if (gtp_tcp_ip_mode
!= 0 || gtpfile
!= NULL
) {
fprintf(stderr
, ("Options `--gtp-input', `--gtp-connect' and `--gtp-listen' "
"are mutually-exclusive\n"));
gtp_tcp_ip_address
= gg_optarg
;
case OPT_GTP_DUMP_COMMANDS
:
gtp_dump_commands_file
= gg_optarg
;
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");
gtp_version
= atoi(gg_optarg
);
"configure option enabled: experimental break-ins\n");
"configure option enabled: cosmic GNU Go \n");
"configure option enabled: large scale captures \n");
if (EXPERIMENTAL_CONNECTIONS
)
"configure option enabled: experimental connections\n");
if (ALTERNATE_CONNECTIONS
)
"configure option enabled: alternate connections\n");
if (EXPERIMENTAL_OWL_EXT
)
"configure option enabled: experimental GAIN/LOSS codes\n");
"configure option enabled: owl threats\n");
"configure option enabled: resignation allowed\n");
"configure option enabled: oracle\n");
"Owl node limit: %d\n", OWL_NODE_LIMIT
);
"Semeai node limit: %d\n", SEMEAI_NODE_LIMIT
);
if (DEFAULT_MEMORY
== -1)
fprintf(stdout
, "Cache size: %d MB (special default value)\n",
fprintf(stdout
, "Cache size: %d MB\n", DEFAULT_MEMORY
);
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");
gameinfo
.handicap
= requested_handicap
;
requested_boardsize
= atoi(gg_optarg
);
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");
case OPT_EXPERIMENTAL_OWL_EXT
:
experimental_owl_ext
= 1;
case OPT_SEMEAI_NODE_LIMIT
:
mandated_semeai_node_limit
= atoi(gg_optarg
);
case OPT_EXPERIMENTAL_CONNECTIONS
:
experimental_connections
= 1;
case OPT_STANDARD_CONNECTIONS
:
experimental_connections
= 0;
case OPT_ALTERNATE_CONNECTIONS
:
alternate_connections
= !alternate_connections
;
experimental_break_in
= 1;
case OPT_WITHOUT_BREAK_IN
:
experimental_break_in
= 0;
case OPT_NO_COSMIC_GNUGO
:
suicide_rule
= FORBIDDEN
;
case OPT_ALLOW_ALL_SUICIDE
:
suicide_rule
= ALL_ALLOWED
;
case OPT_POSITIONAL_SUPERKO
:
case OPT_SITUATIONAL_SUPERKO
:
case OPT_CAPTURE_ALL_DEAD
:
case OPT_PLAY_OUT_AFTERMATH
:
use_monte_carlo_genmove
= 1;
case OPT_MC_GAMES_PER_LEVEL
:
mc_games_per_level
= atoi(gg_optarg
);
if (strlen(gg_optarg
) >= sizeof(mc_pattern_name
)) {
fprintf(stderr
, "Too long name given as value to --mc-patterns option.\n");
strcpy(mc_pattern_name
, gg_optarg
);
case OPT_MC_LIST_PATTERNS
:
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");
strcpy(mc_pattern_filename
, gg_optarg
);
if (strcmp(gg_optarg
, "ascii") == 0)
else if (strcmp(gg_optarg
, "ansi") == 0)
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)
else if (strcmp(gg_optarg
, "gmp") == 0)
else if (strcmp(gg_optarg
, "sgmp") == 0)
fprintf(stderr
, "Invalid mode selection: %s\n", gg_optarg
);
fprintf(stderr
, "Try `gnugo --help' for more information.\n");
if (strlen(gg_optarg
) > 3) {
fprintf(stderr
, "Invalid board coordinate: %s\n", gg_optarg
);
strcpy(decide_this
, gg_optarg
);
playmode
= MODE_DECIDE_STRING
;
case OPT_DECIDE_CONNECTION
:
if (strlen(gg_optarg
) > 7) {
"usage: --decide-connection [first string]/[second string]\n");
strcpy(decide_this
, gg_optarg
);
strtok(decide_this
, "/");
decide_that
= strtok(NULL
, "/");
"usage: --decide-connection [first string]/[second string]\n");
playmode
= MODE_DECIDE_CONNECTION
;
if (strlen(gg_optarg
) > 3) {
fprintf(stderr
, "Invalid board coordinate: %s\n", gg_optarg
);
strcpy(decide_this
, gg_optarg
);
playmode
= MODE_DECIDE_OWL
;
case OPT_DECIDE_DRAGON_DATA
:
if (strlen(gg_optarg
) > 3) {
fprintf(stderr
, "Invalid board coordinate: %s\n", gg_optarg
);
strcpy(decide_this
, gg_optarg
);
playmode
= MODE_DECIDE_DRAGON_DATA
;
if (strlen(gg_optarg
) > 7) {
"usage: --decide-semeai [first dragon]/[second dragon]\n");
strcpy(decide_this
, gg_optarg
);
strtok(decide_this
, "/");
decide_that
= strtok(NULL
, "/");
"usage: --decide-semeai [first dragon]/[second dragon]\n");
playmode
= MODE_DECIDE_SEMEAI
;
case OPT_DECIDE_TACTICAL_SEMEAI
:
if (strlen(gg_optarg
) > 7) {
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
strcpy(decide_this
, gg_optarg
);
strtok(decide_this
, "/");
decide_that
= strtok(NULL
, "/");
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
playmode
= MODE_DECIDE_TACTICAL_SEMEAI
;
case OPT_DECIDE_POSITION
:
playmode
= MODE_DECIDE_POSITION
;
if (strlen(gg_optarg
) > 3) {
fprintf(stderr
, "Invalid board coordinate: %s\n", gg_optarg
);
strcpy(decide_this
, gg_optarg
);
playmode
= MODE_DECIDE_EYE
;
case OPT_DECIDE_COMBINATION
:
playmode
= MODE_DECIDE_COMBINATION
;
case OPT_DECIDE_SURROUNDED
:
if (strlen(gg_optarg
) > 3) {
fprintf(stderr
, "Invalid board coordinate: %s\n", gg_optarg
);
strcpy(decide_this
, gg_optarg
);
playmode
= MODE_DECIDE_SURROUNDED
;
playmode
= MODE_DECIDE_ORACLE
;
mandated_branch_depth
= atoi(gg_optarg
);
case OPT_BACKFILL2_DEPTH
:
mandated_backfill2_depth
= atoi(gg_optarg
);
case OPT_BREAK_CHAIN_DEPTH
:
mandated_break_chain_depth
= atoi(gg_optarg
);
case OPT_SUPERSTRING_DEPTH
:
mandated_superstring_depth
= atoi(gg_optarg
);
mandated_aa_depth
= atoi(gg_optarg
);
mandated_owl_distrust_depth
= atoi(gg_optarg
);
mandated_owl_branch_depth
= atoi(gg_optarg
);
mandated_owl_reading_depth
= atoi(gg_optarg
);
mandated_owl_node_limit
= atoi(gg_optarg
);
set_level(atoi(gg_optarg
));
set_min_level(atoi(gg_optarg
));
set_max_level(atoi(gg_optarg
));
int pos
= string_to_location(board_size
, gg_optarg
);
fprintf(stderr
, "gnugo: use --limit-search <pos>\n");
clock_settings(atoi(gg_optarg
), -1, -1);
clock_settings(-1, atoi(gg_optarg
), -1);
case OPT_CLOCK_BYO_PERIOD
:
clock_settings(-1, -1, atoi(gg_optarg
));
case OPT_DEBUG_INFLUENCE
:
if (strlen(gg_optarg
) > 3) {
fprintf(stderr
, "Invalid board coordinate: %s\n", gg_optarg
);
strcpy(debuginfluence_move
, gg_optarg
);
if (strcmp(gg_optarg
, "white") == 0)
else if (strcmp(gg_optarg
, "black") == 0)
else if (strcmp(gg_optarg
, "both") == 0)
fprintf(stderr
, "Invalid replay color: %s\n", gg_optarg
);
fprintf(stderr
, "Try `gnugo --help' for more information.\n");
if (playmode
== MODE_UNKNOWN
)
playmode
= MODE_LOAD_AND_SCORE
;
playmode
= MODE_LOAD_AND_PRINT
;
printsgffile
= gg_optarg
;
case OPT_PROFILE_PATTERNS
:
prepare_pattern_profiling();
if (strcmp(gg_optarg
, "white") == 0)
else if (strcmp(gg_optarg
, "black") == 0)
fprintf(stderr
, "Invalid color selection: %s\n", gg_optarg
);
fprintf(stderr
, "Try `gnugo --help' for more information.\n");
mirror_stones_limit
= atoi(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)
/* This is the trick to get "--help debug" and "-h debug" to work*/
if (strncmp(argv
[gg_optind
], "debug", 5) == 0)
for (lev
= 12; lev
>= 0; lev
--)
set_depth_values(lev
, 1);
/* NOTE: getopt returns '?' if an illegal option is supplied. */
fprintf(stderr
, "Try `gnugo --help' for more information.\n");
if (requested_boardsize
!= -1) {
if (!check_boardsize(requested_boardsize
, stderr
))
gnugo_clear_board(requested_boardsize
);
/* Start random number seed. */
/* 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
if (strlen(mc_pattern_filename
) > 0) {
if (!mc_load_patterns_from_db(mc_pattern_filename
, NULL
))
} else if (strlen(mc_pattern_name
) > 0) {
if (!choose_mc_patterns(mc_pattern_name
)) {
fprintf(stderr
, "Unknown Monte Carlo pattern database name %s.\n",
fprintf(stderr
, "Use \"--mc-list-patterns\" to list the available databases.\n");
/* Read the infile if there is one. Also play up the position. */
if (!sgftree_readfile(&sgftree
, infilename
)) {
fprintf(stderr
, "Cannot open or parse '%s'\n", infilename
);
if (gameinfo_play_sgftree_rot(&gameinfo
, &sgftree
, untilstring
,
fprintf(stderr
, "Cannot load '%s'\n", infilename
);
/* 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
) {
playmode
= MODE_LOAD_AND_ANALYZE
;
playmode
= (isatty(0)) ? MODE_ANSI
: MODE_GMP
;
if (outfile
&& playmode
!= MODE_LOAD_AND_PRINT
) {
output_check
= fopen(outfile
, "w");
fprintf(stderr
, "Error: could not open '%s' for writing\n", outfile
);
/* not supported by the protocol */
/* EMPTY is valid for play_gmp.c. */
gameinfo
.computer_player
= mandated_color
;
play_gmp(&gameinfo
, playmode
== MODE_SGMP
);
play_solo(&gameinfo
, benchmark
);
fprintf(stderr
, "You must use -l infile with replay mode.\n");
play_replay(&sgftree
, replay_color
);
case MODE_LOAD_AND_ANALYZE
:
if (mandated_color
!= EMPTY
)
gameinfo
.to_move
= mandated_color
;
fprintf(stderr
, "You must use -l infile with load and analyze mode.\n");
oracle_loadsgf(infilename
, untilstring
);
load_and_analyze_sgf_file(&gameinfo
);
case MODE_LOAD_AND_SCORE
:
if (mandated_color
!= EMPTY
)
gameinfo
.to_move
= mandated_color
;
fprintf(stderr
, "gnugo: --score must be used with -l\n");
load_and_score_sgf_file(&sgftree
, &gameinfo
, scoringmode
);
case MODE_LOAD_AND_PRINT
:
fprintf(stderr
, "gnugo: --printsgf must be used with -l\n");
if (mandated_color
!= EMPTY
)
gameinfo
.to_move
= mandated_color
;
sgffile_printsgf(gameinfo
.to_move
, printsgffile
);
case MODE_DECIDE_STRING
: {
fprintf(stderr
, "gnugo: --decide-string must be used with -l\n");
str
= string_to_location(board_size
, decide_this
);
fprintf(stderr
, "gnugo: --decide-string: strange coordinate \n");
case MODE_DECIDE_CONNECTION
: {
fprintf(stderr
, "gnugo: --decide-connection must be used with -l\n");
str1
= string_to_location(board_size
, decide_this
);
"usage: --decide-connection [first string]/[second string]\n");
str2
= string_to_location(board_size
, decide_that
);
"usage: --decide-connection [first string]/[second string]\n");
decide_connection(str1
, str2
);
fprintf(stderr
, "gnugo: --decide-dragon must be used with -l\n");
pos
= string_to_location(board_size
, decide_this
);
fprintf(stderr
, "gnugo: --decide-dragon: strange coordinate \n");
case MODE_DECIDE_DRAGON_DATA
: {
fprintf(stderr
, "gnugo: --decide-dragon-data must be used with -l\n");
pos
= string_to_location(board_size
, decide_this
);
fprintf(stderr
, "gnugo: --decide-dragon-data: strange coordinate \n");
case MODE_DECIDE_SEMEAI
: {
fprintf(stderr
, "gnugo: --decide-semeai must be used with -l\n");
pos1
= string_to_location(board_size
, decide_this
);
"usage: --decide-semeai [first dragon]/[second dragon]\n");
pos2
= string_to_location(board_size
, decide_that
);
"usage: --decide-semeai [first dragon]/[second dragon]\n");
decide_semeai(pos1
, pos2
);
case MODE_DECIDE_TACTICAL_SEMEAI
: {
fprintf(stderr
, "gnugo: --decide-tactical-semeai must be used with -l\n");
pos1
= string_to_location(board_size
, decide_this
);
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
pos2
= string_to_location(board_size
, decide_that
);
"usage: --decide-tactical-semeai [first dragon]/[second dragon]\n");
decide_tactical_semeai(pos1
, pos2
);
case MODE_DECIDE_POSITION
: {
fprintf(stderr
, "gnugo: --decide-position must be used with -l\n");
fprintf(stderr
, "gnugo: --decide-eye must be used with -l\n");
pos
= string_to_location(board_size
, decide_this
);
fprintf(stderr
, "gnugo: --decide-eye: strange coordinate \n");
case MODE_DECIDE_COMBINATION
: {
fprintf(stderr
, "gnugo: --decide-combination must be used with -l\n");
color
= gameinfo
.to_move
;
if (mandated_color
!= EMPTY
)
decide_combination(color
);
case MODE_DECIDE_SURROUNDED
: {
int pos
= string_to_location(board_size
, decide_this
);
"usage: --decide-surrounded [pos]\n");
case MODE_DECIDE_ORACLE
: {
if (mandated_color
!= EMPTY
)
gameinfo
.to_move
= mandated_color
;
fprintf(stderr
, "You must use -l infile with load and analyze mode.\n");
decide_oracle(&gameinfo
, infilename
, untilstring
);
FILE* gtp_input_FILE
= stdin
;
FILE* gtp_output_FILE
= stdout
;
FILE* gtp_dump_commands_FILE
= NULL
;
gtp_input_FILE
= fopen(gtpfile
, "r");
if (gtp_input_FILE
== NULL
) {
fprintf(stderr
, "gnugo: Cannot open file %s\n", gtpfile
);
} else if (gtp_tcp_ip_mode
!= 0) {
unsigned int port
= 65536;
char* port_string
= strchr(gtp_tcp_ip_address
, ':');
const char* host_name
= NULL
;
host_name
= gtp_tcp_ip_address
;
sscanf(port_string
, "%u", &port
);
sscanf(gtp_tcp_ip_address
, "%u", &port
);
fprintf(stderr
, "A valid TCP/IP port number expected\n");
if (gtp_tcp_ip_mode
== OPT_GTP_CONNECT
) {
socket_connect_to(host_name
, port
,
>p_input_FILE
, >p_output_FILE
);
socket_listen_at(host_name
, port
,
>p_input_FILE
, >p_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",
play_gtp(gtp_input_FILE
, gtp_output_FILE
, gtp_dump_commands_FILE
,
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
);
play_twoplayer(&sgftree
, &gameinfo
, infilename
, untilstring
);
if (mandated_color
!= EMPTY
) gameinfo
.computer_player
= OTHER_COLOR(mandated_color
);
oracle_loadsgf(infilename
, untilstring
);
play_ansi(&sgftree
, &gameinfo
, infilename
, untilstring
, true);
if (mandated_color
!= EMPTY
) gameinfo
.computer_player
= OTHER_COLOR(mandated_color
);
oracle_loadsgf(infilename
, untilstring
);
play_ansi(&sgftree
, &gameinfo
, infilename
, untilstring
, false);
if (mandated_color
!= EMPTY
)
gameinfo
.computer_player
= OTHER_COLOR(mandated_color
);
/* Display copyright message in ASCII mode unless --quiet option used. */
oracle_loadsgf(infilename
, untilstring
);
play_ascii(&sgftree
, &gameinfo
, infilename
, untilstring
);
report_pattern_profiling();
sgfFreeNode(sgftree
.root
);
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
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\
--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\
--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\
--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\
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\
--japanese-rules (default)\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\
--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\
--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\
--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\
--standard-connections\n\
--oracle Read the documentation\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\
-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\
"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!*/
--replay <color> replay the moves in a game for color.\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\
Options affecting depth settings and playing strength:\n\
--print-levels shows all this values for levels 12 to 0\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\
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-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-tactical-semeai\n\
* Since the maximum string length is 2048 bytes in VC++ we
printf(USAGE
, DEFAULT_LEVEL
);
printf(USAGE1
, MIN_BOARD
, MAX_BOARD
, MAX_HANDICAP
);
printf(USAGE2
, DEFAULT_MEMORY
<= 0 ? reading_cache_default_size() : (float)DEFAULT_MEMORY
);
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
);
#ifdef ENABLE_SOCKET_SUPPORT
#if !defined(_WIN32) && !defined(_WIN32_WCE)
#define closesocket close
WORD version
= MAKEWORD(1, 1);
if (WSAStartup(version
, &data
) != NO_ERROR
) {
fprintf(stderr
, "WSAStartup() failed with error %d\n", WSAGetLastError());
socket_connect_to(const char* host_name
, unsigned int port
,
FILE** input_file
, FILE** output_file
)
struct sockaddr_in address
;
struct hostent
* host_data
;
host_data
= gethostbyname(host_name
);
|| 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
);
connection_socket
= socket(PF_INET
, SOCK_STREAM
, 0);
if (connection_socket
== -1) {
fprintf(stderr
, "Unexpected error: failed to create a socket\n");
address
.sin_family
= AF_INET
;
address
.sin_port
= htons((unsigned short)port
);
for (address_pointer
= host_data
->h_addr_list
; *address_pointer
;
memcpy(&address
.sin_addr
, *address_pointer
, sizeof address
.sin_addr
);
if (connect(connection_socket
, (struct sockaddr
*)&address
,
fprintf(stderr
, "Failed to connect to %s:%u\n", host_data
->h_name
, port
);
closesocket(connection_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
);
#endif /* USE_WINDOWS_SOCKET_CLUDGE */
socket_listen_at(const char* host_name
, unsigned int port
,
FILE** input_file
, FILE** output_file
)
struct sockaddr_in address
;
struct hostent
* host_data
;
host_data
= gethostbyname(host_name
);
|| 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
);
host_name
= host_data
->h_name
;
memcpy(&address
.sin_addr
, host_data
->h_addr_list
[0],
sizeof address
.sin_addr
);
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");
address
.sin_family
= AF_INET
;
address
.sin_port
= htons((unsigned short)port
);
fprintf(stderr
, "Waiting for a connection on %s:%u...\n",
fprintf(stderr
, "Waiting for a connection on port %u...\n", port
);
if (bind(listening_socket
,
(struct sockaddr
*)&address
, sizeof address
)
|| listen(listening_socket
, 0) == -1
|| (connection_socket
= accept(listening_socket
, NULL
, NULL
)) == -1) {
fprintf(stderr
, "Failed to listen on %s:%u\n", host_name
, port
);
fprintf(stderr
, "Failed to listen on port %u\n", port
);
closesocket(listening_socket
);
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
);
#endif /* USE_WINDOWS_SOCKET_CLUDGE */
socket_close_connection(FILE* input_file
, FILE* output_file
)
/* When connecting, we close the socket first. */
socket_stop_listening(FILE* input_file
, FILE* output_file
)
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.
fread(buffer
, sizeof buffer
, 1, input_file
);
while (!feof(input_file
));
#else /* not ENABLE_SOCKET_SUPPORT */
socket_connect_to(const char* host_name
, unsigned int port
,
FILE** input_file
, FILE** output_file
)
fprintf(stderr
, "GNU Go was compiled without socket support, unable to connect\n");
socket_listen_at(const char* host_name
, unsigned int port
,
FILE** input_file
, FILE** output_file
)
fprintf(stderr
, "GNU Go was compiled without socket support, unable to listen\n");
socket_close_connection(FILE* input_file
, FILE* output_file
)
socket_stop_listening(FILE* input_file
, FILE* output_file
)
#endif /* not ENABLE_SOCKET_SUPPORT */