gnugo-devel
[Top][All Lists]
Advanced

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

Re: [gnugo-devel] fast_defense() improvement


From: Arend Bayer
Subject: Re: [gnugo-devel] fast_defense() improvement
Date: Wed, 2 Jun 2004 00:49:17 +0200 (CEST)


> So this is what the attached patch does. I have also rewritten the

And here it actually is.

Arend


Index: engine/board.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/board.c,v
retrieving revision 1.98
diff -u -p -r1.98 board.c
--- engine/board.c      27 May 2004 00:08:46 -0000      1.98
+++ engine/board.c      1 Jun 2004 22:14:20 -0000
@@ -2383,6 +2383,41 @@ findstones(int str, int maxstones, int *
 }
 
 
+/* Counts how many stones in str1 are directly adjacent to str2.
+ * A limit can be given in the maxstones parameter so that the
+ * function returns immediately. See fast_defense() in reading.c
+ */
+
+int
+count_adjacent_stones(int str1, int str2, int maxstones)
+{
+  int s1, s2;
+  int size;
+  int pos;
+  int k;
+  int count = 0;
+
+  ASSERT_ON_BOARD1(str1);
+  ASSERT1(IS_STONE(board[str1]), str1);
+  ASSERT_ON_BOARD1(str2);
+  ASSERT1(IS_STONE(board[str2]), str2);
+
+  s1 = string_number[str1];
+  s2 = string_number[str2];
+  size = string[s1].size;
+
+  /* Traverse the stones of the string, by following the cyclic chain. */
+  pos = FIRST_STONE(s1);
+  for (k = 0; k < size && count < maxstones; k++) {
+    if (NEIGHBOR_OF_STRING(pos, s2, board[str2]))
+      count++;
+    pos = NEXT_STONE(pos);
+  }
+
+  return count;
+}
+
+
 /* chainlinks returns (in the (adj) array) the chains surrounding
  * the string at (str). The number of chains is returned.
  */
Index: engine/board.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/board.h,v
retrieving revision 1.12
diff -u -p -r1.12 board.h
--- engine/board.h      27 May 2004 00:08:46 -0000      1.12
+++ engine/board.h      1 Jun 2004 22:14:21 -0000
@@ -302,6 +302,7 @@ int have_common_lib(int str1, int str2, 
 /* Count the number of stones in a string. */
 int countstones(int str);
 int findstones(int str, int maxstones, int *stones);
+int count_adjacent_stones(int str1, int str2, int maxstones);
 
 /* Special function for reading.c */
 void incremental_order_moves(int move, int color, int string,
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.214
diff -u -p -r1.214 owl.c
--- engine/owl.c        31 May 2004 13:53:25 -0000      1.214
+++ engine/owl.c        1 Jun 2004 22:14:28 -0000
@@ -576,6 +576,9 @@ do_owl_analyze_semeai(int apos, int bpos
   ASSERT1(board[apos] == owla->color, apos);
   ASSERT1(board[bpos] == owlb->color, bpos);
 
+  apos = find_origin(apos);
+  bpos = find_origin(bpos);
+
   if (stackp <= semeai_branch_depth && (hashflags & HASH_SEMEAI)
       && !pass && owl_phase
       && tt_get(&ttable, SEMEAI, apos, bpos, depth - stackp, NULL,
Index: engine/reading.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/reading.c,v
retrieving revision 1.143
diff -u -p -r1.143 reading.c
--- engine/reading.c    25 May 2004 03:13:45 -0000      1.143
+++ engine/reading.c    1 Jun 2004 22:14:34 -0000
@@ -1240,8 +1240,11 @@ static int
 fast_defense(int str, int liberties, int *libs, int *move)
 {
   int color = board[str];
-  int k;
+  int j, k, l;
   int goal_liberties = (stackp < fourlib_depth ? 5 : 4);
+  int adj, adjs[MAXCHAIN];
+  static unsigned liberty_mark = -1;
+  static unsigned lm[BOARDMAX];
 
   ASSERT1(libs != NULL, str);
   ASSERT1(move != NULL, str);
@@ -1255,6 +1258,82 @@ fast_defense(int str, int liberties, int
       return 1;
     }
   }
+
+  /* Check the cases where an opponent neighbor string is in
+   * atari.
+   */
+  adj = chainlinks2(str, adjs, 1);
+  for (j = 0; j < adj; j++) {
+    int lib;
+    int missing = goal_liberties - liberties;
+    int total = 0;
+    int adj2, adjs2[MAXCHAIN];
+    int alib, alibs[MAXLIBS];
+    int num_adjacent_stones;
+
+    findlib(adjs[j], 1, &lib);
+    /* We aren't interested in ko (at this stage). And playing
+     * our own last liberty to capture is prone to snapbacks,
+     * so better let the 'normal' reading routines do the job.
+     */
+    if ((liberties == 1 && lib == libs[0]
+        && countstones(adjs[j]) <= 2)
+       || is_ko(lib, color, NULL))
+      continue;
+
+    /* Would the capture already gain enough liberties ?
+     * No need to test the case if the move is one of our liberties,
+     * it has already been done in the first loop of this function.
+     */
+    num_adjacent_stones = count_adjacent_stones(adjs[j], str, missing);
+    ASSERT1(num_adjacent_stones >= 1, str);
+    if (!liberty_of_string(lib, str)
+       && num_adjacent_stones >= missing) {
+      *move = lib;
+      return 1;
+    }
+
+    /* What is the total number of liberties of the friendly strings around
+     * the lunch?
+     */
+    if (++liberty_mark == 0)
+      memset(lm, 0, sizeof(lm));
+    /* Loop over all neighbors of the lunch. */
+    adj2 = chainlinks(adjs[j], adjs2);
+    for (k = 0; k < adj2; k++) {
+      /* Loop over all liberties of the neighbor. */
+      alib = findlib(adjs2[k], MAXLIBS, alibs);
+      for (l = 0; l < alib; l++) {
+       if (lm[alibs[l]] != liberty_mark) {
+         lm[alibs[l]] = liberty_mark;
+         total++;
+       }
+      }
+    }
+
+    /* The captured string is treated as common liberties, and
+     * some adjustements are made :
+     * - we're adding a stone for capturing the lunch (-1)
+     * - opponent might be able to remove a liberty (-1)
+     * - and possibly force us to connect (-1)
+     * - reduce us by one more liberty with a throw-in; this
+     *   is only possible if there is only one adjacent stone in the
+     *   lunch to the string (-1)
+     * Probably there are more damezumari-type cases, but as a heuristic,
+     * it seems good enough.
+     */
+    total += countstones(adjs[j]) - 2;
+    if (lm[lib] == liberty_mark)
+      total--;
+    if (num_adjacent_stones == 1)
+      total--;
+
+    if (total >= goal_liberties) {
+      *move = lib;
+      return 1;
+    }
+  }
+
   return 0;
 }
 




reply via email to

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