Ejemplo n.º 1
0
void cEval::ScoreHanging(POS *p, eData *e, int sd) {

  int pc, sq, sc;
  int op = Opp(sd);
  U64 bbHanging = p->cl_bb[op]    & ~e->bbPawnTakes[op];
  U64 bbThreatened = p->cl_bb[op] & e->bbPawnTakes[sd];
  bbHanging |= bbThreatened;      // piece attacked by our pawn isn't well defended
  bbHanging &= e->bbAllAttacks[sd];  // hanging piece has to be attacked
  bbHanging &= ~p->Pawns(op);     // currently we don't evaluate threats against pawns

  U64 bbDefended = p->cl_bb[op] & e->bbAllAttacks[op];
  bbDefended &= e->bbEvAttacks[sd];  // N, B, R attacks (pieces attacked by pawns are scored as hanging)
  bbDefended &= ~e->bbPawnTakes[sd]; // no defense against pawn attack
  bbDefended &= ~p->Pawns(op);    // currently we don't evaluate threats against pawns

  // hanging pieces (attacked and undefended)

  while (bbHanging) {
    sq = BB.PopFirstBit(&bbHanging);
    pc = TpOnSq(p, sq);
    sc = tp_value[pc] / 64;
    Add(e, sd, F_PRESSURE, 10 + sc, 18 + sc);
  }

  // defended pieces under attack

  while (bbDefended) {
    sq = BB.PopFirstBit(&bbDefended);
    pc = TpOnSq(p, sq);
    sc = tp_value[pc] / 96;
    Add(e, sd, F_PRESSURE, 5 + sc, 9 + sc);
  }
}
Ejemplo n.º 2
0
int KPKdraw(POS *p, int sd) {

  int op = Opp(sd);
  U64 bbPawn = p->Pawns(sd);
  U64 bbStrongKing = p->Kings(sd);
  U64 bbWeakKing = p->Kings(op);

  // opposition through a pawn

  if (p->side == sd
  && (bbWeakKing & BB.ShiftFwd(bbPawn, sd))
  && (bbStrongKing & BB.ShiftFwd(bbPawn, op))
  ) return 1;
  
  // weaker side can create opposition through a pawn in one move

  if (p->side == op
  && (BB.KingAttacks(p->king_sq[op]) & BB.ShiftFwd(bbPawn, sd))
  && (bbStrongKing & BB.ShiftFwd(bbPawn, op))
  ) if (!Illegal(p)) return 1;

  // opposition next to a pawn
  
  if (p->side == sd
  && (bbStrongKing & BB.ShiftSideways(bbPawn))
  && (bbWeakKing & BB.ShiftFwd(BB.ShiftFwd(bbStrongKing,sd) ,sd)) 
  ) return 1;

  // TODO: pawn checks king

  return 0;
}
Ejemplo n.º 3
0
void cEval::ScoreKingFile(POS * p, int sd, U64 bbFile, int *shield, int *storm) {

  int shelter = ScoreFileShelter(bbFile & p->Pawns(sd), sd);
  if (bbFile & bbCentralFile) shelter /= 2;
  *shield += shelter;
  *storm += ScoreFileStorm(bbFile & p->Pawns(Opp(sd)), sd);
}
Ejemplo n.º 4
0
int cEval::ScoreKingFile(POS * p, int sd, U64 bbFile) {

  int shelter = ScoreFileShelter(bbFile & p->Pawns(sd), sd);
  int storm = ScoreFileStorm(bbFile & p->Pawns(Opp(sd)), sd);
  if (bbFile & bbCentralFile) return (shelter / 2) + storm;
  else return shelter + storm;
}
Ejemplo n.º 5
0
void cEval::ScorePawns(POS *p, eData *e, int sd) {

  U64 bbPieces, bbSpan, fl_phalanx;
  int sq, fl_unopposed, fl_weak, fl_defended; 
  int op = Opp(sd);
  U64 bbOwnPawns = p->Pawns(sd);
  U64 bbOppPawns = p->Pawns(op);

  // Is color OK?

  assert(sd == WC || sd == BC);

  // Loop through the pawns, evaluating each one

  bbPieces = bbOwnPawns;
  while (bbPieces) {
    sq = BB.PopFirstBit(&bbPieces);

    // Get some information about the pawn we are evaluating

    bbSpan = BB.GetFrontSpan(SqBb(sq), sd);
    fl_defended  = ((SqBb(sq) & e->bbPawnTakes[sd]) != 0);
    fl_unopposed = ((bbSpan & bbOppPawns) == 0);
    fl_weak      = ((Mask.supported[sd][sq] & bbOwnPawns) == 0);
    fl_phalanx   = (BB.ShiftSideways(SqBb(sq)) & bbOwnPawns);

    // Candidate passer

    if (fl_unopposed) {
      if (fl_phalanx) {
      if (BB.PopCnt((Mask.passed[sd][sq] & bbOppPawns)) == 1)
        Add(e, sd, F_PAWNS, passed_bonus_mg[sd][Rank(sq)] / 3, passed_bonus_eg[sd][Rank(sq)] / 3);
      }
    }

    // Doubled pawn

    if (bbSpan & bbOwnPawns)
      Add(e, sd, F_PAWNS, Param.doubled_malus_mg, Param.doubled_malus_eg);

    // Supported pawn

    if (fl_phalanx)       Add(e, sd, F_PAWNS, Param.phalanx[sd][sq] , 2);
    else if (fl_defended) Add(e, sd, F_PAWNS, Param.defended[sd][sq], 1);

    // Weak pawn (two flavours)

    if (fl_weak) {
      if (!(Mask.adjacent[File(sq)] & bbOwnPawns)) 
        Add(e, sd, F_PAWNS, 
		    Param.isolated_malus_mg + Param.isolated_open_malus * fl_unopposed,
			Param.isolated_malus_eg); // isolated pawn
      else 
        Add(e, sd, F_PAWNS, 
			Param.backward_malus_mg[File(sq)] + Param.backward_open_malus * fl_unopposed, 
			Param.backward_malus_eg); // backward pawn
    }
  }
}
Ejemplo n.º 6
0
int Attacked(POS *p, int sq, int sd) {

  return (p->Pawns(sd) & BB.PawnAttacks(Opp(sd),sq) ) ||
         (p->Knights(sd) & BB.KnightAttacks(sq)) ||
         (p->DiagMovers(sd) & BB.BishAttacks(OccBb(p), sq)) ||
         (p->StraightMovers(sd) & BB.RookAttacks(OccBb(p), sq)) ||
         (p->Kings(sd) & BB.KingAttacks(sq));
}
Ejemplo n.º 7
0
void SetAsymmetricEval(int sd) {

  int op = Opp(sd);
  Eval.prog_side = sd;

  curr_weights[sd][SD_ATT] = dyn_weights[DF_OWN_ATT];
  curr_weights[op][SD_ATT] = dyn_weights[DF_OPP_ATT];
  curr_weights[sd][SD_MOB] = dyn_weights[DF_OWN_MOB];
  curr_weights[op][SD_MOB] = dyn_weights[DF_OPP_MOB];
}
Ejemplo n.º 8
0
void sEvaluator::SinglePawnScore(sPosition *p, int side)
{
  int sq, flagIsOpen, flagIsWeak;
  int oppo = Opp(side);
  U64 flagIsPhalanx, flagPhalanx2, flagIsDoubled, bbFrontSpan;
  U64 bbPieces = bbPc(p, side, P);
  U64 bbOwnPawns = bbPieces;
 
  while (bbPieces) {
    sq = PopFirstBit(&bbPieces);

    // gather information about a pawn that is evaluated
	bbFrontSpan   = GetFrontSpan(SqBb(sq), side );
	flagIsDoubled = bbFrontSpan & bbOwnPawns;
    flagIsOpen    = !( bbFrontSpan & bbPc(p, oppo, P) );
	flagIsPhalanx = ShiftEast(SqBb(sq) ) & bbOwnPawns;
	flagPhalanx2  = ShiftWest(SqBb(sq) ) & bbOwnPawns;
	flagIsWeak    = !( bbPawnSupport[side][sq] & bbOwnPawns );
	
	if (flagIsDoubled) {
	    pawnScoreMg[side] += doubledPawn[MG][File(sq)];
	    pawnScoreEg[side] += doubledPawn[EG][File(sq)];
    }

	if (flagIsPhalanx) {
		pawnScoreMg[side] += Data.pawnProperty[PHALANX][MG][side][sq];
		//pawnScoreEg[side] += Data.phalanxEg[side][sq];
	}

	if (flagIsOpen) {
		U64 bbObstacles = bbPassedMask[side][sq] & bbPc(p, oppo, P);
		
	    // passed pawn (some more eval will be done in ScoreP() in eval_pieces.c)
		if (!bbObstacles) {
			if (flagIsDoubled) AddPasserScore(CANDIDATE,side,sq); // back doubled passer is scored like candidate,
			else               AddPasserScore(PASSED,side,sq);    // only frontmost passer gets full credit
		}
		
	    // candidate passer
		if (flagIsPhalanx || flagPhalanx2) { // test lower bonus when !flagIsWeak
		    if (PopCntSparse(bbObstacles) == 1) AddPasserScore(CANDIDATE,side,sq);
	    }
	}
    
	if (flagIsWeak) {
		if (!(bbAdjacentMask[File(sq)] & bbOwnPawns)) { // isolated 
		   AddPawnProperty(ISOLATED,side,sq);
		   if (flagIsOpen) pawnScoreMg[side] += pawnIsolatedOnOpen;
		} else {                                        // backward
		   AddPawnProperty(BACKWARD,side,sq);
		   if (flagIsOpen) pawnScoreMg[side] += pawnBackwardOnOpen;
		}
	}
  }
}
Ejemplo n.º 9
0
void sEvaluator::EvalPawnCenter(sPosition *p, int side)
{
   int oppo = Opp(side);	  
   if (bbPc(p, side, P) & RelSqBb(D4,side) ) {
      // defend central pawns (pawns side by side evaluated as "phalanx")
      if (bbPc(p, side, P) & RelSqBb(E3,side) )  pawnScoreMg[side] += centDefense;
      if (bbPc(p, side, P) & RelSqBb(C3,side) )  pawnScoreMg[side] += centDefense;
   }

   if (bbPc(p, side, P) & RelSqBb(E4,side) ) {
      if ( bbPc(p, side, P) & RelSqBb(D3,side) ) pawnScoreMg[side] += centDefense;
   }
}
Ejemplo n.º 10
0
int KPKdraw(sPosition *p, int stronger)
{
    int weaker = Opp(stronger);
    U64 bbPawn = bbPc(p, stronger, P);
		  
    // opposition through a pawn
	if ( p->side == stronger
	&& (SqBb(p->kingSquare[weaker]) & ShiftFwd(bbPawn, stronger) )
	&& (SqBb(p->kingSquare[stronger]) & ShiftFwd(bbPawn, weaker) )
	) return 1;

    // weaker side can create opposition through a pawn in one move
	if ( p->side == weaker
	&& (bbKingAttacks[p->kingSquare[weaker]] & ShiftFwd(bbPawn, stronger) )
	&& (SqBb(p->kingSquare[stronger]) & ShiftFwd(bbPawn, weaker) )
	) if ( !IllegalPosition(p) ) return 1;

	// TODO: opposition next to a pawn

	return 0;
} 
Ejemplo n.º 11
0
void cEval::ScoreMaterial(POS * p, eData *e, int sd) {

  int op = Opp(sd);

  // Piece configurations

  int tmp = Param.np_table[p->cnt[sd][P]] * p->cnt[sd][N]   // knights lose value as pawns disappear
          - Param.rp_table[p->cnt[sd][P]] * p->cnt[sd][R];  // rooks gain value as pawns disappear

  if (p->cnt[sd][N] > 1) tmp += Param.knight_pair;
  if (p->cnt[sd][R] > 1) tmp += Param.rook_pair_malus;

  if (p->cnt[sd][B] > 1)                                    // Bishop pair
    Add(e, sd, F_OTHERS, SCALE(Param.bish_pair, Param.mat_perc), SCALE((Param.bish_pair+10), Param.mat_perc));

  // "elephantiasis correction" for queen, idea by H.G.Mueller (nb. rookVsQueen doesn't help)

  if (p->cnt[sd][Q])
    tmp -= Param.minorVsQueen * (p->cnt[op][N] + p->cnt[op][B]);

  Add(e, sd, F_OTHERS, SCALE(tmp, Param.mat_perc));
}
Ejemplo n.º 12
0
void cEval::ScoreOutpost(POS * p, eData * e, int sd, int pc, int sq) {

  int mul = 0;
  int tmp = Param.sp_pst_data[sd][pc][sq];
  if (tmp) {
    if (SqBb(sq) & ~e->bbPawnCanTake[Opp(sd)]) mul += 2;  // in the hole of enemy pawn structure
    if (SqBb(sq) & e->bbPawnTakes[sd]) mul += 1;          // defended by own pawn
    if (SqBb(sq) & e->bbTwoPawnsTake[sd]) mul += 1;       // defended by two pawns

    tmp *= mul;
    tmp /= 2;

    Add(e, sd, F_OUTPOST, tmp);
  }

  // Pawn in front of a minor

  if (SqBb(sq) & bbHomeZone[sd]) {
    U64 bbStop = BB.ShiftFwd(SqBb(sq), sd);
    if (bbStop & PcBb(p, sd, P))
      Add(e, sd, F_OUTPOST, Param.minorBehindPawn);
  }
}
Ejemplo n.º 13
0
void cEval::ScorePassers(POS * p, eData *e, int sd) 
{
  U64 bbPieces = p->Pawns(sd);
  int sq, mul, mg_tmp, eg_tmp;
  int op = Opp(sd);
  U64 bbOwnPawns = p->Pawns(sd);
  U64 bbStop;

  while (bbPieces) {
    sq = BB.PopFirstBit(&bbPieces);

    // Passed pawn

    if (!(Mask.passed[sd][sq] & p->Pawns(op))) {

      bbStop = BB.ShiftFwd(SqBb(sq), sd);
      mg_tmp = passed_bonus_mg[sd][Rank(sq)];
      eg_tmp = passed_bonus_eg[sd][Rank(sq)] 
             - ((passed_bonus_eg[sd][Rank(sq)] * Param.dist[sq][p->king_sq[op]]) / 30);

      mul = 100;

      // blocked passers score less

      if (bbStop & OccBb(p)) mul -= 20; // TODO: only with a blocker of opp color

      // our control of stop square
    
      else if ( (bbStop & e->bbAllAttacks[sd]) 
      &&   (bbStop & ~e->bbAllAttacks[op]) ) mul += 10;
  
      // add final score
  
      Add(e, sd, F_PASSERS, (mg_tmp * mul) / 100, (eg_tmp * mul) / 100);
    }
  }
}
Ejemplo n.º 14
0
int Quiesce(POS *p, int ply, int alpha, int beta, int *pv) {

  int best, score, move, new_pv[MAX_PLY];
  MOVES m[1];
  UNDO u[1];
  int op = Opp(p->side);

  // Statistics and attempt at quick exit

  if (InCheck(p)) return QuiesceFlee(p, ply, alpha, beta, pv);

  nodes++;
  CheckTimeout();
  if (abort_search) return 0;
  *pv = 0;
  if (IsDraw(p)) return DrawScore(p);
  if (ply >= MAX_PLY - 1) return Eval.Return(p, 1);

  // Get a stand-pat score and adjust bounds
  // (exiting if eval exceeds beta)

  best = Eval.Return(p, 1);
  if (best >= beta) return best;
  if (best > alpha) alpha = best;

#ifdef USE_QS_HASH
  // Transposition table read

  if (TransRetrieve(p->hash_key, &move, &score, alpha, beta, 0, ply))
    return score;
#endif

  InitCaptures(p, m);

  // Main loop

  while ((move = NextCapture(m))) {

    // Pruning in quiescence search 
	// (not applicable if we are capturing last enemy piece)

	if (p->cnt[op][N] + p->cnt[op][B] + p->cnt[op][R] + p->cnt[op][Q] > 1) {

      // 1. Delta pruning

      if (best + tp_value[TpOnSq(p, Tsq(move))] + 300 < alpha) continue;

      // 2. SEE-based pruning of bad captures

      if (BadCapture(p, move)) continue;
	}

    p->DoMove(move, u);
    if (Illegal(p)) { p->UndoMove(move, u); continue; }

    score = -Quiesce(p, ply + 1, -beta, -alpha, new_pv);

    p->UndoMove(move, u);
    if (abort_search) return 0;

  // Beta cutoff

  if (score >= beta) {
#ifdef USE_QS_HASH
    TransStore(p->hash_key, *pv, best, LOWER, 0, ply);
#endif
    return score;
  }

  // Adjust alpha and score

    if (score > best) {
      best = score;
      if (score > alpha) {
        alpha = score;
        BuildPv(pv, new_pv, move);
      }
    }
  }

#ifdef USE_QS_HASH
  if (*pv) TransStore(p->hash_key, *pv, best, EXACT, 0, ply);
  else     TransStore(p->hash_key,   0, best, UPPER, 0, ply);
#endif

  return best;
}
Ejemplo n.º 15
0
int cEval::ScoreChains(POS *p, int sd)
{
  int mgResult = 0;
  int sq = p->king_sq[sd];
  int op = Opp(sd);

  // basic pointy chain

  if (SqBb(sq) & bbKSCastle[sd]) {

    if (OPP_PAWN(E4)) {
      if (CONTAINS(opPawns, D5, C6)) { // c6-d5-e4 triad
        mgResult -= (CONTAINS(sdPawns, D4, E3)) ? bigChainScore : smallChainScore;
      }

      if (CONTAINS(opPawns, D5, F3)) { // d5-e4-f3 triad
        mgResult -= (OWN_PAWN(E3)) ? bigChainScore : smallChainScore;
      }
    }

    if (OPP_PAWN(E5)) {
      if (CONTAINS(opPawns, F4, D6)) { // d6-e5-f4 triad
        // storm of a "g" pawn in the King's Indian
      if (OPP_PAWN(G5)) {
            mgResult -= 4; 
            if (OPP_PAWN(H4)) return 0; // this is not how you handle pawn chains
      }
        if (OPP_PAWN(G4)) mgResult -= 12;

        mgResult -= (CONTAINS(sdPawns, E4, D5)) ? bigChainScore : smallChainScore;
      }

      if (CONTAINS(opPawns, G3, F4)) { // e5-f4-g3 triad
        mgResult -= (OWN_PAWN(F3)) ? bigChainScore : smallChainScore;
      }
    }
  }
  
  if (SqBb(sq) & bbQSCastle[sd]) {

    // basic pointy chain

    if (OPP_PAWN(D4)) {
      if (CONTAINS(opPawns, E5, F6)) {
        mgResult -= (CONTAINS(sdPawns, E4, D3)) ? bigChainScore : smallChainScore;
      }
      
      if (CONTAINS(opPawns, F5, C3)) {
        mgResult -= (SQ(D3) & sdPawns) ? bigChainScore : smallChainScore;
      }
    }

    if (OPP_PAWN(D5)) {
      if (CONTAINS(opPawns, C4, E6)) {
        // storm of a "b" pawn
        if (OPP_PAWN(B5)) {
          mgResult -= 4;
          if (OPP_PAWN(A4)) return 0; // this is not how you handle pawn chains
        }
        if (OPP_PAWN(B4)) mgResult -= 12;

        mgResult -= (CONTAINS(sdPawns, E4, D5)) ? bigChainScore : smallChainScore;
      }

      if (CONTAINS(opPawns, B3, C4)) {
        mgResult -= (OWN_PAWN(C3)) ? bigChainScore : smallChainScore;
      }
    }
  }

  return mgResult;
}
Ejemplo n.º 16
0
void sManipulator::DoMove(sPosition *p, int move, UNDO *u)
{
  int side = p->side;         // moving side 
  int fsq  = Fsq(move);       // start square
  int tsq  = Tsq(move);       // target square
  int ftp  = TpOnSq(p, fsq);  // moving piece
  int ttp  = TpOnSq(p, tsq);  // captured piece

  U64 bbMove = SqBb(fsq) | SqBb(tsq); // optimization from Stockfish

  // save data for undoing a move
  u->ttp = ttp;
  u->castleFlags = p->castleFlags;
  u->epSquare = p->epSquare;
  u->reversibleMoves = p->reversibleMoves;
  u->hashKey = p->hashKey;
  u->pawnKey = p->pawnKey;

  p->repetitionList[p->head++] = p->hashKey;

  // update reversible move counter (zeroing is done on captures and pawn moves)
  p->reversibleMoves++;

  p->hashKey     ^= zobCastle[p->castleFlags];
  p->castleFlags &= castleMask[fsq] & castleMask[tsq];
  p->hashKey     ^= zobCastle[p->castleFlags];

  // clear en passant square
  if (p->epSquare != NO_SQ) {
    p->hashKey ^= zobEp[File(p->epSquare)];
    p->epSquare = NO_SQ;
  }

  // move a piece from start square
  p->pc[fsq]      = NO_PC;
  p->pc[tsq]      = Pc(side, ftp);
  p->hashKey     ^= zobPiece[Pc(side, ftp)][fsq] ^ zobPiece[Pc(side, ftp)][tsq];
  if (ftp == P) {
	  p->reversibleMoves = 0;
	  p->pawnKey ^= zobPiece[Pc(side, ftp)][fsq] ^ zobPiece[Pc(side, ftp)][tsq];
  } 
  p->bbCl[side]  ^= bbMove;
  p->bbTp[ftp]   ^= bbMove;
  p->pstMg[side] += Data.pstMg[side][ftp][tsq] - Data.pstMg[side][ftp][fsq];
  p->pstEg[side] += Data.pstEg[side][ftp][tsq] - Data.pstEg[side][ftp][fsq];

  // on a king move update king location data
  if (ftp == K) p->kingSquare[side] = tsq;
  
  // capture
  if (ttp != NO_TP) {
	p->reversibleMoves = 0;
    p->hashKey ^= zobPiece[Pc(Opp(side), ttp)][tsq];
	if (ttp == P) 
		p->pawnKey     ^= zobPiece[Pc(Opp(side), ttp)][tsq];
    p->bbCl[Opp(side)] ^= SqBb(tsq);
    p->bbTp[ttp]       ^= SqBb(tsq);
	p->pcCount[Opp(side)][ttp]--;
    p->pieceMat[Opp(side)] -= Data.matValue[ttp];
	p->phase               -= Data.phaseValue[ttp]; 
    p->pstMg[Opp(side)]    -= Data.pstMg[Opp(side)][ttp][tsq];
	p->pstEg[Opp(side)]    -= Data.pstEg[Opp(side)][ttp][tsq];
  }
  
  switch (MoveType(move)) {

  case NORMAL:
    break;

  case CASTLE:
    if (tsq > fsq) {
      fsq += 3;
      tsq -= 1;
    } else {
      fsq -= 4;
      tsq += 1;
    }
    p->pc[fsq]      = NO_PC;
    p->pc[tsq]      = Pc(side, R);
    p->hashKey     ^= zobPiece[Pc(side, R)][fsq] ^ zobPiece[Pc(side, R)][tsq];
    p->bbCl[side]  ^= SqBb(fsq) | SqBb(tsq);
    p->bbTp[R]     ^= SqBb(fsq) | SqBb(tsq);
    p->pstMg[side] += Data.pstMg[side][R][tsq] - Data.pstMg[side][R][fsq];
	p->pstEg[side] += Data.pstEg[side][R][tsq] - Data.pstEg[side][R][fsq];
    break;

  case EP_CAP:
    tsq ^= 8;
    p->pc[tsq]  = NO_PC;
    p->hashKey ^= zobPiece[Pc(Opp(side), P)][tsq];
	p->pawnKey ^= zobPiece[Pc(Opp(side), P)][tsq];
    p->bbCl[Opp(side)] ^= SqBb(tsq);
    p->bbTp[P] ^= SqBb(tsq);
	p->pcCount[Opp(side)][P]--;
	p->phase             -= Data.phaseValue[P];
    p->pstMg[Opp(side)] -= Data.pstMg[Opp(side)][P][tsq];
	p->pstEg[Opp(side)] -= Data.pstEg[Opp(side)][P][tsq];
    break;

  case EP_SET:
    tsq ^= 8;
    if (bbPawnAttacks[side][tsq] & bbPc(p, Opp(side), P)) {
      p->epSquare = tsq;
      p->hashKey ^= zobEp[File(tsq)];
    }
    break;

  // promotion:    (1) add promoted piece and add values associated with it
  case N_PROM:  // (2) remove promoted pawn and substract values associated with it 
  case B_PROM: 
  case R_PROM: 
  case Q_PROM:
    ftp = PromType(move);
    p->pc[tsq]   = Pc(side, ftp);
    p->hashKey  ^= zobPiece[Pc(side, P)][tsq] ^ zobPiece[Pc(side, ftp)][tsq];
	p->pawnKey  ^= zobPiece[Pc(side, P)][tsq];
    p->bbTp[P]  ^= SqBb(tsq);
    p->bbTp[ftp]^= SqBb(tsq);
	p->pcCount[side][ftp]++;
	p->pcCount[side][P]--;
	p->pieceMat[side] += Data.matValue[ftp];
	p->phase          += Data.phaseValue[ftp]       - Data.phaseValue[P];
    p->pstMg[side]    += Data.pstMg[side][ftp][tsq] - Data.pstMg[side][P][tsq];
	p->pstEg[side]    += Data.pstEg[side][ftp][tsq] - Data.pstEg[side][P][tsq];
    break;

  }
  p->side ^= 1;
  p->hashKey ^= SIDE_RANDOM;
}
Ejemplo n.º 17
0
void cEval::ScorePieces(POS *p, eData *e, int sd) {

  U64 bbPieces, bbMob, bbAtt, bbFile, bbContact;
  int op, sq, cnt, tmp, ksq, att = 0, wood = 0;
  int own_pawn_cnt, opp_pawn_cnt;
  int r_on_7th = 0;
  int fwd_weight = 0;
  int fwd_cnt = 0;

  // Is color OK?

  assert(sd == WC || sd == BC);

  // Init variables

  op = Opp(sd);
  ksq = KingSq(p, op);
  U64 bbExcluded = p->Pawns(sd) /*| p->Kings(sd)*/;

  // Init enemy king zone for attack evaluation. We mark squares where the king
  // can move plus two or three more squares facing enemy position.

  U64 bbZone = Mask.king_zone[sd][ksq];

  // Init bitboards to detect check threats
  
  U64 bbKnightChk = BB.KnightAttacks(ksq);
  U64 bbStr8Chk = BB.RookAttacks(OccBb(p), ksq);
  U64 bbDiagChk = BB.BishAttacks(OccBb(p), ksq);
  U64 bbQueenChk = bbStr8Chk | bbDiagChk;
  
  // Knight

  bbPieces = p->Knights(sd);
  while (bbPieces) {
    sq = BB.PopFirstBit(&bbPieces);

    // Knight tropism to enemy king

    Add(e, sd, F_TROPISM, tropism_mg[N] * Param.dist[sq][ksq], tropism_eg[N] * Param.dist[sq][ksq]);

	// Knight forwardness

    if (SqBb(sq) & bbAwayZone[sd]) {
      fwd_weight += 1;
      fwd_cnt += 1;
	}
    
    // Knight mobility

    bbMob = BB.KnightAttacks(sq) & ~p->cl_bb[sd];  // knight is tricky, 
    cnt = BB.PopCnt(bbMob &~e->bbPawnTakes[op]);   // better to have it mobile than defending stuff
    
    Add(e, sd, F_MOB, Param.n_mob_mg[cnt], Param.n_mob_eg[cnt]);  // mobility bonus

    if ((bbMob &~e->bbPawnTakes[op]) & bbKnightChk) 
      att += chk_threat[N]; // check threat bonus

	e->bbAllAttacks[sd] |= BB.KnightAttacks(sq);
    e->bbEvAttacks[sd]  |= bbMob;

    // Knight attacks on enemy king zone

    bbAtt = BB.KnightAttacks(sq);
    if (bbAtt & bbZone) {
      wood++;
      att += king_att[N] * BB.PopCnt(bbAtt & bbZone);
    }

    // Knight outpost

    ScoreOutpost(p, e, sd, N, sq);

  } // end of knight eval

  // Bishop

  bbPieces = p->Bishops(sd);
  while (bbPieces) {
    sq = BB.PopFirstBit(&bbPieces);

    // Bishop tropism to enemy king

    Add(e, sd, F_TROPISM, tropism_mg[B] * Param.dist[sq][ksq], tropism_eg[B] * Param.dist[sq][ksq]);

    // Bishop forwardness

    if (SqBb(sq) & bbAwayZone[sd]) {
      fwd_weight += 1;
      fwd_cnt += 1;
    }

    // Bishop mobility

    bbMob = BB.BishAttacks(OccBb(p), sq);

    if (!(bbMob & bbAwayZone[sd]))               // penalty for bishops unable to reach enemy half of the board
       Add(e, sd, F_MOB, Param.bishConfined);    // (idea from Andscacs)

    cnt = BB.PopCnt(bbMob &~e->bbPawnTakes[op] &~bbExcluded);
    
    Add(e, sd, F_MOB, Param.b_mob_mg[cnt], Param.b_mob_eg[cnt]);   // mobility bonus

    if ((bbMob &~e->bbPawnTakes[op]) & ~p->cl_bb[sd] & bbDiagChk)
      att += chk_threat[B]; // check threat bonus

    e->bbAllAttacks[sd] |= bbMob;
    e->bbEvAttacks[sd]  |= bbMob;

    // Bishop attacks on enemy king zone (including attacks through a queen)

    bbAtt = BB.BishAttacks(OccBb(p) ^ p->Queens(sd) , sq);
    if (bbAtt & bbZone) {
      wood++;
      att += king_att[B] * BB.PopCnt(bbAtt & bbZone);
    }

    // Bishop outpost

    ScoreOutpost(p, e, sd, B, sq);

    // Bishops side by side

    if (ShiftNorth(SqBb(sq)) & p->Bishops(sd) )
      Add(e, sd, F_OTHERS, 4);
    if (ShiftEast(SqBb(sq)) & p->Bishops(sd))
      Add(e, sd, F_OTHERS, 4);

    // Pawns on the same square color as our bishop
  
    if (bbWhiteSq & SqBb(sq)) {
      own_pawn_cnt = BB.PopCnt(bbWhiteSq & p->Pawns(sd)) - 4;
      opp_pawn_cnt = BB.PopCnt(bbWhiteSq & p->Pawns(op)) - 4;
    } else {
      own_pawn_cnt = BB.PopCnt(bbBlackSq & p->Pawns(sd)) - 4;
      opp_pawn_cnt = BB.PopCnt(bbBlackSq & p->Pawns(op)) - 4;
    }

    Add(e, sd, F_OTHERS, -3 * own_pawn_cnt - opp_pawn_cnt);

  } // end of bishop eval

  // Rook

  bbPieces = p->Rooks(sd);
  while (bbPieces) {
    sq = BB.PopFirstBit(&bbPieces);

    // Rook tropism to enemy king

    Add(e, sd, F_TROPISM, tropism_mg[R] * Param.dist[sq][ksq], tropism_eg[R] * Param.dist[sq][ksq]);

	// Rook forwardness

	if (SqBb(sq) & bbAwayZone[sd]) {
      fwd_weight += 2;
	  fwd_cnt += 1;
	}
  
    // Rook mobility

    bbMob = BB.RookAttacks(OccBb(p), sq);
    cnt = BB.PopCnt(bbMob &~bbExcluded);
    Add(e, sd, F_MOB, Param.r_mob_mg[cnt], Param.r_mob_eg[cnt]);    // mobility bonus
    if (((bbMob &~e->bbPawnTakes[op]) & ~p->cl_bb[sd] & bbStr8Chk)  // check threat bonus
    && p->cnt[sd][Q]) {
      att += chk_threat[R]; 

      bbContact = (bbMob & BB.KingAttacks(ksq)) & bbStr8Chk;

      while (bbContact) {
        int contactSq = BB.PopFirstBit(&bbContact);

        // rook exchanges are accepted as contact checks

        if (Swap(p, sq, contactSq) >= 0) {
          att += r_contact_check;
          break;
        }
      }
    }

    e->bbAllAttacks[sd] |= bbMob;
    e->bbEvAttacks[sd]  |= bbMob;

    // Rook attacks on enemy king zone (also through a rook or through a queen)

    bbAtt = BB.RookAttacks(OccBb(p) ^ p->StraightMovers(sd), sq);
    if (bbAtt & bbZone) {
      wood++;
      att += king_att[R] * BB.PopCnt(bbAtt & bbZone);
    }

    // Get rook file

    bbFile = BB.FillNorthSq(sq) | BB.FillSouthSq(sq); // better this way than using front span

    // Queen on rook's file (which might be closed)

    if (bbFile & p->Queens(op)) Add(e, sd, F_LINES, Param.rookOnQueen);

    // Rook on (half) open file

    if (!(bbFile & p->Pawns(sd))) {
      if (!(bbFile & p->Pawns(op))) {
        Add(e, sd, F_LINES, Param.rookOnOpenMg, Param.rookOnOpenEg);
        //if (BB.GetFrontSpan(SqBb(sq), sd) & p->Rooks(sd)) Add(e, sd, F_LINES, 4, 2); // equal
      }
      else {
        // score differs depending on whether half-open file is blocked by defended enemy pawn
        if ((bbFile & p->Pawns(op)) & e->bbPawnTakes[op])
          Add(e, sd, F_LINES, Param.rookOnBadHalfOpenMg, Param.rookOnBadHalfOpenEg);
        else {
          Add(e, sd, F_LINES, Param.rookOnGoodHalfOpenMg, Param.rookOnGoodHalfOpenEg);
        }
      }
    }

    // Rook on the 7th rank attacking pawns or cutting off enemy king

    if (SqBb(sq) & bbRelRank[sd][RANK_7]) {
      if (p->Pawns(op) & bbRelRank[sd][RANK_7]
      ||  p->Kings(op) & bbRelRank[sd][RANK_8]) {
        Add(e, sd, F_LINES, Param.rookOn7thMg, Param.rookOn7thEg);
        r_on_7th++;
      }
    }

  } // end of rook eval

  // Queen

  bbPieces = p->Queens(sd);
  while (bbPieces) {
    sq = BB.PopFirstBit(&bbPieces);

    // Queen tropism to enemy king

    Add(e, sd, F_TROPISM, tropism_mg[Q] * Param.dist[sq][ksq], tropism_eg[Q] * Param.dist[sq][ksq]);

	// Queen forwardness

	if (SqBb(sq) & bbAwayZone[sd]) {
       fwd_weight += 4;
	   fwd_cnt += 1;
	}

    // Queen mobility

    bbMob = BB.QueenAttacks(OccBb(p), sq);
    cnt = BB.PopCnt(bbMob &~bbExcluded);
    Add(e, sd, F_MOB, Param.q_mob_mg[cnt], Param.q_mob_eg[cnt]);  // mobility bonus

    if ((bbMob &~e->bbPawnTakes[op]) & ~p->cl_bb[sd] & bbQueenChk) {  // check threat bonus
      att += chk_threat[Q];

    // Queen contact checks

    bbContact = bbMob & BB.KingAttacks(ksq);
    while (bbContact) {
      int contactSq = BB.PopFirstBit(&bbContact);

        // queen exchanges are accepted as contact checks

        if (Swap(p, sq, contactSq) >= 0) {
          att += q_contact_check;
          break;
        }
      }
    }

    e->bbAllAttacks[sd] |= bbMob;

    // Queen attacks on enemy king zone
   
    bbAtt  = BB.BishAttacks(OccBb(p) ^ p->DiagMovers(sd), sq);
    bbAtt |= BB.RookAttacks(OccBb(p) ^ p->StraightMovers(sd), sq);
    if (bbAtt & bbZone) {
      wood++;
      att += king_att[Q] * BB.PopCnt(bbAtt & bbZone);
    }

    // Queen on 7th rank

    if (SqBb(sq) & bbRelRank[sd][RANK_7]) {
      if (p->Pawns(op) & bbRelRank[sd][RANK_7]
      || p->Kings(op) & bbRelRank[sd][RANK_8]) {
        Add(e, sd, F_LINES, Param.queenOn7thMg, Param.queenOn7thEg);
      }
    }

  } // end of queen eval

  // Score terms using information gathered during piece eval

  if (r_on_7th > 1)                 // two rooks on 7th rank
    Add(e, sd, F_LINES, Param.twoRooksOn7thMg, Param.twoRooksOn7thEg);

  // forwardness (from Toga II 3.0)
  Add(e, sd, (fwd_bonus[fwd_cnt] * fwd_weight * Param.forwardness) / 100, 0); 

  // Score king attacks if own queen is present and there are at least 2 attackers

  if (wood > 1 && p->cnt[sd][Q]) {
    if (att > 399) att = 399;
    Add(e, sd, F_ATT, Param.danger[att]);
  }

}
Ejemplo n.º 18
0
void POS::UndoMove(int move, UNDO *u) {

  int sd  = Opp(side);
  int op  = side;
  int fsq = Fsq(move);
  int tsq = Tsq(move);
  int ftp = Tp(pc[tsq]);    // moving piece
  int ttp = u->ttp;

  castle_flags = u->castle_flags;
  ep_sq = u->ep_sq;
  rev_moves = u->rev_moves;
  pawn_key = u->pawn_key;
  hash_key = u->hash_key;
  head--;
  pc[fsq] = Pc(sd, ftp);
  pc[tsq] = NO_PC;
  cl_bb[sd] ^= SqBb(fsq) | SqBb(tsq);
  tp_bb[ftp] ^= SqBb(fsq) | SqBb(tsq);
#ifndef LEAF_PST
  mg_pst[sd] += Param.mg_pst_data[sd][ftp][fsq] - Param.mg_pst_data[sd][ftp][tsq];
  eg_pst[sd] += Param.eg_pst_data[sd][ftp][fsq] - Param.eg_pst_data[sd][ftp][tsq];
#endif

  // Update king location

  if (ftp == K) king_sq[sd] = fsq;

  // Undo capture

  if (ttp != NO_TP) {
    pc[tsq] = Pc(op, ttp);
    cl_bb[op] ^= SqBb(tsq);
    tp_bb[ttp] ^= SqBb(tsq);
    phase += phase_value[ttp];
#ifndef LEAF_PST
    mg_pst[op] += Param.mg_pst_data[op][ttp][tsq];
    eg_pst[op] += Param.eg_pst_data[op][ttp][tsq];
#endif
    cnt[op][ttp]++;
  }

  switch (MoveType(move)) {

  case NORMAL:
    break;

  case CASTLE:

    // define complementary rook move

    switch (tsq) {
      case C1: { fsq = A1; tsq = D1; break; }
      case G1: { fsq = H1; tsq = F1; break; }
      case C8: { fsq = A8; tsq = D8; break; }
      case G8: { fsq = H8; tsq = F8; break; }
    }

    pc[tsq] = NO_PC;
    pc[fsq] = Pc(sd, R);
    cl_bb[sd] ^= SqBb(fsq) | SqBb(tsq);
    tp_bb[R] ^= SqBb(fsq) | SqBb(tsq);
#ifndef LEAF_PST
    mg_pst[sd] += Param.mg_pst_data[sd][R][fsq] - Param.mg_pst_data[sd][R][tsq];
    eg_pst[sd] += Param.eg_pst_data[sd][R][fsq] - Param.eg_pst_data[sd][R][tsq];
#endif
    break;

  case EP_CAP:
    tsq ^= 8;
    pc[tsq] = Pc(op, P);
    cl_bb[op] ^= SqBb(tsq);
    tp_bb[P] ^= SqBb(tsq);
    phase += phase_value[P];
#ifndef LEAF_PST
    mg_pst[op] += Param.mg_pst_data[op][P][tsq];
    eg_pst[op] += Param.eg_pst_data[op][P][tsq];
#endif
    cnt[op][P]++;
    break;

  case EP_SET:
    break;

  case N_PROM: case B_PROM: case R_PROM: case Q_PROM:
    pc[fsq] = Pc(sd, P);
    tp_bb[P] ^= SqBb(fsq);
    tp_bb[ftp] ^= SqBb(fsq);
    phase += phase_value[P] - phase_value[ftp];
#ifndef LEAF_PST
    mg_pst[sd] += Param.mg_pst_data[sd][P][fsq] - Param.mg_pst_data[sd][ftp][fsq];
    eg_pst[sd] += Param.eg_pst_data[sd][P][fsq] - Param.eg_pst_data[sd][ftp][fsq];
#endif
    cnt[sd][P]++;
    cnt[sd][ftp]--;
    break;
  }
  side ^= 1;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
void SetPosition(POS *p, char *epd) {

  int j, pc;
  static const char pc_char[13] = "PpNnBbRrQqKk";

  for (int sd = 0; sd < 2; sd++) {
    p->cl_bb[sd] = 0ULL;
#ifndef LEAF_PST
    p->mg_pst[sd] = 0;
    p->eg_pst[sd] = 0;
#endif
  }

  p->phase = 0;

  for (int pc = 0; pc < 6; pc++) {
    p->tp_bb[pc] = 0ULL;
    p->cnt[WC][pc] = 0;
    p->cnt[BC][pc] = 0;
  }

  p->castle_flags = 0;
  p->rev_moves = 0;
  p->head = 0;

  for (int i = 56; i >= 0; i -= 8) {
    j = 0;
    while (j < 8) {
      if (*epd >= '1' && *epd <= '8')
        for (pc = 0; pc < *epd - '0'; pc++) {
          p->pc[i + j] = NO_PC;
          j++;
        }
      else {
        for (pc = 0; pc_char[pc] != *epd; pc++)
          ;
        p->pc[i + j] = pc;
        p->cl_bb[Cl(pc)] ^= SqBb(i + j);
        p->tp_bb[Tp(pc)] ^= SqBb(i + j);
        
        if (Tp(pc) == K)
          p->king_sq[Cl(pc)] = i + j;

        p->phase += phase_value[Tp(pc)];
#ifndef LEAF_PST
        p->mg_pst[Cl(pc)] += Param.mg_pst_data[Cl(pc)][Tp(pc)][i + j];
        p->eg_pst[Cl(pc)] += Param.eg_pst_data[Cl(pc)][Tp(pc)][i + j];
#endif
        p->cnt[Cl(pc)][Tp(pc)]++;
        j++;
      }
      epd++;
    }
    epd++;
  }

  // Setting side to move

  if (*epd++ == 'w') p->side = WC;
  else               p->side = BC;

  // Setting castling rights

  epd++;
  if (*epd == '-')
    epd++;
  else {
    if (*epd == 'K') {
      p->castle_flags |= 1;
      epd++;
    }
    if (*epd == 'Q') {
      p->castle_flags |= 2;
      epd++;
    }
    if (*epd == 'k') {
      p->castle_flags |= 4;
      epd++;
    }
    if (*epd == 'q') {
      p->castle_flags |= 8;
      epd++;
    }
  }

  // Setting en passant square (only if capture is possible)

  epd++;
  if (*epd == '-')
    p->ep_sq = NO_SQ;
  else {
    p->ep_sq = Sq(*epd - 'a', *(epd + 1) - '1');
    if (!(BB.PawnAttacks(Opp(p->side), p->ep_sq) & p->Pawns(p->side)))
      p->ep_sq = NO_SQ;
  }

  // Calculating hash keys

  p->hash_key = InitHashKey(p);
  p->pawn_key = InitPawnKey(p);
}