Ticket #199: gunnar_9_1.8b.diff
| File gunnar_9_1.8b.diff, 29.3 KB (added by gunnar, 22 months ago) |
|---|
-
engine/liberty.h
diff --git a/engine/liberty.h b/engine/liberty.h index 8bddec0..f85c11d 100644
a b void compute_eyes_pessimistic(int pos, struct eyevalue *value, 1031 1031 int *pessimistic_min, 1032 1032 int *attack_point, int *defense_point, 1033 1033 struct eye_data eye[BOARDMAX], 1034 struct half_eye_data heye[BOARDMAX]); 1034 struct half_eye_data heye[BOARDMAX], 1035 int eyefilling_points[BOARDMAX]); 1035 1036 void propagate_eye(int pos, struct eye_data eye[BOARDMAX]); 1036 1037 int find_eye_dragons(int origin, struct eye_data eye[BOARDMAX], int eye_color, 1037 1038 int dragons[], int max_dragons); -
engine/optics.c
diff --git a/engine/optics.c b/engine/optics.c index fb3faaf..5f68b39 100644
a b static int read_eye(int pos, int *attack_point, int *defense_point, 59 59 struct eyevalue *value, 60 60 struct eye_data eye[BOARDMAX], 61 61 struct half_eye_data heye[BOARDMAX], 62 int eyefilling_points[BOARDMAX], 62 63 int add_moves); 63 64 static int recognize_eye(int pos, int *attack_point, int *defense_point, 64 65 struct eyevalue *value, 65 66 struct eye_data eye[BOARDMAX], 66 67 struct half_eye_data heye[BOARDMAX], 67 struct vital_points *vp); 68 struct vital_points *vp, 69 int eyefilling_points[BOARDMAX]); 68 70 static void guess_eye_space(int pos, int effective_eyesize, int margins, 69 71 int bulk_score, struct eye_data eye[BOARDMAX], 70 72 struct eyevalue *value, int *pessimistic_min); 73 static struct eye_graph *optical_graph_matcher(int *vpos, 74 signed char *marginal, 75 signed char *edge, 76 signed char *neighbors, 77 signed char *stone, 78 int eye_size, int num_marginals, 79 int *map, 80 struct half_eye_data *heye); 71 81 static void reset_map(int size); 72 82 static void first_map(int *map_value); 73 83 static int next_map(int *q, int map[MAXEYE]); … … compute_eyes(int pos, struct eyevalue *value, 743 753 } 744 754 745 755 /* Look up the eye space in the graphs database. */ 746 if (read_eye(pos, attack_point, defense_point, value, eye, heye, add_moves)) 756 if (read_eye(pos, attack_point, defense_point, value, eye, heye, 757 NULL, add_moves)) 747 758 return; 748 759 749 760 /* Ideally any eye space that hasn't been matched yet should be two … … compute_eyes_pessimistic(int pos, struct eyevalue *value, 771 782 int *pessimistic_min, 772 783 int *attack_point, int *defense_point, 773 784 struct eye_data eye[BOARDMAX], 774 struct half_eye_data heye[BOARDMAX]) 785 struct half_eye_data heye[BOARDMAX], 786 int eyefilling_points[BOARDMAX]) 775 787 { 776 788 static int bulk_coefficients[5] = {-1, -1, 1, 4, 12}; 777 789 … … compute_eyes_pessimistic(int pos, struct eyevalue *value, 882 894 883 895 /* Look up the eye space in the graphs database. */ 884 896 if (read_eye(pos, attack_point, defense_point, value, 885 eye, heye, 0)) {897 eye, heye, eyefilling_points, 0)) { 886 898 *pessimistic_min = min_eyes(value) - margins; 887 899 888 900 /* A single point eye which is part of a ko can't be trusted. */ … … guess_eye_space(int pos, int effective_eyesize, int margins, 1077 1089 static int 1078 1090 read_eye(int pos, int *attack_point, int *defense_point, 1079 1091 struct eyevalue *value, struct eye_data eye[BOARDMAX], 1080 struct half_eye_data heye[BOARDMAX], 1092 struct half_eye_data heye[BOARDMAX], int eyefilling_points[BOARDMAX], 1081 1093 int add_moves) 1082 1094 { 1083 1095 int eye_color; … … read_eye(int pos, int *attack_point, int *defense_point, 1093 1105 struct vital_points *best_vp = &vp; 1094 1106 1095 1107 eye_color = recognize_eye(pos, attack_point, defense_point, value, 1096 eye, heye, &vp );1108 eye, heye, &vp, eyefilling_points); 1097 1109 if (!eye_color) 1098 1110 return 0; 1099 1111 … … read_eye(int pos, int *attack_point, int *defense_point, 1146 1158 1147 1159 heye[combination_halfeye].type = 0; 1148 1160 result = recognize_eye(pos, &apos, &dpos, &combination_value, eye, 1149 heye, &combination_vp );1161 heye, &combination_vp, NULL); 1150 1162 heye[combination_halfeye].type = HALF_EYE; 1151 1163 1152 1164 if (result) { … … read_eye(int pos, int *attack_point, int *defense_point, 1211 1223 1212 1224 heye[ko_halfeye].type = 0; 1213 1225 result = recognize_eye(pos, &apos, &dpos, &ko_value, eye, 1214 heye, &ko_vp );1226 heye, &ko_vp, NULL); 1215 1227 heye[ko_halfeye].type = HALF_EYE; 1216 1228 1217 1229 if (result && max_eyes(value) < max_eyes(&ko_value)) { … … recognize_eye(int pos, int *attack_point, int *defense_point, 1254 1266 struct eyevalue *value, 1255 1267 struct eye_data eye[BOARDMAX], 1256 1268 struct half_eye_data heye[BOARDMAX], 1257 struct vital_points *vp) 1269 struct vital_points *vp, 1270 int eyefilling_points[BOARDMAX]) 1258 1271 { 1259 1272 int pos2; 1260 1273 int eye_color; 1261 1274 int eye_size = 0; 1262 1275 int num_marginals = 0; 1263 1276 int vpos[MAXEYE]; 1264 signed char marginal[MAXEYE], edge[MAXEYE], neighbors[MAXEYE]; 1265 int graph; 1277 signed char marginal[MAXEYE]; 1278 signed char edge[MAXEYE]; 1279 signed char neighbors[MAXEYE]; 1280 signed char stone[MAXEYE]; 1281 struct eye_graph *graph; 1266 1282 int map[MAXEYE]; 1267 1283 int best_score; 1268 1284 int r; 1269 1285 1270 1286 gg_assert(attack_point != NULL); 1271 1287 gg_assert(defense_point != NULL); 1272 1288 1273 1289 /* Set `eye_color' to the owner of the eye. */ 1274 1290 eye_color = eye[pos].color; 1275 1291 … … recognize_eye(int pos, int *attack_point, int *defense_point, 1289 1305 if (marginal[eye_size]) 1290 1306 num_marginals++; 1291 1307 neighbors[eye_size] = eye[pos2].neighbors; 1308 stone[eye_size] = IS_STONE(board[pos2]); 1292 1309 if (0) { 1293 1310 if (marginal[eye_size]) 1294 1311 TRACE("(%1m)", vpos[eye_size]); … … recognize_eye(int pos, int *attack_point, int *defense_point, 1317 1334 num_marginals++; 1318 1335 edge[eye_size] = 0; 1319 1336 neighbors[eye_size] = 1; 1337 stone[eye_size] = 0; 1320 1338 } 1321 1339 1322 1340 eye_size++; 1323 1341 } 1324 1342 } 1325 1343 1344 graph = optical_graph_matcher(vpos, marginal, edge, neighbors, stone, 1345 eye_size, num_marginals, map, heye); 1346 1347 if (!graph) 1348 return 0; 1349 1350 /* We have found a match! Now sort out the vital moves. */ 1351 *value = graph->value; 1352 vp->num_attacks = 0; 1353 vp->num_defenses = 0; 1354 1355 if (eye_move_urgency(value) > 0) { 1356 /* Collect all attack and defense points in the pattern. */ 1357 int k; 1358 1359 for (k = 0; k < eye_size; k++) { 1360 struct eye_vertex *ev = &graph->vertex[k]; 1361 1362 if (ev->flags & EYE_ATTACK_POINT) { 1363 /* Check for a marginal vertex matching a half eye virtual 1364 * marginal. This is the case if a half eye preceeds the 1365 * current vertex in the list. 1366 */ 1367 if (ev->marginal 1368 && map[k] > 0 1369 && vpos[map[k] - 1] != NO_MOVE 1370 && is_halfeye(heye, vpos[map[k] - 1])) { 1371 /* Add all diagonals as vital. */ 1372 int ix; 1373 struct half_eye_data *he = &heye[vpos[map[k] - 1]]; 1374 1375 for (ix = 0; ix < he->num_attacks; ix++) 1376 vp->attacks[vp->num_attacks++] = he->attack_point[ix]; 1377 } 1378 else 1379 vp->attacks[vp->num_attacks++] = vpos[map[k]]; 1380 } 1381 1382 if (ev->flags & EYE_DEFENSE_POINT) { 1383 /* Check for a half eye virtual marginal vertex. */ 1384 if (ev->marginal 1385 && map[k] > 0 1386 && vpos[map[k] - 1] != NO_MOVE 1387 && is_halfeye(heye, vpos[map[k] - 1])) { 1388 /* Add all diagonals as vital. */ 1389 int ix; 1390 struct half_eye_data *he = &heye[vpos[map[k] - 1]]; 1391 1392 for (ix = 0; ix < he->num_defenses; ix++) 1393 vp->defenses[vp->num_defenses++] = he->defense_point[ix]; 1394 } 1395 else 1396 vp->defenses[vp->num_defenses++] = vpos[map[k]]; 1397 } 1398 } 1399 1400 gg_assert(vp->num_attacks > 0 && vp->num_defenses > 0); 1401 1402 /* We now have all vital attack and defense points listed but 1403 * we are also expected to single out of one of each to return 1404 * in *attack_point and *defense_point. Since sometimes those 1405 * are the only vital points considered, we want to choose the 1406 * best ones, in the sense that they minimize the risk for 1407 * error in the eye space analysis. 1408 * 1409 * One example is this position 1410 * 1411 * |..XXXX 1412 * |XXX..X 1413 * |..!O.X 1414 * |OO.O.X 1415 * |.O.!XX 1416 * +------ 1417 * 1418 * where O has an eyespace of the !..! type. The graph 1419 * matching finds that both marginal vertices are vital points 1420 * but here the one at 3-3 fails to defend. (For attack both 1421 * points work but the 3-3 one is still worse since it leaves 1422 * a ko threat.) 1423 * 1424 * In order to differentiate between the marginal points we 1425 * count the number of straight and diagonal neighbors within 1426 * the eye space. In the example above both have one straight 1427 * neighbor each but the edge margin wins because it also has 1428 * a diagonal margin. 1429 */ 1430 1431 best_score = -10; 1432 for (k = 0; k < vp->num_attacks; k++) { 1433 int apos = vp->attacks[k]; 1434 int score = 0; 1435 for (r = 0; r < 8; r++) 1436 if (ON_BOARD(apos + delta[r]) 1437 && eye[apos + delta[r]].color == eye[pos].color 1438 && !eye[apos + delta[r]].marginal) { 1439 score++; 1440 if (r < 4) { 1441 score++; 1442 if (board[apos + delta[r]] != EMPTY) 1443 score++; 1444 } 1445 } 1446 1447 /* If a vital point is not adjacent to any point in the eye 1448 * space, it must be a move to capture or defend a string 1449 * related to a halfeye, e.g. the move * in this position, 1450 * 1451 * ......| 1452 * .XXXX.| 1453 * .X.O..| 1454 * .XO.OO| 1455 * .*XO..| 1456 * ------+ 1457 * 1458 * Playing this is probably a good idea. 1459 */ 1460 if (score == 0) 1461 score += 2; 1462 1463 if (0) 1464 gprintf("attack point %1m score %d\n", apos, score); 1465 1466 if (score > best_score) { 1467 *attack_point = apos; 1468 best_score = score; 1469 } 1470 } 1471 1472 best_score = -10; 1473 for (k = 0; k < vp->num_defenses; k++) { 1474 int dpos = vp->defenses[k]; 1475 int score = 0; 1476 for (r = 0; r < 8; r++) 1477 if (ON_BOARD(dpos + delta[r]) 1478 && eye[dpos + delta[r]].color == eye[pos].color 1479 && !eye[dpos + delta[r]].marginal) { 1480 score++; 1481 if (r < 4) { 1482 score++; 1483 if (board[dpos + delta[r]] != EMPTY) 1484 score++; 1485 } 1486 } 1487 1488 /* If possible, choose a non-sacrificial defense point. 1489 * Compare white T8 and T6 in lazarus:21. 1490 */ 1491 if (safe_move(dpos, eye_color) != WIN) 1492 score -= 5; 1493 1494 /* See comment to the same code for attack points. */ 1495 if (score == 0) 1496 score += 2; 1497 1498 if (0) 1499 gprintf("defense point %1m score %d\n", dpos, score); 1500 1501 if (score > best_score) { 1502 *defense_point = dpos; 1503 best_score = score; 1504 } 1505 } 1506 1507 DEBUG(DEBUG_EYES, " vital points: %1m (attack) %1m (defense)\n", 1508 *attack_point, *defense_point); 1509 DEBUG(DEBUG_EYES, " pattern matched: %d\n", graph->patnum); 1510 1511 } 1512 1513 /* In certain types of semeais it is necessary to fill in nakade 1514 * shapes, e.g. in a position like this: 1515 * 1516 * OOOOOXXXXXX 1517 * OXXXXOOOOOX 1518 * OX.OXXO..OX 1519 * OX.OOXO..OX 1520 * ----------- 1521 * 1522 * However, only one of the lower left liberties leaves a nakade 1523 * shape when O plays there. The code below tries adding a stone at 1524 * each empty vertex in the eyespace and do graph matching to find 1525 * the eyevalue of the resulting eyespace. If it's still only worth 1526 * one eye it is a valid eyefilling point. 1527 * 1528 * In some positions a subset of the eyefilling points give the 1529 * opponent a ko threat. If this can be avoided we prefer the points 1530 * which don't. One example is 1531 * 1532 * XXXX 1533 * XabXX 1534 * XcOdX 1535 * ----- 1536 * 1537 * where playing at the empty vertices a and d leaves a ko threat to 1538 * make two eyes, whereas b and c don't. 1539 * 1540 * We only do this analysis if the information is requested (when 1541 * called from semeai reading), the eyeshape is worth exactly one 1542 * eye, and there are no marginal points (then generally better to 1543 * play those first). 1544 */ 1545 if (eyefilling_points 1546 && min_eyes(value) == 1 && max_eyes(value) == 1 && num_marginals == 0) { 1547 int k; 1548 int num_empty = 0; 1549 /* Count the number of empty points in the eyespace. */ 1550 for (k = 0; k < eye_size; k++) { 1551 if (!stone[k]) 1552 num_empty++; 1553 } 1554 1555 /* We can't fill in an eyespace with only one liberty. It would 1556 * either be suicide or capture the surrounding stones. 1557 */ 1558 if (num_empty > 1) { 1559 int valid_point[MAXEYE]; 1560 int threat[MAXEYE]; 1561 int min_threat = 2; 1562 /* For each empty point, add a stone and do the graph matching 1563 * again. 1564 */ 1565 for (k = 0; k < eye_size; k++) { 1566 if (!stone[k]) { 1567 struct eye_graph *graph2; 1568 stone[k] = 1; 1569 valid_point[k] = 0; 1570 graph2 = optical_graph_matcher(vpos, marginal, edge, neighbors, stone, 1571 eye_size, num_marginals, map, heye); 1572 if (graph2 && max_eyes(&graph2->value) < 2) { 1573 /* This is an effective eyefilling point. Also check 1574 * whether it leaves a ko threat. 1575 */ 1576 valid_point[k] = 1; 1577 threat[k] = max_eye_threat(&graph2->value); 1578 if (threat[k] < min_threat) 1579 min_threat = threat[k]; 1580 } 1581 stone[k] = 0; 1582 } 1583 } 1584 /* Loop through the points once more to record those which are 1585 * both effective eyefilling points and don't leave a ko threat 1586 * if it can be avoided. 1587 */ 1588 for (k = 0; k < eye_size; k++) { 1589 if (!stone[k] && valid_point[k]) { 1590 int pos = vpos[k]; 1591 if (threat[k] == min_threat) { 1592 eyefilling_points[pos] = 1; 1593 TRACE("Eyefilling point at %1m\n", pos); 1594 } 1595 } 1596 } 1597 } 1598 } 1599 1600 TRACE("eye space at %1m of type %d\n", pos, graph->patnum); 1601 return eye_color; 1602 } 1603 1604 1605 /* Perform the actual matching of the graphs in eyes.db. */ 1606 static struct eye_graph * 1607 optical_graph_matcher(int *vpos, signed char *marginal, signed char *edge, 1608 signed char *neighbors, signed char *stone, int eye_size, 1609 int num_marginals, int *map, 1610 struct half_eye_data *heye) 1611 { 1326 1612 /* We attempt to construct a map from the graph to the eyespace 1327 1613 * preserving the adjacency structure. If this can be done, we've 1328 1614 * identified the eyeshape. 1329 1615 */ 1616 int n; 1330 1617 1331 for ( graph = 0; graphs[graph].vertex != NULL; graph++) {1618 for (n = 0; graphs[n].vertex != NULL; n++) { 1332 1619 int q; 1333 1620 1334 if (graphs[ graph].esize != eye_size1335 || graphs[ graph].msize != num_marginals)1621 if (graphs[n].esize != eye_size 1622 || graphs[n].msize != num_marginals) 1336 1623 continue; 1337 1624 1338 1625 reset_map(eye_size); … … recognize_eye(int pos, int *attack_point, int *defense_point, 1340 1627 first_map(&map[0]); 1341 1628 1342 1629 while (1) { 1343 struct eye_vertex *gv = &graphs[ graph].vertex[q];1630 struct eye_vertex *gv = &graphs[n].vertex[q]; 1344 1631 int mv = map[q]; 1345 1632 int ok = 1; 1346 1633 … … recognize_eye(int pos, int *attack_point, int *defense_point, 1354 1641 ok = 0; 1355 1642 1356 1643 if (ok) { 1357 if ( IS_STONE(board[vpos[mv]])) {1644 if (stone[mv]) { 1358 1645 if (!(gv->flags & CAN_CONTAIN_STONE)) 1359 1646 ok = 0; 1360 1647 } … … recognize_eye(int pos, int *attack_point, int *defense_point, 1411 1698 } 1412 1699 } 1413 1700 1414 if (q == eye_size) { 1415 /* We have found a match! Now sort out the vital moves. */ 1416 *value = graphs[graph].value; 1417 vp->num_attacks = 0; 1418 vp->num_defenses = 0; 1419 1420 if (eye_move_urgency(value) > 0) { 1421 /* Collect all attack and defense points in the pattern. */ 1422 int k; 1423 1424 for (k = 0; k < eye_size; k++) { 1425 struct eye_vertex *ev = &graphs[graph].vertex[k]; 1426 1427 if (ev->flags & EYE_ATTACK_POINT) { 1428 /* Check for a marginal vertex matching a half eye virtual 1429 * marginal. This is the case if a half eye preceeds the 1430 * current vertex in the list. 1431 */ 1432 if (ev->marginal 1433 && map[k] > 0 1434 && vpos[map[k] - 1] != NO_MOVE 1435 && is_halfeye(heye, vpos[map[k] - 1])) { 1436 /* Add all diagonals as vital. */ 1437 int ix; 1438 struct half_eye_data *he = &heye[vpos[map[k] - 1]]; 1439 1440 for (ix = 0; ix < he->num_attacks; ix++) 1441 vp->attacks[vp->num_attacks++] = he->attack_point[ix]; 1442 } 1443 else 1444 vp->attacks[vp->num_attacks++] = vpos[map[k]]; 1445 } 1446 1447 if (ev->flags & EYE_DEFENSE_POINT) { 1448 /* Check for a half eye virtual marginal vertex. */ 1449 if (ev->marginal 1450 && map[k] > 0 1451 && vpos[map[k] - 1] != NO_MOVE 1452 && is_halfeye(heye, vpos[map[k] - 1])) { 1453 /* Add all diagonals as vital. */ 1454 int ix; 1455 struct half_eye_data *he = &heye[vpos[map[k] - 1]]; 1456 1457 for (ix = 0; ix < he->num_defenses; ix++) 1458 vp->defenses[vp->num_defenses++] = he->defense_point[ix]; 1459 } 1460 else 1461 vp->defenses[vp->num_defenses++] = vpos[map[k]]; 1462 } 1463 } 1464 1465 gg_assert(vp->num_attacks > 0 && vp->num_defenses > 0); 1466 1467 /* We now have all vital attack and defense points listed but 1468 * we are also expected to single out of one of each to return 1469 * in *attack_point and *defense_point. Since sometimes those 1470 * are the only vital points considered, we want to choose the 1471 * best ones, in the sense that they minimize the risk for 1472 * error in the eye space analysis. 1473 * 1474 * One example is this position 1475 * 1476 * |..XXXX 1477 * |XXX..X 1478 * |..!O.X 1479 * |OO.O.X 1480 * |.O.!XX 1481 * +------ 1482 * 1483 * where O has an eyespace of the !..! type. The graph 1484 * matching finds that both marginal vertices are vital points 1485 * but here the one at 3-3 fails to defend. (For attack both 1486 * points work but the 3-3 one is still worse since it leaves 1487 * a ko threat.) 1488 * 1489 * In order to differentiate between the marginal points we 1490 * count the number of straight and diagonal neighbors within 1491 * the eye space. In the example above both have one straight 1492 * neighbor each but the edge margin wins because it also has 1493 * a diagonal margin. 1494 */ 1495 1496 best_score = -10; 1497 for (k = 0; k < vp->num_attacks; k++) { 1498 int apos = vp->attacks[k]; 1499 int score = 0; 1500 for (r = 0; r < 8; r++) 1501 if (ON_BOARD(apos + delta[r]) 1502 && eye[apos + delta[r]].color == eye[pos].color 1503 && !eye[apos + delta[r]].marginal) { 1504 score++; 1505 if (r < 4) { 1506 score++; 1507 if (board[apos + delta[r]] != EMPTY) 1508 score++; 1509 } 1510 } 1511 1512 /* If a vital point is not adjacent to any point in the eye 1513 * space, it must be a move to capture or defend a string 1514 * related to a halfeye, e.g. the move * in this position, 1515 * 1516 * ......| 1517 * .XXXX.| 1518 * .X.O..| 1519 * .XO.OO| 1520 * .*XO..| 1521 * ------+ 1522 * 1523 * Playing this is probably a good idea. 1524 */ 1525 if (score == 0) 1526 score += 2; 1527 1528 if (0) 1529 gprintf("attack point %1m score %d\n", apos, score); 1530 1531 if (score > best_score) { 1532 *attack_point = apos; 1533 best_score = score; 1534 } 1535 } 1536 1537 best_score = -10; 1538 for (k = 0; k < vp->num_defenses; k++) { 1539 int dpos = vp->defenses[k]; 1540 int score = 0; 1541 for (r = 0; r < 8; r++) 1542 if (ON_BOARD(dpos + delta[r]) 1543 && eye[dpos + delta[r]].color == eye[pos].color 1544 && !eye[dpos + delta[r]].marginal) { 1545 score++; 1546 if (r < 4) { 1547 score++; 1548 if (board[dpos + delta[r]] != EMPTY) 1549 score++; 1550 } 1551 } 1552 1553 /* If possible, choose a non-sacrificial defense point. 1554 * Compare white T8 and T6 in lazarus:21. 1555 */ 1556 if (safe_move(dpos, eye_color) != WIN) 1557 score -= 5; 1558 1559 /* See comment to the same code for attack points. */ 1560 if (score == 0) 1561 score += 2; 1562 1563 if (0) 1564 gprintf("defense point %1m score %d\n", dpos, score); 1565 1566 if (score > best_score) { 1567 *defense_point = dpos; 1568 best_score = score; 1569 } 1570 } 1571 1572 DEBUG(DEBUG_EYES, " vital points: %1m (attack) %1m (defense)\n", 1573 *attack_point, *defense_point); 1574 DEBUG(DEBUG_EYES, " pattern matched: %d\n", graphs[graph].patnum); 1575 1576 } 1577 TRACE("eye space at %1m of type %d\n", pos, graphs[graph].patnum); 1578 1579 return eye_color; 1580 } 1701 /* Successful match. */ 1702 if (q == eye_size) 1703 return &graphs[n]; 1581 1704 } 1582 1705 1583 return 0;1706 return NULL; 1584 1707 } 1585 1708 1586 1709 -
engine/owl.c
diff --git a/engine/owl.c b/engine/owl.c index f44e3e9..7ba2d4c 100644
a b static void owl_determine_life(struct local_owl_data *owl, 209 209 int does_attack, 210 210 struct owl_move_data *moves, 211 211 struct eyevalue *probable_eyes, 212 int *eyemin, int *eyemax); 212 int *eyemin, int *eyemax, 213 int eyefilling_points[BOARDMAX]); 213 214 static void owl_find_relevant_eyespaces(struct local_owl_data *owl, 214 215 int mw[BOARDMAX], int mz[BOARDMAX]); 215 216 static int owl_estimate_life(struct local_owl_data *owl, … … static int owl_estimate_life(struct local_owl_data *owl, 218 219 const char **live_reason, 219 220 int does_attack, 220 221 struct eyevalue *probable_eyes, 221 int *eyemin, int *eyemax); 222 int *eyemin, int *eyemax, 223 int eyefilling_points[BOARDMAX]); 222 224 static int modify_stupid_eye_vital_point(struct local_owl_data *owl, 223 225 int *vital_point, 224 226 int is_attack_point); … … do_owl_analyze_semeai(int apos, int bpos, 642 644 struct matched_patterns_list_data shape_defensive_patterns; 643 645 struct owl_move_data moves[MAX_SEMEAI_MOVES]; 644 646 struct owl_move_data outside_liberty; 647 struct owl_move_data eyefilling_liberty; 645 648 struct owl_move_data common_liberty; 646 649 struct owl_move_data backfill_outside_liberty; 647 650 struct owl_move_data backfill_common_liberty; 648 651 int safe_outside_liberty_found = 0; 652 int eyefilling_liberty_found = 0; 649 653 int safe_common_liberty_found = 0; 650 654 int riskless_move_found = 0; 651 655 signed char mw[BOARDMAX]; … … do_owl_analyze_semeai(int apos, int bpos, 674 678 struct eyevalue probable_eyes_b; 675 679 struct eyevalue dummy_eyes; 676 680 int I_have_more_eyes; 681 int eyefilling_points[BOARDMAX]; 677 682 678 683 SETUP_TRACE_INFO2("do_owl_analyze_semeai", apos, bpos); 679 684 … … do_owl_analyze_semeai(int apos, int bpos, 717 722 #endif 718 723 719 724 outside_liberty.pos = NO_MOVE; 725 eyefilling_liberty.pos = NO_MOVE; 720 726 common_liberty.pos = NO_MOVE; 721 727 backfill_outside_liberty.pos = NO_MOVE; 722 728 backfill_common_liberty.pos = NO_MOVE; … … do_owl_analyze_semeai(int apos, int bpos, 847 853 848 854 if (owl_estimate_life(owla, owlb, vital_defensive_moves, 849 855 &live_reasona, 0, &probable_eyes_a, 850 &eyemin_a, &eyemax_a ))856 &eyemin_a, &eyemax_a, NULL)) 851 857 I_look_alive = 1; 852 858 else if (stackp > 2 && owl_escape_route(owla) >= 5) { 853 859 live_reasona = "escaped"; 854 860 I_look_alive = 1; 855 861 } 856 862 863 memset(eyefilling_points, 0, sizeof(eyefilling_points)); 857 864 if (owl_estimate_life(owlb, owla, vital_offensive_moves, 858 865 &live_reasonb, 1, &probable_eyes_b, 859 &eyemin_b, &eyemax_b ))866 &eyemin_b, &eyemax_b, eyefilling_points)) 860 867 you_look_alive = 1; 861 868 else if (stackp > 2 && owl_escape_route(owlb) >= 5) { 862 869 live_reasonb = "escaped"; … … do_owl_analyze_semeai(int apos, int bpos, 964 971 include_semeai_worms_in_eyespace = 1; 965 972 if (!owl_estimate_life(owlb, owla, vital_offensive_moves, 966 973 &live_reasonb, 1, &dummy_eyes, 967 &eyemin_b, &eyemax_b ))974 &eyemin_b, &eyemax_b, NULL)) 968 975 semeai_review_owl_moves(vital_offensive_moves, owla, owlb, color, 969 976 &safe_outside_liberty_found, 970 977 &safe_common_liberty_found, … … do_owl_analyze_semeai(int apos, int bpos, 1027 1034 1028 1035 if (board[pos] == EMPTY && !mw[pos]) { 1029 1036 if (liberty_of_goal(pos, owlb)) { 1037 int origin = owlb->my_eye[pos].origin; 1030 1038 if (!liberty_of_goal(pos, owla)) { 1031 /* outside liberty */ 1032 if (safe_move(pos, color) == WIN) { 1033 safe_outside_liberty_found = 1; 1034 outside_liberty.pos = pos; 1035 break; 1039 if (!(owlb->my_eye[origin].color == owlb->color 1040 && max_eyes(&owlb->my_eye[origin].value) > 0)) { 1041 /* outside liberty */ 1042 if (safe_move(pos, color) == WIN) { 1043 safe_outside_liberty_found = 1; 1044 outside_liberty.pos = pos; 1045 break; 1046 } 1047 else if (backfill_outside_liberty.pos == NO_MOVE) 1048 backfill_outside_liberty.pos = find_semeai_backfilling_move(bpos, 1049 pos); 1050 } 1051 else { 1052 /* eye-filling liberty */ 1053 if (eyefilling_points[pos]) { 1054 eyefilling_liberty_found = 1; 1055 eyefilling_liberty.pos = pos; 1056 } 1036 1057 } 1037 else if (backfill_outside_liberty.pos == NO_MOVE)1038 backfill_outside_liberty.pos = find_semeai_backfilling_move(bpos,1039 pos);1040 1058 } 1041 1059 else { 1042 1060 /* common liberty */ … … do_owl_analyze_semeai(int apos, int bpos, 1056 1074 /* Add the best liberty filling move available. We first want to 1057 1075 * play outer liberties, second backfilling moves required before 1058 1076 * filling an outer liberty. If no such moves are available we try 1059 * to fill a mutual liberty or play a corresponding backfilling1060 * move.1077 * to locate an eyefilling move. After that we try to fill a mutual 1078 * liberty or play a corresponding backfilling move. 1061 1079 */ 1062 1080 if (!you_look_alive || we_might_be_inessential) { 1063 1081 if (safe_outside_liberty_found … … do_owl_analyze_semeai(int apos, int bpos, 1081 1099 riskless_move_found = 1; 1082 1100 TRACE("Added %1m %d (6)\n", backfill_outside_liberty.pos, move_value); 1083 1101 } 1102 else if (eyefilling_liberty_found 1103 && eyefilling_liberty.pos != NO_MOVE) { 1104 move_value = semeai_move_value(eyefilling_liberty.pos, 1105 owla, owlb, 30, 1106 critical_semeai_worms); 1107 owl_add_move(moves, eyefilling_liberty.pos, move_value, 1108 "safe eyefilling liberty", SAME_DRAGON_NOT_CONNECTED, 1109 NO_MOVE, 0, NO_MOVE, MAX_SEMEAI_MOVES, NULL); 1110 riskless_move_found = 1; 1111 TRACE("Added %1m %d (5)\n", eyefilling_liberty.pos, move_value); 1112 } 1084 1113 else if (safe_common_liberty_found 1085 1114 && common_liberty.pos != NO_MOVE) { 1086 1115 move_value = semeai_move_value(common_liberty.pos, … … do_owl_analyze_semeai(int apos, int bpos, 1232 1261 include_semeai_worms_in_eyespace = 1; 1233 1262 if (!owl_estimate_life(owla, owlb, vital_defensive_moves, 1234 1263 &live_reasona, 0, &dummy_eyes, 1235 &eyemin_a, &eyemax_a )1264 &eyemin_a, &eyemax_a, NULL) 1236 1265 && eyemax_a < 2) { 1237 1266 include_semeai_worms_in_eyespace = 0; 1238 1267 *resulta = 0; … … do_owl_analyze_semeai(int apos, int bpos, 1319 1348 if (!pass && k == 1) { 1320 1349 if ((best_resulta == WIN && best_resultb == 0 1321 1350 && best_move != NO_MOVE 1322 && best_move == common_liberty.pos1351 && (best_move == common_liberty.pos || best_move == eyefilling_liberty.pos) 1323 1352 && stackp == 0) 1324 1353 || (best_resulta == KO_B && best_resultb == KO_B 1325 1354 && is_ko(best_move, owla->color, NULL))) { … … do_owl_attack(int str, int *move, int *wormid, 2096 2125 2097 2126 /* First see whether there is any chance to kill. */ 2098 2127 if (owl_estimate_life(owl, NULL, vital_moves, &live_reason, 1, 2099 &probable_eyes, &eyemin, &eyemax )) {2128 &probable_eyes, &eyemin, &eyemax, NULL)) { 2100 2129 /* 2101 2130 * We need to check here if there's a worm under atari. If yes, 2102 2131 * locate it and report a (gote) GAIN. … … do_owl_defend(int str, int *move, int *wormid, struct local_owl_data *owl, 2763 2792 /* First see whether we might already be alive. */ 2764 2793 if (escape < MAX_ESCAPE) { 2765 2794 if (owl_estimate_life(owl, NULL, vital_moves, &live_reason, 0, 2766 &probable_eyes, &eyemin, &eyemax)) {2795 &probable_eyes, &eyemin, &eyemax, NULL)) { 2767 2796 SGFTRACE(0, WIN, live_reason); 2768 2797 TRACE("%oVariation %d: ALIVE (%s)\n", 2769 2798 this_variation_number, live_reason); … … owl_threaten_defense(int target, int *defend1, int *defend2) 3089 3118 /* 3090 3119 * This function calls owl_determine_life() to get an eye estimate, 3091 3120 * and matchpat() for vital attack moves, and decides according to 3092 * various policies (depth-depend ant) whether the dragon should thus3121 * various policies (depth-dependent) whether the dragon should thus 3093 3122 * be considered alive. 3094 3123 */ 3095 3124 static int … … owl_estimate_life(struct local_owl_data *owl, 3097 3126 struct local_owl_data *second_owl, 3098 3127 struct owl_move_data vital_moves[MAX_MOVES], 3099 3128 const char **live_reason, int does_attack, 3100 struct eyevalue *probable_eyes, int *eyemin, int *eyemax) 3129 struct eyevalue *probable_eyes, int *eyemin, int *eyemax, 3130 int eyefilling_points[BOARDMAX]) 3101 3131 { 3102 3132 SGFTree *save_sgf_dumptree = sgf_dumptree; 3103 3133 int save_count_variations = count_variations; … … owl_estimate_life(struct local_owl_data *owl, 3108 3138 count_variations = 0; 3109 3139 3110 3140 owl_determine_life(owl, second_owl, does_attack, vital_moves, 3111 probable_eyes, eyemin, eyemax );3141 probable_eyes, eyemin, eyemax, eyefilling_points); 3112 3142 3113 3143 matches_found = 0; 3114 3144 memset(found_matches, 0, sizeof(found_matches)); … … owl_estimate_life(struct local_owl_data *owl, 3204 3234 * 3205 3235 * For use in the semeai code, a second dragon can be provided. Set 3206 3236 * this to NULL when only one dragon is involved. 3237 * 3238 * For use from the semeai code it is also possible to find eyefilling 3239 * points, which adds stones to nakade shapes. Set eyefilling_points 3240 * to NULL if this information is not of interest. 3207 3241 */ 3208 3242 3209 3243 static void … … owl_determine_life(struct local_owl_data *owl, 3211 3245 struct local_owl_data *second_owl, 3212 3246 int does_attack, 3213 3247 struct owl_move_data *moves, 3214 struct eyevalue *probable_eyes, int *eyemin, int *eyemax) 3248 struct eyevalue *probable_eyes, int *eyemin, int *eyemax, 3249 int eyefilling_points[BOARDMAX]) 3215 3250 { 3216 3251 int color = owl->color; 3217 3252 struct eye_data *eye = owl->my_eye; … … owl_determine_life(struct local_owl_data *owl, 3290 3325 const char *reason = ""; 3291 3326 compute_eyes_pessimistic(pos, &eyevalue, &pessimistic_min, 3292 3327 &attack_point, &defense_point, 3293 eye, owl->half_eye );3328 eye, owl->half_eye, eyefilling_points); 3294 3329 3295 3330 /* If the eyespace is more in contact with own stones not in the goal, 3296 3331 * than with ones in the goal, there is a risk that we can be cut off
