author | harlekin <harlekin> | 2003-04-25 09:02:41 (UTC) |
---|---|---|
committer | harlekin <harlekin> | 2003-04-25 09:02:41 (UTC) |
commit | bddc2d168776bf7674f9b938f8889051fb9fa7a8 (patch) (side-by-side diff) | |
tree | 5b03d071f18e30e1b023c7bbd07c49346e1ef428 | |
parent | 25ab69ab9964a8de1c05f9ff659a4b8a820eb201 (diff) | |
download | opie-bddc2d168776bf7674f9b938f8889051fb9fa7a8.zip opie-bddc2d168776bf7674f9b938f8889051fb9fa7a8.tar.gz opie-bddc2d168776bf7674f9b938f8889051fb9fa7a8.tar.bz2 |
added patch for freecell mode by radofan, closes bug 736, i hope it helps
-rw-r--r-- | noncore/games/solitaire/canvascardgame.cpp | 3 | ||||
-rw-r--r-- | noncore/games/solitaire/canvascardgame.h | 1 | ||||
-rw-r--r-- | noncore/games/solitaire/freecellcardgame.cpp | 83 | ||||
-rw-r--r-- | noncore/games/solitaire/freecellcardgame.h | 5 |
4 files changed, 90 insertions, 2 deletions
diff --git a/noncore/games/solitaire/canvascardgame.cpp b/noncore/games/solitaire/canvascardgame.cpp index 8e07cc8..8250193 100644 --- a/noncore/games/solitaire/canvascardgame.cpp +++ b/noncore/games/solitaire/canvascardgame.cpp @@ -74,314 +74,315 @@ void CanvasCardPile::addCard( CanvasCard *card ) { int offsetDown = ( qt_screen->deviceWidth() < 200 ) ? 9 : 13; int cardHeight = ( qt_screen->deviceWidth() < 200 ) ? 27 : 36; int cardWidth = ( qt_screen->deviceWidth() < 200 ) ? 20 : 23; if ( !firstCard ) firstCard = card; int height = cardHeight + pileHeight * offsetDown; setSize( cardWidth, height ); pile->resize( cardWidth, height ); QPainter p( pile ); p.translate( -card->x(), -card->y() + pileHeight * offsetDown ); card->draw( p ); pileHeight++; QImage tempImage; tempImage = *pile; tempImage32 = tempImage.convertDepth( 32 ); tempImage32.setAlphaBuffer( TRUE ); for ( int i = 0; i < tempImage32.width(); i++ ) for ( int j = 0; j < tempImage32.height(); j++ ) { QRgb col = tempImage32.pixel( i, j ); int a = 255-j*220/tempImage32.height(); QRgb alpha = qRgba( qRed( col ), qGreen( col ), qBlue( col ), a ); tempImage32.setPixel( i, j, alpha ); } QRgb alpha = qRgba( 0, 0, 0, 0 ); tempImage32.setPixel( 1, 0, alpha ); tempImage32.setPixel( 0, 0, alpha ); tempImage32.setPixel( 0, 1, alpha ); tempImage32.setPixel( cardWidth - 2, 0, alpha ); tempImage32.setPixel( cardWidth - 1, 0, alpha ); tempImage32.setPixel( cardWidth - 1, 1, alpha ); height--; tempImage32.setPixel( 1, height, alpha ); tempImage32.setPixel( 0, height - 1, alpha ); tempImage32.setPixel( 0, height, alpha ); tempImage32.setPixel( cardWidth - 2, height, alpha ); tempImage32.setPixel( cardWidth - 1, height, alpha ); tempImage32.setPixel( cardWidth - 1, height - 1, alpha ); } void CanvasCardPile::advance(int stage) { if ( stage==1 ) { if ( animSteps-- <= 0 ) { CanvasCard *item = firstCard; while (item) { item->show(); item = (CanvasCard *)item->getCardPile()->cardInfront(item); } setVelocity(0,0); setAnimated(FALSE); parent->cancelMoving(); hide(); move(destX,destY); // exact } } QCanvasRectangle::advance(stage); } void CanvasCardPile::animatedMove(int x2, int y2, int steps ) { destX = x2; destY = y2; double x1 = x(), y1 = y(), dx = x2 - x1, dy = y2 - y1; // Ensure a good speed while ( fabs(dx/steps)+fabs(dy/steps) < 5.0 && steps > 4 ) steps--; setAnimated(TRUE); setVelocity(dx/steps, dy/steps); animSteps = steps; } void CanvasCardPile::draw( QPainter& p ) { int ix = (int)x(), iy = (int)y(); p.drawImage( ix, iy, tempImage32 ); } CanvasCardGame::~CanvasCardGame() { // the deletion stuff should be fixed now and only deletes // items created by this CardGame. I haven't verified there are zero // memory leaks yet if ( alphaCardPile ) delete alphaCardPile; } void CanvasCardGame::gameWon() { srand(time(NULL)); QCanvasItemList list = canvas()->allItems(); QCanvasItemList::Iterator it = list.begin(); for (; it != list.end(); ++it) { if ( (*it)->rtti() == canvasCardId ) { // disperse the cards everywhere int x = 300 - rand() % 1000; int y = 300 + rand() % 200; ((CanvasCard *)*it)->animatedMove( x, y, 50 ); } } } void CanvasCardGame::contentsMousePressEvent(QMouseEvent *e) { if ( moving ) return; QCanvasItemList l = canvas()->collisions( e->pos() ); for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) { if ( (*it)->rtti() == canvasCardId ) { moving = (CanvasCard *)*it; if ( moving->animated() ) return; cardXOff = (int)(e->pos().x() - moving->x()); cardYOff = (int)(e->pos().y() - moving->y()); if ( !mousePressCard( moving, e->pos() ) ) { CanvasCard *card = moving; if ( alphaCardPile ) delete alphaCardPile; alphaCardPile = new CanvasCardPile( this, canvas() ); alphaCardPile->move( card->x(), card->y() ); alphaCardPile->savePos(); alphaCardPile->show(); while (card) { alphaCardPile->addCard( card ); card->hide(); card = (CanvasCard *)card->getCardPile()->cardInfront(card); } alphaCardPile->setZ( INT_MAX ); moved = TRUE; } else { if ( alphaCardPile ) alphaCardPile->hide(); } return; } } mousePress( e->pos() ); } /* // // Should have some intelligent way to make double clicking on a // card send it to the most appropriate pile // void CanvasCardGame::contentsMouseDoubleClickEvent(QMouseEvent *e) { QCanvasItemList l = canvas()->collisions( e->pos() ); for (QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it) { if ( (*it)->rtti() == canvasCardId ) { CanvasCard *card = (CanvasCard *)*it; if ( card->animated() ) return; if ( card->getCardPile()->isAllowedToBeMoved(card) ) { if (card->getCardPile()->cardInfront(card) == NULL) { CardPile *pile = first(); if (pile && pile->isAllowedOnTop(card)) { // move card to this pile return; } } } } } } */ void CanvasCardGame::contentsMouseMoveEvent(QMouseEvent *e) { QPoint p = e->pos(); if ( moving ) { moved = TRUE; if (moving->isFacing() != TRUE) return; int tx = (int)p.x() - cardXOff; int ty = (int)p.y() - cardYOff; if (snapOn == TRUE) { CardPile *pile = closestPile( tx, ty, 50 ); if ( pile && pile->isAllowedOnTop( moving ) ) { QPoint p = pile->getHypertheticalNextCardPos(); if ( alphaCardPile ) alphaCardPile->move( p.x(), p.y() ); return; } } if ( alphaCardPile ) alphaCardPile->move( tx, ty ); } } void CanvasCardGame::contentsMouseReleaseEvent(QMouseEvent *e) { QPoint p = e->pos(); Q_UNUSED(p); if ( moving ) { CanvasCard *item = moving; if ( item->animated() ) return; if ( alphaCardPile ) if ( moved ) { CardPile *pile = closestPile((int)alphaCardPile->x(), (int)alphaCardPile->y(), 30); if (pile && pile->isAllowedOnTop(item)) { CardPile *oldPile = item->getCardPile(); Card *c = NULL; if ( oldPile != pile) { while ( item ) { item->show(); if ( oldPile ) { c = oldPile->cardInfront(item); oldPile->removeCard(item); } - pile->addCardToTop(item); item->setCardPile(pile); //item->move( pile->getCardPos(item) ); + pile->addCardToTop(item); QPoint p = pile->getCardPos(item); item->setPos( p.x(), p.y(), highestZ ); highestZ++; + checkUnusable(); // added for freecell to move card to discard pile if (item->getValue() == king && haveWeWon()) { alphaCardPile->hide(); gameWon(); moving = NULL; return; } if (oldPile) { item = (CanvasCard *)c; } else { item = NULL; } } alphaCardPile->hide(); moving = NULL; return; } } alphaCardPile->animatedMove(); } } moved = FALSE; } void CanvasCardGame::readPile( Config& cfg, CardPile *pile, QString name, int& highestZ ) { cfg.setGroup( name ); int numberOfCards = cfg.readNumEntry("NumberOfCards", 0); Card *card = NULL; for ( int i = 0; i < numberOfCards; i++ ) { QString cardStr; cardStr.sprintf( "%i", i ); int val = cfg.readNumEntry( "Card" + cardStr ); bool facing = cfg.readBoolEntry( "CardFacing" + cardStr ); card = cards[ val ]; card->setFace(facing); card->setCardPile(pile); // cam: setCardPile has to happen bevor addCardToTop pile->addCardToTop(card); // due to a empty pointer if you use cardAddedToTop QPoint p = pile->getCardPos( card ); card->setPos( p.x(), p.y(), highestZ ); card->showCard(); highestZ++; } } diff --git a/noncore/games/solitaire/canvascardgame.h b/noncore/games/solitaire/canvascardgame.h index 0dfb85e..d159de6 100644 --- a/noncore/games/solitaire/canvascardgame.h +++ b/noncore/games/solitaire/canvascardgame.h @@ -1,96 +1,97 @@ /********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef CANVAS_CARD_GAME_H #define CANVAS_CARD_GAME_H #include "cardgame.h" #include "canvasshapes.h" #include "canvascard.h" #include <qpe/resource.h> #include <qpe/config.h> #include <qmainwindow.h> #include <qpe/qpemenubar.h> #include <qpainter.h> #include <stdlib.h> #include <time.h> class CanvasCardPile; class CanvasCardGame : public QCanvasView, public CardGame { public: CanvasCardGame(QCanvas &c, bool snap, QWidget *parent = 0, int numOfDecks = 1, const char *name = 0, WFlags f = 0) : QCanvasView( &c, parent, name, f ), CardGame(0,numOfDecks), moved(FALSE), moving(NULL), alphaCardPile( NULL ), cardXOff(0), cardYOff(0), snapOn(snap), numberToDraw(1) { } virtual ~CanvasCardGame(); virtual Card *newCard( eValue v, eSuit s, bool f ) { return new CanvasCard( v, s, f, canvas() ); } virtual void readConfig( Config& cfg ) { Q_UNUSED( cfg ); } virtual void writeConfig( Config& cfg ) { Q_UNUSED( cfg ); } virtual void gameWon(); virtual bool haveWeWon() { return FALSE; } virtual bool mousePressCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); return FALSE; } virtual void mouseReleaseCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); } void cancelMoving() { moving = NULL; } void toggleSnap() { snapOn = (snapOn == TRUE) ? FALSE : TRUE; } void toggleCardsDrawn() { numberToDraw = (numberToDraw == 1) ? 3 : 1; } int cardsDrawn() { return numberToDraw; } void setNumberToDraw(int numToDraw) { this->numberToDraw = numToDraw; } void readPile( Config& cfg, CardPile *pile, QString name, int& highestZ ); protected: void contentsMousePressEvent(QMouseEvent *e); void contentsMouseReleaseEvent(QMouseEvent *e); void contentsMouseMoveEvent(QMouseEvent *e); + virtual void checkUnusable() { } //added for freecell protected: // Mouse event state variables bool moved; CanvasCard *moving; CanvasCardPile *alphaCardPile; int cardXOff, cardYOff; private: bool snapOn; int numberToDraw; }; #endif diff --git a/noncore/games/solitaire/freecellcardgame.cpp b/noncore/games/solitaire/freecellcardgame.cpp index 98415aa..aeb32fc 100644 --- a/noncore/games/solitaire/freecellcardgame.cpp +++ b/noncore/games/solitaire/freecellcardgame.cpp @@ -1,142 +1,225 @@ /********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include <qgfx_qws.h> #include "freecellcardgame.h" extern int highestZ; int numberOfFreeCells = 4; FreecellCardGame::FreecellCardGame(QCanvas *c, bool snap, QWidget *parent) : CanvasCardGame(*c, snap, parent) { numberOfFreeCells = 4; highestZ = 0; int spaceBetweenPiles = ( qt_screen->deviceWidth() < 200 ) ? 21 : 28; int xOrigin = ( qt_screen->deviceWidth() < 200 ) ? 0 : 5; int spacing = ( qt_screen->deviceWidth() < 200 ) ? 0 : 0; for (int i = 0; i < 4; i++) { freecellPiles[i] = new FreecellFreecellPile( xOrigin + i * spaceBetweenPiles, 10, canvas() ); addCardPile(freecellPiles[i]); } for (int i = 0; i < 4; i++) { discardPiles[i] = new FreecellDiscardPile( xOrigin + spacing + 6 + (i + 4) * spaceBetweenPiles, 10, canvas() ); addCardPile(discardPiles[i]); } for (int i = 0; i < 8; i++) { workingPiles[i] = new FreecellWorkingPile( xOrigin + spacing + 2 + i * spaceBetweenPiles, 50, canvas() ); addCardPile(workingPiles[i]); } } void FreecellCardGame::deal(void) { highestZ = 1; beginDealing(); for (int i = 0; i < 52; i++) { Card *card = cards[i]; card->setFace( TRUE ); card->setPos( 0, 0, highestZ ); card->setCardPile( workingPiles[i%8] ); workingPiles[i%8]->addCardToTop( card ); card->move( workingPiles[i%8]->getCardPos( card ) ); card->showCard(); highestZ++; } endDealing(); } +// checks if smaller card with different color, that could be put on top on the +// card, is present in working or freecell pile +bool FreecellCardGame::checkNeeded(Card *card) +{ + if (card->getValue() > 2){ + int i; + Card *c; + for (i=0;i<4;i++){ + c = freecellPiles[i]->cardOnBottom(); + if (c != NULL){ + if (card->isRed()!= c->isRed() && card->getValue()== c->getValue()+1){ + return (false); + } + } + } + for (i=0;i<8;i++){ + c=workingPiles[i]->cardOnBottom(); + while (c!=NULL){ + if (card->isRed() != c->isRed() && card->getValue() == c->getValue()+1) { + return (false); + } + c=workingPiles[i]->cardInfront(c); + } + } + } + return(true); +} + +// added to move cards, on which no card can be moved, to discard pile +void FreecellCardGame::checkUnusable() +{ + int i,j; +// printf("void FreecellCardGame::checkUnusable()\n"); + Card *top_one; + for (i=0;i < 8;i++) + { + top_one = workingPiles[i]->cardOnTop(); + if (top_one != NULL) + { + j = 0; + while ((j < 4)) + { + if (discardPiles[j]->isAllowedOnTop(top_one)){ + if (checkNeeded(top_one)){ + top_one->setCardPile(discardPiles[j]); + workingPiles[i]->removeCard(top_one); +// printf("k %d f work%d to disk%d on %d\n ",top_one->getValue(),i+1,j+1,highestZ); + discardPiles[j]->addCardToTop(top_one); + top_one->setPos(discardPiles[j]->getX(),discardPiles[j]->getY(),highestZ); + highestZ++; + j = 4; + checkUnusable(); + } + } + j++; + } + } + } + for (i=0;i<4;i++){ + top_one = freecellPiles[i]->cardOnTop(); + if (top_one != NULL) + { + j = 0; + while ((j < 4)) + { + if (discardPiles[j]->isAllowedOnTop(top_one)){ + if (checkNeeded(top_one)){ + top_one->setCardPile(discardPiles[j]); + freecellPiles[i]->removeCard(top_one); +// printf("k %d f work%d to disk%d on %d\n ",top_one->getValue(),i+1,j+1,highestZ); + discardPiles[j]->addCardToTop(top_one); + top_one->setPos(discardPiles[j]->getX(),discardPiles[j]->getY(),highestZ); + highestZ++; + j = 4; + checkUnusable(); + } + } + j++; + } + } + } +} + bool FreecellCardGame::mousePressCard( Card *c, QPoint p ) { Q_UNUSED(p); if ( !c->getCardPile()->isAllowedToBeMoved(c) ) { moving = NULL; return TRUE; } return FALSE; } void FreecellCardGame::readConfig( Config& cfg ) { cfg.setGroup("GameState"); // Create Cards, but don't shuffle or deal them yet createDeck(); // Move the cards to their piles (deal them to their previous places) beginDealing(); highestZ = 1; for (int k = 0; k < 4; k++) { QString pile; pile.sprintf( "FreeCellPile%i", k ); readPile( cfg, freecellPiles[k], pile, highestZ ); } for (int k = 0; k < 4; k++) { QString pile; pile.sprintf( "DiscardPile%i", k ); readPile( cfg, discardPiles[k], pile, highestZ ); } for (int k = 0; k < 8; k++) { QString pile; pile.sprintf( "WorkingPile%i", k ); readPile( cfg, workingPiles[k], pile, highestZ ); } highestZ++; endDealing(); } void FreecellCardGame::writeConfig( Config& cfg ) { cfg.setGroup("GameState"); for ( int i = 0; i < 4; i++ ) { QString pile; pile.sprintf( "FreeCellPile%i", i ); freecellPiles[i]->writeConfig( cfg, pile ); } for ( int i = 0; i < 4; i++ ) { QString pile; pile.sprintf( "DiscardPile%i", i ); discardPiles[i]->writeConfig( cfg, pile ); } for ( int i = 0; i < 8; i++ ) { QString pile; pile.sprintf( "WorkingPile%i", i ); workingPiles[i]->writeConfig( cfg, pile ); } } diff --git a/noncore/games/solitaire/freecellcardgame.h b/noncore/games/solitaire/freecellcardgame.h index f1b09ab..2df751b 100644 --- a/noncore/games/solitaire/freecellcardgame.h +++ b/noncore/games/solitaire/freecellcardgame.h @@ -1,152 +1,155 @@ /********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef FREECELL_CARD_GAME_H #define FREECELL_CARD_GAME_H #include "patiencecardgame.h" extern int numberOfFreeCells; class FreecellDiscardPile : public PatienceDiscardPile { public: FreecellDiscardPile(int x, int y, QCanvas *canvas) : PatienceDiscardPile(x, y, canvas) { } }; class FreecellWorkingPile : public PatienceWorkingPile { public: FreecellWorkingPile(int x, int y, QCanvas *canvas) : PatienceWorkingPile(x, y, canvas) { } virtual bool isAllowedOnTop(Card *card) { if ( cardOnBottom() == NULL ) { int numberOfCardsBeingMoved = 0; Card *tempCard = card; - + while ((tempCard != NULL)) { numberOfCardsBeingMoved++; tempCard = cardInfront(tempCard); } if (numberOfCardsBeingMoved > numberOfFreeCells) return FALSE; } if ( card->isFacing() && cardOnTop() == NULL ) return TRUE; return PatienceWorkingPile::isAllowedOnTop( card ); } + virtual bool isAllowedToBeMoved(Card *card) { int nextExpectedValue = (int)card->getValue(); bool nextExpectedColor = card->isRed(); int numberOfCardsBeingMoved = 0; while ((card != NULL)) { numberOfCardsBeingMoved++; if ( (int)card->getValue() != nextExpectedValue ) return FALSE; if ( card->isRed() != nextExpectedColor ) return FALSE; nextExpectedValue--;; nextExpectedColor = !nextExpectedColor; card = cardInfront(card); } if (numberOfCardsBeingMoved <= (numberOfFreeCells + 1)) return TRUE; return FALSE; } virtual void cardRemoved(Card *card) { if ( !isDealing() && !cardOnTop() ) numberOfFreeCells++; PatienceWorkingPile::cardRemoved( card ); } virtual void cardAddedToTop(Card *card) { if ( !isDealing() && cardOnBottom() == card ) numberOfFreeCells--; PatienceWorkingPile::cardAddedToTop( card ); } }; class FreecellFreecellPile : public CardPile, public CanvasRoundRect { public: FreecellFreecellPile(int x, int y, QCanvas *canvas) : CardPile(x, y), CanvasRoundRect(x, y, canvas) { } virtual bool isAllowedOnTop(Card *card) { if ( ( cardOnTop() == NULL ) && ( card->getCardPile()->cardInfront(card) == NULL ) ) return TRUE; return FALSE; } virtual bool isAllowedToBeMoved(Card *card) { Q_UNUSED(card); return TRUE; } virtual void cardAddedToTop(Card *card) { Q_UNUSED(card); numberOfFreeCells--; } virtual void cardRemoved(Card *card) { Q_UNUSED(card); numberOfFreeCells++; } }; class FreecellCardGame : public CanvasCardGame { public: FreecellCardGame(QCanvas *c, bool snap, QWidget *parent = 0); virtual void deal(void); virtual bool haveWeWon() { return ( discardPiles[0]->kingOnTop() && discardPiles[1]->kingOnTop() && discardPiles[2]->kingOnTop() && discardPiles[3]->kingOnTop() ); } virtual void mousePress(QPoint p) { Q_UNUSED(p); } virtual void mouseRelease(QPoint p) { Q_UNUSED(p); } // virtual void mouseMove(QPoint p); virtual bool mousePressCard(Card *card, QPoint p); virtual void mouseReleaseCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); } // virtual void mouseMoveCard(Card *card, QPoint p) { Q_UNUSED(card); Q_UNUSED(p); } + virtual void checkUnusable(); void readConfig( Config& cfg ); void writeConfig( Config& cfg ); bool snapOn; private: + bool checkNeeded(Card *card); FreecellFreecellPile *freecellPiles[8]; FreecellWorkingPile *workingPiles[8]; FreecellDiscardPile *discardPiles[4]; }; #endif |