Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
POOker
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Container Registry
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Garde Remi
POOker
Commits
091547d8
Commit
091547d8
authored
Nov 07, 2018
by
Yildius
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Comments on table.py
parent
18764134
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
56 additions
and
17 deletions
+56
-17
table.py
table/table.py
+56
-17
No files found.
table/table.py
View file @
091547d8
# Game engine
## class Table
# This class is pretty much the game engine, it receives orders from the
# players connected to the front end, handles the money, controls the rules,
# and generates the json for the front end.
# One instance represents one table of poker, several instances may work in
# parallel in order to allow for more players.
#
# Tests :
# t = Table()
# t.addPlayer(Player())
# t.addPlayer(Player())
# t.startHand()
# t.call(1)
# t.call(0)
# Then repeat the last 2 at will
import
time
from
math
import
exp
...
...
@@ -39,6 +36,7 @@ class PlayingMode(Enum):
def
defaultCallBack
():
# Function used as default for objects that require a callback function
print
(
"Default CallBack function."
)
return
...
...
@@ -116,12 +114,13 @@ class Table(object):
self
.
__waitingPlayers
.
append
(
p
)
self
.
__mainMutex
.
release
()
# Return the player at required position, 0 is button
def
__playerAtPos
(
self
,
pos
):
# Return the player index located 'pos' sits after the button
return
(
self
.
__button
+
pos
)
%
len
(
self
.
__players
)
# Passes action to the next player in the hand
def
__nextPos
(
self
):
## Called when a player successfully had an action, changes the active
# player to the next one available
playerFound
=
False
while
not
playerFound
:
self
.
__activePlayer
=
(
self
.
__activePlayer
+
1
)
%
len
(
self
.
__players
)
...
...
@@ -142,6 +141,9 @@ class Table(object):
return
self
.
__activePlayer
def
startHand
(
self
):
## Start a new hand (checks if enough players are still in the game)
# This method resets variable, passes the button, and checks if waiting
# players need to be added and/or cleans busted ones.
self
.
__mainMutex
.
acquire
()
print
(
self
.
__playingMode
)
if
self
.
__playingMode
==
PlayingMode
.
TOURNOI
:
...
...
@@ -190,10 +192,14 @@ class Table(object):
self
.
__mainMutex
.
release
()
def
__nextStep
(
self
):
## Method called when a turn of bet has ended, and the next step of the
# hand is to begin.
# It will check if the hand has already ended (everybody folded,
# all-ins, etc), or simply gather the money bet by the player and go on
# to the next stage of the hand.
self
.
__currentBet
=
0
self
.
__minRaise
=
self
.
__blind
self
.
__pickUpBets
()
# Check if hand has already ended
if
self
.
__checkEndOfHand
():
self
.
__givePot
()
self
.
__button
=
self
.
__playerAtPos
(
1
)
...
...
@@ -226,6 +232,9 @@ class Table(object):
self
.
__nextPos
()
def
__pickUpBets
(
self
):
## Gather the money that was bet by the player and gives it to the pot.
# This method is quite tricky as it must handle all-ins and side pots,
# so many turns of gathering may be required.
pickUpDone
=
False
minAllInValue
=
0
while
not
pickUpDone
:
...
...
@@ -250,6 +259,9 @@ class Table(object):
return
def
__checkEndOfHand
(
self
):
## This method determines if the hand has ended, either by finishing
# the last round of bets, or premature folds/all-ins.
# Returns true if the hand has ended.
handEnded
=
False
if
self
.
__gameState
==
GameState
.
RIVER
or
handEnded
==
True
:
handEnded
=
True
...
...
@@ -262,8 +274,16 @@ class Table(object):
return
handEnded
def
__givePot
(
self
):
# Only one player left
## This method is called when the hand has ended, and the money
# gathered in the pot needs to be redistributed.
# If the hand ended before the river with all-ins, additionnal cards
# must first be drawn to complete the board cards.
# Each side pot is shared between the players allowed to, starting
# the player or players with the best hand down to the players with the
# the lesser hands (thus satisfying both situations of split and side
# pots).
if
self
.
__nbrPlayersInHand
==
1
:
# Only one player left
winningPlayer
=
self
.
__players
[
0
]
for
(
i
,
p
)
in
enumerate
(
self
.
__players
):
if
p
.
isPlaying
:
...
...
@@ -299,7 +319,8 @@ class Table(object):
print
(
"Player {} ({}{}) : {}"
.
format
(
p
.
name
,
p
.
holeCards
[
0
]
.
cardStr
(),
p
.
holeCards
[
1
]
.
cardStr
(),
p
.
hand
.
handStr
()))
remainingPlayers
.
sort
()
remainingPlayers
.
reverse
()
# class players by equivalent classes
# Class players by equivalent classes (all players in the class
# have a hand of identical value, thus needing a split pot)
classedPlayers
=
[[
remainingPlayers
[
0
]]]
for
i
in
range
(
1
,
len
(
remainingPlayers
)):
if
not
remainingPlayers
[
i
]
<
classedPlayers
[
-
1
][
0
]:
...
...
@@ -307,13 +328,17 @@ class Table(object):
else
:
classedPlayers
.
append
([
remainingPlayers
[
i
]])
for
l
in
classedPlayers
:
# Start with the players with the best hand
for
k
in
range
(
len
(
self
.
__pots
)):
# Give pots from the lesser valued on onwards
nbrSharing
=
0
for
i
in
range
(
len
(
l
)):
# Count number of players that share the pot
if
l
[
i
]
.
potId
==
-
1
or
l
[
i
]
.
potId
>=
k
:
nbrSharing
+=
1
if
nbrSharing
and
self
.
__pots
[
k
]:
for
i
in
range
(
len
(
l
)):
# Give away the pot to the players who desserve it
if
l
[
i
]
.
potId
==
-
1
or
l
[
i
]
.
potId
>=
k
:
l
[
i
]
.
receiveChip
(
int
(
self
.
__pots
[
k
]
/
nbrSharing
))
print
(
"Player {} receives {} from pot {}."
.
format
(
l
[
i
]
.
name
,
int
(
self
.
__pots
[
k
]
/
nbrSharing
),
k
))
...
...
@@ -324,6 +349,7 @@ class Table(object):
return
def
__isBettingDone
(
self
):
## Check wether to go to the next player or next stage of the hand
nbrInHand
=
0
for
p
in
self
.
__players
:
if
p
.
isInHand
:
...
...
@@ -336,7 +362,9 @@ class Table(object):
return
True
def
playerAction
(
self
,
action
,
playerId
,
amount
):
# timer management
## Methode called from the front end.
# Checks if the action is globally valid, then call the specific method
# that will check if the precise action is valid.
self
.
__mainMutex
.
acquire
()
self
.
__timer
.
cancel
()
p
=
self
.
__players
[
playerId
]
...
...
@@ -368,6 +396,9 @@ class Table(object):
self
.
__mainMutex
.
release
()
return
True
## Specific action functions, they check the validity of the demand then
# transfers it to the player instance and returns wether the action
# succeded or not.
def
__fold
(
self
,
p
):
if
not
p
.
fold
():
print
(
"Player {} cant fold, fold failed (unexpected)."
.
format
(
p
.
name
))
...
...
@@ -412,9 +443,8 @@ class Table(object):
return
True
# State Table
def
state
(
self
,
userId
):
# Json state for the front end.
rtn
=
json
.
dumps
({
"pot"
:
self
.
__pots
[
0
],
"activePlayer"
:
self
.
__activePlayer
,
...
...
@@ -442,12 +472,14 @@ class Table(object):
return
rtn
def
getPlayerIndex
(
self
,
userId
):
# Transforms a usedId into the position in the player list.
for
(
i
,
p
)
in
enumerate
(
self
.
__players
):
if
p
.
uniqueId
==
userId
:
return
i
return
-
1
def
__getHoleCards
(
self
,
userId
):
# Returns hole cards to be sent with the json.
rtn
=
[]
userIndex
=
self
.
getPlayerIndex
(
userId
)
if
userIndex
==
-
1
:
...
...
@@ -471,6 +503,7 @@ class Table(object):
return
rtn
def
__getBettingRange
(
self
,
userId
):
# Returns betting range to be sent with the json.
userIndex
=
self
.
getPlayerIndex
(
userId
)
if
userIndex
==
-
1
:
return
[]
...
...
@@ -478,6 +511,7 @@ class Table(object):
return
[
self
.
__currentBet
+
self
.
__minRaise
-
p
.
chipsOnTable
,
p
.
remainingChips
]
def
__availableActions
(
self
,
userId
):
# Returns all of the actions that a player may do (sent with the json).
userIndex
=
self
.
getPlayerIndex
(
userId
)
if
userIndex
==
-
1
:
return
[]
...
...
@@ -495,6 +529,7 @@ class Table(object):
return
rslt
def
__getAmountToCall
(
self
,
userId
):
# Returns the amount required to call (sent with the json).
userIndex
=
self
.
getPlayerIndex
(
userId
)
if
userIndex
==
-
1
:
return
0
...
...
@@ -502,6 +537,8 @@ class Table(object):
return
self
.
__currentBet
-
p
.
chipsOnTable
def
__defaultActionCallback
(
self
):
## Callback for the player time-out timer, performs the best action
# available without putting money out.
activePlayerId
=
self
.
__players
[
self
.
__activePlayer
]
.
uniqueId
if
"check"
in
self
.
__availableActions
(
activePlayerId
):
self
.
playerAction
(
"check"
,
self
.
__activePlayer
,
0
)
...
...
@@ -512,6 +549,8 @@ class Table(object):
self
.
__bCastCB
()
def
__calculateBlinds
(
self
):
## Sets blind depending on time elapsed since the first hand
# (tournament mode only)
now
=
time
.
time
()
elapsed
=
now
-
self
.
__startTime
val
=
int
(
exp
(
elapsed
/
60
/
7
)
+
1
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment