Node:Top, Next:, Previous:(dir), Up:(dir)


Node:Introduction, Next:, Previous:Top, Up:Top

Introduction

This is GNU Go, a Go program. Development versions of GNU Go may be found at <http://www.gnu.org/software/gnugo/devel.html>. Contact us at gnugo@gnu.org if you are interested in helping.


Node:Copyright, Next:, Previous:Introduction, Up:Introduction

Copyrights

Copyright 1999 and 2000 by the Free Software Foundation except for the files gmp.c and gmp.h, which are copyrighted by Bill Shubert (wms@hevanet.com).

All files are under the GNU General Public License (see Copying), except gmp.c and gmp.h, the files interface/html/* and win/makefile.win. The two files gmp.c and gmp.h are in the public domain and are free for unrestricted use. The files interface/html/* are not part of GNU Go but are a separate program and are included in the distribution for the convenience of anyone looking for a CGI interface to GNU Go. They were placed in the public domain by their author, Douglas Ridgway, and are free for unrestricted use. The file win/makefile.win is also in the public domain and is free for unrestricted use.


Node:Authors, Next:, Previous:Copyright, Up:Introduction

Authors

GNU Go authors (in chronological order of contribution) are Man Li, Daniel Bump, David Denholm, Gunnar Farneback, Nils Lohner, Jerome Dumonteil, Tommy Thorn, Nicklas Ekstrand, Inge Wallin, Thomas Traber, Douglas Ridgway, Teun Burgers, Tangay Urvoy and Thien-Thi Nguyen.


Node:Thanks, Next:, Previous:Authors, Up:Introduction

Thanks

We would like to thank Jean-Louis Martineau, Piotr Lakomy and Paul Leonard for helpful correspondence. Thanks to everyone who stepped on a bug (and sent us a report)!

Thanks to Peter Gucwa, Heikki Levanto, Michael Margolis and Gary Boos for help with Visual C++.

We would like to thank Stuart Cracraft, Richard Stallman and Man Li for their interest in making this program a part of GNU, William Shubert for writing CGoban and gmp.c and Rene Grothmann for Jago.


Node:News, Next:, Previous:Thanks, Up:Introduction

What's new ?

New in 2.6 (since 2.4):

New in 2.4 (since 2.0):


Node:TODO, Previous:News, Up:Introduction

The GNU Go Task List

You can help make GNU GO the best Go program.

This is a task-list for anyone who is interested in helping with GNU Go. If you want to work on such a project you should correspond with us until we reach a common vision of how the feature will work!

A note about copyright. Before any code can be accepted as a part of the official release of GNU Go, the Free Software Foundation will want you to sign a copyright disclaimer. Please contact the GNU Go maintainer, Daniel Bump (bump@math.stanford.edu), to get more information and the papers to sign.

Below is a list of things YOU could work on. We are already working on some of these tasks, but don't let that stop you. Please contact us or the person assigned to task for further discussion.

1. If you can, send us bug FIXES as well as bug reports. If you see some bad behavior, figure out what causes it, and what to do about fixing it. And send us a patch! If you find an interesting bug and cannot tell us how to fix it, we would be happy to have you tell us about it anyway. Send us the sgf file (if possible) and attach other relevant information, such as the GNU Go version number. In cases of assertion failures and segmentation faults we probably want to know what operating system and compiler you were using, in order to determine if the problem is platform dependent.

2. Tuning the pattern database. This is a sort of art. It is not necessary to do any programming to do this since many of the patterns do not require helpers, or can be handled using autohelpers.

We would like it if a few more Dan level players would learn this skill.

3. The reading code assumes that a string with five liberties is safe. Sometimes this leads to expanding a dead group into enemy territory, a simple waste. An improvement in strength would result from giving heuristics for the strategical viability of a group, based on moyo/escape route considerations. This is also useful for deciding whether a cut is reasonable or needs defending against.

4. The escape potential of a group is today estimated by counting fourth order liberties. While this isn't completely unreasonable, it's also not accurate enough anymore. An improved implementation might use pattern matching (with autohelpers to assist with reading) to identify running moves and ways to break through enclosure.

5. Semeai module is vastly in need of improvement. In fact, semeai can probably be only analyzed by reading to discover what backfilling is needed before we can make atari. Also, semeai module should be able to change the status of dragons.

6. The eye space evaluation doesn't work very well for semi-open spaces along the edges. An improvement here might require extending the basic "local game" model for life and death analysis, as described in See Eyes.

7. The eye space evaluation knows about "chimeras", positions where one player can make two eyes in one move but the opponent also can destroy both in one move. This information is, however, currently not used in the higher levels of life and death reasoning. There are also other interesting positions, such as moves making an eye in sente (i.e. by threatening to make another eye), that would need some consideration. For inspiration you may wish to read the paper "Eyespace Values in Go" by Howard Landman. The paper is linked from the GNU Go development web page.

8. The eye space evaluation would also need to learn about local games ending in various kinds of kos.

9. Life and death reading. The eyespace evaluation is currently completely static. This has the advantage of being very fast, but needing a fairly large pattern database. To incorporate various life and death subtleties in this scheme may require enlarging the pattern database more than we want and/or being very tricky to get right. An alternative is to use reading to deal with some of the complications and then perform static evaluation on the nodes.

10. More life and death reading. One could also consider using reading to fully play out the local games (see Eyes). While this probably would be too slow to employ in actual play, it would still be useful for verifying and/or automatically generating the eye space database. (Inge Wallin has started working on this.)

11. Very much time in the reading is spent counting liberties. It's possible that the reading could be made faster by keeping track of the liberty counts while doing and undoing moves. There is, however, a certain amount of overhead involved here, so a proof of concept would definitely be necessary.


Node:Copying, Next:, Previous:Introduction, Up:Top

GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

Copyright © 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

  1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

    Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

  2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

    You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

  3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

    Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

    In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

  4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

    The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

    If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

  5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
  7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
  8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

    If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

    It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

    This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

  9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

    Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

one line to give the program's name and an idea of what it does.
Copyright (C) 19yy  name of author

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'.  This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.

The hypothetical commands show w and show c should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than show w and show c; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.


Node:User Guide, Next:, Previous:Copying, Up:Top

Using GNU Go


Node:Installation, Next:, Previous:User Guide, Up:User Guide

Installation

In short, ./configure; make will build GNU Go; optionally (running as root) make install will put it into /usr/local/bin and also install the man page. You also will probably want to install CGoban.

Get the most recent tar file from <ftp.gnu.org> or a mirror. A list of mirrors may be found at:

<http://www.gnu.org/order/ftp.html>

Untar the sources, change to the directory gnugo-2.6/. Now do:

  ./configure
  make

This makes a binary called interface/gnugo. Now (running as root) type

  make install

This will install gnugo in /usr/local/bin/, and also install the man page gnugo.6 into /usr/man/man6/.

There are two methods of using GNU Go. You may run it from the command line by just typing gnugo, but it is nicer to run it under X-Windows using CGoban.

Obtain the most recent version of CGoban from Bill Shubert's web site:

<http://www.inetarena.com/~wms/comp/cgoban>

The CGoban version number MUST be 1.9.1 at least or it won't work. Instructions for using CGoban are elsewhere in this document see CGoban.

Problems

On one GNU/Linux machine an incompatible /usr/include/curses.h (from BSD) had declarations inconsistent with those in /usr/include/term.h. The symptom of this problem is compilation errors in engine/moyo.c and engine/showbord.c.

In this case, the correct curses.h was found in /usr/include/ncurses and a correct compilation was obtained after changing

  #include <curses.h>

to

  #include <ncurses/curses.h>

in engine/moyo.c and engine/showbord.c. If you have a problem with errors in engine/moyo.c and engine/showbord.c caused by curses you should try such a remedy first. If this doesn't work, you shouldn't curse. Run configure --disable-color to turn off the color option and compile again. Another alternative if you want color is configure --without-curses --enable-color. This will substitute ansi escape sequences for curses.


Node:Documentation, Next:, Previous:Installation, Up:User Guide

Documentation

Documentation in doc/ consists of a man page gnugo.6, the info files gnugo.info, gnugo.info-1, ... and the Texinfo files from which the info files are built. The Texinfo documentation contains this User's Guide and extensive information about the algorithms of GNU Go, for developers.

If you want a typeset copy of the Texinfo documentation, you can make gnugo.dvi or make gnugo.ps in the doc/ directory.

You can make an HTML version with the command makeinfo --html gnugo.texi. Better HTML documentation may be obtained using texi2html -split_chapter gnugo.html. You can obtain the texi2html utility from <http://www.mathematik.uni-kl.de/~obachman/Texi2html/>. (See also <http://texinfo.org/texi2html/>.) Unfortunately Version 1.58 of texi2html does not support the @option and @command tags. These are supported in Version 1.60-Beta. However our current recommendation is to use Version 1.58, and to add the lines

	      'command', 'CODE',
	      'option', 'SAMP',

to the style_map around line 178 of the perl script.

User documentation can be obtained by running gnugo --help or man gnugo from any terminal, or from the Texinfo documentation.

Documentation for developers is in the Texinfo documentation, and in comments throughout the source. Contact us at gnugo@gnu.org if you are interested in helping to develop this program.


Node:CGoban, Next:, Previous:Documentation, Up:User Guide

Running GNU Go via CGoban

This is an extremely nice way to run GNU Go. CGoban provides a beautiful graphic user interface under X-Windows.

Start CGoban. When the CGoban Control panel comes up, select "Go Modem". You will get the Go Modem Protocol Setup. Choose one (or both) of the players to be "Program," and fill out the box with the path to gnugo. After clicking OK, you get the Game Setup window. Choose "Rules Set" to be Japanese (otherwise handicaps won't work). Set the board size and handicap if you want. Click OK and you are ready to go.

In the Go Modem Protocol Setup window, when you specify the path to GNU Go, you can give it command line options, such as -quiet to suppress most messages. Since the Go Modem Protocol preempts standard I/O other messages are sent to stderr, even if they are not error messages. These will appear in the terminal from which you started CGoban.

Other command line options can be listed by typing gnugo --help -or- man gnugo from any terminal.


Node:Ascii, Next:, Previous:CGoban, Up:User Guide

Ascii Interface

Even if you do not have CGoban installed you can play with GNU Go using its default Ascii interface. Simply type gnugo at the command line, and GNU Go will draw a board. Typing help will give a list of options. At the end of the game, pass twice, and GNU Go will prompt you through the counting. You and GNU Go must agree on the dead groups--you can toggle the status of groups to be removed, and when you are done, GNU Go will report the score.


Node:Emacs, Next:, Previous:Ascii, Up:User Guide

GNU Go mode in Emacs

You can run GNU Go from Emacs. This has the advantage that you place the stones using the cursor arrow keys. This may require Emacs 20.4 or later--it has been tested with Emacs 20.4 but does not work with Emacs 19 or Emacs 20.2.

Load interface/gnugo.el, either by M-x load-file, or by copying the file into your site-lisp directory and adding a line

(autoload 'gnugo "gnugo" "GNU Go" t)

in your .emacs file.

Now you may start GNU Go by M-x gnugo. You will be prompted for command line options see Invoking GNU Go. Using these, you may set the handicap, board size, color and komi.

You can enter commands from the GNU Go ASCII interface after typing :. For example, to take a move back, type :back, or to list all commands, type :help.

Here are the default keybindings:


Node:Jago, Next:, Previous:Emacs, Up:User Guide

Running GNU Go via Jago

Jago, like CGoban is a client capable of providing GNU Go with a graphical user interface. Unlike CGoban, it does not require X-Windows, so it is an attractive alternative under Windows. You will need a Java runtime environment. Obtain Jago at

<http://mathsrv.ku-eichstaett.de/MGF/homes/grothmann/jago/Go.html>

and follow the links there for the Java runtime environment.


Node:GMP, Next:, Previous:Jago, Up:User Guide

Go Modem Protocol

The Go Modem Protocol (GMP) was developed by Bruce Wilcox with input from David Fotland, Anders Kierulf and others, according to the history in

<ftp://www.joy.ne.jp/welcome/igs/Go/programs/protocol.Z>

Any Go program should use this protocol since it is standard. Since CGoban supports this protocol, the user interface for any Go program can be done entirely through CGoban. The programmer can concentrate on the real issues without worrying about drawing stones, resizing the board and other distracting issues.


Node:SGF, Next:, Previous:GMP, Up:User Guide

Smart Go Format

The Smart Go Format (SGF), is the standard format for storing Go games. GNU Go supports both reading and writing SGF files. The SGF specification (FF[4]) is at:

<http://www.red-bean.com/sgf/>


Node:Invoking GNU Go, Previous:SGF, Up:User Guide

Invoking GNU Go: Command line options

Some basic options

Options affecting strength and speed

Ascii mode options:

Development options:

Using --analyze:

The analyze options allow analysis of a game stored as sgf file by using --testmode. When using --testmode with --analyze move tree variations are ignored.

The --analyze option also works with --benchmark and --score. The analyze functions will be executed on every move in --benchmark and --testmode game.

If used with --analyzerfile filename, the results of the analysis are written to the file filename.

Analyzed board states on other modes:

--score end: gnugo analyzes every move it makes at the end of the file until the game is finished.

--score last: board state at the end of the file will be analyzed

--score move number: board state just before movenum will be analyzed

--score position: board state just before position is occupied will be analyzed

--testmode annotation: board state just before the annotated node is reached will be analyzed

description of --analyze options:

You can give more than one --analyze option also by concatenating with "" or by using commas without space.

Usage examples:

gnugo --score end --analyzerfile outputfile -l inputfile
will create outputfile and writes the inputfile to it plus the endgame moves for scoring and adds the result property. If you want to overwrite an already existing result property use --analyze overwrite. This also overwrites DT, AP and RU.
gnugo --score end --analyzerfile outputfile -l inputfile \
          --analyze dragonstatus
same as above, but writes to outputfile the dragonstatus for every move gnugo made from the last move in inputfile to the end of the game.
gnugo --testmode game --analyzerfile outputfile -l inputfile \
         --analyze wormliberties
loads inputfile and writes to outputfile the number of liberties for each worm on every move.
gnugo --testmode annotation --analyzerfile outputfile -l inputfile \
          --analyze capture
loads inputfile and writes to outputfile the capturing move for each weak group on every move followed by a annotation (see Regression)


Node:Overview, Next:, Previous:User Guide, Up:Top

GNU Go engine overview

This document is an overview of the GNU Go internals. Further documentation of how any one module or routine works may be found in the comments in the source files.


Node:Definitions, Next:, Up:Overview

Definitions

In this document wherever we define a concept we use CAPITAL LETTERS for the term being defined.

A WORM is a maximal set of vertices on the board which are connected along the horizontal and vertical lines, and are of the same color, which can be BLACK, WHITE or EMPTY. The term EMPTY applied to a worm means that the worm consists of empty (unoccupied) vertices. It does NOT mean that that the worm is the empty set. A STRING is a nonempty worm. An empty worm is called a CAVITY. If a subset of vertices is contained in a worm, there is a unique worm containing it; this is its WORM CLOSURE.

A DRAGON is a union of strings of the same color which will be treated as a unit. The dragons are recomputed. If two strings are in the same dragon, it is the computer's working hypothesis that they will live or die together and are effectively connected.


Node:Move Generation, Next:, Previous:Definitions, Up:Overview

Move Generation

The engine of GNU Go takes a positions and a color to move and generates the (supposedly) optimal move. This is done by the function genmove() in engine/genmove.c.

The move generation is done in two passes:

  1. information gathering
  2. actual move generation based on the information gathered in pass 1.

Information gathering

First we have to collect as much information as possible about the current position. Such information could be life and death of the groups, moyo status, connection of groups and so on. Information gathering are performed by the following functions, called in this order:

- make_worms()

Collect information about all connected sets of stones (strings) and cavities. This information is stored in the worm[][] array.

- make_dragons

Collect information about connected strings, which are called dragons. Important information here is number of eyes, life status, and connectedness between string.

- make_moyo()

Calculate the "territory", "moyo" and "area" for both sides. "Territory," as used here, is not solid, incontestible territory, but rather the regions which are deemed likely to become actual territory. "Moyo" is the larger region of strong influence which could become territory if the other side does nothing about it. "Area" is a still larger region of general influence. This function also assigns "weakness" to groups which are strategically vulnerable because of strong opposing influence. Weakness is accounted for in the field dragon.safety (see see Dragon).

See Dragon, for make_worms() and make_dragons() more detailed documentation. See Moyo, for the algorithms in make_moyo.

Move generation in GNU Go 2.6

Once we have found out all about the position it is time to generate the best move. Moves are proposed by a number of different move generators with a value attached to them. The values are compared and the best move is picked. If two or more moves have the same value, one of them is picked at random.

The move generators in version 2.6 are:

- fuseki()

Generate a move in the early fuseki. This module is undocumented but will be replaced by something better in the future.

- semeai()

Find out if two dead groups of opposite colors are next to each other and, if so, try to kill the other group. This module is probably the one in the worst condition currently and badly in need of improvement.

- shapes()

Find patterns from patterns/patterns.db in the current position. Each pattern is matched in each of the 8 possible orientations obtainable by rotation and reflection. If the pattern matches, a so called "constraint" may be tested which makes use of reading to determine if the pattern should be used in the current situation. Such constraints can make demands on number of liberties of strings, life and death status, and reading out ladders, etc. The patterns may call helper functions, which may be hand coded (in patterns/helpers.c) or autogenerated.

The patterns can be of a number of different classes with different goals. There are e.g. patterns which try to attack or defend groups, patterns which try to connect or cut groups, and patterns which simply try to make good shape.

See Patterns, for a complete documentation of patterns.

- attacker()

Looks for strings of the opposite color with four liberties or less and tries to kill them.

- defender()

Looks for strings of my color with four liberties or less and tries to defend them.

- eye_finder()

Finds groups of either color which can make two eyes in the next move and looks for the vital point in the eye shapes.

- revise_semeai()

If no move is found yet, change status of opponent groups involved in a semeai from DEAD to UNKNOWN. After this, genmove runs shapes again to see if a new move turns up.

- fill_liberty()

Fill a common liberty. This is only used at the end of the game. If necessary a backfilling or backcapturing move is generated.


Node:Roadmap, Next:, Previous:Move Generation, Up:Overview

Roadmap

The GNU Go engine is contained in two directories, engine/ and patterns/. Code related to the user interface, reading and writing of smart go format files and testing are found in the directories interface/, sgf/ and regression/. Code borrowed from other GNU programs is contained in utils/. Documentation is in docs/.

In this document we will describe the all individual files comprising the engine code in engine/ and patterns/. In interface/ we mention one file:

gmp.c :

This is the Go Modem Protocol interface (courtesy of William Shubert and others). This takes care of all the details of exchanging setup and moves with Cgoban, or any other driving program recognizing the Go Modem Protocol.

In engine/ there are the following files:

attdef.c :

This file contains attacker(), defender() and eye_finder(), three of the move generators called by genmove(). The module attacker() proposes moves which attack enemy strings, while defender() proposes moves which defend friendly strings. The reading necessary to decide whether a string can be captured or defended is contained in reading.c, and has already been called by make_worms(). If a string can be defended, there may be different possible defensive moves, and some of the patterns found by shapes() may move the points of defense. This is the only case where data compiled by make_worms() and make_dragons() is changed by a later routine. Because of this feature, shapes() is called before defender().

Also in attdef.c is eye_finder(). This module looks for dragons having one and a half eyes. If such a dragon (of either color) is found, eye_finder() proposes making or destroying the half eye.

dragon.c :

This contains make_worms() and make_dragons(). These routines are executed before the move-generating modules shapes(), attacker(), defender(), semeai() and eye_finder(). They find all the worms and dragons and collect important information about them, such as how many liberties each has, whether (in GNU Go's opinion) the string or dragon can be captured, etc. This information remains unchanged until the next move, with one exception: some patterns can move the point of defense of a friendly worm which is under attack.

filllib.c :

Code to force filling of dame (backfilling if necessary) at the end of the game.

fuseki.c :

This module generates fuseki (large scale opening) moves at the beginning of the game. This file is undocumented but will be replaced by something better in the future.

genmove.c :

This file contains genmove(), is the routine responsible for generating the next move. Opening moves are generated directly in this file, but it calls on other modules for other moves. The modules called by genmove are shapes() (in shapes.c), attacker() and defender() (in attdef.c), semeai() (in semeai.c) and eye_finder() (in attdef.c). Each module proposes moves, each with a value, and genmove() selects the one with the highest value.

hash.c :

Hashing code used by for reading. (see Hashing)

hash.h :

header file for hash.c.

liberty.h :

Header file for the whole program.

main.c :

Miscellaneous book-keeping (parsing args, signal handlers, etc.) sgf file interfaces (reading and writing) high level game playing (collecting moves from genmove(), keeping track of passes, etc.) Contains very little knowledge about go : only that each side plays alternately, and that two passes marks the end of the game.

matchpat.c :

This file contains matchpat(), which looks for patterns at a particular board location.

moyo.c :

This file contains code to estimate territory and influence. See Moyo, for details.

reading.c :

This file contains code to determine whether any given string can be attacked or defended. See Reading, for details.

semeai.c :

This contains semeai(), the module which tries to win capturing races.

sethand.c :

Initially populate the board with handicap stones.

showbord.c :

This contains showboard(), which draws an ASCII representation of the board, depicting dragons (stones with same letter) and status (color). This was the primary interface in GNU Go 1.2, but is now a debugging aid.

shapes.c :

This file contains shapes(), the module called by genmove() which tries to find moves which match a pattern. The pattern matcher has some sophisticated features. (see Patterns). Briefly, the pattern may take into account both friendly and opposing strength in the area, a string's escape potential, whether or not the pattern makes or breaks a valuable connection, whether it involves a dragon classified as dead, and it can also call a helper function hand tailored to the program which typically does some further reading to decide whether the pattern is appropriate.

optics.c :

This contains the code to recognize eye shapes, documented in See Eyes.

worm.c :

This file contains code which is run at the beginning of each move cycle, before the code in dragon.c, to determine the attributes of every string.

utils.c :

An assortment of utilities, described in greater detail below.

The directory patterns/ contains files related to pattern matching. Currently search for 3 types of patterns: move generation patterns (in patterns.db and similar files such as hoshi.db, autogenerated from hoshi.sgf See Patterns, for details); eyeshape patterns (See Eyes, for eyes.db) and connection patterns (See Dragon, for conn.db).

The following list contains, in addition to distributed source files some intermediate automatically generated files such as patterns.c. These are C source files produced by "compiling" various pattern databases, or in some cases (such as hoshi.db) themselves automatically generated pattern databases produced by "compiling" joseki files in Smart Go Format.

conn.db :

Database of connection patterns.

conn.c :

Automatically generated file, containing connection patterns in form of struct arrays, compiled by mkpat from conn.db.

eyes.c :

Automatically generated file, containing eyeshape patterns in form of struct arrays, compiled by mkpat from eyes.db.

eyes.h :

Header file for eyes.c.

eyes.db :

Database of eyeshape patterns. See Eyes, for details.

helpers.c :

These are helper functions to assist in evaluating moves by matchpat.

hoshi.sgf :

Smart Go Format file containing 4-4 point openings

hoshi.db :

Automatically generated database of 4-4 point opening patterns, make by compiling hoshi.sgf

joseki.c :

Joseki compiler, which takes a joseki file in Smart Go Format, and produces a pattern database.

komoku.sgf :

Smart Go Format file containing 3-4 point openings

komoku.db :

Automatically generated database of 3-4 point opening patterns, make by compiling komoku.sgf

mkeyes.c :

Pattern compiler for the eyeshape databases. This program takes eyes.db as input and produces eyes.c as output.

mkpat.c :

Pattern compiler for the move generation and connection databases. Takes the file patterns.db together with the autogenerated Joseki pattern files hoshi.db, komoku.db, sansan.db, mokuhadzushi.db, takamoku.db and produces patterns.c, or takes conn.db and produces conn.c.

mokuhazushi.sgf :

Smart Go Format file containing 5-3 point openings

mokuhazushi.db :

Pattern database compiled from mokuhadzushi.sgf

sansan.sgf :

Smart Go Format file containing 3-3 point openings

sansan.db :

Pattern database compiled from sansan.sgf

takamoku.sgf :

Smart Go Format file containing 5-4 point openings

takamoku.db :

Pattern database compiled from takamoku.sgf.

patterns.c :

Pattern data, compiled from patterns.db by mkpat.

patterns.h :

Header file relating to the pattern databases.

patterns.db :

This contains the pattern database in human readable form. See PATTERNS for documentation.

Utility files and routines in engine/utils.c

Only a portion of these functions are documented here. Others are discussed elsewhere see Utility Functions.

legal() :

Determines whether a move is legal.

trymove() :

Pushes the board position on the stack, increments stackp, places the stone on the board if the move is legal, removes captures and increments stackp.

pushgo() :

Pushes the board position on the stack and increments stackp.

popgo() :

Pops the stack.

gprintf() :

printf-like fn (see below under TRACING)

TRACE, VTRACE, DEBUG () - see below under Tracing.

abortgo() :

Wrapper around abort() which dumps the stack. Usually this is invoked by means of the macro ASSERT (see ASSERTIONS) below.

utils.c :

Board utility functions :

---

approxlib() :

Counts liberties, but as an optimisation, can be given an upper limit, above which it can stop counting.

count() :

Low level helper for approxlib(), but is used by other fns

updateboard() :

Place a piece on the board, remove captures, and update state information (for ko)


Node:Data Structures, Next:, Previous:Roadmap, Up:Overview

Data structures

The most important global variable is p[][], which is the go board. Each element contains EMPTY, WHITE or BLACK.

stackp is the STACK POINTER. When this is zero, p[][] contains the actual board position. When trymove() is called, it generates a new board position by placing a stone on the board and calling updateboard(). Then stackp is incremented. The old position is saved on the stack.

Thus the value stackp equals the ply below the current position at which the reading code is thinking.

The state of the board can be saved and restored using pushgo() and popgo().

p[][] should not be written to directly. Trial moves should be made using trymove(), which pushes the board, places the piece, checks the move is legal, and updates the board. popgo() undoes the move. When a move is actually made, updateboard() places the piece and removes prisoners.

approxlib() and count() can be called without actually placing a piece. They report what the number of liberties would be if a given piece was placed.

Other important data structures are dragon[][] and worm[][]. These contain information about groups of stones, whether they are alive or dead, where they can be attacked, whether they are cutting groups (split enemy groups), etc.

size, lib, and libi[], libj[] are global variables written to by count() and approxlib(). They return the size of the group, and the number and positions of the liberties.

*NOTE* : if the count is truncated because it reaches the limit on the number of liberties, then size and lib may be smaller than the true value.


Node:Coding Styles, Previous:Data Structures, Up:Overview

Coding styles and conventions

Tracing

A function gprintf() is provided. It is a cut-down printf, supporting only %c, %d, %s, and without field widths, etc. It does, however, add two useful facilities :

%m :

takes two parameters, and displays a formatted board co-ordinate

indentation :

trace messages are automatically indented to reflect the current stack depth, so it is clear during read-ahead when it puts a move down or takes one back.

As a workaround, "outdent" %o at the beginning of the format string suppresses the indentation.

gprintf() is intended to be wrapped by one of the following:

TRACE(fmt, ...) :

print the message if the 'verbose' variable > 0. (verbose is set by -t on the command line)

VTRACE(fmt, ...) :

Verbose trace, only if verbose > 1 (not currently used)

DEBUG(flags, fmt, ...) :

while TRACE is intended to afford an overview of what GNU Go is considering, DEBUG allows occassional in depth study of a module, usually needed when something goes wrong. 'flags' is one of the DEBUG_* symbols in engine/liberty.h. The DEBUG macro tests to see if that bit is set in the 'debug' variable, and prints the message if it is. The debug variable is set using the -d command-line option.

The variable verbose controls the tracing. It can equal 0 (no trace), 1, 2, 3 or 4 for increasing levels of tracing. In practice levels 3 and 4 should only be used when running inside gdb because the volume of tracing is prohibitive. You can set the trace level at the command line by -t for verbose=1, -t -t for verbose=2, etc.

Assertions

Related to tracing are assertions. Developers are strongly encouraged to pepper their code with assertions to ensure that data structures are as they expect. For example, the helper functions make assertions about the contents of the board in the vicinity of the move they are evaluating.

ASSERT() is a wrapper around the standard C assert() function. In addition to the test, it takes an extra pair of parameters which are the co-ordinates of a "relevant" board position.

If an assertion fails, the board position is included in the trace output, and showboard() and popgo() are called to unwind and display the stack.

Fixme

We have adopted the convention of putting the word FIXME in comments to denote known bugs, etc.


Node:Analyzing, Next:, Previous:Overview, Up:Top

Analyzing games stored in SGF files using GNU Go


Node:Traces, Next:, Previous:Analyzing, Up:Analyzing

Interpreting Traces

A quick way to find out roughly the reason for a move is to run

gnugo -l filename -t -a -w -L move number

(You may also want to add --quiet to suppress the copyright message.) In GNU Go 2.6, the weights with which each move is proposed are listed.


Node:Output File, Next:, Previous:Traces, Up:Analyzing

The Output File

If GNU Go is invoked with the option -o filename it will produce an output file. This option can be added at the command line in the Go Modem Protocol Setup Window of CGoban. The output file will show the locations of the moves considered and their weights. It is worth noting that by enlarging the CGoban window to its fullest size it can display 3 digit numbers. Dragons with status DEAD are labelled with an `X', and dragons with status CRITICAL are labelled with a `?'.

Another type of SGF output file is provided by --analyzerfile (see Invoking GNU Go).


Node:Decidestring, Next:, Previous:Output File, Up:Analyzing

Checking the reading code

The --decidestring option is used to check the reading code. This option takes an argument, which is a location on the board in the usual algebraic notation (e.g. --decidestring C17). This will tell you whether the reading code believes the string can be captured, and if so, whether it believes it can be defended, which moves it finds to attack or defend the move, how many nodes it searched in coming to these conclusions. Note that when GNU Go runs normally (not with --decidestring) the points of attack and defense are cached in worm.attack and worm.defend. Later, however, they may be moved, for example during shapes() in response to a D pattern, so the final points of attack and defense which are found may differ from those found by --decidestring.

If used with an output file (-o filename) --decidestring will produce a variation tree showing all the variations which are considered.


Node:Scoring, Next:, Previous:Decidestring, Up:Analyzing

Scoring the game

GNU Go can score the game. If done at the last move, this is usually accurate unless there is a seki. Normally GNU Go will report its opinion about the score at the end of the game, but if you want this information about a game stored in a file, use the --score option.

gnugo --score last -l filename

loads the sgf file and estimates the winner after the last stored move by measuring the influence.

gnugo --score end -l filename

loads the sgf file and GNU Go continues to play after the last stored move by itself up to the very end. Then the winner is determined by counting the territory.

gnugo --score L10 -l filename

loads the sgf file until a stone is placed on L10. Now the winner will be estimated as with gnugo --score last.

gnugo --score 100 -l filename

loads the sgf file until move number 100. Now the winner will be estimated as with gnugo --score last.

If the option -o outputfilename is provided, the results will also be written as comment at the end of the output file.

If the option --analyzerfile outputfilename is provided, the results will be written as comment at the end of the output file, the result property will be set and the territory will be marked.


Node:Colored Display, Previous:Scoring, Up:Analyzing

Colored Display

Dragon Display

You can get a colored ASCII display of the board in which each dragon is assigned a different letter; and the different safety values (ALIVE, DEAD, UNKNOWN, CRITICAL) have different colors. This is very handy for debugging.

Save a game in sgf format using CGoban, or using the -o option with GNU Go itself.

Open an rxvt window. (Xterm will not work. You may also use the Linux console.)

Execute:

gnugo -l [filename] -L [movenum] -T to get the colored display.

The color scheme: Green = ALIVE; Yellow = UNKNOWN; White = DEAD and Red = CRITICAL. Worms which have been amalgamated into the same dragon are labelled with the same letter.

Other useful colored displays may be obtained by using instead:

Eye Space Display

Instead of -T, try this with -E. This gives a colored display of the eyespaces, with marginal eye spaces marked ! (see Eyes).

Moyo Display

The option -m level can give colored displays of the various quantities which are computed in engine/moyo.c.

The moyos found by GNU Go can be displayed from an rxvt window or from the Linux console using the -m option. This takes a parameter:

-m level
   use cumulative values for printing these debug reports :
    1 = ascii printing of territorial evaluation (5/21)
    2 = table of delta_terri values
    4 = ascii printing of moyo evaluation (5/10)
    8 = table of delta_moyo values
   16 = ascii printing of area (weak groups?) (4/0)
   32 = list of area characteristics
   64 = table of meta_connect values
  128 = trace -p fearless option (big_move priority)

Definitions of these fields is given elsewhere (see Moyo).


Node:Dragon, Next:, Previous:Analyzing, Up:Top

Worms and Dragons

Before considering its move, GNU Go collects some data in several arrays. Two of these arrays, called worm and dragon, are discussed in this document. Others are discussed in See Eyes.

This information is intended to help evaluate the connectedness, eye shape, escape potential and life status of each group.

Later routines called by genmove() will then have access to this information. This document attempts to explain the philosophy and algorithms of this preliminary analysis, which is carried out by the two routines make_worm() and make_dragon() in dragon.c.

In this document wherever we define a concept we use CAPITAL LETTERS for the term being defined.

A WORM is a maximal set of vertices on the board which are connected along the horizontal and vertical lines, and are of the same color, which can be BLACK, WHITE or EMPTY. The term EMPTY applied to a worm means that the worm consists of empty (unoccupied) vertices. It does NOT mean that that the worm is the empty set. A STRING is a nonempty worm. An empty worm is called a CAVITY. If a subset of vertices is contained in a worm, there is a unique worm containing it; this is its WORM CLOSURE.

A DRAGON is a union of strings of the same color which will be treated as a unit. The dragons are generated anew at each move. If two strings are in the dragon, it is the computer's working hypothesis that they will live or die together and are effectively connected.

The purpose of the dragon code is to allow the computer to formulate meaningful statements about life and death. To give one example, consider the following situation:

      OOOOO
     OOXXXOO
     OX...XO
     OXXXXXO
      OOOOO

The X's here should be considered a single group with one three-space eye, but they consist of two separate strings. Thus we must amalgamate these two strings into a single dragon. Then the assertion makes sense, that playing at the center will kill or save the dragon, and is a vital point for both players. It would be difficult to formulate this statement if the X's are not perceived as a unit.

The present implementation of the dragon code involve simplifying assumptions which can be refined in later implementations.


Node:Worms, Next:, Previous:Dragon, Up:Dragon

Worms

The array struct worm_data worm[19][19] collects information about the worms. We will give definitions of the various fields. Each field has constant value at each vertex of the worm. We will define each field.

struct worm_data {
{
  int color;
  int size;
  float effective_size;
  int origini;
  int originj;
  int liberties;
  int liberties2;
  int liberties3;
  int liberties4;
  int attacki;
  int attackj;
  int attack_code;
  int lunchi;
  int lunchj;
  int defendi;
  int defendj;
  int defend_code;
  int cutstone;
  int cutstone2;
  int genus;
  int value;
  int ko;
  int inessential;
};

COLOR: If the worm is BLACK or WHITE, that is its color. Cavities (empty worms) have an additional attribute which we call BORDERCOLOR. This will be one of BLACK_BORDER, WHITE_BORDER or GRAY_BORDER. Specifically, if all the worms adjacent to a given empty worm have the same color (black or white) then we define that to be the bordercolor. Otherwise the bordercolor is gray.

Rather than define a new field, we keep this data in the field color. Thus for every worm, the color field will have one of the following values: BLACK, WHITE, GRAY_BORDER, BLACK_BORDER or WHITE_BORDER. The last three categories are empty worms classified by bordercolor.

SIZE: This field contains the cardinality of the worm.

ORIGIN: Each worm has a distinguished member, called its ORIGIN. Its coordinates are (origini, originj). The purpose of this field is to make it easy to determine when two vertices lie in the same worm: we compare their origin. Also if we wish to perform some test once for each worm, we simply perform it at the origin and ignore the other vertices. The origin is characterized by the test:

(worm[m][n].origini == m) && (worm[m][n].originj == n).

LIBERTIES: For a nonempty worm the field liberties is the number of liberties of the string. This is supplemented by LIBERTIES2, LIBERTIES3 and LIBERTIES4, which are the number of second order, third order and fourth order liberties, respectively.

The definition of liberties of order >1 is adapted to the problem of detecting the shape of the surrounding cavity. In particular we want to be able to see if a group is loosely surrounded. A LIBERTY OF ORDER n is an empty vertex which may be connected to the string by placing n stones of the same color on the board, but no fewer. The path of connection may pass through an intervening group of the same color. The stones placed at distance >1 may not touch a group of the opposite color. Connections through ko are not permitted. Thus in the following configuration:

          .XX...    We label the     .XX.4.
          XO....    liberties of     XO1234
          XO....    order < 5 of     XO1234
          ......    the O group:     ..2.4.
          .X.X..                     .X.X..

The convention that liberties of order >1 may not touch a group of the opposite color means that knight's moves and one space jumps are perceived as impenetrable barriers. This is useful in determining when the string is becoming surrounded.

We say that n is the DISTANCE of the liberty of order n from the dragon.

ATTACK: If it is determined that the string may be easily captured, (attacki, attackj) points to an attacking move. In the present implementation, this is only used for strings with <4 liberties. The algorithm in reading.c is fairly reliable at finding ladders but poor at finding nets (geta). This module therefore needs rewriting. If no attacking move is found, then attacki == -1.

ATTACK_CODE: 1 if the worm can be captured unconditionally, 2 or 3 if it can be captured with ko. If can be captured provided the attacker is willing to ignore any ko threat, then the attack_code == 2. If it can be captured provided the attacker can come up with a sufficiently large ko threat, then the attack_code == 3.

LUNCH: If lunchi != -1 then (lunchi, lunchj) points to a boundary worm which can be easily captured. (It does not matter whether or not the string can be defended.)

DEFEND: If there is an attack on the string (stored in the ATTACK field defined above), and there is a move which defends the string, this move is stored in (defendi, defendj). Otherwise defendi == -1.

DEFEND_CODE: 1 if the worm can be defended unconditionally, 2 or 3 if it can be defended with ko. If can be defended provided the defender is willing to ignore any ko threat, then the defend_code == 2. If it can be captured provided the defender can come up with a sufficiently large ko threat, then the defend_code == 3.

CUTSTONE: This field is equal to 2 for cutting stones, 1 for potential cutting stones. Otherwise it is zero. Definitions for this field:

A CUTTING STONE is one adjacent to two enemy strings, which do not have a liberty in common. The most common type of cutting string is in this situation.

          XO
          OX

A POTENTIAL CUTTING STONE is adjacent to two enemy strings which do share a liberty. For example, X in:

          XO
          O.

For cutting strings we set worm[m][n].cutstone=2. For potential cutting strings we set worm[m][n].cutstone=1.

GENUS: There are two separate notions of genus for worms and dragons. The dragon notion is more important, so dragon[m][n].genus is a far more useful field than worm[m][n].genus. Both fields are intended as approximations to the number of eyes. The GENUS of a string is the number of connected components of its complement, minus one. It is an approximation to the number of eyes of the string.

VALUE: A measure of the value of the worm.

KO: For every ko, the flag ko is set to 1 at the ko stone which is in atari, and also at the ko cavity adjacent to it. Thus in this situation:

             XO
            X.XO
             XO

the flag ko is set to 1 at the rightmost X stone, and also at the cavity to its left.

INESSENTIAL: An INESSENTIAL string is one which meets a criterion designed to guarantee that it has no life potential unless a particular surrounding string of the opposite color can be killed. More precisely an INESSENTIAL STRING is a string S of genus zero, not adjacent to any opponent string which can be easily captured, and which has no edge liberties or second order liberties, and which satisfies the following further property: If the string is removed from the board, then the empty worm E which is the worm closure of the set of vertices which it occupied has bordercolor the opposite of the removed string. The empty worm E (empty, that is, as a worm of the board modified by removal of S) consists of the union of support of S together with certain other empty worms which we call the BOUNDARY COMPONENTS of S.

The inessential strings are used in the amalgamation of cavities in make_dragon.

The function makeworms() will generate data for all worms. For empty worms, the following fields are significant: color, size, origini and originj. The liberty, attack, defend, cutstone, genus and inessential fields have significance only for nonempty worms.


Node:Amalgamation, Next:, Previous:Worms, Up:Dragon

Amalgamation

A DRAGON, we have said, is a group of stones which are treated as a unit. It is a working hypothesis that these stones will live or die together. Thus the program will not expect to disconnect an opponent's strings if they have been amalgamated into a single dragon.

The function makedragons() will amalgamate worms into dragons by maintaining separate arrays worms[] and dragons[] containing similar data. Each dragon is a union of worms. Just as the data maintained in worm[19][19] is constant on each worm, the data in dragon[19][19] is constant on each dragon.

AMALGAMATION of two worms means means in practice replacing the origin of one worm by the origin of the other. Amalgamation takes place in two stages: first, the amalgamation of empty worms (cavities) into empty dragons (caves); then, the amalgamation of colored worm into dragons.

Amalgamation of cavities

As we have already defined it, a CAVITY is an empty worm. A CAVE is an empty dragon.

Under certain circumstances we want to amalgamate two or more cavities into a single cave. This is done before we amalgamate strings. An example where we wish to amalgamate two empty strings is the following:

      OOOOO
     OOXXXOO
     OXaObXO
     OOXXXOO
      OOOOO

The two empty worms at a and b are to be amalgamated.

We have already defined a string to be INESSENTIAL if it meets a criterion designed to guarantee that it has no life potential unless a particular surrounding string of the opposite color can be killed. An INESSENTIAL STRING is a string S of genus zero which is not a cutting string or potential cutting string, and which has no edge liberties or second order liberties (the last condition should be relaxed), and which satisfies the following further property: If the string is removed from the board, then the empty worm E which is the worm closure of the set of vertices which it occupied has bordercolor the opposite of the removed string.

Thus in the previous example, after removing the inessential string at the center the worm closure of the center vertex consists of an empty worm of size 3 including a and b. The latter are the boundary components.

The last condition in the definition of inessential worms excludes examples such as this:

        OOOO
       OXXOO
      OXX.XO
      OX.XXO
      OOXXO
       OOO

Neither of the two X strings should be considered inessential (together they form a live group!) and indeed after removing one of them the resulting space has gray bordercolor, so by this definition these worms are not inessential.

Some strings which should by rights be considered inessential will be missed by this criterion.

The algorithm for amalgamation of empty worms consists of amalgamating the boundary components of any inessential worm. The resulting dragon has bordercolor the opposite of the removed string.

Any dragon consisting of a single cavity has bordercolor equal to that of the cavity.

Amalgamation of strings

Amalgamation of nonempty worms in GNU Go 2.6 proceeds as follows. First we amalgamate all boundary components of an eyeshape. Thus in the following example:

.OOOO.       The four X strings are amalgamated into a
OOXXO.       single dragon because they are the boundary
OX..XO       components of a blackbordered cave. The
OX..XO       cave could contain an inessential string
OOXXO.       with no effect on this amalgamation.
XXX...

The code for this type of amalgamation is in the routine dragon_eye(), discussed further in EYES.

Next, we amalgamate strings which seem uncuttable. We amalgamate dragons which either share two or more common liberties, or share one liberty into the which the opponent cannot play without being captured. (ignores ko rule).

   X.    X.X     XXXX.XXX         X.O
   .X    X.X     X......X         X.X
                 XXXXXX.X         OXX

A database of connection patterns may be found in patterns/conn.db.


Node:Connection, Next:, Previous:Amalgamation, Up:Dragon

Connection

The fields black_eye.cut and white_eye.cut are set where the opponent can cut, and this is done by the B (break) class patterns in conn.db. There are two important uses for this field, which can be accessed by the autohelper functions xcut() and ocut(). The first use is to stop amalgamation in positions like

..X..
OO*OO
X.O.X
..O..

where X can play at * to cut off either branch. What happens here is that first connection pattern 6 finds the double cut and marks * as a cutting point. Later the C (connection) class patterns in conn.db are searched to find secure connections over which to amalgamate dragons. Normally a diagonal connection would be deemed secure and amalgamated by connection pattern 3, but there is a constraint requiring that neither of the empty intersections is a cutting point.

This is far from perfect. It would be better to amalgamate in either direction, preferably leaving the smallest part as a tail to save or sacrifice.

The other use is to simplify making alternative connection patterns to the solid connection. Positions where the diag_miai helper thinks a connection is necessary are marked as cutting points by connection pattern 12. Thus we can write a connection pattern like CC23c:

?xx?
XO*?               straight extension to connect
O..?

:8,90,0,C,5,5,0,2,2,NULL

?xx?
XOb?
Oa.?

;xcut(a) && odefend_against(b,a)

where we verify that a move at * would stop the enemy from safely playing at the cutting point, thus defending against the cut.


Node:Half Eyes, Next:, Previous:Connection, Up:Dragon

Half Eyes and False Eyes

A HALF EYE is a place where, if the defender plays first, and eye will materialize, but where if the attacker plays first, no eye will materialize. A FALSE EYE is a vertex which is surrounded by a dragon yet is not an eye. Here is a half eye:

XXXXX
OO..X
O.O.X
OOXXX

Here is a false eye:

XXXXX
XOO.X
O.O.X
OOXXX

The "topological" algorithm for determining half and false eyes is described elsewhere (see Eye Topology).

The half eye data is collected in the dragon array. Before this is done, however, an auxiliary array called half_eye_data is filled with information. The type is 0, or else HALF_EYE or FALSE_EYE depending on which type is found; and (ki, kj) points to a move to kill the half eye.

struct half_eye_data half_eye[19][19];

struct half_eye_data {
  int type;         /* HALF_EYE or FALSE_EYE; */
  int ki;           /* (ki,kj) is the move to kill or live */
  int kj;
};

The arrays half_eye[19][19], half_eyei[19][19] and half_eyej[19][19] are filled. First, half_eye[m][n] is zero unless a half eye or false eye is found at the empty vertex (m,n); in this case, it is assigned the value FALSE_EYE or HALF_EYE, and (half_eyei[m][n], half_eyej[m][n]) points to the dragon having the false or half eye.


Node:Distance and Strategic Distance, Next:, Previous:Half Eyes, Up:Dragon

Distance and Strategic Distance

The DISTANCE from an empty vertex to black is the length of the shortest path from the vertex to any black stone, not passing through a white stone. The STRATEGIC DISTANCE is defined similarly except that the path may not pass through any liberty of any white stone, except possibly at the beginning. The distance or strategic distance is -1 (representating infinity) if no such path may be found. Distance and strategic distance to white are defined similarly.

For example in the following diagram on the edge, the distance from the vertex at a to the color X is six:

...........
..X.XXOOO...
...XOO.a.OO
...........
-----------

because we can find the following path of length 6 from a to X:

...........
..X.XXOOO...
...6OO1a.OO
...5432....
-----------

The strategic distance is infinite, however. The above path is not admissible for strategic distance, because at 3 and 4 it passes through O's liberties. The path at 1 also is an O liberty but this is admissible since it is at the very beginning of the path.

