[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] owl attack moves and semeais
From: |
Arend Bayer |
Subject: |
[gnugo-devel] owl attack moves and semeais |
Date: |
Wed, 7 Apr 2004 21:05:42 +0200 (CEST) |
IMO, we should always apply the following logic when deciding whether a
stone is alive (assuming, for simplicity, it's the opponent to move next):
- if it's tactically capturable => dead
- otherwise, if owl alive => alive
- otherwise, if there is a single semeai that this dragon can win => alive
- otherwise, dead
[Corollary: reading code may never claim successful attack when in fact it
is not, but is allowed to claim no attack when in fact there is; owl may
never claim life when the dragon is in fact dead.]
This patch tries to apply this logic for owl attack moves: If the attacked
dragon is involved in a semeai, we have to check whether it can win the
semeai after the owl attack move has been played. If not, we only award
a strategical attack move reason.
Arend
- more info about semeais in dragon_data2
- double-check owl attack moves against dragons involved in (a) semeai(s)
Index: engine/dragon.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/dragon.c,v
retrieving revision 1.133
diff -u -p -r1.133 dragon.c
--- engine/dragon.c 31 Mar 2004 13:20:58 -0000 1.133
+++ engine/dragon.c 7 Apr 2004 16:58:41 -0000
@@ -760,8 +760,7 @@ initialize_supplementary_dragon_data(voi
dragon2[d].surround_status = 0;
set_eyevalue(&dragon2[d].genus, 0, 0, 0, 0);
- dragon2[d].semeai = 0;
- dragon2[d].semeai_margin_of_safety = -1;
+ dragon2[d].semeais = 0;
dragon2[d].semeai_defense_point = NO_MOVE;
dragon2[d].semeai_attack_point = NO_MOVE;
dragon2[d].owl_attack_point = NO_MOVE;
@@ -1604,7 +1603,7 @@ show_dragons(void)
gprintf("... owl defendable at %1m, code %d\n",
d2->owl_defense_point, d2->owl_defense_code);
}
- if (dd->status == CRITICAL && d2->semeai) {
+ if (dd->status == CRITICAL && d2->semeais) {
if (d2->semeai_defense_point)
gprintf("... semeai defense move at %1m\n", d2->semeai_defense_point);
if (d2->semeai_attack_point)
@@ -2427,15 +2426,15 @@ report_dragon(FILE *outfile, int pos)
d2->owl_second_defense_point);
gfprintf(outfile, "owl_attack_kworm %1m\n", d2->owl_attack_kworm);
gfprintf(outfile, "owl_defense_kworm %1m\n", d2->owl_defense_kworm);
- gfprintf(outfile, "semeai %d\n", d2->semeai);
- gfprintf(outfile, "semeai_margin_of_safety %d\n",
- d2->semeai_margin_of_safety);
+ gfprintf(outfile, "semeais %d\n", d2->semeais);
gfprintf(outfile, "semeai_defense_point %1m\n", d2->semeai_defense_point);
gfprintf(outfile, "semeai_defense_certain %d\n",
d2->semeai_defense_certain);
+ gfprintf(outfile, "semeai_defense_target %1m\n",
+ d2->semeai_defense_target);
gfprintf(outfile, "semeai_attack_point %1m\n", d2->semeai_attack_point);
gfprintf(outfile, "semeai_attack_certain %d\n", d2->semeai_attack_certain);
- gfprintf(outfile, "semeai_target %1m\n", d2->semeai_target);
+ gfprintf(outfile, "semeai_attack_target %1m\n", d2->semeai_attack_target);
gfprintf(outfile, "strings ");
for (ii = BOARDMIN; ii < BOARDMAX; ii++)
if (ON_BOARD(ii)
Index: engine/genmove.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/genmove.c,v
retrieving revision 1.86
diff -u -p -r1.86 genmove.c
--- engine/genmove.c 31 Mar 2004 13:20:58 -0000 1.86
+++ engine/genmove.c 7 Apr 2004 16:58:41 -0000
@@ -293,8 +293,8 @@ void
collect_move_reasons(int color)
{
worm_reasons(color);
- owl_reasons(color);
semeai_move_reasons(color);
+ owl_reasons(color);
break_in_move_reasons(color);
}
@@ -665,7 +665,7 @@ revise_semeai(int color)
for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
if (ON_BOARD(pos)
&& dragon[pos].color == other
- && DRAGON2(pos).semeai
+ && DRAGON2(pos).semeais
&& dragon[pos].status == DEAD) {
found_one = 1;
dragon[pos].status = UNKNOWN;
Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.209
diff -u -p -r1.209 liberty.h
--- engine/liberty.h 11 Feb 2004 12:36:27 -0000 1.209
+++ engine/liberty.h 7 Apr 2004 16:58:41 -0000
@@ -344,13 +344,15 @@ void add_antisuji_move(int pos);
void add_semeai_move(int pos, int dr);
void add_semeai_threat(int pos, int dr);
-void add_owl_attack_move(int pos, int dr, int code);
+void add_owl_attack_move(int pos, int dr, int kworm, int code);
void add_owl_defense_move(int pos, int dr, int code);
void add_owl_attack_threat_move(int pos, int dr, int code);
void add_owl_defense_threat_move(int pos, int dr, int code);
void add_owl_prevent_threat_move(int pos, int dr);
void add_owl_uncertain_defense_move(int pos, int dr);
void add_owl_uncertain_attack_move(int pos, int dr);
+void add_gain_move(int pos, int target1, int target2);
+void add_loss_move(int pos, int target1, int target2);
void add_my_atari_atari_move(int pos, int size);
void add_your_atari_atari_move(int pos, int size);
@@ -362,6 +364,15 @@ void add_strategical_attack_move(int pos
void add_strategical_defense_move(int pos, int dr);
void add_worthwhile_threat_move(int pos);
void add_replacement_move(int from, int to);
+
+/* Parameters to add_either_move and add_all_move */
+#define ATTACK_STRING 1
+#define DEFEND_STRING 2
+void add_either_move(int pos, int reason1, int target1,
+ int reason2, int target2);
+void add_all_move(int pos, int reason1, int target1,
+ int reason2, int target2);
+
int set_minimum_move_value(int pos, float value);
void set_maximum_move_value(int pos, float value);
void set_minimum_territorial_value(int pos, float value);
@@ -378,18 +389,6 @@ void scale_randomness(int pos, float sca
void register_good_attack_threat(int move, int target);
int is_known_good_attack_threat(int move, int target);
-/* Parameters to add_either_move and add_all_move */
-#define ATTACK_STRING 1
-#define DEFEND_STRING 2
-void add_either_move(int pos, int reason1, int target1,
- int reason2, int target2);
-void add_all_move(int pos, int reason1, int target1,
- int reason2, int target2);
-
-void add_gain_move(int pos, int target1, int target2);
-void add_loss_move(int pos, int target1, int target2);
-
-
int get_attack_threats(int pos, int max_strings, int strings[]);
int get_defense_threats(int pos, int max_strings, int strings[]);
void get_saved_worms(int pos, char saved[BOARDMAX]);
@@ -503,6 +502,8 @@ int attack_threat_move_known(int move, i
int defense_threat_move_known(int move, int str);
void worm_reasons(int color);
+int semeai_move_reason_known(int move, int dr);
+
int does_attack(int move, int str);
int does_defend(int move, int str);
int double_atari(int move, int color, float *value,
@@ -875,13 +876,13 @@ struct dragon_data2 {
int surround_status; /* Is it surrounded? */
int surround_size; /* Size of the surrounding area */
- int semeai; /* true if a dragon is part of a semeai */
- int semeai_margin_of_safety; /* if small, the semeai is close */
+ int semeais; /* number of semeais in which the dragon is involved */
int semeai_defense_point;/* Move found by semeai code to rescue dragon */
int semeai_defense_certain;
+ int semeai_defense_target; /* The opponent dragon involved in the semeai */
int semeai_attack_point; /* Move found by semeai code to kill dragon */
int semeai_attack_certain;
- int semeai_target; /* The opponent dragon involved in the semeai */
+ int semeai_attack_target; /* The opponent dragon involved in the semeai */
enum dragon_status owl_threat_status; /* CAN_THREATEN_ATTACK/DEFENSE */
enum dragon_status owl_status; /* (ALIVE, DEAD, UNKNOWN, CRITICAL,
UNCHECKED) */
int owl_attack_point; /* vital point for attack */
Index: engine/move_reasons.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/move_reasons.c,v
retrieving revision 1.123
diff -u -p -r1.123 move_reasons.c
--- engine/move_reasons.c 23 Feb 2004 21:27:01 -0000 1.123
+++ engine/move_reasons.c 7 Apr 2004 16:58:41 -0000
@@ -574,6 +574,12 @@ owl_move_vs_worm_known(int pos, int what
return owl_move_reason_known(pos, dragon[what].origin);
}
+int
+semeai_move_reason_known(int pos, int what)
+{
+ return move_reason_known(pos, SEMEAI_MOVE, what);
+}
+
/* Check whether a worm is inessential */
static int
concerns_inessential_worm(int pos, int what)
@@ -1030,16 +1036,6 @@ add_all_move(int pos, int reason1, int t
void
-add_gain_move(int pos, int target1, int target2)
-{
- int what1 = dragon[target1].origin;
- int what2 = worm[target2].origin;
- int index = find_pair_data(what1, what2);
- ASSERT1(target2 != NO_MOVE, pos);
- add_move_reason(pos, OWL_ATTACK_MOVE_GAIN, index);
-}
-
-void
add_loss_move(int pos, int target1, int target2)
{
int what1 = dragon[target1].origin;
@@ -1142,7 +1138,7 @@ add_strategical_defense_move(int pos, in
* code reports an attack on the dragon (dr).
*/
void
-add_owl_attack_move(int pos, int dr, int code)
+add_owl_attack_move(int pos, int dr, int kworm, int code)
{
dr = dragon[dr].origin;
@@ -1153,6 +1149,10 @@ add_owl_attack_move(int pos, int dr, int
add_move_reason(pos, OWL_ATTACK_MOVE_GOOD_KO, dr);
else if (code == KO_B)
add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dr);
+ else if (code == GAIN) {
+ ASSERT_ON_BOARD1(kworm);
+ add_move_reason(pos, OWL_ATTACK_MOVE_GAIN, find_pair_data(dr, kworm));
+ }
}
/*
Index: engine/move_reasons.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/move_reasons.h,v
retrieving revision 1.39
diff -u -p -r1.39 move_reasons.h
--- engine/move_reasons.h 23 Feb 2004 21:27:01 -0000 1.39
+++ engine/move_reasons.h 7 Apr 2004 16:58:41 -0000
@@ -189,6 +189,7 @@ int defense_move_reason_known(int pos, i
int owl_attack_move_reason_known(int pos, int what);
int owl_defense_move_reason_known(int pos, int what);
int owl_move_reason_known(int pos, int what);
+int semeai_move_reason_known(int pos, int what);
int get_biggest_owl_target(int pos);
int is_antisuji_move(int pos);
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.201
diff -u -p -r1.201 owl.c
--- engine/owl.c 10 Mar 2004 21:34:17 -0000 1.201
+++ engine/owl.c 7 Apr 2004 16:58:41 -0000
@@ -4732,9 +4732,51 @@ goaldump(const char goal[BOARDMAX])
gprintf("\n");
}
+/*
+ * Owl attack moves are ineffective when the dragon can still live in a
+ * semeai. This function tests whether an owl attack move has this problem.
+ * If not, an owl attack move reason is added, otherwise we treat the
+ * move as a strategic attack.
+ */
+static void
+test_owl_attack_move(int pos, int dr, int kworm, int acode)
+{
+ int color = OTHER_COLOR(board[dr]);
+ if (DRAGON2(dr).semeais == 0
+ || DRAGON2(dr).semeai_defense_point == NO_MOVE
+ || (DRAGON2(dr).semeais == 1 && semeai_move_reason_known(pos, dr))
+ || acode == GAIN) {
+ add_owl_attack_move(pos, dr, kworm, acode);
+ DEBUG(DEBUG_OWL, "owl: %1m attacks %1m (%s) at move %d\n",
+ pos, dr, result_to_string(DRAGON2(pos).owl_attack_code),
+ movenum+1);
+ }
+ else {
+ int dr2 = DRAGON2(dr).semeai_defense_target;
+ int semeai_result, certain;
+ int save_verbose = verbose;
+ if (verbose > 0)
+ verbose--;
+ owl_analyze_semeai_after_move(pos, color, dr, dr2, &semeai_result,
+ NULL, NULL, 1, &certain);
+ verbose = save_verbose;
+ if (certain >= DRAGON2(dr).semeai_defense_certain
+ && (semeai_result >= REVERSE_RESULT(acode))) {
+ /* Demote the move reasons. */
+ DEBUG(DEBUG_OWL, "owl: %1m ineffective owl attack on %1m (can live in
semeai with %1m)\n", pos, dr, dr2);
+ add_strategical_attack_move(pos, dr);
+ }
+ else {
+ add_owl_attack_move(pos, dr, kworm, acode);
+ DEBUG(DEBUG_OWL, "owl: %1m attacks %1m (%s) at move %d\n",
+ pos, dr, result_to_string(DRAGON2(pos).owl_attack_code),
+ movenum+1);
+ }
+ }
+}
-/* Add owl reasons. This function should be called once during
- * genmove.
+/* Add owl move reasons. This function should be called once during
+ * genmove. It has to be called after semeai_move_reasons().
*/
void
@@ -4819,27 +4861,10 @@ owl_reasons(int color)
}
}
- /* If owl thinks the dragon is dead but the semeai code has
- * revised the status to critical, then the owl attack point
- * tends to be unreliable. Don't add it in that case.
- *
- * FIXME: Instead of just discarding it, we may want to test
- * whether it also wins the semeai.
- */
- if (DRAGON2(pos).owl_status != CRITICAL)
- continue;
-
- /* If we've reached this far, the attack is okay. */
- if (DRAGON2(pos).owl_attack_code == GAIN) {
- add_gain_move(move, pos, DRAGON2(pos).owl_attack_kworm);
- DEBUG(DEBUG_OWL, "owl: %1m attacks %1m with gain at move %d\n",
- move, pos, movenum+1);
- }
- else {
- add_owl_attack_move(move, pos, DRAGON2(pos).owl_attack_code);
- DEBUG(DEBUG_OWL, "owl: %1m attacks %1m at move %d\n", move, pos,
- movenum+1);
- }
+ /* If we've reached this far, it only remains to check the move
+ * against semeai complications. */
+ test_owl_attack_move(move, pos, DRAGON2(pos).owl_attack_kworm,
+ DRAGON2(pos).owl_attack_code);
}
}
else if (DRAGON2(pos).owl_status == DEAD
@@ -4889,8 +4914,8 @@ owl_reasons(int color)
else if (board[pos] == OTHER_COLOR(color)
&& DRAGON2(pos).owl_attack_point != NO_MOVE
&& DRAGON2(pos).owl_attack_code == GAIN) {
- add_gain_move(DRAGON2(pos).owl_attack_point, pos,
- DRAGON2(pos).owl_attack_kworm);
+ add_owl_attack_move(DRAGON2(pos).owl_attack_point, pos,
+ DRAGON2(pos).owl_attack_kworm, GAIN);
DEBUG(DEBUG_OWL, "owl: %1m attacks %1m with gain at move %d\n",
DRAGON2(pos).owl_attack_point, pos, movenum+1);
}
Index: engine/semeai.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/semeai.c,v
retrieving revision 1.68
diff -u -p -r1.68 semeai.c
--- engine/semeai.c 24 Jan 2004 04:04:56 -0000 1.68
+++ engine/semeai.c 7 Apr 2004 16:58:41 -0000
@@ -169,20 +169,21 @@ semeai()
}
for (d1 = 0; d1 < num_dragons; d1++) {
- int semeai_found = 0;
+ int semeais_found = 0;
int best_defense = 0;
int best_attack = 0;
int defense_move = PASS_MOVE;
int attack_move = PASS_MOVE;
int defense_certain = 0;
int attack_certain = 0;
- int semeai_target = 0;
+ int semeai_attack_target = NO_MOVE;
+ int semeai_defense_target = NO_MOVE;
for (d2 = 0; d2 < num_dragons; d2++) {
if (semeai_results_first[d1][d2] == -1)
continue;
gg_assert(semeai_results_second[d1][d2] != -1);
- semeai_found = 1;
+ semeais_found++;
if (best_defense < semeai_results_first[d1][d2]
|| (best_defense == semeai_results_first[d1][d2]
@@ -190,7 +191,7 @@ semeai()
best_defense = semeai_results_first[d1][d2];
defense_move = semeai_move[d1][d2];
defense_certain = semeai_certain[d1][d2];
- semeai_target = dragon2[d2].origin;
+ semeai_defense_target = dragon2[d2].origin;
}
if (best_attack < semeai_results_second[d2][d1]
|| (best_attack == semeai_results_second[d2][d1]
@@ -198,22 +199,22 @@ semeai()
best_attack = semeai_results_second[d2][d1];
attack_move = semeai_move[d2][d1];
attack_certain = semeai_certain[d2][d1];
- semeai_target = dragon2[d2].origin;
+ semeai_attack_target = dragon2[d2].origin;
}
}
- if (semeai_found) {
- dragon2[d1].semeai = 1;
- if (best_defense != 0 && best_attack != 0) {
+ if (semeais_found) {
+ dragon2[d1].semeais = semeais_found;
+ if (best_defense != 0 && best_attack != 0)
update_status(DRAGON(d1).origin, CRITICAL, CRITICAL);
- dragon2[d1].semeai_defense_point = defense_move;
- dragon2[d1].semeai_defense_certain = defense_certain;
- dragon2[d1].semeai_attack_point = attack_move;
- dragon2[d1].semeai_attack_certain = attack_certain;
- dragon2[d1].semeai_target = semeai_target;
- }
else if (best_attack == 0 && attack_certain)
update_status(DRAGON(d1).origin, ALIVE, ALIVE);
+ dragon2[d1].semeai_defense_point = defense_move;
+ dragon2[d1].semeai_defense_certain = defense_certain;
+ dragon2[d1].semeai_defense_target = semeai_defense_target;
+ dragon2[d1].semeai_attack_point = attack_move;
+ dragon2[d1].semeai_attack_certain = attack_certain;
+ dragon2[d1].semeai_attack_target = semeai_attack_target;
}
}
find_moves_to_make_seki();
@@ -279,10 +280,11 @@ find_moves_to_make_seki()
int d = dragon[str].id;
DEBUG(DEBUG_SEMEAI, "Move to make seki at %1m (%1m vs %1m)\n",
defend_move, str, opponent);
- dragon2[d].semeai = 1;
+ dragon2[d].semeais++;
update_status(str, CRITICAL, CRITICAL);
dragon2[d].semeai_defense_point = defend_move;
dragon2[d].semeai_defense_certain = certain;
+ dragon2[d].semeai_defense_target = opponent;
/* We need to determine a proper attack move (the one that
* prevents seki). Currently we try the defense move first,
@@ -317,7 +319,7 @@ find_moves_to_make_seki()
dragon2[d].semeai_attack_point, opponent, str);
dragon2[d].semeai_attack_certain = certain;
- dragon2[d].semeai_target = opponent;
+ dragon2[d].semeai_attack_target = opponent;
}
}
}
@@ -381,7 +383,7 @@ semeai_move_reasons(int color)
int resulta, resultb, semeai_move, s_result_certain;
for (d = 0; d < number_of_dragons; d++)
- if (dragon2[d].semeai && DRAGON(d).status == CRITICAL) {
+ if (dragon2[d].semeais && DRAGON(d).status == CRITICAL) {
if (DRAGON(d).color == color
&& dragon2[d].semeai_defense_point
&& (dragon2[d].owl_defense_point == NO_MOVE
@@ -392,7 +394,7 @@ semeai_move_reasons(int color)
DEBUG(DEBUG_SEMEAI, "Adding semeai defense move for %1m at %1m\n",
DRAGON(d).origin, dragon2[d].semeai_defense_point);
if (neighbor_of_dragon(dragon2[d].semeai_defense_point,
- dragon2[d].semeai_target)
+ dragon2[d].semeai_defense_target)
&& !neighbor_of_dragon(dragon2[d].semeai_defense_point,
dragon2[d].origin)
&& !is_self_atari(dragon2[d].semeai_defense_point, color)) {
@@ -403,14 +405,14 @@ semeai_move_reasons(int color)
* moves to the move list.
*/
- liberties = findlib(dragon2[d].semeai_target, MAXLIBS, libs);
+ liberties = findlib(dragon2[d].semeai_defense_target, MAXLIBS, libs);
for (r = 0; r < liberties; r++) {
if (!neighbor_of_dragon(libs[r], dragon2[d].origin)
&& !is_self_atari(libs[r], color)
&& libs[r] != dragon2[d].semeai_defense_point) {
owl_analyze_semeai_after_move(libs[r], color,
- dragon2[d].semeai_target,
+ dragon2[d].semeai_defense_target,
dragon2[d].origin,
&resulta, &resultb, &semeai_move,
1, &s_result_certain);
@@ -437,17 +439,17 @@ semeai_move_reasons(int color)
if (neighbor_of_dragon(dragon2[d].semeai_attack_point,
dragon2[d].origin)
&& !neighbor_of_dragon(dragon2[d].semeai_attack_point,
- dragon2[d].semeai_target)
+ dragon2[d].semeai_attack_target)
&& !is_self_atari(dragon2[d].semeai_attack_point, color)) {
liberties = findlib(dragon2[d].origin, MAXLIBS, libs);
for (r = 0; r < liberties; r++) {
- if (!neighbor_of_dragon(libs[r], dragon2[d].semeai_target)
+ if (!neighbor_of_dragon(libs[r], dragon2[d].semeai_attack_target)
&& !is_self_atari(libs[r], color)
&& libs[r] != dragon2[d].semeai_attack_point) {
owl_analyze_semeai_after_move(libs[r], color, dragon2[d].origin,
- dragon2[d].semeai_target,
+ dragon2[d].semeai_attack_target,
&resulta, &resultb, &semeai_move,
1, &s_result_certain);
if (resulta == 0 && resultb == 0) {
Index: engine/value_moves.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
retrieving revision 1.119
diff -u -p -r1.119 value_moves.c
--- engine/value_moves.c 23 Feb 2004 21:27:01 -0000 1.119
+++ engine/value_moves.c 7 Apr 2004 16:58:41 -0000
@@ -354,10 +354,7 @@ do_find_more_owl_attack_and_defense_move
int acode = owl_does_attack(pos, dd, &kworm);
if (acode >= DRAGON2(dd).owl_attack_code) {
- if (acode == GAIN)
- add_gain_move(pos, dd, kworm);
- else
- add_owl_attack_move(pos, dd, acode);
+ add_owl_attack_move(pos, dd, kworm, acode);
if (save_verbose)
gprintf("Move at %1m upgraded to owl attack on %1m (%s).\n",
pos, dd, result_to_string(acode));
@@ -484,10 +481,7 @@ find_more_owl_attack_and_defense_moves(i
int kworm = NO_MOVE;
int acode = owl_does_attack(pos2, pos, &kworm);
if (acode >= DRAGON2(pos).owl_attack_code) {
- if (acode == GAIN)
- add_gain_move(pos2, pos, kworm);
- else
- add_owl_attack_move(pos2, pos, acode);
+ add_owl_attack_move(pos2, pos, kworm, acode);
if (save_verbose)
gprintf("Move at %1m also owl attacks %1m (%s).\n",
pos2, pos, result_to_string(acode));
@@ -696,7 +690,7 @@ induce_secondary_move_reasons(int color)
for (i = 0; i < DRAGON2(aa).neighbors; i++) {
int bb = dragon2[DRAGON2(aa).adjacent[i]].origin;
if (dragon[bb].color == color && worm[bb].attack_codes[0] == 0
- && !DRAGON2(bb).semeai) {
+ && !DRAGON2(bb).semeais) {
add_strategical_defense_move(pos, bb);
do_find_more_owl_attack_and_defense_moves(color, pos,
STRATEGIC_DEFEND_MOVE,
- [gnugo-devel] owl attack moves and semeais,
Arend Bayer <=