PRUNE.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:11k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /* --------------------------------------------------------------------------
  2. This function is qsort's callback
  3. to sort the moves based on quality
  4. -------------------------------------------------------------------------- */
  5. int __cdecl cmpgle(const void* elem1, const void* elem2)
  6. {
  7.     if (    (*(struct _piece_order_struct *)elem1).q     >
  8.             (*(struct _piece_order_struct *)elem2).q     )
  9.         return -1;
  10.     else if (    (*(struct _piece_order_struct *)elem1).q     <
  11.                  (*(struct _piece_order_struct *)elem2).q     )
  12.         return 1;
  13.     else
  14.         return 0;
  15. }
  16. /* --------------------------------------------------------------------------
  17. THIS IS THE CHECKERS ENGINE::
  18. b           - is the start board - it will be changed on return to
  19.               reflect the move or moves (in the case of a double jump)
  20.               made
  21. t           - is whos turn it is RED or BLACK
  22. j           - is jump continuation - must be 0
  23. prune_depth - how many levels to recurse to determine what to prune
  24. prune_size  - how many branches of the pruned tree to pursue (note:
  25.               each piece is considered as one branch even though it
  26.               it results in as many as four actual branches
  27. max_depth   - after the tree has been pruned how far should it recurse
  28.               must be greater than the prune_depth
  29. side effects:
  30.             Calls PrintBoard (debugio.cpp)
  31. note: we may wish to use iterative deepening here and base things on time
  32. -------------------------------------------------------------------------- */
  33. long PlayBestMove(BOARD b, int t, int j, int d,
  34.                     int prune_depth, int prune_size, int max_depth)
  35. {
  36.     /* ----- stack variables ----- */
  37.     int  moves_made        =  0;
  38.     int  best_move_type    = -1;
  39.     int  best_move_number  = -1;
  40.     long best_move_quality = -1;
  41.     long alpha_beta_c      = -1;
  42.     int  fBreak            = 0;
  43.     int  i;
  44.     #ifdef DEBUG
  45.     int  jumps_made        =  0;
  46.     #endif
  47.     AssertSz(prune_size <= SQRS_MAX, "me. prune size is way to big");
  48.     AssertSz(prune_size > 1, "how much? prune size is way to small");
  49.     AssertSz(0 == b[0], "b sub zero should equal zero");
  50.     AssertSz(0 == b[SQRS_MAX-1], "b sub MAX-1 should equal zero");
  51.     /* ----- debug ----- */
  52.     if (debug && d < 3) PrintBoard(b,d);
  53.     /* ----- initialize tables and variables ----- */
  54.     depth_maximum = max_depth;
  55.     computer_color = t;
  56.     for (i=0; i<SQRS_MAX; i++)
  57.         {
  58.         piece_order[i].m = (SQUARE) i;
  59.         piece_order[i].q = -1;
  60.         }
  61.     /* ----- seed the random number generator ----- */
  62.     #ifdef DEBUG
  63.     srand( 0 );
  64.     #else
  65.     #ifdef TEST
  66.     srand( 0 );
  67.     #else
  68.     srand( (unsigned)time( NULL ) );
  69.     #endif
  70.     #endif
  71.     /* ----- iterate through all possible moves AT PRUNE_DEPTH ----- */
  72.     if (prune_depth > 0)
  73.         {
  74.         depth_maximum = prune_depth;
  75.         pdebug(stddbgmin,"PlayBestMove d=%d %s(%d)n",d,__FILE__,__LINE__);
  76.         for (i=0;i<SQRS_MAX; i++)
  77.             {
  78.             int piece;
  79.             piece = (int) piece_order[i].m;
  80.             if (0 == (b[piece] & t)) continue; /* not our piece */
  81.             moves_made += IterateJumps(b,piece,t,d,&best_move_type,&best_move_number,&piece_order[i].q,alpha_beta_c,best_move_quality,&fBreak);
  82.             AssertSz(0 == fBreak,"I must not prune at the root level of the tree");
  83.             #ifdef DEBUG
  84.             jumps_made += moves_made;
  85.             #endif
  86.             }
  87.         if (0 == moves_made /* enforce the must jump rule */
  88.             #ifndef HIGH_PERFORMANCE
  89.                 || 0==rConfig.iMustJump
  90.             #endif
  91.             )
  92.             {
  93.             pdebug(stddbgmin,"could not find a jumping move to make %s(%d)n",__FILE__,__LINE__);
  94.             for (i=0;i<SQRS_MAX; i++)
  95.                 {
  96.                 int piece;
  97.                 piece = (int) piece_order[i].m;
  98.                 if (0 == (b[piece] & t)) continue; /* not our piece */
  99.                 moves_made += IterateMoves(b,piece,t,d,&best_move_type,&best_move_number,&piece_order[i].q,alpha_beta_c,best_move_quality,&fBreak);
  100.                 AssertSz(0 == fBreak,"I ought not prune at the root level of the tree");
  101.                 }
  102.             }
  103.         if (0 == moves_made)
  104.             {
  105.             pdebug(stddbgmin,"could not find a move to make (error not handled) %s(%d)n",__FILE__,__LINE__);
  106.             AssertSz(0, "I give up... why don't you go instead");
  107.             }
  108.         }
  109.     else
  110.         {
  111.         moves_made = 1000;
  112.         prune_size = SQRS_MAX;
  113.         }
  114.     /* ----- if we only have one move to make, dont recurse again ----- */
  115.     if (moves_made > 1)
  116.         {
  117.         /* ----- shuffle the moves ----- */
  118.         for (i=SQRS_MAX-1; i > 0; i--)
  119.             {
  120.             int r;
  121.             struct _piece_order_struct temp;
  122.             /* ----- pick a random interchange ----- */
  123.             r = ((unsigned int)rand()) % ((unsigned int) i);
  124.             /* ----- swap the order ----- */
  125.             temp = piece_order[i];
  126.             piece_order[i] = piece_order[r];
  127.             piece_order[r] = temp;
  128.             }
  129.         /* ----- sort the move table based on the move qualities
  130.                 of each move that we tried ----- */
  131.         pdebug(stddbgmin,"sorting... %s(%d)n",__FILE__,__LINE__);
  132.         qsort(piece_order,SQRS_MAX, sizeof(struct _piece_order_struct), cmpgle);
  133.         pdebug(stddbgmin,"done sorting. %s(%d)n",__FILE__,__LINE__);
  134.         /* ----- recurse the pruned board to a deeper level ----- */
  135. continue_jump:
  136.         moves_made = 0;
  137.         depth_maximum = max_depth;
  138.         pdebug(stddbgmin,"recursing pruned PlayBestMove d=%d %s(%d)n",d,__FILE__,__LINE__);
  139.         for (i=0;i<prune_size; i++)
  140.             {
  141.             int piece;
  142.             piece = (int) piece_order[i].m;
  143.             if (0 == (b[piece] & t)) continue; /* not our piece */
  144.             moves_made += IterateJumps(b,piece,t,d,&best_move_type,&best_move_number,&best_move_quality,alpha_beta_c,best_move_quality,&fBreak);
  145.             AssertSz(0 == fBreak,"x2 I must not prune at the root level of the tree");
  146.             #ifdef DEBUG
  147.             jumps_made += moves_made;
  148.             #endif
  149.             }
  150.         if ((0 == moves_made
  151.             #ifndef HIGH_PERFORMANCE
  152.                 || 0==rConfig.iMustJump
  153.             #endif
  154.             )&& 0 == j) /* enforce the must jump rule */
  155.             {
  156.             pdebug(stddbgmin,"could not find a jumping move to make %s(%d)n",__FILE__,__LINE__);
  157.             for (i=0;i<prune_size; i++)
  158.                 {
  159.                 int piece;
  160.                 piece = (int) piece_order[i].m;
  161.                 pdebug(stddbgmin,"Next move piece=%d i=%d %s(%d)n",piece,i,__FILE__,__LINE__);
  162.                 if (0 == (b[piece] & t)) continue; /* not our piece */
  163.                 moves_made += IterateMoves(b,piece,t,d,&best_move_type,&best_move_number,&best_move_quality,alpha_beta_c,best_move_quality,&fBreak);
  164.                 AssertSz(0 == fBreak,"x3 I must not prune at the root level of the tree");
  165.                 }
  166.             }
  167.         if (0 == moves_made)
  168.             {
  169.             pdebug(stddbgmin,"could not find a move to make (error ! handled) %s(%d)n",__FILE__,__LINE__);
  170.             #ifdef DEBUG
  171.             AssertSz(jumps_made, "Your turn.  I mean.  Can I move or something? .. nevermind .. why don't you just go");
  172.             #endif
  173.             }
  174.         }
  175.     /* ----- do the first step of any jumps ----- */
  176.     if (best_move_type > TYPE_BLACK2)
  177.         {
  178.         switch (best_move_type)
  179.             {
  180.             case TYPE_RED_JUMP0   :
  181.                 j = red_jump_lut[best_move_number][1]  ;
  182.                 piece_order[0].m = (SQUARE) j;
  183.                 MakeMoveNoKing_RED_JUMP0(b,best_move_number);
  184.                 if (0 != red_jump_lut[best_move_number][4] && !(KING & b[red_jump_lut[best_move_number][1]])) goto no_jump;
  185.                 break;
  186.             case TYPE_RED_JUMP2   :
  187.                 j = red_jump_lut[best_move_number][3]  ;
  188.                 piece_order[0].m = (SQUARE) j;
  189.                 MakeMoveNoKing_RED_JUMP2(b,best_move_number);
  190.                 if (0 != red_jump_lut[best_move_number][4] && !(KING & b[red_jump_lut[best_move_number][3]])) goto no_jump;
  191.                 break;
  192.             case TYPE_BLACK_JUMP0 :
  193.                 j = black_jump_lut[best_move_number][1];
  194.                 piece_order[0].m = (SQUARE) j;
  195.                 MakeMoveNoKing_BLACK_JUMP0(b,best_move_number);
  196.                 if (0 != black_jump_lut[best_move_number][4] && !(KING & b[black_jump_lut[best_move_number][1]])) goto no_jump;
  197.                 break;
  198.             case TYPE_BLACK_JUMP2 :
  199.                 j = black_jump_lut[best_move_number][3];
  200.                 piece_order[0].m = (SQUARE) j;
  201.                 MakeMoveNoKing_BLACK_JUMP2(b,best_move_number);
  202.                 if (0 != black_jump_lut[best_move_number][4] && !(KING & b[black_jump_lut[best_move_number][3]])) goto no_jump;
  203.                 break;
  204.             default:
  205.                 AssertSz(0, "end case");
  206.                 break;
  207.             }
  208.         /* ----- re-initialize ----- */
  209.         prune_size        =  1; /* ! force it to use only the jump destination as a move */
  210.         moves_made        =  0;
  211.         best_move_type    = -1;
  212.         best_move_number  = -1;
  213.         best_move_quality = -1;
  214.         goto continue_jump;
  215.         }
  216. no_jump:
  217.     switch (best_move_type)
  218.         {
  219.         case TYPE_RED0        :
  220.             MakeMove_RED0(b,best_move_number);
  221.             break;
  222.         case TYPE_RED2        :
  223.             MakeMove_RED2(b,best_move_number);
  224.             break;
  225.         case TYPE_BLACK0      :
  226.             MakeMove_BLACK0(b,best_move_number);
  227.             break;
  228.         case TYPE_BLACK2      :
  229.             MakeMove_BLACK2(b,best_move_number);
  230.             break;
  231.         case TYPE_RED_JUMP0   :
  232.         case TYPE_RED_JUMP2   :
  233.         case TYPE_BLACK_JUMP0 :
  234.         case TYPE_BLACK_JUMP2 :
  235.             pdebug(stddbgmin,"skipping a jump move in IO %s(%d)n",__FILE__,__LINE__);
  236.             break;
  237.         default:
  238.             pdebug(stddbgmin,"printmove did not make the move on the board %s(%d)n",__FILE__,__LINE__);
  239.             pdebug(stddbgmin,"this could be a jump continuation %s(%d)n",__FILE__,__LINE__);
  240.             break;
  241.         }
  242.     // make sure everything is kinged (in case we jumped to this point)
  243.     if (RED & b[1]) b[1] |= KING;
  244.     if (RED & b[2]) b[2] |= KING;
  245.     if (RED & b[3]) b[3] |= KING;
  246.     if (RED & b[4]) b[4] |= KING;
  247.     if (BLACK & b[32]) b[32] |= KING;
  248.     if (BLACK & b[31]) b[31] |= KING;
  249.     if (BLACK & b[30]) b[30] |= KING;
  250.     if (BLACK & b[29]) b[29] |= KING;
  251.     /* ----- return to caller ----- */
  252.     return best_move_quality;
  253. }