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