commit 6fa67ece7d1aade1eff583afcb983ad973507db6 Author: fejy Date: Sun Jan 12 13:19:14 2025 -0500 first commit diff --git a/blackjack/blackjack.py b/blackjack/blackjack.py new file mode 100644 index 0000000..db3ad05 --- /dev/null +++ b/blackjack/blackjack.py @@ -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") + diff --git a/blackjack/maubot.yaml b/blackjack/maubot.yaml new file mode 100644 index 0000000..30af7f2 --- /dev/null +++ b/blackjack/maubot.yaml @@ -0,0 +1,6 @@ +maubot: 0.1.0 +id: nearfuture.maubot.blackjack +version: 0.1.0 +modules: + - blackjack +main_class: BlackjackBot