1 /*
2  * Copyright (C) 2001-2009 Stephan Kulow <coolo@kde.org>
3  * Copyright (C) 2010 Parker Coates <coates@kde.org>
4  *
5  * License of original code:
6  * -------------------------------------------------------------------------
7  *   Permission to use, copy, modify, and distribute this software and its
8  *   documentation for any purpose and without fee is hereby granted,
9  *   provided that the above copyright notice appear in all copies and that
10  *   both that copyright notice and this permission notice appear in
11  *   supporting documentation.
12  *
13  *   This file is provided AS IS with no warranties of any kind.  The author
14  *   shall have no liability with respect to the infringement of copyrights,
15  *   trade secrets or any patents by this file or any part thereof.  In no
16  *   event will the author be liable for any lost revenue or profits or
17  *   other special, indirect and consequential damages.
18  * -------------------------------------------------------------------------
19  *
20  * License of modifications/additions made after 2009-01-01:
21  * -------------------------------------------------------------------------
22  *   This program is free software; you can redistribute it and/or
23  *   modify it under the terms of the GNU General Public License as
24  *   published by the Free Software Foundation; either version 2 of
25  *   the License, or (at your option) any later version.
26  *
27  *   This program is distributed in the hope that it will be useful,
28  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  *   GNU General Public License for more details.
31  *
32  *   You should have received a copy of the GNU General Public License
33  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
34  * -------------------------------------------------------------------------
35  */
36 
37 #include "golf.h"
38 
39 // own
40 #include "dealerinfo.h"
41 #include "speeds.h"
42 #include "patsolve/golfsolver.h"
43 #include "pileutils.h"
44 #include "settings.h"
45 // KF
46 #include <KLocalizedString>
47 
48 
Golf(const DealerInfo * di)49 Golf::Golf( const DealerInfo * di )
50   : DealerScene( di )
51 {
52 }
53 
54 
initialize()55 void Golf::initialize()
56 {
57     const qreal dist_x = 1.11;
58     const qreal smallNeg = -1e-6;
59 
60     setDeckContents();
61 
62     talon = new PatPile( this, 0, QStringLiteral("talon") );
63     talon->setPileRole(PatPile::Stock);
64     talon->setLayoutPos(0, smallNeg);
65     talon->setSpread(0, 0);
66     talon->setKeyboardSelectHint( KCardPile::NeverFocus );
67     talon->setKeyboardDropHint( KCardPile::NeverFocus );
68     connect( talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal );
69 
70     waste = new PatPile( this, 8, QStringLiteral("waste") );
71     waste->setPileRole(PatPile::Foundation);
72     waste->setLayoutPos(1.1, smallNeg);
73     waste->setSpread(0.12, 0);
74     waste->setRightPadding( 5 * dist_x );
75     waste->setWidthPolicy( KCardPile::GrowRight );
76     waste->setKeyboardSelectHint( KCardPile::NeverFocus );
77     waste->setKeyboardDropHint( KCardPile::AutoFocusTop );
78 
79     for( int r = 0; r < 7; ++r )
80     {
81         stack[r] = new PatPile( this, 1 + r, QStringLiteral("stack%1").arg(r) );
82         stack[r]->setPileRole(PatPile::Tableau);
83         stack[r]->setLayoutPos(r*dist_x,0);
84         // Manual tweak of the pile z values to make some animations better.
85         stack[r]->setZValue((7-r)/100.0);
86         stack[r]->setBottomPadding( 1.3 );
87         stack[r]->setHeightPolicy( KCardPile::GrowDown );
88         stack[r]->setKeyboardSelectHint( KCardPile::AutoFocusTop );
89         stack[r]->setKeyboardDropHint( KCardPile::NeverFocus );
90     }
91 
92     setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Draw);
93     auto solver = new GolfSolver( this );
94     solver->default_max_positions = Settings::golfSolverIterationsLimit();
95     setSolver( solver );
96 
97     connect( this, &KCardScene::cardClicked, this, &DealerScene::tryAutomaticMove );
98 }
99 
100 
checkAdd(const PatPile * pile,const QList<KCard * > & oldCards,const QList<KCard * > & newCards) const101 bool Golf::checkAdd(const PatPile * pile, const QList<KCard*> & oldCards, const QList<KCard*> & newCards) const
102 {
103     return pile->pileRole() == PatPile::Foundation
104            && ( newCards.first()->rank() == oldCards.last()->rank() + 1
105                 || newCards.first()->rank() == oldCards.last()->rank() - 1 );
106 }
107 
108 
checkRemove(const PatPile * pile,const QList<KCard * > & cards) const109 bool Golf::checkRemove(const PatPile * pile, const QList<KCard*> & cards) const
110 {
111     return pile->pileRole() == PatPile::Tableau
112            && cards.first() == pile->topCard();
113 }
114 
115 
restart(const QList<KCard * > & cards)116 void Golf::restart( const QList<KCard*> & cards )
117 {
118     QList<KCard*> cardList = cards;
119 
120     for ( int i = 0; i < 5; ++i )
121         for ( int r = 0; r < 7; ++r )
122             addCardForDeal( stack[r], cardList.takeLast(), true, stack[6]->pos() );
123 
124     while ( !cardList.isEmpty() )
125     {
126         KCard * c = cardList.takeFirst();
127         c->setPos( talon->pos() );
128         c->setFaceUp( false );
129         talon->add( c );
130     }
131 
132     startDealAnimation();
133 
134     flipCardToPile(talon->topCard(), waste, DURATION_MOVE);
135 
136     Q_EMIT newCardsPossible( true );
137 }
138 
139 
newCards()140 bool Golf::newCards()
141 {
142     if ( talon->isEmpty() )
143          return false;
144 
145     flipCardToPile(talon->topCard(), waste, DURATION_MOVE);
146 
147     if ( talon->isEmpty() )
148         Q_EMIT newCardsPossible( false );
149 
150     return true;
151 }
152 
153 
drop()154 bool Golf::drop()
155 {
156     for ( int i = 0; i < 7; ++i )
157         if ( !stack[i]->isEmpty() )
158             return false;
159 
160     if ( !talon->isEmpty() )
161     {
162         flipCardToPile( talon->topCard(), waste, DURATION_MOVE );
163         takeState();
164         return true;
165     }
166 
167     return false;
168 }
169 
170 
setGameState(const QString & state)171 void Golf::setGameState( const QString & state )
172 {
173     Q_UNUSED( state );
174     Q_EMIT newCardsPossible( !talon->isEmpty() );
175 }
176 
solverFormat() const177 QString Golf::solverFormat() const
178 {
179     QString output;
180     output += QLatin1String("Foundations: ") + (waste->isEmpty() ? QLatin1String("-") : cardToRankSuitString(waste->topCard())) + QLatin1Char('\n');
181     output += QLatin1String("Talon:");
182     for ( int i = talon->count()-1; i >= 0; --i )
183     {
184         output += QLatin1Char(' ')+cardToRankSuitString(talon->at( i ));
185     }
186     output += QLatin1Char('\n');
187     for (int i = 0; i < 7 ; i++)
188         cardsListToLine(output, stack[i]->cards());
189     return output;
190 }
191 
192 static class GolfDealerInfo : public DealerInfo
193 {
194 public:
GolfDealerInfo()195     GolfDealerInfo()
196       : DealerInfo(I18N_NOOP("Golf"), GolfId)
197     {}
198 
createGame() const199     DealerScene *createGame() const override
200     {
201         return new Golf( this );
202     }
203 } golfDealerInfo;
204 
205 
206 
207