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