diff options
Diffstat (limited to 'libksirtet/common')
-rw-r--r-- | libksirtet/common/Makefile.am | 28 | ||||
-rw-r--r-- | libksirtet/common/README | 1 | ||||
-rw-r--r-- | libksirtet/common/ai.cpp | 356 | ||||
-rw-r--r-- | libksirtet/common/ai.h | 122 | ||||
-rw-r--r-- | libksirtet/common/board.cpp | 286 | ||||
-rw-r--r-- | libksirtet/common/board.h | 75 | ||||
-rw-r--r-- | libksirtet/common/commonprefs.kcfgc | 9 | ||||
-rw-r--r-- | libksirtet/common/factory.cpp | 28 | ||||
-rw-r--r-- | libksirtet/common/factory.h | 36 | ||||
-rw-r--r-- | libksirtet/common/field.cpp | 243 | ||||
-rw-r--r-- | libksirtet/common/field.h | 68 | ||||
-rw-r--r-- | libksirtet/common/highscores.cpp | 60 | ||||
-rw-r--r-- | libksirtet/common/highscores.h | 20 | ||||
-rw-r--r-- | libksirtet/common/inter.cpp | 150 | ||||
-rw-r--r-- | libksirtet/common/inter.h | 62 | ||||
-rw-r--r-- | libksirtet/common/libksirtet2.kcfg | 36 | ||||
-rw-r--r-- | libksirtet/common/main.cpp | 60 | ||||
-rw-r--r-- | libksirtet/common/main.h | 22 | ||||
-rw-r--r-- | libksirtet/common/misc_ui.cpp | 194 | ||||
-rw-r--r-- | libksirtet/common/misc_ui.h | 81 | ||||
-rw-r--r-- | libksirtet/common/settings.cpp | 54 | ||||
-rw-r--r-- | libksirtet/common/settings.h | 28 | ||||
-rw-r--r-- | libksirtet/common/types.cpp | 16 | ||||
-rw-r--r-- | libksirtet/common/types.h | 26 |
24 files changed, 2061 insertions, 0 deletions
diff --git a/libksirtet/common/Makefile.am b/libksirtet/common/Makefile.am new file mode 100644 index 00000000..1c11265d --- /dev/null +++ b/libksirtet/common/Makefile.am @@ -0,0 +1,28 @@ +INCLUDES = -I$(top_builddir)/libksirtet -I$(top_srcdir)/libksirtet -I$(srcdir)/../base -I$(top_srcdir)/libkdegames/highscore -I$(top_srcdir)/libkdegames $(all_includes) + +# Don't compile with hidden symbols since we are a library. +if disable_VISIBILITY +KDE_CXXFLAGS = -fvisibility=default +endif + +noinst_LTLIBRARIES = libksirtetcommon.la +libksirtetcommon_la_LDFLAGS = $(all_libraries) -no-undefined +libksirtetcommon_la_DEPENDENCIES = $(LIB_KDEGAMES_DEP) $(top_builddir)/libksirtet/lib/libksirtetmultiplayers.la $(top_builddir)/libksirtet/base/libksirtetbase.la +libksirtetcommon_la_LIBADD = $(LIB_KDEGAMES) $(top_builddir)/libksirtet/lib/libksirtetmultiplayers.la $(top_builddir)/libksirtet/base/libksirtetbase.la + +noinst_HEADERS = types.h factory.h misc_ui.h highscores.h \ + board.h ai.h field.h settings.h inter.h main.h +libksirtetcommon_la_SOURCES = types.cpp factory.cpp misc_ui.cpp \ + highscores.cpp \ + board.cpp ai.cpp field.cpp settings.cpp \ + inter.cpp main.cpp commonprefs.kcfgc +METASOURCES = misc_ui.moc board.moc ai.moc field.moc \ + settings.moc inter.moc main.moc + +ai.lo: ../base/baseprefs.h +board.lo: ../base/baseprefs.h +commonprefs.lo: ../base/baseprefs.h +field.lo: ../base/baseprefs.h +inter.lo: ../base/baseprefs.h +misc_ui.lo: ../base/baseprefs.h + diff --git a/libksirtet/common/README b/libksirtet/common/README new file mode 100644 index 00000000..03ffa387 --- /dev/null +++ b/libksirtet/common/README @@ -0,0 +1 @@ +This directory contains code shared between ksirtet and kfouleggs. diff --git a/libksirtet/common/ai.cpp b/libksirtet/common/ai.cpp new file mode 100644 index 00000000..bc1c6722 --- /dev/null +++ b/libksirtet/common/ai.cpp @@ -0,0 +1,356 @@ +#include "ai.h" +#include "ai.moc" + +#include <assert.h> + +#include <qlabel.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qlayout.h> +#include <qgrid.h> +#include <qwhatsthis.h> + +#include <klocale.h> +#include <kconfig.h> +#include <kapplication.h> + +#include "commonprefs.h" +#include "board.h" +#include "base/piece.h" +#include "base/factory.h" + + +//----------------------------------------------------------------------------- +AIPiece::AIPiece() + : _current(0) +{} + +AIPiece::~AIPiece() +{ + delete _current; +} + +void AIPiece::init(const Piece *piece, Board *b) +{ + _piece = piece; + _board = b; + if ( _current==0 ) _current = new Piece; + reset(); +} + +void AIPiece::reset() +{ + curPos = 0; + curRot = 0; + if (_piece) _current->copy(_piece); +// else _current->generateNext(0); + nbRot = _current->nbConfigurations() - 1; + nbPos = _board->matrix().width() - _current->size().first + 1; +} + +bool AIPiece::increment() +{ + curPos++; + if ( curPos==nbPos ) { + if ( curRot==nbRot ) { +// if ( _piece || _current->type()==Piece::info().nbTypes() ) { + reset(); + return false; +// } +// _current->generateNext(_current->type()+1); +// nbRot = _current->nbConfigurations() - 1; +// curRot = 0; + } + _current->rotate(true, QPoint(0, 0)); + nbPos = _board->matrix().width() - _current->size().first + 1; + curRot++; + curPos = 0; + } + return true; +} + +bool AIPiece::place() +{ + if ( curRot==3 ) { + if ( !_board->rotateRight() ) return false; + } else for (uint i=0; i<curRot; i++) + if ( !_board->rotateLeft() ) return false; + curDec = curPos - _board->currentPos().first - _current->min().first; + if ( curDec!=0 && _board->moveRight(curDec)!=(uint)kAbs(curDec) ) + return false; + _board->dropDown(); + return !_board->isGameOver(); +} + +//----------------------------------------------------------------------------- +const AI::Data AI::LastData = { 0, 0, 0, false, 0 }; + +AI::AI(uint tTime, uint oTime, const Data *DATA) + : timer(this), thinkTime(tTime), orderTime(oTime), stopped(false), + board(0) +{ + connect(&timer, SIGNAL(timeout()), SLOT(timeout())); + + for (uint i=0; DATA[i].name; i++) { + Element element; + element.coefficient = 0.; + element.trigger = 0; + element.data = &DATA[i]; + _elements.append(element); + } + settingsChanged(); +} + +void AI::resizePieces(uint size) +{ + uint oldSize = pieces.size(); + for (uint i=size; i<oldSize; i++) delete pieces[i]; + pieces.resize(size); + for (uint i=oldSize; i<size; i++) pieces[i] = new AIPiece; +} + +AI::~AI() +{ + delete board; + resizePieces(0); +} + +void AI::initThink() +{ + board->copy(*main); +} + +void AI::launch(Board *m) +{ + main = m; + if ( board==0 ) + board = static_cast<Board *>(bfactory->createBoard(false, 0)); + + pieces[0]->init(main->currentPiece(), board); // current + if ( pieces.size()>=2 ) pieces[1]->init(main->nextPiece(), board); // next + + state = Thinking; + hasBestPoints = false; + startTimer(); +} + +void AI::stop() +{ + timer.stop(); + stopped = true; +} + +void AI::start() +{ + if (stopped) { + startTimer(); + stopped = false; + } +} + +void AI::startTimer() +{ + switch (state) { + case Thinking: timer.start(thinkTime, true); break; + case GivingOrders: timer.start(orderTime, true); break; + } +} + +void AI::timeout() +{ + switch (state) { + case Thinking: + if ( think() ) state = GivingOrders; + break; + case GivingOrders: + if ( emitOrder() ) return; + break; + } + + startTimer(); +} + +bool AI::emitOrder() +{ + if ( bestRot==3 ) { + bestRot = 0; + main->pRotateRight(); + } else if (bestRot) { + bestRot--; + main->pRotateLeft(); + } else if ( bestDec>0 ) { + bestDec--; + main->pMoveRight(); + } else if ( bestDec<0 ) { + bestDec++; + main->pMoveLeft(); + } else { + main->pDropDownStart(); + return true; + } + return false; +} + +bool AI::think() +{ + initThink(); + bool moveOk = true; + for (uint i=0; i<pieces.size(); i++) + if ( !pieces[i]->place() ) { + moveOk = false; + break; + } + if (moveOk) { + double p = points(); + if ( !hasBestPoints || p>bestPoints + || (p==hasBestPoints && random.getBool()) ) { + hasBestPoints = true; + bestPoints = p; + bestDec = pieces[0]->dec(); + bestRot = pieces[0]->rot(); + } + } + + for (uint i=pieces.size(); i>0; i--) + if ( pieces[i-1]->increment() ) return false; + return true; +} + +double AI::points() const +{ + double pts = 0; + for (uint i=0; i<_elements.size(); i++) { + if ( _elements[i].coefficient==0.0 ) continue; + double v = _elements[i].data->function(*main, *board); + if ( _elements[i].data->triggered && qRound(v)<_elements[i].trigger ) + continue; + pts += _elements[i].coefficient * v; + } + return pts; +} + +void AI::settingsChanged() +{ + int d = CommonPrefs::thinkingDepth(); + resizePieces(d); + for (uint i=0; i<_elements.size(); i++) { + const Data &data = *_elements[i].data; + _elements[i].coefficient = AIConfig::coefficient(data); + if (data.triggered) _elements[i].trigger = AIConfig::trigger(data); + } + if ( timer.isActive() ) launch(main); +} + +double AI::nbOccupiedLines(const Board &, const Board ¤t) +{ + return current.matrix().height() - current.nbClearLines(); +} + +double AI::nbHoles(const Board &, const Board ¤t) +{ + uint nb = 0; + for (uint i=0; i<current.matrix().width(); i++) { + for (int j=current.firstColumnBlock(i)-1; j>=0; j--) { + KGrid2D::Coord c(i, j); + if ( current.matrix()[c]==0 ) nb++; + } + } + return nb; +} + +double AI::peakToPeak(const Board &, const Board ¤t) +{ + int min = current.matrix().height()-1; + for (uint i=0; i<current.matrix().width(); i++) + min = kMin(min, current.firstColumnBlock(i)); + return (int)current.firstClearLine()-1 - min; +} + +double AI::mean(const Board &, const Board ¤t) +{ + double mean = 0; + for (uint i=0; i<current.matrix().width(); i++) + mean += current.firstColumnBlock(i); + return mean / current.matrix().width(); +} + +double AI::nbSpaces(const Board &main, const Board ¤t) +{ + double nb = 0; + double m = mean(main, current); + for (uint i=0; i<current.matrix().width(); i++) { + int j = current.firstColumnBlock(i); + if ( j<m ) nb += m - j; + } + return nb; +} + +double AI::nbRemoved(const Board &main, const Board ¤t) +{ + return current.nbRemoved() - main.nbRemoved(); +} + + +//----------------------------------------------------------------------------- +const uint AIConfig::minThinkingDepth = 1; +const uint AIConfig::maxThinkingDepth = 2; + +AIConfig::AIConfig(const QValueVector<AI::Element> &elements) + : QWidget(0, "ai config") +{ + QGridLayout *top = new QGridLayout(this, 3, 2, KDialog::marginHint(), + KDialog::spacingHint()); + + QLabel *label = new QLabel(i18n("Thinking depth:"), this); + top->addWidget(label, 0, 0); + KIntNumInput *in = new KIntNumInput(this, "kcfg_ThinkingDepth"); + in->setRange(minThinkingDepth, maxThinkingDepth); + top->addWidget(in, 0, 1); + + top->addRowSpacing(1, KDialog::spacingHint()); + + QGrid *grid = new QGrid(2, this); + top->addMultiCellWidget(grid, 2, 2, 0, 1); + for (uint i=0; i<elements.size(); i++) { + const AI::Data &data = *elements.at(i).data; + QLabel *label = new QLabel(i18n(data.label), grid); + if (data.whatsthis) QWhatsThis::add(label, i18n(data.whatsthis)); + label->setFrameStyle(QFrame::Panel | QFrame::Plain); + + QVBox *vb = new QVBox(grid); + if (data.whatsthis) QWhatsThis::add(vb, i18n(data.whatsthis)); + vb->setMargin(KDialog::spacingHint()); + vb->setSpacing(KDialog::spacingHint()); + vb->setFrameStyle(QFrame::Panel | QFrame::Plain); + if (data.triggered) { + KIntNumInput *trig = new KIntNumInput(vb, triggerKey(data.name)); + trig->setRange(0, 10, 1, true); + } + KDoubleNumInput *coeff = new KDoubleNumInput(vb, coefficientKey(data.name)); + coeff->setRange(0.0, 1.0, 1.0, true); + } +} + +QCString AIConfig::triggerKey(const char *name) +{ + return "kcfg_Trigger_" + QCString(name); +} + +QCString AIConfig::coefficientKey(const char *name) +{ + return "kcfg_Coefficient_" + QCString(name); +} + +double AIConfig::coefficient(const AI::Data &data) +{ + KConfigSkeletonItem *item = CommonPrefs::self()->findItem( QString("Coefficient_%1").arg(data.name) ); + assert(item); + return item->property().toDouble(); +} + +int AIConfig::trigger(const AI::Data &data) +{ + KConfigSkeletonItem *item = CommonPrefs::self()->findItem( QString("Trigger_%1").arg(data.name) ); + assert(item); + return item->property().toInt(); +} diff --git a/libksirtet/common/ai.h b/libksirtet/common/ai.h new file mode 100644 index 00000000..da298abc --- /dev/null +++ b/libksirtet/common/ai.h @@ -0,0 +1,122 @@ +#ifndef COMMON_AI_H +#define COMMON_AI_H + +#include <qtimer.h> +#include <qvaluevector.h> + +#include <kdialogbase.h> +#include <knuminput.h> +#include <krandomsequence.h> +#include "lib/libksirtet_export.h" + +class Board; +class Piece; + + +//----------------------------------------------------------------------------- +class LIBKSIRTET_EXPORT AIPiece +{ + public: + AIPiece(); + ~AIPiece(); + + void init(const Piece *p, Board *b); + bool place(); + bool increment(); + + int dec() const { return curDec; } + uint rot() const { return curRot; } + + private: + uint nbPos, nbRot, curPos, curRot; + int curDec; + const Piece *_piece; + Piece *_current; + Board *_board; + + void reset(); +}; + +//----------------------------------------------------------------------------- +class LIBKSIRTET_EXPORT AI : public QObject +{ + Q_OBJECT + public: + struct Data { + const char *name, *label, *whatsthis; + bool triggered; + double (*function)(const Board &, const Board &); + }; + static const Data LastData; + + AI(uint thinkTime, uint orderTime, const Data *DATA); + virtual ~AI(); + + void launch(Board *main); + void stop(); + void start(); + + class Element { + public: + const Data *data; + double coefficient; + int trigger; + }; + const QValueVector<Element> &elements() const { return _elements; } + + void settingsChanged(); + + private slots: + void timeout(); + + protected: + virtual void initThink(); + + static double nbOccupiedLines(const Board &, const Board &); + static double nbHoles(const Board &, const Board &); + static double nbSpaces(const Board &, const Board &); + static double peakToPeak(const Board &, const Board &); + static double mean(const Board &, const Board &); + static double nbRemoved(const Board &, const Board &); + + private: + bool think(); + void startTimer(); + bool emitOrder(); + double points() const; + void resizePieces(uint size); + + QTimer timer; + enum ThinkState { Thinking, GivingOrders }; + ThinkState state; + uint thinkTime, orderTime; + bool stopped; + QMemArray<AIPiece *> pieces; + QValueVector<Element> _elements; + Board *main, *board; + KRandomSequence random; + + bool hasBestPoints; + double bestPoints; + int bestDec; + uint bestRot; +}; + +//----------------------------------------------------------------------------- +class LIBKSIRTET_EXPORT AIConfig : public QWidget +{ + Q_OBJECT + public: + AIConfig(const QValueVector<AI::Element> &elements); + + static double coefficient(const AI::Data &data); + static int trigger(const AI::Data &data); + + private: + static QCString triggerKey(const char *name); + static QCString coefficientKey(const char *name); + + static const uint minThinkingDepth, maxThinkingDepth; +}; + +#endif diff --git a/libksirtet/common/board.cpp b/libksirtet/common/board.cpp new file mode 100644 index 00000000..f5f011a6 --- /dev/null +++ b/libksirtet/common/board.cpp @@ -0,0 +1,286 @@ +#include "board.h" +#include "board.moc" + +#include <knotifyclient.h> +#include <klocale.h> + +#include "factory.h" +#include "base/piece.h" +#include "misc_ui.h" +#include "ai.h" +#include "commonprefs.h" + + +Board::Board(bool graphic, GiftPool *gp, QWidget *parent) + : BaseBoard(graphic, parent), + _giftPool(gp), aiEngine(0) +{} + +Board::~Board() +{ + delete aiEngine; +} + +void Board::setType(bool _ai) +{ + Q_ASSERT( graphic() ); + if (_ai) { + if ( aiEngine==0 ) aiEngine = cfactory->createAI(); + } else { + delete aiEngine; + aiEngine = 0; + } +} + +void Board::start(const GTInitData &data) +{ + randomGarbage.setSeed(data.seed); + _giftPool->reset(); + BaseBoard::start(data); +} + +void Board::stop() +{ + BaseBoard::stop(); + if (aiEngine) aiEngine->stop(); +} + +void Board::showBoard(bool show) +{ + BaseBoard::showBoard(show); + showCanvas(_next, show); +} + +void Board::unpause() +{ + BaseBoard::unpause(); + if (aiEngine) aiEngine->start(); // eventually restart thinking +} + +void Board::updateLevel() +{ + uint nb = cfactory->cbi.nbRemovedToLevel; + if ( nbRemoved()>=level()*nb ) updateLevel(level()+1); +} + +void Board::updateLevel(uint newLevel) +{ + BaseBoard::updateLevel(newLevel); + emit levelUpdated(); + if ( graphic() ) startTimer(); +} + +void Board::settingsChanged() +{ + BaseBoard::settingsChanged(); + if (aiEngine) aiEngine->settingsChanged(); +} + +/*****************************************************************************/ +void Board::pMoveLeft() +{ + if ( state!=Normal ) return; + moveLeft(); + main->update(); +} + +void Board::pMoveRight() +{ + if ( state!=Normal ) return; + moveRight(); + main->update(); +} + +void Board::pMoveLeftTotal() +{ + if ( state!=Normal ) return; + moveLeft(bfactory->bbi.width); + main->update(); +} + +void Board::pMoveRightTotal() +{ + if ( state!=Normal ) return; + moveRight(bfactory->bbi.width); + main->update(); +} + +void Board::pOneLineDown() +{ + if ( state!=Normal ) return; + oneLineDown(); + main->update(); +} + +void Board::pDropDownStart() +{ + if ( state!=Normal ) return; + _dropHeight = 0; + oneLineDown(); + if ( state==Normal ) { + state = DropDown; + startTimer(); + } + main->update(); +} + +void Board::pDropDownStop() +{ + if ( state!=DropDown || CommonPrefs::directDropDownEnabled() ) return; + state = Normal; + startTimer(); + main->update(); +} + +void Board::pRotateLeft() +{ + if ( state!=Normal ) return; + rotateLeft(); + main->update(); +} + +void Board::pRotateRight() +{ + if ( state!=Normal ) return; + rotateRight(); + main->update(); +} + +void Board::pieceDropped(uint dropHeight) +{ + if ( state==DropDown ) state = Normal; + else _dropHeight = dropHeight; + _beforeGlue(true); +} + +void Board::_beforeGlue(bool first) +{ + if ( graphic() ) { + state = (beforeGlue(_dropHeight>=1, first) ? BeforeGlue : Normal); + if ( state==BeforeGlue ) { + startTimer(); + return; + } + } + gluePiece(); +} + +void Board::gluePiece() +{ + BaseBoard::gluePiece(); + _afterGlue(true); + if ( graphic() ) KNotifyClient::event(winId(), "glued", i18n("Piece glued")); +} + +void Board::_afterGlue(bool first) +{ + bool b = afterGlue(!graphic(), first); + if ( graphic() ) { + state = (b ? AfterGlue : Normal); + if ( state==AfterGlue ) { + startTimer(); + return; + } + } + + updateScore(score() + _dropHeight); + if ( needRemoving() ) _beforeRemove(true); + else _afterAfterRemove(); +} + +bool Board::afterAfterRemove() +{ + // checkGift + if ( graphic() && _giftPool->pending() ) { + if ( putGift(_giftPool->take()) ) { + computeInfos(); + _afterGift(true); + return true; + } else return false; + } + return newPiece(); +} + +void Board::_afterGift(bool first) +{ + Q_ASSERT( graphic() ); + state = (afterGift(first) ? AfterGift : Normal); + if ( state==AfterGift ) startTimer(); + else afterAfterRemove(); +} + +bool Board::newPiece() +{ + Q_ASSERT( !graphic() || state==Normal ); + if ( !BaseBoard::newPiece() ) return false; + if ( graphic() ) { + main->update(); + _next->update(); + if (aiEngine) aiEngine->launch(this); + // else : a human player can think by himself ... + } + return true; +} + +bool Board::timeout() +{ + if ( BaseBoard::timeout() ) return true; + + switch (state) { + case DropDown: _dropHeight++; + case Normal: oneLineDown(); break; + case BeforeGlue: _beforeGlue(false); break; + case AfterGlue: _afterGlue(false); break; + case AfterGift: _afterGift(false); break; + default: return false; + } + main->update(); + return true; +} + +uint Board::normalTime() const +{ + return cfactory->cbi.baseTime / (1 + level()); +} + +bool Board::startTimer() +{ + if ( BaseBoard::startTimer() ) return true; + + switch (state) { + case Normal: + timer.start(normalTime()); + break; + case DropDown: + timer.start(cfactory->cbi.dropDownTime); + break; + case BeforeGlue: + timer.start(cfactory->cbi.beforeGlueTime, true); + break; + case AfterGlue: + timer.start(cfactory->cbi.afterGlueTime, true); + break; + case AfterGift: + timer.start(cfactory->cbi.afterGiftTime, true); + break; + default: + return false; + } + return true; +} + + +//----------------------------------------------------------------------------- +bool Board::beforeGlue(bool bump, bool first) +{ + if ( !bump ) return false; + if (first) { + loop = 0; + return true; + } else loop++; + + float dec = BasePrefs::blockSize() * (loop+1) * -0.1; + if ( BasePrefs::animationsEnabled() ) bumpCurrentPiece((int)dec); + + return ( loop!=cfactory->cbi.nbBumpStages ); +} diff --git a/libksirtet/common/board.h b/libksirtet/common/board.h new file mode 100644 index 00000000..97c37c17 --- /dev/null +++ b/libksirtet/common/board.h @@ -0,0 +1,75 @@ +#ifndef COMMON_BOARD_H +#define COMMON_BOARD_H + +#include "base/board.h" + +#include "lib/libksirtet_export.h" + +class GiftPool; +class AI; + +class LIBKSIRTET_EXPORT Board : public BaseBoard +{ + Q_OBJECT + public: + Board(bool graphic, GiftPool *, QWidget *parent); + virtual ~Board(); + + void setType(bool computer); + virtual void start(const GTInitData &); + void unpause(); + void stop(); + + virtual uint gift() = 0; + virtual bool needRemoving() = 0; + + GiftPool *giftPool() const { return _giftPool; } + + public slots: + void pMoveLeft(); + void pMoveRight(); + void pDropDownStart(); + void pDropDownStop(); + void pOneLineDown(); + void pRotateLeft(); + void pRotateRight(); + void pMoveLeftTotal(); + void pMoveRightTotal(); + + private slots: + bool timeout(); + + signals: + void levelUpdated(); + + protected: + KRandomSequence randomGarbage; + + virtual bool beforeGlue(bool bump, bool first); + virtual void gluePiece(); + virtual bool afterGlue(bool /*doAll*/, bool /*first*/) { return false; } + virtual bool afterGift(bool /*first*/) { return false; } + virtual bool putGift(uint) = 0; + + virtual uint normalTime() const; + void updateLevel(); + + void settingsChanged(); + + private: + uint _dropHeight; + GiftPool *_giftPool; + AI *aiEngine; + + bool newPiece(); + void pieceDropped(uint dropHeight); + void _afterGift(bool first); + void _beforeGlue(bool first); + void _afterGlue(bool first); + bool afterAfterRemove(); + bool startTimer(); + void showBoard(bool show); + void updateLevel(uint newLevel); +}; + +#endif diff --git a/libksirtet/common/commonprefs.kcfgc b/libksirtet/common/commonprefs.kcfgc new file mode 100644 index 00000000..8e41b16f --- /dev/null +++ b/libksirtet/common/commonprefs.kcfgc @@ -0,0 +1,9 @@ +# Code generation options for kconfig_compiler +File=libksirtet2.kcfg +IncludeFiles=base/baseprefs.h +ClassName=CommonPrefs +Inherits=BasePrefs +Singleton=true +#Mutators=true +#CustomAdditions=true +Mutators=false diff --git a/libksirtet/common/factory.cpp b/libksirtet/common/factory.cpp new file mode 100644 index 00000000..1b239a82 --- /dev/null +++ b/libksirtet/common/factory.cpp @@ -0,0 +1,28 @@ +#include "factory.h" + +#include "ai.h" +#include "settings.h" + + +CommonFactory::CommonFactory(const MainData &md, const BaseBoardInfo &bbi, + const CommonBoardInfo &ci) + : BaseFactory(md, bbi), cbi(ci) +{} + +QWidget *CommonFactory::createAppearanceConfig() +{ + return new AppearanceConfig; +} + +QWidget *CommonFactory::createGameConfig() +{ + return new GameConfig; +} + +QWidget *CommonFactory::createAIConfig() +{ + AI *ai = createAI(); + QWidget *cw = new AIConfig(ai->elements()); + delete ai; + return cw; +} diff --git a/libksirtet/common/factory.h b/libksirtet/common/factory.h new file mode 100644 index 00000000..c0b40d66 --- /dev/null +++ b/libksirtet/common/factory.h @@ -0,0 +1,36 @@ +#ifndef COMMON_FACTORY_H +#define COMMON_FACTORY_H + +#include "base/factory.h" + +#include "lib/libksirtet_export.h" + +struct CommonBoardInfo { + uint baseTime, dropDownTime, beforeGlueTime, afterGlueTime; + uint afterGiftTime, nbBumpStages; + uint nbRemovedToLevel; + uint nbGiftLeds, maxGiftsToSend, giftShowerTimeout, giftPoolTimeout; +}; + +class BaseField; +class AI; + +#define cfactory static_cast<CommonFactory *>(BaseFactory::self()) + +class LIBKSIRTET_EXPORT CommonFactory : public BaseFactory +{ + public: + CommonFactory(const MainData &, const BaseBoardInfo &, + const CommonBoardInfo &); + + const CommonBoardInfo &cbi; + + virtual BaseField *createField(QWidget *parent) = 0; + virtual AI *createAI() = 0; + + QWidget *createAIConfig(); + virtual QWidget *createAppearanceConfig(); + virtual QWidget *createGameConfig(); +}; + +#endif diff --git a/libksirtet/common/field.cpp b/libksirtet/common/field.cpp new file mode 100644 index 00000000..2d67062e --- /dev/null +++ b/libksirtet/common/field.cpp @@ -0,0 +1,243 @@ +#include "field.h" +#include "field.moc" + +#include <qwhatsthis.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klocale.h> +#include <kprogress.h> +#include <kgameprogress.h> +#include <kcanvasrootpixmap.h> +#include <kgamelcd.h> + +#include "base/baseprefs.h" +#include "factory.h" +#include "highscores.h" +#include "misc_ui.h" +#include "board.h" +#include "commonprefs.h" + + +Field::Field(QWidget *parent) +: MPSimpleBoard(parent), BaseField(this) +{ +// column 1 + // score LCD + scoreList = new KGameLCDList(this); + showScore = new KGameLCD(6, scoreList); + scoreList->append(showScore); + showTime = new KGameLCDClock(scoreList); + scoreList->append(showTime); + lcds->addWidget(scoreList, 1, 0); + lcds->setRowStretch(2, 1); + + // removed LCD + removedList = new KGameLCDList(i18n(bfactory->mainData.removedLabel), this); + lcds->addWidget(removedList, 3, 0); + lcds->setRowStretch(4, 1); + + // level progress + levelLabel = new QLabel(this); + levelLabel->setAlignment(AlignCenter); + lcds->addWidget(levelLabel, 5, 0); + toLevel = new KProgress(this); + toLevel->setTextEnabled(true); + toLevel->setFormat("1"); + QWhatsThis::add(toLevel, i18n("Display the progress to complete the current level or stage.")); + lcds->addWidget(toLevel, 6, 0); + lcds->setRowStretch(7, 1); + +// column 2 + // previous player height + prevHeight = new PlayerProgress(board, this, "prev_progress"); + QWhatsThis::add(prevHeight, i18n("Previous player's height")); + top->addWidget(prevHeight, 1, 1, AlignHCenter); + +// column 3 + // pending gift shower + Board *b = static_cast<Board *>(board); + top->addWidget(b->giftPool(), 0, 2, AlignCenter); + + // shadow piece + shadow = new Shadow(board, this); + QWhatsThis::add(shadow, i18n("Shadow of the current piece")); + top->addWidget(shadow, 2, 2); + +// column 4 + // next player height + nextHeight = new PlayerProgress(board, this, "next_progress"); + QWhatsThis::add(nextHeight, i18n("Next player's height")); + top->addWidget(nextHeight, 1, 3, AlignHCenter); + +// column 5 + // next piece shower + QVBoxLayout *vbl = new QVBoxLayout(10); + top->addLayout(vbl, 1, 4); + vbl->addStretch(1); + + labShowNext = new QLabel(i18n("Next Tile"), this); + labShowNext->setAlignment(AlignCenter); + vbl->addWidget(labShowNext, 0); + showNext = new ShowNextPiece(board, this); + _snRootPixmap = new KCanvasRootPixmap(showNext); + _snRootPixmap->start(); + vbl->addWidget(showNext, 0); + vbl->addStretch(4); + + connect(board, SIGNAL(scoreUpdated()), SLOT(scoreUpdatedSlot())); + connect(board, SIGNAL(levelUpdated()), SLOT(levelUpdated())); + connect(board, SIGNAL(removedUpdated()), SLOT(removedUpdated())); + + initVariableGUI(); +} + +void Field::levelUpdated() +{ + toLevel->setFormat(QString::number(board->level())); + // necessary to update string ... + int p = toLevel->progress(); + toLevel->setProgress(p+1); + toLevel->setProgress(p); +} + +void Field::removedUpdated() +{ + uint nb = cfactory->cbi.nbRemovedToLevel; + toLevel->setProgress(isArcade() ? board->arcadeDone() + : board->nbRemoved() % nb); +} + +void Field::showOpponents(bool show) +{ + Board *b = static_cast<Board *>(board); + if (show) { + prevHeight->show(); + nextHeight->show(); + b->giftPool()->show(); + } else { + prevHeight->hide(); + nextHeight->hide(); + b->giftPool()->hide(); + } +} + +void Field::settingsChanged() +{ + BaseField::settingsChanged(); + QColor color = BasePrefs::fadeColor(); + double s = BasePrefs::fadeIntensity(); + _snRootPixmap->setFadeEffect(s, color); + showNext->canvas()->setBackgroundColor(color); + bool b = CommonPrefs::showNextPiece(); + if (b) { + showNext->show(); + labShowNext->show(); + } else { + showNext->hide(); + labShowNext->hide(); + } + b = CommonPrefs::showPieceShadow(); + if (b) shadow->show(); + else shadow->hide(); +} + +void Field::_init(bool AI, bool multiplayer, bool server, bool first, + const QString &name) +{ + BaseField::init(AI, multiplayer, server, first, name); + showOpponents(multiplayer); + static_cast<Board *>(board)->setType(AI); +} + +void Field::_initFlag(QDataStream &s) +{ + ServerInitData sid; + s >> sid; + GTInitData data; + data.seed = sid.seed; + data.initLevel = sid.initLevel; + + shadow->setDisplay(true); + toLevel->setValue(0); + showTime->reset(); + showTime->start(); + + BaseField::start(data); + initVariableGUI(); +} + +void Field::initVariableGUI() +{ + if ( board->isArcade() ) { + scoreList->title()->setText(i18n("Elapsed time")); + showScore->hide(); + showTime->show(); + QWhatsThis::add(scoreList, i18n("Display the elapsed time.")); + levelLabel->setText(i18n("Stage")); + toLevel->setTotalSteps( board->arcadeTodo() ); + } else { + scoreList->title()->setText(i18n("Score")); + showScore->show(); + showTime->hide(); + QWhatsThis::add(scoreList, i18n("<qt>Display the current score.<br/>It turns <font color=\"blue\">blue</font> if it is a highscore and <font color=\"red\">red</font> if it is the best local score.</qt>")); + levelLabel->setText(i18n("Level")); + toLevel->setTotalSteps(cfactory->cbi.nbRemovedToLevel); + } +} + +void Field::_playFlag(QDataStream &s) +{ + ServerPlayData spd; + s >> spd; + prevHeight->setValue(spd.prevHeight); + nextHeight->setValue(spd.nextHeight); + if (spd.gift) + static_cast<Board *>(board)->giftPool()->put(spd.gift); +} + +void Field::_pauseFlag(bool p) +{ + pause(p); + shadow->setDisplay(!p); + if (p) showTime->stop(); + else showTime->start(); +} + +void Field::_stopFlag(bool gameover) +{ + BaseField::stop(gameover); + showTime->stop(); +} + +void Field::_dataOut(QDataStream &s) +{ + _cpd.height = board->firstClearLine(); + _cpd.end = static_cast<Board *>(board)->isGameOver(); + _cpd.gift = static_cast<Board *>(board)->gift(); + s << _cpd; +} + +KExtHighscore::Score Field::currentScore() const +{ + KExtHighscore::Score score(_cpd.end ? KExtHighscore::Lost : KExtHighscore::Won); + score.setScore(board->score()); + score.setData("level", board->level()); + score.setData("removed", board->nbRemoved()); + return score; +} + +void Field::_gameOverDataOut(QDataStream &s) +{ + s << currentScore(); +} + +void Field::moveLeft() { static_cast<Board *>(board)->pMoveLeft(); } +void Field::moveRight() { static_cast<Board *>(board)->pMoveRight(); } +void Field::dropDownStart() { static_cast<Board *>(board)->pDropDownStart(); } +void Field::dropDownStop() { static_cast<Board *>(board)->pDropDownStop(); } +void Field::oneLineDown() { static_cast<Board *>(board)->pOneLineDown(); } +void Field::rotateLeft() { static_cast<Board *>(board)->pRotateLeft(); } +void Field::rotateRight() { static_cast<Board *>(board)->pRotateRight(); } +void Field::moveLeftTotal() { static_cast<Board *>(board)->pMoveLeftTotal(); } +void Field::moveRightTotal() { static_cast<Board *>(board)->pMoveRightTotal();} diff --git a/libksirtet/common/field.h b/libksirtet/common/field.h new file mode 100644 index 00000000..8179539b --- /dev/null +++ b/libksirtet/common/field.h @@ -0,0 +1,68 @@ +#ifndef COMMON_FIELD_H +#define COMMON_FIELD_H + +#include "lib/mp_simple_board.h" +#include "base/field.h" +#include "types.h" + +#include "lib/libksirtet_export.h" + + +class ShowNextPiece; +class GiftShower; +class Shadow; +class KProgress; +class KGameProgress; +class KGameLCDClock; + +class LIBKSIRTET_EXPORT Field : public MPSimpleBoard, public BaseField +{ + Q_OBJECT + public: + Field(QWidget *parent); + + public slots: + void moveLeft(); + void moveRight(); + void dropDownStart(); + void dropDownStop(); + void oneLineDown(); + void rotateLeft(); + void rotateRight(); + void moveLeftTotal(); + void moveRightTotal(); + + virtual void settingsChanged(); + + protected slots: + void scoreUpdatedSlot() { scoreUpdated(); } + virtual void levelUpdated(); + virtual void removedUpdated(); + + private: + KGameLCDClock *showTime; + ShowNextPiece *showNext; + KProgress *toLevel; + QLabel *labShowNext, *levelLabel; + KGameProgress *prevHeight, *nextHeight; + Shadow *shadow; + KCanvasRootPixmap *_snRootPixmap; + ClientPlayData _cpd; + + void _init(bool AI, bool multiplayer, bool server, bool first, + const QString &name); + void showOpponents(bool show); + void initVariableGUI(); + + void _initFlag(QDataStream &); + void _playFlag(QDataStream &); + void _pauseFlag(bool pause); + void _stopFlag(bool gameover); + void _dataOut(QDataStream &); + void _gameOverDataOut(QDataStream &); + void _initDataOut(QDataStream &) {} + + KExtHighscore::Score currentScore() const; +}; + +#endif diff --git a/libksirtet/common/highscores.cpp b/libksirtet/common/highscores.cpp new file mode 100644 index 00000000..799a31b9 --- /dev/null +++ b/libksirtet/common/highscores.cpp @@ -0,0 +1,60 @@ +#include "highscores.h" + +#include <klocale.h> +#include <kapplication.h> +#include <kconfig.h> + +#include "base/factory.h" + + +using namespace KExtHighscore; + +CommonHighscores::CommonHighscores() +{ + Item *item = new Item((uint)1, i18n("Level"), Qt::AlignRight); + addScoreItem("level", item); + item = new Item((uint)0, i18n(bfactory->mainData.removedLabel), + Qt::AlignRight); + addScoreItem("removed", item); +} + +void CommonHighscores::convertLegacy(uint) +{ + KConfigGroupSaver cg(kapp->config(), "High Scores"); + for (uint i=0; i<10; i++) { + QString name + = cg.config()->readEntry(QString("name%1").arg(i), QString::null); + if ( name.isNull() ) break; + if ( name.isEmpty() ) name = i18n("anonymous"); + uint score + = cg.config()->readUnsignedNumEntry(QString("score%1").arg(i), 0); + uint level + = cg.config()->readUnsignedNumEntry(QString("level%1").arg(i), 1); + Score s(Won); + s.setScore(score); + s.setData("name", name); + s.setData("level", level); + submitLegacyScore(s); + } +} + +bool CommonHighscores::isStrictlyLess(const Score &s1, const Score &s2) const +{ + uint l1 = s1.data("level").toUInt(); + uint r1 = s1.data("removed").toUInt(); + uint l2 = s2.data("level").toUInt(); + uint r2 = s2.data("removed").toUInt(); + + if ( s1.score()==s2.score() ) { + if ( l1==l2 ) return r1<r2; + else return l1<l2; + } else return BaseHighscores::isStrictlyLess(s1, s2); +} + +void CommonHighscores::additionalQueryItems(KURL &url, const Score &s) const +{ + uint l = s.data("level").toUInt(); + addToQueryURL(url, "scoreLevel", QString::number(l)); + uint r = s.data("removed").toUInt(); + addToQueryURL(url, "scoreRemoved", QString::number(r)); +} diff --git a/libksirtet/common/highscores.h b/libksirtet/common/highscores.h new file mode 100644 index 00000000..f04c0d2e --- /dev/null +++ b/libksirtet/common/highscores.h @@ -0,0 +1,20 @@ +#ifndef COMMON_HIGHSCORES_H +#define COMMON_HIGHSCORES_H + +#include "base/highscores.h" + +#include "lib/libksirtet_export.h" + +class LIBKSIRTET_EXPORT CommonHighscores : public BaseHighscores +{ + public: + CommonHighscores(); + + private: + void convertLegacy(uint level); + bool isStrictlyLess(const KExtHighscore::Score &, + const KExtHighscore::Score &) const; + void additionalQueryItems(KURL &, const KExtHighscore::Score &) const; +}; + +#endif diff --git a/libksirtet/common/inter.cpp b/libksirtet/common/inter.cpp new file mode 100644 index 00000000..e9f1688b --- /dev/null +++ b/libksirtet/common/inter.cpp @@ -0,0 +1,150 @@ +#include "inter.h" +#include "inter.moc" + +#include <klocale.h> +#include <kaction.h> +#include <kapplication.h> + +#include "factory.h" +#include "field.h" +#include "commonprefs.h" +#include "main.h" + + +const ActionData Interface::ACTION_DATA[Nb_Actions] = { + { I18N_NOOP("Move Left"), "move left", SLOT(moveLeft()), 0 }, + { I18N_NOOP("Move Right"), "move right", SLOT(moveRight()), 0 }, + { I18N_NOOP("Drop Down"), "drop down", SLOT(dropDownStart()), + SLOT(dropDownStop()) }, + { I18N_NOOP("One Line Down"), "one line down", SLOT(oneLineDown()), 0 }, + { I18N_NOOP("Rotate Left"), "rotate left", SLOT(rotateLeft()), 0 }, + { I18N_NOOP("Rotate Right"), "rotate right", SLOT(rotateRight()), 0 }, + { I18N_NOOP("Move to Left Column"), "move left total", + SLOT(moveLeftTotal()), 0 }, + { I18N_NOOP("Move to Right Column"), "move right total", + SLOT(moveRightTotal()), 0 } +}; + +const int Interface::KEYCODE_ONE[Nb_Actions] = { + Key_Left, Key_Right, Key_Down, Key_Shift, Key_Up, Key_Return, + CTRL+Key_Left, CTRL+Key_Right +}; +const int Interface::KEYCODE_TWO[Nb_Actions] = { + Key_F, Key_G, Key_D, Key_Space, Key_E, Key_C, SHIFT+Key_F, SHIFT+Key_G +}; + +Interface::Interface(const MPGameInfo &gi, QWidget *parent) + : MPSimpleInterface(gi, Nb_Actions, ACTION_DATA, parent) +{ + setDefaultKeycodes(1, 0, KEYCODE_ONE); + setDefaultKeycodes(2, 0, KEYCODE_TWO); + setDefaultKeycodes(2, 1, KEYCODE_ONE); +} + +MPBoard *Interface::newBoard(uint i) +{ + Field *f = static_cast<Field *>(cfactory->createField(this)); + f->settingsChanged(); + connect(this, SIGNAL(settingsChanged()), f, SLOT(settingsChanged())); + if ( i==0 ) _firstField = f; + return f; +} + +void Interface::normalGame() +{ + singleHuman(); +} + +void Interface::arcadeGame() +{ + singleHuman(); + _firstField->setArcade(); +} + +void Interface::_init() +{ + if ( !server() ) return; + _data.resize(nbPlayers()); + _scores.setPlayerCount( nbPlayers() ); + for (uint i=0; i<nbPlayers(); i++) + _scores.setName(i, playerName(i)); +} + +bool Interface::_readPlayData() +{ + bool end = false; + for (uint i=0; i<nbPlayers(); i++) { + readingStream(i) >> _data[i]; + if (_data[i].end) end = true; + } + return end; +} + +void Interface::_sendPlayData() +{ + ServerPlayData sd; + for(uint i=0; i<nbPlayers(); i++) { + sd.prevHeight = _data[prev(i)].height; + sd.nextHeight = _data[next(i)].height; + sd.gift = _data[prev(i)].gift; + writingStream(i) << sd; + } +} + +void Interface::_showHighscores(QWidget *parent) +{ + if ( !server() || nbPlayers()!=1 ) _scores.show(parent); + else BaseInterface::_showHighscores(parent); +} + +void Interface::_showGameOverData() +{ + if ( !server() || nbPlayers()!=1 ) _scores.show(this); + else if ( !_firstField->isArcade() ) { + _score.setType(KExtHighscore::Won); + BaseField::gameOver(_score, this); + } +} + +uint Interface::prev(uint i) const +{ + if ( i==0 ) return nbPlayers()-1; + else return i-1; +} + +uint Interface::next(uint i) const +{ + if ( i==(nbPlayers()-1) ) return 0; + else return i+1; +} + +// server only +void Interface::_treatInit() +{ + ServerInitData sid; + sid.seed = kapp->random(); + sid.initLevel = CommonPrefs::initialGameLevel(); + for (uint i=0; i<nbPlayers(); i++) { + sid.prevName = playerName(prev(i)); + sid.nextName = playerName(next(i)); + sid.name = playerName(i); + writingStream(i) << sid; + } +} + +void Interface::_sendGameOverData(QDataStream &s) +{ + bool multiplayers = ( nbPlayers()>1 ); + for (uint i=0; i<nbPlayers(); i++) { + readingStream(i) >> _score; + if (multiplayers) _scores.addScore(i, _score); + } + if (multiplayers) s << _scores; + // else no need to send anything +} + +// client only +void Interface::_readGameOverData(QDataStream &s) +{ + s >> _scores; +} diff --git a/libksirtet/common/inter.h b/libksirtet/common/inter.h new file mode 100644 index 00000000..e38c2ed5 --- /dev/null +++ b/libksirtet/common/inter.h @@ -0,0 +1,62 @@ +#ifndef COMMON_INTER_H +#define COMMON_INTER_H + +#include <kexthighscore.h> +#include "lib/libksirtet_export.h" + +#include "lib/mp_simple_interface.h" +#include "base/inter.h" +#include "types.h" +#include "board.h" + + +class Field; + +class LIBKSIRTET_EXPORT Interface : public MPSimpleInterface, public BaseInterface +{ + Q_OBJECT +public: + Interface(const MPGameInfo &, QWidget *parent); + +signals: + void settingsChanged(); + +public slots: + void normalGame(); + void arcadeGame(); + void settingsChangedSlot() { emit settingsChanged(); } + +protected: + void _showHighscores(QWidget *parent); + +private: + QMemArray<ClientPlayData> _data; + KExtHighscore::Score _score; + KExtHighscore::MultiplayerScores _scores; + Field *_firstField; + + enum Action { Nb_Actions = 8 }; + static const ActionData ACTION_DATA[Nb_Actions]; + static const int KEYCODE_ONE[Nb_Actions]; + static const int KEYCODE_TWO[Nb_Actions]; + + MPBoard *newBoard(uint); + void setInitData(uint player, ServerInitData &); + uint prev(uint i) const; + uint next(uint i) const; + + void _readGameOverData(QDataStream &s); + void _sendGameOverData(QDataStream &s); + void _firstInit() {} + void _treatInit(); + void _init(); + void _showGameOverData(); + bool _readPlayData(); + void _sendPlayData(); + + void _start() { MPSimpleInterface::start(); } + void _pause() { MPSimpleInterface::pause(); } + bool _isPaused() const { return MPSimpleInterface::isPaused(); } +}; + +#endif diff --git a/libksirtet/common/libksirtet2.kcfg b/libksirtet/common/libksirtet2.kcfg new file mode 100644 index 00000000..27ee72e3 --- /dev/null +++ b/libksirtet/common/libksirtet2.kcfg @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <group name="Options"> + <entry name="ShowNextPiece" type="Bool" key="show next piece"> + <label>Show next piece.</label> + <default>true</default> + </entry> + <entry name="ShowPieceShadow" type="Bool" key="show piece shadow"> + <label>Show the shadow of a piece.</label> + <default>true</default> + </entry> + <entry name="ShowDetailedRemoved" type="Bool" key="show detailed removed"> + <label>Show detailed 'removed lines'.</label> + <default>false</default> + </entry> + <entry name="InitialGameLevel" type="Int" key="init level" min="1" max="20"> + <label>The inital level of new games.</label> + <default>1</default> + <min>1</min> + <max>20</max> + </entry> + <entry name="DirectDropDownEnabled" type="Bool" key="direct drop down"> + <label>Enable direct dropping of pieces.</label> + <default>false</default> + </entry> + </group> + <group name="AI"> + <entry name="ThinkingDepth" type="Int" key="thinking depth" min="1" max="2"> + <label>The thinking depth</label> + <default>2</default> + </entry> + </group> +</kcfg> diff --git a/libksirtet/common/main.cpp b/libksirtet/common/main.cpp new file mode 100644 index 00000000..004b86ca --- /dev/null +++ b/libksirtet/common/main.cpp @@ -0,0 +1,60 @@ +#include "main.h" +#include "main.moc" + +#include <klocale.h> +#include <kaction.h> +#include <kstdaction.h> +#include <kkeydialog.h> +#include <kconfigdialog.h> + +#include "inter.h" +#include "factory.h" + +void MainWindow::addConfig(KConfigDialog *dialog) +{ + QWidget *w = cfactory->createAIConfig(); + if (w) dialog->addPage(w, i18n("A.I."), "personal"); +} + +void MainWindow::init() +{ + Interface *inter = static_cast<Interface *>(_inter); + inter->normalGame(); + setFocusPolicy(StrongFocus); + + // Modes + bool ama = ( bfactory->bbi.nbArcadeStages!=0 ); + QString s = (ama ? i18n("&Single Human (Normal)") : i18n("&Single Human")); + (void)new KAction(s, 0, inter, SLOT(normalGame()), + actionCollection(), "mp_single_human"); + if (ama) (void)new KAction(i18n("&Single Human (Arcade)"), 0, + inter, SLOT(arcadeGame()), + actionCollection(), "mp_arcade"); + (void)new KAction(i18n("Human vs &Human"), 0, inter, SLOT(humanVsHuman()), + actionCollection(), "mp_human_vs_human"); + (void)new KAction(i18n("Human vs &Computer"), 0, + inter, SLOT(humanVsComputer()), + actionCollection(), "mp_human_vs_computer"); + (void)new KAction(i18n("&More..."), 0, inter, SLOT(dialog()), + actionCollection(), "mp_more"); + + buildGUI(inter); + connect(this, SIGNAL(settingsChanged()), + inter, SLOT(settingsChangedSlot())); +} + +void MainWindow::addKeys(KKeyDialog &d) +{ + static_cast<Interface *>(_inter)->addKeys(d); +} + +void MainWindow::saveKeys() +{ + static_cast<Interface *>(_inter)->saveKeys(); +} + +void MainWindow::focusInEvent(QFocusEvent *e) +{ + static_cast<Interface *>(_inter)->setFocus(); + BaseMainWindow::focusInEvent(e); +} diff --git a/libksirtet/common/main.h b/libksirtet/common/main.h new file mode 100644 index 00000000..d22b7273 --- /dev/null +++ b/libksirtet/common/main.h @@ -0,0 +1,22 @@ +#ifndef COMMON_MAIN_H +#define COMMON_MAIN_H + +#include "base/main.h" + +#include "lib/libksirtet_export.h" + +class LIBKSIRTET_EXPORT MainWindow : public BaseMainWindow +{ + Q_OBJECT +public: + MainWindow() {} + +protected: + void init(); + void addConfig(KConfigDialog *); + void addKeys(KKeyDialog &); + void saveKeys(); + virtual void focusInEvent(QFocusEvent *e); +}; + +#endif diff --git a/libksirtet/common/misc_ui.cpp b/libksirtet/common/misc_ui.cpp new file mode 100644 index 00000000..45cfb440 --- /dev/null +++ b/libksirtet/common/misc_ui.cpp @@ -0,0 +1,194 @@ +#include "misc_ui.h" +#include "misc_ui.moc" + +#include <qpainter.h> + +#include "base/piece.h" +#include "base/board.h" +#include "base/baseprefs.h" +#include "base/kzoommainwindow.h" +#include "factory.h" + +const uint GIFT_SHOWER_TIMEOUT = 800; +const uint GIFT_POOL_TIMEOUT = 2000; + +const uint SHADOW_HEIGHT = 10; + +const uint GI_WIDTH = 15; +const uint GI_HEIGHT = 11; +const uint ARROW_HEIGHT = 3; +const uint ARROW_WIDTH = 7; + +const uint LED_WIDTH = 15; +const uint LED_HEIGHT = 15; +const uint LED_SPACING = 5; + +/*****************************************************************************/ +ShowNextPiece::ShowNextPiece(BaseBoard *board, QWidget *parent) + : FixedCanvasView(parent, "show_next_piece") +{ + setCanvas(board->next()); + setFrameStyle(QFrame::Panel | QFrame::Sunken); + KZoomMainWindow::addWidget(this); +} + +/*****************************************************************************/ +Shadow::Shadow(BaseBoard *board, QWidget *parent) + : QWidget(parent, "shadow"), _xOffset(board->frameWidth()), + _board(board), _show(false) +{ + KZoomMainWindow::addWidget(this); + connect(board, SIGNAL(updatePieceConfigSignal()), SLOT(update())); +} + +QSize Shadow::sizeHint() const +{ + return QSize(_xOffset + _board->matrix().width() * BasePrefs::blockSize(), + SHADOW_HEIGHT); +} + +QSizePolicy Shadow::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +void Shadow::setDisplay(bool show) +{ + _show = show; + update(); +} + +void Shadow::paintEvent(QPaintEvent *) +{ + if ( !_show ) return; + + const Piece *piece = _board->currentPiece(); + uint pf = piece->min().first + _board->currentPos().first; + uint pl = pf + piece->size().first - 1; + + QPainter p(this); + p.setBrush(black); + p.setPen(black); + for (uint i=pf; i<=pl; i++) { + QRect r(_xOffset + i * BasePrefs::blockSize() + 1 , 0, + BasePrefs::blockSize() - 2, SHADOW_HEIGHT); + p.drawRect(r); + } +} + + +/*****************************************************************************/ +class Led : public QWidget +{ + public: + Led(const QColor &c, QWidget *parent) + : QWidget(parent), col(c), _on(FALSE) {} + + QSizePolicy sizePolicy() const + { return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } + QSize sizeHint() const { return QSize(LED_WIDTH, LED_HEIGHT); } + + void on() { if (!_on) { _on = TRUE; repaint(); } } + void off() { if (_on) {_on = FALSE; repaint(); } } + void setColor(const QColor &c) { if (c!=col) { col = c; repaint(); } } + + protected: + void paintEvent(QPaintEvent *) { + QPainter p(this); + p.setBrush((_on ? col.light() : col.dark())); + p.setPen(black); + p.drawEllipse(0, 0, width(), height()); + } + + private: + QColor col; + bool _on; +}; + +GiftPool::GiftPool(QWidget *parent) + : QHBox(parent, "gift_pool"), nb(0), ready(false) +{ + setSpacing(LED_SPACING); + leds.resize(cfactory->cbi.nbGiftLeds); + for (uint i=0; i<leds.size(); i++) + leds.insert(i, new Led(yellow, this)); +} + +QSize GiftPool::sizeHint() const +{ + QSize s = (leds.size() ? leds[0]->sizeHint() : QSize()); + return QSize((s.width()+LED_SPACING)*leds.size()-LED_SPACING, s.height()); +} + +QSizePolicy GiftPool::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +void GiftPool::put(uint n) +{ + if ( n==0 ) return; + if ( nb==0 && !ready ) + QTimer::singleShot(cfactory->cbi.giftPoolTimeout, + this, SLOT(timeout())); + uint e = QMIN(nb+n, leds.size()); + for (uint i=nb; i<e; i++) leds[i]->on(); + uint f = QMIN(nb+n-e, leds.size()); + for (uint i=0; i<f; i++) leds[i]->setColor(red); + nb += n; +} + +uint GiftPool::take() +{ + Q_ASSERT(ready); + for (uint i=0; i<leds.size(); i++) { + leds[i]->setColor(yellow); + leds[i]->off(); + } + uint max = cfactory->cbi.maxGiftsToSend; + if ( nb>max ) { + uint p = nb - max; + nb = 0; + put(p); + return max; + } else { + ready = false; + uint t = nb; + nb = 0; + return t; + } +} + +void GiftPool::reset() +{ + killTimers(); + ready = false; + nb = 0; + for (uint i=0; i<leds.size(); i++) { + leds[i]->setColor(yellow); + leds[i]->off(); + } +} + +//----------------------------------------------------------------------------- +PlayerProgress::PlayerProgress(BaseBoard *board, QWidget *parent, + const char *name) + : KGameProgress(0, board->matrix().height(), 0, KGameProgress::Vertical, + parent, name), _board(board) +{ + setBackgroundColor(lightGray); + setTextEnabled(false); + setBarColor(blue); + KZoomMainWindow::addWidget(this); +} + +QSize PlayerProgress::sizeHint() const +{ + return QSize(10, _board->matrix().height() * BasePrefs::blockSize()) + + 2 * QSize(frameWidth(), frameWidth()); +} + +QSizePolicy PlayerProgress::sizePolicy() const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} diff --git a/libksirtet/common/misc_ui.h b/libksirtet/common/misc_ui.h new file mode 100644 index 00000000..3a89acaa --- /dev/null +++ b/libksirtet/common/misc_ui.h @@ -0,0 +1,81 @@ +#ifndef COMMON_MISC_UI_H +#define COMMON_MISC_UI_H + +#include <qcanvas.h> +#include <qptrvector.h> +#include <qhbox.h> + +#include <kgameprogress.h> +#include "lib/libksirtet_export.h" + +#include "base/board.h" + +/*****************************************************************************/ +class LIBKSIRTET_EXPORT ShowNextPiece : public FixedCanvasView +{ + Q_OBJECT + public: + ShowNextPiece(BaseBoard *, QWidget *parent); +}; + +/*****************************************************************************/ +class LIBKSIRTET_EXPORT Shadow : public QWidget +{ + Q_OBJECT + public: + Shadow(BaseBoard *, QWidget *parent); + + virtual QSize sizeHint() const; + virtual QSizePolicy sizePolicy() const; + void setDisplay(bool show); + + private: + int _xOffset; + const BaseBoard *_board; + bool _show; + + void paintEvent(QPaintEvent *); +}; + +/*****************************************************************************/ +class Led; + +class LIBKSIRTET_EXPORT GiftPool : public QHBox +{ + Q_OBJECT + public: + GiftPool(QWidget *parent); + + virtual QSize sizeHint() const; + virtual QSizePolicy sizePolicy() const; + + void reset(); + void put(uint); + uint take(); + bool pending() const { return ready; } + + private slots: + void timeout() { ready = true; } + + private: + QPtrVector<Led> leds; + uint _timeout, nb; + bool ready; +}; + + +/*****************************************************************************/ +class LIBKSIRTET_EXPORT PlayerProgress : public KGameProgress +{ + Q_OBJECT +public: + PlayerProgress(BaseBoard *board, QWidget *parent = 0, const char *name = 0); + + virtual QSize sizeHint() const; + virtual QSizePolicy sizePolicy() const; + +private: + BaseBoard *_board; +}; + +#endif diff --git a/libksirtet/common/settings.cpp b/libksirtet/common/settings.cpp new file mode 100644 index 00000000..902d1e56 --- /dev/null +++ b/libksirtet/common/settings.cpp @@ -0,0 +1,54 @@ +#include "settings.h" +#include "settings.moc" + +#include <qlabel.h> +#include <qlayout.h> +#include <qcheckbox.h> +#include <qwhatsthis.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kdialog.h> +#include <kglobal.h> + + +//----------------------------------------------------------------------------- +AppearanceConfig::AppearanceConfig() +{ + int row = _grid->numRows(); + int col = _grid->numCols(); + + QCheckBox *cb = new QCheckBox(i18n("Show piece's shadow"), _main, "kcfg_ShowPieceShadow"); + _grid->addMultiCellWidget(cb, row, row, 0, col-1); + + cb = new QCheckBox(i18n("Show next piece"), _main, "kcfg_ShowNextPiece"); + _grid->addMultiCellWidget(cb, row+1, row+1, 0, col-1); + + cb = new QCheckBox(i18n("Show detailed \"removed lines\" field"), _main, "kcfg_ShowDetailedRemoved"); + _grid->addMultiCellWidget(cb, row+2, row+2, 0, col-1); +} + +//----------------------------------------------------------------------------- +GameConfig::GameConfig() + : QWidget(0, "game config") +{ + QVBoxLayout *top = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); + + _grid = new QGridLayout(top, 3, 2); + _grid->setColStretch(1, 1); + + QLabel *label = new QLabel(i18n("Initial level:"), this); + _grid->addWidget(label, 0, 0); + KIntNumInput *in = new KIntNumInput(this, "kcfg_InitialGameLevel"); + in->setRange(1, 20, 1, true); + _grid->addWidget(in, 0, 1); + + _grid->addRowSpacing(1, KDialog::spacingHint()); + + QCheckBox *cb = new QCheckBox(i18n("Direct drop down"), this, "kcfg_DirectDropDownEnabled"); + QWhatsThis::add(cb, i18n("Drop down is not stopped when drop down key is released.")); + _grid->addMultiCellWidget(cb, 2, 2, 0, 1); + + top->addStretch(1); +} + diff --git a/libksirtet/common/settings.h b/libksirtet/common/settings.h new file mode 100644 index 00000000..ceda13a1 --- /dev/null +++ b/libksirtet/common/settings.h @@ -0,0 +1,28 @@ +#ifndef COMMON_SETTINGS_H +#define COMMON_SETTINGS_H + +#include "base/settings.h" + +#include "lib/libksirtet_export.h" + + +//----------------------------------------------------------------------------- +class LIBKSIRTET_EXPORT AppearanceConfig : public BaseAppearanceConfig +{ + Q_OBJECT +public: + AppearanceConfig(); +}; + +//----------------------------------------------------------------------------- +class LIBKSIRTET_EXPORT GameConfig : public QWidget +{ + Q_OBJECT +public: + GameConfig(); + +protected: + QGridLayout *_grid; +}; + +#endif diff --git a/libksirtet/common/types.cpp b/libksirtet/common/types.cpp new file mode 100644 index 00000000..05d91db3 --- /dev/null +++ b/libksirtet/common/types.cpp @@ -0,0 +1,16 @@ +#include "types.h" + +LIBKSIRTET_EXPORT QDataStream &operator <<(QDataStream &s, const ClientPlayData &d) + { s << d.height << d.gift << d.end; return s; } +LIBKSIRTET_EXPORT QDataStream &operator >>(QDataStream &s, ClientPlayData &d) + { s >> d.height >> d.gift >> d.end; return s; } + +LIBKSIRTET_EXPORT QDataStream &operator <<(QDataStream &s, const ServerPlayData &d) + { s << d.prevHeight << d.nextHeight << d.gift; return s; } +LIBKSIRTET_EXPORT QDataStream &operator >>(QDataStream &s, ServerPlayData &d) + { s >> d.prevHeight >> d.nextHeight >> d.gift; return s; } + +LIBKSIRTET_EXPORT QDataStream &operator <<(QDataStream &s, const ServerInitData &d) +{ s << d.initLevel << d.seed << d.nextName << d.prevName << d.name; return s; } +LIBKSIRTET_EXPORT QDataStream &operator >>(QDataStream &s, ServerInitData &d) +{ s >> d.initLevel >> d.seed >> d.nextName >> d.prevName >> d.name; return s; } diff --git a/libksirtet/common/types.h b/libksirtet/common/types.h new file mode 100644 index 00000000..8a30d276 --- /dev/null +++ b/libksirtet/common/types.h @@ -0,0 +1,26 @@ +#ifndef COMMON_TYPES_H +#define COMMON_TYPES_H + +#include <qdatastream.h> + +#include "lib/libksirtet_export.h" + + +struct ClientPlayData { Q_UINT8 height, gift, end; }; +LIBKSIRTET_EXPORT QDataStream &operator <<(QDataStream &s, const ClientPlayData &d); +LIBKSIRTET_EXPORT QDataStream &operator >>(QDataStream &s, ClientPlayData &d); + +struct ServerPlayData { Q_UINT8 prevHeight, nextHeight, gift; }; +LIBKSIRTET_EXPORT QDataStream &operator <<(QDataStream &s, const ServerPlayData &d); +LIBKSIRTET_EXPORT QDataStream &operator >>(QDataStream &s, ServerPlayData &d); + +class ServerInitData +{ + public: + QString prevName, nextName, name; + Q_UINT32 initLevel, seed; +}; +LIBKSIRTET_EXPORT QDataStream &operator <<(QDataStream &s, const ServerInitData &d); +LIBKSIRTET_EXPORT QDataStream &operator >>(QDataStream &s, ServerInitData &d); + +#endif |