[solved] I'm unable to see why this doesn't work (blackjack game)

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3792
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

[solved] I'm unable to see why this doesn't work (blackjack game)

#1 Post by Imperf3kt »

Can somebody fluent with python give me a bit of a hand, I'm struggling to understand what I've created here and why it doesn't work.
This is mostly my own work, so I'm not even sure if I'm doing things correctly, being a novice.

Code: Select all

##blackjack experiment##

init python:
    
    class Card:
        
        def __init__(self, suit, val):
            self.suit = suit
            self.value = val
            
    class Deck:
        
        def __init__(self):
            self.cards = []
            self.build()
        
        def build(self):
            for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
                for v in range(1, 14):
                    self.cards.append(Card(s, v))
        
        def show(self):
            for c in self.cards:
                c.show()
        
        def shuffle(self):
            for i in range(len(self.cards) - 1, 0, -1):
                r = renpy.random.randint(0, i)
                self.cards[i], self.cards[r] = self.cards[r], self.cards[i]
        
        def drawCard(self):
            drawn = self.cards.pop()
            if drawn == 11:drawn = "J"
            if drawn == 12:drawn = "Q"
            if drawn == 13:drawn = "K"
            if drawn == 14:drawn = "A"
            
            return drawn
        
    class Player:
        
        def __init__(self, name):
            self.name = name
            self.hand = []
        
        def draw(self, deck):
            self.hand.append(deck.drawCard())
            return self
        
        def showHand(self):
            cards = ""
            for card in self.hand:
                cards += "{} of {}".format(card.value, card.suit) + " "
            return cards
        
        def discard(self):
            del self.hand[:]
        
        def total(hand):
            total = 0
            for card in hand:
                if card == "J" or card == "Q" or card == "K":
                    total += 10
                elif card == "A":
                    if total >= 11:
                        total += 1
                    else:
                        total += 11
                else:
                    total += card
            return total
            
            
define deck = Deck()
define player1 = Player("Your")
define dealer = Player("Dealer")
default discard_pile = []
default first_bet = True

label start:
    
    if len(deck.cards) == 0:
        $ del discard_pile[:]
        $ discard_pile = []
        $ deck.shuffle()
    else:
        pass

label hand_start:
    
    $ player1.draw(deck)
    $ player1.draw(deck)
    $ dealer.draw(deck)
    $ dealer.draw(deck)
    $ player1_cards = player1.showHand()
    $ dealer_cards = dealer.showHand()
    
    $ first_bet = True
    
    "Discard pile: [discard_pile]"
    "[player1.name] cards are [player1_cards]"
    "[dealer.name] cards are [dealer_cards]"

label turn:
    
    menu:
        "Hit":
            $ player1.draw(deck)
            $ player1_cards = player1.showHand()
            $ first_bet = False
            "[player1_cards]"
            
            if player1.total < 21:
                jump turn
            elif player1.total == 21:
                jump results
            elif player1.total > 21:
                jump bust
            
        "Stand":
            jump results
        
        "Double down" if first_bet:
            $ player1.draw(deck)
            $ player1_cards = player1.showHand()
            jump results

    return

label bust:
    
    "Over 21, Bust"
    call reset_hand
    jump hand_start

label results:
    
    if dealer.total == player1.total:
        call reset_hand
        jump push
    elif dealer.total > player1.total:
        call reset_hand
        jump lose
    elif dealer.total < player1.total:
        call reset_hand
        jump win

label push:
    "Push"
    jump hand_start

label lose:
    "You lose"
    jump hand_start

label win:
    "You win"
    jump hand_start

label reset_hand:
    $ player1_discard = player1.showHand()
    $ dealer_discard = dealer.showHand()
    $ discard_pile.append(dealer_discard)
    $ discard_pile.append(player1_discard)
    $ player1.discard()
    $ dealer.discard()
    return
So last night I could randomly shuffle a deck of cards and draw some out to be used in some manner.

