#include "dealer.h" #include #include #include "deck.h" #include #include "tdemainwindow.h" #include #include #include #include #include #include "cardmaps.h" #include "speeds.h" #include #include "version.h" // ================================================================ // class MoveHint MoveHint::MoveHint(Card *card, Pile *to, bool d) { m_card = card; m_to = to; m_dropiftarget = d; } // ================================================================ // class DealerInfoList DealerInfoList *DealerInfoList::_self = 0; static KStaticDeleter dl; DealerInfoList *DealerInfoList::self() { if (!_self) _self = dl.setObject(_self, new DealerInfoList()); return _self; } void DealerInfoList::add(DealerInfo *dealer) { list.append(dealer); } // ================================================================ // class Dealer Dealer *Dealer::s_instance = 0; Dealer::Dealer( TDEMainWindow* _parent , const char* _name ) : TQCanvasView( 0, _parent, _name ), towait(0), myActions(0), ademo(0), ahint(0), aredeal(0), takeTargets(false), _won(false), _waiting(0), stop_demo_next(false), _autodrop(true), _gameRecorded(false) { setResizePolicy(TQScrollView::Manual); setVScrollBarMode(AlwaysOff); setHScrollBarMode(AlwaysOff); setGameNumber(kapp->random()); myCanvas.setAdvancePeriod(30); // myCanvas.setBackgroundColor( darkGreen ); setCanvas(&myCanvas); myCanvas.setDoubleBuffering(true); undoList.setAutoDelete(true); demotimer = new TQTimer(this); connect(demotimer, TQT_SIGNAL(timeout()), TQT_SLOT(demo())); assert(!s_instance); s_instance = this; } const Dealer *Dealer::instance() { return s_instance; } void Dealer::setBackgroundPixmap(const TQPixmap &background, const TQColor &midcolor) { _midcolor = midcolor; canvas()->setBackgroundPixmap(background); for (PileList::Iterator it = piles.begin(); it != piles.end(); ++it) { (*it)->resetCache(); (*it)->initSizes(); } } void Dealer::setupActions() { TQPtrList actionlist; kdDebug(11111) << "setupActions " << actions() << endl; if (actions() & Dealer::Hint) { ahint = new TDEAction( i18n("&Hint"), TQString::fromLatin1("wizard"), Key_H, TQT_TQOBJECT(this), TQT_SLOT(hint()), parent()->actionCollection(), "game_hint"); actionlist.append(ahint); } else ahint = 0; if (actions() & Dealer::Demo) { ademo = new TDEToggleAction( i18n("&Demo"), TQString::fromLatin1("1rightarrow"), CTRL+Key_D, TQT_TQOBJECT(this), TQT_SLOT(toggleDemo()), parent()->actionCollection(), "game_demo"); actionlist.append(ademo); } else ademo = 0; if (actions() & Dealer::Redeal) { aredeal = new TDEAction (i18n("&Redeal"), TQString::fromLatin1("queue"), 0, TQT_TQOBJECT(this), TQT_SLOT(redeal()), parent()->actionCollection(), "game_redeal"); actionlist.append(aredeal); } else aredeal = 0; parent()->guiFactory()->plugActionList( parent(), TQString::fromLatin1("game_actions"), actionlist); } Dealer::~Dealer() { if (!_won) countLoss(); clearHints(); parent()->guiFactory()->unplugActionList( parent(), TQString::fromLatin1("game_actions")); while (!piles.isEmpty()) delete piles.first(); // removes itself if (s_instance == this) s_instance = 0; } TDEMainWindow *Dealer::parent() const { return dynamic_cast(TQCanvasView::parent()); } // ---------------------------------------------------------------- void Dealer::hint() { unmarkAll(); clearHints(); getHints(); for (HintList::ConstIterator it = hints.begin(); it != hints.end(); ++it) mark((*it)->card()); clearHints(); canvas()->update(); } void Dealer::getHints() { for (PileList::Iterator it = piles.begin(); it != piles.end(); ++it) { if (!takeTargetForHints() && (*it)->target()) continue; Pile *store = *it; if (store->isEmpty()) continue; // kdDebug(11111) << "trying " << store->top()->name() << endl; CardList cards = store->cards(); while (cards.count() && !cards.first()->realFace()) cards.remove(cards.begin()); CardList::Iterator iti = cards.begin(); while (iti != cards.end()) { if (store->legalRemove(*iti)) { // kdDebug(11111) << "could remove " << (*iti)->name() << endl; for (PileList::Iterator pit = piles.begin(); pit != piles.end(); ++pit) { Pile *dest = *pit; if (dest == store) continue; if (store->indexOf(*iti) == 0 && dest->isEmpty() && !dest->target()) continue; if (!dest->legalAdd(cards)) continue; bool old_prefer = checkPrefering( dest->checkIndex(), dest, cards ); if (!takeTargetForHints() && dest->target()) newHint(new MoveHint(*iti, dest)); else { store->hideCards(cards); // if it could be here as well, then it's no use if ((store->isEmpty() && !dest->isEmpty()) || !store->legalAdd(cards)) newHint(new MoveHint(*iti, dest)); else { if (old_prefer && !checkPrefering( store->checkIndex(), store, cards )) { // if checkPrefers says so, we add it nonetheless newHint(new MoveHint(*iti, dest)); } } store->unhideCards(cards); } } } cards.remove(iti); iti = cards.begin(); } } } bool Dealer::checkPrefering( int /*checkIndex*/, const Pile *, const CardList& ) const { return false; } void Dealer::clearHints() { for (HintList::Iterator it = hints.begin(); it != hints.end(); ++it) delete *it; hints.clear(); } void Dealer::newHint(MoveHint *mh) { hints.append(mh); } bool Dealer::isMoving(Card *c) const { return movingCards.find(c) != movingCards.end(); } void Dealer::contentsMouseMoveEvent(TQMouseEvent* e) { if (movingCards.isEmpty()) return; moved = true; for (CardList::Iterator it = movingCards.begin(); it != movingCards.end(); ++it) { (*it)->moveBy(e->pos().x() - moving_start.x(), e->pos().y() - moving_start.y()); } PileList sources; TQCanvasItemList list = canvas()->collisions(movingCards.first()->rect()); for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Card::RTTI) { Card *c = dynamic_cast(*it); assert(c); if (!c->isFaceUp()) continue; if (c->source() == movingCards.first()->source()) continue; if (sources.findIndex(c->source()) != -1) continue; sources.append(c->source()); } else { if ((*it)->rtti() == Pile::RTTI) { Pile *p = static_cast(*it); if (p->isEmpty() && !sources.contains(p)) sources.append(p); } else { kdDebug(11111) << "unknown object " << *it << " " << (*it)->rtti() << endl; } } } // TODO some caching of the results unmarkAll(); for (PileList::Iterator it = sources.begin(); it != sources.end(); ++it) { bool b = (*it)->legalAdd(movingCards); if (b) { if ((*it)->isEmpty()) { (*it)->setSelected(true); marked.append(*it); } else { mark((*it)->top()); } } } moving_start = e->pos(); canvas()->update(); } void Dealer::mark(Card *c) { c->setSelected(true); if (!marked.contains(c)) marked.append(c); } void Dealer::unmarkAll() { for (TQCanvasItemList::Iterator it = marked.begin(); it != marked.end(); ++it) { (*it)->setSelected(false); } marked.clear(); } void Dealer::contentsMousePressEvent(TQMouseEvent* e) { unmarkAll(); stopDemo(); if (waiting()) return; TQCanvasItemList list = canvas()->collisions(e->pos()); kdDebug(11111) << "mouse pressed " << list.count() << " " << canvas()->allItems().count() << endl; moved = false; if (!list.count()) return; if (e->button() == Qt::LeftButton) { if (list.first()->rtti() == Card::RTTI) { Card *c = dynamic_cast(list.first()); assert(c); CardList mycards = c->source()->cardPressed(c); for (CardList::Iterator it = mycards.begin(); it != mycards.end(); ++it) (*it)->setAnimated(false); movingCards = mycards; moving_start = e->pos(); } return; } if (e->button() == Qt::RightButton) { if (list.first()->rtti() == Card::RTTI) { Card *preview = dynamic_cast(list.first()); assert(preview); if (!preview->animated() && !isMoving(preview)) preview->getUp(); } return; } // if it's nothing else, we move the cards back contentsMouseReleaseEvent(e); } class Hit { public: Pile *source; TQRect intersect; bool top; }; typedef TQValueList HitList; void Dealer::contentsMouseReleaseEvent( TQMouseEvent *e) { if (!moved) { if (!movingCards.isEmpty()) { movingCards.first()->source()->moveCardsBack(movingCards); movingCards.clear(); } TQCanvasItemList list = canvas()->collisions(e->pos()); if (list.isEmpty()) return; TQCanvasItemList::Iterator it = list.begin(); if ((*it)->rtti() == Card::RTTI) { Card *c = dynamic_cast(*it); assert(c); if (!c->animated()) { if ( cardClicked(c) ) { countGame(); } takeState(); canvas()->update(); } return; } if ((*it)->rtti() == Pile::RTTI) { Pile *c = dynamic_cast(*it); assert(c); pileClicked(c); takeState(); canvas()->update(); return; } } if (!movingCards.count()) return; Card *c = static_cast(movingCards.first()); assert(c); unmarkAll(); TQCanvasItemList list = canvas()->collisions(movingCards.first()->rect()); HitList sources; for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Card::RTTI) { Card *c = dynamic_cast(*it); assert(c); if (!c->isFaceUp()) continue; if (c->source() == movingCards.first()->source()) continue; Hit t; t.source = c->source(); t.intersect = c->rect().intersect(movingCards.first()->rect()); t.top = (c == c->source()->top()); bool found = false; for (HitList::Iterator hi = sources.begin(); hi != sources.end(); ++hi) { if ((*hi).source == c->source()) { found = true; if ((*hi).intersect.width() * (*hi).intersect.height() > t.intersect.width() * t.intersect.height()) { (*hi).intersect = t.intersect; (*hi).top |= t.top; } } } if (found) continue; sources.append(t); } else { if ((*it)->rtti() == Pile::RTTI) { Pile *p = static_cast(*it); if (p->isEmpty()) { Hit t; t.source = p; t.intersect = p->rect().intersect(movingCards.first()->rect()); t.top = true; sources.append(t); } } else { kdDebug(11111) << "unknown object " << *it << " " << (*it)->rtti() << endl; } } } for (HitList::Iterator it = sources.begin(); it != sources.end(); ) { if (!(*it).source->legalAdd(movingCards)) it = sources.remove(it); else ++it; } if (sources.isEmpty()) { c->source()->moveCardsBack(movingCards); } else { HitList::Iterator best = sources.begin(); HitList::Iterator it = best; for (++it; it != sources.end(); ++it ) { if ((*it).intersect.width() * (*it).intersect.height() > (*best).intersect.width() * (*best).intersect.height() || ((*it).top && !(*best).top)) { best = it; } } countGame(); c->source()->moveCards(movingCards, (*best).source); takeState(); } movingCards.clear(); canvas()->update(); } void Dealer::contentsMouseDoubleClickEvent( TQMouseEvent*e ) { stopDemo(); unmarkAll(); if (waiting()) return; if (!movingCards.isEmpty()) { movingCards.first()->source()->moveCardsBack(movingCards); movingCards.clear(); } TQCanvasItemList list = canvas()->collisions(e->pos()); if (list.isEmpty()) return; TQCanvasItemList::Iterator it = list.begin(); if ((*it)->rtti() != Card::RTTI) return; Card *c = dynamic_cast(*it); assert(c); if (!c->animated()) { if ( cardDblClicked(c) ) { countGame(); } takeState(); } } TQSize Dealer::minimumCardSize() const { return minsize; } void Dealer::resizeEvent(TQResizeEvent *e) { int x = width(); int y = height(); int hs = horizontalScrollBar()->sizeHint().height(); int vs = verticalScrollBar()->sizeHint().width(); int mx = minsize.width(); int my = minsize.height(); int dx = x; int dy = y; bool showh = false; bool showv = false; if (mx > x) { dx = mx; if (my + vs < y) dy -= vs; else { showv = true; } showh = true; } else if (my > y) { dy = my; if (mx + hs < x) dx -= hs; else showh = true; showv = true; } canvas()->resize(dx, dy); resizeContents(dx, dy); setVScrollBarMode(showv ? AlwaysOn : AlwaysOff); setHScrollBarMode(showh ? AlwaysOn : AlwaysOff); if (!e) updateScrollBars(); else TQCanvasView::resizeEvent(e); } bool Dealer::cardClicked(Card *c) { return c->source()->cardClicked(c); } void Dealer::pileClicked(Pile *c) { c->cardClicked(0); } bool Dealer::cardDblClicked(Card *c) { if (c->source()->cardDblClicked(c)) return true; if (c->animated()) return false; if (c == c->source()->top() && c->realFace()) { Pile *tgt = findTarget(c); if (tgt) { CardList empty; empty.append(c); c->source()->moveCards(empty, tgt); canvas()->update(); return true; } } return false; } void Dealer::startNew() { if (!_won) countLoss(); if ( ahint ) ahint->setEnabled( true ); if ( ademo ) ademo->setEnabled( true ); if ( aredeal ) aredeal->setEnabled( true ); toldAboutLostGame = false; minsize = TQSize(0,0); _won = false; _waiting = 0; _gameRecorded=false; kdDebug(11111) << "startNew stopDemo\n"; stopDemo(); kdDebug(11111) << "startNew unmarkAll\n"; unmarkAll(); kdDebug(11111) << "startNew setAnimated(false)\n"; TQCanvasItemList list = canvas()->allItems(); for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Card::RTTI) static_cast(*it)->disconnect(); (*it)->setAnimated(true); (*it)->setAnimated(false); } undoList.clear(); emit undoPossible(false); emit updateMoves(); kdDebug(11111) << "startNew restart\n"; restart(); takeState(); Card *towait = 0; for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Card::RTTI) { towait = static_cast(*it); if (towait->animated()) break; } } kdDebug(11111) << "startNew takeState\n"; if (!towait) takeState(); else connect(towait, TQT_SIGNAL(stoped(Card*)), TQT_SLOT(slotTakeState(Card *))); resizeEvent(0); } void Dealer::slotTakeState(Card *c) { if (c) c->disconnect(); takeState(); } void Dealer::enlargeCanvas(TQCanvasRectangle *c) { if (!c->isVisible() || c->animated()) return; bool changed = false; if (c->x() + c->width() + 10 > minsize.width()) { minsize.setWidth(int(c->x()) + c->width() + 10); changed = true; } if (c->y() + c->height() + 10 > minsize.height()) { minsize.setHeight(int(c->y()) + c->height() + 10); changed = true; } if (changed) resizeEvent(0); } typedef class TQValueList CardStateList; bool operator==( const State & st1, const State & st2) { return st1.cards == st2.cards && st1.gameData == st2.gameData; } State *Dealer::getState() { TQCanvasItemList list = canvas()->allItems(); State * st = new State; for (TQCanvasItemList::ConstIterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Card::RTTI) { Card *c = dynamic_cast(*it); assert(c); CardState s; s.it = c; s.source = c->source(); if (!s.source) { kdDebug(11111) << c->name() << " has no parent\n"; assert(false); } s.source_index = c->source()->indexOf(c); s.x = c->realX(); s.y = c->realY(); s.z = c->realZ(); s.faceup = c->realFace(); s.tookdown = c->takenDown(); st->cards.append(s); } } qHeapSort(st->cards); // Game specific information st->gameData = getGameState( ); return st; } void Dealer::setState(State *st) { CardStateList * n = &st->cards; TQCanvasItemList list = canvas()->allItems(); for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Pile::RTTI) { Pile *p = dynamic_cast(*it); assert(p); CardList cards = p->cards(); for (CardList::Iterator it = cards.begin(); it != cards.end(); ++it) (*it)->setTakenDown(p->target()); p->clear(); } } for (CardStateList::ConstIterator it = n->begin(); it != n->end(); ++it) { Card *c = (*it).it; CardState s = *it; bool target = c->takenDown(); // abused s.source->add(c, s.source_index); c->setVisible(s.source->isVisible()); c->setAnimated(false); c->setX(s.x); c->setY(s.y); c->setZ(int(s.z)); c->setTakenDown(s.tookdown || (target && !s.source->target())); c->turn(s.faceup); } // restore game-specific information setGameState( st->gameData ); delete st; canvas()->update(); } void Dealer::takeState() { kdDebug(11111) << "takeState\n"; State *n = getState(); if (!undoList.count()) { emit updateMoves(); undoList.append(n); } else { State *old = undoList.last(); if (*old == *n) { delete n; n = 0; } else { emit updateMoves(); undoList.append(n); } } if (n) { if (isGameWon()) { won(); return; } else if (isGameLost() && !toldAboutLostGame) { if ( ahint ) ahint->setEnabled( false ); if ( ademo ) ademo->setEnabled( false ); if ( aredeal ) aredeal->setEnabled( false ); TQTimer::singleShot(400, TQT_TQOBJECT(this), TQT_SIGNAL(gameLost())); toldAboutLostGame = true; return; } } if (!demoActive() && !waiting()) TQTimer::singleShot(TIME_BETWEEN_MOVES, TQT_TQOBJECT(this), TQT_SLOT(startAutoDrop())); emit undoPossible(undoList.count() > 1 && !waiting()); } void Dealer::saveGame(TQDomDocument &doc) { TQDomElement dealer = doc.createElement("dealer"); doc.appendChild(dealer); dealer.setAttribute("id", _id); dealer.setAttribute("number", TQString::number(gameNumber())); TQString data = getGameState(); if (!data.isEmpty()) dealer.setAttribute("data", data); dealer.setAttribute("moves", TQString::number(getMoves())); bool taken[1000]; memset(taken, 0, sizeof(taken)); TQCanvasItemList list = canvas()->allItems(); for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Pile::RTTI) { Pile *p = dynamic_cast(*it); assert(p); if (taken[p->index()]) { kdDebug(11111) << "pile index " << p->index() << " taken twice\n"; return; } taken[p->index()] = true; TQDomElement pile = doc.createElement("pile"); pile.setAttribute("index", p->index()); CardList cards = p->cards(); for (CardList::Iterator it = cards.begin(); it != cards.end(); ++it) { TQDomElement card = doc.createElement("card"); card.setAttribute("suit", (*it)->suit()); card.setAttribute("value", (*it)->rank()); card.setAttribute("faceup", (*it)->isFaceUp()); card.setAttribute("x", (*it)->realX()); card.setAttribute("y", (*it)->realY()); card.setAttribute("z", (*it)->realZ()); card.setAttribute("name", (*it)->name()); pile.appendChild(card); } dealer.appendChild(pile); } } /* TQDomElement eList = doc.createElement("undo"); TQPtrListIterator it(undoList); for (; it.current(); ++it) { State *n = it.current(); TQDomElement state = doc.createElement("state"); if (!n->gameData.isEmpty()) state.setAttribute("data", n->gameData); TQDomElement cards = doc.createElement("cards"); for (TQValueList::ConstIterator it2 = n->cards.begin(); it2 != n->cards.end(); ++it2) { TQDomElement item = doc.createElement("item"); (*it2).fillNode(item); cards.appendChild(item); } state.appendChild(cards); eList.appendChild(state); } dealer.appendChild(eList); */ // kdDebug(11111) << doc.toString() << endl; } void Dealer::openGame(TQDomDocument &doc) { unmarkAll(); TQDomElement dealer = doc.documentElement(); setGameNumber(dealer.attribute("number").toULong()); undoList.clear(); TQDomNodeList piles = dealer.elementsByTagName("pile"); TQCanvasItemList list = canvas()->allItems(); CardList cards; for (TQCanvasItemList::ConstIterator it = list.begin(); it != list.end(); ++it) if ((*it)->rtti() == Card::RTTI) cards.append(static_cast(*it)); Deck::deck()->collectAndShuffle(); for (TQCanvasItemList::Iterator it = list.begin(); it != list.end(); ++it) { if ((*it)->rtti() == Pile::RTTI) { Pile *p = dynamic_cast(*it); assert(p); for (uint i = 0; i < piles.count(); ++i) { TQDomElement pile = piles.item(i).toElement(); if (pile.attribute("index").toInt() == p->index()) { TQDomNodeList pcards = pile.elementsByTagName("card"); for (uint j = 0; j < pcards.count(); ++j) { TQDomElement card = pcards.item(j).toElement(); Card::Suit s = static_cast(card.attribute("suit").toInt()); Card::Rank v = static_cast(card.attribute("value").toInt()); for (CardList::Iterator it2 = cards.begin(); it2 != cards.end(); ++it2) { if ((*it2)->suit() == s && (*it2)->rank() == v) { if (TQString((*it2)->name()) == "Diamonds Eight") { kdDebug(11111) << i << " " << j << endl; } p->add(*it2); (*it2)->setAnimated(false); (*it2)->turn(card.attribute("faceup").toInt()); (*it2)->setX(card.attribute("x").toInt()); (*it2)->setY(card.attribute("y").toInt()); (*it2)->setZ(card.attribute("z").toInt()); (*it2)->setVisible(p->isVisible()); cards.remove(it2); break; } } } } } } } setGameState( dealer.attribute("data") ); if (undoList.count() > 1) { setState(undoList.take(undoList.count() - 1)); takeState(); // copying it again emit undoPossible(undoList.count() > 1); } emit updateMoves(); takeState(); } void Dealer::undo() { unmarkAll(); stopDemo(); if (undoList.count() > 1) { undoList.removeLast(); // the current state setState(undoList.take(undoList.count() - 1)); emit updateMoves(); takeState(); // copying it again emit undoPossible(undoList.count() > 1); if ( toldAboutLostGame ) { // everything's possible again if ( ahint ) ahint->setEnabled( true ); if ( ademo ) ademo->setEnabled( true ); toldAboutLostGame = false; } } } Pile *Dealer::findTarget(Card *c) { if (!c) return 0; CardList empty; empty.append(c); for (PileList::ConstIterator it = piles.begin(); it != piles.end(); ++it) { if (!(*it)->target()) continue; if ((*it)->legalAdd(empty)) return *it; } return 0; } void Dealer::setWaiting(bool w) { if (w) _waiting++; else _waiting--; emit undoPossible(!waiting()); kdDebug(11111) << "setWaiting " << w << " " << _waiting << endl; } void Dealer::setAutoDropEnabled(bool a) { _autodrop = a; TQTimer::singleShot(TIME_BETWEEN_MOVES, TQT_TQOBJECT(this), TQT_SLOT(startAutoDrop())); } bool Dealer::startAutoDrop() { if (!autoDrop()) return false; TQCanvasItemList list = canvas()->allItems(); for (TQCanvasItemList::ConstIterator it = list.begin(); it != list.end(); ++it) if ((*it)->animated()) { TQTimer::singleShot(TIME_BETWEEN_MOVES, TQT_TQOBJECT(this), TQT_SLOT(startAutoDrop())); return true; } kdDebug(11111) << "startAutoDrop\n"; unmarkAll(); clearHints(); getHints(); for (HintList::ConstIterator it = hints.begin(); it != hints.end(); ++it) { MoveHint *mh = *it; if (mh->pile()->target() && mh->dropIfTarget() && !mh->card()->takenDown()) { setWaiting(true); Card *t = mh->card(); CardList cards = mh->card()->source()->cards(); while (cards.count() && cards.first() != t) cards.remove(cards.begin()); t->setAnimated(false); t->turn(true); int x = int(t->x()); int y = int(t->y()); t->source()->moveCards(cards, mh->pile()); t->move(x, y); kdDebug(11111) << "autodrop " << t->name() << endl; t->moveTo(int(t->source()->x()), int(t->source()->y()), int(t->z()), STEPS_AUTODROP); connect(t, TQT_SIGNAL(stoped(Card*)), TQT_SLOT(waitForAutoDrop(Card*))); return true; } } clearHints(); return false; } void Dealer::waitForAutoDrop(Card * c) { kdDebug(11111) << "waitForAutoDrop " << c->name() << endl; setWaiting(false); c->disconnect(); takeState(); } long Dealer::gameNumber() const { return gamenumber; } void Dealer::setGameNumber(long gmn) { // Deal in the range of 1 to INT_MAX. gamenumber = ((gmn < 1) ? 1 : ((gmn > 0x7FFFFFFF) ? 0x7FFFFFFF : gmn)); } void Dealer::addPile(Pile *p) { piles.append(p); } void Dealer::removePile(Pile *p) { piles.remove(p); } void Dealer::stopDemo() { kdDebug(11111) << "stopDemo " << waiting() << " " << stop_demo_next << endl; if (waiting()) { stop_demo_next = true; return; } else stop_demo_next = false; if (towait == (Card*)-1) towait = 0; if (towait) { towait->disconnect(); towait = 0; } demotimer->stop(); if (ademo) ademo->setChecked(false); } bool Dealer::demoActive() const { return (towait || demotimer->isActive()); } void Dealer::toggleDemo() { if (demoActive()) { stopDemo(); } else demo(); } class CardPtr { public: Card *ptr; }; bool operator <(const CardPtr &p1, const CardPtr &p2) { return ( p1.ptr->z() < p2.ptr->z() ); } void Dealer::won() { if (_won) return; _won = true; // update score, 'win' in demo mode also counts (keep it that way?) { // wrap in own scope to make TDEConfigGroupSave work TDEConfig *config = kapp->config(); TDEConfigGroupSaver kcs(config, scores_group); unsigned int n = config->readUnsignedNumEntry(TQString("won%1").arg(_id),0) + 1; config->writeEntry(TQString("won%1").arg(_id),n); n = config->readUnsignedNumEntry(TQString("winstreak%1").arg(_id),0) + 1; config->writeEntry(TQString("winstreak%1").arg(_id),n); unsigned int m = config->readUnsignedNumEntry(TQString("maxwinstreak%1").arg(_id),0); if (n>m) config->writeEntry(TQString("maxwinstreak%1").arg(_id),n); config->writeEntry(TQString("loosestreak%1").arg(_id),0); } // sort cards by increasing z TQCanvasItemList list = canvas()->allItems(); TQValueList cards; for (TQCanvasItemList::ConstIterator it=list.begin(); it!=list.end(); ++it) if ((*it)->rtti() == Card::RTTI) { CardPtr p; p.ptr = dynamic_cast(*it); assert(p.ptr); cards.push_back(p); } qHeapSort(cards); // disperse the cards everywhere TQRect can(0, 0, canvas()->width(), canvas()->height()); TQValueList::ConstIterator it = cards.begin(); for (; it != cards.end(); ++it) { (*it).ptr->turn(true); TQRect p(0, 0, (*it).ptr->width(), (*it).ptr->height()); int x, y; do { x = 3*canvas()->width()/2 - kapp->random() % (canvas()->width() * 2); y = 3*canvas()->height()/2 - (kapp->random() % (canvas()->height() * 2)); p.moveTopLeft(TQPoint(x, y)); } while (can.intersects(p)); (*it).ptr->moveTo( x, y, 0, STEPS_WON); } bool demo = demoActive(); stopDemo(); canvas()->update(); emit gameWon(demo); } MoveHint *Dealer::chooseHint() { if (hints.isEmpty()) return 0; for (HintList::ConstIterator it = hints.begin(); it != hints.end(); ++it) { if ((*it)->pile()->target() && (*it)->dropIfTarget()) return *it; } return hints[randseq.getLong(hints.count())]; } void Dealer::demo() { if (waiting()) return; if (stop_demo_next) { stopDemo(); return; } stop_demo_next = false; unmarkAll(); towait = (Card*)-1; clearHints(); getHints(); demotimer->stop(); MoveHint *mh = chooseHint(); if (mh) { // assert(mh->card()->source()->legalRemove(mh->card())); CardList empty; CardList cards = mh->card()->source()->cards(); bool after = false; for (CardList::Iterator it = cards.begin(); it != cards.end(); ++it) { if (*it == mh->card()) after = true; if (after) empty.append(*it); } assert(!empty.isEmpty()); int *oldcoords = new int[2*empty.count()]; int i = 0; for (CardList::Iterator it = empty.begin(); it != empty.end(); ++it) { Card *t = *it; Q_ASSERT(!t->animated()); t->setAnimated(false); t->turn(true); oldcoords[i++] = int(t->realX()); oldcoords[i++] = int(t->realY()); } assert(mh->card()->source() != mh->pile()); // assert(mh->pile()->legalAdd(empty)); mh->card()->source()->moveCards(empty, mh->pile()); i = 0; for (CardList::Iterator it = empty.begin(); it != empty.end(); ++it) { Card *t = *it; int x1 = oldcoords[i++]; int y1 = oldcoords[i++]; int x2 = int(t->realX()); int y2 = int(t->realY()); t->move(x1, y1); t->moveTo(x2, y2, int(t->z()), STEPS_DEMO); } delete [] oldcoords; newDemoMove(mh->card()); } else { Card *t = demoNewCards(); if (t) { newDemoMove(t); } else if (isGameWon()) { canvas()->update(); emit gameWon(true); return; } else stopDemo(); } takeState(); } Card *Dealer::demoNewCards() { return 0; } void Dealer::newDemoMove(Card *m) { towait = m; connect(m, TQT_SIGNAL(stoped(Card*)), TQT_SLOT(waitForDemo(Card*))); } void Dealer::waitForDemo(Card *t) { if (t == (Card*)-1) return; if (towait != t) return; t->disconnect(); towait = 0; demotimer->start(250, true); } bool Dealer::isGameWon() const { for (PileList::ConstIterator it = piles.begin(); it != piles.end(); ++it) { if (!(*it)->target() && !(*it)->isEmpty()) return false; } return true; } bool Dealer::isGameLost() const { return false; } bool Dealer::checkRemove( int, const Pile *, const Card *) const { return true; } bool Dealer::checkAdd( int, const Pile *, const CardList&) const { return true; } void Dealer::drawPile(KPixmap &pixmap, Pile *pile, bool selected) { TQPixmap bg = myCanvas.backgroundPixmap(); TQRect bounding(int(pile->x()), int(pile->y()), cardMap::CARDX(), cardMap::CARDY()); pixmap.resize(bounding.width(), bounding.height()); pixmap.fill(TQt::white); if (!bg.isNull()) { for (int x=bounding.x()/bg.width(); x<(bounding.x()+bounding.width()+bg.width()-1)/bg.width(); x++) { for (int y=bounding.y()/bg.height(); y<(bounding.y()+bounding.height()+bg.height()-1)/bg.height(); y++) { int sx = 0; int sy = 0; int dx = x*bg.width()-bounding.x(); int dy = y*bg.height()-bounding.y(); int w = bg.width(); int h = bg.height(); if (dx < 0) { sx = -dx; dx = 0; } if (dy < 0) { sy = -dy; dy = 0; } bitBlt(TQT_TQPAINTDEVICE(&pixmap), dx, dy, TQT_TQPAINTDEVICE(&bg), sx, sy, w, h, TQt::CopyROP, true); } } } float s = -0.4; float n = -0.3; int mid = TQMAX( TQMAX(midColor().red(), midColor().green()), midColor().blue()); // if it's too dark - light instead of dark if (mid < 120) { s *= -1; n = 0.4; } KPixmapEffect::intensity(pixmap, selected ? s : n); } int Dealer::freeCells() const { int n = 0; for (PileList::ConstIterator it = piles.begin(); it != piles.end(); ++it) if ((*it)->isEmpty() && !(*it)->target()) n++; return n; } void Dealer::setAnchorName(const TQString &name) { kdDebug(11111) << "setAnchorname " << name << endl; ac = name; } TQString Dealer::anchorName() const { return ac; } void Dealer::wheelEvent( TQWheelEvent *e ) { TQWheelEvent ce( viewport()->mapFromGlobal( e->globalPos() ), e->globalPos(), e->delta(), e->state()); viewportWheelEvent(&ce); if ( !ce.isAccepted() ) { if ( e->orientation() ==Qt::Horizontal && hScrollBarMode () == AlwaysOn ) TQApplication::sendEvent( horizontalScrollBar(), e); else if (e->orientation() ==Qt::Vertical && vScrollBarMode () == AlwaysOn ) TQApplication::sendEvent( verticalScrollBar(), e); } else { e->accept(); } } void Dealer::countGame() { if ( !_gameRecorded ) { kdDebug(11111) << "counting game as played." << endl; TDEConfig *config = kapp->config(); TDEConfigGroupSaver kcs(config, scores_group); unsigned int Total = config->readUnsignedNumEntry(TQString("total%1").arg(_id),0); ++Total; config->writeEntry(TQString("total%1").arg(_id),Total); _gameRecorded = true; } } void Dealer::countLoss() { if ( _gameRecorded ) { // update score TDEConfig *config = kapp->config(); TDEConfigGroupSaver kcs(config, scores_group); unsigned int n = config->readUnsignedNumEntry(TQString("loosestreak%1").arg(_id),0) + 1; config->writeEntry(TQString("loosestreak%1").arg(_id),n); unsigned int m = config->readUnsignedNumEntry(TQString("maxloosestreak%1").arg(_id),0); if (n>m) config->writeEntry(TQString("maxloosestreak%1").arg(_id),n); config->writeEntry(TQString("winstreak%1").arg(_id),0); } } #include "dealer.moc"