version 1.4.30b
[polyglot.git] / move_gen.c
diff --git a/move_gen.c b/move_gen.c
new file mode 100644 (file)
index 0000000..2d45564
--- /dev/null
@@ -0,0 +1,328 @@
+\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