Tonight, I added the ability to add up the value of the cards drawn in hopes of creating a blackjack game. I got as far as ensuring the player could draw more cards as desired (but haven't worked on the dealer yet) and it should automatically send you to the correct label (win, lose, bust, blackjack, etc)
Instead, it seems to draw the cards out in reverse order every single time, starting with the King of Hearts and I don't know why.
The scoring system also doesn't seem to work, always sending the player to "lose" and sometimes giving weird results.

Cards 11 -14 are supposed to be replaced with J - A respectively, but aren't and I'm unsure why.

What puzzles me most is why the "discard_pile" list shows [] when shown as text and when populated, shows ['u'<card>]
Last edited by Imperf3kt on Wed Sep 11, 2019 5:05 pm, edited 1 time in total.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
Enviel
Newbie
Posts: 11
Joined: Sat Apr 12, 2014 2:55 pm
Contact:

Re: I'm unable to see why this doesn't work

#2 Post by Enviel »

Instead, it seems to draw the cards out in reverse order every single time, starting with the King of Hearts and I don't know why.
You only call deck.shuffle() in label start if deck is empty. As the deck is not shuffled, cards always come in fixed order.
Cards 11 -14 are supposed to be replaced with J - A respectively, but aren't and I'm unsure why.
In Deck.draw, you have these lines

Code: Select all

if drawn == 11:drawn = "J"
This does not work because you are comparing Card object to a number, instead of comparing card's value. Additionally, you'd also replace the card object with a string, which would lead to problems elsewhere.
Using the card.value does the trick here.

Code: Select all

if drawn.value == 11:drawn.value = "J"
The scoring system also doesn't seem to work, always sending the player to "lose" and sometimes giving weird results.
Similarly to previous one, you need to use card.value instead of card.
Since Player class has it's own hand, you don't need that as a parameter for total(). However, you always need self for methods inside classes, so that magic things work. And from self you can access hand using self.hand.

Code: Select all

def total(self):
    total = 0
    for card in self.hand:
        if card.value == "J" or card.value == "Q" or card.value == "K":
            total += 10
    ...
And when using it in label result, you want to call it by adding () at the end.

Code: Select all

if dealer.total() == player1.total():
What puzzles me most is why the "discard_pile" list shows [] when shown as text and when populated, shows ['u'<card>]
Printing a list directly gives less than optimal experience. You could do same thing as in showHand() or

Code: Select all

$ discardtext = ''.join(discard_pile)
"Discard pile: [discardtext]"
to get it printed correctly.

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3792
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: I'm unable to see why this doesn't work

#3 Post by Imperf3kt »

Great, once again thank you so much. The solutions were all so simple, I can't believe I didn't see it.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3792
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: [solved] I'm unable to see why this doesn't work (blackjack game)

#4 Post by Imperf3kt »

I'm in need of further help with this project.

I'm just baffled by how to get a list to show as text, and its starting to really get to me.
I have this currently, and I have no idea why (again)
Image

what I need is to somehow remove the first entries (I only want the last entry to show.)

I also cannot seem to get rid of that [u' no matter what I do. Applying the previous method suggested

Code: Select all

$ discardtext = ''.join(discard_pile)
"Discard pile: [discardtext]"
only gives me errors.


This is what I currently have, and will eventually replace some bits with images instead of text, but for now I just need it to work so I can test it.

Code: Select all


init python:
    
    class Card:
        
        def __init__(self, suit, val):
            self.suit = suit
            self.value = val
            
    class Deck:
        
        def __init__(self):
            self.cards = []*4
            self.build()
        
        def build(self):
            for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
                for v in range(2, 14):
                    self.cards.append(Card(s, v))
        
        def show(self):
            for c in self.cards:
                c.show()
        
        def shuffle(self):
            for i in range(len(self.cards) - 1, 0, -1):
                r = renpy.random.randint(0, i)
                self.cards[i], self.cards[r] = self.cards[r], self.cards[i]
        
        def drawCard(self):
            drawn = self.cards.pop()
            if drawn.value == 11:drawn.value = "J"
            if drawn.value == 12:drawn.value = "Q"
            if drawn.value == 13:drawn.value = "K"
            if drawn.value == 14:drawn.value = "A"
            
            return drawn
        
    class Player:
        
        def __init__(self, name):
            self.name = name
            self.hand = []
        
        def draw(self, deck):
            self.hand.append(deck.drawCard())
            return self
        
        def showHand(self):
            cards = ""
            for card in self.hand:
                cards += "{} of {}".format(card.value, card.suit) + " "
            return cards
        
        def discard(self):
            del self.hand[:]
        
        def total(self):
            total = 0
            for card in self.hand:
                if card.value == "J" or card.value == "Q" or card.value == "K":
                    total += 10
                elif card.value == "A":
                    if total >= 11:
                        total += 1
                    else:
                        total += 11
                else:
                    total += card.value
            return total
            
            
define deck = Deck()
define player1 = Player("Your")
define dealer = Player("Dealer")
default first_bet = True

default playertotal = 0
default dealertotal = 0

default lastcard = []

label start:
    
    show screen stats
    
#    if len(deck.cards) == 0:
    $ deck.shuffle()


label hand_start:
    
    call reset_hand
    
    $ player1.draw(deck)
    $ player1.draw(deck)
    $ dealer.draw(deck)
    $ dealer.draw(deck)
    
    $ player1_cards = player1.showHand()
    $ dealer_cards = dealer.showHand()
    
    $ first_bet = True
    
    
    "[player1.name] cards are [player1_cards]"
    "[dealer.name] cards are [dealer_cards]"

label turn:
    
    menu:
        "Hit":
            $ player1.draw(deck)
            $ player1_cards = player1.showHand()
            $ first_bet = False
            "[player1_cards]"
            
            if player1.total() < 21:
                jump turn
            elif player1.total() == 21:
                jump dealer_turn
            elif player1.total() > 21:
                jump bust
            
        "Stand":
            jump dealer_turn
        
        "Double down" if first_bet:
            $ player1.draw(deck)
            $ player1_cards = player1.showHand()
            jump dealer_turn


label dealer_turn:
    
    if dealer.total() < 17:
        if dealer.total() < player1.total():
            $ dealer.draw(deck)
        $ lastcard.append(player1.showHand())
        "Dealer draws [lastcard]"
        jump dealer_turn
    elif dealer.total() == 21:
        jump results
    elif dealer.total() > 21:
        call reset_hand
        jump win
    else:
        jump results

label bust:
    
    "Over 21, Bust"
    call reset_hand
    jump hand_start

label results:
    
    $ playertotal = player1.total()
    $ dealertotal = dealer.total()
    
    "Your hand: [player1_cards], [playertotal]"
    "Dealer's hand: [dealer_cards], [dealertotal]"
    
    if dealer.total() == player1.total():
        jump push
    elif dealer.total() > player1.total():
        jump lose
    elif dealer.total() < player1.total():
        jump win

label push:
    
    "The hand is a push"
    jump hand_start

label lose:

    "You lose"
    jump hand_start

label win:
    
    "You win"
    jump hand_start

label reset_hand:
    
    $ player1.discard()
    $ dealer.discard()
    return

screen stats():
    
    python:
        ptotal = player1.total()
        dtotal = dealer.total()
    
    fixed:
        text "Your hand: [ptotal]":
            xpos 0.2
            ypos 0.05
        text "Dealer's hand: [dtotal]":
            xpos 0.8
            ypos 0.05
I'm lost, confused, and about to throw something out the window. Could anyone help me understand this again.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
Enviel
Newbie
Posts: 11
Joined: Sat Apr 12, 2014 2:55 pm
Contact:

Re: [solved] I'm unable to see why this doesn't work (blackjack game)

#5 Post by Enviel »

a = "".join(lastcard) should work here the same way it worked on discard pile. What error are you getting?

However, since showHand() returns a single string of cards in hand, getting the last card from that would be somewhat annoying.

Instead, I'd add a new method to Player class that returns the latest card.

Code: Select all

def getLastCard(self):
    card = self.hand[-1]
    return "{} of {}".format(card.value, card.suit)

Code: Select all

$ lastcard = dealer.getLastCard()
"Dealer draws [lastcard]"
Here the hand[-1] refers to first item from the right side of the list, i.e. the last item.

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3792
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: [solved] I'm unable to see why this doesn't work (blackjack game)

#6 Post by Imperf3kt »

Thanks, I'd completely forgotten how to do that.
I tried so many things last night that I almost messed up the rest of my code in my confusion. Lucky I kept a backup :P

The .join method never actually worked for me, when using it, it returns nothing and the text reads blank.
I ended up scrapping the discard pile thing because it was causing too many issues.
Thanks to your help though I think I've almost got the framework ready for use. I do need to use four decks of cards though, need to combine them somehow.

I really appreciate your help in this, thanks for being patient with me. This is all so confusing for me and yet at the same time it's not. If that makes sense xD

___________

Sneaky edit to post a work in progress sample.
https://mega.nz/#!NFUxAIwT!F5DQUUg0OHp5 ... rRPmH84V2Q
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot]