// Five AI Player // Author: coolypf // #define TEST_PERF #ifdef TEST_PERF #include <Windows.h> #endif #include <iostream> #include <string> #include <algorithm> #include <math.h> #include <memory.h> #include <time.h> using namespace std; const int infinite = 10000000; const int s[4][3][2] = { {{100000, 0}, {15000, -200000}, {10, 0}}, {{15000, -50000}, {100, -200}, {5, 0}}, {{50, -50}, {10, -5}, {2, 0}}, {{10, -5}, {2, -1}, {1, 0}} }; const int range = 15; const int black = 1; const int white = 2; int self, enemy; int rnd; clock_t start_time; int tle; int board[range][range]; struct Combo { int x; int y; int score; bool operator < (const Combo &ano) const { return (score > ano.score); } }; void AI(int, int); int backtrace(int, int, int[][range], int); int evalutatestep(const int[][range], int, int, int); int evaluate(const int[][range], int); inline int onboard(int x, int y) { return (x>=0 && y>=0 && x<range && y<range) ? 1 : 0; } int main() { int x, y; string cmd; rnd = 0; memset(board, 0, sizeof(board)); cin >> cmd; cin >> self; enemy = black + white - self; while(1){ rnd ++; cin >> cmd; cin >> x >> y; if(onboard(x, y)) board[x][y] = enemy; start_time = clock(); tle = 0; AI(x, y); } return 0; } void AI(int px, int py) { int x = 0, y = 0; int decide = 0; int guess = 0; static int ppx, ppy, myx, myy, cx, cy; #ifdef TEST_PERF LARGE_INTEGER pf_li; double pf_freq, pf_st, pf_ed, pf_t; static double pf_maxtime = 0.0; QueryPerformanceFrequency(&pf_li); pf_freq=(double)pf_li.QuadPart; QueryPerformanceCounter(&pf_li); pf_st=(double)pf_li.QuadPart; int break_at = 0; #endif if(self == black && rnd == 1) { decide = 1; x = 7; y = 7; } if(self == white && rnd == 1) { int mindelta = infinite; if((px - 7)*(px - 7) + (py - 7)*(py - 7) > 32) { x = 7; y = 7; decide = 1; } else for(int i=3; i<=11; ++i) for(int j=3; j<=11; ++j) { int d1 = (i - px)*(i - px) + (j - py)*(j - py); int d2 = (i - 7)*(i - 7) + (j - 7)*(j - 7); if(d1 == 2 && d2 < mindelta) { mindelta = d2; x = i; y = j; decide = 1; cx = px; cy = py; } } } if(!decide) { static Combo vc[range*range]; static int mark[range][range]; int cur = 0; memset(mark, 0, sizeof(mark)); for(int i=0; i<range; ++i) { for(int j=0; j<range; ++j) { if(board[i][j] == 0 && ( onboard(i, j-1) && board[i][j-1] || onboard(i, j-2) && board[i][j-2] || onboard(i, j+1) && board[i][j+1] || onboard(i, j+2) && board[i][j+2] || onboard(i-1, j) && board[i-1][j] || onboard(i-2, j) && board[i-2][j] || onboard(i+1, j) && board[i+1][j] || onboard(i+2, j) && board[i+2][j] || onboard(i-1, j-1) && board[i-1][j-1] || onboard(i-2, j-2) && board[i-2][j-2] || onboard(i+1, j+1) && board[i+1][j+1] || onboard(i+2, j+2) && board[i+2][j+2] || onboard(i-1, j+1) && board[i-1][j+1] || onboard(i-2, j+2) && board[i-2][j+2] || onboard(i+1, j-1) && board[i+1][j-1] || onboard(i+2, j-2) && board[i+2][j-2] )) { vc[cur].x = i; vc[cur].y = j; vc[cur].score = evalutatestep(board, i, j, self); cur ++; mark[i][j] = 1; } } } sort(vc, vc+cur); guess = cur; cur = min(cur, 22); if(vc[0].score < infinite && rnd < 107) { int maxs = -infinite-100; for(int i=0; i<cur; ++i) { int nx = vc[i].x, ny = vc[i].y; int bakx[25], baky[25], bakc = 0; board[nx][ny] = self; for(int u=-2; u<=2; ++u) { for(int v=-2; v<=2; ++v) if(onboard(nx+u, ny+v) && mark[nx+u][ny+v] == 0 && abs(u) + abs(v) != 3) { mark[nx+u][ny+v] = 1; bakx[bakc] = nx + u; baky[bakc] = ny + v; bakc ++; } } vc[i].score = backtrace(4, 11, mark, maxs); if(vc[i].score > maxs) { maxs = vc[i].score; } board[nx][ny] = 0; for(int j=0; j<bakc; ++j) mark[bakx[j]][baky[j]] = 0; } sort(vc, vc + cur); if((clock() - start_time)*1000/CLOCKS_PER_SEC < 960) { maxs = -infinite-100; int maxi = -1; for(int i=0; i<cur; ++i) { int nx = vc[i].x, ny = vc[i].y; int bakx[25], baky[25], bakc = 0; board[nx][ny] = self; for(int u=-2; u<=2; ++u) { for(int v=-2; v<=2; ++v) if(onboard(nx+u, ny+v) && mark[nx+u][ny+v] == 0 && abs(u) + abs(v) != 3) { mark[nx+u][ny+v] = 1; bakx[bakc] = nx + u; baky[bakc] = ny + v; bakc ++; } } vc[i].score = backtrace(6, 11, mark, maxs); if(tle == 0 && vc[i].score > maxs) { maxs = vc[i].score; maxi = i; } board[nx][ny] = 0; for(int j=0; j<bakc; ++j) mark[bakx[j]][baky[j]] = 0; #ifdef TEST_PERF break_at = i + 1; #endif if((clock() - start_time)*1000/CLOCKS_PER_SEC > 960 || tle) break; } if(maxi >= 0) vc[0] = vc[maxi]; } } decide = 1; x = vc[0].x; y = vc[0].y; } ppx = px; ppy = py; myx = x; myy = y; board[x][y] = self; #ifdef TEST_PERF QueryPerformanceCounter(&pf_li); pf_ed = (double)pf_li.QuadPart; pf_t = (pf_ed - pf_st) / pf_freq * 1000; if(pf_t > pf_maxtime) pf_maxtime = pf_t; cout << x << " " << y << " " << break_at << " " << (int)pf_t << " " << (int)pf_maxtime << endl << flush; #else cout << x << " " << y << endl << flush; #endif } int evaluate(const int b[][range], int c) { static const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}; static const int dy[] = {0, 1, 1, 1, 0, -1, -1, -1}; int score = 0; int close[8], bclose[8], jump[8], bjump[8]; int cnt[4][3]; for(int i=0; i<range; ++i) for(int j=0; j<range; ++j) { if(b[i][j] == 0) continue; int color = b[i][j]; int factor = (color != c) ? 1 : 0; memset(cnt, 0, sizeof(cnt)); memset(close, 0, sizeof(close)); memset(bclose, 0, sizeof(bclose)); memset(jump, 0, sizeof(jump)); memset(bjump, 0, sizeof(bjump)); for(int d=0; d<8; ++d) { int x = i + dx[d], y = j + dy[d]; for( ; onboard(x, y) && b[x][y] == color; x+=dx[d], y+=dy[d], ++close[d]); for( ; onboard(x, y) && b[x][y] == 0; x+=dx[d], y+=dy[d], ++bclose[d]); for( ; onboard(x, y) && b[x][y] == color; x+=dx[d], y+=dy[d], ++jump[d]); for( ; onboard(x, y) && b[x][y] == 0; x+=dx[d], y+=dy[d], ++bjump[d]); } for(int d=0; d<4; ++d) { int l = d + 4; if(close[l] + close[d] >= 4) return (1 - 2*factor) * infinite; else if(close[l] + close[d] == 3) { if(bclose[l] > 0 && bclose[d] > 0) { if(factor) return -infinite; else cnt[0][0]++; } else if(bclose[l] > 0 || bclose[d] > 0) { if(factor) return -infinite; else cnt[0][1]++; } else cnt[0][2]++; } else if(close[l] + close[d] == 2) { if(bclose[l] > 0 && bclose[d] > 0) { if(jump[l] > 0 && bclose[l] == 1 || jump[d] > 0 && bclose[d] == 1) { if(factor) return -infinite; else cnt[0][1]++; } else if(bclose[l] > 1 || bclose[d] > 1) cnt[1][0]++; else cnt[1][1]++; } else if(bclose[l] > 0 || bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 0 || bclose[d] == 1 && jump[d] > 0) { if(factor) return -infinite; else cnt[0][1]++; } else if(bclose[l] > 1 || bclose[d] > 1) cnt[1][1]++; else cnt[1][2]++; } else cnt[1][2]++; } else if(close[l] + close[d] == 1) { if(bclose[l] > 0 && bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 1 || bclose[d] == 1 && jump[d] > 1) { if(factor) return -infinite; else cnt[0][1]++; } else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 0 || bclose[d] == 1 && jump[d] == 1 && bjump[d] > 0) cnt[1][0]++; else if(bclose[l] == 1 && jump[l] == 1 || bclose[d] == 1 && jump[d] == 1) cnt[1][1]++; else if(bclose[l] > 1 || bclose[d] > 1) cnt[2][0]++; else cnt[2][2]++; } else if(bclose[l] > 0 || bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 1 || bclose[d] == 1 && jump[d] > 1) { if(factor) return -infinite; else cnt[0][1]++; } else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 0 || bclose[d] == 1 && jump[d] == 1 && bjump[d] > 0) cnt[1][1]++; else if(bclose[l] > 2 || bclose[d] > 2) cnt[2][1]++; else cnt[2][2]++; } else cnt[2][2]++; } else { if(bclose[l] > 0 && bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 2 || bclose[d] == 1 && jump[d] > 2) { if(factor) return -infinite; else cnt[0][1]++; } else if(bclose[l] == 1 && jump[l] == 2 && bjump[l] > 0 || bclose[d] == 1 && jump[d] == 2 && bjump[d] > 0) cnt[1][0]++; else if(bclose[l] == 1 && jump[l] == 2 || bclose[d] == 1 && jump[d] == 2) cnt[1][1]++; else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 1 || bclose[d] == 1 && jump[d] == 1 && bjump[d] > 1) cnt[2][0]++; else if(bclose[l] > 2 || bclose[d] > 2) cnt[3][0]++; else cnt[3][1]++; } else if(bclose[l] > 0 || bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 2 || bclose[d] == 1 && jump[d] > 2) { if(factor) return -infinite; else cnt[0][1]++; } else if(bclose[l] == 1 && jump[l] == 2 && bjump[l] > 0 || bclose[d] == 1 && jump[d] == 2 && bjump[d] > 0) cnt[1][1]++; else if(bclose[l] == 1 && jump[l] == 1 && bjump[l] > 1 || bclose[d] == 1 && jump[d] == 1 && bjump[d] > 1) cnt[2][1]++; else if(bclose[l] > 3 || bclose[d] > 3) cnt[3][1]++; else cnt[3][2]++; } else cnt[3][2]++; } } for(int u=0; u<4; ++u) for(int v=0; v<3; ++v) score += cnt[u][v]*s[u][v][factor]; if(cnt[0][1] > 1 || cnt[0][1] == 1 && cnt[1][0] > 0) score += s[0][0][factor] * 2; } return score; } int evalutatestep(const int b[][range], int i, int j, int c) { static const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}; static const int dy[] = {0, 1, 1, 1, 0, -1, -1, -1}; int score = 0; int close[8], bclose[8], jump[8]; int c4a, c4b, c3a, c3b, c2a, c2b, c1a, c1b; for(int test=0; test<2; ++test) { c4a = 0; c4b = 0; c3a = 0; c3b = 0; c2a = 0; c2b = 0; c1a = 0; c1b = 0; memset(close, 0, sizeof(close)); memset(bclose, 0, sizeof(bclose)); memset(jump, 0, sizeof(jump)); for(int d=0; d<4; ++d) { int l = d + 4; int x = i + dx[d], y = j + dy[d]; int u = i + dx[l], v = j + dy[l]; for( ; onboard(x, y) && b[x][y] == c; x+=dx[d], y+=dy[d], ++close[d]); for( ; onboard(u, v) && b[u][v] == c; u+=dx[l], v+=dy[l], ++close[l]); if(close[l] + close[d] >= 4) { if(test == 0) return infinite; return (infinite - 1000); } else { for( ; onboard(x, y) && b[x][y] == 0; x+=dx[d], y+=dy[d], ++bclose[d]); for( ; onboard(u, v) && b[u][v] == 0; u+=dx[l], v+=dy[l], ++bclose[l]); if(close[l] + close[d] == 3) { if(bclose[l] > 0 && bclose[d] > 0) c4a++; else if(bclose[l] > 0 || bclose[d] > 0) c4b++; } else if(bclose[l] > 0 || bclose[d] > 0) { for( ; onboard(x, y) && b[x][y] == c; x+=dx[d], y+=dy[d], ++jump[d]); for( ; onboard(u, v) && b[u][v] == c; u+=dx[l], v+=dy[l], ++jump[l]); if(close[l] + close[d] == 2) { if(bclose[l] > 0 && bclose[d] > 0) { if(jump[l] > 0 && bclose[l] == 1 || jump[d] > 0 && bclose[d] == 1) c4b++; else if(bclose[l] > 1 || bclose[d] > 1) c3a++; else c3b++; } else { if(bclose[l] == 1 && jump[l] > 0 || bclose[d] == 1 && jump[d] > 0) c4b++; else if(bclose[l] > 1 || bclose[d] > 1) c3b++; } } else if(close[l] + close[d] == 1) { if(bclose[l] > 0 && bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 1 || bclose[d] == 1 && jump[d] > 1) c4b++; else if(bclose[l] == 1 && jump[l] == 1) { if(onboard(u, v) && b[u][v] == 0) c3a++; else c3b++; } else if(bclose[d] == 1 && jump[d] == 1) { if(onboard(x, y) && b[x][y] == 0) c3a++; else c3b++; } else if(bclose[l] > 1 || bclose[d] > 1) c2a++; } else { if(bclose[l] == 1 && jump[l] > 1 || bclose[d] == 1 && jump[d] > 1) c4b++; else if(bclose[l] == 1 && jump[l] == 1 && onboard(u, v) && b[u][v] == 0) c3b++; else if(bclose[d] == 1 && jump[d] == 1 && onboard(x, y) && b[x][y] == 0) c3b++; else if(bclose[l] > 1 || bclose[d] > 1) c2b++; } } else { if(bclose[l] > 0 && bclose[d] > 0) { if(bclose[l] == 1 && jump[l] > 2 || bclose[d] == 1 && jump[d] > 2) c4b++; else if(bclose[l] == 1 && jump[l] == 2) { if(onboard(u, v) && b[u][v] == 0) c3a++; else c3b++; } else if(bclose[d] == 1 && jump[d] == 2) { if(onboard(x, y) && b[x][y] == 0) c3a++; else c3b++; } else if(bclose[l] == 1 && jump[l] == 1 && onboard(u, v) && b[u][v] == 0 && onboard(u+dx[l], v+dy[l]) && b[u+dx[l]][v+dy[l]] == 0) c2a++; else if(bclose[d] == 1 && jump[d] == 1 && onboard(x, y) && b[x][y] == 0 && onboard(x+dx[d], y+dy[d]) && b[x+dx[d]][y+dy[d]] == 0) c2a++; else if(bclose[l] > 2 || bclose[d] > 2) c1a++; } else { if(bclose[l] == 1 && jump[l] > 2 || bclose[d] == 1 && jump[d] > 2) c4b++; else if(bclose[l] == 1 && jump[l] == 2 && onboard(u, v) && b[u][v] == 0) c3b++; else if(bclose[d] == 1 && jump[d] == 2 && onboard(x, y) && b[x][y] == 0) c3b++; else if(bclose[l] == 1 && jump[l] == 1 && onboard(u, v) && b[u][v] == 0 && onboard(u+dx[l], v+dy[l]) && b[u+dx[l]][v+dy[l]] == 0) c2b++; else if(bclose[d] == 1 && jump[d] == 1 && onboard(x, y) && b[x][y] == 0 && onboard(x+dx[d], y+dy[d]) && b[x+dx[d]][y+dy[d]] == 0) c2b++; else if(bclose[l] > 2 || bclose[d] > 2) c1b++; } } } } } if(test == 0) { score += c4a * s[0][0][0]; score += c4b * s[0][1][0]; score += c3a * s[1][0][0]; score += c3b * s[1][1][0]; score += c2a * s[2][0][0]; score += c2b * s[2][1][0]; score += c1a * s[3][0][0]; score += c1b * s[3][1][0]; if(c4b > 1 || c4b == 1 && c3a > 0) score += s[0][0][0]; } else { score -= c4a * s[1][0][1]; score -= c4b * s[1][1][1]; score -= c3a * s[2][0][1]; score -= c3b * s[2][1][1]; score -= c2a * s[3][0][1]; score -= c2b * s[3][1][1]; if(c4b > 1 || c4b == 1 && c3a > 0) score -= s[1][0][1]; } c = self + enemy - c; } return score; } int backtrace(int turn, int limit, int mark[][range], int mm) { static Combo vch[10][range*range]; if(turn <= 0) return evaluate(board, self); int color = (turn % 2) ? self : enemy; Combo *vc = vch[turn]; int cur = 0; int tmpscore; if((clock() - start_time)*1000/CLOCKS_PER_SEC > 960) { tle = 1; return 0; } for(int i=0; i<range; ++i) { for(int j=0; j<range; ++j) if(board[i][j] == 0 && mark[i][j] != 0) { tmpscore = evalutatestep(board, i, j, color); if(tmpscore >= infinite) { if(color == enemy) return -(infinite + turn); else return (infinite + turn); } vc[cur].x = i; vc[cur].y = j; vc[cur].score = tmpscore; cur ++; } } sort(vc, vc + cur); cur = min(cur, limit); int ret = (color == self) ? (-infinite-100) : (infinite+100); for(int i=0; i<cur; ++i) { int nx = vc[i].x, ny = vc[i].y; int bakx[25], baky[25], bakc = 0; board[nx][ny] = color; for(int u=-2; u<=2; ++u) { for(int v=-2; v<=2; ++v) if(onboard(nx+u, ny+v) && mark[nx+u][ny+v] == 0 && abs(u) + abs(v) != 3) { mark[nx+u][ny+v] = 1; bakx[bakc] = nx + u; baky[bakc] = ny + v; bakc ++; } } int score = backtrace(turn - 1, limit, mark, ret); if(color == self && score > ret) { ret = score; } else if(color == enemy && score < ret) { ret = score; } board[nx][ny] = 0; for(int j=0; j<bakc; ++j) mark[bakx[j]][baky[j]] = 0; if(color == self && ret >= mm || color == enemy && ret <= mm) return ret; if(tle) return 0; } return ret; }