Simulate a game of Craps

18

Craps is a fairly simple dice game often played in casinos. Even if you aren't a gambler (which I'm not), it's still a fairly interesting game. Here's the rules:

At the start of a game of Craps there's what is called the come-out round. The player rolls two d6s (six-sided die) and the two die rolls are added. If the result is 7 or 11, the person automatically wins (this is known as a natural). If the result is 2, 3 or 12 the person automatically loses (this is known as crapping out). Otherwise, the result is set as the point for the point round.

After this, the point round begins. During the point round, the player must continuously roll 2 d6s until the person rolls a 7 or his/her point from the previous round. If the person rolls a 7, they lose. If they roll their point, they win.

Challenge

Implement a simple program that simulates a game of craps. If the person rolls a natural or a crap-out during the come-out round, the program should output "Natural: " or "Crapping out: " followed by the die-roll and then exit. Otherwise, it should output "Point: " followed by the point. Then, during the point round, it should output every die-roll until a 7 or the point is reached. If the person wins, it should output "Pass"; if they lose it should output "Don't Pass".

Reference Implementation

Groovy, 277 bytes

def a={return Math.random()*6+1};int b=a()+a();(b<4||b==12)?{println"Crapping out: "+b}():{(b==7||b==11)?{println"Natural: "+b}():{println"Point: "+b;for(;;){int x=a()+a();println x;(x==7)?{println"Don't Pass";System.exit(0)}():{if(x==b){println"Pass";System.exit(0)}}()}}()}()

Try it online.

Sample outputs

Natural: 7

Crapping out: 3

Point: 9
4
8
11
9
Pass

and

Point: 5
3
7
Don't Pass

This is , so shortest code wins.

(DISCLAIMER: This challenge is not intended to promote gambling in any way. Remember, the house always wins.)

a spaghetto

Posted 2015-10-22T20:54:37.267

Reputation: 10 647

You can't make your program shorter by picking a random number between 1 and 12 for the die roll; it must be two numbers picked between 1 and 6. - What about picking a random value in [1, 12] from a distribution that is identical to adding two uniform random values in [1, 6]? – Mego – 2016-08-16T08:28:42.957

@Mego Whoa, old challenge. Yes that would be fine. I think that warning was mostly just to make sure people realized that a uniform distribution between [1, 12] isn't the same as a 2d6. I'll rewrite it a little bit. – a spaghetto – 2016-08-16T15:30:46.703

Answers

6

Ruby 164

Pretty straightforward. Interesting features:

The crapping out cases are summarised as r%12<4 and the remaining natural cases are summarised as r%4==3.

The initial string is stored in c and further rolls are taken only if this is later alphabetically than the single letter ?P (which only occurs for Point.)

f=->{rand(6)+rand(6)+2}
s=0
r=f[]
print c=r%12<4?'Crapping out':r%4==3?'Natural':'Point',": #{r}
"
c>?P&&(until s==r||s==7
p s=f[]end
print s==7?"Don't ":"","Pass")

Level River St

Posted 2015-10-22T20:54:37.267

Reputation: 22 049

Love the way how you check for the remainder instead for 2,3,7,11 or 12 seperatly! – Jeroen – 2015-10-27T12:08:27.170

6

Python 3, 190 bytes

from random import*
r=randrange
p=print
a=r(5)+r(5)+2
c=890145//3**a%3
p(['Point:','Crapping out:','Natural:'][c],a)
if c<1:
 while 7!=c!=a:c=r(5)+r(5)+2;p(c)
 p(['Pass',"Don't pass"][c==7])

This is based on Celeo's answer; I replaced some lengthy conditionals with a magic number that encodes a LUT for each number, reused a variable, and did a few other miscellaneous golfs. Still room to golf; it's probably possible to get under 170.

I didn't try to use Python 2, so I don't know if it would be shorter.

lirtosiast

Posted 2015-10-22T20:54:37.267

Reputation: 20 331

1Care to explain how you got that magic number and how it works? – Karl Napf – 2016-08-16T08:44:28.730

5

Python 2, 226 224 bytes

First pass and there's a lot of code there:

from random import*
r=randrange
a=r(5)+r(5)+2
if a in[7,11]:print'Natural:',a
elif a in[2,3,12]:print'Crapping out:',a
else:
 print'Point:',a
 b=0
 while b not in[7,a]:b=r(5)+r(5)+2;print b
 print'Pass'if b-7else"Don't pass"

Thanks to Mego for 2 bytes!

Celeo

Posted 2015-10-22T20:54:37.267

Reputation: 520

Few issues with this. It doesn't print out "Point: " followed by the number if the roll wasn't a natural or a crap. Also, there should be a space between the : and the number. – a spaghetto – 2015-10-22T21:37:32.560

