-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathmove.hpp
More file actions
142 lines (113 loc) · 4.26 KB
/
move.hpp
File metadata and controls
142 lines (113 loc) · 4.26 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once
#include "common.hpp"
#include "square.hpp"
#include "util/types.hpp"
#include <optional>
#include <string_view>
namespace Clockwork {
struct Position;
static_assert(static_cast<u16>(PieceType::Knight) == 2);
enum class MoveFlags : u16 {
Normal = 0b0000 << 12,
Castle = 0b0001 << 12,
CaptureBit = 0b0100 << 12,
EnPassant = 0b0110 << 12,
PromotionBit = 0b1000 << 12,
PromoKnight = (0b1000 | (static_cast<u16>(PieceType::Knight) - 2)) << 12,
PromoBishop = (0b1000 | (static_cast<u16>(PieceType::Bishop) - 2)) << 12,
PromoRook = (0b1000 | (static_cast<u16>(PieceType::Rook) - 2)) << 12,
PromoQueen = (0b1000 | (static_cast<u16>(PieceType::Queen) - 2)) << 12,
PromoCapture = 0b1100 << 12,
PromoKnightCapture = (0b1100 | (static_cast<u16>(PieceType::Knight) - 2)) << 12,
PromoBishopCapture = (0b1100 | (static_cast<u16>(PieceType::Bishop) - 2)) << 12,
PromoRookCapture = (0b1100 | (static_cast<u16>(PieceType::Rook) - 2)) << 12,
PromoQueenCapture = (0b1100 | (static_cast<u16>(PieceType::Queen) - 2)) << 12,
};
inline std::optional<MoveFlags>
build_move_flags(bool castle, bool en_passant, bool capture, PieceType promo) {
using enum MoveFlags;
if (castle) {
return Castle;
}
if (en_passant) {
return EnPassant;
}
u16 flags = 0;
if (capture) {
flags |= static_cast<u16>(CaptureBit);
}
if (promo != PieceType::None) {
if (promo < PieceType::Knight || promo > PieceType::Queen) {
return std::nullopt;
}
flags |= (static_cast<u16>(promo) - 2) << 12;
}
return static_cast<MoveFlags>(flags);
}
struct Move {
u16 raw = 0;
constexpr Move() = default;
constexpr Move(Square from, Square to, MoveFlags flags = MoveFlags::Normal) {
raw = static_cast<u16>(from.raw | (to.raw << 6) | static_cast<u16>(flags));
}
static constexpr Move none() {
return {};
}
[[nodiscard]] constexpr Square from() const {
return Square{static_cast<u8>(raw & 0x3F)};
}
[[nodiscard]] constexpr Square to() const {
return Square{static_cast<u8>((raw >> 6) & 0x3F)};
}
[[nodiscard]] constexpr u16 from_to() const {
return raw & 0xFFF;
}
[[nodiscard]] constexpr MoveFlags flags() const {
return MoveFlags{static_cast<u16>(raw & (0xF << 12))};
}
[[nodiscard]] constexpr bool is_capture() const {
return raw & static_cast<u16>(MoveFlags::CaptureBit);
}
[[nodiscard]] constexpr bool is_promotion() const {
return raw & static_cast<u16>(MoveFlags::PromotionBit);
}
[[nodiscard]] constexpr bool is_castle() const {
return flags() == MoveFlags::Castle;
}
[[nodiscard]] constexpr bool is_en_passant() const {
return flags() == MoveFlags::EnPassant;
}
[[nodiscard]] constexpr std::optional<PieceType> promo() const {
if (!is_promotion()) {
return std::nullopt;
}
static_assert(static_cast<u16>(PieceType::Knight) == 2);
return static_cast<PieceType>(((raw >> 12) & 0b0011) + 2);
}
// Parse UCI move notation
// All legal moves will be parsed, but a successfully parsed move is not guaranteed to be legal.
static std::optional<Move> parse(std::string_view str, const Position& context);
// Parse Standard Algebraic notation (SAN) moves
// All legal moves will be parsed, but a successfully parsed move is not guaranteed to be legal.
static std::optional<Move> parseSan(std::string_view san, const Position& context);
[[nodiscard]] constexpr bool operator==(const Move& other) const = default;
[[nodiscard]] constexpr bool operator!=(const Move& other) const = default;
friend std::ostream& operator<<(std::ostream& os, Move mv) {
os << mv.from();
if (!g_frc && mv.flags() == MoveFlags::Castle) {
if (mv.to().file() < mv.from().file()) {
os << 'c';
} else {
os << 'g';
}
os << mv.to().rank() + 1;
} else {
os << mv.to();
}
if (auto promo = mv.promo()) {
os << piece_char(*promo);
}
return os;
}
};
}