Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Question regarding: Aspiraton Window Search (a correction)

Author: Dann Corbit

Date: 16:50:11 05/31/02

Go up one level in this thread


On May 31, 2002 at 18:50:18, Omid David wrote:

>I forgot to change "negascout" to "AlphaBeta" in 7th line for better
>illustration. Here is the correction:
>
>int AspWin(int estimate, int delta, int depth)
>{
>int alpha = estimate - delta;
>int beta = estimate + delta;
>int best;
>
>best = AlphaBeta(alpha, beta, depth);
>
>/* re-search */
>if(best <= alpha)
>best = AlphaBeta(-10000, beta, depth);
>else if(best >= beta)
>best = AlphaBeta(alpha, 10000, depth);
>
>/* is there any better way to handle this very rare case? */
>if(best >= beta || best <= alpha)
>best = AlphaBeta(-10000, 10000, depth);
>
>return best;
>}

ExChess does this:

/*----------------------- Search function ---------------------*/
// Driver for the search process.  1st initialize important data
// structures, the do iterative deeping until time runs out.
move search(position p, int time_limit, int T)
{
  char outstring[60], mstring[10];
  int g, done, pvi;
  long elapsed;
  position pv_pos;
  turn = T;
  root_wtm = p.wtm;
  nomove.t = 0;

#if DEBUG
 outfile.open("search.log");
#endif

  // logging the current position in FEN format
  if(logging) {
   logfile <<
"---------------------------------------------------------------\n";
   logfile << "Starting search on position:\n";
   int lcount; square lsqr;
   for(int rank = 7; rank >= 0; rank--) {
     lcount = 0;
     for(int file = 0; file < 8; file++) {
       lsqr = p.sq[SQR(file,rank)];
       if(lsqr.type) {
	if(lcount) { logfile << lcount; lcount = 0; }
        if(lsqr.side)
         logfile << name[lsqr.type];
        else logfile << bname[lsqr.type];
       } else lcount ++;
     }
     if(lcount) logfile << lcount;
     if(rank) logfile << "/";
   }
   if(p.wtm) logfile << " w ";
   else logfile << " b ";
   if(p.castle&1) logfile << "K";
   if(p.castle&2) logfile << "Q";
   if(p.castle&4) logfile << "k";
   if(p.castle&8) logfile << "q";
   if(!p.castle)  logfile << "-";
   if(p.ep)
    logfile << " " << char(FILE(p.ep) + 97) << (RANK(p.ep) + 1);
   else logfile << " -";
   logfile << "\n";
  }

  // Set start of search depth
  if(pc[0][0].t == p.last.t && pc[0][0].t) {
   start_depth = MAX(last_depth-1, 1);
  } else if(pc[0][1].t == p.last.t && pc[0][1].t && !last_ponder) {
   start_depth = MAX(last_depth-2, 1);
  } else {
   start_depth = 1;
  }

  // setting counts to zero
  node_count = 0; eval_count = 0; time_count = 0;
  phash_count = 0; hash_count = 0; hmove_count = 0; q_count = 0;
  null_cutoff = 0; extensions = 0; internal_iter = 0;
  egtb_probes = 0; egtb_hits = 0; fail_high = 0; first_fail_high = 0;

  time_check_interval = 500;

  // setup some search parameters - for old hash entries
  if(h_id > 100 || h_id < 0) h_id = 1;
  h_id++;

  // is this a pondering session, if so - make the move from the pv
  if(ponder) {
   if(book && !pc[0][1].t) ponder_move = opening_book(p.hcode, p);
   else ponder_move = pc[0][1];
   if(ics) { ics = 0; print_move(p, ponder_move, mstring); ics = 1; }
   else print_move(p, ponder_move, mstring);
   if(ponder_move.t) {
     if(!exec_move(&p, ponder_move, 0)) { ponder_time = 0; return nomove; }
   } else { ponder_time = 0; return nomove; }
   if(!ALLEG && post) {
    cout << "Hint: " << mstring << "\n";
    cout.flush();
   }
   if(logging) logfile << "***** Ponder Move: " << mstring << " *****\n";
   // add ponder move to position list
   p_list[T-1] = p.hcode;
   // set ponder time doubling
   ponder_time_double = 0;
  }

  // initializing eval
  init_score(&p, T);

  // checking tablebases at root
#if TABLEBASES
  if(p.pieces[0] + p.pieces[1]
      + p.plist[0][PAWN][0] + p.plist[1][PAWN][0] <= EGTB) {
   root_tb_score = probe_tb(&p, 0);
  } else root_tb_score = -1;
#else
  root_tb_score = -1;
#endif  /* TABLEBASES */

  // checking book
  if(book && !ponder) {
    book_search = 1;
    bookm = opening_book(p.hcode, p);
    book_search = 0;
    if(bookm.t) {
     pc[0][0] = bookm; pc[0][1].t = 0;
     if(logging) {
      if(ics) { ics = 0; print_move(p, bookm, mstring); ics = 1; }
      else print_move(p, bookm, mstring);
      logfile << "Book Move Found: " << mstring << "\n";
     }
     learn_positions[T-1].hcode.key = 0;
     learn_positions[T-1].hcode.address = 0;
     return pc[0][0];
    } else {
     no_book++;
     if(no_book >= 3) book = 0;
    }
  }

  // if last search was a ponder and if user made expected move and
  // if ponder time is greater than limit, return best move
  if(last_ponder && ponder_time >= (time_limit<<ponder_time_double) &&
     p.last.t == ponder_move.t && pc[0][0].t) {
   if(logging) {
    if(ics) cout << "tellics whisper Guessed last move! Score: "
		 << g_last << " Ply: " << last_depth << "\n";
    if(ics) { ics = 0; print_move(p, pc[0][0], mstring); ics = 1; }
    else print_move(p, pc[0][0], mstring);
    logfile << "Guessed Last Move! Returning: " << mstring << "\n";
   }
   cout.flush();
   if(T>2 && T<MAX_GAME_PLY-1) predicted[T-3] = 1;
   return pc[0][0];
  }
  if(last_ponder && p.last.t == ponder_move.t && pc[0][0].t && !book_search) {
   start_depth = MAX(last_depth-1,1);
   h_id--; // reset hash id to mark entries as current
   if(logging) {
    logfile << "Guessed last move, but searching deeper...\n";
    if(ics) cout << "tellics whisper Guessed last move, searching deeper...\n";
   }
   cout.flush();
   // set target time
   limit = (time_limit<<ponder_time_double) - ponder_time;
  } else {
   pc[0][0].t = NOMOVE;   // clear first move in the pv
   limit = time_limit;    // set target time
  }

  // set the learn position information to zero unless
  // we have something to put in
  if(!tsuite && !analysis_mode && !book_search
      && T < MAX_GAME_PLY-1 && T) {
   learn_positions[T-1].hcode.key = 0;
   learn_positions[T-1].hcode.address = 0;
  }

  // we didn't predict the last move - for learning info
  if(start_depth == 1 && T > 2 && T < MAX_GAME_PLY-1) predicted[T-3] = 0;
  else if(T > 2 && T < MAX_GAME_PLY-1) predicted[T-3] = 1;

  last_ponder = 0;
  ponder_time = 0;
  max_limit = int(MIN(4*time_limit, timeleft/6.0));
  if(!tsuite && !analysis_mode) {
   limit = MIN(max_limit, limit);
   if(timeleft < 500) {
    start_depth = 1;
    time_check_interval = 50;
   }
  }
  start_time = GetTime();
  last_depth = 1;

  // adjusting hash code for game stage
  or(p.hcode, stage_code[stage]);

  // initialize history table
  for(int i = 0; i < 64; i++)
   for(int j = 0; j < 64; j++) history[i][j] = 0;

  if(logging) {
   logfile << "Target search time: " << time_limit << "\n";
   logfile << "Starting depth: " << start_depth << "\n";
   logfile << "Game stage: " << stage << "\n";
  }

  // Main search loop for iterative deeping
  for(max_ply = start_depth; max_ply < MAXD-1; max_ply++)
  {
    sp[0] = p;
    node_count++;

    max_depth = max_ply;

    if(max_ply != start_depth)
     { root_alpha = g_last-25; root_beta = g_last+25; }
    else
     { root_alpha = -MATE; root_beta = +MATE; }

    done = 2;

    while(1) {
     g = pvs(root_alpha, root_beta, (max_ply-1)*UNIT_DEPTH+INIT_EXT, 0);
     if(g == -TIME_FLAG) break;
     if(g <= root_alpha) {
      if(done == 2) {
       root_beta = root_alpha+1; root_alpha = -MATE;
      } else if(done == 1) {
       root_beta = +MATE; root_alpha = -MATE;
      } else break;
      done--;
     } else if(g >= root_beta) {
      if(done == 2) {
       root_alpha = root_beta-1; root_beta = +MATE;
      } else if(done == 1) {
       root_beta = +MATE; root_alpha = -MATE;
      } else break;
      done--;
     } else break;
    }

    if(!pc[0][0].t && start_depth != 1) {
	 start_depth = 1;
	 max_ply = 0;
	 continue;
    }

    // writing pv into hash table to be searched first

    pv_pos = p; pvi = 0;

    while(pc[0][pvi].t) {
     put_move(pv_pos.hcode, pc[0][pvi].t);
     exec_move(&pv_pos, pc[0][pvi], 0);
     if(pvi > 1 && !tsuite && !analysis_mode
                && !book_search && T < 255) {
       learn_positions[T-1] = pv_pos;
       learn_rootpos[T-1] = p;
     }
     pvi++;
    }

    if(post && !ics && g != -TIME_FLAG) {
      search_display(g, start_time, node_count, max_ply);
      best_depth = max_ply;
    }

    // if time is up, or we found a mate... break
    if(inter() || g == -TIME_FLAG) break;

    g_last = g;
    last_depth = max_ply;

    if((g == 0 && max_ply > MAXD-3) ||
        ((g > (MATE>>1) || g < -(MATE>>1)) && max_ply > 2)) break;

  }

  elapsed = GetTime() - start_time;  if(!elapsed) elapsed = 1;

  if(ponder) {
   last_ponder = 1; ponder_time = elapsed;
  }

  // adjusting hash code for game stage
  or(p.hcode, stage_code[stage]);

  if(!xboard && !ALLEG && post) {
   cout << "\nnode_count = " << node_count
        << " quiescent nodes = " << q_count
        << " eval_count = " << eval_count << "\n";
   cout << "hash hits = " << hash_count
        << " hash moves = " << hmove_count
        << " pawn hash hits = " << phash_count << "\n";
   cout << "node_rate = " << int(100.0*(float(node_count)/float(elapsed)))
        << " null cuts = " << null_cutoff
        << " exten = " << extensions
        << " int_iter = " << internal_iter << "\n";
   cout << "egtb_probes = " << egtb_probes
        << " egtb_hits = " << egtb_hits
        << " fail_high(%) = " <<
int(100.0*(float(first_fail_high)/float(fail_high))) << "\n";
  }

  if(logging) {
   logfile << "node_count = " << node_count
        << " quiescent nodes = " << q_count
        << " eval_count = " << eval_count << "\n";
   logfile << "hash hits = " << hash_count
        << " hash moves = " << hmove_count
        << " pawn hash hits = " << phash_count << "\n";
   logfile << "node_rate = " << int(100.0*(float(node_count)/float(elapsed)))
        << " null cuts = " << null_cutoff
        << " exten = " << extensions
        << " int_iter = " << internal_iter << "\n";
   logfile << "egtb_probes = " << egtb_probes
        << " egtb_hits = " << egtb_hits
        << " fail_high(%) = " <<
int(100.0*(float(first_fail_high)/float(fail_high))) << "\n";
  }

  // Kibitz the search results to ics server
  if(ics && !ALLEG && !ponder && logging) {
   if(xboard) sprintf(outstring, "tellics whisper ");
   else sprintf(outstring, "\n Search summary: ");
   cout << outstring;
   if(wbest > (MATE>>1)) {
     sprintf(outstring, "MATE+(in %i moves) ", (MATE-wbest)>>1);
   } else if(wbest < -(MATE>>1)) {
     sprintf(outstring, "MATE-(in %i moves) ", (MATE+wbest)>>1);
   } else if(wbest >= 0) {
     sprintf(outstring, "+%.2f, ", float(wbest)/value[PAWN]);
   } else {
     sprintf(outstring, "%.2f, ", float(wbest)/value[PAWN]);
   }
   cout << outstring;
   if (elapsed >= 5)
    sprintf(outstring, "%i ply, nps: %.0f ",
             wply, float(node_count*100)/elapsed);
   else sprintf(outstring, "%i ply ", wply);
   cout << outstring;
   cout << "\n";
  }

#if DEBUG
 outfile.close();
#endif

  // learning if applicable
  if(!ponder && learn_bk && BOOK_LEARNING) {
    if(!book && learn_count > 0 && wbest > +LEARN_SCORE)
      { book_learn(1); learned = learn_count; learn_count = -1; }
    else if(!book && learn_count > 0 && wbest < -LEARN_SCORE)
      { book_learn(0); learn_count = -1; }
    else if(learned && wbest < -LEARN_SCORE)
      { learn_count = learned; book_learn(-1);
        learned = 0; learn_count = -1; }
   }

  if(wbest < -(MATE>>1) && T < MAX_GAME_PLY-1
      && !tsuite && !analysis_mode && !book_search && td_learning) {
   learn_scores = 1;
   score_learning(T, p.wtm);
   learn_scores = 0;
   td_learning = 0;
  }

  if(logging) {
   if(ics) { ics = 0; print_move(p, pc[0][0], mstring); ics = 1; }
   else print_move(p, pc[0][0], mstring);
   if(!ponder)
    logfile << "Return move from search: " << mstring << "\n";
   if(ponder) {
     logfile << "***** Pondering ended ***** Time: " << ponder_time
             << ", Time required doublings: " << ponder_time_double << "\n";
   }
   logfile <<
"---------------------------------------------------------------\n";
  }

  return pc[0][0];

}




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.