Line data Source code
1 : /*
2 : * Copyright (C) 2014 Fulvio Benini
3 :
4 : * This file is part of Scid (Shane's Chess Information Database).
5 : *
6 : * Scid is free software: you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation.
9 : *
10 : * Scid is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with Scid. If not, see <http://www.gnu.org/licenses/>.
17 : */
18 :
19 : #ifndef FULLMOVE_H
20 : #define FULLMOVE_H
21 :
22 : #include "common.h"
23 : #include <string>
24 :
25 : class FullMove {
26 : // ** Lower 16 bits are compatible with Stockfish's Move **
27 : // bits 0- 5: destination square (from 0 to 63)
28 : // bits 6-11: origin square (from 0 to 63)
29 : // bits 12-13: promotion piece type -2 (from QUEEN-2 to KNIGHT-2)
30 : // bits 14-15: special move flag: promotion (1), en passant (2), castling (3)
31 :
32 : // ** Info for undoing the move **
33 : // bits 16-17: castling flags - TODO
34 : // bits 18-20: enpassant file - TODO
35 : // bits 21-23: captured pieceT
36 :
37 : // ** Info for direct SAN conversion **
38 : // bits 24-26: moving pieceT
39 : // bit 27: black to move
40 : // bit 28: ambiguous move, insert from fyle
41 : // bit 29: ambiguous move, insert from rank
42 : // bit 30: check
43 :
44 : // ** TODO: Use this flag to embed tags, variations, etc.. in a move stream
45 : // bit 31: special flag
46 : uint32_t m_;
47 :
48 : public:
49 6902 : constexpr FullMove(uint32_t m = 0) : m_(m){};
50 :
51 1 : FullMove(colorT c, squareT kingSq, squareT rookSq)
52 : // Castle: encoding as king to rook allows the undoing of chess360 moves
53 1 : : FullMove(c, kingSq, rookSq, KING) {
54 1 : m_ |= (3 << 14);
55 1 : }
56 :
57 34 : FullMove(colorT c, squareT from, squareT to, pieceT pt) {
58 34 : m_ = to | (from << 6) | (pt << 24) | (c << 27);
59 34 : }
60 :
61 2425730 : operator bool() const { return m_ != 0; }
62 0 : bool operator!=(const FullMove& f) const { return m_ != f.m_; }
63 39 : bool isPromo() const { return (m_ & (3 << 14)) == (1 << 14); }
64 : bool isEnpassant() const { return (m_ & (3 << 14)) == (2 << 14); }
65 34 : bool isCastle() const { return (m_ & (3 << 14)) == (3 << 14); }
66 234375 : squareT getTo() const { return m_ & 0x3F; }
67 2418832 : squareT getFrom() const { return (m_ >> 6) & 0x3F; }
68 67 : pieceT getPiece() const { return (m_ >> 24) & 0x07; }
69 34 : colorT getColor() const { return (m_ >> 27 & 1) ? BLACK : WHITE; }
70 10 : pieceT getPromo() const { return ((m_ >> 12) & 0x03) +2; }
71 33 : pieceT getCaptured() const { return (m_ >> 21) & 0x07; }
72 34 : std::string getSAN(colorT* toMove = 0) const {
73 68 : std::string res;
74 34 : if (toMove) *toMove = getColor();
75 34 : squareT to = getTo();
76 34 : squareT from = getFrom();
77 34 : if (to == 0 && from == 0) return "--";
78 34 : if (isCastle()) {
79 1 : res = (to > from) ? "O-O" : "O-O-O";
80 1 : bool check = (m_ >> 30) & 1;
81 1 : if (check)
82 1 : res += "+";
83 1 : return res;
84 : }
85 33 : bool fromFyle = (m_ >> 28) & 1;
86 33 : bool fromRank = (m_ >> 29) & 1;
87 33 : bool check = (m_ >> 30) & 1;
88 33 : bool capture = (getCaptured() != 0);
89 :
90 33 : switch (getPiece()) {
91 4 : case BISHOP: res += "B"; break;
92 7 : case KNIGHT: res += "N"; break;
93 7 : case ROOK: res += "R"; break;
94 9 : case QUEEN: res += "Q"; break;
95 0 : case KING: res += "K"; break;
96 6 : default: //PAWN
97 6 : if (capture) res += 'a' + (from % 8);
98 : }
99 33 : if (fromFyle) res += 'a' + (from % 8);
100 33 : if (fromRank) res += '1' + (from / 8);
101 33 : if (capture) res += "x";
102 33 : res += 'a' + (to % 8);
103 33 : res += '1' + (to / 8);
104 33 : if (isPromo()) {
105 5 : switch (getPromo()) {
106 1 : case BISHOP: res += "=B"; break;
107 0 : case KNIGHT: res += "=N"; break;
108 1 : case ROOK: res += "=R"; break;
109 3 : case QUEEN: res += "=Q"; break;
110 : }
111 : }
112 33 : if (check) res += "+";
113 33 : return res;
114 : }
115 :
116 5 : void setPromo(pieceT promo) {
117 5 : ASSERT(promo == QUEEN || promo == ROOK || promo == BISHOP ||
118 : promo == KNIGHT);
119 5 : m_ |= ((promo - 2) << 12) | (1 << 14);
120 5 : }
121 7 : void setCapture(pieceT piece, bool enPassant) {
122 7 : m_ |= ((piece & 0x07) << 21);
123 7 : if (enPassant) m_ |= (2 << 14);
124 7 : }
125 21 : void setAmbiguity(bool fyle, bool rank) {
126 21 : m_ &= ~(3 << 28);
127 21 : if (fyle)
128 18 : m_ |= (1 << 28);
129 21 : if (rank)
130 6 : m_ |= (1 << 29);
131 21 : }
132 10 : void setCheck() { m_ |= (1 << 30); }
133 : };
134 :
135 : #endif
|