summaryrefslogtreecommitdiff
path: root/src/engine/moves.c
blob: 56bb47d9695ceb35623ce5261cef0cb538c53360 (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
#include "moves.h"
#include "bitboard.h"

#include "moves/vec.c"
#include "moves/king.c"
#include "moves/knight.c"
#include "moves/pawn.c"
#include "moves/rook.c"
#include "moves/bishop.c"
#include "moves/queen.c"

#include <assert.h>

void get_moves(moves_t* moves, position_t position) {
  get_pawn_moves(moves, position);
  get_knight_moves(moves, position);
  get_king_moves(moves, position);
  get_rook_moves(moves, position);
  get_bishop_moves(moves, position);
  get_queen_moves(moves, position);
}

int find_piece_on_square(position_t* p, int square) {
  if ((p->bitboards[WHITE_KING]   >> square) & 1) return WHITE_KING;
  if ((p->bitboards[WHITE_QUEEN]  >> square) & 1) return WHITE_QUEEN;
  if ((p->bitboards[WHITE_ROOK]   >> square) & 1) return WHITE_ROOK;
  if ((p->bitboards[WHITE_BISHOP] >> square) & 1) return WHITE_BISHOP;
  if ((p->bitboards[WHITE_KNIGHT] >> square) & 1) return WHITE_KNIGHT;
  if ((p->bitboards[WHITE_PAWN]   >> square) & 1) return WHITE_PAWN;
  if ((p->bitboards[BLACK_KING]   >> square) & 1) return BLACK_KING;
  if ((p->bitboards[BLACK_QUEEN]  >> square) & 1) return BLACK_QUEEN;
  if ((p->bitboards[BLACK_ROOK]   >> square) & 1) return BLACK_ROOK;
  if ((p->bitboards[BLACK_BISHOP] >> square) & 1) return BLACK_BISHOP;
  if ((p->bitboards[BLACK_KNIGHT] >> square) & 1) return BLACK_KNIGHT;
  if ((p->bitboards[BLACK_PAWN]   >> square) & 1) return BLACK_PAWN;
  assert(0);
}

void position_make_move(position_t* position, move_t* move) {
  if (move->flags & MOVE_LONG_CASTLE) {
    if (position->turn == WHITE_TURN) {
      assert(position->bitboards[WHITE_KING] == 16);
      assert((position->bitboards[WHITE_ROOK] >> 0) & 1);
    
      position->bitboards[WHITE_KING] = 2;
      position->bitboards[WHITE_ROOK] += 3;
    } else if (position->turn == BLACK_TURN) {
      assert(position->bitboards[BLACK_KING] == 1152921504606846976ULL);
      assert((position->bitboards[BLACK_ROOK] >> 56) & 1);

      position->bitboards[BLACK_KING] = 144115188075855872ULL;
      position->bitboards[WHITE_ROOK] &= ~((bitboard_t)1 << 56);
      position->bitboards[WHITE_ROOK] |= (bitboard_t)1 << 58;
    }
    return;
  }
  if (move->flags & MOVE_SHORT_CASTLE) {
    if (position->turn == WHITE_TURN) {
      assert(position->bitboards[WHITE_KING] == 16);
      assert((position->bitboards[WHITE_ROOK] >> 7) & 1);

      position->bitboards[WHITE_KING] = 64;
      position->bitboards[WHITE_ROOK] &= ~((bitboard_t)1 << 7);
      position->bitboards[WHITE_ROOK] |= (bitboard_t)1 << 5;
    } else if (position->turn == BLACK_TURN) {
      assert(position->bitboards[BLACK_KING] == 1152921504606846976ULL);
      assert((position->bitboards[BLACK_ROOK] >> 63) & 1);

      position->bitboards[WHITE_KING] = 4611686018427387904ULL;
      position->bitboards[WHITE_ROOK] &= ~((bitboard_t)1 << 63);
      position->bitboards[WHITE_ROOK] |= (bitboard_t)1 << 61;
    }
    return;
  }

  int piece_type = find_piece_on_square(position, move->from);
  position->bitboards[piece_type] &= ~(1 << move->from);
  if (move->flags & MOVE_PROMOTE_Q) {
    int q_type = position->turn == WHITE_TURN ? WHITE_QUEEN : BLACK_QUEEN;
    position->bitboards[q_type] |= 1 << move->to;
    return;
  }
  if (move->flags & MOVE_PROMOTE_R) {
    int q_type = position->turn == WHITE_TURN ? WHITE_ROOK : BLACK_ROOK;
    position->bitboards[q_type] |= 1 << move->to;
    return;
  }
  if (move->flags & MOVE_PROMOTE_B) {
    int q_type = position->turn == WHITE_TURN ? WHITE_BISHOP : BLACK_BISHOP;
    position->bitboards[q_type] |= 1 << move->to;
    return;
  }
  if (move->flags & MOVE_PROMOTE_N) {
    int q_type = position->turn == WHITE_TURN ? WHITE_KNIGHT : BLACK_KNIGHT;
    position->bitboards[q_type] |= 1 << move->to;
    return;
  }
  if (move->flags & MOVE_EN_PASSANT) {
    int target_sqr;
    if (position->turn == WHITE_TURN) target_sqr = move->to - 8;
    else target_sqr = move->to + 8;
    
    int to_remove_piece_type = find_piece_on_square(position, target_sqr);
    position->bitboards[piece_type] |= 1 << move->to;
    position->bitboards[to_remove_piece_type] &= ~(1 << target_sqr);
    return;
  }

  if (move->flags & MOVE_CAPTURE) {
    int to_remove_piece_type = find_piece_on_square(position, move->to);
    position->bitboards[to_remove_piece_type] &= ~(1 << move->to);
  }

  // i can't put this above the find_piece_on_square function, because there
  // is a possibility that piece_type would resolve to the piece that is being
  // moved, which would mess with the ~(1 << to_sqr)
  position->bitboards[piece_type] |= 1 << move->to;
}