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
21 template <typename _LegalityCheck
>
23 static QRegExp pattern
;
25 typedef _LegalityCheck LegalityCheck
;
26 typedef typename
LegalityCheck::GameState GameState
;
27 typedef typename
GameState::Board Board
;
28 typedef typename
Board::Piece Piece
;
29 typedef typename
GameState::Move Move
;
33 virtual bool isAmbiguous(const Move
& move
, const GameState
& ref
) const;
34 virtual QString
square(const Point
& p
, const Point
& size
) const;
35 virtual QString
symbol(const Piece
& piece
) const;
36 virtual typename
Piece::Type
getType(const QChar
& letter
) const;
38 Serializer(const QString
& rep
);
39 virtual ~Serializer();
41 QString
serialize(const Move
&, const GameState
& ref
);
42 Move
deserialize(const QString
& str
, const GameState
& ref
);
44 Move
parse(const QString
&, int& offset
, int ysize
, const GameState
& ref
);
45 Move
parse(const QString
&, int ysize
, const GameState
& ref
);
50 template <typename LegalityCheck
>
51 Serializer
<LegalityCheck
>::Serializer(const QString
& rep
)
55 template <typename LegalityCheck
>
56 Serializer
<LegalityCheck
>::~Serializer() { }
58 template <typename LegalityCheck
>
59 bool Serializer
<LegalityCheck
>::isAmbiguous(const Move
& move
, const GameState
& ref
) const {
60 Piece piece
= move
.drop();
62 piece
= ref
.board().get(move
.from());
64 bool ambiguous
= false;
65 if (move
.drop() == Piece()) {
66 for (int i
= 0; i
< ref
.board().size().x
; i
++) {
67 for (int j
= 0; j
< ref
.board().size().x
; j
++) {
69 if (p
== move
.from() || ref
.board().get(p
) != piece
)
71 Move
mv(p
, move
.to());
72 LegalityCheck
check(ref
);
73 if (check
.legal(mv
)) {
84 template <typename LegalityCheck
>
85 QString Serializer
<LegalityCheck
>::square(const Point
& p
, const Point
& size
) const {
86 QString res
= QString::number(size
.x
- p
.x
);
87 if (m_rep
== "decorated") {
88 res
+= "{num_" + QString::number(p
.y
+ 1) + "}";
91 res
+= QString(p
.y
+ 'a');
98 template <typename LegalityCheck
>
99 QString Serializer
<LegalityCheck
>::serialize(const Move
& move
, const GameState
& ref
) {
100 Piece piece
= move
.drop();
101 if (piece
== Piece())
102 piece
= ref
.board().get(move
.from());
106 if (m_rep
== "simple") {
107 if (move
.drop() != Piece()) {
108 res
+= symbol(piece
);
111 res
+= square(move
.from(), ref
.board().size());
112 res
+= square(move
.to(), ref
.board().size());
113 if (move
.promoteTo() != -1)
118 bool ambiguous
= isAmbiguous(move
, ref
);
121 if (piece
.promoted())
124 res
+= symbol(piece
);
127 res
+= square(move
.from(), ref
.board().size());
130 if (move
.drop() != Piece())
132 else if (ref
.board().get(move
.to()) != Piece())
137 res
+= square(move
.to(), ref
.board().size());
139 // if it is a promotion
140 if (move
.promoteTo() != -1)
142 // if it is a refused promotion
143 else if (ref
.canPromote(piece
) &&
144 move
.drop() == Piece() &&
145 ref
.promotionZone(ref
.turn(), move
.to())) {
153 template <typename LegalityCheck
>
154 QString Serializer
<LegalityCheck
>::symbol(const Piece
& piece
) const {
155 if (m_rep
== "decorated") {
157 if (piece
.promoted())
159 res
+= piece
.typeName();
160 if (piece
.type() == Piece::KING
)
161 res
+= piece
.color() == Piece::BLACK
? '1' : '2';
165 if (piece
.type() == Piece::KNIGHT
)
168 return piece
.typeName()[0].toUpper();
172 template <typename LegalityCheck
>
173 typename Serializer
<LegalityCheck
>::Piece::Type
174 Serializer
<LegalityCheck
>::getType(const QChar
& letter
) const {
175 switch(letter
.toLower().toAscii()) {
181 return Piece::BISHOP
;
185 return Piece::KNIGHT
;
187 return Piece::SILVER
;
193 return Piece::INVALID_TYPE
;
197 template <typename LegalityCheck
>
198 QRegExp Serializer
<LegalityCheck
>::
200 pattern("^(([+])?([PRBLNSGK]))?((\\d*)([a-wyzA-Z])?)([-x*])?"
202 "(\\d+[a-zA-Z])?([+=])?[\?!]*");
204 template <typename LegalityCheck
>
205 typename Serializer
<LegalityCheck
>::Move
206 Serializer
<LegalityCheck
>::parse(const QString
& str
, int& offset
,
207 int ysize
, const GameState
& ref
) {
208 if (pattern
.indexIn(str
, offset
, QRegExp::CaretAtOffset
) != -1) {
210 typename Serializer
<LegalityCheck
>::Piece::Type type
;
215 type
= getType(pattern
.cap(3)[0]);
216 promoted
= pattern
.cap(2) == "+";
217 Point
to(ref
.board().size().x
- pattern
.cap(8)[0].digitValue(),
218 pattern
.cap(8)[1].toAscii() - 'a');
219 promotion
= (pattern
.cap(9) == "+") ? 1 : -1;
221 if (pattern
.cap(7) == "*") // is a drop ?
222 return Move(Piece(ref
.turn(), type
), to
);
224 from
= Point((pattern
.cap(5).length() == 0) ? -1 :
225 ref
.board().size().x
- pattern
.cap(5)[0].digitValue(),
226 (pattern
.cap(6).length() == 0) ? -1 :
227 pattern
.cap(6)[0].toAscii() - 'a');
229 if (from
.valid()) { // explicit from ?
230 candidate
= Move(from
, to
, static_cast<typename
Piece::Type
>(promotion
));
232 else { // resolve implicit from
233 for (int i
= 0; i
< ref
.board().size().x
; i
++) {
234 for (int j
= 0; j
< ref
.board().size().y
; j
++) {
236 Piece piece
= ref
.board().get(p
);
238 Move
mv(p
, to
, static_cast<typename
Piece::Type
>(promotion
));
239 if (p
.resembles(from
) &&
240 piece
.type() == type
&&
241 piece
.promoted() == promoted
&&
242 piece
.color() == ref
.turn()) {
244 LegalityCheck
check(ref
);
245 if (check
.legal(mv
)) {
246 if (candidate
.valid()) {
248 std::cerr
<< "ambiguous !";
252 // ok, we have found a candidate move
261 if (!candidate
.valid())
262 std::cerr
<< "error - piece not found";
264 offset
+= pattern
.matchedLength();
268 kDebug() << "error!!!! " << qPrintable(str
.mid(offset
));
269 return Move(Point::invalid(),Point::invalid());
273 template <typename LegalityCheck
>
274 typename Serializer
<LegalityCheck
>::Move
275 Serializer
<LegalityCheck
>::parse(const QString
& str
, int ysize
,
276 const GameState
& ref
) {
278 return parse(str
, offset
, ysize
, ref
);
281 template <typename LegalityCheck
>
282 typename Serializer
<LegalityCheck
>::Move
283 Serializer
<LegalityCheck
>::deserialize(const QString
& str
, const GameState
& ref
) {
284 if (str
[0].isDigit()) {
286 Point
orig(ref
.board().size().x
- str
[0].digitValue(), str
[1].toAscii() - 'a');
287 Point
dest(ref
.board().size().x
- str
[2].digitValue(), str
[3].toAscii() - 'a');
288 return Move(orig
, dest
, ((str
.size() > 4) && (str
[4] == '+')) ? 1 : -1);
291 return parse(str
, ref
.board().size().y
, ref
);
295 } // namespace HLVariant
297 #endif // HLVARIANT__SHOGI__SERIALIZER_H