void ChessBoard::generatePawnMoves(ChessBoard& board, int sqSrc, Moves& mvs) { int sqDst; if (board.m_sdPlayer != SQ_SIDE(sqSrc)) { sqDst = sqSrc - 1; if (IN_BOARD(sqDst) && board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } sqDst = sqSrc + 1; if (IN_BOARD(sqDst) && board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } } if (board.m_sdPlayer==0) { sqDst = sqSrc - 16; } else{ sqDst = sqSrc + 16; } if (IN_BOARD(sqDst) && board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } }
inline int BlackPawnMoves(const BOARD *board, SQUARE orig, MOVE *poss_moves, int nmoves, char noncaptures) { SQUARE dest = orig + ROW_DOWN; if(noncaptures && IN_BOARD(dest) && board->squares[dest] == EMPTY){ if(ROW(dest) == FIRST_ROW){ if(poss_moves) poss_moves[nmoves] = Move(B_QUEEN, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(B_KNIGHT, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(B_ROOK, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(B_BISHOP, dest, orig); nmoves++; }else{ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; if(ROW(dest) == SIXTH_ROW){ dest = dest + ROW_DOWN; if(IN_BOARD(dest)){ if(board->squares[dest] == EMPTY){ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } } } } } for(int i = 0; b_pawn_capture[i]; i++){ dest = orig + b_pawn_capture[i]; if(IN_BOARD(dest)){ if(board->squares[dest] == EMPTY){ if(dest == board->en_passant){ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } }else if(GET_COLOR(board->squares[dest])){ if(ROW(dest) == FIRST_ROW){ if(poss_moves) poss_moves[nmoves] = Move(B_QUEEN, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(B_KNIGHT, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(B_ROOK, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(B_BISHOP, dest, orig); nmoves++; }else{ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } } } } return nmoves; }
inline int WhitePawnMoves(const BOARD *board, SQUARE orig, MOVE *poss_moves, int nmoves, char noncaptures) { SQUARE dest = orig + ROW_UP; if(noncaptures && IN_BOARD(dest) && board->squares[dest] == EMPTY){ if(ROW(dest) == EIGHT_ROW){ /*Promotions.*/ if(poss_moves) poss_moves[nmoves] = Move(W_QUEEN, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(W_KNIGHT, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(W_ROOK, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(W_BISHOP, dest, orig); nmoves++; }else{ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; if(ROW(dest) == THIRD_ROW){ dest = dest + ROW_UP; if(IN_BOARD(dest) && board->squares[dest] == EMPTY){ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } } } } for(int i = 0; w_pawn_capture[i]; i++){ dest = orig + w_pawn_capture[i]; if(IN_BOARD(dest)){ if(board->squares[dest] == EMPTY){ if(dest == board->en_passant){ /*Captures en Passant.*/ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } }else if(GET_COLOR(board->squares[dest]) == BLACK){ if(ROW(dest) == EIGHT_ROW){ if(poss_moves) poss_moves[nmoves] = Move(W_QUEEN, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(W_KNIGHT, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(W_ROOK, dest, orig); nmoves++; if(poss_moves) poss_moves[nmoves] = Move(W_BISHOP, dest, orig); nmoves++; }else{ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } } } } return nmoves; }
inline int NonSlidingMoves(const BOARD *board, SQUARE orig, MOVE *poss_moves, int nmoves, char noncaptures) { PIECE p = board->squares[orig]; for(const SQUARE *d = deltas[p]; *d; d++){ SQUARE dest = orig + *d; if(IN_BOARD(dest)){ if(board->squares[dest] == EMPTY){ if(noncaptures){ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } }else if(GET_COLOR(board->squares[dest]) != GET_COLOR(p)){ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } } } return nmoves; }
inline int SlidingMoves(const BOARD *board, SQUARE orig, MOVE *poss_moves, int nmoves, char noncaptures) { PIECE p = board->squares[orig]; for(const SQUARE *d = deltas[p]; *d; d++){ for(SQUARE dest = orig + *d; IN_BOARD(dest); dest += *d){ if(board->squares[dest] == EMPTY){ if(noncaptures){ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; } }else if(GET_COLOR(board->squares[dest]) != GET_COLOR(p)) { /*Different color Piece, capture, stop sliding.*/ if(poss_moves) poss_moves[nmoves] = Move(0, dest, orig); nmoves++; break; }else break; /*same color piece, stop sliding.*/ } } return nmoves; }
void ChessBoard::generateBishopMoves(ChessBoard& board, int sqSrc, Moves& mvs) { static const int ccBishopDelta[4] = {-34, -30, 30, 34}; static const int ccBishopPin[4] = {-17, -15, 15, 17}; for(int i=0; i<4; i++) { int sqDst = sqSrc + ccBishopDelta[i]; if (!IN_BOARD(sqDst)) continue; int sqPin = sqSrc + ccBishopPin[i]; if (board.m_data[sqPin]) continue; if (SAME_HALF(sqSrc, sqDst)) { if (board.isInBoard(sqDst) && board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } } } }
void ChessBoard::generateKnightMoves(ChessBoard& board, int sqSrc, Moves& mvs) { static const int ccKingDelta[4] = {-16, -1, 1, 16}; static const int ccKnightDelta[4][2] = {{-33, -31}, {-18, 14}, {-14, 18}, {31, 33}}; for (int i=0; i<4; i++) { int sqPin = sqSrc + ccKingDelta[i]; if (IN_BOARD(sqPin) && board.m_data[sqPin]==0) { //马腿没有东西 for(int j=0; j<2; j++) { int sqDst = sqSrc + ccKnightDelta[i][j]; if (board.isInBoard(sqDst) && board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } } } } }
void ChessBoard::generateCannonMoves(ChessBoard& board, int sqSrc, Moves& mvs) { static const int delta[4] = {-16, -1, 1, 16}; for(int i=0; i<4; i++) { int sqDst = sqSrc; bool skiped = false; while (true) { sqDst += delta[i]; if (!IN_BOARD(sqDst)) break; if (!board.m_data[sqDst]) { if (!skiped) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } } else{ if (!skiped) { skiped = true; } else{ int pc = board.m_data[sqDst]; if (pc!=0) { if (board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } } break; } } } } }
void ChessBoard::generateRookMoves(ChessBoard& board, int sqSrc, Moves& mvs) { static const int delta[4] = {-16, -1, 1, 16}; for(int i=0; i<4; i++) { int sqDst = sqSrc; while (true) { sqDst += delta[i]; if (!IN_BOARD(sqDst)) break; if (!board.m_data[sqDst]) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } else{ if (board.canMove(board, sqSrc, sqDst)) { mvs.append(ChessBoard::mv(sqSrc, sqDst)); } break; } } } }
BOOL _PositionStruct::Checked() const { int i, j, sqSrc, sqDst; int pcSelfSide, pcOppSide, pcDst, nDelta; pcSelfSide = SIDE_TAG(sdPlayer); pcOppSide = OPP_SIDE_TAG(sdPlayer); for (sqSrc = 0; sqSrc < 256; sqSrc ++) { if (ucpcSquares[sqSrc] != pcSelfSide + PIECE_KING) { continue; } if (ucpcSquares[SQUARE_FORWARD(sqSrc, sdPlayer)] == pcOppSide + PIECE_PAWN) { return TRUE; } for (nDelta = -1; nDelta <= 1; nDelta += 2) { if (ucpcSquares[sqSrc + nDelta] == pcOppSide + PIECE_PAWN) { return TRUE; } } for (i = 0; i < 4; i ++) { if (ucpcSquares[sqSrc + ccAdvisorDelta[i]] != 0) { continue; } for (j = 0; j < 2; j ++) { pcDst = ucpcSquares[sqSrc + ccKnightCheckDelta[i][j]]; if (pcDst == pcOppSide + PIECE_KNIGHT) { return TRUE; } } } for (i = 0; i < 4; i ++) { nDelta = ccKingDelta[i]; sqDst = sqSrc + nDelta; while (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (pcDst != 0) { if (pcDst == pcOppSide + PIECE_ROOK || pcDst == pcOppSide + PIECE_KING) { return TRUE; } break; } sqDst += nDelta; } sqDst += nDelta; while (IN_BOARD(sqDst)) { int pcDst = ucpcSquares[sqDst]; if (pcDst != 0) { if (pcDst == pcOppSide + PIECE_CANNON) { return TRUE; } break; } sqDst += nDelta; } } return FALSE; } return FALSE; }
int _PositionStruct::GenerateMovesFrom(int sqSrc, int *mvs, BOOL bCapture) const { int i, j, nGenMoves, nDelta, sqDst; int pcSelfSide, pcOppSide, pcSrc, pcDst; nGenMoves = 0; pcSelfSide = SIDE_TAG(sdPlayer); pcOppSide = OPP_SIDE_TAG(sdPlayer); if (sqSrc >= 0 && sqSrc < 256) { pcSrc = ucpcSquares[sqSrc]; if ((pcSrc & pcSelfSide) == 0) { return nGenMoves; } switch (pcSrc - pcSelfSide) { case PIECE_KING: for (i = 0; i < 4; i ++) { sqDst = sqSrc + ccKingDelta[i]; if (!IN_FORT(sqDst)) { continue; } pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } break; case PIECE_ADVISOR: for (i = 0; i < 4; i ++) { sqDst = sqSrc + ccAdvisorDelta[i]; if (!IN_FORT(sqDst)) { continue; } pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } break; case PIECE_BISHOP: for (i = 0; i < 4; i ++) { sqDst = sqSrc + ccAdvisorDelta[i]; if (!(IN_BOARD(sqDst) && HOME_HALF(sqDst, sdPlayer) && ucpcSquares[sqDst] == 0)) { continue; } sqDst += ccAdvisorDelta[i]; pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } break; case PIECE_KNIGHT: for (i = 0; i < 4; i ++) { sqDst = sqSrc + ccKingDelta[i]; if (ucpcSquares[sqDst] != 0) { continue; } for (j = 0; j < 2; j ++) { sqDst = sqSrc + ccKnightDelta[i][j]; if (!IN_BOARD(sqDst)) { continue; } pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } } break; case PIECE_ROOK: for (i = 0; i < 4; i ++) { nDelta = ccKingDelta[i]; sqDst = sqSrc + nDelta; while (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (pcDst == 0) { if (!bCapture) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } else { if ((pcDst & pcOppSide) != 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } break; } sqDst += nDelta; } } break; case PIECE_CANNON: for (i = 0; i < 4; i ++) { nDelta = ccKingDelta[i]; sqDst = sqSrc + nDelta; while (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (pcDst == 0) { if (!bCapture) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } else { break; } sqDst += nDelta; } sqDst += nDelta; while (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (pcDst != 0) { if ((pcDst & pcOppSide) != 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } break; } sqDst += nDelta; } } break; case PIECE_PAWN: sqDst = SQUARE_FORWARD(sqSrc, sdPlayer); if (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } if (AWAY_HALF(sqSrc, sdPlayer)) { for (nDelta = -1; nDelta <= 1; nDelta += 2) { sqDst = sqSrc + nDelta; if (IN_BOARD(sqDst)) { pcDst = ucpcSquares[sqDst]; if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) { mvs[nGenMoves] = MOVE(sqSrc, sqDst); nGenMoves ++; } } } } break; } } return nGenMoves; }
void PreGenInit(void) { int i, j, k, n, sqSrc, sqDst; RC4Struct rc4; SlideMoveStruct smv; SlideMaskStruct sms; // 首先初始化Zobrist键值表 rc4.InitZero(); PreGen.zobrPlayer.InitRC4(rc4); for (i = 0; i < 14; i ++) { for (j = 0; j < 256; j ++) { PreGen.zobrTable[i][j].InitRC4(rc4); } } // 然后初始化屏蔽位行和屏蔽位列 // 注:位行和位列不包括棋盘以外的位,所以就会频繁使用"+/- RANK_TOP/FILE_LEFT" for (sqSrc = 0; sqSrc < 256; sqSrc ++) { if (IN_BOARD(sqSrc)) { PreGen.wBitRankMask[sqSrc] = 1 << (FILE_X(sqSrc) - FILE_LEFT); PreGen.wBitFileMask[sqSrc] = 1 << (RANK_Y(sqSrc) - RANK_TOP); } else { PreGen.wBitRankMask[sqSrc] = 0; PreGen.wBitFileMask[sqSrc] = 0; } } // 然后生成车炮横向的预置数组(数组的应用参阅"pregen.h") for (i = 0; i < 9; i ++) { for (j = 0; j < 512; j ++) { // 初始化借助于“位行”的车和炮的着法预生成数组,包括以下几个步骤: // 1. 初始化临时变量"SlideMoveTab",假设没有着法,用起始格填充 smv.ucNonCap[0] = smv.ucNonCap[1] = smv.ucRookCap[0] = smv.ucRookCap[1] = smv.ucCannonCap[0] = smv.ucCannonCap[1] = smv.ucSuperCap[0] = smv.ucSuperCap[1] = i + FILE_LEFT; sms.wNonCap = sms.wRookCap = sms.wCannonCap = sms.wSuperCap = 0; // 提示:参阅"pregen.h",...[0]表示最大一格,向右移动和下移动都用[0],反之亦然 // 2. 考虑向右移动的目标格,填充...[0], for (k = i + 1; k <= 8; k ++) { if ((j & (1 << k)) != 0) { smv.ucRookCap[0] = FILE_DISP(k + FILE_LEFT); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[0] = FILE_DISP(k + FILE_LEFT); sms.wNonCap |= 1 << k; } for (k ++; k <= 8; k ++) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[0] = FILE_DISP(k + FILE_LEFT); sms.wCannonCap |= 1 << k; break; } } for (k ++; k <= 8; k ++) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[0] = FILE_DISP(k + FILE_LEFT); sms.wSuperCap |= 1 << k; break; } } // 3. 考虑向左移动的目标格,填充...[1] for (k = i - 1; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucRookCap[1] = FILE_DISP(k + FILE_LEFT); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[1] = FILE_DISP(k + FILE_LEFT); sms.wNonCap |= 1 << k; } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[1] = FILE_DISP(k + FILE_LEFT); sms.wCannonCap |= 1 << k; break; } } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[1] = FILE_DISP(k + FILE_LEFT); sms.wSuperCap |= 1 << k; break; } } // 4. 为"smv"和"sms"的值作断言 __ASSERT_BOUND_2(3, smv.ucNonCap[1], smv.ucNonCap[0], 11); __ASSERT_BOUND_2(3, smv.ucRookCap[1], smv.ucRookCap[0], 11); __ASSERT_BOUND_2(3, smv.ucCannonCap[1], smv.ucCannonCap[0], 11); __ASSERT_BOUND_2(3, smv.ucSuperCap[1], smv.ucSuperCap[0], 11); __ASSERT_BITRANK(sms.wNonCap); __ASSERT_BITRANK(sms.wRookCap); __ASSERT_BITRANK(sms.wCannonCap); __ASSERT_BITRANK(sms.wSuperCap); // 5. 将临时变量"smv"和"sms"拷贝到着法预生成数组中 PreGen.smvRankMoveTab[i][j] = smv; PreGen.smsRankMaskTab[i][j] = sms; } } // 然后生成车炮纵向的预置数组(数组的应用参阅"pregen.h") for (i = 0; i < 10; i ++) { for (j = 0; j < 1024; j ++) { // 初始化借助于“位列”的车和炮的着法预生成数组,包括以下几个步骤: // 1. 初始化临时变量"smv",假设没有着法,用起始格填充 smv.ucNonCap[0] = smv.ucNonCap[1] = smv.ucRookCap[0] = smv.ucRookCap[1] = smv.ucCannonCap[0] = smv.ucCannonCap[1] = smv.ucSuperCap[0] = smv.ucSuperCap[1] = (i + RANK_TOP) * 16; sms.wNonCap = sms.wRookCap = sms.wCannonCap = sms.wSuperCap = 0; // 2. 考虑向下移动的目标格,填充...[0] for (k = i + 1; k <= 9; k ++) { if ((j & (1 << k)) != 0) { smv.ucRookCap[0] = RANK_DISP(k + RANK_TOP); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[0] = RANK_DISP(k + RANK_TOP); sms.wNonCap |= 1 << k; } for (k ++; k <= 9; k ++) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[0] = RANK_DISP(k + RANK_TOP); sms.wCannonCap |= 1 << k; break; } } for (k ++; k <= 9; k ++) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[0] = RANK_DISP(k + RANK_TOP); sms.wSuperCap |= 1 << k; break; } } // 3. 考虑向上移动的目标格,填充...[1] for (k = i - 1; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucRookCap[1] = RANK_DISP(k + RANK_TOP); sms.wRookCap |= 1 << k; break; } smv.ucNonCap[1] = RANK_DISP(k + RANK_TOP); sms.wNonCap |= 1 << k; } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucCannonCap[1] = RANK_DISP(k + RANK_TOP); sms.wCannonCap |= 1 << k; break; } } for (k --; k >= 0; k --) { if ((j & (1 << k)) != 0) { smv.ucSuperCap[1] = RANK_DISP(k + RANK_TOP); sms.wSuperCap |= 1 << k; break; } } // 4. 为"smv"和"sms"的值作断言 __ASSERT_BOUND_2(3, smv.ucNonCap[1] >> 4, smv.ucNonCap[0] >> 4, 12); __ASSERT_BOUND_2(3, smv.ucRookCap[1] >> 4, smv.ucRookCap[0] >> 4, 12); __ASSERT_BOUND_2(3, smv.ucCannonCap[1] >> 4, smv.ucCannonCap[0] >> 4, 12); __ASSERT_BOUND_2(3, smv.ucSuperCap[1] >> 4, smv.ucSuperCap[0] >> 4, 12); __ASSERT_BITFILE(sms.wNonCap); __ASSERT_BITFILE(sms.wRookCap); __ASSERT_BITFILE(sms.wCannonCap); __ASSERT_BITFILE(sms.wSuperCap); // 5. 将临时变量"smv"和"sms"拷贝到着法预生成数组中 PreGen.smvFileMoveTab[i][j] = smv; PreGen.smsFileMaskTab[i][j] = sms; } } // 接下来生成着法预生成数组,连同将军预判数组 for (sqSrc = 0; sqSrc < 256; sqSrc ++) { if (IN_BOARD(sqSrc)) { // 生成帅(将)的着法预生成数组 n = 0; for (i = 0; i < 4; i ++) { sqDst = sqSrc + cnKingMoveTab[i]; if (IN_FORT(sqDst)) { PreGen.ucsqKingMoves[sqSrc][n] = sqDst; n ++; } } __ASSERT(n <= 4); PreGen.ucsqKingMoves[sqSrc][n] = 0; // 生成仕(士)的着法预生成数组 n = 0; for (i = 0; i < 4; i ++) { sqDst = sqSrc + cnAdvisorMoveTab[i]; if (IN_FORT(sqDst)) { PreGen.ucsqAdvisorMoves[sqSrc][n] = sqDst; n ++; } } __ASSERT(n <= 4); PreGen.ucsqAdvisorMoves[sqSrc][n] = 0; // 生成相(象)的着法预生成数组,包括象眼数组 n = 0; for (i = 0; i < 4; i ++) { sqDst = sqSrc + cnBishopMoveTab[i]; if (IN_BOARD(sqDst) && SAME_HALF(sqSrc, sqDst)) { PreGen.ucsqBishopMoves[sqSrc][n] = sqDst; PreGen.ucsqBishopPins[sqSrc][n] = BISHOP_PIN(sqSrc, sqDst); n ++; } } __ASSERT(n <= 4); PreGen.ucsqBishopMoves[sqSrc][n] = 0; // 生成马的着法预生成数组,包括马腿数组 n = 0; for (i = 0; i < 8; i ++) { sqDst = sqSrc + cnKnightMoveTab[i]; if (IN_BOARD(sqDst)) { PreGen.ucsqKnightMoves[sqSrc][n] = sqDst; PreGen.ucsqKnightPins[sqSrc][n] = KNIGHT_PIN(sqSrc, sqDst); n ++; } } __ASSERT(n <= 8); PreGen.ucsqKnightMoves[sqSrc][n] = 0; // 生成兵(卒)的着法预生成数组 for (i = 0; i < 2; i ++) { n = 0; sqDst = SQUARE_FORWARD(sqSrc, i); sqDst = sqSrc + (i == 0 ? -16 : 16); if (IN_BOARD(sqDst)) { PreGen.ucsqPawnMoves[i][sqSrc][n] = sqDst; n ++; } if (AWAY_HALF(sqSrc, i)) { for (j = -1; j <= 1; j += 2) { sqDst = sqSrc + j; if (IN_BOARD(sqDst)) { PreGen.ucsqPawnMoves[i][sqSrc][n] = sqDst; n ++; } } } __ASSERT(n <= 3); PreGen.ucsqPawnMoves[i][sqSrc][n] = 0; } } } // 最后清空局面预评价结构 memset(&PreEval, 0, sizeof(PreEvalStruct)); PreEval.bPromotion = false; // 缺省是不允许升变的 }
int AttackingPieces(const BOARD *board, SQUARE square, COLOR attacking_color, SQUARE *attacking_sqs) { int attackers = 0; SQUARE attacking_sq = 0; PIECE N_attacker, B_attacker, R_attacker, Q_attacker, K_attacker; if (attacking_color) { for (int i = 0; w_pawn_capture[i]; i++) { attacking_sq = square - w_pawn_capture[i]; if (IN_BOARD(attacking_sq) && board->squares[attacking_sq] == W_PAWN) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; } } N_attacker = W_KNIGHT, B_attacker = W_BISHOP, R_attacker = W_ROOK, Q_attacker = W_QUEEN, K_attacker = W_KING; } else { for (int i = 0; b_pawn_capture[i]; i++) { attacking_sq = square - b_pawn_capture[i]; if (IN_BOARD(attacking_sq) && board->squares[attacking_sq] == B_PAWN) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; } } N_attacker = B_KNIGHT, B_attacker = B_BISHOP, R_attacker = B_ROOK, Q_attacker = B_QUEEN, K_attacker = B_KING; } for (int i = 0; knight_delta[i]; i++) { attacking_sq = square + knight_delta[i]; if (IN_BOARD(attacking_sq)) { if (board->squares[attacking_sq] == N_attacker) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; } } } for (int i = 0; bishop_delta[i]; i++) { for (attacking_sq = square + bishop_delta[i]; IN_BOARD(attacking_sq); attacking_sq += bishop_delta[i]) { if (board->squares[attacking_sq] == EMPTY) { continue; } else if (board->squares[attacking_sq] == B_attacker) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; break; } else if (board->squares[attacking_sq] == Q_attacker) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; break; } else break; /*Piece other than bishop/queen, or different color, stop sliding*/ } } for (int i = 0; rook_delta[i]; i++) { for (attacking_sq = square + rook_delta[i]; IN_BOARD(attacking_sq); attacking_sq += rook_delta[i]) { if (board->squares[attacking_sq] == EMPTY) { continue; } else if (board->squares[attacking_sq] == R_attacker) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; break; } else if (board->squares[attacking_sq] == Q_attacker) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; break; } else break; } } for (int i = 0; king_delta[i]; i++) { attacking_sq = square + king_delta[i]; if (IN_BOARD(attacking_sq)) { if (board->squares[attacking_sq] == K_attacker) { if (attacking_sqs) attacking_sqs[attackers++] = attacking_sq; else return 1; break; } } } return attackers; }
bool ChessBoard::isChecked() { //qDebug()<<"Enter isChecked"; // 找到棋盘上的帅(将),再做以下判断: int pcKing = PIECE_KING + (m_sdPlayer + 1) * 8; //qDebug()<<"pcKing="<<pcKing; for (int sqSrc = 0; sqSrc < 256; sqSrc ++) { if (m_data[sqSrc]!=pcKing) { continue; } // 1. 判断是否被对方的兵(卒)将军 int pcOppPawn = PIECE_PAWN + (2 - m_sdPlayer) * 8; static const int delta[2][4] = {{-1, 1, -16},{-1, 1, 16}}; for(int i=0; i<4; i++) { int sqDst = sqSrc + delta[m_sdPlayer][i]; if (m_data[sqDst]==pcOppPawn) { //qDebug()<<"pawn IsChecked true"; return true; } } // 2. 判断是否被对方的马将军(以仕(士)的步长当作马腿) int pcOppKnight = PIECE_KNIGHT + (2 - m_sdPlayer) * 8; static const int ccPinDelta[4] = {-17, -15, 15, 17}; static const int ccKnightDelta[4][2] = {{-33, -18}, {-31, -14}, {14, 31}, {18, 33}}; for (int i=0; i<4; i++) { //qDebug()<<"kinght PinDelta="<<ccPinDelta[i]; int sqPin = sqSrc + ccPinDelta[i]; if (m_data[sqPin]) continue; for (int j=0; j<2; j++) { int sqDst = sqSrc + ccKnightDelta[i][j]; if (m_data[sqDst]==pcOppKnight) { //qDebug()<<"knight IsChecked true"; return true; } } } // 3. 判断是否被对方的车或炮将军(包括将帅对脸) int pcOppRook = PIECE_ROOK + (2 - m_sdPlayer) * 8; int pcOppCannon = PIECE_CANNON + (2 - m_sdPlayer) * 8; int pcOppKing = PIECE_KING + (2 - m_sdPlayer) * 8; static const int rookDelta[4] = {-16, -1, 1, 16}; for(int i=0; i<4; i++) { int sqDst = sqSrc; bool skiped = false; while (true) { sqDst += rookDelta[i]; if (!IN_BOARD(sqDst)) break; int pcDst = m_data[sqDst]; if (!skiped && (pcDst==pcOppRook || pcDst==pcOppKing)) { //qDebug()<<"rook IsChecked true"; return true; } if (pcDst) { if (!skiped) { skiped = true; } else{ if (pcDst==pcOppCannon) { //qDebug()<<"cannon IsChecked true"; return true; } break; } } } } } return false; }
void PositionStruct::PreEvaluate(void) { int i, sq, nMidgameValue, nWhiteAttacks, nBlackAttacks, nWhiteSimpleValue, nBlackSimpleValue; uint8_t ucvlPawnPiecesAttacking[256], ucvlPawnPiecesAttackless[256]; if (!bInit) { bInit = true; // 初始化"PreEvalEx.cPopCnt16"数组,只需要初始化一次 for (i = 0; i < 65536; i ++) { PreEvalEx.cPopCnt16[i] = PopCnt16(i); } } // 首先判断局势处于开中局还是残局阶段,方法是计算各种棋子的数量,按照车=6、马炮=3、其它=1相加。 nMidgameValue = PopCnt32(this->dwBitPiece & BOTH_BITPIECE(ADVISOR_BITPIECE | BISHOP_BITPIECE | PAWN_BITPIECE)) * OTHER_MIDGAME_VALUE; nMidgameValue += PopCnt32(this->dwBitPiece & BOTH_BITPIECE(KNIGHT_BITPIECE | CANNON_BITPIECE)) * KNIGHT_CANNON_MIDGAME_VALUE; nMidgameValue += PopCnt32(this->dwBitPiece & BOTH_BITPIECE(ROOK_BITPIECE)) * ROOK_MIDGAME_VALUE; // 使用二次函数,子力很少时才认为接近残局 nMidgameValue = (2 * TOTAL_MIDGAME_VALUE - nMidgameValue) * nMidgameValue / TOTAL_MIDGAME_VALUE; __ASSERT_BOUND(0, nMidgameValue, TOTAL_MIDGAME_VALUE); PreEval.vlAdvanced = (TOTAL_ADVANCED_VALUE * nMidgameValue + TOTAL_ADVANCED_VALUE / 2) / TOTAL_MIDGAME_VALUE; __ASSERT_BOUND(0, PreEval.vlAdvanced, TOTAL_ADVANCED_VALUE); for (sq = 0; sq < 256; sq ++) { if (IN_BOARD(sq)) { PreEval.ucvlWhitePieces[0][sq] = PreEval.ucvlBlackPieces[0][SQUARE_FLIP(sq)] = (uint8_t) ((cucvlKingPawnMidgameAttacking[sq] * nMidgameValue + cucvlKingPawnEndgameAttacking[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); PreEval.ucvlWhitePieces[3][sq] = PreEval.ucvlBlackPieces[3][SQUARE_FLIP(sq)] = (uint8_t) ((cucvlKnightMidgame[sq] * nMidgameValue + cucvlKnightEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); PreEval.ucvlWhitePieces[4][sq] = PreEval.ucvlBlackPieces[4][SQUARE_FLIP(sq)] = (uint8_t) ((cucvlRookMidgame[sq] * nMidgameValue + cucvlRookEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); PreEval.ucvlWhitePieces[5][sq] = PreEval.ucvlBlackPieces[5][SQUARE_FLIP(sq)] = (uint8_t) ((cucvlCannonMidgame[sq] * nMidgameValue + cucvlCannonEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); ucvlPawnPiecesAttacking[sq] = PreEval.ucvlWhitePieces[0][sq]; ucvlPawnPiecesAttackless[sq] = (uint8_t) ((cucvlKingPawnMidgameAttackless[sq] * nMidgameValue + cucvlKingPawnEndgameAttackless[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); } } for (i = 0; i < 16; i ++) { PreEvalEx.vlHollowThreat[i] = cvlHollowThreat[i] * (nMidgameValue + TOTAL_MIDGAME_VALUE) / (TOTAL_MIDGAME_VALUE * 2); __ASSERT_BOUND(0, PreEvalEx.vlHollowThreat[i], cvlHollowThreat[i]); PreEvalEx.vlCentralThreat[i] = cvlCentralThreat[i]; } // 然后判断各方是否处于进攻状态,方法是计算各种过河棋子的数量,按照车马2炮兵1相加。 nWhiteAttacks = nBlackAttacks = 0; for (i = SIDE_TAG(0) + KNIGHT_FROM; i <= SIDE_TAG(0) + ROOK_TO; i ++) { if (this->ucsqPieces[i] != 0 && BLACK_HALF(this->ucsqPieces[i])) { nWhiteAttacks += 2; } } for (i = SIDE_TAG(0) + CANNON_FROM; i <= SIDE_TAG(0) + PAWN_TO; i ++) { if (this->ucsqPieces[i] != 0 && BLACK_HALF(this->ucsqPieces[i])) { nWhiteAttacks ++; } } for (i = SIDE_TAG(1) + KNIGHT_FROM; i <= SIDE_TAG(1) + ROOK_TO; i ++) { if (this->ucsqPieces[i] != 0 && WHITE_HALF(this->ucsqPieces[i])) { nBlackAttacks += 2; } } for (i = SIDE_TAG(1) + CANNON_FROM; i <= SIDE_TAG(1) + PAWN_TO; i ++) { if (this->ucsqPieces[i] != 0 && WHITE_HALF(this->ucsqPieces[i])) { nBlackAttacks ++; } } // 如果本方轻子数比对方多,那么每多一个轻子(车算2个轻子)威胁值加2。威胁值最多不超过8。 nWhiteSimpleValue = PopCnt16(this->wBitPiece[0] & ROOK_BITPIECE) * 2 + PopCnt16(this->wBitPiece[0] & (KNIGHT_BITPIECE | CANNON_BITPIECE)); nBlackSimpleValue = PopCnt16(this->wBitPiece[1] & ROOK_BITPIECE) * 2 + PopCnt16(this->wBitPiece[1] & (KNIGHT_BITPIECE | CANNON_BITPIECE)); if (nWhiteSimpleValue > nBlackSimpleValue) { nWhiteAttacks += (nWhiteSimpleValue - nBlackSimpleValue) * 2; } else { nBlackAttacks += (nBlackSimpleValue - nWhiteSimpleValue) * 2; } nWhiteAttacks = MIN(nWhiteAttacks, TOTAL_ATTACK_VALUE); nBlackAttacks = MIN(nBlackAttacks, TOTAL_ATTACK_VALUE); PreEvalEx.vlBlackAdvisorLeakage = TOTAL_ADVISOR_LEAKAGE * nWhiteAttacks / TOTAL_ATTACK_VALUE; PreEvalEx.vlWhiteAdvisorLeakage = TOTAL_ADVISOR_LEAKAGE * nBlackAttacks / TOTAL_ATTACK_VALUE; __ASSERT_BOUND(0, nWhiteAttacks, TOTAL_ATTACK_VALUE); __ASSERT_BOUND(0, nBlackAttacks, TOTAL_ATTACK_VALUE); __ASSERT_BOUND(0, PreEvalEx.vlBlackAdvisorLeakage, TOTAL_ADVISOR_LEAKAGE); __ASSERT_BOUND(0, PreEvalEx.vlBlackAdvisorLeakage, TOTAL_ADVISOR_LEAKAGE); for (sq = 0; sq < 256; sq ++) { if (IN_BOARD(sq)) { PreEval.ucvlWhitePieces[1][sq] = PreEval.ucvlWhitePieces[2][sq] = (uint8_t) ((cucvlAdvisorBishopThreatened[sq] * nBlackAttacks + (PreEval.bPromotion ? cucvlAdvisorBishopPromotionThreatless[sq] : cucvlAdvisorBishopThreatless[sq]) * (TOTAL_ATTACK_VALUE - nBlackAttacks)) / TOTAL_ATTACK_VALUE); PreEval.ucvlBlackPieces[1][sq] = PreEval.ucvlBlackPieces[2][sq] = (uint8_t) ((cucvlAdvisorBishopThreatened[SQUARE_FLIP(sq)] * nWhiteAttacks + (PreEval.bPromotion ? cucvlAdvisorBishopPromotionThreatless[SQUARE_FLIP(sq)] : cucvlAdvisorBishopThreatless[SQUARE_FLIP(sq)]) * (TOTAL_ATTACK_VALUE - nWhiteAttacks)) / TOTAL_ATTACK_VALUE); PreEval.ucvlWhitePieces[6][sq] = (uint8_t) ((ucvlPawnPiecesAttacking[sq] * nWhiteAttacks + ucvlPawnPiecesAttackless[sq] * (TOTAL_ATTACK_VALUE - nWhiteAttacks)) / TOTAL_ATTACK_VALUE); PreEval.ucvlBlackPieces[6][sq] = (uint8_t) ((ucvlPawnPiecesAttacking[SQUARE_FLIP(sq)] * nBlackAttacks + ucvlPawnPiecesAttackless[SQUARE_FLIP(sq)] * (TOTAL_ATTACK_VALUE - nBlackAttacks)) / TOTAL_ATTACK_VALUE); } } for (i = 0; i < 16; i ++) { PreEvalEx.vlWhiteBottomThreat[i] = cvlBottomThreat[i] * nBlackAttacks / TOTAL_ATTACK_VALUE; PreEvalEx.vlBlackBottomThreat[i] = cvlBottomThreat[i] * nWhiteAttacks / TOTAL_ATTACK_VALUE; } // 检查预评价是否对称 #ifndef NDEBUG for (sq = 0; sq < 256; sq ++) { if (IN_BOARD(sq)) { for (i = 0; i < 7; i ++) { __ASSERT(PreEval.ucvlWhitePieces[i][sq] == PreEval.ucvlWhitePieces[i][SQUARE_MIRROR(sq)]); __ASSERT(PreEval.ucvlBlackPieces[i][sq] == PreEval.ucvlBlackPieces[i][SQUARE_MIRROR(sq)]); } } } for (i = FILE_LEFT; i <= FILE_RIGHT; i ++) { __ASSERT(PreEvalEx.vlWhiteBottomThreat[i] == PreEvalEx.vlWhiteBottomThreat[FILE_FLIP(i)]); __ASSERT(PreEvalEx.vlBlackBottomThreat[i] == PreEvalEx.vlBlackBottomThreat[FILE_FLIP(i)]); } #endif // 调整不受威胁方少掉的仕(士)相(象)分值 this->vlWhite = ADVISOR_BISHOP_ATTACKLESS_VALUE * (TOTAL_ATTACK_VALUE - nBlackAttacks) / TOTAL_ATTACK_VALUE; this->vlBlack = ADVISOR_BISHOP_ATTACKLESS_VALUE * (TOTAL_ATTACK_VALUE - nWhiteAttacks) / TOTAL_ATTACK_VALUE; // 如果允许升变,那么不受威胁的仕(士)相(象)分值就少了一半 if (PreEval.bPromotion) { this->vlWhite /= 2; this->vlBlack /= 2; } // 最后重新计算子力位置分 for (i = 16; i < 32; i ++) { sq = this->ucsqPieces[i]; if (sq != 0) { __ASSERT_SQUARE(sq); this->vlWhite += PreEval.ucvlWhitePieces[PIECE_TYPE(i)][sq]; } } for (i = 32; i < 48; i ++) { sq = this->ucsqPieces[i]; if (sq != 0) { __ASSERT_SQUARE(sq); this->vlBlack += PreEval.ucvlBlackPieces[PIECE_TYPE(i)][sq]; } } }