[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [gnugo-devel] connect before capture !
From: |
Paul Pogonyshev |
Subject: |
Re: [gnugo-devel] connect before capture ! |
Date: |
Sat, 29 Jan 2005 23:22:48 +0200 |
User-agent: |
KMail/1.4.3 |
Alain Baeckeroot wrote:
> Hello
>
> This gnugo 3.6 against itself:
>
> An weird game , with noticeable
> W 42 connect W stones because of atari,
> W 44 eat 3 B stones responsible for the atari !
>
> This seems to be a pure mistake ;)
>
> (preceded by an incredible connection due to sente loss
> caused by a useless B d3 ...)
I have a patch that solves it. The patch tries to be more intelligent
when computing tactical followup values. Apart from solving this problem,
it also gives a pass in nngs4:580. The pass looks quite accidental (I
assume W E5 is supposed to kill black stones), but still not bad: now GNU
Go doesn't give any followup to W H5 for threating G6, because black's
response at G5 would threat to defend J5 in turn.
I didn't compare node counters, but it must not cost anything.
With regards to Alain's testcase, the first part of the patch (concerned
with reducing followup based on `ATTACK_MOVE' reasons) reduces the
followup of D9. The second part keeps the followup for G7 (though
reduces it a little); previously, G7 followup was removed altogether,
because the defense move at J9 would threat the stone at G7.
Paul
--- value_moves.c 23 Jan 2005 00:06:01 +0200 1.144
+++ value_moves.c 29 Jan 2005 21:18:01 +0200
@@ -2004,23 +2004,98 @@ estimate_territorial_value(int pos, int
&& find_defense(aa, &defense_move) == WIN
&& defense_move != NO_MOVE) {
int bad_followup;
- if (trymove(defense_move, other,
- "estimate_territorial_value-b", NO_MOVE)) {
- if (board[pos] == EMPTY || attack(pos, NULL) != 0) {
+ int attack_move;
+
+ if (attack(pos, &attack_move) != WIN) {
+ int i;
+
+ if (trymove(defense_move, other,
+ "estimate_territorial_value-b", NO_MOVE)) {
+ if (board[pos] == EMPTY || attack(pos, NULL) != 0) {
+ popgo();
+ popgo();
+ break;
+ }
+
+ /* Now check all `ATTACK_MOVE' reasons for this same
+ * move. If the defense against current threat makes a
+ * string attacked by this move defendable, we reduce
+ * the followup.
+ *
+ * Adjustments done later are concerned with current
+ * dragon states. Here we actually try to check if
+ * opponent's reply to our move will have a followup in
+ * turn.
+ */
+ for (i = 0; i < MAX_REASONS; i++) {
+ int reason = move[pos].reason[i];
+ int attacked_string;
+ if (reason < 0)
+ break;
+
+ attacked_string = move_reasons[reason].what;
+ if (move_reasons[reason].type == ATTACK_MOVE
+ && board[attacked_string] == other) {
+ int defense_code = find_defense(attacked_string, NULL);
+ double down_coefficient = 0.0;
+
+ switch (defense_code) {
+ case WIN:
+ down_coefficient = 2.0;
+ break;
+
+ case KO_A:
+ down_coefficient = 2.0 * 0.5;
+ break;
+
+ case KO_B:
+ down_coefficient = 2.0 * 0.7;
+ break;
+ }
+
+ if (adjustment_down
+ < (worm[attacked_string].effective_size
+ * down_coefficient)) {
+ adjustment_down = (worm[attacked_string].effective_size
+ * down_coefficient);
+ }
+ }
+ }
+
popgo();
+ }
+ }
+ else {
+ /* Our move is attackable to begin with. However, maybe
+ * the attack is not sufficient to defend opponent's
+ * string?
+ */
+ if (trymove(attack_move, other,
+ "estimate_territorial_value-c", NO_MOVE)) {
+ if (attack(aa, NULL) == 0) {
+ /* It is sufficient, no followup. */
+ popgo();
+ popgo();
+ break;
+ }
+
popgo();
- break;
}
- popgo();
+
+ /* Heuristically reduce the followup, since our string
+ * will be still attackable if opponent defends his
+ * string.
+ */
+ adjustment_down = 2 * countstones(pos);
}
-
+
bad_followup = 0;
for (s = 0; s < num_adj; s++) {
int lib;
if (countlib(adjs[s]) == 1) {
findlib(adjs[s], 1, &lib);
if (trymove(lib, other,
- "estimate_territorial_value-c", NO_MOVE)) {
+ "estimate_territorial_value-d", NO_MOVE)) {
if (!attack(aa, NULL)
&& (board[pos] == EMPTY || attack(pos, NULL) != 0)) {
popgo();