Skip to content

Commit

Permalink
engine: store parsed options
Browse files Browse the repository at this point in the history
  • Loading branch information
lemonsqueeze committed Mar 31, 2019
1 parent 27389f5 commit 4fdcb51
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 74 deletions.
99 changes: 94 additions & 5 deletions engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,99 @@
#include "pachi.h"


/**************************************************************************************************/
/* Engine options */

/* Parse comma separated @arg, fill @options. */
static void
engine_options_parse(const char *arg, options_t *options)
{
options->n = 0;
if (!arg) return;

option_t *option = &options->o[0];
char *tmp_arg = strdup(arg);
char *next = tmp_arg;

for (options->n = 0; *next; options->n++, option++) {
assert(options->n < ENGINE_OPTIONS_MAX);

char *optspec = next;
next += strcspn(next, ",");
if (*next) *next++ = 0; else *next = 0;

char *optname = optspec;
char *optval = strchr(optspec, '=');
if (optval) *optval++ = 0;

option->name = strdup(optname);
option->val = (optval ? strdup(optval) : NULL);
}

free(tmp_arg);
}

static void
engine_options_free(options_t *options)
{
for (int i = 0; i < options->n; i++) {
free(options->o[i].name);
free(options->o[i].val);
}
}

static void
engine_options_copy(options_t *dest, options_t *src)
{
memcpy(dest, src, sizeof(*src));
}

void
engine_init(engine_t *e, int id, char *e_arg, board_t *b)
engine_options_print(options_t *options)
{
pachi_engine_init(e, id, e_arg, b);
fprintf(stderr, "engine options:\n");
for (int i = 0; i < options->n; i++)
if (options->o[i].val) fprintf(stderr, " %s=%s\n", options->o[i].name, options->o[i].val);
else fprintf(stderr, " %s\n", options->o[i].name);
}


/**************************************************************************************************/

/* init from scratch, preserving options. */
static void
engine_init_(engine_t *e, int id, board_t *b)
{
options_t options;
//engine_options_print(&e->options);

engine_options_copy(&options, &e->options);
memset(e, 0, sizeof(*e));
engine_options_copy(&e->options, &options);

e->id = id;
pachi_engine_init(e, id, b);
}

/* init from scratch */
void
engine_init(engine_t *e, int id, const char *e_arg, board_t *b)
{
engine_options_parse(e_arg, &e->options);
engine_init_(e, id, b);
}

void
engine_done(engine_t *e)
{
if (e->done) e->done(e);
if (e->data) free(e->data);
engine_options_free(&e->options);
memset(e, 0, sizeof(*e));
}

engine_t*
new_engine(int id, char *e_arg, board_t *b)
new_engine(int id, const char *e_arg, board_t *b)
{
engine_t *e = malloc2(engine_t);
engine_init(e, id, e_arg, b);
Expand All @@ -33,12 +111,19 @@ delete_engine(engine_t **e)
}

void
engine_reset(engine_t *e, board_t *b, char *e_arg)
engine_reset(engine_t *e, board_t *b)
{
int engine_id = e->id;
options_t options;

engine_options_copy(&options, &e->options); /* Save options. */

e->options.n = 0;
b->es = NULL;
engine_done(e);
engine_init(e, engine_id, e_arg, b);

engine_options_copy(&e->options, &options); /* Restore options. */
engine_init_(e, engine_id, b);
}

void
Expand All @@ -63,6 +148,9 @@ engine_ownermap(engine_t *e, board_t *b)
return (e->ownermap ? e->ownermap(e, b) : NULL);
}


/**************************************************************************************************/

/* For engines best_move(): Add move @c with prob @r to best moves @best_c, @best_r */
void
best_moves_add(coord_t c, float r, coord_t *best_c, float *best_r, int nbest)
Expand Down Expand Up @@ -107,3 +195,4 @@ best_moves_print(board_t *b, char *str, coord_t *best_c, int nbest)
fprintf(stderr, "]\n");
return strlen(str);
}

104 changes: 55 additions & 49 deletions engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@
#include "gtp.h"
#include "ownermap.h"

typedef struct {
char *name;
char *val;
} option_t;

#define ENGINE_OPTIONS_MAX 50

typedef struct {
option_t o[ENGINE_OPTIONS_MAX];
int n;
} options_t;


