How to generate this preinitialized array for magic bitboards? - java

I am currently trying to make my chess engine faster, and am looking at implementing magic bitboards for my sliding piece attack generation. I am using a bitboard representation of the chessboard with the a1 square being the furthest right bit, and h8 being the furthest left. I am looking at this site:
https://rhysre.net/fast-chess-move-generation-with-magic-bitboards.html#:~:text=A%20bitboard%20is%20simply%20a,and%20bit%2063%20%3D%20h8)
Specifically the code snippet found towards the bottom of the page that reads:
U64 getBishopAttacksMagic(int square, U64 blockers) {
// Mask blockers to only include bits on diagonals
blockers &= BISHOP_MASKS[square];
// Generate the key using a multiplication and right shift
U64 key = (blockers * BISHOP_MAGICS[square]) >> (64 - BISHOP_INDEX_BITS[square]);
// Return the preinitialized attack set bitboard from the table
return BISHOP_TABLE[square][key];
}
I already have Shallow blues magic numbers(each number corresponding to a square), and I already have pre initialized attack masks for the bishop piece stored in a 64 length array(again each number corresponding to a square). So i know how to get the key. But how do I generate the last array which takes the key, "BISHOP_TABLE" array? I do not understand how to generate that 2d array given an attack mask and magic number for each square. Thank you for your help in advance.

