Moggy: Support independent (non-zero) debug level setting
[pachi.git] / playout.c
blob452a92c5199086a51d9e49cbe748d3908a682366
1 #define DEBUG
2 #include <assert.h>
3 #include <math.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
8 #include "board.h"
9 #include "debug.h"
10 #include "engine.h"
11 #include "move.h"
12 #include "ownermap.h"
13 #include "playout.h"
15 #define PLDEBUGL(n) DEBUGL_(policy->debug_level, n)
18 int
19 play_random_game(struct playout_setup *setup,
20 struct board *b, enum stone starting_color,
21 struct playout_amafmap *amafmap,
22 struct board_ownermap *ownermap,
23 struct playout_policy *policy)
25 assert(setup && policy);
27 int gamelen = setup->gamelen - b->moves;
28 if (gamelen < 10)
29 gamelen = 10;
31 if (policy->setboard)
32 policy->setboard(policy, b);
34 enum stone color = starting_color;
36 int passes = is_pass(b->last_move.coord) && b->moves > 0;
38 while (gamelen-- && passes < 2) {
39 coord_t coord;
40 coord = policy->choose(policy, b, color);
42 if (is_pass(coord)) {
43 play_random:
44 /* Defer to uniformly random move choice. */
45 /* This must never happen if the policy is tracking
46 * internal board state, obviously. */
47 assert(!policy->setboard);
48 board_play_random(b, color, &coord, (ppr_permit) policy->permit, policy);
50 } else {
51 struct move m;
52 m.coord = coord; m.color = color;
53 if (board_play(b, &m) < 0) {
54 if (PLDEBUGL(4)) {
55 fprintf(stderr, "Pre-picked move %d,%d is ILLEGAL:\n",
56 coord_x(coord, b), coord_y(coord, b));
57 board_print(b, stderr);
59 goto play_random;
63 #if 0
64 /* For UCT, superko test here is downright harmful since
65 * in superko-likely situation we throw away literally
66 * 95% of our playouts; UCT will deal with this fine by
67 * itself. */
68 if (unlikely(b->superko_violation)) {
69 /* We ignore superko violations that are suicides. These
70 * are common only at the end of the game and are
71 * rather harmless. (They will not go through as a root
72 * move anyway.) */
73 if (group_at(b, coord)) {
74 if (DEBUGL(3)) {
75 fprintf(stderr, "Superko fun at %d,%d in\n", coord_x(coord, b), coord_y(coord, b));
76 if (DEBUGL(4))
77 board_print(b, stderr);
79 return 0;
80 } else {
81 if (DEBUGL(6)) {
82 fprintf(stderr, "Ignoring superko at %d,%d in\n", coord_x(coord, b), coord_y(coord, b));
83 board_print(b, stderr);
85 b->superko_violation = false;
88 #endif
90 if (PLDEBUGL(7)) {
91 fprintf(stderr, "%s %s\n", stone2str(color), coord2sstr(coord, b));
92 if (PLDEBUGL(8))
93 board_print(b, stderr);
96 if (unlikely(is_pass(coord))) {
97 passes++;
98 } else {
99 /* We don't care about nakade counters, since we want
100 * to avoid taking pre-nakade moves into account only
101 * if they happenned in the tree before nakade nodes;
102 * but this is always out of the tree. */
103 if (amafmap) {
104 if (amafmap->map[coord] == S_NONE || amafmap->map[coord] == color)
105 amafmap->map[coord] = color;
106 else if (amafmap->record_nakade)
107 amaf_op(amafmap->map[coord], +);
108 amafmap->game[amafmap->gamelen].coord = coord;
109 amafmap->game[amafmap->gamelen].color = color;
110 amafmap->gamelen++;
111 assert(amafmap->gamelen < sizeof(amafmap->game) / sizeof(amafmap->game[0]));
114 passes = 0;
117 if (setup->mercymin && abs(b->captures[S_BLACK] - b->captures[S_WHITE]) > setup->mercymin)
118 break;
120 color = stone_other(color);
123 float score = board_fast_score(b);
124 int result = (starting_color == S_WHITE ? score * 2 : - (score * 2));
126 if (DEBUGL(6)) {
127 fprintf(stderr, "Random playout result: %d (W %f)\n", result, score);
128 if (DEBUGL(7))
129 board_print(b, stderr);
132 if (ownermap)
133 board_ownermap_fill(ownermap, b);
135 if (b->ps)
136 free(b->ps);
138 return result;