Files
camel_race/game.py
2018-06-17 20:28:44 +02:00

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