Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Nullmove question

Author: martin fierz

Date: 07:36:30 01/13/04

Go up one level in this thread


On January 13, 2004 at 10:28:54, Michel Langeveld wrote:

>The idea of Nullmove is that you let a player have the right to do two moves
>during a game. If he can't win with this right then his position is really bad,
>and we count it as lost.
>--------------------------------------------------------------------------------
>original
>6    318    343459     -8  b1c3 b8c6 i1h3 d7d6 h3f4 c8f5
>7   1782   2188112      3  b1c3 d7d5 d2d4 c8f5 i1h3 i8h6 c1f4
>
>nullmove with: if (!c && !nullmoved && depth - 1 - R > 0)
>6    215    227824     -8  b1c3 b8c6 i1h3 d7d6 h3f4 c8f5
>7    859   1008458      3  i1h3 d7d5 d2d4 c8f5 b1c3 i8h6 c1f4
>
>nullmove with :if (!c && !nullmoved)
>6     59     63778     -3  i1h3 d7d6 g1f3 i8h6 b1c3 b8c6
>7    342    403509      3  i1h3 d7d5 d2d4 c8f5 c1f4 i8h6 b1c3
>
>My question is do I have to protect that after a nullmove we go immediatly into
>quiesce or can I live without this protection?

i don't protect against it. as you can see you get a massive speedup without it.
what i (and many others of course, before me) do is to generate checks at the
first ply of qsearch. so if you nullmove, go to qsearch, you probably find out
whether you're being mated or not. if you don't have checks on the first ply of
QS, you will happily cut off in a position where your opponent can mate in one.

so doing checks in QS is a way of protecting yourself here.

then again lots of people don't do checks in QS - a well-known example for this
is crafty.

cheers
  martin


>--------------------------------------------------------------------------------
>
>/* search() does just that, in negamax fashion */
>int search(int alpha, int beta, int depth)
>{
>   int i, j, x;
>   int his_piece;
>   BOOL c, f;
>
>   int best_score;
>
>   /* we're as deep as we want to be; call quiesce() to get
>      a reasonable score and return it. */
>   if (depth <= 0)
>      return quiesce(alpha,beta);
>   ++nodes;
>
>   /* do some housekeeping every 1024 nodes */
>   if ((nodes & 1023) == 0)
>      checkup();
>
>   pv_length[ply] = ply;
>
>   /* if this isn't the root of the search tree (where we have
>      to pick a move and can't simply return 0) then check to
>      see if the position is a repeat. if so, we can assume that
>      this line is a draw and return 0. */
>   if (ply && reps())
>      return 0;
>
>   /* are we too deep? */
>   if (ply >= MAX_PLY - 1)
>      return eval();
>   if (hply >= HIST_STACK - 1)
>      return eval();
>
>   /* are we in check? */
>   c = in_check(side);
>
>   //we are not check and did not do a nullmove before
>
>   //Question : what if clausule can we use here?
>   if (!c && !nullmoved)
>   {
>      //set the end marker
>      first_move[ply + 1] = first_move[ply];
>      makenullmove();
>      x = -search(-beta, -beta + 1, depth - 1 - R);
>      takebacknullmove();
>
>      if (x >= beta)
>        return beta;
>
>      //restore that fact that we are not check
>      c = FALSE;
>   }
>
>   /* if we are in check don't seach deeper */
>   if (c) depth++;
>
>   gen();
>   if (follow_pv)  /* are we following the PV? */
>      sort_pv();
>   f = FALSE;
>
>   best_score = -10000;
>
>   /* loop through the moves */
>   for (i = first_move[ply]; i < first_move[ply + 1]; ++i) {
>      sort(i);
>      if (!makemove(gen_dat[i].m))
>         continue;
>      f = TRUE;
>
>      if (best_score == -10000)
>         x = -search(-beta, -alpha, depth - 1);
>      else
>      {
>         x = -search(-(alpha + 1), -alpha, depth - 1);
>         if (x > alpha && x < beta)
>         {
>            x = -search(-beta, -alpha, depth - 1);
>         }
>      }
>
>      takeback();
>
>      if (x > best_score) {
>
>         best_score = x;
>
>         if (x > alpha) {
>
>            /* this move caused a cutoff, so increase the history
>               value so it gets ordered high next time we can
>               search it */
>            if (x >= beta) {
>               addkiller(gen_dat[i].m);
>               his_piece = piece[gen_dat[i].m.b.from];
>               history[side][his_piece][gen_dat[i].m.b.to] += depth;
>               return beta;
>            }
>            alpha = x;
>
>            /* update the PV */
>            pv[ply][ply] = gen_dat[i].m;
>            for (j = ply + 1; j < pv_length[ply + 1]; ++j)
>               pv[ply][j] = pv[ply + 1][j];
>            pv_length[ply] = pv_length[ply + 1];
>         }
>      }
>   }
>
>   /* no legal moves? then we're in checkmate or stalemate */
>   if (!f) {
>      if (c)
>         return -10000 + ply;
>      else
>         return 0;
>   }
>
>   /* fifty move draw rule */
>   if (fifty >= 100)
>      return 0;
>
>   return best_score;
>}



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.