//返回一个你的落子决定 std::pair<int, int> othello_ai::get(){ adjust_valuemap(); //获得所有可落子的位置,按先行后列的顺序 std::vector< std::pair<int, int> > ans = o.allmove(o.mycolor); std::cerr<<std::endl<<"starting running ..."<<std::endl; next = seize_peak(ans); if ( next.first >= 0 && next.second >= 0 ) { std::cerr<<std::endl<<"-->> player "<<o.mycolor<<" move ("<<next.first<<", "<<next.second<<")"<<std::endl; return next; } turn(o, o.mycolor, MAXVALUE, DEPTH); //while (!steps.empty()) { // next = steps.top(); // steps.pop(); //} if (next.first >= 0 && next.second >= 0) { if (next.first == ans[0].first && next.second == ans[1].second) std::cerr<<std::endl<<"turn choose first"<<std::endl; std::cerr<<std::endl<<"-->> player "<<o.mycolor<<" move ("<<next.first<<", "<<next.second<<")"<<std::endl; return next; } else { std::cerr<<std::endl<<"have to choose first"<<std::endl; return ans[0]; } }
void othello_ai::adjust_valuemap() { if ( o.is(o.mycolor, 0, 0) ) { valuemap[0][1] *= (valuemap[0][1] < 0) ? -1 : 1; valuemap[1][0] *= (valuemap[1][0] < 0) ? -1 : 1; valuemap[1][1] *= (valuemap[1][1] < 0) ? -1 : 1; } if ( o.is(o.mycolor, 0, MAXEDGE - 1) ) { valuemap[0][MAXEDGE - 2] *= (valuemap[0][MAXEDGE - 2] < 0) ? -1 : 1; valuemap[1][MAXEDGE - 1] *= (valuemap[1][MAXEDGE - 1] < 0) ? -1 : 1; valuemap[1][MAXEDGE - 2] *= (valuemap[1][MAXEDGE - 2] < 0) ? -1 : 1; } if ( o.is(o.mycolor, MAXEDGE - 1, 0) ) { valuemap[MAXEDGE - 2][1] *= (valuemap[MAXEDGE - 2][1] < 0) ? -1 : 1; valuemap[MAXEDGE - 1][0] *= (valuemap[MAXEDGE - 1][0] < 0) ? -1 : 1; valuemap[MAXEDGE - 2][1] *= (valuemap[MAXEDGE - 2][1] < 0) ? -1 : 1; } if ( o.is(o.mycolor, MAXEDGE - 1, MAXEDGE - 1) ) { valuemap[MAXEDGE - 1][MAXEDGE - 2] *= (valuemap[MAXEDGE - 1][MAXEDGE - 2] < 0) ? -1 : 1; valuemap[MAXEDGE - 2][MAXEDGE - 1] *= (valuemap[MAXEDGE - 2][MAXEDGE - 1] < 0) ? -1 : 1; valuemap[MAXEDGE - 2][MAXEDGE - 2] *= (valuemap[MAXEDGE - 2][MAXEDGE - 2] < 0) ? -1 : 1; } }
int othello_ai::evaluation(othello16 o_t, int player) { int total_black = o_t.count(BLACK); int total_white = o_t.count(WHITE); std::string map = o_t.tostring(); int value = 0, i, j, num = 0, liberty_value = 0; if (total_black + total_white <= 48 ) { // 前期 for (i = 0; i < MAXEDGE; i ++) { for (j = 0; j < MAXEDGE; j ++) { num = i * MAXEDGE + j; if (map[num] == BLANK + '0') { continue; } value += ( ( o_t.mycolor == map[num] - '0' ) ? 1 : -1 ) * valuemap[i][j]; } } return value; } else if (total_black + total_white <= 192 ) { // 中期 for (i = 0; i < MAXEDGE; i ++) { for (j = 0; j < MAXEDGE; j ++) { num = i * MAXEDGE + j; if (map[num] == BLANK + '0') { continue; } value += ( ( o_t.mycolor == map[num] - '0' ) ? 1 : -1 ) * valuemap[i][j]; } } liberty_value += 4 * o_t.canmove(player) * ((player == o_t.mycolor) ? 1 : -1); return value + liberty_value; } }
void othello_ai::init(int color, string s){ o.init(color, s);//让sdk初始化局面 cost[0][0] = 9; cost[0][15] = 9; cost[15][0] = 9; cost[15][15] = 9; int i; int j; for(i = 2 ;i < 14 ; i ++) { cost[0][i] = 4; cost[i][0] = 4; cost[15][i] = 4; cost[i][15] = 4; } for(i = 0; i < 16; i ++) { cost[1][i] = -2; cost[14][i] = -2; cost[i][1] = -2; cost[i][14] = -2; } cost[1][1] = -20; cost[1][0] = -20; cost[0][1] = -20; cost[0][14] = -20; cost[1][14] = -20; cost[1][15] = -20; cost[14][0] = -20; cost[14][1] = -20; cost[15][1] = -20; cost[14][15] = -20; cost[14][14] = -20; cost[15][14] = -20; for(i = 2 ; i < 14; i ++) for(j = 2 ; j < 14 ; j ++) cost[i][j] = 1; }
int othello_ai::result(othello16 a) { int n1, n2, n3, n4; int num = 0;//棋子个数差 int canput;//可下子差(行动力) int bothputnum; int pos = 0;//布局差 int evaluation = 0; int potential_canput = 0; vector<pair<int, int> > t1 = o.allmove(o.mycolor); vector<pair<int, int> > t2 = o.allmove(3 - o.mycolor); canput = t1.size() - t2.size(); bothputnum = t1.size() + t2.size(); int total; string borad = a.tostring(); num = a.count(a.mycolor) - a.count(3 - a.mycolor);//棋子个数差 total = a.count(a.mycolor) + a.count(3 - a.mycolor); if(bothputnum == 0) { if(num > 0) return 99999; else if(num < 0) return -99999; else return 0; } int i,j,z; for(i = 0 ; i < 16 ; i ++) { for(j = 0 ; j < 16 ; j ++) { char t = borad.at(i * 16 + j); if(t == '0' + a.mycolor) { pos = pos + cost[i][j]; } else if(t == '0' + 3 - a.mycolor) { pos = pos - cost[i][j]; } } } int x[9]; for(i = 0 ; i < 16 ; i ++) { for(j = 0 ; j < 16 ; j ++) { for(z = 0 ; z < 9 ; z ++) { x[z] = i * 16 + j + (z/3 - 1) * 16 + (z%3 - 1); if(x[z] >= 0 && x[z] <= 255) { char t = borad.at(i * 16 + j); char t1 = borad.at(x[z]); if(t1 == '0') { if(t == '0' + a.mycolor) { potential_canput = potential_canput - 1; } else if(t == '0' + 3 - a.mycolor) { potential_canput = potential_canput + 1; } } } } } } if(total < 210) { n1 = 1; n2 = 4; n3 = 3; n4 = 4; } else { n1 = 4; n2 = 2; n3 = 1; n4 = 2; } evaluation =n1 * num + n2 * canput + n3 * pos + n4 * potential_canput; return evaluation; }
void othello_ai::move(int color, int x, int y){ o.play(color, x, y);//告诉sdk落子情况,改变局面 }
pair<int, int> othello_ai::get(){ vector<pair<int, int> > ans = o.allmove(o.mycolor); //获得所有可落子的位置,按先行后列的顺序 if(o.tostring().at(0) == '0' + o.mycolor) { cost[0][1] = 5; cost[1][0] = 5; } if(o.tostring().at(15) == '0' + o.mycolor) { cost[0][14] = 5; cost[1][15] = 5; } if(o.tostring().at(16*15) == '0' + o.mycolor) { cost[14][0] = 5; cost[15][1] = 5; } if(o.tostring().at(16*16 - 1) == '0' + o.mycolor) { cost[14][15] = 5; cost[15][14] = 5; } int len = ans.size(); int i; int max = 0; int pos = 0; int position = 0; for(i = 0 ; i < len ; i ++) { int n = cost[ans[i].first][ans[i].second]; if(max < n) { max = n; pos = i; } } if(max > 0) { std::cerr<<"----------------------------------------------------"<<"\n"; std::cerr<<"time : "<<get_time()<<" choose:"<<pos<<"\n"; return ans[pos]; } if(len == 1) { std::cerr<<"====================================================="<<"\n"; std::cerr<<"time : "<<get_time()<<" choose: 0"<<"\n"; return ans[0]; } max = 0; pos = 0; for(i = 0 ; i < len ; i ++) { temp = o; temp.play(temp.mycolor,ans[i].first,ans[i].second); int t = f(temp, 1, position, max); // std::cerr<<t<<" "<<"line: 1"<<"\n"; if(i == 0) max = t; position = 1; if(max < t) { max = t; pos = i; } } std::cerr<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<"\n"; std::cerr<<"time : "<<get_time()<<" choose:"<<pos<<"\n"; return ans[pos];//返回落子位置为第一个可下的点 }
int othello_ai::f(othello16 a, int line, int position, int var) { if(line == 4) { int x; x = result(a); return x; } else { int number = line % 2; int color; if(number == 1) color = 3 - a.mycolor; else color = a.mycolor; vector<pair<int, int> > t = a.allmove(color); int len = t.size(); int i = 0; int max = var; int pos = 0; if(position == 1) pos = 1; if(line == 2) pos = 0; for( ; i < len ; i ++) { temp = a; temp.play(color,t[i].first,t[i].second); int t = f(temp,line + 1, pos ,max); // std::cerr<<t<<" "<<" var: "<<var<<" "<<"line: "<<line + 1<<"\n"; if(i == 0) { max = t; } pos = 1; if(number == 1) { if(max > t) { max = t; } if(t <= var && position > 0) { // std::cerr<<"------"<<"\n"; return t; } } else { if(t >= var && position > 0) { // std::cerr<<"------"<<"\n"; return t; } if(max < t) { max = t; } } } // std::cerr<<"\n"; return max; } }
//初始化阶段,告知你所执子的颜色,和当前棋盘落子情况s void othello_ai::init(int color, std::string s){ o.init(color, s); init_valuemap(); std::cerr<<"My color is "<<o.mycolor<<std::endl; }
int othello_ai::turn(othello16 o_upper, int player, int backpoint, int depth) { // 检查超时 int runtime = get_time(); if (runtime > 1800) { std::cerr<<"time "<<runtime<<" overflow"<<std::endl; return (player == o.mycolor) ? MAXVALUE : -MAXVALUE; } -- depth; // std::cerr<<"player "<<player<<" my color "<<o.mycolor<<std::endl; othello16 o_t; int value_t, value_mark; std::pair<int, int> step_mark (-1, -1); // 初始化value_mark if (player == o.mycolor) { value_mark = -MAXVALUE; } else { value_mark = MAXVALUE; } std::vector< std::pair<int, int> > nextlist = o_upper.allmove(player); std::string map = o_upper.tostring(); if ( nextlist.size() == 0 ) { // 无可下点 std::cerr<<"nowhere to move "; return (player == o.mycolor) ? -MAXVALUE : MAXVALUE; } else if (depth <= 0) { // 到达最深层,计算估价函数值 // std::cerr<<"tree hight "<<depth<<std::endl; std::vector< std::pair<int, int> >::iterator it; for (it = nextlist.begin() ; it != nextlist.end(); ++ it) { // 初始化当前棋盘 o_t.init(o.mycolor, map); // 落子 o_t.play(player, (*it).first, (*it).second); // string2map(o_t.tostring()); value_t = evaluation(o_t, player); std::cerr<<std::endl<<"depth "<<DEPTH - depth<<":"; for (int k = 0; k < DEPTH - depth; k ++) std::cerr<<" "; std::cerr<<"leaf ("<<(*it).first<<", "<<(*it).second<<") value "<<value_t<<", "; if ( (player == o.mycolor && value_t >= value_mark) || (player != o.mycolor && value_t <= value_mark) ) { value_mark = value_t; } // 剪枝 if (player == o.mycolor && value_mark >= backpoint) { std::cerr<<"cut beta parent value "<<backpoint<<" current value "<<value_mark<<std::endl; return value_mark; } else if (player != o.mycolor && value_mark <= backpoint) { std::cerr<<"cut alpha parent value "<<backpoint<<" current value "<<value_mark<<std::endl; return value_mark; } } return value_mark; } else { // 普通情况 std::vector< std::pair<int, int> >::iterator it; for (it = nextlist.begin() ; it != nextlist.end(); ++ it) { // 初始化当前棋盘 o_t.init(o.mycolor, map); // 落子 o_t.play(player, (*it).first, (*it).second); // string2map(o_t.tostring()); value_t = turn(o_t, 3 - player, value_mark, depth); if (value_t == MAXVALUE || value_t == -MAXVALUE) { // 子问题超时 break; } std::cerr<<std::endl<<"depth "<<DEPTH - depth<<":"; for (int k = 0; k < DEPTH - depth; k ++) std::cerr<<" "; std::cerr<<"node ("<<(*it).first<<", "<<(*it).second<<") value "<<value_t<<", "; if ( (player == o.mycolor && value_t >= value_mark)// 己方落子 || (player != o.mycolor && value_t <= value_mark) ) {//对方落子 value_mark = value_t; step_mark.first = (*it).first; step_mark.second = (*it).second; } // 剪枝 if (player == o.mycolor && value_mark >= backpoint) { std::cerr<<"cut beta parent value "<<backpoint<<" current value "<<value_mark<<std::endl; break; } else if (player != o.mycolor && value_mark <= backpoint) { std::cerr<<"cut alpha parent value "<<backpoint<<" current value "<<value_mark<<std::endl; break; } } if (depth = DEPTH - 1) { next.first = step_mark.first; next.second = step_mark.second; } return value_mark; } }
//告知所有下子情况(包括你自己的落子情况) void othello_ai::move(int color, int x, int y){ o.play(color, x, y); }