[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnugo-devel] arend_3_4.4: strategic evaluation
From: |
Arend Bayer |
Subject: |
[gnugo-devel] arend_3_4.4: strategic evaluation |
Date: |
Mon, 17 Jun 2002 18:57:31 +0200 (CEST) |
- segment_regions also computes territorial value of regions if available
- new in dragon2 array: post owl moyo size, its terr. value, dragon weakness
- strategic dragon evaluation rewritten, setting dragon2[].weakness
- moved interpolate to gg_interpolate in gg_utils.c
So here is the strategy patch I already mentioned. What is new is that we
now use the post owl influence computation to estimate a dragon's weakness.
This has the advantage that we can use the territorial value of the moyo
instead of just using its size. Of course a moyo of size 8 that is pure
territory is more useful than a moyo of size 10 that is expected to yield 3
points of territory.
This means I needed to do a few modifications to examine_position().
Apart from that, the patch is mostly just smoothening out the rules used
in dragon_safety in value_moves.c into continuos valuations. To do this,
I found linear interpolation to be a good compromise between fine tuning
possibilities and robust behaviour.
The breakage of CVS+arend_3_4.4 is appr. 28 PASSes and 9 FAILs.
There certainly can be done further tuning on this patch. Some issues are:
- perhaps introduce capping of effective dragon size
- look at behaviour together with --experimental-semeai/connections and
--owl-threats
Also, show_dragons() doesn't report the new dragon fields yet.
Arend
Index: engine/dragon.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/dragon.c,v
retrieving revision 1.66
diff -u -r1.66 dragon.c
--- engine/dragon.c 15 Jun 2002 21:39:19 -0000 1.66
+++ engine/dragon.c 17 Jun 2002 16:53:45 -0000
@@ -47,6 +47,7 @@
#include <ctype.h>
#include "liberty.h"
+#include "gg_utils.h"
static void initialize_supplementary_dragon_data(void);
static void find_neighbor_dragons(void);
@@ -57,7 +58,8 @@
static int compute_dragon_status(int pos);
static void dragon_eye(int pos, struct eye_data[BOARDMAX]);
static int compute_escape(int pos, int dragon_status_known);
-static void compute_surrounding_moyo_sizes(int opposite);
+static void compute_surrounding_moyo_sizes(int opposite,
+ int dragon_status_known);
static int dragon2_initialized;
static int lively_white_dragons;
@@ -320,15 +322,15 @@
/* Compute the surrounding moyo sizes. */
for (d = 0; d < number_of_dragons; d++)
- dragon2[d].moyo = 2 * BOARDMAX;
+ dragon2[d].moyo_size_pre_owl = 2 * BOARDMAX;
/* Set moyo sizes according to initial_influence. */
- compute_surrounding_moyo_sizes(0);
+ compute_surrounding_moyo_sizes(0, 0);
/* Set moyo sizes according to initial_opposite_influence if
* this yields smaller results.
*/
- compute_surrounding_moyo_sizes(1);
+ compute_surrounding_moyo_sizes(1, 0);
time_report(2, " time to compute moyo sizes", NO_MOVE, 1.0);
-
+
/* Determine status: ALIVE, DEAD, CRITICAL or UNKNOWN */
for (str = BOARDMIN; str < BOARDMAX; str++)
if (ON_BOARD(str)) {
@@ -370,9 +372,9 @@
/* Some dragons can be ignored but be extra careful with big dragons. */
if (DRAGON2(str).escape_route > 25
- || DRAGON2(str).moyo > 20
- || (DRAGON2(str).moyo > 10
- && DRAGON2(str).moyo > dragon[str].size)) {
+ || DRAGON2(str).moyo_size_pre_owl > 20
+ || (DRAGON2(str).moyo_size_pre_owl > 10
+ && DRAGON2(str).moyo_size_pre_owl > dragon[str].size)) {
dragon[str].owl_status = UNCHECKED;
dragon[str].owl_attack_point = NO_MOVE;
dragon[str].owl_defense_point = NO_MOVE;
@@ -499,9 +501,9 @@
&& dragon[str].origin == str) {
/* Some dragons can be ignored but be extra careful with big dragons. */
if (DRAGON2(str).escape_route > 25
- || DRAGON2(str).moyo > 20
- || (DRAGON2(str).moyo > 10
- && DRAGON2(str).moyo > dragon[str].size)) {
+ || DRAGON2(str).moyo_size_pre_owl > 20
+ || (DRAGON2(str).moyo_size_pre_owl > 10
+ && DRAGON2(str).moyo_size_pre_owl > dragon[str].size)) {
dragon[str].owl_threat_status = UNCHECKED;
dragon[str].owl_second_attack_point = NO_MOVE;
dragon[str].owl_second_defense_point = NO_MOVE;
@@ -573,13 +575,13 @@
dragon2[d].safety = CRITICAL;
else if (dragon[origin].owl_status == UNCHECKED
&& true_genus < 4
- && dragon2[d].moyo <= 10)
+ && dragon2[d].moyo_size_pre_owl <= 10)
dragon2[d].safety = WEAK;
else if (dragon_invincible(origin))
dragon2[d].safety = INVINCIBLE;
- else if (true_genus >= 6 || dragon2[d].moyo > 20)
+ else if (true_genus >= 6 || dragon2[d].moyo_size_pre_owl > 20)
dragon2[d].safety = STRONGLY_ALIVE;
- else if ((2 * true_genus + dragon2[d].moyo
+ else if ((2 * true_genus + dragon2[d].moyo_size_pre_owl
+ 2 * (dragon2[d].lunch != NO_MOVE) < 8
&& dragon2[d].escape_route < 10)
|| (dragon[origin].owl_threat_status == CAN_THREATEN_ATTACK)) {
@@ -743,7 +745,9 @@
for (d = 0; d < number_of_dragons; d++) {
dragon2[d].neighbors = 0;
dragon2[d].hostile_neighbors = 0;
- dragon2[d].moyo = -1;
+ dragon2[d].moyo_size_pre_owl = -1;
+ dragon2[d].moyo_size_post_owl = -1;
+ dragon2[d].moyo_territorial_value = 0.0;
dragon2[d].safety = -1;
dragon2[d].escape_route = 0;
dragon2[d].genus = 0;
@@ -1163,7 +1167,7 @@
d2->escape_route,
snames[dd->status],
snames[dd->matcher_status],
- d2->moyo,
+ d2->moyo_size_pre_owl,
safety_names[d2->safety]);
gprintf(", owl status %s\n", snames[dd->owl_status]);
if (dd->owl_status == CRITICAL) {
@@ -1333,7 +1337,7 @@
if (lunch == NO_MOVE || worm[lunch].cutstone < 2) {
if (true_genus < 3
&& DRAGON2(pos).escape_route == 0
- && DRAGON2(pos).moyo < 5)
+ && DRAGON2(pos).moyo_size_pre_owl < 5)
return DEAD;
if (true_genus == 3
@@ -1578,7 +1582,8 @@
if (dragon[ii].status == ALIVE)
escape_value[ii] = 6;
else if (dragon[ii].status == UNKNOWN
- && (DRAGON2(ii).escape_route > 5 || DRAGON2(ii).moyo > 5))
+ && (DRAGON2(ii).escape_route > 5
+ || DRAGON2(ii).moyo_size_pre_owl > 5))
escape_value[ii] = 4;
}
else {
@@ -1596,9 +1601,11 @@
* Sum up the surrounding moyo sizes for each dragon. Write this into
* dragon2[].moyo if it is smaller than the current entry. If (opposite)
* is true, we use initial_opposite_influence, otherwise initial_influence.
+ * If dragons_known is false, then .moyo_size_pre_owl is set, otherwise
+ * .moyo_size_post_owl and .moyo_territorial_value.
*/
static void
-compute_surrounding_moyo_sizes(int opposite)
+compute_surrounding_moyo_sizes(int opposite, int dragon_status_known)
{
int pos;
int d;
@@ -1610,6 +1617,7 @@
memset(mx, 0, sizeof(mx));
for (d = 0; d < number_of_dragons; d++) {
int this_moyo_size = 0;
+ float this_moyo_value = 0.0;
for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
int moyo_number = moyos.segmentation[pos];
if (moyo_number == 0
@@ -1621,15 +1629,140 @@
if (mx[moyo_number] != d + 1) {
mx[moyo_number] = d + 1;
this_moyo_size += moyos.size[moyo_number];
+ this_moyo_value += moyos.territorial_value[moyo_number];
}
}
- if (this_moyo_size < dragon2[d].moyo)
- dragon2[d].moyo = this_moyo_size;
+ if (!dragon_status_known) {
+ if (this_moyo_size < dragon2[d].moyo_size_pre_owl) {
+ dragon2[d].moyo_size_pre_owl = this_moyo_size;
+ }
+ }
+ else
+ if (this_moyo_size < dragon2[d].moyo_size_post_owl) {
+ dragon2[d].moyo_size_post_owl = this_moyo_size;
+ dragon2[d].moyo_territorial_value = this_moyo_value;
+ }
}
}
+struct interpolation_data moyo_value2weakness =
+ { 5, 0.0, 15.0, {1.0, 0.65, 0.3, 0.15, 0.05, 0.0}};
+struct interpolation_data escape_route2weakness =
+ { 5, 0.0, 25.0, {1.0, 0.6, 0.3, 0.1, 0.05, 0.0}};
+struct interpolation_data genus2weakness =
+ { 6, 0.0, 3.0, {1.0, 0.95, 0.8, 0.5, 0.2, 0.1, 0.0}};
+
+/* This function tries to guess a coefficient measuring the weakness of
+ * a dragon. This coefficient * the effective size of the dragon can be
+ * used to award a strategic penalty for weak dragons.
+ */
+static float
+compute_dragon_weakness_value(int d)
+{
+ float true_genus = ((float) dragon2[d].genus)
+ + 0.5 * ((float) dragon2[d].heyes
+ + (dragon2[d].lunch != NO_MOVE ? 1.0 : 0.0));
+ int origin = dragon2[d].origin;
+ float escape_route = (float) dragon2[d].escape_route;
+ int dragon_safety = dragon2[d].safety;
+ int i,j;
+
+ float weakness_value[3];
+ float weakness;
+
+ if (dragon_safety == INVINCIBLE|| dragon_safety == INESSENTIAL)
+ return 0.0;
+ if (dragon_safety == TACTICALLY_DEAD)
+ return 1.0;
+
+ if (dragon_safety == DEAD)
+ return 1.0;
+
+ if (dragon_safety == CRITICAL)
+ return 0.9;
+
+ /* Possible ingredients for the computation:
+ * '+' means currently used, '-' means not (yet?) used
+ * - pre-owl moyo_size
+ * + post-owl moyo_size and its territory value!
+ * + escape factor
+ * + number of eyes
+ * - minus number of vital attack moves?
+ * + from owl:
+ * + attack certain?
+ * - number of owl nodes
+ * - maybe reading shadow?
+ * + threat to attack?
+ * - possible connections to neighbour dragons
+ */
+
+ weakness_value[0] = gg_interpolate(&moyo_value2weakness,
+ dragon2[d].moyo_territorial_value);
+ weakness_value[1] = gg_interpolate(&escape_route2weakness,
+ escape_route);
+ weakness_value[2] = gg_interpolate(&genus2weakness, true_genus);
+
+ DEBUG(DEBUG_DRAGONS, "Computing weakness of dragon at %1m:\n", origin);
+ DEBUG(DEBUG_DRAGONS, " moyo value %f -> %f, escape %f -> %f, eyes %f ->
%f,",
+ dragon2[d].moyo_territorial_value, weakness_value[0],
+ escape_route, weakness_value[1], true_genus, weakness_value[2]);
+
+ for (i = 0; i < 3; i++)
+ for (j = i + 1; j < 3; j++)
+ if (weakness_value[j] < weakness_value[i]) {
+ float tmp = weakness_value[i];
+ weakness_value[i] = weakness_value[j];
+ weakness_value[j] = tmp;
+ }
+
+ /* The overall weakness is mostly, but not completely determined by the
+ * best value found so far:
+ */
+ weakness = gg_min(0.7 * weakness_value[0] + 0.3 * weakness_value[1],
+ 1.3 * weakness_value[0]);
+
+ /* Now corrections due to (uncertain) owl results resp. owl threats. */
+ if (!dragon[origin].owl_attack_certain)
+ weakness += gg_min(0.25 * (1.0 - weakness), 0.25 * weakness);
+ if (!dragon[origin].owl_defense_certain)
+ weakness += gg_min(0.25 * (1.0 - weakness), 0.25 * weakness);
+ if (dragon[origin].owl_threat_status == CAN_THREATEN_ATTACK)
+ weakness += 0.15 * (1.0 - weakness);
+
+ if (weakness < 0.0)
+ weakness = 0.0;
+ if (weakness > 1.0)
+ weakness = 1.0;
+
+ DEBUG(DEBUG_DRAGONS, " result: %f.\n", weakness);
+
+ return weakness;
+}
+
+/* This function has to be called _after_ the owl analysis and the
+ * subsequent re-run of the influence code.
+ */
+void
+compute_refined_dragon_weaknesses()
+{
+ int d;
+
+ /* Compute the surrounding moyo sizes. */
+ for (d = 0; d < number_of_dragons; d++)
+ dragon2[d].moyo_size_post_owl = 2 * BOARDMAX;
+ /* Set moyo sizes according to initial_influence. */
+ compute_surrounding_moyo_sizes(0, 1);
+ /* Set moyo sizes according to initial_opposite_influence if
+ * this yields smaller results.
+ */
+ compute_surrounding_moyo_sizes(1, 1);
+
+ for (d = 0; d < number_of_dragons; d++)
+ dragon2[d].weakness = compute_dragon_weakness_value(d);
+}
+
/*
* Test whether two dragons are the same. Used by autohelpers and elsewhere.
*/
@@ -1743,43 +1876,46 @@
return;
}
- gfprintf(outfile,"color %s\n",
color_to_string(dragon[pos].color));
- gfprintf(outfile,"origin %1m\n", dragon[pos].origin);
- gfprintf(outfile,"size %d\n", dragon[pos].size);
- gfprintf(outfile,"effective_size %f\n", dragon[pos].effective_size);
- gfprintf(outfile,"heyes %d\n", DRAGON2(pos).heyes);
- gfprintf(outfile,"heye %1m\n", DRAGON2(pos).heye);
- gfprintf(outfile,"genus %d\n", DRAGON2(pos).genus);
- gfprintf(outfile,"escape_route %d\n", DRAGON2(pos).escape_route);
- gfprintf(outfile,"lunch %1m\n", DRAGON2(pos).lunch);
+ gfprintf(outfile,"color %s\n", color_to_string(d->color));
+ gfprintf(outfile,"origin %1m\n", d->origin);
+ gfprintf(outfile,"size %d\n", d->size);
+ gfprintf(outfile,"effective_size %f\n", d->effective_size);
+ gfprintf(outfile,"heyes %d\n", d2->heyes);
+ gfprintf(outfile,"heye %1m\n", d2->heye);
+ gfprintf(outfile,"genus %d\n", d2->genus);
+ gfprintf(outfile,"escape_route %d\n", d2->escape_route);
+ gfprintf(outfile,"lunch %1m\n", d2->lunch);
gfprintf(outfile,"status %s\n",
- status_to_string(dragon[pos].status));
+ status_to_string(d->status));
gfprintf(outfile,"owl_status %s\n",
- status_to_string(dragon[pos].owl_status));
+ status_to_string(d->owl_status));
gfprintf(outfile,"matcher_status %s\n",
- status_to_string(dragon[pos].matcher_status));
+ status_to_string(d->matcher_status));
gfprintf(outfile,"owl_threat_status %s\n",
- status_to_string(dragon[pos].owl_threat_status));
- gfprintf(outfile,"owl_attack %1m\n",
dragon[pos].owl_attack_point);
+ status_to_string(d->owl_threat_status));
+ gfprintf(outfile,"owl_attack %1m\n", d->owl_attack_point);
gfprintf(outfile,"owl_attack_certain %s\n",
- (dragon[pos].owl_attack_certain) ? "YES" : "NO");
- gfprintf(outfile,"owl_2nd_attack %1m\n",
dragon[pos].owl_second_attack_point);
- gfprintf(outfile,"owl_defend %1m\n",
dragon[pos].owl_defense_point);
+ (d->owl_attack_certain) ? "YES" : "NO");
+ gfprintf(outfile,"owl_2nd_attack %1m\n",
d->owl_second_attack_point);
+ gfprintf(outfile,"owl_defend %1m\n", d->owl_defense_point);
gfprintf(outfile,"owl_defense_certain %s\n",
- (dragon[pos].owl_defense_certain) ? "YES" : "NO");
- gfprintf(outfile,"owl_2nd_defend %1m\n",
dragon[pos].owl_second_defense_point);
- gfprintf(outfile,"semeai %d\n", DRAGON2(pos).semeai);
+ (d->owl_defense_certain) ? "YES" : "NO");
+ gfprintf(outfile,"owl_2nd_defend %1m\n",
+ d->owl_second_defense_point);
+ gfprintf(outfile,"semeai %d\n", d2->semeai);
gfprintf(outfile,"semeai_margin_of_safety %d\n",
- DRAGON2(pos).semeai_margin_of_safety);
+ d2->semeai_margin_of_safety);
gfprintf(outfile,"neighbors ");
- for (k = 0; k < DRAGON2(pos).neighbors; k++)
- gfprintf(outfile,"%1m ", DRAGON(DRAGON2(pos).adjacent[k]).origin);
+ for (k = 0; k < d2->neighbors; k++)
+ gfprintf(outfile,"%1m ", DRAGON(d2->adjacent[k]).origin);
gfprintf(outfile,"\nhostile neighbors %d\n", d2->hostile_neighbors);
- gfprintf(outfile,"moyo %d\n", DRAGON2(pos).moyo);
+ gfprintf(outfile,"moyo size pre owl %d\n", d2->moyo_size_pre_owl);
+ gfprintf(outfile,"moyo size post owl %d\n", d2->moyo_size_post_owl);
+ gfprintf(outfile,"moyo territorial value %f\n", d2->moyo_territorial_value);
gfprintf(outfile,"safety %s\n",
- safety_to_string(DRAGON2(pos).safety));
+ safety_to_string(d2->safety));
+ gfprintf(outfile,"weakness estimate %f\n", d2->weakness);
gfprintf(outfile,"strings ");
-
for (ii = BOARDMIN; ii < BOARDMAX; ii++)
if (ON_BOARD(ii)
&& worm[ii].origin == ii
Index: engine/genmove.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/genmove.c,v
retrieving revision 1.41
diff -u -r1.41 genmove.c
--- engine/genmove.c 6 May 2002 14:27:31 -0000 1.41
+++ engine/genmove.c 17 Jun 2002 16:53:48 -0000
@@ -49,6 +49,7 @@
static int dragons_examined_without_owl = -1;
static int dragons_examined = -1;
static int initial_influence2_examined = -1;
+static int dragons_refinedly_examined = -1;
static int revise_semeai(int color);
static int revise_thrashing_dragon(int color, float advantage);
@@ -81,6 +82,7 @@
dragons_examined_without_owl = -1;
dragons_examined = -1;
initial_influence2_examined = -1;
+ dragons_refinedly_examined = -1;
/* Prepare our table of move reasons. */
clear_move_reasons();
@@ -165,15 +167,24 @@
verbose = save_verbose;
- if (printworms)
- show_dragons();
-
- if (NEEDS_UPDATE(initial_influence2_examined))
+ if (NEEDS_UPDATE(initial_influence2_examined)) {
compute_initial_influence(color, 1);
+ }
if (how_much == EXAMINE_INITIAL_INFLUENCE2) {
gg_assert(test_gray_border() < 0);
return;
}
+
+ if (NEEDS_UPDATE(dragons_refinedly_examined)) {
+ compute_refined_dragon_weaknesses();
+ }
+ if (how_much == FULL_EXAMINE_DRAGONS) {
+ gg_assert(test_gray_border() < 0);
+ return;
+ }
+
+ if (printworms)
+ show_dragons();
}
Index: engine/gnugo.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/gnugo.h,v
retrieving revision 1.57
diff -u -r1.57 gnugo.h
--- engine/gnugo.h 22 May 2002 19:22:25 -0000 1.57
+++ engine/gnugo.h 17 Jun 2002 16:53:51 -0000
@@ -373,6 +373,7 @@
#define EXAMINE_DRAGONS 4
#define EXAMINE_OWL_REASONS 5
#define EXAMINE_INITIAL_INFLUENCE2 6
+#define FULL_EXAMINE_DRAGONS 7
#define EXAMINE_ALL 99
@@ -449,6 +450,7 @@
/* dragon.c */
void make_dragons(int color, int stop_before_owl, int save_verbose);
+void compute_refined_dragon_weaknesses(void);
void initialize_dragon_data(void);
void show_dragons(void);
int dragon_status(int pos);
Index: engine/influence.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.c,v
retrieving revision 1.56
diff -u -r1.56 influence.c
--- engine/influence.c 29 May 2002 09:26:49 -0000 1.56
+++ engine/influence.c 17 Jun 2002 16:54:00 -0000
@@ -1084,6 +1084,9 @@
if (q->black_strength[i][j] > 0.0)
accumulate_influence(q, i, j, BLACK);
}
+
+ if (q->is_territorial_influence)
+ value_territory(q, m, n, color);
segment_influence(q);
if (((q == &initial_influence || q == &initial_opposite_influence)
@@ -1211,34 +1214,6 @@
return EMPTY;
}
-#define MAX_INTERPOLATION_STEPS 20
-struct interpolation_data
-{
- int sections;
- float range_lowerbound;
- float range_upperbound;
- float values[MAX_INTERPOLATION_STEPS + 1];
-};
-
-static float
-interpolate(struct interpolation_data *f, float x)
-{
- int i;
- float ratio;
- float diff;
- if (x < f->range_lowerbound)
- return f->values[0];
- else if (x > f->range_upperbound)
- return f->values[f->sections];
- else {
- ratio = ((float) f->sections) * (x - f->range_lowerbound)
- /(f->range_upperbound - f->range_lowerbound);
- i = ratio;
- diff = ratio - ((float)i);
- return ((1-diff)*f->values[i] + diff* f->values[i+1]);
- }
-}
-
/* This curve determines how much influence is needed at least to claim
* an intersection as territory, in dependence of the "center value".
* (In the center, more effort is needed to get territory!)
@@ -1295,8 +1270,8 @@
dist_j = gg_min(4, dist_j);
central = (float) 2 * gg_min(dist_i, dist_j) + dist_i + dist_j;
ratio = gg_max(q->black_influence[i][j], q->white_influence[i][j])
- / interpolate(&min_infl_for_territory, central);
- first_guess[i][j] *= interpolate(&territory_correction, ratio);
+ / gg_interpolate(&min_infl_for_territory, central);
+ first_guess[i][j] *= gg_interpolate(&territory_correction, ratio);
/* Dead stone, upgrade to territory. Notice that this is not
* the point for a prisoner, which is added later. Instead
@@ -1382,11 +1357,12 @@
* for the color playing it. Ideally this should never happen, but
* currently we need this workaround.
*/
- ASSERT2(color == EMPTY || ON_BOARD2(m, n), m, n);
- if (color == BLACK && q->territory_value[m][n] < 0.0)
- q->territory_value[m][n] = 0.0;
- else if (color == WHITE && q->territory_value[m][n] > 0.0)
- q->territory_value[m][n] = 0.0;
+ if (ON_BOARD2(m,n)) {
+ if (color == BLACK && q->territory_value[m][n] < 0.0)
+ q->territory_value[m][n] = 0.0;
+ else if (color == WHITE && q->territory_value[m][n] > 0.0)
+ q->territory_value[m][n] = 0.0;
+ }
}
@@ -1409,6 +1385,7 @@
* the rest of the region.
*/
int size = 0;
+ float terr_val = 0.0;
int queue_start = 0;
int queue_end = 1;
int color = region_owner(q, m, n);
@@ -1421,8 +1398,11 @@
int j = q->queuej[queue_start];
int k;
queue_start++;
- if (q->p[i][j] != color)
+ if (q->p[i][j] != color) {
size++;
+ if (q->is_territorial_influence)
+ terr_val += gg_abs(q->territory_value[i][j]);
+ }
segmentation[i][j] = q->number_of_regions;
for (k = 0; k < 4; k++) {
int di = deltai[k];
@@ -1442,6 +1422,7 @@
else
q->region_type[q->number_of_regions] = BLACK_REGION | type;
q->region_size[q->number_of_regions] = size;
+ q->region_territorial_value[q->number_of_regions] = terr_val;
if (0)
gprintf("Region %d of type %d (color %s) at %m. Size %d\n",
q->number_of_regions, q->region_type[q->number_of_regions],
@@ -1550,6 +1531,8 @@
/* Export size and owner info. */
for (i = min_moyo_id; i <= max_moyo_id; i++) {
moyos->size[i - min_moyo_id + 1] = q->region_size[i];
+ moyos->territorial_value[i - min_moyo_id + 1]
+ = q->region_territorial_value[i];
if (q->region_type[i] & BLACK_REGION)
moyos->owner[i - min_moyo_id + 1] = BLACK;
else
@@ -1586,7 +1569,6 @@
compute_influence(&initial_influence, OTHER_COLOR(color), -1, -1,
NULL, NULL);
if (dragons_known) {
- value_territory(&initial_influence, -1, -1, EMPTY);
if ((printmoyo & PRINTMOYO_VALUE_TERRITORY)
&& (printmoyo & PRINTMOYO_INITIAL_INFLUENCE))
print_influence_territory(&initial_influence,
@@ -1695,6 +1677,7 @@
> move_influence.white_strength[i][j]))
accumulate_influence(&followup_influence, i, j, color);
+ value_territory(&followup_influence, m, n, color);
}
/* Let color play at (m, n) and compute the influence after this move,
@@ -1720,9 +1703,6 @@
compute_followup_influence(m, n, color, saved_stones);
decrease_depth_values();
popgo();
-
- value_territory(&move_influence, m, n, color);
- value_territory(&followup_influence, m, n, color);
if (m == debug_influence_i
&& n == debug_influence_j && m >= 0) {
Index: engine/influence.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/influence.h,v
retrieving revision 1.11
diff -u -r1.11 influence.h
--- engine/influence.h 29 May 2002 09:26:49 -0000 1.11
+++ engine/influence.h 17 Jun 2002 16:54:01 -0000
@@ -104,6 +104,7 @@
int area_segmentation[MAX_BOARD][MAX_BOARD];
int region_type[MAX_REGIONS];
int region_size[MAX_REGIONS];
+ float region_territorial_value[MAX_REGIONS];
int number_of_regions;
int dragons_known; /* True if this is a post-owl influence computation. */
Index: engine/liberty.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/liberty.h,v
retrieving revision 1.104
diff -u -r1.104 liberty.h
--- engine/liberty.h 15 Jun 2002 21:39:19 -0000 1.104
+++ engine/liberty.h 17 Jun 2002 16:54:05 -0000
@@ -524,6 +524,7 @@
int segmentation[BOARDMAX]; /* Numbers the moyos. */
int size[MAX_MOYOS];
int owner[MAX_MOYOS];
+ float territorial_value[MAX_MOYOS];
};
/* Influence functions. */
@@ -758,8 +759,11 @@
int adjacent[MAX_NEIGHBOR_DRAGONS]; /* adjacent dragons */
int neighbors; /* number of adjacent dragons */
int hostile_neighbors; /* neighbors of opposite color */
- int moyo; /* size of surrounding influence moyo */
+ int moyo_size_pre_owl; /* size of surrounding influence moyo */
+ int moyo_size_post_owl; /* size of surrounding influence moyo, */
+ float moyo_territorial_value; /* ...and its territorial value */
int safety; /* a more detailed status estimate */
+ float weakness; /* A new (3.3.x) continuos estimate of the dragon's safety */
int escape_route; /* a measurement of likelihood of escape */
int genus; /* the number of eyes (approximately) */
int heyes; /* the number of half eyes */
Index: engine/owl.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/owl.c,v
retrieving revision 1.91
diff -u -r1.91 owl.c
--- engine/owl.c 3 Jun 2002 15:00:59 -0000 1.91
+++ engine/owl.c 17 Jun 2002 16:54:24 -0000
@@ -4364,7 +4364,8 @@
if (dragon[pos].status == ALIVE)
owl->escape_values[pos] = 6;
else if (dragon[pos].status == UNKNOWN
- && (DRAGON2(pos).escape_route > 5 || DRAGON2(pos).moyo > 5))
+ && (DRAGON2(pos).escape_route > 5
+ || DRAGON2(pos).moyo_size_pre_owl > 5))
owl->escape_values[pos] = 4;
}
DEBUG(DEBUG_ESCAPE, "%o%d", owl->escape_values[pos]);
Index: engine/sgfdecide.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/sgfdecide.c,v
retrieving revision 1.34
diff -u -r1.34 sgfdecide.c
--- engine/sgfdecide.c 15 Jun 2002 21:39:19 -0000 1.34
+++ engine/sgfdecide.c 17 Jun 2002 16:54:27 -0000
@@ -295,7 +295,7 @@
return ;
}
reset_engine();
- silent_examine_position(board[pos], EXAMINE_DRAGONS);
+ silent_examine_position(board[pos], FULL_EXAMINE_DRAGONS);
gprintf("Dragon at %1m:\n", pos);
report_dragon(stderr, pos);
Index: engine/value_moves.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/value_moves.c,v
retrieving revision 1.40
diff -u -r1.40 value_moves.c
--- engine/value_moves.c 12 Jun 2002 15:35:06 -0000 1.40
+++ engine/value_moves.c 17 Jun 2002 16:54:38 -0000
@@ -771,7 +771,8 @@
/*
- * An attempt to estimate the safety of a dragon.
+ * Returns the pre-computed weakness of a dragon, with corrections
+ * according to ignore_dead_draggons.
*
* FIXME: Important to test more exactly how effective a strategical
* attack or defense of a weak dragon is. This can be done by
@@ -782,18 +783,6 @@
* rather where it's called.
*/
-static float safety_values[10] = {
-/* DEAD */ 0.0,
-/* ALIVE */ 0.9,
-/* CRITICAL */ 0.1,
-/* INESSENTIAL */ 1.0, /* Yes, 1.0. We simply don't worry about it. */
-/* TACT. DEAD */ 0.0,
-/* WEAK */ 0.4,
-/* WEAK ALIVE */ 0.6,
-/* SEKI */ 0.8,
-/* STR. ALIVE */ 1.0,
-/* INVINCIBLE */ 1.0};
-
static float
dragon_safety(int dr, int ignore_dead_dragons)
{
@@ -812,28 +801,7 @@
if (doing_scoring && dragon_safety == ALIVE)
return 1.0;
- /* More detailed guesses for WEAK and WEAKLY_ALIVE dragons. */
- if (dragon_safety == WEAK || dragon_safety == WEAKLY_ALIVE) {
- int escape = DRAGON2(dr).escape_route;
- int moyo = DRAGON2(dr).moyo;
- /* If escape <= 5 and moyo <= 10, the dragon won't be WEAK, since
- * the owl code has been run.
- */
- if (escape < 10 && moyo < 5)
- return 0.1;
- else if (escape < 15 && moyo < 5)
- return 0.2;
- else if (escape < 10 && moyo < 10)
- return 0.3;
- else if (escape < 5 && moyo < 15)
- return 0.4;
- else if (escape < 15 && moyo < 15)
- return 0.7;
- else
- return 0.9;
- }
-
- return safety_values[dragon_safety];
+ return (1.0 - DRAGON2(dr).weakness);
}
/*
@@ -935,7 +903,7 @@
* assume it doesn't help dragon a to connect to b.
*/
if (safety2 == CRITICAL && true_genus2 == 0
- && DRAGON2(dragonb).moyo == 0)
+ && DRAGON2(dragonb).moyo_size_pre_owl == 0)
return 0.0;
Index: interface/play_gtp.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/interface/play_gtp.c,v
retrieving revision 1.77
diff -u -r1.77 play_gtp.c
--- interface/play_gtp.c 15 Jun 2002 21:39:19 -0000 1.77
+++ interface/play_gtp.c 17 Jun 2002 16:54:47 -0000
@@ -2624,7 +2624,7 @@
if (stackp > 0)
return gtp_failure(id, "dragon data unavailable when stackp > 0");
- examine_position(EMPTY, EXAMINE_DRAGONS);
+ examine_position(EMPTY, FULL_EXAMINE_DRAGONS);
gtp_printid(id, GTP_SUCCESS);
Index: utils/gg_utils.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/utils/gg_utils.c,v
retrieving revision 1.25
diff -u -r1.25 gg_utils.c
--- utils/gg_utils.c 18 Apr 2002 21:21:31 -0000 1.25
+++ utils/gg_utils.c 17 Jun 2002 16:54:50 -0000
@@ -395,6 +395,27 @@
} while (gap > 1 || swap_made);
}
+/* Linearly interpoloate f(x) from the data given in interpolation_data. */
+float
+gg_interpolate(struct interpolation_data *f, float x)
+{
+ int i;
+ float ratio;
+ float diff;
+ if (x < f->range_lowerbound)
+ return f->values[0];
+ else if (x > f->range_upperbound)
+ return f->values[f->sections];
+ else {
+ ratio = ((float) f->sections) * (x - f->range_lowerbound)
+ /(f->range_upperbound - f->range_lowerbound);
+ i = (int) ratio;
+ diff = ratio - ((float)i);
+ /* printf(stderr, "Floating point Ratio: %f, integer: %d, diff %f",
ratio, i, diff); */
+ return ((1-diff)*f->values[i] + diff* f->values[i+1]);
+ }
+}
+
/* Reorientation of point (i, j) into (*ri, *rj) */
void
Index: utils/gg_utils.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/utils/gg_utils.h,v
retrieving revision 1.10
diff -u -r1.10 gg_utils.h
--- utils/gg_utils.h 18 Apr 2002 21:21:31 -0000 1.10
+++ utils/gg_utils.h 17 Jun 2002 16:54:50 -0000
@@ -67,6 +67,16 @@
void gg_sort(void *base, size_t nel, size_t width,
int (*compar)(const void *, const void *));
+#define MAX_INTERPOLATION_STEPS 20
+struct interpolation_data
+{
+ int sections;
+ float range_lowerbound;
+ float range_upperbound;
+ float values[MAX_INTERPOLATION_STEPS + 1];
+};
+
+float gg_interpolate(struct interpolation_data *f, float x);
const char *gg_version(void);
- [gnugo-devel] arend_3_4.4: strategic evaluation,
Arend Bayer <=