1 
2 // attack.cpp
3 
4 // includes
5 
6 #include "board.h"
7 #include "colour.h"
8 #include "move.h"
9 #include "attack.h"
10 #include "piece.h"
11 #include "util.h"
12 
13 // macros
14 
15 #define DELTA_INC(delta)  (DeltaInc[128+(delta)])
16 #define DELTA_MASK(delta) (DeltaMask[128+(delta)])
17 
18 // "constants"
19 
20 const sint8 KnightInc[8+1] = {
21    -33, -31, -18, -14, +14, +18, +31, +33, 0
22 };
23 
24 const sint8 BishopInc[4+1] = {
25    -17, -15, +15, +17, 0
26 };
27 
28 const sint8 RookInc[4+1] = {
29    -16, -1, +1, +16, 0
30 };
31 
32 const sint8 QueenInc[8+1] = {
33    -17, -16, -15, -1, +1, +15, +16, +17, 0
34 };
35 
36 const sint8 KingInc[8+1] = {
37    -17, -16, -15, -1, +1, +15, +16, +17, 0
38 };
39 
40 // variables
41 
42 static sint8 DeltaInc[256];
43 static uint8 DeltaMask[256];
44 
45 // prototypes
46 
47 // static bool delta_is_ok (int delta);
48 // static bool inc_is_ok   (int inc);
49 
50 // functions
51 
52 // attack_init()
53 
attack_init()54 void attack_init() {
55 
56    int delta;
57    int dir, inc, dist;
58 
59    for (delta = -128; delta < +128; delta++) {
60       DeltaInc[128+delta] = IncNone;
61       DeltaMask[128+delta] = 0;
62    }
63 
64    DeltaMask[128-17] |= BlackPawnFlag;
65    DeltaMask[128-15] |= BlackPawnFlag;
66 
67    DeltaMask[128+15] |= WhitePawnFlag;
68    DeltaMask[128+17] |= WhitePawnFlag;
69 
70    for (dir = 0; dir < 8; dir++) {
71       delta = KnightInc[dir];
72       ASSERT(delta_is_ok(delta));
73       DeltaMask[128+delta] |= KnightFlag;
74    }
75 
76    for (dir = 0; dir < 4; dir++) {
77       inc = BishopInc[dir];
78       ASSERT(inc!=IncNone);
79       for (dist = 1; dist < 8; dist++) {
80          delta = inc*dist;
81          ASSERT(delta_is_ok(delta));
82          ASSERT(DeltaInc[128+delta]==IncNone);
83          DeltaInc[128+delta] = inc;
84          DeltaMask[128+delta] |= BishopFlag;
85       }
86    }
87 
88    for (dir = 0; dir < 4; dir++) {
89       inc = RookInc[dir];
90       ASSERT(inc!=IncNone);
91       for (dist = 1; dist < 8; dist++) {
92          delta = inc*dist;
93          ASSERT(delta_is_ok(delta));
94          ASSERT(DeltaInc[128+delta]==IncNone);
95          DeltaInc[128+delta] = inc;
96          DeltaMask[128+delta] |= RookFlag;
97       }
98    }
99 
100    for (dir = 0; dir < 8; dir++) {
101       delta = KingInc[dir];
102       ASSERT(delta_is_ok(delta));
103       DeltaMask[128+delta] |= KingFlag;
104    }
105 }
106 
107 // delta_is_ok()
108 
109 // static bool delta_is_ok(int delta) {
110 //
111 //    if (delta < -119 || delta > +119) return false;
112 //
113 //    return true;
114 // }
115 
116 // inc_is_ok()
117 
118 // static bool inc_is_ok(int inc) {
119 //
120 //    int dir;
121 //
122 //    for (dir = 0; dir < 8; dir++) {
123 //       if (KingInc[dir] == inc) return true;
124 //    }
125 //
126 //    return false;
127 // }
128 
129 // is_in_check()
130 
is_in_check(const board_t * board,int colour)131 bool is_in_check(const board_t * board, int colour) {
132 
133    ASSERT(board_is_ok(board));
134    ASSERT(colour_is_ok(colour));
135 
136    return is_attacked(board,king_pos(board,colour),colour_opp(colour));
137 }
138 
139 // is_attacked()
140 
is_attacked(const board_t * board,int to,int colour)141 bool is_attacked(const board_t * board, int to, int colour) {
142 
143    const uint8 * ptr;
144    int from, piece;
145 
146    ASSERT(board_is_ok(board));
147    ASSERT(square_is_ok(to));
148    ASSERT(colour_is_ok(colour));
149 
150    for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) {
151 
152       piece = board->square[from];
153       ASSERT(colour_equal(piece,colour));
154 
155       if (piece_attack(board,piece,from,to)) return true;
156    }
157 
158    return false;
159 }
160 
161 // piece_attack()
162 
piece_attack(const board_t * board,int piece,int from,int to)163 bool piece_attack(const board_t * board, int piece, int from, int to) {
164 
165    int delta;
166    int inc, sq;
167 
168    ASSERT(board_is_ok(board));
169    ASSERT(piece_is_ok(piece));
170    ASSERT(square_is_ok(from));
171    ASSERT(square_is_ok(to));
172 
173    delta = to - from;
174    ASSERT(delta_is_ok(delta));
175 
176    if ((piece & DELTA_MASK(delta)) == 0) return false; // no pseudo-attack
177 
178    if (!piece_is_slider(piece)) return true;
179 
180    inc = DELTA_INC(delta);
181    ASSERT(inc_is_ok(inc));
182 
183    for (sq = from+inc; sq != to; sq += inc) {
184       ASSERT(square_is_ok(sq));
185       if (board->square[sq] != Empty) return false; // blocker
186    }
187 
188    return true;
189 }
190 
191 // is_pinned()
192 
is_pinned(const board_t * board,int from,int to,int colour)193 bool is_pinned(const board_t * board, int from, int to, int colour) {
194 
195    int king;
196    int inc;
197    int sq, piece;
198 
199    ASSERT(board!=NULL);
200    ASSERT(square_is_ok(from));
201    ASSERT(square_is_ok(to));
202    ASSERT(colour_is_ok(colour));
203 
204    king = king_pos(board,colour);
205 
206    inc = DELTA_INC(king-from);
207    if (inc == IncNone) return false; // not a line
208 
209    sq = from;
210    do sq += inc; while (board->square[sq] == Empty);
211 
212    if (sq != king) return false; // blocker
213 
214    sq = from;
215    do sq -= inc; while ((piece=board->square[sq]) == Empty);
216 
217    return square_is_ok(sq)
218        && (piece & DELTA_MASK(king-sq)) != 0
219        && piece_colour(piece) == colour_opp(colour)
220        && DELTA_INC(king-to) != inc;
221 }
222 
223 // end of attack.cpp
224 
225