132 lines
3.3 KiB
Python
132 lines
3.3 KiB
Python
from random import shuffle
|
|
from typing import List, Dict, Optional
|
|
from collections import deque
|
|
|
|
nums = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
|
|
suits = ['H', 'S', 'D', 'C']
|
|
|
|
|
|
def get_deck(add_jokers: bool=False) -> deque:
|
|
if add_jokers:
|
|
jokers = ['J', 'J']
|
|
else:
|
|
jokers = []
|
|
return deque([n + s for n in nums for s in suits] + jokers)
|
|
|
|
|
|
def create_new_random_card_deck(add_jokers: bool=False) -> deque:
|
|
deck = get_deck(add_jokers)
|
|
shuffle(deck)
|
|
return deck
|
|
|
|
|
|
class CamelGame:
|
|
deck: deque
|
|
ace_position: dict
|
|
|
|
side_list: list
|
|
side_length = 8
|
|
side_open = 0
|
|
|
|
state: str
|
|
|
|
bets: List[Dict]
|
|
|
|
def __init__(self):
|
|
self.deck = create_new_random_card_deck(False)
|
|
for ace in ['AH', 'AS', 'AD', 'AC']:
|
|
self.deck.remove(ace) # remove the aces
|
|
|
|
self.ace_position = {
|
|
'AH': 0,
|
|
'AS': 0,
|
|
'AD': 0,
|
|
'AC': 0,
|
|
}
|
|
|
|
self.side_list = []
|
|
|
|
self.state = None
|
|
self.bets = []
|
|
|
|
def init_game(self):
|
|
for _ in range(self.side_length):
|
|
self.side_list.append(self.deck.pop())
|
|
|
|
self.state = 'initialized'
|
|
|
|
def do_round(self) -> Optional[str]:
|
|
if self.state != 'active':
|
|
print("Game is not stated yet or already done")
|
|
return None
|
|
|
|
card = self.popcard()
|
|
|
|
if any(v == self.side_length for v in self.ace_position.values()):
|
|
self.state = 'done'
|
|
|
|
return card
|
|
|
|
def bet(self, user: str, suit: str, amount: int) -> bool:
|
|
if self.state != 'initialized':
|
|
return False
|
|
if any(b['user'] == user for b in self.bets):
|
|
return False
|
|
if suit not in suits:
|
|
return False
|
|
self.bets.append({'user': user, 'suit': suit, 'amount': amount})
|
|
return True
|
|
|
|
def start_game(self):
|
|
if self.state != 'initialized':
|
|
return False
|
|
self.state = 'active'
|
|
return True
|
|
|
|
def get_drinks(self) -> Optional[Dict]:
|
|
if self.state != 'done':
|
|
return None
|
|
result = {}
|
|
winner = self.get_winner()[-1]
|
|
|
|
drinks = sum(map(lambda b: b['amount'], filter(lambda b: b['suit'] == winner, self.bets)))
|
|
|
|
for bet in self.bets:
|
|
if bet['suit'] == winner:
|
|
mdrinks = 0
|
|
else:
|
|
mdrinks = drinks + bet['amount']
|
|
result[bet['user']] = mdrinks
|
|
|
|
return result
|
|
|
|
def get_winner(self) -> Optional[str]:
|
|
for card, pos in self.ace_position.items():
|
|
if pos == self.side_length:
|
|
return card
|
|
return None
|
|
|
|
def get_open_side_cards(self) -> list:
|
|
open_cards = self.side_list[:self.side_open]
|
|
return open_cards + ['XX'] * (self.side_length - self.side_open)
|
|
|
|
def popcard(self) -> str:
|
|
next_card = self.deck.pop()
|
|
move_card = 'A' + next_card[-1]
|
|
|
|
self.ace_position[move_card] += 1
|
|
|
|
self.check_and_open_side()
|
|
|
|
return move_card
|
|
|
|
def check_and_open_side(self):
|
|
if not all(v > self.side_open for v in self.ace_position.values()):
|
|
return
|
|
|
|
opened_card = self.side_list[self.side_open]
|
|
moved_ace = 'A' + opened_card[-1]
|
|
self.ace_position[moved_ace] = self.side_open
|
|
|
|
self.side_open += 1
|