Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: questions.

Author: Uri Blass

Date: 11:55:02 03/24/04

Go up one level in this thread


On March 24, 2004 at 14:49:07, Uri Blass wrote:

>On March 24, 2004 at 12:04:36, Tord Romstad wrote:
>
>>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
>
>
>I do not understand your arrays
>
>What is the reason that SmallestAttacker[0]=10?
>Based on Rebel attack table there should be no attackers in that case.
>
>Note that I also has similiar code to Crafty to calculate SEE but I decided to
>have in my code before i++ when I translate it to your varaibles:
>
>If (i>1)&&(attackers[i]>attackers[i-2]+attacked)
>{
> i++;
> break;
>}
>
>The logic is that there are cases when the rest of the pieces are simply not
>relevant to decide about the value of SEE.
>
>If I have BxP QXB RxQ then it is clear that the value of see is one pawn and I
>do not need to calculate more captures in the same square.
>
>I generalized this example to find the formula that I give here.
>Note that I do not know if it helps Crafty in speed because the if command may
>make things slower but I decided that for my slow SEE it is probably better to
>check if I can generate a cut off based on previous captures in order not to
>calculate the smallest attacker again.
>
>I almost do not use SEE in my program today and I guess that I may compare speed
>with the if and without the if when I decide to use it more.
>
>Uri

I forgot to add that I also check in the same condition that the value of SEE is
not too high because value of SEE above 20 means capturing the king so I also
can get out of the loop.

Uri



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.