Spring naar bijdragen

Blackjack Simulatie 1 miljoen handen


DeValsspeler

Aanbevolen berichten

In het topic Berekeningen voor het huisvoordeel van blackjack in HC is via wiskundige berekeningen aangetoond dat het huisvoordeel bij blackjack rond de 0,67% is. Dit topic is tot stand gekomen omdat @dobbelsteen deze waarde niet geloofde en nergens kon terugvinden hoe deze waarde bepaald is. Daartoe heb ik het betreffende topic geopend en vervolgens exact getoond hoe deze waarde via berekeningen is gevonden. Daarnaast heb ik er ook nog twee video’s geplaatst (te vinden op de eerste pagina van het topic), waarin de man achter wizardofodds.com exact laat zien hoe je het huisvoordeel bij blackjack in excel kunt berekenen. Ook hij komt via zijn berekeningen op vergelijkbare waarden.

Ondanks dat in dat topic dus twee methodes om het huisvoordeel bij blackjack te berekenen volledig worden uitgelegd, en dus stap voor stap te controleren zijn, gelooft @dobbelsteen nog steeds niet dat het huisvoordeel bij blackjack zo klein is en wil hij graag een simulatie zien. Vandaar dit topic.

Ik heb een simulatie geschreven die 1 miljoen blackjack handen speelt volgens de regels van Holland Casino:

  • -          Dealer stand op soft 17

  • -          Dubbelen alleen op totalen 9, 10, 11

  • -          Dubbelen na splitsen toegestaan

  • -          Slechts één kaart op gesplitste azen

  • -          Maximaal 4 keer splitsen (ik weet niet zeker of dit het geval is in HC, maar als je vaker mag splitsen is het huisvoordeel alleen maar kleiner, dus dat moet geen punt zijn)

  • -          blackjack betaalt 3 tegen 2

Verder wordt er volgens de basis strategie die bij deze regels de beste is gespeeld. Deze strategie is onder andere in eerder genoemd topic bepaald en luidt als volgt:

216077324_Basisstrategie.jpg.0cecf0a93ed7001216747503d22251b8.jpg

Toegegeven, bij het programmeren van de simulatie gaf het splitsen ook mij de meeste problemen, maar dat is natuurlijk geen reden om het hele splitsen maar weg te laten, zoals @dobbelsteen in zijn poging deed om het huisvoordeel te berekenen.

Het hele programma voor de simulatie zal ik in mijn volgende post tonen en toelichten. Hieronder vast de output met een korte toelichting.

In de output worden van elke hand achtereenvolgens de kaarten van de speler en de kaarten van de dealer getoond. De eerste kaart van de dealer is de dealer up card. Zo is dus te controleren of inderdaad volgens de hierboven staande basis strategie is gespeeld. Daarna volgt de inzet en de uitbetaling van de betreffende hand. Bij een push is de uitbetaling natuurlijk gelijk aan de inzet. Bij verlies 0 en bij winst 2x de inzet.

Vervolgens wordt de totale inzet en totale uitbetaling tot dan toe gegeven. Zo kun je eenvoudig controleren na elke hand of dit nog steeds klopt. Als laatste wordt het uitbetalingspercentage tot dan toe gegeven, wat niets anders is dan de totale uitbetaling gedeeld door de totale inzet.

Is een hand een blackjack, wordt er gedubbeld of gesplitst, dan staat dit boven de hand aangegeven. Bij splitsen wordt eerst de hand getoond die gesplitst wordt en daarna volgen twee handen (of meer als er vaker gesplitst wordt) waarbij de eerste spelerskaart in beide gevallen de splits kaart is en waarbij beide handen tegen dezelfde dealer hand zitten (zie laatste hand in onderstaande voorbeeld)

 

Player: 10 8
Dealer: 5 2 7 7
Bet: 10
Payout: 0
Total bet: 10
Total payout: 0
Uitbetalingspercentage: Total payout/Total bet = 0

Player: 10 7
Dealer: 10 10
Bet: 10
Payout: 0
Total bet: 20
Total payout: 0
Uitbetalingspercentage: Total payout/Total bet = 0

Player: 2 5 1
Dealer: 6 10 10
Bet: 10
Payout: 20
Total bet: 30
Total payout: 20
Uitbetalingspercentage: Total payout/Total bet = 0.666667

Player: 10 5 10
Dealer: 9 10
Bet: 10
Payout: 0
Total bet: 40
Total payout: 20
Uitbetalingspercentage: Total payout/Total bet = 0.5

Player: 1 3 3 7
Dealer: 2 10 9
Bet: 10
Payout: 0
Total bet: 50
Total payout: 20
Uitbetalingspercentage: Total payout/Total bet = 0.4

