gnugo-devel
[Top][All Lists]
Advanced

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

Re: [gnugo-devel] Re: Ranked Robot (fwd)


From: Gunnar Farnebäck
Subject: Re: [gnugo-devel] Re: Ranked Robot (fwd)
Date: Thu, 26 Aug 2004 04:10:54 +0200
User-agent: EMH/1.14.1 SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.3 Emacs/21.3 (sparc-sun-solaris2.9) MULE/5.0 (SAKAKI)

I wrote (on August 3):
> 2. GNU Go plays black, white mirrors
> 
> Play tengen within some 10 to 20 moves.
> 
> 4. GNU Go plays white, black starts at tengen and mirrors, komi < 0.
> 
> Start a sequence to capture tengen within 10 to 20 moves.

Implemented by the appended patch. As I intend this to go into 3.6 it
would be good if someone can take a look to see that everything looks
good.

- basic strategies to break mirror go implemented

While doing this I stepped onto a bug in mkpat. If the last pattern in
patterns.db has a constraint or an action, the autohelper code will be
written twice, giving a compilation error in patterns.c. See the
comment near the end of the patch. Paul, do you have any idea where
the bug might be?

/Gunnar

Index: engine/board.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/board.h,v
retrieving revision 1.13
diff -u -r1.13 board.h
--- engine/board.h      7 Jun 2004 17:18:54 -0000       1.13
+++ engine/board.h      25 Aug 2004 22:26:31 -0000
@@ -157,6 +157,8 @@
 #define BOARD(i, j)   board[POS(i, j)]
 
 
+#define MIRROR_MOVE(pos) POS(board_size - 1 - I(pos), board_size - 1 - J(pos))
+
 /* ================================================================ */
 /*                         global variables                         */
 /* ================================================================ */
Index: engine/genmove.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/genmove.c,v
retrieving revision 1.93
diff -u -r1.93 genmove.c
--- engine/genmove.c    19 Jul 2004 12:23:08 -0000      1.93
+++ engine/genmove.c    25 Aug 2004 22:26:31 -0000
@@ -52,8 +52,8 @@
 static int revise_thrashing_dragon(int color, float our_score,
                                                  float advantage);
 
+static void break_mirror_go(int color);
 static int find_mirror_move(int *move, int color);
-static int test_symmetry_after_move(int move, int color);
 static int should_resign(int color, float our_score);
 
 void sgfShowConsideredMoves(void);
@@ -428,6 +428,9 @@
     fuseki(color);
   gg_assert(stackp == 0);
 
+  /* Look for moves too break mirror play by the opponent. */
+  break_mirror_go(color);
+  
   /* The general pattern database. */
   shapes(color);
   time_report(1, "shapes", NO_MOVE, 1.0);
@@ -709,7 +709,6 @@
  * To be able to deal with handicap stones we use a somewhat weak
  * definition of symmetry.
  */
-#define MIRROR_MOVE(pos) POS(board_size - 1 - I(pos), board_size - 1 - J(pos))
 
 static int
 find_mirror_move(int *move, int color)
