File indexing completed on 2024-05-12 08:00:35
0001 /* 0002 * Copyright (C) 1997 Rodolfo Borges <barrett@labma.ufrj.br> 0003 * Copyright (C) 1998-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 "mod3.h" 0039 0040 // own 0041 #include "dealerinfo.h" 0042 #include "patsolve/mod3solver.h" 0043 // KF 0044 #include <KLocalizedString> 0045 0046 Mod3::Mod3(const DealerInfo *di) 0047 : DealerScene(di) 0048 { 0049 } 0050 0051 void Mod3::initialize() 0052 { 0053 // Piles are placed very close together. Set layoutSpacing to 0 to prevent 0054 // interference between them. 0055 setLayoutSpacing(0.0); 0056 0057 const qreal dist_x = 1.114; 0058 const qreal dist_y = 1.31; 0059 const qreal bottomRowY = 3 * dist_y + 0.2; 0060 const qreal rightColumX = 8 * dist_x + 0.8; 0061 0062 // This patience uses 2 deck of cards. 0063 setDeckContents(2); 0064 0065 talon = new PatPile(this, 0, QStringLiteral("talon")); 0066 talon->setPileRole(PatPile::Stock); 0067 talon->setLayoutPos(rightColumX, bottomRowY); 0068 talon->setSpread(0, 0); 0069 talon->setKeyboardSelectHint(KCardPile::NeverFocus); 0070 talon->setKeyboardDropHint(KCardPile::NeverFocus); 0071 connect(talon, &KCardPile::clicked, this, &DealerScene::drawDealRowOrRedeal); 0072 0073 aces = new PatPile(this, 50, QStringLiteral("aces")); 0074 aces->setPileRole(PatPile::FoundationType1); 0075 aces->setLayoutPos(rightColumX, 0.5); 0076 aces->setBottomPadding(2.5); 0077 aces->setKeyboardSelectHint(KCardPile::NeverFocus); 0078 aces->setKeyboardDropHint(KCardPile::ForceFocusTop); 0079 0080 for (int r = 0; r < 4; ++r) { 0081 for (int c = 0; c < 8; ++c) { 0082 int pileIndex = r * 10 + c + 1; 0083 QString objectName = QStringLiteral("stack%1_%2").arg(r).arg(c); 0084 stack[r][c] = new PatPile(this, pileIndex, objectName); 0085 0086 // The first 3 rows are the playing field, the fourth is the store. 0087 if (r < 3) { 0088 stack[r][c]->setLayoutPos(dist_x * c, dist_y * r); 0089 // Very tight spread makes it easy to quickly tell number of 0090 // cards in each pile and we don't care about the cards beneath. 0091 stack[r][c]->setSpread(0, 0.08); 0092 stack[r][c]->setBottomPadding(0.23); 0093 } else { 0094 stack[r][c]->setLayoutPos(dist_x * c, bottomRowY); 0095 stack[r][c]->setBottomPadding(0.8); 0096 } 0097 stack[r][c]->setPileRole(r == 0 ? PatPile::FoundationType2 0098 : r == 1 ? PatPile::FoundationType3 0099 : r == 2 ? PatPile::FoundationType4 0100 : PatPile::Tableau); 0101 stack[r][c]->setHeightPolicy(KCardPile::GrowDown); 0102 stack[r][c]->setKeyboardSelectHint(KCardPile::AutoFocusTop); 0103 stack[r][c]->setKeyboardDropHint(KCardPile::AutoFocusTop); 0104 } 0105 } 0106 0107 setActions(DealerScene::Hint | DealerScene::Demo | DealerScene::Deal); 0108 setSolver(new Mod3Solver(this)); 0109 } 0110 0111 bool mod3CheckAdd(int baseRank, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) 0112 { 0113 if (oldCards.isEmpty()) 0114 return newCards.first()->rank() == baseRank; 0115 else 0116 return oldCards.first()->rank() == baseRank && newCards.first()->suit() == oldCards.last()->suit() 0117 && newCards.first()->rank() == oldCards.last()->rank() + 3; 0118 } 0119 0120 bool Mod3::checkAdd(const PatPile *pile, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) const 0121 { 0122 switch (pile->pileRole()) { 0123 case PatPile::FoundationType1: 0124 return newCards.size() == 1 && newCards.first()->rank() == KCardDeck::Ace; 0125 case PatPile::FoundationType2: 0126 return mod3CheckAdd(KCardDeck::Two, oldCards, newCards); 0127 case PatPile::FoundationType3: 0128 return mod3CheckAdd(KCardDeck::Three, oldCards, newCards); 0129 case PatPile::FoundationType4: 0130 return mod3CheckAdd(KCardDeck::Four, oldCards, newCards); 0131 case PatPile::Tableau: 0132 return oldCards.isEmpty(); 0133 case PatPile::Stock: 0134 default: 0135 return false; 0136 } 0137 } 0138 0139 bool Mod3::checkRemove(const PatPile *pile, const QList<KCard *> &cards) const 0140 { 0141 switch (pile->pileRole()) { 0142 case PatPile::FoundationType2: 0143 case PatPile::FoundationType3: 0144 case PatPile::FoundationType4: 0145 case PatPile::Tableau: 0146 return cards.first() == pile->topCard(); 0147 case PatPile::FoundationType1: 0148 case PatPile::Stock: 0149 default: 0150 return false; 0151 } 0152 } 0153 0154 void Mod3::cardsMoved(const QList<KCard *> &cards, KCardPile *oldPile, KCardPile *newPile) 0155 { 0156 if (oldPile->isEmpty() && !talon->isEmpty()) { 0157 PatPile *p = dynamic_cast<PatPile *>(oldPile); 0158 if (p && p->pileRole() == PatPile::Tableau) 0159 flipCardToPile(talon->topCard(), oldPile, DURATION_MOVE); 0160 } 0161 0162 DealerScene::cardsMoved(cards, oldPile, newPile); 0163 } 0164 0165 void Mod3::restart(const QList<KCard *> &cards) 0166 { 0167 for (KCard *c : cards) { 0168 c->setPos(talon->pos()); 0169 c->setFaceUp(false); 0170 talon->add(c); 0171 } 0172 0173 for (int r = 0; r < 4; r++) { 0174 for (int c = 0; c < 8; ++c) { 0175 KCard *card = talon->topCard(); 0176 card->setFaceUp(true); 0177 // moveCardToPileAtSpeed( card, stack[r][c], DEAL_SPEED ); 0178 0179 addCardForDeal(stack[r][c], card, true, talon->pos()); 0180 0181 // Fudge the z values to keep cards from popping through one another. 0182 card->setZValue(card->zValue() + ((4 - r) * (4 - r)) + ((8 - c) * (8 - c))); 0183 } 0184 } 0185 0186 startDealAnimation(); 0187 Q_EMIT newCardsPossible(true); 0188 } 0189 0190 bool Mod3::newCards() 0191 { 0192 if (talon->isEmpty()) 0193 return false; 0194 0195 for (int c = 0; c < 8; ++c) { 0196 if (talon->isEmpty()) 0197 break; 0198 0199 flipCardToPileAtSpeed(talon->topCard(), stack[3][c], DEAL_SPEED * 2); 0200 } 0201 0202 if (talon->isEmpty()) 0203 Q_EMIT newCardsPossible(false); 0204 0205 return true; 0206 } 0207 0208 void Mod3::setGameState(const QString &state) 0209 { 0210 Q_UNUSED(state); 0211 Q_EMIT newCardsPossible(!talon->isEmpty()); 0212 } 0213 0214 static class Mod3DealerInfo : public DealerInfo 0215 { 0216 public: 0217 Mod3DealerInfo() 0218 : DealerInfo(kli18n("Mod3"), Mod3Id) 0219 { 0220 } 0221 0222 DealerScene *createGame() const override 0223 { 0224 return new Mod3(this); 0225 } 0226 } mod3DealerInfo; 0227 0228 #include "moc_mod3.cpp"