7 ###--------------------------------------------------------------------------
18 if ($max <= 255) { $nby = 1; $get = "C"; }
19 elsif ($max <= 65535) { $nby = 2; $get = "S"; }
20 else { $nby = 4; $get = "L"; }
22 my $lim = unpack $get, "\xff" x
$nby;
23 my $m = int $lim/$max;
25 do { $r = unpack $get, $me->bytes($nby); } while $r >= $thresh;
29 package Deal
::BufferedRandom
;
31 @ISA = qw(Deal
::Random
);
42 if ($n > length $me->{buf
}) {
43 my $want = ($n + 4095 - length $me->{buf
})&-4096;
45 my $more = $me->fetch($want);
46 $want -= length $more;
51 my $chunk = substr $me->{buf
}, 0, $n;
52 $me->{buf
} = substr $me->{buf
}, $n;
56 package Deal
::SysRandom
;
58 @ISA = qw(Deal
::BufferedRandom
);
69 open my $rand, "/dev/urandom" or die "open (/dev/urandom): $!";
76 defined (read $me->{rand}, my $more, $want)
77 or die "read (/dev/urandom): $!";
81 package Deal
::SeedRandom
;
83 use Digest
::SHA
qw(sha256
);
85 @ISA = qw(Deal
::BufferedRandom
);
88 my ($pkg, @args) = @_;
101 my ($me, $want) = @_;
102 return sha256
(pack "La*", $me->{i
}++, $me->{seed
});
105 ###--------------------------------------------------------------------------
110 our $RAND = Deal
::SysRandom
->new;
115 for (my $i = 0; $i < $n - 1; $i++) {
116 my $k = $i + $r->range($n - $i);
117 ($x[$i], $x[$k]) = ($x[$k], $x[$i]);
122 our @LINE; $LINE[$_] = $_%4 + 1 for 0..51;
124 sub line
() { return shuffle
$RAND, @LINE; }
126 ###--------------------------------------------------------------------------
127 ### Generating hands for study.
129 our @RANK = ("A", "K", "Q", "J", "10", "9",
130 "8", "7", "6", "5", "4", "3", "2");
131 our @SUIT = ("C", "D", "H", "S");
133 for (my $r = 0; $r < @RANK; $r++)
134 { for my $s (@SUIT) { push @DECK, [$s, $r]; } }
136 our @SEAT = ("N", "W", "S", "E");
137 our @VULN = ("None", "N/S", "E/W", "All");
139 our %HCP = ("A" => 4, "K" => 3, "Q" => 2, "J" => 1);
145 ## Work out the cards and sort them into suits.
146 for my $s (@SUIT) { $card{$s} = []; }
147 for my $c (@cards) { push @
{$card{$c->[0]}}, $c->[1]; }
149 @
{$card{$s}} = map { $RANK[$_] } sort { $a <=> $b } @
{$card{$s}};
152 ## Count the high-card points and losers.
156 my @c = @
{$card{$s}};
158 my %c = map { $_ => 1 } @c;
159 for my $i (keys %HCP) { $hcp += $HCP{$i} if $c{$i}; }
160 for my $i ("A", "K", "Q") {
162 $ltc++ unless $c{$i};
167 return { %card, ltc
=> $ltc, hcp
=> $hcp };
172 $deal->{seed
} //= lc(MIME
::Base32
::encode
($RAND->bytes(16)));
173 my $r = Deal
::SeedRandom
->new($deal->{seed
});
174 my @cards = shuffle
$r, @DECK;
175 for my $s (@SEAT) { $deal->{$s} = hand
splice @cards, 0, 13; }
176 $deal->{dealer
} //= $r->range(4);
177 $deal->{vuln
} //= $r->range(4);
182 ###----- That's all, folks --------------------------------------------------