/*--------------------------------------------------------------------------- mod3.cpp implements a patience card game Copyright (C) 1997 Rodolfo Borges * 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 "mod3.h" #include "cardmaps.h" #include <klocale.h> #include "deck.h" #include <kdebug.h> //-------------------------------------------------------------------------// Mod3::Mod3( TDEMainWindow* parent, const char* _name) : Dealer( parent, _name ) { const int dist_x = cardMap::CARDX() * 11 / 10 + 1; const int dist_y = cardMap::CARDY() * 11 / 10 + 1; const int margin = cardMap::CARDY() / 3; // This patience uses 2 deck of cards. deck = Deck::new_deck( this, 2); deck->move(8 + dist_x * 8 + 20, 8 + dist_y * 3 + margin); connect(deck, TQT_SIGNAL(clicked(Card*)), TQT_SLOT(deckClicked(Card*))); aces = new Pile(50, this); aces->move(16 + dist_x * 8, 8 + dist_y / 2); aces->setTarget(true); aces->setCheckIndex(2); aces->setAddFlags(Pile::addSpread | Pile::several); for ( int r = 0; r < 4; r++ ) { for ( int c = 0; c < 8; c++ ) { stack[r][c] = new Pile ( r * 10 + c + 1, this ); stack[r][c]->move( 8 + dist_x * c, 8 + dist_y * r + margin * ( r == 3 )); // The first 3 rows are the playing field, the fourth is the store. if ( r < 3 ) { stack[r][c]->setCheckIndex( 0 ); stack[r][c]->setTarget(true); } else { stack[r][c]->setAddFlags( Pile::addSpread ); stack[r][c]->setCheckIndex( 1 ); } } } setTakeTargetForHints(true); setActions(Dealer::Hint | Dealer::Demo ); } //-------------------------------------------------------------------------// bool Mod3::checkAdd( int checkIndex, const Pile *c1, const CardList& cl) const { // kdDebug(11111) << "checkAdd " << checkIndex << " " << c1->top()->name() << " " << c1->index() << " " << c1->index() / 10 << endl; if (checkIndex == 0) { Card *c2 = cl.first(); if (c1->isEmpty()) return (c2->rank() == ( ( c1->index() / 10 ) + 2 ) ); kdDebug(11111) << "not empty\n"; if (c1->top()->suit() != c2->suit()) return false; kdDebug(11111) << "same suit\n"; if (c2->rank() != (c1->top()->rank()+3)) return false; kdDebug(11111) << "+3 " << c1->cardsLeft() << " " << c1->top()->rank() << " " << c1->index()+1 << endl; if (c1->cardsLeft() == 1) return (c1->top()->rank() == ((c1->index() / 10) + 2)); kdDebug(11111) << "+1\n"; return true; } else if (checkIndex == 1) { return c1->isEmpty(); } else if (checkIndex == 2) { return cl.first()->rank() == Card::Ace; } else return false; } bool Mod3::checkPrefering( int checkIndex, const Pile *c1, const CardList& c2) const { return (checkIndex == 0 && c1->isEmpty() && c2.first()->rank() == (c1->index()+1)); } //-------------------------------------------------------------------------// void Mod3::restart() { deck->collectAndShuffle(); deal(); } //-------------------------------------------------------------------------// void Mod3::dealRow(int row) { if (deck->isEmpty()) return; for (int c = 0; c < 8; c++) { Card *card; card = deck->nextCard(); stack[row][c]->add (card, false, true); } } void Mod3::deckClicked(Card*) { kdDebug(11111) << "deck clicked " << deck->cardsLeft() << endl; if (deck->isEmpty()) return; unmarkAll(); dealRow(3); takeState(); } //-------------------------------------------------------------------------// void Mod3::deal() { unmarkAll(); CardList list = deck->cards(); /* for (CardList::Iterator it = list.begin(); it != list.end(); ++it) if ((*it)->rank() == Card::Ace) { aces->add(*it); (*it)->hide(); } */ kdDebug(11111) << "init " << aces->cardsLeft() << " " << deck->cardsLeft() << endl; for (int r = 0; r < 4; r++) dealRow(r); } Card *Mod3::demoNewCards() { if (deck->isEmpty()) return 0; deckClicked(0); return stack[3][0]->top(); } bool Mod3::startAutoDrop() { return false; } bool Mod3::isGameLost() const { int n,row,col; kdDebug(11111) << "isGameLost ?"<< endl; bool nextTest=false; // If there is an empty stack or an ace below, the game is not lost. for (col=0; col < 8; col++){ if (stack[3][col]->isEmpty() || stack[3][col]->at(0)->rank() == Card::Ace) return false; } // Ok, so no empty stack below. // If there is neither an empty stack on the board (an ace counts // as this) nor a card placed in the correct row, all is lost. // Otherwise we have to do more tests. for (n = 0; n < 24; n++) { row = n / 8; col = n % 8; // If there is a stack on the board that is either empty or // contains an ace, the game is not finished. if (stack[row][col]->isEmpty() || stack[row][col]->at(0)->rank() == Card::Ace) { nextTest = true; break; } // If there is a card that is correctly placed, the game is // not lost. if (stack[row][col]->at(0)->rank() == Card::Two + row) { nextTest = true; break; } } if (!nextTest) return true; // If there are more cards in the deck, the game is not lost. if (!deck->isEmpty()) return false; int n2, row2, col2, col3; Card *ctop; Card *card; // For all stacks on the board, check if: // for (n = 0; n < 24; n++){ row = n / 8; col = n % 8; // Empty stack: Can we move a card there? if (stack[row][col]->isEmpty()) { // Can we move a card from below? for (col3=0; col3 < 8; col3++) { if (stack[3][col3]->top()->rank() == (Card::Two+row)) return false; } // Can we move a card from another row? for (n2 = 0; n2 < 16; n2++) { row2 = (row + 1 + (n2 / 8)) % 3; col2 = n2 % 8; if (stack[row2][col2]->isEmpty()) continue; if (stack[row2][col2]->top()->rank() == (Card::Two + row)) return false; } } else { // Non-empty stack. ctop = stack[row][col]->top(); kdDebug(11111) << "considering ["<<row<<"]["<<col<<"] " << ctop->name() << flush; // Card not in its final position? Then we can't build on it. if (stack[row][col]->at(0)->rank() != Card::Two + row) continue; // Can we move a card from below here? for (col3 = 0; col3 < 8; col3++) { card = stack[3][col3]->top(); if (card->suit() == ctop->suit() && card->rank() == ctop->rank() + 3) return false; } kdDebug(11111) <<" Can't stack from bottom row" << flush; // Can we move a card from another stack here? for (int n_2 = 1; n_2 < 24; n_2++) { n2 = (n + n_2) % 24; row2 = n2 / 8; col2 = n2 % 8; if (stack[row2][col2]->isEmpty()) continue; card = stack[row2][col2]->top(); // Only consider cards that are not on top of other cards. if (stack[row2][col2]->indexOf(card) != 0) continue; if (card->suit() == ctop->suit() && card->rank() == ctop->rank() + 3) return false; } } } return true; } static class LocalDealerInfo5 : public DealerInfo { public: LocalDealerInfo5() : DealerInfo(I18N_NOOP("M&od3"), 5) {} virtual Dealer *createGame(TDEMainWindow *parent) { return new Mod3(parent); } } ldi5; //-------------------------------------------------------------------------// #include"mod3.moc" //-------------------------------------------------------------------------//