Simple question about SEE

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
Andres Valverde
Posts: 557
Joined: Sun Feb 18, 2007 11:07 pm
Location: Almeria. SPAIN

Simple question about SEE

Post by Andres Valverde »

From the chess programming wiki :

Code: Select all

int see(int square, int side)
{
   value = 0;
   piece = get_smallest_attacker(square, side);
   /* skip if the square isn't attacked anymore by this side */
   if ( piece )
   {
      make_capture(piece, square);
      /* Do not consider captures if they lose material, therefor max zero */
      value = max (0, piece_just_captured() -see(square, other(side)) );
      undo_capture(piece, square);
   }

   return value;
}

"This uses a trick, equivalent to negamax in tree search, where the loss for the current side is the gain for the opposite side. This can be seen in the expression piece_just_captured() - see(square); which is the value of the piece captured (piece_just_captured()) minus the gain that the opponent might make after the move by recapturing. If that term becomes negative, one would better choose standing pat rather than to capture, which can be done by a conditional assignment, or by a max function with zero as second argument."

Following this method, I only get SEE values >=0, so I can't discriminate between bad and equal captures (both get a 0). The question is, how can I get negative values for bad captures?.
Saludos, Andres
User avatar
hgm
Posts: 27793
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Simple question about SEE

Post by hgm »

The point is that you usually SEE a move, while this routine SEEs a square. The first move should be forced, because it might not be the lowest attacker that makes the capture, and must not allow the option of standing pat. Otherwise there would indeed never be a bad capture, as they become neutral by simply not making them! :lol:

So you will need an additional routine

Code: Select all

int SEE(int from, int to, int side) 
{ 
   value = 0; 
   piece = board[from]; 

      make_capture(piece, to); 
      value = piece_just_captured() - see(to, other(side)); 
      undo_capture(piece, to); 

   return value; 
} 
User avatar
Andres Valverde
Posts: 557
Joined: Sun Feb 18, 2007 11:07 pm
Location: Almeria. SPAIN

Re: Simple question about SEE

Post by Andres Valverde »

hgm wrote:The point is that you usually SEE a move, while this routine SEEs a square. The first move should be forced, because it might not be the lowest attacker that makes the capture, and must not allow the option of standing pat. Otherwise there would indeed never be a bad capture, as they become neutral by simply not making them! :lol:

So you will need an additional routine

Code: Select all

int SEE(int from, int to, int side) 
{ 
   value = 0; 
   piece = board[from]; 

      make_capture(piece, to); 
      value = piece_just_captured() - see(to, other(side)); 
      undo_capture(piece, to); 

   return value; 
} 
Thanks Harm, that was what i was figuring out, but it had failed because a bug in my "found the smaller attacker" routine so I got confused.

Now it is working.. let's see wether that improves EveAnn or not :-)

BTW, maybe it can be added to the wiki article.
Saludos, Andres
Gerd Isenberg
Posts: 2250
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: Simple question about SEE

Post by Gerd Isenberg »

Andres Valverde wrote:
hgm wrote:The point is that you usually SEE a move, while this routine SEEs a square. The first move should be forced, because it might not be the lowest attacker that makes the capture, and must not allow the option of standing pat. Otherwise there would indeed never be a bad capture, as they become neutral by simply not making them! :lol:

So you will need an additional routine

Code: Select all

int SEE(int from, int to, int side) 
{ 
   value = 0; 
   piece = board[from]; 

      make_capture(piece, to); 
      value = piece_just_captured() - see(to, other(side)); 
      undo_capture(piece, to); 

   return value; 
} 
Thanks Harm, that was what i was figuring out, but it had failed because a bug in my "found the smaller attacker" routine so I got confused.

Now it is working.. let's see wether that improves EveAnn or not :-)

BTW, maybe it can be added to the wiki article.
Thanks to HGM as well.

Will add it, although it would prefer some more programmers here would contribute to cpw. Did the videos scare most people that much ;-)

Cheers,
Gerd
paulo
Posts: 53
Joined: Wed Dec 15, 2010 7:31 pm

Re: Simple question about SEE

Post by paulo »

Hi,

Is SEE usually used only for capture moves or can it also be used to order quite moves?

Thanks.

Paulo
paulo
Posts: 53
Joined: Wed Dec 15, 2010 7:31 pm

Re: Simple question about SEE

Post by paulo »

Another small question:

Do you know where I can get a good set of test positions to exhaustively test move generation and move ordering?

Thanks again.

Paulo
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Simple question about SEE

Post by Ferdy »

paulo wrote:Hi,

Is SEE usually used only for capture moves or can it also be used to order quite moves?

Thanks.

Paulo
SEE - static exchange evaluation, this is intended for captures. To probably improve it consider king pins and pins on higher ranked pieces that are more valuable than the value of captured pieces.
example:
e2e4 e7e5 g1f3 d7d6 d2d4 c8g4.
Now with white to play your SEE at square e5 should not be > 0 because the knight at f3 is pinned on the queen by bishop at g4.
Sample SEE sequence: d4xe5 (+pawn) d6xe5 (0).
If you play f3xe5 (+pawn) - not accurate because now g4xd1 is possible or even better Qd8xd1 mate.

You can use SEE to order non-capture moves also as you have asked.
example:
e2e4 c7c5 g1f3 d7d6 f1b5+.
And now black has 4 replies, Nb8c6, Nb8d7, Bc8d7 and Qd8d7. If you play Nb8c6 - a non capture move, its SEE at square c6 is zero. For other moves such as Nb8d7, Bc8d7 - SEE at square d7 is also zero. But for move Qd8d7 the SEE on square d7 is < 0 because of:
b5xd7 (-queen) c8xd7 (-queen+bishop) or
b5xd7 (-queen) b8xd7 (-queen+bishop).

You can use SEE everywhere as long as you can afford it. Bottom line is test, test and test it. This is a never ending testing contest :) .
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Simple question about SEE

Post by bob »

paulo wrote:Hi,

Is SEE usually used only for capture moves or can it also be used to order quite moves?

Thanks.

Paulo
See works for any move. For example, to see if a pawn promotion is safe, or if a checking move is safe, even if it is not a capture...
paulo
Posts: 53
Joined: Wed Dec 15, 2010 7:31 pm

Re: Simple question about SEE

Post by paulo »

Thanks Ferdinand and Bob.

My question was more in the sense how is SEE used in current top engines but since we have available the source of Stockfish, Ivanhoe, Gull, etc., I guess I can take a look ;)

Paulo
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Simple question about SEE

Post by bob »

paulo wrote:Thanks Ferdinand and Bob.

My question was more in the sense how is SEE used in current top engines but since we have available the source of Stockfish, Ivanhoe, Gull, etc., I guess I can take a look ;)

Paulo
I use it to defer "losing captures" until late in the search, and exclude them from the q-search completely. I also use SEE to avoid extending unsafe checks since they are generally pointless. Often one avoids LMR on captures, but if SEE says a capture is bad, why not reduce it to dismiss it with less effort? Etc...