Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: sliding attacks in three #define

Author: rasjid chan

Date: 03:13:45 04/09/04

Go up one level in this thread


On April 09, 2004 at 04:55:25, Gerd Isenberg wrote:

>On April 09, 2004 at 02:30:36, rasjid chan wrote:
>
>>
>>
>>I have a set of simple macros for bitboard operations and they are meant for
>>those with a new chess program and like to implement fast complete
>>attacks by bishops and rooks. It is basically just three #define and all sliding
>>attacks would then be available for use in evaluations and move ordering. Of
>>course it is only when we don't yet count instruction cycles,
>>but then after things are moving we could EASILY upgrade to
>>rotated bitboards.
>>
>>The only requirement is that the "all" bits must be available. Most chess
>>programmers sooner or later will have to use some bitboard operations as
>>there seem no escape for the sliding pieces and it is usually necessary to
>>incrementally update the "all" bits after makemove()and unmake().
>>
>>These bitboard operations just make use of simple direct intuitive
>>operations.If we have a single bit x, then x - 1 divides the board into
>>upper half and lower half and add to it some bitwise operations which
>>everyone say is fast. The only memory access is U64 diagonal[2][15]
>>and it is much better than U64 attack[64][64].
>>For those not using 0x88, they just need some simple editing.
>>
>>If anyone has something faster or can make them faster, please post.
>>
>>Best Regards
>>Rasjid
>>
>>
>>typedef unsigned _int64		U64
>>
>>#define GetFile64(sq)             ((sq) & 7)
>>#define GetRank64(sq)	          ((sq) >> 3)
>>#define iGetFile(sq88)            ((sq88) & 7)
>>#define iGetRank(sq88)            ((sq88) >> 4)
>>#define sq88Bit(sq88)             ((U64)1 << (((sq88) + ((sq88) & 7)) >> 1))
>>#define sq64Bit(sq64)	          (((U64)1) << (sq64))
>>#define sq88RankBits(sq88)       ((U64)0xff << ((sq88) >> 1 & 0370))
>>#define sq88FileBits(sq88)        ((U64) 0x0101010101010101 << ((sq88) & 7))
>>
>>//*** global variables
>>U64 all, diagonal[2][15];
>>
>>
>>//*** Start - bitboard attack operations for sliding pieces
>>
>>/*
>>	This test that the in-between arc (x, y) is clear of any bits.
>>        path is the complete bit path along x, y across the board
>>  */
>>
>>#define 	brq_path_clear(x, y, path)
>>	((x) <= (y)
>>	? ((x) == (y)  || isqBit(y) - 1 & ~(isqBit(x) - 1 | isqBit(x))
>>          &     (path)        & all ? 0 : 1)
>>		: (isqBit(x) - 1 & ~(isqBit(y) - 1 | isqBit(y))
>>                   & (path) & all ? 0 : 1))
>>
>>/*
>>	 given any two sq88 x, y , this test if they attack along
>>         diagonals.
>>  */
>>
>>#define		bstyle_attack(x, y)
>>	(iGetRank(x) + iGetFile(x) == iGetRank(y) + iGetFile(y)
>>		? (brq_path_clear(x, y, diagonal[1][iGetRank(x)
>>                     + iGetFile(x)]) ? 1 : 0)
>>		: (iGetRank(x) - iGetFile(x) == iGetRank(y) - iGetFile(y)
>>   	?  (brq_path_clear(x, y, diagonal[0][7 + iGetRank(x) - iGetFile(x)])
>>    ? 1 : 0) : 0))
>>
>>/*
>>	 given any two sq88 x, y , this test if they attack along
>>     rank or file.
>>  */
>>
>>#define		rstyle_attack(x, y)
>>	(iGetRank(x) == iGetRank(y)
>> 	? (brq_path_clear(x, y, isqRankBits(x)) ? 1 :  0)
>>			: (iGetFile(x) == iGetFile(y)
>>		?  (brq_path_clear(x, y, isqFileBits(x)) ? 1 :  0) : 0))
>>
>>
>>//*** End - bitboard attack operations for sliding pieces
><init code snipped>
>
>
>Hi Rasjid,
>
>Well, i have some problems to read/understand your macros ;-(
>Didn't you need some backslashes to connect all that lines to _one_ macro line?

Hi,

How can we have #define that extends to the nexct line. My consultant
newphew just back from Australia with a BSc(Computer Science) also
said cannot be done. So just to make the appear on a page, I just
have to cut them to the next line.

They would be like these when I paste from my code:-

#define 	brq_path_clear(x, y, path)		((x) <= (y) ? ((x) == (y)  || isqBit(y) - 1
& ~(isqBit(x) - 1 | isqBit(x)) & (path) & all ? 0 : 1) : (isqBit(x) - 1 &
~(isqBit(y) - 1 | isqBit(y)) & (path) & all ? 0 : 1))
#define		bstyle_attack(x, y)      (iGetRank(x) + iGetFile(x) == iGetRank(y) +
iGetFile(y) ? (brq_path_clear(x, y, diagonal[1][iGetRank(x) + iGetFile(x)]) ? 1
: 0): (iGetRank(x) - iGetFile(x) == iGetRank(y) - iGetFile(y) ?
(brq_path_clear(x, y, diagonal[0][7 + iGetRank(x) - iGetFile(x)]) ? 1 : 0) : 0))
#define		rstyle_attack(x, y)       (iGetRank(x) == iGetRank(y) ?
(brq_path_clear(x, y, isqRankBits(x)) ? 1 :  0) : (iGetFile(x) == iGetFile(y) ?
(brq_path_clear(x, y, isqFileBits(x)) ? 1 :  0) : 0))



