Poker Simulator Design Writeup
(New page: = Elliot Fisher's Design = == 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 ar...) |
|||
Line 1: | Line 1: | ||
− | |||
− | |||
== Intro == | == 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. | + | 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. | ||
Line 38: | Line 38: | ||
[[Image: Poker Class Diagram v4.png|thumb|800px|centre|'''Class Diagram''']] | [[Image: Poker Class Diagram v4.png|thumb|800px|centre|'''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 == | == Design Breakdown == | ||
+ | === Card Analyser === | ||
+ | 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 == | == Design Patterns == | ||
− | Observer | + | === 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). | |
− | Iterator | + | {| |
+ | |- | ||
+ | | 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 === | ||
+ | |||
+ | PokerStyleFactory | ||
+ | |||
+ | === Singleton === | ||
+ | |||
+ | PokerGame | ||
+ | |||
+ | === Iterator === | ||
+ | |||
+ | used throughout RegularCardAnalyser to iterate though Sets of Cards. | ||
== Principles Followed == | == Principles Followed == | ||
Line 62: | Line 142: | ||
== Principles Violated == | == Principles Violated == | ||
+ | |||
+ | == Parting Comments == |
Revision as of 23:01, 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).
- Texas Hold 'em rules: [Texas Hold 'em]
- Poker hand rankings: [Hand ranks]
- Information about different poker variants: [Poker Variants]
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
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
Card Analyser
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
PokerStyleFactory
Singleton
PokerGame
Iterator
used throughout RegularCardAnalyser to iterate though Sets of Cards.