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.