Author Topic: Blackjack  (Read 56317 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #210 on: July 07, 2020, 11:20:19 am »
Over on my iPad, I have a deck shuffling program which is very simple. I create a random array with numbers from 1 to 52, and these numbers serve as an index to another table that holds the card number and suit. I use graphics (UNICODE or the iPad's expanded ASCII Code) and the suit is the same size as the number.

I can bring it over to QB64 and get it to work if you are interested in it. I can even create options where you can create a shuffled array with 4 to 8 decks if you can use it.

Can shuffle be simpler than this from my last code post, from all my code that needs shuffle)?
Code: QB64: [Select]
  1.     FOR i = 52 TO 2 STEP -1 'shuffle
  2.         SWAP deck$(INT(RND * i) + 1), deck$(i)
  3.     NEXT
  4.  

Welcome aboard George!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Blackjack
« Reply #211 on: July 07, 2020, 12:16:13 pm »
So is this like an  official  group project or what? how many different people have added actual material for this? 4-5? or am I just skim reading the wrong parts?
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #212 on: July 07, 2020, 12:44:42 pm »
So is this like an  official  group project or what? how many different people have added actual material for this? 4-5? or am I just skim reading the wrong parts?

Hi @Cobalt

Currently I am running code in which you can test your own AI. Started around reply #195. I think we have finished for awhile the beautiful graphics and audio game. (Check Best Answer for the latest on that.)

The AI should be fairly easy to write, just make a Function that returns "h" for hit or "d" for double down anything else is signal to stay.

The players() array name has been changed to p() array and the Dealers player number = nPlayers check code in next reply.

Love to get your input, if you have an idea you can just describe it and I can write it up or take a shot at your own Function.


« Last Edit: July 07, 2020, 01:13:08 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #213 on: July 07, 2020, 12:49:29 pm »
I have updated my AI tester for more AI players. Now they overlap when AI players exceed 4 or 5 but we are OK, you can mouse over a certain player and see how they are doing while the Dealer is running the game. Do try and stay out of way of the updating with your mouse.

Code: QB64: [Select]
  1. ' No suits shown for cards A is Ace, J, Q, K are Jack, Queen, King, X is for 10
  2. '2020-07-05 fix hit (it wasn't broken), delete line card$ = inkey$ before loop
  3. ' force dealer to hit on 16 stay 17
  4. ' ties are push
  5. ' bring in double down option
  6. ' fix dealer has Blackjack should tell also fix exposing 2nd card
  7. ' work this towards converting to multiple AI players, so players stats are all located in PlayerType
  8. ' 2020-07-06 Installed AI and mods for it
  9. ' 2020-07-06 new Compact Tester with 2nd AI
  10. ' 2020-07-06 start Blackjack Multi AI Tester off of Compact Tester
  11. '            add in allot of code worked out in Blackjack with Bots 2019-06-07
  12. '            Yes, major overhaul of last year bot code which was/is neat!
  13. '            Thanks Johnno and Steve for some interesting AI ideas to try!
  14. ' 2020-07-07 for Blackjack Multi AI Tester #2, I hope to do something kind of interesting with displaying players
  15. '            Yes Mouse over a player you want to check on but try and stay out of way of updating.
  16.  
  17. DEFINT A-Z
  18.  
  19. _TITLE "Blackjack Multi AI Tester #2     Mouse over a player you want to check " ' started 2019-06-06, revisit and match functions with B+J Balckjack with audio and graphics.
  20.  
  21. CONST nPlayers = 9 'dealer counts as the last player   this number depends on how many AI's to test
  22. CONST xmax = 800, ymax = 500, margin = 4
  23. CONST rank$ = "A23456789XJQK" 'for building deck and figuring Totals
  24. CONST bH = 14, bW = 20 ' box height and box width in rows and columns
  25. CONST white = &HFFFFFFFF, black = &HFF000000, bc = &HFF008822, fc = &HFFCCCCFF
  26.  
  27. TYPE PlayerType
  28.     ID AS STRING '        name of bot including dealer bot
  29.     Col AS INTEGER '      left corner column
  30.     Row AS INTEGER '      top row
  31.     FC AS _UNSIGNED LONG 'player colors are assigned in init FC are alternating Black and White
  32.     BC AS _UNSIGNED LONG 'random light and dark opposite print FC
  33.     Hand AS STRING '      cards are 1 char strings 10 is X
  34.     Ace AS INTEGER '      flag has ace for totalling hand
  35.     Bust AS INTEGER '     flag for final reckoning
  36.     BJ AS INTEGER '       flag for final reckoning
  37.     Total AS INTEGER '    card total of hand
  38.     Chips AS _INTEGER64 ' players status
  39.     SetBet AS _INTEGER64 'regular bet amount
  40.     Bet AS _INTEGER64 '   players bet each round
  41.  
  42. DIM SHARED deck$(1 TO 52), p(1 TO nPlayers) AS PlayerType, deckIndex, round, allOut, player, blockDealer, tN AS LONG
  43. SCREEN _NEWIMAGE(xmax, ymax, 32)
  44. DIM i, card$
  45. ON TIMER(tN, .5) checkMouseOver
  46.  
  47. initGame
  48. 'FOR i = 1 TO nPlayers
  49. '    showPlayer i
  50. 'NEXT
  51. TIMER(tN) ON
  52.     clearPlayers 'clears screen too and shuffles deck
  53.  
  54.     FOR i = 1 TO 2
  55.         FOR player = 1 TO nPlayers 'each Player is dealt 2 cards
  56.             IF player <> nPlayers THEN
  57.                 IF p(player).Chips > 0 THEN
  58.                     allOut = 0 'signal everyone is out of chips is false
  59.                     PlayerAddCard player
  60.                     showPlayer player
  61.                     _DELAY .5
  62.                 END IF
  63.             ELSE
  64.                 IF allOut THEN
  65.                     EXIT DO
  66.                 ELSE
  67.                     PlayerAddCard player
  68.                     showPlayer player
  69.                     _DELAY .5
  70.                 END IF
  71.             END IF
  72.         NEXT
  73.     NEXT
  74.  
  75.     IF p(nPlayers).BJ = 0 THEN 'dealer does not have BJ
  76.         FOR player = 1 TO nPlayers - 1
  77.             showPlayer player
  78.             _DELAY 1
  79.             WHILE p(player).Total < 21
  80.                 SELECT CASE player ' this has to be coded for exactly all nPlayers - 1
  81.                     CASE 1: card$ = Johnno$(player)
  82.                     CASE 2: card$ = Johnno$(player)
  83.                     CASE 3: card$ = Steve$(player)
  84.                     CASE 4: card$ = Steve$(player)
  85.                     CASE 5: card$ = bplusAI$(player)
  86.                     CASE 6: card$ = bplusAI$(player)
  87.                     CASE 7: card$ = bplusAI2$(player)
  88.                     CASE 8: card$ = bplusAI2$(player)
  89.                 END SELECT
  90.                 IF card$ = "h" THEN cp player, 13, "Hit"
  91.                 IF card$ = "d" THEN cp player, 13, "Double Down"
  92.                 IF card$ <> "h" AND card$ <> "d" THEN cp player, 13, "Stay"
  93.                 _DELAY 2
  94.                 IF card$ = "h" THEN
  95.                     PlayerAddCard player
  96.                     showPlayer player
  97.                     _DELAY 1
  98.                 ELSEIF card$ = "d" AND LEN(p(player).Hand) = 2 THEN
  99.                     p(player).Bet = 2 * p(player).Bet
  100.                     PlayerAddCard player
  101.                     showPlayer player
  102.                     _DELAY 1
  103.                     EXIT WHILE
  104.                 ELSE 'stayed
  105.                     showPlayer player
  106.                     _DELAY 1
  107.                     EXIT WHILE
  108.                 END IF
  109.             WEND
  110.         NEXT
  111.     END IF
  112.  
  113.     blockDealer = 0
  114.     showPlayer nPlayers
  115.     _DELAY 1
  116.     WHILE p(nPlayers).Total < 17
  117.         cp nPlayers, 11, "Dealer takes a card."
  118.         _DELAY 1
  119.         PlayerAddCard nPlayers
  120.         showPlayer nPlayers
  121.         _DELAY 1
  122.     WEND
  123.  
  124.     '    final Reckoning
  125.     FOR player = 1 TO nPlayers - 1
  126.         showPlayer player
  127.         IF p(player).Total > 21 OR (p(player).Total < p(nPlayers).Total AND p(nPlayers).Total < 22) THEN
  128.             cp player, 13, "Lost" + STR$(p(player).Bet)
  129.             p(player).Chips = p(player).Chips - p(player).Bet
  130.             p(nPlayers).Chips = p(nPlayers).Chips + p(player).Bet
  131.         ELSEIF p(player).Total = p(nPlayers).Total AND p(player).BJ = 0 THEN
  132.             cp player, 13, "Push"
  133.         ELSE
  134.             IF p(player).BJ THEN
  135.                 cp player, 13, "Win!" + STR$(p(player).Bet + .5 * p(player).Bet)
  136.                 p(player).Chips = p(player).Chips + p(player).Bet + .5 * p(player).Bet
  137.                 p(nPlayers).Chips = p(nPlayers).Chips - p(player).Bet - .5 * p(player).Bet
  138.             ELSE
  139.                 cp player, 13, "Win!" + STR$(p(player).Bet)
  140.                 p(player).Chips = p(player).Chips + p(player).Bet
  141.                 p(nPlayers).Chips = p(nPlayers).Chips - p(player).Bet
  142.             END IF
  143.         END IF
  144.         IF p(player).Chips = 0 THEN cp player, 14, "Out of chips!"
  145.         _DELAY 3
  146.     NEXT
  147. LOOP UNTIL allOut
  148.  
  149. SUB checkMouseOver
  150.     DIM mx, my, i
  151.     mx = _MOUSEX / 8 - .5 * bW: my = _MOUSEY / 16
  152.     IF my >= 18 THEN
  153.         FOR i = 1 TO nPlayers - 1
  154.             IF ABS(mx - p(i).Col) <= .5 * bW - 1 THEN showPlayer i
  155.         NEXT
  156.     END IF
  157.  
  158. SUB clearPlayers
  159.     DIM i
  160.     COLOR fc, bc: CLS
  161.     round = round + 1: allOut = -1
  162.     FOR i = 1 TO nPlayers
  163.         p(i).Hand = ""
  164.         p(i).Ace = 0
  165.         p(i).Total = 0
  166.         p(i).BJ = 0
  167.         p(i).Bust = 0
  168.         'because of double down option I have to reset bet during play and set it back at each new round
  169.         'make sure we aren't betting more than our chips count at least to start
  170.         IF p(i).Chips < p(i).SetBet THEN p(i).Bet = p(i).Chips ELSE p(i).Bet = p(i).SetBet
  171.     NEXT
  172.     FOR i = 52 TO 2 STEP -1 'shuffle
  173.         SWAP deck$(INT(RND * i) + 1), deck$(i)
  174.     NEXT
  175.     'deck$(5) = "A": deck$(10) = "J"  'check immediate show of Blackjack for dealer
  176.     deckIndex = 0: blockDealer = -1
  177.  
  178. FUNCTION bplusAI$ (pn) ' first try
  179.     SELECT CASE p(pn).Total
  180.         CASE IS < 10: bplusAI$ = "h" 'no caps!
  181.         CASE 10, 11
  182.             IF LEN(p(pn).Hand) = 2 THEN bplusAI$ = "d" ELSE bplusAI$ = "h"
  183.         CASE IS < 15
  184.             IF RND < .5 THEN bplusAI$ = "h" ELSE bplusAI$ = "whatever"
  185.         CASE ELSE: bplusAI$ = "Show me the money!"
  186.     END SELECT
  187.  
  188. FUNCTION bplusAI2$ (pN) 'after trying first want to try this make it more likely to hit on 12 than 13, 14...
  189.     SELECT CASE p(pN).Total
  190.         CASE IS < 10: bplusAI2$ = "h" 'no caps!
  191.         CASE 10, 11 'double down unless dealer showing an Ace which is like insurance for dealer
  192.             IF LEN(p(pN).Hand) = 2 AND LEFT$(p(nPlayers).Hand, 1) <> "A" THEN bplusAI2$ = "d" ELSE bplusAI2$ = "h"
  193.         CASE 12: IF RND < .75 THEN bplusAI2$ = "h" ELSE bplusAI2$ = "whatever"
  194.         CASE 13: IF RND < .5 THEN bplusAI2$ = "h" ELSE bplusAI2$ = "whatever"
  195.         CASE 14: IF RND < .25 THEN bplusAI2$ = "h" ELSE bplusAI2$ = "whatever"
  196.         CASE ELSE: bplusAI2$ = "Show me the money!"
  197.     END SELECT
  198.  
  199. FUNCTION Johnno$ (pN)
  200.     IF p(pN).Total = 10 OR p(pN).Total = 11 AND LEN(p(pN).Hand) = 2 THEN
  201.         Johnno$ = "d"
  202.     ELSEIF p(pN).Total = 10 OR p(pN).Total = 11 AND LEN(p(pN).Hand) <> 2 THEN
  203.         Johnno$ = "h"
  204.     ELSEIF 12 <= p(pN).Total AND p(pN).Total <= 15 THEN
  205.         SELECT CASE LEFT$(p(nPlayers).Hand, 1)
  206.             CASE "A", "K", "Q", "J", "X", "9": Johnno$ = "h"
  207.             CASE "7", "8": IF RND < .5 THEN Johnno$ = "h"
  208.             CASE ELSE: Johnno$ = "Hope to Bust em"
  209.         END SELECT
  210.     ELSEIF p(pN).Total < 12 THEN
  211.         Johnno$ = "h"
  212.     ELSE
  213.         Johnno$ = "Stay"
  214.     END IF
  215.  
  216. FUNCTION Steve$ (pN) 'how simple is this! never bust make dealer work for it
  217.     IF p(pN).Total < 12 THEN Steve$ = "h"
  218.  
  219. SUB PlayerAddCard (rec) 'updates player's hand and total
  220.     DIM i AS INTEGER, cv AS INTEGER
  221.     deckIndex = deckIndex + 1
  222.     p(rec).Hand = p(rec).Hand + deck$(deckIndex)
  223.     IF deck$(deckIndex) = "A" THEN p(rec).Ace = -1
  224.     p(rec).Total = 0
  225.     FOR i = 1 TO LEN(p(rec).Hand)
  226.         IF INSTR(rank$, MID$(p(rec).Hand, i, 1)) > 10 THEN cv = 10 ELSE cv = INSTR(rank$, MID$(p(rec).Hand, i, 1))
  227.         p(rec).Total = p(rec).Total + cv
  228.     NEXT
  229.     IF p(rec).Total < 12 AND p(rec).Ace THEN p(rec).Total = p(rec).Total + 10
  230.     IF LEN(p(rec).Hand) = 2 AND p(rec).Total = 21 THEN p(rec).BJ = -1
  231.     IF p(rec).Total > 21 THEN p(rec).Bust = -1
  232.  
  233. SUB showPlayer (nPlayer)
  234.     DIM i AS INTEGER, S$
  235.     COLOR p(nPlayer).FC, p(nPlayer).BC
  236.     FOR i = 0 TO bH - 1 'clear our block
  237.         'PRINT p(nPlayer).Row + i, p(nPlayer).Col
  238.         LOCATE p(nPlayer).Row + i, p(nPlayer).Col: PRINT SPACE$(bW);
  239.     NEXT
  240.     cp nPlayer, 1, "Round:" + STR$(round)
  241.     cp nPlayer, 3, p(nPlayer).ID
  242.     cp nPlayer, 5, "Chips:" + STR$(p(nPlayer).Chips)
  243.     IF nPlayer <> nPlayers THEN cp nPlayer, 6, "Bet:" + STR$(p(nPlayer).Bet)
  244.     FOR i = 1 TO LEN(p(nPlayer).Hand) 'with 12 aces could get very long hands
  245.         S$ = S$ + MID$(p(nPlayer).Hand, i, 1) + " "
  246.     NEXT
  247.     cp nPlayer, 8, "___Hand___"
  248.     IF nPlayer = nPlayers AND LEN(p(nPlayer).Hand) = 2 AND p(nPlayer).Total <> 21 AND blockDealer THEN
  249.         S$ = LEFT$(S$, 2) + "?"
  250.         cp nPlayer, 9, S$
  251.         cp nPlayer, 10, "Total: ??"
  252.     ELSE
  253.         cp nPlayer, 9, S$
  254.         cp nPlayer, 10, "Total:" + STR$(p(nPlayer).Total)
  255.     END IF
  256.  
  257.     IF p(nPlayer).Bust THEN cp nPlayer, 11, "Busted"
  258.     IF p(nPlayer).BJ THEN cp nPlayer, 11, "Blackjack"
  259.  
  260. SUB initGame 'the stuff that never changes
  261.     DIM i, spacer
  262.     FOR i = 1 TO 52 'get deck ready
  263.         deck$(i) = MID$(rank$ + rank$ + rank$ + rank$, i, 1)
  264.     NEXT
  265.  
  266.     'for printing in each players window area of screen = blackjack table
  267.     'xmax/8 =  2*margin + bW *(nplayers -1) + spacer *(nplayer-2)
  268.     spacer = ((xmax / 8) - margin - bW * (nPlayers - 1)) / (nPlayers - 2)
  269.  
  270.     FOR i = 1 TO nPlayers
  271.         IF i <> nPlayers THEN
  272.             SELECT CASE i
  273.                 CASE 1: p(i).ID = "Johnno 1"
  274.                 CASE 2: p(i).ID = "Johnno 2"
  275.                 CASE 3: p(i).ID = "Steve 1"
  276.                 CASE 4: p(i).ID = "Steve 2"
  277.                 CASE 5: p(i).ID = "bplus First AI 1"
  278.                 CASE 6: p(i).ID = "bplus First AI 2"
  279.                 CASE 7: p(i).ID = "bplus 2nd AI 1"
  280.                 CASE 8: p(i).ID = "bplus 2nd AI 2"
  281.             END SELECT
  282.             p(i).Col = margin + (i - 1) * (spacer + bW)
  283.             p(i).Row = 18
  284.             p(i).Chips = 100
  285.             p(i).SetBet = 2
  286.             IF i MOD 2 THEN
  287.                 p(i).BC = _RGB32(RND * 128, RND * 128, RND * 128)
  288.             ELSE
  289.                 p(i).BC = _RGB32(RND * 128 + 127, RND * 128 + 127, RND * 128 + 127)
  290.             END IF
  291.         ELSE
  292.             p(i).ID = "Dealer"
  293.             p(i).Col = (xmax / 8 - bW) / 2
  294.             p(i).Row = 2
  295.             p(i).Chips = -100 * (nPlayers - 1)
  296.             IF i MOD 2 THEN p(i).BC = &HFF000000 ELSE p(i).BC = &HFFFFFFFF
  297.         END IF
  298.         IF i MOD 2 THEN p(i).FC = &HFFFFFFFF ELSE p(i).FC = &HFF000000
  299.     NEXT
  300.  
  301.     'ask the user / YOU what e prefers for betting
  302.     COLOR fc, bc: CLS
  303.     cp 0, 10, "*** Blackjack Multi AI Tester ***"
  304.     cp 0, 12, "Each AI bot starts with 100 chips and bets 2 each round."
  305.     cp 0, 13, "Dealer must hit on 16 or less."
  306.     cp 0, 14, "Blackjack pays 1.5 X the bet."
  307.     cp 0, 15, "Double down option available when you get 2 cards."
  308.     cp 0, 16, "It Doubles the bet and you get one more card."
  309.     cp 0, 20, "press any to continue..."
  310.     SLEEP
  311.  
  312. SUB cp (nPlayer, row, s AS STRING) 'center print a string on the given row
  313.     IF nPlayer THEN
  314.         COLOR p(nPlayer).FC, p(nPlayer).BC
  315.         LOCATE p(nPlayer).Row + row, p(nPlayer).Col + (bW - LEN(s)) / 2: PRINT s;
  316.     ELSE
  317.         COLOR fc, bc
  318.         LOCATE row, (xmax / 8 - LEN(s)) / 2: PRINT s;
  319.     END IF
  320.  
  321.  

