[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] vital owl defense
From: |
Arend Bayer |
Subject: |
[gnugo-devel] vital owl defense |
Date: |
Sat, 16 Nov 2002 20:44:09 +0100 (CET) |
While there are matching vital owl attack patterns, we make it harder
for do_owl_defend to claim life (and hence cut the search).
However, the moves themselves are discarded. This is changed by this
patch. If owl_estimate_life() would estimate the dragon to be alive
without this rule, it inserts the top scoring vital attack move into
the vital_moves list as a defense against the vital owl attack.
As sometimes the right defense could be somewhere else than the attack
move, this can be indicated in the pattern by a '!'. However, this
does not seem necessary for many patterns.
This reduces owl nodes for nngs.tst by ~2% and probably gets exactly
one PASS for the whole regression test suite (a good one).
Arend
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.121
diff -u -p -r1.121 owl.c
--- engine/owl.c 15 Nov 2002 19:39:45 -0000 1.121
+++ engine/owl.c 16 Nov 2002 19:39:49 -0000
@@ -111,6 +111,7 @@ struct owl_move_data {
const char *name; /* name of the pattern suggesting the move */
int same_dragon; /* whether the move extends the dragon or not */
int escape; /* true if an escape pattern is matched */
+ int defense_pos; /* defense coordinate for vital owl attack patterns. */
};
struct matched_pattern_data {
@@ -153,7 +154,8 @@ static void owl_shapes_callback(int m, i
struct pattern *pattern_db,
int ll, void *data);
static void owl_add_move(struct owl_move_data *moves, int move, int value,
- const char *reason, int same_dragon, int escape);
+ const char *reason, int same_dragon, int escape,
+ int defense_pos);
static void owl_determine_life(struct local_owl_data *owl,
struct local_owl_data *second_owl,
int komaster, int does_attack,
@@ -632,7 +634,7 @@ do_owl_analyze_semeai(int apos, int bpos
owl_add_move(moves, vital_defensive_moves[k].pos,
move_value, "vital defensive move",
vital_defensive_moves[k].same_dragon,
- vital_defensive_moves[k].escape);
+ vital_defensive_moves[k].escape, NO_MOVE);
}
for (k = 0;
k < MAX_SEMEAI_MOVES && vital_offensive_moves[k].pos != NO_MOVE;
@@ -662,7 +664,7 @@ do_owl_analyze_semeai(int apos, int bpos
owl_add_move(moves, vital_offensive_moves[k].pos,
move_value, vital_offensive_moves[k].name,
same_dragon,
- vital_offensive_moves[k].escape);
+ vital_offensive_moves[k].escape, NO_MOVE);
}
for (k = 0;
k < MAX_SEMEAI_MOVES && shape_defensive_moves[k].pos != NO_MOVE;
@@ -689,7 +691,7 @@ do_owl_analyze_semeai(int apos, int bpos
move_value,
shape_defensive_moves[k].name,
shape_defensive_moves[k].same_dragon,
- shape_defensive_moves[k].escape);
+ shape_defensive_moves[k].escape, NO_MOVE);
}
for (k = 0;
k < MAX_SEMEAI_MOVES && shape_offensive_moves[k].pos != NO_MOVE;
@@ -720,7 +722,7 @@ do_owl_analyze_semeai(int apos, int bpos
move_value,
shape_offensive_moves[k].name,
same_dragon,
- shape_offensive_moves[k].escape);
+ shape_offensive_moves[k].escape, NO_MOVE);
}
/* If no owl moves were found, turn off the owl phase */
if (moves[0].pos == 0)
@@ -810,20 +812,20 @@ do_owl_analyze_semeai(int apos, int bpos
move_value = semeai_move_value(outside_liberty.pos,
owla, owlb, 50);
owl_add_move(moves, outside_liberty.pos, move_value,
- "safe outside liberty", 0, 0);
+ "safe outside liberty", 0, 0, NO_MOVE);
}
else if (backfilling_move_found && backfilling_move.pos != NO_MOVE) {
move_value = semeai_move_value(backfilling_move.pos,
owla, owlb, 50);
owl_add_move(moves, backfilling_move.pos, move_value,
- "backfilling move", 0, 0);
+ "backfilling move", 0, 0, NO_MOVE);
}
else if (safe_common_liberty_found
&& common_liberty.pos != NO_MOVE) {
move_value = semeai_move_value(common_liberty.pos,
owla, owlb, 10);
owl_add_move(moves, common_liberty.pos, move_value,
- "safe common liberty", 1, 0);
+ "safe common liberty", 1, 0, NO_MOVE);
}
/* Now we are ready to try moves. Turn on the sgf output ... */
sgf_dumptree = save_sgf_dumptree;
@@ -1868,6 +1870,7 @@ do_owl_defend(int str, int *move, int *w
int eyemin = -1; /* Lower bound on the number of eyes. */
int eyemax = -1; /* Upper bound on the number of eyes. */
struct eyevalue probable_eyes; /* Best guess of eyevalue. */
+ int escape_route;
const char *live_reason;
int move_cutoff;
Read_result *read_result = NULL;
@@ -1912,7 +1915,8 @@ do_owl_defend(int str, int *move, int *w
* FIXME: Should introduce a new owl depth value rather than having
* this hardwired value.
*/
- if (stackp > 2 && owl_escape_route(owl) >= 5) {
+ escape_route = owl_escape_route(owl);
+ if (stackp > 2 && escape_route >= 5) {
/* FIXME: We probably should make distinction in the returned
* result whether the dragon lives by making two eyes or by
* escaping.
@@ -1984,6 +1988,12 @@ do_owl_defend(int str, int *move, int *w
READ_RETURN(read_result, move, shape_moves[0].pos, WIN);
}
moves = shape_moves;
+
+ if (eyemax == 0 && escape_route == 0)
+ move_cutoff = 67;
+ else if (eyemax <= 1 && escape_route <= 2)
+ move_cutoff = 32;
+
break;
case 0:
@@ -2325,8 +2335,22 @@ owl_estimate_life(struct local_owl_data
gg_assert(0);
return 1;
}
- else
- return 0;
+
+ if (!does_attack
+ && (*eyemin + matches_found >= 2
+ || (*eyemin + matches_found == 1 && min_eyes(probable_eyes) >= 4)
+ || (stackp > owl_distrust_depth
+ && min_eyes(probable_eyes) >= 2))) {
+ /* We are not yet alive only due to owl vital attack patterns matching.
+ * Let's try to defend against it.
+ */
+ owl_add_move(vital_moves, dummy_moves[0].defense_pos,
+ dummy_moves[0].value, dummy_moves[0].name, 2, 0, NO_MOVE);
+ }
+
+
+
+ return 0;
}
@@ -2577,7 +2601,7 @@ owl_determine_life(struct local_owl_data
TRACE("vital point looked stupid, moved it to %1m\n",
attack_point);
- owl_add_move(moves, attack_point, value, reason, 1, 0);
+ owl_add_move(moves, attack_point, value, reason, 1, 0, NO_MOVE);
vital_values[attack_point] = value;
eyes_attack_points[num_eyes] = attack_point;
}
@@ -2628,7 +2652,7 @@ owl_determine_life(struct local_owl_data
TRACE("vital point looked stupid, moved it to %1m\n",
defense_point);
- owl_add_move(moves, defense_point, value, reason, 1, 0);
+ owl_add_move(moves, defense_point, value, reason, 1, 0, NO_MOVE);
vital_values[defense_point] = value;
}
}
@@ -2706,14 +2730,16 @@ owl_determine_life(struct local_owl_data
TRACE("save lunch at %1m with %1m, score %d\n",
owl->lunch[lunch], defense_point, value);
- owl_add_move(moves, defense_point, value, "save lunch", 1, 0);
+ owl_add_move(moves, defense_point, value,
+ "save lunch", 1, 0, NO_MOVE);
}
else {
attack_point = improve_lunch_attack(owl->lunch[lunch],
owl->lunch_attack_point[lunch]);
TRACE("eat lunch at %1m with %1m, score %d\n",
owl->lunch[lunch], attack_point, value);
- owl_add_move(moves, attack_point, value, "eat lunch", 1, 0);
+ owl_add_move(moves, attack_point, value, "eat lunch",
+ 1, 0, NO_MOVE);
num_lunch++;
eyevalue_list[num_eyes++] = e;
}
@@ -3243,6 +3269,7 @@ owl_shapes_callback(int m, int n, int co
struct owl_move_data *moves = data; /* considered moves passed as data */
int same_dragon = 1;
int escape = 0;
+ int defense_pos;
/* Pick up the location of the move */
move = AFFINE_TRANSFORM(pattern->movei, pattern->movej, ll, m, n);
@@ -3307,8 +3334,19 @@ owl_shapes_callback(int m, int n, int co
escape = 1;
else
escape = 0;
+
+ /* Finally, check for position of defense move. */
+ {
+ int k;
+ defense_pos = move;
+ for (k = 0; k < pattern->patlen; k++)
+ if (pattern->patn[k].att == ATT_not)
+ defense_pos = AFFINE_TRANSFORM(pattern->patn[k].x, pattern->patn[k].y,
+ ll, m, n);
+ }
- owl_add_move(moves, move, tval, pattern->name, same_dragon, escape);
+ owl_add_move(moves, move, tval, pattern->name, same_dragon, escape,
+ defense_pos);
}
@@ -3316,7 +3354,7 @@ owl_shapes_callback(int m, int n, int co
static void
owl_add_move(struct owl_move_data *moves, int move, int value,
- const char *reason, int same_dragon, int escape)
+ const char *reason, int same_dragon, int escape, int defense_pos)
{
int k;
@@ -3363,6 +3401,7 @@ owl_add_move(struct owl_move_data *moves
*/
moves[k].same_dragon = same_dragon;
moves[k].escape = escape;
+ moves[k].defense_pos = defense_pos;
}
break;
}
Index: patterns/owl_vital_apats.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/owl_vital_apats.db,v
retrieving revision 1.31
diff -u -p -r1.31 owl_vital_apats.db
--- patterns/owl_vital_apats.db 20 Oct 2002 10:43:25 -0000 1.31
+++ patterns/owl_vital_apats.db 16 Nov 2002 19:39:50 -0000
@@ -40,6 +40,7 @@
# x : your piece or empty
# o : my piece or empty
# * : my next move
+# ! : your defense move against * (if different)
# -, | : edge of board
# + : corner of board
#
@@ -203,7 +204,7 @@ XOOXXx
?XX???
XaaXXx
-.aX*.x
+!aX*.x
------
;attack(a) && !defend(a)
@@ -227,7 +228,7 @@ Pattern VA13
|XX? take ko to maybe kill
|*XX
|XOX
-|O.O
+|O!O
+---
:8,s,value(85)
@@ -244,7 +245,7 @@ Pattern VA13
Pattern VA14
?OX force X to defend inside own eyespace
-OX.
+OX!
*XO
---
@@ -293,7 +294,7 @@ X..?
Pattern VA17
xXXOo exploit shortage of liberties
-.O*XO
+!O*XO
.X.Xo
:8,s,value(35)
@@ -307,7 +308,7 @@ aO*XO
Pattern VA18
-XX.O throw in to kill an eye
+XX!O throw in to kill an eye
.*X?
XXO?
@@ -445,7 +446,7 @@ Pattern VA26
# gf New pattern. (3.1.15)
??XX? making nakade is only chance to kill, unless we can capture
-?XO.X some of the wall
+?XO!X some of the wall
X*XOX
X.OX?
?XX??
@@ -509,7 +510,7 @@ Pattern VA29
# gf New pattern. (3.1.15)
|XXX? not two certain eyes
-|.O.X
+|!O.X
|OX*x
+----
@@ -519,7 +520,7 @@ Pattern VA29
Pattern VA30
# gf New pattern. (3.1.15)
-?XX. atari to destroy eye
+?XX! atari to destroy eye
X.*X
?XX?
@@ -538,7 +539,7 @@ Pattern VA31
?O.|
OX.|
X.X|
-X.*|
+X!*|
??.|
:8,s,value(76)
@@ -548,7 +549,7 @@ Pattern VA32
# tm New pattern (3.1.15) (see maeda0:60)
?O*|
-OX.|
+OX!|
X.X|
XXO|
@@ -560,7 +561,7 @@ Pattern VA33
?X|
XO|
-.O|
+!O|
*X|
:8,-,value(76)
@@ -572,7 +573,7 @@ Pattern VA34
?X?
XOX
-.OX
+!OX
*XO
:8,-,value(76)
@@ -620,7 +621,7 @@ Pattern VA37
?xXO?
?X.XO
-O.X.*
+O.X!*
-----
:8,-,value(45)
@@ -638,7 +639,7 @@ Pattern VA38
# See trevora:25
??O
-x.. capture a string at the edge of an eyespace
+x!. capture a string at the edge of an eyespace
.*X
...
---
@@ -658,7 +659,7 @@ Pattern VA39
# tm New Pattern (3.1.16)
XO*| atari to kill eye
-.XX|
+!XX|
XOO|
:8,s,value(95)
@@ -693,7 +694,7 @@ Pattern VA41
XXO
.*X
-..X
+!.X
:8,s,value(95)
@@ -811,7 +812,7 @@ Pattern VA48
+----
|.*..
-|XX.O
+|XX!O
:8,s,value(75)
- [gnugo-devel] vital owl defense,
Arend Bayer <=