View Javadoc

1   /**********************************************
2    * Copyright (C) 2009 Lukas Laag
3    * This file is part of carballo-gwt.
4    * 
5    * carballo-gwt is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * carballo-gwt is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with carballo-gwt.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package com.alonsoruibal.chess.bitboard;
19  
20  import com.google.gwt.core.client.GWT;
21  import com.google.gwt.user.client.Window;
22  
23  public class JSONAttackGenerator implements AttackGenerator {
24  	public void run() {
25  		long t1 = System.currentTimeMillis();
26  		BitboardAttacks.rook = new long[64] ;
27  		BitboardAttacks.rookMask = new long[64];
28  		BitboardAttacks.rookMagic = new long[64][];
29  		BitboardAttacks.bishop = new long[64];
30  		BitboardAttacks.bishopMask = new long[64];
31  		BitboardAttacks.bishopMagic = new long[64][];
32  		BitboardAttacks.knight = new long[64];
33  		BitboardAttacks.king = new long[64];
34  		BitboardAttacks.pawnDownwards = new long[64];
35  		BitboardAttacks.pawnUpwards = new long[64];
36  
37  		long square = 1;
38  		byte i = 0;
39  		while (square != 0) {
40  			BitboardAttacks.rook[i] = squareAttackedAuxSlider(square, +8, BitboardUtils.b_u)
41  					| squareAttackedAuxSlider(square, -8, BitboardUtils.b_d)
42  					| squareAttackedAuxSlider(square, -1, BitboardUtils.b_r)
43  					| squareAttackedAuxSlider(square, +1, BitboardUtils.b_l);
44  
45  			BitboardAttacks.rookMask[i] = squareAttackedAuxSliderMask(square, +8, BitboardUtils.b_u)
46  					| squareAttackedAuxSliderMask(square, -8, BitboardUtils.b_d)
47  					| squareAttackedAuxSliderMask(square, -1, BitboardUtils.b_r)
48  					| squareAttackedAuxSliderMask(square, +1, BitboardUtils.b_l);
49  
50  			BitboardAttacks.bishop[i] = squareAttackedAuxSlider(square, +9, BitboardUtils.b_u | BitboardUtils.b_l) 
51  					| squareAttackedAuxSlider(square, +7, BitboardUtils.b_u | BitboardUtils.b_r)
52  					| squareAttackedAuxSlider(square, -7, BitboardUtils.b_d | BitboardUtils.b_l)
53  					| squareAttackedAuxSlider(square, -9, BitboardUtils.b_d | BitboardUtils.b_r);
54  			BitboardAttacks.bishopMask[i] = squareAttackedAuxSliderMask(square, +9, BitboardUtils.b_u | BitboardUtils.b_l) 
55  					| squareAttackedAuxSliderMask(square, +7, BitboardUtils.b_u | BitboardUtils.b_r)
56  					| squareAttackedAuxSliderMask(square, -7, BitboardUtils.b_d | BitboardUtils.b_l)
57  					| squareAttackedAuxSliderMask(square, -9, BitboardUtils.b_d | BitboardUtils.b_r);
58  
59  			BitboardAttacks.knight[i] = squareAttackedAux(square, +17, BitboardUtils.b2_u | BitboardUtils.b_l)
60  					| squareAttackedAux(square, +15, BitboardUtils.b2_u | BitboardUtils.b_r)
61  					| squareAttackedAux(square, -15, BitboardUtils.b2_d | BitboardUtils.b_l)
62  					| squareAttackedAux(square, -17, BitboardUtils.b2_d | BitboardUtils.b_r)
63  					| squareAttackedAux(square, +10, BitboardUtils.b_u | BitboardUtils.b2_l)
64  					| squareAttackedAux(square, +6, BitboardUtils.b_u | BitboardUtils.b2_r)
65  					| squareAttackedAux(square, -6, BitboardUtils.b_d | BitboardUtils.b2_l)
66  					| squareAttackedAux(square, -10, BitboardUtils.b_d | BitboardUtils.b2_r);
67  
68  			BitboardAttacks.pawnUpwards[i] = squareAttackedAux(square, 7, BitboardUtils.b_u | BitboardUtils.b_r)
69  					| squareAttackedAux(square, 9, BitboardUtils.b_u | BitboardUtils.b_l);
70  
71  			BitboardAttacks.pawnDownwards[i] = squareAttackedAux(square, -7, BitboardUtils.b_d | BitboardUtils.b_l)
72  					| squareAttackedAux(square, -9, BitboardUtils.b_d | BitboardUtils.b_r);
73  
74  			BitboardAttacks.king[i] = squareAttackedAux(square, +8, BitboardUtils.b_u)
75  					| squareAttackedAux(square, -8, BitboardUtils.b_d)
76  					| squareAttackedAux(square, -1, BitboardUtils.b_r)
77  					| squareAttackedAux(square, +1, BitboardUtils.b_l)
78  					| squareAttackedAux(square, +9, BitboardUtils.b_u | BitboardUtils.b_l)
79  					| squareAttackedAux(square, +7, BitboardUtils.b_u | BitboardUtils.b_r)
80  					| squareAttackedAux(square, -7, BitboardUtils.b_d | BitboardUtils.b_l)
81  					| squareAttackedAux(square, -9, BitboardUtils.b_d | BitboardUtils.b_r);
82  
83  			// And now generate magics			
84  			int rookPositions = (1 << BitboardAttacks.rookShiftBits[i]);
85  			BitboardAttacks.rookMagic[i] = new long[rookPositions];
86  		    for (int j = 0; j < rookPositions; j++) {
87  		      long pieces = generatePieces(j, BitboardAttacks.rookShiftBits[i], BitboardAttacks.rookMask[i]);
88  		      int magicIndex = magicTransform(pieces, BitboardAttacks.rookMagicNumber[i], BitboardAttacks.rookShiftBits[i]);
89  		      BitboardAttacks.rookMagic[i][magicIndex] = getRookShiftAttacks(square, pieces);
90  		    }
91  			
92  			int bishopPositions = (1 << BitboardAttacks.bishopShiftBits[i]);
93  			BitboardAttacks.bishopMagic[i] = new long[bishopPositions];
94  		    for (int j = 0; j < bishopPositions; j++) {
95  		      long pieces = generatePieces(j, BitboardAttacks.bishopShiftBits[i], BitboardAttacks.bishopMask[i]);
96  		      int magicIndex = magicTransform(pieces, BitboardAttacks.bishopMagicNumber[i], BitboardAttacks.bishopShiftBits[i]);
97  		      BitboardAttacks.bishopMagic[i][magicIndex] = getBishopShiftAttacks(square, pieces);
98  		    }
99  		    
100 			square <<= 1;
101 			i++;
102 		}
103 		long t2 = System.currentTimeMillis();
104 		GWT.log("ellapsed: " + (t2 - t1));
105 		if ("true".equals(Window.Location.getParameter("debug"))) {
106 			Window.alert("ellapsed: " + (t2 - t1));
107 		}
108 	}
109 	
110 	public static int magicTransform(long b, long magic, byte bits) {
111 		  return (int)((b * magic) >>> (64 - bits));
112 	}
113 
114 	private static long squareAttackedAux(long square, int shift, long border) {
115 		if ((square & border) == 0) {
116 			if (shift > 0) square <<= shift; else square >>>= -shift;
117 			return square;
118 		}
119 		return 0;
120 	}
121 	
122 	private static long squareAttackedAuxSlider(long square, int shift, long border) {
123 		long ret = 0;
124 		while ((square & border) == 0) {
125 			if (shift > 0) square <<= shift; else square >>>= -shift;
126 			ret |= square;
127 		}
128 		return ret;
129 	}
130 
131 	private static long squareAttackedAuxSliderMask(long square, int shift, long border) {
132 		long ret = 0;
133 		while ((square & border) == 0) {
134 			if (shift > 0) square <<= shift; else square >>>= -shift;
135 			if ((square & border) == 0) ret |= square;
136 		}
137 		return ret;
138 	}
139 
140 	/** 
141 	 * witout magic bitboards, too expensive, but neccesary for magic generation
142 	 */
143 	static long getRookShiftAttacks(long square, long all) {
144 		return checkSquareAttackedAux(square, all, +8, BitboardUtils.b_u) |
145 			checkSquareAttackedAux(square, all, -8, BitboardUtils.b_d) |
146 			checkSquareAttackedAux(square, all, -1, BitboardUtils.b_r) |
147 			checkSquareAttackedAux(square, all, +1, BitboardUtils.b_l);
148 	}
149 	
150 	static long getBishopShiftAttacks(long square, long all) {
151 		return checkSquareAttackedAux(square, all, +9, BitboardUtils.b_u | BitboardUtils.b_l) |
152 			checkSquareAttackedAux(square, all, +7, BitboardUtils.b_u | BitboardUtils.b_r) |
153 			checkSquareAttackedAux(square, all, -7, BitboardUtils.b_d | BitboardUtils.b_l) |
154 			checkSquareAttackedAux(square, all, -9, BitboardUtils.b_d | BitboardUtils.b_r);
155 	}
156 	
157 	/**
158 	 * Attacks for sliding pieces
159 	 */
160 	private static long checkSquareAttackedAux(long square, long all, int shift, long border) {
161 		long ret = 0;
162 		while ((square & border) == 0) {
163 			if (shift>0) square <<= shift; else square >>>= -shift;
164 			ret |= square;
165 			// If we collide with other piece
166 			if ((square & all) != 0) break;
167 		}
168 		return ret;
169 	}
170 	
171 	/**
172 	 * Fills pieces from a mask. Neccesary for magic generation
173 	 * variable bits is the mask bytes number
174 	 * index goes from 0 to 2^bits
175 	 */
176 	static long generatePieces(int index, int bits, long mask) {
177 		  int i;
178 		  long lsb;
179 		  long result = 0L;
180 		  for (i = 0; i < bits; i++) {
181 			lsb = mask & (-mask);
182 		    mask ^= lsb; // Deactivates lsb bit of the mask to get next bit next time
183 		    if ((index & (1 << i)) != 0) result |= lsb; // if bit is set to 1
184 		  }
185 		  return result;
186 	}
187 }