summaryrefslogtreecommitdiff
path: root/src/search/pawn_moves.c
blob: f015e7d7f860bbf1e0b6f7cb792c7d0af16700ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "../search.h"
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>

bitboard_t get_white_pawn_forwardmoves(moves_t* moves, position_t position) {
  bitboard_t enemy_bitboard = blacks(position);
  bitboard_t friendly_pieces =
    position.bitboards[WHITE_KING] |
    position.bitboards[WHITE_QUEEN] |
    position.bitboards[WHITE_ROOK] |
    position.bitboards[WHITE_BISHOP] |
    position.bitboards[WHITE_KNIGHT] |
    position.bitboards[WHITE_PAWN];
  bitboard_t friendly_pawns = position.bitboards[WHITE_PAWN];
  bitboard_t y = friendly_pieces | enemy_bitboard;
  bitboard_t x = ~((friendly_pawns << 8) & y) & (friendly_pawns << 8);
  bitboard_t first_move_x = x & BITMASK_RANK_C;

  first_move_x |= (first_move_x << 8) & (~y);
  x |= first_move_x;

  return x;
}
bitboard_t get_black_pawn_forwardmoves(moves_t* moves, position_t position) {
  bitboard_t enemy_bitboard = whites(position);
  bitboard_t friendly_pieces =
    position.bitboards[BLACK_KING] |
    position.bitboards[BLACK_QUEEN] |
    position.bitboards[BLACK_ROOK] |
    position.bitboards[BLACK_BISHOP] |
    position.bitboards[BLACK_KNIGHT] |
    position.bitboards[BLACK_PAWN];
  bitboard_t friendly_pawns = position.bitboards[BLACK_PAWN];
  bitboard_t y = friendly_pieces | enemy_bitboard;
  bitboard_t x = ~((friendly_pawns << 8) & y) & (friendly_pawns << 8);
  bitboard_t first_move_x = x | BITMASK_RANK_F;

  first_move_x |= (first_move_x >> 8) & (~y);
  x |= first_move_x;

  return x;
}

void get_pawn_moves(moves_t* moves, position_t position) {
  assert_valid_position(position);

  bitboard_t forward_moves;
  bitboard_t friendly_pawns;
  if (position.turn == WHITE_TURN) {
    forward_moves = get_white_pawn_forwardmoves(moves, position);
    friendly_pawns = position.bitboards[WHITE_PAWN];
  } else {
    forward_moves = get_black_pawn_forwardmoves(moves, position);
    friendly_pawns = position.bitboards[BLACK_PAWN];
  }

  bitboard_t column_masks[8] = {
    BITMASK_COLM_1,
    BITMASK_COLM_2,
    BITMASK_COLM_3,
    BITMASK_COLM_4,
    BITMASK_COLM_5,
    BITMASK_COLM_6,
    BITMASK_COLM_7,
    BITMASK_COLM_8,
  };

  for (int i = 0; i < 8; i++) {
    bitboard_t item = column_masks[i] & forward_moves;
    bitboard_t pawns = column_masks[i] & friendly_pawns;

    int from = __builtin_ctzll(pawns);
    pawns &= (pawns - 1);
    int next_from = __builtin_ctzll(pawns);
    while (item) {
      int to = __builtin_ctzll(item);
      if (to > next_from) {
        from = next_from;
        pawns &= (pawns - 1);
        next_from = __builtin_ctzll(pawns);
      }
      item &= (item - 1);
      add_move(moves, from, to);
    }
  }

  if (position.passantable_column != 0) {
    bitboard_t PASSANT_RANK;
    int rank_shift;
    int from_shift;
    if (position.turn == WHITE_TURN) {
      PASSANT_RANK = BITMASK_RANK_E;
      rank_shift = 40;
      from_shift = -9;
    } else {
      PASSANT_RANK = BITMASK_RANK_D;
      from_shift = 7;
      rank_shift = 16;
    }

    int left = 0, right = 0;
    if (position.passantable_column > 1) left = position.passantable_column - 1;
    if (position.passantable_column < 8) right = position.passantable_column + 1;
    if (left != 0) {
      bitboard_t MASK = column_masks[left - 1] & friendly_pawns & PASSANT_RANK;
      if (MASK != 0) {
        add_move(
          moves,
          left + rank_shift + from_shift,
          position.passantable_column + rank_shift - 1
        );
      }
    }
    if (right != 0) {
      bitboard_t MASK = column_masks[right - 1] & friendly_pawns & PASSANT_RANK;
      if (MASK != 0) {
        add_move(
          moves,
          right + rank_shift + from_shift,
          position.passantable_column + rank_shift - 1
        );
      }
    }
  }
}