import os
import time
from typing import Any, Dict, List
from . import viewer
def _parse_action_string(config: Dict[str, Any], done: bool) -> str:
action_string = ""
prev_action = config["prev_action"]
if not done:
if prev_action is not None:
action_string = "Player {} {}"
player, bet, fold = prev_action
if fold:
action = "folded "
else:
if bet:
action = "bet {} ".format(bet)
else:
action = "checked "
action_string = action_string.format(player + 1, action)
action_string += "Action on Player {}".format(config["action"] + 1)
return action_string
def _parse_win_string(config: Dict[str, Any], done: bool) -> str:
win_string = ""
if done:
win_string = "Player"
if sum(payout > 0 for payout in config["payouts"]) > 1:
win_string += "s {} won {} respectively"
else:
win_string += " {} won {}"
players = []
payouts = []
for player, payout in enumerate(config["payouts"]):
if payout > 0:
players.append(str(player + 1))
payouts.append(str(payout))
win_string = win_string.format(", ".join(players), ", ".join(payouts))
return win_string
[docs]class ASCIIViewer(viewer.PokerViewer):
"""Poker game renderer which prints an ascii representation of the
table state to the terminal
Parameters
----------
num_players : int
number of players
num_hole_cards : int
number of hole cards
num_community_cards : int
number of community cards
"""
POS_DICT = {
2: [0, 5],
3: [0, 3, 6],
4: [0, 2, 4, 6],
5: [0, 2, 4, 6, 8],
6: [0, 1, 3, 5, 6, 8],
7: [0, 1, 3, 5, 6, 7, 9],
8: [0, 1, 2, 4, 5, 6, 7, 9],
9: [0, 1, 2, 4, 5, 6, 7, 8, 9],
10: list(range(10)),
}
KEYS = (
["p{}".format(idx) for idx in range(10)]
+ ["p{}c".format(idx) for idx in range(10)]
+ ["a{}".format(idx) for idx in range(10)]
+ ["b{}".format(idx) for idx in range(10)]
+ ["sb", "bb", "ccs", "pot", "action"]
)
def __init__(
self, num_players: int, num_hole_cards: int, num_community_cards: int, **kwargs
) -> None:
super(ASCIIViewer, self).__init__(
num_players, num_hole_cards, num_community_cards, **kwargs
)
dir_path = os.path.dirname(os.path.realpath(__file__))
with open("{}/ascii_table.txt".format(dir_path), "r") as file:
self.table = file.read()
self.player_pos = self.POS_DICT[num_players]
def _parse_string(self, config: Dict[str, Any]) -> str:
action = config["action"]
button = config["button"]
done = config["done"]
positions = ["p{}".format(idx) for idx in self.player_pos]
players = self._parse_players(config, done, action)
action_string = _parse_action_string(config, done)
win_string = _parse_win_string(config, done)
str_config = {key: "" for key in self.KEYS}
# community cards
ccs = [str(card) for card in config["community_cards"]]
ccs += ["--"] * (self.num_community_cards - len(ccs))
ccs_string = "[" + ",".join(ccs) + "]"
str_config["ccs"] = ccs_string
# pot
if not done:
str_config["pot"] = "{:,}".format(config["pot"])
str_config["a{}".format(self.player_pos[action])] = "X"
else:
str_config["pot"] = "0"
# button + player positions
str_config["b{}".format(self.player_pos[button])] = "D "
street_commits = config["street_commits"]
all_in = config["all_in"]
iterator = zip(players, street_commits, positions, all_in)
for player, street_commit, pos, all_in in iterator:
str_config[pos] = player
str_config[pos + "c"] = "{:,}".format(street_commit)
if all_in and not done:
str_config["a" + pos[1:]] = "A"
# payouts
if done:
payouts: List[int] = config["payouts"]
for payout, pos in zip(payouts, positions):
str_config[pos + "c"] = "{:,}".format(payout)
# action + win string
str_config["action"] = action_string
str_config["win"] = win_string
string = self.table.format(**str_config)
return string
def _parse_players(self, config: Dict[str, Any], done: bool, action: int):
players = []
iterator = zip(config["hole_cards"], config["stacks"], config["active"])
for idx, (hand, stack, active) in enumerate(iterator):
if not active:
players.append(
"{:2}. ".format(idx + 1)
+ ",".join(["--"] * self.num_hole_cards)
+ " {:,}".format(stack)
)
continue
if done or idx == action:
players.append(
"{:2}. ".format(idx + 1)
+ ",".join([str(card) for card in hand])
+ " {:,}".format(stack)
)
continue
players.append(
"{:2}. ".format(idx + 1)
+ ",".join(["??"] * self.num_hole_cards)
+ " {:,}".format(stack)
)
return players
[docs] def render(self, config: Dict[str, Any], sleep: float = 0) -> None:
"""Render ascii table representation based on the table
configuration
Parameters
----------
config : Dict[str, Any]
sleep : float, optional
sleep time after render, by default 0
Examples
--------
>>> from clubs import Card
>>> config = {
... 'action': 0, # int - position of active player
... 'active': [True, True], # List[bool] - list of active players
... 'all_in': [False, False], # List[bool] - list of all in players
... 'community_cards': [], # List[Card] - list of community cards
... 'dealer': 0, # int - position of dealer
... 'done': False, # bool - toggle if hand is completed
... 'hole_cards': [[Card("Ah")], [Card("Ac")]], # List[List[Card]] -
... # list of list of hole card
... 'pot': 10, # int - chips in pot
... 'payouts': [0, 0], # List[int] - list of chips won for each player
... 'prev_action': [1, 10, 0], # Tuple[int, int, int] -
... # last position bet and fold
... 'street_commits': [10, 20] # List[int] - list of number of
... # chips added to pot from each
... # player on current street
... 'stacks': [100, 100] # List[int] - list of stack sizes
... }
"""
string = self._parse_string(config)
print(string)
if sleep:
time.sleep(sleep)