⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.c

📁 GNU国际象棋C++源代码Windows版的
💻 C
📖 第 1 页 / 共 4 页
字号:
            Tree[i].flags = 0;
            Tree[i].reply = 0;
            Tree[i].score = (beta == -20000) ? score : alpha; 
            TrPnt[ply+1] = i+1;
                                if (abs (score) > 9000) Tree[i].flags |= exact; 
            if (beta == -20000) return (score); 
                                    else return (alpha); 
               }

         }
        }
      /* ok try the transition file if its there */
      else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
          && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
        {
            if (beta == -20000 || alpha > beta)
         {
             bstline[ply] = PV;
             bstline[ply + 1] = 0;
             /*
              * make sure the move is in the
              * MoveList
              */
             if (ply == 1)
               {
              struct leaf tmp;
              register int spnt;
              for (spnt = TrPnt[ply]; spnt < TrPnt[ply + 1]; spnt++)
                {
               if (((Tree[spnt].f << 8) | Tree[spnt].t) == PV)
                 {
                           if (ply == 1 && Tree[spnt].score == DONTUSE) {bstline[1] = 0; break;}
                     Tree[spnt].score = (beta == -20000) ? score : alpha;
                     if (abs (score) > 9000) Tree[spnt].flags |= exact;
                     if (spnt != TrPnt[ply])
                  {
                      tmp = Tree[TrPnt[ply]];
                      Tree[TrPnt[ply]] = Tree[spnt];
                      Tree[spnt] = tmp;
                  }
                     PutInTTable (side, score, depth, ply, alpha, beta, PV);
                     if (beta == -20000) return (score);
                     else return (alpha);
                 }
                }
                } else {
                                register int i = TrPnt[ply];
                                Tree[i].t = PV & 0x3f;
                                Tree[i].f = PV>>8;
                                Tree[i].score = (beta == -20000) ? score : alpha;
            TrPnt[ply+1] = i+1;
                                if (abs (score) > 9000) Tree[i].flags |= exact;
                                if (beta == -20000) return (score);
                                    else return (alpha);
                              }
 

         }
        }
     }
#endif /* ttblsz */

  if ((depth > 0) || InChk || (background && ply < Sdepth + 2)) 
    {
      if (ply >1)
   MoveList (side, ply);
   quiescent = false;
    }
  else
    {
      CaptureList (side, ply);
      quiescent = true;
    }

  /* no moves return what we have */

  /*
   * normally a search will continue til past goal and no more capture
   * moves exist
   */
  /* unless it hits DepthBeyond */
  if (TrPnt[ply] == TrPnt[ply + 1]) 
    return (!InChk ? score : -10000+ply);


  /* if not at goal set best = -inf else current score */
  best = (depth > 0) ? -12000 : score;
#ifdef NULLMOVE

  PVarisave = PVari;
  if (!didnull &&    /* no previous null-move */
      !PVari &&         /* no null-move during the PV */
      (ply > 1) &&      /* not at ply 1 */
      (depth > 1) &&
      !InChk &&         /* no check */
      (emtl[side] > valueQ))
    /* enough material such that zugzwang is unlike but who knows which value
       is suitable? */
    {

      /* ok, we make a null move, i.e.  this means we have nothing to do
    but we have to keep the some arrays up to date otherwise gnuchess
    gets confused.  Maybe somebody knows exactly which informations are
    important and which not.

    Another idea is that we try the null-move first and generate the
    moves later.  This may save time but we have to take care that
    PV and other variables contain the right value so that the move
    ordering works right.
    */
      register struct GameRec *g;
      SHORT rdepth;

      nxtline[ply + 1] = 0;
      CptrFlag[ply] = 0;
      PawnThreat[ply] = 0;
      Tscore[ply] = score;
      PVsave = PV;
      PV = 0;
      null = 1;
      g = &GameList[++GameCnt];
      g->hashkey = hashkey;
      g->hashbd = hashbd;
      epsquare = -1;
      TOsquare = -1;
      g->Game50 = Game50;
      g->gmove = 0;
      g->flags = 0;
      g->piece = 0;
      g->color = neutral;
      rdepth = (depth-3 < 0 ? 0 : depth-3);
      nmscore = -search (xside, ply + 1, rdepth, ext, -beta, -beta+1, nxtline, &rcnt,false,1);
      null = 0;
      PV = PVsave;
      GameCnt--;
      if (nmscore > beta)
        {
     DepthBeyond -= extdb;
     return (nmscore);
   }
      if (depth <= 3 && score > beta && nmscore < -9000)
          depth++;
    }
