selfatari_cousin(): Suggest counter-captures
[pachi/peepo.git] / tactics / nakade.c
blob257dc49fdc7a81dff498b4afacf87c57f41fd413
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
5 #define DEBUG
6 #include "board.h"
7 #include "debug.h"
8 #include "move.h"
9 #include "tactics/nakade.h"
12 coord_t
13 nakade_point(struct board *b, coord_t around, enum stone color)
15 /* First, examine the nakade area. For sure, it must be at most
16 * six points. And it must be within color group(s). */
17 #define NAKADE_MAX 6
18 coord_t area[NAKADE_MAX]; int area_n = 0;
20 area[area_n++] = around;
22 for (int i = 0; i < area_n; i++) {
23 foreach_neighbor(b, area[i], {
24 if (board_at(b, c) == stone_other(color))
25 return pass;
26 if (board_at(b, c) == S_NONE) {
27 bool dup = false;
28 for (int j = 0; j < area_n; j++)
29 if (c == area[j]) {
30 dup = true;
31 break;
33 if (dup) continue;
35 if (area_n >= NAKADE_MAX) {
36 /* Too large nakade area. */
37 return pass;
39 area[area_n++] = c;
41 });
44 /* We also collect adjecency information - how many neighbors
45 * we have for each area point, and histogram of this. This helps
46 * us verify the appropriate bulkiness of the shape. */
47 int neighbors[area_n]; int ptbynei[9] = {area_n, 0};
48 memset(neighbors, 0, sizeof(neighbors));
49 for (int i = 0; i < area_n; i++) {
50 for (int j = i + 1; j < area_n; j++)
51 if (coord_is_adjecent(area[i], area[j], b)) {
52 ptbynei[neighbors[i]]--;
53 neighbors[i]++;
54 ptbynei[neighbors[i]]++;
55 ptbynei[neighbors[j]]--;
56 neighbors[j]++;
57 ptbynei[neighbors[j]]++;
61 /* For each given neighbor count, arbitrary one coordinate
62 * featuring that. */
63 coord_t coordbynei[9];
64 for (int i = 0; i < area_n; i++)
65 coordbynei[neighbors[i]] = area[i];
67 switch (area_n) {
68 case 1: return pass;
69 case 2: return pass;
70 case 3: assert(ptbynei[2] == 1);
71 return coordbynei[2]; // middle point
72 case 4: if (ptbynei[3] != 1) return pass; // long line
73 return coordbynei[3]; // tetris four
74 case 5: if (ptbynei[3] == 1 && ptbynei[1] == 1) return coordbynei[3]; // bulky five
75 if (ptbynei[4] == 1) return coordbynei[4]; // cross five
76 return pass; // long line
77 case 6: if (ptbynei[4] == 1 && ptbynei[2] == 3)
78 return coordbynei[4]; // rabbity six
79 return pass; // anything else
80 default: assert(0);