Finally restored knight fancy animation.
[tagua/yd.git] / src / variants / chess.cpp
blob4251ead2c094ce361f0cd0553a5b60fa00ab2711
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;
29 typedef UnwrappedGraphicalAPI<ChessVariant> ChessGraphicalAPI;
31 class ChessAnimator {
32 ChessGraphicalAPI::Ptr m_cinterface;
33 public:
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);
46 if( !c && f ) {
47 //current->set(i, f);
48 NamedSprite sprite = m_cinterface->setPiece(i, f, false);
49 res.addPreAnimation(Animate::appear(sprite), Animate::Instant);
51 else if (c && !f) {
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
65 return res;
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);
75 if (piece) {
76 bool knight = m_cinterface->position()->get(move.from).type() == KNIGHT;
77 int mtype = knight
78 ? Animate::move::LShaped | Animate::move::Rotating
79 : Animate::move::Straight;
80 res.addPreAnimation(Animate::move(piece, move.to, mtype));
82 else
83 ERROR("Bug!!!");
85 if (captured)
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);
92 if (capturedPawn) {
93 QPoint real = m_cinterface->converter()->toReal(phantom);
94 res.addPostAnimation(Animate::disappear(capturedPawn));
96 else
97 ERROR("Bug!!!");
99 else if (move.type() == ChessMove::Promotion) {
100 ChessPiece promoted = final.get(move.to);
102 if (promoted) {
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));
109 else
110 ERROR("Bug!!!");
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));
129 return res;
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));
142 if (!piece) {
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);
160 if (pawn_piece) {
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);
165 piece = 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;
189 int mtype = knight
190 ? Animate::move::LShaped | Animate::move::Rotating
191 : Animate::move::Straight;
192 res.addPreAnimation(Animate::move(piece, move.from, mtype));
194 return res;
198 void ChessVariant::forallPieces(PieceFunction& f) {
199 f(WHITE, KING);
200 f(WHITE, QUEEN);
201 f(WHITE, ROOK);
202 f(WHITE, BISHOP);
203 f(WHITE, KNIGHT);
204 f(WHITE, PAWN);
205 f(BLACK, KING);
206 f(BLACK, QUEEN);
207 f(BLACK, ROOK);
208 f(BLACK, BISHOP);
209 f(BLACK, KNIGHT);
210 f(BLACK, PAWN);
213 VariantInfo* ChessVariant::info() {
214 if (!static_chess_variant)
215 static_chess_variant = new WrappedVariantInfo<ChessVariant>;
216 return static_chess_variant;