Deal with non-promotable shogi pieces.
[tagua/yd.git] / src / hlvariant / shogi / serializer.h
blob5c863bbe70f42e4cd4809769a0efa1cba9f19c3f
1 /*
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.
9 */
11 #ifndef HLVARIANT__SHOGI__SERIALIZER_H
12 #define HLVARIANT__SHOGI__SERIALIZER_H
14 #include <QString>
16 namespace HLVariant {
17 namespace Shogi {
19 template <typename _LegalityCheck>
20 class Serializer {
21 public:
22 enum {
23 SIMPLE = 0,
24 COMPACT = 1,
25 DECORATED = 2
28 typedef _LegalityCheck LegalityCheck;
29 typedef typename LegalityCheck::GameState GameState;
30 typedef typename GameState::Board Board;
31 typedef typename Board::Piece Piece;
32 typedef typename GameState::Move Move;
33 protected:
34 int m_rep;
36 virtual bool isAmbiguous(const Move& move, const GameState& ref) const;
37 virtual QString square(const Point& p, const Point& size) const;
38 virtual QString symbol(const Piece& piece) const;
39 virtual typename Piece::Type getType(const QChar& letter) const;
40 public:
41 Serializer(int rep);
42 virtual ~Serializer();
44 QString serialize(const Move&, const GameState& ref);
45 Move deserialize(const QString& str, const GameState& ref);
48 // IMPLEMENTATION
50 template <typename LegalityCheck>
51 Serializer<LegalityCheck>::Serializer(int rep)
52 : m_rep(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();
61 if (piece == Piece())
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++) {
68 Point p(i, j);
69 if (p == move.from() || ref.board().get(p) != piece)
70 continue;
71 Move mv(p, move.to());
72 LegalityCheck check(ref);
73 if (check.legal(mv)) {
74 ambiguous = true;
75 break;
81 return ambiguous;
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) + "}";
90 else {
91 res += QString(p.y + 'a');
94 return res;
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());
104 QString res;
106 switch (m_rep) {
107 case SIMPLE:
108 if (move.drop() != Piece()) {
109 res += symbol(piece);
110 res += '*';
111 } else
112 res += square(move.from(), ref.board().size());
113 res += square(move.to(), ref.board().size());
114 if (move.promoteTo() != -1)
115 res += "+";
116 return res;
117 case COMPACT:
118 case DECORATED:
119 default:
121 bool ambiguous = isAmbiguous(move, ref);
123 QString res;
124 if (piece.promoted())
125 res += "+";
127 res += symbol(piece);
129 if (ambiguous) {
130 res += square(move.from(), ref.board().size());
133 if (move.drop() != Piece())
134 res += "*";
135 else if (ref.board().get(move.to()) != Piece())
136 res += "x";
137 else
138 res += "-";
140 res += square(move.to(), ref.board().size());
142 // if it is a promotion
143 if (move.promoteTo() != -1)
144 res += "+";
145 // if it is a refused promotion
146 else if (ref.canPromote(piece) &&
147 move.drop() == Piece() &&
148 ref.promotionZone(ref.turn(), move.to())) {
149 res += "=";
152 return res;
157 template <typename LegalityCheck>
158 QString Serializer<LegalityCheck>::symbol(const Piece& piece) const {
159 if (m_rep == DECORATED) {
160 QString res = "{";
161 if (piece.promoted())
162 res += "p_";
163 res += piece.typeName();
164 if (piece.type() == Piece::KING)
165 res += piece.color() == Piece::BLACK ? '1' : '2';
166 return res + "}";
168 else {
169 if (piece.type() == Piece::KNIGHT)
170 return "N";
171 else
172 return piece.typeName()[0].toUpper();
176 template <typename LegalityCheck>
177 typename Serializer<LegalityCheck>::Piece::Type
178 Serializer<LegalityCheck>::getType(const QChar& letter) const {
179 switch(letter.toLower().toAscii()) {
180 case 'p':
181 return Piece::PAWN;
182 case 'r':
183 return Piece::ROOK;
184 case 'b':
185 return Piece::BISHOP;
186 case 'l':
187 return Piece::LANCE;
188 case 'n':
189 return Piece::KNIGHT;
190 case 's':
191 return Piece::SILVER;
192 case 'g':
193 return Piece::GOLD;
194 case 'k':
195 return Piece::KING;
196 default:
197 return Piece::INVALID_TYPE;
201 template <typename LegalityCheck>
202 typename Serializer<LegalityCheck>::Move
203 Serializer<LegalityCheck>::deserialize(const QString& str, const GameState& ref) {
204 if (str[0].isDigit()) {
205 // this is a move
206 Point orig(ref.board().size().x - str[0].digitValue(), str[1].toAscii() - 'a');
207 Point dest(ref.board().size().x - str[2].digitValue(), str[3].toAscii() - 'a');
208 return Move(orig, dest, ((str.size() > 4) && (str[4] == '+')) ? 1 : -1);
210 else {
211 if (str[1] != '*') {
212 std::cerr << "Expected a star, got a '" << str[1].toAscii() << "'" << std::endl;
213 return Move();
215 typename Piece::Type t = getType(str[0]);
216 Point to(ref.board().size().x - str[2].digitValue(), str[3].toAscii() - 'a');
217 return Move(Piece(ref.turn(), t), to);
222 } // namespace Shogi
223 } // namespace HLVariant
225 #endif // HLVARIANT__SHOGI__SERIALIZER_H