Whoops! Fixed not printing 'Point: #'. In the output, there is a space. – Celeo – 2015-10-22T21:43:08.680

Ah OK. I don't use Python very much anymore so I was uncertain about how the ,a works. – a spaghetto – 2015-10-22T21:43:57.367

I golfed your code down to 198 in Python 3, which is 192 in Python 2. Do you want the suggestions, or should I post my own answer? – lirtosiast – 2015-10-23T02:28:33.567

@ThomasKwa If you put a bunch of work into it, post as a separate answer so you can get some rep for it. – Celeo – 2015-10-23T15:37:05.723

@Mego Thanks for the suggestion! – Celeo – 2015-10-26T15:21:59.130

5

C99, 366 312 293 277 bytes

This is my first post here, so I'm going to guess that this can be improved by a lot.

#include<stdlib.h>
#include<time.h>
#define r rand()%6+1
#define p printf(
main(c,s){srand(time(0));s=r+r;int*a=s==7||s==11?"Natural:%d":2-s||3-s||12-s?0:"Crapping out:%d";if(a){p a,s);return 0;}p"Point:%d\n",c=s);do p"%d\n",s=r+r);while(7-s&&s-c);p(7-s)?"Pass":"Don't pass");}

Expanded Version

#include<stdlib.h>
#include<time.h>
#define r rand()%6+1
#define p printf(
main(c,s){
    srand(time(0));
    s=r+r;
    int*a=s==7||s==11?"Natural:%d":2-s||3-s||12-s?0:"Crapping out:%d";
    if(a) {p a,s);return 0;}
    p"Point:%d\n",c=s);
    do p"%d\n",s=r+r);
    while(7-s&&s-c);
    p(7-s)?"Pass":"Don't pass");
}

As you can see, there's a good amount of redundancy here that can most likely be done away with.

Credits to @Mego for helping to make this smaller.

Chris Loonam

Posted 2015-10-22T20:54:37.267

Reputation: 585

1As long as it compiles somewhere, you're good. – lirtosiast – 2015-10-24T04:13:13.013

@Mego thanks for pointing that out, that managed to get rid of 19 bytes. – Chris Loonam – 2015-10-25T23:11:13.230

Got some more off getting rid of a and b and also using the subtraction method along with ternary operators. – Chris Loonam – 2015-10-26T02:42:52.253

3

PHP 230 228 218 199 192 188 Bytes

186 bytes without the <?

<?$a=rand(1,6)+rand(1,6);$a%4==3?die("Natural: $a"):$a%12<4?die("Crapping out: $a"):print"Point: $a
";while(1){($b=rand(1,6)+rand(1,6))==7?die("Don't Pass"):$b==$a?die("Pass"):print"$b
";}

First attempt at code golf! Not sure if using </br> would be allowed though? As this would not work in a console (as a new line). Let me know if this is not allowed and will alter my code.

EDIT (16-8-16): After getting better at codegolf I noticed some possible improvements. This still works using the command line interface. Replaced </br> with an hard enter.

Jeroen

Posted 2015-10-22T20:54:37.267

Reputation: 210

Natural is spelt "Natural" and not "Naturel". – user41805 – 2015-10-27T12:08:47.510

Changed it. Thanks – Jeroen – 2015-10-27T12:26:01.270

2

Javascript 262

var r=(x=>Math.floor(Math.random()*6+1)),a=r()+r();if(a<4||a==12){alert("Crapping out: "+a)}else if(a==7||a==11){alert("Natural: "+a)}else{alert("Point: "+a);while(1){var b = r()+r();if(b==a){alert("pass");break}if(b==7){alert("dont't pass");break}alert(""+b)}}

user902383

Posted 2015-10-22T20:54:37.267

Reputation: 1 360

1

PowerShell, 181 183 179 178 167 165 bytes

-10 bytes thanks to mazzy
-2 bytes thanks to Xcali

switch -r($z=&($x={(random 6)+(random 6)+2})){'7|11'{"Natural: $z"}'2|3'{"Crapping out: $z"}default{"Point: $z"
do{($m=&$x)}until($m-in7,$z)"Don't "*!($m-7)+'Pass'}}

Try it online!

Unrolled version:

#Switch using regex on $z which is...
#&($x={...}) first assigns $x to a scriptblock then calls it, saving the return to $z
switch -r($z=&($x={(random 6)+(random 6)+2})){
    '7|11' {"Natural: $z"}
    '2|3' {"Crapping out: $z"}
    default{
        "Point: $z"

        #Call the diceroll scriptblock until you Pass,
        #while pushing each roll to output
        do{($m=&$x)}
        until($m-in7,$z)
        "Don't "*!($m-7)+'Pass'
    }
}

