Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

player.py 7.1 KB
Newer Older
Yildius's avatar
Yildius committed
1 2 3 4 5 6 7 8 9 10 11
## class Player
#  This class handles the status of a player, without much responsibility.
#  It takes care of:
#   - unique ID, name
#   - player status (playing, busted, all-in, etc)
#   - player's chips (until they are sent to the pot)
#   - related pot (when side-pots occur)
#   - hand handling (receives its holecards, computes its hand with boardcards)
#   - comparison operator with another player (based and hand value)
#

12
from uuid import uuid4
Yildius's avatar
Yildius committed
13 14
from enum import Enum

Arnaud Chevalier's avatar
Arnaud Chevalier committed
15
from player.hand import Hand
Arnaud Chevalier's avatar
Arnaud Chevalier committed
16

Yildius's avatar
Yildius committed
17

Yildius's avatar
Yildius committed
18 19 20 21 22
class PlayerState(Enum):
    PLAYING = 0
    FOLDED = 1
    ALL_IN = 2
    BUSTED = 3
Arnaud Chevalier's avatar
Arnaud Chevalier committed
23 24 25
    CALLED = 4
    CHECKED = 5
    RAISED = 6
Yildius's avatar
Yildius committed
26

Arnaud Chevalier's avatar
Arnaud Chevalier committed
27

Arnaud Chevalier's avatar
Arnaud Chevalier committed
28 29 30
class Player:

    # INIT
Arnaud Chevalier's avatar
Arnaud Chevalier committed
31
    def __init__(self, name):
32
        self.__uniqueId = str(uuid4())
Arnaud Chevalier's avatar
Arnaud Chevalier committed
33
        self.__hand = Hand()
34 35 36
        self.__chips = int(0)
        self.__cards = []
        self.__chipsOnTable = int(0)
37
        self.__hasHadAction = False
38
        self.__playerState = PlayerState.PLAYING
Arnaud Chevalier's avatar
Arnaud Chevalier committed
39
        self.__name = name
40 41
        self.__potId = -1
        self.__won = False
Arnaud Chevalier's avatar
Arnaud Chevalier committed
42 43

    # GETTERS & SETTERS
Yildius's avatar
Yildius committed
44
    @property
45
    def isPlaying(self):
Arnaud Chevalier's avatar
Arnaud Chevalier committed
46
        return self.__playerState == PlayerState.PLAYING or self.__playerState == PlayerState.CHECKED or self.__playerState == PlayerState.CALLED or self.__playerState == PlayerState.RAISED
Yildius's avatar
Yildius committed
47 48 49

    @property
    def isInHand(self):
Arnaud Chevalier's avatar
Arnaud Chevalier committed
50
        return self.__playerState == PlayerState.PLAYING or self.__playerState == PlayerState.CHECKED or self.__playerState == PlayerState.CALLED or self.__playerState == PlayerState.RAISED or self.__playerState == PlayerState.ALL_IN
Yildius's avatar
Yildius committed
51 52 53

    @property
    def isAllIn(self):
54
        return self.__playerState == PlayerState.ALL_IN
55

56
    @property
57
    def chipsOnTable(self):
58 59
        return self.__chipsOnTable

60
    @property
61 62 63
    def hasHadAction(self):
        return self.__hasHadAction

64 65
    @property
    def hand(self):
66 67
        return self.__hand

68 69
    @property
    def holeCards(self):
Yildius's avatar
Yildius committed
70 71
        return self.__cards

72
    @property
Arnaud Chevalier's avatar
Arnaud Chevalier committed
73
    def remainingChips(self):
74
        return self.__chips
Arnaud Chevalier's avatar
Arnaud Chevalier committed
75

Arnaud Chevalier's avatar
Arnaud Chevalier committed
76 77 78 79
    @property
    def uniqueId(self):
        return self.__uniqueId

80 81 82 83
    @property
    def name(self):
        return self.__name

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    @property
    def potId(self):
        return self.__potId

    @potId.setter
    def potId(self, id):
        self.__potId = id

    @property
    def won(self):
        return self.__won

    @won.setter
    def won(self, won):
        self.__won = won

100 101 102 103
    @property
    def playerState(self):
        return self.__playerState

Yildius's avatar
Yildius committed
104 105 106
    def isComparable(self):
        return self.__hand.isLoaded()

Arnaud Chevalier's avatar
Arnaud Chevalier committed
107
    # PRIVATE METHODS
108
    def __putMoneyOnTable(self, amount):
Yildius's avatar
Yildius committed
109 110 111 112 113 114 115 116
        ## called by 'call' or 'bet', puts money from the player's stack on the
        # table, but not yet on the pot.
        #  This methode is in charge of putting the player all-in if necessary,
        # and makes sure that the player's stack is nto negative.
        #  Receives the expected amount to be extracted from the stack, and
        # returns the amount that was actually extracted.
        #
        amountBet = 0
Yildius's avatar
Yildius committed
117
        if self.isAllIn:
118
            print("Player {} is already All In".format(self.__name))
Yildius's avatar
Yildius committed
119 120
            return 0
        if amount >= self.__chips:
121
            print("Player {} is All In".format(self.__name))
122
            self.__playerState = PlayerState.ALL_IN
Yildius's avatar
Yildius committed
123 124 125
            amountBet = self.__chips
            self.__chipsOnTable += self.__chips
            self.__chips = 0
126
        else:
127
            print("Player {} bet {}".format(self.__name, amount))
Yildius's avatar
Yildius committed
128 129 130 131
            amountBet = amount
            self.__chips -= amount
            self.__chipsOnTable += amount
        return amountBet
Arnaud Chevalier's avatar
Arnaud Chevalier committed
132 133

    # PUBLIC METHODS
