예제 #1
0
class Machine:
    def __init__(self, topleft, size):
        self.rect = pg.Rect(topleft, size)
        self.font = prepare.FONTS["Saniretro"]
        self.text_size = 35
        self.text_color = "white"
        self.padding = 25
        self.btn_width = self.btn_height = 100
        self.btn_padding = 35
        self.credits_sound = prepare.SFX["bingo-pay-money"]
        self.bet_sound = prepare.SFX["bingo-pick-1"]

        self.main_buttons = []
        self.coins_button = None
        self.cash_button = None
        self.yes_no_buttons = []

        self.info_labels = []
        self.help_labels = []

        self.max_bet = 5
        self.bet_value = 1

        self.current_bet = 0
        self.last_bet = 0
        self.credits = 0

        self.win = 0
        self.state = "GAME OVER"

        self.player = None
        self.pay_board = None
        self.dealer = None

    def startup(self, player):
        self.state = "GAME OVER"
        self.current_bet = 0
        self.last_bet = 0
        self.credits = 0
        self.win = 0
        self.player = player
        self.build()
        self.dealer.startup()

    def build(self):
        x, y = self.rect.topleft
        w, h = self.rect.size

        # calculate pay board position
        x += self.padding
        y += self.padding
        w -= self.padding * 2
        h = 319
        self.pay_board = PayBoard((x, y), (w, h))

        # calculate cards table position
        y += self.padding + self.pay_board.rect.h
        h = 300
        self.dealer = Dealer((x, y), (w, h))

        # buttons
        y = self.dealer.rect.bottom + self.padding * 4 + self.btn_padding
        self.build_main_buttons(x, y)
        self.build_coins_button(y)
        self.build_cash_button(y)
        self.build_yes_no_buttons()

    def build_main_buttons(self, x, y):
        self.main_buttons = []

        button_list = [('bet', self.bet_one, None),
                       ('bet max', self.bet_max, None),
                       ('hold', self.make_held, '0'),
                       ('hold', self.make_held, '1'),
                       ('hold', self.make_held, '2'),
                       ('hold', self.make_held, '3'),
                       ('hold', self.make_held, '4'),
                       ('draw', self.draw_cards, None)]

        settings = {
            "fill_color": pg.Color("#222222"),
            "font": self.font,
            "font_size": 25,
            "hover_text_color": pg.Color("white"),
            "disable_text_color": pg.Color("#cccccc"),
            "hover_fill_color": pg.Color("#353535"),
            "disable_fill_color": pg.Color("#999999"),
            "active": False
        }

        for text, func, args in button_list:
            rect_style = (x, y, self.btn_width, self.btn_height)
            settings.update({
                'text': text,
                'hover_text': text,
                'disable_text': text,
                'call': func,
                'args': args
            })
            button = Button(rect_style, **settings)
            self.main_buttons.append(button)
            x += self.btn_width + self.btn_padding

    def build_coins_button(self, y):
        settings = {
            "text": "Insert coin",
            "hover_text": "Insert coin",
            "fill_color": pg.Color("gold"),
            "font": self.font,
            "font_size": self.text_size,
            "text_color": pg.Color("#333333"),
            "hover_text_color": pg.Color("#333333"),
            "disable_text_color": pg.Color("#cccccc"),
            "hover_fill_color": pg.Color("yellow"),
            "disable_fill_color": pg.Color("#999999"),
            "call": self.insert_coin
        }

        rect_style = (
            (self.rect.right + self.padding),
            y,
            200,
            60,
        )
        self.coins_button = Button(rect_style, **settings)

    def build_cash_button(self, y):
        settings = {
            "text": "Cash out",
            "hover_text": "Cash out",
            "fill_color": pg.Color("gold"),
            "font": self.font,
            "font_size": self.text_size,
            "text_color": pg.Color("#333333"),
            "hover_text_color": pg.Color("#333333"),
            "disable_text_color": pg.Color("#cccccc"),
            "hover_fill_color": pg.Color("yellow"),
            "disable_fill_color": pg.Color("#999999"),
            "call": self.cash_out
        }

        rect_style = (
            (self.rect.right + self.padding),
            (y - 300),
            200,
            60,
        )
        self.cash_button = Button(rect_style, **settings)

    def build_yes_no_buttons(self):
        self.yes_no_buttons = []
        from_center = 125
        settings = {
            "text": "Yes",
            "hover_text": "Yes",
            "font": self.font,
            "font_size": 80,
            "text_color": pg.Color("white"),
            "hover_text_color": pg.Color("white"),
            "fill_color": pg.Color("#0000c3"),
            "hover_fill_color": pg.Color("blue"),
            "call": self.check_double_up,
            "args": (True, ),
            "bindings": [pg.K_y]
        }
        rect_style = (0, 0, 200, 100)
        button = Button(rect_style, **settings)
        button.rect.centerx = self.dealer.rect.centerx - from_center
        button.rect.centery = self.dealer.rect.centery
        self.yes_no_buttons.append(button)

        settings.update({
            'text': 'No',
            'hover_text': 'No',
            'call': self.check_double_up,
            'args': (False, ),
            "bindings": [pg.K_n]
        })
        rect_style = (0, 0, 200, 100)
        button = Button(rect_style, **settings)
        button.rect.centerx = self.dealer.rect.centerx + from_center
        button.rect.centery = self.dealer.rect.centery
        self.yes_no_buttons.append(button)

    def make_help_labels(self, rect):
        labels = []
        text = "Double up ?"
        label = Blinker(self.font, 100, text, "red", {
            "centerx": rect.centerx,
            "top": rect.top
        }, 700)
        labels.append(label)
        text = "If selected card beats dealers, player wins. Ace is highest, two is lowest"
        label = MultiLineLabel(self.font,
                               self.text_size,
                               text,
                               self.text_color, {"center": rect.center},
                               align="center")
        labels.append(label)

        return labels

    def make_info_label(self, rect):
        labels = []
        y = rect.bottom + self.padding
        if self.state == "WON" or self.state == "DOUBLE UP":
            text = "you have won: {} double up to: {}".format(
                self.win, self.win * 2)
            label = MultiLineLabel(self.font,
                                   35,
                                   text,
                                   self.text_color, {
                                       "centerx": rect.centerx,
                                       "top": y
                                   },
                                   char_limit=20,
                                   align="center")
            labels.append(label)
        else:
            if self.state == "GAME OVER":
                if self.win > 0:
                    text = 'you win {}'.format(self.win)
                    label = Label(self.font, self.text_size, text,
                                  self.text_color, {
                                      "centerx": rect.centerx,
                                      "top": y
                                  })
                    labels.append(label)
                elif self.current_bet == 0:
                    text = "game over"
                    label = Label(self.font, self.text_size, text,
                                  self.text_color, {
                                      "centerx": rect.centerx,
                                      "top": y
                                  })
                    labels.append(label)

        text = 'Credits {}'.format(self.credits)
        label = Label(self.font, self.text_size, text, self.text_color,
                      {"topright": (rect.right, y)})
        labels.append(label)
        coins_text = "Current Bet {}".format(self.current_bet)
        label = Label(self.font, self.text_size, coins_text, self.text_color,
                      {"topleft": (rect.x, y)})
        labels.append(label)

        balance = 'Balance: ${}'.format(self.player.cash)
        pos = ((self.rect.right + self.padding), (self.rect.top + 300))
        label = Label(self.font, 50, balance, self.text_color,
                      {"topleft": pos})
        labels.append(label)

        return labels

    def insert_coin(self, *args):
        if self.state == "GAME OVER":
            self.start_waiting()
            self.credits += self.bet_value
            self.player.cash -= self.bet_value
            self.credits_sound.play()

    def start_waiting(self):
        self.dealer.playing = True
        self.dealer.waiting = True

    def cash_out(self, *args):
        total_credits = self.credits
        self.credits = 0

        if self.state == "GAME OVER":
            total_credits += self.current_bet
            self.current_bet = 0

        self.player.cash += total_credits
        for _ in range(total_credits):
            self.credits_sound.play()

    def toggle_buttons(self, buttons, active=True):
        for button in buttons:
            button.active = active

    def bet_one(self, *args):
        if self.credits > 0 and self.current_bet < self.max_bet:
            self.current_bet += 1
            self.credits -= 1
            self.bet_sound.play()
        elif self.current_bet > 1:
            self.credits += self.current_bet - 1
            self.current_bet = 1
            self.bet_sound.play()
        self.pay_board.update_bet_rect(self.current_bet)
        self.main_buttons[-1].active = True  # draw button

    def bet_max(self, *args):
        if self.credits > 0:
            if self.credits >= (self.max_bet - self.current_bet):
                aux = self.max_bet - self.current_bet
                self.current_bet += aux
                self.credits -= aux
            else:
                self.current_bet += self.credits
                self.credits = 0
            self.bet_sound.play()
            self.draw_cards()
        self.pay_board.update_bet_rect(self.current_bet)
        self.main_buttons[-1].active = True  # draw button

    def make_last_bet(self):
        """ """
        if self.credits > 0:
            if self.credits >= self.last_bet:
                self.current_bet = self.last_bet
                self.credits -= self.last_bet
            else:
                self.current_bet = self.credits
                self.credits = 0
        self.pay_board.update_bet_rect(self.current_bet)

    def new_game(self):
        self.state = "PLAYING"
        self.dealer.startup()
        self.dealer.playing = True
        self.dealer.waiting = False
        self.win = 0
        self.player.increase('games played')

        if self.current_bet == 0 and self.last_bet > 0:
            self.make_last_bet()

        self.player.increase('total wagered', self.current_bet)
        self.dealer.draw_cards()
        rank = self.dealer.evaluate_hand()
        self.pay_board.update_rank_rect(rank)

        for button in self.main_buttons:
            button.active = True
        # bet and bet max buttons
        self.toggle_buttons((self.main_buttons[0], self.main_buttons[1]),
                            False)

    def evaluate_final_hand(self):
        self.dealer.draw_cards()
        rank = self.dealer.evaluate_hand()
        self.pay_board.update_rank_rect(rank)
        if rank != NO_HAND:
            index = self.current_bet - 1
            self.win = PAYTABLE[index][rank]
            self.help_labels = self.make_help_labels(self.pay_board.rect)
            self.player.increase('games won')
            self.state = "WON"
        else:
            self.player.increase('games lost')
            self.player.increase('total lost', self.current_bet)
            self.state = "GAME OVER"
            self.start_waiting()

        self.last_bet = self.current_bet
        self.current_bet = 0

    def draw_cards(self, *args):
        if self.current_bet > 0 or self.last_bet > 0:
            if self.state == "GAME OVER":
                self.pay_board.reset()
                self.new_game()
            elif self.state == "PLAYING":
                self.evaluate_final_hand()

    def make_held(self, *args):
        """ Some unknown issue with 0 Int args,
            so Str values passed to the func and
            here are converted to Int"""
        index = int(args[0])
        if self.state == "PLAYING":
            self.dealer.toggle_held(index)

        elif self.state == "DOUBLE UP":
            if index > 0:  # if is not the first card
                win = self.dealer.select_card(index)
                self.dealer.draw_cards()
                if win:
                    self.win *= 2
                    self.player.increase('double ups won')
                    self.state = "WON"
                    self.pay_board.rank_sound.play()
                else:
                    self.win = 0
                    self.player.increase('double ups lost')
                    # Use last_bet because it has already been updated to the bet from the current hand
                    self.player.increase('total lost', self.last_bet)
                    self.state = "GAME OVER"
                    self.start_waiting()

    def check_double_up(self, *args):
        double_up = args[0][0]
        if double_up:
            self.help_labels = self.make_help_labels(self.pay_board.rect)
            self.dealer.start_double_up()
            self.state = "DOUBLE UP"
            self.dealer.double_up = True
        else:
            self.credits += self.win
            self.player.increase('total won', self.win)
            self.state = "GAME OVER"
            self.start_waiting()

    def get_event(self, event, scale):
        self.coins_button.get_event(event)
        self.cash_button.get_event(event)
        for button in self.main_buttons:
            button.get_event(event)
        if self.state == "WON":
            for button in self.yes_no_buttons:
                button.get_event(event)

        if event.type == pg.MOUSEBUTTONDOWN:
            if self.state == "PLAYING" or self.state == "DOUBLE UP":
                mouse_pos = tools.scaled_mouse_pos(scale)
                index = self.dealer.get_event(mouse_pos)
                if type(index) == int:
                    self.make_held(str(index))  # Little hack

    def update(self, mouse_pos, dt):
        self.info_labels = self.make_info_label(self.dealer.rect)

        if self.state == "GAME OVER":
            if self.credits == 0:
                if self.current_bet == 0:
                    # Turn all the buttons off
                    self.toggle_buttons(self.main_buttons, False)
                    self.dealer.playing = False
                elif self.current_bet == 1:
                    # Turn everything except Draw off
                    self.toggle_buttons(self.main_buttons[0:-1], False)
                    # Turn Draw on
                    self.toggle_buttons([self.main_buttons[-1]])
                else:
                    # Turn everything except Draw and Bet One off
                    self.toggle_buttons(self.main_buttons[1:-1], False)
                    # Turn Bet On and Draw on
                    self.toggle_buttons(
                        [self.main_buttons[0], self.main_buttons[-1]])
            else:
                if self.current_bet > 0 or self.last_bet > 0:
                    # Turn on Bet, Bet Max and Draw Buttons
                    self.toggle_buttons([
                        self.main_buttons[0], self.main_buttons[1],
                        self.main_buttons[-1]
                    ])
                    # Turn other buttons off
                    self.toggle_buttons(self.main_buttons[2:-1], False)
                else:
                    # Turn on Bet and Bet Max
                    self.toggle_buttons(self.main_buttons[0:2])
                    # Turn other buttons off
                    self.toggle_buttons(self.main_buttons[2:], False)

        self.dealer.update(dt)

        if self.state == "WON":
            for button in self.yes_no_buttons:
                button.update(mouse_pos)
        if self.state == "WON" or self.state == "DOUBLE UP":
            for label in self.help_labels:
                if isinstance(label, Blinker):
                    label.update(dt)
            self.main_buttons[-1].active = False

        self.coins_button.update(mouse_pos)
        self.cash_button.update(mouse_pos)
        for button in self.main_buttons:
            button.update(mouse_pos)

    def draw(self, surface):
        self.dealer.draw(surface)
        for label in self.info_labels:
            label.draw(surface)
        for button in self.main_buttons:
            button.draw(surface)
        self.coins_button.draw(surface)
        self.cash_button.draw(surface)
        if self.state == "WON":
            for button in self.yes_no_buttons:
                button.draw(surface)
        if self.state == "WON" or self.state == "DOUBLE UP":
            for label in self.help_labels:
                label.draw(surface)
        else:
            self.pay_board.draw(surface)
예제 #2
0
class BlackjackGame(object):
    """Represents a single game of blackjack."""
    draw_group = pg.sprite.Group()
    move_animations = pg.sprite.Group()
    advisor = Advisor(draw_group, move_animations)
    advisor.active = True
    advisor_back = prepare.GFX["advisor_back"]
    advisor_front = prepare.GFX["advisor_front"]
    advisor_back_dim = prepare.GFX["advisor_back_dim"]
    advisor_front_dim = prepare.GFX["advisor_front_dim"]
    font = prepare.FONTS["Saniretro"]
    result_font = prepare.FONTS["Saniretro"]
    deal_sounds = [prepare.SFX[name] for name in ["cardplace{}".format(x) for x in (2, 3, 4)]]
    chip_sounds = [prepare.SFX[name] for name in ["chipsstack{}".format(x) for x in (3, 5, 6)]]
    chip_size = (48, 30)
    screen_rect = pg.Rect((0, 0), prepare.RENDER_SIZE)
    advisor_active = True

    def __init__(self, casino_player, player_cash, chips=None, chip_pile=None):
        self.deck = Deck((20, 100), prepare.CARD_SIZE, 40)
        self.dealer = Dealer()
        self.chip_rack = ChipRack((1100, 130), self.chip_size)
        self.moving_stacks = []
        self.casino_player = casino_player
        self.player = Player(self.chip_size, player_cash, chips, chip_pile)
        self.labels = self.make_labels()
        self.current_player_hand = self.player.hands[0]
        self.quick_bet = 0
        self.last_bet = 0
        rect = self.advisor_back.get_rect().union(self.advisor_front.get_rect())
        self.advisor_button = Button(rect, call=self.toggle_advisor)

    def make_labels(self):
        labels_info = [
                ("Drop chips in chip rack", 36, "antiquewhite", 100,
                {"midtop": (self.chip_rack.rect.centerx, self.chip_rack.rect.bottom + 5)}),
                ("to make change", 36, "antiquewhite", 100,
                {"midtop": (self.chip_rack.rect.centerx, self.chip_rack.rect.bottom + 60)}),
                ("Blackjack Pays 3 to 2", 64, "gold3", 120, {"midtop": (580, 300)}),
                ("Dealer must draw to 16 and stand on 17", 48, "antiquewhite", 100,
                {"midtop": (580, 240)})
                ]
        labels = []
        for info in labels_info:
            label = Label(self.font, info[1], info[0], info[2], info[4], bg=prepare.FELT_GREEN)
            label.image.set_alpha(info[3])
            labels.append(label)
        return labels

    def toggle_advisor(self, *args):
        BlackjackGame.advisor_active = not BlackjackGame.advisor_active

    def tally_hands(self):
        """
        Calculate result of each player hand and set appropriate
        flag for each hand.
        """
        if self.dealer.hand.blackjack:
            for hand in self.player.hands:
                hand.loser = True
        elif self.dealer.hand.busted:
            for hand in self.player.hands:
                if not hand.busted and not hand.blackjack:
                    hand.winner = True
        else:
            d_score = self.dealer.hand.best_score()
            for hand in self.player.hands:
                if not hand.busted:
                    p_score = hand.best_score()
                    if p_score == 21 and len(hand.cards) == 2:
                        hand.blackjack = True
                    elif p_score < d_score:
                        hand.loser = True
                    elif p_score == d_score:
                        hand.push = True
                    else:
                        hand.winner = True

    def pay_out(self):
        """
        Calculate player win amounts, update stats and return chips
        totalling total win amount.
        """
        cash = 0
        for hand in self.player.hands:
            bet = hand.bet.get_chip_total()
            self.casino_player.increase("hands played")
            self.casino_player.increase("total bets", bet)
            if hand.busted:
                self.casino_player.increase("busts")
                self.casino_player.increase("hands lost")
            elif hand.loser:
                self.casino_player.increase("hands lost")
            elif hand.blackjack:
                cash += int(bet * 2.5)
                self.casino_player.increase("blackjacks")
                self.casino_player.increase("hands won")
            elif hand.winner:
                cash += bet * 2
                self.casino_player.increase("hands won")
            elif hand.push:
                cash += bet
                self.casino_player.increase("pushes")

        self.casino_player.increase("total winnings",  cash)
        chips = cash_to_chips(cash, self.chip_size)
        return chips

    def get_event(self, event):
        self.advisor_button.get_event(event)

    def update(self, dt, mouse_pos):
        self.advisor_button.update(mouse_pos)
        total_text = "Chip Total:  ${}".format(self.player.chip_pile.get_chip_total())
        screen = self.screen_rect
        self.chip_total_label = Label(self.font, 48, total_text, "gold3",
                               {"bottomleft": (screen.left + 3, screen.bottom - 3)})
        self.chip_rack.update()
        if self.advisor_active:
            self.move_animations.update(dt)