enum engine_id {
E_RANDOM,
E_REPLAY,
Expand All @@ -22,97 +35,85 @@ enum engine_id {
E_MAX,
};


typedef struct engine engine_t;

typedef void (*engine_init_t)(engine_t *e, char *arg, board_t *b);
typedef enum parse_code (*engine_notify_t)(engine_t *e, board_t *b, int id, char *cmd, char *args, char **reply);
typedef void (*engine_board_print_t)(engine_t *e, board_t *b, FILE *f);
typedef char *(*engine_notify_play_t)(engine_t *e, board_t *b, move_t *m, char *enginearg);
typedef char *(*engine_result_t)(engine_t *e, board_t *b);
typedef char *(*engine_chat_t)(engine_t *e, board_t *b, bool in_game, char *from, char *cmd);
typedef coord_t (*engine_genmove_t)(engine_t *e, board_t *b, time_info_t *ti, enum stone color, bool pass_all_alive);
typedef char *(*engine_genmoves_t)(engine_t *e, board_t *b, time_info_t *ti, enum stone color,
char *args, bool pass_all_alive, void **stats_buf, int *stats_size);
typedef void (*engine_best_moves_t)(engine_t *e, board_t *b, time_info_t *ti, enum stone color,
coord_t *best_c, float *best_r, int nbest);
typedef char *(*engine_genmoves_t)(engine_t *e, board_t *b, time_info_t *ti, enum stone color,
char *args, bool pass_all_alive, void **stats_buf, int *stats_size);
typedef void (*engine_evaluate_t)(engine_t *e, board_t *b, time_info_t *ti, floating_t *vals, enum stone color);
typedef void (*engine_analyze_t)(engine_t *e, board_t *b, enum stone color, int start);
typedef void (*engine_evaluate_t)(engine_t *e, board_t *b, time_info_t *ti, floating_t *vals, enum stone color);
typedef void (*engine_dead_group_list_t)(engine_t *e, board_t *b, move_queue_t *mq);
typedef ownermap_t* (*engine_ownermap_t)(engine_t *e, board_t *b);
typedef char *(*engine_result_t)(engine_t *e, board_t *b);
typedef void (*engine_stop_t)(engine_t *e);
typedef void (*engine_done_t)(engine_t *e);
typedef ownermap_t* (*engine_ownermap_t)(engine_t *e, board_t *b);
typedef void (*engine_livegfx_hook_t)(engine_t *e);

/* This is engine data structure. A new engine instance is spawned

/* Engine data structure. A new engine instance is spawned
* for each new game during the program lifetime. */
struct engine {
int id;
char *name;
char *comment;

/* If set, do not reset the engine state on clear_board. */
bool keep_on_clear;
options_t options;

bool keep_on_clear; /* If set, do not reset the engine state on clear_board. */

engine_notify_t notify;
engine_notify_t notify;
engine_board_print_t board_print;
engine_notify_play_t notify_play;
engine_chat_t chat;
engine_livegfx_hook_t livegfx_hook; /* GoGui hook */



engine_genmove_t genmove; /* Generate a move. If pass_all_alive is true, <pass> shall be generated only */
engine_genmove_t genmove_analyze; /* if all stones on the board can be considered alive, without regard to "dead" */
/* considered stones. */
engine_genmoves_t genmoves; /* Used by distributed engine */
engine_best_moves_t best_moves; /* List best moves for current position.
* Call engine_best_move() for data to be initialized correctly. */
engine_analyze_t analyze; /* Tell engine to start pondering for the sake of frontend running Pachi. */

engine_evaluate_t evaluate; /* Evaluate feasibility of player @color playing at all free moves. Will
* simulate each move from b->f[i] for time @ti, then set
* 1-max(opponent_win_likelihood) in vals[i]. */

engine_dead_group_list_t dead_group_list; /* One dead group per queued move (coord_t is (ab)used as group_t). */
engine_ownermap_t ownermap; /* Return current ownermap, if engine supports it. */
engine_result_t result;

/* Generate a move. If pass_all_alive is true, <pass> shall be generated only
* if all stones on the board can be considered alive, without regard to "dead"
* considered stones. */
engine_genmove_t genmove;
engine_genmove_t genmove_analyze;

/* Used by distributed engine */
engine_genmoves_t genmoves;

/* List best moves for current position.
* Call engine_best_move() for data to be initialized correctly. */
engine_best_moves_t best_moves;

/* Evaluate feasibility of player @color playing at all free moves. Will
* simulate each move from b->f[i] for time @ti, then set
* 1-max(opponent_win_likelihood) in vals[i]. */
engine_evaluate_t evaluate;

/* Tell engine to start pondering for the sake of frontend running Pachi. */
engine_analyze_t analyze;

/* One dead group per queued move (coord_t is (ab)used as group_t). */
engine_dead_group_list_t dead_group_list;

/* Pause any background thinking being done, but do not tear down
* any data structures yet. */
engine_stop_t stop;

/* e->data and e will be free()d by caller afterwards. */
engine_done_t done;

/* Return current ownermap, if engine supports it. */
engine_ownermap_t ownermap;

/* GoGui hook */
engine_livegfx_hook_t livegfx_hook;

engine_stop_t stop; /* Pause any background thinking being done, but do not tear down
* any data structures yet. */
engine_done_t done; /* e->data and e will be free()d by caller afterwards. */

void *data;
};


/* Initialize engine. Call engine_done() later when finished with it. */
void engine_init(engine_t *e, int id, char *e_arg, board_t *b);
void engine_init(engine_t *e, int id, const char *e_arg, board_t *b);

/* Clean up what engine_init() did. */
void engine_done(engine_t *e);

/* Allocate and initialize a new engine.
* Call delete_engine() when done. */
engine_t* new_engine(int id, char *e_arg, board_t *b);
engine_t* new_engine(int id, const char *e_arg, board_t *b);
void delete_engine(engine_t **e);

/* engine_done() + engine_init(), more or less. */
void engine_reset(engine_t *e, board_t *b, char *e_arg);
void engine_reset(engine_t *e, board_t *b);


/* Convenience functions for engine actions: */
Expand All @@ -130,4 +131,9 @@ void best_moves_add_full(coord_t c, float r, void *d, coord_t *best_c, float *be
int best_moves_print(board_t *b, char *str, coord_t *best_c, int nbest);


/* Engine options */

void engine_options_print(options_t *options);


#endif
8 changes: 4 additions & 4 deletions gtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,13 +746,13 @@ cmd_undo(board_t *b, engine_t *e, time_info_t *ti, gtp_t *gtp)
}

static void
undo_reload_engine(gtp_t *gtp, board_t *b, engine_t *e, char *e_arg)
undo_reload_engine(gtp_t *gtp, board_t *b, engine_t *e)
{
if (DEBUGL(3)) fprintf(stderr, "reloading engine after undo(s).\n");

gtp->undo_pending = false;

engine_reset(e, b, e_arg);
engine_reset(e, b);

/* Reset board */
int handicap = b->handicap;
Expand Down Expand Up @@ -1008,7 +1008,7 @@ gtp_internal_init()
* Even basic input checking is missing. */

enum parse_code
gtp_parse(gtp_t *gtp, board_t *b, engine_t *e, char *e_arg, time_info_t *ti, char *buf)
gtp_parse(gtp_t *gtp, board_t *b, engine_t *e, time_info_t *ti, char *buf)
{
if (strchr(buf, '#'))
*strchr(buf, '#') = 0;
Expand All @@ -1033,7 +1033,7 @@ gtp_parse(gtp_t *gtp, board_t *b, engine_t *e, char *e_arg, time_info_t *ti, cha

/* Undo: reload engine after first non-undo command. */
if (gtp->undo_pending && strcasecmp(gtp->cmd, "undo"))
undo_reload_engine(gtp, b, e, e_arg);
undo_reload_engine(gtp, b, e);

if (e->notify && gtp_is_valid(e, gtp->cmd)) {
char *reply;
Expand Down
2 changes: 1 addition & 1 deletion gtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ typedef struct

void gtp_init(gtp_t *gtp);

enum parse_code gtp_parse(gtp_t *gtp, board_t *b, struct engine *e, char *e_arg, time_info_t *ti, char *buf);
enum parse_code gtp_parse(gtp_t *gtp, board_t *b, struct engine *e, time_info_t *ti, char *buf);
bool gtp_is_valid(struct engine *e, const char *cmd);

/* Output one line, end-of-line \n added automatically. */
Expand Down
2 changes: 1 addition & 1 deletion joseki.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ joseki_load(int bsize)
skip_sequence(buf, 4096, f, &lineno);

gtp.quiet = true;
enum parse_code c = gtp_parse(&gtp, b, &e, NULL, ti, buf); /* quiet */
enum parse_code c = gtp_parse(&gtp, b, &e, ti, buf); /* quiet */
/* TODO check gtp command didn't gtp_error() also, will still return P_OK on error ... */
if (c != P_OK && c != P_ENGINE_RESET)
die("%s:%i gtp command '%s' failed, aborting.\n", fname, lineno, buf);
Expand Down
Loading

0 comments on commit 4fdcb51

Please sign in to comment.