#elif defined DEEPNULL

  /*
   * The deepnull algoritm is taken from the article by
   * Christian Donninger in ICCA journal Vol 16, No. 3.  TomV
   */
  PVarisave = PVari;
  if ((flag.deepnull ? !didnull : !null) &&  /* no previous null-move */
      !flag.nonull &&
      !no_null &&
      !PVari &&         /* no null-move during the PV */
      (ply > (flag.deepnull ? 1: 2)) &&      /* not at ply 1 */
      (score > alpha - 150 || !flag.deepnull) &&
      (ply <= Sdepth || flag.deepnull) &&
      (depth > (flag.deepnull ? (flag.verydeep ? 1: 2): 3)) &&
      !InChk &&         /* no check */
      /* enough material such that zugzwang is unlikely: */
      ! (emtl[xside] == 0 || emtl[side] <= valueB))
    {

      /* ok, we make a null move, i.e.  this means we have nothing to do
    but we have to keep the some arrays up to date otherwise gnuchess
    gets confused.

    Another idea is that we try the null-move first and generate the
    moves later.  This may save time but we have to take care that
    PV and other variables contain the right value so that the move
    ordering works right.
    */
      CptrFlag[ply] = 0;
      PawnThreat[ply] = 0;
      Tscore[ply] = score;
      PVsave = PV;
      PV = 0;
      epsquare = -1;
      TOsquare = -1;
      if (!null)
        null= ply;
      if (flag.deepnull) {
        nmscore = -search (xside, ply + 1, (depth >= 3 ? depth - 3: 0), ext, -beta, -alpha, nxtline, &rcnt,false,1);
        if (ply == null)
          null = 0;
        PV = PVsave;
   if (nmscore > beta) {
     DepthBeyond-= extdb;
     return nmscore;
        }
   if (nmscore > alpha)
     alpha= nmscore;
        if (depth <= 3 && ply < DepthBeyond-depth-4
            && score >= beta && nmscore < score - 350)
              depth++;
      } else {
        best = -search (xside, ply + 1, depth - 2, ext, -beta - 1, -beta, nxtline, &rcnt, false, 1);
        null = 0;
        PV = PVsave;
        if (best < alpha) best = -12000;
        else if (best > beta) {
      DepthBeyond-= extdb;
           return (best);
        }  else best = -12000;
      }
    }