Can't mouse over while getting a screen shot but here is a game with 8 AI bots + Dealer bot
 
Multi AI tester 2.PNG
« Last Edit: July 07, 2020, 12:55:30 pm by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: Blackjack
« Reply #214 on: July 07, 2020, 06:57:35 pm »
Nine hands playing from one deck. That would mean a serious amount of shuffling... lol  Ah, but then, The Dealer is supposed to perform miracles... lol

Suggestion: Increase the screen size. Place the Dealer top centre. Three players from top to bottom on both the left and right sides. The remaining two in the 'gap' along the bottom. Another layout: Dealer in the center of screen. Two players left and right and above and below the Dealer.

My other guess would be that this version is a 'concept' of controlling multiple AI and 'layout' is not relevant.... lol

I'm curious. In 'real' Blackjack, how many players can actually play, and how does the dealer determine how many 'decks' to use?
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #215 on: July 07, 2020, 07:52:02 pm »
My other guess would be that this version is a 'concept' of controlling multiple AI and 'layout' is not relevant.... lol

Yeah pretty much that, an experiment. I did like how well the mouse over thing did work off a timer but...

Yeah! you know it's nice to see all the hands clearly. I could probably fit 8 comfortably or go bigger screen as you say. I've also noticed that it is nice for cards to layout from left to right without a centering function shifting them left and right.

