pachi_py/pachi/replay/replay.c (90 lines of code) (raw):
#include <stdio.h>
#include <stdlib.h>
#include "board.h"
#include "debug.h"
#include "engine.h"
#include "joseki/base.h"
#include "move.h"
#include "playout.h"
#include "playout/light.h"
#include "playout/moggy.h"
#include "replay/replay.h"
/* Internal engine state. */
struct replay {
int debug_level;
struct playout_policy *playout;
};
static coord_t *
replay_genmove(struct engine *e, struct board *b, struct time_info *ti, enum stone color, bool pass_all_alive)
{
struct replay *r = e->data;
struct playout_setup s; memset(&s, 0, sizeof(s));
coord_t coord = r->playout->choose(r->playout, &s, b, color);
if (!is_pass(coord)) {
struct move m;
m.coord = coord; m.color = color;
if (board_play(b, &m) >= 0)
goto have_move;
if (DEBUGL(2)) {
fprintf(stderr, "Pre-picked move %d,%d is ILLEGAL:\n",
coord_x(coord, b), coord_y(coord, b));
board_print(b, stderr);
}
}
/* Defer to uniformly random move choice. */
board_play_random(b, color, &coord, (ppr_permit) r->playout->permit, r->playout);
have_move:
if (!group_at(b, coord)) {
/* This was suicide. Just pass. */
/* XXX: We should check for non-suicide alternatives. */
return coord_pass();
}
return coord_copy(coord);
}
struct replay *
replay_state_init(char *arg, struct board *b)
{
struct replay *r = calloc2(1, sizeof(struct replay));
r->debug_level = 1;
if (arg) {
char *optspec, *next = arg;
while (*next) {
optspec = next;
next += strcspn(next, ",");
if (*next) { *next++ = 0; } else { *next = 0; }
char *optname = optspec;
char *optval = strchr(optspec, '=');
if (optval) *optval++ = 0;
if (!strcasecmp(optname, "debug")) {
if (optval)
r->debug_level = atoi(optval);
else
r->debug_level++;
} else if (!strcasecmp(optname, "playout") && optval) {
char *playoutarg = strchr(optval, ':');
if (playoutarg)
*playoutarg++ = 0;
if (!strcasecmp(optval, "moggy")) {
r->playout = playout_moggy_init(playoutarg, b, joseki_load(b->size));
} else if (!strcasecmp(optval, "light")) {
r->playout = playout_light_init(playoutarg, b);
} else {
fprintf(stderr, "Replay: Invalid playout policy %s\n", optval);
}
} else {
fprintf(stderr, "Replay: Invalid engine argument %s or missing value\n", optname);
}
}
}
if (!r->playout)
r->playout = playout_light_init(NULL, b);
r->playout->debug_level = r->debug_level;
return r;
}
struct engine *
engine_replay_init(char *arg, struct board *b)
{
struct replay *r = replay_state_init(arg, b);
struct engine *e = calloc2(1, sizeof(struct engine));
e->name = "PlayoutReplay";
e->comment = "I select moves blindly according to playout policy. I won't pass as long as there is a place on the board where I can play. When we both pass, I will consider all the stones on the board alive.";
e->genmove = replay_genmove;
e->data = r;
return e;
}