[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] read_eye() patch
From: |
Paul Pogonyshev |
Subject: |
[gnugo-devel] read_eye() patch |
Date: |
23 Oct 2003 01:24:35 +0000 |
This patch solves owl:232 in an algorithmic way. No other breakage.
I'm not sure if the patch worth it, but the cost must be negligible.
Node counters (3.5.2-pre-1 + the patch):
1512174446 2466795 8795625
Paul
--- optics.c.~1.82.~ 2003-08-25 00:39:17.000000000 +0000
+++ optics.c 2003-10-22 21:29:23.000000000 +0000
@@ -989,7 +989,7 @@ guess_eye_space(int pos, int effective_e
/* This function does some minor reading to improve the results of
- * recognize_eye(). Currently, it has to duties. One is to read
+ * recognize_eye(). Currently, it has three duties. One is to read
* positions like this:
*
* .XXXX| with half eye with proper eye
@@ -1000,14 +1000,14 @@ guess_eye_space(int pos, int effective_e
*
* recognize_eye() sees the eyespace of the white dragon as shown
* (there's a half eye at a and it is considered the same as '!.' by
- * the optics code). Normally, that eye shape gives only one secure
+ * the optics code). Normally, that eye shape gives only one secure
* eye, and owl thinks that the white dragon is dead unconditionally.
* This function tries to turn such ko-dependent half eyes into proper
- * eyes and chooses the best alternative. Note that we don't have any
+ * eyes and chooses the best alternative. Note that we don't have any
* attack/defense codes here, since owl will determine them itself.
*
- * Another one is related to some cases when replacing half eyes with
- * '!.' doesn't work. E.g. consider this eye (optics:328):
+ * The second is related to some cases when replacing half eyes with
+ * '!.' doesn't work. E.g. consider this eye (optics:328):
*
* XXXOO eye graph is 310:
* X..X.
@@ -1017,15 +1017,22 @@ guess_eye_space(int pos, int effective_e
*
* When this function detects such a half eye that can be attacked
* and/or defended inside its eyespace, it tries to turn it into a
- * proper eye and see what happens. In case it gives an improvement
+ * proper eye and see what happens. In case it gives an improvement
* for attacker and/or defender, the function keeps new result but
* only if new vital points are also vital points for the half eye.
* The heuristics used here might need improvements since they are
- * based on a single game position.
+ * based on very few game positions.
+ *
+ * Finally, when the best defense of an eye is capturable and is not
+ * in the eye itself (is not a sacrifice that prevents a dead shape)
+ * and the attack on the eye is in ko, this function finds a
+ * backfilling move. Note that if the attack is unconditional, there
+ * is no sense in backfilling, since opponent will simply kill the eye
+ * in response.
*
* If add_moves != 0, this function may add move reasons for (color)
- * at the vital points which are found by recognize_eye(). If add_moves
- * == 0, set color to be EMPTY.
+ * at the vital points which are found by recognize_eye(). If
+ * add_moves == 0, set color to be EMPTY.
*/
static int
read_eye(int pos, int *attack_point, int *defense_point,
@@ -1176,6 +1183,57 @@ read_eye(int pos, int *attack_point, int
}
}
+ /* If the best defense move is not safe and is outside the eye under
+ * consideration and the attack on the eye is a ko, then we might
+ * have time to backfill.
+ */
+ if (*defense_point
+ && !safe_move(*defense_point, eye_color)
+ && eye[*defense_point].origin != pos
+ && is_ko(*attack_point, OTHER_COLOR(eye_color), NULL)) {
+ int num_moves = 0;
+ int moves[MAX_BOARD * MAX_BOARD];
+
+ for (k = 0; k < 4; k++) {
+ if (board[*defense_point + delta[k]] == eye_color) {
+ int i;
+ int num_chainlinks;
+ int chainlinks[MAXCHAIN];
+
+ num_chainlinks = chainlinks2(*defense_point + delta[k], chainlinks, 1);
+
+ for (i = 0; i < num_chainlinks; i++)
+ findlib(chainlinks[i], 1, &moves[num_moves++]);
+ }
+ }
+
+ if (is_self_atari(*defense_point, eye_color)) {
+ if (approxlib(*defense_point, eye_color, 1, &moves[num_moves]))
+ num_moves++;
+ }
+
+ for (k = 0; k < num_moves; k++) {
+ int i;
+
+ for (i = 0; i < k; i++) {
+ if (moves[i] == moves[k])
+ break;
+ }
+
+ if (i ==k
+ && trymove(moves[k], eye_color, "read_eye",
+ NO_MOVE, EMPTY, NO_MOVE)) {
+ if (safe_move(*defense_point, eye_color) == WIN) {
+ *defense_point = moves[k];
+ popgo();
+ break;
+ }
+
+ popgo();
+ }
+ }
+ }
+
if (add_moves) {
if (eye_color == color) {
for (k = 0; k < best_vp->num_defenses; k++)
@@ -2393,6 +2451,7 @@ test_eyeshape(int eyesize, int *eye_vert
verbose = save_verbose;
}
+
/********************************************************************
* The following static functions are helpers for analyze_eyegraph()
* further down. The purpose is to evaluate eye graphs according to
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnugo-devel] read_eye() patch,
Paul Pogonyshev <=