Split
9 9

Player: 9 3
Dealer: 6 3 6 10
Bet: 10
Payout: 20
Total bet: 60
Total payout: 40
Uitbetalingspercentage: Total payout/Total bet = 0.666667

Player: 9 10
Dealer: 6 3 6 10
Bet: 10
Payout: 20
Total bet: 70
Total payout: 60
Uitbetalingspercentage: Total payout/Total bet = 0.857143

 

Het simulatie programma heeft op bovenstaande manier 1 miljoen handen weggeschreven in een bestand. Dit bestand is zodanig groot dat ik het opgedeeld heb in vier bestanden en deze kunnen hieronder bekeken worden. Je kunt eenvoudig controleren dat dit opeenvolgende handen zijn door totale inzet en totale uitbetaling van de laatste hand in document 1 te vergelijken met de eerste hand in document 2 etc.

Blackjack Simulatie 1 miljoen handen deel 1

Blackjack Simulatie 1 miljoen handen deel 2

Blackjack Simulatie 1 miljoen handen deel 3

Blackjack Simulatie 1 miljoen handen deel 4

Scroll je door naar de laaste hand in document 4 dan zie je daar het uitbetalingspercentage staan na 1 miljoen handen gespeeld volgens bovenstaande strategie. Voor de meesten zal de uitkomst geen verrassing zijn: 0.993399. Met andere woorden, bovenstaande strategie geeft een uitbetalingspercentage van 99,34% en het huisvoordeel is dus 0,66%. Nagenoeg gelijk aan de eerder berekende huisvoordelen in het andere topic.

In de volgende post zal ik het volledige programma plaatsen en zonodig toelichten, zodat @dobbelsteen kan controleren dat alles juist is gedaan. Voor nu kan hij in elk geval de miljoen handen na lopen om te controleren of alle handen juist zijn gespeeld en de totale inzet en uitbetaling goed zijn berekend.

Link naar opmerking
Deel via andere websites

In deze post deel ik het volledige programma van de simulatie. Mensen die twijfelen of de gegenereerde handen wel eerlijk zijn gekozen kunnen dat hier controleren. Specifieke vragen over hoe het programma de handen speelt beantwoord ik met liefde, vragen over hoe c++ werkt zijn in dit topic niet de bedoeling, die kun je prima op internet opzoeken.

In de code zelf staat ook nog eens uitleg bij de meeste regels achter //-tekens, zo kun je als het goed is precies volgen wat het programma doet.

In het hoofdprogramma worden de eerste twee kaarten voor de speler en de eerste kaart voor de dealer gegenereerd. Vervolgens wordt eerst de dealerhand uitgespeeld. Dit is om te zorgen dat we later bij splitsen zeker zijn dat de gesplitste handen tegen dezelfde dealer hand komen te zitten. Aangezien alle kaarten random worden gekozen, maakt dit voor uiteindelijke uitkomsten niet uit. Zolang we maar bij het spelen van de hand alleen kijken naar de eerste kaart van de dealer.

Nadat de dealershand gespeeld is, wordt het tot dan toe gegenereerde in de functie gestopt die de spelershand verder speelt:

    int totalBet = 0;                                   //slaat totale inzet op
    int totalPayout = 0;                                //slaat totale uitbetaling op

