first commit
This commit is contained in:
238
blackjack/blackjack.py
Normal file
238
blackjack/blackjack.py
Normal file
@@ -0,0 +1,238 @@
|
||||
import random
|
||||
|
||||
|
||||
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
|
||||
from maubot import Plugin, MessageEvent
|
||||
from maubot.handlers import command
|
||||
|
||||
class BlackjackBot(Plugin):
|
||||
|
||||
values = ['2','3','4','5','6','7','8','9','10','Jack','Queen','King','Ace']
|
||||
suites = ['Hearts', 'Clubs', 'Diamonds', 'Spades']
|
||||
deck = []
|
||||
players = []
|
||||
game_pending = False
|
||||
game_started = False
|
||||
awaiting_commands = False
|
||||
player_cards = {}
|
||||
player_score = {}
|
||||
dealer_cards = []
|
||||
dealer_score = 0
|
||||
player_status = {}
|
||||
|
||||
def init_game(self):
|
||||
self.deck = [(card, category) for category in self.suites for card in self.values]
|
||||
|
||||
|
||||
def end_game(self):
|
||||
self.players = []
|
||||
self.game_pending = False
|
||||
self.game_started = False
|
||||
self.awaiting_commands = False
|
||||
self.player_cards = {}
|
||||
self.player_score = {}
|
||||
self.dealer_cards = []
|
||||
self.dealer_score = 0
|
||||
self.player_status = {}
|
||||
|
||||
def card_value(self, card):
|
||||
if card[0] in ['Jack', 'Queen', 'King']:
|
||||
return 10
|
||||
elif card[0] == 'Ace':
|
||||
return 11
|
||||
else:
|
||||
return int(card[0])
|
||||
|
||||
def get_score(self, cards):
|
||||
score = 0
|
||||
aces = 0
|
||||
for card in cards:
|
||||
score += self.card_value(card)
|
||||
if (card[0] == 'Ace'):
|
||||
aces += 1
|
||||
while (score > 21 and aces > 0):
|
||||
aces -= 1
|
||||
score -= 10
|
||||
return score
|
||||
|
||||
|
||||
def cards_named(self, cards):
|
||||
named_list = []
|
||||
for card in cards:
|
||||
named_list.append(card[0] + " of " + card[1])
|
||||
return named_list
|
||||
|
||||
def shuffle_deck(self) -> None:
|
||||
random.shuffle(self.deck)
|
||||
|
||||
def add_player(self, player) -> None:
|
||||
self.players.append(player)
|
||||
|
||||
async def dealers_turn(self, evt: MessageEvent) -> None:
|
||||
players_bust = 0
|
||||
for player in self.players:
|
||||
if (self.player_status[player] == -1):
|
||||
players_bust += 1
|
||||
if (players_bust == len(self.players)):
|
||||
for player in self.players:
|
||||
await evt.respond("Player " + player + " loses")
|
||||
self.end_game()
|
||||
return
|
||||
|
||||
await evt.respond("Cards of Dealer: " + ', '.join(self.cards_named(self.dealer_cards)))
|
||||
await evt.respond("Score of Dealer: " + str(self.dealer_score))
|
||||
|
||||
while (self.dealer_score < 17):
|
||||
await evt.respond("Dealer draws")
|
||||
self.dealer_cards.append(self.deck.pop())
|
||||
self.dealer_score = self.get_score(self.dealer_cards)
|
||||
await evt.respond("Cards of Dealer: " + ', '.join(self.cards_named(self.dealer_cards)))
|
||||
await evt.respond("Score of Dealer: " + str(self.dealer_score))
|
||||
if (self.dealer_score > 21):
|
||||
await evt.respond("Dealer busts!")
|
||||
for player in self.players:
|
||||
if (self.player_status[player] != -1):
|
||||
await evt.respond("Player " + player + " wins!")
|
||||
elif (self.player_status[player] == -1):
|
||||
await evt.respond("Player " + player + " loses")
|
||||
else:
|
||||
for player in self.players:
|
||||
if (self.player_status[player] != -1):
|
||||
if (self.player_score[player] > self.dealer_score):
|
||||
await evt.respond("Player " + player + " wins!")
|
||||
elif (self.player_score[player] == self.dealer_score):
|
||||
await evt.respond("Player " + player + " pushes")
|
||||
elif (self.player_score[player] < self.dealer_score):
|
||||
await evt.respond("Player " + player + " loses")
|
||||
elif (self.player_status[player] == -1):
|
||||
await evt.respond("Player " + player + " loses")
|
||||
self.end_game()
|
||||
|
||||
def bj_match(self, command: str) -> bool:
|
||||
return command in ["blackjack", "bj"]
|
||||
|
||||
@command.new(aliases=bj_match)
|
||||
async def blackjack(self, evt: MessageEvent) -> None:
|
||||
if ( not self.game_pending and not self.game_started ):
|
||||
self.game_pending = True;
|
||||
await evt.respond("Starting a game of Blackjack, type !join to play")
|
||||
|
||||
def join_match(self, command: str) -> bool:
|
||||
return command in ["join", "j"]
|
||||
|
||||
@command.new(aliases=join_match)
|
||||
async def join(self, evt: MessageEvent) -> None:
|
||||
if (self.game_pending):
|
||||
if (evt.sender in self.players):
|
||||
return
|
||||
self.add_player(evt.sender)
|
||||
await evt.respond("Player " + evt.sender + " has joined the game!")
|
||||
await evt.respond("When all players have joined, type !begin to start the game")
|
||||
|
||||
|
||||
def begin_match(self, command: str) -> bool:
|
||||
return command in ["begin", "b"]
|
||||
|
||||
@command.new(aliases=begin_match)
|
||||
async def begin(self, evt: MessageEvent) -> None:
|
||||
if (self.game_pending):
|
||||
self.game_pending = False
|
||||
self.game_started = True
|
||||
self.init_game()
|
||||
self.shuffle_deck()
|
||||
for player in self.players:
|
||||
self.player_cards[player] = [self.deck.pop(), self.deck.pop()]
|
||||
self.player_status[player] = 0
|
||||
self.player_score[player] = self.get_score(self.player_cards[player])
|
||||
|
||||
self.dealer_cards = [self.deck.pop(), self.deck.pop()]
|
||||
self.dealer_score = self.get_score(self.dealer_cards)
|
||||
for player in self.players:
|
||||
await evt.respond("Cards " + player + " has: " + ', '.join(self.cards_named(self.player_cards[player])))
|
||||
await evt.respond("Score of " + player + ": "+ str(self.player_score[player]))
|
||||
if (self.player_score[player] == 21):
|
||||
await evt.respond("Player " + player + " has blackjack!")
|
||||
self.player_status[player] = 2
|
||||
if (self.dealer_score == 21):
|
||||
await evt.respond("Cards of Dealer: " + ' '.join(self.cards_named(self.dealer_cards)))
|
||||
await evt.respond("Dealer has blackjack!")
|
||||
for player in self.players:
|
||||
if (self.player_score[player] == 21):
|
||||
await evt.respond("Player " + player + " pushes")
|
||||
elif (self.player_score[player] < 21):
|
||||
await evt.respond("Player " + player + " loses")
|
||||
self.end_game()
|
||||
return
|
||||
else:
|
||||
await evt.respond("Cards of Dealer: " + ' '.join(self.cards_named(self.dealer_cards[1:])))
|
||||
self.awaiting_commands = True
|
||||
|
||||
# edge case handling when all players get blackjack
|
||||
waiting_for_players = 0
|
||||
for player in self.players:
|
||||
if (self.player_status[player] == 0):
|
||||
waiting_for_players += 1
|
||||
if (waiting_for_players == 0):
|
||||
self.end_game()
|
||||
|
||||
def hit_match(self, command: str) -> bool:
|
||||
return command in ["hit", "h"]
|
||||
|
||||
@command.new(aliases=hit_match)
|
||||
async def hit(self, evt: MessageEvent) -> None:
|
||||
player = evt.sender
|
||||
if (self.awaiting_commands and player in self.players):
|
||||
if (self.player_status[player] != 0):
|
||||
return
|
||||
self.player_cards[player].append(self.deck.pop())
|
||||
self.player_score[player] = self.get_score(self.player_cards[player])
|
||||
await evt.respond("Cards " + player + " has: " + ', '.join(self.cards_named(self.player_cards[player])))
|
||||
await evt.respond("Score of " + player + ": "+ str(self.player_score[player]))
|
||||
if (self.player_score[player] > 21 ):
|
||||
self.player_status[player] = -1
|
||||
await evt.respond("Player " + player + " busts!")
|
||||
|
||||
waiting_for_players = 0
|
||||
for player in self.players:
|
||||
if (self.player_status[player] == 0):
|
||||
waiting_for_players += 1
|
||||
|
||||
if (waiting_for_players == 0):
|
||||
await self.dealers_turn(evt)
|
||||
|
||||
def stand_match(self, command: str) -> bool:
|
||||
return command in ["stand", "stay", "s"]
|
||||
|
||||
@command.new(aliases=stand_match)
|
||||
async def stand(self, evt: MessageEvent) -> None:
|
||||
player = evt.sender
|
||||
if (self.awaiting_commands and player in self.players):
|
||||
if (self.player_status[player] != 0):
|
||||
return
|
||||
self.player_status[player] = 1
|
||||
|
||||
waiting_for_players = 0
|
||||
for player in self.players:
|
||||
if (self.player_status[player] == 0):
|
||||
waiting_for_players += 1
|
||||
|
||||
if (waiting_for_players == 0):
|
||||
await self.dealers_turn(evt)
|
||||
|
||||
|
||||
@command.new("end")
|
||||
async def end(self, evt: MessageEvent) -> None:
|
||||
if (self.game_pending or self.game_started):
|
||||
self.end_game()
|
||||
await evt.respond("Blackjack has ended")
|
||||
|
||||
|
||||
@command.new("help")
|
||||
async def help(self, evt: MessageEvent) -> None:
|
||||
await evt.respond("!blackjack to initiate a new game players can join")
|
||||
await evt.respond("!join to join a pending game")
|
||||
await evt.respond("!begin to start once everyone is on")
|
||||
await evt.respond("!hit to draw a new card")
|
||||
await evt.respond("!stand to stop drawing")
|
||||
await evt.respond("!end to stop a currently running game")
|
||||
|
||||
Reference in New Issue
Block a user