views:

410

answers:

4

My brother turns 21 in a couple of weeks and my parents and I are taking him to Las Vegas. For my 21st, I brought $200 to gamble in Vegas and came home with around $450, mostly from playing craps. I plan on bringing $200 again for this trip and before I go I thought I'd run some craps simulations to see if I can double my money again.

I've read from several sources that the house has the smallest advantage in craps when placing a passline bet with maximum odds. From my memory, and as surveyed by Wizard of Odds, most casinos on the Strip are 3-4-5 odds with a $5 minimum. Taking this into account, here is a simulation of a craps session (of 100 dice rolls) in PHP:

<?php

$stash = 200;
$bet = 5;

for($i=100; $i--;) {

    $dice1 = mt_rand(1, 6);
    $dice2 = mt_rand(1, 6);
    $total = $dice1 + $dice2;

    if(!$button) {
        if($total===7 || $total===11) {
            $stash += $bet;
        }
        elseif($total===2 || $total===3 || $total===12) {
            $stash -= $bet;
        }
        else {
            $button = $total;
            if($total===4 || $total===10) {
                $odds = $bet*3;
            }
            elseif($total===5 || $total===9) {
                $odds = $bet*4;
            }
            elseif($total===6 || $total===8) {
                $odds = $bet*5;
            }
        }
    }
    else {
        if($total===7) {
            $button = 0;
            $stash -= ($bet + $odds);
        }
        elseif($total===$button) {
            $button = 0;
            $stash += $bet;
            if($total===4 || $total===10) {
                $stash += $odds*2/1;
            }
            elseif($total===5 || $total===9) {
                $stash += $odds*3/2;
            }
            elseif($total===6 || $total===8) {
                $stash += $odds*6/5;
            }
        }
    }

    echo 'Stash: $'.$stash.'<br/>';

}

?>

Is there anything wrong with my math here? While there are peaks and troughs throughout each session, this simulation more often doubles its money before going broke. Considering the house always has the edge in craps, even if it's just a fraction of a percent, I'm perplexed by this result.

+4  A: 

Well, right off the bat, I can see that you've got an error in the simple 7 or 11 win case: You're supposed to win your bet, not twice your bet.

Edit: I believe the payout for the odds bet is commensurate with the actual probability. You are twice as likely to roll 7 (lose your odds) than 10, so you should get paid 2:1 when you win on a 4 or 10; and only paid 6:5 when you win on a 6 or 8.

John Y
I modified the source - how does it look to you now? Do the odds winnings need adjusting or is the simulation correct?
Kevin
@Kevin: I think you've gotten all the payouts correct now, to my understanding of craps. However, the answers given by other people contain ways to improve and expand on your simulation.
John Y
+6  A: 

I'd be careful with any piece of code written to "prove" you're more likely to double your money at craps (or any other game of chance) before you go broke. Las Vegas is a sprawling city in the desert of Nevada as a testament to two things:

  1. Eventually, the house always wins
  2. People are bad at math

There is no game any casino would put on their floor that didn't leverage both rules. If your code disagrees with Vegas, I'm putting my money on Vegas.

Update:

Here is some C++ I wrote based on your original code. The original problem you posted was if you could double your money before you went broke more often than not. I followed up the code I wrote with some results.

#include <iostream>

int die_roll()
{
    return std::rand() % 6 + 1;
}

int win_count_g(0);
int loss_count_g(0);

// return true when double our money.
// return false when we can't bet anymore.
bool test_loop(int cash)
{
    static const int bet_k(5);

    int goal(cash * 2);
    int button(0);

    while (true)
    {
        if (cash >= goal)
            return true;
        else if (cash < bet_k)
            return false;

        int roll(die_roll() + die_roll());
        int odds(0); // additional odds bet

        if (button == 0)
        {
            if (roll == 7 || roll == 11)
            {
                ++win_count_g;
                cash += bet_k;
            }
            else if (roll == 2 || roll == 3 || roll == 12)
            {
                ++loss_count_g;
                cash -= bet_k;
            }
            else
            {
                button = roll;

                if (roll == 4 || roll == 10)
                {
                    odds = std::min(cash - bet_k, bet_k * 3);
                }
                else if (roll == 5 || roll == 9)
                {
                    odds = std::min(cash - bet_k, bet_k * 4);
                }
                else // if (roll == 6 || roll == 8)
                {
                    odds = std::min(cash - bet_k, bet_k * 5);
                }
            }
        }
        else
        {
            if (roll == 7)
            {
                ++loss_count_g;
                button = 0;
                cash -= bet_k + odds;
            }
            else if (roll == button)
            {
                ++win_count_g;
                button = 0;
                cash += bet_k;

                if (roll == 4 || roll == 10)
                {
                    cash += odds * 2;
                }
                else if (roll == 5 || roll == 9)
                {
                    cash += odds * 3 / 2;
                }
                else // if (roll == 6 || roll == 8)
                {
                    cash += odds * 6 / 5;
                }
            }
        }
    }
}