We maintain these data in the arrays distance_to_black[19][19] and distance_to_white[19][19], and similarly for the strategic_distance. They may also be accessed by the functions distance_to() and strategic_distance_to() in utils.c.


Node:Dragons, Next:, Previous:Distance and Strategic Distance, Up:Dragon

Dragons

The array struct dragon_data dragon[19][19] collects information about the dragons. We will give definitions of the various fields. Each field has constant value at each vertex of the dragon. We will define each field.

struct dragon_data {
  int color;
  int origini;
  int originj;
  int borderi;
  int borderj;
  int size;
  float effective_size;
  int heyes;
  int heyei;
  int heyej;
  int genus;
  int escape_route;
  int escape2;
  int lunchi;
  int lunchj;
  int status;
  int safety;
  int vitality;
  int semeai;
};

COLOR: For strings, this is BLACK or WHITE. For caves, it is BLACK_BORDER, WHITE_BORDER or GRAY_BORDER. The meaning of these concepts is the same as for worms.

ORIGIN: The origin of the dragon is a unique particular vertex of the dragon, useful for determining when two vertices belong to the same dragon. Before amalgamation the worm origins are copied to the dragon origins. Amalgamation of two dragons amounts to changing the origin of one.

BORDER: This field is relevant for caves. If the color of the cave is BLACK_BORDER or WHITE_BORDER then the surrounding worms all have the same color BLACK or WHITE and these have been amalgamated into a dragon with origin (borderi, borderj).

