void vgprintf(FILE *outputfile, const char *fmt, va_list ap) { if (fmt[0] == '%' && fmt[1] == 'o') fmt += 2; /* cancel indent */ else if (stackp > 0) fprintf(outputfile, "%.*s", stackp*2, " "); for (; *fmt; ++fmt) { if (*fmt == '%') { switch (*++fmt) { case 'c': { /* rules of promotion => passed as int, not char */ int c = va_arg(ap, int); putc(c, outputfile); break; } case 'd': { int d = va_arg(ap, int); fprintf(outputfile, "%d", d); break; } case 'x': { unsigned int d = va_arg(ap, unsigned int); fprintf(outputfile, "%x", d); break; } case 'f': { double f = va_arg(ap, double); /* passed as double, not float */ fprintf(outputfile, "%.2f", f); break; } case 's': { char *s = va_arg(ap, char *); fputs(s, outputfile); break; } case '2': fmt++; if (*fmt != 'm' && *fmt != 'M') { fprintf(outputfile, "\n\nUnknown format string '2%c'\n", *fmt); break; } /* else fall through - 2 modifier on %m is default. */ case 'm': case 'M': { char movename[4]; int m = va_arg(ap, int); int n = va_arg(ap, int); if (m == -1 && n == -1) fputs("PASS", outputfile); else if (!ON_BOARD2(m, n)) fprintf(outputfile, "[%d,%d]", m, n); else { /* Generate the move name. */ if (n < 8) movename[0] = n + 65; else movename[0] = n + 66; if (*fmt == 'm') sprintf(movename+1, "%d", board_size - m); else sprintf(movename+1, "%-2d", board_size - m); fputs(movename, outputfile); } break; } case '1': fmt++; if (*fmt != 'm' && *fmt != 'M') { fprintf(outputfile, "\n\nUnknown format string '1%c'\n", *fmt); break; } else { char movename[4]; int pos = va_arg(ap, int); int m = I(pos); int n = J(pos); if (pos == NO_MOVE) fputs("PASS", outputfile); else if (!ON_BOARD1(pos)) fprintf(outputfile, "[%d]", pos); else { /* Generate the move name. */ if (n < 8) movename[0] = n + 65; else movename[0] = n + 66; if (*fmt == 'm') sprintf(movename + 1, "%d", board_size - m); else sprintf(movename + 1, "%-2d", board_size - m); fputs(movename, outputfile); } break; } case 'H': { unsigned long h = va_arg(ap, unsigned long); fprintf(outputfile, "%lx", h); break; } case 'C': { int color = va_arg(ap, int); fputs(color_to_string(color), outputfile); break; } default: fprintf(outputfile, "\n\nUnknown format character '%c'\n", *fmt); break; } } else putc(*fmt, outputfile); }
static void compute_active_owl_area(struct persistent_cache_entry *entry, const char goal[BOARDMAX], int goal_color) { int k, r; int pos; int other = OTHER_COLOR(goal_color); signed char active[BOARDMAX]; /* We let the active area be the goal + * distance four expansion through empty intersections and own stones + * adjacent opponent strings + * liberties and neighbors of adjacent opponent strings with less than * five liberties + * liberties and neighbors of low liberty neighbors of adjacent opponent * strings with less than five liberties. */ for (pos = BOARDMIN; pos < BOARDMAX; pos++) if (ON_BOARD(pos)) active[pos] = (goal[pos] != 0); /* Also add critical moves to the active area. */ if (ON_BOARD1(entry->move)) active[entry->move] = 1; if (ON_BOARD1(entry->move2)) active[entry->move2] = 1; /* Distance four expansion through empty intersections and own stones. */ for (k = 1; k < 5; k++) { for (pos = BOARDMIN; pos < BOARDMAX; pos++) { if (!ON_BOARD(pos) || board[pos] == other || active[pos] > 0) continue; if ((ON_BOARD(SOUTH(pos)) && active[SOUTH(pos)] == k) || (ON_BOARD(WEST(pos)) && active[WEST(pos)] == k) || (ON_BOARD(NORTH(pos)) && active[NORTH(pos)] == k) || (ON_BOARD(EAST(pos)) && active[EAST(pos)] == k)) { if (board[pos] == EMPTY) active[pos] = k + 1; else signed_mark_string(pos, active, (signed char) (k + 1)); } } } /* Adjacent opponent strings. */ for (pos = BOARDMIN; pos < BOARDMAX; pos++) { if (board[pos] != other || active[pos] != 0) continue; for (r = 0; r < 4; r++) { int pos2 = pos + delta[r]; if (ON_BOARD(pos2) && board[pos2] != other && active[pos2] != 0) { signed_mark_string(pos, active, 1); break; } } } /* Liberties of adjacent opponent strings with less than five liberties + * liberties of low liberty neighbors of adjacent opponent strings * with less than five liberties. */ for (pos = BOARDMIN; pos < BOARDMAX; pos++) { if (board[pos] == other && active[pos] > 0 && countlib(pos) < 5) { int libs[4]; int liberties = findlib(pos, 4, libs); int adjs[MAXCHAIN]; int adj; for (r = 0; r < liberties; r++) active[libs[r]] = 1; /* Also add liberties of neighbor strings if these are three * or less. */ adj = chainlinks(pos, adjs); for (r = 0; r < adj; r++) { signed_mark_string(adjs[r], active, -1); if (countlib(adjs[r]) <= 3) { int s; int adjs2[MAXCHAIN]; int adj2; liberties = findlib(adjs[r], 3, libs); for (s = 0; s < liberties; s++) active[libs[s]] = 1; adj2 = chainlinks(pos, adjs2); for (s = 0; s < adj2; s++) signed_mark_string(adjs2[s], active, -1); } } } } for (pos = BOARDMIN; pos < BOARDMAX; pos++) { int value = board[pos]; if (!ON_BOARD(pos)) continue; if (!active[pos]) value = GRAY; else if (IS_STONE(board[pos]) && countlib(pos) > 4 && active[pos] > 0) value |= HIGH_LIBERTY_BIT; entry->board[pos] = value; } }
static void showchar(int i, int j, int empty, int xo) { struct dragon_data *d; /* dragon data at (i, j) */ struct dragon_data2 *d2; int x; ASSERT_ON_BOARD2(i, j); x = BOARD(i, j); d = &(dragon[POS(i, j)]); d2 = &(dragon2[d->id]); if (x == EMPTY) { if (xo != 2) fprintf(stderr, " %c", empty); else { int empty_color; char empty_char; if (black_eye[POS(i, j)].color == BLACK) { if (white_eye[POS(i, j)].color == WHITE) empty_color = domain_colors[3]; else empty_color = domain_colors[1]; if (black_eye[POS(i, j)].marginal) empty_char = '!'; else empty_char = 'x'; } else if (white_eye[POS(i, j)].color == WHITE) { empty_color = domain_colors[2]; if (white_eye[POS(i, j)].marginal) empty_char = '!'; else empty_char = 'o'; } else { empty_color = domain_colors[0]; empty_char = '.'; } write_color_char(empty_color, empty_char); } } else { int w; if (xo == 0 || ! ON_BOARD1(d->origin)) { fprintf(stderr, " %c", BOARD(i, j) == BLACK ? 'X' : 'O'); return; } /* Figure out ascii character for this dragon. This is the * dragon number allocated to the origin of this worm. */ w = dragon_num[d->origin]; if (!w) { /* Not yet allocated - allocate next one. */ /* Count upwards for black, downwards for white to reduce confusion. */ if (BOARD(i, j) == BLACK) w = dragon_num[d->origin] = next_black++; else w = dragon_num[d->origin] = next_white--; } w = w%26 + (BOARD(i, j) == BLACK ? 'A' : 'a'); /* Now draw it. */ if (xo == 1) write_color_char(colors[BOARD(i, j)][d->crude_status], w); else if (xo == 2) { if (BOARD(i, j) == BLACK) write_color_char(domain_colors[1], 'X'); else write_color_char(domain_colors[2], 'O'); } else if (xo == 3) write_color_char(colors[BOARD(i, j)][d2->owl_status], w); else if (xo == 4) write_color_char(colors[BOARD(i, j)][d->status], w); } }
void store_persistent_owl_cache(int routine, int apos, int bpos, int cpos, int result, int move, int move2, int certain, int tactical_nodes, char goal[BOARDMAX], int goal_color) { char active[BOARDMAX]; int pos; int k; int r; int other = OTHER_COLOR(goal_color); gg_assert(stackp == 0); /* If cache is full, first try to purge it. */ if (persistent_owl_cache_size == MAX_OWL_CACHE_SIZE) purge_persistent_owl_cache(); /* FIXME: Kick out oldest or least expensive entry instead of giving up. */ if (persistent_owl_cache_size == MAX_OWL_CACHE_SIZE) { TRACE_OWL_PERFORMANCE("Persistent owl cache full.\n"); return; } persistent_owl_cache[persistent_owl_cache_size].boardsize = board_size; persistent_owl_cache[persistent_owl_cache_size].routine = routine; persistent_owl_cache[persistent_owl_cache_size].apos = apos; persistent_owl_cache[persistent_owl_cache_size].bpos = bpos; persistent_owl_cache[persistent_owl_cache_size].cpos = cpos; persistent_owl_cache[persistent_owl_cache_size].result = result; persistent_owl_cache[persistent_owl_cache_size].result_certain = certain; persistent_owl_cache[persistent_owl_cache_size].move = move; persistent_owl_cache[persistent_owl_cache_size].move2 = move2; persistent_owl_cache[persistent_owl_cache_size].tactical_nodes = tactical_nodes; persistent_owl_cache[persistent_owl_cache_size].movenum = movenum; /* Remains to set the board. We let the active area be * the goal + * distance four expansion through empty intersections and own stones + * adjacent opponent strings + * liberties of adjacent opponent strings with less than five liberties + * liberties of low liberty neighbors of adjacent opponent strings * with less than five liberties. */ for (pos = BOARDMIN; pos < BOARDMAX; pos++) if (ON_BOARD(pos)) active[pos] = (goal[pos] != 0); /* Also add critical moves to the active area. */ if (ON_BOARD1(move)) active[move] = 1; if (ON_BOARD1(move2)) active[move2] = 1; /* Distance four expansion through empty intersections and own stones. */ for (k = 1; k < 5; k++) { for (pos = BOARDMIN; pos < BOARDMAX; pos++){ if (!ON_BOARD(pos) || board[pos] == other || active[pos] != 0) continue; if ((ON_BOARD(SOUTH(pos)) && active[SOUTH(pos)] == k) || (ON_BOARD(WEST(pos)) && active[WEST(pos)] == k) || (ON_BOARD(NORTH(pos)) && active[NORTH(pos)] == k) || (ON_BOARD(EAST(pos)) && active[EAST(pos)] == k)) { if (board[pos] == EMPTY) active[pos] = k + 1; else mark_string(pos, active, (char) (k + 1)); } } } /* Adjacent opponent strings. */ for (pos = BOARDMIN; pos < BOARDMAX; pos++) { if (board[pos] != other || active[pos] != 0) continue; for (r = 0; r < 4; r++) { int pos2 = pos + delta[r]; if (ON_BOARD(pos2) && board[pos2] != other && active[pos2] != 0) { mark_string(pos, active, (char) 1); break; } } } /* Liberties of adjacent opponent strings with less than five liberties + * liberties of low liberty neighbors of adjacent opponent strings * with less than five liberties. */ for (pos = BOARDMIN; pos < BOARDMAX; pos++) { if (board[pos] == other && active[pos] != 0 && countlib(pos) < 5) { int libs[4]; int liberties = findlib(pos, 4, libs); int adjs[MAXCHAIN]; int adj; for (r = 0; r < liberties; r++) active[libs[r]] = 1; /* Also add liberties of neighbor strings if these are three * or less. */ adj = chainlinks(pos, adjs); for (r = 0; r < adj; r++) { if (countlib(adjs[r]) <= 3) { int s; liberties = findlib(adjs[r], 3, libs); for (s = 0; s < liberties; s++) active[libs[s]] = 1; } } } } for (pos = BOARDMIN; pos < BOARDMAX; pos++) { int value = board[pos]; if (!ON_BOARD(pos)) continue; if (!active[pos]) value = GRAY; else if (IS_STONE(board[pos]) && countlib(pos) > 4) value |= HIGH_LIBERTY_BIT; persistent_owl_cache[persistent_owl_cache_size].board[pos] = value; } if (debug & DEBUG_OWL_PERSISTENT_CACHE) { gprintf("%o Stored result in cache (entry %d):\n", persistent_owl_cache_size); print_persistent_owl_cache_entry(persistent_owl_cache_size); } persistent_owl_cache_size++; }