Esempio n. 1
0
// Enleve tout ce qui est en echec.
void TMoveList::ChoisiMove(int ply, int wtm)
{
#ifdef JOURNAL
	journal.Log( "ChoisiMove: NbMove: %d\n", nbmove );
#endif
  if ( nbmove == 0 )
    return;

  currmove = 0;
  int iDernierValide = -1;
  // Verifier chaque coup.
  while( currmove < nbmove ) {

    // Effectuer le coup et verifier si est en echec.
    MakeMove(ply, moves[currmove], wtm);
    int bEstEchec = Check(wtm);
    UnmakeMove(ply, moves[currmove], wtm);

    // Si le coup est valide le copier dans la case suivant le dernier
    // coup valide trouver.
    if ( !bEstEchec ) {
      iDernierValide++;
      moves[iDernierValide] = moves[currmove];
    }

    currmove++;
  }
  // Nombre de coup valide.
  nbmove = iDernierValide+1;
}
Esempio n. 2
0
void cmd_pgnreplay(void)
{
  char tmp_epd[]=".tmp.epd";
  char data[MAXSTR]="";
  FILE *epdfile=NULL;
  char epdline[MAXSTR]="";

  PGNReadFromFile (token[1],1);

  SaveEPD( tmp_epd );
  epdfile = fopen( tmp_epd, "r" );
  if ( fgets( epdline, MAXSTR, epdfile ) == NULL ) {
    printf( _("Incorrect epd file\n") );
    return;
  }

  strcpy( data, "setboard " );
  int i=0;
  while ( epdline[i] != '\n' ) {
    data[i+9] = epdline[i];
    ++i;
  }
  data[i+9] = '\0';

  SetDataToEngine( data );
  SetAutoGo( true );

  pgnloaded = 1;
  pgncnt = GameCnt;

  while (GameCnt >= 0) {
    if (GameCnt >= 0) {
      CLEAR (flags, ENDED);
      CLEAR (flags, TIMEOUT);
      ChangeColor( true );
      SetAutoGo( true );
      UnmakeMove (board.side, &Game[GameCnt].move);
      if (GameCnt >= 0) {
        UnmakeMove (board.side, &Game[GameCnt].move);
      }
    }
  }

  cmd_first();
}
Esempio n. 3
0
void cmd_first(void)
{
  if (!pgnloaded)
    return;

  while (GameCnt >= 0) {
    if (GameCnt >= 0) {
      CLEAR (flags, ENDED);
      CLEAR (flags, TIMEOUT);
      ChangeColor( true );
      SetAutoGo( true );
      UnmakeMove (board.side, &Game[GameCnt].move);
      if (GameCnt >= 0) {
        UnmakeMove (board.side, &Game[GameCnt].move);
      }
    }
  }

  ShowBoard ();
}
Esempio n. 4
0
void PopfromRecord(Gamerec *g, Position *p, int len, int count)
{

int i;

i = len * (len-1) / 2;
i += count - 1;

UnmakeMove(p, &(g->moves[i]));

g->moves[i].mtype = EMPTY;

}
Esempio n. 5
0
void cmd_previous(void)
{
  if (!pgnloaded)
    return;

  if (GameCnt >= 0) {
    ChangeColor( true );
    SetAutoGo( true );
    UnmakeMove (board.side, &Game[GameCnt].move);
  }
  else {
    printf(_("Initial position reached. There are no earlier moves.\n"));
    return;
  }

  printf("%d. ",GameCnt/2+1);
  printf("%s\n", Game[GameCnt].SANmv);
  ShowBoard ();
}
bool Position::IsGameOver(std::string& message)
{
  bool hasMoves = false;
  MoveList mvlist;
  mvlist.GenAllMoves(*this);
  for (int i = 0; i < mvlist.Size(); ++i)
  {
    if (MakeMove(mvlist[i].m_mv))
    {
      hasMoves = true;
      UnmakeMove();
      break;
    }
  }
  
  if (hasMoves == false)
  {
    if (InCheck())
      message = (m_side == WHITE)? "0-1 {Black mates}" : "1-0 {White mates}";
    else
      message = "1/2-1/2 {Draw: stalemate}";
    return true;
  }

  if (EstimateDraw(*this) == EVAL_THEORETICAL_DRAW)
  {
    message = "1/2-1/2 {Draw: material}";
    return true;
  }

  if (GetRepetitions() >= 3)
  {
    message = "1/2-1/2 {Draw: 3rd repetition}";
    return true;
  }

  return false;
}
Esempio n. 7
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;
}
bool Position::MakeMove(Move mv)
{
  Undo& undo = _undos[_undoSize++];
  undo.m_castlings = m_castlings;
  undo.m_ep = m_ep;
  undo.m_fifty = m_fifty;
  undo.m_hash = m_hash;
  undo.m_mv = mv;

  FLD from = mv.From();
  FLD to = mv.To();
  PIECE piece = mv.Piece();
  PIECE captured = mv.Captured();
  PIECE promotion = mv.Promotion();

  COLOR side = m_side;
  COLOR opp = side ^ 1;
  m_hash ^= s_hashSide[1];

  ++m_fifty;
  if (captured)
  {
    m_fifty = 0;
    if (to == m_ep)
      Remove(to + 8 - 16 * side);
    else
      Remove(to);
  }
  Remove(from);
  Put(to, piece);

  m_ep = NF;
  switch (piece)
  {
  case PW:
  case PB:
    m_fifty = 0;
    if (to - from == -16 + 32 * side)
      m_ep = to + 8 - 16 * side;
    else if (promotion)
    {
      Remove(to);
      Put(to, promotion);
    }
    break;

  case KW:
    m_Kings[WHITE] = to;
    if (from == E1)
    {
      if (to == G1)
      {
        Remove(H1);
        Put(F1, RW);
        m_castlings ^= WHITE_DID_O_O;
      }
      else if (to == C1)
      {
        Remove(A1);
        Put(D1, RW);
        m_castlings ^= WHITE_DID_O_O_O;        
      }
    }
    break;

  case KB:
    m_Kings[BLACK] = to;
    if (from == E8)
    {
      if (to == G8)
      {
        Remove(H8);
        Put(F8, RB);
        m_castlings ^= BLACK_DID_O_O;        
      }
      else if (to == C8)
      {
        Remove(A8);
        Put(D8, RB);
        m_castlings ^= BLACK_DID_O_O_O;        
      }
    }
    break;

  default:
    break;
  }

  static const U8 castlingDelta[64] =
  {
    0xf7, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xfb,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xfd, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xfe
  };

  m_castlings &= castlingDelta[from];
  m_castlings &= castlingDelta[to];

  ++m_ply;
  m_side ^= 1;
  
  if (IsAttacked(m_Kings[side], opp))
  {
    UnmakeMove();
    return false;
  }

  return true;
}
Esempio n. 9
0
int AnyLegalMoves(Position *pos)  {

int i, j, x, y, direc;
unsigned char side = pos->side, xside;
SQUARE board[12][12];
Listnode l, *ml = &l;

ClearMoves(ml);
for(i = 0; i < MAXLEGAL; i++) {
  ml->moves[i].oldep = pos->epstatus;
  ml->moves[i].oldcastle = pos->castle;  }

if(side == WHITE)  {
  xside = BLACK;  direc = 1;  }
else {
  xside = WHITE;  direc = -1;  }

memcpy(&(board[0][0]), &(pos->board[0][0]), sizeof(SQUARE) * 144);

for(i = 2; i < 10; i++)
  for(j = 2; j < 10; j++)  {
    if(board[i][j] != 0 && (board[i][j] & side))  {
      if(board[i][j] & KNIGHT)  {
        x = -1; y = -2;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = -1; y = 2;
        if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = 1; y = -2;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
      	x = 1; y = 2;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
       	x = -2; y = -1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = -2; y = 1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = 2; y = -1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = 2; y = 1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
      }
      if((board[i][j] & BISHOP) || (board[i][j] & QUEEN))  {
        for(x = 1; (board[i-x][j-x] != OFFBOARD) && (!(board[i-x][j-x] & side)); x++)
          if(board[i-x][j-x] & xside)  {  
            AddMove(ml, i, j, i-x, j-x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i-x, j-x, NORMAL);
        for(x = 1; (board[i-x][j+x] != OFFBOARD) && (!(board[i-x][j+x] & side)); x++)
          if(board[i-x][j+x] & xside)  {  
            AddMove(ml, i, j, i-x, j+x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i-x, j+x, NORMAL);
        for(x = 1; (board[i+x][j-x] != OFFBOARD) && (!(board[i+x][j-x] & side)); x++)
          if(board[i+x][j-x] & xside)  {  
            AddMove(ml, i, j, i+x, j-x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i+x, j-x, NORMAL);
        for(x = 1; (board[i+x][j+x] != OFFBOARD) && (!(board[i+x][j+x] & side)); x++)
          if(board[i+x][j+x] & xside)  {  
            AddMove(ml, i, j, i+x, j+x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i+x, j+x, NORMAL);
      }
      if((board[i][j] & ROOK) || (board[i][j] & QUEEN))  {
        for(x = 1; (board[i-x][j] != OFFBOARD) && (!(board[i-x][j] & side)); x++)
          if(board[i-x][j] & xside) {
            AddMove(ml, i, j, i-x, j, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i-x, j, NORMAL);
        for(x = 1; (board[i+x][j] != OFFBOARD) && (!(board[i+x][j] & side)); x++)
          if(board[i+x][j] & xside) {
            AddMove(ml, i, j, i+x, j, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i+x, j, NORMAL);
        for(x = 1; (board[i][j-x] != OFFBOARD) && (!(board[i][j-x] & side)); x++)
          if(board[i][j-x] & xside) {
            AddMove(ml, i, j, i, j-x, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i, j-x, NORMAL);
        for(x = 1; (board[i][j+x] != OFFBOARD) && (!(board[i][j+x] & side)); x++)
          if(board[i][j+x] & xside) {
            AddMove(ml, i, j, i, j+x, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i, j+x, NORMAL);
      }
      if(board[i][j] & KING)  {
        for(x = -1; x <= 1; x++)
          for(y = -1; y <= 1; y++)  {
            if(x == 0 && y == 0) continue;
            if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
              if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
              else AddMove(ml, i, j, i+x, j+y, NORMAL);
            }
          }
        }
      if(board[i][j] & PAWN)  {
        if(board[i][j+direc] == 0) {
          if((direc == -1 && j == 3) || (direc == 1 && j == 8))
            AddMove(ml, i, j, i, j+direc, PROMOTE);
          else AddMove(ml, i, j, i, j+direc, NORMAL);
        }
        if((direc == -1 && j == 8) || (direc == 1 && j == 3)) 
          if(board[i][j+direc+direc] == 0 && board[i][j+direc] == 0) 
            AddMove(ml, i, j, i, j+direc+direc, TWOMOVE);
        if((board[i-1][j+direc] != OFFBOARD) && (board[i-1][j+direc] & xside)) {
          if((direc == -1 && j == 3) || (direc == 1 && j == 8))
            AddMove(ml, i, j, i-1, j+direc, PROMCAP);
          else AddMove(ml, i, j, i-1, j+direc, CAPTURE);      
        }
        if((board[i+1][j+direc] != OFFBOARD) && (board[i+1][j+direc] & xside)) {
          if((direc == -1 && j == 3) || (direc == 1 && j == 8))
            AddMove(ml, i, j, i+1, j+direc, PROMCAP);
          else AddMove(ml, i, j, i+1, j+direc, CAPTURE); 
        }
        if(pos->epstatus > 0 && direc == 1)  /* there is at least one ep square */  {
          if(j == 6 && IsEpSquare(i-1, 6, pos->epstatus) == 1 && board[i-1][j+direc] == 0)
            AddMove(ml, i, j, i-1, j+direc, ENPASSANT);
          if(j == 6 && IsEpSquare(i+1, 6, pos->epstatus) == 1 && board[i+1][j+direc] == 0)
            AddMove(ml, i, j, i+1, j+direc, ENPASSANT);
        }

        if(pos->epstatus > 0 && direc == -1)  {
          if(j == 5 && IsEpSquare(i-1, 5, pos->epstatus) == 1 && board[i-1][j+direc] == 0)
            AddMove(ml, i, j, i-1, j+direc, ENPASSANT);
          if(j == 5 && IsEpSquare(i+1, 5, pos->epstatus) == 1 && board[i+1][j+direc] == 0)
            AddMove(ml, i, j, i+1, j+direc, ENPASSANT);   
         }

      }

      for(x = 0; ml->moves[x].mtype != EMPTY; x++)  {
        MakeMove(pos, &(ml->moves[x]));
        if(IsCheck(pos, side) == 1)  {
          UnmakeMove(pos, &(ml->moves[x]));
          ml->moves[x].mtype = EMPTY;
          ml->num--;  }
        else UnmakeMove(pos, &(ml->moves[x]));
        }

        if(ml->num > 0) {   return 1;  }

      }
    }

return 0;

}
Esempio n. 10
0
void GenerateMoves(Listnode *ml, Position *pos)
{

int i, j, x, y, direc, cancastle;
unsigned char side = pos->side, xside;
SQUARE board[12][12];

if(side == WHITE)  {
  xside = BLACK;  direc = 1;  }
else {
  xside = WHITE;  direc = -1;  }

ClearMoves(ml);
for(i = 0; i < MAXLEGAL; i++) {
  ml->moves[i].oldep = pos->epstatus;
  ml->moves[i].oldcastle = pos->castle;  }

memcpy(&(board[0][0]), &(pos->board[0][0]), sizeof(SQUARE) * 144);

for(i = 2; i < 10; i++)  {
  for(j = 2; j < 10; j++)  {
    if(board[i][j] != 0 && (board[i][j] & side))  {
      if(board[i][j] & KNIGHT)  {
        x = -1; y = -2;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = -1; y = 2;
        if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = 1; y = -2;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
      	x = 1; y = 2;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
       	x = -2; y = -1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = -2; y = 1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = 2; y = -1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
        x = 2; y = 1;
	if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
          if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
          else AddMove(ml, i, j, i+x, j+y, NORMAL);
        }
      }
      if((board[i][j] & BISHOP) || (board[i][j] & QUEEN))  {
        for(x = 1; (board[i-x][j-x] != OFFBOARD) && (!(board[i-x][j-x] & side)); x++)
          if(board[i-x][j-x] & xside)  {  
            AddMove(ml, i, j, i-x, j-x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i-x, j-x, NORMAL);
        for(x = 1; (board[i-x][j+x] != OFFBOARD) && (!(board[i-x][j+x] & side)); x++)
          if(board[i-x][j+x] & xside)  {  
            AddMove(ml, i, j, i-x, j+x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i-x, j+x, NORMAL);
        for(x = 1; (board[i+x][j-x] != OFFBOARD) && (!(board[i+x][j-x] & side)); x++)
          if(board[i+x][j-x] & xside)  {  
            AddMove(ml, i, j, i+x, j-x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i+x, j-x, NORMAL);
        for(x = 1; (board[i+x][j+x] != OFFBOARD) && (!(board[i+x][j+x] & side)); x++)
          if(board[i+x][j+x] & xside)  {  
            AddMove(ml, i, j, i+x, j+x, CAPTURE);
            break;  }
	  else AddMove(ml, i, j, i+x, j+x, NORMAL);
        }
      if((board[i][j] & ROOK) || (board[i][j] & QUEEN))  {
        for(x = 1; (board[i-x][j] != OFFBOARD) && (!(board[i-x][j] & side)); x++)
          if(board[i-x][j] & xside) {
            AddMove(ml, i, j, i-x, j, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i-x, j, NORMAL);
        for(x = 1; (board[i+x][j] != OFFBOARD) && (!(board[i+x][j] & side)); x++)
          if(board[i+x][j] & xside) {
            AddMove(ml, i, j, i+x, j, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i+x, j, NORMAL);
        for(x = 1; (board[i][j-x] != OFFBOARD) && (!(board[i][j-x] & side)); x++)
          if(board[i][j-x] & xside) {
            AddMove(ml, i, j, i, j-x, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i, j-x, NORMAL);
        for(x = 1; (board[i][j+x] != OFFBOARD) && (!(board[i][j+x] & side)); x++)
          if(board[i][j+x] & xside) {
            AddMove(ml, i, j, i, j+x, CAPTURE);
            break;  }
          else AddMove(ml, i, j, i, j+x, NORMAL);
        }
      if(board[i][j] & KING)  {
        for(x = -1; x <= 1; x++)
          for(y = -1; y <= 1; y++)  {
            if(x == 0 && y == 0) continue;
            if((board[i+x][j+y] != OFFBOARD) && (!(board[i+x][j+y] & side))) {
              if(board[i+x][j+y] & xside)  AddMove(ml, i, j, i+x, j+y, CAPTURE);
              else AddMove(ml, i, j, i+x, j+y, NORMAL);
            }
          }
        }
      if(board[i][j] & PAWN)  {
        if(board[i][j+direc] == 0) {
          if((direc == -1 && j == 3) || (direc == 1 && j == 8))
            AddMove(ml, i, j, i, j+direc, PROMOTE);
          else AddMove(ml, i, j, i, j+direc, NORMAL);
        }
        if((direc == -1 && j == 8) || (direc == 1 && j == 3))
          if(board[i][j+direc+direc] == 0 && board[i][j+direc] == 0) 
            AddMove(ml, i, j, i, j+direc+direc, TWOMOVE);
        if((board[i-1][j+direc] != OFFBOARD) && (board[i-1][j+direc] & xside)) {
          if((direc == -1 && j == 3) || (direc == 1 && j == 8))
            AddMove(ml, i, j, i-1, j+direc, PROMCAP);
          else AddMove(ml, i, j, i-1, j+direc, CAPTURE);      
        }
        if((board[i+1][j+direc] != OFFBOARD) && (board[i+1][j+direc] & xside)) {
          if((direc == -1 && j == 3) || (direc == 1 && j == 8))
            AddMove(ml, i, j, i+1, j+direc, PROMCAP);
          else AddMove(ml, i, j, i+1, j+direc, CAPTURE); 
        }
        /* there is at least one ep square */  
        if(pos->epstatus > 0 && direc == 1) {
          if(j == 6 && IsEpSquare(i-1, 6, pos->epstatus) == 1 && board[i-1][j+direc] == 0)
            AddMove(ml, i, j, i-1, j+direc, ENPASSANT);
          if(j == 6 && IsEpSquare(i+1, 6, pos->epstatus) == 1 && board[i+1][j+direc] == 0)
            AddMove(ml, i, j, i+1, j+direc, ENPASSANT);
        }

        if(pos->epstatus > 0 && direc == -1)  {
          if(j == 5 && IsEpSquare(i-1, 5, pos->epstatus) == 1 && board[i-1][j+direc] == 0)
            AddMove(ml, i, j, i-1, j+direc, ENPASSANT);
          if(j == 5 && IsEpSquare(i+1, 5, pos->epstatus) == 1 && board[i+1][j+direc] == 0)
            AddMove(ml, i, j, i+1, j+direc, ENPASSANT);   
        }
      }
    }
  }
}

if((pos->castle & WKC) && side == WHITE)  {
  cancastle = 1;
  for(i = KFILE; i <= 8; i++) 
    if(Attacked(pos, i, 2, xside) == 1) cancastle = 0;
  for(i = Minval(7, KFILE); i <= 8; i++)
    if(i != KFILE && i != KRFILE && board[i][2] != 0) cancastle = 0;
 if(cancastle == 1)
    AddMove(ml, KFILE, 2, 8, 2, KSCASTLE);  }
if((pos->castle & BKC) && side == BLACK)  {
  cancastle = 1;
  for(i = KFILE; i <= 8; i++) 
    if(Attacked(pos, i, 9, xside) == 1) cancastle = 0;
  for(i = Minval(7, KFILE); i <= 8; i++)
    if(i != KFILE && i != KRFILE && board[i][9] != 0) cancastle = 0;
 if(cancastle == 1)
    AddMove(ml, KFILE, 9, 8, 9, KSCASTLE);  }
if((pos->castle & WQC) && side == WHITE)  {
  cancastle = 1;
  for(i = Minval(4, KFILE); i <= Maxval(4, KFILE); i++) 
    if(Attacked(pos, i, 2, xside) == 1) cancastle = 0;
  for(i = Minval(QRFILE + 1, 4); i <= Maxval(5, KFILE); i++)
    if(i != KFILE && i != QRFILE && board[i][2] != 0) cancastle = 0;
 if(cancastle == 1)
    AddMove(ml, KFILE, 2, 4, 2, QSCASTLE);  }
if((pos->castle & BQC) && side == BLACK)  {
  cancastle = 1;
  for(i = Minval(4, KFILE); i <= Maxval(4, KFILE); i++) 
    if(Attacked(pos, i, 9, xside) == 1) cancastle = 0;
  for(i = Minval(QRFILE + 1, 4); i <= Maxval(5, KFILE); i++)
    if(i != KFILE && i != QRFILE && board[i][9] != 0) cancastle = 0;
 if(cancastle == 1)
    AddMove(ml, KFILE, 9, 4, 9, QSCASTLE);  }

for(i = 0; ml->moves[i].mtype != EMPTY; i++)  {
  MakeMove(pos, &(ml->moves[i]));
  if(IsCheck(pos, side) == 1)  {
    UnmakeMove(pos, &(ml->moves[i]));
    ml->moves[i].mtype = EMPTY;
    ml->num--;  }
  else UnmakeMove(pos, &(ml->moves[i]));
  }

}
Esempio n. 11
0
int SearchRoot (int depth, int alpha, int beta)
/**************************************************************************
 *
 *  This perform searches at ply=1.  For ply>1, it calls the more generic
 *  search() routine.  The rationale for splitting these is because at
 *  ply==1, things are done slightly differently than from the other plies,
 *  e.g. print PVs, not testing null move etc.
 *
 **************************************************************************/
{
   int best, score, savealpha;
   int side, xside;
   int ply, nodetype;
   leaf *p, *pbest;

   ply = 1; 
   side = board.side;
   xside = 1^side;
   ChkCnt[2] = ChkCnt[1];
   ThrtCnt[2] = ThrtCnt[1];
   KingThrt[white][ply] = MateScan (white);
   KingThrt[black][ply] = MateScan (black);
   InChk[ply] = SqAtakd (board.king[side], xside);
   if (InChk[ply] && ChkCnt[ply] < 3*Idepth/DEPTH)
   {
      ChkExtCnt++;
      ChkCnt[ply+1]++;
      depth += DEPTH;
   }
   best = -INFINITY;
   savealpha = alpha;
   nodetype = PV;
   pbest = NULL;

   for (p = TreePtr[1]; p < TreePtr[2]; p++)
   {
      pick (p, 1); 
      ShowThinking (p, ply);
      MakeMove (side, &p->move);
      NodeCnt++;
      
      /*  If first move, search against full alpha-beta window  */
      if (p == TreePtr[1])
      {
         score = -Search (2, depth-DEPTH, -beta, -alpha, nodetype);
         /*
	    The following occurs when we are re-searching a fail high move
            and now it has fail low.  This can be disastrous, so immediately
	    adjust alpha and research.
          */
	 if (beta == INFINITY && score <= alpha)
	 {
	    alpha = -INFINITY;
            score = -Search (2, depth-DEPTH, -beta, -alpha, nodetype);
         }
      }

      /*  Else search against zero window  */
      else
      {
	 nodetype = CUT;
         alpha = MAX (best, alpha);            
         score = -Search (2, depth-DEPTH, -alpha-1, -alpha, nodetype);
         if (score > best)
         {
            if (alpha < score && score < beta)
	    {
	       nodetype = PV;
               score = -Search (2, depth-DEPTH, -beta, -score, nodetype);
	    }
         }
      }
      UnmakeMove (xside, &p->move);

      ply1score = p->score = score;
      if (score > best)
      {
         best = score;
	 pbest = p;
         if (best > alpha)
         {
            rootscore = best;
            RootPV = p->move;
	    if (best >= beta)
	       goto done;
            ShowLine (RootPV, best, '&');
         }
      }

      if (flags & TIMEOUT)
      {
	/* XXX: It seems that ply == 1 always at this point */
         best = (ply & 1 ? rootscore : -rootscore );
	 return (best);
      }

      if (SearchDepth == 0 && (NodeCnt & TIMECHECK) == 0)
      {
         GetElapsed ();
         if ((et >= SearchTime && (rootscore == -INFINITY-1 || 
		ply1score > lastrootscore - 25 || flags & SOLVE)) ||
	     et >= maxtime)
	    SET (flags, TIMEOUT);        
      }

      if (MATE+1 == best+1)
         return (best);
   }

/*  If none of the move is good, we still want to try the same first move */
   if (best <= savealpha)
      TreePtr[1]->score = savealpha;

/*****************************************************************************
 *
 *  Out of main search loop.
 *
 *****************************************************************************/
done:

   /*  Update history  */
   if (best > savealpha)
      history[side][pbest->move & 0x0FFF] += HISTSCORE(depth/DEPTH);

   rootscore = best;
   return (best);
}
Esempio n. 12
0
int CNegaScout_TT_HH::NegaScout(int depth, int alpha, int beta){
	int count,i;
	int type;
	int a,b,t;
	int side;
	int score;
	
	i = IsGameOver(m_cur_position, depth);
	if (i != 0)
		return i;
	
	side = 1-(m_max_depth-depth)%2;
	
	score = m_tt->LookupHashTable(alpha, beta, depth, side);
	if (score != INVALID_SCORE && depth != m_max_depth){
		/*if (depth == m_max_depth){
			ChessMove move = new ChessMove();
			move.Move = m_tt.LookupBestMove(side);
			m_best_move = move;
		}*/
		return score;
	}
	
	if (depth <= 0)	
	{
		score = m_evaluator->Evaluate(m_cur_position, side == 0, depth);
		m_tt->EnterHashTable(EXACT, score, depth, side);
		return score;
	}
	
	//m_nMovecount = 0;
	count = m_move_generator->CreatePossibleMove(m_cur_position, m_moves, depth, side);
	AddMoves(count, depth);
	
	for (i = 0; i < count; ++i) 
	{
		m_move_list[depth][i].m_score = m_hh->GetHistoryScore(m_move_list[depth][i]);
	}
	m_hh->MergeSort(m_move_list[depth], count, false);
	
	int bestmove = -1;
	
    a = alpha;
    b = beta;
    int eval_is_exact = 0;
    for (i = 0; i < count; ++i){
		m_tt->HashMakeMove(m_move_list[depth][i], m_cur_position);
		type = MakeMove(m_move_list[depth][i]);

		t = -NegaScout(depth-1 , -b, -a);

		if (t > a && t < beta && i > 0){
			a = -NegaScout (depth-1, -beta, -t);     /* re-search */
			eval_is_exact = 1; 
			if(depth == m_max_depth){
				m_best_move = m_move_list[depth][i];
				//m_tt.EnterHashBestMove(m_best_move.Move, side);
			}
			bestmove = i; 
		}
		
		m_tt->HashUnmakeMove(m_move_list[depth][i], type, m_cur_position); 
		UnmakeMove(m_move_list[depth][i],type); 
		if (a < t){
			eval_is_exact = 1;
			a = t;
			if(depth == m_max_depth) {
				m_best_move = m_move_list[depth][i];
				//m_tt.EnterHashBestMove(m_best_move.Move, side);
			}
		}
		if (a >= beta) 
		{
			m_tt->EnterHashTable(LOWER_BOUND, a, depth, side);
			m_hh->EnterHistoryScore(m_move_list[depth][i], depth);
			return a;
		}
		b = a + 1;                      /* set new null window */
	}
	if (bestmove != -1)
		m_hh->EnterHistoryScore(m_move_list[depth][bestmove], depth);
	if (eval_is_exact != 0) 
		m_tt->EnterHashTable(EXACT, a, depth, side);
	else 
		m_tt->EnterHashTable(UPPER_BOUND, a, depth, side);
	return a;
}
Esempio n. 13
0
int Quiesce (uint8_t ply, int alpha, int beta)
/**************************************************************************
 *
 *  Our quiescent search.  This quiescent search is able to recognize
 *  mates.
 *
 **************************************************************************/
{
   uint8_t side, xside;
   int best, delta, score, savealpha;
   leaf *p, *pbest;

   if (EvaluateDraw ())
      return (DRAWSCORE);

   side = board.side;
   xside = 1^side;
   InChk[ply] = SqAtakd (board.king[side], xside);
   best = Evaluate (alpha, beta);
   if (best >= beta && !InChk[ply])
      return (best);
   TreePtr[ply+1] = TreePtr[ply];
   if (InChk[ply])
   {
      GenCheckEscapes (ply);
      if (TreePtr[ply] == TreePtr[ply+1])
         return (-MATE+ply-2);
      if (best >= beta)
         return (best);
      SortMoves (ply);
   }
   else
   {
      GenCaptures (ply);
      if (TreePtr[ply] == TreePtr[ply+1])
         return (best);
      SortCaptures (ply); 
   }

   savealpha = alpha;
   pbest = NULL;
   alpha = MAX(best, alpha);
   delta = MAX (alpha - 150 - best, 0);

   for (p = TreePtr[ply]; p < TreePtr[ply+1]; p++)
   {
      pick (p, ply);

      /* We are in check or capture cannot bring score near alpha, give up */
      if (!InChk[ply] && SwapOff (p->move) < delta)
         continue;

      /* If capture cannot bring score near alpha, give up */
      if (p->score == -INFINITY)
	 continue;

#ifdef THREATEXT
/*  See search.c for an explanation of the code below  */
      if (threatply+1 == ply) 
      {
         if ((TOSQ(p->move) == FROMSQ(threatmv)) || 
		(FROMSQ(p->move) == TOSQ(threatmv)))
	    continue;
      }
      if (threatply && threatply+3 == ply && FROMSQ(p->move) == TOSQ(threatmv))
	 continue;
#endif

      MakeMove (side, &p->move);
      QuiesCnt++;
      if (SqAtakd (board.king[side], xside))
      {
         UnmakeMove (xside, &p->move);
         continue;
      }
      score = -Quiesce (ply+1, -beta, -alpha);
      UnmakeMove (xside, &p->move);
      if (score > best)
      {
         best = score;
	 pbest = p;
         if (best >= beta)
	    goto done;
         alpha = MAX (alpha, best);
      }
   }

done:
   if (flags & USEHASH && pbest != NULL)
      TTPut (side, 0, ply, savealpha, beta, best, pbest->move);

   return (best);
}
Esempio n. 14
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;
}
Esempio n. 15
0
// 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;
}
Esempio n. 16
0
int Search (int ply, int depth, int alpha, int beta, int nodetype)
/**************************************************************************
 *
 *  The basic algorithm for this search routine came from Anthony 
 *  Marsland.  It is a PVS (Principal Variation Search) algorithm.
 *  The fail-soft alpha-beta technique is also used for improved
 *  pruning.
 *
 **************************************************************************/
{
   int best, score, nullscore, savealpha;
   int side, xside;
   int rc, t0, t1, firstmove;
   int fcut, fdel, donull, savenode, nullthreatdone, extend;
   leaf *p, *pbest;
   int g0, g1;
   int upperbound;

   /* Check if this position is a known draw */
   if (EvaluateDraw ())
      return (DRAWSCORE);
   if (GameCnt >= Game50+3 && Repeat())
   {
      RepeatCnt++;
      return (DRAWSCORE); 
   }

   side = board.side;
   xside = 1^side;
   donull = true;

/*************************************************************************
 *
 *  Perform some basic search extensions.
 *  1.  One reply extensions.  
 *  2.  If in check, extend (maximum of Idepth-1).
 *  3.  If there is a threat to the King, extend (not beyond 2*Idepth)
 *  4.  If recapture to same square and not beyond Idepth+2
 *  5.  If pawn move to 7th rank at the leaf node, extend.
 *
 *************************************************************************/
   extend = false;
   InChk[ply] = SqAtakd (board.king[side], xside);
   if (InChk[ply])
   {
      TreePtr[ply+1] = TreePtr[ply];
      GenCheckEscapes (ply);
      if (TreePtr[ply] == TreePtr[ply+1])
         return (-MATE+ply-2);
      if (TreePtr[ply]+1 == TreePtr[ply+1])
      {
         depth += DEPTH;
	 extend = true;
         OneRepCnt++;
      }
   }

/*
   We've already found a mate at the next ply.  If we aren't being mated by 
   a shorter line, so just return the current material value.
*/
   if (rootscore + ply >= MATE)
      return (MATERIAL);

   g0 = Game[GameCnt].move;
   g1 = GameCnt > 0 ? Game[GameCnt-1].move : 0;
   t0 = TOSQ(g0); 
   t1 = TOSQ(g1);
   ChkCnt[ply+1] = ChkCnt[ply];
   ThrtCnt[ply+1] = ThrtCnt[ply];
   KingThrt[white][ply] = MateScan (white);
   KingThrt[black][ply] = MateScan (black);
   if (InChk[ply]  && /* ChkCnt[ply] < Idepth-1*/ ply <= 2*Idepth/DEPTH)
   {
      ChkExtCnt++;
      ChkCnt[ply+1]++;
      depth += DEPTH;
      extend = true;
   }
   else if (!KingThrt[side][ply-1] && KingThrt[side][ply] && ply <= 2*Idepth/DEPTH)
   {
      KingExtCnt++;
      extend = true;
      depth += DEPTH;
      extend = true;
      donull = false;
   }
   /* Promotion extension */
   else if (g0 & PROMOTION)
   {
      PawnExtCnt++;
      depth += DEPTH;
      extend = true;
   }
   /* Recapture extension */
   else if ((g0 & CAPTURE) && (board.material[computer] - 
	board.material[1^computer] == RootMaterial))
   {
      RcpExtCnt++;
      depth += DEPTH;
      extend = true;
   }
   /* 6th or 7th rank extension */
   else if (depth <= DEPTH && cboard[t0] == pawn && (RANK(t0) == rank7[xside] || RANK(t0) == rank6[xside]))
   {
      PawnExtCnt++;
      depth += DEPTH;
      extend = true;
   }

/**************************************************************************** 
 *
 *  The following extension is to handle cases when the opposing side is 
 *  delaying the mate by useless interposing moves. 
 *
 ****************************************************************************/
   if (ply > 2 && InChk[ply-1] && cboard[t0] != king && t0 != t1 && 
	 !SqAtakd (t0, xside))
   {
      HorzExtCnt++;
      depth += DEPTH;
      extend = true;
   }

/***************************************************************************
 *
 *  This is a new code to perform search reductiion.  We introduce some
 *  form of selectivity here.
 *
 **************************************************************************/

   if (depth <= 0)
      return (Quiesce (ply, alpha, beta)); 

/**************************************************************************** 
 *
 *  Probe the transposition table for a score and a move.
 *  If the score is an upperbound, then we can use it to improve the value
 *  of beta.  If a lowerbound, we improve alpha.  If it is an exact score,
 *  if we now get a cut-off due to the new alpha/beta, return the score.
 *
 ***************************************************************************/
   Hashmv[ply] = 0;
   upperbound = INFINITY;
   if (flags & USEHASH)
   {
      rc = TTGet (side, depth, ply, alpha, beta, &score, &g1);
      if (rc)
      {
         Hashmv[ply] = g1 & MOVEMASK;
         switch (rc)
         {
            case POORDRAFT  :  break;
	    case EXACTSCORE :  return (score);
            case UPPERBOUND :  beta = MIN (beta, score);
			       upperbound = score;
			       donull = false;
	                       break;
            case LOWERBOUND :  /*alpha = MAX (alpha, score);*/
			       alpha = score;
	                       break;
	    case QUIESCENT  :  Hashmv[ply] = 0;
	                       break;
	    default : break;
         }
	 if (alpha >= beta)
	    return (score);
      }
   }

/*****************************************************************************
 *
 *  Perform the null move here.  There are certain cases when null move
 *  is not done.  
 *  1.  When the previous move is a null move.
 *  2.  At the frontier (depth == 1)
 *  3.  At a PV node.
 *  4.  If side to move is in check.
 *  5.  If the material score + pawn value is still below beta.
 *  6.  If we are being mated at next ply.
 *  7.  If hash table indicate the real score is below beta (UPPERBOUND).
 *  8.  If side to move has less than or equal to a bishop in value.
 *  9.  If Idepth <= 3.  This allows us to find mate-in 2 problems quickly.
 *  10. We are looking for a null threat.
 *
 *****************************************************************************/
   if (ply > 4 && InChk[ply-2] && InChk[ply-4])
      donull = false;
   if (flags & USENULL && g0 != NULLMOVE && depth > DEPTH && nodetype != PV &&
       !InChk[ply] && MATERIAL+ValueP > beta && beta > -MATE+ply && donull &&
	board.pmaterial[side] > ValueB && !threatply)
   {
      TreePtr[ply+1] = TreePtr[ply];
      MakeNullMove (side);
      nullscore = -Search (ply+1, depth-DEPTH-R, -beta, -beta+1, nodetype);
      UnmakeNullMove (xside); 
      if (nullscore >= beta)
      {
         NullCutCnt++;
         return (nullscore);
      }
      if ( depth-DEPTH-R >= 1 && MATERIAL > beta && nullscore <= -MATE+256)
      {
         depth += DEPTH;
	 extend = true;
      }
   }

   if (InChk[ply] && TreePtr[ply]+1 < TreePtr[ply+1])
      SortMoves (ply);

   pickphase[ply] = PICKHASH;
   GETNEXTMOVE;

/*************************************************************************
 *
 *  Razoring + Futility.
 *  At depth 3, if there is no extensions and we are really bad, decrease
 *  the search depth by 1.
 *  At depth 2, if there is no extensions and we are quite bad, then we
 *  prune all non checking moves and capturing moves that don't bring us up
 *  back to alpha.
 *  Caveat: Skip all this if we are in the ending.
 *
 *************************************************************************/
   fcut = false;
   fdel = MAX (ValueQ, maxposnscore[side]);
   if (!extend && nodetype != PV && depth == 3*DEPTH && FUTSCORE <= alpha)
   {
      depth = 2*DEPTH;
      RazrCutCnt++;
   }
   fdel = MAX (ValueR, maxposnscore[side]);
   fcut = (!extend && nodetype != PV && depth == 2*DEPTH && FUTSCORE <= alpha);
   if (!fcut)
   {
      fdel = MAX (3*ValueP, maxposnscore[side]);
      fcut = (nodetype != PV && depth == DEPTH && FUTSCORE <= alpha);
   }

   MakeMove (side, &p->move);
   NodeCnt++;
   g0 = g1 = 0;
   while ((g0 = SqAtakd (board.king[side], xside)) > 0 ||
      	 (fcut && FUTSCORE < alpha && !SqAtakd (board.king[xside], side) &&
	  !MateScan (xside)))
   {
      if (g0 == 0) g1++;
      UnmakeMove (xside, &p->move);
      if (GETNEXTMOVE == false)
         return (g1 ? Evaluate(alpha,beta) : DRAWSCORE);
      MakeMove (side, &p->move);
      NodeCnt++;
   }
   firstmove = true;
   pbest = p;
   best = -INFINITY;
   savealpha = alpha;
   nullthreatdone = false;
   nullscore = INFINITY;
   savenode = nodetype;
   if (nodetype != PV)
      nodetype = (nodetype == CUT) ? ALL : CUT;

   while (1)
   {
      /* We have already made the move before the loop. */
      if (firstmove)
      {
         firstmove = false;
         score = -Search (ply+1, depth-DEPTH, -beta, -alpha, nodetype);
      }

      /* Zero window search for rest of moves */
      else
      {
	 if (GETNEXTMOVE == false)
	    break;

#ifdef THREATEXT
/****************************************************************************
 *
 *  This section needs to be explained.  We are doing a null threat search
 *  and the previous ply was the null move.  Inhibit any move which captures
 *  the fail-high moving piece.  Also inhibit any move by the piece which is 
 *  captured by the fail-high move.  Both these moves cannot be executed in
 *  the actual threat, so.....
 *  Also 3 plies later, inhibit moves out of the target square of the PV/fail
 *  high move as this is also not possible.
 *
 ****************************************************************************/
	 if (threatply+1 == ply)
	 { 
	    if ((TOSQ(p->move) == FROMSQ(threatmv)) ||
			 (FROMSQ(p->move) == TOSQ(threatmv)))
	       continue; 
	 }
         if (threatply && threatply+3 == ply && FROMSQ(p->move)==TOSQ(threatmv))
            continue;
#endif

         MakeMove (side, &p->move);
         NodeCnt++;
         if (SqAtakd (board.king[side], xside)) 
         {
            UnmakeMove (xside, &p->move);
            continue;
         }

/*****************************************************************************
 *
 *  Futility pruning.  The idea is that at the frontier node (depth == 1),
 *  if the side on the move is materially bad, then if the move doesn't win
 *  back material or the move isn't a check or doesn't threatened the king, 
 *  then there is no point in searching this move.  So skip it.  
 *  Caveat:  However if the node is a PV, we skip this test.
 *
 *****************************************************************************/
      	 if (fcut && FUTSCORE <= alpha && !SqAtakd (board.king[xside], side) &&
		!MateScan (xside))
		
         {
            UnmakeMove (xside, &p->move);
	    FutlCutCnt++;
	    NodeCnt--;
            continue;
         }
         NodeCnt++;

         if (nodetype == PV)
            nodetype = CUT;
         alpha = MAX (best, alpha);                /* fail-soft condition */
         score = -Search (ply+1, depth-DEPTH, -alpha-1, -alpha, nodetype);
         if (score > best)
         {
	    if (savenode == PV)
	       nodetype = PV;
            if (alpha < score && score < beta)
	    {
               score = -Search (ply+1, depth-DEPTH, -beta, -score, nodetype);
	    } 
	    if (nodetype == PV && score <= alpha &&
		Game[GameCnt+1].move == NULLMOVE)
	    {
               score = -Search (ply+1, depth-DEPTH, -alpha, INFINITY, nodetype);
	    }
         }
      }
      UnmakeMove (xside, &p->move);

/*  Perform threat extensions code */
#ifdef THREATEXT
      if ((score >= beta || nodetype == PV) && !InChk[ply] && g0 != NULLMOVE &&
	!threatply && depth == 4 && ThrtCnt[ply] < 1)
      {
	 if (!nullthreatdone)
	 {
	    threatply = ply;
	    threatmv  = p->move;
            MakeNullMove (side);
            nullscore = -Search(ply+1, depth-1-R, -alpha+THREATMARGIN, 
			-alpha+THREATMARGIN+1, nodetype);
            UnmakeNullMove (xside); 
	    nullthreatdone = true;
	    threatply = 0;
	 }
	 if (nullscore <= alpha-THREATMARGIN)
	 {
	    ThrtExtCnt++;
            ThrtCnt[ply+1]++;
            MakeMove (side, &p->move);
            score = -Search (ply+1, depth, -beta, -alpha, nodetype);
            UnmakeMove (xside, &p->move);
            ThrtCnt[ply+1]--;
         }
      }	
#endif
      
      if (score > best)
      {
         best = score;
         pbest = p;
	 if (best >= beta)
	    goto done;
      }

      if (flags & TIMEOUT)
      {
         best = (ply & 1 ? rootscore : -rootscore);
	 return (best);
      }

      if (SearchDepth == 0 && (NodeCnt & TIMECHECK) == 0)
      {
         GetElapsed ();
         if ((et >= SearchTime && (rootscore == -INFINITY-1 || 
		ply1score > lastrootscore - 25 || flags & SOLVE)) ||
	     et >= maxtime)
	    SET (flags, TIMEOUT);        
      }

/*  The following line should be explained as I occasionally forget too :) */
/*  This code means that if at this ply, a mating move has been found,     */
/*  then we can skip the rest of the moves!  				   */
      if (MATE+1 == best+ply)
         goto done;
   } 

/*****************************************************************************
 *
 *  Out of main search loop.
 *
 *****************************************************************************/
done:

/*
   if (upperbound < best)
      printf ("Inconsistencies %d %d\n", upperbound, best);
*/

   /*  Save the best move inside the transposition table  */
   if (flags & USEHASH)
      TTPut (side, depth, ply, savealpha, beta, best, pbest->move); 

   /*  Update history  */
   if (best > savealpha)
      history[side][pbest->move & 0x0FFF] += HISTSCORE(depth/DEPTH);

   /*  Don't store captures as killers as they are tried before killers */
   if (!(pbest->move & (CAPTURE | PROMOTION)) && best > savealpha)
   {
      if (killer1[ply] == 0)
         killer1[ply] = pbest->move & MOVEMASK;
      else if ((pbest->move & MOVEMASK) != killer1[ply])
         killer2[ply] = pbest->move & MOVEMASK;
   }

   return (best);
}
Esempio n. 17
0
/*
 *******************************************************************************
 *                                                                             *
 *   Ponder() is the driver for "pondering" (thinking on the opponent's time.) *
 *   its operation is simple:  Find a predicted move by (a) taking the second  *
 *   move from the principal variation, or (b) call lookup to see if it finds  *
 *   a suggested move from the transposition table.  Then, make this move and  *
 *   do a search from the resulting position.  While pondering, one of three   *
 *   things can happen:  (1) A move is entered, and it matches the predicted   *
 *   move.  We then switch from pondering to thinking and search as normal;    *
 *   (2) A move is entered, but it does not match the predicted move.  We then *
 *   abort the search, unmake the pondered move, and then restart with the     *
 *   move entered.  (3) A command is entered.  If it is a simple command, it   *
 *   can be done without aborting the search or losing time.  If not, we abort *
 *   the search, execute the command, and then attempt to restart pondering if *
 *   the command didn't make that impossible.                                  *
 *                                                                             *
 *******************************************************************************
 */
int Ponder(int wtm) {
  TREE *const tree = block[0];
  int dalpha = -999999, dbeta = 999999, i;
  unsigned *n_ponder_moves, *mv;
  int save_move_number, tlom, value;

/*
 ************************************************************
 *                                                          *
 *  First, let's check to see if pondering is allowed, or   *
 *  if we should avoid pondering on this move since it is   *
 *  the first move of a game, or if the game is over, or    *
 *  "force" mode is active, or there is input in the queue  *
 *  that needs to be read and processed.                    *
 *                                                          *
 ************************************************************
 */
  if (!ponder || force || over || CheckInput())
    return 0;
  save_move_number = move_number;
/*
 ************************************************************
 *                                                          *
 *  Check the ponder move for legality.  If it is not a     *
 *  legal move, we have to take action to find something to *
 *  ponder.                                                 *
 *                                                          *
 ************************************************************
 */
  strcpy(ponder_text, "none");
  if (ponder_move) {
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
      ponder_move = 0;
      Print(4095, "ERROR.  ponder_move is illegal (1).\n");
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
      Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
    }
  }
/*
 ************************************************************
 *                                                          *
 *  First attempt, do a hash probe.  However, since a hash  *
 *  collision is remotely possible, we still need to verify *
 *  that the transposition/refutation best move is actually *
 *  legal.                                                  *
 *                                                          *
 ************************************************************
 */
  if (!ponder_move) {
    HashProbe(tree, 0, 0, wtm, dalpha, dbeta, &value);
    if (tree->hash_move[0])
      ponder_move = tree->hash_move[0];
    if (ponder_move) {
      if (!VerifyMove(tree, 1, wtm, ponder_move)) {
        Print(4095, "ERROR.  ponder_move is illegal (2).\n");
        Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
        ponder_move = 0;
      }
    }
  }
/*
 ************************************************************
 *                                                          *
 *  Second attempt.  If that didn't work, then we try what  *
 *  I call a "puzzling" search.  Which is simply a shorter  *
 *  time-limit search for the other side, to find something *
 *  to ponder.                                              *
 *                                                          *
 ************************************************************
 */
  if (!ponder_move) {
    TimeSet(puzzle);
    if (time_limit < 20)
      return 0;
    puzzling = 1;
    tree->status[1] = tree->status[0];
    Print(32, "              puzzling over a move to ponder.\n");
    last_pv.pathl = 0;
    last_pv.pathd = 0;
    for (i = 0; i < MAXPLY; i++) {
      tree->killers[i].move1 = 0;
      tree->killers[i].move2 = 0;
    }
    Iterate(wtm, puzzle, 0);
    for (i = 0; i < MAXPLY; i++) {
      tree->killers[i].move1 = 0;
      tree->killers[i].move2 = 0;
    }
    puzzling = 0;
    if (tree->pv[0].pathl)
      ponder_move = tree->pv[0].path[1];
    if (!ponder_move)
      return 0;
    for (i = 1; i < (int) tree->pv[0].pathl; i++)
      last_pv.path[i] = tree->pv[0].path[i + 1];
    last_pv.pathl = tree->pv[0].pathl - 1;
    last_pv.pathd = 0;
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
      ponder_move = 0;
      Print(4095, "ERROR.  ponder_move is illegal (3).\n");
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
      return 0;
    }
  }
/*
 ************************************************************
 *                                                          *
 *  Display the move we are going to "ponder".              *
 *                                                          *
 ************************************************************
 */
  if (wtm)
    Print(32, "White(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
            wtm, ponder_move));
  else
    Print(32, "Black(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
            wtm, ponder_move));
  sprintf(ponder_text, "%s", OutputMove(tree, 0, wtm, ponder_move));
  if (post)
    printf("Hint: %s\n", ponder_text);
/*
 ************************************************************
 *                                                          *
 *  Set the ponder move list and eliminate illegal moves.   *
 *  This list is used to test the move entered while we are *
 *  pondering, since we need a move list for the input      *
 *  screening process.                                      *
 *                                                          *
 ************************************************************
 */
  n_ponder_moves = GenerateCaptures(tree, 0, wtm, ponder_moves);
  num_ponder_moves =
      GenerateNoncaptures(tree, 0, wtm, n_ponder_moves) - ponder_moves;
  for (mv = ponder_moves; mv < ponder_moves + num_ponder_moves; mv++) {
    MakeMove(tree, 0, wtm, *mv);
    if (Check(wtm)) {
      UnmakeMove(tree, 0, wtm, *mv);
      *mv = 0;
    } else
      UnmakeMove(tree, 0, wtm, *mv);
  }
/*
 ************************************************************
 *                                                          *
 *  Now, perform an iterated search, but with the special   *
 *  "pondering" flag set which changes the time controls    *
 *  since there is no need to stop searching until the      *
 *  opponent makes a move.                                  *
 *                                                          *
 ************************************************************
 */
  MakeMove(tree, 0, wtm, ponder_move);
  tree->curmv[0] = ponder_move;
  tree->rep_list[++rep_index] = HashKey;
  tlom = last_opponent_move;
  last_opponent_move = ponder_move;
  if (kibitz)
    strcpy(kibitz_text, "n/a");
  thinking = 0;
  pondering = 1;
  if (!wtm)
    move_number++;
  ponder_value = Iterate(Flip(wtm), think, 0);
  rep_index--;
  move_number = save_move_number;
  pondering = 0;
  thinking = 0;
  last_opponent_move = tlom;
  UnmakeMove(tree, 0, wtm, ponder_move);
/*
 ************************************************************
 *                                                          *
 *  Search completed. the possible return values are:       *
 *                                                          *
 *  (0) No pondering was done, period.                      *
 *                                                          *
 *  (1) Pondering was done, opponent made the predicted     *
 *      move, and we searched until time ran out in a       *
 *      normal manner.                                      *
 *                                                          *
 *  (2) Pondering was done, but the ponder search           *
 *      terminated due to either finding a mate, or the     *
 *      maximum search depth was reached.  The result of    *
 *      this ponder search are valid, but only if the       *
 *      opponent makes the correct (predicted) move.        *
 *                                                          *
 *  (3) Pondering was done, but the opponent either made a  *
 *      different move, or entered a command that has to    *
 *      interrupt the pondering search before the command   *
 *      (or move) can be processed.  This forces Main() to  *
 *      avoid reading in a move/command since one has been  *
 *      read into the command buffer already.               *
 *                                                          *
 ************************************************************
 */
  if (input_status == 1)
    return 1;
  if (input_status == 2)
    return 3;
  return 2;
}
Esempio n. 18
0
void ShowLine (int move __attribute__ ((unused)), int score, char c)
/*****************************************************************************
 *
 *  Print out the latest PV found during the search.
 *  The only move we know is the root move.  The rest of the PV is taken
 *  from the hash table.  This strategy avoids all the headaches associated
 *  with returning the PV up from the leaf to the root.
 *
 *****************************************************************************/
{
   int i, len;
   int pvar[MAXPLYDEPTH];

   /* SMC */
   if (!(flags & POST))
     return;
   if (NodeCnt < 500000 && (flags & SOLVE)) {
      /* printf("NodeCnt = %d\n",NodeCnt); getchar(); */
      return;
   }
   if (Idepth == DEPTH && c == '&')
      return;
   if ((flags & XBOARD) && c == '&')
      return;
   if (rootscore == -INFINITY-1)
      return;
   GetElapsed ();

   /*
    * What is the reason for these different output formats, in
    * particular for et?
    */
   if (flags & XBOARD) {
     if (score > MATE-255) {
       printf ("%d%c Mat%d %d %lu\t", Idepth/DEPTH, c,
                (int)(MATE+2-abs(score))/2, (int)(et*100), NodeCnt+QuiesCnt);
       if (ofp != stdout)
	 fprintf (ofp,"%2d%c%7.2f  Mat%02d%10lu\t", Idepth/DEPTH, c, et,
                (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
     } else if (score < -MATE+255) {
       printf ("%d%c -Mat%2d %d %lu\t", Idepth/DEPTH, c,
                (int)(MATE+2-abs(score))/2, (int)(et*100), NodeCnt+QuiesCnt);
       if (ofp != stdout)
	 fprintf (ofp,"%2d%c%7.2f -Mat%02d%10lu\t", Idepth/DEPTH, c, et,
		 (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
     } else {
	 printf ("%d%c %d %d %lu\t", Idepth/DEPTH, c, (int)score, 
		 (int)(et*100), NodeCnt+QuiesCnt);
	 if (ofp != stdout) 
	   fprintf (ofp,"%2d%c%7.2f%7d%10lu\t", Idepth/DEPTH, c, et, score, NodeCnt+QuiesCnt);	 
       }
   }
   else {
     if (score > MATE-255) {
       printf ("\r%2d%c%7.2f  Mat%02d%10lu\t", Idepth/DEPTH, c, et,
                (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
       if (ofp != stdout)
	 fprintf (ofp,"\r%2d%c%7.2f  Mat%02d%10lu\t", Idepth/DEPTH, c, et,
                (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
     } else if (score < -MATE+255) {
       printf ("\r%2d%c%7.2f -Mat%02d%10lu\t", Idepth/DEPTH, c, et,
	     (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
       if (ofp != stdout)
	 fprintf (ofp,"\r%2d%c%7.2f -Mat%02d%10lu\t", Idepth/DEPTH, c, et,
		 (MATE+2-abs(score))/2, NodeCnt+QuiesCnt);
     } else {
	 printf ("\r%2d%c%7.2f%7d%10lu\t", Idepth/DEPTH, c, et, score, NodeCnt+QuiesCnt);
	 if (ofp != stdout) 
	   fprintf (ofp,"\r%2d%c%7.2f%7d%10lu\t", Idepth/DEPTH, c, et, score, NodeCnt+QuiesCnt);	 
      }
   }

   if (c == '-')
   {
      printf ("\n");
      if (ofp != stdout) fprintf(ofp, "\n");
      return;
   }
   else if (c == '+')
   {
      SANMove (RootPV, 1);
      printf (" %s\n", SANmv);
      if (ofp != stdout) fprintf (ofp," %s\n", SANmv);
      return;
   }

   SANMove (RootPV, 1);
   printf (" %s", SANmv);
   if (ofp != stdout) fprintf (ofp," %s", SANmv);
   MakeMove (board.side, &RootPV);
   TreePtr[3] = TreePtr[2];
   GenMoves (2);
   len = strlen (SANmv);
   i = 2;
   pvar[1] = RootPV;

   /*  We fill the rest of the PV with moves from the hash table */
   if ((flags & USEHASH))
   {
      while (TTGetPV (board.side, i, rootscore, &pvar[i]))
      {
         if ((MATESCORE(score) && abs(score) == MATE+2-i) || Repeat ())
            break;
  
         if (len >= 32)
         {
            printf ("\n\t\t\t\t");
	    if (ofp != stdout) fprintf (ofp,"\n\t\t\t\t");
            len = 0;
         }
         SANMove (pvar[i], i);
         printf (" %s", SANmv);
	 if (ofp != stdout) fprintf (ofp," %s", SANmv);
         MakeMove (board.side, &pvar[i]);
         TreePtr[i+2] = TreePtr[i+1];
         GenMoves (++i);
         len += strlen (SANmv);
      }
   }

   printf ("\n");
   if (ofp != stdout) fprintf(ofp,"\n");
   for (--i; i; i--)
      UnmakeMove (board.side, &pvar[i]);
   fflush (stdout);
   if (ofp != stdout) fflush (ofp);
}
Esempio n. 19
0
void InputCmd ()
/*************************************************************************
 *
 *  This is the main user command interface driver.
 *
 *************************************************************************/
{
   const char *color[2] = { "White", "Black" };
   int suffix;
   int i;
   leaf *ptr; 
   int ncmds;
   char *x,*trim;

   CLEAR (flags, THINK);
   memset(userinput,0,sizeof(userinput));
   memset(cmd,0,sizeof(cmd));
#ifndef HAVE_LIBREADLINE /* Why is this necessary anyway? */
   memset(inputstr,0,sizeof(inputstr));
#endif

#ifdef HAVE_LIBREADLINE
	 if (isatty(STDIN_FILENO)) {
	    sprintf(s,"%s (%d) %c ", color[board.side], (GameCnt+1)/2 + 1, prompt);
	    inputstr = readline(s);
	    if (inputstr == NULL) return;
	    if (*inputstr) {
	       add_history(inputstr);
	    }
	    if (strlen(inputstr) > INPUT_SIZE-1) {
	       printf("Warning: Input line truncated to %d characters.\n", INPUT_SIZE -1 );
	       inputstr[INPUT_SIZE-1] = '\000';
	    }
	 } else {
	    inputstr = malloc(INPUT_SIZE);
	    if (inputstr == NULL) {
	       perror("InputCmd");
	       exit(EXIT_FAILURE);
	    }
	    fgets(inputstr, INPUT_SIZE, stdin);
	    if (inputstr[0]) {
	       inputstr[strlen(inputstr)-1] = 0;
	    }
	 }
#else /* !HAVE_LIBREADLINE */
	if (!(flags & XBOARD)) {
	  printf ("%s (%d) %c ", color[board.side], (GameCnt+1)/2 + 1, prompt);
	  fflush(stdout);
        }
	fgets (inputstr, INPUT_SIZE, stdin) ;
#endif /* HAVE_LIBREADLINE */

	cmd[0] = '\n';
	strcpy(userinput,inputstr);
	sscanf (inputstr, "%s %[^\n]", cmd, inputstr);
	if (cmd[0] == '\n')
	  goto done;
	cmd[0] = subcmd[0] = setting[0] = subsetting[0] = '\0';
        ncmds = sscanf (userinput,"%s %s %s %[^\n]",
			cmd,subcmd,setting,subsetting);

   /* Put options after command back in inputstr - messy */
   sprintf(inputstr,"%s %s %s",subcmd,setting,subsetting);

   trim = inputstr + strlen(inputstr) - 1;
   while ( trim>=inputstr && *trim==' ')
                *trim--='\0';

   if (strcmp (cmd, "quit") == 0 || strcmp (cmd, "exit") == 0)
      SET (flags, QUIT);
   else if (strcmp (cmd, "help") == 0)
      ShowHelp (inputstr);
   else if (strcmp (cmd, "show") == 0)
      ShowCmd (inputstr);
   else if (strncmp (cmd, "book", 4) == 0) {
      if (strncmp(inputstr, "add",3) == 0) {
        sscanf (inputstr, "add %s", file);
        if (access(file,F_OK) < 0) {
	  printf("The syntax to add a new book is:\n\n\tbook add file.pgn\n");
        } else {
          BookPGNReadFromFile (file);
	}
      } else if (strncmp (inputstr, "on", 2) == 0 || strncmp (inputstr, "prefer", 6) == 0) {
	bookmode = BOOKPREFER;
	printf("book now on.\n");
      } else if (strncmp (inputstr, "off", 3) == 0) {
	bookmode = BOOKOFF;
	printf("book now off.\n");
      } else if (strncmp (inputstr, "best", 4) == 0) {
	bookmode = BOOKBEST;
	printf("book now best.\n");
      } else if (strncmp (inputstr, "worst", 5) == 0) {
	bookmode = BOOKWORST;
	printf("book now worst.\n");
      } else if (strncmp (inputstr, "random", 6) == 0) {
	bookmode = BOOKRAND;
	printf("book now random.\n");
      }
   } else if (strcmp (cmd, "test") == 0)
      TestCmd (inputstr);
   else if (strcmp (cmd, "version") == 0)
      ShowVersion ();
   else if (strcmp (cmd, "pgnsave") == 0)
           {     
		if ( strlen(inputstr) > 0 && strlen(inputstr) < INPUT_SIZE )
      		  PGNSaveToFile (inputstr,"");
		else
		  printf("Invalid filename.\n");
	   }
   else if (strcmp (cmd, "pgnload") == 0)
      PGNReadFromFile (inputstr);
   else if (strcmp (cmd, "manual") == 0)
      SET (flags, MANUAL);
   else if (strcmp (cmd, "debug") == 0)
   {
      SET (flags, DEBUGG);
      Debugmvl = 0;
      if (strcmp (inputstr, "debug") == 0)
      {
         while (strcmp (inputstr, s))
         {
            sscanf (inputstr, "%s %[^\n]", s, inputstr);
            ptr = ValidateMove (s);
            Debugmv[Debugmvl++] = ptr->move;
            MakeMove (board.side, &ptr->move);
         } 
         i = Debugmvl;
         while (i)
         {
            UnmakeMove (board.side, &Debugmv[--i]);
         } 
      }
   }
   else if (strcmp (cmd, "force") == 0)
	SET (flags, MANUAL);
   else if (strcmp (cmd, "white") == 0)
	;
   else if (strcmp (cmd, "black") == 0)
	;
   else if (strcmp (cmd, "hard") == 0)
	;
   else if (strcmp (cmd, "easy") == 0)
	;
   else if (strcmp (cmd, "list") == 0) {
	if (inputstr[0] == '?')
	{
	  printf("name    - list known players alphabetically\n");
	  printf("score   - list by GNU best result first \n");
	  printf("reverse - list by GNU worst result first\n");
	} else {
          sscanf (inputstr, "%s %[^\n]", cmd, inputstr);
          if (inputstr == '\000') DBListPlayer("rscore");
	  else DBListPlayer(inputstr);
	}
   }
   else if (strcmp (cmd, "post") == 0)
	SET (flags, POST);
   else if (strcmp (cmd, "nopost") == 0)
	CLEAR (flags, POST);
   else if (strcmp (cmd, "name") == 0) {
      strcpy(name, inputstr);
      x = name;
      while (*x != '\000') {
        if (*x == ' ') {
	  *x = '\000';
	  break;
	}
        x++;
      }
      suffix = 0;
      for (;;) {
	sprintf(logfile,"log.%03d",suffix);
 	sprintf(gamefile,"game.%03d",suffix);
	if (access(logfile,F_OK) < 0) {
	  ofp = fopen(logfile,"w");
	  break;
	} else 
	  suffix++;
      }
   }
   else if (strcmp (cmd, "result") == 0) {
     if (ofp != stdout) {  
	fprintf(ofp, "result: %s\n",inputstr);
	fclose(ofp); 
	ofp = stdout;
        printf("Save to %s\n",gamefile);
        PGNSaveToFile (gamefile, inputstr);
	DBUpdatePlayer (name, inputstr);
     }
   }	
   else if (strcmp (cmd, "rating") == 0) {
      sscanf(inputstr,"%d %d",&myrating,&opprating); 
      fprintf(ofp,"my rating = %d, opponent rating = %d\n",myrating,opprating); 
      /* Change randomness of book based on opponent rating. */
      /* Basically we play narrower book the higher the opponent */
      if (opprating >= 1700) bookfirstlast = 2;
      else if (opprating >= 1700) bookfirstlast = 2;
      else bookfirstlast = 2;
   }
   else if (strcmp (cmd, "activate") == 0) {
	CLEAR (flags, TIMEOUT);
	CLEAR (flags, ENDED);
   }
   else if (strcmp (cmd, "new") == 0) {
     InitVars ();
     NewPosition ();
     CLEAR (flags, MANUAL);
     CLEAR (flags, THINK);
     myrating = opprating = 0;
   }
   else if (strcmp (cmd, "time") == 0) {
     sscanf (inputstr, "%s %[^\n]", s, inputstr);
     TimeLimit[1^board.side] = atoi(s) / 100.0f ;
   }
   else if (strcmp (cmd, "otim") == 0)
	;
   else if (strcmp (cmd, "random") == 0)
	;
   else if (strcmp (cmd, "hash") == 0)
   {
      sscanf (inputstr, "%s %[^\n]", cmd, inputstr);
      if (strcmp (cmd, "off") == 0)
         CLEAR (flags, USEHASH);
      else if (strcmp (cmd, "on") == 0)
         SET (flags, USEHASH);
      printf ("Hashing %s\n", flags & USEHASH ? "on" : "off");
   }
   else if (strcmp (cmd, "hashsize") == 0)
   {
      if (inputstr[0] == 0) {
	 printf("Current HashSize is %u slots\n", HashSize);
      } else {
	 i = atoi (inputstr);
	 TTHashMask = 0;
	 while ((i >>= 1) > 0)
	 {
	    TTHashMask <<= 1;
	    TTHashMask |= 1;
	 }
	 HashSize = TTHashMask + 1;
	 printf ("Adjusting HashSize to %u slots\n", HashSize);
	 InitHashTable (); 
      }
   }
   else if (strcmp (cmd, "null") == 0)