summaryrefslogtreecommitdiffstats
path: root/kpoker
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitc90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch)
tree6d8391395bce9eaea4ad78958617edb20c6a7573 /kpoker
downloadtdegames-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 'kpoker')
-rw-r--r--kpoker/AUTHORS11
-rw-r--r--kpoker/ChangeLog306
-rw-r--r--kpoker/DESCRIPTION2
-rw-r--r--kpoker/Makefile.am20
-rw-r--r--kpoker/README20
-rw-r--r--kpoker/TODO38
-rw-r--r--kpoker/betbox.cpp136
-rw-r--r--kpoker/betbox.h114
-rw-r--r--kpoker/defines.h75
-rw-r--r--kpoker/global.h27
-rw-r--r--kpoker/hi128-app-kpoker.pngbin0 -> 8605 bytes
-rw-r--r--kpoker/hi16-app-kpoker.pngbin0 -> 646 bytes
-rw-r--r--kpoker/hi22-app-kpoker.pngbin0 -> 3624 bytes
-rw-r--r--kpoker/hi32-app-kpoker.pngbin0 -> 1456 bytes
-rw-r--r--kpoker/hi48-app-kpoker.pngbin0 -> 2505 bytes
-rw-r--r--kpoker/hi64-app-kpoker.pngbin0 -> 3413 bytes
-rw-r--r--kpoker/kpaint.cpp209
-rw-r--r--kpoker/kpaint.h121
-rw-r--r--kpoker/kpoker.cpp1484
-rw-r--r--kpoker/kpoker.desktop75
-rw-r--r--kpoker/kpoker.h364
-rw-r--r--kpoker/kpokerui.rc30
-rw-r--r--kpoker/main.cpp54
-rw-r--r--kpoker/newgamedlg.cpp204
-rw-r--r--kpoker/newgamedlg.h104
-rw-r--r--kpoker/optionsdlg.cpp119
-rw-r--r--kpoker/optionsdlg.h68
-rw-r--r--kpoker/player.cpp292
-rw-r--r--kpoker/player.h220
-rw-r--r--kpoker/playerbox.cpp262
-rw-r--r--kpoker/playerbox.h154
-rw-r--r--kpoker/poker.cpp531
-rw-r--r--kpoker/poker.h234
-rw-r--r--kpoker/sound.cpp47
-rw-r--r--kpoker/sounds/Makefile.am6
-rw-r--r--kpoker/sounds/cardflip.wavbin0 -> 1172 bytes
-rw-r--r--kpoker/sounds/hold.wavbin0 -> 1334 bytes
-rw-r--r--kpoker/sounds/lose.wavbin0 -> 5964 bytes
-rw-r--r--kpoker/sounds/win.wavbin0 -> 21831 bytes
-rw-r--r--kpoker/top.cpp266
-rw-r--r--kpoker/top.h70
-rw-r--r--kpoker/version.h3
42 files changed, 5666 insertions, 0 deletions
diff --git a/kpoker/AUTHORS b/kpoker/AUTHORS
new file mode 100644
index 00000000..866b0428
--- /dev/null
+++ b/kpoker/AUTHORS
@@ -0,0 +1,11 @@
+Codeing:
+Jochen Tuchbreiter <whynot@mabi.de>
+Mario Weilguni <mweilguni@kde.org>
+Andreas Beckermann <b_mann@gmx.de>
+Inge Wallin <inge@lysator.liu.se>
+
+Helping persons:
+Chris Holmes - idea of writing this game and parts of the visual appearence
+John Fitzgibbon - provided the card images
+Nico Schirwing - drew the backsides of the cards
+
diff --git a/kpoker/ChangeLog b/kpoker/ChangeLog
new file mode 100644
index 00000000..f38991bf
--- /dev/null
+++ b/kpoker/ChangeLog
@@ -0,0 +1,306 @@
+2005-09-15 Inge Wallin <ingwa@shihonage.lkpg.cendio.se>
+
+ Bump version number for release of KDE 3.5
+ * version.h (KPOKER_RELEASE_DATE): Bump version from 1.0 to 1.1
+
+2005-02-18 Inge Wallin <inge@lysator.liu.se>
+
+ * version.h (KPOKER_VERSION): Bumped version to 1.0 for KDE 3.4.
+
+2005-01-26 Inge Wallin <inge@lysator.liu.se>
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Code cleaning
+ * Make all blink parameters follow the m_ convention.
+
+2005-01-18 <inge@lysator.liu.se>
+
+ Continue the code cleaning.
+ * kpoker.h (PokerGameType): new type
+ * (PokerGame): All public members now private.
+ * Make the player array owned by kpok instead of PokerGame.
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Continue making more members of PokerGame private.
+ * kpoker.h (PokerGame::m_activePlayers): now private
+
+ ----------------- CVS commit on stuff below --------------------
+
+ * Bump version to 0.8alpha in anticipation of KDE 3.4.
+
+ Make members of PokerGame private.
+ * kpoker.cpp (Pokergame::newGame): new method
+ (PokerGame::m_minBet and m_maxBet): now private
+
+2004-11-20 Inge Wallin <inge@lysator.liu.se>
+
+ Fix bug 93636: When "Fold" is pressed, the current round should be
+ ended immediately.
+ * kpoker.cpp (out): Call drawClick(), i.e. go to next game state,
+ instead of setting up the drawButton to let the user do it.
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Fix bug 93635: The status bar is wrong in many places.
+ * top.cpp (PokerWindow): connect the signal to clear the status
+ bar to the proper slot.
+
+2004-11-03 Inge Wallin <inge@lysator.liu.se>
+
+ Rename the game states into something more logical
+ * kpoker.{h,cpp}: Renaming of poker game states
+
+ Exchange the faulty term "mix" for the correct one "shuffle".
+ * poker.{h,cpp}: mix() -> shuffle()
+ * misc files: call shuffle() instead.
+
+2004-09-12 Inge Wallin <inge@lysator.liu.se>
+
+ Fix bug 88584: Use proper poker terminology:
+ * kpoker.cpp (kpok::misc): Set text on "Draw" button according to
+ game state
+
+ Code cleaning:
+ * kpoker.{h,cpp} (kpok): remove member newGameDlg
+ * kpoker.{h,cpp} (PokerGameState): StateDraw -> StateStartRound
+ * kpoker.{h,cpp} (PokerGameState): uppercase state names.
+ * misc: added some comments
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Continue separation of class kpok into model/view
+ * kpoker.h (PokerGame): make m_deck, m_state, m_pot, m_isDirty
+ private members and create accessor methods for them.
+ * kpoker.cpp, kpoker.cpp: Use the accessor methods.
+ * kpoker.{h,cpp} (PokerGame::newRound): new method
+
+2004-09-11 Inge Wallin <inge@lysator.liu.se>
+
+ Introduced a class CardDeck
+ * poker.{h,cpp} (CardDeck): new class
+ * kpoker.{h,cpp} (PokerGame): new class
+ * kpoker.{h,cpp} (kpok::done): removed
+
+ Started separation of kpok into a poker game class and a view:
+ * kpoker.{h,cpp} (PokerGame): new class
+
+ Some cleanup
+ * player.{h,cpp}: Renamed class Player into PokerPlayer
+ * kpoker.{h,cpp}: references to Player -> PokerPlayer
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Remove a lot of unused methods and other cleanup
+ * poker.{h,cpp} (cleanFoundCards()): make protected
+ * player.h (Player::getCard()): don't convert to int.
+ * player.h (Player::cleanFoundCard()): remove
+ * playerbox.{h,cpp}: Prefix all members with m_.
+ (PlayerBox::getCashLabel{X,Y}): remove
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Break out all poker and card stuff into its own file
+ * poker.{h,cpp}: New files.
+ * player.{h,cpp}(card/poker stuff): moved to poker.{h,cpp}
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Remove all debug traces:
+ * player.h(Player::takeCard())
+ * player.cpp(PokerHand::operator<())
+ * kpoker.cpp(kpok::winner())
+
+ Move loading of card images to class CardImages:
+ * kpaint.{h,cpp}(CardImages::loadCards(),CardImages::loadDeck()): new methods.
+ * kpoker.{h,cpp}(loadCards,loadDeck): removed
+
+ Remove somestuff.cpp:
+ * somestuff.cpp: removed
+ * kpok::initWindow(): moved to kpoker.cpp
+ * Makefile.am(kpoker_SOURCES): remove somestuff.cpp
+
+ ----------------- CVS commit on stuff below --------------------
+
+ Use the constants from the card classes.
+ * defines.h: Removed highestCard and CARDS
+ * player.h(numCards): new constant
+ * kpaint.cpp, kpoker.cpp, player.cpp, playerbox.cpp,
+ somestuff.cpp: Use numCards and PokerHandSize instead
+
+ Rename initSomeStuff() into initWindow()
+ * somestuff.cpp: Rename
+ * kpoker.cpp(kpok::kpok): Call initWindow() instead
+
+ Make the card images private.
+ * kpaint.h, kpaint.cpp(CardImages): make m_deck and m_cardImages
+ private
+ * kpoker.cpp (loadCards, loadDeck): Call the loading of cards
+ differently
+
+2004-09-05 Inge Wallin <inge@lysator.liu.se>
+
+ Start structural cleanup
+ * kpoker.cpp (winner): Move from testers.cpp to kpoker.cpp.
+ * testers.cpp: deleted
+
+2004-09-03 Inge Wallin <inge@lysator.liu.se>
+
+ Fix bug 88548: Kpoker: When you save a game and then immediately
+ quit, kpoker asks if you want to save the game anyway
+ * kpoker::isDirty: New member
+ * misc: set and use isDirty
+
+2004-09-01 Inge Wallin <inge@lysator.liu.se>
+
+ * Removed the old code from the time before the switch of the
+ poker evaluation code. This was all contained in #if 0 - #endif
+ pairs.
+
+2004-08-31 Inge Wallin <inge@lysator.liu.se>
+
+ Finish the great code cleanup.
+ * kpoker.h, kpoker.cpp (only visually, though. Structure remains
+ to be cleaned further.)
+
+ * main.cpp (main): Fixed copyright notice in About dialog.
+
+2004-08-30 Inge Wallin <inge@lysator.liu.se>
+
+ Continue the great code cleanup.
+ * optionsdlg.h, optionsdlg.cpp
+ * newgamedlg.h, newgamedlg.cpp
+
+2004-08-29 Inge Wallin <inge@lysator.liu.se>
+
+ Continue the great code cleanup.
+ * sound.cpp
+ * top.h, top.cpp
+ * defines.h
+ * kpaint.h, kpaint.cpp
+ * playerbox.h, playerbox.cpp
+ * kpoker.h (Status): Renamed into PokerGameState
+ * betbox.h, betbox.cpp
+ * somestuff.cpp
+ * testers.cpp
+ * player.h, player.cpp
+
+2004-08-28 Inge Wallin <inge@lysator.liu.se>
+
+ Start of the great code cleanup
+ * global.h
+ * main.cpp
+
+2004-08-26 Inge Wallin <inge@lysator.liu.se>
+
+ Rewrote the whole evaluation of a poker hand.
+ * player.h, player.cpp (PokerHand): New class
+ * kpaint.cpp, kpoker.cpp, kpoker.h, playerbox.cpp, testers.cpp:
+ use the new code.
+
+2004-08-22 Inge Wallin <inge@lysator.liu.se>
+
+ Substituted the cardHelp array with a function Player::rank()
+ * player.h (cardHelp): removed
+ * player.cpp (initCardHelp): removed
+ * player.cpp (rank): new function
+ * kpoker.cpp (misc): don't call initCardHelp().
+
+
+----------------------------------------------------------------
+FIXME: The rest of this file should be named NEWS instead, since it is
+ only about releases.
+
+Version 0.7 (Andreas Beckermann <b_mann@gmx.de>)
+
+- added computer player
+- fixed some bugs, added many more
+- added bet/raise
+- added a QGroupBox for every player
+- improved status
+- added possibility to start the game without installing
+- added an optionsdialog
+- added further options which are not in the dialog
+- moved clickToHold and LHLabel to the new statusbar
+- started API documenting
+- much more
+
+------------------------------------------------------------------------------
+Version 0.6 (Mario Weilguni <mweilguni@kde.org>)
+- made it work with new KDE-2 API
+- made it work with --enable-final
+
+------------------------------------------------------------------------------
+Version 0.5
+
+- fixed a problem with the recognition of straights (the combo ace-2-3-4-5 was
+ not recognized in all versions <0.4.1
+
+- cleaned up the code a little
+
+- KPoker is now considered to be stable - I fixed all reported bugs and I did
+ not find any new ones :)
+
+------------------------------------------------------------------------------
+Version 0.4.1
+
+Silly me deleted some important lines that were initializing a timer while
+merging my version of 0.4 with the one in the CVS. This caused 0.4 to
+segfault when you press "Draw Cards" :-(
+
+- [Robert William] put version.h back in.
+
+- integrated version.h so that there is only one #define for the version &
+ release date (and not multiple ones like before)
+
+- put epilogue into the documentation
+
+------------------------------------------------------------------------------
+Version 0.4
+
+- deleted version.h because it is of no use
+- put in that nice "wave" effect
+- added sm-support
+- some internal stuff (as usual :)
+
+------------------------------------------------------------------------------
+Version 0.3.1
+
+- [Robert Williams] added getHelpMenu()
+- [Robert Williams] added version.h
+- changed minor look&feel stuff
+
+------------------------------------------------------------------------------
+Version 0.3
+
+- kpoker got adapted to the new fsstnd (thanks Coolo !)
+- kpoker now supports KLocale (only works in the kdegames-distribution)
+- added german language file (kdegames distribution only)
+- kpoker should now run on DEC Alphas (thanks Uwe Thiem :)
+
+------------------------------------------------------------------------------
+Version 0.2
+
+- reduced number of colors needed by the images for the backsides of cards
+- KPoker documentation is now written in .sgml format
+- lots of changes in makefiles
+- fixed that "#include <top.h>" bug.
+- sound support (experimental - *please* report problems)
+
+------------------------------------------------------------------------------
+Version 0.1.2
+
+- made kpoker use KTopLevelWidget + the new menubars
+- fixed silly problem with cardImage
+- finished the helpfile
+- built in new icon
+- built in new backsides of cards (1000 thanks to our "icon/graphics Man")
+
+------------------------------------------------------------------------------
+Version 0.1.1
+
+- made kpoker more "KDE conform" (like inserted separator between
+ help/help and help/about)
+- fixed a few silly bugs/problems
+- started to do the helpfile (halfway done right now)
diff --git a/kpoker/DESCRIPTION b/kpoker/DESCRIPTION
new file mode 100644
index 00000000..3f679e18
--- /dev/null
+++ b/kpoker/DESCRIPTION
@@ -0,0 +1,2 @@
+A little clone of those highly addictive, simple pocket poker games.
+
diff --git a/kpoker/Makefile.am b/kpoker/Makefile.am
new file mode 100644
index 00000000..8c72a34f
--- /dev/null
+++ b/kpoker/Makefile.am
@@ -0,0 +1,20 @@
+SUBDIRS = sounds
+
+INCLUDES = -I$(top_srcdir)/libkdegames $(all_includes)
+METASOURCES = AUTO
+KDE_ICON = kpoker
+
+bin_PROGRAMS = kpoker
+kpoker_SOURCES = kpoker.cpp kpaint.cpp top.cpp main.cpp betbox.cpp \
+ optionsdlg.cpp player.cpp playerbox.cpp newgamedlg.cpp poker.cpp
+kpoker_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kpoker_LDADD = $(LIB_KDEGAMES)
+kpoker_DEPENDENCIES = $(LIB_KDEGAMES_DEP)
+
+xdg_apps_DATA = kpoker.desktop
+
+rcdir = $(kde_datadir)/kpoker
+rc_DATA = kpokerui.rc
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kpoker.pot
diff --git a/kpoker/README b/kpoker/README
new file mode 100644
index 00000000..923ece84
--- /dev/null
+++ b/kpoker/README
@@ -0,0 +1,20 @@
+This is version 0.8 (nearly) of KPoker a not that simple poker clone
+for the K Desktop Environment <http://www.kde.org>.
+
+This version is considered to be pretty stable. Please take a look at
+the file ChangeLog to see what was changed recently.
+
+Have fun with the game and report any problems / bugs suggestions.
+
+
+ Andreas Beckerman and Inge Wallin
+
+
+Copyright (c) 1997-2000, by Jochen Tuchbreiter <whynot@mabi.de>
+This Program is distributed under the GPL. See the file COPYING for details
+
+This game is maintained by
+Andreas Beckermann <b_mann@gmx.de>
+Inge Wallin <inge@lysator.liu.se>
+
+
diff --git a/kpoker/TODO b/kpoker/TODO
new file mode 100644
index 00000000..fb954169
--- /dev/null
+++ b/kpoker/TODO
@@ -0,0 +1,38 @@
+ * Now
+
+
+ * Soon
+
+
+ * Further code cleanups:
+
+ - Separate the kpok class into a game object that holds all the
+ players, what state the game is in, the pot, etc, and a view of
+ the same.
+
+ This should result in a new class PokerGame and another one
+ PokerGameView. The class kpok (why the name abbreviation?) must
+ die.
+
+ - Separate card blinking into the card widget.
+
+ - Separate the waving motion into the winner box widget.
+
+ - CardImages shouldn't inherit QWidget.
+
+ - Make CardWidget::heldLabel private.
+
+ * Betting figures are funny. The program indicates that we have bet
+ even before the "Draw" or "Fold" buttons are pressed. Then the bet
+ amount decreases again. The correct behaviour is to not add the
+ amount until the user OKs it, i.e. presses "See".
+
+ Also, the "Adjust Bet" button doesn't look like it does anything as
+ it is now, although it actually does.
+
+ * Rewrite the README file. It is totally out of date.
+
+ * The documentation is totally out of sync with the program.
+
+ * Hiscore table?
+
diff --git a/kpoker/betbox.cpp b/kpoker/betbox.cpp
new file mode 100644
index 00000000..e152573f
--- /dev/null
+++ b/kpoker/betbox.cpp
@@ -0,0 +1,136 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "betbox.h"
+
+
+BetBox::BetBox(QWidget* parent, const char* name)
+ : QGroupBox(parent, name)
+{
+ QVBoxLayout* topLayout = new QVBoxLayout(this, 1, 1);
+ QGridLayout* g = new QGridLayout(topLayout, 2, 2, 1);
+ QHBoxLayout* l = new QHBoxLayout(topLayout, 1);
+
+ bet5Up = new QPushButton(this);
+ g->addWidget(bet5Up, 0, 0);
+ bet10Up = new QPushButton(this);
+ g->addWidget(bet10Up, 0, 1);
+ bet5Down = new QPushButton(this);
+ g->addWidget(bet5Down, 1, 0);
+ bet10Down = new QPushButton(this);
+ g->addWidget(bet10Down, 1, 1);
+
+ adjustBet = new QPushButton(this);
+ l->addWidget(adjustBet, 0);
+ l->addStretch(1);
+ foldButton = new QPushButton(this);
+ l->addWidget(foldButton, 0);
+
+ bet5Up->setText(QString("+%1").arg(KGlobal::locale()->formatMoney(5)));
+ bet10Up->setText(QString("+%1").arg(KGlobal::locale()->formatMoney(10)));
+ bet5Down->setText(QString("-%1").arg(KGlobal::locale()->formatMoney(5)));
+ bet10Down->setText(QString("-%1").arg(KGlobal::locale()->formatMoney(10)));
+ adjustBet->setText(i18n("Adjust Bet"));
+ foldButton->setText(i18n("Fold"));
+
+ //connects
+ connect(bet5Up, SIGNAL(clicked()), SLOT(bet5UpClicked()));
+ connect(bet10Up, SIGNAL(clicked()), SLOT(bet10UpClicked()));
+ connect(bet5Down, SIGNAL(clicked()), SLOT(bet5DownClicked()));
+ connect(bet10Down, SIGNAL(clicked()), SLOT(bet10DownClicked()));
+ connect(foldButton, SIGNAL(clicked()), SLOT(foldClicked()));
+ connect(adjustBet, SIGNAL(clicked()), SLOT(adjustBetClicked()));
+
+ stopRaise();
+}
+
+
+BetBox::~BetBox()
+{
+ delete bet5Up;
+ delete bet10Up;
+ delete bet5Down;
+ delete bet10Down;
+ delete adjustBet;
+ delete foldButton;
+}
+
+
+void BetBox::bet5UpClicked()
+{
+ emit betChanged(5);
+}
+
+void BetBox::bet10UpClicked()
+{
+ emit betChanged(10);
+}
+
+void BetBox::bet5DownClicked()
+{
+ emit betChanged(-5);
+}
+
+void BetBox::bet10DownClicked()
+{
+ emit betChanged(-10);
+}
+
+
+void BetBox::adjustBetClicked()
+{
+ emit betAdjusted();
+}
+
+
+void BetBox::foldClicked()
+{
+ emit fold();
+}
+
+
+void BetBox::beginRaise()
+{
+ adjustBet->setEnabled(true);
+ foldButton->setEnabled(true);
+
+ bet5Up->setEnabled(false);
+ bet10Up->setEnabled(false);
+ bet5Down->setEnabled(false);
+ bet10Down->setEnabled(false);
+}
+
+
+void BetBox::stopRaise()
+{
+ adjustBet->setEnabled(false);
+ foldButton->setEnabled(false);
+
+ bet5Up->setEnabled(true);
+ bet10Up->setEnabled(true);
+ bet5Down->setEnabled(true);
+ bet10Down->setEnabled(true);
+}
+
+
+#include "betbox.moc"
diff --git a/kpoker/betbox.h b/kpoker/betbox.h
new file mode 100644
index 00000000..2aa54894
--- /dev/null
+++ b/kpoker/betbox.h
@@ -0,0 +1,114 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef BETBOX_H
+#define BETBOX_H
+
+#include <qgroupbox.h>
+
+class QPushButton;
+
+
+/**
+ * This class provides a QGroupBox with several button
+ *
+ * The bet up / down buttons are used to change the player bet directly,
+ * the adjustBet and out buttons depend on the computers bet
+ * @short This is a box with several buttons used to bet / raise
+ **/
+class BetBox : public QGroupBox
+{
+ Q_OBJECT
+
+ public:
+ BetBox(QWidget* parent = 0, const char* name = 0);
+ ~BetBox();
+
+
+ /**
+ * Disables the usual bet up/down buttons and shows the adjust bet and fold buttons
+ *
+ * Used when the compputer player raised the players bet / raise
+ **/
+ void beginRaise();
+
+ /**
+ * Hides the Adjust bet / Fold buttons and enables the usual bet up / down buttons
+ **/
+ void stopRaise();
+
+ signals:
+ /**
+ * This signal is emitted when the user clicks on a bet up / down button
+ *
+ * The Value of the Button is sent as a parameter (change)
+ **/
+ void betChanged(int change);
+
+ /**
+ * This signal is emitted when the user clicks on the adjust bet button
+ **/
+ void betAdjusted();
+
+ /**
+ * This signal is emitted when the user clicks on the fold button
+ **/
+ void fold();
+
+ protected slots:
+ /**
+ * Emits the signal @ref betChanged(5)
+ **/
+ void bet5UpClicked();
+
+ /**
+ * Emits the signal @ref betChanged(10)
+ **/
+ void bet10UpClicked();
+
+ /**
+ * Emits the signal @ref betChanged(-5)
+ **/
+ void bet5DownClicked();
+
+ /**
+ * Emits the signal @ref betChanged(-10)
+ **/
+ void bet10DownClicked();
+
+ /**
+ * Emits the signal @ref betAdjusted()
+ **/
+ void adjustBetClicked();
+
+ /**
+ * Emits the signal @ref fold()
+ **/
+ void foldClicked();
+
+
+ private:
+ QPushButton *bet5Up;
+ QPushButton *bet10Up;
+ QPushButton *bet5Down;
+ QPushButton *bet10Down;
+ QPushButton *adjustBet;
+ QPushButton *foldButton;
+};
+
+
+#endif
diff --git a/kpoker/defines.h b/kpoker/defines.h
new file mode 100644
index 00000000..3da071f6
--- /dev/null
+++ b/kpoker/defines.h
@@ -0,0 +1,75 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+/* Some defines for the outlook etc. */
+#ifndef DEFINES_H
+#define DEFINES_H
+
+
+// ----------------------------------------------------------------
+// Graphical layout
+
+
+#define cardHeight 96
+#define cardWidth 72
+
+#define cardDistFromTop 20
+#define cardDistFromBottom 10
+#define cardHDist 10
+
+#define CLHBorderDistance 5
+#define CLHDistFromTop 180
+#define CLHWidth 140
+
+// Some derived constants
+#define PLAYERBOX_WIDTH ((cardWidth + cardHDist) * PokerHandSize + cardHDist + 135)
+#define PLAYERBOX_HEIGHT (cardHeight + cardDistFromTop + cardDistFromBottom)
+#define DISTANCE_FROM_2ND_BOX 100
+
+#define wonLabelVDist (cardHeight + cardDistFromTop + cardDistFromBottom + 10)
+#define clickToHoldVDist 130
+
+#define BORDER 10
+#define PLAYERBOX_BORDERS 15
+#define PLAYERBOX_HDISTANCEOFWIDGETS 10
+
+
+#define MAX_PLAYERS 2 // TODO: maximal 4-> see lskat for computer players
+
+
+// ----------------------------------------------------------------
+// Default values
+
+
+#define START_MONEY 100
+#define DEFAULT_PLAYERS 1 // change to 2 later
+
+// Will be overridden by config file:
+#define SOUND_DEFAULT true
+#define BLINKING_DEFAULT true
+#define SHOWNEWGAME_DEFAULT false
+#define ADJUST_DEFAULT true
+#define LOADGAME_DEFAULT true
+
+// changeable in OptionsDlg (and will be overridden by config file):
+#define DRAWDELAY 300
+#define MIN_BET 5
+#define MAX_BET 20
+#define CASH_PER_ROUND 5
+
+
+#endif
diff --git a/kpoker/global.h b/kpoker/global.h
new file mode 100644
index 00000000..d4755abd
--- /dev/null
+++ b/kpoker/global.h
@@ -0,0 +1,27 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GLOBAL__H__
+#define __GLOBAL__H__
+
+#include <klocale.h>
+#include <kconfig.h>
+
+extern KLocale *locale;
+extern KConfig *conf;
+
+#endif
+
diff --git a/kpoker/hi128-app-kpoker.png b/kpoker/hi128-app-kpoker.png
new file mode 100644
index 00000000..e2a5570a
--- /dev/null
+++ b/kpoker/hi128-app-kpoker.png
Binary files differ
diff --git a/kpoker/hi16-app-kpoker.png b/kpoker/hi16-app-kpoker.png
new file mode 100644
index 00000000..38b3a8c0
--- /dev/null
+++ b/kpoker/hi16-app-kpoker.png
Binary files differ
diff --git a/kpoker/hi22-app-kpoker.png b/kpoker/hi22-app-kpoker.png
new file mode 100644
index 00000000..9e939a49
--- /dev/null
+++ b/kpoker/hi22-app-kpoker.png
Binary files differ
diff --git a/kpoker/hi32-app-kpoker.png b/kpoker/hi32-app-kpoker.png
new file mode 100644
index 00000000..409f4764
--- /dev/null
+++ b/kpoker/hi32-app-kpoker.png
Binary files differ
diff --git a/kpoker/hi48-app-kpoker.png b/kpoker/hi48-app-kpoker.png
new file mode 100644
index 00000000..097fc5fd
--- /dev/null
+++ b/kpoker/hi48-app-kpoker.png
Binary files differ
diff --git a/kpoker/hi64-app-kpoker.png b/kpoker/hi64-app-kpoker.png
new file mode 100644
index 00000000..9ad09b3b
--- /dev/null
+++ b/kpoker/hi64-app-kpoker.png
Binary files differ
diff --git a/kpoker/kpaint.cpp b/kpoker/kpaint.cpp
new file mode 100644
index 00000000..c6322aee
--- /dev/null
+++ b/kpoker/kpaint.cpp
@@ -0,0 +1,209 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+// QT includes
+#include <qdir.h>
+#include <qlayout.h>
+
+// KDE includes
+//#include <kglobal.h>
+#include <kdebug.h>
+#include <kcarddialog.h>
+
+// own includes
+#include "defines.h"
+#include "poker.h"
+#include "kpaint.h"
+
+
+// ================================================================
+// class CardImages
+
+
+QPixmap *CardImages::m_cardPixmaps;
+QPixmap *CardImages::m_deck;
+
+
+CardImages::CardImages(QWidget* parent, const char* name)
+ : QWidget(parent, name)
+{
+ m_cardPixmaps = new QPixmap[numCards];
+ m_deck = new QPixmap;
+
+ // Hide the window.
+ // FIXME: Why is this a QWidget?
+ hide();
+ // loadCards();
+}
+
+
+CardImages::~CardImages()
+{
+ delete[] m_cardPixmaps;
+ delete m_deck;
+}
+
+
+QPixmap *
+CardImages::getCardImage(int card) const
+{
+ if (card == 0)
+ return m_deck;
+ else
+ return &m_cardPixmaps[card-1];
+}
+
+
+// Load all the card images from the directory 'cardDir'.
+
+void
+CardImages::loadCards(QString cardDir)
+{
+ for (int i = 0; i < numCards; i++) {
+ QString card = KCardDialog::getCardPath(cardDir, i + 1);
+
+ if (card.isEmpty() || !m_cardPixmaps[i].load(card)) {
+ if (!card.isEmpty())
+ kdWarning() << "Could not load " << card << " trying default" << endl;
+ card = KCardDialog::getCardPath(KCardDialog::getDefaultCardDir(), i+1);
+ if (!m_cardPixmaps[i].load(card)) {
+ kdError() << "Could not load " << card << endl;
+ }
+ }
+ }
+}
+
+
+// Load the backside of the card deck from the file name in 'path'.
+
+void
+CardImages::loadDeck(QString path)
+{
+ if (!m_deck->load(path)) {
+ kdWarning() << "Could not load deck - loading default deck" << endl;
+ path = KCardDialog::getDefaultDeck();
+ if (!m_deck->load(path))
+ kdError() << "Could not load deck" << endl;
+ }
+}
+
+
+// ================================================================
+// class CardWidget
+
+
+extern CardImages *cardImages;
+
+
+CardWidget::CardWidget( QWidget *parent, const char *name )
+ : QPushButton( parent, name )
+{
+ m_held = false;
+
+ setBackgroundMode( NoBackground ); // disables flickering
+ connect(this, SIGNAL(clicked()), this, SLOT(ownClick()));
+
+ setFixedSize(cardWidth, cardHeight);
+}
+
+
+void CardWidget::paintCard(int cardType)
+{
+ // Remap the card from the natural poker card values to the names
+ // used by the card decks in KDE.
+ //
+ // FIXME: This is an ugly hack. The correct way would be to add a
+ // method paintCard(CardValue card), but that will have to
+ // wait until we break out the card stuff to its own file so
+ // that there is something to include.
+ int card;
+ int rank;
+ int suit;
+
+ if (cardType == 0)
+ card = 0;
+ else {
+ suit = (cardType - 1) % 4;
+ rank = (cardType - 1) / 4;
+
+ rank = 12 - rank; // ace-two --> two-ace
+ switch (suit) {
+ case 0: break; // Clubs
+ case 1: suit = 3; break; // Diamonds
+ case 2: suit = 1; break; // Spades
+ case 3: suit = 2; break; // Hearts
+ }
+ card = rank * 4 + suit + 1;
+ }
+
+ // Select the pixmap to use.
+#if 0
+ if (card == 0) {
+ m_pm = &cardImage->m_deck;
+ } else {
+ m_pm = &cardImage->m_cardPixmaps[card-1];
+ }
+#else
+ m_pm = cardImages->getCardImage(card);
+#endif
+
+ // Set the pixmap in the QPushButton that we inherit from.
+ if ( m_pm->size() != QSize( 0, 0 ) ) { // is an image loaded?
+ setPixmap(*m_pm);
+ }
+}
+
+
+void CardWidget::repaintDeck()
+{
+ setPixmap(*m_pm);
+ setFixedSize(cardImages->getWidth(), cardImages->getHeight());
+
+ ((QWidget*) parent())->layout()->invalidate();
+ ((QWidget*) parent())->setFixedSize( ((QWidget*) parent())->sizeHint());
+}
+
+
+/* Emit the pClicked signal.
+ */
+
+void CardWidget::ownClick()
+{
+ emit pClicked(this);
+}
+
+
+bool CardWidget::getHeld()
+{
+ return m_held;
+}
+
+
+void CardWidget::setHeld(bool newheld)
+{
+ m_held = newheld;
+}
+
+
+bool CardWidget::toggleHeld()
+{
+ m_held = !m_held;
+ return m_held;
+}
+
+
+#include "kpaint.moc"
diff --git a/kpoker/kpaint.h b/kpoker/kpaint.h
new file mode 100644
index 00000000..ae4c1d29
--- /dev/null
+++ b/kpoker/kpaint.h
@@ -0,0 +1,121 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __CardWidget__
+#define __CardWidget__
+
+
+#include <assert.h>
+
+#include <qpushbutton.h>
+#include <qpixmap.h>
+
+
+class QLabel;
+
+
+/**
+ * This class loads all pictures, first. So they don't have to be loaded after the start again
+ * @short A help class for loading the pictures
+ **/
+
+class CardImages : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ CardImages( QWidget *parent = 0, const char *name = 0 );
+ ~CardImages();
+
+ // FIXME: Use CardValue instead of int when the cards are in their
+ // own file.
+ QPixmap *getCardImage(int card) const;
+ QPixmap *getDeck() const { return m_deck; }
+
+ int getWidth() const { return m_cardPixmaps[0].width(); }
+ int getHeight() const { return m_cardPixmaps[0].height(); }
+
+ void loadDeck(QString path);
+ void loadCards(QString cardDir);
+
+ private:
+ static QPixmap *m_cardPixmaps;
+ static QPixmap *m_deck;
+};
+
+
+/**
+ * This class extends the QPushButton by some methods / variables to provide a card with held labels and so on
+ *
+ * @short The cards
+ **/
+class CardWidget : public QPushButton
+{
+ Q_OBJECT
+
+ public:
+ CardWidget( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Paints the deck if cardType = 0 or the card specified in cardType
+ * @param cardType the card to be painted. 0 is the deck
+ **/
+ void paintCard(int cardType);
+
+ /**
+ * @return The held status of this card
+ **/
+ bool getHeld();
+
+ /**
+ * Sets the new held
+ * @param newHeld specifies the new held
+ **/
+ void setHeld(bool newheld);
+
+ /**
+ * Toggle the boolean member m_held.
+ **/
+ bool toggleHeld(); /* returns the new value of held*/
+
+
+ void repaintDeck();
+
+ signals:
+ /**
+ * This signal is emitted by @ref ownClick()
+ * @param CardWidget is a this pointer
+ **/
+ void pClicked(CardWidget *);
+
+ protected slots:
+ /**
+ * Emits the signal @ref pClicked() when the player clicks on the card
+ **/
+ void ownClick();
+
+
+ private:
+ QPixmap *m_pm; // the loaded pixmap
+ bool m_held;
+
+ public:
+ QLabel *heldLabel;
+};
+
+
+#endif
diff --git a/kpoker/kpoker.cpp b/kpoker/kpoker.cpp
new file mode 100644
index 00000000..2956b42c
--- /dev/null
+++ b/kpoker/kpoker.cpp
@@ -0,0 +1,1484 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// QT includes
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qlayout.h>
+
+// KDE includes
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kaudioplayer.h>
+#include <kcarddialog.h>
+
+// own includes
+#include "betbox.h"
+#include "kpaint.h"
+#include "optionsdlg.h"
+#include "newgamedlg.h"
+#include "player.h"
+#include "playerbox.h"
+#include "version.h"
+#include "kpoker.h"
+#include "defines.h"
+
+
+// ================================================================
+// Class PokerGame
+
+
+PokerGame::PokerGame(KRandomSequence *random)
+ : m_deck(random)
+{
+ // We don't need to save if we just started.
+ m_isDirty = false;
+
+ // Some defaults.
+ m_type = SinglePlayer;
+}
+
+
+PokerGame::~PokerGame()
+{
+ m_activePlayers.clear();
+ m_removedPlayers.clear();
+}
+
+
+void
+PokerGame::dealCards(PokerPlayer *player, bool skip[])
+{
+ CardValue card;
+
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (skip[i])
+ continue;
+
+ card = m_deck.getTopCard();
+
+ player->takeCard(i, card);
+ }
+}
+
+
+void
+PokerGame::activatePlayer(PokerPlayer *player)
+{
+ if (!m_activePlayers.contains(player)) {
+ m_activePlayers.append(player);
+ m_removedPlayers.remove(player);
+ }
+}
+
+
+void
+PokerGame::inactivatePlayer(PokerPlayer *player)
+{
+ if (m_activePlayers.contains(player)) {
+ m_activePlayers.remove(player);
+ m_removedPlayers.append(player);
+ }
+}
+
+
+void
+PokerGame::newGame(PokerGameType type,
+ int numPlayers, PokerPlayer *players,
+ int minBet, int maxBet)
+{
+ m_type = type;
+
+ // Store the players. These are never changed in the current implementation.
+ m_numPlayers = numPlayers;
+ m_players = players;
+
+ setBettingLimits(minBet, maxBet);
+
+ setState(StateStartRound);
+
+ // Initiate player arrays. Make all players active from the start.
+ m_activePlayers.clear();
+ m_removedPlayers.clear();
+ for (unsigned int i = 0; i < m_numPlayers; i++)
+ m_activePlayers.append(&m_players[i]);
+
+ // Inform players how much they may bet.
+ for (unsigned int i = 0; i < m_activePlayers.count(); i++)
+ m_activePlayers.at(i)->setBetDefaults(m_minBet, m_maxBet);
+}
+
+
+void
+PokerGame::newRound()
+{
+ // Reset the pot to zero.
+ m_pot = 0;
+
+ // Collect the cards and shuffle them.
+ m_deck.reset();
+ m_deck.shuffle();
+
+ // Clear the list of active and removed players.
+ m_activePlayers.clear();
+ m_removedPlayers.clear();
+}
+
+
+// ================================================================
+// Global variables
+
+
+CardImages *cardImages;
+
+
+// ================================================================
+// Class kpok
+
+
+kpok::kpok(QWidget *parent, const char *name)
+ : QWidget(parent, name),
+ m_game(&m_random)
+{
+ QString version;
+
+ m_random.setSeed(0);
+
+ // This class owns the players. Create them here.
+ // Currently we always allocate two - one human and one computer.
+ m_numPlayers = 2; // FIXME: Hard coded!!
+ m_players = new PokerPlayer[m_numPlayers];
+
+ // Initialize the first one to human...
+ m_players[0].setHuman();
+ m_players[0].setName(i18n("You"));
+
+ // ...and the rest to computer players.
+ for (int unsigned i = 1; i < m_numPlayers; i++)
+ m_players[i].setName(QString("Computer %1").arg(i-1));
+
+ lastHandText = "";
+
+ version = kapp->caption() + " " + KPOKER_VERSION;
+ setCaption( version );
+
+ mOptions = 0;
+
+ playerBox = 0;
+ adjust = false;
+
+ initWindow(); // FIXME: Change this name!!!
+ initSound();
+
+ if (!readEntriesAndInitPoker())
+ exit(0);
+}
+
+
+kpok::~kpok()
+{
+ if (mOptions != 0) {
+ if (m_numPlayers > 1)
+ m_game.setBettingLimits(mOptions->getMinBet(), mOptions->getMaxBet());
+
+ drawDelay = mOptions->getDrawDelay();
+ // cashPerRound = mOptions->getCashPerRound(); // NOT(!) configurable
+ }
+
+ KConfig* conf = kapp->config();
+ conf->setGroup("General");
+ conf->writeEntry("MinBet", m_game.getMinBet());
+ conf->writeEntry("MaxBet", m_game.getMaxBet());
+ // conf->writeEntry("CashPerRound", cashPerRound);
+ conf->writeEntry("DrawDelay", drawDelay);
+
+
+ delete[] m_players;
+
+ for (unsigned int i = 0; i < m_numPlayers; i++)
+ delete playerBox[i];
+ delete[] playerBox;
+
+ delete mOptions;
+}
+
+
+// Init the main window and load the configuration and card images.
+//
+// Only called by kpok::kpok() once.
+
+void kpok::initWindow()
+{
+ m_blinking = true;
+ m_blinkStat = 0;
+ m_blinkingBox = 0;
+
+ // General font stuff. Define myFixedFont and wonFont.
+ QFont myFixedFont;
+ myFixedFont.setPointSize(12);
+ QFont wonFont;
+ wonFont.setPointSize(14);
+ wonFont.setBold(true);
+
+ topLayout = new QVBoxLayout(this, BORDER);
+ QVBoxLayout* topInputLayout = new QVBoxLayout;
+ topLayout->addLayout(topInputLayout);
+
+ QHBoxLayout* betLayout = new QHBoxLayout;
+ inputLayout = new QHBoxLayout;
+ inputLayout->addLayout(betLayout);
+ topInputLayout->addLayout(inputLayout);
+
+ // The draw button
+ drawButton = new QPushButton(this);
+ drawButton->setText(i18n("&Deal"));
+ connect(drawButton, SIGNAL(clicked()), this, SLOT(drawClick()));
+ inputLayout->addWidget(drawButton);
+ inputLayout->addStretch(1);
+
+ // The waving text
+ QFont waveFont;
+ waveFont.setPointSize(16);
+ waveFont.setBold(true);
+ QFontMetrics tmp(waveFont);
+
+ // The widget where the winner is announced.
+ mWonWidget = new QWidget(this);
+ inputLayout->addWidget(mWonWidget, 2);
+ mWonWidget->setMinimumHeight(50); //FIXME hardcoded value for the wave
+ mWonWidget->setMinimumWidth(tmp.width(i18n("You won %1").arg(KGlobal::locale()->formatMoney(100))) + 20); // workaround for width problem in wave
+ QHBoxLayout* wonLayout = new QHBoxLayout(mWonWidget);
+ wonLayout->setAutoAdd(true);
+
+ wonLabel = new QLabel(mWonWidget);
+ wonLabel->setFont(wonFont);
+ wonLabel->setAlignment(AlignCenter);
+ wonLabel->hide();
+ inputLayout->addStretch(1);
+
+ // The pot view
+ potLabel = new QLabel(this);
+ potLabel->setFont(myFixedFont);
+ potLabel->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+ inputLayout->addWidget(potLabel, 0, AlignCenter);
+
+ // Label widget in the lower left.
+ clickToHold = new QLabel(this);
+ clickToHold->hide();
+
+ // Timers
+ blinkTimer = new QTimer(this);
+ connect( blinkTimer, SIGNAL(timeout()), SLOT(bTimerEvent()) );
+
+ waveTimer = new QTimer(this);
+ connect( waveTimer, SIGNAL(timeout()), SLOT(waveTimerEvent()) );
+
+ drawTimer = new QTimer(this);
+ connect (drawTimer, SIGNAL(timeout()), SLOT(drawCardsEvent()) );
+
+ // and now the betUp/Down Buttons
+ betBox = new BetBox(this, 0);
+ betLayout->addWidget(betBox);
+ connect(betBox, SIGNAL(betChanged(int)), this, SLOT(betChange(int)));
+ connect(betBox, SIGNAL(betAdjusted()), this, SLOT(adjustBet()));
+ connect(betBox, SIGNAL(fold()), this, SLOT(out()));
+
+ // some tips
+ QToolTip::add(drawButton, i18n("Continue the round"));
+ QToolTip::add(potLabel, i18n("The current pot"));
+
+ // Load all cards into pixmaps first -> in the constructor.
+ cardImages = new CardImages(this, 0);
+
+ // The configuration
+ KConfig* conf = kapp->config();
+ conf->setGroup("General");
+
+ // Load the card deck.
+ if (conf->readBoolEntry("RandomDeck", true)) {
+ cardImages->loadDeck(KCardDialog::getRandomDeck());
+ } else {
+ cardImages->loadDeck(conf->readPathEntry("DeckPath", KCardDialog::getDefaultDeck()));
+ }
+ if (conf->readBoolEntry("RandomCardDir", true)) {
+ cardImages->loadCards(KCardDialog::getRandomCardDir());
+ } else {
+ cardImages->loadCards(conf->readPathEntry("CardPath",
+ KCardDialog::getDefaultCardDir()));
+ }
+}
+
+
+// Start a new complete game (not a round).
+
+void kpok::newGame()
+{
+ NewGameDlg* newGameDlg;
+
+ // Get a "New Game" dialog.
+ lastHandText = "";
+ newGameDlg = new NewGameDlg(this);
+ newGameDlg->hideReadingFromConfig();
+
+ if (newGameDlg->exec()) {
+ stopBlinking();
+ stopDrawing();
+ stopWave();
+
+ // Delete the old values.
+ for (unsigned int i = 0; i < m_numPlayers; i++)
+ delete playerBox[i];
+ delete[] playerBox;// necessary?
+
+ int numPlayers = newGameDlg->getPlayers();
+
+ // Most things will be done in initPoker.
+ initPoker(numPlayers);
+
+ // Set/show the name and money of all players.
+ for (unsigned int i = 0; i < m_numPlayers; i++) {
+ m_players[i].setName(newGameDlg->name(i));
+ playerBox[i]->showName();
+ m_players[i].setCash((newGameDlg->money() >= m_game.getMinBet())
+ ? newGameDlg->money() : START_MONEY);
+ m_game.setDirty();
+ }
+
+ // Show the money for all players and the pot.
+ paintCash();
+
+ // Activate the Draw button.
+ drawButton->setText(i18n("&Deal"));
+ drawButton->setEnabled(true);
+ }
+
+ delete newGameDlg;
+}
+
+
+void kpok::newRound()
+{
+ bool onePlayerGame = false;
+
+ m_game.newRound();
+
+ playerBox[0]->setHeldEnabled(false);
+
+ if (m_numPlayers == 1)
+ onePlayerGame = true;
+
+ readOptions(); // maybe some options have changed so check em
+
+ if (m_players[0].getCash() < m_game.getMinBet())
+ noMoney();
+ else {
+ for (unsigned int i = 0; i < m_numPlayers; i++) {
+ if (m_players[i].getCash() >= m_game.getMinBet())
+ m_game.activatePlayer(&m_players[i]);
+ else
+ removePlayerFromRound(&m_players[i]);
+ }
+ }
+
+ if (m_game.getNumActivePlayers() == 1 && m_game.getType() != SinglePlayer)
+ switchToOnePlayerRules();
+
+ m_blinkingBox = 0;
+ wonLabel->hide();
+ stopBlinking();
+ stopWave();
+
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++)
+ m_game.getActivePlayer(i)->newRound();
+
+ // We are beginning a new round so every card is available.
+ drawAllDecks();
+ playerBox[0]->showHelds(false);
+
+ // Deal first cards of the round
+ bool skip[PokerHandSize];
+ for (int i = 0; i < PokerHandSize; i++)
+ skip[i] = false;
+
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++)
+ drawCards(m_game.getActivePlayer(i), skip);
+
+ if (m_game.getNumActivePlayers() > 1) {
+ findHumanPlayer()->changeBet(m_game.getMinBet());
+ m_game.bet(m_game.getMinBet());
+ betBox->show();
+ }
+ else {
+ m_game.getActivePlayer(0)->changeBet(cashPerRound);
+ betBox->hide();
+ }
+
+ paintCash();
+
+ drawTimer->start(drawDelay, TRUE);
+}
+
+
+void kpok::bet()
+{
+ // The players will bet, now. Player 1 (the human one ;-)) has
+ // already bet using the betBox ALL players (except player 1 who has
+ // already had) will get a chance to raise the value if nobody
+ // raises further that player will not get another chance, else he
+ // will.
+
+ bool raised = false;
+ int oldMustBet = 0;
+ if (m_game.getState() == StateBet2)
+ oldMustBet = currentMustBet;
+
+ if (m_game.getState() == StateBet1 || m_game.getState() == StateBet2) {
+ // The betting has just begun. This can be either the first or
+ // the second betting phase (state == StateBet1 or StateBet2).
+ // FIXME: These state names must be changed!
+
+ // Find out how much the other players must bet.
+ currentMustBet = findHumanPlayer()->getCurrentBet();
+
+ // First bet as usual.
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ PokerPlayer *player = m_game.getActivePlayer(i);
+ int playerBet = 0;
+
+ if (player->getHuman())
+ continue;
+
+ if (m_game.getState() == StateBet1) // first bet phase
+ playerBet = player->bet(currentMustBet);
+ else if (m_game.getState() == StateBet2) // 2nd bet phase
+ playerBet = player->raise(currentMustBet);
+
+ if (playerBet < currentMustBet) {
+ removePlayerFromRound(player);
+ // FIXME: This should be bet from the beginning!
+ if (m_game.getState() == StateBet1)
+ m_game.bet(m_game.getMinBet());
+ i--;
+ }
+ else {
+ // The player is seeing or has raised.
+
+ if (playerBet > currentMustBet)
+ raised = true;
+
+ currentMustBet = playerBet;
+ m_game.bet(currentMustBet - oldMustBet);
+ }
+ }
+ }
+ else if (m_game.getState() == StateRaise1
+ || m_game.getState() == StateRaise2) {
+
+ // The bet has been raised.
+ paintCash();
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ PokerPlayer *player = m_game.getActivePlayer(i);
+
+ // human player
+ if (player->getCurrentBet() < currentMustBet && player->getHuman()) {
+ removePlayerFromRound(player);
+ i--;
+ }
+ }
+ }
+
+ paintCash();
+
+
+ oldBet_raise = findHumanPlayer()->getCurrentBet(); // used by out() only
+ if (m_game.getState() == StateBet1 || m_game.getState() == StateBet2) {
+ if (raised) {
+ if (m_game.getState() == StateBet1)
+ m_game.setState(StateRaise1);
+ else
+ m_game.setState(StateRaise2);
+
+ if (adjust)
+ adjustBet();
+ else
+ out(); // not necessary
+ betBox->setEnabled(true);
+ betBox->beginRaise();
+ if (adjust)
+ emit statusBarMessage(i18n("Clicking on draw means you adjust your bet"));
+ else
+ emit statusBarMessage(i18n("Clicking on draw means you are out"));
+ }
+ else {
+ if (m_game.getState() == StateBet1)
+ m_game.setState(StateExchangeCards);
+ else
+ m_game.setState(StateSee);
+ }
+ }
+ else if (m_game.getState() == StateRaise1 && !raised) {
+ emit clearStatusBar();
+ // weWillAdjustLabel->hide();
+ betBox->stopRaise();
+ m_game.setState(StateExchangeCards);
+ }
+ else if (m_game.getState() == StateRaise2 && !raised) {
+ emit clearStatusBar();
+ // weWillAdjustLabel->hide();
+ betBox->stopRaise();
+ m_game.setState(StateSee);
+ }
+
+
+ // Check if player 1 is out -> for players > 2
+ // TODO: maybe if (!m_activePlayers.contains(humanPlayer))
+ // {exchangeCards(); bet(); displayerWinner_computer();return;}
+
+
+ // don't continue game if player 1 is alone
+ // TODO: port to players > 2
+ // this is ONLY working for players <= 2
+ if (m_game.getNumInactivePlayers() >= 1
+ && m_game.getNumActivePlayers() == 1)
+ displayWinner_Computer(m_game.getActivePlayer(0), true);
+}
+
+
+void kpok::out()
+{
+ // weWillAdjustLabel->hide();
+ emit clearStatusBar();
+
+ m_game.bet(oldBet_raise - findHumanPlayer()->getCurrentBet());
+ findHumanPlayer()->changeBet(oldBet_raise
+ - findHumanPlayer()->getCurrentBet());
+ paintCash();
+
+ // Go to next state immediately. (Previously we told the user to
+ // click the action button.)
+ drawClick();
+ //drawButton->setText(i18n("&End Round"));
+}
+
+
+void kpok::adjustBet()
+{
+ emit clearStatusBar();
+
+ betChange(currentMustBet - findHumanPlayer()->getCurrentBet());
+ paintCash();
+}
+
+
+// Initiate for a completely new game (not a round).
+//
+// This is called from newGame(), readEntriesAndInitPoker(), loadGame().
+//
+
+void kpok::initPoker(unsigned int numPlayers)
+{
+ m_numPlayers = numPlayers;
+
+ // Tell the game about the players also.
+ PokerGameType gametype = (numPlayers == 1) ? SinglePlayer : MultiPlayer;
+
+ // Read some defaults.
+ kapp->config()->setGroup("General");
+ int minBet = kapp->config()->readNumEntry("MinBet", MIN_BET);
+ int maxBet = kapp->config()->readNumEntry("MaxBet", MAX_BET);
+
+ // Start a new poker game using the data found out above.
+ m_game.newGame(gametype, m_numPlayers, m_players, minBet, maxBet);
+
+ // Not (yet) configurable
+ cashPerRound = CASH_PER_ROUND;
+ drawDelay = kapp->config()->readNumEntry("DrawDelay", DRAWDELAY);
+
+ m_blinkingBox = 0;
+ currentMustBet = m_game.getMinBet();
+
+ // --- Graphics ---
+
+ // Make all labels / boxes / cardwidgets for every player.
+ playerBox = new PlayerBox *[numPlayers];
+
+ for (int unsigned i = 0; i < numPlayers; i++) {
+ playerBox[i] = new PlayerBox(i == 0, this);
+ playerBox[i]->setPlayer(&m_players[i]);
+ if (i == 0)
+ topLayout->insertWidget(0, playerBox[i]);
+ else
+ topLayout->addWidget(playerBox[i]);
+ playerBox[i]->showName();
+
+ // If it has been deleted and created again it hasn't be shown
+ // correctly - hiding and re-showing solves the problem.
+ playerBox[i]->hide();
+ playerBox[i]->show();
+ }
+
+ // Connects for player 1
+ //
+ // FIXME: Make CardWidget::toggleHeld() work.
+ playerBox[0]->activateToggleHeld();
+ connect(playerBox[0], SIGNAL(toggleHeld()), this, SLOT(toggleHeld()));
+
+ // hide some things
+ playerBox[0]->showHelds(false);
+ wonLabel->hide();
+ emit showClickToHold(false);
+
+ // Different meaning of the status for single and multi player games.
+ if (m_game.getNumActivePlayers() > 1) {
+ setHand(i18n("Nobody"), false);
+ betBox->show();
+ betBox->setEnabled(false);
+ potLabel->show();
+ }
+ else {
+ setHand(i18n("Nothing"));
+ betBox->hide();
+ potLabel->hide();
+ playerBox[0]->singlePlayerGame(cashPerRound);
+ }
+
+ // Some final inits.
+ drawStat = 0;
+ waveActive = 0;
+ fCount = 0;
+
+ // Finally clear the pot and show the decks/cash - in one word: begin :-)
+ m_game.clearPot();
+ drawAllDecks();
+ for (unsigned int i = 0; i < m_numPlayers; i++) {
+ playerBox[i]->repaintCard();
+ }
+ paintCash();
+ playerBox[0]->setHeldEnabled(false);
+}
+
+
+void kpok::paintCash()
+{
+ for (unsigned int i = 0; i < m_numPlayers; i++) {
+ playerBox[i]->showCash();
+ }
+ potLabel->setText(i18n("Pot: %1").arg(KGlobal::locale()->formatMoney(m_game.getPot())));
+}
+
+
+void kpok::updateLHLabel()
+{
+ if (!lastHandText.isEmpty())
+ setHand(lastHandText);
+ else if (m_game.getNumActivePlayers() > 1)
+ setHand(i18n("Nobody"), false);
+ else
+ setHand(i18n("Nothing"));
+}
+
+
+void kpok::setHand(const QString& newHand, bool lastHand)
+{
+ emit changeLastHand(newHand, lastHand);
+
+ lastHandText = newHand;
+}
+
+
+void kpok::toggleHeld()
+{
+ if (m_game.getState() == StateBet1 || m_game.getState() == StateRaise1)
+ playSound("hold.wav");
+}
+
+
+void kpok::drawClick()
+{
+ if (!drawButton->isEnabled())
+ return;
+
+ // If this is the start of a new round, then deal new cards.
+ if (m_game.getState() == StateStartRound) {
+ drawButton->setEnabled(false);
+ betBox->setEnabled(false);
+ newRound();
+ }
+ else if (m_game.getState() == StateBet1) { // bet
+ emit showClickToHold(false);
+
+ bet();
+ if (m_game.getState() == StateExchangeCards) {// should be set in bet()
+ drawClick();
+ }
+ }
+ else if (m_game.getState() == StateRaise1) { // continue bet
+ bet();
+ if (m_game.getState() == StateExchangeCards) {// should be set in bet()
+ drawClick();
+ }
+ }
+ else if (m_game.getState() == StateExchangeCards) { // exchange cards
+ drawButton->setEnabled(false);
+ playerBox[0]->setHeldEnabled(false);
+ betBox->setEnabled(false);
+ bool skip[PokerHandSize];
+ for (int i = 0; i < PokerHandSize; i++)
+ skip[i] = false;
+
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ if (!m_game.getActivePlayer(i)->getHuman())
+ m_game.getActivePlayer(i)->exchangeCards(skip);
+ else {
+ for (int i = 0; i < PokerHandSize; i++) {
+ skip[i] = playerBox[0]->getHeld(i);
+ if (!skip[i])
+ playerBox[0]->paintDeck(i);
+ }
+ }
+ drawCards(m_game.getActivePlayer(i), skip);
+ }
+
+ if (playerBox[0]->getHeld(0))
+ drawTimer->start(0, TRUE);
+ else
+ drawTimer->start(drawDelay, TRUE);
+ }
+ else if (m_game.getState() == StateBet2) { // raise
+ setBetButtonEnabled(false);
+ bet();
+
+ if (m_game.getState() == StateSee)//should be set in bet()->if no one has raised
+ drawClick();
+ }
+ else if (m_game.getState() == StateRaise2) {
+ bet();
+ if (m_game.getState() == StateSee)
+ drawClick();
+ }
+ else if (m_game.getState() == StateSee)
+ winner();
+}
+
+
+void kpok::drawCards(PokerPlayer* p, bool skip[])
+{
+ m_game.dealCards(p, skip);
+}
+
+
+void kpok::displayWinner_Computer(PokerPlayer* winner, bool othersPassed)
+{
+ // Determine the box that contains the winner.
+ for (unsigned int i = 0; i < m_numPlayers; i++) {
+ if (&m_players[i] == winner)
+ m_blinkingBox = i;
+ }
+
+ // Give the pot to the winner.
+ winner->setCash(winner->getCash() + m_game.getPot());
+ m_game.setDirty();
+
+ // Generate a string with winner info and show it.
+ QString label;
+ if (winner->getHuman())
+ label = i18n("You won %1").arg(KGlobal::locale()->formatMoney(m_game.getPot()));
+ else
+ label = i18n("%1 won %2").arg(winner->getName()).arg(KGlobal::locale()->formatMoney(m_game.getPot()));
+ wonLabel->setText(label);
+
+ // Start the waving motion of the text.
+ QFont waveFont;
+ waveFont.setBold(true);
+ waveFont.setPointSize(16);
+ QFontMetrics tmp(waveFont);
+ mWonWidget->setMinimumWidth(tmp.width(label) + 20);
+
+ // Play a suitable sound.
+ if (winner->getHuman()) {
+ playSound("win.wav");
+ wonLabel->hide();
+ startWave();
+ }
+ else {
+ playSound("lose.wav");
+ wonLabel->show();
+ }
+
+ m_game.clearPot();
+ m_game.setState(StateStartRound);
+ drawButton->setEnabled(true);
+ setHand(winner->getName(), false);
+ paintCash();
+
+ // Only start blinking if player 1 is still in.
+ if (m_game.isActivePlayer(&m_players[0]) && !othersPassed)
+ startBlinking();
+
+ drawButton->setText(i18n("&Deal New Round"));
+}
+
+
+void kpok::showComputerCards()
+{
+ // Don't show cards of 'out' players.
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ if (!m_game.getActivePlayer(i)->getHuman()){
+ playerBox[i]->paintCard(drawStat); //TODO change:
+
+ if (i == 1) //TODO : CHANGE!
+ playSound("cardflip.wav");//perhaps in playerbox or even in cardwidget
+ }
+ }
+
+ if (drawStat == 4) { // just did last card
+ drawButton->setEnabled(true);
+ drawStat = 0;
+ } else { // only inc drawStat if not done with displaying
+ drawStat++;
+ showComputerCards();
+ }
+}
+
+
+void kpok::setBetButtonEnabled(bool enabled)
+{
+ betBox->setEnabled(enabled);
+}
+
+
+void kpok::drawCardsEvent()
+{
+ if (!playerBox[0]->getHeld(drawStat)) {
+ playerBox[0]->paintCard(drawStat);
+
+ playSound("cardflip.wav");//maybe in playerbox or even in cardwidget
+ }
+
+ if (drawStat == 4) { // just did last card
+ drawButton->setEnabled(true);
+ betBox->setEnabled(true);
+ drawStat = 0;
+
+ if (m_game.getState() == StateExchangeCards) {
+ if (m_game.getType() == SinglePlayer)
+ result();
+ else {
+ // Now give players the chance to raise.
+ drawButton->setText(i18n("&See!"));
+ m_game.setState(StateBet2);
+ }
+ } else if (m_game.getState() == StateStartRound) {
+ playerBox[0]->setHeldEnabled(true);
+
+ emit showClickToHold(true);
+ //clickToHold->show();
+ //TODO:
+ m_game.setState(StateBet1);
+ drawButton->setText(i18n("&Draw New Cards"));
+ }
+
+ } else { // only inc drawStat if not done with displaying
+ drawStat++;
+ // look at next card and if it is held instantly call drawCardEvent again
+ if (playerBox[0]->getHeld(drawStat))
+ drawTimer->start(0,TRUE);
+ else
+ drawTimer->start(drawDelay,TRUE);
+ }
+}
+
+
+// Called to display the result in a single player game.
+
+void kpok::result()
+{
+ int testResult = m_game.getActivePlayer(0)->testHand();
+ switch (testResult) {
+ case Pair:
+ if (m_game.getActivePlayer(0)->getHand().get_firstRank() < JACK) {
+ displayWin(i18n("Nothing"), 0);
+ break;
+ }
+
+ displayWin(i18n("One Pair"), 5);
+ break;
+
+ case TwoPairs:
+ displayWin(i18n("Two Pairs"), 10);
+ break;
+
+ case ThreeOfAKind:
+ displayWin(i18n("3 of a Kind"), 15);
+ break;
+
+ case Straight:
+ displayWin(i18n("Straight"), 20);
+ break;
+
+ case Flush:
+ displayWin(i18n("Flush"), 25);
+ break;
+
+ case FullHouse:
+ displayWin(i18n("Full House"), 40);
+ break;
+
+ case FourOfAKind:
+ displayWin(i18n("4 of a Kind"), 125);
+ break;
+
+ case StraightFlush:
+ displayWin(i18n("Straight Flush"), 250);
+ break;
+
+ case RoyalFlush:
+ displayWin(i18n("Royal Flush"), 2000);
+ break;
+
+ default:
+ displayWin(i18n("Nothing"), 0);
+ break;
+ }
+
+ startBlinking();
+ m_game.setState(StateStartRound);
+
+ if (m_game.getActivePlayer(0)->getCash() < cashPerRound)
+ noMoney();
+}
+
+
+// Display winner and give money and so on.
+
+void kpok::winner()
+{
+ PokerPlayer *winner;
+
+ showComputerCards();
+
+ winner = m_game.getActivePlayer(0);
+ for (int i = 1; i < m_game.getNumActivePlayers(); i++) {
+ if (winner->getHand() < m_game.getActivePlayer(i)->getHand()) {
+ //kdDebug() << "Hand 2 is better." << endl;
+ winner = m_game.getActivePlayer(i);
+ }
+ else {
+ //kdDebug() << "Hand 1 is better." << endl;
+ }
+ }
+
+ displayWinner_Computer(winner, false);
+}
+
+
+void kpok::noMoney()
+{
+ KMessageBox::sorry(0, i18n("You Lost"), i18n("Oops, you went bankrupt.\n"
+ "Starting a new game.\n"));
+ newGame();
+}
+
+
+void kpok::startBlinking()
+{
+ blinkTimer->start(650);
+}
+
+
+void kpok::stopBlinking()
+{
+ blinkTimer->stop();
+ m_blinkStat = 1;
+ m_blinkingBox = 0;
+}
+
+
+void kpok::startWave()
+{
+ waveTimer->start(40);
+ waveActive = true;
+}
+
+
+void kpok::stopWave()
+{
+ waveTimer->stop();
+ fCount = -1; /* clear image */
+ repaint ( FALSE );
+ waveActive = false;
+}
+
+
+void kpok::stopDrawing()
+{
+ drawTimer->stop();
+}
+
+
+void kpok::waveTimerEvent()
+{
+ fCount = (fCount + 1) & 15;
+ repaint( FALSE );
+}
+
+
+void kpok::bTimerEvent()
+{
+ if (m_blinking) {
+ if (m_blinkStat != 0) {
+ playerBox[m_blinkingBox]->blinkOn();
+ m_blinkStat = 0;
+ } else {
+ playerBox[m_blinkingBox]->blinkOff();
+ m_blinkStat = 1;
+ }
+ }
+}
+
+
+void kpok::displayWin(const QString& hand, int cashWon)
+{
+ QString buf;
+
+ setHand(hand);
+ m_game.getActivePlayer(0)->setCash(m_game.getActivePlayer(0)->getCash()
+ + cashWon);
+ m_game.setDirty();
+ paintCash();
+
+ if (cashWon) {
+ playSound("win.wav");
+ buf = i18n("You won %1!").arg(KGlobal::locale()->formatMoney(cashWon));
+ } else {
+ playSound("lose.wav");
+ buf = i18n("Game Over"); // locale
+ }
+ wonLabel->setText(buf);
+
+ if (!cashWon)
+ wonLabel->show();
+ else {
+ wonLabel->hide();
+ startWave();
+ }
+
+ drawButton->setText(i18n("&Deal New Round"));
+}
+
+
+void kpok::paintEvent( QPaintEvent *)
+{
+ /* NOTE: This was shamelessy stolen from the "hello world" example
+ * coming with Qt Thanks to the Qt-Guys for doing such a cool
+ * example 8-)
+ */
+
+ if (!waveActive) {
+ return;
+ }
+
+ QString txt = wonLabel->text();
+ wonLabel->hide();
+
+ static int sin_tbl[16] = {
+ 0, 38, 71, 92, 100, 92, 71, 38, 0, -38, -71, -92, -100, -92, -71, -38};
+
+ if ( txt.isEmpty() ) {
+ return;
+ }
+
+ QFont wonFont;
+ wonFont.setPointSize(18);
+ wonFont.setBold(true);
+
+ QFontMetrics fm = QFontMetrics(wonFont);
+
+ int w = fm.width(txt) + 20;
+ int h = fm.height() * 2;
+ while (w > mWonWidget->width() && wonFont.pointSize() > 6) {// > 6 for emergency abort...
+ wonFont.setPointSize(wonFont.pointSize() - 1);
+ fm = QFontMetrics(wonFont);
+ w = fm.width(txt) + 20;
+ h = fm.height() * 2;
+ }
+
+ int pmx = mWonWidget->width() / 2 - w / 2;
+ int pmy = 0;
+ // int pmy = (playerBox[0]->x() + playerBox[0]->height() + 10) - h / 4;
+
+ QPixmap pm( w, h );
+ pm.fill( mWonWidget, pmx, pmy );
+
+ if (fCount == -1) { /* clear area */
+ bitBlt( mWonWidget, pmx, pmy, &pm );
+ return;
+ }
+
+ QPainter p;
+ int x = 10;
+ int y = h/2 + fm.descent();
+ unsigned int i = 0;
+ p.begin( &pm );
+ p.setFont( wonFont );
+ p.setPen( QColor(0,0,0) );
+
+ while ( i < txt.length() ) {
+ int i16 = (fCount+i) & 15;
+
+ p.drawText( x, y-sin_tbl[i16]*h/800, QString(txt[i]), 1 );
+ x += fm.width( txt[i] );
+ i++;
+ }
+ p.end();
+
+ // 4: Copy the pixmap to the Hello widget
+ bitBlt( mWonWidget, pmx, pmy, &pm );
+}
+
+
+void kpok::drawAllDecks()
+{
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ for (int i2 = 0; i2 < PokerHandSize; i2++) {
+ m_game.getActivePlayer(i)->takeCard(i2, 0);
+ playerBox[i]->paintCard(i2);
+ }
+ }
+}
+
+
+void kpok::removePlayerFromRound(PokerPlayer* removePlayer)
+{
+ removePlayer->setOut(true);
+ m_game.inactivatePlayer(removePlayer);
+
+ for (int i = 0; i < m_game.getNumPlayers(); i++)
+ playerBox[i]->showCash();
+}
+
+
+void kpok::switchToOnePlayerRules()
+{
+ KMessageBox::information(0, i18n("You are the only player with money!\n"
+ "Switching to one player rules..."),
+ i18n("You Won"));
+
+ // Hide all computer players.
+ for (unsigned int i = 1; i < m_numPlayers; i++) {
+ playerBox[i]->hide();
+ }
+
+ m_game.setType(SinglePlayer);
+
+ betBox->hide();
+ potLabel->hide();
+ playerBox[0]->singlePlayerGame(cashPerRound);
+ setHand(i18n("Nothing"));
+}
+
+
+PokerPlayer* kpok::findHumanPlayer()
+{
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ if (m_game.getActivePlayer(i)->getHuman())
+ return m_game.getActivePlayer(i);
+ }
+
+ return m_game.getActivePlayer(0);//error
+}
+
+
+bool kpok::readEntriesAndInitPoker()
+{
+ NewGameDlg *newGameDlg = NULL;
+ KConfig *conf = kapp->config();
+ int numPlayers = DEFAULT_PLAYERS;
+
+ conf->setGroup("NewGameDlg");
+ bool showNewGameDlg = conf->readBoolEntry("showNewGameDlgOnStartup", false);
+ bool aborted = false;
+ bool oldGame = false;
+
+ if (showNewGameDlg) {
+ newGameDlg = new NewGameDlg(this);
+ if (!newGameDlg->exec())
+ return false; // exit game
+ }
+
+ if (!aborted && (!showNewGameDlg || showNewGameDlg &&
+ newGameDlg->readFromConfigFile())) {
+ // Try starting an old game.
+ //kdDebug() << "Trying to load old game" << endl;
+ oldGame = loadGame();
+ if (oldGame)
+ return true;
+ }
+
+ if (!aborted && showNewGameDlg && !oldGame) {
+ // Don't use config file - just take the values from the dialog.
+ // (This is also config - the dialog defaults are from config.)
+ numPlayers = newGameDlg->getPlayers();
+ if (numPlayers <= 0)
+ aborted = true;
+
+ for (int i = 0; i < numPlayers; i++) {
+ m_players[i].setName(newGameDlg->name(i));
+ m_players[i].setCash(newGameDlg->money());
+ m_game.setDirty();
+ }
+ }
+ initPoker(numPlayers);
+
+ if (newGameDlg != 0) {
+ delete newGameDlg;
+ }
+
+ return true;
+}
+
+
+void kpok::betChange(int betChange)
+{
+ PokerPlayer* p = findHumanPlayer();
+
+ switch(m_game.getState()){
+ case StateBet1:
+ if (p->getCurrentBet() + betChange >= m_game.getMinBet() &&
+ p->getCurrentBet() + betChange <= m_game.getMaxBet()) {
+ // Bet at least getMinBet() but not more than getMaxBet().
+ if (p->changeBet(betChange))
+ m_game.bet(betChange);
+ }
+ break;
+ case StateBet2:
+ case StateRaise2:
+ case StateRaise1:
+ if (p->getCurrentBet() + betChange >= currentMustBet
+ && p->getCurrentBet() + betChange <= currentMustBet + m_game.getMaxBet()) {
+ if (p->changeBet(betChange))
+ m_game.bet(betChange);
+ }
+ break;
+ default:
+ break;
+ }
+
+ paintCash();
+}
+
+
+void kpok::saveGame()
+{
+ kapp->config()->setGroup("Save");
+ saveGame(kapp->config());
+}
+
+
+void kpok::saveGame(KConfig* conf)
+{
+ // kdWarning() << "save game" << endl;
+ int players = m_game.getNumPlayers();
+
+ conf->writeEntry("players", players);
+ conf->writeEntry("lastHandText", lastHandText);
+
+ for (int i = 0; i < players; i++) {
+ conf->writeEntry(QString("Name_%1").arg(i), m_players[i].getName());
+ conf->writeEntry(QString("Human_%1").arg(i), m_players[i].getHuman());
+ conf->writeEntry(QString("Cash_%1").arg(i), m_players[i].getCash());
+ }
+
+ m_game.clearDirty();
+}
+
+
+void kpok::toggleSound() { setSound(!sound); }
+void kpok::toggleBlinking() { setBlinking(!m_blinking); }
+void kpok::toggleAdjust() { setAdjust(!adjust); }
+
+
+void kpok::slotPreferences()
+{
+ if ( mOptions==0 )
+ mOptions = new OptionsDlg(this, 0, m_numPlayers);
+
+ if (m_numPlayers > 1)
+ mOptions->init(drawDelay, m_game.getMaxBet(), m_game.getMinBet());
+ else
+ mOptions->init(drawDelay, cashPerRound);
+
+ if (!mOptions->exec()) {
+ delete mOptions;
+ mOptions = 0;
+ }
+}
+
+
+void kpok::setAdjust(bool ad)
+{
+ adjust = ad;
+
+ //update guessed money statusbar if we currently are in need of adjust
+ if (m_game.getState() == StateRaise1
+ || m_game.getState() == StateRaise2) {
+ if (adjust)
+ adjustBet();
+ else
+ out();
+ }
+}
+
+
+bool kpok::initSound()
+{
+ sound = true;
+ return true;
+}
+
+
+void kpok::playSound(const QString &soundname)
+{
+ if (sound)
+ KAudioPlayer::play(locate("data", QString("kpoker/sounds/")+soundname));
+}
+
+
+void kpok::setSound(bool s)
+{
+ sound = s;
+}
+
+
+void kpok::readOptions()
+{
+ if (mOptions != 0) {
+ if (m_numPlayers > 1) {
+ m_game.setBettingLimits(mOptions->getMinBet(), mOptions->getMaxBet());
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++)
+ m_game.getActivePlayer(i)->setBetDefaults(m_game.getMinBet(),
+ m_game.getMaxBet()); // inform players how much they may bet
+ }
+ drawDelay = mOptions->getDrawDelay();
+ // kdDebug() << cashPerRound << endl;
+ // cashPerRound = mOptions->getCashPerRound(); // NOT(!) configurable
+ delete mOptions;
+ mOptions = 0;
+ }
+}
+
+
+bool kpok::loadGame()
+{
+ kapp->config()->setGroup("Save");
+ return loadGame(kapp->config());
+}
+
+
+bool kpok::loadGame(KConfig* conf)
+{
+ int numPlayers = DEFAULT_PLAYERS;
+
+ // conf->setGroup("Save");
+ numPlayers = conf->readNumEntry("players", -1);
+
+ if (numPlayers > 0) {
+ for (int i = 0; i < numPlayers; i++) {
+ QString buf = conf->readEntry(QString("Name_%1").arg(i),
+ "Player");
+ m_players[i].setName(buf);
+ bool human = conf->readBoolEntry(QString("Human_%1").arg(i),
+ false);
+ if (human)
+ m_players[i].setHuman(); // i == 0
+ int cash = conf->readNumEntry(QString("Cash_%1").arg(i),
+ START_MONEY);
+ m_players[i].setCash(cash);
+ m_game.setDirty();
+ }
+ initPoker(numPlayers);
+
+ // after initPoker because initPoker does a default initialization
+ // of lastHandText
+ conf->setGroup("Save");
+ lastHandText = conf->readEntry("lastHandText", "");
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// These slots are called from keyboard shortcuts ('1'..'5')
+
+void kpok::exchangeCard1() { playerBox[0]->cardClicked(1); }
+void kpok::exchangeCard2() { playerBox[0]->cardClicked(2); }
+void kpok::exchangeCard3() { playerBox[0]->cardClicked(3); }
+void kpok::exchangeCard4() { playerBox[0]->cardClicked(4); }
+void kpok::exchangeCard5() { playerBox[0]->cardClicked(5); }
+
+
+// This slot is called when the user wants to change some aspect of
+// the card deck (front or back).
+//
+// FIXME: Maybe the slot should be moved to top.cpp instead and simply
+// call a setDeck() or setBack() method in kpok.
+
+void kpok::slotCardDeck()
+{
+ kapp->config()->setGroup("General");
+ QString deckPath = kapp->config()->readPathEntry("DeckPath", 0);
+ QString cardPath = kapp->config()->readPathEntry("CardPath", 0);
+ bool randomDeck, randomCardDir;
+
+ // Show the "Select Card Deck" dialog and load the images for the
+ // selected deck, if any.
+ if (KCardDialog::getCardDeck(deckPath, cardPath, this, KCardDialog::Both,
+ &randomDeck, &randomCardDir)
+ == QDialog::Accepted) {
+
+ // Load backside and front images.
+ if (playerBox && m_blinking && (m_blinkStat == 0))
+ bTimerEvent();
+
+ cardImages->loadDeck(deckPath);
+ cardImages->loadCards(cardPath);
+
+ for (int i = 0; i < m_game.getNumActivePlayers(); i++) {
+ playerBox[i]->repaintCard();
+ }
+
+ // Save selected stuff in the configuration.
+ kapp->config()->writePathEntry("DeckPath", deckPath);
+ kapp->config()->writeEntry("RandomDeck", randomDeck);
+ kapp->config()->writePathEntry("CardPath", cardPath);
+ kapp->config()->writeEntry("RandomCardDir", randomCardDir);
+ }
+}
+
+
+#include "kpoker.moc"
diff --git a/kpoker/kpoker.desktop b/kpoker/kpoker.desktop
new file mode 100644
index 00000000..000f2aca
--- /dev/null
+++ b/kpoker/kpoker.desktop
@@ -0,0 +1,75 @@
+[Desktop Entry]
+Name=KPoker
+Name[af]=Kpoker
+Name[be]=Покер
+Name[bn]=কে-পোকার
+Name[ca]=Pòquer
+Name[eo]=Pokero
+Name[hi]=के-पोकर
+Name[is]=Póker
+Name[ne]=केडीई पोकर
+Name[pa]=ਕੇ-ਪੋਕਰ
+Name[pl]=Poker
+Name[sv]=Kpoker
+Name[ta]=Kபோக்கர்
+Name[tg]=KПокер
+Name[th]=โป๊กเกอร์ - K
+Name[tr]=Poker
+Name[uk]=Покер
+Name[zh_TW]=KPoker 紙牌遊戲
+Exec=kpoker %i %m -caption "%c"
+Icon=kpoker
+DocPath=kpoker/index.html
+GenericName=Poker Card Game
+GenericName[be]=Картачная гульня ў покер
+GenericName[bg]=Покер
+GenericName[bn]=পোকার নামের তাস খেলা
+GenericName[bs]=Igra pokera
+GenericName[ca]=Joc de Pòquer
+GenericName[cs]=Karetní hra poker
+GenericName[cy]=Gêm Cerdiau Poker
+GenericName[da]=Poker kortspil
+GenericName[de]=Poker Kartenspiel
+GenericName[el]=Παιχνίδι καρτών Poker
+GenericName[eo]=Pokera Kartludo
+GenericName[es]=Juego de cartas de Poker
+GenericName[et]=Pokker
+GenericName[eu]=Poker jokoa
+GenericName[fa]=بازی Poker Card
+GenericName[fi]=Pokeri-korttipeli
+GenericName[fr]=Jeu de Poker
+GenericName[he]=משחק פוקר
+GenericName[hr]=Kartaška igra Pokera
+GenericName[hu]=Póker
+GenericName[is]=Pókerspil
+GenericName[it]=Gioco del Poker
+GenericName[ja]=ポーカーゲーム
+GenericName[km]=ល្បែង​បៀផែ
+GenericName[ko]=카드 놀이
+GenericName[lt]=Pokeris (kortų žaidimas)
+GenericName[lv]=Pokera spēle
+GenericName[mk]=Играта покер
+GenericName[nb]=Kortspillet poker
+GenericName[nds]=Pokern
+GenericName[ne]=पोकर कार्ड खेल
+GenericName[nl]=Poker-kaartspel
+GenericName[nn]=Kortspelet poker
+GenericName[pa]=ਪੋਕਰ ਤਾਸ਼ ਖੇਡ
+GenericName[pl]=Poker
+GenericName[pt]=Jogo de Cartas de Póquer
+GenericName[pt_BR]=Jogo de Poker
+GenericName[ru]=Покер
+GenericName[se]=Goartaspeallu poker
+GenericName[sk]=Kartová hra Poker
+GenericName[sl]=Igra s kartami pokra
+GenericName[sr]=Покер, игра са картама
+GenericName[sr@Latn]=Poker, igra sa kartama
+GenericName[sv]=Pokerkortspel
+GenericName[ta]=போக்கர் அட்டை விளையாட்டு
+GenericName[uk]=Карти - гра в покер
+GenericName[zh_TW]=紙牌遊戲
+Terminal=false
+Type=Application
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Game;CardGame;
diff --git a/kpoker/kpoker.h b/kpoker/kpoker.h
new file mode 100644
index 00000000..21a41ebc
--- /dev/null
+++ b/kpoker/kpoker.h
@@ -0,0 +1,364 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef KPOKER_H
+#define KPOKER_H
+
+
+// QT includes
+#include <qwidget.h>
+#include <qptrlist.h>
+
+// KDE includes
+#include <krandomsequence.h>
+
+// own includes
+#include "poker.h"
+
+
+// QT classes
+class QPushButton;
+class QLineEdit;
+class QLabel;
+class QFrame;
+class QLineEdit;
+class QFrame;
+class QHBoxLayout;
+class QVBoxLayout;
+
+// KDE classes
+class KConfig;
+
+
+// own classes
+class BetBox;
+class CardWidget;
+class OptionsDlg;
+class NewGameDlg;
+class PokerPlayer;
+class PlayerBox;
+
+
+// ================================================================
+// Poker Game
+
+
+enum PokerGameType {
+ SinglePlayer,
+ MultiPlayer
+};
+
+
+enum PokerGameState {
+ StateStartRound=0, // Before dealing. Deal cards to switch state.
+
+ StateBet1,
+ StateRaise1,
+
+ StateExchangeCards,
+
+ StateBet2,
+ StateRaise2,
+
+ StateSee
+};
+
+
+// A PokerGame would be the main class in any poker game. It controls
+// the game flow and has control over all the players.
+//
+// FIXME: This is very much in flux right now. It is in the process
+// of being separated from class kpok. A lot of things need to
+// be done. Among them are:
+// - Finish separation from kpok.
+
+class PokerGame {
+public:
+ PokerGame(KRandomSequence *random);
+ ~PokerGame();
+
+ PokerGameType getType() const { return m_type; }
+ void setType(PokerGameType type) { m_type = type; }
+
+ // The state of the current round.
+ PokerGameState getState() const { return m_state; }
+ void setState(PokerGameState state) { m_state = state; }
+
+ // Money in the game.
+ void clearPot() { m_pot = 0; }
+ int getPot() const { return m_pot; }
+ void bet(int amount) { m_pot += amount; }
+ void bet(PokerPlayer * player, int amount);
+
+ int getMinBet() const { return m_minBet; }
+ int getMaxBet() const { return m_maxBet; }
+ void setBettingLimits(int minBet, int maxBet)
+ { m_minBet = minBet; m_maxBet = maxBet; }
+
+ // Players
+ int getNumPlayers() const { return m_numPlayers; }
+ int getNumActivePlayers() const { return m_activePlayers.count(); }
+ int getNumInactivePlayers() const { return m_removedPlayers.count(); }
+ PokerPlayer * getActivePlayer(unsigned int nr) { return m_activePlayers.at(nr); }
+ void activatePlayer(PokerPlayer *player);
+ void inactivatePlayer(PokerPlayer *player);
+ bool isActivePlayer(PokerPlayer *player) const { return m_activePlayers.contains(player); }
+
+ // Misc
+ // FIXME: clearDirty should only be called by a save method
+ // The isDirty flag should only be set internally.
+ void setDirty() { m_isDirty = true; }
+ void clearDirty() { m_isDirty = false; }
+ bool isDirty() const { return m_isDirty; }
+
+ // Some more complex methods. FIXME: These must be expanded!
+ void newGame(PokerGameType type,
+ int numPlayers, PokerPlayer *players,
+ int minBet, int MaxBet);
+ void newRound();
+
+ void dealCards(PokerPlayer *player, bool skip[]);
+
+
+ private:
+
+ // ----------------------------------------------------------------
+ // Properties of the entire game, not just one round:
+
+ PokerGameType m_type; // The current type of game
+ unsigned int m_numPlayers; // Used for constructing and deleting only
+ PokerPlayer *m_players; // The players (owned by kpok)
+
+ int m_minBet; // the money the player will bet if he wants or not
+ int m_maxBet; // max total bet including minBet.
+
+ // True if we need to save before exiting.
+ // This is the case if the cash has changed for any of the players.
+ bool m_isDirty;
+
+ // ----------------------------------------------------------------
+ // Properties of the current round:
+
+ PokerGameState m_state; // The current phase of the game round
+ CardDeck m_deck; // The card deck we are using
+ int m_pot; // The amount of money people have bet.
+
+ // The players in the game.
+ QPtrList<PokerPlayer> m_activePlayers; // players still in the round
+ QPtrList<PokerPlayer> m_removedPlayers; // players out of this round
+};
+
+
+// ================================================================
+// Poker Game View
+
+
+class kpok : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ kpok(QWidget * parent = 0, const char *name = 0);
+ virtual ~kpok();
+
+ QString getName (int playerNr);
+ void paintCash();
+
+ bool isDirty() const { return m_game.isDirty(); }
+
+ void setBlinking(bool bl) { m_blinking = bl; }
+ void setAdjust(bool ad);
+ void setSound(bool s);
+
+ void updateLHLabel();//temporary function, only called once
+
+ bool getSound() const { return sound; }
+ bool getBlinking() const { return m_blinking; }
+ bool getAdjust() const { return adjust; }
+
+ signals:
+ void changeLastHand(const QString &newHand, bool lastHand = true);
+ void showClickToHold(bool show);
+ void statusBarMessage(QString);
+ void clearStatusBar();
+
+ protected:
+ void initWindow(); // called only once
+ void readOptions();
+ void drawCards(PokerPlayer* p, bool skip[]);
+ void newRound();
+ void noMoney();
+ void paintEvent( QPaintEvent * );
+ void playSound(const QString &filename);
+ void setBetButtonEnabled(bool enabled);
+ void setHand(const QString& newHand, bool lastHand = true);
+ void setLastWinner(const QString& lastWinner);
+ void startBlinking();
+ void stopBlinking();
+ void stopDrawing();
+ void result();
+ void winner();
+
+ void bet();
+
+ void displayWin(const QString& hand, int cashWon);
+
+ /**
+ * Displays the winner, adds the pot to his money
+ *
+ * othersPassed = true means all the other players didn't bet
+ **/
+ void displayWinner_Computer(PokerPlayer* winner, bool othersPassed);
+
+ void removePlayerFromRound(PokerPlayer* removePlayer);
+ void switchToOnePlayerRules();
+
+ /**
+ * @return The human player if he is in the game
+ **/
+ PokerPlayer* findHumanPlayer();
+
+ /**
+ * This method first reads the config file then starts a
+ * newGame Dialog if it wasn't forbidden in config
+ *
+ * After all options and defaults were set the method starts
+ * @ref initPoker() with only the number of the players as an
+ * argument or with a complete player class, depending on the
+ * options the player chose @return True if successful false
+ * if player clicked 'cancel' in the new game dialog
+ **/
+ bool readEntriesAndInitPoker();
+
+ /**
+ * This should only be done in the see phase and shows the
+ * cards of the computer players
+ **/
+ void showComputerCards();
+
+ /**
+ * The main method for starting the game
+ *
+ * It constructs the players if only the number of players
+ * are given or uses an existing array Then all player boxes
+ * are being constructed as well as some smaller things like
+ * the pot
+ * @param players the number of the players
+ * @param ownAllPlayers This is used if there is already an array of players existing e.g. from @ref readEntriesAndInitPoker()
+ **/
+ void initPoker(unsigned int numPlayers);
+
+ /**
+ * Gives all players the deck as a card
+ **/
+ void drawAllDecks();
+
+
+ public slots:
+ void slotCardDeck();
+ void toggleSound();
+ void toggleAdjust();
+ void toggleBlinking();
+ void slotPreferences();
+
+ bool initSound();
+
+ /**
+ * Just as the name says: This method/slot saves the current
+ * game (to the config file)
+ *
+ * The game can be loaded on startup by activating the button
+ * 'read from config'
+ **/
+ void saveGame(KConfig* conf);
+
+ bool loadGame(KConfig* conf);
+ bool loadGame();
+ // void commandCallback(int id);
+ void newGame();
+ void saveGame();
+
+ void exchangeCard1();
+ void exchangeCard2();
+ void exchangeCard3();
+ void exchangeCard4();
+ void exchangeCard5();
+ void drawClick();
+
+ protected slots:
+ void bTimerEvent();
+ void drawCardsEvent();
+ void waveTimerEvent();
+
+ void betChange(int);
+ void adjustBet();
+ void out();
+
+ void startWave();
+ void stopWave();
+ void toggleHeld(); // play a sound
+
+ private:
+ // The "document" - the game itself
+ PokerGame m_game; // The game that this widget is showing.
+ unsigned int m_numPlayers;
+ PokerPlayer *m_players; // The players
+
+ int cashPerRound; // single player game: the ante
+ int currentMustBet; // the minimum bet amount
+ int oldBet_raise; // used for raising only
+
+ int drawDelay;
+
+ // Graphical layout.
+ QVBoxLayout *topLayout;
+ QHBoxLayout *inputLayout;
+ QLabel *potLabel;
+ BetBox *betBox;
+ QPushButton *drawButton; // the main Button
+ QLabel *wonLabel; // the winner
+ QLabel *clickToHold;
+ QWidget *mWonWidget;
+
+ PlayerBox **playerBox; //one box per player
+
+ // Dialogs
+ OptionsDlg* mOptions;
+
+ // Other stuff
+ KRandomSequence m_random;
+
+ QTimer *blinkTimer; // the winning cards will blink
+ QTimer *drawTimer; // delay between drawing of the cards
+ QTimer *waveTimer; // for displaying of the win (if winner == human)
+
+ bool adjust; // allow user to adjust the bet.
+ int drawStat; // status of drawing (which card already was drawn etc.
+
+ bool sound;
+
+ bool m_blinking; // True if card should blink when winning.
+ int m_blinkStat; // status of blinking
+ int m_blinkingBox; // box of winning player
+
+ bool waveActive;
+ int fCount;
+
+ QString lastHandText;
+};
+
+#endif
diff --git a/kpoker/kpokerui.rc b/kpoker/kpokerui.rc
new file mode 100644
index 00000000..3ad1ddcb
--- /dev/null
+++ b/kpoker/kpokerui.rc
@@ -0,0 +1,30 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kpoker" version="2">
+
+<MenuBar>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Separator append="show_merge"/>
+ <Action name="options_sound" append="show_merge"/>
+ <Action name="options_blinking" append="show_merge"/>
+ <Action name="options_adjust" append="show_merge"/>
+ </Menu>
+</MenuBar>
+
+<Menu name="popup">
+ <Action name="options_show_menubar"/>
+ <Action name="options_show_statusbar"/>
+ <Separator/>
+ <Action name="options_sound"/>
+ <Action name="options_blinking"/>
+ <Action name="options_adjust"/>
+ <Action name="options_save_options"/>
+ <Separator/>
+ <Action name="options_configure_carddeck"/>
+ <Action name="options_configure"/>
+ <Separator/>
+ <Action name="game_new"/>
+ <Separator/>
+ <Action name="game_quit"/>
+</Menu>
+
+</kpartgui>
diff --git a/kpoker/main.cpp b/kpoker/main.cpp
new file mode 100644
index 00000000..b4a27509
--- /dev/null
+++ b/kpoker/main.cpp
@@ -0,0 +1,54 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+
+#include "version.h"
+#include "top.h"
+
+static const char description[] = I18N_NOOP("KDE Poker Game");
+
+int main( int argc, char *argv[] )
+{
+ KAboutData aboutData("kpoker", I18N_NOOP("KPoker"),
+ KPOKER_VERSION, description, KAboutData::License_GPL,
+ "(c) 1997-2003 Jochen Tuchbreiter, Andreas Beckermann\n"
+ "(c) 2004 Jochen Tuchbreiter, Andreas Beckermann, Inge Wallin",
+ I18N_NOOP("For a full list of credits see helpfile\nAny suggestions, bug reports etc. are welcome"));
+
+ aboutData.addAuthor("Inge Wallin",
+ I18N_NOOP("Code for poker rules"), "inge@lysator.liu.se");
+ aboutData.addAuthor("Andreas Beckermann",
+ I18N_NOOP("Current maintainer"), "b_mann@gmx.de");
+ aboutData.addAuthor("Jochen Tuchbreiter",
+ I18N_NOOP("Original author"), "whynot@mabi.de");
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ KApplication myApp;
+ KGlobal::locale()->insertCatalogue("libkdegames");
+
+ if (myApp.isRestored())
+ RESTORE(PokerWindow)
+ else {
+ PokerWindow *MainScreen = new PokerWindow;
+ myApp.setMainWidget( MainScreen );
+ MainScreen->show();
+ }
+ return myApp.exec();
+}
diff --git a/kpoker/newgamedlg.cpp b/kpoker/newgamedlg.cpp
new file mode 100644
index 00000000..002833b6
--- /dev/null
+++ b/kpoker/newgamedlg.cpp
@@ -0,0 +1,204 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+// QT includes
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+
+// KDE includes
+#include <klocale.h>
+#include <knuminput.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <knumvalidator.h>
+
+// own includes
+#include "defines.h"
+#include "newgamedlg.h"
+
+
+NewGameDlg::NewGameDlg(QWidget* parent)
+ : KDialogBase(Plain, i18n("New Game"),
+ Ok|Cancel, Ok, parent, 0, true, true)
+{
+ QVBoxLayout *topLayout = new QVBoxLayout(plainPage(), spacingHint());
+ QHBoxLayout *l = new QHBoxLayout(topLayout);
+
+ KConfig* conf = kapp->config();
+ conf->setGroup("NewGameDlg");
+ bool showNewGameDlg = conf->readBoolEntry("showNewGameDlgOnStartup",
+ SHOWNEWGAME_DEFAULT);
+ bool readConfig = conf->readBoolEntry("readFromConfig",
+ LOADGAME_DEFAULT);
+ int playerNr = conf->readNumEntry("players", DEFAULT_PLAYERS);
+ int money = conf->readNumEntry("startMoney", START_MONEY);
+
+ readFromConfig = new QCheckBox(i18n("Try loading a game"), plainPage());
+ readFromConfig->adjustSize();
+ readFromConfig->setChecked(readConfig);
+ l->addWidget(readFromConfig);
+
+ readFromConfigLabel = new QLabel(i18n("The following values are used if loading from config fails"), plainPage());
+ if (!readFromConfig->isChecked())
+ readFromConfigLabel->hide();
+ readFromConfigLabel->adjustSize();
+ l->addWidget(readFromConfigLabel);
+ connect(readFromConfig, SIGNAL(toggled(bool)),
+ this, SLOT(changeReadFromConfig(bool)));
+
+ players = new KIntNumInput(playerNr, plainPage());
+ players->setRange(1, MAX_PLAYERS);
+ players->setLabel(i18n("How many players do you want?"));
+ topLayout->addWidget(players);
+
+ l = new QHBoxLayout(topLayout);
+ l->addWidget(new QLabel(i18n("Your name:"), plainPage()));
+ player1Name = new QLineEdit(plainPage());
+ l->addWidget(player1Name);
+
+ l = new QHBoxLayout(topLayout);
+ l->addWidget(new QLabel(i18n("Players' starting money:"), plainPage()));
+ moneyOfPlayers = new QLineEdit(QString("%1").arg(money), plainPage());
+ moneyOfPlayers->setValidator( new KIntValidator( 0,999999,moneyOfPlayers ) );
+
+ l->addWidget(moneyOfPlayers);
+
+ l = new QHBoxLayout(topLayout);
+ l->addWidget(new QLabel(i18n("The names of your opponents:"), plainPage()));
+ computerNames = new QComboBox(true, plainPage());
+ computerNames->setInsertionPolicy(QComboBox::AtCurrent);
+ l->addWidget(computerNames);
+
+ l = new QHBoxLayout(topLayout);
+ l->addWidget(new QLabel(i18n("Show this dialog every time on startup"),
+ plainPage()));
+ showDialogOnStartup = new QCheckBox(plainPage());
+ showDialogOnStartup->setChecked(showNewGameDlg);
+ l->addWidget(showDialogOnStartup);
+
+ setPlayerNames();
+}
+
+
+NewGameDlg::~NewGameDlg()
+{
+ if (result() == Accepted) {
+ KConfig* conf = kapp->config();
+ conf->setGroup("NewGameDlg"); // defaults for the newGameDlg only
+ conf->writeEntry("showNewGameDlgOnStartup", showOnStartup());
+ conf->writeEntry("readFromConfig", readFromConfigFile()); // just a default!
+ conf->writeEntry("players", getPlayers());
+ conf->writeEntry("startMoney", money());
+ }
+
+ //delete the visible elements:
+ delete readFromConfigLabel;
+ delete readFromConfig;
+ delete players;
+ delete moneyOfPlayers;
+ delete showDialogOnStartup;
+ delete player1Name;
+ delete computerNames;
+
+}
+
+
+void NewGameDlg::setPlayerNames(int no, QString playerName)
+{
+ if (no < 0) {
+ kapp->config()->setGroup("Save");
+ player1Name->setText(kapp->config()->readEntry("Name_0", i18n("You")));
+ computerNames->clear();
+ for (int i = 1; i < MAX_PLAYERS; i++) {
+ computerNames->insertItem(kapp->config()->readEntry(QString("Name_%1").arg(i), i18n("Computer %1").arg(i)));
+ }
+ } else if (no == 0) {
+ player1Name->setText(playerName);
+ } else {
+ if (computerNames->count() > no)
+ computerNames->insertItem(playerName, no-1);
+ else
+ computerNames->changeItem(playerName, no-1);
+ }
+}
+
+
+void NewGameDlg::changeReadFromConfig(bool show)
+{
+ if (show)
+ readFromConfigLabel->show();
+ else
+ readFromConfigLabel->hide();
+}
+
+
+bool NewGameDlg::showOnStartup()
+{
+ return showDialogOnStartup->isChecked();
+}
+
+
+int NewGameDlg::getPlayers()
+{
+ return players->value();
+}
+
+
+bool NewGameDlg::readFromConfigFile()
+{
+ return readFromConfig->isChecked();
+}
+
+
+int NewGameDlg::money()
+{
+ bool ok = true;
+ int money = moneyOfPlayers->text().toInt(&ok);
+ if (ok)
+ return money;
+ else
+ return START_MONEY;
+}
+
+
+QString NewGameDlg::name(int nr)
+{
+ if (computerNames->currentText() != computerNames->text(computerNames->currentItem()))
+ computerNames->changeItem(computerNames->currentText(), computerNames->currentItem());
+
+ if (nr == 0)
+ return player1Name->text();
+
+ if (nr <= computerNames->count())
+ return computerNames->text(nr-1);
+
+ return i18n("Player");
+}
+
+
+void NewGameDlg::hideReadingFromConfig()
+{
+ readFromConfig->hide();
+ readFromConfigLabel->hide();
+ readFromConfig->setChecked(false);
+}
+
+
+#include "newgamedlg.moc"
diff --git a/kpoker/newgamedlg.h b/kpoker/newgamedlg.h
new file mode 100644
index 00000000..5588f0aa
--- /dev/null
+++ b/kpoker/newgamedlg.h
@@ -0,0 +1,104 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef NEWGAMEDLG_H
+#define NEWGAMEDLG_H
+
+
+#include <kdialogbase.h>
+
+
+class KIntNumInput;
+
+class QLineEdit;
+class QCheckBox;
+class QLabel;
+class QComboBox;
+
+
+/**
+ * This dialog is shown on startup or when a new game is started
+ *
+ * Here you can set some options like the default money, players, the names and so on
+ * @short The dialog shown on startup or when a new game is started
+ **/
+class NewGameDlg : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ NewGameDlg(QWidget* parent = 0);
+ ~NewGameDlg();
+
+ /**
+ * @return The player number the user has set
+ **/
+ int getPlayers();
+
+ /**
+ * @return True if the user wants to read options from the config file false if not
+ **/
+ bool readFromConfigFile();
+
+ /**
+ * You can write the return into a config file which choses to start this dialog on startup
+ * @return True if the user wants this dialog to be shown on startup
+ **/
+ bool showOnStartup();
+
+ /**
+ * @return The start money of all players
+ **/
+ int money();
+
+ /**
+ * @param nr The number of the player
+ * @return The name of the player specified in nr
+ **/
+ QString name(int nr);
+
+ /**
+ * This method hides the button where the user can choose to read values from config file
+ *
+ * It is used when a new game is started - you can load with config file on startup only
+ **/
+ void hideReadingFromConfig();
+
+ void setPlayerNames(int no = -1, QString playerName = 0);
+
+
+ protected slots:
+ /**
+ * This slot hides the readFromConfigLabel when the user does not want to read from config or shows it if the user does
+ *
+ * The label warns that the other values are used as default values if reading from config fails
+ **/
+ void changeReadFromConfig( bool );
+
+
+ private:
+ QLabel *readFromConfigLabel;
+ QCheckBox *readFromConfig;
+ KIntNumInput *players;
+ QLineEdit *moneyOfPlayers;
+ QCheckBox *showDialogOnStartup;
+ QLineEdit *player1Name;
+ QComboBox *computerNames;
+};
+
+
+#endif
diff --git a/kpoker/optionsdlg.cpp b/kpoker/optionsdlg.cpp
new file mode 100644
index 00000000..e009c3d2
--- /dev/null
+++ b/kpoker/optionsdlg.cpp
@@ -0,0 +1,119 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+// QT includes
+#include <qlabel.h>
+#include <qlayout.h>
+
+// KDE includes
+#include <klocale.h>
+#include <knuminput.h>
+
+// own includes
+#include "optionsdlg.h"
+#include "defines.h"
+
+
+OptionsDlg::OptionsDlg(QWidget* parent, const char* name, int _players)
+ : KDialogBase(Plain, i18n("Options")/*?*/, Ok|Cancel, Ok,
+ parent, name, true, true)
+{
+ QVBoxLayout* topLayout = new QVBoxLayout(plainPage(), spacingHint());
+ maxBet = 0;
+ minBet = 0;
+
+ if (_players <= 0)
+ players = DEFAULT_PLAYERS;
+ else
+ players = _players;
+
+ topLayout->addWidget(new QLabel(i18n("All changes will be activated in the next round."), plainPage()));
+
+ drawDelay = new KIntNumInput(0, plainPage());
+ drawDelay->setLabel(i18n("Draw delay:"));
+ topLayout->addWidget(drawDelay);
+
+ if (players > 1) {
+ maxBet = new KIntNumInput(0, plainPage());
+ maxBet->setLabel(i18n("Maximal bet:"));
+ topLayout->addWidget(maxBet);
+
+ minBet = new KIntNumInput(0, plainPage());
+ minBet->setLabel(i18n("Minimal bet:"));
+ topLayout->addWidget(minBet);
+ }
+}
+
+
+OptionsDlg::~OptionsDlg()
+{
+}
+
+
+void OptionsDlg::init(int _drawDelay, int _maxBetOrCashPerRound, int _minBet)
+{
+ if (_minBet < 0)
+ defaultMinBet = MIN_BET;
+ if (_maxBetOrCashPerRound < 0 && players > 1)
+ defaultMaxBet = MAX_BET;
+ else if (_maxBetOrCashPerRound < 0)
+ defaultCashPerRound = CASH_PER_ROUND;
+ if (_drawDelay < 0)
+ _drawDelay = DRAWDELAY;
+
+ drawDelay->setValue(_drawDelay);
+ if (maxBet)
+ maxBet->setValue(_maxBetOrCashPerRound);
+ if (minBet && players > 1)
+ minBet->setValue(_minBet);
+}
+
+
+int OptionsDlg::getMaxBet()
+{
+ if (!maxBet || players <= 1)
+ return defaultMaxBet;
+
+ return maxBet->value();
+}
+
+
+int OptionsDlg::getMinBet()
+{
+ if (!minBet || players <= 1)
+ return defaultMinBet;
+
+ return minBet->value();
+}
+
+
+int OptionsDlg::getCashPerRound()
+{
+ if (!maxBet || players > 1)
+ return defaultCashPerRound;
+
+ return maxBet->value();
+}
+
+
+int OptionsDlg::getDrawDelay()
+{
+ return drawDelay->value();
+}
+
+
+#include "optionsdlg.moc"
diff --git a/kpoker/optionsdlg.h b/kpoker/optionsdlg.h
new file mode 100644
index 00000000..c1573133
--- /dev/null
+++ b/kpoker/optionsdlg.h
@@ -0,0 +1,68 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef OPTIONSDLG_H
+#define OPTIONSDLG_H
+
+#include <kdialogbase.h>
+
+
+class QLineEdit;
+class QCheckBox;
+class QLabel;
+class QComboBox;
+
+class KIntNumInput;
+
+
+/**
+ * This dialog is will set some options which mostly become active when a new
+ * round is started
+ *
+ * Here you can set some options like the maxBet, maybe names and so on
+ * @short The options dialog
+ **/
+class OptionsDlg : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ OptionsDlg(QWidget* parent = 0, const char* name = 0, int _players = 1);
+ ~OptionsDlg();
+
+ void init(int _drawDelay, int _maxBetOrCashPerRound, int minBet = -1);
+ int getMaxBet();
+ int getMinBet();
+ int getCashPerRound();
+ int getDrawDelay();
+
+ private:
+ int players;
+ int defaultMaxBet;
+ int defaultMinBet;
+ int defaultCashPerRound;
+ int defaultDrawDelay;
+ // QLineEdit* maxBet;
+ // QLineEdit* minBet;
+ // QLineEdit* drawDelay;
+ KIntNumInput* maxBet;
+ KIntNumInput* minBet;
+ KIntNumInput* drawDelay;
+};
+
+
+#endif
diff --git a/kpoker/player.cpp b/kpoker/player.cpp
new file mode 100644
index 00000000..9fb4e5d8
--- /dev/null
+++ b/kpoker/player.cpp
@@ -0,0 +1,292 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "player.h"
+#include "defines.h"
+
+
+// ================================================================
+// class Player
+
+
+PokerPlayer::PokerPlayer()
+ : m_hand()
+{
+ m_name = "Player";
+ m_isHuman = false;
+
+ m_money = START_MONEY;
+ currentBet = 0;
+
+ isOut = false;
+ // random.setSeed(0);
+}
+
+
+PokerPlayer::~PokerPlayer()
+{
+}
+
+
+// ----------------------------------------------------------------
+
+
+void PokerPlayer::giveCardsBack()
+{
+ m_hand.clear();
+}
+
+
+void PokerPlayer::giveCardBack(int cardNr)
+{
+ m_hand.clear(cardNr);
+}
+
+
+/* Set skip[i] to true if the corresponding card should *not* be
+ * exchanged.
+ */
+
+void PokerPlayer::exchangeCards(bool skip[])
+{
+ //TODO: improve!
+ // this is still a VERY simple method!
+
+ m_hand.analyze();
+ for (int i = 0; i < PokerHandSize; i++) {
+ skip[i] = m_hand.getFoundCard(i);
+ }
+}
+
+
+/* Prepare the player for a new round.
+ */
+
+void PokerPlayer::newRound()
+{
+ giveCardsBack();
+
+ currentBet = 0;
+ isOut = false;
+}
+
+
+int PokerPlayer::bet(int origBet, bool mayRaise)
+{
+ // NOT useable for (status == continueBet) !!!
+ // needs a rewrite for games with > 2 players
+ int bet = origBet;
+
+ // first bet minBet
+ currentBet = minBet;
+ m_money -= currentBet;
+ bet -= currentBet;
+ int newBet = bet; // bet at least the old bet
+
+ if (bet > getCash())// we don't have the money :-(
+ return 0;
+
+ // calculate the chances and bet any value
+ int chance = sortedResult();
+
+ if (chance < 350) { // 3 of a kind or better!!
+ newBet = maxBet - (int)random.getLong(maxBet /2);//we subtract a
+ // random number to hide our cards (every player would
+ // know we have good cards if we would bet maxBet)
+ }
+ else if (chance < 400) { // 2 pairs
+ newBet = bet + (int)random.getLong(maxBet /2 + origBet);
+ if (newBet > maxBet)
+ newBet = maxBet;
+ }
+ else if (chance < 500) { // one pair
+ newBet = bet + (int)random.getLong(maxBet /4 + 1);
+ if (newBet > getCash() - 2 * minBet)
+ newBet = bet;
+ if (bet >= getCash() /3)
+ newBet = 0;
+ }
+ else if (chance < 506) { // best card is at least a ten
+ newBet = bet;
+ if (bet >= getCash() /3)
+ newBet = 0;
+ }
+ else { // bad cards
+ if (getCash() - bet >= bet) {// we would still have some money
+ newBet = bet;
+ if (bet >= getCash() /4)
+ newBet = 0;
+ }
+ else
+ newBet = 0;
+ }
+
+ // and now a final re-check
+ if (newBet > bet) {
+ if (random.getLong(20) == 0)
+ newBet = bet;
+ else if (random.getLong(30) <= 1)
+ newBet = bet + (newBet - bet) /2;
+ }
+
+ if (newBet > getCash())
+ newBet = bet; // maybe raise only a little bit but by now just do not raise
+
+ if (!mayRaise && newBet > bet)
+ newBet = bet;
+
+ if (!changeBet(newBet))
+ return 0; // BIG error
+
+ return currentBet;
+}
+
+
+int PokerPlayer::raise(int origRaise)
+{
+ // NOT useable for (status == continueRaise) !!!
+ // needs a rewrite for games with > 2 players
+ int raise = origRaise - getCurrentBet();
+ int newRaise = raise;
+
+ if (newRaise > getCash())// we don't have the money :-(
+ return 0;
+
+ // Calculate the chances and bet any value.
+ int chance = sortedResult();
+
+ if (chance < 350) { // 3 of a kind or better!!
+ newRaise = maxBet - (int)random.getLong(maxBet - maxBet /2);
+ // we subtract a random number to hide our cards
+ // (every player would know we have good cards if
+ // we would bet maxBet)
+ }
+ else if (chance < 400) { // 2 pairs
+ newRaise = raise + (int)random.getLong(maxBet /2 + origRaise + 10);
+ if (newRaise > maxBet)
+ newRaise = maxBet;
+ }
+ else if (chance < 500) { // one pair
+ newRaise = raise + (int)random.getLong(maxBet /4 + 1);
+ if (newRaise > getCash() - 2 * minBet)
+ newRaise = raise;
+ if (raise >= getCash() /2)
+ newRaise = 0;
+ }
+ else if (chance < 506) { // best card is at least a ten
+ newRaise = raise;
+ if (raise >= getCash() /2)
+ newRaise = 0;
+ }
+ else { // bad cards
+ if (getCash() - raise >= raise && raise <= minBet * 2) { // we would still have some money
+ if (raise > getCash() /2)
+ newRaise = 0;
+ else
+ newRaise = raise;
+ }
+ else
+ newRaise = 0;
+ }
+
+ // And now a final re-check.
+ if (newRaise > raise) {
+ if (random.getLong(20) == 0)
+ newRaise = raise;
+ else if (random.getLong(30) <= 1)
+ newRaise = raise + (newRaise - raise) /2;
+ }
+
+ if (newRaise > getCash())
+ newRaise = raise; // maybe raise only a little bit but by now just do not raise
+
+ if (!changeBet(newRaise))
+ return 0; // BIG error
+
+ return currentBet;
+}
+
+
+bool PokerPlayer::changeBet(int betChange)
+{
+ if (currentBet + betChange >= 0 && getCash() - betChange >= 0) {
+ setCash(getCash() - betChange);
+ currentBet += betChange;
+ return true;
+ }
+ return false;
+}
+
+
+int PokerPlayer::sortedResult()
+{
+ PokerHandType result = m_hand.analyze();
+
+ //Ok, the result produced by testHand() is a little bit... uncomfortable
+ //so lets sort it for use in displayWinner_Computer()
+ //additionally we extend the values e.g. by bestCard and so on
+
+ int newResult = m_hand.getCardScore();
+
+ // FIXME: Change this so that scores are higher for better hands.
+ // Don't forget to change m_hand.getCardScore() as well.
+ switch (result) {
+ case RoyalFlush:
+ newResult += 0; // the royal flush is the best you can get
+ break;
+ case StraightFlush:
+ newResult += 50; // straight flush
+ break;
+ case FourOfAKind:
+ newResult += 100; // 4 of a kind
+ break;
+ case FullHouse:
+ newResult += 150; // full house
+ break;
+ case Flush:
+ newResult += 200; // flush
+ break;
+ case Straight:
+ newResult += 250; // straight
+ break;
+ case ThreeOfAKind:
+ newResult += 300; // 3 of a kind
+ break;
+ case TwoPairs:
+ newResult += 350; // two pairs
+ break;
+ case Pair:
+ newResult += 400; // one pair
+ break;
+ case HighCard:
+ {
+ CardValue bestCard = m_hand.findNextBest(ROOF, false);
+ newResult = 500 + ((int) H_ACE - (int) bestCard);
+ }
+ break;
+
+ default:
+ // Shouldn't get here.
+ assert(0);
+ }
+
+ return newResult;
+ // The lowest newResult is now the best.
+}
diff --git a/kpoker/player.h b/kpoker/player.h
new file mode 100644
index 00000000..7d3988cf
--- /dev/null
+++ b/kpoker/player.h
@@ -0,0 +1,220 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef PLAYER_H
+#define PLAYER_H
+
+// QT includes
+#include <qstring.h>
+
+// KDE includes
+#include <krandomsequence.h>
+#include <kdebug.h>
+
+// own includes
+#include "poker.h"
+
+
+// ================================================================
+// Player classes
+
+
+class PokerPlayer
+{
+ public:
+ PokerPlayer();
+ ~PokerPlayer();
+
+ /**
+ * Calculates the money which the computer will bet
+ *
+ * use @ref changeBet() for human players
+ * @param bet The minimum bet that the player has to bet. probably the same as the bet the human player has bet before
+ * @param mayRaise Specifies if the player may raise
+ * @return The player's bet
+ **/
+ int bet(int bet, bool mayRaise = true);
+
+ /**
+ * Same as @ref bet() but should bet a little bit more if the cards are good enough (they were already exchanged)
+ **/
+ int raise(int raise);
+
+ /**
+ * This method changes the player's bet by betChange
+ * @param Specifies the change
+ * @return true if successful, false if not
+ **/
+ bool changeBet(int betChange);
+
+ /**
+ * Only used by computer players
+ *
+ * Calculates which cards shall be exchanged
+ * @param skip[] Will be set true if the card shall be exchanged (if the 1st card shall be exchanged so skip[0] will be true)
+ **/
+ void exchangeCards(bool skip[]);
+
+ /**
+ * This method will return all cards to the pile which means that all cards will be set to 0 (=deck)
+ **/
+ void giveCardsBack();
+
+ /**
+ * Returns a card to the pile
+ * @param cardNr specifies the card which will be returned to the pile
+ **/
+ void giveCardBack(int cardNr);
+
+ /**
+ * Begins a new round
+ **/
+ void newRound();
+
+ /**
+ * Sets the player's cash to newCash
+ * @param newCash The new cash
+ **/
+ void setCash(int newCash) { m_money = newCash; }
+
+ /**
+ * This makes the player human
+ **/
+ void setHuman() { m_isHuman = true; }
+
+ /**
+ * Sets a new name
+ * @param newName The new name of the player
+ **/
+ void setName(const QString &newName) { m_name = newName; }
+
+ /**
+ * Informs the player that he is out (or is not out anymore)
+ * @param newOut true if player is out or false if player is back to the game
+ **/
+ void setOut(bool newOut) { isOut = newOut; }
+
+ /**
+ * Takes a card
+ * @param nr The number of the card (0 = first card)
+ * @param value The card itself
+ **/
+ void takeCard(int nr, int value) {
+#if 0
+ const char *suitnames[] = {"C_", "D_", "S_", "H_"};
+ if (value > 0)
+ kdDebug() << "Got card " << suitnames[(value - 1) % 4]
+ << (value - 1) / 4 + 2 << endl;
+#endif
+ m_hand.setCard(nr, (CardValue) value);
+ }
+
+ /**
+ * Informs the player about new rules
+ * @param min The minimum possible bet
+ * @param max The maximum possible bet
+ **/
+ void setBetDefaults(int min, int max) { minBet = min; maxBet = max; }
+
+ /**
+ * @param cardNr The number of the card (0 = first card)
+ * @return The card
+ **/
+ CardValue getCard(int cardNr) const { return m_hand.getCard(cardNr);}
+
+ PokerHand &getHand() { return m_hand; }
+
+ /**
+ * @return The money of the player
+ **/
+ int getCash() const { return m_money; }
+
+ /**
+ * @return How much the player has bet
+ **/
+ int getCurrentBet() const { return currentBet; }
+
+ /**
+ * Returns the found card at nr
+ *
+ * The found cards specify the best cards the player has, e.g. if the player has one pair both cards will be found here
+ * @param nr The number of the wanted foundCard
+ * @return The found card number nr
+ **/
+ bool getFoundCard(int nr) const { return m_hand.getFoundCard(nr); }
+
+ /**
+ * @return If the player is human or not
+ **/
+ bool getHuman() const { return m_isHuman; }
+
+ /**
+ * @return The name of the player
+ **/
+ QString getName() const { return m_name; }
+
+ // FIXME: Rename to hasFolded?
+ /**
+ * @return True if the player is out or false if not
+ **/
+ bool out() { return isOut; }
+
+
+ /**
+ * This test the cards of the player; searches for the result
+ *
+ * Used by @ref sortedResult() and in one player games
+ * @return The result (10 = the best, 0 = nothing)
+ **/
+ PokerHandType testHand() { return m_hand.analyze(); }
+
+
+ protected:
+
+ /**
+ * This sorts the result generated by @ref testHand() a little bit to be used in games with more than one player
+ * @return The points of the hand (a royal flush is e.g. 0, a best card is 500 + the best card)
+ **/
+ int sortedResult();
+
+
+ private:
+ // Basic data:
+ QString m_name; // The name of the player.
+ bool m_isHuman; // True if the player is human.
+
+ // The hand itself
+ PokerHand m_hand;
+
+ // The financial situation
+ int m_money;
+ int currentBet;
+
+ // True if we are out of the game (have folded).
+ bool isOut;
+
+ // Properties of the game.
+ // FIXME: Move this to the game itself.
+ // FIXME: Add a pointer to the poker game object.
+ int minBet;
+ int maxBet;
+
+ // Extra stuff
+ KRandomSequence random;
+};
+
+#endif
diff --git a/kpoker/playerbox.cpp b/kpoker/playerbox.cpp
new file mode 100644
index 00000000..cdfb216c
--- /dev/null
+++ b/kpoker/playerbox.cpp
@@ -0,0 +1,262 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <qtooltip.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qhbox.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "player.h"
+#include "playerbox.h"
+#include "defines.h"
+#include "kpaint.h"
+
+
+PlayerBox::PlayerBox(bool playerOne, QWidget* parent, const char* name)
+ : QGroupBox(parent, name)
+{
+ QHBoxLayout* l = new QHBoxLayout(this, PLAYERBOX_BORDERS,
+ PLAYERBOX_HDISTANCEOFWIDGETS);
+
+ // The card and "held" label arrays.
+ m_cardWidgets = new CardWidget *[PokerHandSize];
+ m_heldLabels = new QLabel *[PokerHandSize];
+
+ QFont myFixedFont;
+ myFixedFont.setPointSize(12);
+
+ // Generate the 5 cards
+ for (int i = 0; i < PokerHandSize; i++) {
+ QVBoxLayout* vl = new QVBoxLayout(0);
+ l->addLayout(vl, 0);
+
+ QHBox* cardBox = new QHBox(this);
+ vl->addWidget(cardBox, 0);
+ cardBox->setFrameStyle(Box | Sunken);
+ m_cardWidgets[i] = new CardWidget(cardBox);
+ cardBox->setFixedSize(cardBox->sizeHint());
+
+ // Only add the "held" labels if this is the first player (the human one).
+ if (playerOne) {
+ QHBox* b = new QHBox(this);
+ m_heldLabels[i] = new QLabel(b);
+ m_heldLabels[i]->setText(i18n("Held"));
+ b->setFrameStyle(Box | Sunken);
+ b->setFixedSize(b->sizeHint());
+ m_cardWidgets[i]->heldLabel = m_heldLabels[i];
+
+ QHBoxLayout* heldLayout = new QHBoxLayout(0);
+ heldLayout->addWidget(b, 0, AlignCenter);
+ vl->insertLayout(0, heldLayout, 0);
+ vl->insertStretch(0, 1);
+ vl->addStretch(1);
+ }
+ }
+
+ // Add the cash and bet labels.
+ {
+ QVBoxLayout* vl = new QVBoxLayout;
+ l->addLayout(vl);
+ vl->addStretch();
+
+ m_cashLabel = new QLabel(this);
+ m_cashLabel->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+ m_cashLabel->setFont(myFixedFont);
+ vl->addWidget(m_cashLabel, 0, AlignHCenter);
+ vl->addStretch();
+
+ m_betLabel = new QLabel(this);
+ m_betLabel->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+ m_betLabel->setFont(myFixedFont);
+ vl->addWidget(m_betLabel, 0, AlignHCenter);
+ vl->addStretch();
+ }
+
+ QToolTip::add(m_cashLabel,
+ i18n("Money of %1").arg("Player"));//change via showName()
+
+ // Assume that we have a multiplayer game.
+ m_singlePlayer = false;
+}
+
+
+PlayerBox::~PlayerBox()
+{
+ delete[] m_cardWidgets;
+ delete[] m_heldLabels;
+}
+
+
+// ----------------------------------------------------------------
+
+
+
+void PlayerBox::resizeEvent(QResizeEvent* e)
+{
+ QGroupBox::resizeEvent(e);
+
+ showCash();
+ showName();
+}
+
+
+void PlayerBox::showCash()
+{
+ // Show the amount of cash the player has.
+ m_cashLabel->setText(i18n("Cash: %1")
+ .arg(KGlobal::locale()->formatMoney(m_player->getCash())));
+
+ // Show how much we have bet during this round.
+ if (m_player->out())
+ m_betLabel->setText(i18n("Out"));
+ else {
+ if (m_singlePlayer)
+ m_betLabel->setText(i18n("Cash per round: %1")
+ .arg(KGlobal::locale()->formatMoney(m_cashPerRound)));
+ else
+ m_betLabel->setText(i18n("Bet: %1")
+ .arg(KGlobal::locale()-> formatMoney(m_player->getCurrentBet())));
+ }
+}
+
+
+// Sshow the name of the player. Suppose that the players name has
+// changed.
+
+void PlayerBox::showName()
+{
+ setTitle(m_player->getName());
+ QToolTip::remove(m_cashLabel);
+ QToolTip::add(m_cashLabel, i18n("Money of %1").arg(m_player->getName()));
+}
+
+
+// Show or unshow all the held labels depending on the 'on' parameter.
+
+void PlayerBox::showHelds(bool on)
+{
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (on)
+ m_cardWidgets[i]->heldLabel->show();
+ else {
+ m_cardWidgets[i]->heldLabel->hide();
+ m_cardWidgets[i]->setHeld(on);
+ }
+ }
+}
+
+
+void PlayerBox::paintCard(int nr)
+{
+ m_cardWidgets[nr]->paintCard(m_player->getCard(nr));
+ m_cardWidgets[nr]->show();
+}
+
+
+// Activate the held labels for this player (human player).
+
+void PlayerBox::activateToggleHeld()
+{
+ for (int i = 0; i < PokerHandSize; i++) {
+ connect(m_cardWidgets[i], SIGNAL(pClicked(CardWidget*)),
+ this, SLOT(cardClicked(CardWidget*)));
+ }
+}
+
+
+void PlayerBox::cardClicked(CardWidget* MyCW)
+{
+ emit toggleHeld();
+ if (m_enableHeldLabels && MyCW->toggleHeld())
+ MyCW->heldLabel->show();
+ else
+ MyCW->heldLabel->hide();
+}
+
+
+void PlayerBox::paintDeck(int nr)
+{
+ m_player->giveCardBack(nr);
+ paintCard(nr);
+}
+
+
+void PlayerBox::blinkOn()
+{
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (m_player->getFoundCard(i))
+ hideCard(i);
+ }
+}
+
+
+void PlayerBox::blinkOff()
+{
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (!m_cardWidgets[i]->isVisible())
+ paintCard(i);
+ }
+}
+
+
+void PlayerBox::setHeldEnabled(bool on)
+{
+ m_enableHeldLabels = on;
+ if (!on) {
+ for (int i = 0; i < PokerHandSize; i++)
+ m_heldLabels[i]->hide();
+ }
+}
+
+
+void PlayerBox::singlePlayerGame(int newCashPerRound)
+{
+ m_singlePlayer = true;
+ m_cashPerRound = newCashPerRound;
+}
+
+
+void PlayerBox::hideCard(int nr)
+{
+ m_cardWidgets[nr]->hide();
+}
+
+
+bool PlayerBox::getHeld(int nr) const
+{
+ return m_cardWidgets[nr]->getHeld();
+}
+
+
+void PlayerBox::cardClicked(int no)
+{
+ cardClicked(m_cardWidgets[no-1]);
+}
+
+
+void PlayerBox::repaintCard()
+{
+ for (int i = 0; i < PokerHandSize; i++)
+ m_cardWidgets[i]->repaintDeck();
+}
+
+
+#include "playerbox.moc"
diff --git a/kpoker/playerbox.h b/kpoker/playerbox.h
new file mode 100644
index 00000000..4d769170
--- /dev/null
+++ b/kpoker/playerbox.h
@@ -0,0 +1,154 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef PLAYERBOX_H
+#define PLAYERBOX_H
+
+
+#include <qgroupbox.h>
+
+
+class QLabel;
+
+
+class PokerPlayer;
+class CardWidget;
+
+
+class PlayerBox : public QGroupBox
+{
+ Q_OBJECT
+
+ public:
+ PlayerBox(bool playerOne, QWidget* parent = 0, const char* name = 0);
+ ~PlayerBox();
+
+ void cardClicked(int no);
+
+ /**
+ * Show the name of the player who owns this box. Use m_player to
+ * get the name.
+ **/
+ void showName();
+
+ /**
+ * Paints the cash
+ **/
+ void showCash(); // and some more
+
+ /**
+ * Sets the player which is used e.g. by @ref showCash()
+ * @param p The guy who owns this box
+ **/
+ void setPlayer(PokerPlayer* p) { m_player = p; }
+
+ /**
+ * Hides the card nr (0 = first card)
+ *
+ * Used to let the cards blink.
+ * @param nr The number of the card which will be hidden
+ **/
+ void hideCard(int nr);
+
+ /**
+ * @param nr The number of the card (where 0 = first card)
+ * @return If the card nr shall be held
+ **/
+ bool getHeld(int nr) const;
+
+ /**
+ * shows all held labels or hides them all
+ * @param on Shows all all labels if true and hides them if false
+ **/
+ void showHelds(bool on);
+
+ /**
+ * Enables the held labels if on is true or disables them
+ * (e.g. after exchange phase) if false
+ * @param e Enables held labels if true, disables if false
+ **/
+ void setHeldEnabled(bool on);
+
+ // FIXME: Combine these two into paintCard(int nr, bool showFront);
+ /**
+ * Paints the card nr
+ * @param nr The number of the card (where 0 = first card)
+ **/
+ void paintCard(int nr);
+
+ /**
+ * Paints the deck
+ * @param nr The number of the card (where 0 = first card)
+ **/
+ void paintDeck(int nr);
+
+ /**
+ * Starts a one player game
+ * @param newCashPerRound The cash that the player has to pay every round
+ **/
+ void singlePlayerGame(int newCashPerRound);
+
+ /**
+ * Activates the held labels for this player (human player)
+ **/
+ void activateToggleHeld();
+
+ /**
+ * Begins blinking of the winning cards
+ **/
+ void blinkOn();
+
+ /**
+ * Stops blinking of the winning cards
+ **/
+ void blinkOff();
+
+ void repaintCard();
+
+
+ protected:
+ virtual void resizeEvent( QResizeEvent* e );
+
+
+ protected slots:
+ void cardClicked(CardWidget* );
+
+
+ signals:
+ void toggleHeld();
+
+ private:
+ // The player that acts on the hand.
+ PokerPlayer *m_player; // The player object.
+
+ // Properties of the game
+ bool m_singlePlayer; // True if this is the only player in the game.
+ int m_cashPerRound; // one player game only FIXME: Rename into "ante"?
+
+ // The card widgets and "held" widgets
+ CardWidget **m_cardWidgets;
+ QLabel **m_heldLabels;
+ bool m_enableHeldLabels; // True if held labels are enabled.
+
+ // The labels at the right hand side of the box.
+ QLabel *m_cashLabel;
+ QLabel *m_betLabel;
+
+
+};
+#endif
+
diff --git a/kpoker/poker.cpp b/kpoker/poker.cpp
new file mode 100644
index 00000000..6143d342
--- /dev/null
+++ b/kpoker/poker.cpp
@@ -0,0 +1,531 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "poker.h"
+
+
+// ================================================================
+// Card classes
+
+
+CardDeck::CardDeck(KRandomSequence *random)
+{
+ m_random = random;
+
+ reset();
+}
+
+
+CardDeck::~CardDeck()
+{
+}
+
+
+// ----------------------------------------------------------------
+
+
+void
+CardDeck::reset()
+{
+ int i;
+ CardValue card;
+
+ for (i = 0, card = lowestCard; i < numCards; i++, card = card + 1)
+ m_cards[i] = card;
+ m_topCard = 0;
+
+}
+
+
+void
+CardDeck::shuffle()
+{
+ CardValue tmp;
+ int card;
+
+ if (m_topCard == numCards)
+ return;
+
+ for (int i = m_topCard; i < numCards - 1; i++) {
+ // Choose a random card from the not-yet-shuffled ones.
+ card = m_random->getLong(numCards - i) + i;
+
+ // Exchange the random card with the current card.
+ tmp = m_cards[i];
+ m_cards[i] = m_cards[card];
+ m_cards[card] = tmp;
+ }
+}
+
+
+CardValue
+CardDeck::getTopCard()
+{
+ if (m_topCard == numCards)
+ return DECK;
+
+ return m_cards[m_topCard++];
+}
+
+
+// ================================================================
+// Poker types
+
+
+QString PokerHandNames[] = {
+ "High Card",
+ "Pair",
+ "Two Pairs",
+ "Three Of A Kind",
+ "Straight",
+ "Flush",
+ "Full House",
+ "Four Of A Kind",
+ "Straight Flush",
+ "Royal Flush"
+};
+
+
+PokerHand::PokerHand()
+{
+ clear();
+}
+
+
+PokerHand::~PokerHand()
+{
+}
+
+
+// Compare two poker hands, and return true if the first one is less
+// valuable than the second one. Otherwise return false.
+
+bool
+PokerHand::operator<(PokerHand &hand2)
+{
+ CardValue card1;
+ CardValue card2;
+ int i;
+
+ // Make sure all relevant fields are initialized.
+ if (m_changed)
+ analyze();
+ if (hand2.m_changed)
+ hand2.analyze();
+
+#if 0
+ kdDebug() << "Hand 1: " << PokerHandNames[(int) m_type]
+ << " (" << ((int) m_firstRank) + 2
+ << ", " << ((int) m_secondRank) + 2
+ << ")" << endl;
+ kdDebug() << "Hand 2: " << PokerHandNames[(int) hand2.m_type]
+ << " (" << ((int) hand2.m_firstRank) + 2
+ << ", " << ((int) hand2.m_secondRank) + 2
+ << ")" << endl;
+#endif
+
+ // 1. If we have a better hand, then it is simple.
+ if (m_type != hand2.m_type)
+ return m_type < hand2.m_type;
+
+ // 2. If the hands are equal, check the internal parts of the hand
+ // type (like the first and second pair of two pairs).
+ switch (m_type) {
+ case HighCard:
+ case Pair:
+ case ThreeOfAKind:
+ case Straight:
+ case FourOfAKind:
+ case StraightFlush:
+ case RoyalFlush:
+ if (m_firstRank != hand2.m_firstRank)
+ return m_firstRank < hand2.m_firstRank;
+ break;
+
+ case TwoPairs:
+ case FullHouse:
+ // Compare the first rank first, and then the second.
+ if (m_firstRank != hand2.m_firstRank)
+ return m_firstRank < hand2.m_firstRank;
+ if (m_secondRank != hand2.m_secondRank)
+ return m_secondRank < hand2.m_secondRank;
+ break;
+
+ case Flush:
+ card1 = ROOF;
+ card2 = ROOF;
+ for (i = 0; i < PokerHandSize; i++) {
+ card1 = findNextBest(card1, true);
+ card2 = hand2.findNextBest(card2, true);
+
+ if (card1 != card2)
+ return card1 < card2;
+ }
+ // If we get here all the card ranks are the same in both hands.
+ // This means that they have to be of different suits.
+ break;
+
+ default:
+ // Shouldn't get here.
+ assert(0);
+ }
+
+ // 3. Ok, the hands themselves are the same. Now check if the cards
+ // outside the hands differ.
+ card1 = ROOF;
+ card2 = ROOF;
+ while (card1 != DECK) {
+ card1 = findNextBest(card1, false);
+ card2 = hand2.findNextBest(card2, false);
+
+ if (card1 != card2)
+ return card1 < card2;
+ }
+
+ // 4. *Every* rank is the same. Then they must differ in suit.
+
+ card1 = rank2card(m_firstRank + 1);
+ card2 = rank2card(hand2.m_firstRank + 1);
+
+ return card1 < card2;
+}
+
+
+// ----------------------------------------------------------------
+// Ordinary methods
+
+
+// Clear the hand - set all entries to DECK.
+void
+PokerHand::clear()
+{
+ for (int i = 0; i < PokerHandSize; i++)
+ m_cards[i] = DECK;
+
+ m_changed = true;
+}
+
+
+/* Throw away card no 'cardno'.
+ */
+
+void
+PokerHand::clear(int cardno)
+{
+ m_cards[cardno] = DECK;
+
+ m_changed = true;
+}
+
+
+CardValue
+PokerHand::getCard(int cardno) const
+{
+ return m_cards[cardno];
+}
+
+
+void
+PokerHand::setCard(int cardno, CardValue card)
+{
+ m_cards[cardno] = card;
+
+ m_changed = true;
+}
+
+
+bool
+PokerHand::findRank(CardRank the_rank) const
+{
+ for (int i = 0; i < PokerHandSize; i++)
+ if (rank(m_cards[i]) == the_rank)
+ return true;
+
+ return false;
+}
+
+
+bool
+PokerHand::findSuit(CardSuit the_suit) const
+{
+ for (int i = 0; i < PokerHandSize; i++)
+ if (suit(m_cards[i]) == the_suit)
+ return true;
+
+ return false;
+}
+
+
+// Return the next lower card value below the card 'roof'.
+//
+// If 'getFound' is true, then search only those cards that are marked
+// as found, i.e. are among those that determine the hand type.
+// Otherwise search the cards that are *not* among these.
+//
+
+CardValue
+PokerHand::findNextBest(CardValue roof, bool getFound) const
+{
+ CardValue next;
+
+ next = DECK;
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (m_cards[i] > next && m_cards[i] < roof
+ && (getFound == m_foundCards[i]))
+ next = m_cards[i];
+ }
+
+ return next;
+}
+
+
+int
+PokerHand::testStraight()
+{
+ CardRank lowest = ACE;
+
+ /* Set ranks[i] to the value of each card and find the lowest value. */
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (rank(m_cards[i]) < lowest)
+ lowest = rank(m_cards[i]);
+ }
+
+ // Look for special cases ace-2-3-4-5.
+ // (very ugly but fast to write):
+ if ((findRank(ACE) && findRank(TWO)
+ && findRank(THREE) && findRank(FOUR)
+ && findRank(FIVE))) {
+ m_firstRank = FIVE;
+ }
+ else {
+
+ for (int i = 0; i < PokerHandSize; i++)
+ if (!findRank(lowest + i))
+ return 0; // did not find a straight
+
+ m_firstRank = lowest + 4;
+ }
+
+ // Found a straight. Record it in foundCards[].
+ for (int i = 0; i < PokerHandSize; i++)
+ addFoundCard(i);
+
+ // Check for a royal flush
+ if (lowest == TEN)
+ return 2;
+
+ // An ordinary straight: return 1.
+ return 1;
+}
+
+
+bool
+PokerHand::testFlush()
+{
+ int theSuit;
+ CardValue highest_card;
+
+ highest_card = m_cards[0];
+ theSuit = suit(m_cards[0]);
+ for (int i = 1; i < PokerHandSize; i++) {
+ if (theSuit != suit(m_cards[i]))
+ return 0;
+
+ if (m_cards[i] > highest_card)
+ highest_card = m_cards[i];
+ }
+
+ // Found a flush. Now record the cards.
+ for (int i = 0; i < PokerHandSize; i++)
+ addFoundCard(i);
+ m_firstRank = rank(highest_card);
+
+ return true;
+}
+
+
+PokerHandType
+PokerHand::analyze()
+{
+ if (m_changed)
+ m_type = do_analyze();
+
+ return m_type;
+}
+
+
+PokerHandType
+PokerHand::do_analyze()
+{
+ CardValue card1;
+ CardValue card2;
+ int i;
+ int j;
+
+ cleanFoundCards();
+ m_changed = 0;
+
+ int isStraight = testStraight();
+
+ // Detect special cases;
+ if (isStraight) {
+ if (testFlush()) {
+ if (isStraight == 2)
+ return RoyalFlush;
+ else
+ return StraightFlush;
+ }
+ else
+ return Straight;
+ }
+
+ if (testFlush())
+ return Flush;
+
+ /* Find number of matches. */
+ int matching = 0;
+ for (i = 0; i < PokerHandSize; i++) {
+ for (j = i + 1; j < PokerHandSize; j++)
+ if (rank(m_cards[i]) == rank(m_cards[j])) {
+ matching++;
+ addFoundCard(i);
+ addFoundCard(j);
+ }
+ }
+
+ // The algorithm above gives the following results for each case below.
+ switch (matching) {
+ case 0: // High card
+ card1 = findNextBest(ROOF, false);
+ m_firstRank = rank(card1);
+ m_secondRank = (CardRank) -1;
+
+ // In this case, there are no marked cards. Since we need to mark
+ // the best card, we have to search for it and then mark it.
+ for (i = 0; i < PokerHandSize; i++) {
+ if (m_cards[i] == card1) {
+ addFoundCard(i);
+ break;
+ }
+ }
+ return HighCard;
+
+ case 1: // Pair
+ m_firstRank = rank(findNextBest(ROOF, true));
+ m_secondRank = (CardRank) -1;
+ return Pair;
+
+ case 2: // Two pairs
+ card1 = findNextBest(ROOF, true);
+
+ // Must do this twice, since the first card we get is the second
+ // card of the first pair.
+ card2 = findNextBest(card1, true);
+ card2 = findNextBest(card2, true);
+
+ m_firstRank = rank(card1);
+ m_secondRank = rank(card2);
+ return TwoPairs;
+
+ case 3: // 3 of a kind
+ m_firstRank = rank(findNextBest(ROOF, true));
+ return ThreeOfAKind;
+
+ case 4: // Full house
+ // This is the only tricky case since the value is determined more
+ // by the 3 of a kind than by the pair. The rank of the 3 of a
+ // kind can be lower then the pair, though.
+
+ // Get the best and third best cards into val1 and val2.
+ card1 = findNextBest(ROOF, true);
+ card2 = findNextBest(card1, true);
+ card2 = findNextBest(card2, true);
+
+ // Now we have one of two different cases:
+ // 1. rank(card1) == rank(card2): the 3 of a kind is biggest.
+ // 2. rank(card1) > rank(card2): the pair is biggest.
+ if (rank(card1) == rank(card2)) {
+ m_firstRank = rank(card1);
+ m_secondRank = rank(findNextBest(card2, true));
+ }
+ else {
+ m_firstRank = rank(card2);
+ m_secondRank = rank(card1);
+ }
+ return FullHouse;
+
+ case 6: // 4 of a kind
+ m_firstRank = rank(findNextBest(ROOF, true));
+ return FourOfAKind;
+
+ default:
+ break;
+ }
+
+ // Shouldn't get here.
+ assert(0);
+
+ return (PokerHandType) -1;
+}
+
+
+// FIXME: When we fix the scores, in raise() and bet() to be higher
+// with better hands, then change the "rank(C_ACE) -" stuff
+// below.
+//
+int
+PokerHand::getCardScore() const
+{
+ int score = 0;
+
+ for (int i = 0; i < PokerHandSize; i++) {
+ if (m_foundCards[i])
+ score += rank(C_ACE) - rank(m_cards[i]);
+ }
+
+ return score;
+}
+
+
+bool
+PokerHand::getFoundCard(int cardNum) const
+{
+ return m_foundCards[cardNum];
+}
+
+
+
+// ----------------------------------------------------------------
+// PokerHand protected methods
+
+
+void
+PokerHand::cleanFoundCards()
+{
+ for (int i = 0; i < PokerHandSize; i++)
+ m_foundCards[i] = false;
+}
+
+
+void
+PokerHand::addFoundCard(int cardNum)
+{
+ m_foundCards[cardNum] = true;
+}
diff --git a/kpoker/poker.h b/kpoker/poker.h
new file mode 100644
index 00000000..5a944d99
--- /dev/null
+++ b/kpoker/poker.h
@@ -0,0 +1,234 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef POKER_H
+#define POKER_H
+
+#include <qstring.h>
+#include <krandomsequence.h>
+#include <kdebug.h>
+
+
+// ================================================================
+// Card classes
+
+
+// FIXME: DECK should be renamed to NO_CARD and moved to -1. (or maybe not)
+// FIXME: Add Joker as well.
+//
+
+typedef enum {
+ DECK=0,
+ C_TWO, D_TWO, S_TWO, H_TWO,
+ C_THREE, D_THREE, S_THREE, H_THREE,
+ C_FOUR, D_FOUR, S_FOUR, H_FOUR,
+ C_FIVE, D_FIVE, S_FIVE, H_FIVE,
+ C_SIX, D_SIX, S_SIX, H_SIX,
+ C_SEVEN, D_SEVEN, S_SEVEN, H_SEVEN,
+ C_EIGHT, D_EIGHT, S_EIGHT, H_EIGHT,
+ C_NINE, D_NINE, S_NINE, H_NINE,
+ C_TEN, D_TEN, S_TEN, H_TEN,
+ C_JACK, D_JACK, S_JACK, H_JACK,
+ C_QUEEN, D_QUEEN, S_QUEEN, H_QUEEN,
+ C_KING, D_KING, S_KING, H_KING,
+ C_ACE, D_ACE, S_ACE, H_ACE,
+ ROOF // to get a roof on the value.
+} CardValue;
+
+const CardValue lowestCard = C_TWO;
+const CardValue highestCard = H_ACE;
+const int numCards = (int) H_ACE;
+
+
+typedef enum {
+ Clubs = 0, // The least valuable suit
+ Diamonds,
+ Spades,
+ Hearts // The most valuable suit
+} CardSuit;
+
+
+typedef enum {
+ TWO = 0, // The least valuable rank
+ THREE,
+ FOUR,
+ FIVE,
+ SIX,
+ SEVEN,
+ EIGHT,
+ NINE,
+ TEN,
+ JACK,
+ QUEEN,
+ KING,
+ ACE // The most valuable rank
+} CardRank;
+
+
+
+inline CardValue
+operator+(CardValue card, int offset)
+{
+ return (CardValue) ((int) card + offset);
+}
+
+
+
+// Get the suit from a card.
+
+inline CardSuit
+suit(CardValue card)
+{
+ // Need to subtract one since DECK == 0.
+ return (CardSuit) (((int) card - 1) % 4);
+}
+
+
+// Get the rank from a card
+
+inline CardRank
+rank(CardValue card)
+{
+ // Need to subtract one since DECK == 0.
+ return (CardRank) (((int) card - 1) / 4);
+}
+
+
+// Add an offset (can be negative) to a rank.
+//
+// NOTE: No overflow check is done. This is mainly used for type
+// conversion reasons.
+
+inline CardRank
+operator+(CardRank rank1, int offset)
+{
+ return (CardRank) ((int) rank1 + offset);
+}
+
+
+// Get the first card of a certain rank. This is the same rank of clubs.
+
+inline CardValue
+rank2card(CardRank rank)
+{
+ return (CardValue) (((int) rank) * 4 + 1);
+}
+
+// ----------------------------------------------------------------
+// Class CardDeck
+
+
+class CardDeck {
+ public:
+ CardDeck(KRandomSequence *random);
+ ~CardDeck();
+
+ void reset();
+ void shuffle();
+ CardValue getTopCard();
+
+ private:
+ CardValue m_cards[numCards];
+ int m_topCard;
+
+ KRandomSequence *m_random;
+};
+
+
+// ----------------------------------------------------------------
+// Poker related
+
+
+typedef enum {
+ HighCard,
+ Pair,
+ TwoPairs,
+ ThreeOfAKind,
+ Straight,
+ Flush,
+ FullHouse,
+ FourOfAKind,
+ StraightFlush,
+ RoyalFlush
+} PokerHandType;
+
+// Name strings for all the hands
+extern QString PokerHandNames[];
+
+
+// Number of cards in the hand.
+const int PokerHandSize = 5;
+
+class PokerHand {
+ public:
+ PokerHand();
+ ~PokerHand();
+
+ // Operators
+ bool operator<(PokerHand &hand2);
+
+ // Clear the hand or just one card - set the entries in question to DECK.
+ void clear();
+ void clear(int cardno);
+
+ // Card stuff
+ CardValue getCard(int cardno) const;
+ void setCard(int cardno, CardValue card);
+ bool findRank(CardRank rank) const;
+ bool findSuit(CardSuit suit) const;
+ CardValue findNextBest(CardValue roof, bool onlyFound) const;
+
+ // Poker stuff
+ int testStraight();
+ bool testFlush();
+ PokerHandType analyze();
+ CardRank get_firstRank() const { return m_firstRank; }
+ CardRank get_secondRank() const { return m_secondRank; }
+
+ bool getFoundCard(int cardNum) const;
+ int getCardScore() const;
+
+
+ protected:
+ // Clear the foundCards array.
+ void cleanFoundCards();
+
+ // Handle the "found" cards, i.e. those that comprise the scoring part.
+ void addFoundCard(int cardNum);
+
+ // Analyze the poker hand. This is the most important function of all.
+ PokerHandType do_analyze();
+
+
+ private:
+ // Primary data: The cards themselves.
+ CardValue m_cards[PokerHandSize];
+
+ // ----------------------------------------------------------------
+ // Secondary data: can be derived from the Primary data.
+ bool m_changed; // true if something has changed since the
+ // secondary data was last recalculated.
+
+ PokerHandType m_type; // Pair, Two Pairs, etc
+ CardRank m_firstRank; // Rank of first component
+ CardRank m_secondRank; // Rank of second component
+
+ bool m_foundCards[PokerHandSize]; // True for all scoring cards
+};
+
+
+#endif
diff --git a/kpoker/sound.cpp b/kpoker/sound.cpp
new file mode 100644
index 00000000..f029d03a
--- /dev/null
+++ b/kpoker/sound.cpp
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <qstring.h>
+
+#include <kstandarddirs.h>
+
+// sound support
+#include <kaudioplayer.h>
+
+#include "global.h"
+#include "kpoker.h"
+
+
+bool kpok::initSound()
+{
+ sound = true;
+ return true;
+}
+
+void kpok::playSound(const char *soundname)
+{
+ if (!sound)
+ return;
+
+ KAudioPlayer::play(locate("data", QString("kpoker/sounds/")+soundname));
+
+}
+
+void kpok::setSound(bool s)
+{
+ sound = s;
+}
+
diff --git a/kpoker/sounds/Makefile.am b/kpoker/sounds/Makefile.am
new file mode 100644
index 00000000..6ded1881
--- /dev/null
+++ b/kpoker/sounds/Makefile.am
@@ -0,0 +1,6 @@
+
+wavsdir = $(kde_datadir)/kpoker/sounds
+wavs_DATA = cardflip.wav hold.wav lose.wav win.wav
+
+EXTRA_DIST = $(wavs_DATA)
+
diff --git a/kpoker/sounds/cardflip.wav b/kpoker/sounds/cardflip.wav
new file mode 100644
index 00000000..37e7ceb1
--- /dev/null
+++ b/kpoker/sounds/cardflip.wav
Binary files differ
diff --git a/kpoker/sounds/hold.wav b/kpoker/sounds/hold.wav
new file mode 100644
index 00000000..f6969da1
--- /dev/null
+++ b/kpoker/sounds/hold.wav
Binary files differ
diff --git a/kpoker/sounds/lose.wav b/kpoker/sounds/lose.wav
new file mode 100644
index 00000000..9f9c72c3
--- /dev/null
+++ b/kpoker/sounds/lose.wav
Binary files differ
diff --git a/kpoker/sounds/win.wav b/kpoker/sounds/win.wav
new file mode 100644
index 00000000..d7cc5b2a
--- /dev/null
+++ b/kpoker/sounds/win.wav
Binary files differ
diff --git a/kpoker/top.cpp b/kpoker/top.cpp
new file mode 100644
index 00000000..b2e8137f
--- /dev/null
+++ b/kpoker/top.cpp
@@ -0,0 +1,266 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+// QT includes
+#include <qkeycode.h>
+#include <qcursor.h>
+
+// KDE includes
+#include <kapplication.h>
+#include <kmenubar.h>
+#include <kstatusbar.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kstdgameaction.h>
+#include <kaction.h>
+#include <kshortcut.h>
+
+// own includes
+#include "top.h"
+#include "kpoker.h"
+#include "defines.h"
+#include "version.h"
+
+
+PokerWindow::PokerWindow()
+{
+ m_kpok = new kpok(this, 0);
+ setCentralWidget( m_kpok );
+ m_kpok->show();
+
+ clickToHoldIsShown = false;
+
+ LHLabel = new QLabel(statusBar());
+ LHLabel->adjustSize();
+
+ connect(m_kpok, SIGNAL(changeLastHand(const QString &, bool)),
+ this, SLOT(setHand(const QString &, bool)));
+ connect(m_kpok, SIGNAL(showClickToHold(bool)),
+ this, SLOT(showClickToHold(bool)));
+ connect(m_kpok, SIGNAL(clearStatusBar()),
+ this, SLOT(clearStatusBar()));
+ connect(m_kpok, SIGNAL(statusBarMessage(QString)),
+ this, SLOT(statusBarMessage(QString)));
+
+ statusBar()->addWidget(LHLabel, 0, true);
+ m_kpok->updateLHLabel();
+ //FIXME: LHLabel is shown twize until the bar is repainted!
+
+ initKAction();
+ readOptions();
+}
+
+
+PokerWindow::~PokerWindow()
+{
+}
+
+
+// ----------------------------------------------------------------
+
+
+void PokerWindow::initKAction()
+{
+ //Game
+ KStdGameAction::gameNew(m_kpok, SLOT(newGame()), actionCollection());
+ KStdGameAction::save(m_kpok, SLOT(saveGame()), actionCollection());
+ KStdGameAction::quit(this, SLOT(close()), actionCollection());
+
+ //Settings
+ showMenubarAction =
+ KStdAction::showMenubar(this, SLOT(toggleMenubar()), actionCollection());
+
+ soundAction = new KToggleAction(i18n("Soun&d"), 0, m_kpok,
+ SLOT(toggleSound()), actionCollection(), "options_sound");
+ if (m_kpok->getSound())
+ m_kpok->toggleSound();
+ blinkingAction = new KToggleAction(i18n("&Blinking Cards"), 0, m_kpok,
+ SLOT(toggleBlinking()), actionCollection(), "options_blinking");
+ if (m_kpok->getBlinking())
+ m_kpok->toggleBlinking();
+ adjustAction = new KToggleAction(i18n("&Adjust Bet is Default"), 0,
+ m_kpok, SLOT(toggleAdjust()), actionCollection(), "options_adjust");
+ if (m_kpok->getAdjust())
+ m_kpok->toggleAdjust();
+
+ showStatusbarAction =
+ KStdAction::showStatusbar(this, SLOT(toggleStatusbar()), actionCollection());
+
+ KStdAction::saveOptions(this, SLOT(saveOptions()), actionCollection());
+ KStdGameAction::carddecks(m_kpok, SLOT(slotCardDeck()), actionCollection());
+ KStdAction::preferences(m_kpok, SLOT(slotPreferences()), actionCollection());
+
+ // Keyboard shortcuts.
+ (void)new KAction(i18n("Draw"), KShortcut(Qt::Key_Return), m_kpok,
+ SLOT(drawClick()), actionCollection(), "draw");
+ (void)new KAction(i18n("Exchange Card 1"), KShortcut(Qt::Key_1), m_kpok,
+ SLOT(exchangeCard1()), actionCollection(), "exchange_card_1");
+ (void)new KAction(i18n("Exchange Card 2"), KShortcut(Qt::Key_2), m_kpok,
+ SLOT(exchangeCard2()), actionCollection(), "exchange_card_2");
+ (void)new KAction(i18n("Exchange Card 3"), KShortcut(Qt::Key_3), m_kpok,
+ SLOT(exchangeCard3()), actionCollection(), "exchange_card_3");
+ (void)new KAction(i18n("Exchange Card 4"), KShortcut(Qt::Key_4), m_kpok,
+ SLOT(exchangeCard4()), actionCollection(), "exchange_card_4");
+ (void)new KAction(i18n("Exchange Card 5"), KShortcut(Qt::Key_5), m_kpok,
+ SLOT(exchangeCard5()), actionCollection(), "exchange_card_5");
+
+ setupGUI( KMainWindow::Save | StatusBar | Keys | Create);
+}
+
+
+void PokerWindow::readOptions()
+{
+ KConfig* conf = kapp->config();
+ conf->setGroup("General");
+
+ if (m_kpok->getSound() != conf->readBoolEntry("Sound", true))
+ soundAction->activate();
+
+ if (m_kpok->getBlinking() != conf->readBoolEntry("Blinking", true))
+ blinkingAction->activate();
+
+ if (m_kpok->getAdjust() != conf->readBoolEntry("Adjust", true))
+ adjustAction->activate();
+
+ if ( showMenubarAction->isChecked() !=
+ conf->readBoolEntry("ShowMenubar", true))
+ showMenubarAction->activate();
+
+ if ( showStatusbarAction->isChecked() !=
+ conf->readBoolEntry("ShowStatusbar", true))
+ showStatusbarAction->activate();
+}
+
+
+void PokerWindow::toggleMenubar()
+{
+ if (!menuBar()->isHidden())
+ menuBar()->hide();
+ else
+ menuBar()->show();
+}
+
+
+void PokerWindow::toggleStatusbar()
+{
+ if (!statusBar()->isHidden())
+ statusBar()->hide();
+ else
+ statusBar()->show();
+}
+
+
+/* Ask the user if he/she wants to save the game. This virtual method
+ * is called from the Quit KAction (I think).
+ */
+
+bool PokerWindow::queryClose()
+{
+ if (!m_kpok->isDirty())
+ return true;
+
+ // Only ask if the game is changed in some way.
+ switch(KMessageBox::warningYesNoCancel(this, i18n("Do you want to save this game?"), QString::null, KStdGuiItem::save(), KStdGuiItem::dontSave())) {
+ case KMessageBox::Yes :
+ m_kpok->saveGame();
+ return true;
+ case KMessageBox::No :
+ return true;
+ default :
+ return false;
+ }
+}
+
+
+/* Show the hand or winner in the status bar at the lower right.
+ *
+ * Which is shown depends on wether this is a one player game or a two
+ * player game.
+ */
+
+void PokerWindow::setHand(const QString &newHand, bool lastHand)
+{
+ if (lastHand)
+ LHLabel->setText(i18n("Last hand: ") + newHand);
+ else
+ LHLabel->setText(i18n("Last winner: ") + newHand);
+ LHLabel->adjustSize();
+}
+
+
+void PokerWindow::showClickToHold(bool show)
+{
+ if (show) {
+ statusBar()->clear();
+ statusBar()->message(i18n("Click a card to hold it"));
+ clickToHoldIsShown = true;
+ } else if (clickToHoldIsShown) {
+ statusBar()->clear();
+ clickToHoldIsShown = false;
+ }
+}
+
+
+void PokerWindow::statusBarMessage(QString s)
+{
+ clearStatusBar();
+ statusBar()->message(s);
+ clickToHoldIsShown = false;
+}
+
+
+void PokerWindow::clearStatusBar()
+{
+ if (!clickToHoldIsShown)
+ statusBar()->clear();
+}
+
+
+void PokerWindow::saveOptions()
+{
+ KConfig* conf = kapp->config();
+ conf->setGroup("General");
+
+ conf->writeEntry("Sound", soundAction->isChecked());
+ conf->writeEntry("Blinking", blinkingAction->isChecked());
+ conf->writeEntry("Adjust", adjustAction->isChecked());
+ conf->writeEntry("ShowMenubar", showMenubarAction->isChecked());
+ conf->writeEntry("ShowStatusbar", showStatusbarAction->isChecked());
+}
+
+
+bool PokerWindow::eventFilter(QObject*, QEvent* e)
+{
+ if (e->type() == QEvent::MouseButtonPress) {
+
+ if (((QMouseEvent*)e)->button() == RightButton) {
+ QPopupMenu* popup = (QPopupMenu*) factory()->container("popup", this);
+ if (popup)
+ popup->popup(QCursor::pos());
+ return true;
+ } else
+ return false;
+ }
+
+ return false;
+}
+
+#include "top.moc"
+
diff --git a/kpoker/top.h b/kpoker/top.h
new file mode 100644
index 00000000..715aa20d
--- /dev/null
+++ b/kpoker/top.h
@@ -0,0 +1,70 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __PokerWindow__
+#define __PokerWindow__
+
+
+#include <kmainwindow.h>
+
+
+class QLabel;
+class KToggleAction;
+class kpok;
+
+
+class PokerWindow : public KMainWindow
+{
+ Q_OBJECT
+
+ public:
+ PokerWindow();
+ ~PokerWindow();
+
+ protected:
+ virtual bool queryClose();
+ bool eventFilter(QObject*, QEvent*);
+ void initKAction();
+ void readOptions();
+
+ protected slots:
+ // void saveProperties(KConfig*);
+ // void readProperties(KConfig*);
+ void setHand(const QString &newHand, bool lastHand = true);
+ void showClickToHold(bool show);
+ void statusBarMessage(QString);
+ void clearStatusBar();
+ void saveOptions();
+ void toggleMenubar();
+ void toggleStatusbar();
+
+ private:
+ kpok *m_kpok;
+
+ KToggleAction *soundAction;
+ KToggleAction *blinkingAction;
+ KToggleAction *adjustAction;
+ KToggleAction *showMenubarAction;
+ KToggleAction *showStatusbarAction;
+
+ // statusbar elements:
+ QLabel *LHLabel;
+
+ bool clickToHoldIsShown;
+};
+
+#endif
diff --git a/kpoker/version.h b/kpoker/version.h
new file mode 100644
index 00000000..5d3e1503
--- /dev/null
+++ b/kpoker/version.h
@@ -0,0 +1,3 @@
+#define KPOKER_VERSION "1.1"
+#define KPOKER_RELEASE_DATE "2005-09-15"
+