2016 ソフトウェア設計及び演習用の班Wiki

16::gr11::engine.c

#include "engine.h"

int move_possible(int board[YMAX][XMAX], int x, int y, int color)
{
	int dx, dy;
	int _x, _y;
	int cnt;

	if (board[y][x] != NO_COLOR)
		return 0;

	for (dy = -1; dy <= 1; ++dy)
		for (dx = -1; dx <= 1; ++dx) {
			if (dx == 0 && dy == 0)
				continue;

			cnt = 0;
			_x = x + dx, _y = y + dy;
			while (_x >= 0 && _x < XMAX && _y >= 0 && _y < YMAX &&
					board[_y][_x] == 1 - color) {
				_x += dx, _y += dy;
				++cnt;
			}
			if (_x >= 0 && _x < XMAX && _y >= 0 && _y < YMAX &&
					board[_y][_x] == color && cnt > 0)
				return 1;
		}
	return 0;
}

int alpha_beta(int board[YMAX][XMAX], int alpha, int beta, int depth, 
		int color, int* pos)
{
	int dx, dy;
	int _x, _y;
	int i, j;
	int ret, temp;
	int idx;
	int res;
	list_t S, 
		   list_pos;
	point_t point;

	if (depth <= 0) {
		ret = calc_value(board, color);
		return ret;
	}

	init_list(&list_pos);
	for (i = 0; i < YMAX && alpha < beta; ++i)
		for (j = 0; j < XMAX && alpha < beta; ++j) {
			if (board[i][j] != NO_COLOR)
				continue;

			init_list(&S);
			for (dy = -1; dy <= 1; ++dy)
				for (dx = -1; dx <= 1; ++dx) {
					if (dx == 0 && dy == 0)
						continue;

					_x = j + dx, _y = i + dy;
					while (_x >= 0 && _x < XMAX && _y >= 0 && _y < YMAX &&
							board[_y][_x] == 1 - color)
						_x += dx, _y += dy;

					if (_x >= 0 && _x < XMAX && _y >= 0 && _x < YMAX &&
							board[_y][_x] == color)
						for (_x -= dx, _y -= dy; _x != j || _y != i; _x -= dx, _y -= dy) {
							board[_y][_x] = color;
							point.y = _y, point.x = _x;
							push(&S, point);
						}
				}
			if (empty(&S))
				continue;

			res = -alpha_beta(board, -beta, -alpha, depth - 1, 1 - color, &temp);

			while (!empty(&S)) {
				point = top(&S);
				pop(&S);

				_x = point.x, _y = point.y;
				board[_y][_x] = 1 - color;
			}
			if (res > alpha) {
				alpha = res;

				point.x = j;
				point.y = i;

				init_list(&list_pos);
				push(&list_pos, point);
			} else if (res == alpha) {
				point.x = j;
				point.y = i;
				push(&list_pos, point);
			}
		}

	if (!empty(&list_pos)) {
		idx = rand() % list_pos.size;
		*pos = list_pos.s[idx].y * 8 + list_pos.s[idx].x;
	}

	return alpha;
}



int minimax(int board[YMAX][XMAX], int alpha, int beta, int depth, 
		int color, int* pos)
{
	int ret;
	int i, j;
	int _x, _y;
	int dx, dy;
	int temp;
	list_t list_pos, S;
	point_t point;

	if (depth <= 0) {
		ret = evaluate(board, color);
		return ret;
	}

	init_list(&list_pos);
	if (color == WHITE) {
		for (i = 0; i < 8 && alpha < beta; ++i)
			for (j = 0; j < 8 && alpha < beta; ++j) {
				if (board[i][j] != NO_COLOR)
					continue;

				init_list(&S);
				for (dy = -1; dy <= 1; ++dy)
					for (dx = -1; dx <= 1; ++dx) {
						if (dx == 0 && dy == 0)
							continue;

						_x = j + dx, _y = i + dy;
						while (_x >= 0 && _x < XMAX && _y >= 0 &&
								_y < YMAX && board[_y][_x] == 1 - color)
							_x += dx, _y += dy;

						if (_x >= 0 && _x < XMAX && _y >= 0 && _y < YMAX &&
								board[_y][_x] == color)
							for (_x -= dx, _y -= dy; _x != j || _y != i; _x -= dx, _y -= dy) {
								board[_y][_x] = color;
								point.y = _y, point.x = _x;
								push(&S, point);
							}

					}
				if (empty(&S))
					continue;
				ret = minimax(board, alpha, beta, depth - 1, 1 - color, &temp);

				while (!empty(&S)) {
					point = top(&S);
					pop(&S);

					_x = point.x, _y = point.y;
					board[_y][_x] = 1 - color;
				}
				if (ret > alpha) {
					alpha = ret;
					point.x = j, point.y = i;

					init_list(&list_pos);
					push(&list_pos, point);
				} else if (ret == alpha) {
					point.x = j, point.y = i;
					push(&list_pos, point);
				}
			}
		if (!empty(&list_pos)) {
			int idx = rand() % list_pos.size;
			*pos = 8 * list_pos.s[idx].y + list_pos.s[idx].x;
		}
		return alpha;
	} 

	for (i = 0; i < 8 && alpha < beta; ++i)
		for (j = 0; j < 8 && alpha < beta; ++j) {
			if (board[i][j] != NO_COLOR)
				continue;

			init_list(&S);
			for (dy = -1; dy <= 1; ++dy)
				for (dx = -1; dx <= 1; ++dx) {
					if (dx == 0 && dy == 0)
						continue;

					_x = j + dx, _y = i + dy;
					while (_x >= 0 && _x < XMAX && _y >= 0 && _y < YMAX &&
							board[_y][_x] == 1 - color)
						_x += dx, _y += dy;

					if (_x >= 0 && _x < XMAX && _y >= 0 && _y < YMAX &&
							board[_y][_x] == color)
						for (_x -= dx, _y -= dy; _x != j || _y != i; _x -= dx, _y -= dy) {
							board[_y][_x] = color;
							point.y = _y, point.x = _x;
							push(&S, point);
						}
				}
			if (empty(&S))
				continue;
			ret = minimax(board, alpha, beta, depth - 1, 1 - color, &temp);

			while (!empty(&S)) {
				point = top(&S);
				pop(&S);

				_x = point.x, _y = point.y;
				board[_y][_x] = 1 - color;
			}

			if (ret < beta) {
				beta = ret;
				point.x = j, point.y = i;

				init_list(&list_pos);
				push(&list_pos, point);
			} else if (ret == beta) {
				point.x = j, point.y = i;
				push(&list_pos, point);
			}

		}
	if (!empty(&list_pos)) {
		int idx = rand() % list_pos.size;
		*pos = 8 * list_pos.s[idx].y + list_pos.s[idx].x;
	}
	return beta;
}



void computer_turn(int board[YMAX][XMAX], int recommend_depth, int white_score, int black_score, int* x, int* y)
{
	int pos, ret;
	int depth = (recommend_depth == 0 ? 7 : 1);

	if (move_possible(board, 0, 0, WHITE)) {
		*x = 0, *y = 0;
		return;
	} else if (move_possible(board, 0, 7, WHITE)) {
		*x = 0, *y = 7;
		return;
	} else if (move_possible(board, 7, 0, WHITE)) {
		*x = 7, *y = 0;
		return;
	} else if (move_possible(board, 7, 7, WHITE)) {
		*x = 7, *y = 7;
		return;
	}

	coeff = 100 - (100 * (evaluate(board, WHITE) + evaluate(board, BLACK) + depth - 4)) / 60;
	if (white_score + black_score + depth + 3 >= XMAX * YMAX)
		depth = XMAX * YMAX - white_score - black_score;
	else if (white_score + black_score + depth + 4 >= XMAX * YMAX)
		depth += 2;
	else if (white_score + black_score + depth + 5 >= XMAX * YMAX)
		++depth;

	ret = alpha_beta(board, -ILLEGAL_NUMBER, ILLEGAL_NUMBER, depth, WHITE, &pos);

	if (ret == -ILLEGAL_NUMBER)
		return;
	*x = pos % 8;
	*y = pos / 8;
}


void setup_board_weight()
{
	int i, j;

	for (i = 0; i < YMAX; ++i)
		for (j = 0; j < XMAX; ++j) {
			if (i == 1 || i == 6)
				board_weight[i][j] = -1;
			else
				board_weight[i][j] = 0;
			if (j == 2 || j == 5)
				board_weight[i][j] -= 1;
		}

	board_weight[0][0] = 2;
	board_weight[7][0] = 2;
	board_weight[0][7] = 2;
	board_weight[7][7] = 2;

	board_weight[0][1] = -1;
	board_weight[1][0] = -1;
	board_weight[0][6] = -1;
	board_weight[6][0] = -1;
	board_weight[7][1] = -1;
	board_weight[1][7] = -1;
	board_weight[7][6] = -1;
	board_weight[6][7] = -1;
}


int evaluate(int board[YMAX][XMAX], int color)
{
	int sum = 0;
	int i, j;

	for (i = 0; i < YMAX; ++i)
		for (j = 0; j < XMAX; ++j)
			if (board[i][j] == color)
				sum += board_weight[i][j];
	return sum;
}


int calc_value(int board[YMAX][XMAX], int self_color)
{
	int ret;
	int opponent = 1 - self_color;
	int self_score, opponent_score;

	self_score = evaluate(board, self_color);
	opponent_score = evaluate(board, opponent);

	ret = (100 - coeff) * (self_score - opponent_score) + 
		coeff * BC_WEIGHT * (self_score - opponent_score);

	return ret;
}


最終更新日:2016/08/02 16:54:14