[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] Preparatory patch
From: |
Inge Wallin |
Subject: |
[gnugo-devel] Preparatory patch |
Date: |
Tue, 18 Dec 2001 19:54:16 +0100 (MET) |
Here is a patch that is preparatory for a more advanced handling of
combinations of threats.
I started this change a few days ago, but I hope that it applies
cleanly to the current version in CVS. In particular I hope that it
doesn't clash to heavily with Arends scheme to filter out redundant
move reasons.
Summary:
- remove all _THREAT move reasons
- new member in move_reason: is_threat
- All move reasons except strategic attacks and defends can now be
threats
- handling of threats in move_reasons.c rewritten
- calls to add and remove move reasons changed to new calling
standards everywhere
- some minor cleanup
I have run the regressions and not found any discrepancies. However,
not all trace output is exactly the same yet so I think there is some
subtle differences still. I will continue the work until everything
is exactly the same as before, when seen from the outside.
After that I will tackle find_double_threats() in combinations.c,
making it handle many more threats than just attacks. For those of
you working with readconnect, now might, by the way, be a good time to
implement threats to connect our groups and threats to disconnect the
opponent groups.
After *that* it might be time to make a more general atari_atari. At
that time the name atari_atari might not be descriptive anymore. The
alternative name threat_chain comes to mind.
-Inge
diff -ur gnugo-sync/engine/combination.c gnugo-iw/engine/combination.c
--- gnugo-sync/engine/combination.c Fri Dec 14 21:40:47 2001
+++ gnugo-iw/engine/combination.c Sun Dec 16 13:43:51 2001
@@ -78,7 +78,7 @@
if (save_verbose)
gprintf("Combination attack for %C with size %d found at %1m\n",
color, aa_val, attack_point);
- add_my_atari_atari_move(attack_point, aa_val);
+ add_my_atari_atari_move(attack_point, aa_val, FALSE);
}
aa_val = atari_atari(other, &attack_point, &defense_point, save_verbose);
@@ -86,7 +86,7 @@
if (save_verbose)
gprintf("Combination attack for %C with size %d found at %1m, defense at
%1m\n",
other, aa_val, attack_point, defense_point);
- add_your_atari_atari_move(defense_point, aa_val);
+ add_your_atari_atari_move(defense_point, aa_val, FALSE);
}
verbose = save_verbose;
@@ -143,17 +143,17 @@
|| board[a_threatened_groups[l]] == EMPTY) {
if (!attack(ii, NULL)) {
add_attack_either_move(ii, a_threatened_groups[k],
- a_threatened_groups[l]);
- remove_attack_threat_move(ii, a_threatened_groups[k]);
- remove_attack_threat_move(ii, a_threatened_groups[l]);
+ a_threatened_groups[l], FALSE);
+ remove_attack_move(ii, a_threatened_groups[k], TRUE);
+ remove_attack_move(ii, a_threatened_groups[l], TRUE);
}
}
else if (!defend_both(a_threatened_groups[k],
a_threatened_groups[l])) {
add_attack_either_move(ii, a_threatened_groups[k],
- a_threatened_groups[l]);
- remove_attack_threat_move(ii, a_threatened_groups[k]);
- remove_attack_threat_move(ii, a_threatened_groups[l]);
+ a_threatened_groups[l], FALSE);
+ remove_attack_move(ii, a_threatened_groups[k], TRUE);
+ remove_attack_move(ii, a_threatened_groups[l], TRUE);
}
}
popgo();
@@ -177,7 +177,7 @@
/* ================================================================ */
-/* atari_atari(color, *move) looks for a series of ataris on
+/* atari_atari(color, *move) looks for a series of threats on
* strings of the other color culminating in the capture of
* a string which is thought to be invulnerable by the reading
* code. Such a move can be missed since it may be that each
diff -ur gnugo-sync/engine/dragon.c gnugo-iw/engine/dragon.c
--- gnugo-sync/engine/dragon.c Thu Dec 13 20:23:17 2001
+++ gnugo-iw/engine/dragon.c Sat Dec 15 01:33:13 2001
@@ -33,10 +33,10 @@
static void find_neighbor_dragons(void);
static void add_adjacent_dragons(int a, int b);
static void add_adjacent_dragon(int a, int b);
-static int dragon_invincible(int pos);
-static int compute_dragon_status(int pos);
+static int dragon_invincible(int pos);
+static int compute_dragon_status(int pos);
static void dragon_eye(int pos, struct eye_data[BOARDMAX]);
-static int compute_escape(int pos, int dragon_status_known);
+static int compute_escape(int pos, int dragon_status_known);
static void compute_surrounding_moyo_sizes(int opposite);
static int dragon2_initialized;
@@ -374,8 +374,10 @@
/* Compute the surrounding moyo sizes. */
for (d = 0; d < number_of_dragons; d++)
dragon2[d].moyo = 2 * BOARDMAX;
+
/* Set moyo sizes according to initial_influence. */
compute_surrounding_moyo_sizes(0);
+
/* Set moyo sizes according to initial_opposite_influence if
* this yields smaller results.
*/
@@ -1115,7 +1117,7 @@
/*
- * dragon_eye(pos, eye_data) is invoked with (pos) the origin of an
+ * dragon_eye(origin, eye_data) is invoked with (origin) the origin of an
* eyespace. It unites all the worms adjacent to non-marginal points
* of the eyespace into a single dragon.. In addition to marginal eye
* space points, amalgamation is inhibited for points with the
@@ -1125,7 +1127,7 @@
*/
static void
-dragon_eye(int pos, struct eye_data eye[BOARDMAX])
+dragon_eye(int origin, struct eye_data eye[BOARDMAX])
{
int i, j;
int ii;
@@ -1134,14 +1136,14 @@
int k;
/* don't amalgamate across ikken tobi */
- if (eye[pos].esize == 3 && eye[pos].msize > 1)
+ if (eye[origin].esize == 3 && eye[origin].msize > 1)
return;
- DEBUG(DEBUG_DRAGONS, "amalgamate dragons around %1m\n", pos);
- if (eye[pos].color == BLACK_BORDER)
+ DEBUG(DEBUG_DRAGONS, "amalgamate dragons around %1m\n", origin);
+ if (eye[origin].color == BLACK_BORDER)
color = BLACK;
else {
- gg_assert(eye[pos].color == WHITE_BORDER);
+ gg_assert(eye[origin].color == WHITE_BORDER);
color = WHITE;
}
@@ -1149,7 +1151,7 @@
for (j = 0; j < board_size; j++) {
ii = POS(i, j);
- if (eye[ii].origin == pos
+ if (eye[ii].origin == origin
&& !eye[ii].marginal
&& !(eye[ii].type & INHIBIT_CONNECTION)) {
for (k = 0; k < 4; k++) {
@@ -1173,7 +1175,7 @@
if ((eye[ii].color == BLACK_BORDER
|| eye[ii].color == WHITE_BORDER)
- && eye[ii].origin == pos)
+ && eye[ii].origin == origin)
{
eye[ii].dragon = dr;
}
diff -ur gnugo-sync/engine/gnugo.h gnugo-iw/engine/gnugo.h
--- gnugo-sync/engine/gnugo.h Thu Dec 13 20:23:17 2001
+++ gnugo-iw/engine/gnugo.h Sun Dec 16 13:32:52 2001
@@ -50,6 +50,11 @@
/* ================================================================ */
+/* truth values */
+#define FALSE 0
+#define TRUE 1
+
+
/* Colors */
#define EMPTY 0
#define WHITE 1
diff -ur gnugo-sync/engine/liberty.h gnugo-iw/engine/liberty.h
--- gnugo-sync/engine/liberty.h Fri Dec 14 21:40:47 2001
+++ gnugo-iw/engine/liberty.h Sun Dec 16 13:55:28 2001
@@ -308,30 +308,25 @@
void clear_move_reasons(void);
void add_lunch(int eater, int food);
void remove_lunch(int eater, int food);
-void add_attack_move(int pos, int ww, int code);
-void add_defense_move(int pos, int ww, int code);
-void add_attack_threat_move(int pos, int ww, int code);
-void remove_attack_threat_move(int pos, int ww);
-void add_defense_threat_move(int pos, int ww, int code);
+void add_attack_move(int pos, int ww, int code, int is_threat);
+void remove_attack_move(int pos, int ww, int is_threat);
+void add_defense_move(int pos, int ww, int code, int is_threat);
void add_connection_move(int pos, int dr1, int dr2);
void add_cut_move(int pos, int dr1, int dr2);
void add_antisuji_move(int pos);
-void add_semeai_move(int pos, int dr);
-void add_semeai_threat(int pos, int dr);
+void add_semeai_move(int pos, int dr, int is_threat);
-void add_owl_attack_move(int pos, int dr, 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_attack_move(int pos, int dr, int code, int is_threat);
+void add_owl_defense_move(int pos, int dr, int code, int is_threat);
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_my_atari_atari_move(int pos, int size);
-void add_your_atari_atari_move(int pos, int size);
-void add_vital_eye_move(int pos, int eyespace, int color);
-void add_attack_either_move(int pos, int str1, int str2);
-void add_defend_both_move(int pos, int str1, int str2);
+void add_my_atari_atari_move(int pos, int size, int is_threat);
+void add_your_atari_atari_move(int pos, int size, int is_threat);
+void add_vital_eye_move(int pos, int eyespace, int color, int is_threat);
+void add_attack_either_move(int pos, int str1, int str2, int is_threat);
+void add_defend_both_move(int pos, int str1, int str2, int is_threat);
void add_block_territory_move(int pos);
void add_expand_territory_move(int pos);
void add_expand_moyo_move(int pos);
diff -ur gnugo-sync/engine/move_reasons.c gnugo-iw/engine/move_reasons.c
--- gnugo-sync/engine/move_reasons.c Tue Dec 11 03:40:47 2001
+++ gnugo-iw/engine/move_reasons.c Sun Dec 16 23:30:26 2001
@@ -313,18 +313,22 @@
* Find a reason in the list of reasons. If necessary, add a new entry.
*/
static int
-find_reason(int type, int what)
+find_reason(int type, int what, int is_threat)
{
int k;
for (k = 0; k < next_reason; k++)
- if ((move_reasons[k].type == type) && (move_reasons[k].what == what))
+ if ((move_reasons[k].type == type)
+ && (move_reasons[k].what == what)
+ && (move_reasons[k].is_threat == is_threat))
return k;
/* Add a new entry. */
gg_assert(next_reason < MAX_MOVE_REASONS);
move_reasons[next_reason].type = type;
move_reasons[next_reason].what = what;
+ move_reasons[next_reason].is_threat = is_threat;
next_reason++;
+
return next_reason - 1;
}
@@ -333,7 +337,7 @@
* table is full.
*/
static void
-add_move_reason(int pos, int type, int what)
+add_move_reason(int pos, int type, int what, int is_threat)
{
int k;
@@ -347,12 +351,13 @@
if (r < 0)
break;
if (move_reasons[r].type == type
- && move_reasons[r].what == what)
+ && move_reasons[r].what == what
+ && move_reasons[r].is_threat == is_threat)
return; /* Reason already listed. */
}
/* Reason not found, add it if there is place left. */
if (k<MAX_REASONS)
- move[pos].reason[k] = find_reason(type, what);
+ move[pos].reason[k] = find_reason(type, what, is_threat);
}
/*
@@ -360,7 +365,7 @@
* wasn't there.
*/
static void
-remove_move_reason(int pos, int type, int what)
+remove_move_reason(int pos, int type, int what, int is_threat)
{
int k;
int n = -1; /* Position of the move reason to be deleted. */
@@ -371,7 +376,8 @@
if (r < 0)
break;
if (move_reasons[r].type == type
- && move_reasons[r].what == what)
+ && move_reasons[r].what == what
+ && move_reasons[r].is_threat == is_threat)
n = k;
}
@@ -389,10 +395,10 @@
/*
* Check whether a move reason already is recorded for a move.
- * A negative value for 'what' means only match 'type'.
+ * A negative value for 'what' means only match 'type' and 'is_threat'.
*/
static int
-move_reason_known(int pos, int type, int what)
+move_reason_known(int pos, int type, int what, int is_threat)
{
int k;
int r;
@@ -404,7 +410,8 @@
break;
if (move_reasons[r].type == type
&& (what < 0
- || move_reasons[r].what == what))
+ || move_reasons[r].what == what)
+ && move_reasons[r].is_threat == is_threat)
return 1;
}
return 0;
@@ -415,11 +422,11 @@
* A negative value for 'what' means only match 'type'.
*/
static int
-attack_move_reason_known(int pos, int what)
+attack_move_reason_known(int pos, int what, int is_threat)
{
- return (move_reason_known(pos, ATTACK_MOVE, what)
- || move_reason_known(pos, ATTACK_MOVE_GOOD_KO, what)
- || move_reason_known(pos, ATTACK_MOVE_BAD_KO, what));
+ return (move_reason_known(pos, ATTACK_MOVE, what, is_threat)
+ || move_reason_known(pos, ATTACK_MOVE_GOOD_KO, what, is_threat)
+ || move_reason_known(pos, ATTACK_MOVE_BAD_KO, what, is_threat));
}
/*
@@ -427,11 +434,11 @@
* A negative value for 'what' means only match 'type'.
*/
static int
-defense_move_reason_known(int pos, int what)
+defense_move_reason_known(int pos, int what, int is_threat)
{
- return (move_reason_known(pos, DEFEND_MOVE, what)
- || move_reason_known(pos, DEFEND_MOVE_GOOD_KO, what)
- || move_reason_known(pos, DEFEND_MOVE_BAD_KO, what));
+ return (move_reason_known(pos, DEFEND_MOVE, what, is_threat)
+ || move_reason_known(pos, DEFEND_MOVE_GOOD_KO, what, is_threat)
+ || move_reason_known(pos, DEFEND_MOVE_BAD_KO, what, is_threat));
}
/*
@@ -439,11 +446,11 @@
* A negative value for 'what' means only match 'type'.
*/
static int
-owl_attack_move_reason_known(int pos, int what)
+owl_attack_move_reason_known(int pos, int what, int is_threat)
{
- return (move_reason_known(pos, OWL_ATTACK_MOVE, what)
- || move_reason_known(pos, OWL_ATTACK_MOVE_GOOD_KO, what)
- || move_reason_known(pos, OWL_ATTACK_MOVE_BAD_KO, what));
+ return (move_reason_known(pos, OWL_ATTACK_MOVE, what, is_threat)
+ || move_reason_known(pos, OWL_ATTACK_MOVE_GOOD_KO, what, is_threat)
+ || move_reason_known(pos, OWL_ATTACK_MOVE_BAD_KO, what, is_threat));
}
/*
@@ -451,11 +458,11 @@
* A negative value for 'what' means only match 'type'.
*/
static int
-owl_defense_move_reason_known(int pos, int what)
+owl_defense_move_reason_known(int pos, int what, int is_threat)
{
- return (move_reason_known(pos, OWL_DEFEND_MOVE, what)
- || move_reason_known(pos, OWL_DEFEND_MOVE_GOOD_KO, what)
- || move_reason_known(pos, OWL_DEFEND_MOVE_BAD_KO, what));
+ return (move_reason_known(pos, OWL_DEFEND_MOVE, what, is_threat)
+ || move_reason_known(pos, OWL_DEFEND_MOVE_GOOD_KO, what, is_threat)
+ || move_reason_known(pos, OWL_DEFEND_MOVE_BAD_KO, what, is_threat));
}
/*
@@ -463,58 +470,26 @@
* at (ww).
*/
void
-add_attack_move(int pos, int ww, int code)
-{
- int worm_number = find_worm(worm[ww].origin);
-
- ASSERT_ON_BOARD1(ww);
- if (code == WIN)
- add_move_reason(pos, ATTACK_MOVE, worm_number);
- else if (code == KO_A)
- add_move_reason(pos, ATTACK_MOVE_GOOD_KO, worm_number);
- else if (code == KO_B)
- add_move_reason(pos, ATTACK_MOVE_BAD_KO, worm_number);
-}
-
-/*
- * Add to the reasons for the move at (pos) that it defends the worm
- * at (ww).
- */
-void
-add_defense_move(int pos, int ww, int code)
+add_attack_move(int pos, int ww, int code, int is_threat)
{
int worm_number = find_worm(worm[ww].origin);
ASSERT_ON_BOARD1(ww);
if (code == WIN)
- add_move_reason(pos, DEFEND_MOVE, worm_number);
+ add_move_reason(pos, ATTACK_MOVE, worm_number, is_threat);
else if (code == KO_A)
- add_move_reason(pos, DEFEND_MOVE_GOOD_KO, worm_number);
+ add_move_reason(pos, ATTACK_MOVE_GOOD_KO, worm_number, is_threat);
else if (code == KO_B)
- add_move_reason(pos, DEFEND_MOVE_BAD_KO, worm_number);
-}
-
-/*
- * Add to the reasons for the move at (pos) that it threatens to
- * attack the worm at (ww).
- */
-void
-add_attack_threat_move(int pos, int ww, int code)
-{
- int worm_number = find_worm(worm[ww].origin);
- UNUSED(code);
-
- ASSERT_ON_BOARD1(ww);
- add_move_reason(pos, ATTACK_THREAT_MOVE, worm_number);
+ add_move_reason(pos, ATTACK_MOVE_BAD_KO, worm_number, is_threat);
}
void
-remove_attack_threat_move(int pos, int ww)
+remove_attack_move(int pos, int ww, int is_threat)
{
int worm_number = find_worm(worm[ww].origin);
ASSERT_ON_BOARD1(ww);
- remove_move_reason(pos, ATTACK_THREAT_MOVE, worm_number);
+ remove_move_reason(pos, ATTACK_MOVE, worm_number, is_threat);
}
/*
@@ -522,13 +497,17 @@
* at (ww).
*/
void
-add_defense_threat_move(int pos, int ww, int code)
+add_defense_move(int pos, int ww, int code, int is_threat)
{
int worm_number = find_worm(worm[ww].origin);
- UNUSED(code);
ASSERT_ON_BOARD1(ww);
- add_move_reason(pos, DEFEND_THREAT_MOVE, worm_number);
+ if (code == WIN)
+ add_move_reason(pos, DEFEND_MOVE, worm_number, is_threat);
+ else if (code == KO_A)
+ add_move_reason(pos, DEFEND_MOVE_GOOD_KO, worm_number, is_threat);
+ else if (code == KO_B)
+ add_move_reason(pos, DEFEND_MOVE_BAD_KO, worm_number, is_threat);
}
@@ -547,7 +526,8 @@
if (r < 0)
break;
- if (move_reasons[r].type == ATTACK_THREAT_MOVE)
+ if (move_reasons[r].type == ATTACK_MOVE
+ && move_reasons[r].is_threat == TRUE)
strings[num_strings++] = worms[move_reasons[r].what];
if (num_strings == max_strings)
@@ -571,7 +551,8 @@
if (r < 0)
break;
- if (move_reasons[r].type == DEFEND_THREAT_MOVE)
+ if (move_reasons[r].type == DEFEND_MOVE
+ && move_reasons[r].is_threat == TRUE)
strings[num_strings++] = worms[move_reasons[r].what];
if (num_strings == max_strings)
@@ -599,7 +580,7 @@
if (dragon1 == dragon2)
return;
connection = find_connection(dragon1, dragon2);
- add_move_reason(pos, CONNECT_MOVE, connection);
+ add_move_reason(pos, CONNECT_MOVE, connection, FALSE);
}
/*
@@ -629,7 +610,7 @@
|| (worm[dr2].attack_codes[0] != 0 && worm[dr2].defend_codes[0] == 0))
return;
- add_move_reason(pos, CUT_MOVE, connection);
+ add_move_reason(pos, CUT_MOVE, connection, FALSE);
}
/*
@@ -640,7 +621,7 @@
void
add_antisuji_move(int pos)
{
- add_move_reason(pos, ANTISUJI_MOVE, 0);
+ add_move_reason(pos, ANTISUJI_MOVE, 0, FALSE);
}
/*
@@ -652,28 +633,12 @@
* must be added for the two dragons.
*/
void
-add_semeai_move(int pos, int dr)
-{
- int the_dragon = find_dragon(dragon[dr].origin);
-
- ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, SEMEAI_MOVE, the_dragon);
-}
-
-/*
- * Add to the reasons for the move at (pos) that given two
- * moves in a row a move here can win the dragon (friendly or
- * not) at (dr) in semeai. Such a move can be used as a
- * ko threat, and it is also given some value due to uncertainty
- * in the counting of liberties.
- */
-void
-add_semeai_threat(int pos, int dr)
+add_semeai_move(int pos, int dr, int is_threat)
{
int the_dragon = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, SEMEAI_THREAT, the_dragon);
+ add_move_reason(pos, SEMEAI_MOVE, the_dragon, is_threat);
}
/*
@@ -681,7 +646,7 @@
* point for the eye space at (eyespace) of color.
*/
void
-add_vital_eye_move(int pos, int eyespace, int color)
+add_vital_eye_move(int pos, int eyespace, int color, int is_threat)
{
int eye;
@@ -690,7 +655,7 @@
eye = find_eye(white_eye[eyespace].origin, color);
else
eye = find_eye(black_eye[eyespace].origin, color);
- add_move_reason(pos, VITAL_EYE_MOVE, eye);
+ add_move_reason(pos, VITAL_EYE_MOVE, eye, is_threat);
}
/*
@@ -702,7 +667,7 @@
* distinct and that neither is undefendable.
*/
void
-add_attack_either_move(int pos, int str1, int str2)
+add_attack_either_move(int pos, int str1, int str2, int is_threat)
{
int worm1 = find_worm(worm[str1].origin);
int worm2 = find_worm(worm[str2].origin);
@@ -720,7 +685,7 @@
return;
worm_pair = find_worm_pair(worm1, worm2);
- add_move_reason(pos, ATTACK_EITHER_MOVE, worm_pair);
+ add_move_reason(pos, ATTACK_EITHER_MOVE, worm_pair, is_threat);
}
/*
@@ -729,7 +694,7 @@
* reason is only used for defense of own stones.
*/
void
-add_defend_both_move(int pos, int str1, int str2)
+add_defend_both_move(int pos, int str1, int str2, int is_threat)
{
int worm1 = find_worm(worm[str1].origin);
int worm2 = find_worm(worm[str2].origin);
@@ -737,7 +702,7 @@
ASSERT_ON_BOARD1(str1);
ASSERT_ON_BOARD1(str2);
- add_move_reason(pos, DEFEND_BOTH_MOVE, worm_pair);
+ add_move_reason(pos, DEFEND_BOTH_MOVE, worm_pair, is_threat);
}
/*
@@ -747,7 +712,7 @@
void
add_block_territory_move(int pos)
{
- add_move_reason(pos, BLOCK_TERRITORY_MOVE, 0);
+ add_move_reason(pos, BLOCK_TERRITORY_MOVE, 0, FALSE);
}
/*
@@ -757,7 +722,7 @@
void
add_expand_territory_move(int pos)
{
- add_move_reason(pos, EXPAND_TERRITORY_MOVE, 0);
+ add_move_reason(pos, EXPAND_TERRITORY_MOVE, 0, FALSE);
}
/*
@@ -767,7 +732,7 @@
void
add_expand_moyo_move(int pos)
{
- add_move_reason(pos, EXPAND_MOYO_MOVE, 0);
+ add_move_reason(pos, EXPAND_MOYO_MOVE, 0, FALSE);
}
/*
@@ -845,7 +810,7 @@
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dragon1);
+ add_move_reason(pos, STRATEGIC_ATTACK_MOVE, dragon1, FALSE);
}
/*
@@ -858,7 +823,7 @@
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dragon1);
+ add_move_reason(pos, STRATEGIC_DEFEND_MOVE, dragon1, FALSE);
}
/*
@@ -866,17 +831,17 @@
* 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 code, int is_threat)
{
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
if (code == WIN)
- add_move_reason(pos, OWL_ATTACK_MOVE, dragon1);
+ add_move_reason(pos, OWL_ATTACK_MOVE, dragon1, is_threat);
else if (code == KO_A)
- add_move_reason(pos, OWL_ATTACK_MOVE_GOOD_KO, dragon1);
+ add_move_reason(pos, OWL_ATTACK_MOVE_GOOD_KO, dragon1, is_threat);
else if (code == KO_B)
- add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dragon1);
+ add_move_reason(pos, OWL_ATTACK_MOVE_BAD_KO, dragon1, is_threat);
}
/*
@@ -884,34 +849,17 @@
* code reports a defense of the dragon (dr).
*/
void
-add_owl_defense_move(int pos, int dr, int code)
+add_owl_defense_move(int pos, int dr, int code, int is_threat)
{
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
if (code == WIN)
- add_move_reason(pos, OWL_DEFEND_MOVE, dragon1);
+ add_move_reason(pos, OWL_DEFEND_MOVE, dragon1, is_threat);
else if (code == KO_A)
- add_move_reason(pos, OWL_DEFEND_MOVE_GOOD_KO, dragon1);
+ add_move_reason(pos, OWL_DEFEND_MOVE_GOOD_KO, dragon1, is_threat);
else if (code == KO_B)
- add_move_reason(pos, OWL_DEFEND_MOVE_BAD_KO, dragon1);
-}
-
-/*
- * Add to the reasons for the move at (pos) that the owl
- * code reports a move threatening to attack the dragon enemy (dr).
- * That is, if the attacker is given two moves in a row, (pos)
- * can be the first move.
- */
-void
-add_owl_attack_threat_move(int pos, int dr, int code)
-{
- int dragon1 = find_dragon(dragon[dr].origin);
- UNUSED(code);
-
- ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, OWL_ATTACK_THREAT, dragon1);
- add_worthwhile_threat_move(pos);
+ add_move_reason(pos, OWL_DEFEND_MOVE_BAD_KO, dragon1, is_threat);
}
/* The owl code found the friendly dragon alive, or the unfriendly dragon
@@ -925,7 +873,7 @@
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, UNCERTAIN_OWL_DEFENSE, dragon1);
+ add_move_reason(pos, UNCERTAIN_OWL_DEFENSE, dragon1, FALSE);
}
/* The owl code found the opponent dragon alive, or the friendly
@@ -939,24 +887,7 @@
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, UNCERTAIN_OWL_ATTACK, dragon1);
-}
-
-/*
- * Add to the reasons for the move at (pos) that the owl
- * code reports a move threatening to rescue the dragon (dr).
- * That is, if the defender is given two moves in a row, (pos)
- * can be the first move.
- */
-void
-add_owl_defense_threat_move(int pos, int dr, int code)
-{
- int dragon1 = find_dragon(dragon[dr].origin);
- UNUSED(code);
-
- ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, OWL_DEFENSE_THREAT, dragon1);
- add_worthwhile_threat_move(pos);
+ add_move_reason(pos, UNCERTAIN_OWL_ATTACK, dragon1, FALSE);
}
/* Add to the reasons for the move at (ti, tj) that it captures
@@ -965,9 +896,9 @@
* permitted per move.
*/
void
-add_my_atari_atari_move(int pos, int size)
+add_my_atari_atari_move(int pos, int size, int is_threat)
{
- add_move_reason(pos, MY_ATARI_ATARI_MOVE, size);
+ add_move_reason(pos, MY_ATARI_ATARI_MOVE, size, is_threat);
}
/* Add to the reasons for the move at (ti, tj) that an opponent move there
@@ -976,9 +907,9 @@
* by the defender is safe---presumably it defends the threat.
* Only one such move reason is permitted per move. */
void
-add_your_atari_atari_move(int pos, int size)
+add_your_atari_atari_move(int pos, int size, int is_threat)
{
- add_move_reason(pos, YOUR_ATARI_ATARI_MOVE, size);
+ add_move_reason(pos, YOUR_ATARI_ATARI_MOVE, size, is_threat);
}
@@ -996,7 +927,7 @@
int dragon1 = find_dragon(dragon[dr].origin);
ASSERT_ON_BOARD1(dr);
- add_move_reason(pos, OWL_PREVENT_THREAT, dragon1);
+ add_move_reason(pos, OWL_PREVENT_THREAT, dragon1, FALSE);
}
/*
@@ -1131,9 +1062,10 @@
break;
what = move_reasons[r].what;
- if (move_reasons[r].type == DEFEND_MOVE
- || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
- || move_reasons[r].type == DEFEND_MOVE_BAD_KO) {
+ if ((move_reasons[r].type == DEFEND_MOVE
+ || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
+ || move_reasons[r].type == DEFEND_MOVE_BAD_KO)
+ && move_reasons[r].is_threat == FALSE) {
int origin = worm[worms[what]].origin;
int ii;
for (ii = BOARDMIN; ii < BOARDMAX; ii++)
@@ -1158,9 +1090,10 @@
break;
what = move_reasons[r].what;
- if (move_reasons[r].type == OWL_DEFEND_MOVE
- || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO
- || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO) {
+ if ((move_reasons[r].type == OWL_DEFEND_MOVE
+ || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO
+ || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO)
+ && move_reasons[r].is_threat == FALSE) {
int origin = dragon[dragons[what]].origin;
int ii;
for (ii = BOARDMIN; ii < BOARDMAX; ii++)
@@ -1223,16 +1156,17 @@
if (r < 0)
break;
what = move_reasons[r].what;
- if (move_reasons[r].type == ATTACK_MOVE
- || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
- || move_reasons[r].type == ATTACK_MOVE_BAD_KO
- || move_reasons[r].type == DEFEND_MOVE
- || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
- || move_reasons[r].type == DEFEND_MOVE_BAD_KO
- || move_reasons[r].type == CONNECT_MOVE
- || move_reasons[r].type == CUT_MOVE
- || move_reasons[r].type == ATTACK_EITHER_MOVE
- || move_reasons[r].type == DEFEND_BOTH_MOVE)
+ if ((move_reasons[r].type == ATTACK_MOVE
+ || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
+ || move_reasons[r].type == ATTACK_MOVE_BAD_KO
+ || move_reasons[r].type == DEFEND_MOVE
+ || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
+ || move_reasons[r].type == DEFEND_MOVE_BAD_KO
+ || move_reasons[r].type == CONNECT_MOVE
+ || move_reasons[r].type == CUT_MOVE
+ || move_reasons[r].type == ATTACK_EITHER_MOVE
+ || move_reasons[r].type == DEFEND_BOTH_MOVE)
+ && move_reasons[r].is_threat == FALSE)
break;
}
@@ -1250,21 +1184,21 @@
* unless we already know the move works as defense move.
*/
if (board[aa] == color
- && !defense_move_reason_known(ii, unstable_worms[k]))
+ && !defense_move_reason_known(ii, unstable_worms[k], FALSE))
if (!attack(aa, NULL)) {
if (!cursor_at_start_of_line)
TRACE("\n");
TRACE("%ofound extra point of defense of %1m at %1m\n",
aa, ii);
cursor_at_start_of_line = 1;
- add_defense_move(ii, aa, WIN);
+ add_defense_move(ii, aa, WIN, FALSE);
}
/* string of opponent color, see if there still is a defense,
* unless we already know the move works as attack move.
*/
if (board[aa] == other
- && !attack_move_reason_known(ii, unstable_worms[k]))
+ && !attack_move_reason_known(ii, unstable_worms[k], FALSE))
if (!find_defense(aa, NULL)) {
/* Maybe find_defense() doesn't find the defense. Try to
* defend with the stored defense move.
@@ -1285,7 +1219,7 @@
TRACE("%ofound extra point of attack of %1m at %1m\n",
aa, ii);
cursor_at_start_of_line = 1;
- add_attack_move(ii, aa, WIN);
+ add_attack_move(ii, aa, WIN, FALSE);
}
}
}
@@ -1334,14 +1268,16 @@
if (move_reasons[r].type == STRATEGIC_ATTACK_MOVE
|| move_reasons[r].type == STRATEGIC_DEFEND_MOVE)
dd1 = dragons[what];
- else if (move_reasons[r].type == ATTACK_MOVE
- || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
- || move_reasons[r].type == ATTACK_MOVE_BAD_KO
- || move_reasons[r].type == DEFEND_MOVE
- || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
- || move_reasons[r].type == DEFEND_MOVE_BAD_KO)
+ else if ((move_reasons[r].type == ATTACK_MOVE
+ || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
+ || move_reasons[r].type == ATTACK_MOVE_BAD_KO
+ || move_reasons[r].type == DEFEND_MOVE
+ || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
+ || move_reasons[r].type == DEFEND_MOVE_BAD_KO)
+ && move_reasons[r].is_threat == FALSE)
dd1 = worms[what];
- else if (move_reasons[r].type == VITAL_EYE_MOVE) {
+ else if (move_reasons[r].type == VITAL_EYE_MOVE
+ && move_reasons[r].is_threat == FALSE) {
int ee = eyes[move_reasons[r].what];
int ecolor = eyecolor[move_reasons[r].what];
@@ -1353,7 +1289,8 @@
if (dd1 == NO_MOVE) /* Maybe we should assert this not to happen. */
continue;
}
- else if (move_reasons[r].type == CONNECT_MOVE) {
+ else if (move_reasons[r].type == CONNECT_MOVE
+ && move_reasons[r].is_threat == FALSE) {
int dragon1 = conn_dragon1[move_reasons[r].what];
int dragon2 = conn_dragon2[move_reasons[r].what];
dd1 = dragons[dragon1];
@@ -1379,30 +1316,32 @@
continue;
if ((move_reasons[r].type == STRATEGIC_ATTACK_MOVE
- || move_reasons[r].type == ATTACK_MOVE
- || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
- || move_reasons[r].type == ATTACK_MOVE_BAD_KO
- || (move_reasons[r].type == VITAL_EYE_MOVE
- && board[dd] == OTHER_COLOR(color)))
- && !owl_attack_move_reason_known(pos, find_dragon(dd))) {
+ || ((move_reasons[r].type == ATTACK_MOVE
+ || move_reasons[r].type == ATTACK_MOVE_GOOD_KO
+ || move_reasons[r].type == ATTACK_MOVE_BAD_KO
+ || (move_reasons[r].type == VITAL_EYE_MOVE
+ && board[dd] == OTHER_COLOR(color)))
+ && move_reasons[r].is_threat == FALSE))
+ && !owl_attack_move_reason_known(pos, find_dragon(dd), FALSE)) {
int acode = owl_does_attack(pos, dd);
if (acode >= dragon[dd].owl_attack_code) {
- add_owl_attack_move(pos, dd, acode);
+ add_owl_attack_move(pos, dd, acode, FALSE);
TRACE("Move at %1m owl attacks %1m, result %d.\n", pos, dd, acode);
}
}
if ((move_reasons[r].type == STRATEGIC_DEFEND_MOVE
- || move_reasons[r].type == CONNECT_MOVE
- || move_reasons[r].type == DEFEND_MOVE
- || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
- || move_reasons[r].type == DEFEND_MOVE_BAD_KO
- || (move_reasons[r].type == VITAL_EYE_MOVE
- && board[dd] == color))
- && !owl_defense_move_reason_known(pos, find_dragon(dd))) {
+ || ((move_reasons[r].type == CONNECT_MOVE
+ || move_reasons[r].type == DEFEND_MOVE
+ || move_reasons[r].type == DEFEND_MOVE_GOOD_KO
+ || move_reasons[r].type == DEFEND_MOVE_BAD_KO
+ || (move_reasons[r].type == VITAL_EYE_MOVE
+ && board[dd] == color))
+ && move_reasons[r].is_threat == FALSE))
+ && !owl_defense_move_reason_known(pos, find_dragon(dd), FALSE)) {
int dcode = owl_does_defend(pos, dd);
if (dcode >= dragon[dd].owl_defense_code) {
- add_owl_defense_move(pos, dd, dcode);
+ add_owl_defense_move(pos, dd, dcode, FALSE);
TRACE("Move at %1m owl defends %1m, result %d.\n", pos, dd, dcode);
}
}
@@ -1426,12 +1365,13 @@
if (r < 0)
break;
- if (move_reasons[r].type == OWL_ATTACK_MOVE
- || move_reasons[r].type == OWL_ATTACK_MOVE_GOOD_KO
- || move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO
- || move_reasons[r].type == OWL_DEFEND_MOVE
- || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO
- || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO) {
+ if ((move_reasons[r].type == OWL_ATTACK_MOVE
+ || move_reasons[r].type == OWL_ATTACK_MOVE_GOOD_KO
+ || move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO
+ || move_reasons[r].type == OWL_DEFEND_MOVE
+ || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO
+ || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO)
+ && move_reasons[r].is_threat == FALSE) {
dd = dragons[move_reasons[r].what];
if (are_neighbor_dragons(dd, pos)) {
worth_trying = 1;
@@ -1442,16 +1382,16 @@
if (worth_trying) {
if (board[pos] == color
- && !owl_defense_move_reason_known(pos2, find_dragon(pos))) {
+ && !owl_defense_move_reason_known(pos2, find_dragon(pos), FALSE))
{
int dcode = owl_does_defend(pos2, pos);
if (dcode >= dragon[pos].owl_defense_code)
- add_owl_defense_move(pos2, pos, dcode);
+ add_owl_defense_move(pos2, pos, dcode, FALSE);
}
else if (board[pos] != color
- && !owl_attack_move_reason_known(pos2, find_dragon(pos))) {
+ && !owl_attack_move_reason_known(pos2, find_dragon(pos),
FALSE)) {
int acode = owl_does_attack(pos2, pos);
if (acode >= dragon[pos].owl_attack_code)
- add_owl_attack_move(pos2, pos, acode);
+ add_owl_attack_move(pos2, pos, acode, FALSE);
}
}
}
@@ -1463,7 +1403,7 @@
/*
* It's often bad to run away with a worm that is in a strategically
* weak position. This function gives heuristics for determining
- * whether a move at (ti, tj) to defend the worm (ai, aj) is
+ * whether a move at (tt) to defend the worm (aa) is
* strategically sound.
*
* FIXME: This function has played out its role. Should be eliminated.
@@ -1494,7 +1434,6 @@
* few liberties. Thus a defense move isn't necessarily a cut
* move. This problem can be solved when we have a working
* connection reader.
- *
*/
static void
@@ -1519,8 +1458,9 @@
if (r < 0)
break;
- if (move_reasons[r].type == ATTACK_MOVE
- || move_reasons[r].type == DEFEND_MOVE) {
+ if ((move_reasons[r].type == ATTACK_MOVE
+ || move_reasons[r].type == DEFEND_MOVE)
+ && move_reasons[r].is_threat == FALSE) {
aa = worms[move_reasons[r].what];
if (worm[aa].defend_codes[0] == 0)
@@ -1536,6 +1476,7 @@
* reason.
*/
if (move_reasons[r].type == DEFEND_MOVE
+ && move_reasons[r].is_threat == FALSE
&& !strategically_sound_defense(aa, pos))
continue;
@@ -1575,7 +1516,8 @@
continue;
if (dd != ee) {
- if (move_reasons[r].type == ATTACK_MOVE) {
+ if (move_reasons[r].type == ATTACK_MOVE
+ && move_reasons[r].is_threat == FALSE) {
/* Exclude the case when (aa) is dead and both
* (dd) and (ee) are strongly alive or
* better. Then the move would only be losing
@@ -1636,7 +1578,8 @@
continue;
if (dd != ee) {
- if (move_reasons[r].type == ATTACK_MOVE) {
+ if (move_reasons[r].type == ATTACK_MOVE
+ && move_reasons[r].is_threat == FALSE) {
/* Exclude the case when (aa) is dead and both
* (dd) and (ee) are strongly alive or
* better. Then the move would only be losing
@@ -1664,7 +1607,8 @@
}
}
}
- else if (move_reasons[r].type == OWL_ATTACK_MOVE) {
+ else if (move_reasons[r].type == OWL_ATTACK_MOVE
+ && move_reasons[r].is_threat == FALSE) {
aa = dragons[move_reasons[r].what];
for (i = 0; i < DRAGON2(aa).neighbors; i++) {
int bb = dragon2[DRAGON2(aa).adjacent[i]].origin;
@@ -1700,11 +1644,17 @@
int r = move[pos].reason[k];
int type;
int what;
+ int is_threat;
if (r == -1)
break;
type = move_reasons[r].type;
what = move_reasons[r].what;
+ is_threat = move_reasons[r].is_threat;
+
+ /* FIXME: Check if threats should really just be dismissed
+ * (the old code did).
+ */
switch (type) {
case CUT_MOVE:
/* We don't trust cut moves, unless some other move reason
@@ -1718,6 +1668,8 @@
case OWL_DEFEND_MOVE_GOOD_KO:
case OWL_DEFEND_MOVE_BAD_KO:
case MY_ATARI_ATARI_MOVE:
+ if (is_threat)
+ break;
tactical_safety = 1;
safety = 1;
break;
@@ -1732,7 +1684,9 @@
case OWL_ATTACK_MOVE:
case OWL_ATTACK_MOVE_GOOD_KO:
case OWL_ATTACK_MOVE_BAD_KO:
- {
+ if (is_threat)
+ break;
+ else {
int aa = NO_MOVE;
int bb = NO_MOVE;
int size;
@@ -1866,9 +1820,14 @@
case DEFEND_MOVE:
case DEFEND_MOVE_GOOD_KO:
case DEFEND_MOVE_BAD_KO:
- {
+ if (is_threat)
+ break;
+ else {
int aa = worms[what];
+ if (is_threat)
+ break;
+
if (dragon[aa].matcher_status == ALIVE)
/* It would be better if this never happened, but it does
* sometimes. The owl reading can be very slow then.
@@ -1879,13 +1838,11 @@
safety = 1;
break;
}
-
- case ATTACK_THREAT_MOVE:
- case DEFEND_THREAT_MOVE:
- break;
case CONNECT_MOVE:
- {
+ if (is_threat)
+ break;
+ else {
int dragon1 = conn_dragon1[move_reasons[r].what];
int dragon2 = conn_dragon2[move_reasons[r].what];
int aa = dragons[dragon1];
@@ -1945,51 +1902,49 @@
pos = POS(m, n);
for (k = 0; k < MAX_REASONS; k++) {
-
+ int is_threat;
+
int r = move[pos].reason[k];
if (r < 0)
break;
- switch(move_reasons[r].type) {
+ is_threat = move_reasons[r].is_threat;
+ switch (move_reasons[r].type) {
case ATTACK_MOVE:
aa = worms[move_reasons[r].what];
- gprintf("Move at %1m attacks %1m%s\n", pos, aa,
- (worm[aa].defend_codes[0] == 0) ? " (defenseless)" : "");
+ gprintf("Move at %1m %s %1m%s\n", pos,
+ is_threat ? "threatens to attack" : "attacks", aa,
+ (!is_threat && worm[aa].defend_codes[0] == 0) ? "
(defenseless)" : "");
break;
case ATTACK_MOVE_GOOD_KO:
aa = worms[move_reasons[r].what];
- gprintf("Move at %1m attacks %1m%s with good ko\n", pos, aa,
- (worm[aa].defend_codes[0] == 0) ? " (defenseless)" : "");
+ gprintf("Move at %1m %s %1m%s with good ko\n", pos,
+ is_threat ? "threatens to attack" : "attacks", aa,
+ (!is_threat && worm[aa].defend_codes[0] == 0) ? "
(defenseless)" : "");
break;
case ATTACK_MOVE_BAD_KO:
aa = worms[move_reasons[r].what];
- gprintf("Move at %1m attacks %1m%s with bad ko\n", pos, aa,
- (worm[aa].defend_codes[0] == 0) ? " (defenseless)" : "");
+ gprintf("Move at %1m %s %1m%s with bad ko\n", pos,
+ is_threat ? "threatens to attack" : "attacks", aa,
+ (!is_threat && worm[aa].defend_codes[0] == 0) ? "
(defenseless)" : "");
break;
case DEFEND_MOVE:
aa = worms[move_reasons[r].what];
- gprintf("Move at %1m defends %1m\n", pos, aa);
+ gprintf("Move at %1m %s %1m\n", pos,
+ is_threat ? "threatens to defend" : "defends", aa);
break;
case DEFEND_MOVE_GOOD_KO:
aa = worms[move_reasons[r].what];
- gprintf("Move at %1m defends %1m with good ko\n", pos, aa);
+ gprintf("Move at %1m %s %1m with good ko\n", pos,
+ is_threat ? "threatens to defend" : "defends", aa);
break;
case DEFEND_MOVE_BAD_KO:
aa = worms[move_reasons[r].what];
- gprintf("Move at %1m defends %1m with bad ko\n", pos, aa);
+ gprintf("Move at %1m %s %1m with bad ko\n", pos,
+ is_threat ? "threatens to defend" : "defends", aa);
break;
- case ATTACK_THREAT_MOVE:
- case DEFEND_THREAT_MOVE:
- aa = worms[move_reasons[r].what];
-
- if (move_reasons[r].type == ATTACK_THREAT_MOVE)
- gprintf("Move at %1m threatens to attack %1m\n", pos, aa);
- else if (move_reasons[r].type == DEFEND_THREAT_MOVE)
- gprintf("Move at %1m threatens to defend %1m\n", pos, aa);
- break;
-
case UNCERTAIN_OWL_DEFENSE:
aa = dragons[move_reasons[r].what];
if (board[aa] == color)
@@ -2018,12 +1973,8 @@
case SEMEAI_MOVE:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m wins semeai for %1m\n", pos, aa);
- break;
-
- case SEMEAI_THREAT:
- aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m threatens to win semeai for %1m\n", pos, aa);
+ gprintf("Move at %1m %s semeai for %1m\n", pos,
+ is_threat ? "threatens to win" : "wins", aa);
break;
case VITAL_EYE_MOVE:
@@ -2052,38 +2003,34 @@
case OWL_ATTACK_MOVE:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-attacks %1m\n", pos, aa);
+ gprintf("Move at %1m %s %1m\n", pos,
+ is_threat ? "threatens to owl-attack" : "owl-attacks", aa);
break;
case OWL_ATTACK_MOVE_GOOD_KO:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-attacks %1m with good ko\n", pos, aa);
+ gprintf("Move at %1m %s %1m with good ko\n", pos,
+ is_threat ? "threatens to owl-attack" : "owl-attacks", aa);
break;
case OWL_ATTACK_MOVE_BAD_KO:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-attacks %1m with bad ko\n", pos, aa);
+ gprintf("Move at %1m %s %1m with bad ko\n", pos,
+ is_threat ? "threatens to owl-attack" : "owl-attacks", aa);
break;
case OWL_DEFEND_MOVE:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-defends %1m\n", pos, aa);
+ gprintf("Move at %1m %s %1m\n", pos,
+ is_threat ? "threatens to owl-defend" : "owl-defends", aa);
break;
case OWL_DEFEND_MOVE_GOOD_KO:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-defends %1m with good ko\n", pos, aa);
+ gprintf("Move at %1m %s %1m with good ko\n", pos,
+ is_threat ? "threatens to owl-defend" : "owl-defends", aa);
break;
case OWL_DEFEND_MOVE_BAD_KO:
aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-defends %1m with bad ko\n", pos, aa);
- break;
-
- case OWL_ATTACK_THREAT:
- aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-threatens to attack %1m\n", pos, aa);
- break;
-
- case OWL_DEFENSE_THREAT:
- aa = dragons[move_reasons[r].what];
- gprintf("Move at %1m owl-threatens to defend %1m\n", pos, aa);
+ gprintf("Move at %1m %s %1m with bad ko\n", pos,
+ is_threat ? "threatens to owl-defend" : "owl-defends", aa);
break;
case OWL_PREVENT_THREAT:
@@ -2419,7 +2366,103 @@
case ATTACK_MOVE_GOOD_KO:
case ATTACK_MOVE_BAD_KO:
aa = worms[move_reasons[r].what];
+
+ if (move_reasons[r].is_threat) {
+ /* Threat on our stones. */
+ if (board[aa] == color)
+ break;
+
+ if (dragon[aa].matcher_status == DEAD) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threatens to capture %1m (dead)\n", pos, aa);
+ break;
+ }
+
+ if (DRAGON2(aa).safety == INESSENTIAL || worm[aa].inessential) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threatens to capture %1m (inessential)\n",
+ pos, aa);
+ break;
+ }
+
+ /* If the move also owl attacks the same stones, there is
+ * no use to threaten tactically.
+ */
+ if (owl_attack_move_reason_known(pos, find_dragon(aa), FALSE)) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threaten to capture %1m (owl attacked as well)\n",
+ pos, aa);
+ break;
+ }
+ /* The followup value of a move threatening to attack (aa)
+ * is twice its effective size, with adjustments. If the
+ * worm has an adjacent (friendly) dead dragon we add its
+ * value. On the other hand if it has an adjacent critical
+ * worm, and if (pos) does not defend that worm, we subtract
+ * the value of the worm, since (aa) may be defended by
+ * attacking that worm. We make at most one adjustment
+ * of each type.
+ *
+ * FIXME: It might be possible that parts of the dragon
+ * can be cut in the process of capturing the (aa)
+ * worm. In that case, not the entire size of the
+ * adjacent dead dragon should be counted as a positive
+ * adjustment. However, it seems difficult to do this
+ * analysis, and in most cases it won't apply, so we
+ * leave it as it is for now.
+ *
+ * FIXME: The same analysis should be applied to
+ * DEFEND_THREAT_MOVE,
+ * ATTACK_EITHER_MOVE, DEFEND_BOTH_MOVE. It should be
+ * broken out as separate functions and dealt with in
+ * a structured manner.
+ */
+
+ if (trymove(pos, color, "estimate_territorial_value",
+ NO_MOVE, EMPTY, NO_MOVE)) {
+ int adjs[MAXCHAIN];
+ float adjusted_value = 2 * worm[aa].effective_size;
+ float adjustment_up = 0.0;
+ float adjustment_down = 0.0;
+ int s;
+ int num_adj;
+
+ /* In rare cases it may happen that the trymove() above
+ * actually removed the string at aa.
+ */
+ if (board[aa] == EMPTY)
+ num_adj = 0;
+ else
+ num_adj = chainlinks(aa, adjs);
+
+ for (s = 0; s < num_adj; s++) {
+ int adj = adjs[s];
+
+ if (same_string(pos, adj))
+ continue;
+ if (dragon[adj].color == color
+ && dragon[adj].matcher_status == DEAD
+ && 2*dragon[adj].effective_size > adjustment_up)
+ adjustment_up = 2*dragon[adj].effective_size;
+ if (dragon[adj].color == color
+ && attack(adj, NULL)
+ && 2*worm[adj].effective_size > adjustment_down)
+ adjustment_down = 2*worm[adj].effective_size;
+ }
+ adjusted_value += adjustment_up;
+ adjusted_value -= adjustment_down;
+ if (adjusted_value > 0.0) {
+ add_followup_value(pos, adjusted_value);
+ TRACE(" %1m: %f (followup) - threatens to capture %1m\n",
+ pos, adjusted_value, aa);
+ }
+ popgo();
+ }
+ break;
+ }
+
+ /* Not a threat if we reach this point. */
gg_assert(board[aa] != color);
/* Defenseless stone. */
@@ -2460,7 +2503,7 @@
/* If the move also owl attacks the same stones, count points
* for that move reason instead.
*/
- if (owl_attack_move_reason_known(pos, find_dragon(aa))) {
+ if (owl_attack_move_reason_known(pos, find_dragon(aa), FALSE)) {
DEBUG(DEBUG_MOVE_REASONS,
" %1m: 0.0 - attack on %1m (owl attacked as well)\n", pos, aa);
break;
@@ -2493,6 +2536,44 @@
case DEFEND_MOVE_BAD_KO:
aa = worms[move_reasons[r].what];
+ if (move_reasons[r].is_threat) {
+
+ /* Threat on our stones. FIXME: Bug? Should be other_color? */
+ if (board[aa] == color)
+ break;
+
+ if (dragon[aa].matcher_status == DEAD) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threatens to defend %1m (dead)\n", pos, aa);
+ break;
+ }
+
+ /* If the stones are inessential, there is no value in saving them. */
+ if (worm[aa].inessential || DRAGON2(aa).safety == INESSENTIAL) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threaten to defend %1m (inessential)\n", pos, aa);
+ break;
+ }
+
+ /* If the move also owl defends the same stones, there is no
+ * use in saving them
+ */
+ if (owl_defense_move_reason_known(pos, find_dragon(aa), FALSE)) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threaten to defend of %1m (owl defended as
well)\n",
+ pos, aa);
+ break;
+ }
+
+ add_followup_value(pos, 2 * worm[aa].effective_size);
+
+ TRACE(" %1m: %f (followup) - threatens to defend %1m\n",
+ pos, 2 * worm[aa].effective_size, aa);
+
+ break;
+ }
+
+ /* Not a threat if we reach this point. */
gg_assert(board[aa] == color);
/*
@@ -2530,7 +2611,7 @@
/* If the move also owl defends the same stones, count points
* for that move reason instead.
*/
- if (owl_defense_move_reason_known(pos, find_dragon(aa))) {
+ if (owl_defense_move_reason_known(pos, find_dragon(aa), FALSE)) {
DEBUG(DEBUG_MOVE_REASONS,
" %1m: 0.0 - defense of %1m (owl defended as well)\n", pos, aa);
break;
@@ -2558,139 +2639,6 @@
does_block = 1;
break;
- case ATTACK_THREAT_MOVE:
- aa = worms[move_reasons[r].what];
-
- /* Threat on our stones. */
- if (board[aa] == color)
- break;
-
- if (dragon[aa].matcher_status == DEAD) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threatens to capture %1m (dead)\n", pos, aa);
- break;
- }
-
- if (DRAGON2(aa).safety == INESSENTIAL || worm[aa].inessential) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threatens to capture %1m (inessential)\n",
- pos, aa);
- break;
- }
-
- /* If the move also owl attacks the same stones, there is
- * no use to threaten tactically.
- */
- if (owl_attack_move_reason_known(pos, find_dragon(aa))) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threaten to capture %1m (owl attacked as well)\n",
- pos, aa);
- break;
- }
-
- /* The followup value of a move threatening to attack (aa)
- * is twice its effective size, with adjustments. If the
- * worm has an adjacent (friendly) dead dragon we add its
- * value. On the other hand if it has an adjacent critical
- * worm, and if (pos) does not defend that worm, we subtract
- * the value of the worm, since (aa) may be defended by
- * attacking that worm. We make at most one adjustment
- * of each type.
- *
- * FIXME: It might be possible that parts of the dragon
- * can be cut in the process of capturing the (aa)
- * worm. In that case, not the entire size of the
- * adjacent dead dragon should be counted as a positive
- * adjustment. However, it seems difficult to do this
- * analysis, and in most cases it won't apply, so we
- * leave it as it is for now.
- *
- * FIXME: The same analysis should be applied to
- * DEFEND_THREAT_MOVE,
- * ATTACK_EITHER_MOVE, DEFEND_BOTH_MOVE. It should be
- * broken out as separate functions and dealt with in
- * a structured manner.
- */
-
- if (trymove(pos, color, "estimate_territorial_value",
- NO_MOVE, EMPTY, NO_MOVE)) {
- int adjs[MAXCHAIN];
- float adjusted_value = 2 * worm[aa].effective_size;
- float adjustment_up = 0.0;
- float adjustment_down = 0.0;
- int s;
- int num_adj;
-
- /* In rare cases it may happen that the trymove() above
- * actually removed the string at aa.
- */
- if (board[aa] == EMPTY)
- num_adj = 0;
- else
- num_adj = chainlinks(aa, adjs);
-
- for (s = 0; s < num_adj; s++) {
- int adj = adjs[s];
-
- if (same_string(pos, adj))
- continue;
- if (dragon[adj].color == color
- && dragon[adj].matcher_status == DEAD
- && 2*dragon[adj].effective_size > adjustment_up)
- adjustment_up = 2*dragon[adj].effective_size;
- if (dragon[adj].color == color
- && attack(adj, NULL)
- && 2*worm[adj].effective_size > adjustment_down)
- adjustment_down = 2*worm[adj].effective_size;
- }
- adjusted_value += adjustment_up;
- adjusted_value -= adjustment_down;
- if (adjusted_value > 0.0) {
- add_followup_value(pos, adjusted_value);
- TRACE(" %1m: %f (followup) - threatens to capture %1m\n",
- pos, adjusted_value, aa);
- }
- popgo();
- }
- break;
-
- case DEFEND_THREAT_MOVE:
- aa = worms[move_reasons[r].what];
-
- /* Threat on our stones. */
- if (board[aa] == color)
- break;
-
- if (dragon[aa].matcher_status == DEAD) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threatens to defend %1m (dead)\n", pos, aa);
- break;
- }
-
- /* If the stones are inessential, there is no value in saving them. */
- if (worm[aa].inessential || DRAGON2(aa).safety == INESSENTIAL) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threaten to defend %1m (inessential)\n", pos, aa);
- break;
- }
-
- /* If the move also owl defends the same stones, there is no
- * use in saving them
- */
- if (owl_defense_move_reason_known(pos, find_dragon(aa))) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threaten to defend of %1m (owl defended as well)\n",
- pos, aa);
- break;
- }
-
- add_followup_value(pos, 2 * worm[aa].effective_size);
-
- TRACE(" %1m: %f (followup) - threatens to defend %1m\n",
- pos, 2 * worm[aa].effective_size, aa);
-
- break;
-
case UNCERTAIN_OWL_DEFENSE:
/* This move reason is valued as a strategical value. */
break;
@@ -2716,11 +2664,38 @@
break;
case SEMEAI_MOVE:
+ if (move_reasons[r].is_threat) {
+ /* If this move also owl attacks or defends the same dragon, we
+ * count the points for that move reason instead.
+ */
+ if (owl_attack_move_reason_known(pos, move_reasons[r].what, FALSE)
+ || owl_defense_move_reason_known(pos, move_reasons[r].what, FALSE))
+ break;
+
+ aa = dragons[move_reasons[r].what];
+
+ /* If the dragon consists of a single worm, and this move
+ * tactically attacks or defends that worm, count the points for
+ * that move reason instead.
+ */
+ if (worm[aa].size == dragon[aa].size
+ && (attack_move_reason_known(pos, find_worm(aa), FALSE)
+ || defense_move_reason_known(pos, find_worm(aa), FALSE)))
+ break;
+
+ /* threaten to win the semeai as a ko threat */
+ add_followup_value(pos, 2 * dragon[aa].effective_size);
+ TRACE(" %1m: %f (followup) - threatens to win semeai for %1m\n",
+ pos, 2 * dragon[aa].effective_size, aa);
+
+ break;
+ }
+
/* If this move also owl attacks or defends the same dragon, we
* count the points for that move reason instead.
*/
- if (owl_attack_move_reason_known(pos, move_reasons[r].what)
- || owl_defense_move_reason_known(pos, move_reasons[r].what))
+ if (owl_attack_move_reason_known(pos, move_reasons[r].what, FALSE)
+ || owl_defense_move_reason_known(pos, move_reasons[r].what, FALSE))
break;
aa = dragons[move_reasons[r].what];
@@ -2730,8 +2705,8 @@
* that move reason instead.
*/
if (worm[aa].size == dragon[aa].size
- && (attack_move_reason_known(pos, find_worm(aa))
- || defense_move_reason_known(pos, find_worm(aa))))
+ && (attack_move_reason_known(pos, find_worm(aa), FALSE)
+ || defense_move_reason_known(pos, find_worm(aa), FALSE)))
break;
this_value = 2 * dragon[aa].effective_size;
@@ -2739,32 +2714,6 @@
tot_value += this_value;
break;
- case SEMEAI_THREAT:
- /* If this move also owl attacks or defends the same dragon, we
- * count the points for that move reason instead.
- */
- if (owl_attack_move_reason_known(pos, move_reasons[r].what)
- || owl_defense_move_reason_known(pos, move_reasons[r].what))
- break;
-
- aa = dragons[move_reasons[r].what];
-
- /* If the dragon consists of a single worm, and this move
- * tactically attacks or defends that worm, count the points for
- * that move reason instead.
- */
- if (worm[aa].size == dragon[aa].size
- && (attack_move_reason_known(pos, find_worm(aa))
- || defense_move_reason_known(pos, find_worm(aa))))
- break;
-
- /* threaten to win the semeai as a ko threat */
- add_followup_value(pos, 2 * dragon[aa].effective_size);
- TRACE(" %1m: %f (followup) - threatens to win semeai for %1m\n",
- pos, 2 * dragon[aa].effective_size, aa);
-
- break;
-
case VITAL_EYE_MOVE:
/* These are upgraded to owl attacks or defenses in
* find_more_owl_attack_and_defense_moves() and should no longer
@@ -2778,8 +2727,69 @@
case OWL_DEFEND_MOVE:
case OWL_DEFEND_MOVE_GOOD_KO:
case OWL_DEFEND_MOVE_BAD_KO:
+
aa = dragons[move_reasons[r].what];
+
+ if (move_reasons[r].is_threat) {
+ /* FIXME: currently we don't combine ko handling with threats. */
+
+ if (move_reasons[r].type == OWL_ATTACK_MOVE) {
+ if (dragon[aa].matcher_status == DEAD) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threatens to owl attack %1m (dead)\n",
+ pos, aa);
+ break;
+ }
+
+ if (DRAGON2(aa).safety == INESSENTIAL) {
+ DEBUG(DEBUG_MOVE_REASONS,
+ " %1m: 0.0 - threatens to capture %1m (inessential)\n",
+ pos, aa);
+ break;
+ }
+
+ /* The followup value of a move threatening to attack (aa) is
+ * twice its effective size, unless it has an adjacent
+ * (friendly) critical dragon. In that case it's probably a
+ * mistake to make the threat since it can defend itself with
+ * profit.
+ *
+ * FIXME: We probably need to verify that the critical dragon is
+ * substantial enough that capturing it saves the threatened
+ * dragon.
+ */
+ {
+ float value = 2 * dragon[aa].effective_size;
+ int s;
+
+ for (s = 0; s < DRAGON2(aa).neighbors; s++) {
+ int d = DRAGON2(aa).adjacent[s];
+ int adj = dragon2[d].origin;
+
+ if (dragon[adj].color == color
+ && dragon[adj].matcher_status == CRITICAL
+ && dragon2[d].safety != INESSENTIAL
+ && !owl_defense_move_reason_known(pos, find_dragon(adj),
FALSE))
+ value = 0.0;
+ }
+
+ if (value > 0.0) {
+ add_followup_value(pos, value);
+ TRACE(" %1m: %f (followup) - threatens to owl attack %1m\n",
+ pos, value, aa);
+ }
+ }
+ }
+ else if (move_reasons[r].type == OWL_DEFEND_MOVE) {
+ add_followup_value(pos, 2 * dragon[aa].effective_size);
+ TRACE(" %1m: %f (followup) - threatens to owl defend %1m\n",
+ pos, 2 * dragon[aa].effective_size, aa);
+ }
+ break;
+ }
+ /* Not a threat if we reach this point. */
+
if (DRAGON2(aa).safety == INESSENTIAL) {
DEBUG(DEBUG_MOVE_REASONS,
" %1m: 0 - owl attack/defend for inessential dragon %1m\n",
@@ -2803,9 +2813,10 @@
int ii;
for (ii = BOARDMIN; ii < BOARDMAX; ii++) {
if (IS_STONE(board[ii]) && is_same_dragon(ii, aa)) {
- if (move_reasons[r].type == OWL_ATTACK_MOVE
- || move_reasons[r].type == OWL_ATTACK_MOVE_GOOD_KO
- || move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO)
+ if ((move_reasons[r].type == OWL_ATTACK_MOVE
+ || move_reasons[r].type == OWL_ATTACK_MOVE_GOOD_KO
+ || move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO)
+ && move_reasons[r].is_threat == FALSE)
saved_stones[ii] = INFLUENCE_CAPTURED_STONE;
else
saved_stones[ii] = INFLUENCE_SAVED_STONE;
@@ -2816,17 +2827,20 @@
/* FIXME: How much should we reduce the value for ko attacks? */
this_value = 2 * dragon[aa].effective_size;
- if (move_reasons[r].type == OWL_ATTACK_MOVE
- || move_reasons[r].type == OWL_DEFEND_MOVE)
+ if ((move_reasons[r].type == OWL_ATTACK_MOVE
+ || move_reasons[r].type == OWL_DEFEND_MOVE)
+ && move_reasons[r].is_threat == FALSE)
this_value = 0.0;
- else if (move_reasons[r].type == OWL_ATTACK_MOVE_GOOD_KO
- || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO) {
+ else if ((move_reasons[r].type == OWL_ATTACK_MOVE_GOOD_KO
+ || move_reasons[r].type == OWL_DEFEND_MOVE_GOOD_KO)
+ && move_reasons[r].is_threat == FALSE) {
this_value *= 0.3;
TRACE(" %1m: -%f - owl attack/defense of %1m only with good ko\n",
pos, this_value, aa);
}
- else if (move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO
- || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO) {
+ else if ((move_reasons[r].type == OWL_ATTACK_MOVE_BAD_KO
+ || move_reasons[r].type == OWL_DEFEND_MOVE_BAD_KO)
+ && move_reasons[r].is_threat == FALSE) {
this_value *= 0.5;
TRACE(" %1m: -%f - owl attack/defense of %1m only with bad ko\n",
pos, this_value, aa);
@@ -2836,63 +2850,6 @@
does_block = 1;
break;
- case OWL_ATTACK_THREAT:
- aa = dragons[move_reasons[r].what];
-
- if (dragon[aa].matcher_status == DEAD) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threatens to owl attack %1m (dead)\n", pos, aa);
- break;
- }
-
- if (DRAGON2(aa).safety == INESSENTIAL) {
- DEBUG(DEBUG_MOVE_REASONS,
- " %1m: 0.0 - threatens to capture %1m (inessential)\n",
- pos, aa);
- break;
- }
-
- /* The followup value of a move threatening to attack (aa) is
- * twice its effective size, unless it has an adjacent
- * (friendly) critical dragon. In that case it's probably a
- * mistake to make the threat since it can defend itself with
- * profit.
- *
- * FIXME: We probably need to verify that the critical dragon is
- * substantial enough that capturing it saves the threatened
- * dragon.
- */
- {
- float value = 2 * dragon[aa].effective_size;
- int s;
-
- for (s = 0; s < DRAGON2(aa).neighbors; s++) {
- int d = DRAGON2(aa).adjacent[s];
- int adj = dragon2[d].origin;
-
- if (dragon[adj].color == color
- && dragon[adj].matcher_status == CRITICAL
- && dragon2[d].safety != INESSENTIAL
- && !owl_defense_move_reason_known(pos, find_dragon(adj)))
- value = 0.0;
- }
-
- if (value > 0.0) {
- add_followup_value(pos, value);
- TRACE(" %1m: %f (followup) - threatens to owl attack %1m\n",
- pos, value, aa);
- }
- }
- break;
-
- case OWL_DEFENSE_THREAT:
- aa = dragons[move_reasons[r].what];
-
- add_followup_value(pos, 2 * dragon[aa].effective_size);
- TRACE(" %1m: %f (followup) - threatens to owl defend %1m\n",
- pos, 2 * dragon[aa].effective_size, aa);
- break;
-
case OWL_PREVENT_THREAT:
/* A move attacking a dragon whose defense can be threatened.
*/
@@ -3044,6 +3001,11 @@
case DEFEND_MOVE:
case DEFEND_MOVE_GOOD_KO:
case DEFEND_MOVE_BAD_KO:
+
+ /* Only handle moves that work right out. */
+ if (move_reasons[r].is_threat)
+ break;
+
worm1 = move_reasons[r].what;
aa = worms[worm1];
@@ -3109,8 +3071,8 @@
*/
if (dragon[bb].matcher_status != DEAD
&& dragon[bb].size == worm[bb].size
- && (attack_move_reason_known(pos, find_worm(bb))
- || defense_move_reason_known(pos, find_worm(bb))))
+ && (attack_move_reason_known(pos, find_worm(bb), FALSE)
+ || defense_move_reason_known(pos, find_worm(bb), FALSE)))
this_value = 0.0;
/* If this dragon can be tactically attacked and the move
@@ -3125,12 +3087,13 @@
break;
- case ATTACK_THREAT_MOVE:
- case DEFEND_THREAT_MOVE:
- break;
-
case ATTACK_EITHER_MOVE:
case DEFEND_BOTH_MOVE:
+
+ /* Only handle moves that work right out. */
+ if (move_reasons[r].is_threat)
+ break;
+
/* This is complete nonsense, but still better than nothing.
* FIXME: Do this in a reasonable way.
*/
@@ -3148,22 +3111,22 @@
* either worm, this move reason has no additional value.
*/
if (move_reasons[r].type == ATTACK_EITHER_MOVE
- && (attack_move_reason_known(pos, worm1)
- || attack_move_reason_known(pos, worm2)))
+ && (attack_move_reason_known(pos, worm1, FALSE)
+ || attack_move_reason_known(pos, worm2, FALSE)))
break;
if (move_reasons[r].type == DEFEND_BOTH_MOVE
- && (defense_move_reason_known(pos, worm1)
- || defense_move_reason_known(pos, worm2)))
+ && (defense_move_reason_known(pos, worm1, FALSE)
+ || defense_move_reason_known(pos, worm2, FALSE)))
break;
/* Also if there is a combination attack, we assume it covers
* the same thing.
*/
if (move_reasons[r].type == ATTACK_EITHER_MOVE
- && move_reason_known(pos, MY_ATARI_ATARI_MOVE, -1))
+ && move_reason_known(pos, MY_ATARI_ATARI_MOVE, -1, FALSE))
break;
if (move_reasons[r].type == DEFEND_BOTH_MOVE
- && move_reason_known(pos, YOUR_ATARI_ATARI_MOVE, -1))
+ && move_reason_known(pos, YOUR_ATARI_ATARI_MOVE, -1, FALSE))
break;
{
@@ -3197,6 +3160,10 @@
if (doing_scoring && !move[pos].move_safety)
break;
+ /* Only handle moves that work right out. */
+ if (move_reasons[r].is_threat)
+ break;
+
d1 = conn_dragon1[move_reasons[r].what];
d2 = conn_dragon2[move_reasons[r].what];
aa = dragons[d1];
@@ -3251,12 +3218,16 @@
if (bb == NO_MOVE) /* Maybe we should assert this not to happen. */
break;
+ /* Only handle moves that work right out. */
+ if (move_reasons[r].is_threat)
+ break;
+
/* If there is an owl attack/defend move reason for this location,
* we don't care about it, since otherwise we would count the
* points twice.
*/
- if (owl_defense_move_reason_known(pos, find_dragon(bb))
- || owl_attack_move_reason_known(pos, find_dragon(bb))) {
+ if (owl_defense_move_reason_known(pos, find_dragon(bb), FALSE)
+ || owl_attack_move_reason_known(pos, find_dragon(bb), FALSE)) {
DEBUG(DEBUG_MOVE_REASONS,
" %1m: 0.0 - vital for %1m: owl attack/defense as well\n",
pos, bb);
@@ -3321,7 +3292,7 @@
if (dragon[adj].color == color
&& dragon[adj].matcher_status == CRITICAL
&& dragon2[d].safety != INESSENTIAL
- && !owl_defense_move_reason_known(pos, find_dragon(adj)))
+ && !owl_defense_move_reason_known(pos, find_dragon(adj), FALSE))
this_value = 0.0;
}
}
@@ -3386,17 +3357,17 @@
*/
if (dragon[aa].matcher_status != DEAD
&& dragon[aa].size == worm[aa].size
- && (attack_move_reason_known(pos, find_worm(aa))
- || defense_move_reason_known(pos, find_worm(aa))))
+ && (attack_move_reason_known(pos, find_worm(aa), FALSE)
+ || defense_move_reason_known(pos, find_worm(aa), FALSE)))
continue;
/* If the dragon has been owl captured, owl defended, or involved
* in a semeai, we have likewise already counted the points as
* territorial value.
*/
- if (owl_attack_move_reason_known(pos, k)
- || owl_defense_move_reason_known(pos, k)
- || move_reason_known(pos, SEMEAI_MOVE, k)) {
+ if (owl_attack_move_reason_known(pos, k, FALSE)
+ || owl_defense_move_reason_known(pos, k, FALSE)
+ || move_reason_known(pos, SEMEAI_MOVE, k, FALSE)) {
/* But if the strategical value was larger than the territorial
* value (e.g. because connecting to strong dragon) we award the
* excess value as a bonus.
@@ -3522,8 +3493,10 @@
if (move_reasons[mr1].type != move_reasons[mr2].type)
return move_reasons[mr2].type - move_reasons[mr1].type;
- else
+ else if (move_reasons[mr2].what != move_reasons[mr1].what)
return move_reasons[mr2].what - move_reasons[mr1].what;
+ else
+ return move_reasons[mr2].is_threat - move_reasons[mr1].is_threat;
}
diff -ur gnugo-sync/engine/move_reasons.h gnugo-iw/engine/move_reasons.h
--- gnugo-sync/engine/move_reasons.h Sat Nov 10 23:52:48 2001
+++ gnugo-iw/engine/move_reasons.h Sun Dec 16 14:49:55 2001
@@ -24,13 +24,13 @@
/* values for move_reason.type */
#define ATTACK_MOVE 1
#define DEFEND_MOVE 2
-#define ATTACK_THREAT_MOVE 3
-#define DEFEND_THREAT_MOVE 4
+/*#define ATTACK_THREAT_MOVE 3*/
+/*#define DEFEND_THREAT_MOVE 4*/
#define CONNECT_MOVE 5
#define CUT_MOVE 6
#define ANTISUJI_MOVE 7
#define SEMEAI_MOVE 8
-#define SEMEAI_THREAT 9
+/*#define SEMEAI_THREAT 9*/
#define VITAL_EYE_MOVE 12
#define ATTACK_EITHER_MOVE 13
#define DEFEND_BOTH_MOVE 14
@@ -41,8 +41,8 @@
#define STRATEGIC_DEFEND_MOVE 19
#define OWL_ATTACK_MOVE 20
#define OWL_DEFEND_MOVE 21
-#define OWL_ATTACK_THREAT 22
-#define OWL_DEFENSE_THREAT 23
+/*#define OWL_ATTACK_THREAT 22*/
+/*#define OWL_DEFENSE_THREAT 23*/
#define OWL_PREVENT_THREAT 24
#define UNCERTAIN_OWL_ATTACK 25
#define UNCERTAIN_OWL_DEFENSE 26
@@ -65,6 +65,7 @@
int type; /* e.g. attack, defend, or connect */
int what; /* pointer into list of strings, list of pair of dragons,
or similar */
+ int is_threat; /* 1 if this is only a threat, 0 if it works outright */
};
struct move_data {
diff -ur gnugo-sync/engine/optics.c gnugo-iw/engine/optics.c
--- gnugo-sync/engine/optics.c Fri Dec 14 21:40:49 2001
+++ gnugo-iw/engine/optics.c Sun Dec 16 13:54:18 2001
@@ -1656,11 +1656,11 @@
if (add_moves) {
if (eye_color != color) {
for (k = 0; k < num_attacks; k++)
- add_vital_eye_move(attack_points[k], pos, eye_color);
+ add_vital_eye_move(attack_points[k], pos, eye_color, FALSE);
}
else {
for (k = 0; k < num_defenses; k++)
- add_vital_eye_move(defense_points[k], pos, eye_color);
+ add_vital_eye_move(defense_points[k], pos, eye_color, FALSE);
}
}
}
diff -ur gnugo-sync/engine/owl.c gnugo-iw/engine/owl.c
--- gnugo-sync/engine/owl.c Thu Dec 13 20:23:22 2001
+++ gnugo-iw/engine/owl.c Sun Dec 16 13:57:15 2001
@@ -2782,7 +2782,7 @@
if (board[pos] == color) {
if (dragon[pos].owl_defense_point != NO_MOVE) {
add_owl_defense_move(dragon[pos].owl_defense_point, pos,
- dragon[pos].owl_defense_code);
+ dragon[pos].owl_defense_code, FALSE);
DEBUG(DEBUG_OWL, "owl: %1m defends %1m at move %d\n",
dragon[pos].owl_defense_point, pos, movenum+1);
}
@@ -2842,7 +2842,7 @@
}
/* If we've reached this far, the attack is okay. */
- add_owl_attack_move(move, pos, dragon[pos].owl_attack_code);
+ add_owl_attack_move(move, pos, dragon[pos].owl_attack_code, FALSE);
DEBUG(DEBUG_OWL, "owl: %1m attacks %1m at move %d\n", move, pos,
movenum+1);
}
@@ -2852,12 +2852,12 @@
&& dragon[pos].owl_threat_status == CAN_THREATEN_DEFENSE) {
if (board[pos] == color
&& dragon[pos].owl_defense_point != NO_MOVE)
- add_owl_defense_threat_move(dragon[pos].owl_defense_point, pos, WIN);
+ add_owl_defense_move(dragon[pos].owl_defense_point, pos, WIN, TRUE);
if (board[pos] == color
&& dragon[pos].owl_second_defense_point != NO_MOVE
&& is_legal(dragon[pos].owl_second_defense_point, color))
- add_owl_defense_threat_move(dragon[pos].owl_second_defense_point,
- pos, WIN);
+ add_owl_defense_move(dragon[pos].owl_second_defense_point,
+ pos, WIN, TRUE);
/* If the opponent can threaten to live, an attacking
* move gets a small value to make sure it's really dead.
*/
@@ -2871,11 +2871,11 @@
&& board[pos] == OTHER_COLOR(color)
&& dragon[pos].owl_threat_status == CAN_THREATEN_ATTACK) {
if (dragon[pos].owl_attack_point != NO_MOVE)
- add_owl_attack_threat_move(dragon[pos].owl_attack_point, pos, WIN);
+ add_owl_attack_move(dragon[pos].owl_attack_point, pos, WIN, TRUE);
if (dragon[pos].owl_second_attack_point != NO_MOVE
&& is_legal(dragon[pos].owl_second_attack_point, color))
- add_owl_attack_threat_move(dragon[pos].owl_second_attack_point, pos,
- WIN);
+ add_owl_attack_move(dragon[pos].owl_second_attack_point, pos,
+ WIN, TRUE);
}
/* The owl code found the friendly dragon alive, but was uncertain,
* and an extra point of defense was found, so this might
diff -ur gnugo-sync/engine/semeai.c gnugo-iw/engine/semeai.c
--- gnugo-sync/engine/semeai.c Tue Dec 11 03:41:01 2001
+++ gnugo-iw/engine/semeai.c Sun Dec 16 13:55:27 2001
@@ -185,10 +185,10 @@
else { /* pass == 1 */
if (a_status == CRITICAL
&& best_result_a[k] != DEAD)
- add_owl_defense_move(move[k], apos, WIN);
+ add_owl_defense_move(move[k], apos, WIN, FALSE);
if (b_status == CRITICAL
&& worst_result_b[k] == DEAD)
- add_owl_attack_move(move[k], bpos, WIN);
+ add_owl_attack_move(move[k], bpos, WIN, FALSE);
}
} /* loop over neighbor dragons */
if (pass == 0 && semeai_found) {
@@ -285,7 +285,7 @@
if (dragon[my_dragon].owl_defense_point != NO_MOVE
&& owl_does_attack(dragon[my_dragon].owl_defense_point, your_dragon)) {
add_owl_attack_move(dragon[my_dragon].owl_defense_point, your_dragon,
- WIN);
+ WIN, FALSE);
DEBUG(DEBUG_SEMEAI, "added owl attack of %1m at %1m\n",
your_dragon, dragon[my_dragon].owl_defense_point);
owl_code_sufficient = 1;
@@ -307,7 +307,7 @@
if (dragon[your_dragon].owl_attack_point != NO_MOVE
&& owl_does_defend(dragon[your_dragon].owl_attack_point, my_dragon)) {
add_owl_defense_move(dragon[your_dragon].owl_attack_point, my_dragon,
- WIN);
+ WIN, FALSE);
DEBUG(DEBUG_SEMEAI, "added owl defense of %1m at %1m\n",
my_dragon, dragon[your_dragon].owl_attack_point);
if (dragon[my_dragon].owl_status == DEAD) {
@@ -724,13 +724,13 @@
int margin_of_safety)
{
if (my_status == CRITICAL)
- add_semeai_move(move, my_dragon);
+ add_semeai_move(move, my_dragon, FALSE);
else if (margin_of_safety == 1)
- add_semeai_threat(move, my_dragon);
+ add_semeai_move(move, my_dragon, TRUE);
if (your_status == CRITICAL)
- add_semeai_move(move, your_dragon);
+ add_semeai_move(move, your_dragon, FALSE);
else if (margin_of_safety == 1)
- add_semeai_threat(move, your_dragon);
+ add_semeai_move(move, your_dragon, TRUE);
}
diff -ur gnugo-sync/engine/worm.c gnugo-iw/engine/worm.c
--- gnugo-sync/engine/worm.c Wed Dec 5 19:49:51 2001
+++ gnugo-iw/engine/worm.c Sun Dec 16 13:48:20 2001
@@ -1324,10 +1324,10 @@
for (k = 0; k < MAX_TACTICAL_POINTS; k++) {
if (worm[pos].attack_codes[k] != 0)
add_attack_move(worm[pos].attack_points[k], pos,
- worm[pos].attack_codes[k]);
+ worm[pos].attack_codes[k], FALSE);
if (worm[pos].attack_threat_codes[k] != 0)
- add_attack_threat_move(worm[pos].attack_threat_points[k], pos,
- worm[pos].attack_threat_codes[k]);
+ add_attack_move(worm[pos].attack_threat_points[k], pos,
+ worm[pos].attack_threat_codes[k], TRUE);
}
}
@@ -1335,11 +1335,11 @@
for (k = 0; k < MAX_TACTICAL_POINTS; k++) {
if (worm[pos].defend_codes[k] != 0)
add_defense_move(worm[pos].defense_points[k], pos,
- worm[pos].defend_codes[k]);
+ worm[pos].defend_codes[k], FALSE);
if (worm[pos].defense_threat_codes[k] != 0)
- add_defense_threat_move(worm[pos].defense_threat_points[k], pos,
- worm[pos].defense_threat_codes[k]);
+ add_defense_move(worm[pos].defense_threat_points[k], pos,
+ worm[pos].defense_threat_codes[k], TRUE);
}
}
}
diff -ur gnugo-sync/patterns/mkpat.c gnugo-iw/patterns/mkpat.c
--- gnugo-sync/patterns/mkpat.c Thu Dec 13 20:23:41 2001
+++ gnugo-iw/patterns/mkpat.c Sun Dec 16 13:59:09 2001
@@ -223,8 +223,8 @@
{"antisuji", 1, "add_antisuji_move(%s)"},
{"add_connect_move",2, "add_connection_move(move,%s,%s)"},
{"add_cut_move", 2, "add_cut_move(move,%s,%s)"},
- {"add_attack_either_move",2,"add_attack_either_move(move,%s,%s)"},
- {"add_defend_both_move",2, "add_defend_both_move(move,%s,%s)"},
+ {"add_attack_either_move",2,"add_attack_either_move(move,%s,%s,FALSE)"},
+ {"add_defend_both_move",2, "add_defend_both_move(move,%s,%s,FALSE)"},
{"same_dragon", 2, "is_same_dragon(%s,%s)"},
{"same_string", 2, "same_string(%s,%s)"},
{"dragonsize", 1, "dragon[%s].size"},
- [gnugo-devel] Preparatory patch,
Inge Wallin <=
Re: [gnugo-devel] Preparatory patch, Arend Bayer, 2001/12/18