int main()
{
    srand(time(0));

    ofstream output("outputBlackjackSimulatie.txt");    //file waarin de gegenereerde handen worden weggeschreven, zodat spel gecontroleerd kan worden

    int firstCardPlayer;                                //eerste kaart speler
    int secondCardPlayer;                               //tweede kaart speler
    int dealerUpCard;                                   //dealer up kaart
    bool hitDealerHand = false;                         //geeft weer of dealer een kaart neemt
    vector<int> dealerHand;                             //variable met volledige hand van dealer
    int nextDealerCard;                                 //variabele voor volgende kaart dealer
    int nSplits;                                        //houdt bij hoe vaak we splitsen, maximaal naar 4 handen

    //start van de hand
    for (int i = 0;i < 1000000;i++)                     //we doen alles 1 miljoen keer
    {
        nSplits = 0;                                    //bij aanvang van de hand hebben we nog 0 keer gesplitst

        firstCardPlayer = getRandomCard();              //creëert een random kaart (zie functie getRandomCard) als eerste kaart voor de speler
        dealerUpCard = getRandomCard();                 //creëert random kaart als dealer up kaart
        secondCardPlayer = getRandomCard();             //tweede kaart voor spelers hand

        //om bij handen die gesplitst moeten worden te zorgen dat beide nieuwe handen tegen dezelfde dealer hand komen te zitten
        //spelen we eerst de dealer hand uit. Aangezien alle kaarten random gekozen worden, maakt dit voor de uiteindelijke resultaten niet uit
        //uiteraard wordt bij spelen van de speler hand alleen gekeken naar de eerste kaart van de dealer

        dealerHand.clear();                                 //zorg dat dealerhand leeg is
        dealerHand.push_back(dealerUpCard);                 //sla de eerste kaart van dealer op in dealerhand
        nextDealerCard = getRandomCard();                   //creëer random tweede kaart voor dealer
        dealerHand.push_back(nextDealerCard);               //sla tweede kaart op in dealer hand

        hitDealerHand = hitDealerCheck(dealerHand);         //checkt of dealer een kaart moet nemen (zie functie hitDealerCheck)
        while (hitDealerHand)                               //zolang dealer een kaart moet nemen:
        {
            nextDealerCard = getRandomCard();                   //creëer nieuwe random card
            dealerHand.push_back(nextDealerCard);               //voeg kaart toe aan dealer hand
            hitDealerHand = hitDealerCheck(dealerHand);         //check of dealer nog een kaart moet nemen
        }                                                       //als dit het geval is, gaat code weer naar while(hitDealerHand)

        //hand kan nu gespeeld worden volgens de basisstrategie, zie functie playHand
        playHand(firstCardPlayer, secondCardPlayer, dealerUpCard, dealerHand, nSplits, output);

    }


    output.close();
}

De functie die een random kaart genereert, kiest willekeurig een getal van 1-13. Vervolgens worden getallen 11-13 (boer, vrouw, heer) omgezet naar de waarde 10. Hierbij wordt er dus van een oneindig aantal spellen uitgegaan. In het topic waar de basis strategie werd berekend is dit ook gedaan en akkoord bevonden door @dobbelsteen, dus dat zal nu ook het geval zijn.

int getRandomCard()
{
   int randomNumber = rand() % 13 + 1;      //creëert random nummer van 1-13
   if (randomNumber > 10)                   //als het nummer >10 (en dus boer, vrouw of heer representeert)
        randomNumber = 10;                  //zetten we de waarde naar 10
   return randomNumber;                     //waarde van aas staat voor nu op 1, wordt later gekeken of hij als 11 moet tellen
}

 

De volgende functie checkt of de dealer een kaart moet nemen. Hierin wordt gebruik gemaakt van de functies die het totaal van een hand tellen en de functie die checkt of een hand een soft hand is, een hand met een aas die nog voor 11 kan tellen.

bool hitDealerCheck(vector<int> dealerHand)
{
    int handTotal = calculateHandTotal(dealerHand);                             //berekent het totaal van de hand, zie functie calculateHandTotal
    bool softHand = softHandCheck(dealerHand, handTotal);                       //checkt of hand een soft hand is, zie functie softHandCheck

    if ((softHand) && (handTotal >= 7))                                         //als dealer soft hand heeft en totaal is >=7, dan heeft dealer >= soft 17
        return false;                                                           //en past

    if (handTotal >= 17)                                                        //als dealer totaal van >= 17 heeft
        return false;                                                           //dan past dealer

    return true;                                                                //in alle andere gevallen neemt dealer een kaart
}

Berekent totaal van een hand:
int calculateHandTotal(vector<int> hand)
{
    int total = 0;                            //totaal begint op 0
    for (int i = 0;i < hand.size();i++)       //voor elke kaart in de hand
    {
        total += hand[i];                     //voeg de waarde van de kaart toe aan totaal
    }
    return total;                             //geef het totaal van de hand terug
}  

Kijkt of een hand een soft hand is:
bool softHandCheck(vector<int> hand, int handTotal)
{
    bool handContainsAce = false;                     //slaat op of de hand minimaal één aas bevat
    for (int i = 0;i < hand.size();i++)               //voor elke kaart in de spelershand
    {
        if (hand[i] == 1)                             //kijk of de waarde gelijk is aan 1
            handContainsAce = true;                   //zo ja, dan bevat de hand een A
    }
    if ((handContainsAce) && (handTotal < 12))        //als hand een A bevat en het total is kleiner dan 12
        return true;                                  //dan kan de A ook nog als 11 tellen en dus is het een softhand
    else
        return false;                                 //anders is het een hard hand
}

 

Vervolgens wordt de hand gespeeld door de functie playHand die je hieronder ziet. Daaronder volgt een toelichting met de code van andere functies die in deze functie worden gebruikte

