diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | c90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch) | |
tree | 6d8391395bce9eaea4ad78958617edb20c6a7573 /knetwalk/src/mainwindow.cpp | |
download | tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'knetwalk/src/mainwindow.cpp')
-rw-r--r-- | knetwalk/src/mainwindow.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/knetwalk/src/mainwindow.cpp b/knetwalk/src/mainwindow.cpp new file mode 100644 index 00000000..15e615ed --- /dev/null +++ b/knetwalk/src/mainwindow.cpp @@ -0,0 +1,421 @@ +/*************************************************************************** + * Copyright (C) 2004, 2005 Andi Peredri * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 * + * as published by the Free Software Foundation (see COPYING) * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + ***************************************************************************/ + +#include <qaction.h> +#include <qapplication.h> +#include <qeventloop.h> +#include <qgrid.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qprocess.h> +#include <qpushbutton.h> +#include <qsettings.h> +#include <qsound.h> +#include <qtimer.h> +#include <qtoolbutton.h> +#include <qwhatsthis.h> + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kscoredialog.h> +#include <khighscore.h> +#include <kstdaction.h> +#include <kaction.h> +#include <kstdgameaction.h> +#include <kmenubar.h> +#include <kstatusbar.h> +#include <kdebug.h> +#include <knotifyclient.h> +#include <knotifydialog.h> +#include <kexthighscore.h> + +#include "settings.h" +#include "cell.h" +#include "mainwindow.h" + +static QMap<Cell::Dirs, Cell::Dirs> contrdirs; + +MainWindow::MainWindow(QWidget *parent, const char* name, WFlags /*fl*/) : + KMainWindow(parent, name, WStyle_NoBorder) +{ + m_clickcount = 0; + + contrdirs[Cell::U] = Cell::D; + contrdirs[Cell::R] = Cell::L; + contrdirs[Cell::D] = Cell::U; + contrdirs[Cell::L] = Cell::R; + + KNotifyClient::startDaemon(); + + KStdGameAction::gameNew(this, SLOT(slotNewGame()), actionCollection()); + + KStdGameAction::highscores(this, SLOT(showHighscores()), actionCollection()); + KStdGameAction::quit(this, SLOT(close()), actionCollection()); + KStdGameAction::configureHighscores(this, SLOT(configureHighscores()), actionCollection()); + + m_levels = KStdGameAction::chooseGameType(0, 0, actionCollection()); + QStringList lst; + lst += i18n("Novice"); + lst += i18n("Normal"); + lst += i18n("Expert"); + lst += i18n("Master"); + m_levels->setItems(lst); + + setFixedSize(minimumSizeHint()); + + statusBar()->insertItem("abcdefghijklmnopqrst: 0 ",1); + setAutoSaveSettings(); + createGUI(); + connect(m_levels, SIGNAL(activated(int)), this, SLOT(newGame(int))); + + + QWhatsThis::add(this, i18n("<h3>Rules of the Game</h3>" + "<p>You are the system administrator and your goal" + " is to connect each computer to the central server." + "<p>Click the right mouse button to turn the cable" + " in a clockwise direction, and the left mouse button" + " to turn it in a counter-clockwise direction." + "<p>Start the LAN with as few turns as possible!")); + + //const int cellsize = KGlobal::iconLoader()->loadIcon("knetwalk/background.png", KIcon::User, 32).width(); + const int cellsize = 32; + const int gridsize = cellsize * MasterBoardSize + 2; + + QGrid* grid = new QGrid(MasterBoardSize, this); + grid->setFrameStyle(QFrame::Panel | QFrame::Sunken); + grid->setFixedSize(gridsize, gridsize); + setCentralWidget(grid); + + Cell::initPixmaps(); + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + { + board[i] = new Cell(grid, i); + board[i]->setFixedSize(cellsize, cellsize); + connect(board[i], SIGNAL(lClicked(int)), SLOT(lClicked(int))); + connect(board[i], SIGNAL(rClicked(int)), SLOT(rClicked(int))); + connect(board[i], SIGNAL(mClicked(int)), SLOT(mClicked(int))); + } + srand(time(0)); + + slotNewGame(); +} + +void MainWindow::configureHighscores() +{ + KExtHighscore::configure(this); +} + +void MainWindow::showHighscores() +{ + KExtHighscore::show(this); +} + +void MainWindow::slotNewGame() +{ + newGame( Settings::skill() ); +} + +void MainWindow::newGame(int sk) +{ + if (sk==Settings::EnumSkill::Novice || sk==Settings::EnumSkill::Normal + || sk==Settings::EnumSkill::Expert || sk==Settings::EnumSkill::Master) + { + Settings::setSkill(sk); + } + + if(Settings::skill() == Settings::EnumSkill::Master) wrapped = true; + else wrapped = false; + + KExtHighscore::setGameType(Settings::skill()); + + Settings::writeConfig(); + + m_clickcount = 0; + QString clicks = i18n("Click: %1"); + statusBar()->changeItem(clicks.arg(QString::number(m_clickcount)),1); + + KNotifyClient::event(winId(), "startsound", i18n("New Game")); + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + { + board[i]->setDirs(Cell::None); + board[i]->setConnected(false); + board[i]->setRoot(false); + board[i]->setLocked(false); + } + + const int size = (Settings::skill() == Settings::EnumSkill::Novice) ? NoviceBoardSize : + (Settings::skill() == Settings::EnumSkill::Normal) ? NormalBoardSize : + (Settings::skill() == Settings::EnumSkill::Expert) ? ExpertBoardSize : MasterBoardSize; + + const int start = (MasterBoardSize - size) / 2; + const int rootrow = rand() % size; + const int rootcol = rand() % size; + + root = board[(start + rootrow) * MasterBoardSize + start + rootcol]; + root->setConnected(true); + root->setRoot(true); + + while(true) + { + for(int row = start; row < start + size; row++) + for(int col = start; col < start + size; col++) + board[row * MasterBoardSize + col]->setDirs(Cell::Free); + + CellList list; + list.append(root); + if(rand() % 2) addRandomDir(list); + + while(!list.isEmpty()) + { + if(rand() % 2) + { + addRandomDir(list); + if(rand() % 2) addRandomDir(list); + list.remove(list.begin()); + } + else + { + list.append(list.first()); + list.remove(list.begin()); + } + } + + int cells = 0; + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + { + Cell::Dirs d = board[i]->dirs(); + if((d != Cell::Free) && (d != Cell::None)) cells++; + } + if(cells >= MinimumNumCells) break; + } + + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + board[i]->rotate((rand() % 4) * 90); + updateConnections(); +} + +bool MainWindow::updateConnections() +{ + bool newconnection[MasterBoardSize * MasterBoardSize]; + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + newconnection[i] = false; + + CellList list; + if(!root->isRotated()) + { + newconnection[root->index()] = true; + list.append(root); + } + while(!list.isEmpty()) + { + Cell* cell = list.first(); + Cell* ucell = uCell(cell); + Cell* rcell = rCell(cell); + Cell* dcell = dCell(cell); + Cell* lcell = lCell(cell); + + if((cell->dirs() & Cell::U) && ucell && (ucell->dirs() & Cell::D) && + !newconnection[ucell->index()] && !ucell->isRotated()) + { + newconnection[ucell->index()] = true; + list.append(ucell); + } + if((cell->dirs() & Cell::R) && rcell && (rcell->dirs() & Cell::L) && + !newconnection[rcell->index()] && !rcell->isRotated()) + { + newconnection[rcell->index()] = true; + list.append(rcell); + } + if((cell->dirs() & Cell::D) && dcell && (dcell->dirs() & Cell::U) && + !newconnection[dcell->index()] && !dcell->isRotated()) + { + newconnection[dcell->index()] = true; + list.append(dcell); + } + if((cell->dirs() & Cell::L) && lcell && (lcell->dirs() & Cell::R) && + !newconnection[lcell->index()] && !lcell->isRotated()) + { + newconnection[lcell->index()] = true; + list.append(lcell); + } + list.remove(list.begin()); + } + + bool isnewconnection = false; + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + { + if(!board[i]->isConnected() && newconnection[i]) + isnewconnection = true; + board[i]->setConnected(newconnection[i]); + } + return isnewconnection; +} + +void MainWindow::addRandomDir(CellList& list) +{ + Cell* cell = list.first(); + Cell* ucell = uCell(cell); + Cell* rcell = rCell(cell); + Cell* dcell = dCell(cell); + Cell* lcell = lCell(cell); + + typedef QMap<Cell::Dirs, Cell*> CellMap; + CellMap freecells; + + if(ucell && ucell->dirs() == Cell::Free) freecells[Cell::U] = ucell; + if(rcell && rcell->dirs() == Cell::Free) freecells[Cell::R] = rcell; + if(dcell && dcell->dirs() == Cell::Free) freecells[Cell::D] = dcell; + if(lcell && lcell->dirs() == Cell::Free) freecells[Cell::L] = lcell; + if(freecells.isEmpty()) return; + + CellMap::ConstIterator it = freecells.constBegin(); + for(int i = rand() % freecells.count(); i > 0; --i) ++it; + + cell->setDirs(Cell::Dirs(cell->dirs() | it.key())); + it.data()->setDirs(contrdirs[it.key()]); + list.append(it.data()); +} + +Cell* MainWindow::uCell(Cell* cell) const +{ + if(cell->index() >= MasterBoardSize) + return board[cell->index() - MasterBoardSize]; + else if(wrapped) + return board[MasterBoardSize * (MasterBoardSize - 1) + cell->index()]; + else return 0; +} + +Cell* MainWindow::dCell(Cell* cell) const +{ + if(cell->index() < MasterBoardSize * (MasterBoardSize - 1)) + return board[cell->index() + MasterBoardSize]; + else if(wrapped) + return board[cell->index() - MasterBoardSize * (MasterBoardSize - 1)]; + else return 0; +} + +Cell* MainWindow::lCell(Cell* cell) const +{ + if(cell->index() % MasterBoardSize > 0) + return board[cell->index() - 1]; + else if(wrapped) + return board[cell->index() - 1 + MasterBoardSize]; + else return 0; +} + +Cell* MainWindow::rCell(Cell* cell) const +{ + if(cell->index() % MasterBoardSize < MasterBoardSize - 1) + return board[cell->index() + 1]; + else if(wrapped) + return board[cell->index() + 1 - MasterBoardSize]; + else return 0; +} + +void MainWindow::lClicked(int index) +{ + rotate(index, true); +} + +void MainWindow::rClicked(int index) +{ + rotate(index, false); +} + +void MainWindow::mClicked(int index) +{ + board[index]->setLocked( !board[index]->isLocked() ); +} + +void MainWindow::rotate(int index, bool toleft) +{ + const Cell::Dirs d = board[index]->dirs(); + if((d == Cell::Free) || (d == Cell::None) || isGameOver() || board[index]->isLocked() ) + { + KNotifyClient::event(winId(), "clicksound"); + blink(index); + } + else + { + KNotifyClient::event(winId(), "turnsound"); + board[index]->rotate(toleft ? -6 : 6); + updateConnections(); + for(int i = 0; i < 14; i++) + { + kapp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput); + QTimer::singleShot(20, board[index], SLOT(update())); + kapp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput | QEventLoop::WaitForMore); + board[index]->rotate(toleft ? -6 : 6); + } + + if (updateConnections()) + KNotifyClient::event(winId(), "connectsound"); + + m_clickcount++; + QString clicks = i18n("Click: %1"); + statusBar()->changeItem(clicks.arg(QString::number(m_clickcount)),1); + + if (isGameOver()) + { + KNotifyClient::event(winId(), "winsound"); + blink(index); + + KExtHighscore::Score score(KExtHighscore::Won); + score.setScore(m_clickcount); + KExtHighscore::submitScore(score, this); + } + } +} + +void MainWindow::blink(int index) +{ + for(int i = 0; i < board[index]->width() * 2; i += 2) + { + kapp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput); + QTimer::singleShot(20, board[index], SLOT(update())); + kapp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput | + QEventLoop::WaitForMore); + board[index]->setLight(i); + } + board[index]->setLight(0); +} + +bool MainWindow::isGameOver() +{ + for(int i = 0; i < MasterBoardSize * MasterBoardSize; i++) + { + const Cell::Dirs d = board[i]->dirs(); + if((d != Cell::Free) && (d != Cell::None) && !board[i]->isConnected()) + return false; + } + return true; +} + +void MainWindow::closeEvent(QCloseEvent* event) +{ + event->accept(); +} + +void MainWindow::configureNotifications() +{ + KNotifyDialog::configure(this); +} + +#include "mainwindow.moc" |