[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]  


Eyes and Half Eyes

The purpose of this document is to describe the algorithm used in GNU Go 2.6 to determine eyes.

Local games

Each connected eyespace of a dragon affords a local game which yields a local game tree. The score of this local game is the number of eyes it yields. Usually if the players take turns and make optimal moves, the end scores will differ by 0 or 1. In this case, the local game may be represented by a single number, which is an integer or half integer. Thus if `n(O)' is the score if `O' moves first, both players alternate (no passes) and make alternate moves, and similarly `n(X)', the game can be represented by `{n(O)|n(X)}'. Thus {1|1} is an eye, {2|1} is an eye plus a half eye, etc.

The exceptional game {2|0} can occur, though rarely. We call an eyespace yielding this local game a CHIMERA. The dragon is alive if any of the local games ends up with a score of 2 or more, so {2|1} is not different from {3|1}. Thus {3|1} is NOT a chimera.

Here is an example of a chimera:

XXXXX
XOOOX
XO.OOX
XX..OX
XXOOXX
XXXXX

Eye spaces

In order that each eyespace be assignable to a dragon, it is necessary that all the dragons surrounding it be amalgamated (see section Amalgamation). This is the function of dragon_eye().

An EYE SPACE for a black dragon is a collection of vertices adjacent to a dragon which may not yet be completely closed off, but which can potentially become eyespace. If an open eye space is sufficiently large, it will yield two eyes. Vertices at the edge of the eye space (adjacent to empty vertices outside the eye space) are called MARGINAL.

Here is an example from a game:


 |. X . X X . . X O X O 
 |X . . . . . X X O O O
 |O X X X X . . X O O O
 |O O O O X . O X O O O
 |. . . . O O O O X X O
 |X O . X X X . . X O O
 |X O O O O O O O X X O
 |. X X O . O X O . . X
 |X . . X . X X X X X X
 |O X X O X . X O O X O

Here the `O' dragon which is surrounded in the center has open eye space. In the middle of this open eye space are three dead `X' stones. This space is large enough that O cannot be killed. We can abstract the properties of this eye shape as follows. Marking certain vertices as follows:


 |- X - X X - - X O X O 
 |X - - - - - X X O O O
 |O X X X X - - X O O O
 |O O O O X - O X O O O
 |! . . . O O O O X X O
 |X O . X X X . ! X O O
 |X O O O O O O O X X O
 |- X X O - O X O - - X
 |X - - X - X X X X X X
 |O X X O X - X O O X O

the shape in question has the form:


!...
  .XXX.!

The marginal vertices are marked with an exclamation point (`!'). The captured `X' stones inside the eyespace are naturally marked `X'.

The precise algorithm by which the eye spaces are determined is somewhat complex. Documentation of this algorithm is in the comments in the source to the function make_domains() in `src/optics.c'.

The eyespaces can be conveniently displayed using a colored ascii diagram by running gnugo -E.

The eyespace as local game

In the abstraction, an eyespace consists of a set of vertices labelled:


!  .  X

Tables of many eyespaces are found in the database `patterns/eyes.db'. Each of these may be thought of as a local game. The result of this game is listed after the eyespace in the form :max,min, where max is the number of eyes the pattern yields if `O' moves first, while min is the number of eyes the pattern yields if `X' moves first. The player who owns the eye space is denoted `O' throughout this discussion. Since three eyes are no better than two, there is no attempt to decide whether the space yields two eyes or three, so max never exceeds 2. Patterns with min>1 are omitted from the table.

For example, we have:

Pattern 1

  x
!x*x

:2,1

Here notation is as above, except that `x' means `X' or EMPTY. The result of the pattern is not different if `X' has stones at these vertices or not.

We may abstract the local game as follows. The two players `O' and `X' take turns moving, or either may pass.

RULE 1: `O' for his move may remove any vertex marked `!' or marked `.' .

RULE 2: `X' for his move may replace a `.' by an `X'.

RULE 3: `X' may remove a `!'. In this case, each `.' adjacent to the "!" which is removed becomes a "!" . If an "`X'" adjoins the "!" which is removed, then that "`X'" and any which are connected to it are also removed. Any `.' which are adjacent to the removed `X''s then become `.'

Thus if `O' moves first he can transform the eyeshape in the above example to:

 ...            or      !...
  .XXX.!                  .XXX.

However if `X' moves he may remove the `!' and the `.'s adjacent to the `!' become `!' themselves. Thus if `X' moves first he may transform the eyeshape to:

 !..           or    !..
  .XXX.!              .XXX!

NOTE: A nuance which is that after the `X:1', `O:2' exchange below, `O' is threatening to capture three X stones, hence has a half eye to the left of 2. This is subtle, and there are other such subtleties which our abstraction will not capture. Some of these at least can be dealt with by a refinements of the scheme, but we will content ourselves for the time being with a simplified


 |- X - X X - - X O X O 
 |X - - - - - X X O O O
 |O X X X X - - X O O O
 |O O O O X - O X O O O
 |1 2 . . O O O O X X O
 |X O . X X X . 3 X O O
 |X O O O O O O O X X O
 |- X X O - O X O - - X
 |X - - X - X X X X X X
 |O X X O X - X O O X O

We will not attempt to characterize the terminal states of the local game (some of which could be seki) or the scoring.

An example

Here is a local game which yields exactly one eye, no matter who moves first:


!
...
...!

Here are some variations, assuming `O' moves first.

!        (start position)
...
...!

...      (after `O''s move)
...!

