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

Windows编程

开发平台:

Visual C++

  1. /* function prototyping for internal functions */
  2. long CheckMiniMaxAlphaBeta(BOARD b, int t, int j, int d, long c, long p);
  3. #define JUMP_CONT_DEEPER 1
  4. /* --------------------------------------------------------------------------
  5. true if previous level should prune
  6. else false
  7. note: it would be possible to not prune equal qualities becuase they
  8.       may be used to increase the number of available suggestions
  9. statistics: 02:42:00  3-13-1994
  10.             if this function is return 0, six levels takes 33 seconds
  11.             if this function is implemented, six levels takes 9 seconds
  12. -------------------------------------------------------------------------- */
  13. inline int AlphaBeta(int t,long q, long c)
  14. {
  15.     pdebug(stddbg,"alpha-beta pruning t=%d q=%ld c=%ld %s(%d)n",t,q,c,__FILE__,__LINE__);
  16.     if (c > 0)
  17.         {
  18.         if (computer_color & t)
  19.             {
  20.             if (q > c)
  21.                 {
  22.                 pdebug(stddbg,"alpha-beta COMP pruning t=%d q=%ld c=%ld %s(%d)n",t,q,c,__FILE__,__LINE__);
  23.                 return 1;
  24.                 }
  25.             }
  26.         else
  27.             {
  28.             if (q < c)
  29.                 {
  30.                 pdebug(stddbg,"alpha-beta USER pruning t=%d q=%ld c=%ld %s(%d)n",t,q,c,__FILE__,__LINE__);
  31.                 return 1;
  32.                 }
  33.             }
  34.         }
  35.     return 0;
  36. }
  37. /* --------------------------------------------------------------------------
  38. The algorithm is basically a min-max tree
  39. This function takes care of whether or no we remember the Min or the Max
  40. In checkers terms this means the following:
  41.     if it is my (the computers) move, pick the move that results in the highest quality
  42.     if it is your move, remember the move that does the most damage (min quality)
  43. Parameters:
  44.     t    - whos turn it is (RED or BLACK)
  45.     type - the move type.  this parameter should be a constant from check.h
  46.            it says if it the move is a black or red move, and if the move is
  47.            a sliding or jumping move.  This also indicates if the move is a
  48.            move towards the left or towards the right.
  49.     number - this is the index into the move table derived from 'type'
  50.     d      - current recursion depth (debugging purposes only)
  51.     besttype    - type corresponding with bestquality
  52.     bestnumber  - number corresponding with bestquality
  53.     bestquality - either a min or a max of qualities depending on current turn
  54. -------------------------------------------------------------------------- */
  55. inline void RememberMove(int t,int type, int number, long q,int d,
  56.                          int* besttype, int* bestnumber, long* bestquality,
  57.                          long c, long p, int* fBreak)
  58. {
  59.     *fBreak = AlphaBeta(t,q,c);
  60.     if (q == *bestquality)
  61.         {
  62.         pdebug(stddbg,"evaluation (equal move) t=%d type=%d num=%d q=%ld d=%d %s(%d)n",t,type,number,q,d,__FILE__,__LINE__);
  63.         if (1 & rand()) return;
  64.         }
  65.     else if (computer_color & t)
  66.         {
  67.         pdebug(stddbg,"evaluation (computer) t=%d type=%d num=%d q=%ld d=%d %s(%d)n",t,type,number,q,d,__FILE__,__LINE__);
  68.         if (q < *bestquality) return;
  69.         }
  70.     else
  71.         {
  72.         pdebug(stddbg,"evaluation (opponent) t=%d type=%d num=%d q=%ld d=%d %s(%d)n",t,type,number,q,d,__FILE__,__LINE__);
  73.         if (*bestquality > 0 && q > *bestquality) return;
  74.         }
  75.     pdebug(stddbg,"RememberMove! evaluated t=%d type=%d num=%d q=%ld d=%d %s(%d)n",t,type,number,q,d,__FILE__,__LINE__);
  76.     *besttype = type;
  77.     *bestnumber = number;
  78.     *bestquality = q;
  79.     return;
  80. }
  81. /* --------------------------------------------------------------------------
  82. This function calls recurse for each possible jumping move for t's turn
  83. starting from the start position
  84. Note: there is special logic to crown men since landing in a crown position
  85.       can not continue the jump, but having a man that is already a king land
  86.       in a crown position can continue a jump.
  87. If the piece I am moving is a king, I look at both BLACK and RED moves.
  88. Parameters:
  89.     b     - board (value is not changed)
  90.     start - starting position
  91.     t     - whos turn it is (RED or BLACK)
  92.     besttype    - type corresponding with bestquality
  93.     bestnumber  - number corresponding with bestquality
  94.     bestquality - either a min or a max of qualities depending on current turn
  95. -------------------------------------------------------------------------- */
  96. int IterateJumps(BOARD b, int start, int t, int d,
  97.                  int* besttype, int* bestnumber, long* bestquality,
  98.                  long c, long p, int *fBreak)
  99. {
  100.     int moves_made=0;
  101.     long q;
  102.     SQUARE play_board[SQRS_MAX];
  103.     if ((RED == t) || (KING & b[start]))
  104.         {
  105.         AssertSz(b[start] & t, "chicken");
  106.         if (0 == b[red_jump_lut[start][1]] && red_jump_lut[start][1] && (next(t) & b[red_jump_lut[start][0]]))
  107.             {
  108.             pdebug(stddbg,"trying RED_JUMP0 std move %d %s(%d)n",start,__FILE__,__LINE__);
  109.             CopyBoard(b,play_board);
  110.             MakeMoveNoKing_RED_JUMP0(play_board,start);
  111.             if (0 == red_jump_lut[start][4] || (KING & play_board[red_jump_lut[start][1]]))
  112.                 {
  113.                 q = CheckMiniMaxAlphaBeta(play_board,t,red_jump_lut[start][1],JUMP_CONT_DEEPER+d,c,p);
  114.                 }
  115.             else
  116.                 {
  117.                 AssertSz(play_board[red_jump_lut[start][1]], "what the?");
  118.                 play_board[red_jump_lut[start][1]] |= red_jump_lut[start][4];
  119.                 q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  120.                 }
  121.             RememberMove(t,TYPE_RED_JUMP0,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  122.             ++moves_made;
  123.             }
  124.         if (0 == b[red_jump_lut[start][3]] && red_jump_lut[start][3] && (next(t) & b[red_jump_lut[start][2]]))
  125.             {
  126.             pdebug(stddbg,"trying RED_JUMP2 std move %d %s(%d)n",start,__FILE__,__LINE__);
  127.             CopyBoard(b,play_board);
  128.             MakeMoveNoKing_RED_JUMP2(play_board,start);
  129.             if (0 == red_jump_lut[start][4] || (KING & play_board[red_jump_lut[start][3]]))
  130.                 {
  131.                 q = CheckMiniMaxAlphaBeta(play_board,t,red_jump_lut[start][3],JUMP_CONT_DEEPER+d,c,p);
  132.                 }
  133.             else
  134.                 {
  135.                 AssertSz(play_board[red_jump_lut[start][3]], "this stupid piece");
  136.                 play_board[red_jump_lut[start][3]] |= red_jump_lut[start][4];
  137.                 q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  138.                 }
  139.             RememberMove(t,TYPE_RED_JUMP2,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  140.             ++moves_made;
  141.             }
  142.         }
  143.     if ((BLACK == t) || (KING & b[start]))
  144.         {
  145.         AssertSz(b[start] & t, "but... I thought it was my turn");
  146.         if (0 == b[black_jump_lut[start][1]] && black_jump_lut[start][1] && (next(t) & b[black_jump_lut[start][0]]))
  147.             {
  148.             pdebug(stddbg,"trying BLACK_JUMP0 std move %d %s(%d)n",start,__FILE__,__LINE__);
  149.             CopyBoard(b,play_board);
  150.             MakeMoveNoKing_BLACK_JUMP0(play_board,start);
  151.             if (0 == black_jump_lut[start][4] || (KING & play_board[black_jump_lut[start][1]]))
  152.                 {
  153.                 q = CheckMiniMaxAlphaBeta(play_board,t,black_jump_lut[start][1],JUMP_CONT_DEEPER+d,c,p);
  154.                 }
  155.             else
  156.                 {
  157.                 AssertSz(play_board[black_jump_lut[start][1]], "you thought it was who's turn?");
  158.                 play_board[black_jump_lut[start][1]] |= black_jump_lut[start][4];
  159.                 q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  160.                 }
  161.             RememberMove(t,TYPE_BLACK_JUMP0,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  162.             ++moves_made;
  163.             }
  164.         if (0 == b[black_jump_lut[start][3]] && black_jump_lut[start][3] && (next(t) & b[black_jump_lut[start][2]]))
  165.             {
  166.             pdebug(stddbg,"trying BLACK_JUMP2 std move %d %s(%d)n",start,__FILE__,__LINE__);
  167.             CopyBoard(b,play_board);
  168.             MakeMoveNoKing_BLACK_JUMP2(play_board,start);
  169.             if (0 == black_jump_lut[start][4] || (KING & play_board[black_jump_lut[start][3]]))
  170.                 {
  171.                 q = CheckMiniMaxAlphaBeta(play_board,t,black_jump_lut[start][3],JUMP_CONT_DEEPER+d,c,p);
  172.                 }
  173.             else
  174.                 {
  175.                 AssertSz(play_board[black_jump_lut[start][3]], "maggots");
  176.                 play_board[black_jump_lut[start][3]] |= black_jump_lut[start][4];
  177.                 q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  178.                 }
  179.             RememberMove(t,TYPE_BLACK_JUMP2,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  180.             ++moves_made;
  181.             }
  182.         }
  183.     return moves_made;
  184. }
  185. /* --------------------------------------------------------------------------
  186. This function calls recurse after making each possible sliding move for t's turn
  187. starting from the start position
  188. If the piece I am moving is a king, I look at both BLACK and RED moves.
  189. Parameters:
  190.     b     - board (value is not changed)
  191.     start - starting position
  192.     t     - whos turn it is (RED or BLACK)
  193.     besttype    - type corresponding with bestquality
  194.     bestnumber  - number corresponding with bestquality
  195.     bestquality - either a min or a max of qualities depending on current turn
  196. -------------------------------------------------------------------------- */
  197. int IterateMoves(BOARD b, int start, int t, int d,
  198.                  int* besttype, int* bestnumber, long* bestquality,
  199.                  long c, long p, int *fBreak)
  200. {
  201.     int moves_made=0;
  202.     long q;
  203.     SQUARE play_board[SQRS_MAX];
  204.     if ((RED == t) || (KING & b[start]))
  205.         {
  206.         AssertSz(b[start] & t, "I wish I could fly");
  207.         if (0 == b[red_lut[start][0]] && red_lut[start][0])
  208.             {
  209.             pdebug(stddbg,"trying RED0 std move %d %s(%d)n",start,__FILE__,__LINE__);
  210.             CopyBoard(b,play_board);
  211.             MakeMove_RED0(play_board,start);
  212.             q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  213.             RememberMove(t,TYPE_RED0,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  214.             ++moves_made;
  215.             }
  216.         if (0 == b[red_lut[start][2]] && red_lut[start][2])
  217.             {
  218.             pdebug(stddbg,"trying RED2 std move %d %s(%d)n",start,__FILE__,__LINE__);
  219.             CopyBoard(b,play_board);
  220.             MakeMove_RED2(play_board,start);
  221.             q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  222.             RememberMove(t,TYPE_RED2,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  223.             ++moves_made;
  224.             }
  225.         }
  226.     if ((BLACK == t) || (KING & b[start]))
  227.         {
  228.         AssertSz(b[start] & t, "what are you... ");
  229.         if (0 == b[black_lut[start][0]] && black_lut[start][0])
  230.             {
  231.             pdebug(stddbg,"trying BLACK0 std move %d %s(%d)n",start,__FILE__,__LINE__);
  232.             CopyBoard(b,play_board);
  233.             MakeMove_BLACK0(play_board,start);
  234.             q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  235.             RememberMove(t,TYPE_BLACK0,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  236.             ++moves_made;
  237.             }
  238.         if (0 == b[black_lut[start][2]] && black_lut[start][2])
  239.             {
  240.             pdebug(stddbg,"trying BLACK2 std move %d %s(%d)n",start,__FILE__,__LINE__);
  241.             CopyBoard(b,play_board);
  242.             MakeMove_BLACK2(play_board,start);
  243.             q = CheckMiniMaxAlphaBeta(play_board,next(t),0,1+d,p,*bestquality);
  244.             RememberMove(t,TYPE_BLACK2,start,q,d,besttype,bestnumber,bestquality,c,p,fBreak);
  245.             ++moves_made;
  246.             }
  247.         }
  248.     return moves_made;
  249. }
  250. /* --------------------------------------------------------------------------
  251. RECURSIVE MIN MAX ALGORITHM
  252. Parameters:
  253.     b - pointer to the board
  254.     t - whos turn it is (RED or BLACK)
  255.     j - space on board in which jump landed or zero if this
  256.         is not a jump continuation
  257.     d - depth of recursion
  258.     alpha-beta pruning parameters:
  259.     c - cutoff value for min max algorithm
  260.     p - threshold to be passed on to next level
  261. always returns the value of the best outcome of the board
  262. note: this function is to be called from within the checkers engine only
  263. note: this function evaluates moves based on the piece order structure defined
  264.       in lut.cpp.  The reason for this is that we gain two things by looking
  265.       at the best moves first:
  266.         1) pruning is more effective
  267.         2) if we must give up due to time constraint, we have already
  268.            evaluated some of the best moves.
  269. -------------------------------------------------------------------------- */
  270. long CheckMiniMaxAlphaBeta(BOARD b, int t, int j, int d, long c, long p)
  271. {
  272.     /* ----- stack variables ----- */
  273.     int  moves_made        = 0;
  274.     int  best_move_type    = -1;
  275.     int  best_move_number  = -1;
  276.     long best_move_quality = -1;
  277.     int  fBreak            = 0;
  278.     /* ----- debug ----- */
  279.     #ifdef DEBUG
  280.     debug=1;
  281.     if (debug && d < 7) PrintBoard(b,d);
  282.     #endif
  283.     AssertSz(b[0] == 0, "no b for my b my for my be my");
  284.     AssertSz(d >= 0, "i am so tired of this");
  285.     /* ----- if we have reached maximum depth, return now ----- */
  286.     if (d >= depth_maximum) return QualityOfBoard(b,next(t));
  287.     /* ----- iterate through all possible moves ----- */
  288.     if (0 == j)
  289.         {
  290.         int i;
  291.         pdebug(stddbg,"standard iteration d=%d %s(%d)n",d,__FILE__,__LINE__);
  292.         for (i=0;i<SQRS_MAX; i++)
  293.             {
  294.             int piece;
  295.             piece = (int) piece_order[i].m;
  296.             if (0 == (b[piece] & t)) continue; /* not our piece */
  297.             moves_made += IterateJumps(b,piece,t,d,&best_move_type,&best_move_number,&best_move_quality,c,p,&fBreak);
  298.             if (fBreak)
  299.                 {
  300.                 AssertSz(moves_made,"I'm pruning something I have not looked at...");
  301.                 break;
  302.                 }
  303.             }
  304.         if (0 == moves_made /* enforce the must jump rule */
  305.             #ifndef HIGH_PERFORMANCE
  306.                 || 0==rConfig.iMustJump
  307.             #endif
  308.             )
  309.             {
  310.             pdebug(stddbg,"could not find a jumping move to make %s(%d)n",__FILE__,__LINE__);
  311.             for (i=0;i<SQRS_MAX; i++)
  312.                 {
  313.                 int piece;
  314.                 piece = (int) piece_order[i].m;
  315.                 if (0 == (b[piece] & t)) continue; /* not our piece */
  316.                 moves_made += IterateMoves(b,piece,t,d,&best_move_type,&best_move_number,&best_move_quality,c,p,&fBreak);
  317.                 if (fBreak)
  318.                     {
  319.                     AssertSz(moves_made,"to Scottland, I have not been");
  320.                     break;
  321.                     }
  322.                 }
  323.             }
  324.         if (0 == moves_made)
  325.             {
  326.             pdebug(stddbg,"could not find a move to make (error not handled) %s(%d)n",__FILE__,__LINE__);
  327.             return QualityOfBoard(b,next(t));
  328.             }
  329.         return best_move_quality;
  330.         }
  331.     /* ----- handle jump continuation ----- */
  332.     pdebug(stddbg,"jump continuation d=%d %s(%d)n",d,__FILE__,__LINE__);
  333.     moves_made = IterateJumps(b,j,t,d,&best_move_type,&best_move_number,&best_move_quality,c,p,&fBreak);
  334.     // AssertSz(0==fBreak,"is this a valid assert?");
  335.     if (0==moves_made)
  336.         {
  337.         return CheckMiniMaxAlphaBeta(b,next(t),0,d,p,best_move_quality);
  338.         }
  339.     return best_move_quality;
  340. } /* end CheckMiniMaxAlphaBeta */