SIZE: This is the cardinality of the dragon.

HEYES: This is the number of half eyes the dragon has. A HALF EYE is a pattern where an eye may or may not materialize, depending on who moves first. If any half eyes are found, (heyi,heyj) points to a move which will create an eye.

GENUS: The GENUS of a nonempty dragon consists of the number of distinct adjacent caves whose bordercolor is the color of the dragon, minus the number of false eyes found. The genus is a computable approximation to the number of eyes a dragon has.

VALUE: A measure of the value of the dragon.

ESCAPE ROUTE: The field dragon[m][n].escape_route is the maximum value of worm[i][j].liberties4 over the worms of the dragon. This is a measure of the escape potential of the string.

LUNCH: If lunchi != -1, then (lunchi, lunchj) points to a boundary worm which can be captured easily. In contrast with the worm version of this parameter, we exclude strings which cannot be saved.

STATUS: An attempt is made to classify the dragons as ALIVE, DEAD, CRITICAL or UNKNOWN. The CRITICAL classification means that the fate of the dragon depends on who moves first in the area. The exact definition is in the function dragon_status(). If the dragon is found to be surrounded, the status is DEAD if it has less than 1.5 eyes or if the reading code determines that it can be killed, ALIVE if it has 2 or more eyes, and CRITICAL if it has 1.5 eyes. A lunch generally counts as a half eye in these calculations. If it has less than 2 eyes but seems possibly able to escape, the status may be UNKNOWN.

It is of the utmost importance accomplish this classification as accurately as possible. Unfortunately this is not easy. A problem is that the algorithm described is that it occasionally classifies dragons as DEAD which can actually form two eyes.

SAFETY: This is a field similar to status but more useful for some purposes. In moyo.c there is a heuristic test for weakness based on the influence of surrounding dragons. The safety field is the same as the status unless the status is UNKNOWN. If the status is UNKNOWN then dragon.safety is set to CRITICAL if it is found to be weak by the algorithm in moyo.c.

VITALITY: A measure of the life potential of the dragon, used in semeai().

SEMEAI: true if the dragon is involved in a semeai (capturing race).


Node:Dragons in Color, Previous:Dragons, Up:Dragon

Colored display

You can get a colored ASCII display of the board in which each dragon is assigned a different letter; and the different safety values (ALIVE, DEAD, UNKNOWN, CRITICAL) have different colors. This is very handy for debugging.

Save a game in sgf format using CGoban, or using the -o option with GNU Go itself.

Open an rxvt window. (Xterm will not work. You may also use the Linux console.)

Execute:

gnugo -l [filename] -L [movenum] -T to get the colored display.

The color scheme: Green = ALIVE; Yellow = UNKNOWN; White = DEAD and Red = CRITICAL. Worms which have been amalgamated into the same dragon are labelled with the same letter.

Other useful colored displays may be obtained by using instead:

The colored displays are documented elsewhere (see Colored Display).


Node:Eyes, Next:, Previous:Dragon, Up:Top

Eyes and Half Eyes

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


Node:Local Games, Next:, Previous:Eyes, Up: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


Node:Eye Space, Next:, Previous:Local Games, Up:Eyes

Eye spaces

In order that each eyespace be assignable to a dragon, it is necessary that all the dragons surrounding it be amalgamated (see 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.


Node:Eye Space as Local Game, Next:, Previous:Eye Space, Up:Eyes

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.


Node:Eye Example, Next:, Previous:Eye Space as Local Game, Up:Eyes

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!


. !
.!


Node:Graphs, Next:, Previous:Eye Example, Up:Eyes

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 Eye Topology).

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 !.


Node:Eye Shape, Next:, Previous:Graphs, Up:Eyes

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}.


Node:Eye Topology, Previous:Eye Shape, Up:Eyes

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.


Node:Moyo, Next:, Previous:Eyes, Up:Top

Moyo

The file moyo.c contains algorithms for the computation of a number of useful things. Most can be displayed visually using the -m option (see Colored Display).


Node:Bouzy, Next:, Previous:Moyo, Up:Moyo

Bouzy's 5/21 algorithm

Bouzy's dissertation is available at:

<ftp://www.joy.ne.jp/welcome/igs/Go/computer/bbthese.ps.Z>

It contains an algorithm inspired by prior work of Zobrist and ideas from computer vision for determining territory. This algorithm is based on two simple operations, DILATION and EROSION. Applying dilation 5 times and erosion 21 times determines the territory.

To get a feeling for the algorithm, take a position in the early middle game and try the colored display using the -m 1 option in an RXVT window. The regions considered territory by this algorithm tend to coincide with the judgement of a strong human player.

Before running the algorithm, dead stones (dragon.status==0) must be "removed."

Referring to page 86 of Bouzy's thesis, we start with a function taking a high value (ex : +128 for black, -128 for white) on stones on the goban, 0 to empty intersections. We may iterate the following operations:

dilation : for each intersection of the goban, if the intersection is >= 0, and not adjacent to a <0 one, then add to the intersection the number of adjacent >0 intersections. The same for other color : if the intersection is <=0, and not adjacent to a >0 one, then sub to it the number of <0 intersections.

erosion : for each intersection >0 (or <0), substract (or add) the number of adjacent <=0 (or >=0) intersection. Stop at zero.

It's unbelievable, but it works.

the algorithm is just : 5 dilations, then 21 erosion. The number of erosions should be 1+n(n-1) where n=number of dilation, since this permit to have an isolated stone to give no territory. Thus the couple 4/13 also works, but it is often not good, for example when there is territory on the 6th line.

For example, let us start with a tobi.

           128    0    128

1 dilation :

            1          1

       1   128    2   128   1

            1          1

2 dilations :

            1          1

       2    2     3    2    2

   1   2   132    4   132   2   1

       2    2     3    2    2

            1          1

3 dilations :

            1          1

       2    2     3    2    2

   2   4    6     6    6    4   2

1  2   6   136    8   136   6   2   1

   2   4    6     6    6    4   2

       2    2     3    2    2

            1          1

and so on...

Next, with the same example

3 dilations and 1 erosion :

             2     2     2

    0   4    6     6     6    4

0   2   6   136    8    136   6    2

    0   4    6     6     6    4

             2     2     2

3 dilations and 2 erosions :

                 1

      2    6     6     6    2

      6   136    8    136   6

      2    6     6     6    2

                 1

3 dil. / 3 erosions :

           5     6     5

      5   136    8    136   5

           5     6     5

3/4 :

          3     5     3

      2  136    8    136   2

          3     5     3

3/5 :

          1     4     1

         136    8    136

          1     4     1

3/6 :

                3

         135    8    135

                3

3/7 :

         132    8    132

I interpret this as a 1 point territory.


Node:Implementation, Next:, Previous:Bouzy, Up:Moyo

Implementation

The file moyo.c currently uses this algorithm by three ways : 5/21 for territory evaluation, 5/10 for moyo evaluation, and 4/0 for "area ownership", aka "big moyo" and meta cut/connect. Beware, these evaluations don't care of the life and death status of groups. It's only a "graphical" analysis of areas of influence.

After dragon evaluation, the function make_moyo() is called once to make the static evaluation of the goban : make_moyo() returns the difference in estimated territory (terri_eval[0]) and computes terri_eval[3] and moyo_eval[3]. It also computes the area_grid for area ownership & (future) weak group analysis. All functions assume that stones evaluated DEAD in the Dragon structure are really dead, and act as they were removed from the board. Technically, the dilations are made with binary operators (one row of the goban is stored in two integer, one black and one white), then the result is stored in a classical array [19][19] for the erosion computation.

These functions can be used with a color argument whose value is for current player or for opponent color: delta_terri, diff_terri, delta_terri_color, delta_moyo, diff_moyo, delta_moyo_color, meta_connect and delta_area_color.

The 5,21,10 ... values are stored in the constants:

#define MAX_DILAT 5
#define MAX_ERODE 21
/* 4 or 5 */
#define MOY_DILAT 5    /* for delta_moyo */
/* must MOY_ERODE <= MAX_ERODE if MOY_DILAT != MAX_DILAT*/
#define MOY_ERODE 10

/* number of dilation for area ownership, must be <= MAX_DILAT */
#define OWNER_DILAT 4


Node:5/21 Territory, Next:, Previous:Implementation, Up:Moyo

5/21 : territory

As we have seen, 5 dilations/21 erosions produces GNU Go's image of territory. These values are determined by the following considerations:

the public functions are :

extern variables :


int terri_eval[3] computed once by make_moyo()
   terri_eval[WHITE] : white territory
   terri_eval[BLACK] : black territory
   terri_eval[0] : difference in territory (color - other_color)

int terri_test[3] computed by delta_terri()
   terri_test[WHITE] : territory evaluation from delta_terri() for BLACK
   terri_test[BLACK] : territory evaluation from delta_terri() for WHITE
   terri_test[0] : return of delta_terri(), difference in territorial
   evaluation between terri_test() and first call to make_moyo().

Sample: b marks black's estimated territory (X), w or White (O).

White to play : a move to J11 will bring +7 territorial balance.

   A B C D E F G H J K L M N
13 b b b b . . . . . . . . . 13
12 b b b X b . . . . . . . . 12
11 b b b b b . . . . . O . . 11
10 b b b X b . . . . . . . . 10
 9 b b b b . . . . . . X . . 9
 8 b b X b . . . . . . . . . 8     White territory 22
 7 b b b . . . . . . . . . . 7
 6 . b b . . . . . . . . . . 6     Black territory 30
 5 . . b . . . . . . . O . . 5
 4 . . . X . . . . w w w w w 4
 3 . . . . . . O w w O w w w 3
 2 . . . . . . . w w w w w w 2
 1 . . . . . . . w w w w w w 1
   A B C D E F G H J K L M N

delta_terri :

 20 21 20 19 11 10 10  8  7  6  3  4  3
 23 23 21  X 12 11 13 10  8  6  3  3  4
 25 26 25 22 10 11  8  8  7  6  O  5  5
 24 26 27  X  9  8  8  5  5  2  3  7  7
 25 27 26 13 10  7  7  7  5  4  X 11  8
 23 25  X 12 10  9  6  8  5  6  5 10  5
 21 19 18 13 11 11 11 10  6  5  5  4  5
 14 14 14 13 11 12 13  7  5  2  2  2  2
 14 12 11 11 12 11  7  5  2  0  O  1  1
 11 10  9  X  9  5  4  2  0 -1 -1 -1  1
  9  8 14  7  4  3  O -1 -1  O -1 -1 -1
  8  7  6  7  6  2  1 -1 -1 -1 -1 -1 -1
  5  4  5  4  3  2  1  0 -1 -1 -1 -1 -1


Node:5/10 Moyo, Next:, Previous:5/21 Territory, Up:Moyo

5/10 : moyo

5 dilations and 10 erode give a value we call MOYO. Moyo has an advantage over territory (5/21) since it permits immediate computation of the value of a move. It is intended to be used in conjunction with some patterns as an helper. The value 5 and 10 are empiric, other could have a similar effect : 4/8, 5/9 , etc... Using 5 dilation permit to use some common results with territorial evaluation 5/21. The moyo evaluation does not count prisonners nor komi, but takes in account dragon DEAD stones.

the public functions are :

extern variables :

int moyo_eval[3] is computed once by make_moyo()
   moyo_eval[WHITE] : white moyo evaluation
   moyo_eval[BLACK] : black moyo evaluation
   moyo_eval[0] : difference in moyo (color - other_color)

int moyo_test[3] is computed by delta_moyo for testing one move
   moyo_test[WHITE] : white moyo evaluation from delta_moyo()
   moyo_test[BLACK] : ...
   moyo_test[0] : return of delta_moyo(), difference in
     moyo between test moyo and first moyo evaluation (color - other_color)

Example: white to play. A move at F4 would increase moyo balance by 20 points for white.

   A B C D E F G H J K L M N
13 b b b b b b b b b b . . . 13
12 b b b b b b b b b b . . . 12
11 b b b b X b b b b b . . . 11
10 b b X b b b b b b X . . . 10
 9 b b b b b b . . . . . . . 9
 8 b b b b b . . . . . O w . 8     White territory 18
 7 . . b X b . . . . . w w w 7
 6 . . . . . . . . . w w w w 6     Black territory 32
 5 . . . . . . . . . w w w w 5
 4 . . w O w . . . w w w w w 4   W/B moyo 36/50 : -14
 3 . . w w w w . . w w O w w 3
 2 . . . w . . . . . w w w w 2
 1 . . . . . . . . . w w w w 1
   A B C D E F G H J K L M N

delta_moyo :

 15 17 19 23 24 26 21 21 18 19 15 11  9
 18 20 20 24 29 29 24 23 20 21 20 14  8
 17 23 19 16  X 26 33 31 21 19 25 14  8
 16 20  X 15 16 35 34 32 29  X 13 10  5
 16 16 18 15 16 17 23 39 19  7  4  4  2
 15 16 13 29 17 25 24 20 12  6  O  0  0
 14 16 17  X 23 23 21 18 14  6  1  0  0
 20 13 13 13 16 19 31 14 11  7  3  0  0
 17 16  6  8  9 25 25 23  8  5  2 -1  0
 13 14 12  O 17 20 21 19 17  3  2 -1 -1
 11 11  9 22 13 17 17 17 16 14  O -1 -1
 11  9 21 20 21 13 16 15 14 12 12 -1 -1
  9 21 20 20 20 21 13 14 12 12 12 12 -1


Node:4/0 Area, Next:, Previous:5/10 Moyo, Up:Moyo

4/0 : area ownership

This algorithm finds areas of influence, something bigger than classical moyo, with light connection between stones. This tool is intended to find weak and strong groups very early in the game. Currently it is used as an helper to find moves who cut ot connect these areas at a large scale. This module of GNU Go will probably evolve.

The first use will be to test if a tested move will :

The public functions are :

The values for cutting/connecting can be changed (all this need tuning):

/* number of bonus points for each group connected and opponent
   group cut
*/
#define GR_BONUS_CONNECT 15
#define GR_BONUS_CUT 10

Sample:

The 'b' black area are changed to '-' for readibility. A white move at K5 got 25 points : this means that meta_connect thinks it would separate the J3 stone from K10, and connect the white stones together:

   A B C D E F G H J K L M N
13 . . - - . w w . - - - . . 13
12 . - - - . w w . - - - - . 12
11 - - - - . w w . - - - - - 11
10 - - - X . O w . - X - - - 10
 9 - - - - . w w . - - - - - 9
 8 - - X - - w w . - - - - . 8     White territory 2
 7 - - - - - w w . - - w w . 7
 6 - - - . . w . - - w w w w 6     Black territory 4
 5 . . . w w w - - - w w w w 5
 4 w w w w w w - - - w O w w 4   W/B moyo 19/24 : -5
 3 w w w O w w - - X - w w w 3
 2 w w w w w w - - - - w w w 2
 1 . w w w w w - - - - w w . 1
   A B C D E F G H J K L M N

area 2 A11: color B, 2 stone 28 spaces area 4 A4: color W, 2 stone 39 spaces area 9 G5: color B, 2 stone 46 spaces area 11 K6: color W, 1 stone 21 spaces

meta_connect :

  .  .  .  .  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .  .  .  .  .
  .  .  .  X  .  O  . 10 10  X  .  .  .
  .  .  .  .  .  . 10 10 25 25 10  .  .
  .  .  X  .  . 10 10 25 25 25 25 10  .
  .  .  .  . 10 10 10 25 25 25 25 25  .
  .  .  .  .  . 10 25 25 25 25 25 10  .
  .  .  .  .  .  . 25 25 25 25 10  .  .
  .  .  .  .  .  .  . 25 25 10  O  .  .
  .  .  .  O  .  .  .  .  X  .  .  .  .
  .  .  .  .  .  .  .  . 15  .  .  .  .
  .  .  .  .  .  .  . 15 15 15  .  .  .

After white K5, black played G3, now playing in the center could connect all white forces.

   A B C D E F G H J K L M N
