示例#1
0
文件: bench.c 项目: cutechess/sloppy
/* Run a test position (eg. WAC, ECM, WCSAC).

   Format of pos: <FEN> <"bm" or "am"> <move>; <position id>;
   - "bm" means <move> is the best move, "am" means <move> should be avoided
   - the move is in SAN notation
   - position id can be omitted
   - example: R7/P4k2/8/8/8/8/r7/6K1 w - - bm Rg8; id "WAC.018";
   
   The time limit must be defined in <chess> before running the test.

   Returns -1 on error
            0 for unsolved test
            1 for solved test
            2 for cancelled test  */
int
test_pos(Chess *chess, const char *pos)
{
	char tmp_pos[MAX_BUF];
	char *pos_item = NULL;
	char *svptr = NULL;
	U32 move;
	bool find_best;

	strlcpy(tmp_pos, pos, MAX_BUF);
	
	/* See if we're looking for the best move or avoiding a move.
	   By doing that we'll also get to the end of the FEN string.  */
	if ((pos_item = strstr(tmp_pos, " bm ")) != NULL)
		find_best = true;
	else if ((pos_item = strstr(tmp_pos, " am ")) != NULL) {
		find_best = false;
		my_error("'Avoid move' positions not currently allowed");
		return -1;
	} else
		return -1;

	*pos_item = 0; /* end of FEN string */
	pos_item += 4; /* best move or move to avoid */
	
	if (fen_to_board(&chess->board, tmp_pos))
		return -1;

	/* Get the move string.  */
	if ((pos_item = strtok_r(pos_item, ";", &svptr)) == NULL)
		return -1;
	/* Some positions have a series of moves (a pv) as the solution. We
	   only care about the first one, so make sure to pick just one.  */
	svptr = strchr(pos_item, ' ');
	if (svptr != NULL)
		*svptr = '\0';
	
	move = san_to_move(&chess->board, pos_item);
	if (move == NULLMOVE) {
		printf("Illegal test solution: %s\n", pos_item);
		return -1;
	}
	id_search(chess, move);
	if (chess->sd.cmd_type != CMDT_CONTINUE)
		return 2;
	if (chess->sd.move == move)
		return 1;

	return 0;
}
示例#2
0
void game_make_move_str(char *move_str, int ui_update) {
	board_t new_board = *history->last->board;
	move_t *engine_move;

	DBG_LOG("Parsing move string '%s'", move_str);

	engine_move = san_to_move(&new_board, move_str);

	if (!engine_move)
		engine_move = fullalg_to_move(&new_board, move_str);
	if (engine_move) {
		game_make_move(engine_move, ui_update);
		free(engine_move);
	} else
		DBG_ERROR("Failed to parse move string '%s'", move_str);
}
示例#3
0
文件: pgn.c 项目: cutechess/sloppy
/* Read a PGN file (a collection of one or more games in PGN format) and store
   the positions and their win/loss ratios in an AVL tree (**tree).
   The AVL tree can later be written in an opening book file (book.bin).
   
   Returns the number of new positions added to the tree, or -1 on error.  */
