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