int GetDrawFactor(POS *p, int sd) 
{
  int op = Opp(sd);

  // Case 1: KPK with edge pawn (else KBPK recognizer would break)

  if (PcMatNone(p, sd)
  && PcMatNone(p, op)
  && p->cnt[sd][P] == 1    // TODO: all pawns of a stronger side on a rim
  && p->cnt[op][P] == 0) { // TODO: accept pawns for a weaker side

    if (p->Pawns(sd) & FILE_H_BB
    &&  p->Kings(op) & bbKingBlockH[sd]) return 0;

    if (p->Pawns(sd) & FILE_A_BB
    &&  p->Kings(op) & bbKingBlockA[sd]) return 0;
  }

  // Case 2: KBPK(P) draws with edge pawn and wrong bishop

  if (PcMatB(p, sd)
	  && PcMatNone(p, op)
	  && p->cnt[sd][P] == 1) { // TODO: all pawns of a stronger side on a rim

	  if (p->Pawns(sd) & FILE_H_BB
		  && NotOnBishColor(p, sd, REL_SQ(H8, sd))
		  && p->Kings(op)  & bbKingBlockH[sd]) return 0;

	  if (p->Pawns(sd) & FILE_A_BB
		  && NotOnBishColor(p, sd, REL_SQ(A8, sd))
		  && p->Kings(op)  & bbKingBlockA[sd]) return 0;
  }

  // Case 3: KBP vs Km
  // drawn when defending king stands on pawn's path and can't be driven out 
  // by a bishop (must be dealt with before opposite bishops ending)

  if (PcMatB(p, sd)
  && PcMat1Minor(p, op)
  && p->cnt[sd][P] == 1
  && p->cnt[op][P] == 0
  && (SqBb(p->king_sq[op]) & BB.GetFrontSpan(p->Pawns(sd), sd))
  && NotOnBishColor(p, sd, p->king_sq[op]) ) 
     return 0;

  // Case 4: Bishops of opposite color

  if (PcMatB(p, sd) && PcMatB(p, op) && DifferentBishops(p)) {

     // 4a: single bishop cannot win without pawns
     if (p->cnt[sd][P] == 0) return 0;

     // 4b: different bishops with a single pawn on the own half of the board
     if (p->cnt[sd][P] == 1
     &&  p->cnt[op][P] == 0) {
       if (bbHomeZone[sd] & p->Pawns(sd)) return 0;

     // TODO: 4c: distant bishop controls a square on pawn's path
     }

     // 4d: halve the score for pure BOC endings
     return 32;
  }


  if (p->cnt[sd][P] == 0) {

    // Case 5: low and almost equal material with no pawns

    if (p->cnt[op][P] == 0) {
      if (PcMatRm(p, sd) && PcMatRm(p, op)) return 8;
      if (PcMatR (p, sd) && PcMatR (p, op)) return 8;
      if (PcMatQ (p, sd) && PcMatQ (p, op)) return 8;
      if (PcMat2Minors(p, sd) && PcMatR(p, op)) return 8;
    }

	// Case 6: two knights
	if (PcMatNN(p, sd)) {
		if (p->cnt[op][P] == 0) return 0;
		else return 4;
	}
     
    // Case 7: K(m) vs K(m) or Km vs Kp(p)
    if (p->cnt[sd][Q] + p->cnt[sd][R] == 0 && p->cnt[sd][B] + p->cnt[sd][N] < 2 ) 
    return 0;

    // Case 8: KR vs Km(p)
    if (PcMatR(p, sd) && PcMat1Minor(p, op) ) return 16;

    // Case 9: KRm vs KR(p)
    if (p->cnt[sd][R] == 1 && p->cnt[sd][Q] == 0 &&  p->cnt[sd][B] + p->cnt[sd][N] == 1
    &&  PcMatR(p, op) ) return 16;

    // Case 10: KQm vs KQ(p)
    if (p->cnt[sd][Q] == 1 && p->cnt[sd][R] == 0 && p->cnt[sd][B] + p->cnt[sd][N] == 1
    &&  PcMatQ(p, op) ) return 32;

    // Case 11: Kmm vs KB(p)
    if (PcMat2Minors(p,sd) &&  PcMatB(p, op) ) return 16;

    // Case 12: KBN vs Km(p)
    if (PcMatBN(p, sd) &&  PcMat1Minor(p, op) ) return 16;

	// Case 13: KRR vs KRm(p)
	if (PcMatRR(p, sd) && PcMatRm(p, op)) return 16;

	// Case 14: KRRm vs KRR(p)
	if (p->cnt[sd][R] == 2 && p->cnt[sd][Q] == 0 && p->cnt[sd][B] + p->cnt[sd][N] == 1
    && PcMatRR(p, op)) return 16;
  }

  // Case 15: KRP vs KR

  if (PcMatR(p, sd) && PcMatR(p, op) && p->cnt[sd][P] == 1 && p->cnt[op][P] == 0) {

    // 15a: good defensive position with a king on pawn's path increases drawing chances

    if ((SqBb(p->king_sq[op]) & BB.GetFrontSpan(p->Pawns(sd), sd)))
      return 32; // 1/2

    // 15b: draw code for rook endgame with edge pawn

    if ((RelSqBb(A7, sd) & p->Pawns(sd))
    && ( RelSqBb(A8, sd) & p->Rooks(sd))
    && ( FILE_A_BB & p->Rooks(op))
    && ((RelSqBb(H7, sd) & p->Kings(op)) || (RelSqBb(G7, sd) & p->Kings(op)))
    ) return 0; // dead draw

    if ((RelSqBb(H7, sd) & p->Pawns(sd))
    && ( RelSqBb(H8, sd) & p->Rooks(sd))
    && ( FILE_H_BB & p->Rooks(op))
    && ((RelSqBb(A7, sd) & p->Kings(op)) || (RelSqBb(B7, sd) & p->Kings(op)))
    ) return 0; // dead draw

  }

  return 64;
}
Exemple #2
0
void cParam::DynamicInit(void) {

  Eval.prog_side = NO_CL;
  ResetEngine();

  // Init piece/square values together with material value of the pieces.

  for (int sq = 0; sq < 64; sq++) {
    for (int sd = 0; sd < 2; sd++) {
 
      mg_pst[sd][P][REL_SQ(sq, sd)] = SCALE(pc_value[P], mat_perc) + SCALE(pstPawnMg[pst_style][sq], pst_perc);
      eg_pst[sd][P][REL_SQ(sq, sd)] = SCALE(pc_value[P], mat_perc) + SCALE(pstPawnEg[pst_style][sq], pst_perc);
      mg_pst[sd][N][REL_SQ(sq, sd)] = SCALE(pc_value[N], mat_perc) + SCALE(pstKnightMg[pst_style][sq], pst_perc);
      eg_pst[sd][N][REL_SQ(sq, sd)] = SCALE(pc_value[N], mat_perc) + SCALE(pstKnightEg[pst_style][sq], pst_perc);
      mg_pst[sd][B][REL_SQ(sq, sd)] = SCALE(pc_value[B], mat_perc) + SCALE(pstBishopMg[pst_style][sq], pst_perc);
      eg_pst[sd][B][REL_SQ(sq, sd)] = SCALE(pc_value[B], mat_perc) + SCALE(pstBishopEg[pst_style][sq], pst_perc);
      mg_pst[sd][R][REL_SQ(sq, sd)] = SCALE(pc_value[R], mat_perc) + SCALE(pstRookMg[pst_style][sq], pst_perc);
      eg_pst[sd][R][REL_SQ(sq, sd)] = SCALE(pc_value[R], mat_perc) + SCALE(pstRookEg[pst_style][sq], pst_perc);
      mg_pst[sd][Q][REL_SQ(sq, sd)] = SCALE(pc_value[Q], mat_perc) + SCALE(pstQueenMg[pst_style][sq], pst_perc);
      eg_pst[sd][Q][REL_SQ(sq, sd)] = SCALE(pc_value[Q], mat_perc) + SCALE(pstQueenEg[pst_style][sq], pst_perc);
      mg_pst[sd][K][REL_SQ(sq, sd)] = pstKingMg[pst_style][sq];
      eg_pst[sd][K][REL_SQ(sq, sd)] = pstKingEg[pst_style][sq];

      phalanx[sd][REL_SQ(sq, sd)] = pstPhalanxPawn[sq];
      defended[sd][REL_SQ(sq, sd)] = pstDefendedPawn[sq];

      sp_pst_data[sd][N][REL_SQ(sq, sd)] = pstKnightOutpost[sq];
      sp_pst_data[sd][B][REL_SQ(sq, sd)] = pstBishopOutpost[sq];
    }
  }

  // Init tables for adjusting piece values 
  // according to the number of own pawns

  for (int i = 0; i < 9; i++) {
    np_table[i] = adj[i] * np_bonus;
    rp_table[i] = adj[i] * rp_malus;
  }

  // Init backward pawns table, adding file offset to base value

  for (int i = 0; i < 8; i++) {
    backward_malus_mg[i] = backward_malus_base + file_adj[i];
  }

  // Init imbalance table, so that we can expose option for exchange delta

  for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {

      // insert original values
      imbalance[i][j] = imbalance_data[i][j];

      // insert value defined by the user
      if (imbalance[i][j] == Ex) imbalance[i][j] = exchange_imbalance;
      if (imbalance[i][j] == -Ex) imbalance[i][j] = -exchange_imbalance;
    }
  }

  // Init mobility tables

  if (mob_style == 0) {
    for (int i = 0; i < 9; i++) {
      n_mob_mg[i] = 4 * (i-4);
      n_mob_eg[i] = 4 * (i-4);
    }

    for (int i = 0; i < 14; i++) {
      b_mob_mg[i] = 5 * (i-7);
      b_mob_eg[i] = 5 * (i-7);
    }

    for (int i = 0; i < 15; i++) {
      r_mob_mg[i] = 2 * (i-7);
      r_mob_eg[i] = 4 * (i-7);
    }

    for (int i = 0; i < 28; i++) {
      q_mob_mg[i] = 1 * (i-14);
      q_mob_eg[i] = 2 * (i-14);
    }

  }

  if (mob_style == 1) {
    for (int i = 0; i < 9; i++) {
      n_mob_mg[i] = n_mob_mg_decreasing[i];
      n_mob_eg[i] = n_mob_eg_decreasing[i];
    }

    for (int i = 0; i < 14; i++) {
      b_mob_mg[i] = b_mob_mg_decreasing[i];
      b_mob_eg[i] = b_mob_eg_decreasing[i];
    }

    for (int i = 0; i < 15; i++) {
      r_mob_mg[i] = r_mob_mg_decreasing[i];
      r_mob_eg[i] = r_mob_eg_decreasing[i];
    }

    for (int i = 0; i < 28; i++) {
      q_mob_mg[i] = q_mob_mg_decreasing[i];
      q_mob_eg[i] = q_mob_eg_decreasing[i];
    }

  }

  // Init king attack table

  for (int t = 0, i = 1; i < 512; ++i) {
    t = Min(maxAttScore, Min(int(attCurveMult * i * i), t + maxAttStep));
    danger[i] = (t * 100) / 256; // rescale to centipawns
    // TODO: init separately for Black and White in SetAsymmetricEval() to gain some speed
  }
}