2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2007 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
11 #ifndef HLVARIANT__CHESS__SERIALIZER_H
12 #define HLVARIANT__CHESS__SERIALIZER_H
14 #include "legalitycheck.h"
20 template <typename MoveGenerator
>
24 * Possible string representations for moves.
27 SIMPLE
= 0, /// The most direct way of representing a move.
28 COMPACT
= 1, /// Compact notation. This corresponds to SAN notation for games that support it.
29 DECORATED
= 2 /// Symbolic figurine notation. Figurine names are enclosed in braces.
32 typedef typename
MoveGenerator::LegalityCheck LegalityCheck
;
33 typedef typename
LegalityCheck::GameState GameState
;
34 typedef typename
GameState::Move Move
;
35 typedef typename
GameState::Board::Piece Piece
;
40 virtual QString
suffix(const Move
& move
, const GameState
& ref
);
42 virtual QString
san(const Move
& move
, const GameState
& ref
);
44 virtual void minimal_notation(SAN
& san
, const GameState
& ref
);
46 virtual Move
get_san(const SAN
& san
, const GameState
& ref
);
49 * Create a serializer to a given string representation for moves.
50 * \param rep A move representation.
51 * \sa MoveRepresentation.
55 virtual ~Serializer();
58 * Serialize a move given a reference game state.
59 * We assume the move has already been tested against @a ref.
60 * Calling this function on an untested or illegal move is safe but its return
62 * Do not try to call this function on an invalid move.
63 * \param ref The position in which this move shall be executed.
64 * \return A string representation for this move.
66 virtual QString
serialize(const Move
& move
, const GameState
& ref
);
69 * Convert a string representation of a move back to a move object.
70 * \param ref The position in which this move shall be executed.
71 * \return A move corresponding to the given string representation.
73 virtual Move
deserialize(const QString
& str
, const GameState
& ref
);
79 template <typename MoveGenerator
>
80 Serializer
<MoveGenerator
>::Serializer(int rep
)
83 template <typename MoveGenerator
>
84 Serializer
<MoveGenerator
>::~Serializer() { }
86 template <typename MoveGenerator
>
87 QString Serializer
<MoveGenerator
>::san(const Move
& move
, const GameState
& ref
) {
93 Piece piece
= ref
.board().get(move
.from());
94 Piece captured
= ref
.board().get(move
.captureSquare());
97 return ""; // no piece in the initial square
99 if (move
.kingSideCastling()) {
102 else if (move
.queenSideCastling()) {
105 else if (piece
.type() == Piece::PAWN
) {
106 if (captured
!= Piece())
107 res
= move
.from().col() + "x";
109 res
+= move
.to().toString(ref
.board().size().y
);
112 if (piece
.type() != Piece::PAWN
)
113 res
= piece
.typeName()[0].toUpper();
116 tmp
.from
= move
.from();
118 tmp
.type
= piece
.type();
119 tmp
.castling
= SAN::NoCastling
;
120 minimal_notation(tmp
, ref
);
122 res
+= tmp
.from
.toString(ref
.board().size().y
);
123 if (captured
!= Piece())
125 res
+= tmp
.to
.toString(ref
.board().size().y
);
128 if (move
.promoteTo() != -1)
129 res
+= "=" + QString(Piece::typeName(
130 static_cast<typename
Piece::Type
>(move
.promoteTo())
133 res
+= suffix(move
, ref
);
138 template <typename MoveGenerator
>
139 QString Serializer
<MoveGenerator
>::serialize(const Move
& move
, const GameState
& ref
) {
143 int ysize
= ref
.board().size().y
;
144 QString res
= move
.from().toString(ysize
) + move
.to().toString(ysize
);
145 if (move
.promoteTo() != -1)
148 static_cast<typename
Piece::Type
>(move
.promoteTo())
153 return san(move
, ref
);
156 QString res
= san(move
, ref
);
157 res
.replace('K', "{king}");
158 res
.replace('Q', "{queen}");
159 res
.replace('R', "{rook}");
160 res
.replace('N', "{knight}");
161 res
.replace('B', "{bishop}");
162 res
.replace('P', "{pawn}");
170 template <typename MoveGenerator
>
171 QString Serializer
<MoveGenerator
>::suffix(const Move
& move
, const GameState
& ref
) {
175 MoveGenerator
generator(tmp
);
176 if (generator
.check(Piece::oppositeColor(ref
.turn()))) {
177 if (generator
.stalled())
187 template <typename MoveGenerator
>
188 typename Serializer
<MoveGenerator
>::Move
189 Serializer
<MoveGenerator
>::get_san(const SAN
& san
, const GameState
& ref
) {
195 if (san
.castling
!= SAN::NoCastling
) {
196 Point from
= ref
.kingStartingPosition(ref
.turn());
197 Point to
= from
+ (san
.castling
== SAN::KingSide
? Point(2,0) : Point(-2,0));
198 Piece king
= ref
.board().get(from
);
199 if (king
.type() != Piece::KING
)
202 candidate
= Move(from
, to
);
203 LegalityCheck
check(ref
);
204 if (check
.legal(candidate
))
211 if (san
.from
.valid()) {
212 candidate
= Move(san
.from
, san
.to
, static_cast<typename
Piece::Type
>(san
.promotion
));
215 for (int i
= 0; i
< ref
.board().size().x
; i
++) {
216 for (int j
= 0; j
< ref
.board().size().y
; j
++) {
218 Piece piece
= ref
.board().get(p
);
220 Move
mv(p
, san
.to
, static_cast<typename
Piece::Type
>(san
.promotion
));
221 if (p
.resembles(san
.from
) &&
222 piece
.type() == san
.type
&&
223 piece
.color() == ref
.turn()) {
225 LegalityCheck
check(ref
);
226 if (check
.legal(mv
)) {
227 if (candidate
.valid()) {
232 // ok, we have found a candidate move
244 template <typename MoveGenerator
>
245 typename Serializer
<MoveGenerator
>::Move
246 Serializer
<MoveGenerator
>::deserialize(const QString
& str
, const GameState
& ref
) {
249 return Move(); // BROKEN
253 tmp
.load(str
, ref
.board().size().y
);
254 return get_san(tmp
, ref
);
258 // no need to parse decorated moves
264 #define TRY(x) if(get_san(x, ref).valid()) return;
265 template <typename MoveGenerator
>
266 void Serializer
<MoveGenerator
>::minimal_notation(SAN
& san
, const GameState
& ref
) {
267 Point from
= san
.from
;
268 san
.castling
= SAN::NoCastling
;
270 // try notation without starting point
271 san
.from
= Point::invalid();
274 // add column indication
275 san
.from
= Point(from
.x
, -1);
278 // add row indication
279 san
.from
= Point(-1, from
.y
);
282 // add complete starting point
288 } // namespace HLVariant
290 #endif // HLVARIANT__CHESS__SERIALIZER_H