@@ -718,7 +717,7 @@
   int mirror_move;
   if (last_move != NO_MOVE) {
     mirror_move = MIRROR_MOVE(last_move);
-    if (test_symmetry_after_move(mirror_move, color)) {
+    if (test_symmetry_after_move(mirror_move, color, 0)) {
       *move = mirror_move;
       return 1;
     }
@@ -726,7 +725,7 @@
   else {
     for (mirror_move = BOARDMIN; mirror_move < BOARDMAX; mirror_move++) {
       if (ON_BOARD(mirror_move)
-        && test_symmetry_after_move(mirror_move, color)) {
+          && test_symmetry_after_move(mirror_move, color, 0)) {
           *move = mirror_move;
           return 1;
       }
@@ -736,29 +735,26 @@
   return 0;
 }
 
-static int
-test_symmetry_after_move(int move, int color)
-{
-  int pos;
-  int result = 1;
 
-  if (board[move] != EMPTY)
-    return 0;
-  if (!trymove(move, color, "find_mirror_move", NO_MOVE))
-    return 0;
-  
-  for (pos = BOARDMIN; pos <= MIRROR_MOVE(pos); pos++) {
-    if ((board[pos] == EMPTY) ^ (board[MIRROR_MOVE(pos)] == EMPTY)) {
-      result = 0;
-      break;
-    }
+/* Detect if a white opponent has played mirror go for at least 10
+ * moves and if so play on tengen.
+ *
+ * Mirror breaking moves in other situations are handled by patterns
+ * in patterns.db.
+ */
+static void break_mirror_go(int color)
+{
+  int tengen = POS((board_size - 1) / 2, (board_size - 1) / 2);
+  if (board[tengen] == EMPTY
+      && color == BLACK
+      && stones_on_board(BLACK | WHITE) > 10
+      && test_symmetry_after_move(tengen, color, 1)) {
+    set_minimum_move_value(tengen, 30.0);
+    TRACE("Play %1m to break mirror go, value 30.\n", tengen);
   }
-  
-  popgo();
-
-  return result;
 }
 
+
 /* Helper to decide whether GG should resign a game
  */
 static int
Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.224
diff -u -r1.224 liberty.h
--- engine/liberty.h    24 Aug 2004 15:24:30 -0000      1.224
+++ engine/liberty.h    25 Aug 2004 22:26:31 -0000
@@ -548,6 +548,7 @@
 int defend_against(int move, int color, int apos);
 int somewhere(int color, int check_alive, int num_moves, ...);
 int visible_along_edge(int color, int apos, int bpos);
+int test_symmetry_after_move(int move, int color, int strict);
 
 /* Printmoyo values, specified by -m flag. */
 #define PRINTMOYO_TERRITORY         0x01
Index: engine/utils.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/utils.c,v
retrieving revision 1.96
diff -u -r1.96 utils.c
--- engine/utils.c      4 Jun 2004 01:28:13 -0000       1.96
+++ engine/utils.c      25 Aug 2004 22:26:31 -0000
@@ -267,6 +267,48 @@
   return 0;
 }
 
+/* Is the board symmetric (or rather antisymmetric) with respect to
+ * mirroring in tengen after a specific move has been played? If the
+ * move is PASS_MOVE, check the current board.
+ *
+ * If strict is set we require that each stone is matched by a stone
+ * of the opposite color at the mirrored vertex. Otherwise we only
+ * require that each stone is matched by a stone of either color.
+ */
+int
+test_symmetry_after_move(int move, int color, int strict)
+{
+  int pos;
+  int result = 1;
+
+  if (move != PASS_MOVE) {
+    if (board[move] != EMPTY)
+      return 0;
+    if (!trymove(move, color, "find_mirror_move", NO_MOVE))
+      return 0;
+  }
+  
+  for (pos = BOARDMIN; pos < MIRROR_MOVE(pos); pos++) {
+    int sum;
+    if (!ON_BOARD(pos))
+      continue;
+    
+    sum = board[pos] + board[MIRROR_MOVE(pos)];
+    if (sum != EMPTY + EMPTY && sum != BLACK + WHITE) {
+      if (strict || sum == EMPTY + WHITE || sum == EMPTY + BLACK) {
+      result = 0;
+      break;
+      }
+    }
+  }
+
+  if (move != PASS_MOVE)
+    popgo();
+  
+  return result;
+}
+
+
 /* The function play_break_through_n() plays a sequence of moves,
  * alternating between the players and starting with color. After
  * having played through the sequence, the three last coordinate pairs
Index: patterns/helpers.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/helpers.c,v
retrieving revision 1.62
diff -u -r1.62 helpers.c
--- patterns/helpers.c  31 May 2004 13:57:54 -0000      1.62
+++ patterns/helpers.c  25 Aug 2004 22:26:31 -0000
@@ -775,6 +775,35 @@
 }
 
 
+/* Returns true if
+ *
+ * 1. The board size is odd.
+ * 2. A white move is being generated.
+ * 3. The komi is less than or equal to zero.
+ * 4. str is placed at tengen.
+ * 5. At least 10 moves have been played.
+ * 6. The board is currently mirror symmetric.
+ *
+ * This is intended for patterns to break mirror go when black starts at
+ * tengen and then mirrors white. We only care about breaking the mirroring
+ * if komi is non-positive, otherwise the mirroring is to our advantage.
+ */
+int
+break_mirror_helper(int str, int color)
+{
+  if (board_size % 2 == 1
+      && color == WHITE
+      && komi <= 0.0
+      && I(str) == (board_size - 1) / 2
+      && J(str) == (board_size - 1) / 2
+      && stones_on_board(BLACK | WHITE) > 10
+      && test_symmetry_after_move(PASS_MOVE, EMPTY, 1))
+    return 1;
+
+  return 0;
+}
+
+
 /*
  * LOCAL Variables:
  * tab-width: 8
Index: patterns/mkpat.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/mkpat.c,v
retrieving revision 1.137
diff -u -r1.137 mkpat.c
--- patterns/mkpat.c    18 Aug 2004 14:10:37 -0000      1.137
+++ patterns/mkpat.c    25 Aug 2004 22:26:31 -0000
@@ -110,7 +110,7 @@
 #define MAXACTION              10000
 #define MAXPATNO               5000
 #define MAXLABELS              20
-#define MAXPARAMS              15
+#define MAXPARAMS              20
 #define MAX_INPUT_FILE_NAMES   10
 #define MAXNAME                80
 
@@ -436,7 +436,8 @@
                 "adjacent_to_stone_in_atari(%s)"},
   {"adjacent_to_defendable_stone_in_atari", 1, 0, 1.0,
                 "adjacent_to_defendable_stone_in_atari(%s)"},
-  {"good_attack_threat",       2, 0, 0.01, "register_good_attack_threat(%s, 
%s)"}
+  {"good_attack_threat",       2, 0, 0.01, "register_good_attack_threat(%s, 
%s)"},
+  {"break_mirror_helper",      1, 0, 0.01, "break_mirror_helper(%s, color)"}
 };
 
 
Index: patterns/patterns.db
===================================================================
RCS file: /cvsroot/gnugo/gnugo/patterns/patterns.db,v
retrieving revision 1.129
diff -u -r1.129 patterns.db
--- patterns/patterns.db        22 Aug 2004 13:07:31 -0000      1.129
+++ patterns/patterns.db        25 Aug 2004 22:26:31 -0000
@@ -15093,4 +15093,193 @@
 :8,s,value(3),thrash_around_helper
 
 
+######################################################################
+#
+# Mirror breaking patterns.
+#
+# Patterns to break mirror go strategies being employed by the opponent.
+#
+######################################################################
+
+Pattern M1
+# gf New pattern. (3.5.11)
+
+.....
+.....
+..X..
+..*..
+.....
+
+:|,-,value(30)
+
+.mil.
+.dbgq
+.fAe.
+ph*c.
+.kjn.
+
+;oplay_attack(*,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M2
+# gf New pattern. (3.5.11)
+
+.....
+..X..
+..X..
+..O*.
+.....
+
+:8,-,value(40)
+
+.mil.
+.dXgq
+.fAe.
+phO*.
+.kjn.
+
+;oplay_attack(*,d,e,f,g,h,i,j,k,l,m,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M3
+# gf New pattern. (3.5.11)
+
+.....
+.XX..
+..X*.
+..OO.
+.....
+
+:8,-,value(40)
+
+.mil.
+.XXgq
+.fA*.
+phOO.
+.kjn.
+
+;oplay_attack(*,f,g,h,i,j,k,l,m,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M4
+# gf New pattern. (3.5.11)
+
+.....
+.XX*.
+.XXO.
+..OO.
+.....
+
+:8,-,value(40)
+
+.mil.
+.XX*q
+.XAO.
+phOO.
+.kjn.
+
+;oplay_attack(*,h,i,j,k,l,m,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M5
+# gf New pattern. (3.5.11)
+
+..*..
+.XXO.
+.XXO.
+.XOO.
+.....
+
+:8,-,value(40)
+
+.m*l.
+.XXOq
+.XAO.
+pXOO.
+.kjn.
+
+;oplay_attack(*,j,k,l,m,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M6
+# gf New pattern. (3.5.11)
+
+..O..
+.XXO.
+.XXO.
+.XOO.
+.*X..
+
+:8,-,value(40)
+
+.mOl.
+.XXOq
+.XAO.
+pXOO.
+.*Xn.
+
+;oplay_attack(*,l,m,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M7
+# gf New pattern. (3.5.11)
+
+.*OX.
+.XXO.
+.XXO.
+.XOO.
+.OX..
+
+:8,-,value(70)
+
+.*OX.
+.XXOq
+.XAO.
+pXOO.
+.OXn.
+
+;oplay_attack(*,n,p,q,A) && break_mirror_helper(A)
+
+
+Pattern M8
+# gf New pattern. (3.5.11)
+
+.OOX.
+.XXO.
+.XXO.
+*XOO.
+.OXX.
+
+:8,-,value(60)
+
+.OOX.
+.XXOq
+.XAO.
+*XOO.
+.OXX.
+
+;oplay_attack(*,q,A) && break_mirror_helper(A)
+
+
+Pattern M9
+# gf New pattern. (3.5.11)
+#    FIXME:
+#    This is a complete dummy pattern with no effect at all (notice
+#    the lack of classifications, values, helpers, and actions).
+#    It is only included because a pattern with constraint or action
+#    at the end of patterns.db triggers a bug in mkpat, causing the
+#    same autohelper to be written twice, yielding a compilation
+#    error for patterns.c. This seems to have something to do with
+#    the fact that patterns.db and patterns2.db are concatenated by
+#    mkpat.
+
+.OOX.
+.XXO.
+.XXO.
+.XOO.
+*OXX.
+
+:8,-
+
+
 # END OF FILE




reply via email to

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