--- /dev/null
+\r
+// move_gen.c\r
+\r
+// includes\r
+\r
+#include "attack.h"\r
+#include "board.h"\r
+#include "colour.h"\r
+#include "list.h"\r
+#include "move.h"\r
+#include "move_gen.h"\r
+#include "move_legal.h"\r
+#include "piece.h"\r
+#include "util.h"\r
+\r
+// prototypes\r
+\r
+static void add_all_moves (list_t * list, const board_t * board);\r
+static void add_castle_moves (list_t * list, const board_t * board);\r
+\r
+static void add_pawn_move (list_t * list, int from, int to);\r
+\r
+// functions\r
+\r
+// gen_legal_moves()\r
+\r
+void gen_legal_moves(list_t * list, const board_t * board) {\r
+\r
+ ASSERT(list!=NULL);\r
+ ASSERT(board_is_ok(board));\r
+\r
+ gen_moves(list,board);\r
+ filter_legal(list,board);\r
+}\r
+\r
+// gen_moves()\r
+\r
+void gen_moves(list_t * list, const board_t * board) {\r
+\r
+ ASSERT(list!=NULL);\r
+ ASSERT(board_is_ok(board));\r
+\r
+ list_clear(list);\r
+\r
+ add_all_moves(list,board);\r
+ if (!is_in_check(board,board->turn)) add_castle_moves(list,board);\r
+}\r
+\r
+// add_all_moves()\r
+\r
+static void add_all_moves(list_t * list, const board_t * board) {\r
+\r
+ int me, opp;\r
+ const uint8 * ptr;\r
+ const sint8 * ptr_inc;\r
+ int from, to;\r
+ int inc;\r
+ int piece, capture;\r
+\r
+ ASSERT(list_is_ok(list));\r
+ ASSERT(board_is_ok(board));\r
+\r
+ me = board->turn;\r
+ opp = colour_opp(me);\r
+\r
+ for (ptr = board->list[me]; (from=*ptr) != SquareNone; ptr++) {\r
+\r
+ piece = board->square[from];\r
+ ASSERT(colour_equal(piece,me));\r
+\r
+ switch (piece_type(piece)) {\r
+\r
+ case WhitePawn64:\r
+\r
+ to = from + 15;\r
+ if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
+ add_pawn_move(list,from,to);\r
+ }\r
+\r
+ to = from + 17;\r
+ if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
+ add_pawn_move(list,from,to);\r
+ }\r
+\r
+ to = from + 16;\r
+ if (board->square[to] == Empty) {\r
+ add_pawn_move(list,from,to);\r
+ if (square_rank(from) == Rank2) {\r
+ to = from + 32;\r
+ if (board->square[to] == Empty) {\r
+ ASSERT(!square_is_promote(to));\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case BlackPawn64:\r
+\r
+ to = from - 17;\r
+ if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
+ add_pawn_move(list,from,to);\r
+ }\r
+\r
+ to = from - 15;\r
+ if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
+ add_pawn_move(list,from,to);\r
+ }\r
+\r
+ to = from - 16;\r
+ if (board->square[to] == Empty) {\r
+ add_pawn_move(list,from,to);\r
+ if (square_rank(from) == Rank7) {\r
+ to = from - 32;\r
+ if (board->square[to] == Empty) {\r
+ ASSERT(!square_is_promote(to));\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case Knight64:\r
+\r
+ for (ptr_inc = KnightInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
+ to = from + inc;\r
+ capture = board->square[to];\r
+ if (capture == Empty || colour_equal(capture,opp)) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case Bishop64:\r
+\r
+ for (ptr_inc = BishopInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
+ for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ if (colour_equal(capture,opp)) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case Rook64:\r
+\r
+ for (ptr_inc = RookInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
+ for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ if (colour_equal(capture,opp)) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case Queen64:\r
+\r
+ for (ptr_inc = QueenInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
+ for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ if (colour_equal(capture,opp)) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case King64:\r
+\r
+ for (ptr_inc = KingInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
+ to = from + inc;\r
+ capture = board->square[to];\r
+ if (capture == Empty || colour_equal(capture,opp)) {\r
+ list_add(list,move_make(from,to));\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ ASSERT(FALSE);\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+// add_castle_moves()\r
+\r
+static void add_castle_moves(list_t * list, const board_t * board) {\r
+\r
+ int me, opp;\r
+ int rank;\r
+ int king_from, king_to;\r
+ int rook_from, rook_to;\r
+ bool legal;\r
+ int inc;\r
+ int sq;\r
+\r
+ ASSERT(list_is_ok(list));\r
+ ASSERT(board_is_ok(board));\r
+\r
+ ASSERT(!is_in_check(board,board->turn));\r
+\r
+ me = board->turn;\r
+ opp = colour_opp(me);\r
+\r
+ rank = colour_is_white(me) ? Rank1 : Rank8;\r
+\r
+ // h-side castling\r
+\r
+ if (board->castle[me][SideH] != SquareNone) {\r
+\r
+ king_from = king_pos(board,me);\r
+ king_to = square_make(FileG,rank);\r
+ rook_from = board->castle[me][SideH];\r
+ rook_to = square_make(FileF,rank);\r
+\r
+ ASSERT(square_rank(king_from)==rank);\r
+ ASSERT(square_rank(rook_from)==rank);\r
+ ASSERT(board->square[king_from]==(King64|me)); // HACK\r
+ ASSERT(board->square[rook_from]==(Rook64|me)); // HACK\r
+ ASSERT(rook_from>king_from);\r
+\r
+ legal = TRUE;\r
+\r
+ if (king_to != king_from) {\r
+\r
+ inc = (king_to > king_from) ? +1 : -1;\r
+\r
+ for (sq = king_from+inc; TRUE; sq += inc) {\r
+\r
+ if (sq != rook_from && board->square[sq] != Empty) legal = FALSE;\r
+ if (is_attacked(board,sq,opp)) legal = FALSE;\r
+\r
+ if (sq == king_to) break;\r
+ }\r
+ }\r
+\r
+ if (rook_to != rook_from) {\r
+\r
+ inc = (rook_to > rook_from) ? +1 : -1;\r
+\r
+ for (sq = rook_from+inc; TRUE; sq += inc) {\r
+ if (sq != king_from && board->square[sq] != Empty) legal = FALSE;\r
+ if (sq == rook_to) break;\r
+ }\r
+ }\r
+\r
+ if (legal) list_add(list,move_make(king_from,rook_from));\r
+ }\r
+\r
+ // a-side castling\r
+\r
+ if (board->castle[me][SideA] != SquareNone) {\r
+\r
+ king_from = king_pos(board,me);\r
+ king_to = square_make(FileC,rank);\r
+ rook_from = board->castle[me][SideA];\r
+ rook_to = square_make(FileD,rank);\r
+\r
+ ASSERT(square_rank(king_from)==rank);\r
+ ASSERT(square_rank(rook_from)==rank);\r
+ ASSERT(board->square[king_from]==(King64|me)); // HACK\r
+ ASSERT(board->square[rook_from]==(Rook64|me)); // HACK\r
+ ASSERT(rook_from<king_from);\r
+\r
+ legal = TRUE;\r
+\r
+ if (king_to != king_from) {\r
+\r
+ inc = (king_to > king_from) ? +1 : -1;\r
+\r
+ for (sq = king_from+inc; TRUE; sq += inc) {\r
+\r
+ if (sq != rook_from && board->square[sq] != Empty) legal = FALSE;\r
+ if (is_attacked(board,sq,opp)) legal = FALSE;\r
+\r
+ if (sq == king_to) break;\r
+ }\r
+ }\r
+\r
+ if (rook_to != rook_from) {\r
+\r
+ inc = (rook_to > rook_from) ? +1 : -1;\r
+\r
+ for (sq = rook_from+inc; TRUE; sq += inc) {\r
+ if (sq != king_from && board->square[sq] != Empty) legal = FALSE;\r
+ if (sq == rook_to) break;\r
+ }\r
+ }\r
+\r
+ if (legal) list_add(list,move_make(king_from,rook_from));\r
+ }\r
+}\r
+\r
+// add_pawn_move()\r
+\r
+static void add_pawn_move(list_t * list, int from, int to) {\r
+\r
+ int move;\r
+\r
+ ASSERT(list_is_ok(list));\r
+ ASSERT(square_is_ok(from));\r
+ ASSERT(square_is_ok(to));\r
+\r
+ move = move_make(from,to);\r
+\r
+ if (square_is_promote(to)) {\r
+ list_add(list,move|MovePromoteKnight);\r
+ list_add(list,move|MovePromoteBishop);\r
+ list_add(list,move|MovePromoteRook);\r
+ list_add(list,move|MovePromoteQueen);\r
+ } else {\r
+ list_add(list,move);\r
+ }\r
+}\r
+\r
+// end of move_gen.cpp\r
+\r