gnugo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnugo-devel] twogtp_1_32.1


From: Daniel Bump
Subject: [gnugo-devel] twogtp_1_32.1
Date: Tue, 9 Apr 2002 22:18:27 -0700

The attached patch helps make twogtp properly deterministic. The
changes to twogtp itself add the random seeds to the sgf
file. They also make sure a new random seed is generated for
every game. The new seed is generated by calling the random
number generator, then the random number generator is restarted.
(The alternative would be to consult the time to get a new seed.)

As a consequence if we get a crash, we can copy the
random seeds from the sgf file into the command line:

twogtp --black "gnugo --mode gtp --quiet -r 1119124199" --white "gnugo --mode 
gtp --quiet -r 1577886685" --games 2 --boardsize 9 --sgffile tmpa.sgf

The first game will then be the game of the crash.

I want to explain the new call to gg_srand in play_gtp().
Omitting this change, one has the following bad behavior:

$ gnugo --quiet --mode gtp -r 10
random_number
= 415550974

random_number
= 1189290343

set_random_seed 10
= 

random_number
= 381070644

This is not what we want. The random number should be the
same as the first sequence. If this isn't true, it's hard
to reconstruct the game.

The reason for this failure is that initializing the hashing
makes calls to the random number generator, putting us at a
different point in the sequence of pseudorandom numbers.  The
cure is to restart the random number generator after this is
done.

Clearly this is not what we want---if we reset the random
seed, we should get the same sequence of random numbers. The
change to play_gtp() fixes this.

$ gnugo --quiet --mode gtp -r 10
random_number
= 381070644

random_number
= 818516479

set_random_seed 10
= 

random_number
= 381070644

random_number
= 818516479

There's still a couple of problems with this patch.

(1) We still get different moves from play_gmp.
(2) After this patch, twogtp no longer works with GNU Go 3.0.

I'll leave this out of the CVS until these two problems are
fixed, in the meantime I'm putting this patch up for discussion.

- new gtp functions new_random_seed, random_number
- play_gtp() restarts the random number generator after hashing initiated
- twogtp closes sgf file on illegal moves and other errors
- twogtp reseeds and restarts the the random number generator for each move
- twogtp puts the random seeds in the sgf file
- twogtp does not repeat duplicate scores if both engines agree


Index: interface/play_gtp.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/play_gtp.c,v
retrieving revision 1.70
diff -u -r1.70 play_gtp.c
--- interface/play_gtp.c        7 Apr 2002 17:00:31 -0000       1.70
+++ interface/play_gtp.c        10 Apr 2002 05:00:19 -0000
@@ -76,6 +76,8 @@
 DECLARE(gtp_get_handicap);
 DECLARE(gtp_get_random_seed);
 DECLARE(gtp_set_random_seed);
+DECLARE(gtp_new_random_seed);
+DECLARE(gtp_random_number);
 DECLARE(gtp_genmove);
 DECLARE(gtp_genmove_black);
 DECLARE(gtp_genmove_white);
@@ -173,6 +175,8 @@
   {"get_handicap",           gtp_get_handicap},
   {"get_random_seed",                gtp_get_random_seed},
   {"set_random_seed",                gtp_set_random_seed},
+  {"new_random_seed",                gtp_new_random_seed},
+  {"random_number",          gtp_random_number},
   {"genmove_black",           gtp_genmove_black},
   {"genmove_white",           gtp_genmove_white},
   {"get_connection_node_counter", gtp_get_connection_node_counter},
@@ -255,6 +259,8 @@
   
   /* Prepare pattern matcher and reading code. */
   reset_engine();
+  /* restart the random number generator at the beginning */
+  gg_srand(random_seed);
   gtp_main_loop(commands, gtp_input);
 }
 
@@ -2948,14 +2954,45 @@
 gtp_set_random_seed(char *s, int id)
 {
   int seed;
+
   if (sscanf(s, "%d", &seed) < 1)
     return gtp_failure(id, "invalid seed");
   
   random_seed = seed;
+  gg_srand(random_seed);
   return gtp_success(id, "");
 }
 
+/* Function:  Generate and set a new random seed
+ * Arguments: none
+ * Fails:     never
+ * Returns:   new random seed
+ */
 
