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.
12 #include <boost/shared_ptr.hpp>
13 #include "variants/chess.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;
29 typedef UnwrappedGraphicalAPI
<ChessVariant
> ChessGraphicalAPI
;
32 ChessGraphicalAPI::Ptr m_cinterface
;
34 ChessAnimator(ChessGraphicalAPI::Ptr cinterface
)
35 : m_cinterface(cinterface
) {
38 AnimationGroupPtr
warp(const ChessPosition
& final
) {
39 const ChessPosition
* current
= m_cinterface
->position();
40 AnimationFactory
res(m_cinterface
->inner());
42 for (Point i
= current
->first(); i
<= current
->last(); i
= current
->next(i
)) {
43 ChessPiece c
= current
->get(i
);
44 ChessPiece f
= final
.get(i
);
48 NamedSprite sprite
= m_cinterface
->setPiece(i
, f
, false);
49 res
.addPreAnimation(Animate::appear(sprite
), Animate::Instant
);
52 NamedSprite old_sprite
= m_cinterface
->takeSprite(i
);
53 res
.addPreAnimation(Animate::disappear(old_sprite
), Animate::Instant
);
55 else if(c
&& f
&& !(c
== f
) ) {
56 NamedSprite old_sprite
= m_cinterface
->takeSprite(i
);
57 NamedSprite sprite
= m_cinterface
->setPiece(i
, f
, false);
58 res
.addPreAnimation(Animate::morph(old_sprite
, sprite
), Animate::Instant
);
62 //BROKEN: implement pool update
68 boost::shared_ptr
<AnimationGroup
> forward(const ChessPosition
& final
, const ChessMove
& move
) {
69 AnimationFactory
res(m_cinterface
->inner());
71 NamedSprite piece
= m_cinterface
->takeSprite(move
.from
);
72 NamedSprite captured
= m_cinterface
->takeSprite(move
.to
);
73 m_cinterface
->setSprite(move
.to
, piece
);
76 bool knight
= m_cinterface
->position()->get(move
.from
).type() == KNIGHT
;
78 ? Animate::move::LShaped
| Animate::move::Rotating
79 : Animate::move::Straight
;
80 res
.addPreAnimation(Animate::move(piece
, move
.to
, mtype
));
86 res
.addPostAnimation(Animate::destroy(captured
));
88 if (move
.type() == ChessMove::EnPassantCapture
) {
89 Point
phantom(move
.to
.x
, move
.from
.y
);
90 NamedSprite capturedPawn
= m_cinterface
->takeSprite(phantom
);
93 QPoint real
= m_cinterface
->converter()->toReal(phantom
);
94 res
.addPostAnimation(Animate::disappear(capturedPawn
));
99 else if (move
.type() == ChessMove::Promotion
) {
100 ChessPiece promoted
= final
.get(move
.to
);
103 QPoint real
= m_cinterface
->converter()->toReal(move
.to
);
104 NamedSprite old_sprite
= m_cinterface
->getSprite(move
.to
);
105 NamedSprite new_sprite
= m_cinterface
->setPiece(move
.to
, promoted
, /*false,*/ false);
107 res
.addPostAnimation(Animate::morph(old_sprite
, new_sprite
));
112 else if (move
.type() == ChessMove::KingSideCastling
) {
113 Point rookSquare
= move
.to
+ Point(1,0);
114 Point rookDestination
= move
.from
+ Point(1,0);
116 NamedSprite rook
= m_cinterface
->takeSprite(rookSquare
);
117 m_cinterface
->setSprite(rookDestination
, rook
);
118 res
.addPreAnimation(Animate::move(rook
, rookDestination
));
120 else if (move
.type() == ChessMove::QueenSideCastling
) {
121 Point rookSquare
= move
.to
+ Point(-2,0);
122 Point rookDestination
= move
.from
+ Point(-1,0);
124 NamedSprite rook
= m_cinterface
->takeSprite(rookSquare
);
125 m_cinterface
->setSprite(rookDestination
, rook
);
126 res
.addPreAnimation(Animate::move(rook
, rookDestination
));
132 boost::shared_ptr
<AnimationGroup
> back(const ChessPosition
& final
, const ChessMove
& move
) {
133 AnimationFactory
res(m_cinterface
->inner());
135 NamedSprite piece
= m_cinterface
->takeSprite(move
.to
);
136 NamedSprite captured
;
137 if (ChessPiece captured_piece
= final
.get(move
.to
)) {
138 captured
= m_cinterface
->setPiece(move
.to
, captured_piece
, false);
139 res
.addPreAnimation(Animate::appear(captured
));
143 piece
= m_cinterface
->createPiece(move
.to
, final
.get(move
.from
), false);
144 res
.addPreAnimation(Animate::appear(piece
));
147 m_cinterface
->setSprite(move
.from
, piece
);
150 if (move
.type() == ChessMove::EnPassantCapture
) {
151 Point
phantom(move
.to
.x
, move
.from
.y
);
153 if (ChessPiece pawn_piece
= final
.get(phantom
)) {
154 NamedSprite captured_pawn
= m_cinterface
->setPiece(phantom
, pawn_piece
, false);
155 res
.addPreAnimation(Animate::appear(captured_pawn
));
158 else if (move
.type() == ChessMove::Promotion
) {
159 ChessPiece pawn_piece
= final
.get(move
.from
);
161 NamedSprite pawn
= m_cinterface
->createPiece(move
.to
, pawn_piece
, false);
162 res
.addPreAnimation(Animate::morph(piece
, pawn
));
163 // replace piece with pawn
164 m_cinterface
->setSprite(move
.from
, pawn
);
168 else if (move
.type() == ChessMove::KingSideCastling
) {
169 Point rookSquare
= move
.to
+ Point(1,0);
170 Point rookDestination
= move
.from
+ Point(1,0);
172 NamedSprite rook
= m_cinterface
->takeSprite(rookDestination
);
173 m_cinterface
->setSprite(rookSquare
, rook
);
175 res
.addPreAnimation(Animate::move(rook
, rookSquare
));
177 else if (move
.type() == ChessMove::QueenSideCastling
) {
178 Point rookSquare
= move
.to
+ Point(-2,0);
179 Point rookDestination
= move
.from
+ Point(-1,0);
181 NamedSprite rook
= m_cinterface
->takeSprite(rookDestination
);
182 m_cinterface
->setSprite(rookSquare
, rook
);
184 res
.addPreAnimation(Animate::move(rook
, rookSquare
));
188 bool knight
= m_cinterface
->position()->get(move
.to
).type() == KNIGHT
;
190 ? Animate::move::LShaped
| Animate::move::Rotating
191 : Animate::move::Straight
;
192 res
.addPreAnimation(Animate::move(piece
, move
.from
, mtype
));
198 void ChessVariant::forallPieces(PieceFunction
& f
) {
213 VariantInfo
* ChessVariant::info() {
214 if (!static_chess_variant
)
215 static_chess_variant
= new WrappedVariantInfo
<ChessVariant
>;
216 return static_chess_variant
;