Commit | Line | Data |
---|---|---|
7eeb782e AT |
1 | If you want to write your own interface to GNU Go, or if you want to |
2 | create a go application using the GNU Go engine, this chapter is of | |
3 | interest to you. | |
4 | ||
5 | First an overview: GNU Go consists of two parts: the GNU Go @i{engine} | |
6 | and a program (user interface) which uses this engine. These are linked | |
7 | together into one binary. The current program implements the following | |
8 | user modes: | |
9 | ||
10 | @itemize @bullet | |
11 | @item An interactive board playable on ASCII terminals | |
12 | @item solo play - GNU Go plays against itself | |
13 | @item replay - a mode which lets the user investigate moves in an existing | |
14 | SGF file. | |
15 | @item GMP - Go Modem Protocol, a protocol for automatic play between two | |
16 | computers. | |
17 | @item GTP - Go Text Protocol, a more general go protocol, @pxref{GTP}. | |
18 | @end itemize | |
19 | @cindex API | |
20 | ||
21 | The GNU Go engine can be used in other applications. For example, supplied | |
22 | with GNU Go is another program using the engine, called @file{debugboard}, | |
23 | in the directory @file{interface/debugboard/}. The program debugboard lets the | |
24 | user load SGF files and can then interactively look at different properties of | |
25 | the position such as group status and eye status. | |
26 | ||
27 | The purpose of this Chapter is to show how to interface your own | |
28 | program such as @code{debugboard} with the GNU Go engine. | |
29 | ||
30 | Figure 1 describes the structure of a program using the GNU Go | |
31 | engine. | |
32 | ||
33 | @example | |
34 | @group | |
35 | +-----------------------------------+ | |
36 | | | | |
37 | | Go application | | |
38 | | | | |
39 | +-----+----------+------+ | | |
40 | | | | | | | |
41 | | | Game | | | | |
42 | | | handling | | | | |
43 | | | | | | | |
44 | | +----+-----+ | | | |
45 | | SGF | Move | | | |
46 | | handling | generation | | | |
47 | | | | | | |
48 | +----------+------------+-----------+ | |
49 | | | | |
50 | | Board handling | | |
51 | | | | |
52 | +-----------------------------------+ | |
53 | ||
54 | Figure 1: The structure of a program using the GNU Go engine | |
55 | ||
56 | @end group | |
57 | @end example | |
58 | ||
59 | The foundation is a library called @code{libboard.a} which provides | |
60 | efficient handling of a go board with rule checks for moves, with | |
61 | incremental handling of connected strings of stones and with methods to | |
62 | efficiently hash go positions. | |
63 | ||
64 | On top of this, there is a library which helps the application use | |
65 | Smart Game Format (SGF) files, with complete handling of game trees in | |
66 | memory and in files. This library is called @code{libsgf.a} | |
67 | ||
68 | The main part of the code within GNU Go is the move generation | |
69 | library which given a position generates a move. This part of the | |
70 | engine can also be used to manipulate a go position, add or remove | |
71 | stones, do tactical and strategic reading and to query the engine for | |
72 | legal moves. These functions are collected into @code{libengine.a}. | |
73 | ||
74 | The game handling code helps the application programmer keep tracks | |
75 | of the moves in a game. Games can be saved to | |
76 | SGF files and then later be read back again. These are also within | |
77 | @code{libengine.a}. | |
78 | ||
79 | The responsibility of the application is to provide the user with a | |
80 | user interface, graphical or not, and let the user interact with the | |
81 | engine. | |
82 | ||
83 | @menu | |
84 | * Getting Started:: How to use the engine in your program | |
85 | * Basic Data Structures:: Basic Data Structures in the Engine | |
86 | * The Board State:: The board_state `struct' | |
87 | * Positional Functions:: Functions which manipulate a Position | |
88 | @end menu | |
89 | ||
90 | @node Getting Started | |
91 | ||
92 | @section How to use the engine in your own program: getting started | |
93 | ||
94 | To use the GNU Go engine in your own program you must include | |
95 | the file @file{gnugo.h}. This file describes the whole public API. There is | |
96 | another file, @file{liberty.h}, which describes the internal interface within | |
97 | the engine. If you want to make a new module within the engine, e.g. for | |
98 | suggesting moves you will have to include this file also. In this section we | |
99 | will only describe the public interface. | |
100 | ||
101 | @findex init_gnugo | |
102 | Before you do anything else, you have to call the function | |
103 | @code{init_gnugo()}. This function initializes everything within the engine. | |
104 | It takes one parameter: the number of megabytes the engine can use for | |
105 | the internal hash table. In addition to this the engine will use a few | |
106 | megabytes for other purposes such as data describing groups (liberties, | |
107 | life status, etc), eyes and so on. | |
108 | ||
109 | @node Basic Data Structures | |
110 | @section Basic Data Structures in the Engine | |
111 | @cindex data structures | |
112 | @cindex position struct | |
113 | ||
114 | ||
115 | There are some basic definitions in gnugo.h which are used | |
116 | everywhere. The most important of these are the numeric declarations of | |
117 | colors. Each intersection on the board is represented by one of these: | |
118 | ||
119 | @example | |
120 | @group | |
121 | ||
122 | color value | |
123 | EMPTY 0 | |
124 | WHITE 1 | |
125 | BLACK 2 | |
126 | ||
127 | @end group | |
128 | @end example | |
129 | ||
130 | There is a macro, @code{OTHER_COLOR(color)} which can be used to get the | |
131 | other color than the parameter. This macro can only be used on @code{WHITE} | |
132 | or @code{BLACK}, but not on @code{EMPTY}. | |
133 | @findex OTHER_COLOR | |
134 | ||
135 | GNU Go uses two different representations of the board, for | |
136 | most purposes a one-dimensional one, but for a few purposes a | |
137 | two dimensional one (@pxref{Libboard}). The one-dimensional | |
138 | board was introduced before GNU Go 3.2, while the two-dimensional | |
139 | board dates back to the ancestral program written by Man Lung Li | |
140 | before 1995. The API still uses the two-dimensional board, so | |
141 | the API functions have not changed much since GNU Go 3.0. | |
142 | ||
143 | @node The Board State | |
144 | ||
145 | @section The board_state struct | |
146 | @cindex board_state | |
147 | ||
148 | A basic data structure in the engine is the @code{board_state} struct. | |
149 | This structure is internal to the engine and is defined in @file{liberty.h}. | |
150 | ||
151 | @example | |
152 | @group | |
153 | ||
154 | typedef unsigned char Intersection; | |
155 | ||
156 | struct board_state @{ | |
157 | int board_size; | |
158 | ||
159 | Intersection board[BOARDSIZE]; | |
160 | int board_ko_pos; | |
161 | int black_captured; | |
162 | int white_captured; | |
163 | ||
164 | Intersection initial_board[BOARDSIZE]; | |
165 | int initial_board_ko_pos; | |
166 | int initial_white_captured; | |
167 | int initial_black_captured; | |
168 | int move_history_color[MAX_MOVE_HISTORY]; | |
169 | int move_history_pos[MAX_MOVE_HISTORY]; | |
170 | int move_history_pointer; | |
171 | ||
172 | float komi; | |
173 | int move_number; | |
174 | @}; | |
175 | ||
176 | @end group | |
177 | @end example | |
178 | ||
179 | Here @code{Intersection} stores @code{EMPTY}, @code{WHITE} or | |
180 | @code{BLACK}. It is currently defined as an @code{unsigned char} to make | |
181 | it reasonably efficient in both storage and access time. The board state | |
182 | contains an array of @code{Intersection}'s representing the board. | |
183 | The move history is contained in the struct. Also contained in | |
184 | the struct is the location of a ko (@code{EMPTY}) if the last | |
185 | move was not a ko capture, the komi, the number of captures, and | |
186 | corresponding data for the initial position at the beginning | |
187 | of the move history. | |
188 | ||
189 | @node Positional Functions | |
190 | ||
191 | @section Functions which manipulate a Position | |
192 | ||
193 | All the functions in the engine that manipulate Positions have names | |
194 | prefixed by @code{gnugo_}. These functions still use the two-dimensional | |
195 | representation of the board (@pxref{The Board Array}). Here is a complete | |
196 | list, as prototyped in @file{gnugo.h}: | |
197 | ||
198 | @itemize | |
199 | @item @code{void init_gnugo(float memory)} | |
200 | @findex init_gnugo | |
201 | @quotation | |
202 | Initialize the gnugo engine. This needs to be called | |
203 | once only. | |
204 | @end quotation | |
205 | @item @code{void gnugo_clear_board(int boardsize)} | |
206 | @findex gnugo_clear_board | |
207 | @quotation | |
208 | Clear the board. | |
209 | @end quotation | |
210 | @item @code{void gnugo_set_komi(float new_komi)} | |
211 | @findex gnugo_set_komi | |
212 | @quotation | |
213 | Set the komi. | |
214 | @end quotation | |
215 | @item @code{void gnugo_add_stone(int i, int j, int color)} | |
216 | @findex gnugo_add_stone | |
217 | @quotation | |
218 | Place a stone on the board | |
219 | @end quotation | |
220 | @item @code{void gnugo_remove_stone(int i, int j)} | |
221 | @findex gnugo_remove_stone | |
222 | @quotation | |
223 | Remove a stone from the board | |
224 | @end quotation | |
225 | @item @code{int gnugo_is_pass(int i, int j)} | |
226 | @findex gnugo_is_pass | |
227 | @quotation | |
228 | Return true if (i,j) is PASS_MOVE | |
229 | @end quotation | |
230 | @item @code{void gnugo_play_move(int i, int j, int color)} | |
231 | @findex gnugo_play_move | |
232 | @quotation | |
233 | Play a move and start the clock | |
234 | @end quotation | |
235 | @item @code{int gnugo_undo_move(int n)} | |
236 | @findex gnugo_undo_move | |
237 | @quotation | |
238 | Undo n permanent moves. Returns 1 if successful and 0 if it fails. | |
239 | If n moves cannot be undone, no move is undone. | |
240 | @end quotation | |
241 | @item @code{int gnugo_play_sgfnode(SGFNode *node, int to_move)} | |
242 | @findex gnugo_play_sgfnode | |
243 | @quotation | |
244 | Perform the moves and place the stones from the SGF node on the | |
245 | board. Return the color of the player whose turn it is to move. | |
246 | @end quotation | |
247 | @item @code{int gnugo_play_sgftree(SGFNode *root, int *until, SGFNode **curnode)} | |
248 | @findex gnugo_play_sgftree | |
249 | @quotation | |
250 | Play the moves in ROOT UNTIL movenumber is reached. Return the color of the | |
251 | player whose turn it is to move. | |
252 | @end quotation | |
253 | @item @code{int gnugo_is_legal(int i, int j, int color)} | |
254 | @findex gnugo_is_legal | |
255 | @quotation | |
256 | Interface to @code{is_legal()}. | |
257 | @end quotation | |
258 | @item @code{int gnugo_is_suicide(int i, int j, int color)} | |
259 | @findex gnugo_is_suicide | |
260 | @quotation | |
261 | Interface to @code{is_suicide()}. | |
262 | @end quotation | |
263 | @item @code{int gnugo_placehand(int handicap)} | |
264 | @findex gnugo_placehand | |
265 | @quotation | |
266 | Interface to placehand. Sets up handicap pieces and | |
267 | returns the number of placed handicap stones. | |
268 | @end quotation | |
269 | @item @code{void gnugo_recordboard(SGFNode *root)} | |
270 | @findex gnugo_recordboard | |
271 | @quotation | |
272 | Interface to @code{sgffile_recordboard()} | |
273 | @end quotation | |
274 | @item @code{int gnugo_sethand(int handicap, SGFNode *node)} | |
275 | @findex gnugo_sethand | |
276 | @quotation | |
277 | Interface to placehand. Sets up handicap stones and | |
278 | returns the number of placed handicap stones, updating the sgf file | |
279 | @end quotation | |
280 | @item @code{float gnugo_genmove(int *i, int *j, int color, int *resign)} | |
281 | @findex gnugo_genmove | |
282 | @quotation | |
283 | Interface to @code{genmove()}. | |
284 | @end quotation | |
285 | @item @code{int gnugo_attack(int m, int n, int *i, int *j)} | |
286 | @findex gnugo_attack | |
287 | @quotation | |
288 | Interface to @code{attack()}. | |
289 | @end quotation | |
290 | @item @code{int gnugo_find_defense(int m, int n, int *i, int *j)} | |
291 | @findex gnugo_find_defense | |
292 | @quotation | |
293 | Interface to @code{find_defense()}. | |
294 | @end quotation | |
295 | @item @code{void gnugo_who_wins(int color, FILE *outfile)} | |
296 | @findex gnugo_who_wins | |
297 | @quotation | |
298 | Interface to @code{who_wins()}. | |
299 | @end quotation | |
300 | @item @code{float gnugo_estimate_score(float *upper, float *lower)} | |
301 | @findex gnugo_estimate_score | |
302 | @quotation | |
303 | Put upper and lower score estimates into @code{*upper}, @code{*lower} and | |
304 | return the average. A positive score favors white. In computing | |
305 | the upper bound, @code{CRITICAL} dragons are awarded to white; in | |
306 | computing the lower bound, they are awarded to black. | |
307 | @end quotation | |
308 | @item @code{void gnugo_examine_position(int color, int how_much)} | |
309 | @findex gnugo_examine_position | |
310 | @quotation | |
311 | Interface to @code{examine_position}. | |
312 | @end quotation | |
313 | @item @code{int gnugo_get_komi()} | |
314 | @findex gnugo_get_komi | |
315 | @quotation | |
316 | Report the komi. | |
317 | @end quotation | |
318 | @item @code{void gnugo_get_board(int b[MAX_BOARD][MAX_BOARD])} | |
319 | @findex gnugo_get_board | |
320 | @quotation | |
321 | Place the board into the @samp{b} array. | |
322 | @end quotation | |
323 | @item @code{int gnugo_get_boardsize()} | |
324 | @findex gnugo_get_boardsize | |
325 | @quotation | |
326 | Report the board size. | |
327 | @end quotation | |
328 | @item @code{int gnugo_get_move_number()} | |
329 | @findex gnugo_get_move_number | |
330 | @quotation | |
331 | Report the move number. | |
332 | @end quotation | |
333 | @end itemize | |
334 | ||
335 | @section Game handling | |
336 | ||
337 | The functions (in @pxref{Positional Functions}) are all that are needed to | |
338 | create a fully functional go program. But to make the life easier for the | |
339 | programmer, there is a small set of functions specially designed for handling | |
340 | ongoing games. | |
341 | ||
342 | The data structure describing an ongoing game is the @code{Gameinfo}. It | |
343 | is defined as follows: | |
344 | ||
345 | @example | |
346 | @group | |
347 | ||
348 | typedef struct @{ | |
349 | int handicap; | |
350 | ||
351 | int to_move; /* whose move it currently is */ | |
352 | SGFTree game_record; /* Game record in sgf format. */ | |
353 | ||
354 | int computer_player; /* BLACK, WHITE, or EMPTY (used as BOTH) */ | |
355 | ||
356 | char outfilename[128]; /* Trickle file */ | |
357 | FILE *outfile; | |
358 | @} Gameinfo; | |
359 | ||
360 | @end group | |
361 | @end example | |
362 | ||
363 | The meaning of @code{handicap} should be obvious. @code{to_move} is the | |
364 | color of the side whose turn it is to move. | |
365 | ||
366 | The SGF tree @code{game_record} is used to store all the moves in the entire | |
367 | game, including a header node which contains, among other things, komi | |
368 | and handicap. | |
369 | ||
370 | If one or both of the opponents is the computer, the field | |
371 | @code{computer_player} is used. Otherwise it can be ignored. | |
372 | ||
373 | GNU Go can use a trickle file to continuously save all the moves of an | |
374 | ongoing game. This file can also contain information about internal | |
375 | state of the engine such as move reasons for various locations or move | |
376 | valuations. The name of this file should | |
377 | be stored in @code{outfilename} and the file pointer to the open file is | |
378 | stored in @code{outfile}. If no trickle file is used, | |
379 | @code{outfilename[0]} will contain a null character and @code{outfile} | |
380 | will be set to @code{NULL}. | |
381 | ||
382 | @subsection Functions which manipulate a Gameinfo | |
383 | ||
384 | All the functions in the engine that manipulate Gameinfos have names | |
385 | prefixed by @code{gameinfo_}. Here is a complete list, as prototyped in | |
386 | @file{gnugo.h}: | |
387 | ||
388 | @itemize | |
389 | @item @code{void gameinfo_clear(Gameinfo *ginfo, int boardsize, float komi)} | |
390 | @findex gameinfo_clear | |
391 | @quotation | |
392 | Initialize the @code{Gameinfo} structure. | |
393 | @end quotation | |
394 | @item @code{void gameinfo_print(Gameinfo *ginfo)} | |
395 | @findex gameinfo_print | |
396 | @quotation | |
397 | Print a gameinfo. | |
398 | @end quotation | |
399 | @item @code{void gameinfo_load_sgfheader(Gameinfo *gameinfo, SGFNode *head)} | |
400 | @findex gameinfo_load_sgfheader | |
401 | @quotation | |
402 | Reads header info from sgf structure and sets the appropriate variables. | |
403 | @end quotation | |
404 | @item @code{void gameinfo_play_move(Gameinfo *ginfo, int i, int j, int color)} | |
405 | @findex gameinfo_play_move | |
406 | @quotation | |
407 | Make a move in the game. Return 1 if the move was legal. In that | |
408 | case the move is actually done. Otherwise return 0. | |
409 | @end quotation | |
410 | @item @code{int gameinfo_play_sgftree_rot(Gameinfo *gameinfo, SGFNode *head, const char *untilstr, int orientation)} | |
411 | @findex gameinfo_play_sgftree_rot | |
412 | @quotation | |
413 | Play the moves in an SGF tree. Walk the main variation, actioning the | |
414 | properties into the playing board. Returns the color of the next move to be | |
415 | made. Head is an sgf tree. Untilstr is an optional string of the form either | |
416 | 'L12' or '120' which tells it to stop playing at that move or move | |
417 | number. When debugging, this is the location of the move being examined. | |
418 | @end quotation | |
419 | @item @code{int gameinfo_play_sgftree(Gameinfo *gameinfo, SGFNode *head, const char *untilstr)} | |
420 | @findex gameinfo_play_sgftree | |
421 | @quotation | |
422 | Same as previous function, using standard orientation. | |
423 | @end quotation | |
424 | @end itemize | |
425 | ||
426 |