summaryrefslogtreecommitdiffstats
path: root/kpat/napoleon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpat/napoleon.cpp')
-rw-r--r--kpat/napoleon.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/kpat/napoleon.cpp b/kpat/napoleon.cpp
new file mode 100644
index 00000000..ffdf245c
--- /dev/null
+++ b/kpat/napoleon.cpp
@@ -0,0 +1,204 @@
+/*
+ napoleon.cpp implements a patience card game
+
+ Copyright (C) 1995 Paul Olav Tvete
+
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+
+ */
+
+#include "napoleon.h"
+#include <klocale.h>
+#include "deck.h"
+#include "cardmaps.h"
+
+Napoleon::Napoleon( KMainWindow* parent, const char* _name )
+ : Dealer( parent, _name )
+{
+ deck = Deck::new_deck( this );
+ connect(deck, SIGNAL(clicked(Card *)), SLOT(deal1(Card*)));
+
+ pile = new Pile( 1, this );
+ pile->setAddFlags( Pile::disallow );
+
+ for (int i = 0; i < 4; i++)
+ {
+ store[i] = new Pile( 2 + i, this );
+ store[i]->setCheckIndex( 0 );
+ target[i] = new Pile( 6 + i, this);
+ target[i]->setRemoveFlags( Pile::disallow );
+ target[i]->setCheckIndex(2);
+ target[i]->setTarget(true);
+ }
+
+ const int dist_store = cardMap::CARDX() * 55 / 100;
+ const int dist_target = dist_store / 2;
+ const int centre_x = 10 + cardMap::CARDX() + dist_store;
+ const int centre_y = 10 + cardMap::CARDY() + dist_store;
+
+ deck->move( centre_x + cardMap::CARDX() * 47 / 10, centre_y + cardMap::CARDY() + dist_store);
+ pile->move( centre_x + cardMap::CARDX() * 33 / 10, centre_y + cardMap::CARDY() + dist_store);
+
+ centre = new Pile( 10, this );
+ centre->setRemoveFlags( Pile::disallow );
+ centre->setCheckIndex(1);
+ centre->setTarget(true);
+
+ store[0]->move( centre_x, centre_y - cardMap::CARDY() - dist_store );
+ store[1]->move( centre_x + cardMap::CARDX() + dist_store, centre_y);
+ store[2]->move( centre_x, centre_y + cardMap::CARDY() + dist_store );
+ store[3]->move( centre_x - cardMap::CARDX() - dist_store, centre_y);
+ target[0]->move( centre_x - cardMap::CARDX() - dist_target, centre_y - cardMap::CARDY() - dist_target );
+ target[1]->move( centre_x + cardMap::CARDX() + dist_target, centre_y - cardMap::CARDY() - dist_target);
+ target[2]->move( centre_x + cardMap::CARDX() + dist_target, centre_y + cardMap::CARDY() + dist_target);
+ target[3]->move( centre_x - cardMap::CARDX() - dist_target, centre_y + cardMap::CARDY() + dist_target);
+ centre->move(centre_x, centre_y);
+
+ setActions(Dealer::Hint | Dealer::Demo);
+}
+
+void Napoleon::restart() {
+ deck->collectAndShuffle();
+ deal();
+}
+
+bool Napoleon::CanPutTarget( const Pile* c1, const CardList& cl) const {
+ Card *c2 = cl.first();
+
+ if (c1->isEmpty())
+ return c2->rank() == Card::Seven;
+ else
+ return (c2->rank() == c1->top()->rank() + 1);
+}
+
+bool Napoleon::CanPutCentre( const Pile* c1, const CardList& cl) const {
+ Card *c2 = cl.first();
+
+ if (c1->isEmpty())
+ return c2->rank() == Card::Six;
+
+ if (c1->top()->rank() == Card::Ace)
+ return (c2->rank() == Card::Six);
+ else
+ return (c2->rank() == c1->top()->rank() - 1);
+}
+
+bool Napoleon::checkAdd( int checkIndex, const Pile *c1, const CardList& c2) const
+{
+ switch (checkIndex) {
+ case 0:
+ return c1->isEmpty();
+ case 1:
+ return CanPutCentre(c1, c2);
+ case 2:
+ return CanPutTarget(c1, c2);
+ default:
+ return false;
+ }
+}
+
+void Napoleon::deal() {
+ if (deck->isEmpty())
+ return;
+
+ for (int i=0; i<4; i++)
+ store[i]->add(deck->nextCard(), false, false);
+}
+
+void Napoleon::deal1(Card *) {
+ Card *c = deck->nextCard();
+ if (!c)
+ return;
+ pile->add(c, true, false);
+ c->move(deck->x(), deck->y());
+ c->flipTo(int(pile->x()), int(pile->y()), 8);
+}
+
+Card *Napoleon::demoNewCards()
+{
+ if (deck->isEmpty())
+ return 0;
+ deal1(0);
+ return pile->top();
+}
+
+void Napoleon::getHints() {
+ CardList cards;
+ for (int i = 0; i < 4; i++)
+ {
+ if (!store[i]->isEmpty())
+ cards.append(store[i]->top());
+ }
+ if (pile->top())
+ cards.append(pile->top());
+
+ for (CardList::Iterator it = cards.begin(); it != cards.end(); ++it) {
+ CardList empty;
+ empty.append(*it);
+ if (CanPutCentre(centre, empty)) {
+ newHint(new MoveHint(*it, centre));
+ continue;
+ }
+ for (int i = 0; i < 4; i++) {
+ if (CanPutTarget(target[i], empty)) {
+ newHint(new MoveHint(*it, target[i]));
+ break;
+ }
+ }
+ }
+ if (pile->isEmpty())
+ return;
+
+ for (int i = 0; i < 4; i++) {
+ if (store[i]->isEmpty()) {
+ newHint(new MoveHint(pile->top(), store[i]));
+ return;
+ }
+ }
+}
+
+bool Napoleon::isGameLost() const
+{
+ CardList cards;
+ for (int i = 0; i < 4; i++)
+ {
+ if (store[i]->isEmpty())
+ return false;
+ else
+ cards.append(store[i]->top());
+ }
+
+ if (pile->top())
+ cards.append(pile->top());
+
+ for (CardList::Iterator it = cards.begin(); it != cards.end(); ++it) {
+ CardList empty;
+ empty.append(*it);
+ if(CanPutCentre(centre,empty)) return false;
+ for(int i=0; i<4; i++)
+ if(CanPutTarget(target[i],empty)) return false;
+ }
+
+ return (deck->isEmpty());
+}
+
+
+
+static class LocalDealerInfo4 : public DealerInfo
+{
+public:
+ LocalDealerInfo4() : DealerInfo(I18N_NOOP("&Napoleon's Tomb"), 4) {}
+ virtual Dealer *createGame(KMainWindow *parent) { return new Napoleon(parent); }
+} ldi3;
+
+#include "napoleon.moc"