diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | c90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch) | |
tree | 6d8391395bce9eaea4ad78958617edb20c6a7573 /kpoker | |
download | tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kpoker')
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 <[email protected]> +Mario Weilguni <[email protected]> +Andreas Beckermann <[email protected]> +Inge Wallin <[email protected]> + +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 <[email protected]> + + 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 <[email protected]> + + * version.h (KPOKER_VERSION): Bumped version to 1.0 for KDE 3.4. + +2005-01-26 Inge Wallin <[email protected]> + + ----------------- CVS commit on stuff below -------------------- + + Code cleaning + * Make all blink parameters follow the m_ convention. + +2005-01-18 <[email protected]> + + 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 <[email protected]> + + 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 <[email protected]> + + 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 <[email protected]> + + 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 <[email protected]> + + 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 <[email protected]> + + Start structural cleanup + * kpoker.cpp (winner): Move from testers.cpp to kpoker.cpp. + * testers.cpp: deleted + +2004-09-03 Inge Wallin <[email protected]> + + 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 <[email protected]> + + * 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 <[email protected]> + + 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 <[email protected]> + + Continue the great code cleanup. + * optionsdlg.h, optionsdlg.cpp + * newgamedlg.h, newgamedlg.cpp + +2004-08-29 Inge Wallin <[email protected]> + + 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 <[email protected]> + + Start of the great code cleanup + * global.h + * main.cpp + +2004-08-26 Inge Wallin <[email protected]> + + 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 <[email protected]> + + 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 <[email protected]>) + +- 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 <[email protected]>) +- 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 <[email protected]> +This Program is distributed under the GPL. See the file COPYING for details + +This game is maintained by +Andreas Beckermann <[email protected]> +Inge Wallin <[email protected]> + + 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 Binary files differnew file mode 100644 index 00000000..e2a5570a --- /dev/null +++ b/kpoker/hi128-app-kpoker.png diff --git a/kpoker/hi16-app-kpoker.png b/kpoker/hi16-app-kpoker.png Binary files differnew file mode 100644 index 00000000..38b3a8c0 --- /dev/null +++ b/kpoker/hi16-app-kpoker.png diff --git a/kpoker/hi22-app-kpoker.png b/kpoker/hi22-app-kpoker.png Binary files differnew file mode 100644 index 00000000..9e939a49 --- /dev/null +++ b/kpoker/hi22-app-kpoker.png diff --git a/kpoker/hi32-app-kpoker.png b/kpoker/hi32-app-kpoker.png Binary files differnew file mode 100644 index 00000000..409f4764 --- /dev/null +++ b/kpoker/hi32-app-kpoker.png diff --git a/kpoker/hi48-app-kpoker.png b/kpoker/hi48-app-kpoker.png Binary files differnew file mode 100644 index 00000000..097fc5fd --- /dev/null +++ b/kpoker/hi48-app-kpoker.png diff --git a/kpoker/hi64-app-kpoker.png b/kpoker/hi64-app-kpoker.png Binary files differnew file mode 100644 index 00000000..9ad09b3b --- /dev/null +++ b/kpoker/hi64-app-kpoker.png 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>&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"), "[email protected]"); + aboutData.addAuthor("Andreas Beckermann", + I18N_NOOP("Current maintainer"), "[email protected]"); + aboutData.addAuthor("Jochen Tuchbreiter", + I18N_NOOP("Original author"), "[email protected]"); + 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 Binary files differnew file mode 100644 index 00000000..37e7ceb1 --- /dev/null +++ b/kpoker/sounds/cardflip.wav diff --git a/kpoker/sounds/hold.wav b/kpoker/sounds/hold.wav Binary files differnew file mode 100644 index 00000000..f6969da1 --- /dev/null +++ b/kpoker/sounds/hold.wav diff --git a/kpoker/sounds/lose.wav b/kpoker/sounds/lose.wav Binary files differnew file mode 100644 index 00000000..9f9c72c3 --- /dev/null +++ b/kpoker/sounds/lose.wav diff --git a/kpoker/sounds/win.wav b/kpoker/sounds/win.wav Binary files differnew file mode 100644 index 00000000..d7cc5b2a --- /dev/null +++ b/kpoker/sounds/win.wav 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" + |