void test(int cash)
{
    win_count_g = 0;
    loss_count_g = 0;

    int doubled(0);
    int broke(0);

    for (int i(0); i < 10000; ++i)
        if (test_loop(cash))
            ++doubled;
        else
            ++broke;

    float win_percentage(static_cast<float>(doubled) / (doubled + broke) * 100.0);

    std::cout << "starting cash: $" << cash
              << "; doubled: " << doubled
              << "; broke: " << broke
              << " (" << win_percentage << "% win)"
              << "; loop wins: " << win_count_g
              << "; loop losses: " << loss_count_g
              << std::endl;
}

int main ()
{
    static const int cash_set_k[] =
    {
        5,
        10,
        20,
        50,
        100,
        200,
        400,
        800,
        1000
    };
    static const int cash_set_size_k(sizeof(cash_set_k) / sizeof(cash_set_k[0]));

    std::for_each(&cash_set_k[0], &cash_set_k[cash_set_size_k], &test);

    return 0;
}

Results:

starting cash: $5; doubled: 4944; broke: 5056 (49.44% win); loop wins: 4944; loop losses: 5056
starting cash: $10; doubled: 4862; broke: 5138 (48.62% win); loop wins: 19706; loop losses: 20258
starting cash: $20; doubled: 4755; broke: 5245 (47.55% win); loop wins: 78360; loop losses: 80320
starting cash: $50; doubled: 4345; broke: 5655 (43.45% win); loop wins: 489406; loop losses: 502506
starting cash: $100; doubled: 3553; broke: 6447 (35.53% win); loop wins: 1914393; loop losses: 1972273
starting cash: $200; doubled: 2468; broke: 7532 (24.68% win); loop wins: 7172464; loop losses: 7375024
starting cash: $400; doubled: 861; broke: 9139 (8.61% win); loop wins: 22615369; loop losses: 23277609
starting cash: $800; doubled: 112; broke: 9888 (1.12% win); loop wins: 54556881; loop losses: 56121041
starting cash: $1000; doubled: 31; broke: 9969 (0.31% win); loop wins: 69308617; loop losses: 71296217
fbrereto
Your code looks like what I came up with except you need to take the initial bet into account when calculating your odds bet. ie. `odds = std::min( cash - bet_k, bet_k * 3);` instead of `odds = std::min(cash, bet_k * 3);`
ghoppe
Thanks, updated; interestingly enough, I didn't see that change have any effect on the results. That'd make for an interesting pull from Vegas: bet on the odds, and Vegas gives you a minimum odds bet on the house!
fbrereto
+2  A: 

You're not checking to see if you have enough left in the stash to place your desired odds bet. In fact, you're not checking the size of your stash at all. It's unsurprising that this simulation will be able to beat the house more often if you are able to bet even if your stash size is negative.

By the way, I ran 50,000 iterations of your simulation of 100 dice throws (with my modification of maximum bet of stash remaining) and came up with the following:

wins: 23807

losses: 25465

push (you leave with $200): 728

avg. winnings: $109.07

ghoppe
One other thing I just realized, your simulation throws the dice 100 times and walks away without regard to how much money is left on the table, so the avg winnings and number of wins should be a bit less than that.
ghoppe
So I ran this modified script (50,000 iterations) with the additional caveat of "not leaving money on the table" ten times and came up with the following win percentages: 48.6%, 48.1%, 48.2%, 48.0%, 47.7%, 48.4%, 48.0%, 48.2%, 48.2%, 47.7%. In short: no, you can't beat Vegas. :)
ghoppe
A: 

I wrote the same type of simulation in .net when I returned from Vegas this February. Same story, I played craps twice while I was there, $100 in on a $5 max bet table, played the same strategy with a $5 pass line bet and maximum odds bet. I came out with $450. When I ran my simulation, same results, about 49% chance you would win, 51% chance the casino would win. Turns out the game of craps in one elaborate coin toss.

Gene