pachi_py/pachi/tactics/util.h (42 lines of code) (raw):
#ifndef PACHI_TACTICS_UTIL_H
#define PACHI_TACTICS_UTIL_H
/* Advanced tactical checks non-essential to the board implementation. */
#include "board.h"
#include "debug.h"
struct move_queue;
/* Checks if there are any stones in n-vincinity of coord. */
bool board_stone_radar(struct board *b, coord_t coord, int distance);
/* Measure various distances on the board: */
/* Distance from the edge; on edge returns 0. */
static int coord_edge_distance(coord_t c, struct board *b);
/* Distance of two points in gridcular metric - this metric defines
* circle-like structures on the square grid. */
static int coord_gridcular_distance(coord_t c1, coord_t c2, struct board *b);
/* Construct a "common fate graph" from given coordinate; that is, a weighted
* graph of intersections where edges between all neighbors have weight 1,
* but edges between neighbors of same color have weight 0. Thus, this is
* "stone chain" metric in a sense. */
/* The output are distanes from start stored in given [board_size2()] array;
* intersections further away than maxdist have all distance maxdist+1 set. */
void cfg_distances(struct board *b, coord_t start, int *distances, int maxdist);
/* Compute an extra komi describing the "effective handicap" black receives
* (returns 0 for even game with 7.5 komi). @stone_value is value of single
* handicap stone, 7 is a good default. */
/* This is just an approximation since in reality, handicap seems to be usually
* non-linear. */
floating_t board_effective_handicap(struct board *b, int first_move_value);
/* Decide if the given player wins counting on the board, considering
* that given groups are dead. (To get the list of dead groups, use
* e.g. groups_of_status().) */
bool pass_is_safe(struct board *b, enum stone color, struct move_queue *mq);
/* Returns estimated number of remaining moves for one player until end of game. */
int board_estimated_moves_left(struct board *b);
/* To avoid running out of time, assume we always have at least 30 more moves
* to play if we don't have more precise information from gtp time_left: */
#define MIN_MOVES_LEFT 30
/* Tactical evaluation of move @coord by color @color, given
* simulation end position @b. I.e., a move is tactically good
* if the resulting group stays on board until the game end.
* The value is normalized to [0,1]. */
/* We can also take into account surrounding stones, e.g. to
* encourage taking off external liberties during a semeai. */
static double board_local_value(bool scan_neis, struct board *b, coord_t coord, enum stone color);
static inline int
coord_edge_distance(coord_t c, struct board *b)
{
int x = coord_x(c, b), y = coord_y(c, b);
int dx = x > board_size(b) / 2 ? board_size(b) - 1 - x : x;
int dy = y > board_size(b) / 2 ? board_size(b) - 1 - y : y;
return (dx < dy ? dx : dy) - 1 /* S_OFFBOARD */;
}
static inline int
coord_gridcular_distance(coord_t c1, coord_t c2, struct board *b)
{
int dx = abs(coord_dx(c1, c2, b)), dy = abs(coord_dy(c1, c2, b));
return dx + dy + (dx > dy ? dx : dy);
}
static inline double
board_local_value(bool scan_neis, struct board *b, coord_t coord, enum stone color)
{
if (scan_neis) {
/* Count surrounding friendly stones and our eyes. */
int friends = 0;
foreach_neighbor(b, coord, {
friends += board_at(b, c) == color || board_at(b, c) == S_OFFBOARD || board_is_one_point_eye(b, c, color);
});
return (double) (2 * (board_at(b, coord) == color) + friends) / 6.f;
} else {
return (board_at(b, coord) == color) ? 1.f : 0.f;
}
}
#endif