What do you think about the dealer down at the bottom right corner, then we just work left to right, top to bottom?


You know, think about it, the dealer has to keep hitting until has at least 17. 17 to 21 is a window of... oh it's 5 cards. I've been thinking 4 because 21-17 but it is 5 cards. And yet it just drains chips from players, there must be some better strategy. The tip about looking at dealers up card was interesting intelligence and I am beginning to think double down is only good on 11 and only if dealer has lower card.

I will play around with layout and AI options.

BTW in real Blackjack the casinos set their own standards and I am pretty sure no one uses only one deck which means its possible to get a huge number of aces.
« Last Edit: July 07, 2020, 07:58:10 pm by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: Blackjack
« Reply #216 on: July 07, 2020, 08:45:59 pm »
Position of the Dealer... Traditionally the Dealer is at the 'head' of the table... I assume that to be the 'top' with all players within reach at the 'bottom'. The 'reach' could explain the shape of the table... The problem with 'that' layout, for the screen, would be that all the player would be side-by-side. Did you have any plans on a limit to player numbers? Knowing the limit would help in  determining the layout.

But, then again, who says that the game has to be 'traditional'? lol

I remember, during lunch breaks at work, we used to play Pontoon (or 21), and betting was a little different. There was the initial bet then if the player had 11 or less in two cards, the player could 'buy' an extra card and choose to 'hit' if more than 11. If you are after 'bleeding a player dry' then that might be the way to go... lol  Just recalled that... I know. I'm shocked as well..!! Remembering something from 4 decades ago... Shocked!

