in reply to check my logic & a random number issue
The reason I think something is wrong, is because when I simulated just 100 trials, there were a number of identical net win/loss results that occured twice. Is my logic, or random number generation the problem?
Other than just eyeballing the results, what statistical analyses have you performed? Have you checked that your average dice roll is 7? When I added code in to print the average dice roll, I noticed that there's a condition that you haven't covered.
if ($roll == $point)
{
$gameover = 1;
if ($roll == 6 || $roll == 8)
{
$gameover = 1; #not necessary
$winnings += 1.2 + 1;
print "WIN $winnings\n";
}
elsif ($roll == 5 || $roll == 9)
{
$gameover = 1; # not necessary
$winnings += 1.5 + 1;
print "WIN $winnings\n";
}
elsif ($roll == 4 || $roll == 10)
{
$gameover = 1; # not necessary
$winnings += 2 + 1;
print "WIN $winnings\n";
}
else
{
print "what happens here?"; # loss? draw?
}
}
Because you put $gameover = 1 at the start of that conditional block you don't need to continue to do so for each specific condition. Unless, of course, you had intended to remove that first $gameover = 1.
Is it these kind of pairs that are bothering you?
LOSE -1
average dice roll: 7
LOSE -1
average dice roll: 8
LOSE -2
average dice roll: 7
LOSE -2
average dice roll: 7
LOSE -1
average dice roll: 7
LOSE -1
average dice roll: 7
because chances are high that these are just statistical fluctuations. If you look at the dice rolls that generate these losses you'll find that they're all different. The game of craps may just be weighted to encourage losses. ;)
You'll notice that 8 in my average dice roll. This is a running average and those 5 losses just happened to be results 5 - 10 of a simulation. The average ought to stay around 7 but will fluctuate around it through about 3 standard errors. ;)
So, in conclusion, yes there is a logic error in your code, your game occasionally ends without setting wins or losses. Had you kept a total of games played you might have spotted this. Whether or not your random number generator is non-random or your use of it is flawed can only really be determined by analysing it in the same using something similar to what dws suggested.
Your logic may contain other errors but as I've never studied the game of craps I have no idea what the frequency of certain results should be. Should you lose more often than you win, but win bigger? Should you lose 1 unit twice as often as you lose 2 units? I'm 100% certain that there are statistic tables out there for this game just as there are for other casino games. Once you have that data, you'll be able to analyse your results better and check whether they're in line with what they should be.
Hope it helps
jarich
PS: for the interests of simplifying your code, you can easily drop the database stuff.
PPS: FWIW in the interests of not installing more stuff, my roll function came out to be:
sub rolldice()
{
# was: my $roll = int(rand(12)) + 1;
my $d1 = int(rand(6)) + 1;
my $d2 = int(rand(6)) + 1;
my $roll = $d1 + $d2;
return $roll;
}
Update: Didn't think hard enough about my rolldice function. Fixed now.
Re: Re: check my logic & a random number issue
by blahblahblah (Priest) on Oct 11, 2002 at 04:15 UTC
|
While it can't hurt to add the "else... what happens here" block that you suggest for checking errors, I don't think it would ever be reached. All of that code is inside a block where $roll == $point. If $point is ever set to anything other than 4,5,6,8,9,10, the game is over on the first roll.
Another thing you might want to do is round the winnings down for each game. I'm pretty sure that's what the casinos do. And maybe make the minimum bet something more typical, like $5. In addition to making it more realistic, these two things combined might make the results very different than a simple $1 bet with no rounding. I don't feel like doing the math, though, so that's just a gut feeling.
When I've played I've won a lot by betting the minimum on the pass line and then doubling the minimum for the odds. Watch out for those bets in the middle -- they're not worth it! | [reply] |
|
Very good catch.
My modifications to the code changed the way it worked and therefore the responses I got. My roll function allowed "1" to be returned, which ought to be impossible (with two dice). A mistake I made when making my version strict compliant prevented this mistake from showing up in my version, so I assumed it was a bug in the original code (using my roll function though).
In which case I can't see any logic errors in the code (except perhaps for not validating the roll dice value and catching errors that shouldn't happen in that extra else statement).
What I said about doing proper statistical analyses is still valid. ;)
Oh, and don't take the fact that I made mistakes in a quick and dirty strict compliancy conversion to be an argument for not using strict. ;) This (as well as formatting) was sorely missed in the original version of this code.
jarich
| [reply] |
Re: Re: check my logic & a random number issue
by Daruma (Curate) on Oct 11, 2002 at 05:19 UTC
|
Greetings!!
PPS: FWIW in the interests of not installing more stuff, my roll function came out to be:
sub rolldice()
{
my $roll = int(rand(12)) + 1;
return $roll;
}
After reading your node, jarich, I began wondering how different Math::Random, int(rand(6)) and int(rand(12)) might be... I noted your suggested rolldice() subroutine quoted above. To appropriately spread the roll result to mimic a table craps game, there should be a curve peaking at seven. I decided to slap together a quick test...
#!c:\perl\bin\perl.exe
use strict;
use warnings;
use diagnostics;
use Math::Random;
my $num_rolls = 10000;
my @rollhashes;
for (my $i=0; $i<4; $i++) {
$rollhashes[$i] = { 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0,
7 => 0, 8 => 0, 9 => 0, 10 => 0, 11 => 0, 12 => 0
};
}
for (1 .. $num_rolls) {
my $m1 = random_uniform_integer(1,1,6);
my $m2 = random_uniform_integer(1,1,6);
my $math = $m1 + $m2;
$rollhashes[2]{$math}++;
my $m0 = random_uniform_integer(2,1,12);
$rollhashes[0]{$m0}++;
my $r1 = (int(rand(6) + 1));
my $r2 = (int(rand(6) + 1));
my $rand = $r1 + $r2;
$rollhashes[3]{$rand}++;
my $r0 = (int(rand(12) + 2));
$rollhashes[1]{$r0}++;
}
print "\nUSING TWO DICE:\n";
print "\nMath::Random\t\tint(rand)\n";
for (my $i = 2; $i <= 12; $i++) {
my $n = sprintf("%02d",$i);
print "$n = $rollhashes[2]{$i}\t\t$n = $rollhashes[3]{$i}\n";
}
print "\nUSING ONE DIE:\n";
print "\nMath::Random\t\tint(rand)\n";
for (my $i = 2; $i <= 12; $i++) {
my $n = sprintf("%02d",$i);
print "$n = $rollhashes[0]{$i}\t\t$n = $rollhashes[1]{$i}\n";
}
And here is the output:
USING TWO DICE:
Math::Random int(rand)
02 = 271 02 = 270
03 = 533 03 = 606
04 = 876 04 = 849
05 = 1129 05 = 1172
06 = 1364 06 = 1362
07 = 1640 07 = 1632
08 = 1390 08 = 1402
09 = 1101 09 = 1079
10 = 876 10 = 838
11 = 540 11 = 535
12 = 280 12 = 255
USING ONE DIE:
Math::Random int(rand)
02 = 862 02 = 852
03 = 853 03 = 835
04 = 795 04 = 865
05 = 849 05 = 876
06 = 817 06 = 772
07 = 801 07 = 836
08 = 822 08 = 801
09 = 809 09 = 814
10 = 856 10 = 821
11 = 891 11 = 841
12 = 823 12 = 848
So, using one die rather than two has a tremendous impact on the spread of the numbers! Additionally, I noted that the differences between using Math::Random and int(rand(6)) were fairly slight. After running the above code over numerous tests, I found them to be quite comparable. In the interest of not installing more than is necessary, I would go with the int(rand(6)) rather than slurping in the Math::Random goodies.
Craps is my favorite Vegas game... I find it to be the most fun and exciting of all the games I've tried. (Probably more fun than it should be!)
-Daruma
Update: formatting changes and fixed reference to jarich's rand(12) usage... Thanks, jarich!!
Update2:Reworked my unnecessarily long code with a few loops... | [reply] [d/l] [select] |
|
You're quite right. When you use a single dice (twelve sided) the probability of getting any number (1 to 12 inclusive) is just 1/12. When you use two dices of 6 sides each the probability of each number is markedly different.
Value Probability Combinations
1 0
2 1/36 1:1
3 2/36 1:2, 2:1
4 3/36 1:3, 2:2, 3,1
5 4/36 1:4, 2:3, 3:2, 4:1
6 5/36 1:5, 2:4, 3:3, 4:2, 5:1
7 6/36 1:6, 2:5, 3:4, 4:3, 5:2, 6:1
8 5/36 2:6, 3:5, 4:4, 5:3, 6:2
9 4/36 3:6, 4:5, 5:4, 6:3
10 3/36 4:6, 5:5, 6:4
11 2/36 5:6, 6:5
12 1/36 6:6
Of course, if you're not using a truely random or very, very convincing pseudo-random generator you probably won't quite get these probabilities.
Considering that 7 is a bad number to get in Craps, it'd be nicer to use just a 12 sided dice, but then the Casinos would have to rig the game another way to get their money. ;)
It's good to know that for this kind of example rand() is as good as Math::Random.
jarich | [reply] [d/l] |
|
If you look at the dice rolls that generate these losses you'll find that they're all different.
Jarich: I think that explains the issue I was seeing. You can lose with a craps roll on the come out roll, and then win the next round with a winning odds bet on a 6 OR a winning odds bet on an 8, and the net win will still be the same. Basically different roll combinations are likely to yield the same net win/loss result. I'm sure I'll find some to be fairly common.
Daruma: Thanks for putting up the results of Math::Random vs. int(rand). When you look at the probabilities of the various outcomes, and compare them with the actual real-life probabilities, although they both have fairly normal distributions, the Math::Random yields a better result.
Math::Random int(rand)
roll occ prob roll occ prob
2 271 2.71% 2 270 2.70%
3 533 5.33% 3 606 6.06%
4 876 8.76% 4 849 8.49%
5 1129 11.29% 5 1172 11.72%
6 1364 13.64% 6 1362 13.62%
7 1640 16.40% 7 1632 16.32%
8 1390 13.90% 8 1402 14.02%
9 1101 11.01% 9 1079 10.79%
10 876 8.76% 10 838 8.38%
11 540 5.40% 11 535 5.35%
12 280 2.80% 12 255 2.55%
real life
roll prob
1 2.78%
3 5.56%
4 8.33%
5 11.11%
6 13.89%
7 16.67%
8 13.89%
9 11.11%
10 8.33%
11 5.56%
12 2.78%
Thanks for all the help so far. Now I guess it comes down to a random number issue. Are there any perl modules, or different techniques I can use to get the rolls as random and close to real-life as possible, or is Math::Random likely as good as it will get?
Thanks for the continued help! | [reply] [d/l] |
|
|