Search and Mobility

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

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

Search and Mobility

Post by outAtime »

Hi all. I have spent alot of time trying to implement some sort of mobility scores in eval. Still not exactly as i would like e.g.

Code: Select all

int rook_mobility_black(int sq, int offsets[])
{
  int q, *c = offsets, t = 0;
 
  for ( ; *c; c++)
       for (q = sq + *c; board[q] == npiece; q += *c)
           t++; 
		  		  
	   for (q = sq + *c; board[q] == wknight; q += *c)
           t++; 
		   
	   for (q = sq + *c; board[q] == wbishop; q += *c)
           t++; 
		  
       for (q = sq + *c; board[q] == wqueen; q += *c)
           t++; 
		  
       for (q = sq + *c; board[q] == wpawn; q += *c)
           t++;
		   
	   for (q = sq + *c; board[q] == wking; q += *c)
           t++;    
	       
  return t;
}

int black_queen_mobility(int sq)  { return bishop_mobility_black(sq, b_ofs) + rook_mobility_black(sq,r_ofs) ; } 
int black_rook_mobility(int sq)  { return rook_mobility_black(sq, r_ofs); }
int black_bishop_mobility(int sq){ return bishop_mobility_black(sq, b_ofs); }
int white_queen_mobility(int sq)  { return bishop_mobility_white(sq, b_ofs) + rook_mobility_white(sq,r_ofs) ; }
int white_rook_mobility(int sq)  { return rook_mobility_white(sq, r_ofs); }
int white_bishop_mobility(int sq){ return bishop_mobility_white(sq, b_ofs); }
also the mobility code basically takes 2 ply away, especially during the early middle game when there a plenty of pieces.. so any improvement is offset by the lack of depth in _search_ and Im not sure how to proceed. It would be nice to speed up search a bit at this point, but Ive already added LMR and some extended null move. No success yet with increasing LMR above 2, as has been tried with other programs when moves searched are above some number. Also no success with LMR in the root_search. Thanks.
outAtime
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Search and Mobility

Post by bob »

outAtime wrote:Hi all. I have spent alot of time trying to implement some sort of mobility scores in eval. Still not exactly as i would like e.g.

Code: Select all

int rook_mobility_black(int sq, int offsets[])
{
  int q, *c = offsets, t = 0;
 
  for ( ; *c; c++)
       for (q = sq + *c; board[q] == npiece; q += *c)
           t++; 
		  		  
	   for (q = sq + *c; board[q] == wknight; q += *c)
           t++; 
		   
	   for (q = sq + *c; board[q] == wbishop; q += *c)
           t++; 
		  
       for (q = sq + *c; board[q] == wqueen; q += *c)
           t++; 
		  
       for (q = sq + *c; board[q] == wpawn; q += *c)
           t++;
		   
	   for (q = sq + *c; board[q] == wking; q += *c)
           t++;    
	       
  return t;
}

int black_queen_mobility(int sq)  { return bishop_mobility_black(sq, b_ofs) + rook_mobility_black(sq,r_ofs) ; } 
int black_rook_mobility(int sq)  { return rook_mobility_black(sq, r_ofs); }
int black_bishop_mobility(int sq){ return bishop_mobility_black(sq, b_ofs); }
int white_queen_mobility(int sq)  { return bishop_mobility_white(sq, b_ofs) + rook_mobility_white(sq,r_ofs) ; }
int white_rook_mobility(int sq)  { return rook_mobility_white(sq, r_ofs); }
int white_bishop_mobility(int sq){ return bishop_mobility_white(sq, b_ofs); }
also the mobility code basically takes 2 ply away, especially during the early middle game when there a plenty of pieces.. so any improvement is offset by the lack of depth in _search_ and Im not sure how to proceed. It would be nice to speed up search a bit at this point, but Ive already added LMR and some extended null move. No success yet with increasing LMR above 2, as has been tried with other programs when moves searched are above some number. Also no success with LMR in the root_search. Thanks.
Several ideas.

(1) counting each square equally is not a very good measure of mobility. I would much rather have a bishop attacking d4-e5-f6 than to have one attacking a5-b6-c7. You can weight the squares to take care of this.

(2) the loops are hellishly expensive. I use bitboards, and I pre-compute the mobility scores, and rather than generating moves and counting squares in the search, I just use a magic index into a mobility table that gives the sum of the weighted values for all squares attacked based on the current board occupancy.

(3) you can do some caching. Once you calculate rook mobility, you can save the score, and the contents of the rank/file, and the next time you get back to the mobility calculation and the same squares on the rook's rank/file are occupied, just use the last calculated score. You could take this a bit further if you want and save N previously calculated scores.
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Search and Mobility

Post by jwes »

outAtime wrote:Hi all. I have spent alot of time trying to implement some sort of mobility scores in eval. Still not exactly as i would like e.g.

Code: Select all

int rook_mobility_black(int sq, int offsets[])
{
  int q, *c = offsets, t = 0;
 
  for ( ; *c; c++)
       for (q = sq + *c; board[q] == npiece; q += *c)
           t++; 
		  		  
	   for (q = sq + *c; board[q] == wknight; q += *c)
           t++; 
		   
	   for (q = sq + *c; board[q] == wbishop; q += *c)
           t++; 
		  
       for (q = sq + *c; board[q] == wqueen; q += *c)
           t++; 
		  
       for (q = sq + *c; board[q] == wpawn; q += *c)
           t++;
		   
	   for (q = sq + *c; board[q] == wking; q += *c)
           t++;    
	       
  return t;
}

