Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: questions.

Author: Tord Romstad

Date: 09:04:36 03/24/04

Go up one level in this thread


On March 24, 2004 at 11:30:49, Daniel Shawul wrote:

>Hi
>
>Is it too costy to add checks only for captures in quiescent.
>In my engine non capture checks decrease nps significantly.May be it is because
>it is hard [at least for me] to generate only checking moves.But the capture
>checks seem to work good in test suites and practically no decrease in nps in
>actual play.Has any one have the same experience.

I've found that generating checks (including non-captures and discovered
checks) isn't that expensive, and that it pays off.  A few hints:

1. Don't generate checks immediately.  Generate and search captures and
promotions first.  Only when all captures and promotions have been searched
and you still don't have a cutoff, consider generating checks.

2. Don't search checks at all qnodes.  If the side to move has a winning
material advantage, or if one of the captures searched gave a winning
advantage (but still not big enough to cause a cutoff), searching checks
is probably not worth the effort.  Other factors to consider is the king
safety of the opponent (checks are more likely to be effective if the
opponent's king is exposed) and the path leading to the node (if there
were many checks, mate threats and other attacking moves in the last few
plies, checks are more likely to be important).

3. Use your SEE to cull losing checks, like you (probably) already do for
captures.

>Another completely different question.
>Can attack tables efficently replace the conventional SEE routine.
>Ed says in his paper he uses a table look up scheme to find hanging pieces.
>But what about pinned attackers? [which the conventional SEE handles well].
>Also i can't see how a table indexed by the two 8-bit variables give an
>approximation of the SEE outcome.
>for example if rebel's wb[sq] = 110 11000  [3 white attacks by pawns and
>knights]. How do i know whether it is 2 pawns and 1 kinght or 2 kinghts and a
>pawn attacking the square?

You don't.  You simply have to make a guess.  In Gothmog, I always assume
that the smallest-valued pieces are most numerous.  In the case above, I
assume 2 pawns and 1 knight.

>I think using this method for see will make the already inaccurate SEE worse.
>Am i right?

Yes.  If you are worried about it, you can teach your program to recognize
the cases when the attack table based SEE is likely to be wrong, and use a
conventional SEE in these cases.  Call the regular SEE when there is a pin,
or when the number of attackers is bigger than the different types of pieces.
I did this until very recently, but have now removed it in order to make
things simpler.  It has no noticable effect at all on Gothmog's strength.

In case you're interested, you'll find the code for my attack-table-based
SEE below.  My attack tables are currently identical to Ed's, but instead
of using a lookup table I calculate the SEE value from the attack table
entries and store the results in a small hash table.  The hash table is
optional, you can enable or disable it by #defining or #undefining
SEE_CACHE.  The code is loosely based on the SEE in Crafty (thanks, Bob).

If you find this code useful, you (and everybody else, of course) are free
to use it in any way you want.


#if defined(SEE_CACHE)
uint32 SeeCache[256];
uint32 VZob1[256], VZob2[256], PieceZob[13];

void init_see_cache() {
  int i;
  for(i=0; i<13; i++) PieceZob[i] = Random32();
  for(i=0; i<256; i++) VZob1[i] = Random32();
  for(i=0; i<256; i++) VZob2[i] = Random32();
  for(i=0; i<256; i++) SeeCache[i] = 0; }
#endif


/* Value of smallest attacking piece */
uint8 SmallestAttacker[256] = {
  10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  100, 100, 100, 100, 100, 100, 100, 100, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
  5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1,
  3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1 };


/* New attack vector with smallest attacker removed */
uint8 SmallestRemoved[256] = {
  0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 9, 10, 11, 12, 13, 14, 0, 0, 17, 18, 19, 20,
  21, 22, 15, 16, 17, 26, 27, 28, 29, 30, 0, 0, 33, 34, 35, 36, 37, 38, 31, 32,
  33, 42, 43, 44, 45, 46, 31, 32, 33, 50, 51, 52, 53, 54, 47, 48, 49, 50, 59,
  60, 61, 62, 0, 0, 65, 66, 67, 68, 69, 70, 63, 64, 65, 74, 75, 76, 77, 78, 63,
  64, 65, 82, 83, 84, 85, 86, 79, 80, 81, 82, 91, 92, 93, 94, 63, 64, 65, 98,
  99, 100, 101, 102, 95, 96, 97, 98, 107, 108, 109, 110, 95, 96, 97, 98, 115,
  116, 117, 118, 111, 112, 113, 114, 115, 124, 125, 126, 0, 0, 129, 130, 131,
  132, 133, 134, 127, 128, 129, 138, 139, 140, 141, 142, 127, 128, 129, 146,
  147, 148, 149, 150, 143, 144, 145, 146, 155, 156, 157, 158, 127, 128, 129,
  162, 163, 164, 165, 166, 159, 160, 161, 162, 171, 172, 173, 174, 159, 160,
  161, 162, 179, 180, 181, 182, 175, 176, 177, 178, 179, 188, 189, 190, 127,
  128, 129, 194, 195, 196, 197, 198, 191, 192, 193, 194, 203, 204, 205, 206,
  191, 192, 193, 194, 211, 212, 213, 214, 207, 208, 209, 210, 211, 220, 221,
  222, 191, 192, 193, 194, 227, 228, 229, 230, 223, 224, 225, 226, 227, 236,
  237, 238, 223, 224, 225, 226, 227, 244, 245, 246, 239, 240, 241, 242, 243,
  244, 253 };


/* Piece values, P=1, N=B=3, R=5, Q=10, K=100 */
uint8 CompactPieceValues[16] = {0, 1, 3, 3, 5, 10, 100, 1, 3, 3, 5, 10, 100};


/* compute_see() is the attack table based SEE routine.
 * piece = The piece under attack.
 * u1 = WhiteAttacks[square containing piece]
 * u2 = BlackAttacks[square containing piece]
 * Returns the expected value of capturing the piece. */

int compute_see(int piece, int u1, int u2) {
  int attackers[16];
  int i=1, colour=BLACK, attacked, pc;
  int v[2];
#if defined(SEE_CACHE)
  uint32 key, index;
#endif

  if(piece==0) return 0;
  if(piece<=WK) {v[0] = u2; v[1] = u1;} else {v[0] = u1; v[1] = u2;};
  if(v[0]==0) return 0;
  if(v[1]==0) return CompactPieceValues[piece];

#if defined(SEE_CACHE)
  key = PieceZob[piece]^VZob1[u1]^VZob2[u2];
  index = key&0xFF;
  if((SeeCache[index]&0xFFFFFF00)==(key&0xFFFFFF00))
    return SeeCache[index]&0xFF;
#endif

  attackers[0] = CompactPieceValues[piece];
  attacked = SmallestAttacker[v[0]];
  v[0] = SmallestRemoved[v[0]];

  do {
    pc = SmallestAttacker[v[colour]];
    v[colour] = SmallestRemoved[v[colour]];
    attackers[i] = -attackers[i-1]+attacked;
    attacked = pc;
    i++;
    colour^=1;
  } while(v[colour]);

  while(--i)
    if(attackers[i] > -attackers[i-1]) attackers[i-1] = -attackers[i];
  if(attackers[0]<0) attackers[0] = 0;

#if defined(SEE_CACHE)
  SeeCache[index] = (key&0xFFFFFF00)|attackers[0];
#endif

  return attackers[0]; }


/* End of code */


Tord



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.