Index: engine/board.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/board.c,v retrieving revision 1.64 diff -u -r1.64 board.c --- engine/board.c 4 Jan 2003 14:57:29 -0000 1.64 +++ engine/board.c 8 Jan 2003 08:55:05 -0000 @@ -4577,6 +4577,15 @@ } +int +square_dist(int pos1, int pos2) +{ + int idist = I(pos1) - I(pos2); + int jdist = J(pos1) - J(pos2); + return idist*idist + jdist*jdist; +} + + /* * Local Variables: * tab-width: 8 Index: engine/dragon.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/dragon.c,v retrieving revision 1.98 diff -u -r1.98 dragon.c --- engine/dragon.c 5 Jan 2003 15:49:15 -0000 1.98 +++ engine/dragon.c 8 Jan 2003 08:55:08 -0000 @@ -309,6 +309,23 @@ } find_neighbor_dragons(); + + for (d = 0; d < number_of_dragons; d++) { + dragon2[d].surround_status + = compute_surroundings(dragon2[d].origin, NO_MOVE, 0, + &(dragon2[d].surround_size)); + if (dragon2[d].surround_status == SURROUNDED) { + dragon2[d].escape_route = 0; + if (debug & DEBUG_DRAGONS) + gprintf ("surrounded dragon found at %1m\n", dragon2[d].origin); + } + else if (dragon2[d].surround_status == WEAKLY_SURROUNDED) { + dragon2[d].escape_route >>= 1; + if (debug & DEBUG_DRAGONS) + gprintf ("weakly surrounded dragon found at %1m\n", dragon2[d].origin); + } + } + time_report(2, " pre-owl dragon data", NO_MOVE, 1.0); if (stop_before_owl) @@ -531,18 +548,6 @@ time_report(2, " owl threats ", NO_MOVE, 1.0); - for (d = 0; d < number_of_dragons; d++) { - dragon2[d].surround_status - = compute_surroundings(dragon2[d].origin, NO_MOVE, 0, - &(dragon2[d].surround_size)); - if (debug & DEBUG_DRAGONS) { - if (dragon2[d].surround_status == 1) - gprintf ("surrounded dragon found at %1m\n", dragon2[d].origin); - if (dragon2[d].surround_status == 2) - gprintf ("weakly surrounded dragon found at %1m\n", dragon2[d].origin); - } - } - /* Compute the safety value. */ for (d = 0; d < number_of_dragons; d++) { Index: engine/liberty.h =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v retrieving revision 1.150 diff -u -r1.150 liberty.h --- engine/liberty.h 3 Jan 2003 18:23:42 -0000 1.150 +++ engine/liberty.h 8 Jan 2003 08:55:13 -0000 @@ -220,6 +220,8 @@ int rotate1(int pos, int rot); int inv_rotate1(int pos, int rot); +int square_dist(int pos1, int pos2); + /* Is this point inside the board? */ #if 0 #define ON_BOARD2(i, j) ((i)>=0 && (j)>=0 && (i) 8) { + /* discard markings if we can find 2 stones + * that verify : + * - it is closer to the goal than we are + * - it is closer to us than the goal is + * - they are closer to each other than we are to the goal + */ + for (i = BOARDMIN; i < BOARDMAX; i++) + if (ON_BOARD(i) && mn[i] && i != dpos + && sd[i] < sd[dpos] + && square_dist(i, dpos) < sd[dpos]) { + for (j = i + 1; j < BOARDMAX; j++) + if (ON_BOARD(j) && mn[j] && j != dpos + && sd[j] < sd[dpos] + && square_dist(j, dpos) < sd[dpos] + && square_dist(i, j) < sd[dpos]) { + mn[dpos] = 0; + found_some = 1; + break; + } + if (mn[dpos] == 0) + break; + } + } + } while(found_some); + + /* prepare corner array */ + + for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) + if (ON_BOARD(dpos) && mn[dpos]) + corner[corners++] = dpos; + + /* compute gravity center of the goal */ + + for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) + if (ON_BOARD(dpos) && mf[dpos]) { + gi += I(dpos); + gj += J(dpos); + stones++; + } + gi /= stones; + gj /= stones; + gg = POS(gi, gj); + + /* sort the corner array */ + + gg_sort(corner, corners, sizeof(int), compare_angles); + /* if apos is non NULL, mark it. */ if (apos) { gg_assert(ON_BOARD(apos)); - mn[apos] =1; + mn[apos] = 1; } + if (showboard == 1) { + show_surround_map(mf, mn); + } + /* find top row of surrounding polyhedron */ top_row = -1; @@ -138,6 +241,7 @@ break; } } + /* find bottom row */ bottom_row = -1; @@ -182,7 +286,7 @@ break; } - /* find the corners on the left side */ + /* find the corners on the right side */ for (right_corners = 1; I(right_corner[right_corners-1]) < bottom_row; right_corners++) { @@ -278,34 +382,98 @@ * are not neighbors are less likely to be helpful. */ - for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) + for (dpos = BOARDMIN; dpos < BOARDMAX; dpos++) { + int mpos; if (ON_BOARD(dpos) && mn[dpos] == 1 && board[dpos] == color && are_neighbor_dragons(pos, dpos) && !mf[dpos]) { - int mpos; for (mpos = BOARDMIN; mpos < BOARDMAX; mpos++) if (ON_BOARD(mpos) && is_same_dragon(mpos, dpos)) mf[mpos] = 2; } + /* A special case + * + * . X X . + * X O . X + * X . O O + * . O . . + * + * The O stone hasn't been amalgamated and the surround computations + * might think this single stone dragon is surrounded, which in turn + * can generate overvaluation of moves around this stone. + * Consequently, we allow inclusion of the stones at kosumi distance + * in the mf (friendly) array. + */ + if (ON_BOARD(dpos) + && mn[dpos] == 2 + && board[dpos] == color + && are_neighbor_dragons(pos, dpos) + && !mf[dpos]) { + for (k = 4; k < 8; k++) + if (ON_BOARD(dpos + delta[k]) && board[dpos + delta[k]] == color + && mn[dpos + delta[k]] == 1 + && board[dpos + delta[k-4]] == EMPTY + && board[dpos + delta[(k-3)%4]] == EMPTY) { + for (mpos = BOARDMIN; mpos < BOARDMAX; mpos++) + if (ON_BOARD(mpos) && is_same_dragon(mpos, dpos)) + mf[mpos] = 2; + } + } + } /* determine the surround status of the dragon */ surrounded = SURROUNDED; - for (m = 0; m < board_size; m++) - for (n = 0; n < board_size; n++) { - if (mf[POS(m, n)]) { - if (mn[POS(m, n)] == 0) { - surrounded = 0; - break; - } - else if (mn[POS(m, n)] == 2) - surrounded = WEAKLY_SURROUNDED; - } + /* Compute the maximum surround status awarded + * If distances between enclosing stones are large, reduce to + * WEAKLY_SURROUNDED. If (really) too large, then reduce to 0 + * FIXME: constants chosen completely ad hoc. Possibly better tunings + * can be found. + */ + + for (k = 0; k < corners - 1; k++) { + if (is_edge_vertex(corner[k]) + && is_edge_vertex(corner[k+1])) + continue; + if (square_dist(corner[k], corner[k+1]) > 60) { + surrounded = 0; + break; } + else if (square_dist(corner[k], corner[k+1]) > 27) + surrounded = WEAKLY_SURROUNDED; + } + if (surrounded + && (!is_edge_vertex(corner[0]) + || !is_edge_vertex(corner[corners-1]))) { + if (square_dist(corner[0], corner[corners-1]) > 60) + surrounded = 0; + else if (square_dist(corner[0], corner[corners-1]) > 27) + surrounded = WEAKLY_SURROUNDED; + } + + if (surrounded) + for (m = 0; m < board_size; m++) + for (n = 0; n < board_size; n++) { + if (mf[POS(m, n)]) { + if (mn[POS(m, n)] == 0) { + surrounded = 0; + break; + } + else if (mn[POS(m, n)] == 2) + surrounded = WEAKLY_SURROUNDED; + } + } + + /* revise the status for single stone dragons. */ + + if (stones == 1 + && surrounded == WEAKLY_SURROUNDED + && mn[pos] == 2) + surrounded = 0; /* revise the status if an ikken tobi jumps out. */ @@ -352,36 +520,7 @@ } } if (showboard == 1 || (showboard == 2 && surrounded)) { - start_draw_board(); - for (m = 0; m < board_size; m++) - for (n = 0; n < board_size; n++) { - int col, c; - - if (mf[POS(m,n)]) { - if (mn[POS(m,n)] ==1 ) - col = GG_COLOR_RED; - else if (mn[POS(m,n)] == 2) - col = GG_COLOR_YELLOW; - else - col = GG_COLOR_GREEN; - } - else if (mn[POS(m,n)] == 1) - col = GG_COLOR_BLUE; - else if (mn[POS(m,n)] == 2) - col = GG_COLOR_CYAN; - else - col = GG_COLOR_BLACK; - if (board[POS(m, n)] == BLACK) - c = 'X'; - else if (board[POS(m, n)] == WHITE) - c = 'O'; - else if (mn[POS(m, n)]) - c = '*'; - else - c = '.'; - draw_color_char(m, n, c, col); - } - end_draw_board(); + show_surround_map(mf, mn); } if (!apos && surrounded && surround_pointer < MAX_SURROUND) { memcpy(surroundings[surround_pointer].surround_map, mn, sizeof(mn)); @@ -398,6 +537,127 @@ } return surrounded; } + + +/* Computes the minimum distance to the goal + */ + +static int +goal_dist(int pos, char goal[BOARDMAX]) +{ + int dist = 10000; + int ii; + + for (ii = BOARDMIN; ii 0) { + if (dj_b != 0 || di_b <= 0) + return -1; + return 0; + } + else { + if (dj_b > 0) + return -1; + else if (dj_b < 0 || di_b > 0) + return 1; + else + return 0; + } + } + + sin_a = (float)di_a / sqrt(di_a*di_a + dj_a*dj_a); + sin_b = (float)di_b / sqrt(di_b*di_b + dj_b*dj_b); + + if (dj_a > 0) { + if (dj_b <= 0) + return 1; + if (sin_a > sin_b) + return 1; + else if (sin_a < sin_b) + return -1; + else + return 0; + } + else { /* if (dj_a < 0) */ + if (dj_b > 0) + return -1; + if (sin_a < sin_b) + return 1; + else if (sin_a > sin_b) + return -1; + else + return 0; + } + +} + + +static void +show_surround_map(char mf[BOARDMAX], char mn[BOARDMAX]) +{ + int m, n; + + start_draw_board(); + for (m = 0; m < board_size; m++) + for (n = 0; n < board_size; n++) { + int col, c; + + if (mf[POS(m,n)]) { + if (mn[POS(m,n)] ==1 ) + col = GG_COLOR_RED; + else if (mn[POS(m,n)] == 2) + col = GG_COLOR_YELLOW; + else + col = GG_COLOR_GREEN; + } + else if (mn[POS(m,n)] == 1) + col = GG_COLOR_BLUE; + else if (mn[POS(m,n)] == 2) + col = GG_COLOR_CYAN; + else + col = GG_COLOR_BLACK; + if (board[POS(m, n)] == BLACK) + c = 'X'; + else if (board[POS(m, n)] == WHITE) + c = 'O'; + else if (mn[POS(m, n)]) + c = '*'; + else + c = '.'; + draw_color_char(m, n, c, col); + } + end_draw_board(); +} + + int is_surrounded(int dr) Index: engine/value_moves.c =================================================================== RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v retrieving revision 1.76 diff -u -r1.76 value_moves.c --- engine/value_moves.c 2 Jan 2003 00:23:29 -0000 1.76 +++ engine/value_moves.c 8 Jan 2003 08:55:25 -0000 @@ -457,14 +457,6 @@ -static int -bdist(int pos1, int pos2) -{ - int idist = I(pos1) - I(pos2); - int jdist = J(pos1) - J(pos2); - return idist*idist + jdist*jdist; -} - /* * Any move that captures or defends a worm also potentially connects * or cuts the surrounding strings. Find these secondary move reasons @@ -612,7 +612,7 @@ for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) if (ON_BOARD(pos2) && board[pos2] == EMPTY && cut_possible(pos2, OTHER_COLOR(color)) - && bdist(pos, pos2) <= 5) + && square_dist(pos, pos2) <= 5) for (j = 0; j < 8; j++) { int pos3 = pos2 + delta[j]; if (ON_BOARD(pos3) && board[pos3] == color