Author: Vasik Rajlich
Date: 05:20:57 03/25/04
Go up one level in this thread
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
Tord,
I like the SEE chache idea - but why did you make it so small? Wouldn't
something like 10k entries give you much better hit rate & speedup?
Vas
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.