|
While this post has a good amount of substance, I found it rather hard to understand due to small mistakes (or hidden assumptions, or something else?). All of which seem easily fixed/clarified, but these sorts of things are unnecessary friction for readers. Edit: Thanks to Jasper for stating the big hidden assumption made by the author - that he is only considering the case of being blocked by enemy pieces, not one's own pieces. This is motivated by the fact that one can use the same side occupancy board to trivially remove all moves that are illegal due to self-blocking. This resolves many of the technical issues, although again, it should be be made explicit. The typos/silly errors and pedagogical mistakes remain. Some examples: - According to the first bitboard (and the convention stated in the OP), A2 has index 8, not 1. - In the second bitboard, the rook on e4 should be able to move to e1,a4,e8,h4. - max of 9 relevant occupancy bits for a bishop - how? A bishop on e4 for example would have to check b1,c2,d3,f5,g6,h7 and a8,b7,c6,d5,f3,g2,h1 for a total of 13 bits. Similar mistake for a the rook. - The so called "original" masked occupancy bitboard was not mentioned previously - That same bitboard has variables b1,b2,b3,b4,b5 on it, a notational collision with the squares b1-b5.
- The variables b1-b5 are in the wrong place (presumably they were meant to be on c3,d4,e5,f6,g7 since the bishop is on b2, and again there is the question of why not h8 and the other missing squares). - Magic number comes out of nowhere. What is it doing? Presumably the purpose is to extract the relevant positional bits to be the most significant ones while keeping the order, done through the multiplication + bitmasking, but this should be explicitly stated. We also have no idea how it is derived. - What are the "collisions" actually collisions of? It would be nice to see an example of this. |
Some background: I taught a class on chess engines this spring (at some point, I'll write up a postmortem on it, maybe). This post was originally derived from my lecture notes for the class, and was (if I remember correctly) the 5th lecture, so I could make more assumptions about the students being steeped in chess-engine lingo.
Josh Triplett is entirely correct here on the masking technique. There are two steps to sliding-piece move generation: first, creating the set of squares a piece can "see," and then the set that it can attack. Magic bitboards are used for generating the set of squares a piece can see.
In terms of where magic bitboards come from: there's not that much in terms of logical derivation. You just have to kind of squint and say, "yeah, I believe that'll work." Magic numbers are found by brute force trial-and-error.
Collisions are caused when the magic multiply doesn't actually yield a perfect bit extraction. Imagine if O * M >> 59 was instead some gross expression of all five bits. The magic number for B1 here is actually an exception - things are not usually so easy. However, if two different positions have the same attack set, and they get sent to the same index by a magic multiply, it doesn't matter that they collided because they map to the same value.