File indexing completed on 2024-05-12 08:00:31

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 "clock.h"
0038 
0039 // own
0040 #include "dealerinfo.h"
0041 #include "patsolve/clocksolver.h"
0042 // KF
0043 #include <KLocalizedString>
0044 
0045 Clock::Clock(const DealerInfo *di)
0046     : DealerScene(di)
0047 {
0048 }
0049 
0050 void Clock::initialize()
0051 {
0052     setSceneAlignment(AlignHCenter | AlignVCenter);
0053 
0054     setDeckContents();
0055 
0056     const qreal dist_x = 1.11;
0057     const qreal ys[12] = {0. / 96, 15. / 96, 52. / 96, 158. / 96, 264. / 96, 301. / 96, 316. / 96, 301. / 96, 264. / 96, 158. / 96, 52. / 96, 15. / 96};
0058     const qreal xs[12] = {200. / 72, 280. / 72, 360. / 72, 400. / 72, 360. / 72, 280. / 72, 200. / 72, 120. / 72, 40. / 72, 0. / 72, 40. / 72, 120. / 72};
0059 
0060     for (int i = 0; i < 12; ++i) {
0061         target[i] = new PatPile(this, i + 1, QStringLiteral("target%1").arg(i));
0062         target[i]->setPileRole(PatPile::Foundation);
0063         target[i]->setLayoutPos(4 * dist_x + 0.4 + xs[i], 0.2 + ys[i]);
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 < 8; ++i) {
0070         store[i] = new PatPile(this, 14 + i, QStringLiteral("store%1").arg(i));
0071         store[i]->setPileRole(PatPile::Tableau);
0072         store[i]->setLayoutPos(dist_x * (i % 4), 2.5 * (i / 4));
0073         store[i]->setBottomPadding(1.3);
0074         store[i]->setKeyboardSelectHint(KCardPile::AutoFocusTop);
0075         store[i]->setKeyboardDropHint(KCardPile::AutoFocusTop);
0076     }
0077 
0078     setActions(DealerScene::Hint | DealerScene::Demo);
0079     setSolver(new ClockSolver(this));
0080 }
0081 
0082 void Clock::restart(const QList<KCard *> &cards)
0083 {
0084     static const KCardDeck::Suit suits[12] = {KCardDeck::Diamonds,
0085                                               KCardDeck::Spades,
0086                                               KCardDeck::Hearts,
0087                                               KCardDeck::Clubs,
0088                                               KCardDeck::Diamonds,
0089                                               KCardDeck::Spades,
0090                                               KCardDeck::Hearts,
0091                                               KCardDeck::Clubs,
0092                                               KCardDeck::Diamonds,
0093                                               KCardDeck::Spades,
0094                                               KCardDeck::Hearts,
0095                                               KCardDeck::Clubs};
0096     static const KCardDeck::Rank ranks[12] = {KCardDeck::Nine,
0097                                               KCardDeck::Ten,
0098                                               KCardDeck::Jack,
0099                                               KCardDeck::Queen,
0100                                               KCardDeck::King,
0101                                               KCardDeck::Two,
0102                                               KCardDeck::Three,
0103                                               KCardDeck::Four,
0104                                               KCardDeck::Five,
0105                                               KCardDeck::Six,
0106                                               KCardDeck::Seven,
0107                                               KCardDeck::Eight};
0108 
0109     const QPointF center = (target[0]->pos() + target[6]->pos()) / 2;
0110 
0111     int j = 0;
0112     QList<KCard *> cardList = cards;
0113     while (!cardList.isEmpty()) {
0114         KCard *c = cardList.takeLast();
0115         for (int i = 0; i < 12; ++i) {
0116             if (c->rank() == ranks[i] && c->suit() == suits[i]) {
0117                 QPointF initPos = (2 * center + target[(i + 2) % 12]->pos()) / 3;
0118                 addCardForDeal(target[i], c, true, initPos);
0119                 c = nullptr;
0120                 break;
0121             }
0122         }
0123         if (c) {
0124             addCardForDeal(store[j], c, true, store[j < 4 ? 0 : 4]->pos());
0125             j = (j + 1) % 8;
0126         }
0127     }
0128 
0129     startDealAnimation();
0130 }
0131 
0132 bool Clock::drop()
0133 {
0134     return false;
0135 }
0136 
0137 bool Clock::checkAdd(const PatPile *pile, const QList<KCard *> &oldCards, const QList<KCard *> &newCards) const
0138 {
0139     if (pile->pileRole() == PatPile::Tableau) {
0140         return oldCards.isEmpty() || newCards.first()->rank() == oldCards.last()->rank() - 1;
0141     } else {
0142         return oldCards.last()->suit() == newCards.first()->suit()
0143             && (newCards.first()->rank() == oldCards.last()->rank() + 1
0144                 || (oldCards.last()->rank() == KCardDeck::King && newCards.first()->rank() == KCardDeck::Ace));
0145     }
0146 }
0147 
0148 bool Clock::checkRemove(const PatPile *pile, const QList<KCard *> &cards) const
0149 {
0150     return pile->pileRole() == PatPile::Tableau && cards.first() == pile->topCard();
0151 }
0152 
0153 static class ClockDealerInfo : public DealerInfo
0154 {
0155 public:
0156     ClockDealerInfo()
0157         : DealerInfo(kli18n("Grandfather's Clock"), GrandfathersClockId)
0158     {
0159     }
0160 
0161     DealerScene *createGame() const override
0162     {
0163         return new Clock(this);
0164     }
0165 } clockDealerInfo;
0166 
0167 #include "moc_clock.cpp"