• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegames API Reference
  • KDE Home
  • Contact Us
 

KShisen

  • sources
  • kde-4.14
  • kdegames
  • kshisen
  • src
app.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * KShisen - A japanese game similar to mahjongg *
3  * Copyright 1997 Mario Weilguni <mweilguni@sime.com> *
4  * Copyright 2002-2004 Dave Corrie <kde@davecorrie.com> *
5  * Copyright 2007 Mauricio Piacentini <mauricio@tabuleiro.com> *
6  * Copyright 2009-2011 Frederik Schwarzer <schwarzer@kde.org> *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20  ***************************************************************************/
21 
22 #include "app.h"
23 #include "board.h"
24 #include "prefs.h"
25 #include "ui_settings.h"
26 
27 #include <kmahjonggconfigdialog.h>
28 #include <highscore/kscoredialog.h>
29 #include <kstandardgameaction.h>
30 
31 #include <kaction.h>
32 #include <kactioncollection.h>
33 #include <kconfig.h>
34 #include <kconfigdialog.h>
35 #include <kdebug.h>
36 #include <kglobal.h>
37 #include <kicon.h>
38 #include <klineedit.h>
39 #include <klocale.h>
40 #include <kmenu.h>
41 #include <kmessagebox.h>
42 #include <kpushbutton.h>
43 #include <kseparator.h>
44 #include <kshortcutsdialog.h>
45 #include <kstandardaction.h>
46 #include <kstandarddirs.h>
47 #include <kstandardguiitem.h>
48 #include <kstatusbar.h>
49 #include <ktoggleaction.h>
50 
51 #include <QTimer>
52 
53 #include <cmath>
54 
55 
59 class Settings : public QWidget, public Ui::Settings
60 {
61 public:
62  Settings(QWidget *parent)
63  : QWidget(parent) {
64  setupUi(this);
65  }
66 };
67 
68 App::App(QWidget *parent)
69  : KXmlGuiWindow(parent),
70  m_gameTipLabel(0),
71  m_gameTimerLabel(0),
72  m_gameTilesLabel(0),
73  m_gameCheatLabel(0),
74  m_board(0)
75 {
76  m_board = new Board(this);
77  m_board->setObjectName(QLatin1String("board"));
78 
79  setCentralWidget(m_board);
80 
81  setupStatusBar();
82  setupActions();
83  setupGUI();
84 
85  updateItems();
86 }
87 
88 
89 void App::setupStatusBar()
90 {
91  m_gameTipLabel = new QLabel(i18n("Select a tile"), statusBar());
92  statusBar()->addWidget(m_gameTipLabel, 1);
93 
94  m_gameTimerLabel = new QLabel(i18n("Time: 0:00:00"), statusBar());
95  statusBar()->addWidget(m_gameTimerLabel);
96 
97  m_gameTilesLabel = new QLabel(i18n("Removed: 0/0"), statusBar());
98  statusBar()->addWidget(m_gameTilesLabel);
99 
100  m_gameCheatLabel = new QLabel(i18n("Cheat mode"), statusBar());
101  statusBar()->addWidget(m_gameCheatLabel);
102  m_gameCheatLabel->hide();
103 }
104 
105 void App::setupActions()
106 {
107  // Game
108  KStandardGameAction::gameNew(this, SIGNAL(invokeNewGame()), actionCollection());
109  KStandardGameAction::restart(this, SLOT(restartGame()), actionCollection());
110  KStandardGameAction::pause(this, SLOT(togglePause()), actionCollection());
111  KStandardGameAction::highscores(this, SLOT(showHighscores()), actionCollection());
112  KStandardGameAction::quit(this, SLOT(close()), actionCollection());
113 
114  // Move
115  KStandardGameAction::undo(this, SLOT(undo()), actionCollection());
116  KStandardGameAction::redo(this, SLOT(redo()), actionCollection());
117  KStandardGameAction::hint(this, SLOT(hint()), actionCollection());
118 
119  KToggleAction *soundAction = new KToggleAction(KIcon(QLatin1String("speaker")), i18n("Play Sounds"), this);
120  soundAction->setChecked(Prefs::sounds());
121  actionCollection()->addAction(QLatin1String("sounds"), soundAction);
122  connect(soundAction, SIGNAL(triggered(bool)), m_board, SLOT(setSoundsEnabled(bool)));
123 
124  // Settings
125  KStandardAction::preferences(this, SLOT(showSettingsDialog()), actionCollection());
126 
127  connect(m_board, SIGNAL(cheatStatusChanged()), this, SLOT(updateCheatDisplay()));
128  connect(m_board, SIGNAL(changed()), this, SLOT(updateItems()));
129  connect(m_board, SIGNAL(tilesDoNotMatch()), this, SLOT(notifyTilesDoNotMatch()));
130  connect(m_board, SIGNAL(invalidMove()), this, SLOT(notifyInvalidMove()));
131  connect(m_board, SIGNAL(selectATile()), this, SLOT(notifySelectATile()));
132  connect(m_board, SIGNAL(selectAMatchingTile()), this, SLOT(notifySelectAMatchingTile()));
133  connect(m_board, SIGNAL(selectAMove()), this, SLOT(notifySelectAMove()));
134 
135  QTimer *timer = new QTimer(this);
136  connect(timer, SIGNAL(timeout()), this, SLOT(updateTimeDisplay()));
137  timer->start(1000);
138 
139  connect(m_board, SIGNAL(changed()), this, SLOT(updateTileDisplay()));
140  connect(m_board, SIGNAL(endOfGame()), this, SLOT(slotEndOfGame()));
141 
142  connect(this, SIGNAL(invokeNewGame()), m_board, SLOT(newGame()));
143  connect(m_board, SIGNAL(newGameStarted()), this, SLOT(newGame()));
144 }
145 
146 void App::newGame()
147 {
148  setCheatModeEnabled(false);
149  setPauseEnabled(false);
150  updateItems();
151 }
152 
153 void App::restartGame()
154 {
155  m_board->setUpdatesEnabled(false);
156  while (m_board->canUndo()) {
157  m_board->undo();
158  }
159  m_board->resetRedo();
160  m_board->resetTimer();
161  setCheatModeEnabled(false);
162  m_board->setGameOverEnabled(false);
163  m_board->setGameStuckEnabled(false);
164  m_board->setUpdatesEnabled(true);
165  updateItems();
166 }
167 
168 void App::togglePause()
169 {
170  m_board->setPauseEnabled(!m_board->isPaused());
171 }
172 
173 void App::setPauseEnabled(bool enabled)
174 {
175  m_board->setPauseEnabled(enabled);
176  updateItems();
177 }
178 
179 void App::undo()
180 {
181  if (!m_board->canUndo()) {
182  return;
183  }
184  m_board->undo();
185  setCheatModeEnabled(true);
186 
187  // If the game is stuck (no matching tiles anymore), the player can decide
188  // to undo some steps and try a different approach.
189  m_board->setGameStuckEnabled(false);
190 
191  updateItems();
192 }
193 
194 void App::redo()
195 {
196  if (!m_board->canRedo()) {
197  return;
198  }
199  m_board->redo();
200  updateItems();
201 }
202 
203 void App::hint()
204 {
205 #ifdef DEBUGGING
206  m_board->makeHintMove();
207 #else
208  m_board->showHint();
209  setCheatModeEnabled(true);
210 #endif
211  updateItems();
212 }
213 
214 void App::updateItems()
215 {
216  if (m_board->isOver()) {
217  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Undo))->setEnabled(false);
218  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Redo))->setEnabled(false);
219  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Pause))->setEnabled(false);
220  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Hint))->setEnabled(false);
221  } else if (m_board->isPaused()) {
222  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Undo))->setEnabled(false);
223  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Redo))->setEnabled(false);
224  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Restart))->setEnabled(false);
225  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Pause))->setChecked(true);
226  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Hint))->setEnabled(false);
227  } else if (m_board->isStuck()) {
228  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Pause))->setEnabled(false);
229  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Hint))->setEnabled(false);
230  } else {
231  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Undo))->setEnabled(m_board->canUndo());
232  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Redo))->setEnabled(m_board->canRedo());
233  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Restart))->setEnabled(m_board->canUndo());
234  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Pause))->setEnabled(true);
235  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Pause))->setChecked(false);
236  actionCollection()->action(KStandardGameAction::name(KStandardGameAction::Hint))->setEnabled(true);
237  }
238 }
239 
240 void App::slotEndOfGame()
241 {
242  if (m_board->tilesLeft() > 0) {
243  m_board->setGameStuckEnabled(true);
244  } else {
245  m_board->setGameOverEnabled(true);
246  QString timeString = i18nc("time string: hh:mm:ss", "%1:%2:%3",
247  QString().sprintf("%02d", m_board->currentTime() / 3600),
248  QString().sprintf("%02d", (m_board->currentTime() / 60) % 60),
249  QString().sprintf("%02d", m_board->currentTime() % 60));
250  KScoreDialog::FieldInfo scoreInfo;
251  scoreInfo[KScoreDialog::Score].setNum(score(m_board->xTiles(), m_board->yTiles(), m_board->currentTime(), m_board->gravityFlag()));
252  scoreInfo[KScoreDialog::Time] = timeString;
253 
254  KScoreDialog scoreDialog(KScoreDialog::Name | KScoreDialog::Time | KScoreDialog::Score, this);
255  scoreDialog.addField(KScoreDialog::Custom1, i18n("Gravity"), "gravity");
256  // FIXME: This is bad, because the translated words are stored in the highscores and thus switching the language makes ugly things (schwarzer)
257  if (m_board->gravityFlag()) {
258  scoreInfo[KScoreDialog::Custom1] = i18n("Yes");
259  } else {
260  scoreInfo[KScoreDialog::Custom1] = i18n("No");
261  }
262  scoreDialog.setConfigGroup(QString("%1x%2").arg(sizeX[Prefs::size()]).arg(sizeY[Prefs::size()]));
263 
264  if (m_board->hasCheated()) {
265  QString message = i18n("\nYou could have been in the highscores\nif you did not use Undo or Hint.\nTry without them next time.");
266  KMessageBox::information(this, message, i18n("End of Game"));
267  } else {
268  if (scoreDialog.addScore(scoreInfo) > 0) {
269  QString message = i18n("Congratulations!\nYou made it into the hall of fame.");
270  scoreDialog.setComment(message);
271  scoreDialog.exec();
272  } else {
273  QString message = i18nc("%1 - time string like hh:mm:ss", "You made it in %1", timeString);
274  KMessageBox::information(this, message, i18n("End of Game"));
275  }
276  }
277  }
278  updateItems();
279 }
280 
281 void App::updateTimeDisplay()
282 {
283  if (m_board->isStuck() || m_board->isOver()) {
284  return;
285  }
286  //kDebug() << "Time: " << m_board->currentTime();
287  int currentTime = m_board->currentTime();
288  QString message = i18n("Your time: %1:%2:%3 %4",
289  QString().sprintf("%02d", currentTime / 3600),
290  QString().sprintf("%02d", (currentTime / 60) % 60),
291  QString().sprintf("%02d", currentTime % 60),
292  m_board->isPaused() ? i18n("(Paused) ") : QString());
293 
294  m_gameTimerLabel->setText(message);
295  // FIXME: temporary hack until I find out why m_board->tilesLeft() in updateTileDisplay() counts the previous state of the board, not the current (schwarzer)
296  updateTileDisplay();
297 }
298 
299 void App::updateTileDisplay()
300 {
301  int numberOfTiles = (m_board->xTiles() * m_board->yTiles());
302  QString message = i18n("Removed: %1/%2 ",
303  QString().sprintf("%d", numberOfTiles - m_board->tilesLeft()),
304  QString().sprintf("%d", numberOfTiles));
305 
306  m_gameTilesLabel->setText(message);
307 }
308 
309 void App::updateCheatDisplay()
310 {
311  m_gameCheatLabel->setVisible(m_board->hasCheated());
312 }
313 
314 int App::score(int x, int y, int seconds, bool gravity) const
315 {
316  double ntiles = x * y;
317  double tilespersec = ntiles / static_cast<double>(seconds);
318 
319  double sizebonus = std::sqrt(ntiles / static_cast<double>(14.0 * 6.0));
320  double points = tilespersec / 0.14 * 100.0;
321 
322  if (gravity) {
323  return static_cast<int>(2.0 * points * sizebonus);
324  } else {
325  return static_cast<int>(points * sizebonus);
326  }
327 }
328 
329 void App::notifySelectATile()
330 {
331  m_gameTipLabel->setText(i18n("Select a tile"));
332 }
333 
334 void App::notifySelectAMatchingTile()
335 {
336  m_gameTipLabel->setText(i18n("Select a matching tile"));
337 }
338 
339 void App::notifySelectAMove()
340 {
341  m_gameTipLabel->setText(i18n("Select the move you want by clicking on the blue line"));
342 }
343 
344 void App::notifyTilesDoNotMatch()
345 {
346  m_gameTipLabel->setText(i18n("This tile did not match the one you selected"));
347 }
348 
349 void App::notifyInvalidMove()
350 {
351  m_gameTipLabel->setText(i18n("You cannot make this move"));
352 }
353 
354 void App::setCheatModeEnabled(bool enabled)
355 {
356  m_board->setCheatModeEnabled(enabled);
357  m_gameCheatLabel->setVisible(enabled);
358 }
359 
360 void App::showHighscores()
361 {
362  KScoreDialog scoreDialog(KScoreDialog::Name | KScoreDialog::Time, this);
363  scoreDialog.addField(KScoreDialog::Custom1, i18n("Gravity"), "gravity");
364  scoreDialog.exec();
365 }
366 
367 void App::keyBindings()
368 {
369  KShortcutsDialog::configure(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this);
370 }
371 
372 void App::showSettingsDialog()
373 {
374  if (KConfigDialog::showDialog("settings")) {
375  return;
376  }
377 
378  //Use the classes exposed by LibKmahjongg for our configuration dialog
379  KMahjonggConfigDialog *dialog = new KMahjonggConfigDialog(this, "settings", Prefs::self());
380  dialog->addPage(new Settings(0), i18n("General"), "games-config-options");
381  dialog->addTilesetPage();
382  dialog->addBackgroundPage();
383  dialog->setHelp(QString(), "kshisen");
384  connect(dialog, SIGNAL(settingsChanged(QString)), m_board, SLOT(loadSettings()));
385  dialog->show();
386 }
387 
388 #include "app.moc"
389 
390 // vim: expandtab:tabstop=4:shiftwidth=4
391 // kate: space-indent on; indent-width 4
Board::canUndo
bool canUndo() const
Returns if undo step is available.
Definition: board.cpp:1454
QWidget
Board::yTiles
int yTiles() const
Definition: board.cpp:184
QWidget::setupUi
void setupUi(QWidget *widget)
Board::setGameStuckEnabled
void setGameStuckEnabled(bool enabled)
Sets whether there are no matching tiles left.
Definition: board.cpp:1962
Board::hasCheated
bool hasCheated() const
Returns whether player is in cheat mode.
Definition: board.cpp:2012
Board::isOver
bool isOver() const
Returns whether the game is over.
Definition: board.cpp:1997
QWidget::setVisible
virtual void setVisible(bool visible)
Board::tilesLeft
int tilesLeft() const
Returns the number of tiles left on the board.
Definition: board.cpp:1809
prefs.h
Board::showHint
void showHint()
Definition: board.cpp:1709
Board::isPaused
bool isPaused() const
Returns whether the game is in pause mode.
Definition: board.cpp:2002
Board::gravityFlag
bool gravityFlag() const
Definition: board.cpp:1875
Prefs::self
static Prefs * self()
Definition: prefs.cpp:17
Prefs::sounds
static bool sounds()
Get Sounds.
Definition: prefs.h:144
Board
Class holding the game board and its functions.
Definition: board.h:136
KXmlGuiWindow
QTimer
Board::isStuck
bool isStuck() const
Returns whether there are still matching tiles left.
Definition: board.cpp:2007
QWidget::setUpdatesEnabled
void setUpdatesEnabled(bool enable)
QObject::setObjectName
void setObjectName(const QString &name)
sizeX
static int sizeX[6]
Definition: board.h:45
QLabel::setText
void setText(const QString &)
App::invokeNewGame
void invokeNewGame()
Invokes the creation of a new game.
QString
QWidget::hide
void hide()
Board::xTiles
int xTiles() const
Definition: board.cpp:179
App::App
App(QWidget *parent=0)
Definition: app.cpp:68
QLatin1String
Board::currentTime
int currentTime() const
Returns the current game time in seconds.
Definition: board.cpp:1824
QString::sprintf
QString & sprintf(const char *cformat,...)
Prefs::size
static int size()
Get Size.
Definition: prefs.h:206
Board::resetRedo
void resetRedo()
Resets the redo history.
Definition: board.cpp:1953
QTimer::start
void start(int msec)
app.h
Board::setPauseEnabled
void setPauseEnabled(bool enabled)
Controls the pause mode.
Definition: board.cpp:1914
Board::canRedo
bool canRedo() const
Returns if redo step is available.
Definition: board.cpp:1459
sizeY
static int sizeY[6]
Definition: board.h:46
Board::redo
void redo()
Redoes one step.
Definition: board.cpp:1686
Board::resetTimer
void resetTimer()
Resets the game timer.
Definition: board.cpp:1939
Board::setGameOverEnabled
void setGameOverEnabled(bool enabled)
Sets whether the game is over.
Definition: board.cpp:1978
QLabel
Board::undo
void undo()
Undoes one step.
Definition: board.cpp:1464
board.h
Board::setCheatModeEnabled
void setCheatModeEnabled(bool enabled)
Sets whether the game is in cheat mode.
Definition: board.cpp:1988
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:18:36 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KShisen

Skip menu "KShisen"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdegames API Reference

Skip menu "kdegames API Reference"
  • granatier
  • kapman
  • kblackbox
  • kgoldrunner
  • kigo
  • kmahjongg
  • KShisen
  • ksquares
  • libkdegames
  •   highscore
  •   libkdegamesprivate
  •     kgame
  • libkmahjongg
  • palapeli
  •   libpala

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal