/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* 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. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* ================================================================ */
/* Show status for a string, a dragon, etc in an SGF file. */
/* ================================================================ */
* decide_string tries to attack and defend the string at (pos),
* and then writes the number of variations considered in the attack
* and defence to the sgf file.
if (board
[pos
] == EMPTY
) {
fprintf(stderr
, "gnugo: --decide-string called on an empty vertex\n");
sgffile_begindump(&tree
);
/* Prepare pattern matcher and reading code. */
acode
= attack(pos
, &aa
);
gprintf("%1m can be attacked at %1m (%d variations)\n",
pos
, aa
, count_variations
);
gprintf("%1m can be attacked with ko (good) at %1m (%d variations)\n",
pos
, aa
, count_variations
);
gprintf("%1m can be attacked with ko (bad) at %1m (%d variations)\n",
pos
, aa
, count_variations
);
if (debug
& DEBUG_READING_PERFORMANCE
) {
gprintf("Reading shadow: \n");
dcode
= find_defense(pos
, &dd
);
gprintf("%1m can be defended at %1m (%d variations)\n",
pos
, dd
, count_variations
);
gprintf("%1m can be defended with ko (good) at %1m (%d variations)\n",
pos
, dd
, count_variations
);
gprintf("%1m can be defended with ko (bad) at %1m (%d variations)\n",
pos
, dd
, count_variations
);
gprintf("%1m cannot be defended (%d variations)\n",
if (debug
& DEBUG_READING_PERFORMANCE
) {
gprintf("Reading shadow: \n");
gprintf("%1m cannot be attacked (%d variations)\n",
if (debug
& DEBUG_READING_PERFORMANCE
) {
gprintf("Reading shadow: \n");
sgffile_enddump(outfilename
);
* decide_connection tries to connect and disconnect the strings at
* (apos) and (bpos), and then writes the number of variations
* considered in the attack and defence to the sgf file.
decide_connection(int apos
, int bpos
)
if (board
[apos
] == EMPTY
|| board
[bpos
] == EMPTY
) {
fprintf(stderr
, "gnugo: --decide-connection called on an empty vertex\n");
if (board
[apos
] != board
[bpos
]) {
fprintf(stderr
, "gnugo: --decide-connection called for strings of different colors\n");
sgffile_begindump(&tree
);
/* Prepare pattern matcher and reading code. */
result
= string_connect(apos
, bpos
, &move
);
gprintf("%1m and %1m are connected as it stands (%d variations)\n",
apos
, bpos
, count_variations
);
gprintf("%1m and %1m can be connected at %1m (%d variations)\n",
apos
, bpos
, move
, count_variations
);
gprintf("%1m and %1m can be connected with ko (good) at %1m (%d variations)\n",
apos
, bpos
, move
, count_variations
);
gprintf("%1m and %1m can be connected with ko (bad) at %1m (%d variations)\n",
apos
, bpos
, move
, count_variations
);
gprintf("%1m and %1m cannot be connected (%d variations)\n",
apos
, bpos
, count_variations
);
result
= disconnect(apos
, bpos
, &move
);
gprintf("%1m and %1m are disconnected as it stands (%d variations)\n",
apos
, bpos
, count_variations
);
gprintf("%1m and %1m can be disconnected at %1m (%d variations)\n",
apos
, bpos
, move
, count_variations
);
gprintf("%1m and %1m can be disconnected with ko (good) at %1m (%d variations)\n",
apos
, bpos
, move
, count_variations
);
gprintf("%1m and %1m can be disconnected with ko (bad) at %1m (%d variations)\n",
apos
, bpos
, move
, count_variations
);
gprintf("%1m and %1m cannot be disconnected (%d variations)\n",
apos
, bpos
, count_variations
);
sgffile_enddump(outfilename
);
* decide_owl (formerly called decide_dragon) tries to attack and defend
* the dragon at (pos), and then writes the number of variations considered
* in the attack and defence to the sgf file.
if (board
[pos
] == EMPTY
) {
fprintf(stderr
, "gnugo: --decide-dragon called on an empty vertex\n");
/* Prepare pattern matcher and reading code. */
silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL
);
gprintf("finished examine_position\n");
/* We want to see the reading performed, not just a result picked
* from the cache. Thus we clear the cache here.
sgffile_begindump(&tree
);
acode
= owl_attack(pos
, &move
, &result_certain
, &kworm
);
gprintf("%1m is dead as it stands", pos
);
gprintf("%1m can be attacked at %1m (%d variations)",
pos
, move
, count_variations
);
gprintf("%1m can be attacked with ko (good) at %1m (%d variations)",
pos
, move
, count_variations
);
gprintf("%1m can be attacked with ko (bad) at %1m (%d variations)",
pos
, move
, count_variations
);
gprintf("%1m can be attacked with gain (captures %1m) at %1m (%d variations)",
pos
, kworm
, move
, count_variations
);
gprintf("%1m cannot be attacked (%d variations)", pos
, count_variations
);
gprintf(" result uncertain\n");
dcode
= owl_defend(pos
, &move
, &result_certain
, &kworm
);
gprintf("%1m is alive as it stands", pos
);
gprintf("%1m can be defended at %1m (%d variations)",
pos
, move
, count_variations
);
gprintf("%1m can be defended with ko (good) at %1m (%d variations)",
pos
, move
, count_variations
);
gprintf("%1m can be defended with ko (bad) at %1m (%d variations)",
pos
, move
, count_variations
);
gprintf("%1m can be defended with loss (loses %1m) at %1m (%d variations)",
pos
, kworm
, move
, count_variations
);
gprintf("%1m cannot be defended (%d variations)",
gprintf(" result uncertain\n");
sgffile_enddump(outfilename
);
* decide_dragon_data prints the dragon data at (pos).
decide_dragon_data(int pos
)
if (board
[pos
] == EMPTY
) {
fprintf(stderr
, "gnugo: --decide-dragon-data called on an empty vertex\n");
silent_examine_position(FULL_EXAMINE_DRAGONS
);
gprintf("Dragon at %1m:\n", pos
);
report_dragon(stderr
, pos
);
/* Print the result of the semeai code on the semeai at apos/bpos,
* optionally writing an sgf file.
decide_semeai(int apos
, int bpos
)
int resulta
, resultb
, move
, result_certain
;
if (color
== EMPTY
|| board
[bpos
] != OTHER_COLOR(color
)) {
gprintf("gnugo: --decide-semeai called on invalid data\n");
/* Prepare pattern matcher and reading code. */
silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL
);
gprintf("finished examine_position\n");
/* We want to see the reading performed, not just a result picked
* from the cache. Thus we clear the cache here. */
sgffile_begindump(&tree
);
gprintf("Analyzing semeai between %1m and %1m, %C moves first\n",
apos
, bpos
, board
[apos
]);
owl_analyze_semeai(apos
, bpos
, &resulta
, &resultb
, &move
, 1,
gprintf("Semeai defense of %1m: result %s %1m\n",
apos
, result_to_string(resulta
), move
);
gprintf("Semeai attack of %1m: result %s %1m\n",
bpos
, result_to_string(resultb
), move
);
gprintf("%d nodes%s\n\n", count_variations
,
result_certain
? "" : ", uncertain result");
gprintf("Analyzing semeai between %1m and %1m, %C moves first\n",
bpos
, apos
, board
[bpos
]);
owl_analyze_semeai(bpos
, apos
, &resultb
, &resulta
, &move
, 1,
gprintf("Semeai defense of %1m: result %s %1m\n",
bpos
, result_to_string(resultb
), move
);
gprintf("Semeai attack of %1m: result %s %1m\n",
apos
, result_to_string(resulta
), move
);
gprintf("%d nodes%s\n", count_variations
,
result_certain
? "" : ", uncertain result");
sgffile_enddump(outfilename
);
decide_tactical_semeai(int apos
, int bpos
)
int resulta
, resultb
, move
, dummy
;
if (color
== EMPTY
|| board
[bpos
] != OTHER_COLOR(color
)) {
gprintf("gnugo: --decide-semeai called on invalid data\n");
/* Prepare pattern matcher and reading code. */
silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL
);
gprintf("finished examine_position\n");
/* We want to see the reading performed, not just a result picked
* from the cache. Thus we clear the cache here. */
sgffile_begindump(&tree
);
/* FIXME: Calling status_to_string() with a result code as argument
* doesn't make sense. It could be changed to result_to_string() but
* the overall formatting needs change as well.
owl_analyze_semeai(apos
, bpos
, &resulta
, &resultb
, &move
, 0, &dummy
);
gprintf("After %s at %1m, %1m is %s, %1m is %s (%d nodes)\n",
apos
, status_to_string(resulta
),
bpos
, status_to_string(resultb
),
owl_analyze_semeai(bpos
, apos
, &resultb
, &resulta
, &move
, 0, &dummy
);
gprintf("After %s at %1m, %1m is %s, %1m is %s (%d nodes)\n",
apos
, status_to_string(resulta
),
bpos
, status_to_string(resultb
),
sgffile_enddump(outfilename
);
* decide_position tries to attack and defend every dragon with
* dragon.escape<6 and writes the variations to an sgf file.
int acode
= 0, dcode
= 0;
static const char *snames
[] = {"dead", "alive", "critical", "unknown"};
/* Prepare pattern matcher and reading code. */
silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL
);
/* We want to see the reading performed, not just a result picked
* from the cache. Thus we clear the cache here. */
sgffile_begindump(&tree
);
for (pos
= BOARDMIN
; pos
< BOARDMAX
; pos
++) {
|| dragon
[pos
].origin
!= pos
|| DRAGON2(pos
).escape_route
>= 6)
gprintf("\nanalyzing %1m\n", pos
);
gprintf("status=%s, escape=%d\n",
snames
[dragon
[pos
].crude_status
], DRAGON2(pos
).escape_route
);
acode
= owl_attack(pos
, &move
, NULL
, &kworm
);
gprintf("%1m is dead as it stands\n", pos
);
gprintf("%1m can be attacked at %1m (%d variations)\n",
pos
, move
, count_variations
);
gprintf("%1m can be attacked with ko (good) at %1m (%d variations)\n",
pos
, move
, count_variations
);
gprintf("%1m can be attacked with ko (bad) at %1m (%d variations)\n",
pos
, move
, count_variations
);
gprintf("%1m can be attacked with gain (captures %1m) at %1m (%d variations)",
pos
, kworm
, move
, count_variations
);
dcode
= owl_defend(pos
, &move
, NULL
, &kworm
);
gprintf("%1m is alive as it stands\n", pos
);
gprintf("%1m can be defended at %1m (%d variations)\n",
pos
, move
, count_variations
);
gprintf("%1m can be defended with ko (good) at %1m (%d variations)\n",
pos
, move
, count_variations
);
gprintf("%1m can be defended with ko (bad) at %1m (%d variations)\n",
pos
, move
, count_variations
);
gprintf("%1m can be defended with loss (loses %1m) at %1m (%d variations)",
pos
, kworm
, move
, count_variations
);
gprintf("%1m cannot be defended (%d variations)\n",
gprintf("%1m cannot be attacked (%d variations)\n",
gprintf("status of %1m revised to CRITICAL\n", pos
);
gprintf("status of %1m revised to DEAD\n", pos
);
gprintf("status of %1m revised to ALIVE\n", pos
);
sgffile_enddump(outfilename
);
* Evaluates the eyespace at (pos) and prints a report. You can get
* more information by adding -d0x02 to the command line.
silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL
);
color
= black_eye
[pos
].color
;
gprintf("The eye at %1m is not of a single color.\n", pos
);
sgffile_begindump(&tree
);
if (black_eye
[pos
].color
== BLACK
) {
eyepos
= black_eye
[pos
].origin
;
compute_eyes(eyepos
, &value
, &attack_point
, &defense_point
,
gprintf("Black eyespace at %1m: %s\n", eyepos
, eyevalue_to_string(&value
));
if (eye_move_urgency(&value
) > 0) {
gprintf(" vital points: %1m (attack) %1m (defense)\n", attack_point
,
if (white_eye
[pos
].color
== WHITE
) {
eyepos
= white_eye
[pos
].origin
;
compute_eyes(eyepos
, &value
, &attack_point
, &defense_point
,
gprintf("White eyespace at %1m: %s\n", eyepos
, eyevalue_to_string(&value
));
if (eye_move_urgency(&value
) > 0) {
gprintf(" vital points: %1m (attack) %1m (defense)\n", attack_point
,
sgffile_enddump(outfilename
);
* decide_combination tries to find a combination attack for (color) by
decide_combination(int color
)
signed char defense_moves
[BOARDMAX
];
/* Prepare pattern matcher and reading code. */
silent_examine_position(EXAMINE_ALL
);
sgffile_begindump(&tree
);
if (atari_atari(color
, &attack_move
, defense_moves
, verbose
)) {
gprintf("Combination attack for %C at %1m, defense at ", color
,
for (pos
= BOARDMIN
; pos
< BOARDMAX
; pos
++) {
if (ON_BOARD(pos
) && defense_moves
[pos
]) {
gprintf("No Combination attack for %C\n", color
);
sgffile_enddump(outfilename
);
decide_surrounded(int pos
)
if (board
[pos
] == EMPTY
) {
fprintf(stderr
, "location must not be empty!\n");
/* Prepare pattern matcher and reading code. */
silent_examine_position(EXAMINE_ALL
);
surround_status
= compute_surroundings(pos
, NO_MOVE
, 1, NULL
);
if (surround_status
== 1)
gprintf("the dragon at %1m is SURROUNDED!\n", pos
);
else if (surround_status
== 2)
gprintf("the dragon at %1m is WEAKLY SURROUNDED!\n", pos
);
gprintf("the dragon at %1m is not surrounded.\n", pos
);
decide_oracle(Gameinfo
*gameinfo
, char *infilename
, char *untilstring
)
sgffile_begindump(&tree
);
oracle_loadsgf(infilename
, untilstring
);
consult_oracle(gameinfo
->to_move
);
sgffile_enddump(outfilename
);