From 33a1fb01f632def8bb5d95ebcdb21c0aa38ef3e4 Mon Sep 17 00:00:00 2001 From: BigGamerGary Date: Wed, 19 Jul 2023 10:45:42 +1000 Subject: [PATCH] Base game works but no win logic --- Acronymbot.py | 9 +- BlackJack.py | 413 ++++++++++++-------------- BlackJack2.py | 167 ----------- BlackJackOld.py | 258 ++++++++++++++++ __pycache__/BlackJack.cpython-310.pyc | Bin 5929 -> 7207 bytes 5 files changed, 448 insertions(+), 399 deletions(-) delete mode 100644 BlackJack2.py create mode 100644 BlackJackOld.py diff --git a/Acronymbot.py b/Acronymbot.py index e21a209..d160a58 100644 --- a/Acronymbot.py +++ b/Acronymbot.py @@ -62,11 +62,11 @@ async def test(interaction:discord.Interaction): class HitOrStand(discord.ui.View): def __init__(self, *, timeout=180): super().__init__(timeout=timeout) - self.content = None + self.content = False @discord.ui.button(label="Hit", style=discord.ButtonStyle.green) async def hit(self, interaction: discord.Interaction, button: discord.ui.Button): - self.content = "h" + self.content = True for child in self.children: child.disabled = True await interaction.response.edit_message(content="You Hit!", view=self) @@ -74,7 +74,7 @@ class HitOrStand(discord.ui.View): @discord.ui.button(label="Stand", style=discord.ButtonStyle.red) async def stand(self, interaction: discord.Interaction, button: discord.ui.Button): - self.content = "s" + self.content = False for child in self.children: child.disabled = True await interaction.response.edit_message(content="You stood!", view=self) @@ -85,7 +85,8 @@ async def bj(interaction: discord.Interaction): discinput = lambda m: discordInput(interaction, m) discoutput = lambda m: discordOutput(interaction, m) await interaction.response.send_message("Let's play Black Jack!") - await blackJack.play_game(interaction.user.id, 100, discinput, discoutput) + await blackJack.play_game(discinput, discoutput) + # await blackJack.play_game(interaction.user.id, 100, discinput, discoutput) async def discordInput(interaction: discord.Interaction, message:str): response = HitOrStand() diff --git a/BlackJack.py b/BlackJack.py index ff1462c..18734f2 100644 --- a/BlackJack.py +++ b/BlackJack.py @@ -1,258 +1,215 @@ import random -import Ledger +from Ledger import Ledger # Game States INIT = 0 -PLAYING = 1 -ENDING = 2 +PLAYERTURN = 1 +DEALERTURN = 2 FINISHED = 3 OVER = 5 CHECKING = 6 +""" +Class which describes playing cards +""" +class Card(): + """ + A joker card has value 0 and suit 0 + """ + HEARTS = 1 + DIAMONDS = 2 + SPADES = 3 + CLUBS = 4 -def convertNumberToCard(cardNumber): - # Cards index from 0 i.e ace is 0, and the highest card value is 51 - if cardNumber <= 12: - cardSuit = "♣" - elif cardNumber <= 25: - cardSuit = "♦" - elif cardNumber <= 38: - cardSuit = "♥" - elif cardNumber <= 51: - cardSuit = "♠" + def __init__(self, value, suit) -> None: + self.value = value + self.suit = suit + self.hidden = False - cardNumber = cardNumber % 13 + def turn_card(self): + # XOR to flip hidden element + self.hidden = self.hidden != True - if cardNumber == 0: - cardNumber = "A" - elif cardNumber == 10: - cardNumber = "J" - elif cardNumber == 11: - cardNumber = "Q" - elif cardNumber == 12: - cardNumber = "K" - else: - cardNumber += 1 - - return "{value}{suit} ".format(value=str(cardNumber), suit=cardSuit) - -def generateDeck(): - return [x for x in range(0, 51)] - -def addCardToHand(hand, deck): - card = deck.pop(0) - hand.append(card) - -def generateHand(hand, deck, handSize = 2): - i = 0 - while i < handSize: - addCardToHand(hand, deck) - i += 1 - -def handNumbersToCards(hand): - cards = "" - for card in hand: - cards += convertNumberToCard(card) - return cards - -def getHandTotal(hand): - cardValue = lambda c: min(c % 13 + 1, 10) - i = 0 - aces = 0 - for card in hand: - card = cardValue(card) - if card == 1: - aces += 1 - else: - i += card + def get_value(self): + return self.value - while aces > 0: - if i < 20: - card = 11 - if (i + card) > 21: - card = 1 - i += card - aces -= 1 - return i + def get_suit(self): + return self.suit -def showDeck(deck): - string = "" - for card in deck: - string += convertNumberToCard(card) - return string + def __str__(self) -> str: + suits = ["J", "♥", "♦", "♠", "♣"] + special_cards = {1: "A", 11: "J", 12: "Q", 13: "K"} + strValue = "" -class BlackJack: - def __init__(self): - self.gameInSession = False - self.playerTurn = True - self.deck = generateDeck() - random.shuffle(self.deck) + if self.value in special_cards.keys(): + strValue = special_cards[self.value] + else: + strValue = str(self.value) + + string = "" + string = f"{suits[self.suit]}{strValue}" + if self.hidden: + string = "??" + return string + + def __repr__(self) -> str: + return str(self) +""" +Class for interacting with a deck of cards +""" +class Deck(): + def __init__(self, joker = False) -> None: + self.deck = [] self.discard = [] - self.playerHand = [] - self.dealerHand = [] - self.ledger = Ledger.Ledger() + self.joker = joker - def returnCards(self): - self.discard.extend(self.playerHand) - self.playerHand.clear() - self.discard.extend(self.dealerHand) - self.dealerHand.clear() + self.deck.extend([Card(x, Card.HEARTS) for x in range(1, 13)]) + self.deck.extend([Card(x, Card.DIAMONDS) for x in range(1, 13)]) + self.deck.extend([Card(x, Card.SPADES) for x in range(1, 13)]) + self.deck.extend([Card(x, Card.CLUBS) for x in range(1, 13)]) - def deal(self): - generateHand(self.playerHand, self.deck) - generateHand(self.dealerHand, self.deck) + if joker: + self.deck.append(Card(0, 0)) def shuffle(self): - self.deck.extend(self.discard) - self.discard.clear() random.shuffle(self.deck) - def stand(self): - if self.playerTurn: - self.playerTurn = False - - def hit(self): - if self.playerTurn: - addCardToHand(self.playerHand, self.deck) - self.playerTurn = False - else: - addCardToHand(self.dealerHand, self.deck) - self.playerTurn = True - - def checkHandState(self, hand): - # Check the hand state and return w if game is won, l if lost and c for continue - total = getHandTotal(hand) - - if total == 21: - return "w" - elif total > 21: - return "l" - else: - return "c" - - def dealerHitLogic(self): - total = getHandTotal(self.dealerHand) - if total >= 17: - self.stand() - return True - else: - self.hit() - - - def checkGameOver(self, state): - gameOver = False - if state == "w": - gameOver = True - elif state == "l": - gameOver = True - return gameOver - - def compareHands(self): - dealerTotal = getHandTotal(self.dealerHand) - playerTotal = getHandTotal(self.playerHand) - if dealerTotal < playerTotal: - return "l" - else: - return "w" - - async def play_game(self, ID, bet, recv, send): - - if self.gameInSession: - await send("Fuck you") - return - else: - self.gameInSession = True - gameState = INIT + def sort(self): + self.deck.sort() + def take_from_deck(self): + card = self.deck.pop() + return card + + def return_to_deck_top(self, card): + self.deck.insert(0, card) + + def returnToDeckBottom(self, card): + self.deck.append(card) + + def addToDiscard(self, card): + self.discard.insert(0, card) + + def returnFromDiscard(self): + self.returnToDeckTop(self.discard.pop()) + + def __str__(self) -> str: + string = "" + for card in self.deck: + string += str(card) + return string + +class Hand(): + def __init__(self) -> None: + self.hand = [] + + def sortHand(self): + self.hand.sort() + + def add_to_hand(self, card): + self.hand.append(card) + + def remove_from_hand(self, index): + return self.hand.pop(index) + + def hide_card(self, index): + card = self.remove_from_hand(index) + card.turn_card() + self.add_to_hand(card) + + def __str__(self) -> str: + string = "" + for card in self.hand: + string += str(card) + string += " " + return string + + def __repr__(self) -> str: + value = 0 + for card in self.hand: + value += card.value + return str(value) + + def __iter__(self): + self.iter = iter(self.hand) + return self.iter + + def __next__(self): + return next(self.iter) + + +class BlackJack: + def __init__(self) -> None: + self.deck = Deck() + self.playerHand = Hand() + self.dealerHand = Hand() + self.ledger = Ledger() + + def deal_card(self, hand): + hand.add_to_hand(self.deck.take_from_deck()) + + def game_setup(self): + # Deal cards in alternate order + self.deck.shuffle() + for _ in range(2): + self.deal_card(self.playerHand) + self.deal_card(self.dealerHand) + + # Hide one of the dealers cards + self.dealerHand.hide_card(1) + + async def show_cards(self, send, displayDealerScore=False): + # Show Cards to player + string = f"Player Hand = {repr(self.playerHand)}: {self.playerHand}\nDealer Hand = ??: {self.dealerHand}" + if displayDealerScore: + string = f"Player Hand = {repr(self.playerHand)}: {self.playerHand}\nDealer Hand = {repr(self.dealerHand)}: {self.dealerHand}" + + await send(string) + + async def play_game(self, recv, send): + gameState = INIT + while gameState != OVER: - if gameState == INIT: + # TODO: Load player statistics + self.game_setup() + gameState = PLAYERTURN - self.returnCards() - playerStats = self.ledger.read(ID) - if playerStats is None: - self.ledger.write(ID) - playerStats = self.ledger.read(ID) - self.deal() - playerWinState = self.checkHandState(self.playerHand) - dealerWinState = self.checkHandState(self.dealerHand) + if gameState == PLAYERTURN: - play = None - playerStood = False - dealerStood = False - validInput = False - - gameState = CHECKING - - elif gameState == PLAYING: - - await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards( - self.playerHand) + "\n" + "Dealers hand = ??: " + convertNumberToCard(self.dealerHand[0]) + "??") - play = await recv("Hit or Stand?") - while not validInput: - if play == "h": - self.hit() - validInput = True - elif play == "s": - self.stand() - playerStood = True - validInput = True - - dealerStood = self.dealerHitLogic() - playerWinState = self.checkHandState(self.playerHand) - dealerWinState = self.checkHandState(self.dealerHand) - gameState = CHECKING - - elif gameState == ENDING: - - # Players turn - self.stand() - # Dealers turn - dealerStood = self.dealerHitLogic() - # Loop ends when game is over - dealerWinState = self.checkHandState(self.dealerHand) - if dealerStood: - - if dealerWinState == "c": - - dealerWinState = self.compareHands() - gameState = CHECKING - - elif gameState == CHECKING: - - if self.checkGameOver(playerWinState) or self.checkGameOver(dealerWinState): - gameState = FINISHED - elif playerStood: - gameState = ENDING + await self.show_cards(send) + playerHit = await recv("Hit or Stand?") + if playerHit: + self.deal_card(self.playerHand) else: - gameState = PLAYING - - elif gameState == FINISHED: - - await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards(self.playerHand) + - "\n" + "Dealers hand = " + str(getHandTotal(self.dealerHand)) + ": " + handNumbersToCards(self.dealerHand)) - if playerWinState == "w": - await send("You won!") - win = (2*bet, 1, 0, ID) - self.ledger.update(ID, win) - elif playerWinState == "l": - await send("You busted!") - loss = (-bet, 0, 1, ID) - self.ledger.update(ID, loss) - elif dealerWinState == "w": - await send("The Dealer reached 21 before you!") - loss = (-bet, 0, 1, ID) - self.ledger.update(ID, loss) - elif dealerWinState == "l": - await send("The Dealer busted before you!") - win = (2*bet, 1, 0, ID) - self.ledger.update(ID, win) - - self.returnCards() - if len(self.deck) < 0.25 * 52: - await send("Shuffling Deck") - self.shuffle() + gameState = DEALERTURN + if int(repr(self.playerHand)) >= 21: + + self.dealerHand.hide_card(1) + gameState = FINISHED + + if gameState == DEALERTURN: + + self.dealerHand.hide_card(1) + self.deal_card(self.dealerHand) + if int(repr(self.dealerHand)) >= 17: + gameState = FINISHED + + if gameState == FINISHED: + + await self.show_cards(send, True) + await send("You won or lost idk lmao") gameState = OVER - self.gameInSession = False + + +def main(): + game = BlackJack() + trueFalseInput = lambda x: input(x) == "h" + game.play_game(recv=trueFalseInput, send=print) + +if __name__ == "__main__": + main() + + diff --git a/BlackJack2.py b/BlackJack2.py deleted file mode 100644 index 62cfc6c..0000000 --- a/BlackJack2.py +++ /dev/null @@ -1,167 +0,0 @@ -import random -from Ledger import Ledger - -""" -Class which describes playing cards -""" -class Card(): - """ - A joker card has value 0 and suit 0 - """ - HEARTS = 1 - DIAMONDS = 2 - SPADES = 3 - CLUBS = 4 - - def __init__(self, value, suit) -> None: - self.value = value - self.suit = suit - self.hidden = False - - def turn_card(self): - # XOR to flip hidden element - self.hidden = self.hidden != True - - def get_value(self): - return self.value - - def get_suit(self): - return self.suit - - def __str__(self) -> str: - suits = ["J", "♥", "♦", "♠", "♣"] - special_cards = {1: "A", 11: "J", 12: "Q", 13: "K"} - strValue = "" - - if self.value in special_cards.keys(): - strValue = special_cards[self.value] - else: - strValue = str(self.value) - - string = "" - string = f"{suits[self.suit]}{strValue}" - if self.hidden: - string = "??" - return string - - def __repr__(self) -> str: - return str(self) -""" -Class for interacting with a deck of cards -""" -class Deck(): - def __init__(self, joker = False) -> None: - self.deck = [] - self.discard = [] - self.joker = joker - - self.deck.extend([Card(x, Card.HEARTS) for x in range(1, 13)]) - self.deck.extend([Card(x, Card.DIAMONDS) for x in range(1, 13)]) - self.deck.extend([Card(x, Card.SPADES) for x in range(1, 13)]) - self.deck.extend([Card(x, Card.CLUBS) for x in range(1, 13)]) - - if joker: - self.deck.append(Card(0, 0)) - - def shuffle(self): - random.shuffle(self.deck) - - def sort(self): - self.deck.sort() - - def take_from_deck(self): - card = self.deck.pop() - return card - - def return_to_deck_top(self, card): - self.deck.insert(0, card) - - def returnToDeckBottom(self, card): - self.deck.append(card) - - def addToDiscard(self, card): - self.discard.insert(0, card) - - def returnFromDiscard(self): - self.returnToDeckTop(self.discard.pop()) - - def __str__(self) -> str: - string = "" - for card in self.deck: - string += str(card) - return string - -class Hand(): - def __init__(self) -> None: - self.hand = [] - - def sortHand(self): - self.hand.sort() - - def add_to_hand(self, card): - self.hand.append(card) - - def remove_from_hand(self, index): - return self.hand.pop(index) - - def hide_card(self, index): - card = self.remove_from_hand(0) - card.turn_card() - self.add_to_hand(card) - - def __str__(self) -> str: - string = "" - for card in self.hand: - string += str(card) - string += " " - return string - - def __iter__(self): - self.iter = iter(self.hand) - return self.iter - - def __next__(self): - return next(self.iter) - - -class BlackJack: - def __init__(self) -> None: - self.deck = Deck() - self.playerHand = Hand() - self.dealerHand = Hand() - self.ledger = Ledger() - - def deal_card(self, hand): - hand.add_to_hand(self.deck.take_from_deck()) - - def game_setup(self): - # Deal cards in alternate order - self.deck.shuffle() - for _ in range(2): - self.deal_card(self.playerHand) - self.deal_card(self.dealerHand) - - # Hide one of the dealers cards - self.dealerHand.hide_card(1) - - def play_game(self): - # Load player statistics - - self.game_setup() - - # Show Cards to player - print("Player Hand:", end=" ") - print(self.playerHand) - print("Dealer Hand:", end=" ") - print(self.dealerHand) - - - -def main(): - game = BlackJack() - game.play_game() - -if __name__ == "__main__": - main() - - diff --git a/BlackJackOld.py b/BlackJackOld.py new file mode 100644 index 0000000..ff1462c --- /dev/null +++ b/BlackJackOld.py @@ -0,0 +1,258 @@ +import random +import Ledger + +# Game States +INIT = 0 +PLAYING = 1 +ENDING = 2 +FINISHED = 3 +OVER = 5 +CHECKING = 6 + + + +def convertNumberToCard(cardNumber): + # Cards index from 0 i.e ace is 0, and the highest card value is 51 + if cardNumber <= 12: + cardSuit = "♣" + elif cardNumber <= 25: + cardSuit = "♦" + elif cardNumber <= 38: + cardSuit = "♥" + elif cardNumber <= 51: + cardSuit = "♠" + + cardNumber = cardNumber % 13 + + if cardNumber == 0: + cardNumber = "A" + elif cardNumber == 10: + cardNumber = "J" + elif cardNumber == 11: + cardNumber = "Q" + elif cardNumber == 12: + cardNumber = "K" + else: + cardNumber += 1 + + return "{value}{suit} ".format(value=str(cardNumber), suit=cardSuit) + +def generateDeck(): + return [x for x in range(0, 51)] + +def addCardToHand(hand, deck): + card = deck.pop(0) + hand.append(card) + +def generateHand(hand, deck, handSize = 2): + i = 0 + while i < handSize: + addCardToHand(hand, deck) + i += 1 + +def handNumbersToCards(hand): + cards = "" + for card in hand: + cards += convertNumberToCard(card) + return cards + +def getHandTotal(hand): + cardValue = lambda c: min(c % 13 + 1, 10) + i = 0 + aces = 0 + for card in hand: + card = cardValue(card) + if card == 1: + aces += 1 + else: + i += card + + while aces > 0: + if i < 20: + card = 11 + if (i + card) > 21: + card = 1 + i += card + aces -= 1 + return i + +def showDeck(deck): + string = "" + for card in deck: + string += convertNumberToCard(card) + return string + +class BlackJack: + def __init__(self): + self.gameInSession = False + self.playerTurn = True + self.deck = generateDeck() + random.shuffle(self.deck) + self.discard = [] + self.playerHand = [] + self.dealerHand = [] + self.ledger = Ledger.Ledger() + + def returnCards(self): + self.discard.extend(self.playerHand) + self.playerHand.clear() + self.discard.extend(self.dealerHand) + self.dealerHand.clear() + + def deal(self): + generateHand(self.playerHand, self.deck) + generateHand(self.dealerHand, self.deck) + + def shuffle(self): + self.deck.extend(self.discard) + self.discard.clear() + random.shuffle(self.deck) + + def stand(self): + if self.playerTurn: + self.playerTurn = False + + def hit(self): + if self.playerTurn: + addCardToHand(self.playerHand, self.deck) + self.playerTurn = False + else: + addCardToHand(self.dealerHand, self.deck) + self.playerTurn = True + + def checkHandState(self, hand): + # Check the hand state and return w if game is won, l if lost and c for continue + total = getHandTotal(hand) + + if total == 21: + return "w" + elif total > 21: + return "l" + else: + return "c" + + def dealerHitLogic(self): + total = getHandTotal(self.dealerHand) + if total >= 17: + self.stand() + return True + else: + self.hit() + + + def checkGameOver(self, state): + gameOver = False + if state == "w": + gameOver = True + elif state == "l": + gameOver = True + return gameOver + + def compareHands(self): + dealerTotal = getHandTotal(self.dealerHand) + playerTotal = getHandTotal(self.playerHand) + if dealerTotal < playerTotal: + return "l" + else: + return "w" + + async def play_game(self, ID, bet, recv, send): + + if self.gameInSession: + await send("Fuck you") + return + else: + self.gameInSession = True + gameState = INIT + + while gameState != OVER: + + if gameState == INIT: + + self.returnCards() + playerStats = self.ledger.read(ID) + if playerStats is None: + self.ledger.write(ID) + playerStats = self.ledger.read(ID) + self.deal() + playerWinState = self.checkHandState(self.playerHand) + dealerWinState = self.checkHandState(self.dealerHand) + + play = None + playerStood = False + dealerStood = False + validInput = False + + gameState = CHECKING + + elif gameState == PLAYING: + + await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards( + self.playerHand) + "\n" + "Dealers hand = ??: " + convertNumberToCard(self.dealerHand[0]) + "??") + play = await recv("Hit or Stand?") + while not validInput: + if play == "h": + self.hit() + validInput = True + elif play == "s": + self.stand() + playerStood = True + validInput = True + + dealerStood = self.dealerHitLogic() + playerWinState = self.checkHandState(self.playerHand) + dealerWinState = self.checkHandState(self.dealerHand) + gameState = CHECKING + + elif gameState == ENDING: + + # Players turn + self.stand() + # Dealers turn + dealerStood = self.dealerHitLogic() + # Loop ends when game is over + dealerWinState = self.checkHandState(self.dealerHand) + if dealerStood: + + if dealerWinState == "c": + + dealerWinState = self.compareHands() + gameState = CHECKING + + elif gameState == CHECKING: + + if self.checkGameOver(playerWinState) or self.checkGameOver(dealerWinState): + gameState = FINISHED + elif playerStood: + gameState = ENDING + else: + gameState = PLAYING + + elif gameState == FINISHED: + + await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards(self.playerHand) + + "\n" + "Dealers hand = " + str(getHandTotal(self.dealerHand)) + ": " + handNumbersToCards(self.dealerHand)) + if playerWinState == "w": + await send("You won!") + win = (2*bet, 1, 0, ID) + self.ledger.update(ID, win) + elif playerWinState == "l": + await send("You busted!") + loss = (-bet, 0, 1, ID) + self.ledger.update(ID, loss) + elif dealerWinState == "w": + await send("The Dealer reached 21 before you!") + loss = (-bet, 0, 1, ID) + self.ledger.update(ID, loss) + elif dealerWinState == "l": + await send("The Dealer busted before you!") + win = (2*bet, 1, 0, ID) + self.ledger.update(ID, win) + + self.returnCards() + if len(self.deck) < 0.25 * 52: + await send("Shuffling Deck") + self.shuffle() + + gameState = OVER + self.gameInSession = False diff --git a/__pycache__/BlackJack.cpython-310.pyc b/__pycache__/BlackJack.cpython-310.pyc index febc2c103277ccb997f6993e718028f3096bf20c..2f67a35e85678362173b1de00525bb9f2bc42389 100644 GIT binary patch literal 7207 zcmbVRTW=f372erhl1qxBWXX1%B52vfX~Hyd-1L$lb!^L)6gzPk$5PUUal55CYuzYP zo?Rt2Apr?w^r1jo^r1kDw1AwV1>8T-AJ89A^mX6bKIyf2%S-xwXO|RLqFl5TW_B)T z=A1cm&NpX9-SP2~h2N={{-R$wX<7ebW%%cyauF%~DKc$o)wUY^+HJM28cLzuu(i{0 zwA*lXu94IEMqU>hg`)Mkr9EA|Z|UNW-SDJd(qpKPp$|ik?7i0<|$c zsgK>a8s%VIPp#QzCMfS%;G`BL)u#6#i&d|wIDakBOM%%_sPEa#DDPg5SsqynDf1gF z=f`LctcDWt6~wn8z60@Hh@Wc|^l=g1ZFpLQZWI%78>K{02$>Jcw`~#CZH%Y2DLsAP zZB%q&!K$5z-OEj*doPr#_{~&TyK8}|w$M~vZidwlo9)e@dbZl^=xVsR5>?L%ouP=v zWhTpDDbAZ9+BBVdi=F)+%Uttiq!4>&ZK*BGx3+BLO0#Th3v$@?`I-~wgkS8ERh(a5 z(K_g$*$spCZ8L_^ri|>NWhU_X;;rVZH=FI?Zu91Bx3#$*bfWO)b<F2r^dgEYRK6p z?OsKA4!RC8C1dLJbIM7k3z#3)mS|}TjfeOw1(7fMeUjtIC$CaIgRUd_nB$!C1Tyg8 zCYVt?JWj;TdzuuFAxo9lZ_mt6(_s?ZxP`(JRQH+MRvON#;ix+QJ9pdGg>9&F6*jZ0 z9#|h*<}0+GRqJtU+v(&YDetIl2Xrp2Yt?z&`qbKTKDB;tqs3Zv&5PPY$%UO2>$P00 z-q@sF{`0qgOuv6hzq{%853!mtG=o^Z6RS6Ct{D6tEpU&E-{XG9R?oh0p_UVs$L?Bi zFN~cqGKqRffj;hdBS)2ljqz|JXstBcve{w71MPeCuQ-p=N@wZdjum_#9lrl8<`CcU zR7JU}VwY9PcI_!xr;EQ{IkitA&S*Geo*t%&U@JR-sQymU6h`l)@0(x)%wHjM8jH8@ z2uaUF+YpxPwF$aTr@0>Zeq8eX^{(D*vt0K5JDbgR+Jn{TZVS!%D|0h978hb~_Ug=A zZ`WrR;{3w(nc2C8ICuHlyO$QsF$y)!jDTTIF%v;gvm~ZP|39EE!}ZalLJsgOsK%js zTqw)Sd9LSFoT*8nYJnj0BYs^(3Nwg%Qa?s3yq^Q|;V;Xm`h+#g;z6DMzP3U+xio`A75>M)oOFmw9th9*g&OY;q#93Az>Q8GGXb z=+O&EpK}|yfFF6=3U-IIs&?#O*>`N%A2+aO%Wjx&qWsW~?K5X%b@#xo#-(%Zl`v{` z*Eh~nErMI8tlrnD!vQ9rIoIyCn(gpB3VrJ2jQSeJ94VqXi{6YV&$HoM{nkVl+LZYY zvRM|si|l`x@CA-JYQnkyW5P3!nsB~9p`qv33bCu9rnsP2LLM-2PLB6DAKZAw{=8uodE$=g}VWEa2IgS5MeaDE_(jN#%ao8_(=YMokompewdb zl}6Ss!Fpg%2_!iPBM@wK*W*ICym|X}J22k^@hFTkuc6~jB(aG};Gl3%haF;0+Y}4p z`oyGhnk1&2u(pL0f{m_;M)JFefpsL|S5duU!VlybW@OZ777jDph7b3lH)ZB*bT@#b zq>5c`(E**um8iKE__s}W-RD-m1HzDKRU+_DivU@QLx4hRSvL>tWZj6n)B`(N`$M~) z7)vTqex(xzPymM<6lN-k@cgJN!r;5{F33b5Q>yovh;x|ckVsBnB-%kD5(G+dWq32p z_bJ6AL|N>TCt|y(yZ%Gc(mpeS3{xBuq^}zzj`KRk!v0_8JXe^FVq9)&jX4vC`hZk# zAnP5IwGa1YY=YL`XD05mW$kk1YS(^XWmoPrCK44Uk}q~Q5{WL6*QlWDSVBGz8%f3D zDJGk8T=h;4ZORZyMmp}tK)Na_8bKKMWtQM=1G?3gy`x^Xw$+^+Z5ZLYAsw_O-uWcT z51j-#oEB`!N)wytj0`Y0y@08 z$V`y)DofXxy~T{KX()*yry=elhlubZIyi}JfoGMKH|{z3LvX;qDaVkag_QYGKNpe0 zTgV0%vJ*Ugajf&i%}a1l&>p@yUDPFf^Lk8|@hxZ-cnAWIortEE}=6$1moOFM+b)@l1US+cRx%)nL^ybkdV7l zR=pD<#zBgVEL?Jb*iCkz)idTqUMT8u5XLg>Fxk%iUkp4G>1?4OjY#|CA!UQM5gfCPT`V(C~iQ(ot zvk_2mj|^zSgaX`X>5(EkTO47!bPNzVd?;oD@OwI zgxuE@AX%RC0Lg^e$+$Rp0QzrO%LPT&4))Vmku6^*{kl<3>iK;XF335OoQ+&ST-s3*Bx73m0 zMzVi$jPq1Yu`e;wtlP##N-l`EfX1JH1Ba>1(=5-m$;@G4trEaoT7n#^dEeLPqGkP$K< zh)YX+wg~ZXx$zs+1&>O2Unv77C!OB${l)DQ&SxGtDG39bzjC-n_6eRf`(F4d-k^yE z_;PVJo}}`4%(6{wB#kTM5NW03NbiAOZ8i%C^!Q`Oh1J^R&a zZ@M%qw$*REZ~=`I2O9aHN*LQ$65h9x8%T(2U}FlmMVf0e)k3Rl0`n9Wc1U;Oa`&U; zE$cHbp73LTT(w>GyqdCyb+=ELQC$uLs6J8Mzft%Eio{BYZ79tRLfHDAwXg zpM$oGXmfc$_LYL82$q!8_|j)y07VWe&(mr;c7!*?$ct!8`5jPddo9OVR!h5M+96F; zme~uK{e$85be@vXBr}v`1{X7Ykd7*2)SW~ooqJ#pq_Q=*^=lE{D3i5?g~0<#p$@pk zyL#7D7b5KBg}oC{MDpCon0K*v>izC!^&>oGgQVRJqw0!YtG3sh-P(BUUaenUjNP~2 zo4a8GP{*a~*Jj?IyRrE0jk;l|x9<&cX?AYrTGACeE1k&PX8*uPVs9RkEnJzKOUcFCnu(c9mxXv|tpTJ!#AHB_0c=?6S0! z;c8Pj_&v0+Z}K0*ctTDxpBzEv9ZXpBMqUiW=c#~X(T1gc?2?ki|2{f?fg~ZIhfB1V z_ncCx>>2iOmccIrTU9g@{kIWz@Rdw%N4P`-z?`3_7wMXteGBV{1&oA*ADtVPr`CA( z*!5T~s3qnaJN+?qxuGMm9X-pYcjhrjhB7C zU#pmNoSpI*3G~-ll2Ckur8csLclpZPsHXjcnEgK;%sG@G1QD8GZLOX>S)B>3&IPaQLa!Ub zsAoi`ZVI!W6K$J_dy~+-efW>c#nD0 z;B;^$VSp=w%YZv7OmHT+EVze-)nlmVX0#s7wl}$aOyql-cMMzs+&4uL+$6XXxM#!! zxI8!p?nO}sXMj8MJm!nZ4K2iKJ1k;i>ZcsXnXdH^_aaP>EPYcyYD#dj@x@T=(NIKrOM-sYN#930M@+j z%Pl92^&pg0UbmZ$6t&LQsw?Xj)t52st|pISu}@!fPF-`_?k(rqyx;6>xn3AtyDI%P z>1?5LJ6!j@%86J_i-yzXf<3nus-EyOhoV~5W}@DO>XcAt)r z^p{bBGRPY4`E6)K#D30i;EvS!6@ke3$tPoWYt$rXFeA24w_8Ej^tZOpRB0I!e_88R z)?Ck(PUz0NIQ8ka-*no+8C252>Ix;@UzNof>3D1IzNJa-$@+!;3w=G^VVcQDP;b(1 z>5ooAD&HxY&zT9t|zK`Y^*z;hz$YE zu|aCE50W}<(Gh~~YsFv0$Zyb2Bz2pWm^^_>lK`YY>KOt$2}ZD<9_bO^gkVF6I$}GV zX^}2COk~g#m;_P5)DxIWqpQjKRYQIm3&{#d-6FKht*#rh)H_#Hy}P)iWfr zKpw~BgLozhYohT%qVmDBw2=ius7lOWk`!nR6S=mb1S2qsR`;0DdmKeq_@;V56d5}V zPk3KApJR}zK{CBzM?9h$M-AS2(~zel4riyyC*kZ2>YXKbXMi^no<`IB7u225oZv)6 z4$B(19`Zp1PFc?+Ds-iS&1iySNqvW=7&S?*NnN2N&jn@Iw^|+^ta(sI*6FshwJMx5 zr!i0&(xldXbj=Ov4p;opY410rWN2bWWCne*dO1NgWj#cyndD+}bTMy|N0eVdbKP*7 z?&0?Yy%}xyBE|-!))sDuZi)Ujv*DAdrI5CLYGmb;7&dlyB$`y8MD@OguA# zaBL33adr@nEftI@JSV}}9t7k3AQ%^tP>kR_i#wf*b3=bVcH&eaE)pEVBw#-cr~@bq z`3}^hp@+t9Cek)^az^BC8>XUJMXfNmo7@f>y|%DY&Bw(xXUkpkmfav|`Ce>q zx1HOrT&h_hUH_nPyK=+=GCoPI?;UbhtRX1OC1-x!-w$<}4 zi;ci-U%yW+8;zFN3LA|#>0A^hOckICp!6@X?&MG)C)2?XmdrC)0TLjWtZgW#OwV0? zPlGQ^+YOQrI3sCS(qJ{{^LH>iHr-nxJhnVVOs3g(9Vtm!`W z3``J`U72-{j35qF?mm=coXQ%=HxWu{4QwKfalE#G(Dod<58F4+1R-fPy4B7mb~f&H zC-&`3{rBywr~A^vYTpS;J~v>A8*t3HrNlCULbW4J9ki3JCU;0`3Vl=1PN4opE>d4_ zg#pH@U`v((CF3^h7Ds?F;=Zh9C?--Es1rjd;|NofN818%MAZ#h7CKS`13oBIlN8ir zb~9#e`2?zvBDr9=*0Xphw;yLh3K|FPq10T5TO|*$93nw`7sCTe#3|JzCl6Q8yK^JN zTVqqC@FvrMm#bO8{00-Epx^hogJNe8FEJE@8hD&wf<2f^krO)5~@ z??{()Dfj>@46cDLLTS;=zLV@5+N8WL{Y{`k{2x(*3pmz~$Wk>~L@tNpEWsKVNq@*= zDC-PaFB4@#zNx>@ewcTtIb#^U` z$ze_w>rmZB-4a?ahikV{@+gHc-^;wuyhZFuufM;cY%?r|C7QbftVsJZvswt9Cmx(h zxg}c4w4$(%;Vld;xmi5Zb0O2TQ?8eb3c-gFz7k;dp8&~`#BzECuYgwC^8>U_4qD+F zdWEPU-$UEfp4P*w_u=Ot+}^)|dKxSIDP7^fEOp{2FF%Qp4q@CU=s${8Ej9bkm`$ku ziPo7YyT^jRsG7CM>vl`saCbr@>p zrAn8ds>IChPR%PrAGV)8d#a*dD7yUY*=}*M6;^y%L6q>s*_f@zEKs4QJ8@v1a)({( zEx%K_>3hc|`KIKRhdg9APaUhBAaup??(vm%x01}SNY{Zw6qTpGU0HSULB=J#$GczJ zHzb+1zk3Z!;`jKuZfRL%x_E=Yg3Zn9Bl1~v#Kux>X(cwUym{#jIgbYUl4`|fBF@~D ztqf$PS-b~f2t_n_4g{jxj7Mqu9 z^EC7-4Y)!r)&lllUc59Po1JZe02}LV*GqCP%CD*uDze3VX}+$nx?yZcxA_jG-kzxE zC~~NgGANdnw{n(Mu+%6da%4Z% za*~qMw*a|9