Choosing to hit

When the player decides to click the hit button, the GameWindow's hit method is called. This simply passes over to the GameScreen class to handle playing the deal animation:

def hit(self):
self.game_screen.hit()

The hit method on our GameScreen needs to set up for the deal animation in much the same way as it did when displaying the initial table:

def hit(self):
self.master.remove_all_buttons()
new_card = self.game_state.draw()
card_number = len(self.game_state.player.hand.cards)
image_pos = self.get_player_card_pos(card_number)

self.cards_to_deal_images.append(new_card.get_file())
self.cards_to_deal_positions.append(image_pos)

self.play_deal_animation()

while self.playing_animation:
self.master.update()

Before playing our animation, we need to remove the hit and stick buttons from our GameWindow. This prevents double-taps of the hit button from causing animation problems.

We draw a card from the deck, check the number of cards the player will now have, calculate its position on the table, and set up the deal animations using our cards_to_deal lists. The deal animation is played and we again wait for it to complete with another while loop:

self.game_state.hit(new_card)
self.update_text()
self.check_for_winner()

Once the animation has finished, we add the card to the GameState, update the text on screen, and check for a winner.

Adding the card on the game state simply passes the card instance over to our player:

def hit(self, card):
self.player.receive_card(card)

To check for a winner, we pass back to the GameState object's check_for_winner method. If it finds a winner, we need to show the dealer's face-down card and the winner text in the middle of the screen. Then we can pass back to the GameWindowobject's on_winner method to display the relevant GUI options:

def check_for_winner(self):
winner = self.game_state.check_for_winner()

if winner:
self.show_dealers_cards(self.game_state.get_table_state())
self.show_winner_text(winner)
self.master.on_winner()
else:
self.master.show_gameplay_buttons()

The GameStateobject's check_for_winner method is much like it was previously, except we can use the player's properties to shorten it slightly:

def check_for_winner(self):
if self.player.has_blackjack:
self.has_winner = 'p'
elif self.player.is_over:
self.has_winner = 'd'

return self.has_winner

If we did not find a winner, the GameWindow will just show our gameplay buttons. These are the usual hit and stick buttons:

def show_gameplay_buttons(self):
self.next_round_button.pack_forget()
self.quit_button.pack_forget()

self.hit_button.pack(side=tk.LEFT, padx=(100, 200))
self.stick_button.pack(side=tk.LEFT)

If, however, we did indeed create a winner from the last draw, we need to reveal the dealer's face-down card. We do this by using the Card class' get_file method to find the image of its front, then drawing it over the top of the card back image:

def show_dealers_cards(self, table_state):
dealer_first_card = table_state['dealer_cards'][0].get_file()
self.create_image((self.CARD_ORIGINAL_POSITION, self.DEALER_CARD_HEIGHT), image=dealer_first_card)

The rest of the logic is handed over to the GUI elements under the GameWindow class:

def on_winner(self):
self.show_next_round_options()

def
show_next_round_options(self):
self.hit_button.pack_forget()
self.stick_button.pack_forget()

self.next_round_button.pack(side=tk.LEFT, padx=(100, 200))
self.quit_button.pack(side=tk.LEFT)

When a winner is found, the hit and stick buttons are removed from the bottom of the window and they are replaced with next round and quit buttons.

The quit button is the same as before, calling the Tk widget's destroy method:

def next_round(self):
self.remove_all_buttons()
self.game_screen.next_round()

Our next_round method removes all buttons from the GUI once again and passes over to the GameScreen, telling it to begin the next round:

def next_round(self):
self.delete(self.winner_text)
self.winner_text = None
self.game_state.assign_winnings()
if self.game_state.player_can_place_bet():
self.game_state.next_round()
self.display_table()
else:
self.show_out_of_money_text()
self.master.on_game_over()

With the new round beginning, we no longer need to display who has won, so we delete the winner text with the Canvasdelete method. We also remove the attribute's value by setting it back to None.

The GameState now needs to give all of the money from the pot to the winner. This is handled by the assign_winnings method:

def assign_winnings(self):
winner = self.has_winner
if winner == 'p':
self.player.add_winnings(self.pot)
self.pot = 0
elif winner == 'd':
self.pot = 0

Should the player win the round, their money will increase by the amount in the pot. If the dealer won, there is no need to assign them the money since they cannot go bust, so the pot is just emptied. If the result was a tie, the pot will remain full, and the whole amount is left to play for in the next round (on top of that round's bet).

The GameState is then free to move on to the next round:

def next_round(self):
self.current_round += 1
self.minimum_bet = self.BASE_BET * self.current_round

self.player.empty_hand()
self.dealer.empty_hand()

self.begin_round()

The current_round attribute is incremented and the new minimum bet is calculated from it. Both players then empty their hands to receive new cards, and the new round begins.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset