File indexing completed on 2024-05-12 04:04:48
0001 /* 0002 * Copyright (C) 2000-2009 Stephan Kulow <coolo@kde.org> 0003 * Copyright (C) 2010 Parker Coates <coates@kde.org> 0004 * 0005 * License of original code: 0006 * ------------------------------------------------------------------------- 0007 * Permission to use, copy, modify, and distribute this software and its 0008 * documentation for any purpose and without fee is hereby granted, 0009 * provided that the above copyright notice appear in all copies and that 0010 * both that copyright notice and this permission notice appear in 0011 * supporting documentation. 0012 * 0013 * This file is provided AS IS with no warranties of any kind. The author 0014 * shall have no liability with respect to the infringement of copyrights, 0015 * trade secrets or any patents by this file or any part thereof. In no 0016 * event will the author be liable for any lost revenue or profits or 0017 * other special, indirect and consequential damages. 0018 * ------------------------------------------------------------------------- 0019 * 0020 * License of modifications/additions made after 2009-01-01: 0021 * ------------------------------------------------------------------------- 0022 * This program is free software; you can redistribute it and/or 0023 * modify it under the terms of the GNU General Public License as 0024 * published by the Free Software Foundation; either version 2 of 0025 * the License, or (at your option) any later version. 0026 * 0027 * This program is distributed in the hope that it will be useful, 0028 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0029 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0030 * GNU General Public License for more details. 0031 * 0032 * You should have received a copy of the GNU General Public License 0033 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0034 * ------------------------------------------------------------------------- 0035 */ 0036 0037 #include "fortyeight.h" 0038 0039 // own 0040 #include "dealerinfo.h" 0041 #include "patsolve/fortyeightsolver.h" 0042 #include "pileutils.h" 0043 #include "speeds.h" 0044 // KF 0045 #include <KLocalizedString> 0046 0047 Fortyeight::Fortyeight(const DealerInfo *di) 0048 : DealerScene(di) 0049 { 0050 } 0051 0052 void Fortyeight::initialize() 0053 { 0054 const qreal dist_x = 1.11; 0055 const qreal smallNeg = -1e-6; 0056 0057 setDeckContents(2); 0058 0059 talon = new PatPile(this, 0, QStringLiteral("talon")); 0060 talon->setPileRole(PatPile::Stock); 0061 talon->setLayoutPos(7 * dist_x, smallNeg); 0062 talon->setZValue(20); 0063 talon->setSpread(0, 0); 0064 talon->setKeyboardSelectHint(KCardPile::NeverFocus); 0065 talon->setKeyboardDropHint(KCardPile::NeverFocus); 0066 connect(talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal); 0067 0068 pile = new PatPile(this, 20, QStringLiteral("pile")); 0069 pile->setPileRole(PatPile::Waste); 0070 pile->setLayoutPos(6 * dist_x, smallNeg); 0071 pile->setLeftPadding(6 * dist_x); 0072 pile->setWidthPolicy(KCardPile::GrowLeft); 0073 pile->setSpread(-0.21, 0); 0074 pile->setKeyboardSelectHint(KCardPile::AutoFocusTop); 0075 pile->setKeyboardDropHint(KCardPile::NeverFocus); 0076 0077 for (int i = 0; i < 8; ++i) { 0078 target[i] = new PatPile(this, 9 + i, QStringLiteral("target%1").arg(i)); 0079 target[i]->setPileRole(PatPile::Foundation); 0080 target[i]->setLayoutPos(dist_x * i, 0); 0081 target[i]->setSpread(0, 0); 0082 target[i]->setKeyboardSelectHint(KCardPile::NeverFocus); 0083 target[i]->setKeyboardDropHint(KCardPile::ForceFocusTop); 0084 } 0085 0086 for (int i = 0; i < 8; ++i) { 0087 stack[i] = new PatPile(this, 1 + i, QStringLiteral("stack%1").arg(i)); 0088 stack[i]->setPileRole(PatPile::Tableau); 0089 stack[i]->setLayoutPos(dist_x * i, 1.1); 0090 stack[i]->setAutoTurnTop(true); 0091 stack[i]->setSpread(0, 0.25); 0092 stack[i]->setBottomPadding(1.75); 0093 stack[i]->setHeightPolicy(KCardPile::GrowDown); 0094 stack[i]->setKeyboardSelectHint(KCardPile::FreeFocus); 0095 stack[i]->setKeyboardDropHint(KCardPile::AutoFocusTop); 0096 } 0097 0098 setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Draw); 0099 setSolver(new FortyeightSolver(this)); 0100 } 0101 0102 void Fortyeight::restart(const QList<KCard *> &cards) 0103 { 0104 lastdeal = false; 0105 0106 QList<KCard *> cardList = cards; 0107 0108 for (int r = 0; r < 4; ++r) { 0109 for (int column = 0; column < 8; ++column) { 0110 QPointF initPos = stack[column]->pos() - QPointF(0, 2 * deck()->cardHeight()); 0111 addCardForDeal(stack[column], cardList.takeLast(), true, initPos); 0112 } 0113 } 0114 0115 while (!cardList.isEmpty()) { 0116 KCard *c = cardList.takeFirst(); 0117 c->setPos(talon->pos()); 0118 c->setFaceUp(false); 0119 talon->add(c); 0120 } 0121 0122 startDealAnimation(); 0123 0124 flipCardToPile(talon->topCard(), pile, DURATION_MOVE); 0125 0126 Q_EMIT newCardsPossible(true); 0127 } 0128 0129 bool Fortyeight::newCards() 0130 { 0131 if (talon->isEmpty()) { 0132 if (lastdeal) { 0133 return false; 0134 } else { 0135 lastdeal = true; 0136 flipCardsToPile(pile->cards(), talon, DURATION_MOVE); 0137 } 0138 } else { 0139 flipCardToPile(talon->topCard(), pile, DURATION_MOVE); 0140 setKeyboardFocus(pile->topCard()); 0141 } 0142 0143 if (talon->isEmpty() && lastdeal) 0144 Q_EMIT newCardsPossible(false); 0145 0146 return true; 0147 } 0148 0149 void Fortyeight::cardsDroppedOnPile(const QList<KCard *> &cards, KCardPile *pile) 0150 { 0151 if (cards.size() <= 1) { 0152 DealerScene::moveCardsToPile(cards, pile, DURATION_MOVE); 0153 return; 0154 } 0155 0156 QList<KCardPile *> freePiles; 0157 for (int i = 0; i < 8; ++i) 0158 if (stack[i]->isEmpty() && stack[i] != pile) 0159 freePiles << stack[i]; 0160 0161 multiStepMove(cards, pile, freePiles, QList<KCardPile *>(), DURATION_MOVE); 0162 } 0163 0164 bool Fortyeight::canPutStore(const KCardPile *pile, const QList<KCard *> &cards) const 0165 { 0166 int frees = 0; 0167 for (int i = 0; i < 8; i++) 0168 if (stack[i]->isEmpty()) 0169 frees++; 0170 0171 if (pile->isEmpty()) // destination is empty 0172 frees--; 0173 0174 if (int(cards.count()) > 1 << frees) 0175 return false; 0176 0177 // ok if the target is empty 0178 if (pile->isEmpty()) 0179 return true; 0180 0181 KCard *c = cards.first(); // we assume there are only valid sequences 0182 0183 return pile->topCard()->suit() == c->suit() && pile->topCard()->rank() == c->rank() + 1; 0184 } 0185 0186 bool Fortyeight::checkAdd(const PatPile *pile, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) const 0187 { 0188 switch (pile->pileRole()) { 0189 case PatPile::Foundation: 0190 return checkAddSameSuitAscendingFromAce(oldCards, newCards); 0191 case PatPile::Tableau: 0192 return canPutStore(pile, newCards); 0193 case PatPile::Stock: 0194 case PatPile::Waste: 0195 default: 0196 return false; 0197 } 0198 } 0199 0200 bool Fortyeight::checkRemove(const PatPile *pile, const QList<KCard *> &cards) const 0201 { 0202 switch (pile->pileRole()) { 0203 case PatPile::Waste: 0204 return cards.first() == pile->topCard(); 0205 case PatPile::Tableau: 0206 return isSameSuitDescending(cards); 0207 case PatPile::Foundation: 0208 case PatPile::Stock: 0209 default: 0210 return false; 0211 } 0212 } 0213 0214 QString Fortyeight::getGameState() const 0215 { 0216 return QString::number(lastdeal); 0217 } 0218 0219 void Fortyeight::setGameState(const QString &state) 0220 { 0221 lastdeal = state.toInt(); 0222 Q_EMIT newCardsPossible(!lastdeal || !talon->isEmpty()); 0223 } 0224 0225 static class FortyEightDealerInfo : public DealerInfo 0226 { 0227 public: 0228 FortyEightDealerInfo() 0229 : DealerInfo(kli18n("Forty & Eight"), FortyAndEightId) 0230 { 0231 } 0232 0233 DealerScene *createGame() const override 0234 { 0235 return new Fortyeight(this); 0236 } 0237 } fortyEightDealerInfo; 0238 0239 #include "moc_fortyeight.cpp"