13 . . - - . w w . - - - . . 13
12 . - - - . w w . - - - - . 12
11 - - - - . w w . - - - - - 11
10 - - - X . O w . - X - - - 10
 9 - - - - . w w . - - - - - 9
 8 - - X - - w w . - - - - . 8     White territory 1
 7 - - - - - w . w w w w w . 7
 6 - - - . . . - w w w w w w 6     Black territory 4
 5 . . . w w - - w w O w w w 5
 4 w w w w w - - - - w O w w 4   W/B moyo 17/26 : -9
 3 w w w O w - X - X - w w w 3
 2 w w w w w - - - - - w w w 2
 1 . w w w w - - - - - w w . 1
   A B C D E F G H J K L M N

area 2 A11: color B, 2 stone 28 spaces area 4 A4: color W, 1 stone 20 spaces area 8 F13: color W, 1 stone 12 spaces area 9 F5: color B, 2 stone 20 spaces area 12 H7: color W, 2 stone 27 spaces area 13 J13: color B, 1 stone 25 spaces

meta_connect :

  .  .  .  .  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  . 15  .  .  .  .  .
  .  .  .  X  .  O 15 15 15  X  .  .  .
  .  .  .  . 15 30 15 15 15 15 15  .  .
  .  .  X 15 30 30 30 15 15 15 15  .  .
  .  . 15 30 30 30 30 30 15 15 15  .  .
  .  . 15 30 30 30 30 30 15 15  .  .  .
  .  .  . 15 30 30 30 30 15  O  .  .  .
  .  .  .  . 15 30 30 15  .  .  O  .  .
  .  .  .  O  . 15  X 10  X  .  .  .  .
  .  .  .  .  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  . 15  .  .  .  .  .


Node:Weak groups, Next:, Previous:4/0 Area, Up:Moyo

Weak groups

Dragon SAFETY is a modification of the dragon STATUS that takes into account the weakness of groups, as found by this algoritm.

Weak dragons with dragon[m][n].status == UNKNOWN

are tagged by

dragon[m][n].safety = CRITICAL

These are defined as having 2 or more stones with between 0 and 20 points of area, computed using the 4/0 algorithm.

Function:

int number_weak(int color): returns the number of weak groups found for one color.


Node:Big move, Next:, Previous:Weak groups, Up:Moyo

Big move priority

(experimental) the use of search_big_move function aim to evaluate the value of moves by an empiric rule. Then, if the move proposed by genmove() got a lower priority, the big_move is played. Use option -p fearless to select it.


Node:Caching, Previous:Big move, Up:Moyo

Caching of delta_*_color() functions

This 3 functions use the same goban stack for storing their results. The stack size is :

#define COLOR_STACK_SIZE 70
static goban_t boardstack[COLOR_STACK_SIZE];

This is intentionally left low to minimise memory usage. When the stack is full, the older values are suppressed when a new need of storage come. (the stored values are available during one "movenum" turn)

Beware: all dead groups are considered as removed for these functions !


Node:Patterns, Next:, Previous:Moyo, Up:Top

The Pattern Code


Node:Patterns Overview, Next:, Previous:Patterns, Up:Patterns

Patterns Overview

A database of patterns is supplied in patterns.db These are ascii representations, of the form:

Pattern EB115

??o|          sente hane
?Oo|
XX*|
...|
?.?|

:8,50,0,O,5,5,5,0,0,sente_hane_helper

where O marks a friendly stone, X marks enemy stones, . marks an empty vertex, * marks O's next move, o marks a square either containing O or empty but not X. (The symbol x, which does not appear in this pattern, means X or .) Finally ? Indicates a location where we don't care what is there, except that it cannot be off the edge of the board.

The line of |'s along the right in this example is the edge of the board itself--this is an edge pattern. Corners can also be indicated. So this pattern describes a hane on the first line. The o makes sure that it would not be in atari immediately, though the matcher can check for this automatically (see class). Elements are not generated for ? markers, but they are not completely ignored - see below.

The line beginning : describes various attributes of the pattern, such as its symmetry and its importance. Optionally, a function called a "helper" can be provided to assist the matcher in deciding the worth of the move, and a simple measure of the influence of nearby stones can be factored in. In this case, there is a helper, the sente_hane_helper, which may be found in helpers.c. Most patterns do not require a helper, and this field is filled with NULL.

The matcher searches the board for places where this layout appears on the board, and chooses the highest scoring pattern.


Node:Pattern Attributes, Next:, Previous:Patterns Overview, Up:Patterns

Pattern Attributes

After the pattern, some supplementary information in the format:

  :trfno, patwt, assistance, classification,
       obonus, xbonus, splitbonus, minrand, maxrand, helper_function

Here trfno represents the number of transformations of the pattern to consider, usually 8 (no symmetry, for historical reasons), or one of |, \, /, -, +, X, where the line represents the axis of symmetry. (E.g. | means symmetrical about a vertical axis.) patwt is the numerical pattern value - if there is a helper function (see below), it is the maximum weight it can return.

The assistance attribute reflects the fact that a pattern may have different values depending on external circumstances. For example, a pattern to connect is less important where I am powerful, but more important where my opponent is powerful. There are two different methods of assistance, wind assistance (see Wind Assistance) and moyo assistance (see Moyo Assistance).

The classification scheme is as follows : a sequence of zero or more of the following characters, each with a different meaning.

One common classification is OX (which rejects pattern if either sides stones are dead). The string - may be used as a placeholder. (In fact any characters other than the above and , are ignored.)

o and O could conceivably appear in a class, meaning it applies only to UNKNOWN. Similarly X and x could be used together.

Some care must be taken with the A and D classes. If more than one worm that can be attacked or defended is present in the pattern, only one of them, arbitrarily chosen, will be found.

The classes B and C can be used together. If both connection values are greater than 0, the pattern is given a combined value which is the larger of them plus a fraction of the smaller one.

The values obtained for the B and C classes are further limited by the sum of the primary pattern weight (patwt) and the assistance value. The bonuses described below are applied after this limitation.

The field obonus is a bonus which is added when the pattern contains any dragon of color O with dragon[m][n].safety != 0. This means that the dragon has size at least 2 and between 0 and 20 points of area, computed by the Bouzy 4/0 algorithm. Similarly the xbonus is added when the pattern contains at least one weak X dragon.

The field splitbonus is a bonus which is added when the move splits opponent dragons on a large scale or joins own dragons in the same manner (see Moyo).

To avoid playing the same moves each game, minrand and maxrand specifies a random adjustment of the move value, uniformly distributed between minrand and maxrand, inclusively. This feature is primarily used for fuseki moves, where the choice of exact moves is a matter of inspiration anyway.

helper_fn is the name of a C function which will be invoked to assist in the evaluation of the pattern. It will be passed the co-ordinates on the board of the pattern element marked *, the rotation of the pattern which has been matched, and the color of the piece for whom the move is being considered. (O in the key above). Facilities are provided for navigating around the pattern taking the rotation into account.


Node:Defensive Patterns, Next:, Previous:Pattern Attributes, Up:Patterns

Defensive Patterns

Usually a pattern will only contribute a move if its value is large enough to outweigh all other moves which have been found. There is an exception to this, however. If the pattern classification string contains a D, the pattern is a defensive one. If an O string is found in the pattern which can be captured, and if the move at * defends it, then the point of defense (worm[m][n].defendi, worm[m][n].defendj) is moved to *. This means that even if the pattern has small value, the defensive move will be remembered later when defender() is run.


Node:Offensive Patterns, Next:, Previous:Defensive Patterns, Up:Patterns

Offensive Patterns

Another exception is patterns with a classification string containing an A. These patterns are offensive ones. If an X string is found in the pattern which can be captured but also defended, and if the move at * also attacks it, then the point of attack (worm[m][n].attacki, worm[m][n].attackj) is moved to *. This means that even if the pattern has small value, the offensive move will be remembered later when attacker() is run. Notice that this means that the suggested move will never find an attack that wasn't found otherwise, but it can be used to capture enemy stones more efficiently or with better shape than the move attacker() would have found unassisted.


Node:Helper Functions, Next:, Previous:Offensive Patterns, Up:Patterns

Helper Functions

Helper functions can be provided to assist the matcher in weighing up the importance of a move. The helper is supplied with the compiled pattern entry in the table, and the (absolute) position on the board of the * point.

One difficulty is that the helper must be able to cope with all the possible transformations of the pattern. To help with this, a transformation number is supplied. This number can be passed to a utility function offset() with the relative co-ordinates in the original, untransformed pattern. This function will return the actual board co-ordinates to use for the indicated stone.

The actual helper functions are in helpers.c. They are declared in patterns.h.

As an example to show how to write a helper function, we consider defend_bamboo_helper. This begins with a comment:

/*

?X?        ?X?
O.O        ObO
O.*        Oat

*/

The image on the left is the actual pattern. On the right we've taken this image and added letters to label (ti, tj), (ai, aj) and (bi, bj). Of course t is always at *, the point where GNU Go will move if the pattern is adopted.

int
defend_bamboo_helper (ARGS)
{
  int ai, aj, bi, bj;
  int tval=0;
  int other=OTHER_COLOR(color);

  OFFSET(0, -1, ai, aj);
  OFFSET(-1, -1, bi, bj);

  if (strategic_distance_to(other, ti, tj)>10)
    return (0); /* solid connection is better */
  if (TRYMOVE(bi, bj, other)) {
    if (TRYMOVE(ai, aj, color)) {
      if (safe_move(ti, tj, other))
	  tval=COMPUTE_SCORE;
      popgo();
    }
    popgo();
  }
  return (tval);
}

The OFFSETs tell GNU Go the positions of the two stones at a=(ai,aj) and b=(bi,bj). The correctness of the coordinates (relative to t=*=(ti,tj)) can be confirmed by consulting the diagram in the prefatory comment. The macro TRYMOVE invokes the function trymove(), ARGS supplies standard arguments to the helper, and COMPUTE_SCORE assigns the value of the pattern (see Pattern Attributes).

The pattern is subjected to two tests. First, the strategic_distance to X (see Dragon) must not be too great. The rationale behind this test is that if the strategic distance is great, then simply making a solid connection probably secures one point more territory. On the other hand if the strategic distance is small, the region in question may not be secure territory, and the bamboo joint is often better.

Hand-coding helpers such as this one is a powerful tool but not always needed. The same functionality can often be obtained more easily using an autohelper (see Autohelpers).


Node:Wind Assistance, Next:, Previous:Helper Functions, Up:Patterns

Wind Assistance

Wind assistance, wind(ucutoff, uvalue, mycutoff, myvalue), is based on the power of the stones in a neighborhood of the considered move. My power (mypower) and your power (upower) are measured by the function testwind(). The actual value of the wind assistance is given by the formula:

To calculate a color's power near the point *, we sum 6-d) where d is the distance of a stone to *, where the sum is over all stones of the given color with d<6.

upower and ucutoff must have the same sign, as must mypower and mycutoff. In practice we have mostly used positive values for these parameters. We have always given uvalue and myvalue the value 1 or in rare instances 2.

For example

"connect if invaded"

OX..
.*.O
.?.?

:8,55,wind(20,1,0,0),-,0,0,0,NULL

These represent additional biases to the score for the influence of nearby stones. The first pair are a multiplier and a cutoff for enemy stones, and the second for friendly stones. The actual weight (computed in the function compute_score()) is given by the formula:

  uvalue*min(upower,abs(ucutoff)) + myvalue*min(mypower,abs(mycutoff)).

Typically uvalue (if nonzero) would have the value 1, meaning that the score increases by 1 for each increase in upower, up to a maximum of ucutoff, after which it does not increase. Thus in this example, the value of the pattern can increase up to 75, becoming more valuable when the opponent becomes strong in the area. This is a good feature for patterns which help the safety of our group.


Node:Moyo Assistance, Next:, Previous:Wind Assistance, Up:Patterns

Moyo Assistance

Moyo assistance, moyo(moyocutoff, moyovalue), is based on an estimation of "moyo" (see Moyo).

In practice this is a combination of territory and influence for both players. The function delta_moyo() computes the difference in moyo between the current position and after the move has been made. The actual value of the moyo assistance is given by the formula:

  moyovalue*min(deltamoyo,moyocutoff)


Node:Tuning, Next:, Previous:Moyo Assistance, Up:Patterns

Moyo Assistance

Since the pattern database decides GNU Go's personality to a very great extent, much time can be devoted to "tuning" it. Here are some suggestions.

