You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/kpat/grandf.cpp

228 lines
6.4 KiB

/***********************-*-C++-*-********
grandf.cpp implements a patience card game
Copyright (C) 1995 Paul Olav Tvete
(C) 2000 Stephan Kulow
* 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 "grandf.h"
#include <klocale.h>
#include "deck.h"
#include <kaction.h>
#include <assert.h>
#include "cardmaps.h"
Grandf::Grandf( KMainWindow* tqparent, const char *name )
: Dealer( tqparent, name )
{
deck = Deck::new_deck(this);
deck->hide();
const int distx = cardMap::CARDX() * 14 / 10;
for (int i=0; i<4; i++) {
target[i] = new Pile(i+1, this);
target[i]->move(10+(i+1)*distx, 10);
target[i]->setType(Pile::KlondikeTarget);
}
for (int i=0; i<7; i++) {
store[i] = new Pile(5+i, this);
store[i]->move(10+distx*i, 10 + cardMap::CARDY() * 15 / 10);
store[i]->setAddFlags(Pile::addSpread | Pile::several);
store[i]->setRemoveFlags(Pile::several | Pile::autoTurnTop);
store[i]->setCheckIndex(1);
}
setActions(Dealer::Hint | Dealer::Demo | Dealer::Redeal);
}
void Grandf::restart() {
deck->collectAndShuffle();
deal();
numberOfDeals = 1;
}
void Grandf::redeal() {
unmarkAll();
if (numberOfDeals < 3) {
collect();
deal();
numberOfDeals++;
}
if (numberOfDeals == 3) {
aredeal->setEnabled(false);
}
takeState();
}
Card *Grandf::demoNewCards()
{
if (numberOfDeals < 3) {
redeal();
return store[3]->top();
} else
return 0;
}
void Grandf::deal() {
int start = 0;
int stop = 7-1;
int dir = 1;
for (int round=0; round < 7; round++)
{
int i = start;
do
{
Card *next = deck->nextCard();
if (next)
store[i]->add(next, i != start, true);
i += dir;
} while ( i != stop + dir);
int t = start;
start = stop;
stop = t+dir;
dir = -dir;
}
int i = 0;
Card *next = deck->nextCard();
while (next)
{
store[i+1]->add(next, false , true);
next = deck->nextCard();
i = (i+1)%6;
}
for (int round=0; round < 7; round++)
{
Card *c = store[round]->top();
if (c)
c->turn(true);
}
aredeal->setEnabled(true);
canvas()->update();
}
/*****************************
Does the collecting step of the game
NOTE: this is not quite correct -- the piles should be turned
facedown (ie partially reversed) during collection.
******************************/
void Grandf::collect() {
unmarkAll();
for (int pos = 6; pos >= 0; pos--) {
CardList p = store[pos]->cards();
for (CardList::ConstIterator it = p.begin(); it != p.end(); ++it)
deck->add(*it, true, false);
}
}
bool Grandf::checkAdd( int checkIndex, const Pile *c1, const CardList& c2) const {
assert (checkIndex == 1);
if (c1->isEmpty())
return c2.first()->rank() == Card::King;
else
return (c2.first()->rank() == c1->top()->rank() - 1)
&& c2.first()->suit() == c1->top()->suit();
}
TQString Grandf::getGameState() const
{
return TQString::number(numberOfDeals);
}
void Grandf::setGameState( const TQString &s)
{
numberOfDeals = s.toInt();
aredeal->setEnabled(numberOfDeals < 3);
}
bool Grandf::isGameLost() const
{
// If we can redeal, then nothing's lost yet.
if (numberOfDeals <3)
return false;
// Work through the stores, look for killer criteria.
for(int i=0; i < 7; i++) {
/* If this store is empty, then iterate through the other stores and
* check if there is a (visible) King card. If so, then we could move
* that to the free store (which means a turn is possible, so the
* game is not lost yet).
*/
if(store[i]->isEmpty()){
for(int i2=1; i2 < 7; i2++) {
int j=(i+i2) % 7;
CardList p = store[j]->cards();
for (CardList::ConstIterator it = p.begin(); it != p.end(); ++it){
Card *c= *it;
if( it != p.begin() && c->realFace() && c->rank() == Card::King)
return false;
}
}
}
else{
/* If this store has an Ace as it's top card, then we can start a
* new target pile!
*/
if(store[i]->top()->rank() == Card::Ace)
return false;
/* Check whether the top card of this store could be added to
* any of the target piles.
*/
for(int j=0; j <4; j++)
if( !target[j]->isEmpty())
if(store[i]->top()->suit() == target[j]->top()->suit())
if( store[i]->top()->rank() == target[j]->top()->rank() +1)
return false;
/* Check whether any (group of) cards from another store could
* be put onto this store's top card.
*/
for(int i2=1; i2 < 7; i2++) {
int j=(i+i2) % 7;
CardList p = store[j]->cards();
for (CardList::ConstIterator it = p.begin(); it != p.end(); ++it){
Card *c= *it;
if( c->realFace() &&
c->rank() == (store[i]->top()->rank()-1) &&
c->suit() == store[i]->top()->suit() )
return false;
}
}
}
}
return true; // can't move.
}
static class LocalDealerInfo1 : public DealerInfo
{
public:
LocalDealerInfo1() : DealerInfo(I18N_NOOP("&Grandfather"), 1) {}
virtual Dealer *createGame(KMainWindow *tqparent) { return new Grandf(tqparent); }
} gfdi;
#include "grandf.moc"