For each square, you need to generate every permutation of blocking pieces inside the bishop mask. For example, using this mask for the square e4 (#28):
8 | 0 0 0 0 0 0 0 0
7 | 0 1 0 0 0 0 0 0
6 | 0 0 1 0 0 0 1 0
5 | 0 0 0 1 0 1 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 1 0 1 0 0
2 | 0 0 1 0 0 0 1 0
1 | 0 0 0 0 0 0 0 0
---------------
a b c d e f g h
since there are 9 set bits, there are 2^9 = 512 different patterns of blocking pieces. The permutation number 339 (as binary = 0b101010011) looks like this:
8 | 0 0 0 0 0 0 0 0
7 | 0 1 0 0 0 0 0 0
6 | 0 0 1 0 0 0 0 0
5 | 0 0 0 1 0 0 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 0 0 0 0 0
2 | 0 0 1 0 0 0 1 0
1 | 0 0 0 0 0 0 0 0
---------------
a b c d e f g h
Bits are read from right (lsb) to left (msb) in the number and are set in the mask from the a file to the h file, 1st rank to 8th. Permutation 0 is an empty board and 511 (0b111111111) is the full mask.
Here's a method that takes a permutation number along with the bishop mask and returns the corresponding blockers bitboard:
private static long blockersPermutation(int iteration, long mask) {
long blockers = 0;
while (iteration != 0) {
if ((iteration & 1) != 0) {
int shift = Long.numberOfTrailingZeros(mask);
blockers |= (1L << shift);
}
iteration >>>= 1;
mask &= (mask - 1); // used in Kernighan's bit count algorithm
// it pops out the least significant bit in the number
}
return blockers;
}
Using this we can calculate the keys with both the magic numbers and the blockers, and we can create their corresponding values, the attack masks.
For each permutation of blocking pieces, create the corresponding attack mask and store it in the table. Include the blocking pieces and the squares on the side of the board in the mask. The attack mask for the blockers #339 on square #28 is:
8 | 0 0 0 0 0 0 0 0
7 | 0 0 0 0 0 0 0 1
6 | 0 0 0 0 0 0 1 0
5 | 0 0 0 1 0 1 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 1 0 1 0 0
2 | 0 0 1 0 0 0 1 0
1 | 0 0 0 0 0 0 0 0
---------------
a b c d e f g h
Here's a Java method to initialize the 64 bishop lookup tables:
private final long[][] BISHOP_LOOKUP = new long[64][512];
private static int getFile(int square) {
return square % 8;
}
private static int getRank(int square) {
return square / 8;
}
private static int getSquare(int rank, int file) {
return rank * 8 + file;
}
// just like the code snippet, generates the key
private static int transform (long blockers, long magic, int shift) {
return (int) ((blockers * magic) >>> (64 - shift));
}
private void initBishopLookup() {
for (int square = 0; square < 64; square++) {
long mask = BISHOP_MASKS[square];
int permutationCount = (1 << Long.bitCount(mask));
for (int i = 0; i < permutationCount; i++) {
long blockers = blockersPermutation(i, mask);
long attacks = 0L;
int rank = getRank(square), r;
int file = getFile(square), f;
for (r = rank + 1, f = file + 1; r <= 7 && f <= 7; r++, f++) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
for (r = rank - 1, f = file + 1; r >= 0 && f <= 7; r--, f++) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
for (r = rank - 1, f = file - 1; r >= 0 && f >= 0; r--, f--) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
for (r = rank + 1, f = file - 1; r <= 7 && f >= 0; r++, f--) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
int key = transform(blockers, BISHOP_MAGICS[square], Long.bitCount(mask));
BISHOP_LOOKUP[square][key] = attacks;
}
}
}
This uses plain magic bitboards with fixed size lookup tables, all of length 512 when masks with less set bits could fit in less space. Like on square b1 the mask uses 5 bits on the diagonal and the table could fit in an array of length 2^5 = 32. We're wasting (512 - 32) * (8 bytes per 64 bits number) / 1024 bytes per Kio = 3.75Kio for this square. Plain magic bitboards take 2Mib of memory for rooks and 256Kib for bishops, using fancy magic bitboards can reduce the total to ~800Kib. It's not really needed though, 2.25Mib of memory is small.

Related

Java undirected Graph distance computation

I am having the following matrix stored in 2d int array result[][]:
0 1 1 0 0 0
1 0 0 1 0 0
1 0 0 1 1 0
0 1 1 0 0 1
0 0 1 0 0 1
0 0 0 1 1 0
I am trying to compute if there are any nodes that are connected with distance of 2 (there is 1 node in between them and no direct connection)
So far I have the following code:
Size is the size of the matrix (n * n) and dis is the distance I am looking for.
for(int row = 0; row < size; row++){
for(int column = 0; column < size; column++){
if(dis == 2){
if((result[row][column] == dis-1 && result[column][column+1] == 1 && result[row][column+1] == 0)){
if(row != column+1){
result[row][column+dis-1] = dis;
result[column+dis-1][row] = dis;
}
}
}
}
}
However, the code does not always work and is not universal if I try to change the distance to 3 or 4 for example.

How to negate base -2 numbers?

I was given a Codility test lately and I was wondering how can I negate -2 base numbers?
For example the array [1,0,0,1,1] represents 9 in base -2:
-2 bases:
1,-2,4,-8,16
1 + (-8) + 16 = 9
[1,0,0,1,1]
Negative 9 in base -2 is:
-2 bases:
1,-2,4,-8
1 + (-2) + -8 = -9
[1,1,0,1]
I'm in the dark regarding the question. There must be some intuitive solution for this. Do you have any hints?
In base −2, a 1 at position i means (−2)i.
So, a [1,1] in positions [i,i+1] means (−2)i + (−2)i+1 = (−2)i + (−2)(−2)i = (1 + −2)(−2)i = −(−2)i.
So you can negate any occurrence of a [1,0] by changing it to a [1,1], and vice versa.
Any other occurrences of 0, of course, can be left intact: −0 = 0.
So in your example, we split [1,0,0,1,1] into [{1,0}, {0}, {1,1}], negate each part to get [{1,1}, {0}, {1,0}], i.e., [1,1,0,1,0], and remove the unnecessary high 0, producing [1,1,0,1].
Let's try a few examples:
(16 -8 4 -2 1)
1 = 0 0 0 0 1
-1 = 0 0 0 1 1
2 = 0 0 1 1 0
-2 = 0 0 0 1 0
3 = 0 0 1 1 1
-3 = 0 1 1 0 1
4 = 0 0 1 0 0
-4 = 0 1 1 0 0
5 = 0 0 1 0 1
-5 = 0 1 1 1 1
We can try to define this mathematically:
Given input I(b) (where B is the bit number),
I = ∑(-2)bI(b) -- definition of base -2)
O = -I -- what we're trying to solve for
O = -∑(-2)bI(b) -- substitution
O = ∑-(-2)bI(b) -- distribution
-(-2)b = (-2)b + (-2)b+1
O = ∑((-2)b + (-2)b+1)I(b) -- substitution
O = ∑((-2)bI(b) + (-2)b+1I(b)) -- substitution
O = ∑(-2)bI(b) + ∑(-2)b+1I(b)
O(b) = I(b) + I(b-1)
Now, this leaves the possibility that O(b) is 0, 1, or 2, since I(b) is always 0 or 1.
If O(b) is a 2, that is a "carry", Let's look at a few examples of carries:
(16 -8 4 -2 1) (16 -8 4 -2 1)
1+1 = 0 0 0 0 2 = 0 0 1 1 0
-2-2 = 0 0 0 2 0 = 0 1 1 0 0
4+4 = 0 0 2 0 0 = 1 1 0 0 0
for each b, starting at 0, if O(b) >= 2, subtract 2 from O(b) and increment O(b+1) and O(b+2). Do this until you reach your maximum B.
Hopefully this explains it in enough detail.
Imagine you have a number A. Then -A = A - 2*A
Or -A = A + (-2)*A. Luckily you have base -2. And (-2)*A is equivalent to left shift by one digit. All you need now is just to implement A << 1 + A. Array shifting is easy. And then you need to implement binary addition with one small difference: each time you carry over a bit you need to multiply it by -1.
public int[] solution(int[] input)
{
var A = new int[input.Length + 1];
var B = new int[input.Length + 1];
input.CopyTo(B, 1);
input.CopyTo(A, 0);
return GetResult(A, B).ToArray();
}
public IEnumerable<int> GetResult(int[] A, int[] B)
{
var r = 0;
for (int i = 0; i < A.Length; i++)
{
var currentSum = A[i] + B[i] + r;
r = -currentSum / 2;
yield return currentSum % 2;
}
}
Sorry, but the example is in C#