예제 #3
0
class BlackjackGame(object):
    """Represents a single game of blackjack."""
    draw_group = pg.sprite.Group()
    move_animations = pg.sprite.Group()
    advisor = Advisor(draw_group, move_animations)
    advisor.active = True
    advisor_back = prepare.GFX["advisor_back"]
    advisor_front = prepare.GFX["advisor_front"]
    advisor_back_dim = prepare.GFX["advisor_back_dim"]
    advisor_front_dim = prepare.GFX["advisor_front_dim"]
    font = prepare.FONTS["Saniretro"]
    result_font = prepare.FONTS["Saniretro"]
    deal_sounds = [
        prepare.SFX[name]
        for name in ["cardplace{}".format(x) for x in (2, 3, 4)]
    ]
    chip_sounds = [
        prepare.SFX[name]
        for name in ["chipsstack{}".format(x) for x in (3, 5, 6)]
    ]
    chip_size = (48, 30)
    screen_rect = pg.Rect((0, 0), prepare.RENDER_SIZE)
    advisor_active = True

    def __init__(self, casino_player, player_cash, chips=None, chip_pile=None):
        self.deck = Deck((20, 100), prepare.CARD_SIZE, 40)
        self.dealer = Dealer()
        self.chip_rack = ChipRack((1100, 130), self.chip_size)
        self.moving_stacks = []
        self.casino_player = casino_player
        self.player = Player(self.chip_size, player_cash, chips, chip_pile)
        self.labels = self.make_labels()
        self.current_player_hand = self.player.hands[0]
        self.quick_bet = 0
        self.last_bet = 0
        rect = self.advisor_back.get_rect().union(
            self.advisor_front.get_rect())
        self.advisor_button = Button(rect, call=self.toggle_advisor)

    def make_labels(self):
        labels_info = [("Drop chips in chip rack", 36, "antiquewhite", 100, {
            "midtop":
            (self.chip_rack.rect.centerx, self.chip_rack.rect.bottom + 5)
        }),
                       ("to make change", 36, "antiquewhite", 100, {
                           "midtop": (self.chip_rack.rect.centerx,
                                      self.chip_rack.rect.bottom + 60)
                       }),
                       ("Blackjack Pays 3 to 2", 64, "gold3", 120, {
                           "midtop": (580, 300)
                       }),
                       ("Dealer must draw to 16 and stand on 17", 48,
                        "antiquewhite", 100, {
                            "midtop": (580, 240)
                        })]
        labels = []
        for info in labels_info:
            label = Label(self.font,
                          info[1],
                          info[0],
                          info[2],
                          info[4],
                          bg=prepare.FELT_GREEN)
            label.image.set_alpha(info[3])
            labels.append(label)
        return labels

    def toggle_advisor(self, *args):
        BlackjackGame.advisor_active = not BlackjackGame.advisor_active

    def tally_hands(self):
        """
        Calculate result of each player hand and set appropriate
        flag for each hand.
        """
        if self.dealer.hand.blackjack:
            for hand in self.player.hands:
                hand.loser = True
        elif self.dealer.hand.busted:
            for hand in self.player.hands:
                if not hand.busted and not hand.blackjack:
                    hand.winner = True
        else:
            d_score = self.dealer.hand.best_score()
            for hand in self.player.hands:
                if not hand.busted:
                    p_score = hand.best_score()
                    if p_score == 21 and len(hand.cards) == 2:
                        hand.blackjack = True
                    elif p_score < d_score:
                        hand.loser = True
                    elif p_score == d_score:
                        hand.push = True
                    else:
                        hand.winner = True

    def pay_out(self):
        """
        Calculate player win amounts, update stats and return chips
        totalling total win amount.
        """
        cash = 0
        for hand in self.player.hands:
            bet = hand.bet.get_chip_total()
            self.casino_player.increase("hands played")
            self.casino_player.increase("total bets", bet)
            if hand.busted:
                self.casino_player.increase("busts")
                self.casino_player.increase("hands lost")
            elif hand.loser:
                self.casino_player.increase("hands lost")
            elif hand.blackjack:
                cash += int(bet * 2.5)
                self.casino_player.increase("blackjacks")
                self.casino_player.increase("hands won")
            elif hand.winner:
                cash += bet * 2
                self.casino_player.increase("hands won")
            elif hand.push:
                cash += bet
                self.casino_player.increase("pushes")

        self.casino_player.increase("total winnings", cash)
        chips = cash_to_chips(cash, self.chip_size)
        return chips

    def get_event(self, event):
        self.advisor_button.get_event(event)

    def update(self, dt, mouse_pos):
        self.advisor_button.update(mouse_pos)
        total_text = "Chip Total:  ${}".format(
            self.player.chip_pile.get_chip_total())
        screen = self.screen_rect
        self.chip_total_label = Label(
            self.font, 48, total_text, "gold3",
            {"bottomleft": (screen.left + 3, screen.bottom - 3)})
        self.chip_rack.update()
        if self.advisor_active:
            self.move_animations.update(dt)
