tree_init: exit cleanly instead of core dump when running out of memory.
[pachi.git] / playout.c
blobe1578f70b6bc00e9356647a4384e276755ae5aa9
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"
16 int
17 play_random_game(struct playout_setup *setup,
18 struct board *b, enum stone starting_color,
19 struct playout_amafmap *amafmap,
20 struct board_ownermap *ownermap,
21 struct playout_policy *policy)
23 assert(setup && policy);
25 int gamelen = setup->gamelen - b->moves;
26 if (gamelen < 10)
27 gamelen = 10;
29 if (policy->setboard)
30 policy->setboard(policy, b);
32 enum stone color = starting_color;
34 int passes = is_pass(b->last_move.coord) && b->moves > 0;
36 while (gamelen-- && passes < 2) {
37 coord_t coord;
38 coord = policy->choose(policy, b, color);
40 if (is_pass(coord)) {
41 play_random:
42 /* Defer to uniformly random move choice. */
43 /* This must never happen if the policy is tracking
44 * internal board state, obviously. */
45 assert(!policy->setboard);
46 board_play_random(b, color, &coord, (ppr_permit) policy->permit, policy);
48 } else {
49 struct move m;
50 m.coord = coord; m.color = color;
51 if (board_play(b, &m) < 0) {
52 if (DEBUGL(4)) {
53 fprintf(stderr, "Pre-picked move %d,%d is ILLEGAL:\n",
54 coord_x(coord, b), coord_y(coord, b));
55 board_print(b, stderr);
57 goto play_random;
61 #if 0
62 /* For UCT, superko test here is downright harmful since
63 * in superko-likely situation we throw away literally
64 * 95% of our playouts; UCT will deal with this fine by
65 * itself. */
66 if (unlikely(b->superko_violation)) {
67 /* We ignore superko violations that are suicides. These
68 * are common only at the end of the game and are
69 * rather harmless. (They will not go through as a root
70 * move anyway.) */
71 if (group_at(b, coord)) {
72 if (DEBUGL(3)) {
73 fprintf(stderr, "Superko fun at %d,%d in\n", coord_x(coord, b), coord_y(coord, b));
74 if (DEBUGL(4))
75 board_print(b, stderr);
77 return 0;
78 } else {
79 if (DEBUGL(6)) {
80 fprintf(stderr, "Ignoring superko at %d,%d in\n", coord_x(coord, b), coord_y(coord, b));
81 board_print(b, stderr);
83 b->superko_violation = false;
86 #endif
88 if (DEBUGL(7)) {
89 fprintf(stderr, "%s %s\n", stone2str(color), coord2sstr(coord, b));
90 if (DEBUGL(8))
91 board_print(b, stderr);
94 if (unlikely(is_pass(coord))) {
95 passes++;
96 } else {
97 /* We don't care about nakade counters, since we want
98 * to avoid taking pre-nakade moves into account only
99 * if they happenned in the tree before nakade nodes;
100 * but this is always out of the tree. */
101 if (amafmap) {
102 if (amafmap->map[coord] == S_NONE || amafmap->map[coord] == color)
103 amafmap->map[coord] = color;
104 else if (amafmap->record_nakade)
105 amaf_op(amafmap->map[coord], +);
106 amafmap->game[amafmap->gamelen].coord = coord;
107 amafmap->game[amafmap->gamelen].color = color;
108 amafmap->gamelen++;
109 assert(amafmap->gamelen < sizeof(amafmap->game) / sizeof(amafmap->game[0]));
112 passes = 0;
115 if (setup->mercymin && abs(b->captures[S_BLACK] - b->captures[S_WHITE]) > setup->mercymin)
116 break;
118 color = stone_other(color);
121 float score = board_fast_score(b);
122 int result = (starting_color == S_WHITE ? score * 2 : - (score * 2));
124 if (DEBUGL(6)) {
125 fprintf(stderr, "Random playout result: %d (W %f)\n", result, score);
126 if (DEBUGL(7))
127 board_print(b, stderr);
130 if (ownermap)
131 board_ownermap_fill(ownermap, b);
133 if (b->ps)
134 free(b->ps);
136 return result;