2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
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__SHOGI__SERIALIZER_H
12 #define HLVARIANT__SHOGI__SERIALIZER_H
20 template <typename _LegalityCheck
>
22 static QRegExp pattern
;
24 typedef _LegalityCheck LegalityCheck
;
25 typedef typename
LegalityCheck::GameState GameState
;
26 typedef typename
GameState::Board Board
;
27 typedef typename
Board::Piece Piece
;
28 typedef typename
GameState::Move Move
;
32 virtual bool isAmbiguous(const Move
& move
, const GameState
& ref
) const;
33 virtual QString
square(const Point
& p
, const Point
& size
) const;
34 virtual QString
symbol(const Piece
& piece
) const;
35 virtual typename
Piece::Type
getType(const QChar
& letter
) const;
37 Serializer(const QString
& rep
);
38 virtual ~Serializer();
40 QString
serialize(const Move
&, const GameState
& ref
);
41 Move
deserialize(const QString
& str
, const GameState
& ref
);
43 Move
parse(const QString
&, int& offset
, int ysize
, const GameState
& ref
);
44 Move
parse(const QString
&, int ysize
, const GameState
& ref
);
49 template <typename LegalityCheck
>
50 Serializer
<LegalityCheck
>::Serializer(const QString
& rep
)
54 template <typename LegalityCheck
>
55 Serializer
<LegalityCheck
>::~Serializer() { }
57 template <typename LegalityCheck
>
58 bool Serializer
<LegalityCheck
>::isAmbiguous(const Move
& move
, const GameState
& ref
) const {
59 Piece piece
= move
.drop();
61 piece
= ref
.board().get(move
.from());
63 bool ambiguous
= false;
64 if (move
.drop() == Piece()) {
65 for (int i
= 0; i
< ref
.board().size().x
; i
++) {
66 for (int j
= 0; j
< ref
.board().size().x
; j
++) {
68 if (p
== move
.from() || ref
.board().get(p
) != piece
)
70 Move
mv(p
, move
.to());
71 LegalityCheck
check(ref
);
72 if (check
.legal(mv
)) {
83 template <typename LegalityCheck
>
84 QString Serializer
<LegalityCheck
>::square(const Point
& p
, const Point
& size
) const {
85 QString res
= QString::number(size
.x
- p
.x
);
86 if (m_rep
== "decorated") {
87 res
+= "{num_" + QString::number(p
.y
+ 1) + "}";
90 res
+= QString(p
.y
+ 'a');
97 template <typename LegalityCheck
>
98 QString Serializer
<LegalityCheck
>::serialize(const Move
& move
, const GameState
& ref
) {
99 Piece piece
= move
.drop();
100 if (piece
== Piece())
101 piece
= ref
.board().get(move
.from());
105 if (m_rep
== "simple") {
106 if (move
.drop() != Piece()) {
107 res
+= symbol(piece
);
110 res
+= square(move
.from(), ref
.board().size());
111 res
+= square(move
.to(), ref
.board().size());
112 if (move
.promoteTo() != -1)
117 bool ambiguous
= isAmbiguous(move
, ref
);
120 if (piece
.promoted())
123 res
+= symbol(piece
);
126 res
+= square(move
.from(), ref
.board().size());
129 if (move
.drop() != Piece())
131 else if (ref
.board().get(move
.to()) != Piece())
136 res
+= square(move
.to(), ref
.board().size());
138 // if it is a promotion
139 if (move
.promoteTo() != -1)
141 // if it is a refused promotion
142 else if (ref
.canPromote(piece
) &&
143 move
.drop() == Piece() &&
144 ref
.promotionZone(ref
.turn(), move
.to())) {
152 template <typename LegalityCheck
>
153 QString Serializer
<LegalityCheck
>::symbol(const Piece
& piece
) const {
154 if (m_rep
== "decorated") {
156 if (piece
.promoted())
158 res
+= piece
.typeName();
159 if (piece
.type() == Piece::KING
)
160 res
+= piece
.color() == Piece::BLACK
? '1' : '2';
164 if (piece
.type() == Piece::KNIGHT
)
167 return piece
.typeName()[0].toUpper();
171 template <typename LegalityCheck
>
172 typename Serializer
<LegalityCheck
>::Piece::Type
173 Serializer
<LegalityCheck
>::getType(const QChar
& letter
) const {
174 switch(letter
.toLower().toAscii()) {
180 return Piece::BISHOP
;
184 return Piece::KNIGHT
;
186 return Piece::SILVER
;
192 return Piece::INVALID_TYPE
;
196 template <typename LegalityCheck
>
197 QRegExp Serializer
<LegalityCheck
>::
199 pattern("^(([+])?([PRBLNSGK]))?((\\d*)([a-wyzA-Z])?)([-x*])?"
201 "(\\d+[a-zA-Z])?([+=])?[\?!]*");
203 template <typename LegalityCheck
>
204 typename Serializer
<LegalityCheck
>::Move
205 Serializer
<LegalityCheck
>::parse(const QString
& str
, int& offset
,
206 int ysize
, const GameState
& ref
) {
207 if (pattern
.indexIn(str
, offset
, QRegExp::CaretAtOffset
) != -1) {
209 typename Serializer
<LegalityCheck
>::Piece::Type type
;
214 type
= getType(pattern
.cap(3)[0]);
215 promoted
= pattern
.cap(2) == "+";
216 Point
to(ref
.board().size().x
- pattern
.cap(8)[0].digitValue(),
217 pattern
.cap(8)[1].toAscii() - 'a');
218 promotion
= (pattern
.cap(9) == "+") ? 1 : -1;
220 if (pattern
.cap(7) == "*") // is a drop ?
221 return Move(Piece(ref
.turn(), type
), to
);
223 from
= Point((pattern
.cap(5).length() == 0) ? -1 :
224 ref
.board().size().x
- pattern
.cap(5)[0].digitValue(),
225 (pattern
.cap(6).length() == 0) ? -1 :
226 pattern
.cap(6)[0].toAscii() - 'a');
228 if (from
.valid()) { // explicit from ?
229 candidate
= Move(from
, to
, static_cast<typename
Piece::Type
>(promotion
));
231 else { // resolve implicit from
232 for (int i
= 0; i
< ref
.board().size().x
; i
++) {
233 for (int j
= 0; j
< ref
.board().size().y
; j
++) {
235 Piece piece
= ref
.board().get(p
);
237 Move
mv(p
, to
, static_cast<typename
Piece::Type
>(promotion
));
238 if (p
.resembles(from
) &&
239 piece
.type() == type
&&
240 piece
.promoted() == promoted
&&
241 piece
.color() == ref
.turn()) {
243 LegalityCheck
check(ref
);
244 if (check
.legal(mv
)) {
245 if (candidate
.valid()) {
247 std::cerr
<< "ambiguous !" << std::endl
;
251 // ok, we have found a candidate move
260 if (!candidate
.valid())
261 std::cerr
<< "error - piece not found" << std::endl
;
263 offset
+= pattern
.matchedLength();
267 std::cout
<< "error!!!! " << qPrintable(str
.mid(offset
)) << std::endl
;
268 return Move(Point::invalid(),Point::invalid());
272 template <typename LegalityCheck
>
273 typename Serializer
<LegalityCheck
>::Move
274 Serializer
<LegalityCheck
>::parse(const QString
& str
, int ysize
,
275 const GameState
& ref
) {
277 return parse(str
, offset
, ysize
, ref
);
280 template <typename LegalityCheck
>
281 typename Serializer
<LegalityCheck
>::Move
282 Serializer
<LegalityCheck
>::deserialize(const QString
& str
, const GameState
& ref
) {
283 if (str
[0].isDigit()) {
285 Point
orig(ref
.board().size().x
- str
[0].digitValue(), str
[1].toAscii() - 'a');
286 Point
dest(ref
.board().size().x
- str
[2].digitValue(), str
[3].toAscii() - 'a');
287 return Move(orig
, dest
, ((str
.size() > 4) && (str
[4] == '+')) ? 1 : -1);
290 return parse(str
, ref
.board().size().y
, ref
);
294 } // namespace HLVariant
296 #endif // HLVARIANT__SHOGI__SERIALIZER_H