Previous: False Margins, Up: Eyes
The public function make_domains()
calls the function
make_primary_domains()
which is static in optics.c. It's purpose
is to compute the domains of influence of each color, used in determining eye
shapes. Note: the term influence as used here is distinct from the
influence in influence.c.
For this algorithm the strings which are not lively are invisible. Ignoring these, the algorithm assigns friendly influence to
Thus in the following diagram, `e' would be assigned friendly influence if `a' and `b' have friendly influence, or `a' and `d'. It is not sufficent for `b' and `d' to have friendly influence, because they are not adjoining.
uabc def ghi
The constraint that the two adjoining vertices not lie on the first line prevents influence from leaking under a stone on the third line.
The first CAVEAT alluded to above is that even if `a' and `b' have friendly influence, this does not cause `e' to have friendly influence if there is a lively opponent stone at `d'. This constraint prevents influence from leaking past knight's move extensions.
The second CAVEAT is that even if `a' and `b' have friendly influence this does not cause `e' to have influence if there are lively opponent stones at `u' and at `c'. This prevents influence from leaking past nikken tobis (two space jumps).
The corner vertices are handled slightly different.
+--- |ab |cd
We get friendly influence at `a' if we have friendly influence at `b' or `c' and no lively unfriendly stone at `b', `c' or `d'.
Here are the public functions in optics.c, except some simple access functions used by autohelpers. The statically declared functions are documented in the source code.
void make_domains(struct eye_data b_eye[BOARDMAX], struct eye_data w_eye[BOARDMAX], int owl_call)
This function is called frommake_dragons()
and fromowl_determine_life()
. It marks the black and white domains (eyeshape regions) and collects some statistics about each one.
void partition_eyespaces(struct eye_data eye[BOARDMAX], int color)
Find connected eyespace components and compute relevant statistics.
void propagate_eye(int origin, struct eye_data eye[BOARDMAX])
propagate_eye(origin) copies the data at the (origin) to the rest of the eye (invariant fields only).
int find_eye_dragons(int origin, struct eye_data eye[BOARDMAX], int eye_color, int dragons[], int max_dragons)
Find the dragon or dragons surrounding an eye space. Up to max_dragons dragons adjacent to the eye space are added to the dragon array, and the number of dragons found is returned.
void compute_eyes(int pos, struct eyevalue *value, int *attack_point, int *defense_point, struct eye_data eye[BOARDMAX], struct half_eye_data heye[BOARDMAX], int add_moves)
Given an eyespace with originpos
, this function computes the minimum and maximum numbers of eyes the space can yield. If max and min are different, then vital points of attack and defense are also generated. Ifadd_moves == 1
, this function may add a move_reason forcolor
at a vital point which is found by the function. Ifadd_moves == 0
, setcolor = EMPTY.
void compute_eyes_pessimistic(int pos, struct eyevalue *value, int *pessimistic_min, int *attack_point, int *defense_point, struct eye_data eye[BOARDMAX], struct half_eye_data heye[BOARDMAX])
This function works like compute_eyes()
, except that it also gives
a pessimistic view of the chances to make eyes. Since it is intended
to be used from the owl code, the option to add move reasons has
been removed.
void add_false_eye(int pos, struct eye_data eye[BOARDMAX], struct half_eye_data heye[BOARDMAX])
turns a proper eyespace into a margin.
int is_eye_space(int pos)
int is_proper_eye_space(int pos)
These functions are used from constraints to identify eye spaces, primarily for late endgame moves.
int max_eye_value(int pos)
Return the maximum number of eyes that can be obtained from the
eyespace at (i, j)
. This is most useful in order to determine
whether the eyespace can be assumed to produce any territory at
all.
int is_marginal_eye_space(int pos)
int is_halfeye(struct half_eye_data heye[BOARDMAX], int pos)
int is_false_eye(struct half_eye_data heye[BOARDMAX], int pos)
These functions simply return information about an eyeshape that has already been analyzed. (They do no real work.)
void find_half_and_false_eyes(int color, struct eye_data eye[BOARDMAX], struct half_eye_data heye[BOARDMAX], int find_mask[BOARDMAX])
Find topological half eyes and false eyes by analyzing the diagonal intersections, as described in the Texinfo documentation (Eyes/Eye Topology).
float topological_eye(int pos, int color, struct eye_data my_eye[BOARDMAX],struct half_eye_data heye[BOARDMAX])
See Texinfo documentation (Eyes:Eye Topology). Returns:Attack and defense points for control of the diagonals are stored in the
- 2 or less if
pos
is a proper eye forcolor
;- between 2 and 3 if the eye can be made false only by ko
- 3 if
pos
is a half eye;- between 3 and 4 if the eye can be made real only by ko
- 4 or more if
pos
is a false eye.heye[]
array.my_eye
is the eye space information with respect tocolor
.
int obvious_false_eye(int pos, int color)
Conservative relative of topological_eye()
. Essentially the same
algorithm is used, but only tactically safe opponent strings on
diagonals are considered. This may underestimate the false/half eye
status, but it should never be overestimated.
void set_eyevalue(struct eyevalue *e, int a, int b, int c, int d)
set parameters into thestruct eyevalue
as follows: (see Eye Local Game Values):struct eyevalue { /* number of eyes if: */ unsigned char a; /* attacker plays first twice */ unsigned char b; /* attacker plays first */ unsigned char c; /* defender plays first */ unsigned char d; /* defender plays first twice */ };
int min_eye_threat(struct eyevalue *e)
Number of eyes if attacker plays first twice (the threat of the first move by attacker).
int min_eyes(struct eyevalue *e)
Number of eyes if attacker plays first followed by alternating play.
int max_eyes(struct eyevalue *e)
Number of eyes if defender plays first followed by alternating play.
int max_eye_threat(struct eyevalue *e)
Number of eyes if defender plays first twice (the threat of the first move by defender).
void add_eyevalues(struct eyevalue *e1, struct eyevalue *e2, struct eyevalue *sum)
Add the eyevalues*e1
and*e2
, leaving the result in *sum. It is safe to letsum
be the same ase1
ore2
.
char * eyevalue_to_string(struct eyevalue *e)
Produces a string containing the eyevalue. Note: the result string is stored in a statically allocated buffer which will be overwritten the next time this function is called.
void test_eyeshape(int eyesize, int *eye_vertices)
/* Test whether the optics code evaluates an eyeshape consistently. */
int analyze_eyegraph(const char *coded_eyegraph, struct eyevalue *value, char *analyzed_eyegraph)
Analyze an eye graph to determine the eye value and vital moves. The eye graph is given by a string which is encoded with `%' for newlines and `O' for spaces. E.g., the eye graph! .X !...is encoded as
OO!%O.X%!...
. (The encoding is needed for the GTP interface to this function.) The result is an eye value and a (nonencoded) pattern showing the vital moves, using the same notation as eyes.db. In the example above we would get the eye value 0112 and the graph (showing ko threat moves).X !.*.If the eye graph cannot be realized, 0 is returned, 1 otherwise.