diff options
Diffstat (limited to 'kpat/pile.cpp')
-rw-r--r-- | kpat/pile.cpp | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/kpat/pile.cpp b/kpat/pile.cpp new file mode 100644 index 00000000..dd419580 --- /dev/null +++ b/kpat/pile.cpp @@ -0,0 +1,463 @@ +#include "pile.h" +#include "dealer.h" +#include <kdebug.h> +#include <qpainter.h> +#include "cardmaps.h" +#include <assert.h> +#include "speeds.h" + +const int Pile::RTTI = 1002; + +const int Pile::Default = 0x0000; +const int Pile::disallow = 0x0001; +const int Pile::several = 0x0002; // default: move one card + +// Add-flags +const int Pile::addSpread = 0x0100; + +// Remove-flags +const int Pile::autoTurnTop = 0x0200; +const int Pile::wholeColumn = 0x0400; + + + +Pile::Pile( int _index, Dealer* _dealer) + : QCanvasRectangle( _dealer->canvas() ), + m_dealer(_dealer), + m_atype(Custom), + m_rtype(Custom), + myIndex(_index), + _target(false) +{ + // Make the patience aware of this pile. + dealer()->addPile(this); + + QCanvasRectangle::setVisible(true); // default + _checkIndex = -1; + m_addFlags = 0; + m_removeFlags = 0; + + setBrush(Qt::black); + setPen(QPen(Qt::black)); + + setZ(0); + initSizes(); +} + + +void Pile::initSizes() +{ + setSpread( cardMap::CARDY() / 5 + 1 ); + setHSpread( cardMap::CARDX() / 9 + 1 ); + setDSpread( cardMap::CARDY() / 8 ); + + setSize( cardMap::CARDX(), cardMap::CARDY() ); +} + +void Pile::setType(PileType type) +{ + setAddType(type); + setRemoveType(type); +} + +void Pile::setAddType(PileType _type) +{ + m_atype = _type; + switch (_type) { + case Custom: + case FreeCell: + break; + case KlondikeTarget: + setTarget(true); + break; + case KlondikeStore: + case GypsyStore: + case FreecellStore: + setAddFlags(Pile::addSpread | Pile::several); + break; + } +} + +void Pile::setRemoveType(PileType _type) +{ + m_rtype = _type; + switch (_type) { + case Custom: + break; + case KlondikeTarget: + setRemoveFlags(Pile::disallow); + break; + case KlondikeStore: + case GypsyStore: + case FreeCell: + break; + case FreecellStore: + setRemoveFlags(Pile::several | Pile::autoTurnTop); + break; + } +} + +Pile::~Pile() +{ + dealer()->removePile(this); + + for (CardList::Iterator it = m_cards.begin(); it != m_cards.end(); ++it) + { + if ((*it)->source() != this) { + int i = -13; + if ((*it)->source()) + i = (*it)->source()->index(); + kdDebug(11111) << "pile doesn't match " << index() << " - " << i << endl; + } + (*it)->setSource(0); + } +} + +void Pile::resetCache() +{ + cache.resize(0, 0); + cache_selected.resize(0, 0); +} + +void Pile::drawShape ( QPainter & painter ) +{ + if (isSelected()) { + if (cache.isNull()) + dealer()->drawPile(cache, this, false); + painter.drawPixmap(int(x()), int(y()), cache); + } else { + if (cache_selected.isNull()) + dealer()->drawPile(cache_selected, this, true); + painter.drawPixmap(int(x()), int(y()), cache_selected); + } +} + +bool Pile::legalAdd( const CardList& _cards ) const +{ + if ( m_addFlags & disallow ) + return false; + + if ( !( m_addFlags & several ) && _cards.count() > 1 ) + return false; + + // getHint removes cards without turning, so it could be it + // checks later if cards can be added to a face down card + if (top() && !top()->realFace()) + return false; + + switch (addType()) { + case Custom: + return dealer()->checkAdd( checkIndex(), this, _cards ); + break; + case KlondikeTarget: + return add_klondikeTarget(_cards); + break; + case FreecellStore: + case KlondikeStore: + return add_klondikeStore(_cards); + break; + case GypsyStore: + return add_gypsyStore(_cards); + break; + case FreeCell: + return add_freeCell(_cards); + } + return false; +} + +bool Pile::legalRemove(const Card *c) const +{ + if ( m_removeFlags & disallow ) { + return false; + } + if ( !( m_removeFlags & several ) && top() != c) + return false; + + switch (removeType()) { + case Custom: + return dealer()->checkRemove( checkIndex(), this, c); + break; + case KlondikeTarget: + case GypsyStore: + case KlondikeStore: + break; + case FreecellStore: + return remove_freecellStore(c); + break; + case FreeCell: + return (top() == c); + break; + } + return true; +} + +void Pile::setVisible(bool vis) +{ + QCanvasRectangle::setVisible(vis); + dealer()->enlargeCanvas(this); + + for (CardList::Iterator it = m_cards.begin(); it != m_cards.end(); ++it) + { + (*it)->setVisible(vis); + dealer()->enlargeCanvas(*it); + } +} + +void Pile::moveBy(double dx, double dy) +{ + QCanvasRectangle::moveBy(dx, dy); + dealer()->enlargeCanvas(this); + + for (CardList::Iterator it = m_cards.begin(); it != m_cards.end(); ++it) + { + (*it)->moveBy(dx, dy); + dealer()->enlargeCanvas(*it); + } +} + +int Pile::indexOf(const Card *c) const +{ + assert(c->source() == this); + return m_cards.findIndex(const_cast<Card*>(c)); // the list is of non-const cards +} + +Card *Pile::at(int index) const +{ + if (index < 0 || index >= int(m_cards.count())) + return 0; + return *m_cards.at(index); +} + +// Return the top card of this pile. +// + +Card *Pile::top() const +{ + if (m_cards.isEmpty()) + return 0; + + return m_cards.last(); +} + +void Pile::clear() +{ + for (CardList::Iterator it = m_cards.begin(); it != m_cards.end(); ++it) + { + (*it)->setSource(0); + } + m_cards.clear(); +} + +void Pile::add( Card *_card, int index) +{ + if (_card->source() == this) + return; + + Pile *source = _card->source(); + if (source) { + _card->setTakenDown(source->target() && !target()); + source->remove(_card); + } + + _card->setSource(this); + + if (index == -1) + m_cards.append(_card); + else { + while (m_cards.count() <= uint(index)) + m_cards.append(0); + assert(m_cards[index] == 0); + m_cards[index] = _card; + } +} + + +// Return the number of pixels in x and y that the card should be +// offset from the start position of the pile. +// +// Note: Default is to only have vertical spread (Y direction). + +QSize Pile::cardOffset( bool _spread, bool _facedown, const Card *before) const +{ + if (_spread) { + if (_facedown) + return QSize(0, dspread()); + else { + if (before && !before->isFaceUp()) + return QSize(0, dspread()); + else + return QSize(0, spread()); + } + } + + return QSize(0, 0); +} + +/* override cardtype (for initial deal ) */ +void Pile::add( Card* _card, bool _facedown, bool _spread ) +{ + if (!_card) + return; + + // The top card + Card *t = top(); + + // If this pile is visible, then also show the card. + if (isVisible()) + _card->show(); + else + _card->hide(); + + _card->turn( !_facedown ); + + QSize offset = cardOffset(_spread, _facedown, t); + + int x2, y2, z2; + + if (t) { + x2 = int(t->realX() + offset.width()); + y2 = int(t->realY() + offset.height()); + z2 = int(t->realZ() + 1); + } else { + x2 = int(x()); + y2 = int(y()); + z2 = int(z() + 1); + } + + add(_card); + + if (_facedown || !isVisible()) { + _card->move( x2, y2 ); + _card->setZ( z2 ); + } else { + _card->moveTo(x2, y2, z2, STEPS_INITIALDEAL); + } + + dealer()->enlargeCanvas(_card); +} + +void Pile::remove(Card *c) +{ + assert(m_cards.contains(c)); + m_cards.remove(c); +} + +void Pile::hideCards( const CardList & cards ) +{ + for (CardList::ConstIterator it = cards.begin(); it != cards.end(); ++it) + m_cards.remove(*it); +} + +void Pile::unhideCards( const CardList & cards ) +{ + for (CardList::ConstIterator it = cards.begin(); it != cards.end(); ++it) + m_cards.append(*it); +} + +CardList Pile::cardPressed(Card *c) +{ + CardList result; + + if (!legalRemove(c)) + return result; + + int below = -1; + + if (!c->isFaceUp()) + return result; + + for (CardList::Iterator it = m_cards.begin(); it != m_cards.end(); ++it) + { + if (c == *it) { + below = 0; + } + if (below >= 0) { + (*it)->setAnimated(false); + (*it)->setZ(128 + below); + below++; + result.append(*it); + } + } + return result; +} + +void Pile::moveCards(CardList &cl, Pile *to) +{ + if (!cl.count()) + return; + + for (CardList::Iterator it = cl.begin(); it != cl.end(); ++it) + to->add(*it); + + if (m_removeFlags & autoTurnTop && top()) { + Card *t = top(); + if (!t->isFaceUp()) { + t->flipTo(int(t->x()), int(t->y()), 8); + canvas()->update(); + } + } + + to->moveCardsBack(cl, false); +} + +void Pile::moveCardsBack(CardList &cl, bool anim) +{ + if (!cl.count()) + return; + + Card *c = cl.first(); + + Card *before = 0; + QSize off; + + int steps = STEPS_MOVEBACK; + if (!anim) + steps = 0; + + for (CardList::Iterator it = m_cards.begin(); it != m_cards.end(); ++it) + { + if (c == *it) { + if (before) { + off = cardOffset(m_addFlags & Pile::addSpread, false, before); + c->moveTo( before->realX() + off.width(), + before->realY() + off.height(), + before->realZ() + 1, steps); + dealer()->enlargeCanvas(c); + } + else { + c->moveTo( int(x()), int(y()), int(z()) + 1, steps); + } + break; + } else + before = *it; + } + + before = c; + CardList::Iterator it = cl.begin(); // == c + ++it; + + off = cardOffset(m_addFlags & Pile::addSpread, false, 0); + + for (; it != cl.end(); ++it) + { + (*it)->moveTo( before->realX() + off.width(), + before->realY() + off.height(), + before->realZ() + 1, steps); + dealer()->enlargeCanvas(*it); + before = *it; + } +} + +bool Pile::cardClicked(Card *c) +{ + emit clicked(c); + return false; +} + +bool Pile::cardDblClicked(Card *c) +{ + emit dblClicked(c); + return false; +} + +#include "pile.moc" |