Continued refactor work.
[tagua.git] / src / variants / reversi.cpp_
blobf60c74b280d76777c73e1c29eb2b7228d063087e
1 /*
2   Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3             (c) 2006 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 #include "reversi.h"
12 #include <map>
13 #include "xchess/animator.impl.h"
14 #include "xchess/piece.h"
15 #include "xchess/move.h"
16 #include "piecefunction.h"
17 #include "highlevel.h"
18 #include "algebraicnotation.h"
19 #include "graphicalposition.h"
20 #include "pointconverter.h"
21 #include "piecegrid.h"
23 using namespace boost;
25 class ReversiPiece {
26 public:
27   typedef PieceColor Color;
28   typedef int Type;
29 private:
30   Color m_color;
31 public:
32   ReversiPiece(Color color, Type)
33   : m_color(color) { }
34   ReversiPiece(Color color)
35   : m_color(color) { }
36   Color color() const { return m_color; }
37   Type type() const { return -1; }
38   int id() const { return static_cast<int>(m_color); }
39   QString name() const { return m_color == WHITE ? "white_stone"
40                                : m_color == BLACK ? "black_stone" : "unknown"; }
41   static Color oppositeColor(Color color) {
42     return color == WHITE ? BLACK : WHITE;
43   }
44   static int getType(const QString&) { return -1; }
45   static QString typeSymbol(int) { return ""; }
47   bool operator==(const ReversiPiece& other) const {
48     return m_color == other.m_color;
49   }
50   bool operator<(const ReversiPiece& other) const {
51     return m_color < other.m_color;
52   }
53   bool equals(const ReversiPiece* other) const {
54     return other && *this == *other;
55   }
58 typedef Point ReversiMove;
60 class ReversiPosition {
61 public:
62   typedef ReversiPiece Piece;
63   typedef ReversiMove Move;
64   typedef std::map<Piece, int> Pool;
65 private:
66   Pool m_pool;
67   PointerGrid<Piece> m_board;
68   Piece::Color m_turn;
70   int checkDirection(const Point& p, const Point& dir) const;
71   void flipDirection(Point p, const Point& dir);
72   void flip(const Point& p);
73 public:
74   ReversiPosition();
75   ReversiPosition(const OptList& l);
76   ReversiPosition(Piece::Color turn, bool wk, bool wq,
77                                           bool bk, bool bq, const Point& ep);
79   Pool& pool() { return m_pool; }
80   const Pool& pool() const { return m_pool; }
81   void addToPool(const Piece&, int) { }
82   void removeFromPool(const Piece&, int) { }
84   Piece::Color turn() const { return m_turn; }
85   void setTurn(Piece::Color turn) { m_turn = turn; }
86   void switchTurn();
87   Piece::Color previousTurn() const { return Piece::oppositeColor(m_turn); }
89   void fromFEN(const QString&, bool& ok) { ok = true;}
90   QString fen(int,int) const { return ""; }
92   static Move getVerboseMove(int turn, const VerboseNotation& m);
93   Move getMove(const AlgebraicNotation& m, bool& ok) const;
95   bool testMove(Move& p) const;
96   void move(const Move& p);
98   Point size() const { return m_board.getSize(); }
99   bool valid(const Point& p) const { return m_board.valid(p); }
100   void setup();
102   const Piece* get(const Point& p) const {
103     return valid(p) ? m_board[p] : 0;
104   }
105   Piece* get(const Point& p) {
106     return valid(p) ? m_board[p] : 0;
107   }
108   const Piece* operator[](const Point& p) const { return get(p); }
109   void set(const Point& p, Piece* piece) {
110     if (!valid(p))
111       return;
112     delete m_board[p];
113     m_board[p] = piece;
114   }
115   void removePiece(const Point& p) { set(p, 0); }
117   bool operator==(const ReversiPosition& other) const;
119   shared_ptr<Piece> moveHint(const Move& m) const;
120   void dump() const { }
121   QStringList borderCoords() const;
124 ReversiPosition::ReversiPosition()
125 : m_board(8,8)
126 , m_turn(WHITE) { }
128 ReversiPosition::ReversiPosition(const OptList&)
129 : m_board(8,8)
130 , m_turn(WHITE) { }
132 ReversiPosition::ReversiPosition(Piece::Color turn, bool, bool, bool, bool, const Point&)
133 : m_board(8,8)
134 , m_turn(turn) { }
136 QStringList ReversiPosition::borderCoords() const
138   QStringList retv;
139   Point p = m_board.getSize();
140   for(int i=0; i<p.x; i++)
141     retv << QChar('a'+i);
142   for(int i=1; i<=p.y; i++)
143     retv += QString::number(i);
144   return retv + retv;
147 ReversiMove ReversiPosition::getMove(const AlgebraicNotation& m, bool& ok) const {
148   ok = true;
149   return m.to;
152 ReversiMove ReversiPosition::getVerboseMove(int /*turn*/, const VerboseNotation& m) {
153   return m.to;
156 void ReversiPosition::setup() {
157   for (int i = 3; i <= 4; i++)
158   for (int j = 3; j <= 4; j++) {
159     m_board[Point(i,j)] = new Piece(
160       (i+j) % 2 == 0 ? WHITE : BLACK);
161   }
164 void ReversiPosition::switchTurn() {
165   m_turn = Piece::oppositeColor(m_turn);
166   for (Point p = m_board.first(); p <= m_board.last(); p = m_board.next(p))
167     if (testMove(p)) return;
168   // no move: restore old turn
169   m_turn = Piece::oppositeColor(m_turn);
172 int ReversiPosition::checkDirection(const Point& p, const Point& dir) const {
173   Point pos = p + dir;
174   int n = 0;
176   while (valid(pos) && m_board[pos]) {
177     if (m_board[pos]->color() != m_turn)
178       n++;
179     else return n;
180     pos += dir;
181   }
183   return 0;
186 void ReversiPosition::flipDirection(Point p, const Point& dir) {
187   const int n = checkDirection(p, dir);
188   for (int i = 0; i < n; i++)
189     flip(p += dir);
192 void ReversiPosition::flip(const Point& p) {
193   Q_ASSERT(m_board[p]);
194   set(p, new Piece(Piece::oppositeColor(m_board[p]->color())));
197 bool ReversiPosition::testMove(Move& p) const {
198   if (!valid(p) || m_board[p]) return false;
200   for (int i = -1; i <= 1; i++)
201   for (int j = -1; j <= 1; j++) {
202     if (i == 0 && j == 0) continue;
203     if (checkDirection(p, Point(i, j)) > 0) return true;
204   }
206   return false;
209 void ReversiPosition::move(const Move& p) {
210   set(p, new Piece(m_turn));
212   for (int i = -1; i <= 1; i++)
213   for (int j = -1; j <= 1; j++) {
214     if (i == 0 && j == 0) continue;
215     flipDirection(p, Point(i, j));
216   }
218   switchTurn();
221 bool ReversiPosition::operator==(const ReversiPosition& other) const {
222   return m_board == other.m_board
223       && m_turn == other.m_turn;
226 shared_ptr<ReversiPiece> ReversiPosition::moveHint(const ReversiMove& /*m*/) const {
227   return shared_ptr<Piece>(new Piece(m_turn));
231 //BEGIN ReversiAnimator ---------------------------------------------------------------------
233 #if 0
235 class ReversiAnimator {
236   typedef boost::shared_ptr<AnimationGroup> AnimationPtr;
239   PointConverter* m_converter;
240   GraphicalPosition* m_position;
241   Random m_random;
243   bool m_anim_movement;
244   bool m_anim_explode;
245   bool m_anim_fade;
246   bool m_anim_rotate;
247 public:
248   ReversiAnimator(PointConverter* converter, GraphicalPosition* position);
249   AnimationPtr warp(AbstractPosition::Ptr);
250   AnimationPtr forward(AbstractPosition::Ptr, const ReversiMove& move);
251   AnimationPtr back(AbstractPosition::Ptr, const ReversiMove& move);
254 ReversiAnimator::ReversiAnimator(PointConverter* converter, GraphicalPosition* position)
255 : m_converter(converter)
256 , m_position(position)
257 , m_anim_movement(false)
258 , m_anim_explode(false)
259 , m_anim_fade(false)
260 , m_anim_rotate(false) {
261   if (position->getBoolSetting("animations", true)) {
262     m_anim_movement = (bool)position->getBoolSetting("animations.movement", true);
263     m_anim_explode = (bool)position->getBoolSetting("animations.explode", true);
264     m_anim_fade = (bool)position->getBoolSetting("animations.fading", true);
265     m_anim_rotate = (bool)position->getBoolSetting("animations.transform", true);
266   }
269 ReversiAnimator::AnimationPtr ReversiAnimator::warp(AbstractPosition::Ptr final) {
270   AnimationPtr res(new AnimationGroup);
271   for (Point i = m_position->first(); i <= m_position->last(); i = m_position->next(i)) {
272     QPoint real = m_converter->toReal(i);
273     Element p = m_position->getElement(i);
274     AbstractPiece::Ptr q = final->get(i);
275     shared_ptr<Animation> a;
277     if (p) {
278       shared_ptr<PieceSprite> sprite = p.sprite();
279       Q_ASSERT(sprite);
281       if (!p.piece()->equals(q)) {
282         shared_ptr<PieceSprite> sprite = p.sprite();
284         if (q) {
285           if((m_anim_explode||m_anim_fade) && m_anim_rotate) {
286             shared_ptr<PieceSprite> new_sprite = m_position->setPiece(i, q, false, false);
287             shared_ptr<AnimationGroup> g(new AnimationGroup);
288             g->addPreAnimation(shared_ptr<Animation>(new GrowAnimation(new_sprite)));
289             if(0)/*m_anim_explode)*/
290               g->addPreAnimation(shared_ptr<Animation>(new ExplodeAnimation(sprite, m_random)));
291             else
292               g->addPreAnimation(shared_ptr<Animation>(new FadeAnimation(sprite, real, 255, 0)));
293             a = g;
294           }
295           else
296             a = shared_ptr<Animation>(new PromotionAnimation( sprite,
297                                           m_position->setPiece(i, q, false, false) ));
298         }
299         else {
300           // remove it
301           m_position->removeElement(i);
302           if(m_anim_fade)
303             a = shared_ptr<Animation>(new FadeAnimation(sprite, real, 255, 0));
304           else
305             a = shared_ptr<Animation>(new CaptureAnimation(sprite));
306         }
307       }
308     }
309     else if (q) {
310       a = shared_ptr<Animation>(new DropAnimation( m_position->setPiece(i, q, false, false) ));
311     }
313     if (a) res->addPreAnimation(a);
314   }
316   return res;
319 ReversiAnimator::AnimationPtr ReversiAnimator::forward(AbstractPosition::Ptr final, const ReversiMove&) {
320   return warp(final);
323 ReversiAnimator::AnimationPtr ReversiAnimator::back(AbstractPosition::Ptr final, const ReversiMove&) {
324   return warp(final);
327 #endif
329 //END ReversiAnimator -----------------------------------------------------------------------
331 class ReversiVariantInfo {
332 public:
333   typedef ReversiPosition Position;
334   typedef Position::Move Move;
335   typedef Position::Piece Piece;
336   typedef class ReversiAnimator Animator;
338   static const bool m_simple_moves = true;
339   static const char *m_name;
340   static const char *m_theme_proxy;
342   static void forallPieces(PieceFunction& f);
343   static int moveListLayout() { return 0; }
344   static OptList positionOptions() { return OptList(); }
347 const char *ReversiVariantInfo::m_name = "Reversi";
348 const char *ReversiVariantInfo::m_theme_proxy = "Reversi";
350 void ReversiVariantInfo::forallPieces(PieceFunction& f) {
351   f(WHITE, -1);
352   f(BLACK, -1);
355 VariantInfo* ReversiVariant::static_reversi_variant = 0;
357 VariantInfo* ReversiVariant::info() {
358   if (!static_reversi_variant)
359     static_reversi_variant = new WrappedVariantInfo<ReversiVariantInfo>;
360   return static_reversi_variant;
363 template <>
364 struct MoveFactory<ReversiVariantInfo> {
365   static ReversiMove createNormalMove(const NormalUserMove& move) {
366     return move.to;
367   }
368   static ReversiMove createDropMove(const ReversiPiece& /*p*/, const Point& to) {
369     return to;
370   }
371   static NormalUserMove toNormal(const ReversiMove& m) {
372     return NormalUserMove(Point::invalid(), m);
373   }
376 template <>
377 class MoveSerializer<ReversiPosition> : public AbstractMoveSerializer {
378   ReversiMove m_move;
379   const ReversiPosition& m_ref;
380 public:
381   MoveSerializer(const ReversiMove& m, const ReversiPosition& ref)
382   : m_move(m), m_ref(ref) { }
384   DecoratedMove toDecoratedMove() const {
385     return DecoratedMove() << SAN();
386   }
388   virtual QString SAN() const {
389     return m_move.toString(m_ref.size().y);
390   }
393 class ReversiAnimator : public SimpleAnimator<ReversiVariantInfo> {
394   typedef SimpleAnimator<ReversiVariantInfo> Base;
395   typedef Base::Position Position;
396   typedef Base::Move Move;
397   typedef Base::GPosition GPosition;
398 public:
399   ReversiAnimator(PointConverter* converter, const boost::shared_ptr<GPosition>& position)
400   : Base(converter, position) { }
402   AnimationPtr forward(const Position& final, const Move&) {
403     return warp(final);
404   }
405   
406   AnimationPtr back(const Position& final, const Move&) {
407     return warp(final);
408   }