Add forgotten files 1.4.70b
[polyglot.git] / move_gen.cpp
1 \r
2 // move_gen.cpp\r
3 \r
4 // includes\r
5 \r
6 #include "attack.h"\r
7 #include "board.h"\r
8 #include "colour.h"\r
9 #include "list.h"\r
10 #include "move.h"\r
11 #include "move_gen.h"\r
12 #include "move_legal.h"\r
13 #include "piece.h"\r
14 #include "util.h"\r
15 \r
16 // prototypes\r
17 \r
18 static void add_all_moves    (list_t * list, const board_t * board);\r
19 static void add_castle_moves (list_t * list, const board_t * board);\r
20 \r
21 static void add_pawn_move    (list_t * list, int from, int to);\r
22 \r
23 // functions\r
24 \r
25 // gen_legal_moves()\r
26 \r
27 void gen_legal_moves(list_t * list, const board_t * board) {\r
28 \r
29    ASSERT(list!=NULL);\r
30    ASSERT(board_is_ok(board));\r
31 \r
32    gen_moves(list,board);\r
33    filter_legal(list,board);\r
34 }\r
35 \r
36 // gen_moves()\r
37 \r
38 void gen_moves(list_t * list, const board_t * board) {\r
39 \r
40    ASSERT(list!=NULL);\r
41    ASSERT(board_is_ok(board));\r
42 \r
43    list_clear(list);\r
44 \r
45    add_all_moves(list,board);\r
46    if (!is_in_check(board,board->turn)) add_castle_moves(list,board);\r
47 }\r
48 \r
49 // add_all_moves()\r
50 \r
51 static void add_all_moves(list_t * list, const board_t * board) {\r
52 \r
53    int me, opp;\r
54    const uint8 * ptr;\r
55    const sint8 * ptr_inc;\r
56    int from, to;\r
57    int inc;\r
58    int piece, capture;\r
59 \r
60    ASSERT(list_is_ok(list));\r
61    ASSERT(board_is_ok(board));\r
62 \r
63    me = board->turn;\r
64    opp = colour_opp(me);\r
65 \r
66    for (ptr = board->list[me]; (from=*ptr) != SquareNone; ptr++) {\r
67 \r
68       piece = board->square[from];\r
69       ASSERT(colour_equal(piece,me));\r
70 \r
71       switch (piece_type(piece)) {\r
72 \r
73       case WhitePawn64:\r
74 \r
75          to = from + 15;\r
76          if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
77             add_pawn_move(list,from,to);\r
78          }\r
79 \r
80          to = from + 17;\r
81          if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
82             add_pawn_move(list,from,to);\r
83          }\r
84 \r
85          to = from + 16;\r
86          if (board->square[to] == Empty) {\r
87             add_pawn_move(list,from,to);\r
88             if (square_rank(from) == Rank2) {\r
89                to = from + 32;\r
90                if (board->square[to] == Empty) {\r
91                   ASSERT(!square_is_promote(to));\r
92                   list_add(list,move_make(from,to));\r
93                }\r
94             }\r
95          }\r
96 \r
97          break;\r
98 \r
99       case BlackPawn64:\r
100 \r
101          to = from - 17;\r
102          if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
103             add_pawn_move(list,from,to);\r
104          }\r
105 \r
106          to = from - 15;\r
107          if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
108             add_pawn_move(list,from,to);\r
109          }\r
110 \r
111          to = from - 16;\r
112          if (board->square[to] == Empty) {\r
113             add_pawn_move(list,from,to);\r
114             if (square_rank(from) == Rank7) {\r
115                to = from - 32;\r
116                if (board->square[to] == Empty) {\r
117                   ASSERT(!square_is_promote(to));\r
118                   list_add(list,move_make(from,to));\r
119                }\r
120             }\r
121          }\r
122 \r
123          break;\r
124 \r
125       case Knight64:\r
126 \r
127          for (ptr_inc = KnightInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
128             to = from + inc;\r
129             capture = board->square[to];\r
130             if (capture == Empty || colour_equal(capture,opp)) {\r
131                list_add(list,move_make(from,to));\r
132             }\r
133          }\r
134 \r
135          break;\r
136 \r
137       case Bishop64:\r
138 \r
139          for (ptr_inc = BishopInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
140             for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
141                list_add(list,move_make(from,to));\r
142             }\r
143             if (colour_equal(capture,opp)) {\r
144                list_add(list,move_make(from,to));\r
145             }\r
146          }\r
147 \r
148          break;\r
149 \r
150       case Rook64:\r
151 \r
152          for (ptr_inc = RookInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
153             for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
154                list_add(list,move_make(from,to));\r
155             }\r
156             if (colour_equal(capture,opp)) {\r
157                list_add(list,move_make(from,to));\r
158             }\r
159          }\r
160 \r
161          break;\r
162 \r
163       case Queen64:\r
164 \r
165          for (ptr_inc = QueenInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
166             for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
167                list_add(list,move_make(from,to));\r
168             }\r
169             if (colour_equal(capture,opp)) {\r
170                list_add(list,move_make(from,to));\r
171             }\r
172          }\r
173 \r
174          break;\r
175 \r
176       case King64:\r
177 \r
178          for (ptr_inc = KingInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
179             to = from + inc;\r
180             capture = board->square[to];\r
181             if (capture == Empty || colour_equal(capture,opp)) {\r
182                list_add(list,move_make(from,to));\r
183             }\r
184          }\r
185 \r
186          break;\r
187 \r
188       default:\r
189 \r
190          ASSERT(false);\r
191          break;\r
192       }\r
193    }\r
194 }\r
195 \r
196 // add_castle_moves()\r
197 \r
198 static void add_castle_moves(list_t * list, const board_t * board) {\r
199 \r
200    int me, opp;\r
201    int rank;\r
202    int king_from, king_to;\r
203    int rook_from, rook_to;\r
204    bool legal;\r
205    int inc;\r
206    int sq;\r
207 \r
208    ASSERT(list_is_ok(list));\r
209    ASSERT(board_is_ok(board));\r
210 \r
211    ASSERT(!is_in_check(board,board->turn));\r
212 \r
213    me = board->turn;\r
214    opp = colour_opp(me);\r
215 \r
216    rank = colour_is_white(me) ? Rank1 : Rank8;\r
217 \r
218    // h-side castling\r
219 \r
220    if (board->castle[me][SideH] != SquareNone) {\r
221 \r
222       king_from = king_pos(board,me);\r
223       king_to = square_make(FileG,rank);\r
224       rook_from = board->castle[me][SideH];\r
225       rook_to = square_make(FileF,rank);\r
226 \r
227       ASSERT(square_rank(king_from)==rank);\r
228       ASSERT(square_rank(rook_from)==rank);\r
229       ASSERT(board->square[king_from]==(King64|me)); // HACK\r
230       ASSERT(board->square[rook_from]==(Rook64|me)); // HACK\r
231       ASSERT(rook_from>king_from);\r
232 \r
233       legal = true;\r
234 \r
235       if (king_to != king_from) {\r
236 \r
237          inc = (king_to > king_from) ? +1 : -1;\r
238 \r
239          for (sq = king_from+inc; true; sq += inc) {\r
240 \r
241             if (sq != rook_from && board->square[sq] != Empty) legal = false;\r
242             if (is_attacked(board,sq,opp)) legal = false;\r
243 \r
244             if (sq == king_to) break;\r
245          }\r
246       }\r
247 \r
248       if (rook_to != rook_from) {\r
249 \r
250          inc = (rook_to > rook_from) ? +1 : -1;\r
251 \r
252          for (sq = rook_from+inc; true; sq += inc) {\r
253             if (sq != king_from && board->square[sq] != Empty) legal = false;\r
254             if (sq == rook_to) break;\r
255          }\r
256       }\r
257 \r
258       if (legal) list_add(list,move_make(king_from,rook_from));\r
259    }\r
260 \r
261    // a-side castling\r
262 \r
263    if (board->castle[me][SideA] != SquareNone) {\r
264 \r
265       king_from = king_pos(board,me);\r
266       king_to = square_make(FileC,rank);\r
267       rook_from = board->castle[me][SideA];\r
268       rook_to = square_make(FileD,rank);\r
269 \r
270       ASSERT(square_rank(king_from)==rank);\r
271       ASSERT(square_rank(rook_from)==rank);\r
272       ASSERT(board->square[king_from]==(King64|me)); // HACK\r
273       ASSERT(board->square[rook_from]==(Rook64|me)); // HACK\r
274       ASSERT(rook_from<king_from);\r
275 \r
276       legal = true;\r
277 \r
278       if (king_to != king_from) {\r
279 \r
280          inc = (king_to > king_from) ? +1 : -1;\r
281 \r
282          for (sq = king_from+inc; true; sq += inc) {\r
283 \r
284             if (sq != rook_from && board->square[sq] != Empty) legal = false;\r
285             if (is_attacked(board,sq,opp)) legal = false;\r
286 \r
287             if (sq == king_to) break;\r
288          }\r
289       }\r
290 \r
291       if (rook_to != rook_from) {\r
292 \r
293          inc = (rook_to > rook_from) ? +1 : -1;\r
294 \r
295          for (sq = rook_from+inc; true; sq += inc) {\r
296             if (sq != king_from && board->square[sq] != Empty) legal = false;\r
297             if (sq == rook_to) break;\r
298          }\r
299       }\r
300 \r
301       if (legal) list_add(list,move_make(king_from,rook_from));\r
302    }\r
303 }\r
304 \r
305 // add_pawn_move()\r
306 \r
307 static void add_pawn_move(list_t * list, int from, int to) {\r
308 \r
309    int move;\r
310 \r
311    ASSERT(list_is_ok(list));\r
312    ASSERT(square_is_ok(from));\r
313    ASSERT(square_is_ok(to));\r
314 \r
315    move = move_make(from,to);\r
316 \r
317    if (square_is_promote(to)) {\r
318       list_add(list,move|MovePromoteKnight);\r
319       list_add(list,move|MovePromoteBishop);\r
320       list_add(list,move|MovePromoteRook);\r
321       list_add(list,move|MovePromoteQueen);\r
322    } else {\r
323       list_add(list,move);\r
324    }\r
325 }\r
326 \r
327 // end of move_gen.cpp\r
328 \r