#endif
  /* if best so far is better than alpha set alpha to best */
  if (best > alpha) alpha = best;
  /********************** main loop ************************************************************************/
  /* look at each move until no more or beta cutoff */
  for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta && best != 9999-ply; pnt++)
    {
      if ((pnt&interval)==0)
       {
        flag.searching=true;
        CheckMessage();
        flag.searching=false;
       }
      NodeCnt++;
      /* find the most interesting looking of the remaining moves */
      if (ply > 1)
   pick (pnt, TrPnt[ply + 1] - 1);
#if defined NULLMOVE || defined DEEPNULL
      PVari = PVarisave && (pnt == pbst); /* Is this the PV? */
#endif

      node = &Tree[pnt];

      /* is this a forbidden move */
      if (ply == 1 && node->score == DONTUSE) { continue;}
#ifdef DEBUG
      if (debuglevel & (512 | 1024))
   {
     if (!tracen)
       traceflag = ((ply > traceply) ? false : true);
     else if (ply <= tracen && (ply == 1 || traceflag))
       {
         if (trace[ply] == (Tree[pnt].t | (Tree[pnt].f << 8)))
      traceflag = true;
         else
      traceflag = false;
       }
     tracelog[ply] = (Tree[pnt].t | (Tree[pnt].f << 8));
     tracelog[ply + 1] = 0;
   }
#endif
      nxtline[ply + 1] = 0;

#ifndef BAREBONES
      /* if at top level */
      if (ply == 1)
   {        /* at the top update search status */
     if (flag.post)
#ifdef QUIETBACKGROUND
       if (!background)
#endif /* QUIETBACKGROUND */
         ShowCurrentMove (pnt, node->f, node->t);
   }
#endif
#ifdef DEBUG
     xxxtmp = node->score;
     tracetmp = traceflag;
#endif
   if (!(node->flags & exact)) {
     /* make the move and go deeper */
     MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
     CptrFlag[ply] = (node->flags & capture) ? TOsquare+1 : 0;
     PawnThreat[ply] = (node->flags & pwnthrt);
     Tscore[ply] = node->score;
     PV = node->reply;
     if (flag.pvs && depth > 0) {
            if (pbst == pnt) {
              node->score= -search (xside, ply + 1,
                                 depth > 0 ? depth - 1 : 0, ext,
                                 -beta, -alpha,
                                 nxtline, &rcnt, quiescent, 0);
            } else {
              node->score= -search(xside, ply + 1,
                              depth > 0 ? depth - 1 : 0, ext,
                              -alpha-1, -alpha,
                              nxtline, &rcnt, quiescent, 0);
              if (node->score >= best && alpha <= node->score
              && node->score <= beta)
                  node->score = -search (xside, ply + 1,
                                 depth > 0 ? depth - 1 : 0, ext,
                                 -beta, -node->score,
                                 nxtline, &rcnt, quiescent, 0);
            }
          } else

     node->score = -search (xside, ply + 1,
             (depth > 0) ? depth - 1 : 0, ext,
             -beta, -alpha,
             nxtline, &rcnt, quiescent, false);
     node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
     if (abs (node->score) > 9000) node->flags |= exact;
     else if (rcnt == 1) node->score /= 2;
          if (node->score == 9999-ply && !ChkFlag[ply]) 
       {
         node->flags |= draw;
              node->score = (-contempt);
       }
     if ((rcnt >= 2 || GameCnt - Game50 > 99 ))
       {
         node->flags |= (draw | exact);
         DRAW = CP[21]; /* Draw */
         node->score = -contempt;
       }
     node->reply = nxtline[ply + 1];
     /* reset to try next move */
     UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
        }
      /* if best move so far */
      if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
   {
     /*
      * all things being equal pick the denser part of the
      * tree
      */
     bestwidth = node->width;

     /*
      * if not at goal depth and better than alpha and not
      * an exact score increment by depth
      */
     if (depth > 0 && node->score > alpha && !(node->flags & exact)) node->score += depth; 
     best = node->score;
     pbst = pnt;
     if (best > alpha) { alpha = best; }
     /* update best line */
     for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j]; 
     bstline[j] = 0;
     bstline[ply] = (node->f << 8) | node->t;
     /* if at the top */
     if (ply == 1)
       {
         /*
          * if its better than the root score make it
          * the root
          */
         if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)) || pnt > 0)
      {
        tmp = Tree[pnt];
        for (j = pnt - 1; j >= 0; j--)
          Tree[j + 1] = Tree[j];
        Tree[0] = tmp;
        pbst = 0;
      }
#ifndef BAREBONES
#ifdef QUIETBACKGROUND
         if (!background)
#endif /* QUIETBACKGROUND */
      if (Sdepth > 2)
        if (best > beta)
          {
            ShowResults (best, bstline, '+');
#ifdef DEBUG41
            debug41 (best, bstline, '+');
#endif
          }
        else if (best < alpha)
          {
            ShowResults (best, bstline, '-');
#ifdef DEBUG41
            debug41 (best, bstline, '-');
#endif
          }
        else
          ShowResults (best, bstline, '&');
#ifdef DEBUG41
         debug41 (best, bstline, '&');
#endif
#endif
         ElapsedTime (2);
         TCcount++;
         if (!background && Sdepth > 2)
      {
        if (best < alpha)
          {
            TCcount = 0;
            ExtraTime += Sdepth * TCleft;
            if (ExtraTime > 12 * TCleft)
           ExtraTime = 12 * TCleft;
            if (best > 300)
           ExtraTime = 0;
            return (best);
          }
      }
       }
   }
      if (flag.timeout)
   {
          DepthBeyond-= extdb;
#if defined NULLMOVE || defined DEEPNULL
     PVari = PVarisave;
#endif
         if (best == -12000)
           return (Tscore[ply - 1]);
         else
           return (best);

   }
    }

  /**************************************************************/
 /*************** out of main loop *****************************/

  if (best == -10000+ply) bstline[ply] = 0;
  node = &Tree[pbst];
  mv = (node->f << 8) | node->t;
#if defined NULLMOVE || defined DEEPNULL
  PVari = PVarisave;
#endif

  /*
   * we have a move so put it in local table - if it's already there
   * done else if not there or needs to be updated also put it in
   * hashfile
   */
#if ttblsz
  if (flag.hash && !quiescent && *rpt == 0 && best == alpha)
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -