File indexing completed on 2024-05-12 04:04:51
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 "simon.h" 0038 0039 // own 0040 #include "dealerinfo.h" 0041 #include "patsolve/simonsolver.h" 0042 #include "pileutils.h" 0043 #include "settings.h" 0044 // KF 0045 #include <KLocalizedString> 0046 0047 Simon::Simon(const DealerInfo *di) 0048 : DealerScene(di) 0049 { 0050 } 0051 0052 void Simon::initialize() 0053 { 0054 setDeckContents(); 0055 0056 const qreal dist_x = 1.11; 0057 0058 for (int i = 0; i < 4; ++i) { 0059 target[i] = new PatPile(this, i + 1, QStringLiteral("target%1").arg(i)); 0060 target[i]->setPileRole(PatPile::Foundation); 0061 target[i]->setLayoutPos((i + 3) * dist_x, 0); 0062 target[i]->setSpread(0, 0); 0063 target[i]->setKeyboardSelectHint(KCardPile::NeverFocus); 0064 target[i]->setKeyboardDropHint(KCardPile::AutoFocusTop); 0065 } 0066 0067 for (int i = 0; i < 10; ++i) { 0068 store[i] = new PatPile(this, 5 + i, QStringLiteral("store%1").arg(i)); 0069 store[i]->setPileRole(PatPile::Tableau); 0070 store[i]->setLayoutPos(dist_x * i, 1.2); 0071 store[i]->setBottomPadding(2.5); 0072 store[i]->setHeightPolicy(KCardPile::GrowDown); 0073 store[i]->setZValue(0.01 * i); 0074 store[i]->setKeyboardSelectHint(KCardPile::AutoFocusDeepestRemovable); 0075 store[i]->setKeyboardDropHint(KCardPile::AutoFocusTop); 0076 } 0077 0078 setActions(DealerScene::Hint | DealerScene::Demo); 0079 auto solver = new SimonSolver(this); 0080 solver->default_max_positions = Settings::simpleSimonSolverIterationsLimit(); 0081 setSolver(solver); 0082 // setNeededFutureMoves( 1 ); // could be some nonsense moves 0083 } 0084 0085 void Simon::restart(const QList<KCard *> &cards) 0086 { 0087 QList<KCard *> cardList = cards; 0088 0089 QPointF initPos(0, -deck()->cardHeight()); 0090 0091 for (int piles = 9; piles >= 3; --piles) 0092 for (int j = 0; j < piles; ++j) 0093 addCardForDeal(store[j], cardList.takeLast(), true, initPos); 0094 0095 for (int j = 0; j < 10; ++j) 0096 addCardForDeal(store[j], cardList.takeLast(), true, initPos); 0097 0098 Q_ASSERT(cardList.isEmpty()); 0099 0100 startDealAnimation(); 0101 } 0102 0103 bool Simon::checkPrefering(const PatPile *pile, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) const 0104 { 0105 return pile->pileRole() == PatPile::Tableau && !oldCards.isEmpty() && oldCards.last()->suit() == newCards.first()->suit(); 0106 } 0107 0108 bool Simon::checkAdd(const PatPile *pile, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) const 0109 { 0110 if (pile->pileRole() == PatPile::Tableau) { 0111 if (!(oldCards.isEmpty() || oldCards.last()->rank() == newCards.first()->rank() + 1)) { 0112 return false; 0113 } 0114 0115 int seqs_count = countSameSuitDescendingSequences(newCards); 0116 0117 if (seqs_count < 0) 0118 return false; 0119 0120 // This is similar to the supermoves of Freecell - we can use empty 0121 // columns to temporarily hold intermediate sub-sequences which are 0122 // not the same suit - only a "false" parent. 0123 // Shlomi Fish 0124 0125 int empty_piles_count = 0; 0126 0127 for (int i = 0; i < 10; ++i) 0128 if (store[i]->isEmpty() && (store[i]->index() != pile->index())) 0129 empty_piles_count++; 0130 0131 return (seqs_count <= (1 << empty_piles_count)); 0132 } else { 0133 return oldCards.isEmpty() && newCards.first()->rank() == KCardDeck::King && newCards.last()->rank() == KCardDeck::Ace && isSameSuitDescending(newCards); 0134 } 0135 } 0136 0137 bool Simon::checkRemove(const PatPile *pile, const QList<KCard *> &cards) const 0138 { 0139 if (pile->pileRole() != PatPile::Tableau) 0140 return false; 0141 0142 int seqs_count = countSameSuitDescendingSequences(cards); 0143 return (seqs_count >= 0); 0144 } 0145 0146 QString Simon::solverFormat() const 0147 { 0148 QString output; 0149 QString tmp; 0150 for (int i = 0; i < 4; i++) { 0151 if (target[i]->isEmpty()) 0152 continue; 0153 tmp += suitToString(target[i]->topCard()->suit()) + QLatin1String("-K "); 0154 } 0155 if (!tmp.isEmpty()) 0156 output += QStringLiteral("Foundations: %1\n").arg(tmp); 0157 0158 for (int i = 0; i < 10; i++) { 0159 cardsListToLine(output, store[i]->cards()); 0160 } 0161 return output; 0162 } 0163 0164 static class SimonDealerInfo : public DealerInfo 0165 { 0166 public: 0167 SimonDealerInfo() 0168 : DealerInfo(kli18n("Simple Simon"), SimpleSimonId) 0169 { 0170 } 0171 0172 DealerScene *createGame() const override 0173 { 0174 return new Simon(this); 0175 } 0176 } simonDealerInfo; 0177 0178 #include "moc_simon.cpp"