void playHand(int firstCardPlayer, int secondCardPlayer, int dealerUpCard, vector<int> dealerHand, int nSplits, ofstream &output)
{
    bool splitThisHand = false;                     //variabele die zegt of we moeten splitsen, default is niet
    bool doubleThisHand = false;                    //variabele die zegt of we moeten dubbelen, default is niet
    bool hitThisHand = false;                       //variabele die zegt of we een kaart nemen, default is niet
    bool blackjackThisHand = false;                 //variabele die zegt of we blackjack hebben, default is niet
    bool blackjackDealerHand = false;               //variable die zegt of dealer blackjack heeft, default is niet

    int playerTotal;                                //variabele voor het totaal van de speler
    int dealerTotal;                                //variabele voor het totaal van de dealer

    int doubleDownCard;                             //mogelijke doubledown kaart
    int hitCard;                                    //mogelijke hit kaart
    int nextDealerCard;                             //mogelijke volgende dealer kaart

    vector<int> playerHand;                         //variabele waarin de volledige hand van de speler opgeslagen wordt
    playerHand.clear();                             //zorg dat de hand leeg is
    playerHand.push_back(firstCardPlayer);          //eerste kaart opgeslagen
    playerHand.push_back(secondCardPlayer);         //tweede kaart opgeslagen

    if (blackjackCheck(firstCardPlayer, secondCardPlayer, nSplits))     //check of we blackjack hebben, zie functie blackjackCheck
    {
        output << "Blackjack" << endl;                                  //schrijf in output file dat we blackjack hebben
        blackjackThisHand = true;
    }
    else if (splitCheck(firstCardPlayer, secondCardPlayer, dealerUpCard, nSplits))          //check of we moeten splitsen, zie functie splitCheck
    {
        output << "Split" << endl;                                                          //schrijf in output file dat we splitsen
        output << firstCardPlayer << " " << secondCardPlayer << endl << endl;               //schrijf in output beide kaarten

        splitThisHand = true;                                                               //bij splitsen moeten er twee nieuwe handen gemaakt worden
        int firstHandSecondCard = getRandomCard();                                          //kies random tweede kaart voor eerste hand
        int secondHandSecondCard = getRandomCard();                                         //kies random tweede kaart voor tweede hand
        nSplits++;                                                                          //we hebben nu 1 keer vaker gesplitst

        playHand(firstCardPlayer, firstHandSecondCard, dealerUpCard, dealerHand, nSplits, output);    //eerste nieuwe hand gaat opnieuw in deze functie
        playHand(secondCardPlayer, secondHandSecondCard, dealerUpCard, dealerHand, nSplits, output);  //tweede nieuwe hand gaat opnieuw in deze functie

    }
    else if ((nSplits > 0) && (firstCardPlayer == 1))                                       //als de hand afkomstig is van gesplitste azen
    {
                                                                                            // krijgen we geen kaart meer
    }
    else if (doubleDownCheck(firstCardPlayer, secondCardPlayer, dealerUpCard))               //check of we moeten dubbelen, zie functie doubleDownCheck
    {
        output << "Double Down" << endl;                                                     //schrijf in output file dat we dubbelen
        doubleThisHand = true;
        doubleDownCard = getRandomCard();                                                    //bij double down krijgt speler 1 extra random kaart
        playerHand.push_back(doubleDownCard);                                                //voeg random kaart aan hand toe
    }
    else if (hitCheck(playerHand, dealerUpCard))                                             //als blackjack, split en double down niet van toepassing zijn
    {                                                                                        //checken of we een kaart nemen, zie functie hitCheck
        hitThisHand = true;
        while (hitThisHand)                                                                  //zolang we een kaart moeten nemen doen we het volgende:
        {
            hitCard = getRandomCard();                                                       //verkrijg nieuwe random kaart
            playerHand.push_back(hitCard);                                                   //voeg kaart toe aan spelershand
            hitThisHand = hitCheck(playerHand, dealerUpCard);                                //check of we nog een kaart moeten nemen
        }                                                                                    //als dit het geval, gaat de code weer naar while(hitThisHand)
    }                                                                                        //anders niet

    //de hand is nu volledig gespeeld
    //na splitsen worden de twee nieuwe handen volledig door de gehele code van deze functie geleid
    //dus hoeft de huidige hand als die gesplitst is verder niet behandeld te worden

    if (!splitThisHand)
    {
        //schrijft de speler hand naar de output file
        output << "Player: ";
        for (int i = 0;i < playerHand.size();i++)       //voor elke kaart in speler hand
            output << playerHand[i] << " ";             //schrijf kaart naar file
        output << endl;

        //schrijft de dealer hand naar de output file
        output << "Dealer: ";
        for (int i = 0;i < dealerHand.size();i++)       //voor elke kaart in dealer hand
            output << dealerHand[i] << " ";             //schrijf kaart naar file
        output << endl;

        //bereken het totaal speler
        playerTotal = calculateHandTotal(playerHand);   //speler totaal met azen als 1 tellend
        if (softHandCheck(playerHand, playerTotal))     //als speler soft totaal heeft
            playerTotal += 10;                          //is het geldende totaal 10 hoger

        //bereken totaal dealer
        dealerTotal = calculateHandTotal(dealerHand);   //net zo voor dealer totaal
        if (softHandCheck(dealerHand, dealerTotal))
            dealerTotal += 10;

        extern int totalBet;                            //zorgt dat we totale inzet vanuit het main programma kunnen wijzigen
        extern int totalPayout;                         //zorgt dat we totale uitbetaling vanuit het main programma kunnen wijzigen

        //bereken de inzet van deze hand, basis inzet is 10
        if (doubleThisHand)                             //als er gedubbeld is
        {
            totalBet += 20;                             //komt er 20 bij de totale inzet
            output << "Bet: 20" << endl;                //schrijf inzet naar output file
        }
        else
        {
            totalBet += 10;                             //anders komt er 10 bij de totale inzet (basisinzet is 10)
            output << "Bet: 10" << endl;                //schrijf inzet naar output file
        }

        blackjackDealerHand = blackjackCheck(dealerHand[0], dealerHand[1], 0);   //check of dealer blackjack heeft, zie functie blackjackCheck

        //bereken de uitbetaling van deze hand, uitbetaling is in dit geval hoeveel je in totaal terugkrijgt, dus inzet hoort hier ook bij
        if (blackjackThisHand)                                                   //als wij een blackjack hebben
        {
            if (!blackjackDealerHand)                                               //en dealer heeft geen blackjack
            {
                totalPayout += 25;                                                      //krijgen we 25 uitbetaald
                output << "Payout: 25" << endl;                                       //schrijf uitbetaling naar output file
            }
            else                                                                    //als dealer ook een blackjack heeft
            {
                totalPayout += 10;                                                      //krijgen we onze inzet terug
                output << "Payout: 10" << endl;
            }

        }
        else if (doubleThisHand)                                                 //als we gedubbeld hebben (dealer heeft dan sowieso geen bj, dus daar hoeven we niet op te testen)
        {
            if (playerTotal <= 21)                                                  //we een totaal <= 21 hebben
            {
                if (playerTotal == dealerTotal)                                         //en speler en dealer hebben gelijke score
                {
                    totalPayout += 20;                                                      //dan krijgen we onze dubbele inzet terug
                    output << "Payout: 20" << endl;
                }
                else if ((playerTotal > dealerTotal) || (dealerTotal > 21))             //als wij beter hebben of dealer > 21 heeft
                {
                    totalPayout += 40;                                                      //dan krijgen we dubbel onze dubbele inzet terug
                    output << "Payout: 40" << endl;
                }
                else                                                                    //in alle andere gevallen
                {
                    output << "Payout: 0" << endl;                                        //krijgen we niets
                }
            }
        }
        else                                                                      //we hebben niet gedubbeld
        {
            if (blackjackDealerHand)                                                    //als dealer een blackjack heeft
            {
                output << "Payout: 0" << endl;                                            //krijgen we niets
            }
            else if (playerTotal <= 21)                                                 //we hebben een totaal <= 21
            {
                if (playerTotal == dealerTotal)                                             //en speler en dealer hebben gelijke score
                {
                    totalPayout += 10;                                                          //dan krijgen we onze inzet terug
                    output << "Payout: 10" << endl;
                }
                else if ((playerTotal > dealerTotal) || (dealerTotal > 21))                 //als wij beter hebben of dealer heeft > 21
                {
                    totalPayout += 20;                                                          //dan krijgen we dubbel onze inzet terug
                    output << "Payout: 20" << endl;
                }
                else                                                                    //in andere gevallen
                {
                    output << "Payout: 0" << endl;                                        //krijgen we niets
                }
            }
            else                                                                    //we hebben > 21
            {
                output << "Payout: 0" << endl;                                          //dus we krijgen niets
            }
        }

        output << "Total bet: " << totalBet << endl;
        output << "Total payout: " << totalPayout << endl;
        output << "Uitbetalingspercentage: Total payout/Total bet = " << (float) totalPayout/totalBet << endl;


        output << endl;
    }
}

 

