// 绘制棋盘 static void DrawBoard(HDC hdc) { int x, y, xx, yy, sq, pc; HDC hdcTmp; // 画棋盘 hdcTmp = CreateCompatibleDC(hdc); SelectObject(hdcTmp, Xqwl.bmpBoard); BitBlt(hdc, 0, 0, BOARD_WIDTH, BOARD_HEIGHT, hdcTmp, 0, 0, SRCCOPY); // 画棋子 for (x = FILE_LEFT; x <= FILE_RIGHT; x ++) { for (y = RANK_TOP; y <= RANK_BOTTOM; y ++) { if (Xqwl.bFlipped) { xx = BOARD_EDGE + (FILE_FLIP(x) - FILE_LEFT) * SQUARE_SIZE; yy = BOARD_EDGE + (RANK_FLIP(y) - RANK_TOP) * SQUARE_SIZE; } else { xx = BOARD_EDGE + (x - FILE_LEFT) * SQUARE_SIZE; yy = BOARD_EDGE + (y - RANK_TOP) * SQUARE_SIZE; } sq = COORD_XY(x, y); pc = pos.ucpcSquares[sq]; if (pc != 0) { DrawTransBmp(hdc, hdcTmp, xx, yy, Xqwl.bmpPieces[pc]); } if (sq == Xqwl.sqSelected || sq == SRC(Xqwl.mvLast) || sq == DST(Xqwl.mvLast)) { DrawTransBmp(hdc, hdcTmp, xx, yy, Xqwl.bmpSelected); } } } DeleteDC(hdcTmp); }
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]; } } }