Ponder

Discussion of chess software programming and technical issues.

Moderator: Ras

outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Ponder

Post by outAtime »

Hi. Could someone post some pseudo code that would make an engine ponder its own move, instead of the opponents? Im not sure whether to do this in search(), but Im assuming it would be done there... I just have search() and root_search, which calls search. maybe :

Code: Select all

if pondering
     root_score = -search (-beta, -alpha, depth-2+extensions, TRUE); 
instead of depth-1 ?

I will try that, don't know if thats right.,
outAtime
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Ponder

Post by outAtime »

nope, thats wrong...any help?
outAtime
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Ponder

Post by outAtime »

maybe I should tell it to switch sides if pondering in think()?
outAtime
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Ponder

Post by outAtime »

Hi. Sorry I just can't find any examples for this. I'll just keep trying my own solutions I suppose till I can find one that works. Any help or a link to a site which might explain this would be great. Thanks all!
outAtime
JVMerlino
Posts: 1404
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

Re: Ponder

Post by JVMerlino »

Here's how I did it, but it could be horribly wrong, since I didn't actually look at anybody else's code on how to do it. Pondering is VERY specific to your program's structure, so typically even pseudo-code may not be very helpful.

Right after Myrddin makes a move, I get the second move from the PV and force it on the search board -- I keep two boards in memory, one that always reflects the game state, and one that reflects the state of the search. I then have Myrddin start thinking on the assumption that the move was actually made.

If the opponent makes that move, then all I do is update a flag which tells the engine that it's no longer pondering, but actually doing a search, which tells it to start checking for time considerations. Other than that, there's nothing to do except make sure that the game board also gets updated (which happens anyway when I get a move from the opponent).

That's the easy part. The hard part is if the opponent does not make the move you are pondering on. You then need a way to roll back the move that your engine is thinking about. This is a two-part process: unmaking the pondering move on the board AND cleanly stopping your search. Once you have done that, you can make the real opponent move, and then just go on as normal.

There is another relatively rare case, in which it is possible to make a move without having a move to ponder on (hash hit at the root, tablebase lookup, etc.). In this case, you just need to be able to handle that case cleanly.

I hope that helps,
jm
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Ponder

Post by outAtime »

Yeah, it is definitely very engine specific, so you are right...I cant imagine implementing this by keeping two seperate boards in memory. Id rather just switch sides and ponder there, keep everything stored in hash table and continue the search if the predicted move is made, or try saving some time,. It seems by what you are suggesting, you have two seperate search() functions, one for regular search() and one for ponder()?
outAtime
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Ponder

Post by outAtime »

Do most programs use two boards for this?
outAtime
mathmoi
Posts: 290
Joined: Mon Mar 13, 2006 5:23 pm
Location: Québec
Full name: Mathieu Pagé

Re: Ponder

Post by mathmoi »

No necessarily,

My engine, MatMoi, only use one board. But it's always copied when the search begins. I do something quite similar to John and I guess everyone else. The algorithm would look like this :

Code: Select all

When the search ends
  Make the move on the board
  Copy the board
  make the second move of the PV on the copy
  search the copy

Code: Select all

When the opponents play:
  Make the opponents move on the board
  if the engine pondered the right move
    Mark the search as a real search instead of a ponder search
    eventually make a move
  else
    stop the search
    search the board
    eventually make a move
   end if
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Ponder

Post by outAtime »

Thankyou! That really helps me to get started :) So I guess I need to figure out how to make the second move of the pv. My regular make looks like this:

Code: Select all

  make (&moves[0], i); 
so maybe if I change the [0] to a [1] that will be the second move of the pv? maybe I should look at it from the point of null move:

Code: Select all

 if (do_null && null_red && piece_count >= 5 && depth >= null_red+1) {
      /* update the rep_history just so things don't get funky: */
      rep_history[game_ply++] = cur_pos;
      fifty++;

      xor (&cur_pos, color_h_values[0]);
      xor (&cur_pos, color_h_values[1]);
      xor (&cur_pos, ep_h_values[ep_square]);
      xor (&cur_pos, ep_h_values[0]);

      white_to_move ^= 1;
      ply++;
      ep_square = 0;
      null_score = -search (-beta, -beta+1, depth-null_red-1, FALSE);
      ep_square = ep_temp;
      ply--;
      white_to_move ^= 1;

      game_ply--;
      fifty--;

      xor (&cur_pos, color_h_values[0]);
      xor (&cur_pos, color_h_values[1]);
      xor (&cur_pos, ep_h_values[ep_square]);
      xor (&cur_pos, ep_h_values[0]);
      assert (cur_pos.x1 == compute_hash ().x1 &&
	      cur_pos.x2 == compute_hash ().x2);

      /* check to see if we ran out of time: */
      if (time_exit)
	return 0;

      /* check to see if we can get a quick cutoff from our null move: */
      if (null_score >= beta)
	return beta;
      
      if (null_score < -INF+10*maxdepth)
	extensions++;
    }
to me it looks like its saving the position and trying a null move, so maybe if I did a ponder_search() in a similar way I wonder if I would be heading in the right direction?
outAtime