Er wordt eerst gecheckt of we een blackjack hebben

bool blackjackCheck(int firstCard, int secondCard, int nSplits)
{
    if (nSplits != 0)                               //als er al gesplitst is
        return false;                               //telt de hand sowieso niet als blackjack, rest van de code wordt niet uitgevoerd

    if ((firstCard == 1) && (secondCard == 10))     //als eerste kaart gelijk is aan 1 (aas) en tweede gelijk aan 10
        return true;                                //dan is het een blackjack, rest van de code wordt niet uitgevoerd

    if ((firstCard == 10) && (secondCard == 1))     //als eerste kaart gelijk is aan 10 en tweede gelijk aan 1 (aas)
        return true;                                //dan is het een blackjack, rest van de code wordt niet uitgevoerd

    return false;                                   //als bovenstaande allemaal niet waar was, is het geen blackjack
}

 

Dan wordt er gecheckt of we moeten splitsen. Is dat het geval dan wordt er met beide kaarten een nieuwe hand gemaakt die weer opnieuw in de functie wordt gestopt.

bool splitCheck(int firstCard, int secondCard, int dealerUpCard, int nSplits)
{
    if (nSplits == 3)           //als we al drie keer gesplitst hebben
        return false;           //mogen we niet meer splitsen, rest van de code wordt niet uitgevoerd

    if (firstCard != secondCard) //als eerste en tweede kaart niet aan elkaar gelijk zijn
        return false;            //kunnen we niet splitsen, rest van de code wordt niet uitgevoerd

    //onderstaande wordt uitgevoerd als we mogen en kunnen splitsen, zie gegeven basis strategie wanneer we willen splitsen

    //als speler 2,2 heeft en dealer 2-7 wordt gesplitst
    if ((firstCard == 2) && (dealerUpCard >= 2) && (dealerUpCard <= 7))
        return true;

    //als speler 3,3 heeft en dealer 2-7 wordt gesplitst
    if ((firstCard == 3) && (dealerUpCard >= 2) && (dealerUpCard <= 7))
        return true;

    //als speler 4,4 heeft en dealer 5-6 wordt gesplitst
    if ((firstCard == 4) && (dealerUpCard >= 5) && (dealerUpCard <= 6))
        return true;

    //als speler 6,6 heeft en dealer 2-6 wordt gesplitst
    if ((firstCard == 6) && (dealerUpCard >= 2) && (dealerUpCard <= 6))
        return true;

    //als speler 7,7 heeft en dealer 2-7 wordt gesplitst
    if ((firstCard == 7) && (dealerUpCard >= 2) && (dealerUpCard <= 7))
        return true;

    //als speler 8,8 heeft en dealer 2-9 wordt gesplitst
    if ((firstCard == 8) && (dealerUpCard >= 2) && (dealerUpCard <= 9))
        return true;

    //als speler 9,9 heeft en dealer geen 7, 10 of A wordt gesplitst
    if ((firstCard == 9) && (dealerUpCard != 7) && (dealerUpCard != 10) && (dealerUpCard != 1))
        return true;

    //als speler A,A heeft en dealer geen A wordt gesplitst
    if ((firstCard == 1) && (dealerUpCard != 1))
        return true;

    //in alle andere gevallen wordt niet gesplitst
    return false;
}

 

