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; } }
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; }
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::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; } }