-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmove.cpp
152 lines (115 loc) · 4.57 KB
/
move.cpp
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
143
144
145
146
147
148
149
150
151
152
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include <cctype>
#include "move.h"
#include "piece.h"
#include "position.h"
////
//// Functions
////
/// move_from_uci() takes a position and a string as input, and attempts to
/// convert the string to a move, using simple coordinate notation (g1f3,
/// a7a8q, etc.). In order to correctly parse en passant captures and castling
/// moves, we need the position. This function is not robust, and expects that
/// the input move is legal and correctly formatted.
Move move_from_uci(const Position& pos, const std::string& str) {
Square from, to;
Piece piece;
Color us = pos.side_to_move();
if (str.length() < 4)
return MOVE_NONE;
// Read the from and to squares
from = make_square(file_from_char(str[0]), rank_from_char(str[1]));
to = make_square(file_from_char(str[2]), rank_from_char(str[3]));
// Find the moving piece
piece = pos.piece_on(from);
// If the string has more than 4 characters, try to interpret the 5th
// character as a promotion.
if (str.length() > 4 && piece == piece_of_color_and_type(us, PAWN))
{
switch (tolower(str[4])) {
case 'n':
return make_promotion_move(from, to, KNIGHT);
case 'b':
return make_promotion_move(from, to, BISHOP);
case 'r':
return make_promotion_move(from, to, ROOK);
case 'q':
return make_promotion_move(from, to, QUEEN);
}
}
// En passant move? We assume that a pawn move is an en passant move
// if the destination square is epSquare.
if (to == pos.ep_square() && piece == piece_of_color_and_type(us, PAWN))
return make_ep_move(from, to);
// Is this a castling move? A king move is assumed to be a castling move
// if the destination square is occupied by a friendly rook, or if the
// distance between the source and destination squares is more than 1.
if (piece == piece_of_color_and_type(us, KING))
{
if (pos.piece_on(to) == piece_of_color_and_type(us, ROOK))
return make_castle_move(from, to);
if (square_distance(from, to) > 1)
{
// This is a castling move, but we have to translate it to the
// internal "king captures rook" representation.
SquareDelta delta = (to > from ? DELTA_E : DELTA_W);
Square s = from;
do s += delta;
while ( pos.piece_on(s) != piece_of_color_and_type(us, ROOK)
&& relative_rank(us, s) == RANK_1);
return relative_rank(us, s) == RANK_1 ? make_castle_move(from, s) : MOVE_NONE;
}
}
return make_move(from, to);
}
/// move_to_uci() converts a move to a string in coordinate notation
/// (g1f3, a7a8q, etc.). The only special case is castling moves, where we
/// print in the e1g1 notation in normal chess mode, and in e1h1 notation in
/// Chess960 mode.
const std::string move_to_uci(Move move, bool chess960) {
std::string str;
Square from = move_from(move);
Square to = move_to(move);
if (move == MOVE_NONE)
str = "(none)";
else if (move == MOVE_NULL)
str = "0000";
else
{
if (move_is_short_castle(move) && !chess960)
return (from == SQ_E1 ? "e1g1" : "e8g8");
if (move_is_long_castle(move) && !chess960)
return (from == SQ_E1 ? "e1c1" : "e8c8");
str = square_to_string(from) + square_to_string(to);
if (move_is_promotion(move))
str += char(tolower(piece_type_to_char(move_promotion_piece(move))));
}
return str;
}
/// Overload the << operator, to make it easier to print moves.
std::ostream& operator << (std::ostream& os, Move m) {
bool chess960 = (os.iword(0) != 0); // See set960()
return os << move_to_uci(m, chess960);
}
/// move_is_ok(), for debugging.
bool move_is_ok(Move m) {
return square_is_ok(move_from(m)) && square_is_ok(move_to(m));
}