#include "game.h"
#include <QTableWidget>
-#include <QDebug>
+#include <QListWidget>
#include <QLabel>
#include <QFile>
#include <QPushButton>
-#include <QFrame>
#include <QApplication>
+#include <QDebug>
+const Piece* findPiece(PieceType type, int rotation)
+{
+ static QHash<QPair<PieceType, int>, const Piece*> pieceCache;
+
+ // Fill the cache on the first run
+ if (pieceCache.size() == 0) {
+ for (int i = 0; ppieces[i].type != PiecesEnd; ++i)
+ pieceCache.insert(QPair<PieceType, int>(ppieces[i].type, ppieces[i].rotation), &ppieces[i]);
+ }
+ QPair<PieceType, int> key(type, rotation);
+ if (pieceCache.contains(key))
+ return pieceCache[key];
+ return 0;
+
+}
QString pieceToIconId(const Piece* piece, bool flow1 = false, bool flow2 = false)
{
void GameField::initGame(int rows_, int cols_, int count, PrePlacedPiece* prePlaced)
{
fieldUi->clear();
- // FIXME: Does the table widget call the destructors of its items...
rows = rows_;
cols = cols_;
QLabel* label = (QLabel*)fieldUi->indexWidget(mIndex);
label->setPixmap(QPixmap(iconId));
- // The pixmap won't show nicely if we're just sleeping...
- QApplication::processEvents();
}
-QHash<QPair<PieceType, int>, const Piece*> AvailablePieces::pieceCache;
-
AvailablePieces::AvailablePieces(QTableWidget* ui)
: pieceUi(ui)
{
connect(pieceUi, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(onItemClicked(QTableWidgetItem*)));
- initPieceCache();
-
// Setup ui
qDebug() << pieceUi->rowCount() << pieceUi->columnCount();
{
int rotation = (id % 4)*90;
PieceType type = (PieceType)(id / 4);
- QPair<PieceType, int> key(type, rotation);
- if (!pieceCache.contains(key))
- return ppieces;
- return pieceCache[key];
-}
-
-void AvailablePieces::initPieceCache()
-{
- for (int i = 0; ppieces[i].type != PiecesEnd; ++i)
- pieceCache.insert(QPair<PieceType, int>(ppieces[i].type, ppieces[i].rotation), &ppieces[i]);
+ return findPiece(type, rotation);
}
void AvailablePieces::initGame(int count, AvailablePiece* pieces)
neededFlow = 0;
int prePlacedCount = 0;
gameData >> prePlacedCount;
- qDebug() << rows << cols;
if (prePlacedCount < 2 || prePlacedCount > 100)
- qFatal("Error reading game file: piece count000");
+ qFatal("Error reading game file: piece count");
PrePlacedPiece* prePlaced = new PrePlacedPiece[prePlacedCount];
for (int i = 0; i < prePlacedCount; ++i) {
- int ix = 0;
- gameData >> ix;
- if (ix < 0 || ix >= noPieces)
- qFatal("Error reading game file: no of pieces");
- prePlaced[i].piece = &ppieces[ix];
+ int type = 0;
+ gameData >> type;
+ if (type < 0 || type >= PiecesEnd)
+ qFatal("Error reading game file: type of pre-placed piece");
+
+ int rotation = 0;
+ gameData >> rotation;
+ if (rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270)
+ qFatal("Error reading game file: rotation of pre-placed piece");
+
+ prePlaced[i].piece = findPiece((PieceType)type, rotation);
+ if (!prePlaced[i].piece)
+ qFatal("Error reading game file: invalid pre-placed piece");
// Record that the liquid must flow through this pre-placed
// piece (if it can)
return;
}
+ if (flowDir == DirPassed) {
+ flowTimer.stop();
+ emit levelPassed(flowScore);
+ }
+
if (flowDir == DirNone) {
// This square contained no pipe or an incompatible pipe. Get
// some more time, so that the user sees the failure before we
flowScore += 10;
if (flowDir == DirDone) {
+ // Again, give the user some time...
if (flowPreplaced < neededFlow) {
flowDir = DirFailed;
// TODO: indicate which pipes were missing
- flowTimer.setInterval(1000);
- }
- else {
- flowTimer.stop();
- emit levelPassed(flowScore);
}
+ else
+ flowDir = DirPassed;
+
+ flowTimer.setInterval(1000);
return;
}
flowPreplaced += 1;
}
-LevelSwitcher::LevelSwitcher(GameController* gameController, QLabel* levelLabel,
- QFrame* startFrame, QLabel* startTitle, QLabel* startLabel, QPushButton* startButton,
- QLabel* scoreLabel,
-
- QStringList levels)
- : gameController(gameController), levelLabel(levelLabel),
- startFrame(startFrame), startTitle(startTitle), startLabel(startLabel), startButton(startButton),
- scoreLabel(scoreLabel),
- levels(levels), level(0), totalScore(0)
+LevelSwitcher::LevelSwitcher(GameController* gameController,
+ QWidget* levelWidget, QListWidget* levelList,
+ QPushButton* levelStartButton,
+ QWidget* startWidget, QLabel* startTitle,
+ QLabel* startLabel, QPushButton* startButton,
+ QLabel* levelLabel, QLabel* scoreLabel,
+ QStringList levelCollections)
+ : gameController(gameController),
+ levelWidget(levelWidget), levelList(levelList), levelStartButton(levelStartButton),
+ startWidget(startWidget), startTitle(startTitle), startLabel(startLabel), startButton(startButton),
+ levelLabel(levelLabel), scoreLabel(scoreLabel),
+ levelCollections(levelCollections), level(0), totalScore(0)
{
+ connect(levelStartButton, SIGNAL(clicked()), this, SLOT(onLevelCollectionChosen()));
+
connect(startButton, SIGNAL(clicked()), this, SLOT(onStartClicked()));
connect(gameController, SIGNAL(levelPassed(int)), this, SLOT(onLevelPassed(int)));
connect(gameController, SIGNAL(levelFailed()), this, SLOT(onLevelFailed()));
startTitle->setText("Starting a new game.");
scoreLabel->setText("0");
+ chooseLevelCollection();
+}
+
+void LevelSwitcher::chooseLevelCollection()
+{
+ levelList->clear();
+ bool first = true;
+ foreach (const QString& collection, levelCollections) {
+ QListWidgetItem *newItem = new QListWidgetItem();
+ newItem->setText(collection);
+ levelList->addItem(newItem); // transfers ownership
+ if (first) {
+ levelList->setCurrentItem(newItem);
+ first = false;
+ }
+ }
+ levelWidget->show();
+}
+
+void LevelSwitcher::onLevelCollectionChosen()
+{
+ levelWidget->hide();
+ QString collection = levelList->currentItem()->text();
+ QFile file(QString(LEVDIR) + "/" + collection + ".dat");
+ if (!file.exists())
+ qFatal("Error reading game file: doesn't exist");
+ file.open(QIODevice::ReadOnly);
+ QTextStream levelData(&file);
+ levels.clear();
+
+ while (!levelData.atEnd())
+ levels << levelData.readLine();
+
+ level = 0;
+ totalScore = 0;
initiateLevel();
}
void LevelSwitcher::onStartClicked()
{
- startFrame->hide();
+ startWidget->hide();
levelLabel->setText(QString::number(level+1));
gameController->startLevel(QString(LEVDIR) + "/" + levels[level] + ".dat");
}
void LevelSwitcher::initiateLevel()
{
+ if (level >= levels.size()) {
+ qWarning() << "Level index too large";
+ return;
+ }
+
QFile file(QString(LEVDIR) + "/" + levels[level] + ".leg");
if (!file.exists())
qFatal("Error reading game file: doesn't exist");
QString introText = gameData.readLine();
introText.replace("IMGDIR", IMGDIR);
+
+ // The start button might be connected to "chooseLevelCollection"
+ startButton->disconnect();
+ connect(startButton, SIGNAL(clicked()), this, SLOT(onStartClicked()));
startLabel->setText(introText);
- startFrame->show();
+ startWidget->show();
}
void LevelSwitcher::onLevelPassed(int score)
else {
startTitle->setText(QString("All levels passed. Score: ") + QString::number(score));
startLabel->setText("Start a new game?");
- // TODO: go to the level set selection screen
+ startButton->disconnect();
+ connect(startButton, SIGNAL(clicked()), this, SLOT(chooseLevelCollection()));
level = 0;
- startFrame->show();
+ startWidget->show();
}
}
}
// Todo next:
-// desktop stuff
-// icon for app manager
-// install all graphics
// better graphics
// save & load
// level collections: introduction + basic
// more levels
// make fixed pipes look different than non-fixed ones
+// color theme
// --------------
// re-placing pieces
// graphical hints on what to do next