... 
..!

... 
..

.X.       (nakade)
..

Here is another variation:


!         (start)
...
...!

!         (after `O''s move)
. .
...!

!         (after `X''s move)
. .
..X!

. .
..X!

. !
.!

Graphs

It is a useful observation that the local game associated with an eyespace depends only on the underlying graph, which as a set consists of the set of vertices, in which two elements are connected by an edge if and only if they are adjacent on the Go board. For example the two eye shapes:


..
 ..

and

....

though distinct in shape have isomorphic graphs, and consequently they are isomorphic as local games. This reduces the number of eyeshapes in the database `patterns/eyes.db'.

A further simplification is obtained through our treatment of half eyes and false eyes. Such patterns are tabulated in the database hey.h. During make_worms, which runs before the eye space analysis, the half eye and false eye patterns are tabulated in the array half_eye.

A half eye is isomorphic to the pattern (!.) . To see this, consider the following two eye shapes:

XOOOOOO
X.....O
XOOOOOO

and:

XXOOOOO
XOa...O
XbOOOOO
XXXXXX

These are equivalent eyeshapes, with isomorphic local games {2|1}. The first has shape:


!....

The second eyeshape has a half eye at a which is taken when `O' or `X' plays at `b'. This is found by the topological criterion (see section Topology of Half Eyes and False Eyes).

ooo      half eye
OhO
*OX

and it is recorded in the half_eye array as follows. If (i,j) are the coordinates of the point `a', half_eye[i][j].type==HALF_EYE and (half_eye[i][j].ki, half_eye[i][j].kj) are the coordinates of `b'.

The graph of the eye_shape, ostensibly `....' is modified by replacing the left `.' by `!'.

Eye shape analysis

The patterns in `patterns/eyes.db' are compiled into graphs represented essentially by linked lists in `patterns/eyes.c'.

Each actual eye space as it occurs on the board is also compiled into a graph. Half eyes are handled as follows. Referring to the example

XXOOOOO
XOa...O
XbOOOOO
XXXXXX

repeated from the preceding discussion, the vertex at `b' is added to the eyespace as a marginal vertex. The adjacency condition in the graph is a macro (in `optics.c'): two vertices are adjacent if they are physically adjacent, or if one is a half eye and the other is its key point.

In recognize_eyes, each such graph arising from an actual eyespace is matched against the graphs in `eyes.c'. If a match is found, the result of the local game is known. If a graph cannot be matched, its local game is assumed to be {2|2}.

Topology of Half Eyes and False Eyes

A HALF EYE is a pattern where an eye may or may not materialize, depending on who moves first. Here is a half eye for O:


   OOOX
   O..X
   OOOX

A FALSE EYE is a cave which cannot become an eye. Here is are two examples of false eyes for O:


   OOX         OOX
   O.O         O.OO
   XOO         OOX

We describe now the topological algorithm used to find half eyes and false eyes.

False eyes and half eyes can locally be characterized by the status of the diagonal intersections from an eye space. For each diagonal intersection, which is not within the eye space, there are three distinct possibilities:

We give the first possibility a value of two, the second a value of one, and the last a value of zero. Summing the values for the diagonal intersections, we have the following criteria:

If the eye space is on the edge, the numbers above should be decreased by 2. An alternative approach is to award diagonal points which are outside the board a value of 1. To obtain an exact equivalence we must however give value 0 to the points diagonally off the corners, i.e. the points with both coordinates out of bounds.

The algorithm to find all topologically false eyes and half eyes is:

For all eye space points with at most one neighbor in the eye space, evaluate the status of the diagonal intersections according to the criteria above and classify the point from the sum of the values.


[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]