Poker Simulator Design Writeup

From CSSEMediaWiki
(Difference between revisions)
Jump to: navigation, search
Line 42: Line 42:
 
== Design Breakdown ==
 
== Design Breakdown ==
  
=== Card Analyser ===
+
=== PokerGame ===
 +
 
 +
Talk about subclassing Singleton
 +
 
 +
 
 +
=== CardAnalyser ===
  
 
I have provided a Wildcard class in the diagram as an example (but not implemented it in my code). Wildcard is a rule variation where specific cards are "wild" which means they can be designated as any card that the player chooses in making a hand.
 
I have provided a Wildcard class in the diagram as an example (but not implemented it in my code). Wildcard is a rule variation where specific cards are "wild" which means they can be designated as any card that the player chooses in making a hand.
 +
  
  
Line 128: Line 134:
 
=== Abstract Factory ===
 
=== Abstract Factory ===
  
PokerStyleFactory
+
The PokerStyleFactory class provides an [[Abstract Factory]] pattern. It is used for creating the related objects for different poker styles - Dealer, Player and Table. I used it to enforce the constraint that only objects of one style of poker may be used at one time, so that, for example, a HoldEmDealer doesn't end up sitting at a Table with DrawPlayers. It is also useful in that it allows for several different styles of poker to be implemented.
 +
 
 +
{|
 +
|-
 +
| Abstract Factory || ''PokerStyleFactory''
 +
|-
 +
| Concrete Factory1 || ''HoldEmFactory''
 +
|-
 +
| Concrete Factory2 || ''DrawFactory''
 +
|-
 +
| Abstract Product1 || ''Dealer''
 +
|-
 +
| Abstract Product2 || ''Player''
 +
|-
 +
| Concrete Product || ''Table''
 +
|-
 +
| Client || ''PokerGame''
 +
|-
 +
|}
  
 
=== Singleton ===
 
=== Singleton ===
  
PokerGame
+
PokerGame is a [[Singleton]] class, and is used to ensure that only one instance of a PokerGame may exist. I have modified the Singleton pattern to allow PokerGame to be subclassed to a CashGame or a TournamentGame (not yet implemented). This is dicussed in more depth above in "Design Breakdown"
  
 
=== Iterator ===
 
=== Iterator ===
  
used throughout RegularCardAnalyser to iterate though Sets of Cards.
+
I have used [[Iterator|Iterators]] throughout RegularCardAnalyser in order to iterate though Sets of Cards.
  
 
== Principles Followed ==
 
== Principles Followed ==
Line 142: Line 166:
  
 
== Principles Violated ==
 
== Principles Violated ==
 +
 +
Not always used [[Iterator]] to iterate though Collections - found it simpler to write for loops to iterate though Lists.
  
 
== Parting Comments ==
 
== Parting Comments ==

Revision as of 23:26, 30 September 2008

Contents

Intro

For my design study I have chosen to create a poker simulator of sorts. I have started this project specifically for the 427 design study. Cards are dealt to a number of players around a table, the hand played through and the winner of the hand determined. The game can continue for an arbitrary number of hands. Currently the user controls each player in turn and can see all the Player's cards, so it is more of a simulator than a full blown poker game. Ideally if I had more time it would be nice to make it multiplayer with some client server functionality, or to implement some AI to play against.

I have implemented the Texas Hold 'em variant of poker (see A Brief Introduction to Poker below), but have left the design open for the implementation of other poker variants and rules. To illustrate this there are classes for the Draw variant of poker and the Wildcard rule in the design, but without full functionality. I have also implemented the "cash game" type of poker, where the game consists of one table and players can come or go as they wish. Alternately a poker game can be "tournament" style, which consists of one or more tables and players aim to win the tournament by taking other players chips and knocking them out until there is one player left. As players are knocked out the tables are balanced and joined together until there is one table; the "final table." I have created a Tournament class to illustrate this possibility, but there is currently no functionality for it.


Haven't had time to implement: There are also different bet limits in poker, I am not sure how this might effect my design if they are to be implemented in the future. The most common is No Limit where you can bet however much you like at any time, even your entire chip stack. There are also Limit games where bets and raises are limited to a fixed amount, and Pot Limit where bets are limited to the size of the pot.


A Brief Introduction to Poker

Poker is a card game where players make bets on the value of the cards in their hand, which accumulate in a central pot. The winner is the player with the highest ranked hand, or the last player to remain in the hand after all other players have folded. In order to stay in contention for the pot a player must match the bet of every other player in the pot. If a player doesn't wish to match a bet, they may fold their hand at any time, making them out of contention for the pot. Play is commenced clockwise around the table from the left of the player in the dealer position. After the hand is completed, the player to the left of the dealer assumes the dealer position for the next hand.

The poker variant implemented in my design is called Texas Hold 'em, and is the most popular form of poker today. In a game of Texas Hold 'em, each player is dealt only two cards face down (the hole cards). A total of five community cards are dealt face up on the table, and each player must make the best possible five card hand using any combination of community cards and their own cards. The first betting round is performed after the players receive their two hole cards. Once this is complete, three community cards are dealt (the flop), and another betting round performed. After this a fourth community card is dealt (the turn), followed by a betting round, then the last community card is dealt (the river), followed by the last betting round.