Bitwise operators and for loop

I'm trying to understand the bitwise and the shift operators. I wrote a simple code to show me the bits in a short type.
class Shift {
public static void main (String args[]) {
short b = 16384;
for (int t = 32768; t > 0; t = t / 2) {
if ((b&t) != 0) System.out.print("1 ");
else System.out.print ("0 ");
}
System.out.println();
b = (short)(b + 2);
for (long t = 2147483648L; t > 0; t = t / 2) {
if ((b&t) != 0) System.out.print ("1 ");
else System.out.print ("0 ");
}
System.out.println();
}
}
And the output is:
C:\>java Shift
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0
I used with the second for an AND with a short (16 bits) and a long (64 bits) and the output is 32-bits.
I don't understand why the output of the second for is 32-bits.
Thank you.
You start your loop with long t = 2147483648L, which is 2^31. Therefore your loop has 32 iterations and prints 32 bits.
If you wish to display more bits, start the loop with long t = 0x4000000000000000L; (which is equivalent to the binary number starting with 01 and ending with 62 0s).

represent correctly a 2d world in java

I am making a scrolling game in Java , I would like a clarification on one point.
I do not save the game level in any structure java , I just read a file ( . gif )
which I modified in a way that :
I use the color decryption to parse through every pixel to pixel and place where the
object meets the requirements that I have established .
for example:
.
.
.
int w = image.getWidth(); //store the dimensions of the level image.
int h = image.getHeight();
for(int x = 0; x < w; x++){
for(int y = 0; y < h; y++){ //check every single pixel with this nested loop
int pixel = image.getRGB(x, y); //get the pixel's rgb value
TYPE_INT_ARGB formatint red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
if(red == 255 && green == 255 && blue == 0)
controller.addPlayer((float)x, (float)y);
else if(red == 255 && green == 255 && blue == 255)
controller.addTerrain(x, y);
}
as you can see i don't save the level in any structure, but I just scan the image file that represents it.
is a good idea to do it this way?
Naturally i store all objects with the controller class where i create an arrayList that contains all game 's objects .
 
You could make a .txt file and create a map like this:
20
10
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0
the 0 would represent air and the 1 a walkable tile. the first value is the map width and the second the map height.
I also recommend you to use a 2d array to store the map information. Now you can read the txt file with a BufferedReader. Hope this code below helps
private final int TILE_SIZE = 30;
private int[][] blocks;
private void loadMap(File file) {
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
mapWidth = Integer.parseInt(reader.readLine());
mapHeight = Integer.parseInt(reader.readLine());
blocks = new int[mapHeight][mapWidth];
for(int col = 0; col < mapHeight; col ++) {
String line = reader.readLine();
String[] tokens = line.split(" ");
for(int row = 0; row < numBlocksRow; row++) {
blocks[col][row] = Integer.parseInt(tokens[row]);
}
}
reader.close();
} catch(Exception e) {
e.printStackTrace();
}
}
private void render(Graphics2D g) {
for(int col = 0; col < mapHeight; col ++) {
for(int row = 0; row < numBlocksRow; row++) {
int block = blocks[col][row];
Color color;
if(block == 1) {
color = Color.white;
} else {
color = Color.black;
}
g.fillRect(row * TILE_SIZE, col * TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
}
}

Need an efficient implementation of the following formula?

I have been trying to implement the following formula
the formula is as follows
summation(from i = 1 to i = K) (M choose i) * i! * StirlingNumberOfSeconfType(N,i)
for the constraints
1 ≤ N ≤ 1000
1 ≤ M ≤ 1000000
1 ≤ K ≤ 1000
but I am failing to get results for large inputs can anyone provide me an efficient implementation of the formula ?
You can try using a double (or a "long double" if you use C or C++ on gcc) to avoid failing for the larger results.
EDIT: Read the question more carefully
Efficient stirling 2nd numbers calculation (question title is misleading I know but read it): https://mathoverflow.net/questions/34151/simple-efficient-representation-of-stirling-numbers-of-the-first-kind
Use http://gmplib.org/ to avoid the overflows.
I recently implemented this using BigInteger. I have the methods as static as it is part of a utility class for my project, change them as you will.
explanations from here:
Stirling Numbers of the second kind
Binomial Coefficient
Rounding is carried out to remove inaccuracies from limitations of variables.
note: BigInteger should only be used if necessary. I am having to calculate the number of combinations possible in arrays of possible maximum long possible, hence I believe BigInteger is required for accuracies in my calculations. If you do not need this accuracy, switch to long.
Comments should explain the code:
/**
* calculates the sterling number of {n k}
*
* #param n
* #param k
* #return
*/
public static BigDecimal SterlingNumber(int n, int k) {
//return 1 or 0 for special cases
if(n == k){
return BigDecimal.ONE;
} else if(k == 0){
return BigDecimal.ZERO;
}
//calculate first coefficient
BigDecimal bdCoefficient = BigDecimal.ONE.divide(new BigDecimal(UtilityMath.factorial(k)), MathContext.DECIMAL64);
//define summation
BigInteger summation = BigInteger.ZERO;
for (int i = 0; i <= k; i++) {
//combination amount = binomial coefficient
BigInteger biCombinationAmount = UtilityMath.getCombinationAmount(k, i, false, false);
//biN = i^n
BigInteger biN = BigInteger.valueOf(i).pow(n);
//plus this calculation onto previous calculation. 1/k! * E(-1^(k-j) * (k, j) j^n)
summation = summation.add(BigInteger.valueOf(-1).pow(k - i).multiply(biCombinationAmount).multiply(biN));
}
return bdCoefficient.multiply(new BigDecimal(summation)).setScale(0, RoundingMode.UP);
}
/**
* get combinations amount where repetition(1:1) is not allowed; and Order
* does not matter (both 1:2 and 2:1 are the same). Otherwise known as
* Bionomial coefficient [1] .
*
* #param iPossibleObservations number of possible observations.
* #param iPatternLength length of each pattern (number of outcomes we are
* selecting. According to [1], if patternLength is 0 or the same as
* iPossibleObservations, this method will return 1
* #return the combination amount where repetition is not allowed and order
* is not taken into consideration.
* #see [1]http://en.wikipedia.org/wiki/Binomial_coefficient
*/
public static BigInteger getCombinationAmountNoRepNoOrder(int iPossibleObservations, int iPatternLength) {
if (iPatternLength == 0 || iPatternLength == iPossibleObservations) {
return BigInteger.ONE;
}
BigInteger biNumOfCombinations;
BigInteger biPossibleObservationsFactorial = factorial(iPossibleObservations);
BigInteger biPatternLengthFactorial = factorial(iPatternLength);
BigInteger biLastFactorial = factorial(iPossibleObservations - iPatternLength);
biNumOfCombinations = biPossibleObservationsFactorial.divide(biPatternLengthFactorial.multiply(biLastFactorial));
return biNumOfCombinations;
}
From this main
public static void main(String[] args) {
System.out.print("\t" + " ");
for (int i = 0; i <= 10; i++) {
System.out.print("\t" + i);
}
System.out.print("\n");
for (int i = 0; i <= 10; i++) {
System.out.print("\t" + i);
for (int j = 0; j <= 10; j++) {
int n = i;
int k = j;
if (k > i) {
System.out.print("\t0");
continue;
}
BigDecimal biSterling = UtilityMath.SterlingNumber(n, k);
System.out.print("\t" + biSterling.toPlainString());
}
System.out.print("\n");
}
}
I have output:
0 1 2 3 4 5 6 7 8 9 10
0 1 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0
2 0 1 1 0 0 0 0 0 0 0 0
3 0 1 3 1 0 0 0 0 0 0 0
4 0 1 7 7 1 0 0 0 0 0 0
5 0 1 5 26 11 1 0 0 0 0 0
6 0 1 31 91 66 15 1 0 0 0 0
7 0 1 63 302 351 140 22 1 0 0 0
8 0 1 127 967 1702 1050 267 28 1 0 0
9 0 1 255 3026 7771 6951 2647 462 36 1 0
10 0 1 511 9331 34106 42525 22828 5880 750 451 1

Categories