+static int
+gtp_new_random_seed(char *s, int id)
+{
+  UNUSED(s);
+
+  random_seed = gg_rand();
+  gg_srand(random_seed);
+
+  return gtp_success(id, "%d", random_seed);
+}
+  
+/* Function:  Generates a random number
+ * Arguments: none
+ * Fails:     never
+ * Returns:   random number
+ */
+
+static int
+gtp_random_number(char *s, int id)
+{
+  UNUSED(s);
+
+  return gtp_success(id, "%d", gg_rand());
+}
 
 
 /*
Index: interface/gtp_examples/twogtp
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/gtp_examples/twogtp,v
retrieving revision 1.4
diff -u -r1.4 twogtp
--- interface/gtp_examples/twogtp       8 Mar 2002 03:11:00 -0000       1.4
+++ interface/gtp_examples/twogtp       10 Apr 2002 05:00:24 -0000
@@ -49,9 +49,11 @@
     my ($repchar, $result) = split(' ', $line, 2);
     if ($repchar eq '=') {
     } elsif ($repchar eq '?') {
-       die "GTP error on executing $cmd:\n $line";
+       print "GTP error on executing $cmd:\n $line";
+       return "ERROR";
     } else {
-       die "Unexpected response on executing $cmd:\n $line";
+       print "Unexpected response on executing $cmd:\n $line";
+       return "ERROR";
     }
     $line = <$hout>;
     print STDERR $line if ($debug);
@@ -63,7 +65,6 @@
     my $size = shift;
     my $board_coords = shift;
     $board_coords =~ tr/A-Z/a-z/;
-#   return "tt" if ($board_coords eq "pass");
     return "" if ($board_coords eq "pass");
     my $first  = substr($board_coords, 0, 1);
     my $number = substr($board_coords, 1);
@@ -147,6 +148,13 @@
     GTP::exec_cmd(${$self->in}, ${$self->out}, "boardsize $size");
 }
 
+sub new_random_seed {
+    my $self = shift;
+    my $size = shift;
+
+    GTP::exec_cmd(${$self->in}, ${$self->out}, "new_random_seed");
+}
+
 sub handicap {
     my $self = shift;
     my $handicap = shift;
@@ -177,6 +185,14 @@
     GTP::exec_cmd(${$self->in}, ${$self->out}, "showboard");
 }
 
+sub get_random_seed {
+    my $self = shift;
+
+    my $ret = GTP::exec_cmd(${$self->in}, ${$self->out}, "get_random_seed");
+    my ($result, $rest) = split(' ', $ret, 2);
+    return $result;
+}
+
 sub score {
     my $self = shift;
 
@@ -217,8 +233,7 @@
     'handicap'         => '$',
     'handicap_stones'  => '@',
     'moves'            => '@',
-    'result'           => 'GTP::Game::Result',
-    'seed'             => '$'
+    'result'           => 'GTP::Game::Result'
 }
 );
 
@@ -240,8 +255,12 @@
     my $handle = new FileHandle;
     $handle->open(">$sgffile") or
        die "Can't write to $sgffile\n";
-    printf $handle "(;GM[1]FF[4]RU[Japanese]SZ[%s]HA[%s]KM[%s]RE[%s]",
-       $size, $self->handicap, $self->komi, $self->result->resultw;
+    my $black_seed = $self->black->get_random_seed;
+    my $white_seed = $self->white->get_random_seed;
+
+    printf $handle "(;GM[1]FF[4]RU[Japanese]SZ[%s]HA[%s]KM[%s]RE[%s]GN[black 
seed:%s white seed:%s]",
+    $size, $self->handicap, $self->komi, $self->result->resultw, 
$self->black->get_random_seed,
+    $self->white->get_random_seed;
     for my $stone (@{$self->handicap_stones}) {
        printf $handle "AB[%s]", GTP::standard_to_sgf($self->size, $stone);
     }
@@ -258,6 +277,8 @@
 }
 
 
+
+
 sub play {
 
     my $self = shift;
@@ -308,9 +329,14 @@
            print "Black plays $move\n" if $verbose;
            $pass = ($move =~ /PASS/i) ? $pass + 1 : 0;
            $self->white->black($move) unless ($move =~ /PASS/);
-           if ($verbose > 1) {
+           if ($verbose == 3) {
+               my $black_seed = $self->black->get_random_seed;
+               printf "Black seed $black_seed\n";
+           }
+           if ($verbose == 2) {
                $self->white->showboard;
            }
+
            $toplay = 'W';
 
         } else {
@@ -324,7 +350,11 @@
            print "White plays $move\n" if $verbose;
            $pass = ($move =~ /PASS/i) ? $pass + 1 : 0;
            $self->black->white($move) unless ($move =~ /PASS/);
-           if ($verbose > 1) {
+           if ($verbose == 3) {
+               my $white_seed = $self->white->get_random_seed;
+               printf "White seed $white_seed\n";
+           }
+           if ($verbose == 2) {
                $self->black->showboard;
            }
            $toplay = 'B';
@@ -334,11 +364,18 @@
 
     my $resultw = $self->white->estimate_score;
     my $resultb = $self->black->estimate_score;
-    print "Result according to W: $resultw\n";
-    print "Result according to B: $resultb\n";
+    if ($resultb eq $resultw) {
+       print "Result: $resultw\n";
+    }
+    else {
+       print "Result according to W: $resultw\n";
+       print "****** according to B: $resultb\n";
+    }
     $self->result->resultw($resultw);
     $self->result->resultb($resultb);
     $self->writesgf($sgffile) if defined $sgffile;
+    $self->black->new_random_seed;
+    $self->white->new_random_seed;
 }
 
 package GTP::Match;
@@ -352,8 +389,7 @@
     'white'    => 'GTP::Player',
     'size'     => '$',
     'komi'     => '$',
-    'handicap' => '$',
-    'seed'     => '$'
+    'handicap' => '$'
 }
 );
 
@@ -453,7 +489,12 @@
 my $i=0;
 for my $r (@results) {
     $i++;
-    printf "Game $i: %s %s\n", $r->resultb, $r->resultw;
+    if ($r->resultb eq $r->resultw) {
+       printf "Game $i: %s\n", $r->resultw;    
+    }
+    else {
+       printf "Game $i: %s %s\n", $r->resultb, $r->resultw;
+    }
 }
 
 $white_pl->quit;







reply via email to

[Prev in Thread] Current Thread [Next in Thread]