En er wordt gecheckt of we moeten dubbelen:

bool doubleDownCheck(int firstCard, int secondCard, int dealerUpCard)
{
    if ((firstCard == 1) || (secondCard == 1))                                //als een van beide spelerskaarten een A is, wordt er niet gedubbeld
        return false;

    int playerTotal = firstCard + secondCard;                                 //spelerstotaal is som van beide kaarten

    //als speler totaal 9 heeft en dealer 3-6 wordt er gedubbeld
    if ((playerTotal == 9) && (dealerUpCard >=3) && (dealerUpCard <= 6))
        return true;

    //als speler totaal 10 heeft en dealer 2-9 wordt er gedubbeld
    if ((playerTotal == 10) && (dealerUpCard >= 2) && (dealerUpCard <= 9))
        return true;

    //als speler totaal 11 heeft en dealer 2-9 wordt er gedubbeld
    if ((playerTotal == 11) && (dealerUpCard >= 2) && (dealerUpCard <= 9))
        return true;

    //in alle andere gevallen wordt er niet gedubbeld
    return false;
}

 

Als dubbelen en splitsen behandeld is, worden er kaarten genomen zolang als de basisstrategie dat zegt:

bool hitCheck(vector<int> playerHand, int dealerUpcard)
{
    int handTotal = calculateHandTotal(playerHand);                             //berekent het totaal van de hand, zie functie calculateHandTotal
    bool softHand = softHandCheck(playerHand, handTotal);                       //checkt of hand een soft hand is, zie functie checkSoftHand


    if (softHand)                                                               //als het een soft total is (aas kan nog als 11 tellen)
    {
        if (handTotal >= 9)                                                     //als totaal 9, 10 of 11 is (softHand heeft sowieso total < 12 als A nog als 1 telt)
            return false;                                                       //wordt er gepast (werkelijke total is dan 19, 20 of 21 en wordt later berekend)

        if ((handTotal == 8) && (dealerUpcard >= 2) && (dealerUpcard <= 8))     //soft 18 tegen dealer 2-8
            return false;                                                       //wordt gepast

        return true;                                                            //alle andere soft totalen krijgen een kaart
    }
    else                                                                        //als het een hard total is
    {
        if ((handTotal == 12) && (dealerUpcard >= 4) && (dealerUpcard <= 6))    //als total 12 is en dealer heeft 4-6
            return false;                                                       //wordt er gepast

        if ((handTotal > 12) && (dealerUpcard >= 2) && (dealerUpcard <= 6))     //als total > 12 en dealer heeft 2-6
            return false;                                                       //wordt er gepast

        if (handTotal >= 17)                                                    //als totaal > 17
            return false;                                                       //wordt er gepast

        return true;                                                            //in alle andere gevallen wordt een kaart genomen.
    }
}

 