The mouse is a great idea... But, with the right kind of surgery, a neural interface could be developed for that 'hands free' feeling... But... mouse will do in a pinch... lol

Logic dictates that, if artificial intelligence can be programmed into a game, then so can artificial stupidity... It's funny but not meant as a joke. "Humor. It is a difficult concept." Star Trek: Wrath of Khan (1982)  People make 'stupid' decisions and make foolish mistakes. Then why not configure the AI to replicate the same behaviour? (throwing in a typical "Doh!" after the event) Just a thought...
Logic is the beginning of wisdom.

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: Blackjack
« Reply #217 on: July 08, 2020, 07:39:18 am »
Congratulations @bplus & @johnno56 , what a collaboration.  In forum stats, this post is way ahead of anything else in Replies.  This will shortly be arriving in Games.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #218 on: July 08, 2020, 12:06:15 pm »
Thanks Qwerkey,

The number of replies is most probably just chit-chat between me and Johnno, but I appreciate encouragement and help offered by Dav, Pete, Steve, George and Pete & Steve's jokes to break monotony and all positive comments QBExile, Old Moses, Ken, Ashish, Spriggsy, jack, Cobalt all showing some sort of interest even Fellippe when I mention a possible glitch between QB64 versions. 😊

I actually considered the cough and gunshots sounds for background, I already had the sounds, funny!

