コード例 #1
0
// Algorithme de recherche MinMax avec des coupes Alpha-Beta.
int Search(int depth, int ply, int wtm, int alpha, int beta, bool do_null)
{
  register int Valeur, AlphaInitiale, check_ext = 0, extension = 0,
           MoveCherche, danger = 0;
  if ( ply >= MAXPLY-1 )
    return beta;

  iNodes++;

  // Si on n'est pas en mode Analyse, Reste-t-il du temps?
  if ( interrupted || (timeabort && !g_bModeAnalyse) ) {
    return beta;
  }

  AlphaInitiale = alpha;

  // Calculer le temps restant.
  if ( (iNodes & 0xFF ) == 0xFF ) {
	  if ( TimeCheck() ) {
		  timeabort = true;
	  }
      // Verifier si il y a quelque chose dans le tampon
      // d'entree.
	 
      if ( inter() ) {
		char buf[10];
		int c = fgetc(stdin);
		if (c == 10)
		{
			c = fgetc(stdin);
			ungetc(c, stdin);
			if (c == '.')
			{
				scanf("%s", &buf);
			    printf( "stat01: %d %d %d %d %d\n", (TempsCenti()-timestamp),
				  iNodes, iProfondeurIteration, cb.MoveList[1].nbmove - cb.MoveList[1].currmove-1,
				  cb.MoveList[1].nbmove );
				journal.Log("received a dot\n");
			}
			else
			{
				interrupted = true;
			}
		}
		else
		{
			ungetc(c, stdin);
			interrupted = true;
		}
	  }
  }


  // Verifier si ce n'est pas une nulle.
  if (Repetition(wtm)) {
	  //if ( 0 < beta ) {
//		pv[ply-1][ply-1] = cb.CurrentPath.moves[ply-1];
		return 0;
//		if ( wtm ) {
//			return DRAWSCORE;
//		}
//		else {
//			return -DRAWSCORE;
//		}
	  //}
  }

  // Regarder dans la table de transposition pour voir si cette position
  // n'a pas deja ete calculer.
#ifdef TRANSPOSITION
  switch( TableTrans->Lookup( cb, ply, depth,
                              wtm, alpha, beta, danger ) ) {
    case SCORE_EXACTE:

      return alpha;
    case BORNE_SUPERIEUR:

      return alpha;
    case BORNE_INFERIEUR:

      return beta;
    case EVITER_NULL:
      do_null = false;
  }

#endif

#ifdef NULL_MOVE

  // En premier, on essai le NULL MOVE.
  if ( do_null ) {
    int nbPiece = wtm?cb.TotalMaterielBlanc:cb.TotalMaterielNoir;
    if ( !cb.inCheck[ply] && nbPiece > 5 && depth > 3 && alpha == beta-1) {
      int EnPassantB = cb.EnPassantB[ply+1];
      int EnPassantN = cb.EnPassantN[ply+1];
      cb.EnPassantB[ply+1] = -1;
      cb.EnPassantN[ply+1] = -1;
      Valeur = -Search(depth-3, ply+1, !wtm, -beta, -beta+1, false);
      cb.EnPassantB[ply+1] = EnPassantB;
      cb.EnPassantN[ply+1] = EnPassantN;
      if ( Valeur >= beta ) {
#ifdef TRANSPOSITION
      TableTrans->StoreRefutation( cb, ply, depth,
                                   wtm, Valeur, alpha, beta, danger );
#endif
        return Valeur;
      }
      if ( Valeur <= -MATE+50 )
        danger = 1;
    }
  }
#endif
  // Internal Iterative Deepening.
/*  if ( depth > 2 && ((!(ply&1) && alpha==root_alpha && beta==root_beta) ||
    ((ply&1) && alpha==-root_beta && beta==-root_alpha)) &&
      cb.HashMove[ply].From == 0 && cb.HashMove[ply].To == 0 ) {
      Valeur = ABSearch( cb, depth-2, ply, wtm, alpha, beta, true );

    if ( Valeur <= alpha ) {
      Valeur = ABSearch( cb, depth-2, ply, wtm, -MATE, beta, true );
    }
    else {
      if ( Valeur < beta ) {
        cb.HashMove[ply] = pv[ply-1][ply];
      }
      else cb.HashMove[ply] = cb.CurrentPath.moves[ply];
    }
  }*/

#ifdef TRANSPOSITION
  Phase[ply] = HASH_MOVE;
#else
//  if ( ((!(ply&1) && alpha==root_alpha && beta==root_beta) ||
//     ( (ply&1) && alpha==-root_beta && beta==-root_alpha)) )
    Phase[ply] = PV_MOVE;
//  else
//    Phase[ply] = GENERATE_CAPTURE_MOVES;
#endif

  // Maintenant, evaluer chaque coup.
  MoveCherche = 0;
  while( Phase[ply]  != NO_MORE_MOVES && !interrupted ) {

    if ( NextMove( cb, ply, wtm ) ) {

      // Si

      // On execute le coup.
      MakeMove(ply, cb.MoveList[ply].CurrentMove(), wtm);
      // Mettre le coup dans le chemin actuel.
      cb.CurrentPath.moves[ply] = cb.MoveList[ply].moves[cb.MoveList[ply].currmove];

      if (!Check(wtm)) {
        MoveCherche++;

        // Si le coup met en echec etendre la recherche d'une profondeur
        // pour qu'il puisse en sortir.
        if (Check(!wtm) ) {
          cb.inCheck[ply+1] = true;
          extension = 1;
          cb.RaisonExtension[ply] = EXTENSION_ECHEC;
        }
        else {
          extension = 0;
          cb.inCheck[ply+1] = false;
          cb.RaisonExtension[ply] = PAS_EXTENSION;
        }

        // Si le coup est une recapture
        // etendre la recherche d'une profondeur.
        if ( cb.CurrentPath.moves[ply].Capture &&
			abs(ValeurPiece[cb.CurrentPath.moves[ply-1].Capture] - ValeurPiece[cb.CurrentPath.moves[ply].Capture]) <= 20 &&
             (cb.CurrentPath.moves[ply-1].To ==
              cb.CurrentPath.moves[ply].To) &&
              cb.RaisonExtension[ply-1] != EXTENSION_RECAPTURE) {
          extension = 1;
          cb.RaisonExtension[ply] = EXTENSION_RECAPTURE;
        }

		// Si on est sur le point de promouvoir un pion, étendre la recherche
		// pour voir si c'est une menace.
		if ( extension == 0 && cb.CurrentPath.moves[ply].Piece == 1 &&
			PromoteExtension[ cb.CurrentPath.moves[ply].To ] ) {
			extension = 1;
			cb.RaisonExtension[ply] = EXTENSION_PROMOTION;
		}

		// Si on pousse un pion passe, pousser la recherche plus
        // loin pour voir si c'est un danger.
        if ( cb.CurrentPath.moves[ply].Piece == pion )
          if ( wtm ) {
            if ( cb.CurrentPath.moves[ply].To <= H5 )
              if ( cb.PionPasseB[cb.CurrentPath.moves[ply].To&7]  ) {
                extension = 1;
                cb.RaisonExtension[ply] = EXTENSION_PIONPASSE;
              }
          }
          else {
            if ( cb.CurrentPath.moves[ply].To >= A4 )
              if ( cb.PionPasseN[cb.CurrentPath.moves[ply].To&7] ) {
                extension = 1;
                cb.RaisonExtension[ply] = EXTENSION_PIONPASSE;
              }
          }


        // Razoring trick. Idee prise dans Crafty.
        if ( depth == 2 && !cb.inCheck[ply] && extension == 0 ) {
          int valeur;
          if ( wtm )
            valeur = Eval(ply, wtm, alpha, beta);
          else
            valeur = -Eval(ply, wtm, alpha, beta);
          if ( valeur+50 < alpha )
            extension = -1;
        }

        // On l'explore.
        // Si c'est la variation principale, Fenetre normale, sinon,
        // fenetre est n et n+1.
		int inpv = 1;
		if (ply&1) {
			if ( alpha != root_alpha || beta != root_beta ) inpv = 0;
		}
		else {
			if ( alpha != -root_beta || beta != -root_alpha ) inpv = 0;
		}
        if ( inpv ) {
          Valeur = -ABSearch(depth-1+extension+danger, ply+1, !wtm, -beta, -alpha, true);
        }
        else {
          Valeur = -ABSearch(depth-1+extension+danger, ply+1, !wtm, -alpha-1, -alpha, true);
          if ( Valeur > alpha && Valeur < beta ) {
			pvsresearch++;
            Valeur = -ABSearch(depth-1+extension+danger, ply+1, !wtm, -beta, -alpha, true);
          }
        }
      }
      else {
        Valeur = -INFINI;
      }

      cb.MoveList[ply].CurrentMove().Score = Valeur;

      // On defait le coup.
      UnmakeMove(ply, cb.MoveList[ply].CurrentMove(), wtm);

	  if (interrupted)
		  return Valeur;

#ifdef DEBUG
      Consistence( cb, cb.MoveList[ply].CurrentMove() );
#endif
      // Est-il meilleur que notre valeur actuelle?
      if ( Valeur > alpha ) {
        if ( Valeur >= beta ) {
#ifdef TRANSPOSITION
          TableTrans->StoreRefutation( cb, ply, depth,
                                       wtm, Valeur, alpha, beta, check_ext );
#endif
		  g_iRefutation++;
          // Verifier si on peu l'utiliser comme killer move.
          if ( Phase[ply] == NON_CAPTURE_MOVES ) {
            cb.AddKiller( &cb.CurrentPath.moves[ply-1], ply-1 );
          }
          else {
            if ( Phase[ply] == KILLER_MOVE_2 )
              cb.Killers[ply-1][0].Score++;
            else if ( Phase[ply] == GENERATE_NON_CAPTURE_MOVES )
              cb.Killers[ply-1][1].Score++;
          }
          return Valeur;
        }
        pv[ply][ply] = cb.CurrentPath.moves[ply];
		pv_length[ply] = pv_length[ply+1];
		memcpy(&pv[ply][ply+1], &pv[ply+1][ply+1], sizeof(TMove)*(pv_length[ply]-ply));
        alpha = Valeur;
      }
    } // if
  }

  // Verifier si il y a mat ou pat.
  if ( MoveCherche == 0 ) {
    if (!Check(wtm)) {
		pv[ply][ply] = cb.CurrentPath.moves[ply];
		return 0;
//		if ( wtm ) {
//			return DRAWSCORE;
//		}
//		else {
//			return -DRAWSCORE;
//		}
    }
    else {
      if ( ply < iMateInPly )
        iMateInPly = ply;
      alpha = -MATE+iMateInPly;
    }
  }

#ifdef TRANSPOSITION
  TableTrans->StoreBest( cb, ply, depth, wtm,
                         alpha, AlphaInitiale, danger );
#endif

  return alpha;
}
コード例 #2
0
ファイル: racine.cpp プロジェクト: slacombe/monik
// Cette routine est la racine de l'arbre de recherche. Elle doit etre separee
// car plusieurs chose ne sont pas utile a la racine. Comme le null move et
// le lookup dans la table de transposition.
int SearchRacine(int depth, int wtm, int alpha, int beta)
{
  register int Valeur, AlphaInitiale, extension = 0;

  AlphaInitiale = alpha;

  // Calculer le temps restant.
  if ( (iNodes & 0xFF ) == 0xFF ) {
	  if ( TimeCheck() ) {
		  timeabort = true;
	  }
      // Verifier si il y a quelque chose dans le tampon
      // d'entree.
      if ( inter() ) {
        interrupted = true;
	  }
  }

  // Maintenant, evaluer chaque coup.
  while( NextMoveRacine( cb, wtm ) && !g_bAbort ) {

    if ( g_bModeAnalyse ) {
      printf( "stat01: %d %d %d %d %d\n", (TempsCenti()-timestamp),
              iNodes, iProfondeurIteration, cb.MoveList[1].nbmove - cb.MoveList[1].currmove-1,
              cb.MoveList[1].nbmove );
    }
    else if ( !xboard ) {
      printf( "\r [%d] (%2d/%d)", iProfondeurIteration, cb.MoveList[1].currmove+1,
               cb.MoveList[1].nbmove );
    }

    // On execute le coup.
	iNodes++;
    MakeMove(1, cb.MoveList[1].CurrentMove(), wtm);
    // Mettre le coup dans le chemin actuel.
    cb.CurrentPath.moves[1] = cb.MoveList[1].moves[cb.MoveList[1].currmove];

    // Si le coup met en echec etendre la recherche d'une profondeur
    // pour qu'il puisse en sortir.
    if ( Check(!wtm) ) {
      cb.inCheck[2] = true;
      extension = 1;
      cb.RaisonExtension[1] = EXTENSION_ECHEC;
    }
    else {
      extension = 0;
      cb.inCheck[2] = false;
      cb.RaisonExtension[1] = PAS_EXTENSION;
    }

    // On l'explore.
    // Si c'est la variation principale, Fenetre normale, sinon,
    // fenetre est n et n+1.
    if ( cb.MoveList[1].currmove == 0 ) {
      Valeur = -ABSearch(depth-1+extension, 2, !wtm, -beta, -alpha, true);
    }
    else {
      Valeur = -ABSearch(depth-1+extension, 2, !wtm, -alpha-1, -alpha, true);
      if ( Valeur > alpha && Valeur < beta ) {
        Valeur = -ABSearch(depth-1+extension, 2, !wtm, -beta, -alpha, true);
      }
    }

    // La nouvelle valeur.
    cb.CurrentPath.moves[1].Score = Valeur;
    cb.MoveList[1].moves[cb.MoveList[1].currmove].Score = Valeur;

    // On defait le coup.
    UnmakeMove(1, cb.MoveList[1].CurrentMove(), wtm);

	if (interrupted)
		return Valeur;

#ifdef DEBUG
    Consistence( cb, cb.MoveList[1].CurrentMove() );
#endif
    // Est-elle meileur que notre valeur actuelle?
    if ( !timeabort || g_bModeAnalyse ) {
      if ( Valeur > alpha ) {
        pv[1][1] = cb.CurrentPath.moves[1];
		pv_length[1] = pv_length[2];
		memcpy( &pv[1][2], &pv[2][2], sizeof( TMove )*(pv_length[1]-1));
        AffichePV(iProfondeurIteration);
        if ( Valeur >= beta ) {
			return Valeur;
		}
        alpha = Valeur;
      }
      else if ( cb.MoveList[1].currmove == 0 )
        return alpha;
    }
  } // while

  return alpha;
}
コード例 #3
0
// Algorithme de recherche MinMax avec des coupes Alpha-Beta.
// Ici on considere seulement les prises.
int Quiescence(int ply, int wtm, int alpha, int beta )
{
  register int Valeur, AlphaInitiale;

  if ( ply >= MAXPLY-1 )
    return beta;

  iNodes++;

  if ( wtm ) {
    Valeur = Eval(ply, wtm, alpha, beta);
  }
  else {
    Valeur = -Eval(ply, wtm, alpha, beta);
  }

  // Remplace si le score est egal au score pour la NULLE.
  if ( Valeur == DRAWSCORE )
    Valeur = DRAWSCORE+1;

  AlphaInitiale = alpha;

  if ( Valeur > alpha ) {
    if ( Valeur >= beta ) return Valeur;
    alpha = Valeur;
    pv_length[ply] = ply-1;
  }

  // On genere toutes les prises.
  cb.MoveList[ply].nbmove = 0;
  GenMoveAttaque(ply, wtm, cb.MoveList[ply]);

  int keep = -1;
  // Le materiel.
  int iScoreMateriel = cb.ScoreMaterielBlanc-cb.ScoreMaterielNoir;
  iScoreMateriel = wtm?iScoreMateriel:-iScoreMateriel;
  int delta = alpha-100-iScoreMateriel;
  int iScoreGain;
  for( int i=0; i<cb.MoveList[ply].nbmove; i++ ) {
    // Garder le coup.
    bool bGarde = false;

    // On cherche seulement les coups qui ramene le materiel proche de alpha.
    // ex. Si celui qui jouent vient de se faire prendre une dame et que alpha
    // dit que le meilleur score est la perte d'un pion et bien ignorer tout
    // les captures qui ramene pas au moins la dame.
    if ( ValeurPiece[cb.MoveList[ply].moves[i].Capture] >= delta ) {
		if (cb.MoveList[ply].moves[i].Capture == ROI) return beta;
		
#ifdef USE_SEE
    	int iScoreCapture = ValeurPiece[cb.MoveList[ply].moves[i].Capture];
    	iScoreGain = iScoreCapture-ValeurPiece[cb.MoveList[ply].moves[i].Piece];
		if ( iScoreGain > 0 ||
			 iScoreGain >= 0 && 
			 delta <= 0 ) {
				bGarde = true;
		}
		else {
			iScoreGain = Echange(cb.MoveList[ply].moves[i].From, cb.MoveList[ply].moves[i].To, wtm );

      		if ( iScoreGain >= 0 ) {
        		bGarde = true;
    		}
		}
#else
		bGarde = true;
#endif
	}
	

    if ( bGarde ) {
      keep++;
      cb.MoveList[ply].moves[i].Score = iScoreGain;
      memcpy( &cb.MoveList[ply].moves[keep],
              &cb.MoveList[ply].moves[i],
              sizeof( TMove ) );
    }
  }
  cb.MoveList[ply].nbmove = keep+1;

  cb.MoveList[ply].currmove = -1;
  cb.MoveList[ply].Tri();
  Phase[ply] = CAPTURE_MOVES;
  // Maintenant, evaluer chaque coup.
  while( NextMove( cb, ply, wtm ) ) {

    // On execute le coup.
    MakeMove(ply, cb.MoveList[ply].CurrentMove(), wtm);
    // Mettre le coup dans le chemin actuel.
    cb.CurrentPath.moves[ply] = cb.MoveList[ply].moves[cb.MoveList[ply].currmove];
    if (!Check(wtm))
      Valeur = -Quiescence(ply+1, !wtm, -beta, -alpha);
    cb.MoveList[ply].CurrentMove().Score = Valeur;

    // On defait le coup.
    UnmakeMove(ply, cb.MoveList[ply].CurrentMove(), wtm);

    // Est-il meileur que notre valeur actuelle?
    if ( Valeur > alpha ) {
      if ( Valeur >= beta ) return Valeur;
	  pv_length[ply] = pv_length[ply+1];
	  pv[ply][ply] = cb.CurrentPath.moves[ply];
	  memcpy(&pv[ply][ply+1], &pv[ply+1][ply], sizeof(TMove)*(pv_length[ply]-ply));
      alpha = Valeur;
    }
#ifdef DEBUG
    Consistence( cb, cb.MoveList[ply].CurrentMove() );
#endif
  }

  return alpha;
}