I'm not sure I understand your question.   But I'll try to explain it a
little better.

Basically, you keep a C structure or the equivalent which tracks each
individual chain.   On your board array you put the index of that structure
(or a pointer to it.)

The structure will look something like this:

  typedef struct
  {
       int color;
       int stone_count;
       int head_stone;
       int liberty_count;

  }  chain_t;

And perhaps other crap you may want to keep.

So lets say you have an array of these, one for each chain on the board with
room to grow.

When you place a stone on the board,  you look at the 4 neighbors to see if
this is going to be a new chain of 1, or connect to an existing chain.    If
it's an existing chain, you will need to create a brand new entry,  set the
stone_count to 1, the liberty count to 1, 2, 3 or 4  (by looking at the 4
surrounding points)  and set the head_stone to the location of the new
stone.    the head_stone can be ANY stone in the group - it's just a way to
quickly reference one of the stones in the group.

Your board of course will have the index of the chain_t.    I start at 1 and
make zero mean empty but you could use -1 to represent empty squares if you
want to.   So if the value of the board array is 5,  it means it is the 5th
chain in the chain_t array and you can immediately see how many stones are
there,  how many liberties etc.

The logic for updating the liberty count is pretty basic.  When you place a
stone next to an existing group,  you know that group loses 1 liberty, so
you subtract 1 from ANY group of either color that touches it (there can
only be 4 at most.)     But then you must check to see if the stone you just
placed created liberties for the group it belongs to.    So you count the
empty points around the new stone that do not already belong to that same
group.     (There is also the case where 2 chains must be merged,  but we
will ignore that for now.)

When a group is captured,  you must do a bit more housekeeping.   You need
to delete it's entry somewhow in the chain array and you will have to
recalculate the liberties for any enemy chain that is currently touching any
of the captured stones.    This is not as hard as it seems once you work it
out.

One way to delete the entry is to just set the stone_count to zero for
instance.   You may want to "compress" the chain list from time to time but
if you make the list big enough,  you will be able to complete one or more
playouts without needing to do this.   You could also keep a "free list" so
that you immediately re-use entries - that's probably what I would recommend
because it's real simple and the free list will never grow very large.

How do you unmake moves?   I suggest that you don't.   Instead, making a
move should either be by state copy,  or if you know you will never need to
unmake a move (such as when doing fast playouts)  you don't have to worry
about it.    But of course you will still want to keep some original copy to
track the state of the actual game.

So your should wrap your whole game state up into a neat little package and
operate only on those.   You will be thankful if you ever decide to go with
parallel processing for instance.

So to make a move you might have something like this in C, this is
non-object oriented version:

   int make( const position *original_state,  position *new_state,
move_type  mv )
   {
       *new_state = *original_state;

       status = low_level_make( new_state,  mv );
       return status;
   }

The  "position" object is a C structure that has the entire board, chain
lists and move history.   The move history can be implemented as a pointer
to previous move states.

So in any kind of recursive search situation, you are simply passing
position states down the tree, never having to unmake a move.    In the
playouts you don't even have to copy state.

With this data structure you can also easily iterate through the chains
without having to loop over every point on the board.    In fact you can
always know exactly how many chains are on the board of either color and do
something wth them if needed.   Or you can quickly count the number of
stones on the board (of course if you wanted to you could keep this in a
separate counter in the position state.)

When you make captures you will need to hit every stone.  I use a recursive
flood fill type of routine to do this.   I know that some programs keep
linked lists of stones - I'm not sure if that is worth the trouble and extra
space.  Mabye it is.     I think I figured out that you rarely have to go
through every stone,  mainly in captures.


Ok, now my disclaimer.   There are some very experienced go programmer here
and they may find this naive or silly.    My reference bots do not use this,
they just do the dumb thing - a single flat array the represents the board
and the stones on it.


- Don















On Fri, Aug 14, 2009 at 6:10 PM, Carter Cheng <carter_ch...@yahoo.com>wrote:

> So to determine where the last two liberties for a group of stones for
> example is the obvious method of just doing it to have some method of
> liberty counting + a exhaustive search to determine the last two liberties
> for example?
>
> --- On Fri, 8/14/09, Don Dailey <dailey....@gmail.com> wrote:
>
> > From: Don Dailey <dailey....@gmail.com>
> > Subject: Re: [computer-go] representing liberties
> > To: "computer-go" <computer-go@computer-go.org>
> > Date: Friday, August 14, 2009, 2:33 PM
> >
> >
> > On Fri, Aug 14, 2009 at 5:13 PM,
> > Carter Cheng <carter_ch...@yahoo.com>
> > wrote:
> >
> > I have been having difficulties selecting a good
> > representation for liberty sets for strings of stones. I am
> > curious how other people might be doing this. I suspect that
> > for heavier playouts one would like to know not only the
> > count of the liberties but also where precisely they might
> > be relatively quickly(to determine if the group is in atari
> > among other things).
> >
> > Simple is best, until you know EXACTLY what you will want
> > to do and how often you will need to do it.
> >
> > Something pretty simple that I have used in the past is to
> > track each chain and incrementally maintain the liberty
> > count.
> >
> >
> > When you plop a stone down,  you have to look at only 4
> > points to see which group if any it belongs to, or if it
> > connects 2 or more groups.    And you can update the
> > liberty counts of all affected groups very quickly.
> >
> >
> > Where there is a capture, you must do considerably more
> > work - but captures represent only a small fraction of the
> > moves.   Small captures are more common than large
> > captures, but they require little work.
> >
> >
> > - Don
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > _______________________________________________
> >
> > computer-go mailing list
> >
> > computer-go@computer-go.org
> >
> > http://www.computer-go.org/mailman/listinfo/computer-go/
> >
> >
> >
> >
> > -----Inline Attachment Follows-----
> >
> > _______________________________________________
> > computer-go mailing list
> > computer-go@computer-go.org
> > http://www.computer-go.org/mailman/listinfo/computer-go/
>
>
>
> _______________________________________________
> computer-go mailing list
> computer-go@computer-go.org
> http://www.computer-go.org/mailman/listinfo/computer-go/
>
_______________________________________________
computer-go mailing list
computer-go@computer-go.org
http://www.computer-go.org/mailman/listinfo/computer-go/

Reply via email to