Special thanks to Johnno, like with Battleship, he can sure dress up my code and keep the ideas flowing for me. Really liked the splash screen specially with our Logo in the neon sign and the Dealer voice. Good eye too, I still don't know if there is difference in card set images? ha! I just used what he provided on faith.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #219 on: July 08, 2020, 01:12:27 pm »
@Qwerkey 

I will go over code and write in some more comments for myself and others for future reference. Should be ready tonight, I've got chores in afternoon.

I have already made the main loop play more efficient with the Mult-players code by setting flags for Blackjacks and Busts handling them in Final Reckoning section instead of separately right after first 2 cards.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #220 on: July 08, 2020, 07:15:28 pm »
I have become intensely curious about Dealer Stats, the distribution of Totals 17 to 21 and over 21 Busts:
Code: QB64: [Select]
  1. _TITLE "BJ Dealer Test - stats" 'b+ 2020-07-08
  2. '  on distribution 17 to 21 in and 22 plus out
  3.  
  4. CONST rank = "A23456789XJQK"
  5. TYPE PlayerType
  6.     ID AS STRING
  7.     Hand AS STRING
  8.     Ace AS INTEGER
  9.     Total AS INTEGER
  10.     chips AS _INTEGER64
  11.     setBet AS _INTEGER64
  12.     bet AS _INTEGER64
  13. DIM SHARED dealer AS PlayerType, deck$(1 TO 52), deckIndex AS INTEGER, stats(17 TO 22)
  14.  
  15. FOR i = 1 TO 52 'get deck ready
  16.     deck$(i) = MID$(rank$ + rank$ + rank$ + rank$, i, 1)
  17.  
  18. WHILE _KEYDOWN(27) = 0
  19.     FOR i = 52 TO 2 STEP -1 'shuffle
  20.         r = INT(RND * i) + 1
  21.         SWAP deck$(r), deck$(i)
  22.     NEXT
  23.     deckIndex = 0: dealer.Total = 0: rounds = rounds + 1: dealer.Hand = "": noBusts = 0: dealer.Ace = 0
  24.     CLS
  25.     PRINT "Round:"; rounds
  26.     WHILE dealer.Total < 17
  27.         PlayerAddCard
  28.         PRINT RIGHT$(dealer.Hand, 1);
  29.         _LIMIT 100
  30.     WEND
  31.     PRINT , dealer.Total: PRINT
  32.     IF dealer.Total > 21 THEN stats(22) = stats(22) + 1 ELSE stats(dealer.Total) = stats(dealer.Total) + 1
  33.     FOR i = 17 TO 22
  34.         PRINT i, stats(i), INT(stats(i) * 10000 / rounds) / 100; "%"
  35.         IF i < 22 THEN noBusts = noBusts + stats(i)
  36.     NEXT
  37.     PRINT
  38.     PRINT "     No Busts:"; noBusts, INT(noBusts * 10000 / rounds) / 100; "%"
  39.     _DISPLAY
  40.     _LIMIT 10
  41.  
  42.  
  43. SUB PlayerAddCard 'updates player's hand and total
  44.     DIM i AS INTEGER, cv AS INTEGER
  45.     deckIndex = deckIndex + 2
  46.     dealer.Hand = dealer.Hand + deck$(deckIndex)
  47.     IF deck$(deckIndex) = "A" THEN dealer.Ace = -1
  48.     dealer.Total = 0
  49.     FOR i = 1 TO LEN(dealer.Hand)
  50.         IF INSTR(rank, MID$(dealer.Hand, i, 1)) > 10 THEN cv = 10 ELSE cv = INSTR(rank, MID$(dealer.Hand, i, 1))
  51.         dealer.Total = dealer.Total + cv
  52.     NEXT
  53.     IF dealer.Total < 12 AND dealer.Ace THEN dealer.Total = dealer.Total + 10
  54.  
  55.  

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Blackjack
« Reply #221 on: July 08, 2020, 07:35:08 pm »
Thank you.

The one I have a little bit longer, but it’s written for the techBASIC on iPad which does not have a SWAP statement.

However, I have noticed playing your blackjack game that it doesn’t quite follow basic play. I’ve noticed where the dealer has a 10 value showing, Everybody’s up to 16 should be hitting, yeah I’ve seen players stand on 13. I never a few other little things but I do understand what you’re trying to do with the AI. And it’s working pretty well so far.

I would however, chance a bust with a dealer showing a 10 value card as an up card, as I do in real life at casinos and do pretty well playing the basic strategy with some of my personal modifications.

Otherwise, you have done a great job on the coding.


Can shuffle be simpler than this from my last code post, from all my code that needs shuffle)?
Code: QB64: [Select]
  1.     FOR i = 52 TO 2 STEP -1 'shuffle
  2.         SWAP deck$(INT(RND * i) + 1), deck$(i)
  3.     NEXT
  4.  

Welcome aboard George!
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Blackjack
« Reply #222 on: July 08, 2020, 07:50:13 pm »
Bbplus,

Here is the code that I have on techBASIC on my iPad. I basically do a manual swap.

The print statements are there so that when I tested it I could see what it was doing and making sure that it was not duplicating any numbers.

Near the technique is just about the same, but what I do is I first preload an array And then swap the numbers around.

The following code is NOT QB64, but it is simple enough that it it will probably run in QB64:

Code: Text: [Select]
  1.  
  2. ! Shuffle a deck of cards, represented by an array contiaining the
  3. ! ordinal number of each card.
  4.  
  5. DIM cards(52) AS INTEGER
  6.  
  7. FOR i = 1 TO 52
  8.     cards(i) = i
  9. NEXT
  10.  
  11. j=0
  12.  
  13. FOR i = 1 to 52
  14.     PRINT "i: ";i
  15.     j = INT(1 + Math.rand*52) ! This generates the random number to swap from
  16.     PRINT "j: ";j
  17.     temp = cards(i)                  ! Saves the card number currently at i
  18.     PRINT "temp=cards(i): ";temp
  19.     cards(i) = cards(j)              ! This swaps position j into i
  20.     PRINT "cards(i)=cards(j): ";cards(i)
  21.     cards(j) = temp                  ! This moves the value that was in i into j
  22.     PRINT "cards(j)=temp: ";cards(j)
  23.     PRINT
  24. NEXT
  25.  
  26. ! Print out the new deck just shuffled
  27. FOR i = 1 TO 52
  28.     PRINT cards(i)
  29. NEXT
  30.  
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #223 on: July 08, 2020, 08:06:13 pm »
Hi @George McGinn

I see you come from Steve McNeill's camp of swapping each card with any of the other 52 cards.

There is a math proof that this is not ideal and leaves slightly less than perfect random distribution (given perfect random generator but who has that?)

"https://en.wikipedia.org/wiki/Fisher–Yates_shuffle"  <<copy/paste between quotes this in browser because underline link usually fails.

Look under Naive Shuffle:
 
Naive shuffle.PNG


EDIT: 2 l's in Steve's last name, I noticed I missed one in George's quote. Sorry Steve.
« Last Edit: July 09, 2020, 01:04:25 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blackjack
« Reply #224 on: July 08, 2020, 08:15:22 pm »
Thank you.

The one I have a little bit longer, but it’s written for the techBASIC on iPad which does not have a SWAP statement.

However, I have noticed playing your blackjack game that it doesn’t quite follow basic play. I’ve noticed where the dealer has a 10 value showing, Everybody’s up to 16 should be hitting, yeah I’ve seen players stand on 13. I never a few other little things but I do understand what you’re trying to do with the AI. And it’s working pretty well so far.

I would however, chance a bust with a dealer showing a 10 value card as an up card, as I do in real life at casinos and do pretty well playing the basic strategy with some of my personal modifications.

Otherwise, you have done a great job on the coding.

Yeah I am testing different Stay Strategies now and 16 looks very good! A slight mod of my previous post:
Code: QB64: [Select]
  1. _TITLE "BJ Dealer Test - stats" 'b+ 2020-07-08
  2. '  on distribution 17 to 21 in and 22 plus out
  3.  
  4. CONST rank = "A23456789XJQK"
  5. TYPE PlayerType
  6.     ID AS STRING
  7.     Hand AS STRING
  8.     Ace AS INTEGER
  9.     Total AS INTEGER
  10.     chips AS _INTEGER64
  11.     setBet AS _INTEGER64
  12.     bet AS _INTEGER64
  13.  
  14. DIM SHARED stay: stay = 18 'compare stay statss 16, 17 (Dealer's), 18
  15.  
  16. DIM SHARED dealer AS PlayerType, deck$(1 TO 52), deckIndex AS INTEGER, stats(stay TO 22)
  17.  
  18. FOR i = 1 TO 52 'get deck ready
  19.     deck$(i) = MID$(rank$ + rank$ + rank$ + rank$, i, 1)
  20.  
  21. WHILE _KEYDOWN(27) = 0
  22.     FOR i = 52 TO 2 STEP -1 'shuffle
  23.         r = INT(RND * i) + 1
  24.         SWAP deck$(r), deck$(i)
  25.     NEXT
  26.     deckIndex = 0: dealer.Total = 0: rounds = rounds + 1: dealer.Hand = "": noBusts = 0: dealer.Ace = 0
  27.     CLS
  28.     PRINT "Round:"; rounds
  29.     WHILE dealer.Total < stay
  30.         PlayerAddCard
  31.         PRINT RIGHT$(dealer.Hand, 1);
  32.         _LIMIT 100
  33.     WEND
  34.     PRINT , dealer.Total: PRINT
  35.     IF dealer.Total > 21 THEN stats(22) = stats(22) + 1 ELSE stats(dealer.Total) = stats(dealer.Total) + 1
  36.     FOR i = stay TO 22
  37.         PRINT i, stats(i), INT(stats(i) * 10000 / rounds) / 100; "%"
  38.         IF i < 22 THEN noBusts = noBusts + stats(i)
  39.     NEXT
  40.     PRINT
  41.     PRINT "     No Busts:"; noBusts, INT(noBusts * 10000 / rounds) / 100; "%"
  42.     _DISPLAY
  43.     _LIMIT 10
  44.  
  45.  
  46. SUB PlayerAddCard 'updates player's hand and total
  47.     DIM i AS INTEGER, cv AS INTEGER
  48.     IF LEN(dealer.Hand) <= 2 THEN deckIndex = deckIndex + 2 ELSE deckIndex = deckIndex + 1
  49.     dealer.Hand = dealer.Hand + deck$(deckIndex)
  50.     IF deck$(deckIndex) = "A" THEN dealer.Ace = -1
  51.     dealer.Total = 0
  52.     FOR i = 1 TO LEN(dealer.Hand)
  53.         IF INSTR(rank, MID$(dealer.Hand, i, 1)) > 10 THEN cv = 10 ELSE cv = INSTR(rank, MID$(dealer.Hand, i, 1))
  54.         dealer.Total = dealer.Total + cv
  55.     NEXT
  56.     IF dealer.Total < 12 AND dealer.Ace THEN dealer.Total = dealer.Total + 10
  57.  
  58.  

I am running stay at 18 now:
 
Stay at 18.PNG


You are right! 16 looked very good compared to 17, a NO Bust rate a little over 80% compared to 72% for Stay at 17 and the percent of Totals 20 or 21 is just slightly lower for Stay at 16 (31%) than it is for stay at 17(32%) based on about 3000 trials which is a pittance I suppose.

As you can see, Stay at 18 has significantly worse Bust Rate!