17
\$\begingroup\$

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.)

\$\endgroup\$
2
  • \$\begingroup\$ 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]? \$\endgroup\$
    – user45941
    Aug 16, 2016 at 8:28
  • \$\begingroup\$ @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. \$\endgroup\$ Aug 16, 2016 at 15:30

11 Answers 11

6
\$\begingroup\$

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")
\$\endgroup\$
1
  • \$\begingroup\$ Love the way how you check for the remainder instead for 2,3,7,11 or 12 seperatly! \$\endgroup\$
    – Jeroen
    Oct 27, 2015 at 12:08
5
\$\begingroup\$

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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Care to explain how you got that magic number and how it works? \$\endgroup\$
    – Karl Napf
    Aug 16, 2016 at 8:44
4
\$\begingroup\$

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.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ As long as it compiles somewhere, you're good. \$\endgroup\$
    – lirtosiast
    Oct 24, 2015 at 4:13
  • \$\begingroup\$ @Mego thanks for pointing that out, that managed to get rid of 19 bytes. \$\endgroup\$ Oct 25, 2015 at 23:11
  • \$\begingroup\$ Got some more off getting rid of a and b and also using the subtraction method along with ternary operators. \$\endgroup\$ Oct 26, 2015 at 2:42
4
\$\begingroup\$

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!

\$\endgroup\$
6
  • \$\begingroup\$ 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. \$\endgroup\$ Oct 22, 2015 at 21:37
  • \$\begingroup\$ Whoops! Fixed not printing 'Point: #'. In the output, there is a space. \$\endgroup\$
    – Celeo
    Oct 22, 2015 at 21:43
  • \$\begingroup\$ Ah OK. I don't use Python very much anymore so I was uncertain about how the ,a works. \$\endgroup\$ Oct 22, 2015 at 21:43
  • \$\begingroup\$ 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? \$\endgroup\$
    – lirtosiast
    Oct 23, 2015 at 2:28
  • \$\begingroup\$ @ThomasKwa If you put a bunch of work into it, post as a separate answer so you can get some rep for it. \$\endgroup\$
    – Celeo
    Oct 23, 2015 at 15:37
3
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ Natural is spelt "Natural" and not "Naturel". \$\endgroup\$
    – user41805
    Oct 27, 2015 at 12:08
  • \$\begingroup\$ Changed it. Thanks \$\endgroup\$
    – Jeroen
    Oct 27, 2015 at 12:26
2
\$\begingroup\$

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)}}
\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ awesome! shorten it up to 178 bytes \$\endgroup\$
    – mazzy
    Jun 5, 2019 at 14:43
  • \$\begingroup\$ 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. \$\endgroup\$
    – mazzy
    Jun 5, 2019 at 15:57
  • 1
    \$\begingroup\$ @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 \$\endgroup\$
    – Veskah
    Jun 5, 2019 at 16:17
  • 1
    \$\begingroup\$ thanks. 168 bytes \$\endgroup\$
    – mazzy
    Jun 5, 2019 at 17:24
  • 2
    \$\begingroup\$ You should be able to take two more off by removing the 1? from your craps regex. \$\endgroup\$
    – Xcali
    Jun 6, 2019 at 2:18
0
\$\begingroup\$

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")
}
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.