134
    def newHand(self):
Yildius's avatar
Yildius committed
135
        # Reset status for the next hand.
136
        self.__hasHadAction = False
Yildius's avatar
Yildius committed
137
        if self.__chips:
138
            self.__playerState = PlayerState.PLAYING
Yildius's avatar
Yildius committed
139
        else:
140
            self.__playerState = PlayerState.BUSTED
Yildius's avatar
Yildius committed
141
        self.__hand = Hand()
142
        self.__potId = -1
143
        self.__won = False
144 145

    def computeHand(self, boardCards):
Yildius's avatar
Yildius committed
146 147 148 149 150
        ## Towards the end of the hand, give the player the board cards and
        # let him find out his hand (the best combination of 5 cards from the 5
        # cards from the board and its 2 hole cards).
        #  Returns the computed best hand.
        #
151
        assert len(boardCards) == 5
152 153
        cards = boardCards + self.__cards
        self.__hand = Hand(boardCards)
154 155 156 157 158 159 160 161 162
        for i in range(len(cards)):
            for j in range(i+1, len(cards)):
                newHandCards = []
                for k in range(len(cards)):
                    if k != i and k != j:
                        newHandCards += [cards[k]]
                newHand = Hand(newHandCards)
                if self.__hand < newHand:
                    self.__hand = newHand
163
        return self.__hand
164

165 166
    def receiveCards(self, card1, card2):
        self.__cards = [card1, card2]
167

168 169
    def receiveChip(self, chips):
        self.__chips += chips
170

171
    def yieldBet(self):
172
        # Moves the money that was on the table to the pot
173
        self.__hasHadAction = False
174 175 176
        temp = self.__chipsOnTable
        self.__chipsOnTable = 0
        return temp
Arnaud Chevalier's avatar
Arnaud Chevalier committed
177

Yildius's avatar
Yildius committed
178
    def yieldPartialBet(self, value):
179 180
        ## Moves part of the money that was on the table to the pot, used for
        # split pots
Yildius's avatar
Yildius committed
181 182 183 184 185
        self.__hasHadAction = False
        chips = min(value, self.__chipsOnTable)
        self.__chipsOnTable -= chips
        return chips

Arnaud Chevalier's avatar
Arnaud Chevalier committed
186
    def giveSB(self, smallBlind):
187
        return self.__putMoneyOnTable(smallBlind)
Arnaud Chevalier's avatar
Arnaud Chevalier committed
188 189

    def giveBB(self, bigBlind):
190
        return self.__putMoneyOnTable(bigBlind)
Arnaud Chevalier's avatar
Arnaud Chevalier committed
191

Yildius's avatar
Yildius committed
192
    # Actions, called by Table.
Arnaud Chevalier's avatar
Arnaud Chevalier committed
193
    # By calling these methods, Table authorises the transaction.
Arnaud Chevalier's avatar
Arnaud Chevalier committed
194
    def bet(self, amount):
Yildius's avatar
Yildius committed
195 196
        # amount is the money to be added
        # Returns the amount actually added
197
        self.__hasHadAction = True
Arnaud Chevalier's avatar
Arnaud Chevalier committed
198
        self.__playerState = PlayerState.RAISED
199
        return self.__putMoneyOnTable(amount)
Arnaud Chevalier's avatar
Arnaud Chevalier committed
200

Arnaud Chevalier's avatar
Arnaud Chevalier committed
201
    def check(self):
Yildius's avatar
Yildius committed
202
        # Returns True if succeeds
203
        self.__hasHadAction = True
Arnaud Chevalier's avatar
Arnaud Chevalier committed
204
        self.__playerState = PlayerState.CHECKED
205
        return True
Arnaud Chevalier's avatar
Arnaud Chevalier committed
206

207
    def call(self, amountToCall):
Yildius's avatar
Yildius committed
208
        # Returns the amount added
209
        self.__hasHadAction = True
Arnaud Chevalier's avatar
Arnaud Chevalier committed
210
        self.__playerState = PlayerState.CALLED
Yildius's avatar
Yildius committed
211
        return self.__putMoneyOnTable(amountToCall - self.__chipsOnTable)
Arnaud Chevalier's avatar
Arnaud Chevalier committed
212

Arnaud Chevalier's avatar
Arnaud Chevalier committed
213
    def fold(self):
Yildius's avatar
Yildius committed
214
        # Returns True if succeeds
215
        self.__hasHadAction = True
216
        self.__playerState = PlayerState.FOLDED
Arnaud Chevalier's avatar
Arnaud Chevalier committed
217
        return True
218

219
    def state(self):
Yildius's avatar
Yildius committed
220
        # returns player state (all in, playing, folded)
221
        if self.__playerState == PlayerState.FOLDED:
Arnaud Chevalier's avatar
Arnaud Chevalier committed
222
            return "FOLD"
223
        if self.__playerState == PlayerState.ALL_IN:
224
            return "ALL IN"
225
        if self.__playerState == PlayerState.BUSTED:
Yildius's avatar
Yildius committed
226
            return "BUSTED"
Arnaud Chevalier's avatar
Arnaud Chevalier committed
227 228 229 230 231 232
        if self.__playerState == PlayerState.CALLED:
            return "CALL"
        if self.__playerState == PlayerState.CHECKED:
            return "CHECK"
        if self.__playerState == PlayerState.RAISED:
            return "RAISE"
Yildius's avatar
Yildius committed
233 234 235
        return ""

    def __lt__(self, player):
Yildius's avatar
Yildius committed
236
        # Compare 2 players based on the value of their hand
Yildius's avatar
Yildius committed
237 238 239
        assert self.isComparable()
        assert player.isComparable()
        return self.hand < player.hand