Als dit allemaal gedaan is, worden de volledige spelershand en volledige dealershand naar de output geschreven. In de file met de output kan dus voor elke hand gecontroleerd worden of deze inderdaad volgens de basisstrategie is gespeeld.

Vervolgens worden de totalen van de hand berekend.

Na het berekenen van totalen wordt de inzet bepaald. Die is 10 tenzij er gedubbeld is, dan is die 20. Handen die gesplitst zijn, zijn elk een afzonderlijke hand geworden die door de functie gaat, en krijgen dus automatisch elk afzonderlijk een inzet van 10. De inzet voor de hand wordt ook naar de output file geschreven.

Vervolgens kan de uitbetaling berekend worden. Denk er hierbij om dat de uitbetaling ook bestaat uit inzet, die krijg je tenslotte terug als je wint of gelijk speelt. De uitbetaling wordt ook naar de output file geschreven

Als laatste wordt er in de output geschreven wat de totale inzet en de totale uitbetaling tot dan toe is en wat het uitbetalingspercentage tot dan toe is wat daar uit volgt.

 

In het topic Berekeningen van het huisvoordeel van blackjack voor HC stonden twee volledig uitgewerkte en controleerbare rekenkundige methodes die ontegenzeggelijk aantonen dat het huisvoordeel van blackjack onder de regels van Holland Casino rond 0,67% ligt. Nu hebben we daar een volledig controleerbare simulatie met hetzelfde resultaat bij. Het programma kan volledig nagezien worden en als kennis van c++ te gering is om het volledig te snappen, kunnen alle handen nagelopen worden om te controleren of er juist is gespeeld en of inzet en uitbetaling correct gedaan zijn.

Iedereen die nu nog steeds beweert dat het huisvoordeel anders is, kan echt niet langer serieus genomen worden.

  • Like 4
  • Thanks 2
Link naar opmerking
Deel via andere websites

Mijn eerste indruk is dat je mijn verwachting overtroffen hebt . Ik heb geen kennis van het programma dat je gebruikt,maar het ziet er zeer professioneel en gedegen uit. Ik heb wel al een aantal vragen maar morgen ga ik het verslag grondig bestuderen. Helaas leg jij me woorden in de mond die ik  niet gesproken hebt. Ik heb alleen getwijfeld omdat op internet meerdere waarden circuleren. Je hebt jezelf de opdracht gegeven een simulatie van 1 M te publiceren. Ik ga mijn programma controleren op bugs. Voorlopig CHAPEAU!!

Link naar opmerking
Deel via andere websites

Die verschillende waarden zijn te verklaren door verschil in regels. Als je zoals in Amerikaanse casino's bij elk totaal mag verdubbelen, dan heb je simpelweg dus meer keuzes om je hand te spelen dan in Holland Casino. Ongetwijfeld zullen daar een aantal keuzes bij zitten die beter voor de speler zijn, en dus wordt niet alleen de basisstrategie anders (soft 18 wil je bijvoorbeeld het liefst dubbelen tegen een 6, maar als dat niet mag zoals in HC, dan heb je dus automatisch een andere basis strategie), ook de verwachtingswaarde wordt daardoor natuurlijk anders.

Het mooie van dit programma is dat het relatief eenvoudig moet zijn om een andere basisstrategie in te voeren, waaruit in veel gevallen dus ongetwijfeld een ander huisvoordeel zal volgen. Mocht je een specifieke basisstrategie willen zien, voer ik die met plezier in.

Link naar opmerking
Deel via andere websites

