Updated README: Equal sign not required with `--mode` flag.
[sgk-go] / doc / board.texi
CommitLineData
7eeb782e
AT
1@menu
2* Board Data Structures:: Board Data Structures
3* The Board Array:: One-dimensional board array
4* Incremental Board:: Incremental board data structures
5* Some Board Functions:: Explanation of some board functions
6@end menu
7
8The foundation of the GNU Go engine is a library of very efficient
9routines for handling go boards. This board library, called
10@file{libboard}, can be used for those programs that only need a
11basic go board but no AI capability. One such program is
12@file{patterns/joseki.c}, which compiles joseki pattern
13databases from SGF files.
14
15If you want to use the board library in your own program, you need all
16the .c-files listed under libboard_SOURCES in engine/Makefile.am, and
17the files in the directories sgf/ and utils/. Then you should include
18engine/board.h in your code.
19
20The library consists of the following files:
21
22@itemize
23@item @file{board.h}
24@quotation
25The public interface to the board library.
26@end quotation
27
28@item @file{board.c}
29@quotation
30The basic board code. It uses incremental algorithms for keeping track
31of strings and liberties on the go board.
32@end quotation
33
34@item @file{boardlib.c}
35@quotation
36This contains all global variable of the board library.
37@end quotation
38
39@item @file{hash.c}
40@quotation
41Code for hashing go positions.
42@end quotation
43
44@item @file{sgffile.c}
45@quotation
46Implementation of output file in SGF format.
47@end quotation
48
49@item @file{printutils.c}
50@quotation
51Utilities for printing go boards and other things.
52@end quotation
53
54@end itemize
55
56To use the board library, you must include @file{liberty.h} just like
57when you use the whole engine, but of course you cannot use all the
58functions declared in it, i.e. the functions that are part of the
59engine, but not part of the board library. You must link your
60application with @code{libboard.a}.
61
62@node Board Data Structures
63@section Board Data structures
64
65The basic data structures of the board correspond tightly to the
66@code{board_state} struct described in @xref{The Board State}. They are all
67stored in global variables for efficiency reasons, the most important of which
68are:
69
70@example
71@group
72
73int board_size;
74Intersection board[MAXSIZE];
75int board_ko_pos;
76
77float komi;
78int white_captured;
79int black_captured;
80
81Hash_data hashdata;
82@end group
83@end example
84
85The description of the @code{Position} struct is applicable to these
86variables also, so we won't duplicate it here. All these variables are
87globals for performance reasons. Behind these variables, there are a
88number of other private data structures. These implement incremental
89handling of strings, liberties and other properties
90(@pxref{Incremental Board}). The variable @code{hashdata} contains information
91about the hash value for the current position (@pxref{Hashing}).
92
93These variables should never be manipulated directly, since they are
94only the front end for the incremental machinery. They can be read, but
95should only be written by using the functions described in the next
96section. If you write directly to them, the incremental data structures
97will become out of sync with each other, and a crash is the likely
98result.
99
100@node The Board Array
101@section The Board Array
102
103GNU Go represents the board in a one-dimensional array called
104@code{board}. For some purposes a two dimensional indexing of the
105board by parameters @code{(i,j)} might be used.
106
107The @code{board} array includes out-of-board markers around the
108board. To make the relation to the old two-dimensional board
109representation clear, this figure shows how the 1D indices correspond
110to the 2D indices when MAX_BOARD is 7.
111
112@example
113@group
114 j -1 0 1 2 3 4 5 6
115i +----------------------------------
116-1| 0 1 2 3 4 5 6 7
117 0| 8 9 10 11 12 13 14 15
118 1| 16 17 18 19 20 21 22 23
119 2| 24 25 26 27 28 29 30 31
120 3| 32 33 34 35 36 37 38 39
121 4| 40 41 42 43 44 45 46 47
122 5| 48 49 50 51 52 53 54 55
123 6| 56 57 58 59 60 61 62 63
124 7| 64 65 66 67 68 69 70 71 72
125@end group
126@end example
127
128To convert between a 1D index @code{pos} and a 2D index @code{(i,j)},
129the macros @code{POS}, @code{I}, and @code{J} are provided, defined as
130below:
131
132@example
133#define POS(i, j) ((MAX_BOARD + 2) + (i) * (MAX_BOARD + 1) + (j))
134#define I(pos) ((pos) / (MAX_BOARD + 1) - 1)
135#define J(pos) ((pos) % (MAX_BOARD + 1) - 1)
136@end example
137
138All 1D indices not corresponding to points on the board have the out
139of board marker value @code{GRAY}. Thus if @code{board_size} and
140@code{MAX_BOARD} both are 7, this looks like
141
142@example
143@group
144 j -1 0 1 2 3 4 5 6
145i +----------------------------------
146-1| # # # # # # # #
147 0| # . . . . . . .
148 1| # . . . . . . .
149 2| # . . . . . . .
150 3| # . . . . . . .
151 4| # . . . . . . .
152 5| # . . . . . . .
153 6| # . . . . . . .
154 7| # # # # # # # # #
155@end group
156@end example
157
158The indices marked @samp{#} have value @code{GRAY}.
159If @code{MAX_BOARD} is 7 and @code{board_size} is only 5:
160
161@example
162@group
163 j -1 0 1 2 3 4 5 6
164i +----------------------------------
165-1| # # # # # # # #
166 0| # . . . . . # #
167 1| # . . . . . # #
168 2| # . . . . . # #
169 3| # . . . . . # #
170 4| # . . . . . # #
171 5| # # # # # # # #
172 6| # # # # # # # #
173 7| # # # # # # # # #
174@end group
175@end example
176
177Navigation on the board is done by the @code{SOUTH}, @code{WEST},
178@code{NORTH}, and @code{EAST} macros,
179
180@example
181#define NS (MAX_BOARD + 1)
182#define WE 1
183#define SOUTH(pos) ((pos) + NS)
184#define WEST(pos) ((pos) - 1)
185#define NORTH(pos) ((pos) - NS)
186#define EAST(pos) ((pos) + 1)
187@end example
188
189There are also shorthand macros @code{SW}, @code{NW}, @code{NE},
190@code{SE}, @code{SS}, @code{WW}, @code{NN}, @code{EE} for two step
191movements.
192
193Any movement from a point on the board to an adjacent or diagonal
194vertex is guaranteed to produce a valid index into the board array, and
195the color found is GRAY if it is not on the board. To do explicit tests
196for out of board there are two macros
197
198@example
199#define ON_BOARD(pos) (board[pos] != GRAY)
200#define ON_BOARD1(pos) (((unsigned) (pos) < BOARDSIZE) && board[pos] != GRAY)
201@end example
202
203where the first one should be used in the algorithms and the second
204one is useful for assertion tests.
205
206The advantage of a one-dimensional board array is that it gives a
207significant performance advantage. We need only one variable to determine
208a board position, which means that many functions need less arguments. Also,
209often one computation is sufficient for 1D-coordinate where we would need
210two with two 2D-coordinates: If we, for example, want to have the
211coordinate of the upper right of @code{pos}, we can do this with
212@code{NORTH(EAST(pos))} instead of @code{(i+1, j-1)}.
213
214@strong{Important}: The 2D coordinate @code{(-1,-1)}, which is used for
215pass and sometimes to indicate no point, maps to the 1D coordinate
216@code{0}, not to @code{-1}. Instead of a plain @code{0}, use one of the
217macros @code{NO_MOVE} or @code{PASS_MOVE}.
218
219A loop over multiple directions is straightforwardly written:
220
221@example
222 for (k = 0; k < 4; k++) @{
223 int d = delta[k];
224 do_something(pos + d);
225 @}
226@end example
227
228The following constants are useful for loops over the entire board and
229allocation of arrays with a 1-1 mapping to the board.
230
231@example
232#define BOARDSIZE ((MAX_BOARD + 2) * (MAX_BOARD + 1) + 1)
233#define BOARDMIN (MAX_BOARD + 2)
234#define BOARDMAX (MAX_BOARD + 1) * (MAX_BOARD + 1)
235@end example
236
237@code{BOARDSIZE} is the actual size of the 1D board array,
238@code{BOARDMIN} is the first index corresponding to a point on the
239board, and @code{BOARDMAX} is one larger than the last index corresponding to
240a point on the board.
241
242Often one wants to traverse the board, carrying out some function
243at every vertex. Here are two possible ways of doing this:
244
245@example
246 int m, n;
247 for (m = 0; m < board_size; m++)
248 for (n = 0; n < board_size; n++) @{
249 do_something(POS(m, n));
250 @}
251@end example
252
253Or:
254
255@example
256 int pos;
257 for (pos = BOARDMIN; pos < BOARDMAX; pos++) @{
258 if (ON_BOARD(pos))
259 do_something(pos);
260 @}
261@end example
262
263
264@node Incremental Board
265@section Incremental Board data structures
266
267In addition to the global board state, the algorithms in @file{board.c}
268implement a method of incremental updates that keeps track of the
269following information for each string:
270
271@itemize @bullet
272@item The color of the string.
273@item Number of stones in the string.
274@item Origin of the string, i.e. a canonical reference point, defined
275to be the stone with smallest 1D board coordinate.
276@item A list of the stones in the string.
277@item Number of liberties.
278@item A list of the liberties. If there are too many liberties the list is
279truncated.
280@item The number of neighbor strings.
281@item A list of the neighbor strings.
282@end itemize
283
284The basic data structure is
285
286@example
287struct string_data @{
288 int color; /* Color of string, BLACK or WHITE */
289 int size; /* Number of stones in string. */
290 int origin; /* Coordinates of "origin", i.e. */
291 /* "upper left" stone. */
292 int liberties; /* Number of liberties. */
293 int libs[MAX_LIBERTIES]; /* Coordinates of liberties. */
294 int neighbors; /* Number of neighbor strings */
295 int neighborlist[MAXCHAIN]; /* List of neighbor string numbers. */
296 int mark; /* General purpose mark. */
297@};
298
299struct string_data string[MAX_STRINGS];
300@end example
301
302It should be clear that almost all information is stored in the
303@code{string} array. To get a mapping from the board coordinates to the
304@code{string} array we have
305
306@example
307static int string_number[BOARDMAX];
308@end example
309
310@noindent
311which contains indices into the @code{string} array. This information is only
312valid at nonempty vertices, however, so it is necessary to first
313verify that @code{board[pos] != EMPTY}.
314
315The @code{string_data} structure does not include an array of the stone
316coordinates. This information is stored in a separate array:
317
318@example
319static int next_stone[BOARDMAX];
320@end example
321
322This array implements cyclic linked lists of stones. Each vertex
323contains a pointer to another (possibly the same) vertex. Starting at
324an arbitrary stone on the board, following these pointers should
325traverse the entire string in an arbitrary order before coming back to
326the starting point. As for the 'string_number' array, this information
327is invalid at empty points on the board. This data structure has the
328good properties of requiring fixed space (regardless of the number of
329strings) and making it easy to add a new stone or join two strings.
330
331Additionally the code makes use of some work variables:
332
333@example
334static int ml[BOARDMAX];
335static int liberty_mark;
336static int string_mark;
337static int next_string;
338static int strings_initialized = 0;
339@end example
340
341The @code{ml} array and @code{liberty_mark} are used to "mark" liberties on
342the board, e.g. to avoid counting the same liberty twice. The convention is
343that if @code{ml[pos]} has the same value as @code{liberty_mark}, then
344@code{pos} is marked. To clear all marks it suffices to increase the value
345of @code{liberty_mark}, since it is never allowed to decrease.
346
347The same relation holds between the @code{mark} field of the @code{string_data}
348structure and @code{string_mark}. Of course these are used for marking
349individual strings.
350
351@code{next_string} gives the number of the next available entry in the
352@code{string} array. Then @code{strings_initialized} is set to one when
353all data structures are known to be up to date. Given an arbitrary board
354position in the @samp{board} array, this is done by calling
355@code{incremental_board_init()}. It is not necessary to call this
356function explicitly since any other function that needs the information
357does this if it has not been done.
358
359The interesting part of the code is the incremental update of the data
360structures when a stone is played and subsequently removed. To
361understand the strategies involved in adding a stone it is necessary
362to first know how undoing a move works. The idea is that as soon as
363some piece of information is about to be changed, the old value is
364pushed onto a stack which stores the value and its address. The stack
365is built from the following structures:
366
367@example
368struct change_stack_entry @{
369 int *address;
370 int value;
371@};
372
373struct change_stack_entry change_stack[STACK_SIZE];
374int change_stack_index;
375@end example
376
377@noindent
378and manipulated with the macros
379
380@example
381BEGIN_CHANGE_RECORD()
382PUSH_VALUE(v)
383POP_MOVE()
384@end example
385
386Calling @code{BEGIN_CHANGE_RECORD()} stores a null pointer in the address
387field to indicate the start of changes for a new move. As mentioned
388earlier @code{PUSH_VALUE()} stores a value and its corresponding address.
389Assuming that all changed information has been duly pushed onto the
390stack, undoing the move is only a matter of calling @code{POP_MOVE()},
391which simply assigns the values to the addresses in the reverse order
392until the null pointer is reached. This description is slightly
393simplified because this stack can only store 'int' values and we need
394to also store changes to the board. Thus we have two parallel stacks
395where one stores @code{int} values and the other one stores
396@code{Intersection} values.
397
398When a new stone is played on the board, first captured opponent
399strings, if any, are removed. In this step we have to push the board
400values and the @code{next_stone} pointers for the removed stones, and
401update the liberties and neighbor lists for the neighbors of the
402removed strings. We do not have to push all information in the
403'string' entries of the removed strings however. As we do not reuse
404the entries they will remain intact until the move is pushed and they
405are back in use.
406
407After this we put down the new stone and get three distinct cases:
408
409@enumerate
410@item The new stone is isolated, i.e. it has no friendly neighbor.
411@item The new stone has exactly one friendly neighbor.
412@item The new stone has at least two friendly neighbors.
413@end enumerate
414
415The first case is easiest. Then we create a new string by using the
416number given by @code{next_string} and increasing this variable. The string
417will have size one, @code{next_stone} points directly back on itself, the
418liberties can be found by looking for empty points in the four
419directions, possible neighbor strings are found in the same way, and
420those need also to remove one liberty and add one neighbor.
421
422In the second case we do not create a new string but extend the
423neighbor with the new stone. This involves linking the new stone into
424the cyclic chain, if needed moving the origin, and updating liberties
425and neighbors. Liberty and neighbor information also needs updating
426for the neighbors of the new stone.
427
428In the third case finally, we need to join already existing strings.
429In order not to have to store excessive amounts of information, we
430create a new string for the new stone and let it assimilate the
431neighbor strings. Thus all information about those can simply be left
432around in the 'string' array, exactly as for removed strings. Here it
433becomes a little more complex to keep track of liberties and neighbors
434since those may have been shared by more than one of the joined
435strings. Making good use of marks it all becomes rather
436straightforward anyway.
437
438The often used construction
439
440@example
441 pos = FIRST_STONE(s);
442 do @{
443 ...
444 pos = NEXT_STONE(pos);
445 @} while (!BACK_TO_FIRST_STONE(s, pos));
446@end example
447
448@noindent
449traverses the stones of the string with number @samp{s} exactly once,
450with @code{pos} holding the coordinates. In general @code{pos} is
451used as board coordinate and @samp{s} as an index into the
452@code{string} array or sometimes a pointer to an entry in the
453@code{string} array.
454
455@node Some Board Functions
456@section Some Board Functions
457
458@strong{Reading}, often called @strong{search} in computer game
459theory, is a fundamental process in GNU Go. This is the process
460of generating hypothetical future boards in order to determine
461the answer to some question, for example "can these stones live."
462Since these are hypothetical future positions, it is important
463to be able to undo them, ultimately returning to the present
464board. Thus a move stack is maintained during reading. When
465a move is tried, by the function @code{trymove}, or its
466variant @code{tryko}. This function pushes the current board
467on the stack and plays a move. The stack pointer @code{stackp},
468which keeps track of the position, is incremented. The function
469@code{popgo()} pops the move stack, decrementing @code{stackp} and
470undoing the last move made.
471
472Every successful @code{trymove()} must be matched with a @code{popgo()}.
473Thus the correct way of using this function is:
474
475@example
476@group
477
478 if (trymove(pos, color, ... )) @{
479 ... [potentially lots of code here]
480 popgo();
481 @}
482
483@end group
484@end example
485
486@noindent
487
488In case the move is a ko capture, the legality of the capture is subject to
489the komaster scheme (@pxref{Ko}).
490
491@itemize @bullet
492@item @code{int trymove(int pos, int color, const char *message)}
493@findex trymove
494@quotation
495Returns true if @code{(pos)} is a legal move for @code{color}. In that
496case, it pushes the board on the stack and makes the move, incrementing
497@code{stackp}. If the reading code is recording reading variations (as
498with @option{--decide-string} or with @option{-o}), the string
499@code{*message} will be inserted in the SGF file as a comment. The
500comment will also refer to the string at @code{str} if this is not
501@code{0}. The value of @code{str} can be NO_MOVE if it is not needed but
502otherwise the location of @code{str} is included in the comment.
503@end quotation
504@item @code{int tryko(int pos, int color, const char *message)}
505@findex tryko
506@quotation
507@code{tryko()} pushes the position onto the stack, and makes a move
508@code{pos} of @code{color}. The move is allowed even if it is an
509illegal ko capture. It is to be imagined that @code{color} has made an
510intervening ko threat which was answered and now the continuation is to
511be explored. Return 1 if the move is legal with the above
512caveat. Returns zero if it is not legal because of suicide.
513@end quotation
514
515@item @code{void popgo()}
516@findex popgo
517@quotation
518Pops the move stack. This function must (eventually) be called after a
519succesful @code{trymove} or @code{tryko} to restore the board
520position. It undoes all the changes done by the call to
521@code{trymove/tryko} and leaves the board in the same state as it was
522before the call.
523
524@strong{NOTE}: If @code{trymove/tryko} returns @code{0}, i.e. the tried
525move was not legal, you must @strong{not} call @code{popgo}.
526@end quotation
527
528@item @code{int komaster_trymove(int pos, int color, const char *message, int str, int *is_conditional_ko, int consider_conditional_ko)}
529@findex komaster_trymove
530@quotation
531Variation of @code{trymove}/@code{tryko} where ko captures (both
532conditional and unconditional) must follow a komaster scheme
533(@pxref{Ko}).
534@end quotation
535
536@end itemize
537
538As you see, @code{trymove()} plays a move which can be easily
539retracted (with @code{popgo()}) and it is call thousands of
540times per actual game move as GNU Go analyzes the board position.
541By contrast the function @code{play_move()} plays a move which
542is intended to be permanent, though it is still possible to
543undo it if, for example, the opponent retracts a move.
544
545@itemize @bullet
546@item @code{void play_move(int pos, int color)}
547@findex play_move
548@quotation
549Play a move. If you want to test for legality you should first call
550@code{is_legal()}. This function strictly follows the algorithm:
551@enumerate
552@item Place a stone of given color on the board.
553@item If there are any adjacent opponent strings without liberties,
554remove them and increase the prisoner count.
555@item If the newly placed stone is part of a string without liberties,
556remove it and increase the prisoner count.
557@end enumerate
558In spite of the name ``permanent move'', this move can (usually) be
559unplayed by @code{undo_move()}, but it is significantly more costly than
560unplaying a temporary move. There are limitations on the available
561move history, so under certain circumstances the move may not be
562possible to unplay at a later time.
563@end quotation
564@item @code{int undo_move(int n)}
565@findex undo_move
566@quotation
567Undo @samp{n} permanent moves. Returns 1 if successful and 0 if it fails.
568If @samp{n} moves cannot be undone, no move is undone.
569@end quotation
570@end itemize
571
572Other board functions are documented in @xref{Board Utilities}.
573