int
pgn_to_tree(const char *filename, AvlNode **tree)
{
	PgnResult result;
	int prev_progress;
	int npos = 0;
	long file_len;
	FILE *fp;
	Board board;

	ASSERT(1, filename != NULL);

	if ((fp = fopen(filename, "r")) == NULL) {
		my_perror("Can't open PGN file %s", filename);
		return -1;
	}

	if (settings.book_type != BOOK_MEM) {
		settings.book_type = BOOK_MEM;
		printf("Changed book mode to \"book in memory\"\n");
	}
	if (*tree == NULL && file_exists(settings.book_file)) {
		printf("Loading opening book to memory...\n");
		book_to_tree(settings.book_file, tree);
	} else if (*tree == NULL)
		printf("Creating a new opening book...\n");

	/* Find out how big the file is.  */
	fseek(fp, 0, SEEK_END);
	file_len = ftell(fp);
	rewind(fp);

	printf("Reading PGN file %s...\n", filename);
	prev_progress = 0;
	progressbar(50, 0);
	while ((result = get_pgn_result(fp)) != RESULT_ERROR) {
		int depth;
		int progress;
		int len;
		char san_move[MAX_BUF];

		/* Games with an unknown result are ignored.  */
		ASSERT(1, result != RESULT_ERROR);
		if (result == NO_RESULT || result == DRAWN_GAME)
			continue;

		depth = 0;
		fen_to_board(&board, START_FEN);

		while ((len = read_move(san_move, MAX_BUF, fp)) >= 0) {
			int points = 0;
			U32 move;

			/* break out of the loop when a new game begins */
			if (depth > 0 && san_move[0] == '[')
				break;
			if (len < 2)
				continue;

			move = san_to_move(&board, san_move);
			if (move == NULLMOVE) {
				#if DEBUG_LEVEL > 0
				update_log("Illegal move in %s: %s, line: %d\n",
				          filename, san_move, get_line_num(fp));
				#endif /* DEBUG_LEVEL > 0 */
				break;
			}

			if ((result == WHITE_WINS && board.color == WHITE)
			||  (result == BLACK_WINS && board.color == BLACK))
				points = 2;

			make_move(&board, move);
			if (save_book_pos(board.posp->key, points, tree))
				npos++;

			if (++depth >= MAX_BOOK_PLIES)
				break;
		}
		progress = (ftell(fp) * 50) / file_len;
		if (progress > prev_progress) {
			progressbar(50, progress);
			prev_progress = progress;
		}
	}
	progressbar(50, 50);
	my_close(fp, filename);
	printf("\n");

	return npos;
}
示例#4
0
int main(int argc, char **argv) {
	cl_options_t cl_options = {0};

	dbg_init();
	DBG_LOG("Version %s", g_version);

	ui = &ui_sdlgl;

	printf("DreamChess %s\n", g_version);

	parse_options(argc, argv, &ui, &cl_options);
	config_init();
	set_cl_options(&cl_options);

	if (!ui) {
		DBG_ERROR("Failed to find a user interface driver");
		exit(1);
	}

	ui->init();

	init_resolution();

	while (1) {
		board_t board;
		int pgn_slot;
		option_t *option;

		if (!(config = ui->config(&pgn_slot)))
			break;

		ch_userdir();
		option = config_get_option("first_engine");

#ifdef __APPLE__
		char temp1[200];
		char temp2[200];

		if (!strcmp(option->string, "dreamer") || !strcmp(option->string, "Dreamer")) {
			CFBundleRef mainBundle = CFBundleGetMainBundle();

			CFURLRef bundledir = CFBundleCopyBundleURL(mainBundle);
			CFStringRef stringref = CFURLCopyFileSystemPath(bundledir, kCFURLPOSIXPathStyle);
			CFStringGetCString(stringref, temp1, 200, kCFStringEncodingMacRoman);

			snprintf(temp2, sizeof(temp2), "%s/contents/MacOS/dreamer", temp1);

			game_set_engine_error(comm_init(temp2));
		} else
			game_set_engine_error(comm_init(option->string));
#else
		game_set_engine_error(comm_init(option->string));
#endif

		comm_send("xboard\n");

		comm_send("new\n");
		comm_send("random\n");

		comm_send("sd %i\n", config->cpu_level);
		comm_send("depth %i\n", config->cpu_level);

		if (config->difficulty == 0)
			comm_send("noquiesce\n");

		if (config->player[WHITE] == PLAYER_UI && config->player[BLACK] == PLAYER_UI)
			comm_send("force\n");

		if (config->player[WHITE] == PLAYER_ENGINE)
			comm_send("go\n");

		in_game = 1;
		board_setup(&board);
		history = history_init(&board);
		move_list_init(&san_list);
		move_list_init(&fan_list);
		move_list_init(&fullalg_list);

		if (pgn_slot >= 0)
			if (game_load(pgn_slot)) {
				DBG_ERROR("Failed to load savegame in slot %i", pgn_slot);
				exit(1);
			}

		ui->update(history->view->board, NULL);
		while (in_game) {
			char *s;

			if ((s = comm_poll())) {
				DBG_LOG("Message from engine: '%s'", s);
				if (!history->result) {
					if ((!strncmp(s, "move ", 4) || strstr(s, "... ")) &&
						config->player[history->last->board->turn] == PLAYER_ENGINE) {
						char *move_str = strrchr(s, ' ') + 1;
						board_t new_board = *history->last->board;
						move_t *engine_move;

						DBG_LOG("Parsing move string '%s'", move_str);

						engine_move = san_to_move(&new_board, move_str);
						if (!engine_move)
							engine_move = fullalg_to_move(&new_board, move_str);
						if (engine_move) {
							audio_play_sound(AUDIO_MOVE);
							do_move(engine_move, 1);
							free(engine_move);
						} else
							DBG_ERROR("Failed to parse move string '%s'", move_str);
					} else if (strstr(s, "llegal move"))
						game_undo();
					/* Ignore result message if we've already determined a result ourselves. */
					else {
						char *start = strchr(s, '{');
						char *end = strchr(s, '}');

						if (start && end && end > start) {
							char *comment = malloc(end - start);
							history->result = malloc(sizeof(result_t));
							strncpy(comment, start + 1, end - start - 1);
							comment[end - start - 1] = '\0';
							history->result->reason = comment;
							if (strstr(s, "1-0")) {
								history->result->code = RESULT_WHITE_WINS;
								ui->show_result(history->result);
							} else if (strstr(s, "1/2-1/2")) {
								history->result->code = RESULT_DRAW;
								ui->show_result(history->result);
							} else if (strstr(s, "0-1")) {
								history->result->code = RESULT_BLACK_WINS;
								ui->show_result(history->result);
							} else {
								free(history->result->reason);
								free(history->result);
								history->result = NULL;
							}
						}
					}
				}

				free(s);
			}
			ui->poll();
		}
		comm_send("quit\n");
		comm_exit();
		history_exit(history);
		move_list_exit(&san_list);
		move_list_exit(&fan_list);
		move_list_exit(&fullalg_list);
	}
	ui->exit();
	dbg_exit();
	return 0;
}