File indexing completed on 2024-05-12 08:00:33
0001 /* 0002 * Copyright (C) 1995 Paul Olav Tvete <paul@troll.no> 0003 * Copyright (C) 2000-2009 Stephan Kulow <coolo@kde.org> 0004 * Copyright (C) 2010 Parker Coates <coates@kde.org> 0005 * 0006 * License of original code: 0007 * ------------------------------------------------------------------------- 0008 * Permission to use, copy, modify, and distribute this software and its 0009 * documentation for any purpose and without fee is hereby granted, 0010 * provided that the above copyright notice appear in all copies and that 0011 * both that copyright notice and this permission notice appear in 0012 * supporting documentation. 0013 * 0014 * This file is provided AS IS with no warranties of any kind. The author 0015 * shall have no liability with respect to the infringement of copyrights, 0016 * trade secrets or any patents by this file or any part thereof. In no 0017 * event will the author be liable for any lost revenue or profits or 0018 * other special, indirect and consequential damages. 0019 * ------------------------------------------------------------------------- 0020 * 0021 * License of modifications/additions made after 2009-01-01: 0022 * ------------------------------------------------------------------------- 0023 * This program is free software; you can redistribute it and/or 0024 * modify it under the terms of the GNU General Public License as 0025 * published by the Free Software Foundation; either version 2 of 0026 * the License, or (at your option) any later version. 0027 * 0028 * This program is distributed in the hope that it will be useful, 0029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0031 * GNU General Public License for more details. 0032 * 0033 * You should have received a copy of the GNU General Public License 0034 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0035 * ------------------------------------------------------------------------- 0036 */ 0037 0038 #include "grandf.h" 0039 0040 // own 0041 #include "dealerinfo.h" 0042 #include "patsolve/grandfsolver.h" 0043 #include "pileutils.h" 0044 #include "speeds.h" 0045 // KF 0046 #include <KLocalizedString> 0047 0048 Grandf::Grandf(const DealerInfo *di) 0049 : DealerScene(di) 0050 { 0051 } 0052 0053 void Grandf::initialize() 0054 { 0055 setDeckContents(); 0056 0057 const qreal distx = 1.4; 0058 const qreal targetOffset = 1.5 * distx; 0059 0060 for (int i = 0; i < 4; ++i) { 0061 target[i] = new PatPile(this, i + 1, QStringLiteral("target%1").arg(i)); 0062 target[i]->setPileRole(PatPile::Foundation); 0063 target[i]->setLayoutPos(targetOffset + i * distx, 0); 0064 target[i]->setSpread(0, 0); 0065 target[i]->setKeyboardSelectHint(KCardPile::NeverFocus); 0066 target[i]->setKeyboardDropHint(KCardPile::ForceFocusTop); 0067 } 0068 0069 for (int i = 0; i < 7; ++i) { 0070 store[i] = new PatPile(this, 5 + i, QStringLiteral("store%1").arg(i)); 0071 store[i]->setPileRole(PatPile::Tableau); 0072 store[i]->setLayoutPos(distx * i, 1.2); 0073 store[i]->setAutoTurnTop(true); 0074 store[i]->setBottomPadding(2.5); 0075 store[i]->setHeightPolicy(KCardPile::GrowDown); 0076 store[i]->setKeyboardSelectHint(KCardPile::FreeFocus); 0077 store[i]->setKeyboardDropHint(KCardPile::AutoFocusTop); 0078 } 0079 0080 setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Redeal); 0081 setSolver(new GrandfSolver(this)); 0082 } 0083 0084 void Grandf::restart(const QList<KCard *> &cards) 0085 { 0086 deal(cards); 0087 numberOfDeals = 1; 0088 Q_EMIT newCardsPossible(true); 0089 } 0090 0091 bool Grandf::newCards() 0092 { 0093 if (numberOfDeals >= 3) 0094 return false; 0095 0096 // NOTE: This is not quite correct. The piles should be turned face down 0097 // (i.e. partially reversed) during collection. 0098 QList<KCard *> collectedCards; 0099 for (int pos = 6; pos >= 0; --pos) { 0100 collectedCards << store[pos]->cards(); 0101 store[pos]->clear(); 0102 } 0103 deal(collectedCards); 0104 takeState(); 0105 0106 numberOfDeals++; 0107 0108 if (numberOfDeals == 3) 0109 Q_EMIT newCardsPossible(false); 0110 0111 return true; 0112 } 0113 0114 void Grandf::deal(const QList<KCard *> &cardsToDeal) 0115 { 0116 setKeyboardModeActive(false); 0117 0118 QList<KCard *> cards = cardsToDeal; 0119 0120 QPointF initPos(1.4 * 3 * deck()->cardWidth(), 1.2 * deck()->cardHeight()); 0121 0122 int start = 0; 0123 int stop = 7 - 1; 0124 int dir = 1; 0125 0126 for (int round = 0; round < 7; round++) { 0127 int i = start; 0128 do { 0129 if (!cards.isEmpty()) 0130 addCardForDeal(store[i], cards.takeLast(), (i == start), initPos); 0131 i += dir; 0132 } while (i != stop + dir); 0133 int t = start; 0134 start = stop; 0135 stop = t + dir; 0136 dir = -dir; 0137 } 0138 0139 int i = 0; 0140 while (!cards.isEmpty()) { 0141 addCardForDeal(store[i + 1], cards.takeLast(), true, initPos); 0142 i = (i + 1) % 6; 0143 } 0144 0145 for (int round = 0; round < 7; round++) { 0146 KCard *c = store[round]->topCard(); 0147 if (c) 0148 c->setFaceUp(true); 0149 } 0150 0151 startDealAnimation(); 0152 } 0153 0154 bool Grandf::checkAdd(const PatPile *pile, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) const 0155 { 0156 switch (pile->pileRole()) { 0157 case PatPile::Tableau: 0158 if (oldCards.isEmpty()) 0159 return newCards.first()->rank() == KCardDeck::King; 0160 else 0161 return newCards.first()->rank() == oldCards.last()->rank() - 1 && newCards.first()->suit() == oldCards.last()->suit(); 0162 case PatPile::Foundation: 0163 default: 0164 return checkAddSameSuitAscendingFromAce(oldCards, newCards); 0165 } 0166 } 0167 0168 bool Grandf::checkRemove(const PatPile *pile, const QList<KCard *> &cards) const 0169 { 0170 return pile->pileRole() == PatPile::Tableau && cards.first()->isFaceUp(); 0171 } 0172 0173 QString Grandf::getGameState() const 0174 { 0175 return QString::number(numberOfDeals); 0176 } 0177 0178 void Grandf::setGameState(const QString &state) 0179 { 0180 numberOfDeals = state.toInt(); 0181 Q_EMIT newCardsPossible(numberOfDeals < 3); 0182 } 0183 0184 static class GrandfDealerInfo : public DealerInfo 0185 { 0186 public: 0187 GrandfDealerInfo() 0188 : DealerInfo(kli18n("Grandfather"), GrandfatherId) 0189 { 0190 } 0191 0192 DealerScene *createGame() const override 0193 { 0194 return new Grandf(this); 0195 } 0196 } grandfDealerInfo; 0197 0198 #include "moc_grandf.cpp"