Betting rounds consist of players either checking (opting to bet nothing if there is no current bet to match), calling an existing bet by putting out the equivalent amount of chips, or raising an existing bet by putting out a greater amount of chips than the existing bet. The winner of the hand wins the money in the pot, or in the case of a draw (two or more players having a hand of equivalent rank) the money is split between the players.

For more information I will refer the reader to Wikipedia. (I love Wikipedia, Wiki Wiki Pedia).

Source Code

My source code is written in Java and can be found here: media:pokerSimulatorCode.tgz

To run it from a shell, type: java PokerSimulator [-gameType] [-variant]

-gameType is either Cash Game (-c) or Tournament (-t). Currently only (-c) is implemented.

-variant specifies the poker variant. Currently only (-h) for HoldEm is implemented.


Class Diagram

Class Diagram

Here is my entire class diagram in all its glory. Note that I have excluded the GUI from the class diagram, as I had to hack it together very quickly before this project was due. Subsequently the GUI is badly designed and is tightly coupled with the rest of the design. In my class diagram $ means static, and # means protected. I have not differentiated between composition and aggregation relationships.

Design Breakdown

PokerGame

Talk about subclassing Singleton


CardAnalyser

I have provided a Wildcard class in the diagram as an example (but not implemented it in my code). Wildcard is a rule variation where specific cards are "wild" which means they can be designated as any card that the player chooses in making a hand.



Critique

Some classes seem to exhibit the Large class smell, namely Table and TablePot. However it is important to note that they are large because of the number methods in them and not the number of fields, if they had too many fields I might have to apply the Extract Class refactoring method. The large number of methods in these classes are required partly because the GUI needed them and partly to satisfy the Law of demeter.

I do not like the relationship between Table, TablePot, PotContribution, Player and PlayerHand. There seems to be some duplicated data in that a Table contains a direct reference to PlayerHands, but also contains a reference to the same PlayerHands though the TablePot - PotContribution - Player - PlayerHand. This problem has been caused by the TablePot and PotContribution classes which have been tacked on last to add the betting/calling/folding functionality. If I had more time on this project my next step would be to refactor these classes, possibly adding a PlayerAction class to deal with betting, calling and folding.

Design Patterns

Observer

I have used the Observer pattern to model the relationship between the Dealer and the TablePot. The Dealer needs to know when the TablePot is modified so he can determine if the betting round is complete or not. Note that the Abstract Subject class is the Java Observable class which implements this pattern, and Dealer implements the Java Observer interface by defining an update() method.

Abstract Subject Observable
Concrete Subject TablePot
Observer Dealer
Concrete Observer HoldEmDealer

Template Method

The analyseCards() method in CardAnalyser is a Template Method. It defines the structure of the algorithm that determines the hand rank of a set of cards. The primitive operations correspond to a check for each possible rank, and subclasses of CardAnalyser can define these operations differently for different rule variations. The algorithms structure is set in the base class because the hand ranks must be checked in order from worst to best so that the best hand rank is returned. (ie a flush might also contain a pair, but it is the flush rank that counts).

Abstract Class CardAnalyser
Concrete Template Method analyseCards()
Abstract primitiveOperation1 checkHighCard()
Abstract primitiveOperation2 checkPair()
Abstract primitiveOperation3 checkTwoPair()
Abstract primitiveOperation4 checkTrips()
Abstract primitiveOperation5 checkStraight()
Abstract primitiveOperation6 checkFlush()
Abstract primitiveOperation7 checkFullHouse()
Abstract primitiveOperation8 checkFourOfKind()
Abstract primitiveOperation9 checkStraightFlush()
Concrete Class1 RegularCardAnalyser
Concrete Class2 WildCardAnalyser

State

The RankedHand class is a State pattern, with PlayerHand as the context. The behaviour of the compareTo() method varies depending on the type of RankedHand, as it is necessary to compare different types of hands in different ways. PlayerHand does not actually contain a RankedHand, but instead creates a new RankedHand and uses it within it's own compareTo() method to determine if another PlayerHand is better.

Context PlayerHand
Abstract State RankedHand
Abstract handle() compareTo()
Concrete State1 FullHand
Concrete State2 PartialHand
Concrete State3 CombinedHand

Abstract Factory

The PokerStyleFactory class provides an Abstract Factory pattern. It is used for creating the related objects for different poker styles - Dealer, Player and Table. I used it to enforce the constraint that only objects of one style of poker may be used at one time, so that, for example, a HoldEmDealer doesn't end up sitting at a Table with DrawPlayers. It is also useful in that it allows for several different styles of poker to be implemented.

Abstract Factory PokerStyleFactory
Concrete Factory1 HoldEmFactory
Concrete Factory2 DrawFactory
Abstract Product1 Dealer
Abstract Product2 Player
Concrete Product Table
Client PokerGame

Singleton

PokerGame is a Singleton class, and is used to ensure that only one instance of a PokerGame may exist. I have modified the Singleton pattern to allow PokerGame to be subclassed to a CashGame or a TournamentGame (not yet implemented). This is dicussed in more depth above in "Design Breakdown"

Iterator

I have used Iterators throughout RegularCardAnalyser in order to iterate though Sets of Cards.

Principles Followed

Principles Violated

Not always used Iterator to iterate though Collections - found it simpler to write for loops to iterate though Lists.

Parting Comments

Personal tools