Met plezier heb ik het programma bekeken.Heel wat jaren geleden heb ik tijdelijk ook in VB geprogrammeerd. Voor de relatief eenvoudige roulette systemen is Excel gemakkelijker. Mijn kennis van VB is volledig vergeten maar ik herken de structuur van het programma. De manier hoe het programma omgaat met de opdrachten van de kaart  is zeer interessant. Deze methode kan ik waarschijnlijk ook in Excel toepassen, waar door het programma eenvoudiger wordt. Ik heb ijverig gezocht naar bugs in het programma maar  niet gevonden.

In principe heb je niet de HE berekend , maar het resultaaat van een sample van 1M handen gespeeld volgens de kaart en met de regels van HC. Met slechts een enkele toets aanslag berekent het programma een nieuw sample. Geeft dit hetzelfde betrouwbare resultaat dan mag je concluderen dat er geen echte bugs zijn en dat de grootte van het sample representief is.
 

Mijn theorie zegt dat elk kansspel op lange termijn eindigt met een verliespercentage gelijk aan de HE.Jouw sample voldoet hieraan, omdat het een berekening is van een systeem.Je mag het eigenlijk geen Basic Strategie noemen maar een Basic systeem.

De HE geldt alleen voor hele grote  of oneindig grote samples.
Deze samples heb ik met macro aangeduid.
Een speler speelt echter een zeer klein aantal handen. Dit zijn dan nano samples.

Alles wat voor macro geldt, geldt niet voor nano.

Jij kunt dit gemakkelijk onderzoeken om de resultaten te laten berekenen voor samples van 100 handen. Dit is een kleine aanpassing van het programma.

De Wizard  of Vegas kun je ook vinden de grote invloed van het aantal decks.

Nogmaals CHAPEAU.

 

 

Link naar opmerking
Deel via andere websites

Ik ben blij dat je hierover te spreken bent.

16 uur geleden zei dobbelsteen:

Alles wat voor macro geldt, geldt niet voor nano

Andersom kun je echter zeggen: als iets voor nano geldt, dan moet het ook voor macro gelden. Heel vaak nano is tenslotte weer macro. Denk je op nanoschaal iets structureels gevonden te hebben, dan moet het dus ook op macro schaal gelden. Geldt het niet op macro schaal, dan is wat je op nano schaal gevonden hebt dus een resultaat van variantie (ook wel geluk).

Link naar opmerking
Deel via andere websites

Het kenmerk van een macro reeks is dat alle gebeurtenissen in gelijke aantallen met minimale verschillen voorkomen. In de natuurwetenschappen weten we dat de natuurlijke eigenschappen heel sterk veranderen in de nano fase..Bijvoorbeeld sommige materialen worden super geleidend bij -273 graden celcius. Op de Universiseit van Twente heeft men speciaal een faculreit  voor de nanowetenschap.
Neem  je uit een macro reeks een nano sample dan  zal in dit klein sample alle elementen niet in gelijke aantallen voorkomen. Hoe kleiner het sample deste groter de verschillen.
Nano samples kunnen wel dezelfde eigenschappen hebben. Voeg je deze samen dan heeft het macro sample ook deze eigenschap .

In een macro sample van rood en zwart  is de verhouding R/Z  gelijk aan 1.  Dit betekent niet dat de verhouding P/M ook 1 is.

Spelers hebben altijd te maken met nano samples.

De uitleg van de strategie voor een kansspel  houd ik liever wat simpeler.

Neem jij random een sample van 100 handen uit jouw 1M sample dan zal het winstpercentage sterk verschillen met de Edge.

Link naar opmerking
Deel via andere websites

Met de kennis van nu kunnen we het BJ systeem van HC, gespeeld met de Basic Srategie, vergelijken met de prestaties van de SSB methode van een enkelvoudig kans van de roulette.

Als  BJ geprogrammeerd is in Excel  dan is het net zo eenvoudig als de voorbeelden in mijn thread. In het voorbeeld van de dubbele zero doe ik het voor 90 samples. Met het computer programma dat DeValsspeler gebruikt is het waarschijnlijke iets lastiger om het resultaat van 90  samples van bijvoorbeeld 100 tot 150 handen te laten berekenen. Ik vermoed dat SSB een beter resultaat zal geven.

Link naar opmerking
Deel via andere websites

Doe mee aan het gesprek

Je kunt nu posten en later registreren. Als je een account hebt, Meld je nu aan om te posten met je account.

Gast
Reageer op deze discussie...

×   Je hebt opgemaakte inhoud geplakt.   Opmaak verwijderen

  Only 75 emoji are allowed.

×   Je link is automatisch geïntegreerd.   In plaats daarvan als link tonen

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Nieuwe aanmaken...