int opponent_feature(int l, int d) { const int o[] = { 0, 2, 1 }; int f = o[l % 3]; if (d > 1) f += opponent_feature(l / 3, d - 1) * 3; return f; }
/** * @brief Opponent feature. * * Compute a feature from the opponent point of view. * @param l feature. * @param d feature size. * @return opponent feature. */ static int opponent_feature(int l, int d) { static const int o[] = {1, 0, 2}; int f = o[l % 3]; if (d > 1) f += opponent_feature(l / 3, d - 1) * 3; return f; }
BOOL OpenEvalData(char *filename) { int stage = 0; int i; UCHAR *buf; char *line, *ctr = NULL; float *p_table, *p_table_op; INT64 evalSize; buf = DecodeEvalData(&evalSize, filename); if (buf == NULL) { return FALSE; } line = strtok_s((char *)buf, "\n", &ctr); while (stage < 60) { /* horizon_ver1 */ p_table = hori_ver1_data[0][stage]; p_table_op = hori_ver1_data[1][stage]; for (i = 0; i < 6561; i++) { p_table[i] = (float)atof(line); /* opponent */ p_table_op[opponent_feature(i, 8)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* horizon_ver2 */ p_table = hori_ver2_data[0][stage]; p_table_op = hori_ver2_data[1][stage]; for (i = 0; i < 6561; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 8)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* horizon_ver3 */ p_table = hori_ver3_data[0][stage]; p_table_op = hori_ver3_data[1][stage]; for (i = 0; i < 6561; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 8)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* diagram_ver1 */ p_table = dia_ver1_data[0][stage]; p_table_op = dia_ver1_data[1][stage]; for (i = 0; i < 6561; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 8)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* diagram_ver2 */ p_table = dia_ver2_data[0][stage]; p_table_op = dia_ver2_data[1][stage]; for (i = 0; i < 2187; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 7)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* diagram_ver3 */ p_table = dia_ver3_data[0][stage]; p_table_op = dia_ver3_data[1][stage]; for (i = 0; i < 729; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 6)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* diagram_ver4 */ p_table = dia_ver4_data[0][stage]; p_table_op = dia_ver4_data[1][stage]; for (i = 0; i < 243; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 5)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* edge */ p_table = edge_data[0][stage]; p_table_op = edge_data[1][stage]; for (i = 0; i < 59049; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 10)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* corner5 + 2X */ p_table = corner5_2_data[0][stage]; p_table_op = corner5_2_data[1][stage]; for (i = 0; i < 59049; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 10)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* corner3_3 */ p_table = corner3_3_data[0][stage]; p_table_op = corner3_3_data[1][stage]; for (i = 0; i < 19683; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 9)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* triangle */ p_table = triangle_data[0][stage]; p_table_op = triangle_data[1][stage]; for (i = 0; i < 59049; i++) { p_table[i] = (float)atof(line); p_table_op[opponent_feature(i, 10)] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } #if 0 /* mobility */ p_table = mobility_data[0][stage]; p_table_op = mobility_data[1][stage]; for (i = 0; i < MOBILITY_NUM; i++) { p_table[i] = (float)atof(line); p_table_op[i] = -p_table[i]; line = strtok_s(NULL, "\n", &ctr); } #endif /* parity */ p_table = parity_data[0][stage]; p_table_op = parity_data[1][stage]; for (i = 0; i < PARITY_NUM; i++) { p_table[i] = (float)atof(line); p_table_op[i] = p_table[i]; line = strtok_s(NULL, "\n", &ctr); } /* constant */ //constant_data[0][stage] = (float)atof(line); //line = strtok_s(NULL, "\n", &ctr); stage++; } free(buf); return TRUE; }
/** * @brief Load the evaluation function features' weights. * * The weights are stored in a global variable, because, once loaded from the * file, they stay constant during the lifetime of the program. As loading * the weights is time & resource consuming, a counter variable check that * the weights are effectively loaded only once. * * @param file File name of the evaluation function data. */ void eval_open(const char* file) { unsigned int edax_header, eval_header; unsigned int version, release, build; double date; const int n_w = 114364; int *T; int ply, i, j, k, l, n; int r; int offset; FILE* f; short *w = NULL; if (EVAL_LOADED++) return; // the following is assumed: // -(unsigned) int are 32 bits if (sizeof (int) != 4) fatal_error("int size is not compatible with Edax.\n"); // -(unsigned) short are 16 bits if (sizeof (short) != 2) fatal_error("short size is not compatible with Edax.\n"); // create unpacking tables T = (int*) malloc(59049 * sizeof (*T)); if (T == NULL) fatal_error("Cannot allocate temporary table variable.\n"); for (l = n = 0; l < 6561; l++){ /* 8 squares : 6561 -> 3321 */ k=((l / 2187) % 3) + ((l / 729) % 3) * 3 + ((l / 243) % 3) * 9 + ((l / 81) % 3) * 27 + ((l / 27) % 3) * 81 + ((l / 9) % 3) * 243 + ((l / 3) % 3) * 729 + (l % 3) * 2187; if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_S8[0][l] = T[l]; EVAL_S8[1][opponent_feature(l, 8)] = T[l]; } for (l = n = 0; l < 2187; l++){ /* 7 squares : 2187 -> 1134 */ k=((l / 729) % 3) + ((l / 243) % 3) * 3 + ((l / 81) % 3) * 9 + ((l / 27) % 3) * 27 + ((l / 9) % 3) * 81 + ((l / 3) % 3) * 243 + (l % 3) * 729; if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_S7[0][l] = T[l]; EVAL_S7[1][opponent_feature(l, 7)] = T[l]; } for (l = n = 0; l < 729; l++){ /* 6 squares : 729 -> 378 */ k=((l / 243) % 3) + ((l / 81) % 3) * 3 + ((l / 27) % 3) * 9 + ((l / 9) % 3) * 27 + ((l / 3) % 3) * 81 + (l % 3) * 243; if (k < l) T[l]=T[k]; else T[l] = n++; EVAL_S6[0][l] = T[l]; EVAL_S6[1][opponent_feature(l, 6)] = T[l]; } for (l = n = 0; l < 243; l++) { /* 5 squares : 243 -> 135 */ k=((l / 81) % 3)+((l / 27) % 3) * 3 + ((l / 9) % 3) * 9+ ((l / 3) % 3) * 27 + (l % 3) * 81; if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_S5[0][l] = T[l]; EVAL_S5[1][opponent_feature(l, 5)] = T[l]; } for (l = n = 0; l < 81; l++) { /* 4 squares : 81 -> 45 */ k=((l / 27) % 3) + ((l / 9) % 3) * 3 + ((l / 3) % 3) * 9 + (l % 3) * 27; if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_S4[0][l] = T[l]; EVAL_S4[1][opponent_feature(l, 4)] = T[l]; } for (l = n = 0;l < 19683; l++) { /* 9 corner squares : 19683 -> 10206 */ k = ((l / 6561) % 3) * 6561 + ((l / 729) % 3) * 2187 + ((l / 2187) % 3) * 729 + ((l / 243) % 3) * 243 +((l / 27) % 3) * 81 + ((l / 81) % 3) * 27 + ((l / 3) % 3) * 9 + ((l / 9) % 3) * 3 + (l % 3); if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_C9[0][l] = T[l]; EVAL_C9[1][opponent_feature(l, 9)] = T[l]; } for (l = n = 0; l < 59049; l++) { /* 10 squares (edge +X ) : 59049 -> 29646 */ k=((l / 19683) % 3) + ((l / 6561) % 3) * 3+((l / 2187) % 3) * 9 + ((l / 729) % 3) * 27 + ((l / 243) % 3) * 81 + ((l / 81) % 3) * 243 + ((l / 27) % 3) * 729 + ((l / 9) % 3) * 2187 + ((l / 3) % 3) * 6561 + (l % 3) * 19683; if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_S10[0][l] = T[l]; EVAL_S10[1][opponent_feature(l, 10)] = T[l]; } for (l = n = 0; l < 59049; l++) { /* 10 squares (angle + X) : 59049 -> 29889 */ k=((l / 19683) % 3) + ((l / 6561) % 3) * 3+((l / 2187) % 3) * 9 + ((l / 729) % 3) * 27 + ((l / 243) % 3) * 243 + ((l / 81) % 3) * 81 + ((l / 27) % 3) * 729 + ((l / 9) % 3) * 2187 + ((l / 3) % 3) * 6561 + (l % 3) * 19683; if (k < l) T[l] = T[k]; else T[l] = n++; EVAL_C10[0][l] = T[l]; EVAL_C10[1][opponent_feature(l, 10)] = T[l]; } free(T); // allocation EVAL_WEIGHT = (short***) malloc(2 * sizeof (*EVAL_WEIGHT)); if (EVAL_WEIGHT == NULL) fatal_error("Cannot evaluation weights.\n"); EVAL_WEIGHT[0] = (short**) malloc(2 * EVAL_N_PLY * sizeof (**EVAL_WEIGHT)); if (EVAL_WEIGHT[0] == NULL) fatal_error("Cannot evaluation weights.\n"); EVAL_WEIGHT[1] = EVAL_WEIGHT[0] + EVAL_N_PLY; EVAL_WEIGHT[0][0] = (short*) malloc(2 * EVAL_N_PLY * EVAL_N_WEIGHT * sizeof (***EVAL_WEIGHT)); if (EVAL_WEIGHT[0][0] == NULL) fatal_error("Cannot evaluation weights.\n"); EVAL_WEIGHT[1][0] = EVAL_WEIGHT[0][0] + EVAL_N_PLY * EVAL_N_WEIGHT; for (ply = 1; ply < EVAL_N_PLY; ply++) { EVAL_WEIGHT[0][ply] = EVAL_WEIGHT[0][ply - 1] + EVAL_N_WEIGHT; EVAL_WEIGHT[1][ply] = EVAL_WEIGHT[1][ply - 1] + EVAL_N_WEIGHT; } // data reading w = (short*) malloc(n_w * sizeof (*w)); // a temporary to read packed weights f = fopen(file, "rb"); if (f == NULL) { fprintf(stderr, "Cannot open %s", file); exit(EXIT_FAILURE); } // File header r = fread(&edax_header, sizeof (int), 1, f); r += fread(&eval_header, sizeof (int), 1, f); if (r != 2 || (!(edax_header == EDAX || eval_header == EVAL) && !(edax_header == XADE || eval_header == LAVE))) fatal_error("%s is not an Edax evaluation file\n", file); r = fread(&version, sizeof (int), 1, f); r += fread(&release, sizeof (int), 1, f); r += fread(&build, sizeof (int), 1, f); r += fread(&date, sizeof (double), 1, f); if (r != 4) fatal_error("Cannot read version info from %s\n", file); if (edax_header == XADE) { version = bswap_int(version); release = bswap_int(release); build = bswap_int(build); } // Weights : read & unpacked them for (ply = 0; ply < EVAL_N_PLY; ply++) { r = fread(w, sizeof (short), n_w, f); if (r != n_w) fatal_error("Cannot read evaluation weight from %s\n", file); if (edax_header == XADE) for (i = 0; i < n_w; ++i) w[i] = bswap_short(w[i]); i = j = offset = 0; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_C9[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_C9[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_C10[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_C10[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S10[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S10[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S10[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S10[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S8[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S8[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S8[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S8[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S8[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S8[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S8[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S8[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S7[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S7[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S6[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S6[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S5[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S5[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; for (k = 0; k < EVAL_SIZE[i]; k++,j++) { EVAL_WEIGHT[0][ply][j] = w[EVAL_S4[0][k] + offset]; EVAL_WEIGHT[1][ply][j] = w[EVAL_S4[1][k] + offset]; } offset += EVAL_PACKED_SIZE[i]; i++; EVAL_WEIGHT[0][ply][j] = w[offset]; EVAL_WEIGHT[1][ply][j] = w[offset]; } fclose(f); free(w); /*if (version == 3 && release == 2 && build == 5)*/ { EVAL_A = -0.10026799, EVAL_B = 0.31027733, EVAL_C = -0.57772603; EVAL_a = 0.07585621, EVAL_b = 1.16492647, EVAL_c = 5.4171698; } info("<Evaluation function weights version %u.%u.%u loaded>\n", version, release, build); }