#include "go.h" static int writeColor(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int index, int keep[21][21]) { int x, y; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ keep[x][y] = (ban->color[X_Y_TO_POS(x, y)] == index); } } return 0; } static int writeSame(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int value, int keep[21][21]) { int x, y; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ keep[x][y] = value; } } return 0; } static int writeHist(FILE *fp_out, const int id, const int tesuu, goban_t *ban, const int tesuu_hist, int keep[21][21]) { int x, y; int pos_old = 0; if (tesuu >= tesuu_hist){ pos_old = ban->histInfo[tesuu - tesuu_hist + 1].pos; } for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ keep[x][y] = (X_Y_TO_POS(x, y) == pos_old); } } return 0; } static int writeLiberty(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int num, int keep[21][21]) { int x, y; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ int pos = X_Y_TO_POS(x, y); int breath = ban->renInfo[ban->renID[pos]].breathPoints; breath = MIN(breath, 8); keep[x][y] = (breath == num); } } return 0; } static int writeLibertyAfterMoveSize(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int num, int keep[21][21]) { int x, y, d; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ int pos = X_Y_TO_POS(x, y); int breath = 0; if (ban->color[pos] == SP){ bb_t breathBB[BB_IDX_SIZE]; CLEAR_BB(breathBB); for (d = 1; d < D_MAX; d+= 2){ /* cross */ const int c = pos + D2DELTA[d]; if (ban->color[c] == SP){ ADD_AN_ELEMENT_TO_BB(breathBB, c); } if (ban->color[c] == TBN2COLOR(ban->tbn)){ int renID = ban->renID[c]; renInfo_t *g = &ban->renInfo[renID]; MERGE_BB(breathBB, g->breathBB); } } ERASE_AN_ELEMENT_FROM_BB(breathBB, pos); breath = bb_pop_cnt(breathBB); } breath = MIN(breath, 8); keep[x][y] = (breath == num); } } return 0; } static int writeCaptureSize(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int num, int keep[21][21]) { int x, y, d; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ int pos = X_Y_TO_POS(x, y); int atari = 0; if (ban->color[pos] == SP){ bb_t atariBB[BB_IDX_SIZE]; CLEAR_BB(atariBB); for (d = 1; d < D_MAX; d+= 2){ /* cross */ const int c = pos + D2DELTA[d]; if (ban->color[c] == OB || ban->color[c] == SP){ continue; } int renID = ban->renID[c]; renInfo_t *g = &ban->renInfo[renID]; if (g->breathPoints == 1 && g->color != TBN2COLOR(ban->tbn)){ MERGE_BB(atariBB, g->occupiedBB); } } atari = bb_pop_cnt(atariBB); } atari = MIN(atari, 8); keep[x][y] = (atari == num); } } return 0; } static int writeCapturedSize(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int num, int keep[21][21]) { int x, y, d; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ int pos = X_Y_TO_POS(x, y); int atari = 0, breath = 0; if (ban->color[pos] == SP){ bb_t breathBB[BB_IDX_SIZE], atariBB[BB_IDX_SIZE]; CLEAR_BB(breathBB); CLEAR_BB(atariBB); for (d = 1; d < D_MAX; d+= 2){ /* cross */ const int c = pos + D2DELTA[d]; if (ban->color[c] == SP){ ADD_AN_ELEMENT_TO_BB(breathBB, c); } if (ban->color[c] == TBN2COLOR(ban->tbn)){ int renID = ban->renID[c]; renInfo_t *g = &ban->renInfo[renID]; MERGE_BB(atariBB, g->occupiedBB); MERGE_BB(breathBB, g->breathBB); } } ERASE_AN_ELEMENT_FROM_BB(breathBB, pos); ADD_AN_ELEMENT_TO_BB(atariBB, pos); breath = bb_pop_cnt(breathBB); atari = bb_pop_cnt(atariBB); if (breath != 1){ atari = 0; } } atari = MIN(atari, 8); keep[x][y] = (atari == num); } } return 0; } static int writeLegality(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int keep[21][21]) { int x, y; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ int pos = X_Y_TO_POS(x, y); keep[x][y] = (ban->color[pos] == SP && judge_eff_te(pos, ban)); } } return 0; } // そこに打つと、相手の石をシチョウで取れるかどうかをcheckする static int writeLadderCapture(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int keep[21][21]) { int x, y, d; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ keep[x][y] = 0; int pos = X_Y_TO_POS(x, y); for (d = 1; d < D_MAX; d += 2){ /* cross */ const int c = pos + D2DELTA[d]; if (ban->color[c] == GET_AITE(TBN2COLOR(ban->tbn))){ int renID = ban->renID[c]; renInfo_t *g = &ban->renInfo[renID]; if (g->breathPoints == 2){ int target = get_another_pos(g->breathBB, pos); if (check_kill(pos, target, ban)){ keep[POS_TO_X(pos)][POS_TO_Y(pos)] = 1; } } } } } } return 0; } // そこに打つと、シチョウで取られるかどうかをcheckする static int writeLadderEscape(FILE *fp_out, const int id, const int tesuu, goban_t *ban, int keep[21][21]) { int x, y; for (y = 1; y <= BOARD_EDGE_SIZE ; y++){ for (x = 1; x <= BOARD_EDGE_SIZE; x++){ keep[x][y] = 0; int pos = X_Y_TO_POS(x, y); if (teOK(pos, ban) && !detect_suicide_or_capture(ban, pos)){ if (check_dead(pos, ban)){ keep[x][y] = 1; } } } } return 0; } int get_feature(FILE *fp, const int i, const int tesuu, goban_t *ban) { int j; //Stone colour 3 Player stone / opponent stone / empty if (ban->tbn == TBN_BK){ writeColor(fp, i, tesuu, ban, BK, ban->feature[0]); writeColor(fp, i, tesuu, ban, WH, ban->feature[1]); } else { writeColor(fp, i, tesuu, ban, WH, ban->feature[0]); writeColor(fp, i, tesuu, ban, BK, ban->feature[1]); } writeColor(fp, i, tesuu, ban, SP, ban->feature[2]); //Ones 1 A constant plane filled with 1 writeSame(fp, i, tesuu, ban, 1, ban->feature[3]); //Turns since 8 How many turns since a move was played for (j = 1; j <= 8; j++){ writeHist(fp, i, tesuu, ban, j, ban->feature[3 + j]); } //Liberties 8 Number of liberties (empty adjacent points) for (j = 1; j <= 8; j++){ writeLiberty(fp, i, tesuu, ban, j, ban->feature[11 + j]); } //Capture size 8 How many opponent stones would be captured for (j = 1; j <= 8; j++){ writeCaptureSize(fp, i, tesuu, ban, j, ban->feature[19 + j]); } //Self-atari size 8 How many of own stones would be captured for (j = 1; j <= 8; j++){ writeCapturedSize(fp, i, tesuu, ban, j, ban->feature[27 + j]); } //Liberties after move 8 Number of liberties after this move is played for (j = 1; j <= 8; j++){ writeLibertyAfterMoveSize(fp, i, tesuu, ban, j, ban->feature[35 + j]); } //Ladder capture 1 Whether a move at this point is a successful ladder capture writeLadderCapture(fp, i, tesuu, ban, ban->feature[44]); // 20160616 //Ladder escape 1 Whether a move at this point is a successful ladder escape writeLadderEscape(fp, i, tesuu, ban, ban->feature[45]); //Sensibleness 1 Whether a move is legal and does not fill its own eyes writeLegality(fp, i, tesuu, ban, ban->feature[46]); //Zeros 1 A constant plane filled with 0 writeSame(fp, i, tesuu, ban, 0, ban->feature[47]); return 0; }