>
>As far as i understand they act like boolean functions, whether two squares are
>connected on an appropriate ray, or whether y is attacked by a bishop/rook on x
>(or vice versa).
>
>So you do something like ...
>

Since you asked, I doubled checked that they have no bugs. Yes,
I debug at every root nodes in debug auto play for non-stop games
and they are compared to simple attacks using standard 0x88 style
of sliding from square x to y and checked if they are not stopped.



>bool isAttacked(BitBoard all, int targetSq, int sourceSq)
>{
>    // precondition: both squares share a common ray

This is basically what it is but no need for the preconditions.
ie, as long as you have your all bits "all" updated, they are for real
attacks. Yes Ithink it is call boolean as the macros evaluate to
either 0 / 1. But we could easily adapt them to functions that
return bits, etc if we want.

take the simple "if" statement :-

if (bstyle_attack(sq1, sq2)){

//execution will enter here if and only if
 1) sq1 and sq2 along diagonals and sq1 != sq2
 2) no bits (all) in between or arc clear -
    meaning the squares can attack as bishop-style.
  any other combinations will not come here

}

>    BitBoard inbetween = bbSquaresInbetween[targetSq][sourceSq];
>    return (inbetween & all) == 0;
>}
>
>... but you want to get rid of the huge 64*64 array and do some computation...


>
>Where do you need that macros? To check the validity of a move (e.g. from
>hashtable) or to genetate moves or attacks with it, as your subject title
>suggests? It it would be interesting to see the usage of bstyle_attack(x,y) and
>rstyle_attack(x,y) macros. How do you compute sliding attacks with this macros?

I find it a little humorous that you ask about usage, just in case ...

eg evaluation().
Say we dont have attack-tables implemented and want to know
if my side bishop at bs_sq  can attack opponent xside queen at q_sq.
we use :-

if (bstyle_attack(bs_sq, q_sq)){
   score[side] += 20;
}

In move odering; say  we have a rook that has a safe move
(sq_from - sq_to) and we want to know if it is also a check move :

if (rstyle_attack(to, xside_king_sq)){
   //move is a check move.
}

They are complete sliding attacks and need only an updated "all" bits

>
>I am not quite sure, but my feeling with your macros is, that they are a bit to
>complicated and therefore difficult to read for me ;-)
>
>Note that those boolean statements
>
>   booleanExpression ? true : false
>   booleanExpression ? 1 : 0
>   booleanExpression
>
>are equivalent.
>
>Expressions with relational operators (==,!=,...) are boolean expressions with
>the value range {0,1}, as well a boolean operators (&&,||,!).
>
>Cheers,
>Gerd

But then I'm not sure how other programmers use bitboards.
I can adapt the above to do a sliding bitboard generator (a silly one)
that extracts the 4 paths of the queen and then using x & - x
get the bits(moves) one at a time; but tell me
how I'm to convert a single bit back to squares w/o huge overhead,
even Dr Hyatt cannot do it. So I can't understand exactly why the term
"bitboard generators" are use and discussed.

Rasjid





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.