1/*
2 * Copyright (C) 1995 Paul Olav Tvete <paul@troll.no>
3 * Copyright (C) 2000-2009 Stephan Kulow <coolo@kde.org>
4 * Copyright (C) 2010 Parker Coates <coates@kde.org>
5 *
6 * License of original code:
7 * -------------------------------------------------------------------------
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted,
10 * provided that the above copyright notice appear in all copies and that
11 * both that copyright notice and this permission notice appear in
12 * supporting documentation.
13 *
14 * This file is provided AS IS with no warranties of any kind. The author
15 * shall have no liability with respect to the infringement of copyrights,
16 * trade secrets or any patents by this file or any part thereof. In no
17 * event will the author be liable for any lost revenue or profits or
18 * other special, indirect and consequential damages.
19 * -------------------------------------------------------------------------
20 *
21 * License of modifications/additions made after 2009-01-01:
22 * -------------------------------------------------------------------------
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License as
25 * published by the Free Software Foundation; either version 2 of
26 * the License, or (at your option) any later version.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35 * -------------------------------------------------------------------------
36 */
37
38#include "grandf.h"
39
40#include "dealerinfo.h"
41#include "pileutils.h"
42#include "speeds.h"
43#include "patsolve/grandfsolver.h"
44
45#include <KLocale>
46
47
48Grandf::Grandf( const DealerInfo * di )
49 : DealerScene( di )
50{
51}
52
53
54void Grandf::initialize()
55{
56 setDeckContents();
57
58 const qreal distx = 1.4;
59 const qreal targetOffset = 1.5 * distx;
60
61 for ( int i = 0; i < 4; ++i )
62 {
63 target[i] = new PatPile( this, i + 1, QString("target%1").arg(i) );
64 target[i]->setPileRole(PatPile::Foundation);
65 target[i]->setLayoutPos(targetOffset+i*distx, 0);
66 target[i]->setSpread(0, 0);
67 target[i]->setKeyboardSelectHint( KCardPile::NeverFocus );
68 target[i]->setKeyboardDropHint( KCardPile::ForceFocusTop );
69 }
70
71 for ( int i = 0; i < 7; ++i )
72 {
73 store[i] = new PatPile( this, 5 + i, QString("store%1").arg(i) );
74 store[i]->setPileRole(PatPile::Tableau);
75 store[i]->setLayoutPos(distx*i, 1.2);
76 store[i]->setAutoTurnTop(true);
77 store[i]->setBottomPadding( 4 );
78 store[i]->setHeightPolicy( KCardPile::GrowDown );
79 store[i]->setKeyboardSelectHint( KCardPile::FreeFocus );
80 store[i]->setKeyboardDropHint( KCardPile::AutoFocusTop );
81 }
82
83 setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Redeal);
84 setSolver( new GrandfSolver( this ) );
85}
86
87void Grandf::restart( const QList<KCard*> & cards )
88{
89 deal( cards );
90 numberOfDeals = 1;
91 emit newCardsPossible( true );
92}
93
94bool Grandf::newCards()
95{
96 if ( numberOfDeals >= 3 )
97 return false;
98
99 // NOTE: This is not quite correct. The piles should be turned face down
100 // (i.e. partially reversed) during collection.
101 QList<KCard*> collectedCards;
102 for ( int pos = 6; pos >= 0; --pos )
103 {
104 collectedCards << store[pos]->cards();
105 store[pos]->clear();
106 }
107 deal( collectedCards );
108 takeState();
109
110 numberOfDeals++;
111
112 if (numberOfDeals == 3)
113 emit newCardsPossible(false);
114
115 return true;
116}
117
118void Grandf::deal( const QList<KCard*> & cardsToDeal )
119{
120 setKeyboardModeActive( false );
121
122 QList<KCard*> cards = cardsToDeal;
123
124 QPointF initPos( 1.4 * 3 * deck()->cardWidth(), 1.2 * deck()->cardHeight() );
125
126 int start = 0;
127 int stop = 7-1;
128 int dir = 1;
129
130 for (int round=0; round < 7; round++)
131 {
132 int i = start;
133 do
134 {
135 if (!cards.isEmpty())
136 addCardForDeal( store[i], cards.takeLast(), (i == start), initPos );
137 i += dir;
138 } while ( i != stop + dir);
139 int t = start;
140 start = stop;
141 stop = t+dir;
142 dir = -dir;
143 }
144
145 int i = 0;
146 while (!cards.isEmpty())
147 {
148 addCardForDeal( store[i+1], cards.takeLast(), true, initPos );
149 i = (i+1)%6;
150 }
151
152 for (int round=0; round < 7; round++)
153 {
154 KCard *c = store[round]->topCard();
155 if (c)
156 c->setFaceUp(true);
157 }
158
159 startDealAnimation();
160}
161
162bool Grandf::checkAdd(const PatPile * pile, const QList<KCard*> & oldCards, const QList<KCard*> & newCards) const
163{
164 switch (pile->pileRole())
165 {
166 case PatPile::Tableau:
167 if (oldCards.isEmpty())
168 return newCards.first()->rank() == KCardDeck::King;
169 else
170 return newCards.first()->rank() == oldCards.last()->rank() - 1
171 && newCards.first()->suit() == oldCards.last()->suit();
172 case PatPile::Foundation:
173 default:
174 return checkAddSameSuitAscendingFromAce(oldCards, newCards);
175 }
176}
177
178bool Grandf::checkRemove(const PatPile * pile, const QList<KCard*> & cards) const
179{
180 return pile->pileRole() == PatPile::Tableau && cards.first()->isFaceUp();
181}
182
183QString Grandf::getGameState() const
184{
185 return QString::number(numberOfDeals);
186}
187
188void Grandf::setGameState( const QString & state )
189{
190 numberOfDeals = state.toInt();
191 emit newCardsPossible(numberOfDeals < 3);
192}
193
194
195
196static class GrandfDealerInfo : public DealerInfo
197{
198public:
199 GrandfDealerInfo()
200 : DealerInfo(I18N_NOOP("Grandfather"), GrandfatherId)
201 {}
202
203 virtual DealerScene *createGame() const
204 {
205 return new Grandf( this );
206 }
207} grandfDealerInfo;
208
209
210#include "grandf.moc"
211