If you want to experiment with modifying the pattern database, invoke with the -a option. This will cause every pattern to be evaluated, even if its maximum possible contribution is smaller than a pattern already found. This makes the program less efficient, but then you can see how much you must increase a pattern value in order to `promote' a better move over the move actually chosen.

You can obtain a Smart Go Format (SGF) record of your game in at least two different ways. One is to use CGoban to record the game. You can also have GNU Go record the game in Smart Go Format, using the -o option. It is best to combine this with -a. Do not try to read the sgf file until the game is finished and you have closed the sgf window. This does not mean that you have to play the game out to its conclusion. You may close the CGoban window on the game and GNU Go will close the sgf file so that you can read it.

If you record a game in SGF form using the -o option, GNU Go will add labels to the board to show all the moves it considered, with their values. This is an extremely useful feature, since one can see at a glance whether the right moves with appropriate weights are being proposed by the pattern matcher. If bad moves are being proposed, one may modify a pattern to exclude it, or reduce the value of the pattern. If important moves are not proposed at all, you may have found a gap in the pattern database, and you can add a pattern. If the right move is proposed but with too low a score, this may be a sign that you should adjust its weight upwards. It is almost always best to make the *minimum* adjustment needed to correct the bad behavior.

If you decide to add a pattern, give some thought to adding the pattern in exactly the right generality by putting ? at irrelevant locations, and by using the o and x options.

First, due to a bug of unknown nature, it occasionally happens that GNU Go will not receive the SIGTERM signal from CGoban that it needs to know that the game is over. When this happens, the sgf file ends without a closing parenthesis, and CGoban will not open the file. You can fix the file by typing:

 echo ")" >>[filename]

at the command line to add this closing parenthesis. Or you could add the ")" using an editor.

Pattern weights exceeding 99 can be displayed by CGoban but you may have to resize the window in order to see all three digits. Grab the lower right margin of the CGoban window and pull it until the window is large. All three digits should be visible.

If you are playing a game without the -o option and you wish to analyze a move, you may still use CGoban's "Save Game" button to get an SGF file. It will not have the values of the moves labelled, of course.

Once you have a game game saved in SGF format, you can analyze any particular move by running:

  gnugo -l [filename] -L [move number] -t -a -w

to see why GNU Go made that move, and if you make changes to the pattern database and recompile the program, you may ask GNU Go to repeat the move to see how the behavior changes.

Alternatively, you can use the CGoban tools to delete all moves after and including the one you want to study, and then load without the -L option.

If a pattern is contributing a bad move, you can adjust its weight downward, or you you can adjust the weight of a pattern which is contributing a good move up. If no pattern is contributing the move that you think should be made, then you may add a pattern.

You can also get a visual display of the dragons using the -T option. The default GNU Go configuration tries to build a version with color support using either curses or the ansi escape sequences. You are more likely to find color support in rxvt than xterm, at least on many systems, so we recommend running:

  gnugo -l [filename] -L [move number] -T

in an rxvt window. If you do not see a color display, and if your host is a GNU/Linux machine, try this again in the Linux console.

Worms belonging to the same dragon are labelled with the same letters. The colors indicate the value of the field dragon.safety, which is set in moyo.c.

Green:  GNU Go thinks the dragon is alive
Yellow: Status unknown
Blue:   GNU Go thinks the dragon is dead
Red:    Status critical (1.5 eyes) or weak by the algorithm
        in moyo.c

If you want to get the same game over and over again, you can eliminate the randomness in GNU Go's play by changing the value of seed in main.c to a fixed nonzero integer. If seed==0, then GNU Go will play a different game each time.


Node:Autohelpers, Next:, Previous:Tuning, Up:Patterns

Autohelpers

In addition to the hand-written helper functions in helpers.c there can be automatic helper functions. These are briefly described in the pattern database and compiled into C source which goes into patterns.c.

The "pattern compiler" is based on the idea of constraint diagrams and expressions. To give an example, one pattern consists of a pair of diagrams:

Pattern ED54

|oOOX           maybe capture corner
|..XO
|.*XO
|..??
+----

:8,85,0,s,10,0,0,0,0,NULL

|obbX
|..Aa
|.*Aa
|..??
+----

;(lib(A)<=4) && (lib(a)>=lib(A)-1) && (lib(b)>=lib(A))
;&& (!dead(A)||attack(a))

The first diagram and the colon line has exactly the same interpretation as usual. The diagram below and the semicolon line(s) are optional and can only be used to reject the pattern given above. Note that some strings now have labels which are referred to in the constraint.

Only strings for which we have constraints need be labeled. Labels may be any letter except OoXxt. To make the database consistent and easy to read it is our convention that X strings should be upper-case and O strings lower-case, but the implementation does not enforce this. Neither does it require that all stones in a string be labeled (it goes with the first appearance) but it is good practice to do so anyway.

The constraint expression is transformed by mkpat into an automatically generated helper function (there is a new field in the pattern struct, so it does not conflict with the old helper). lib(x) can be regarded as a macro which is expanded by mkpat into worm[xi][xj].liberties. The resulting expression must be valid C code, otherwise the generated patterns.c won't compile. In principle any code can be written on the line but to keep the database maintainable we should restrict ourselves to boolean and arithmetic expressions, which anyone should be able to understand and write with no more than a little trouble. If the expression evaluates to true the pattern is accepted by the autohelper, if false it is rejected. If there are multiple semicolon lines for the same pattern, these are concatenated before generating the code.


Node:Autohelper Functions, Next:, Previous:Autohelpers, Up:Patterns

Autohelper Functions

lib(x)
lib2(x)
lib3(x)
lib4(x)

Number of first, second, third, and fourth order liberties of a worm respectively (see Dragon).

xlib(x)
olib(x)

The number of liberties that an enemy or own stone, respectively, would obtain if played at the empty intersection x.

ko(x)

True if x is either a stone or an empty point involved in a ko position.

status(x)
alive(x)
unknown(x)
critical(x)
dead(x)

Status of a dragon. status(x) returns an integer that can have the values ALIVE, UNKNOWN, CRITICAL, or DEAD. The four other functions returns true if the dragon has the corresponding status and false otherwise (see Dragon).

genus(x)

The number of eyes of a dragon. It is only meaningful to compare this value against 0, 1, or 2.

xarea(x)
oarea(x)
xmoyo(x)
omoyo(x)
xterri(x)
oterri(x)

Functions related to various kinds of influence and territory estimations (see Moyo). xarea(x) evaluates to true if x is either a living enemy stone or an empty point within his "area". oarea(x) is analogous but with respect to our stones and area.

cutstone(x) returns worm[x].cutstone, which can be 0, 1, or 2 (see Dragon).

weak(x)

True for a dragon with safety==CRITICAL.

attack(x)
defend(x)

These give the results of tactical reading. attack(x) is true if the worm can be captured, defend(x) is true if there also is a defending move. Please notice that defend(x) will return false if there is no attack on the worm.

safe_xmove(x)
safe_omove(x)

True if an enemy or own stone, respectively, can safely be played at x. By safe it is understood that the move is legal and that it cannot be captured right away.

odefend_against(x,y)
xdefend_against(x,y)

True if an own stone at x would stop the enemy from safely playing at y, and conversely for the second function.

does_defend(x,y)
does_attack(x,y)

True if a move at x defends/attacks the worm at y. For defense a move of the same color as y is tried and for attack a move of the opposite color.

xplay_defend(a,b,c,...,z)
oplay_defend(a,b,c,...,z)
xplay_attack(a,b,c,...,z)
oplay_attack(a,b,c,...,z)

These functions make it possible to do more complex reading experiments in the constraints. All of them work so that first the sequence of moves a, b, c,... is played through with alternating colors, starting with X or O as indicated by the name. Then it is tested whether the worm at z can be attacked or defended, respectively. It doesn't matter who would be in turn to move, a worm of either color may be attacked or defended. For attacks the opposite color of the string being attacked starts moving and for defense the same color starts. The defend functions return true if the worm cannot be attacked in the position or if it can be attacked but also defended. The attack functions return true if there is a way to capture the worm, whether or not it can also be defended.

eye(x)
proper_eye(x)
marginal_eye(x)

True if x is an eye space for either color, a non-marginal eye space for either color, or a marginal eye space for either color, respectively.


Node:Pattern Matcher, Next:, Previous:Autohelper Functions, Up:Patterns

Pattern Matcher

The pattern code in GNU Go 2.6 is fairly straightforward conceptually, but because the matcher consumes a significant part of the time in choosing a move, the code is optimized for speed. Because of this there are implementation details which obscure things slightly.

In GNU Go 2.6, the ascii patterns.db file is precompiled into tables (see patterns.h) by a standalone program mkpat.c, and the resulting file patterns.c is compiled and linked into the main gnugo executable.

Each pattern is compiled to a header, and a sequence of elements, which are (notionally) checked sequentially at every position and orientation of the board. These elements are relative to the pattern 'anchor' (or origin). One X or O stone is (arbitrarily) chosen to represent the origin of the pattern. (We cannot dictate one or the other since some patterns contain only one colour or the other.) All the elements are in co-ordinates relative to this position. So a pattern matches "at" board position (m,n,o) if the the pattern anchor stone is on (m,n), and the other elements match the board when the pattern is transformed by transformation number 'o'. (See below for the details of the transformations, though these should not be necessary)


Node:Symmetry, Next:, Previous:Pattern Matcher, Up:Patterns

Symmetry and Transformations

In general, each pattern must be tried in each of 8 different permutations, to reflect the symmetry of the board. But some patterns have symmetries which mean that it is unnecessary (and therefore inefficient) to try all eight. The first character after the ':' can be one of '8','|','\','/', 'X', '-', '+', representing the axes of symmetry.

transformation   I    -    |     .     \    l    r     /
                ABC  GHI  CBA   IHG   ADG  CFI  GDA   IFC
                DEF  DEF  FED   FED   BEH  BEH  HEB   HEB
                GHI  ABC  IHG   CBA   CFI  ADG  IFC   GDA

                 a    b    c     d     e    f    g     h

Then if the pattern has the following symmetries, the following are true...

|  c=a, d=b, f=e, h=g
-  b=a, c=d, e=f, g=i
\  e=a, g=c, f=b, h=d
/  h=a, f=c, g=b, e=d
X  a=d=e=h, b=c=f=g
+  a=b=c=d, e=f=g=h

We can choose to use transformations a,d,f,g as the unique transformations for patterns with either | or \ symmetry.

Thus we choose to order the transformations a,f,d,g,.... and choose first 2 for X and -, the first 4 for |, -, /, and \, and all 8 for non-symmetrical patterns.


Node:Matcher Details, Next:, Previous:Symmetry, Up:Patterns

Matcher Details

i) An entry in the pattern header states whether the anchor is an X or an O. This helps performance, since all transformations can be rejected at once if the anchor stone does not match. (Ideally, we could just define that the anchor is always O or always X, but some patterns contain no O's and some contain no X's.)

ii) The pattern header contains the size of the pattern (ie the co-ordinates of the top left and bottom right elements) relative to the anchor. This allows the pattern can be rejected quickly if there is not room for the pattern to fit around the anchor stone in a given orientation (ie it is too near the edge of the board). The bounding box information must first be transformed like the elements before it can be tested, and after transforming, we need to work out where the top-left and bottom-right corners are.

iii) The edge constraints are implemented by notionally padding the pattern with rows or columns of '?' until it is exactly 19 elements wide or high. Then the pattern is quickly rejected by (ii) above if it is not at the edge. So the example pattern above is compiled as if it was written

"example"
.OO????????????????
*XX????????????????
o??????????????????
:8,80

iv) The elements in a pattern are sorted so that non-space elements are checked before space elements. It is hoped that, for most of the game, more squares are empty, and so the pattern can be more quickly rejected doing it this way.

v) The patterns themselves are sorted by decreasing maximum-weight, which is the maximum value the pattern can take, taking weight and wind assistance into account. For this to work, the weight stored for patterns with helpers must be the maximum which the helper can return. As a hint, to simplify maintenance, the helper can access the stored weight from the pattern structure passed in.

vi) The actual tests are performed using an 'and-compare' sequence. Each board position is a 2-bit quantity. %00 for empty, %01 for O, %10 for X. We can test for an exact match by and-ing with %11 (no-op), then comparing with 0, 1 or 2. The test for 'o' is the same as a test for 'not-X', ie not %10. So and with %01 should give 0 if it matches. Similarly 'x' is a test that bit 0 is not set.


Node:Grid Optimization, Next:, Previous:Matcher Details, Up:Patterns

The "Grid" Optimization

This is a compile time option. By editing the makefile, you can use this faster code to match patterns. The only disadvantage to using this code is that it might be harder to understand and debug.

As described in (vi), the comparisons between pattern and board are performed as 2-bit bitwise operations. Therefore they can be performed in paralled, 16-at-a-time on a 32-bit machine.

Suppose the board is layed out as follows :

 .X.O....OO
 XXXXO.....
 .X..OOOOOO
 X.X.......
 ....X...O.

which is internally stored internally in a 2d array (binary)

 00 10 00 01 00 00 00 00 01 01
 10 10 10 10 01 00 00 00 00 00
 00 10 00 00 01 01 01 01 01 01
 10 00 10 00 00 00 00 00 00 00
 00 00 00 00 10 00 00 00 01 00

we can compile this to a composite array in which each element stores the state of a 4x4 grid of squares :

 ????????  ????????  ???????? ...
 ??001000  00100001  10000100
 ??101010  10101010  10101001
 ??001000  00100000  10000001

 ??001000  00100001  ...
 ??101010  10101010
 ??001000  00100000
 ??001000  10001000
...

 ??100010  ...
 ??000000
 ????????
 ????????

Where '??' is off the board.

We can store these 32-bit composites in a 2d merged-board array, substituting the illegal value %11 for '??'.

Similarly, for each pattern, mkpat produces appropriate 32-bit and-value masks for the pattern elements near the anchor. It is a simple matter to test the pattern with a similar test to (vi) above, but for 32-bits at a time.


Node:Joseki Compiler, Next:, Previous:Grid Optimization, Up:Patterns

The Joseki Compiler

GNU Go includes a joseki compiler in patterns/joseki.c. This processes an sgf file (with variations) and produces a sequence of patterns which can then be fed back into mkpat. The joseki database is in files in patterns/ called hoshi.sgf, komoku.sgf, sansan.sgf, mokuhadzushi.sgf and takamoku.sgf.

Not every node in the sgf file contributes a pattern. The nodes which contribute patterns have the joseki in the upper right corner, with the boundary marked with an A and the value given by a comment.


Node:Advanced Features, Next:, Previous:Joseki Compiler, Up:Patterns

Advanced Features

The joseki compiler is able to generate a constraint line in the .db. The square symbol is a shortcut for oarea(), the triangle is xarea() and the circle is (!oarea()&&!xarea()) = an empty area.

The delimiter between value and classification in the SGF comment must be ;, for example:

81;
D

Spaces and \n may be omitted.

These features are experimental and are currently not used in the joseki files.


Node:Connection Patterns, Previous:Advanced Features, Up:Patterns

Connection Patterns

The patterns in patterns/conn.db are compiled separately from the other patterns. When a B pattern is found, a cutting point is set in the worm data structure and make eye space marginal for the connection inhibiting entries of the pattern. If it is a C pattern, amalgamate the dragons in the pattern.


Node:Reading, Next:, Previous:Patterns, Up:Top

Reading

The process of visualizing potential moves done by you and your opponent to learn the result of different moves is called "reading".


Node:Reading Basics, Next:, Previous:Reading, Up:Reading

Reading Basics

In GNU Go, this is done by the functions in engine/reading.c. Each of these functions has a separate goal to fill, and they call each other recursively to carry out the reading process.

The reading code makes use of a stack onto which board positions can be pushed. The parameter stackp is zero if GNU Go is examining the true board position; if it is higher than zero, then GNU Go is examining a hypothetical position obtained by playing several moves.

Many of the reading functions make use of null pointers. For example, a call to attack(i, j, &ai, &aj) will return 1 if the string at (i, j) can be captured, 2 or 3 if it can be attacked with ko, and 0 if it is safe. The point of attack (in case it is vulnerable) is returned in (ai, aj). However many times we do not care about the point of attack. In this case, we can substitute a null pointer: attack(i, j, NULL, NULL).

Depth of reading is controlled by a parameter depth. This has a default value DEPTH (in liberty.h), which is set to 14 in the distribution, but it may also be set at the command line using the -D option. If depth is increased, GNU Go will be stronger and slower. GNU Go will read moves past depth, but in doing so it makes simplifying assumptions that can cause it to miss moves.

Specifically, when stackp > depth, GNU Go assumes that as soon as the string can get 3 liberties it is alive. This assumption is sufficient for reading ladders.

Currently the reading code does not try to defend a string by attacking a boundary string with more than two liberties. Because of this restriction, it can make oversights. A symptom of this is two adjacent strings, each having three or four liberties, each classified as DEAD. To resolve such situations, a function small_semeai() (in engine/semeai.c) looks for such pairs of strings and corrects their classification.

The backfill_depth is a similar variable with a default 10. Below this depth, GNU Go will try "backfilling" to capture stones. For example in this situation:

.OOOOOO.    on the edge of the board, O can capture X but
OOXXXXXO    in order to do so he has to first play at a in
.aObX.XO    preparation for making the atari at b. This is
--------    called backfilling.

Backfilling is only tried with stackp <= backfill_depth. The parameter backfill_depth may be set using the -B option.

The fourlib_depth is a parameter with a default of only 5. Below this depth, GNU Go will try to attack strings with four liberties. The fourlib_depth may be set using the -F option.

The parameter ko_depth is a similar cutoff. If stackp<ko_depth, the reading code will make experiments involving taking a ko even if it is not legal to do so (i.e., it is hypothesized that a remote ko threat is made and answered before continuation). This parameter may be set using the -K option.

The reading functions generally return 1 for success, and 0 for failure. If the result depends on ko, they return 2 or 3. A return code of 2 means that the attack or defense is successful provided the attacker or defender is willing to ignore a ko threat; a return code of 3 means the attack or defense is successful provided the player can come up with a sufficiently large ko threat.

A partial list of the functions in reading.c:

The next few functions are essentially special cases of attack and find_defense. They are coded individually.


Node:Hashing, Next:, Previous:Reading Basics, Up:Reading

Hashing of positions

To speed up the reading process, we note that a position can be reached in several different ways. In fact, it is a very common occurrence that a previously checked position is rechecked, often within the same search but from a different branch in the recursion tree.

This wastes a lot of computing resources, so in a number of places, we store away the current position, the function we are in, and which worm is under attack or to be defended. When the search for this position is finished, we also store away the result of the search and which move made the attack or defense succeed.

All this data is stored in a hash table where Go positions are the key and results of the reading for certain functions and groups are the data. You can increase the size of the Hash table using the -M or --memory option see Invoking GNU Go.

The hash table is created once and for all at the beginning of the game by the function hashtable_new(). Although hash memory is thus allocated only once in the game, the table is reinitialized at the beginning of each move by a call to hashtable_clear() from genmove().


Node:Hash Calculation, Next:, Previous:Hashing, Up:Hashing

Calculation of the hash value

The hash algorithm is called Zobrist hashing, and is a standard technique for go and chess programming. The algorithm as used by us works as follows:

  1. First we define a GO POSITION. This positions consists of

    It is not necessary to specify the color to move (white or black) as part of the position. The reason for this is that read results are stored separately for the various reading functions such as attack3, and it is implicit in the calling function which player is to move.

  2. For each location on the board we generate random numbers:

    These random numbers are generated once at initialization time and then used throughout the life time of the hash table.

  3. The hash key for a position is the XOR of all the random numbers which are applicable for the position (white stones, black stones, and ko position).


Node:Hash Organization, Previous:Hash Calculation, Up:Hashing

Organization of the hash table

The hash table consists of 3 parts:

When the hash table is created, these 3 areas are allocated using malloc(). When the hash table is populated, all contents are taken from the Hash nodes and the Read results. No further allocation is done and when all nodes or results are used, the hash table is full. Nothing is deleted from the hash table except when it is totally emptied, at which point it can be used again as if newly initialized.

When a function wants to use the hash table, it looks up the current position using hashtable_search(). If the position doesn't already exist there, it can be entered using

hashtable_enter_position().

Once the function has a pointer to the hash node containing a function, it can search for a result of a previous search using hashnode_search(). If a result is found, it can be used, and if not, a new result can be entered after a search using hashnode_new_result().

Hash nodes which hash to the same position in the hash table (collisions) form a simple linked list. Read results for the same position, created by different functions and different attacked or defended strings also form a linked list.

This is deemed sufficiently efficient for now, but the representation of collisions could be changed in the future. It is also not determined what the optimum sizes for the hash table, the number of positions and the number of results are.


Node:Debugging, Previous:Hashing, Up:Reading

Debugging the reading code

The reading code searches for a path through the move tree to determine whether a string can be captured. We have a tool for investigating this with the --decidestring option. This may be run with or without an output file.

Simply running

gnugo -t -l [input file name] -L [movenumber] --decidestring [location]

will run attack() to determine whether the string can be captured. If it can, it will also run find_defense() to determine whether or not it can be defended. It will give a count of the number of variations read. The -t is necessary, or else GNU Go will not report its findings.

If we add -o output file GNU Go will produce an output file with all variations considered. The variations are numbered in comments.

This file of variations is not very useful without a way of navigating the source code. This is provided with the GDB source file, listed at the end. You can source this from GDB, or just make it your GDB init file.

If you are using GDB to debug GNU Go you may find it less confusing to compile without optimization. The optimization sometimes changes the order in which program steps are executed. For example, to compile reading.c without optimization, edit engine/Makefile to remove the string -O2 from the file, touch engine/reading.c and make. Note that the Makefile is automatically generated and may get overwritten later.

If in the course of reading you need to analyze a result where a function gets its value by returning a cached position from the hashing code, rerun the example with the hashing turned off by the command line option --hash 0. You should get the same result. (If you do not, please send us a bug report.) Don't run --hash 0 unless you have a good reason to, since it increases the number of variations.

With the source file given at the end of this document loaded, we can now navigate the variations. It is a good idea to use cgoban with a small -fontHeight, so that the variation window takes in a big picture. (You can resize the board.)

Suppose after perusing this file, we find that variation 17 is interesting and we would like to find out exactly what is going on here.

The macro 'jt n' will jump to the n-th variation.

(gdb) set args -l [filename] -L [move number] --decidestring [location]
(gdb) tbreak main
(gdb) run
(gdb) jt 17

will then jump to the location in question.

Actually the attack variations and defense variations are numbered separately. (But find_defense() is only run if attack() succeeds, so the defense variations may or may not exist.) It is redundant to have to tbreak main each time. So there are two macros avar and dvar.

(gdb) avar 17

restarts the program, and jumps to the 17-th attack variation.

(gdb) dvar 17

jumps to the 17-th defense variation. Both variation sets are found in the same sgf file, though they are numbered separately.

Other commands defined in this file:


dump will print the move stack.
nv moves to the next variation
ascii i j converts (i,j) to ascii

#######################################################
###############      .gdbinit file      ###############
#######################################################

# this command displays the stack

define dump
set dump_stack()
end

# display the name of the move in ascii

define ascii
set gprintf("%o%m\n",$arg0,$arg1)
end

# move to the next variation

define nv
tbreak trymove
continue
finish
next
end

# move forward to a particular variation

define jt
while (count_variations < $arg0)
nv
end
nv
dump
end

# restart, jump to a particular attack variation

define avar
delete
tbreak sgf_decidestring
run
tbreak attack
continue
jt $arg0
end

# restart, jump to a particular defense variation

define dvar
delete
tbreak sgf_decidestring
run
tbreak attack
continue
finish
next 3
jt $arg0
end


Node:Utility Functions, Next:, Previous:Reading, Up:Top

Utility Functions

Here are some common utility functions from engine/utils.c.


Node:End Game, Next:, Previous:Utility Functions, Up:Top

End Game Patterns

Endgame moves are generated just like any other move by GNU Go. In fact, the concept of endgame does not exist explicitly, but we can consider the endgame to be reached when the move values generally have decreased to about 20 and the endgame patterns come into play. This is typically fairly late, when most of the remaining plays are worth a few points in gote.

It should be noted that GNU Go currently makes no attempt whatsoever to play a theoretically perfect endgame. Instead the goal is just to play a decent, although maybe somewhat passive, endgame. What this means is primarily to play the small endgame moves in roughly the right order.

The endgame is implemented by a number of patterns in patterns.db, classified as EE, edge endgame, or CE, center endgame. In order to play the endgame moves in the right order, the patterns should be valued according to a pessimistic estimation of the size of the move. If the move is gote or reverse sente, it should have a value given by the table below.

Value   Size
1       Fill dame, i.e. 0 points gote.
2       Fill or take an unimportant ko, 1/2 point gote.
3       1 point gote.
4       1 1/2 point gote, typically two stage unimportant ko
        or 1 point gote with a followup of one more point
        gote.
5       2 points gote or 1 point reverse sente.
7       3 points gote.
10      4 points gote or 2 points reverse sente.
15      About 6 points gote or 3 points reverse sente.
20      At least 8 points gote or at least 4 points reverse
        sente.

Small sente moves should be valued at least 5, with the exact value depending on the size of the followup move. Most sente moves are not considered as endgame moves by GNU Go, neither are larger gote or reverse sente moves. A minimal double sente move should at least have value 10, but in most cases they should be played before the endgame.

Example

Pattern CE6

X?        push in
*O

:8,1,0,0,0,0,OX,0,NULL

A move generated from this pattern may be worth one or more points, e.g. in the position

XXXO
..*O
XXXO

where it is required that all stones are alive and it is assumed that the empty points would be territory for X with a stone at *. It could, however, also be applied in a position like

XXXO
.X*O
XXXO

where it only fills a dame. Hence the value of the pattern is no more than 1. To get a larger value for a move in the position above, we need to have a more specific pattern that is guaranteed to be worth at least one point gote, e.g.

Pattern CE6b

X?        push in
*O        1 points gote

:8,3,0,OX,0,0,0,0,0,NULL

X?
aO

;marginal_eye(a)

By taking help of the eye space evaluation we can know for certain that this move is worth at least one point.


Node:Regression, Next:, Previous:End Game, Up:Top

Regression testing

the --mode test option of gnugo allows for testing of moves.

generated moves are tested against annotations and actual moves

/* ANNOTATION PROPERTIES:
* Circle:   Good Move
* Triangle: OK move
* Square:   Bad move   (Mark too... cgoban writes MA instead of SQ)
* Move that was made:  considered good unless annotated (BM, TE)
*/

Example

The regression directory contains an example test-tree.sgf which shows how the testing works. Look at it with your favorite editor, then run it through the test to see how it performs.

A sample test run:

gnugo --mode test --testmode annotation --infile test-tree.sgf --quiet


Node:Concept Index, Next:, Previous:Regression, Up:Top

Concept Index


Node:Functions Index, Previous:Concept Index, Up:Top

Functions Index

Table of Contents