Added backward promotion and en-passant animations.
[tagua.git] / src / variants / chess.cpp
blob23273d66319c8c7410d9b63431d46e0be6fc3a38
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 <QPainter>
12 #include <boost/shared_ptr.hpp>
13 #include "variants/chess.h"
14 #include "common.h"
15 #include "kboard_wrapped.h"
16 #include "moveserializer.impl.h"
17 #include "xchess/animator.impl.h"
18 #include "piecefunction.h"
19 #include "animation.h"
21 using namespace boost;
22 typedef boost::shared_ptr<class Animation> AnimationPtr;
24 const char *ChessVariant::m_name = "Chess";
25 const char *ChessVariant::m_theme_proxy = "Chess";
26 VariantInfo* ChessVariant::static_chess_variant = 0;
30 //BEGIN Dream code
32 typedef UnwrappedGraphicalAPI<ChessVariant> ChessGraphicalAPI;
34 class ChessAnimator {
35 ChessGraphicalAPI::Ptr m_cinterface;
36 Random m_random;
38 public:
39 ChessAnimator(ChessGraphicalAPI::Ptr cinterface)
40 : m_cinterface(cinterface) {
43 AnimationGroupPtr warp(const ChessPosition& final) {
44 const ChessPosition* current = m_cinterface->position();
45 AnimationGroupPtr res(new AnimationGroup);
47 for (Point i = current->first(); i <= current->last(); i = current->next(i)) {
48 ChessPiece c = current->get(i);
49 ChessPiece f = final.get(i);
51 if( !c && f ) {
52 //current->set(i, f);
53 NamedSprite sprite = m_cinterface->setPiece(i, f, false, false);
54 res->addPreAnimation( DropAnimationPtr(new DropAnimation(sprite.sprite())) );
56 else if (c && !f) {
57 //current->set(i, NULL);
58 NamedSprite old_sprite = m_cinterface->takeSprite(i);
59 res->addPreAnimation( CaptureAnimationPtr(new CaptureAnimation(old_sprite.sprite())) );
61 else if(c && f && !(c == f) ) {
62 //current->set(i, f);
63 NamedSprite old_sprite = m_cinterface->takeSprite(i);
64 NamedSprite sprite = m_cinterface->setPiece(i, f, false, false);
65 res->addPreAnimation( PromotionAnimationPtr(new PromotionAnimation(old_sprite.sprite(), sprite.sprite())) );
69 //BROKEN: implement pool update
72 return res;
75 boost::shared_ptr<AnimationGroup> forward(const ChessPosition& final, const ChessMove& move) {
76 // const ChessPosition* current = m_cinterface->position();
78 AnimationGroupPtr res(new AnimationGroup);
79 MovementAnimationPtr ma;
80 //ChessPiece piece = current->get(move.from);
82 NamedSprite piece = m_cinterface->takeSprite(move.from);
83 NamedSprite captured = m_cinterface->takeSprite(move.to);
84 m_cinterface->setSprite(move.to, piece);
86 if (piece)
87 res->addPreAnimation(ma = MovementAnimationPtr(new MovementAnimation(piece.sprite(),
88 m_cinterface->converter()->toReal(move.to))));
89 else
90 std::cout << "Bug!!!!" << std::endl;
91 if (captured)
92 res->addPostAnimation(ExplodeAnimationPtr(new ExplodeAnimation(captured.sprite(), m_random)));
94 if (move.type() == ChessMove::EnPassantCapture) {
95 Point phantom(move.to.x, move.from.y);
96 NamedSprite capturedPawn = m_cinterface->takeSprite(phantom);
98 if (capturedPawn) {
99 QPoint real = m_cinterface->converter()->toReal(phantom);
100 res->addPostAnimation(FadeAnimationPtr(new FadeAnimation(capturedPawn.sprite(),
101 real, 255, 0)));
103 else
104 std::cout << "Bug!!!!" << std::endl;
106 else if (move.type() == ChessMove::Promotion) {
107 ChessPiece promoted = final.get(move.to);
109 if (promoted) {
110 QPoint real = m_cinterface->converter()->toReal(move.to);
111 NamedSprite old_sprite = m_cinterface->getSprite(move.to);
112 NamedSprite new_sprite = m_cinterface->setPiece(move.to, promoted, false, false);
114 if (ma)
115 ma->setTarget(new_sprite.sprite());
117 res->addPostAnimation( FadeAnimationPtr(new FadeAnimation(old_sprite.sprite(), real, 255, 0)) );
118 res->addPostAnimation( FadeAnimationPtr(new FadeAnimation(new_sprite.sprite(), real, 0, 255)) );
120 else
121 std::cout << "Bug!!!!" << std::endl;
123 else if (move.type() == ChessMove::KingSideCastling) {
124 Point rookSquare = move.to + Point(1,0);
125 Point rookDestination = move.from + Point(1,0);
127 NamedSprite rook = m_cinterface->takeSprite(rookSquare);
128 m_cinterface->setSprite(rookDestination, rook);
130 res->addPreAnimation(
131 shared_ptr<Animation>(
132 new MovementAnimation(rook.sprite(),
133 m_cinterface->converter()->toReal(rookDestination)))
136 else if (move.type() == ChessMove::QueenSideCastling) {
137 Point rookSquare = move.to + Point(-2,0);
138 Point rookDestination = move.from + Point(-1,0);
140 NamedSprite rook = m_cinterface->takeSprite(rookSquare);
141 m_cinterface->setSprite(rookDestination, rook);
143 res->addPreAnimation(
144 shared_ptr<Animation>(
145 new MovementAnimation(rook.sprite(),
146 m_cinterface->converter()->toReal(rookDestination)))
150 return res;
153 boost::shared_ptr<AnimationGroup> back(const ChessPosition& final, const ChessMove& move) {
154 AnimationGroupPtr res(new AnimationGroup);
155 MovementAnimationPtr ma;
157 NamedSprite piece = m_cinterface->takeSprite(move.to);
158 NamedSprite captured;
159 if (ChessPiece captured_piece = final.get(move.to)) {
160 captured = m_cinterface->setPiece(move.to, captured_piece, false, false);
161 res->addPreAnimation(FadeAnimationPtr(new FadeAnimation(captured.sprite(),
162 m_cinterface->converter()->toReal(move.to), 0, 255)));
165 if (!piece) {
166 piece = m_cinterface->setPiece(move.to, final.get(move.from), false, false);
167 res->addPreAnimation(FadeAnimationPtr(new FadeAnimation(piece.sprite(),
168 m_cinterface->converter()->toReal(move.to), 0, 255)));
171 m_cinterface->setSprite(move.from, piece);
174 if (move.type() == ChessMove::EnPassantCapture) {
175 Point phantom(move.to.x, move.from.y);
177 if (ChessPiece pawn_piece = final.get(phantom)) {
178 NamedSprite capturedPawn = m_cinterface->setPiece(phantom, pawn_piece, false, false);
179 res->addPreAnimation(FadeAnimationPtr(new FadeAnimation(capturedPawn.sprite(),
180 m_cinterface->converter()->toReal(phantom),
181 0, 255)));
184 else if (move.type() == ChessMove::Promotion) {
185 ChessPiece pawn_piece = final.get(move.from);
186 if (pawn_piece) {
187 NamedSprite pawn = m_cinterface->setPiece(move.from, pawn_piece, false, false);
188 res->addPreAnimation(FadeAnimationPtr(new FadeAnimation(pawn.sprite(),
189 m_cinterface->converter()->toReal(move.to), 0, 255)));
190 res->addPreAnimation(FadeAnimationPtr(new FadeAnimation(piece.sprite(),
191 m_cinterface->converter()->toReal(move.to), 255, 0)));
193 piece = pawn;
196 else if (move.type() == ChessMove::KingSideCastling) {
197 Point rookSquare = move.to + Point(1,0);
198 Point rookDestination = move.from + Point(1,0);
200 NamedSprite rook = m_cinterface->takeSprite(rookSquare);
201 m_cinterface->setSprite(rookDestination, rook);
203 res->addPreAnimation(
204 shared_ptr<Animation>(
205 new MovementAnimation(rook.sprite(),
206 m_cinterface->converter()->toReal(rookDestination)))
209 else if (move.type() == ChessMove::QueenSideCastling) {
210 Point rookSquare = move.to + Point(-2,0);
211 Point rookDestination = move.from + Point(-1,0);
213 NamedSprite rook = m_cinterface->takeSprite(rookSquare);
214 m_cinterface->setSprite(rookDestination, rook);
216 res->addPreAnimation(
217 shared_ptr<Animation>(
218 new MovementAnimation(rook.sprite(),
219 m_cinterface->converter()->toReal(rookDestination)))
223 res->addPreAnimation(ma = MovementAnimationPtr(new MovementAnimation(piece.sprite(),
224 m_cinterface->converter()->toReal(move.from))));
225 return res;
230 //END Dream code
233 void ChessVariant::forallPieces(PieceFunction& f) {
234 f(WHITE, KING);
235 f(WHITE, QUEEN);
236 f(WHITE, ROOK);
237 f(WHITE, BISHOP);
238 f(WHITE, KNIGHT);
239 f(WHITE, PAWN);
240 f(BLACK, KING);
241 f(BLACK, QUEEN);
242 f(BLACK, ROOK);
243 f(BLACK, BISHOP);
244 f(BLACK, KNIGHT);
245 f(BLACK, PAWN);
248 VariantInfo* ChessVariant::info() {
249 if (!static_chess_variant)
250 static_chess_variant = new WrappedVariantInfo<ChessVariant>;
251 return static_chess_variant;