From d48632423eaec04423765784058597cd4892c118 Mon Sep 17 00:00:00 2001 From: "dev@dev.com" Date: Sat, 5 Jun 2021 21:49:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chesspi/chesspi.h | 23 +++++++++----------- chesspi/chesspi_ai.cpp | 46 ++++++++++++++++++++++++++++++--------- chesspi/chesspi_rules.cpp | 37 ++++++++++++++++--------------- chesspi/main.cpp | 12 ++++++---- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/chesspi/chesspi.h b/chesspi/chesspi.h index c4e7b82..d7abcf0 100644 --- a/chesspi/chesspi.h +++ b/chesspi/chesspi.h @@ -33,30 +33,27 @@ struct chess_node{ //走位和显示 //------------------------------------------- -std::vector expand_node(const chess_node & root, const int side); - +std::vector expand_node(const chess_node & root, const int side,bool onlykill=false); +//移动棋子 bool move_node(const chess_node & root, chess_node * new_node,const int oldx, const int oldy,const int newx, const int newy,const int side); - - -bool build_node(const int coordx[/*32*/], const int coordy[/*32*/],const int alive[/*32*/],const int idx, const int newx, const int newy,const int side,int map_coords[/*11*/][10],chess_node * node); - +//转换松散坐标为棋子的压缩格式坐标 +bool build_node(const int coordx[/*32*/], const int coordy[/*32*/],const int alive[/*32*/],const int idx, const int newx, const int newy,const int side,int map_coords[/*11*/][10],chess_node * node,bool onlykill=false); bool build_node(const int coordx[/*32*/], const int coordy[/*32*/],const int alive[/*32*/],const int side,chess_node * node); - +//打印棋盘 void print_node(const chess_node & node,const chess_node & old_node); - +//X镜像反转坐标 void mirror_coordx(const unsigned char cod1[/*32*/],unsigned char cod2[/*32*/]); - +//计算棋盘哈希 std::vector node2hash(const std::vector & nodes); - std::string node2hash(const unsigned char cod[/*32*/], const unsigned int alive); - //AI //------------------------------------------- +//计算走位代价 float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int alive[/*32*/],const int killed,const int idx); - +//建立决策树 std::vector build_tree(const chess_node & root, const int side,const std::vector & history); - +//评估并返回走位 size_t judge_tree(std::vector & tree); #endif // CHESSPI_H diff --git a/chesspi/chesspi_ai.cpp b/chesspi/chesspi_ai.cpp index 3389be8..606e87a 100644 --- a/chesspi/chesspi_ai.cpp +++ b/chesspi/chesspi_ai.cpp @@ -11,7 +11,18 @@ #include #include "chesspi.h" +int max_depth = 5; +//棋子代价 static const unsigned int table_cost[16] = {100000,150,150,150,150,150,150,500,500,150,150,100,100,100,100,100}; +/*! + * \brief calc_cost 计算走位后,idx棋子被击杀的代价,并返回 + * \param coordx 当前各个棋子的X坐标 + * \param coordy 当前各个棋子的Y坐标 + * \param alive 当前各个棋子的存活标记 + * \param killed 总击杀数 + * \param idx 被击杀的棋子 + * \return 击杀代价 + */ float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int alive[/*32*/],const int killed,const int idx) { @@ -30,7 +41,7 @@ float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int ali if (alive[(idx-1)/2*2+1] || alive [(idx-1)/2*2+2]) rescost *= 2; break; - //马战线挺进,以及后期击杀价值高 + //马战线挺进,以及后期击杀价值高 case 5: case 6: if (idx<16 ) @@ -39,7 +50,7 @@ float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int ali rescost *= 1+((11-coordy[idx])/3.0); rescost *= 1 + killed / 4.0; break; - //车战线击杀高 + //车战线击杀高 case 7: case 8: if (idx<16 ) @@ -47,7 +58,7 @@ float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int ali else rescost *= 1+((11-coordy[idx])/3.0); break; - //炮前期击杀高 + //炮前期击杀高 case 9: case 10: if (idx<16 ) @@ -56,7 +67,7 @@ float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int ali rescost *= 1+((11-coordy[idx])/3.0); rescost *= 1 + (32 - killed) / 4.0; break; - //卒过河击杀高 + //卒过河击杀高 case 11: case 12: case 13: @@ -88,9 +99,12 @@ std::vector build_tree(const chess_node & root, const int side,const tree.push_back(root); tree[0].side = side % 2; tree[0].depth = 0; - + int max_nodes = 1000*1000*32; size_t curr_i = 0; - size_t max_nodes = 1024*1024*16; + + //要停留在敌走的偶数步 + const int stop_depth = (max_depth+1)/2 * 2; + while (tree.size()<=max_nodes && curr_i build_tree(const chess_node & root, const int side,const for (int i=0;i()); std::atomic new_appends (0); + #pragma omp parallel for for (int i=curr_i;i=max_nodes) continue; const unsigned char clock = tree[i].depth; + if (clock >= stop_depth) + continue; + bool onlykill = clock >=max_depth; const int tid = omp_get_thread_num(); if ((tree[i].alive & 0x00010001)==0x00010001) { const int curr_side = (side + clock) % 2; std::vector next_status = - expand_node(tree[i],curr_side); + expand_node(tree[i],curr_side,onlykill); const size_t sz = next_status.size(); for (size_t j=0;j build_tree(const chess_node & root, const int side,const bool needI = false; #pragma omp critical { - if (dict.find(ha)==dict.end()) + if (dict.find(ha)==dict.end() && clock+1 <= max_depth) { needI = true; dict.insert(ha); } + else if (dict.find(ha)==dict.end() && clock + 1 <= stop_depth) + { + if (next_status[j].jump_cost[0]+next_status[j].jump_cost[1]>0) + { + needI = true; + dict.insert(ha); + } + } } if (needI) { @@ -135,7 +161,7 @@ std::vector build_tree(const chess_node & root, const int side,const ++new_appends; if (new_appends%1000==0) { - printf ("Thinking.%d... \r",int(new_appends+ts)); + printf ("Thinking.%d:%d... \r",i,int(new_appends+ts)); } } } @@ -149,7 +175,7 @@ std::vector build_tree(const chess_node & root, const int side,const curr_i += (ts - curr_i); } - printf ("Depth = %d \n",tree.rbegin()->depth); + printf ("\nDepth = %d \n",tree.rbegin()->depth); return tree; } diff --git a/chesspi/chesspi_rules.cpp b/chesspi/chesspi_rules.cpp index 5694792..834eebf 100644 --- a/chesspi/chesspi_rules.cpp +++ b/chesspi/chesspi_rules.cpp @@ -9,7 +9,7 @@ #include "chesspi.h" -std::vector expand_node(const chess_node & r_root, const int side) +std::vector expand_node(const chess_node & r_root, const int side,bool onlykill) { const chess_node * root = &r_root; static const int valid_directs[16] = {4,4,4,4,4,8,8,4,4,4,4,3,3,3,3,3}; @@ -36,7 +36,7 @@ std::vector expand_node(const chess_node & r_root, const int side) int coordx[32]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int coordy[32]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int alive[32]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - + int alive_total = 0; if (side==0) { for (int i=0;i<32;++i) @@ -44,6 +44,7 @@ std::vector expand_node(const chess_node & r_root, const int side) coordx[i] = root->coords[i] >> 4; coordy[i] = root->coords[i] & 0x0f; alive[i] = (root->alive & (1< expand_node(const chess_node & r_root, const int side) coordx[i] = 10 - x; coordy[i] = 11 - y; alive[i] = (root->alive & (1< expand_node(const chess_node & r_root, const int side) //有限层级优先顺序 // * 帅士士相相马马车车炮炮兵兵兵兵兵 將仕仕象象馬馬車車砲砲卒卒卒卒卒 - const int order[5][16] = { + const int order[4][16] = { + {7,8,9,10,5,6,11,12,14,15,1,2,3,4,13,0}, + {7,8,9,10,5,6,11,12,1,2,3,4,14,15,13,0}, + {7,8,9,10,5,6,1,2,3,4,11,12,14,15,13,0}, {7,8,9,10,5,6,11,12,14,15,1,2,3,4,13,0}, - {9,10,7,8,5,6,11,12,14,15,1,2,3,4,13,0}, - {5,6,9,10,7,8,11,12,14,15,1,2,3,4,13,0}, - {9,6,5,7,10,8,1,2,3,4,11,12,14,15,13,0}, - {10,8,5,7,9,6,1,2,3,4,11,12,14,15,13,0} }; - int curr_od = rand() % 5; + int curr_od = (32 - alive_total)/8; for (int oi=0;oi<16;++oi) { const int i = order[curr_od][oi]; @@ -91,7 +92,7 @@ std::vector expand_node(const chess_node & r_root, const int side) continue; chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); } @@ -105,7 +106,7 @@ std::vector expand_node(const chess_node & r_root, const int side) { chess_node node; if (!build_node(coordx,coordy,alive,i,coordx[16],coordy[16], - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); } @@ -122,7 +123,7 @@ std::vector expand_node(const chess_node & r_root, const int side) continue; chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); } @@ -141,7 +142,7 @@ std::vector expand_node(const chess_node & r_root, const int side) continue; chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); } @@ -160,7 +161,7 @@ std::vector expand_node(const chess_node & r_root, const int side) continue; chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); } @@ -179,7 +180,7 @@ std::vector expand_node(const chess_node & r_root, const int side) break; chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); if (map_coords[new_y][new_x]) @@ -205,7 +206,7 @@ std::vector expand_node(const chess_node & r_root, const int side) { chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) break; res.push_back(node); } @@ -231,7 +232,7 @@ std::vector expand_node(const chess_node & r_root, const int side) continue; chess_node node; if (!build_node(coordx,coordy,alive,i,new_x,new_y, - side,map_coords,&node)) + side,map_coords,&node,onlykill)) continue; res.push_back(node); } @@ -249,7 +250,7 @@ bool build_node(const int old_coordx[/*32*/], const int old_coordy[/*32*/], const int old_alive[/*32*/], const int idx, const int new_x, const int new_y,const int side, int map_coords[/*11*/][10], -chess_node * node) +chess_node * node,bool onlykill) { //不能吃自己的棋子 if (map_coords[new_y][new_x]>=1 && map_coords[new_y][new_x]<=16) @@ -270,6 +271,8 @@ chess_node * node) assert(map_coords[new_y][new_x]); alive[map_coords[new_y][new_x]-1] = 0; } + else if (onlykill) + return false; //反转 if (side==0) diff --git a/chesspi/main.cpp b/chesspi/main.cpp index 9532742..cd09c29 100644 --- a/chesspi/main.cpp +++ b/chesspi/main.cpp @@ -9,7 +9,7 @@ #include #include #include "chesspi.h" - +extern int max_depth; int main() { //初始棋局 @@ -18,7 +18,6 @@ int main() int alive[32]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; srand(time(0)); - printf ("Side(0=RED,1=BLACK):"); chess_node root; if (!build_node(coordx,coordy,alive,0,&root)) @@ -26,10 +25,15 @@ int main() printf ("创建棋局失败!\n"); return 0; } - - //回合 int side = 0; + int nodesInM = 0; + printf ("Side(0=RED,1=BLACK):"); scanf("%d",&side); + printf ("Max Depth(default 5):"); + scanf("%d",&nodesInM); + if (nodesInM>=4 && nodesInM<10) + max_depth = nodesInM; + //回合 side %=2; if (side <0) side = 1; -- GitLab