1
2from functools import reduce
3from operator import or_
4from pychess.Utils.const import WHITE, BLACK, KING, PAWN, EMPTY, KNIGHT, ROOK, BISHOP, QUEEN, \
5    A1, A2, A3, A4, A5, A6, A7, A8, \
6    B2, C3, D4, E5, F6, G7, H8,\
7    B7, C6, D5, E4, F3, G2, H1, \
8    B1, B8, H2, H7, G3, G6, B3, B6, sliders
9
10from .bitboard import bitPosArray, iterBits, setBit
11
12
13def RANK(cord):
14    return cord >> 3
15
16
17def FILE(cord):
18    return cord & 7
19
20
21# Evaluating constants
22
23PAWN_VALUE = 100
24KNIGHT_VALUE = 300
25BISHOP_VALUE = 330
26ROOK_VALUE = 500
27QUEEN_VALUE = 900
28KING_VALUE = 2000
29PIECE_VALUES = [0, PAWN_VALUE, KNIGHT_VALUE, BISHOP_VALUE, ROOK_VALUE,
30                QUEEN_VALUE, KING_VALUE]
31
32ASEAN_PIECE_VALUES = (0, 100, 450, 300, 630, 180, 2000)
33CRAZY_PIECE_VALUES = (0, 100, 200, 240, 240, 380, 2000)
34ATOMIC_PIECE_VALUES = (0, 100, 90, 0, 220, 850, 2000)
35
36# Maximum possible search depth. The hash structure only allows 8-bit depths.
37MAXPLY = 10
38# Maximum possible score. Mate in n ply is +/- (MATE_VALUE-n).
39# The hash structure only allows signed 16-bit scores.
40MATE_VALUE = MAXVAL = 32767
41MATE_DEPTH = 255
42
43
44def VALUE_AT_PLY(val, ply):
45    """ Return the value of scoring val a given number of plies into the future. """
46    if val >= +32512:
47        return val - ply
48    if val <= -32512:
49        return val + ply
50    return val
51
52
53# How many points does it give to have the piece standing i cords from the
54# opponent king
55pawnTScale = [0, 40, 20, 12, 9, 6, 4, 2, 1, 0]
56bishopTScale = [0, 50, 25, 15, 7, 5, 3, 2, 2, 1]
57knightTScale = [0, 100, 50, 35, 10, 3, 2, 2, 1, 1]
58rookTScale = [0, 50, 40, 15, 5, 2, 1, 1, 1, 0]
59queenTScale = [0, 100, 60, 20, 10, 7, 5, 4, 3, 2]
60
61passedScores = ((0, 48, 48, 120, 144, 192, 240, 0),
62                (0, 240, 192, 144, 120, 48, 48, 0))
63
64# Penalties for one or more isolated pawns on a given file
65isolani_normal = (-8, -10, -12, -14, -14, -12, -10, -8)
66# Penalties if the file is half-open (i.e. no enemy pawns on it)
67isolani_weaker = (-22, -24, -26, -28, -28, -26, -24, -22)
68
69# Distance boards for different pieces
70
71taxicab = [[0] * 64 for i in range(64)]
72sdistance = [[0] * 64 for i in range(64)]
73for fcord in range(64):
74    for tcord in range(fcord + 1, 64):
75        fx = FILE(fcord)
76        fy = RANK(fcord)
77        tx = FILE(tcord)
78        ty = RANK(tcord)
79        taxicab[fcord][tcord] = taxicab[fcord][tcord] = abs(fx - tx) + abs(fy -
80                                                                           ty)
81        sdistance[fcord][tcord] = sdistance[fcord][tcord] = min(
82            abs(fx - tx), abs(fy - ty))
83
84distance = [[[0] * 64 for i in range(64)] for j in range(KING + 1)]
85
86distance[EMPTY] = None
87distance[KING] = sdistance
88distance[PAWN] = sdistance
89
90# Special table for knightdistances
91
92knightDistance = [
93    6, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 6,
94    5, 4, 5, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 5,
95    4, 5, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4,
96    5, 4, 3, 4, 3, 2, 3, 2, 3, 2, 3, 4, 3, 4, 5,
97    4, 3, 4, 3, 2, 3, 2, 3, 2, 3, 2, 3, 4, 3, 4,
98    5, 4, 3, 2, 3, 4, 1, 2, 1, 4, 3, 2, 3, 4, 5,
99    4, 3, 4, 3, 2, 1, 2, 3, 2, 1, 2, 3, 4, 3, 4,
100    5, 4, 3, 2, 3, 2, 3, 0, 3, 2, 3, 2, 3, 4, 5,
101    4, 3, 4, 3, 2, 1, 2, 3, 2, 1, 2, 3, 4, 3, 4,
102    5, 4, 3, 2, 3, 4, 1, 2, 1, 4, 3, 2, 3, 4, 5,
103    4, 3, 4, 3, 2, 3, 2, 3, 2, 3, 2, 3, 4, 3, 4,
104    5, 4, 3, 4, 3, 2, 3, 2, 3, 2, 3, 4, 3, 4, 5,
105    4, 5, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4,
106    5, 4, 5, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 5,
107    6, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 6,
108]
109
110# Calculate
111
112for fcord in range(64):
113    frank = RANK(fcord)
114    ffile = FILE(fcord)
115
116    for tcord in range(fcord + 1, 64):
117        # Notice, that we skip fcord == tcord, as all fields are zero from
118        # scratch in anyway
119
120        trank = RANK(tcord)
121        tfile = FILE(tcord)
122
123        # Knight
124        field = (7 - frank + trank) * 15 + 7 - ffile + tfile
125        distance[KNIGHT][tcord][fcord] = distance[KNIGHT][fcord][tcord] = \
126            knightDistance[field]
127
128        # Rook
129        if frank == trank or ffile == tfile:
130            distance[ROOK][tcord][fcord] = distance[ROOK][fcord][tcord] = 1
131        else:
132            distance[ROOK][tcord][fcord] = distance[ROOK][fcord][tcord] = 2
133
134        # Bishop
135        if abs(frank - trank) == abs(ffile - tfile):
136            distance[BISHOP][tcord][fcord] = distance[BISHOP][fcord][tcord] = 1
137        else:
138            distance[BISHOP][tcord][fcord] = distance[BISHOP][fcord][tcord] = 2
139
140        # Queen
141        if frank == trank or ffile == tfile or abs(frank - trank) == abs(
142                ffile - tfile):
143            distance[QUEEN][tcord][fcord] = distance[QUEEN][fcord][tcord] = 1
144        else:
145            distance[QUEEN][tcord][fcord] = distance[QUEEN][fcord][tcord] = 2
146
147# Special cases for knights in corners
148distance[KNIGHT][A1][B2] = distance[KNIGHT][B2][A1] = 4
149distance[KNIGHT][H1][G2] = distance[KNIGHT][G2][H1] = 4
150distance[KNIGHT][A8][B7] = distance[KNIGHT][B7][A8] = 4
151distance[KNIGHT][H8][G7] = distance[KNIGHT][G7][H8] = 4
152
153###############################################################################
154# Boards used for evaluating
155###############################################################################
156
157pawnScoreBoard = (
158    (0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, -10, -10, 5, 5, 5, -2, -2, -2, 6, 6,
159     -2, -2, -2, 0, 0, 0, 25, 25, 0, 0, 0, 2, 2, 12, 16, 16, 12, 2, 2, 4, 8,
160     12, 16, 16, 12, 4, 4, 4, 8, 12, 16, 16, 12, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0),
161    (0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 16, 16, 12, 4, 4, 4, 8, 12, 16, 16, 12,
162     4, 4, 2, 2, 12, 16, 16, 12, 2, 2, 0, 0, 0, 25, 25, 0, 0, 0, -2, -2, -2, 6,
163     6, -2, -2, -2, 5, 5, 5, -10, -10, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0))
164
165outpost = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166            0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
167            1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
168           (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1,
169            0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
170            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
171
172normalKing = (24, 24, 24, 16, 16, 0, 32, 32, 24, 20, 16, 12, 12, 16, 20, 24,
173              16, 12, 8, 4, 4, 8, 12, 16, 12, 8, 4, 0, 0, 4, 8, 12, 12, 8, 4,
174              0, 0, 4, 8, 12, 16, 12, 8, 4, 4, 8, 12, 16, 24, 20, 16, 12, 12,
175              16, 20, 24, 24, 24, 24, 16, 16, 0, 32, 32)
176
177endingKing = (0, 6, 12, 18, 18, 12, 6, 0, 6, 12, 18, 24, 24, 18, 12, 6, 12, 18,
178              24, 32, 32, 24, 18, 12, 18, 24, 32, 48, 48, 32, 24, 18, 18, 24,
179              32, 48, 48, 32, 24, 18, 12, 18, 24, 32, 32, 24, 18, 12, 6, 12,
180              18, 24, 24, 18, 12, 6, 0, 6, 12, 18, 18, 12, 6, 0)
181
182racingKing = (0, 0, 0, 0, 0, 0, 0, 0,
183              500, 500, 500, 500, 500, 500, 500, 500,
184              950, 950, 950, 950, 950, 950, 950, 950,
185              1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500,
186              2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500,
187              4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000,
188              6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000,
189              14000, 14000, 14000, 14000, 14000, 14000, 14000, 14000)
190
191# Maps for bitboards
192
193d2e2 = (0x0018000000000000, 0x0000000000001800)
194brank7 = (0x000000000000FF00, 0x00FF000000000000)
195brank8 = (0x00000000000000FF, 0xFF00000000000000)
196brank67 = (0x0000000000FFFF00, 0x00FFFF0000000000)
197brank58 = (0x00000000FFFFFFFF, 0xFFFFFFFF00000000)
198brank48 = (0x000000FFFFFFFFFF, 0xFFFFFFFFFF000000)
199
200# Penalties if the file is half-open (i.e. no enemy pawns on it)
201isolani_weaker = (-22, -24, -26, -28, -28, -26, -24, -22)
202
203stonewall = [0, 0]
204# D4, E3, F4
205# - - - - - - - -
206# - - - - - - - -
207# - - - - - - - -
208# - - - - - - - -
209# - - - # - # - -
210# - - - - # - - -
211# - - - - - - - -
212# - - - - - - - -
213stonewall[WHITE] = 0x81400000000
214
215# D5, E6, F5
216# - - - - - - - -
217# - - - - - - - -
218# - - - - # - - -
219# - - - # - # - -
220# - - - - - - - -
221# - - - - - - - -
222# - - - - - - - -
223# - - - - - - - -
224stonewall[BLACK] = 0x81400000000
225
226# - - - - - - - -
227# - - - - - - - -
228# - - - - - - - -
229# - - - - - - - -
230# - - - - - - - -
231# - # - - - - # -
232# # # - - - - # #
233# - - - - - - - -
234qwingpawns1 = (bitPosArray[A2] | bitPosArray[B2], bitPosArray[A7] |
235               bitPosArray[B7])
236qwingpawns2 = (bitPosArray[A2] | bitPosArray[B3], bitPosArray[A7] |
237               bitPosArray[B6])
238kwingpawns1 = (bitPosArray[G2] | bitPosArray[H2], bitPosArray[G7] |
239               bitPosArray[H7])
240kwingpawns2 = (bitPosArray[G3] | bitPosArray[H2], bitPosArray[G6] |
241               bitPosArray[H7])
242
243################################################################################
244#  Ranks and files                                                             #
245################################################################################
246
247rankBits = [255 << i * 8 for i in range(7, -1, -1)]
248fileBits = [0x0101010101010101 << i for i in range(7, -1, -1)]
249
250# Bit boards
251
252WHITE_SQUARES = 0x55AA55AA55AA55AA
253BLACK_SQUARES = 0xAA55AA55AA55AA55
254
255# - - - - - - - -
256# - - - - - - - -
257# - - - - - - - -
258# - - - # # - - -
259# - - - # # - - -
260# - - - - - - - -
261# - - - - - - - -
262# - - - - - - - -
263CENTER_FOUR = 0x0000001818000000
264
265# - - - - - - - -
266# - - - - - - - -
267# - - # # # # - -
268# - - # # # # - -
269# - - # # # # - -
270# - - # # # # - -
271# - - - - - - - -
272# - - - - - - - -
273sbox = 0x00003C3C3C3C0000
274
275# - - - - - - - -
276# - # # # # # # -
277# - # # # # # # -
278# - # # # # # # -
279# - # # # # # # -
280# - # # # # # # -
281# - # # # # # # -
282# - - - - - - - -
283lbox = 0x007E7E7E7E7E7E00
284
285# - - - - - # # #
286# - - - - - # # #
287# - - - - - # # #
288# - - - - - # # #
289# - - - - - # # #
290# - - - - - # # #
291# - - - - - # # #
292# - - - - - # # #
293right = fileBits[5] | fileBits[6] | fileBits[7]
294
295# # # # - - - - -
296# # # # - - - - -
297# # # # - - - - -
298# # # # - - - - -
299# # # # - - - - -
300# # # # - - - - -
301# # # # - - - - -
302# # # # - - - - -
303left = fileBits[0] | fileBits[1] | fileBits[2]
304
305#  Generate the move bitboards.  For e.g. the bitboard for all                 #
306#  the moves of a knight on f3 is given by MoveArray[knight][21].              #
307
308dir = [
309    None,
310    [9, 11],  # Only capture moves are included
311    [-21, -19, -12, -8, 8, 12, 19, 21],
312    [-11, -9, 9, 11],
313    [-10, -1, 1, 10],
314    [-11, -10, -9, -1, 1, 9, 10, 11],
315    [-11, -10, -9, -1, 1, 9, 10, 11],
316    [-9, -11],
317    [-11, -9, 9, 10, 11],
318    [-11, -10, -9, 9, 11],
319    [-11, -9, 9, 11],
320
321    # Following are for front and back walls. Will be removed from list after
322    # the loop
323    [9, 10, 11],
324    [-9, -10, -11]
325]
326
327sliders += [False, False]
328
329map = [
330    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
331    -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, -1, -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
332    -1, 16, 17, 18, 19, 20, 21, 22, 23, -1, -1, 24, 25, 26, 27, 28, 29, 30, 31,
333    -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 40, 41, 42, 43, 44, 45, 46,
334    47, -1, -1, 48, 49, 50, 51, 52, 53, 54, 55, -1, -1, 56, 57, 58, 59, 60, 61,
335    62, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
336    -1, -1, -1, -1
337]
338
339moveArray = [[0] * 64 for i in range(len(dir))]  # moveArray[len(dir)][64]
340
341for piece in range(1, len(dir)):
342    for fcord in range(120):
343        f = map[fcord]
344        if f == -1:
345            # We only generate moves for squares inside the board
346            continue
347        # Create a new bitboard
348        b = 0
349        for d in dir[piece]:
350            tcord = fcord
351            while True:
352                tcord += d
353                t = map[tcord]
354                if t == -1:
355                    # If we landed outside of board, there is no more to look
356                    # for
357                    break
358                b = setBit(b, t)
359                if not sliders[piece]:
360                    # If we are a slider, we should not break, but add the dir
361                    # value once again
362                    break
363        moveArray[piece][f] = b
364
365frontWall = (moveArray[-2], moveArray[-1])
366del moveArray[-1]
367del moveArray[-1]
368del dir[-1]
369del dir[-1]
370del sliders[-1]
371del sliders[-1]
372
373# For each square, there are 8 rays.  The first 4 rays are diagonals
374# for the bishops and the next 4  are file/rank for the rooks.
375# The queen uses all 8 rays.
376# These rays are used for move generation rather than MoveArray[].
377# Also initialize the directions[][] array.  directions[f][t] returns
378# the index into rays[f] array allow us to find the ray in that direction.
379
380directions = [[-1] * 64 for i in range(64)]  # directions[64][64]
381rays = [[0] * 8 for i in range(64)]  # rays[64][8]
382
383for fcord in range(120):
384    f = map[fcord]
385    if f == -1:
386        continue
387    ray = -1
388    for piece in BISHOP, ROOK:
389        for d in dir[piece]:
390            ray += 1
391            b = 0
392            tcord = fcord
393            while True:
394                tcord += d
395                t = map[tcord]
396                if t == -1:
397                    break
398                rays[f][ray] = setBit(rays[f][ray], t)
399                directions[f][t] = ray
400
401# The FromToRay[b2][f6] gives the diagonal ray from c3 to f6;
402# It also produces horizontal/vertical rays as well. If no
403# ray is possible, then a 0 is returned.
404
405fromToRay = [[0] * 64 for i in range(64)]  # fromToRay[64][64]
406
407for piece in BISHOP, ROOK:
408    for fcord in range(120):
409        f = map[fcord]
410        if f == -1:
411            continue
412        for d in dir[piece]:
413            tcord = fcord
414            t = map[tcord]
415
416            while True:
417                b = fromToRay[f][t]
418                tcord += d
419                t = map[tcord]
420                if t == -1:
421                    break
422                fromToRay[f][t] = setBit(fromToRay[f][t], t)
423                fromToRay[f][t] |= b
424
425# The PassedPawnMask variable is used to determine if a pawn is passed.
426#  his mask is basically all 1's from the square in front of the pawn to
427# the promotion square, also duplicated on both files besides the pawn
428# file. Other bits will be set to zero.
429# E.g. PassedPawnMask[white][b3] = 1's in a4-c4-c8-a8 rect, 0 otherwise.
430
431passedPawnMask = [[0] * 64, [0] * 64]
432
433#  Do for white pawns first
434for cord in range(64):
435    passedPawnMask[WHITE][cord] = rays[cord][7]
436    passedPawnMask[BLACK][cord] = rays[cord][4]
437    if cord & 7 != 0:
438        #  If file is not left most
439        passedPawnMask[WHITE][cord] |= rays[cord - 1][7]
440        passedPawnMask[BLACK][cord] |= rays[cord - 1][4]
441    if cord & 7 != 7:
442        #  If file is not right most
443        passedPawnMask[WHITE][cord] |= rays[cord + 1][7]
444        passedPawnMask[BLACK][cord] |= rays[cord + 1][4]
445
446# The IsolaniMask variable is used to determine if a pawn is an isolani.
447# This mask is basically all 1's on files beside the file the pawn is on.
448# Other bits will be set to zero.
449# E.g. isolaniMask[d-file] = 1's in c-file & e-file, 0 otherwise.
450
451isolaniMask = [0] * 8
452
453isolaniMask[0] = fileBits[1]
454isolaniMask[7] = fileBits[6]
455for i in range(1, 7):
456    isolaniMask[i] = fileBits[i - 1] | fileBits[i + 1]
457
458# The SquarePawnMask is used to determine if a king is in the square of
459# the passed pawn and is able to prevent it from queening.
460# Caveat:  Pawns on 2nd rank have the same mask as pawns on the 3rd rank
461# as they can advance 2 squares.
462
463squarePawnMask = [[0] * 64, [0] * 64]
464for cord in range(64):
465    # White mask
466    rank = 7 - RANK(cord)
467    i = max(cord & 56, cord - rank)
468    j = min(cord | 7, cord + rank)
469    for k in range(i, j + 1):
470        squarePawnMask[WHITE][cord] |= bitPosArray[k] | fromToRay[k][k | 56]
471
472    # Black mask
473    rank = RANK(cord)
474    i = max(cord & 56, cord - rank)
475    j = min(cord | 7, cord + rank)
476    for k in range(i, j + 1):
477        squarePawnMask[BLACK][cord] |= bitPosArray[k] | fromToRay[k][k & 7]
478
479# For pawns on 2nd rank, they have same mask as pawns on 3rd rank
480for cord in range(A2, H2 + 1):
481    squarePawnMask[WHITE][cord] = squarePawnMask[WHITE][cord + 8]
482for cord in range(A7, H7 + 1):
483    squarePawnMask[BLACK][cord] = squarePawnMask[BLACK][cord - 8]
484
485# These tables are used to calculate rook, queen and bishop moves
486
487ray00 = [rays[cord][5] | rays[cord][6] | 1 << (63 - cord)
488         for cord in range(64)]
489ray45 = [rays[cord][0] | rays[cord][3] | 1 << (63 - cord)
490         for cord in range(64)]
491ray90 = [rays[cord][4] | rays[cord][7] | 1 << (63 - cord)
492         for cord in range(64)]
493ray135 = [rays[cord][1] | rays[cord][2] | 1 << (63 - cord)
494          for cord in range(64)]
495
496attack00 = [{} for a in range(64)]
497attack45 = [{} for a in range(64)]
498attack90 = [{} for a in range(64)]
499attack135 = [{} for a in range(64)]
500
501cmap = [128, 64, 32, 16, 8, 4, 2, 1]
502rot1 = [A1, A2, A3, A4, A5, A6, A7, A8]
503rot2 = [A1, B2, C3, D4, E5, F6, G7, H8]
504rot3 = [A8, B7, C6, D5, E4, F3, G2, H1]
505
506# To save time, we init a main line for each of the four directions, and next
507# we will translate it for each possible cord
508for cord in range(8):
509    for map in range(1, 256):
510
511        # Skip entries without cord set, as cord will always be set
512        if not map & cmap[cord]:
513            continue
514
515        # Find limits inclusive
516        cord1 = cord2 = cord
517        while cord1 > 0:
518            cord1 -= 1
519            if cmap[cord1] & map:
520                break
521        while cord2 < 7:
522            cord2 += 1
523            if cmap[cord2] & map:
524                break
525
526        # Remember A1 is the left most bit
527        map00 = map << 56
528
529        attack00[cord][map00] = \
530            fromToRay[cord][cord1] |\
531            fromToRay[cord][cord2]
532
533        map90 = reduce(or_, (1 << 63 - rot1[c] for c in iterBits(map00)))
534        attack90[rot1[cord]][map90] = \
535            fromToRay[rot1[cord]][rot1[cord1]] | \
536            fromToRay[rot1[cord]][rot1[cord2]]
537
538        map45 = reduce(or_, (1 << 63 - rot2[c] for c in iterBits(map00)))
539        attack45[rot2[cord]][map45] = \
540            fromToRay[rot2[cord]][rot2[cord1]] | \
541            fromToRay[rot2[cord]][rot2[cord2]]
542
543        map135 = reduce(or_, (1 << 63 - rot3[c] for c in iterBits(map00)))
544        attack135[rot3[cord]][map135] = \
545            fromToRay[rot3[cord]][rot3[cord1]] |\
546            fromToRay[rot3[cord]][rot3[cord2]]
547
548MAXBITBOARD = (1 << 64) - 1
549
550for r in range(A2, A8 + 1, 8):
551    for cord in iterBits(ray00[r]):
552        attack00[cord] = dict((map >> 8, ray >> 8)
553                              for map, ray in attack00[cord - 8].items())
554
555for r in range(B1, H1 + 1):
556    for cord in iterBits(ray90[r]):
557        attack90[cord] = dict((map >> 1, ray >> 1)
558                              for map, ray in attack90[cord - 1].items())
559
560# Bottom right
561for r in range(B1, H1 + 1):
562    for cord in iterBits(ray45[r]):
563        attack45[cord] = dict((map << 8 & MAXBITBOARD, ray << 8 & MAXBITBOARD)
564                              for map, ray in attack45[cord + 8].items())
565
566# Top left
567for r in reversed(range(A8, H8)):
568    for cord in iterBits(ray45[r]):
569        attack45[cord] = dict((map >> 8, ray >> 8)
570                              for map, ray in attack45[cord - 8].items())
571
572# Top right
573for r in range(B8, H8 + 1):
574    for cord in iterBits(ray135[r]):
575        attack135[cord] = dict((map >> 8, ray >> 8)
576                               for map, ray in attack135[cord - 8].items())
577
578# Bottom left
579for r in reversed(range(A1, H1)):
580    for cord in iterBits(ray135[r]):
581        attack135[cord] = dict((map << 8 & MAXBITBOARD, ray << 8 & MAXBITBOARD)
582                               for map, ray in attack135[cord + 8].items())
583