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()) {
106 if (piece
.type() != Piece::PAWN
)
107 res
= piece
.typeName()[0].toUpper();
110 tmp
.from
= move
.from();
112 tmp
.type
= piece
.type();
113 tmp
.castling
= SAN::NoCastling
;
114 minimal_notation(tmp
, ref
);
116 res
+= tmp
.from
.toString(ref
.board().size().y
);
117 if (captured
!= Piece())
119 res
+= tmp
.to
.toString(ref
.board().size().y
);
122 if (move
.promoteTo() != -1)
123 res
+= "=" + QString(Piece::typeName(
124 static_cast<typename
Piece::Type
>(move
.promoteTo())
127 res
+= suffix(move
, ref
);
132 template <typename MoveGenerator
>
133 QString Serializer
<MoveGenerator
>::serialize(const Move
& move
, const GameState
& ref
) {
137 return san(move
, ref
);
140 QString res
= san(move
, ref
);
141 res
.replace('K', "{king}");
142 res
.replace('Q', "{queen}");
143 res
.replace('R', "{rook}");
144 res
.replace('N', "{knight}");
145 res
.replace('B', "{bishop}");
146 res
.replace('P', "{pawn}");
154 template <typename MoveGenerator
>
155 QString Serializer
<MoveGenerator
>::suffix(const Move
& move
, const GameState
& ref
) {
159 MoveGenerator
generator(tmp
);
160 if (generator
.check(ref
.turn())) {
161 if (generator
.stalled())
171 template <typename MoveGenerator
>
172 typename Serializer
<MoveGenerator
>::Move
173 Serializer
<MoveGenerator
>::get_san(const SAN
& san
, const GameState
& ref
) {
179 if (san
.castling
!= SAN::NoCastling
) {
180 Point from
= ref
.kingStartingPosition(ref
.turn());
181 Point to
= from
+ (san
.castling
== SAN::KingSide
? Point(2,0) : Point(-2,0));
182 Piece king
= ref
.board().get(from
);
183 if (king
.type() != Piece::KING
)
186 return Move(from
, to
);
189 if (san
.from
.valid()) {
190 candidate
= Move(san
.from
, san
.to
, static_cast<typename
Piece::Type
>(san
.promotion
));
193 for (int i
= 0; i
< ref
.board().size().x
; i
++) {
194 for (int j
= 0; j
< ref
.board().size().y
; j
++) {
196 Piece piece
= ref
.board().get(p
);
198 Move
mv(p
, san
.to
, static_cast<typename
Piece::Type
>(san
.promotion
));
199 if (p
.resembles(san
.from
) &&
200 piece
.type() == san
.type
&&
201 piece
.color() == ref
.turn()) {
203 LegalityCheck
check(ref
);
204 if (check
.legal(mv
)) {
205 if (candidate
.valid()) {
210 // ok, we have found a candidate move
222 template <typename MoveGenerator
>
223 typename Serializer
<MoveGenerator
>::Move
224 Serializer
<MoveGenerator
>::deserialize(const QString
& str
, const GameState
& ref
) {
227 return Move(); // BROKEN
231 tmp
.load(str
, ref
.board().size().y
);
232 return get_san(tmp
, ref
);
236 // no need to parse decorated moves
242 #define TRY(x) if(get_san(x, ref).valid()) return;
243 template <typename MoveGenerator
>
244 void Serializer
<MoveGenerator
>::minimal_notation(SAN
& san
, const GameState
& ref
) {
245 Point from
= san
.from
;
246 san
.castling
= SAN::NoCastling
;
248 // try notation without starting point
249 san
.from
= Point::invalid();
252 // add column indication
253 san
.from
= Point(from
.x
, -1);
256 // add row indication
257 san
.from
= Point(-1, from
.y
);
260 // add complete starting point
266 } // namespace HLVariant
268 #endif // HLVARIANT__CHESS__SERIALIZER_H