예제 #4
0
class Machine:
    def __init__(self, topleft, size):
        self.rect = pg.Rect(topleft, size)
        self.font = prepare.FONTS["Saniretro"]
        self.text_size = 35
        self.text_color = "white"
        self.padding = 25
        self.btn_width = self.btn_height = 100
        self.btn_padding = 35
        self.credits_sound = prepare.SFX["bingo-pay-money"]
        self.bet_sound = prepare.SFX["bingo-pick-1"]

        self.main_buttons = []
        self.coins_button = None
        self.cash_button = None
        self.yes_no_buttons = []

        self.info_labels = []
        self.help_labels = []

        self.max_bet = 5
        self.bet_value = 1

        self.current_bet = 0
        self.last_bet = 0
        self.credits = 0

        self.win = 0
        self.state = "GAME OVER"

        self.player = None
        self.pay_board = None
        self.dealer = None

    def startup(self, player):
        self.state = "GAME OVER"
        self.current_bet = 0
        self.last_bet = 0
        self.credits = 0
        self.win = 0
        self.player = player
        self.build()
        self.dealer.startup()

    def build(self):
        x, y = self.rect.topleft
        w, h = self.rect.size

        # calculate pay board position
        x += self.padding
        y += self.padding
        w -= self.padding*2
        h = 319
        self.pay_board = PayBoard((x, y), (w, h))

        # calculate cards table position
        y += self.padding + self.pay_board.rect.h
        h = 300
        self.dealer = Dealer((x, y), (w, h))

        # buttons
        y = self.dealer.rect.bottom + self.padding*4 + self.btn_padding
        self.build_main_buttons(x, y)
        self.build_coins_button(y)
        self.build_cash_button(y)
        self.build_yes_no_buttons()

    def build_main_buttons(self, x, y):
        self.main_buttons = []

        button_list = [('bet', self.bet_one, None), ('bet max', self.bet_max, None),
                       ('hold', self.make_held, '0'), ('hold', self.make_held, '1'),
                       ('hold', self.make_held, '2'), ('hold', self.make_held, '3'),
                       ('hold', self.make_held, '4'), ('draw', self.draw_cards, None)]

        settings = {"fill_color": pg.Color("#222222"),
                    "font": self.font,
                    "font_size": 25,
                    "hover_text_color": pg.Color("white"),
                    "disable_text_color": pg.Color("#cccccc"),
                    "hover_fill_color": pg.Color("#353535"),
                    "disable_fill_color": pg.Color("#999999"),
                    "active": False}

        for text, func, args in button_list:
            rect_style = (x, y, self.btn_width, self.btn_height)
            settings.update({'text': text, 'hover_text': text,
                            'disable_text': text, 'call': func, 'args': args})
            button = Button(rect_style, **settings)
            self.main_buttons.append(button)
            x += self.btn_width + self.btn_padding

    def build_coins_button(self, y):
        settings = {"text": "Insert coin",
                    "hover_text": "Insert coin",
                    "fill_color": pg.Color("gold"),
                    "font": self.font,
                    "font_size": self.text_size,
                    "text_color": pg.Color("#333333"),
                    "hover_text_color": pg.Color("#333333"),
                    "disable_text_color": pg.Color("#cccccc"),
                    "hover_fill_color": pg.Color("yellow"),
                    "disable_fill_color": pg.Color("#999999"),
                    "call": self.insert_coin}

        rect_style = ((self.rect.right + self.padding), y, 200, 60,)
        self.coins_button = Button(rect_style, **settings)

    def build_cash_button(self, y):
        settings = {"text": "Cash out",
                    "hover_text": "Cash out",
                    "fill_color": pg.Color("gold"),
                    "font": self.font,
                    "font_size": self.text_size,
                    "text_color": pg.Color("#333333"),
                    "hover_text_color": pg.Color("#333333"),
                    "disable_text_color": pg.Color("#cccccc"),
                    "hover_fill_color": pg.Color("yellow"),
                    "disable_fill_color": pg.Color("#999999"),
                    "call": self.cash_out}

        rect_style = ((self.rect.right + self.padding), (y - 300), 200, 60,)
        self.cash_button = Button(rect_style, **settings)

    def build_yes_no_buttons(self):
        self.yes_no_buttons = []
        from_center = 125
        settings = {"text": "Yes",
                    "hover_text": "Yes",
                    "font": self.font,
                    "font_size": 80,
                    "text_color": pg.Color("white"),
                    "hover_text_color": pg.Color("white"),
                    "fill_color": pg.Color("#0000c3"),
                    "hover_fill_color": pg.Color("blue"),
                    "call": self.check_double_up,
                    "args": (True,),
                    "bindings": [pg.K_y]}
        rect_style = (0, 0, 200, 100)
        button = Button(rect_style, **settings)
        button.rect.centerx = self.dealer.rect.centerx - from_center
        button.rect.centery = self.dealer.rect.centery
        self.yes_no_buttons.append(button)

        settings.update({'text': 'No',
                         'hover_text': 'No',
                         'call': self.check_double_up,
                         'args': (False,),
                         "bindings": [pg.K_n]})
        rect_style = (0, 0, 200, 100)
        button = Button(rect_style, **settings)
        button.rect.centerx = self.dealer.rect.centerx + from_center
        button.rect.centery = self.dealer.rect.centery
        self.yes_no_buttons.append(button)

    def make_help_labels(self, rect):
        labels = []
        text = "Double up ?"
        label = Blinker(self.font, 100, text, "red",
                        {"centerx": rect.centerx, "top": rect.top}, 700)
        labels.append(label)
        text = "If selected card beats dealers, player wins. Ace is highest, two is lowest"
        label = MultiLineLabel(self.font, self.text_size, text,
                               self.text_color, {"center": rect.center}, align="center")
        labels.append(label)

        return labels

    def make_info_label(self, rect):
        labels = []
        y = rect.bottom + self.padding
        if self.state == "WON" or self.state == "DOUBLE UP":
            text = "you have won: {} double up to: {}".format(self.win, self.win*2)
            label = MultiLineLabel(self.font, 35, text, self.text_color,
                                   {"centerx": rect.centerx, "top": y},
                                   char_limit=20, align="center")
            labels.append(label)
        else:
            if self.state == "GAME OVER":
                if self.win > 0:
                    text = 'you win {}'.format(self.win)
                    label = Label(self.font, self.text_size, text,
                                  self.text_color,
                                  {"centerx": rect.centerx, "top": y})
                    labels.append(label)
                elif self.current_bet == 0:
                    text = "game over"
                    label = Label(self.font, self.text_size, text,
                                  self.text_color,
                                  {"centerx": rect.centerx, "top": y})
                    labels.append(label)

        text = 'Credits {}'.format(self.credits)
        label = Label(self.font, self.text_size, text, self.text_color,
                      {"topright": (rect.right, y)})
        labels.append(label)
        coins_text = "Current Bet {}".format(self.current_bet)
        label = Label(self.font, self.text_size, coins_text, self.text_color,
                      {"topleft": (rect.x, y)})
        labels.append(label)

        balance = 'Balance: ${}'.format(self.player.cash)
        pos = ((self.rect.right + self.padding), (self.rect.top + 300))
        label = Label(self.font, 50, balance, self.text_color,
                      {"topleft": pos})
        labels.append(label)

        return labels

    def insert_coin(self, *args):
        if self.state == "GAME OVER":
            self.start_waiting()
            self.credits += self.bet_value
            self.player.cash -= self.bet_value
            self.credits_sound.play()

    def start_waiting(self):
        self.dealer.playing = True
        self.dealer.waiting = True

    def cash_out(self, *args):
        total_credits = self.credits
        self.credits = 0

        if self.state == "GAME OVER":
            total_credits += self.current_bet
            self.current_bet = 0

        self.player.cash += total_credits
        for _ in range(total_credits):
            self.credits_sound.play()

    def toggle_buttons(self, buttons, active=True):
        for button in buttons:
                button.active = active

    def bet_one(self, *args):
        if self.credits > 0 and self.current_bet < self.max_bet:
            self.current_bet += 1
            self.credits -= 1
            self.bet_sound.play()
        elif self.current_bet > 1:
            self.credits += self.current_bet - 1
            self.current_bet = 1
            self.bet_sound.play()
        self.pay_board.update_bet_rect(self.current_bet)
        self.main_buttons[-1].active = True  # draw button

    def bet_max(self, *args):
        if self.credits > 0:
            if self.credits >= (self.max_bet - self.current_bet):
                aux = self.max_bet - self.current_bet
                self.current_bet += aux
                self.credits -= aux
            else:
                self.current_bet += self.credits
                self.credits = 0
            self.bet_sound.play()
            self.draw_cards()
        self.pay_board.update_bet_rect(self.current_bet)
        self.main_buttons[-1].active = True  # draw button

    def make_last_bet(self):
        """ """
        if self.credits > 0:
            if self.credits >= self.last_bet:
                self.current_bet = self.last_bet
                self.credits -= self.last_bet
            else:
                self.current_bet = self.credits
                self.credits = 0
        self.pay_board.update_bet_rect(self.current_bet)

    def new_game(self):
        self.state = "PLAYING"
        self.dealer.startup()
        self.dealer.playing = True
        self.dealer.waiting = False
        self.win = 0
        self.player.increase('games played')

        if self.current_bet == 0 and self.last_bet > 0:
            self.make_last_bet()

        self.player.increase('total wagered', self.current_bet)
        self.dealer.draw_cards()
        rank = self.dealer.evaluate_hand()
        self.pay_board.update_rank_rect(rank)

        for button in self.main_buttons:
            button.active = True
        # bet and bet max buttons
        self.toggle_buttons((self.main_buttons[0], self.main_buttons[1]), False)

    def evaluate_final_hand(self):
        self.dealer.draw_cards()
        rank = self.dealer.evaluate_hand()
        self.pay_board.update_rank_rect(rank)
        if rank != NO_HAND:
            index = self.current_bet - 1
            self.win = PAYTABLE[index][rank]
            self.help_labels = self.make_help_labels(self.pay_board.rect)
            self.player.increase('games won')
            self.state = "WON"
        else:
            self.player.increase('games lost')
            self.player.increase('total lost', self.current_bet)
            self.state = "GAME OVER"
            self.start_waiting()

        self.last_bet = self.current_bet
        self.current_bet = 0

    def draw_cards(self, *args):
        if self.current_bet > 0 or self.last_bet > 0:
            if self.state == "GAME OVER":
                self.pay_board.reset()
                self.new_game()
            elif self.state == "PLAYING":
                self.evaluate_final_hand()

    def make_held(self, *args):
        """ Some unknown issue with 0 Int args,
            so Str values passed to the func and
            here are converted to Int"""
        index = int(args[0])
        if self.state == "PLAYING":
            self.dealer.toggle_held(index)

        elif self.state == "DOUBLE UP":
            if index > 0:  # if is not the first card
                win = self.dealer.select_card(index)
                self.dealer.draw_cards()
                if win:
                    self.win *= 2
                    self.player.increase('double ups won')
                    self.state = "WON"
                    self.pay_board.rank_sound.play()
                else:
                    self.win = 0
                    self.player.increase('double ups lost')
                    # Use last_bet because it has already been updated to the bet from the current hand
                    self.player.increase('total lost', self.last_bet)
                    self.state = "GAME OVER"
                    self.start_waiting()

    def check_double_up(self, *args):
        double_up = args[0][0]
        if double_up:
            self.help_labels = self.make_help_labels(self.pay_board.rect)
            self.dealer.start_double_up()
            self.state = "DOUBLE UP"
            self.dealer.double_up = True
        else:
            self.credits += self.win
            self.player.increase('total won', self.win)
            self.state = "GAME OVER"
            self.start_waiting()

    def get_event(self, event, scale):
        self.coins_button.get_event(event)
        self.cash_button.get_event(event)
        for button in self.main_buttons:
            button.get_event(event)
        if self.state == "WON":
            for button in self.yes_no_buttons:
                button.get_event(event)

        if event.type == pg.MOUSEBUTTONDOWN:
            if self.state == "PLAYING" or self.state == "DOUBLE UP":
                mouse_pos = tools.scaled_mouse_pos(scale)
                index = self.dealer.get_event(mouse_pos)
                if type(index) == int:
                    self.make_held(str(index))  # Little hack

    def update(self, mouse_pos, dt):
        self.info_labels = self.make_info_label(self.dealer.rect)

        if self.state == "GAME OVER":
            if self.credits == 0:
                if self.current_bet == 0:
                    # Turn all the buttons off
                    self.toggle_buttons(self.main_buttons, False)
                    self.dealer.playing = False
                elif self.current_bet == 1:
                    # Turn everything except Draw off
                    self.toggle_buttons(self.main_buttons[0:-1], False)
                    # Turn Draw on
                    self.toggle_buttons([self.main_buttons[-1]])
                else:
                    # Turn everything except Draw and Bet One off
                    self.toggle_buttons(self.main_buttons[1:-1], False)
                    # Turn Bet On and Draw on
                    self.toggle_buttons([self.main_buttons[0], self.main_buttons[-1]])
            else:
                if self.current_bet > 0 or self.last_bet > 0:
                    # Turn on Bet, Bet Max and Draw Buttons
                    self.toggle_buttons([self.main_buttons[0],
                                        self.main_buttons[1],
                                        self.main_buttons[-1]])
                    # Turn other buttons off
                    self.toggle_buttons(self.main_buttons[2:-1], False)
                else:
                    # Turn on Bet and Bet Max
                    self.toggle_buttons(self.main_buttons[0:2])
                    # Turn other buttons off
                    self.toggle_buttons(self.main_buttons[2:], False)

        self.dealer.update(dt)

        if self.state == "WON":
            for button in self.yes_no_buttons:
                button.update(mouse_pos)
        if self.state == "WON" or self.state == "DOUBLE UP":
            for label in self.help_labels:
                if isinstance(label, Blinker):
                    label.update(dt)
            self.main_buttons[-1].active = False

        self.coins_button.update(mouse_pos)
        self.cash_button.update(mouse_pos)
        for button in self.main_buttons:
            button.update(mouse_pos)

    def draw(self, surface):
        self.dealer.draw(surface)
        for label in self.info_labels:
            label.draw(surface)
        for button in self.main_buttons:
            button.draw(surface)
        self.coins_button.draw(surface)
        self.cash_button.draw(surface)
        if self.state == "WON":
            for button in self.yes_no_buttons:
                button.draw(surface)
        if self.state == "WON" or self.state == "DOUBLE UP":
            for label in self.help_labels:
                label.draw(surface)
        else:
            self.pay_board.draw(surface)