def draw_hand_bets(self, surface): for hand in self.hands: hand.bet.draw(surface) amount = max(hand.bet.get_chip_total(), hand.bet_amount) label = Label(self.font, 36, "Bet: ${}".format(amount), "antiquewhite", {"bottomleft": (hand.tl[0], hand.tl[1] - 3)}, bg=prepare.FELT_GREEN) label.image.set_alpha(160) label.draw(surface)
class MessageScreen(ATMState): """ Displays a message from the previous state to the screen and returns to the ATM Menu. """ def __init__(self): super(MessageScreen, self).__init__() self.buttons = ButtonGroup() Button(((1278, 840), (88, 65)), self.buttons, call=self.back_to_menu) def startup(self, persistent): self.persist = persistent msg = self.persist["message"] self.label = Label(self.font, 36, msg, "white", {"center": self.screen_rect.center}) self.exit_label = Label(self.font, 36, "OK", "white", {"midright": (1251, 872)}) def update(self, surface, keys, current, dt, scale, player): self.buttons.update(tools.scaled_mouse_pos(scale)) self.draw(surface) def back_to_menu(self, *args): self.beep() self.next = "MAINMENU" self.done = True def get_event(self, event, scale): self.buttons.get_event(event) if event.type == pg.KEYDOWN: if event.key == pg.K_RETURN: self.back_to_menu() def draw(self, surface): surface.fill(pg.Color("blue2")) self.label.draw(surface) self.exit_label.draw(surface)
class AdvanceScreen(ATMState): def __init__(self): super(AdvanceScreen, self).__init__() self.make_textbox() self.title = Label( self.font, 36, "Enter Cash Advance Amount", "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 300)}, ) self.make_enter_button() def make_dynamic_labels(self, player): text = "The maximum advance is ${:.2f}".format(player.account.max_advance) dyna1 = Label(self.font, 36, text, "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 80)}) fee_text = "A {}% fee will be added to the advance amount".format(player.account.lending_rate * 100) dyna2 = Label(self.font, 36, fee_text, "white", {"midtop": (self.screen_rect.centerx, dyna1.rect.bottom + 10)}) self.dynamic_labels = [dyna1, dyna2] def make_enter_button(self): self.button_labels = [] self.buttons = ButtonGroup() Button(((1278, 840), (88, 65)), self.buttons, bindings=[pg.K_RETURN]) rect_pos = {"midright": (1251, 872)} label = Label(self.font, 36, "Enter", "white", rect_pos, bg="blue2") self.button_labels.append(label) def make_textbox(self): rect = (self.screen_rect.centerx - 200, self.screen_rect.top + 600, 400, 200) self.textbox = TextBox( rect, outline_color=pg.Color("white"), color=pg.Color("blue2"), font=pg.font.Font(self.font, 36), font_color=pg.Color("white"), ) self.textbox.accepted = string.digits self.dollar_sign = Label(self.font, 36, "$", "white", {"midright": (rect[0] - 5, rect[1] + 100)}) self.textbox.update() def leave_message(self, msg): self.make_textbox() self.beep() self.persist["message"] = msg self.next = "MESSAGESCREEN" self.done = True def back_to_menu(self): self.beep() self.next = "MAINMENU" self.done = True def get_event(self, event, scale): self.textbox.get_event(event, tools.scaled_mouse_pos(scale)) self.buttons.get_event(event) if event.type == pg.QUIT: self.back_to_menu() elif event.type == pg.KEYUP: if event.key == pg.K_ESCAPE: self.back_to_menu() def update(self, surface, keys, current, dt, scale, player): self.textbox.update() if not self.textbox.active: self.beep() try: amount = int(self.textbox.final) except ValueError: amount = 0 if amount > player.account.max_advance: amount = 0 self.leave_message("You are not authorized for this amount") else: player.account.cash_advance(amount) player.cash += amount msg = "${:.2f} Dispensed".format(amount) self.leave_message(msg) self.buttons.update(tools.scaled_mouse_pos(scale)) self.make_dynamic_labels(player) self.draw(surface) def draw(self, surface): surface.fill(pg.Color("blue2")) self.title.draw(surface) self.dollar_sign.draw(surface) self.textbox.draw(surface) for label in self.dynamic_labels: label.draw(surface) for b_label in self.button_labels: b_label.draw(surface)
class Bet: def __init__(self, size, topleft, bettable, name, mult_dict, triangles=None, pos=None, size2=None): self.name = name self.multiplier_dict = mult_dict self.triangles = triangles self.alpha = 128 self.bettable_color = (0, 180, 0) self.unbettable_color = (180, 0, 0) self.color = self.bettable_color self.extra_filler_pos = pos self.size2 = size2 self.fillers = [] if self.triangles: for triangle in self.triangles: self.fillers.append(self.setup_fillers(triangle)) self.setup_highlighter(size, topleft) self.text = '' self.setup_label(name, mult_dict) self.bettable = bettable def setup_label(self, text, mult_dict): self.font = prepare.FONTS["Saniretro"] self.font_size = 30 self.bettable_lbl_color = 'white' self.unbettable_lbl_color = 'red' self.lbl_color = self.bettable_lbl_color spacer = 5 self.text += '{}Payoff: {}'.format(' ' * spacer, mult_dict) self.update_label() def update_label(self): self.label_name = Label(self.font, self.font_size, self.text, self.lbl_color, {"bottomleft": (20, 918)}) def setup_highlighter(self, size, topleft): self.highlighter = pg.Surface(size).convert() self.highlighter.set_alpha(self.alpha) self.highlighter.fill(self.color) self.highlighter_rect = self.highlighter.get_rect(topleft=topleft) self.is_draw = False def setup_fillers(self, points): image = pg.Surface(self.size2) if not prepare.DEBUG: image.set_colorkey((0, 0, 0)) image.set_alpha(128) pg.draw.polygon(image, self.color, points, 0) return image def update_highlight_color(self, point): if self.bettable == 'always': self.color = self.bettable_color self.lbl_color = self.bettable_lbl_color elif self.bettable == 'on_point': if point: self.color = self.bettable_color self.lbl_color = self.bettable_lbl_color else: self.color = self.unbettable_color self.lbl_color = self.unbettable_lbl_color elif self.bettable == 'off_point': if not point: self.color = self.bettable_color self.lbl_color = self.bettable_lbl_color else: self.color = self.unbettable_color self.lbl_color = self.unbettable_lbl_color self.highlighter.fill(self.color) self.update_label() def update(self, mouse_pos, point): if self.highlighter_rect.collidepoint(mouse_pos): self.is_draw = True else: self.is_draw = False self.update_highlight_color(point) def draw(self, surface): if self.is_draw: surface.blit(self.highlighter, self.highlighter_rect) self.label_name.draw(surface) if self.triangles and self.extra_filler_pos: for filler in self.fillers: surface.blit(filler, self.extra_filler_pos)
class WithdrawalScreen(ATMState): def __init__(self): super(WithdrawalScreen, self).__init__() self.title = Label( self.font, 36, "Enter Withdrawal Amount", "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 300)}, ) self.make_textbox() self.make_enter_button() def make_enter_button(self): self.buttons = ButtonGroup() self.labels = [] Button(((1278, 840), (88, 65)), self.buttons, bindings=[pg.K_RETURN]) rect_pos = {"midright": (1251, 872)} label = Label(self.font, 36, "Enter", "white", rect_pos, bg="blue2") self.labels.append(label) def make_textbox(self): rect = (self.screen_rect.centerx - 200, self.screen_rect.top + 600, 400, 200) self.textbox = TextBox( rect, outline_color=pg.Color("white"), color=pg.Color("blue2"), font=pg.font.Font(self.font, 36), font_color=pg.Color("white"), ) self.textbox.accepted = string.digits self.dollar_sign = Label(self.font, 36, "$", "white", {"midright": (rect[0] - 5, rect[1] + 100)}) # update needed to set textbox.render_area self.textbox.update() def leave_message(self, msg): self.make_textbox() self.persist["message"] = msg self.next = "MESSAGESCREEN" self.done = True def back_to_menu(self): self.beep() self.next = "MAINMENU" self.done = True def get_event(self, event, scale): self.textbox.get_event(event, tools.scaled_mouse_pos(scale)) self.buttons.get_event(event) if event.type == pg.QUIT: self.back_to_menu() elif event.type == pg.KEYUP: if event.key == pg.K_ESCAPE: self.back_to_menu() def update(self, surface, keys, current, dt, scale, player): self.textbox.update() if not self.textbox.active: self.beep() try: amount = int(self.textbox.final) except ValueError: amount = 0 if player.account.balance >= amount: player.account.withdrawal(amount) player.cash += amount self.leave_message("${:.2f} Withdrawn".format(amount)) else: msg = "Insufficient Funds for Withdrawal" self.leave_message(msg) self.buttons.update(tools.scaled_mouse_pos(scale)) text = "You have ${:.2f} available for withdrawal".format(player.account.balance) self.dyna_label = Label( self.font, 36, text, "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 80)} ) self.draw(surface) def draw(self, surface): surface.fill(pg.Color("blue2")) self.title.draw(surface) self.dollar_sign.draw(surface) self.textbox.draw(surface) for label in self.labels: label.draw(surface) self.dyna_label.draw(surface)
class StatsMenu(data.state.State): """ This state allows the player to choose which game's stats they want to view or return to the lobby. """ name = "stats_menu" def __init__(self): super(StatsMenu, self).__init__() self.font = prepare.FONTS["Saniretro"] self.title = None self.buttons = ButtonGroup() self.labels = [] self.lines = [] self.use_music_handler = False def collect_games_with_stats(self): for name, scene in self.controller.query_all_states().items(): if hasattr(scene, 'initialize_stats'): yield name def make_labels(self): self.labels = [] cash = self.player.cash balance = self.player.account_balance assets = cash + balance starting_cash = prepare.MONEY profit = assets - starting_cash label_info = [("Cash", cash, 110), ("Account", balance, 150), ("Assets", assets, 198), ("Starting Cash", -starting_cash, 238), ("Profit", profit, 283)] left = 500 right = 900 for name, value, topy in label_info: label1 = Label(self.font, 36, name, "white", {"topleft": (left, topy)}) color = "darkgreen" if value >= 0 else "darkred" label2 = Label(self.font, 36, "{:.2f}".format(value), color, {"topright": (right, topy)}) self.labels.extend([label1, label2]) self.lines = [((left, 193), (right, 193)), ((left, 280), (right, 280))] def make_buttons(self, games, screen_rect, col=2): spacer_x = 20 spacer_y = 20 start_y = 410 start_x = (screen_rect.w-NeonButton.width*col-spacer_x*(col-1))//2 buttons = ButtonGroup() for i,game in enumerate(games): y,x = divmod(i, col) pos = (start_x+x*(NeonButton.width+spacer_x), start_y+y*(NeonButton.height+spacer_y)) button = NeonButton(pos, game, self.view_game_stats, game, buttons) pos = (screen_rect.centerx-(NeonButton.width//2), screen_rect.bottom-(NeonButton.height+10)) NeonButton(pos, "Lobby", self.back_to_lobby, None, buttons, bindings=[pg.K_ESCAPE]) return buttons def back_to_lobby(self, *args): self.done = True self.next = "lobby" def view_game_stats(self, game): self.persist["current_game_stats"] = game self.next = "stats_screen" self.done = True def startup(self, current_time, persistent): screen_rect = pg.Rect((0, 0), prepare.RENDER_SIZE) self.title = Label(self.font, 64, "Statistics", "darkred", {"midtop":(screen_rect.centerx, screen_rect.top+10)}) self.start_time = current_time self.persist = persistent self.player = self.persist["casino_player"] games = self.collect_games_with_stats() self.buttons = self.make_buttons(games, screen_rect, 3) self.make_labels() def get_event(self, event, scale=(1,1)): if event.type == pg.QUIT: self.done = True self.next = "lobby" self.buttons.get_event(event) def draw(self, surface): surface.fill(prepare.BACKGROUND_BASE) self.title.draw(surface) self.buttons.draw(surface) for label in self.labels: label.draw(surface) for line in self.lines: pg.draw.line(surface, pg.Color("white"), *line) def update(self, surface, keys, current_time, dt, scale): mouse_pos = tools.scaled_mouse_pos(scale) self.buttons.update(mouse_pos) self.draw(surface)
class Bet: def __init__(self, size, topleft, bettable, name, mult_dict, triangles=None, pos=None, size2=None): self.name = name self.multiplier_dict = mult_dict self.triangles = triangles self.alpha = 128 self.bettable_color = (0, 180, 0) self.unbettable_color = (180, 0, 0) self.color = self.bettable_color self.extra_filler_pos = pos self.size2 = size2 self.fillers = [] if self.triangles: for triangle in self.triangles: self.fillers.append(self.setup_fillers(triangle)) self.setup_highlighter(size, topleft) self.text = "" self.setup_label(name, mult_dict) self.bettable = bettable def setup_label(self, text, mult_dict): self.font = prepare.FONTS["Saniretro"] self.font_size = 30 self.bettable_lbl_color = "white" self.unbettable_lbl_color = "red" self.lbl_color = self.bettable_lbl_color spacer = 5 self.text += "{}Payoff: {}".format(" " * spacer, mult_dict) self.update_label() def update_label(self): self.label_name = Label(self.font, self.font_size, self.text, self.lbl_color, {"bottomleft": (20, 918)}) def setup_highlighter(self, size, topleft): self.highlighter = pg.Surface(size).convert() self.highlighter.set_alpha(self.alpha) self.highlighter.fill(self.color) self.highlighter_rect = self.highlighter.get_rect(topleft=topleft) self.is_draw = False def setup_fillers(self, points): image = pg.Surface(self.size2) if not prepare.DEBUG: image.set_colorkey((0, 0, 0)) image.set_alpha(128) pg.draw.polygon(image, self.color, points, 0) return image def update_highlight_color(self, point): if self.bettable == "always": self.color = self.bettable_color self.lbl_color = self.bettable_lbl_color elif self.bettable == "on_point": if point: self.color = self.bettable_color self.lbl_color = self.bettable_lbl_color else: self.color = self.unbettable_color self.lbl_color = self.unbettable_lbl_color elif self.bettable == "off_point": if not point: self.color = self.bettable_color self.lbl_color = self.bettable_lbl_color else: self.color = self.unbettable_color self.lbl_color = self.unbettable_lbl_color self.highlighter.fill(self.color) self.update_label() def update(self, mouse_pos, point): if self.highlighter_rect.collidepoint(mouse_pos): self.is_draw = True else: self.is_draw = False self.update_highlight_color(point) def draw(self, surface): if self.is_draw: surface.blit(self.highlighter, self.highlighter_rect) self.label_name.draw(surface) if self.triangles and self.extra_filler_pos: for filler in self.fillers: surface.blit(filler, self.extra_filler_pos)
class Betting(GutsState): def __init__(self): super(Betting, self).__init__() self.buttons = ButtonGroup() pos = (self.screen_rect.right - (NeonButton.width + 10), self.screen_rect.bottom - (NeonButton.height + 10)) lobby_button = NeonButton(pos, "Lobby", self.warn, None, self.buttons, bindings=[pg.K_ESCAPE]) def add_bet_to_pot(self): self.game.pot += self.game.bet def make_labels(self): sr = self.screen_rect self.labels = [] self.alpha = 255 self.big_alpha = 255 self.animations = pg.sprite.Group() text = "Free Ride" if self.game.free_ride else "Ante Up" self.big_label = Label(self.font, 320, text, "gold3", {"center": sr.center}, bg=prepare.FELT_GREEN) self.big_label.image.set_colorkey(prepare.FELT_GREEN) left, top = self.big_label.rect.topleft ani = Animation(x=left, y=top - 500, duration=2000, round_values=True) fade = Animation(alpha=0, duration=2000, round_values=True) big_fader = Animation(big_alpha=0, duration=1500, delay=500, round_values=True) fade.start(self) ani.start(self.big_label.rect) big_fader.start(self) self.animations.add(ani, fade, big_fader) if not self.game.free_ride: dest = self.game.pot_label.rect.center for p in self.game.players: pos = p.name_label.rect.center label = Label(self.font, 96, "${}".format(self.game.bet), "darkred", {"center": pos}, bg=prepare.FELT_GREEN) label.image.set_colorkey(prepare.FELT_GREEN) left, top = label.rect.topleft self.labels.append(label) ani = Animation(centerx=dest[0], centery=dest[1], duration=2000, delay=50, round_values=True, transition="in_quart") ani.callback = self.add_bet_to_pot ani.start(label.rect) self.animations.add(ani) fader = Animation(alpha=0, duration=2100, round_values=True) fader.start(self) self.animations.add(fader) def startup(self, game): self.game = game if not self.game.free_ride: if self.game.player.cash < self.game.bet: self.next = "Bankrupt Screen" self.done = True else: self.game.player.cash -= self.game.bet self.game.casino_player.increase("games played") self.game.casino_player.increase("total bets", self.game.bet) self.game.casino_player.increase("hands played") self.make_labels() def get_event(self, event): if self.window: self.window.get_event(event) else: self.buttons.get_event(event) self.advisor_button.get_event(event) def update(self, dt, scale): mouse_pos = tools.scaled_mouse_pos(scale) self.general_update(dt, mouse_pos) if not self.animations: self.done = True self.next = "Dealing" for label in self.labels: label.image.set_alpha(self.alpha) self.big_label.image.set_alpha(self.big_alpha) def draw(self, surface): if not self.done: surface.fill(prepare.FELT_GREEN) self.game.draw(surface) for p in self.game.players: p.draw(surface) for label in self.labels: label.draw(surface) self.big_label.draw(surface) self.buttons.draw(surface) self.money_icon.draw(surface) self.draw_advisor(surface) if self.window: self.window.draw(surface)
class ShowCards(GutsState): def __init__(self): super(ShowCards, self).__init__() self.next = "Show Results" for button in self.buttons: button.active = False def startup(self, game): self.game = game self.alpha = 255 self.showdown_alpha = 255 self.showdown_font_size = 64 self.make_showdown_label() fader = Animation(alpha=0, duration=2500, delay=500, round_values=True) sizer = Animation(showdown_font_size=320, duration=500, round_values=True) fader.start(self) sizer.start(self) quitter = Task(self.end_state, 3000) flipper = Task(self.flip_cards, 1000) self.animations.add(fader, sizer, quitter, flipper) def flip_cards(self): for p in self.game.players: if p.stayed: for card in p.cards: card.face_up = True self.play_flip_sound() def end_state(self): self.done = True def make_showdown_label(self): pos = self.screen_rect.center self.label = Label(self.font, self.showdown_font_size, "Showdown!", "gold3", {"center": pos}, bg=prepare.FELT_GREEN) self.label.image.set_colorkey(prepare.FELT_GREEN) self.label.image.set_alpha(self.alpha) def get_event(self, event): if self.window: self.window.get_event(event) else: self.advisor_button.get_event(event) def update(self, dt, scale): mouse_pos = tools.scaled_mouse_pos(scale) self.general_update(dt, mouse_pos) self.make_showdown_label() def draw(self, surface): surface.fill(prepare.FELT_GREEN) self.game.draw(surface) for player in self.game.players: player.draw(surface) self.buttons.draw(surface) self.money_icon.draw(surface) self.label.draw(surface) self.draw_advisor(surface) if self.window: self.window.draw(surface)
class AdvanceScreen(ATMState): def __init__(self): super(AdvanceScreen, self).__init__() self.make_textbox() self.title = Label( self.font, 36, "Enter Cash Advance Amount", "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 300)}) self.make_enter_button() def make_dynamic_labels(self, player): text = "The maximum advance is ${:.2f}".format( player.account.max_advance) dyna1 = Label( self.font, 36, text, "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 80)}) fee_text = "A {}% fee will be added to the advance amount".format( player.account.lending_rate * 100) dyna2 = Label( self.font, 36, fee_text, "white", {"midtop": (self.screen_rect.centerx, dyna1.rect.bottom + 10)}) self.dynamic_labels = [dyna1, dyna2] def make_enter_button(self): self.button_labels = [] self.buttons = ButtonGroup() Button(((1278, 840), (88, 65)), self.buttons, bindings=[pg.K_RETURN]) rect_pos = {"midright": (1251, 872)} label = Label(self.font, 36, "Enter", "white", rect_pos, bg="blue2") self.button_labels.append(label) def make_textbox(self): rect = (self.screen_rect.centerx - 200, self.screen_rect.top + 600, 400, 200) self.textbox = TextBox(rect, outline_color=pg.Color("white"), color=pg.Color("blue2"), font=pg.font.Font(self.font, 36), font_color=pg.Color("white")) self.textbox.accepted = string.digits self.dollar_sign = Label(self.font, 36, "$", "white", {"midright": (rect[0] - 5, rect[1] + 100)}) self.textbox.update() def leave_message(self, msg): self.make_textbox() self.beep() self.persist["message"] = msg self.next = "MESSAGESCREEN" self.done = True def back_to_menu(self): self.beep() self.next = "MAINMENU" self.done = True def get_event(self, event, scale): self.textbox.get_event(event, tools.scaled_mouse_pos(scale)) self.buttons.get_event(event) if event.type == pg.QUIT: self.back_to_menu() elif event.type == pg.KEYUP: if event.key == pg.K_ESCAPE: self.back_to_menu() def update(self, surface, keys, current, dt, scale, player): self.textbox.update() if not self.textbox.active: self.beep() try: amount = int(self.textbox.final) except ValueError: amount = 0 if amount > player.account.max_advance: amount = 0 self.leave_message("You are not authorized for this amount") else: player.account.cash_advance(amount) player.cash += amount msg = "${:.2f} Dispensed".format(amount) self.leave_message(msg) self.buttons.update(tools.scaled_mouse_pos(scale)) self.make_dynamic_labels(player) self.draw(surface) def draw(self, surface): surface.fill(pg.Color("blue2")) self.title.draw(surface) self.dollar_sign.draw(surface) self.textbox.draw(surface) for label in self.dynamic_labels: label.draw(surface) for b_label in self.button_labels: b_label.draw(surface)
class AIPlayer(object): fold_sounds = [prepare.SFX[x] for x in ["cardslide{}".format(num) for num in (2, 3, 4)]] stay_sounds = [prepare.SFX[x] for x in ["knock{}".format(num) for num in range(1, 7)]] def __init__(self, name, orientation, hand_topleft): self.name = name self.orientation = orientation self.cards = [] self.stayed = False self.passed = False self.hand_topleft = hand_topleft font = prepare.FONTS["Saniretro"] slot_rect = pg.Rect(self.hand_topleft, prepare.CARD_SIZE) if orientation == "left": name_pos = hand_topleft[0] + 60, hand_topleft[1] + 240 db_pos = hand_topleft[0] + 170, hand_topleft[1] + 80 self.card_slots = [slot_rect, slot_rect.move(0, 60)] elif orientation == "right": name_pos = hand_topleft[0] + 60, hand_topleft[1] + 240 db_pos = hand_topleft[0] - 120, hand_topleft[1] + 80 self.card_slots = [slot_rect, slot_rect.move(0, 60)] else: name_pos = hand_topleft[0] + 90, hand_topleft[1] + 210 db_pos = hand_topleft[0] + 60, hand_topleft[1] + 285 self.card_slots = [slot_rect, slot_rect.move(60, 0)] self.name_label = Label(font, 48, self.name, "antiquewhite", {"center": name_pos}, bg=prepare.FELT_GREEN) self.name_label.image.set_alpha(100) center = self.name_label.rect.midbottom label_center = center[0], center[1] + 20 self.stay_label = Label(font, 48, "Stayed in", "gold3", {"center": label_center}, bg=prepare.FELT_GREEN) self.stay_label.image.set_alpha(200) self.pass_label = Label(font, 48, "Passed", "darkred", {"center": label_center}, bg=prepare.FELT_GREEN) self.pass_label.image.set_alpha(200) self.label = None self.dealer_button_topleft = db_pos self.guts = randint(-10, 20) self.won = 0 self.lost = 0 names = ["cardslide{}".format(x) for x in (2, 3, 4)] self.fold_sounds = [prepare.SFX[name] for name in names] def stay(self, game): choice(self.stay_sounds).play() self.stayed = True self.label = self.stay_label game.current_player_index += 1 def stay_out(self, game): choice(self.fold_sounds).play() self.passed = True self.label = self.pass_label self.fold() game.current_player_index += 1 def fold(self): choice(self.fold_sounds).play() for card in self.cards: center = card.rect.center card.face_up = False card.image = pg.transform.rotate(card.image, -90) card.back_image = pg.transform.rotate(card.back_image, -90) card.rect = card.image.get_rect(center=center) self.cards[1].rect = self.cards[0].rect def play_hand(self, game): others = [x for x in game.players if x is not self] stays = len([x for x in others if x.stayed]) if game.dealer is self and stays < 1: self.stay(game) return card_vals = [card.value for card in self.cards] card_vals.sort(reverse=True) vals = "{},{}".format(*card_vals) if vals in STAY_PERCENTS: percent = STAY_PERCENTS[vals] percent += self.guts percent -= stays * 5 risk_it = randint(1, 100) if risk_it < percent: self.stay(game) else: if randint(1, 100) < self.guts: self.stay(game) else: self.stay_out(game) else: risk_it = self.guts if stays < 1: if randint(1, 100) < risk_it: self.stay(game) else: self.stay_out(game) else: self.stay_out(game) def draw(self, surface): self.name_label.draw(surface) for card in self.cards[::-1]: card.draw(surface) if self.label: self.label.draw(surface) def draw_from_deck(self, deck): card = deck.draw_card() x, y = deck.rect.center card.rect.center = (x + 16, y - 10) self.cards.append(card) return card def align_cards(self): for card in self.cards: center = card.rect.center if self.orientation == "left": card.rect = pg.Rect(0,0,card.rect.height, card.rect.width) card.image = pg.transform.rotate(card.image, -90) card.back_image = pg.transform.rotate(card.back_image, -90) elif self.orientation == "right": card.rect = pg.Rect(0,0,card.rect.height, card.rect.width) card.image = pg.transform.rotate(card.image, 90) card.back_image = pg.transform.rotate(card.back_image, 90) card.rect.center = center
class WithdrawalScreen(ATMState): def __init__(self): super(WithdrawalScreen, self).__init__() self.title = Label( self.font, 36, "Enter Withdrawal Amount", "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 300)}) self.make_textbox() self.make_enter_button() def make_enter_button(self): self.buttons = ButtonGroup() self.labels = [] Button(((1278, 840), (88, 65)), self.buttons, bindings=[pg.K_RETURN]) rect_pos = {"midright": (1251, 872)} label = Label(self.font, 36, "Enter", "white", rect_pos, bg="blue2") self.labels.append(label) def make_textbox(self): rect = (self.screen_rect.centerx - 200, self.screen_rect.top + 600, 400, 200) self.textbox = TextBox(rect, outline_color=pg.Color("white"), color=pg.Color("blue2"), font=pg.font.Font(self.font, 36), font_color=pg.Color("white")) self.textbox.accepted = string.digits self.dollar_sign = Label(self.font, 36, "$", "white", {"midright": (rect[0] - 5, rect[1] + 100)}) #update needed to set textbox.render_area self.textbox.update() def leave_message(self, msg): self.make_textbox() self.persist["message"] = msg self.next = "MESSAGESCREEN" self.done = True def back_to_menu(self): self.beep() self.next = "MAINMENU" self.done = True def get_event(self, event, scale): self.textbox.get_event(event, tools.scaled_mouse_pos(scale)) self.buttons.get_event(event) if event.type == pg.QUIT: self.back_to_menu() elif event.type == pg.KEYUP: if event.key == pg.K_ESCAPE: self.back_to_menu() def update(self, surface, keys, current, dt, scale, player): self.textbox.update() if not self.textbox.active: self.beep() try: amount = int(self.textbox.final) except ValueError: amount = 0 if player.account.balance >= amount: player.account.withdrawal(amount) player.cash += amount self.leave_message("${:.2f} Withdrawn".format(amount)) else: msg = "Insufficient Funds for Withdrawal" self.leave_message(msg) self.buttons.update(tools.scaled_mouse_pos(scale)) text = "You have ${:.2f} available for withdrawal".format( player.account.balance) self.dyna_label = Label( self.font, 36, text, "white", {"midtop": (self.screen_rect.centerx, self.screen_rect.top + 80)}) self.draw(surface) def draw(self, surface): surface.fill(pg.Color("blue2")) self.title.draw(surface) self.dollar_sign.draw(surface) self.textbox.draw(surface) for label in self.labels: label.draw(surface) self.dyna_label.draw(surface)
class GutsGame(object): def __init__(self, players, dealer_index, player, casino_player, bet, pot, free_ride): self.players = players self.dealer_index = dealer_index self.current_player_index = 0 self.dealer = self.players[self.dealer_index] self.dealer_button = DealerButton(self.dealer.dealer_button_topleft) self.player = player self.casino_player = casino_player self.bet = bet self.pot = pot self.deal_queue = self.make_deal_queue() self.deck = Deck((640,400)) self.font = prepare.FONTS["Saniretro"] self.make_labels() self.free_ride = free_ride self.game_over = False def update(self): self.make_labels() def make_deal_queue(self): left = self.players[self.dealer_index + 1:] right = self.players[:self.dealer_index + 1] return left + right def make_labels(self): color= "antiquewhite" if self.pot != 420 else "darkgreen" self.pot_label = Label(self.font, 48, "Pot: ${}".format(self.pot), color, {"midleft": (650, 610)}) #{"center": (700, 610)}) def compare_hands(self, player1, player2): h1 = [] h2 = [] for player, vals in [(player1, h1), (player2, h2)]: for card in player.cards: val = card.value if card.value != 1 else 14 vals.append(val) h1.sort(reverse=True) h2.sort(reverse=True) if h1 == h2: return [player1, player2] elif h2[0] == h2[1]: if h1[0] == h1[1] and h1[0] > h2[0]: return [player1] else: return [player2] else: if h1[0] > h2[0] or h1[0] == h1[1]: return [player1] elif h1[0] == h2[0]: if h1[1] > h2[1]: return [player1] else: return [player2] else: return [player2] def get_winners(self): stayed = [x for x in self.players if x.stayed] best = [] for stayer in stayed: if not best: best.append(stayer) else: new_best = [] for b in best: new_best.extend(self.compare_hands(b, stayer)) best = new_best return best def draw(self, surface): self.pot_label.draw(surface) self.deck.draw(surface) self.dealer_button.draw(surface)
class Craps(data.state.State): show_in_lobby = True name = 'craps' def __init__(self): super(Craps, self).__init__() self.screen_rect = pg.Rect((0, 0), prepare.RENDER_SIZE) self.font = prepare.FONTS["Saniretro"] self.font_size = 64 self.buttons = self.make_buttons(self.screen_rect) self.table_orig = prepare.GFX['craps_table'] self.table_color = (0, 153, 51) self.set_table() self.bets = craps_data.BETS self.dice = [dice.Die(self.screen_rect), dice.Die(self.screen_rect, 50)] self.dice_total = 0 self.update_total_label() self.history = [] #[(1,1),(5,4)] self.dice_sounds = [ prepare.SFX['dice_sound1'], prepare.SFX['dice_sound2'], prepare.SFX['dice_sound3'], prepare.SFX['dice_sound4'], ] self.pointchip = point_chip.PointChip() self.points = [4,5,6,8,9,10] self.point = 0 #off position self.widgets = [] if prepare.DEBUG: self.setup_debug_entry() self.debug_die1 = None self.debug_die2 = None self.debug_dice_total = None @staticmethod def initialize_stats(): """Return OrderedDict suitable for use in game stats :return: collections.OrderedDict """ stats = OrderedDict([('times as shooter', 0), ('bets placed', 0), ('bets won', 0), ('bets lost', 0), ('total bets', 0), ('total winnings', 0)]) return stats def setup_debug_entry(self): self.debug_lbl = Label(self.font, self.font_size, '6 6', "gold3", {"center": (750, 950)}) settings = { "command" : self.debug_roll, "inactive_on_enter" : False, 'active': False } self.widgets.append(TextBox((700,1000,150,30), **settings)) def make_buttons(self, screen_rect): buttons = ButtonGroup() y = screen_rect.bottom-NeonButton.height-10 lobby = NeonButton((20,y), "Lobby", self.back_to_lobby, None, buttons) NeonButton((lobby.rect.right+20,y), "Roll", self.roll, None, buttons) return buttons def back_to_lobby(self, *args): self.game_started = False self.next = "lobby" self.done = True def debug_roll(self, id, text): self.roll() try: die1 = int(text.split()[0]) -1 die2 = int(text.split()[1]) -1 accepted = range(0,6) if die1 in accepted and die2 in accepted: self.dice[0].roll_value = die1 self.dice[1].roll_value = die2 else: print('Input needs to be of values 1-6') except IndexError: #user didnt input correct format "VALUE VALUE" print('Input needs to be "VALUE VALUE"') def roll(self, *args): if not self.dice[0].rolling: self.update_history() for die in self.dice: die.reset() if prepare.DEBUG: print(self.history) random.choice(self.dice_sounds).play() def set_table(self): self.table_y = (self.screen_rect.height // 4)*3 self.table_x = self.screen_rect.width self.table = pg.transform.scale(self.table_orig, (self.table_x, self.table_y)) self.table_rect = self.table.get_rect() def startup(self, current_time, persistent): self.persist = persistent #This is the object that represents the user. self.casino_player = self.persist["casino_player"] self.casino_player.current_game = self.name for die in self.dice: die.draw_dice = False self.history = [] def get_event(self, event, scale=(1,1)): if event.type == pg.QUIT: #self.cash_out_player() self.done = True self.next = "lobby" elif event.type == pg.VIDEORESIZE: self.set_table() self.buttons.get_event(event) for widget in self.widgets: widget.get_event(event, tools.scaled_mouse_pos(scale)) def cash_out_player(self): self.casino_player.stats["cash"] = self.player.get_chip_total() def update_total_label(self): self.dice_total_label = Label(self.font, self.font_size, str(self.dice_total), "gold3", {"center": (1165, 245)}) def update_history(self): dice = [] for die in self.dice: dice.append(die.value()) if dice[0]: self.history.append(dice) if len(self.history) > 10: self.history.pop(0) def set_point(self): if not self.point: if self.dice_total in self.points: self.point = self.dice_total if self.dice_total == 7: self.point = 0 def get_dice_total(self, current_time): self.dice_total = 0 for die in self.dice: die.update(current_time) v = die.value() if v: self.dice_total += v def draw(self, surface): surface.fill(self.table_color) surface.blit(self.table, self.table_rect) self.buttons.draw(surface) for h in self.bets.keys(): self.bets[h].draw(surface) for die in self.dice: die.draw(surface) if not self.dice[0].rolling and self.dice[0].draw_dice: self.dice_total_label.draw(surface) self.pointchip.draw(surface) for widget in self.widgets: widget.draw(surface) if prepare.DEBUG: self.debug_lbl.draw(surface) def update(self, surface, keys, current_time, dt, scale): mouse_pos = tools.scaled_mouse_pos(scale) self.buttons.update(mouse_pos) self.draw(surface) self.get_dice_total(current_time) self.set_point() for h in self.bets.keys(): self.bets[h].update(mouse_pos, self.point) self.pointchip.update(current_time, self.dice_total, self.dice[0]) self.update_total_label() for widget in self.widgets: widget.update()
class Betting(GutsState): def __init__(self): super(Betting, self).__init__() self.buttons = ButtonGroup() pos = (self.screen_rect.right-(NeonButton.width+10), self.screen_rect.bottom-(NeonButton.height+10)) lobby_button = NeonButton(pos, "Lobby", self.warn, None, self.buttons, bindings=[pg.K_ESCAPE]) def add_bet_to_pot(self): self.game.pot += self.game.bet def make_labels(self): sr = self.screen_rect self.labels = [] self.alpha = 255 self.big_alpha = 255 self.animations = pg.sprite.Group() text = "Free Ride" if self.game.free_ride else "Ante Up" self.big_label = Label(self.font, 320, text, "gold3", {"center": sr.center}, bg=prepare.FELT_GREEN) self.big_label.image.set_colorkey(prepare.FELT_GREEN) left, top = self.big_label.rect.topleft ani = Animation(x=left, y=top-500, duration=2000, round_values=True) fade = Animation(alpha=0, duration=2000, round_values=True) big_fader = Animation(big_alpha=0, duration=1500, delay=500, round_values=True) fade.start(self) ani.start(self.big_label.rect) big_fader.start(self) self.animations.add(ani, fade, big_fader) if not self.game.free_ride: dest = self.game.pot_label.rect.center for p in self.game.players: pos = p.name_label.rect.center label = Label(self.font, 96, "${}".format(self.game.bet), "darkred", {"center": pos}, bg=prepare.FELT_GREEN) label.image.set_colorkey(prepare.FELT_GREEN) left, top = label.rect.topleft self.labels.append(label) ani = Animation(centerx=dest[0], centery=dest[1], duration=2000, delay=50, round_values=True, transition="in_quart") ani.callback = self.add_bet_to_pot ani.start(label.rect) self.animations.add(ani) fader = Animation(alpha=0, duration=2100, round_values=True) fader.start(self) self.animations.add(fader) def startup(self, game): self.game = game if not self.game.free_ride: if self.game.player.cash < self.game.bet: self.next = "Bankrupt Screen" self.done = True else: self.game.player.cash -= self.game.bet self.game.casino_player.increase("games played") self.game.casino_player.increase("total bets", self.game.bet) self.game.casino_player.increase("hands played") self.make_labels() def get_event(self, event): if self.window: self.window.get_event(event) else: self.buttons.get_event(event) self.advisor_button.get_event(event) def update(self, dt, scale): mouse_pos = tools.scaled_mouse_pos(scale) self.general_update(dt, mouse_pos) if not self.animations: self.done = True self.next = "Dealing" for label in self.labels: label.image.set_alpha(self.alpha) self.big_label.image.set_alpha(self.big_alpha) def draw(self, surface): if not self.done: surface.fill(prepare.FELT_GREEN) self.game.draw(surface) for p in self.game.players: p.draw(surface) for label in self.labels: label.draw(surface) self.big_label.draw(surface) self.buttons.draw(surface) self.money_icon.draw(surface) self.draw_advisor(surface) if self.window: self.window.draw(surface)
class GutsGame(object): def __init__(self, players, dealer_index, player, casino_player, bet, pot, free_ride): self.players = players self.dealer_index = dealer_index self.current_player_index = 0 self.dealer = self.players[self.dealer_index] self.dealer_button = DealerButton(self.dealer.dealer_button_topleft) self.player = player self.casino_player = casino_player self.bet = bet self.pot = pot self.deal_queue = self.make_deal_queue() self.deck = Deck((640, 400)) self.font = prepare.FONTS["Saniretro"] self.make_labels() self.free_ride = free_ride self.game_over = False def update(self): self.make_labels() def make_deal_queue(self): left = self.players[self.dealer_index + 1:] right = self.players[:self.dealer_index + 1] return left + right def make_labels(self): color = "antiquewhite" if self.pot != 420 else "darkgreen" self.pot_label = Label(self.font, 48, "Pot: ${}".format(self.pot), color, {"midleft": (650, 610)}) #{"center": (700, 610)}) def compare_hands(self, player1, player2): h1 = [] h2 = [] for player, vals in [(player1, h1), (player2, h2)]: for card in player.cards: val = card.value if card.value != 1 else 14 vals.append(val) h1.sort(reverse=True) h2.sort(reverse=True) if h1 == h2: return [player1, player2] elif h2[0] == h2[1]: if h1[0] == h1[1] and h1[0] > h2[0]: return [player1] else: return [player2] else: if h1[0] > h2[0] or h1[0] == h1[1]: return [player1] elif h1[0] == h2[0]: if h1[1] > h2[1]: return [player1] else: return [player2] else: return [player2] def get_winners(self): stayed = [x for x in self.players if x.stayed] best = [] for stayer in stayed: if not best: best.append(stayer) else: new_best = [] for b in best: new_best.extend(self.compare_hands(b, stayer)) best = new_best return best def draw(self, surface): self.pot_label.draw(surface) self.deck.draw(surface) self.dealer_button.draw(surface)
class StatsMenu(data.state.State): """ This state allows the player to choose which game's stats they want to view or return to the lobby. """ name = "stats_menu" def __init__(self): super(StatsMenu, self).__init__() self.font = prepare.FONTS["Saniretro"] self.title = None self.buttons = ButtonGroup() self.labels = [] self.lines = [] self.use_music_handler = False def collect_games_with_stats(self): for name, scene in self.controller.query_all_states().items(): if hasattr(scene, 'initialize_stats'): yield name def make_labels(self): self.labels = [] cash = self.player.cash balance = self.player.account_balance assets = cash + balance starting_cash = prepare.MONEY profit = assets - starting_cash label_info = [("Cash", cash, 110), ("Account", balance, 150), ("Assets", assets, 198), ("Starting Cash", -starting_cash, 238), ("Profit", profit, 283)] left = 500 right = 900 for name, value, topy in label_info: label1 = Label(self.font, 36, name, "white", {"topleft": (left, topy)}) color = "darkgreen" if value >= 0 else "darkred" label2 = Label(self.font, 36, "{:.2f}".format(value), color, {"topright": (right, topy)}) self.labels.extend([label1, label2]) self.lines = [((left, 193), (right, 193)), ((left, 280), (right, 280))] def make_buttons(self, games, screen_rect, col=2): spacer_x = 20 spacer_y = 20 start_y = 410 start_x = (screen_rect.w - NeonButton.width * col - spacer_x * (col - 1)) // 2 buttons = ButtonGroup() for i, game in enumerate(games): y, x = divmod(i, col) pos = (start_x + x * (NeonButton.width + spacer_x), start_y + y * (NeonButton.height + spacer_y)) button = NeonButton(pos, game, self.view_game_stats, game, buttons) pos = (screen_rect.centerx - (NeonButton.width // 2), screen_rect.bottom - (NeonButton.height + 10)) NeonButton(pos, "Lobby", self.back_to_lobby, None, buttons, bindings=[pg.K_ESCAPE]) return buttons def back_to_lobby(self, *args): self.done = True self.next = "lobby" def view_game_stats(self, game): self.persist["current_game_stats"] = game self.next = "stats_screen" self.done = True def startup(self, current_time, persistent): screen_rect = pg.Rect((0, 0), prepare.RENDER_SIZE) self.title = Label( self.font, 64, "Statistics", "darkred", {"midtop": (screen_rect.centerx, screen_rect.top + 10)}) self.start_time = current_time self.persist = persistent self.player = self.persist["casino_player"] games = self.collect_games_with_stats() self.buttons = self.make_buttons(games, screen_rect, 3) self.make_labels() def get_event(self, event, scale=(1, 1)): if event.type == pg.QUIT: self.done = True self.next = "lobby" self.buttons.get_event(event) def draw(self, surface): surface.fill(prepare.BACKGROUND_BASE) self.title.draw(surface) self.buttons.draw(surface) for label in self.labels: label.draw(surface) for line in self.lines: pg.draw.line(surface, pg.Color("white"), *line) def update(self, surface, keys, current_time, dt, scale): mouse_pos = tools.scaled_mouse_pos(scale) self.buttons.update(mouse_pos) self.draw(surface)