Added promotion to shogi gamestate.
[tagua/yd.git] / src / hlvariant / shogi / serializer.h
blob9e71ad655512f59dead0d9fe0fd805adebaa150d
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 res += square(move.from(), ref.board().size());
109 if (move.drop() != Piece())
110 res += '*';
111 res += square(move.to(), ref.board().size());
112 if (move.promoteTo() != -1)
113 res += "+";
114 return res;
115 case COMPACT:
116 case DECORATED:
117 default:
119 bool ambiguous = isAmbiguous(move, ref);
121 QString res;
122 if (piece.promoted())
123 res += "+";
125 res += symbol(piece);
127 if (ambiguous) {
128 res += square(move.from(), ref.board().size());
131 if (move.drop() != Piece())
132 res += "*";
133 else if (ref.board().get(move.to()) != Piece())
134 res += "x";
135 else
136 res += "-";
138 res += square(move.to(), ref.board().size());
140 // if it is a promotion
141 if (move.promoteTo() != -1)
142 res += "+";
143 // if it is a refused promotion
144 else if (!piece.promoted() &&
145 move.drop() == Piece() &&
146 ref.promotionZone(ref.turn(), move.to())) {
147 res += "=";
150 return res;
155 template <typename LegalityCheck>
156 QString Serializer<LegalityCheck>::symbol(const Piece& piece) const {
157 if (m_rep == DECORATED) {
158 QString res = "{";
159 if (piece.promoted())
160 res += "p_";
161 return res + piece.typeName() + "}";
163 else {
164 if (piece.type() == Piece::KNIGHT)
165 return "N";
166 else
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 QChar c = letter.toLower();
176 if (c == 'p')
177 return Piece::PAWN;
178 else if (c == 'r')
179 return Piece::ROOK;
180 else if (c == 'b')
181 return Piece::BISHOP;
182 else if (c == 'l')
183 return Piece::LANCE;
184 else if (c == 'n')
185 return Piece::KNIGHT;
186 else if (c == 's')
187 return Piece::SILVER;
188 else if (c == 'g')
189 return Piece::GOLD;
190 else if (c == 'k')
191 return Piece::KING;
192 else
193 return Piece::INVALID_TYPE;
196 template <typename LegalityCheck>
197 typename Serializer<LegalityCheck>::Move
198 Serializer<LegalityCheck>::deserialize(const QString& str, const GameState& ref) {
199 if (str[0].isDigit()) {
200 // this is a move
201 Point orig(ref.board().size().x - str[0].digitValue(), str[1].toAscii() - 'a');
202 Point dest(ref.board().size().x - str[2].digitValue(), str[3].toAscii() - 'a');
203 return Move(orig, dest);
205 else {
206 if (str[1] != '*')
207 return Move();
208 typename Piece::Type t = getType(str[0]);
209 Point to(ref.board().size().x - str[2].digitValue(), str[3].toAscii() - 'a');
210 return Move(Piece(ref.turn(), t), to);
215 } // namespace Shogi
216 } // namespace HLVariant
218 #endif // HLVARIANT__SHOGI__SERIALIZER_H