int black_queen_mobility(int sq)  { return bishop_mobility_black(sq, b_ofs) + rook_mobility_black(sq,r_ofs) ; } 
int black_rook_mobility(int sq)  { return rook_mobility_black(sq, r_ofs); }
int black_bishop_mobility(int sq){ return bishop_mobility_black(sq, b_ofs); }
int white_queen_mobility(int sq)  { return bishop_mobility_white(sq, b_ofs) + rook_mobility_white(sq,r_ofs) ; }
int white_rook_mobility(int sq)  { return rook_mobility_white(sq, r_ofs); }
int white_bishop_mobility(int sq){ return bishop_mobility_white(sq, b_ofs); }
also the mobility code basically takes 2 ply away, especially during the early middle game when there a plenty of pieces.. so any improvement is offset by the lack of depth in _search_ and Im not sure how to proceed. It would be nice to speed up search a bit at this point, but Ive already added LMR and some extended null move. No success yet with increasing LMR above 2, as has been tried with other programs when moves searched are above some number. Also no success with LMR in the root_search. Thanks.
If I understand your code, I think what you want is

Code: Select all

int rook_mobility_black(int sq, int offsets[])
{
  int q, *c = offsets, t = 0;
 
  for ( ; *c; c++)
       for (q = sq + *c; board[q] == npiece; q += *c)
           t++; 
		  		  
       if (board[q] == wpiece)
           t++;    
	       
  return t;
}
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Search and Mobility

Post by outAtime »

Yes, that would be a nice example, id love to have it that way but cant find a way to define wpiece.

Code: Select all

#define frame   0
#define wpawn   1
#define bpawn   2
#define wknight 3
#define bknight 4
#define wking   5
#define bking   6
#define wrook   7
#define brook   8
#define wqueen  9
#define bqueen  10
#define wbishop 11
#define bbishop 12
#define npiece  13

Code: Select all

int init_board[144] = {
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   7,   3,  11,   9,   5,  11,   3,   7,   0,   0,
		0,   0,   1,   1,   1,   1,   1,   1,   1,   1,   0,   0,
		0,   0,  13,  13,  13,  13,  13,  13,  13,  13,   0,   0,
		0,   0,  13,  13,  13,  13,  13,  13,  13,  13,   0,   0,
		0,   0,  13,  13,  13,  13,  13,  13,  13,  13,   0,   0,
		0,   0,  13,  13,  13,  13,  13,  13,  13,  13,   0,   0,
		0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   0,   0,
		0,   0,   8,   4,  12,  10,   6,  12,   4,   8,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 };
Ive tried changing the numbers, say negative numbers for white pieces, or a positive number but the engine dosen't work with the new numbers...
Ive scoured around but cant figure out why.
outAtime
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Search and Mobility

Post by outAtime »

The bitboard idea sounds nice but how trivial would it be to implement? Ive never tried bitboards before. As far as having the mobility weighted by how central a square is i would imagine there would be some duplication of function with the psq tables which tend to be centrally weighted already. Maybe if I removed the psq tables and instead used some sort of centrally weighted mobility... yes, the loops are hellishly expensive.
outAtime
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Search and Mobility

Post by jwes »

outAtime wrote:Yes, that would be a nice example, id love to have it that way but cant find a way to define wpiece.

Code: Select all

#define frame   0
#define wpawn   1
#define bpawn   2
#define wknight 3
#define bknight 4
#define wking   5
#define bking   6
#define wrook   7
#define brook   8
#define wqueen  9
#define bqueen  10
#define wbishop 11
#define bbishop 12
#define npiece  13
Try

Code: Select all

if ((board[q] & 1) == 1)
for white pieces. For black it would be

Code: Select all

if (board[q] && ((board[q] & 1) == 0))
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Search and Mobility

Post by outAtime »

Is that a bitwise way to differentiate between even or odd? Looks pretty good, Ill try it, but what about npiece which is odd (13) would it be counted twice? Sorry, my understanding of this type of bitwise statements is still near the beginning, I understand some but would like to know how its working. And thanks for the suggestion.
outAtime
outAtime
Posts: 226
Joined: Sun Mar 08, 2009 3:08 pm
Location: Canada

Re: Search and Mobility

Post by outAtime »

Code: Select all

int bishop_mobility_black(int sq, int offsets[])
{
  int q, *c = offsets, t = 0;
 
  for ( ; *c; c++)
       for (q = sq + *c; board[q] == npiece; q += *c)
           t++;
		   
	   if (board[q] && ((board[q] & 1) == 0)) 
	       t++;
		  
  return t;
}
where...

Code: Select all

int black_bishop_mobility(int sq){ return bishop_mobility_black(sq, b_ofs); }
and then just simply for now, without any non-linear stuff etc...

Code: Select all

score -= black_bishop_mobility(i) * bme;
returns a compile warning 'q' might be used uninitialized in this function.
outAtime
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Search and Mobility

Post by mcostalba »

outAtime wrote: returns a compile warning 'q' might be used uninitialized in this function.
Try this:

Code: Select all

int bishop_mobility_black(int sq, int offsets[])
{
  int q, *c = offsets, t = 0;

  do {
       for (q = sq + *c; board[q] == npiece; q += *c)
           t++;
  } while (*++c);

  if (board[q] && ((board[q] & 1) == 0))
      t++;

  return t;
}

BTW I'd rename the function as piece_mobility_black() because the code is the same for all the pieces, only the function parameter offsets[] changes.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Search and Mobility

Post by mcostalba »

and if you understand what you are doing you can also write:

Code: Select all

int piece_mobility_black(int sq, int* ofs)
{
  int q, t = 0;

  do {
       for (q = sq + *ofs; board[q] == npiece; q += *ofs)
           t++;
  } while (*++ofs);

  if (board[q] && ((board[q] & 1) == 0))
      t++;

  return t;
}