[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[computer-go] Territory Computation
Hello,
just for fun, I've implemented the territory computation as described in
Bouzy's article "Mathematical Morphology applied to computer Go" (see
http://www.math-info.univ-paris5.fr/~bouzy/publications.html for more
details). Because I've spent some time to understand the algorithm and clean
up Bouzy's code, I'm just offering this "standalone" implementation to
anybody who could find some interest in such a code.
Regards
Jean-Charles
#include <iostream>
#include <time.h>
#include <memory.h>
using namespace std;
#define BOARD_SIZE 19
#define GOBAN_SIZE BOARD_SIZE * BOARD_SIZE
static const int goban[ GOBAN_SIZE ] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,-1,-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,-1, 1, 0, 1, 0, 0, 0, 1, 0,-1, 0,-1, 0, 0,-1, 0, 0,
0, 0,-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0,
0,-1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,-1, 1, 1, 0,
0, 0, 0, 0, 1, 0,-1, 0, 0,-1, 0, 0, 0, 0,-1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static int NEIGHBORS[ GOBAN_SIZE ][ 4 ];
// ----------------------------------------------------------------------------
struct Potential
// ----------------------------------------------------------------------------
{
static int buffer_nature[ GOBAN_SIZE ];
static int nature [ GOBAN_SIZE ];
static int intensity [ GOBAN_SIZE ];
static void copy();
static void dilate_z( int count );
static void dilate_z_element(int);
static void erase_z( int count );
static void erase_z_element(int);
};
// ----------------------------------------------------------------------------
// static data
// ----------------------------------------------------------------------------
int Potential::buffer_nature [ GOBAN_SIZE ] = { 0 };
int Potential::nature [ GOBAN_SIZE ] = { 0 };
int Potential::intensity [ GOBAN_SIZE ] = { 0 };
// ----------------------------------------------------------------------------
void Potential::copy()
// ----------------------------------------------------------------------------
{
memcpy( buffer_nature, nature, sizeof( buffer_nature ));
}
// ----------------------------------------------------------------------------
void Potential::dilate_z( int count )
// ----------------------------------------------------------------------------
{
while ( count-- )
{
copy();
for (int position = 0; position < GOBAN_SIZE; position++ )
{
dilate_z_element( position );
}
}
}
// ----------------------------------------------------------------------------
void Potential::dilate_z_element( int point )
// ----------------------------------------------------------------------------
{
int ma_nature = buffer_nature[ point ];
int direction;
int voisin;
for ( direction = 3; direction >= 0; direction-- )
{
voisin = NEIGHBORS[ point][ direction ];
if ( voisin != -1 &&
buffer_nature[ voisin ] &&
buffer_nature[ voisin ] != ma_nature )
{
if ( ma_nature )
return;
else
ma_nature = buffer_nature[ voisin ];
}
}
if ( !ma_nature )
return;
nature[ point ] = ma_nature;
for (direction = 3; direction >= 0; direction--)
{
voisin = NEIGHBORS[ point ][ direction ];
if ( voisin != -1 &&
buffer_nature[ voisin ] == ma_nature )
{
intensity[ point ]++;
}
}
}
// ----------------------------------------------------------------------------
void Potential::erase_z( int count )
// ----------------------------------------------------------------------------
{
while ( count-- )
{
copy();
for (int idx=0; idx < GOBAN_SIZE; idx++) erase_z_element(idx);
}
}
// ----------------------------------------------------------------------------
void Potential::erase_z_element( int point )
// ----------------------------------------------------------------------------
{
int ma_nature = buffer_nature[ point ];
int voisin;
if ( ma_nature == 0 )
return;
for ( int direction = 3; direction >= 0; direction--)
{
voisin = NEIGHBORS[ point ][ direction ];
if ( voisin != -1 &&
buffer_nature[ voisin ] != ma_nature )
{
if ( !--intensity[ point ] )
{
nature[ point ] = 0;
break;
}
}
}
}
// ----------------------------------------------------------------------------
void dump( const int array[] )
// ----------------------------------------------------------------------------
{
for ( int i = 0; i < BOARD_SIZE; i++ )
{
for ( int j= 0; j < BOARD_SIZE; j++ )
{
cout.width( 3 );
cout << array[ i*BOARD_SIZE + j ];
}
cout << endl;
}
cout << endl;
}
// ----------------------------------------------------------------------------
void dump( const int nature [] ,
const int intensity[] ,
int mode = 0 )
// ----------------------------------------------------------------------------
{
int tmp;
for ( int i = 0; i < BOARD_SIZE; i++ )
{
for ( int j= 0; j < BOARD_SIZE; j++ )
{
tmp = nature [ i*BOARD_SIZE + j ] * intensity[ i*BOARD_SIZE + j ] ;
switch( mode ) {
case 1:
if ( tmp < 0 ) cout << "W ";
if ( tmp > 0 ) cout << "B ";
if ( tmp == 0 ) cout << ". ";
break;
default:
cout.width( 4 );
cout << tmp;
break;
}
}
cout << endl;
}
cout << endl;
}
// ----------------------------------------------------------------------------
void initializeTerritories()
// ----------------------------------------------------------------------------
{
for ( int i = 0; i < GOBAN_SIZE; i++ )
{
switch( goban[ i ] )
{
case 1:
Potential::nature [ i ] = 1;
Potential::intensity[ i ] = 64;
break;
case -1:
Potential::nature [ i ] = -1;
Potential::intensity[ i ] = 64;
break;
default:
Potential::nature [ i ] = 0;
Potential::intensity[ i ] = 0;
break;
}
}
}
// ----------------------------------------------------------------------------
static void initializeNeighbors()
// ----------------------------------------------------------------------------
{
enum { NORTH = 0 ,
EAST = 1 ,
SOUTH = 2 ,
WEST = 3 };
for ( int i = 0; i < GOBAN_SIZE; i++ )
{
for ( int j = 0; j < 4; j++ )
{
switch ( j )
{
case NORTH:
if ( i < BOARD_SIZE )
NEIGHBORS[ i ][ j ] = -1;
else
NEIGHBORS[ i ][ j ] = i - BOARD_SIZE;
break;
case EAST:
if ( ( i + 1 ) % BOARD_SIZE == 0 )
NEIGHBORS[ i ][ j ] = -1;
else
NEIGHBORS[ i ][ j ] = i + 1;
break;
case SOUTH:
if ( i >= GOBAN_SIZE - BOARD_SIZE )
NEIGHBORS[ i ][ j ] = -1;
else
NEIGHBORS[ i ][ j ] = i + BOARD_SIZE;
break;
case WEST:
if ( i % BOARD_SIZE == 0 )
NEIGHBORS[ i ][ j ] = -1;
else
NEIGHBORS[ i ][ j ] = i - 1;
break;
}
}
}
}
// ----------------------------------------------------------------------------
int main( int, char ** )
// ----------------------------------------------------------------------------
{
static int const d = 4;
static int const e = d*(d-1) + 1;
initializeTerritories();
initializeNeighbors ();
dump( goban );
Potential::dilate_z( d );
Potential::erase_z ( e );
dump( Potential::nature, Potential::intensity, 0 );
return 0;
}
_______________________________________________
computer-go mailing list
computer-go@xxxxxxxxxxxxxxxxx
http://www.computer-go.org/mailman/listinfo/computer-go/