There's a few less sticking points now that the list-building logic has been rebuilt into a switch. I think it's still a pretty alright approach. +2 bytes fixing a bug.

Veskah

Posted 2015-10-22T20:54:37.267

Reputation: 3 580

1

awesome! shorten it up to 178 bytes

– mazzy – 2019-06-05T14:43:25.123

I think the condition -notin (7,$z) is not relevant tu the rule During the point round, the player must continuously roll ... the previous round. Now the loop finish when $m equals to 7 or the first round. – mazzy – 2019-06-05T15:57:12.953

1@mazzy That is a wording issue in the question. There's only two rounds. You set the Point only once in the Come-out round and that is your target number for the entire Point round. The previous round refers to the Come-out round – Veskah – 2019-06-05T16:17:33.953

1

thanks. 168 bytes

– mazzy – 2019-06-05T17:24:43.893

@mazzy Dang, I always forget about regex switches. Good stuff – Veskah – 2019-06-05T17:47:00.877

2You should be able to take two more off by removing the 1? from your craps regex. – Xcali – 2019-06-06T02:18:02.213

1

Perl 5, 140 bytes

sub d{1+int rand 6}say$"=($p=&d+&d)%12<4?"Crapping out":$p%4-3?Point:Natural,": $p";if($"gt O){say$_=&d+&d until/7|$p/;say"Don't "x/7/,Pass}

Try it online!

Xcali

Posted 2015-10-22T20:54:37.267

Reputation: 7 671

0

Pyth, 108 bytes

p|K?}J+OS6OS6,7 11"Natural"?}J[2 3 12)"Crapping out"k"Point"+": "JI!KW!}Z,7JIq7=Z
+OS6OS6=K"Don't "))+K"Pass

Try it online!

First pass, can probably find a few savings.

Sok

Posted 2015-10-22T20:54:37.267

Reputation: 5 592

0

Runic Enchantments, 151 bytes

R}}6'RA6'RA2++{{B͍
00B:7=S:b={+?\"Natural: "@>
pping out: "@\:2=}:3=}:c={{++?/"Cra
{:}≠   ?\ 6?;$$k\/ak$00B:$:7≠?\
"Don't "R"Pass"a/\$:$" :tnioP"\

Try it online!

After fixing a bug regarding random numbers (it was re-seeding every time 'RA was called, and the seed was system time, resulting in massive runs of repeated values) this works correctly.

Explanation

Entry is on the second line, as the first line up until is a function for rolling two dice and summing them.

Program flow, with some edge-wrapping and curled redirections unrolled for readability

   R}}6'RA6'RA2++{{B͍                      Roll 2, sum, return
   >00B:7=S:b={+?\                        Entry, make first roll, compare to 7 and 11.
                  "Natural: "@            If true, print "Natural: " and the value, else go down
                 \:2=}:3=}:c={{++?/       Compare to 2, 3, and 12.
"Crapping out: "@                         If true, print "Crapping out: " and the value, else go up
                     \$:$" :tnioP"\       Print "Point: " and value (IP is travelling RTL)
                     /ak$00B:$            Print newline, roll, print
:7≠?\                                     Compare to 7
    \"Don't "R"Pass"ak$$;                 If equal, print a newline and "Don't Pass"
     {:}≠   ?\                            Else compare to initial roll.
             R"Pass"ak$$;                 If equal, print a newline and "Pass"
              6?......ak$00B              Else return to roll loop by printing a newline
                                              and rolling again (. are skipped instructions)

There are only 4 NOP instructions ({:}≠...?\.6?) that would be very difficult to remove due to the space required on other lines (Namely the length of the "Don't " string).

Draco18s no longer trusts SE

Posted 2015-10-22T20:54:37.267

Reputation: 3 053

0

R, 197 bytes

 r=sum(sample(6,2,T));if(r%%12<4)cat("Crap Out",r)else if(r%%4==3)cat("Natural",r)else{cat("Point",r);while(T){cat("",q<-sum(sample(6,2,T)));if(q==7){cat(" Don't");break};if(q>r)break};cat(" Pass")}

Ungolfed

r=sum(sample(6,2,T))
if (r%%12<4)  {
    cat("Crap Out",r) 
} else if (r%%4==3) {
    cat("Natural",r)
} else { 
    cat("Point",r)
    while (T) {
        q = sum(sample(6,2,T))
        cat("",q)
        if (q==7) {
            cat(" Don't")
            break
        }
        if (q>r) break
    }
    cat(" Pass")
}

user5957401

Posted 2015-10-22T20:54:37.267

Reputation: 699