Go Fish/Raku: Difference between revisions

Content added Content deleted
m (remove unneeded parens and 'do')
(→‎{{header|Perl 6}}: Update to work with modern Rakudo)
Line 1: Line 1:
{{collection|Go Fish}}
{{collection|Go Fish}}


{{works with|Rakudo|#23 "Lisbon"}}
{{works with|Rakudo|2017.02}}


<lang perl6>constant BOOKSIZE = 4;
<lang perl6>constant BOOKSIZE = 4;
constant HANDSIZE = 9;
constant HANDSIZE = 9;
constant Str @pips = <two three four five six seven eight nine ten jack queen king ace>;
constant @pips = <two three four five six seven eight nine ten jack queen king ace>;
# The elements of @pips are only names. Pips are represented internally
# The elements of @pips are only names. Pips are represented internally
# as indices of this array.
# as indices of this array.
constant Str @piparticles = <a a a a a a an a a a a a an>;
constant @piparticles = <a a a a a a an a a a a a an>;
constant Str @ppips = <deuces threes fours fives sixes sevens eights nines tens jacks queens kings aces>;
constant @ppips = <deuces threes fours fives sixes sevens eights nines tens jacks queens kings aces>;
constant Str @shortpips = <2 3 4 5 6 7 8 9 T J Q K A>;
constant @shortpips = <2 3 4 5 6 7 8 9 T J Q K A>;
constant $foe_nominative_pronoun = pick 1, <he she it e xe>;
constant $foe_nominative_pronoun = pick 1, <he she it e xe>;


Line 21: Line 21:
sub find ($x, *@a) {
sub find ($x, *@a) {
for @a.kv -> $k, $v {
for @a.kv -> $k, $v {
$v eqv $x and return $k;
$v eq $x and return $k;
}
}
fail 'Not found';
fail 'Not found';
Line 28: Line 28:
sub maxes (&f, *@a) {
sub maxes (&f, *@a) {
my $x = [max] map &f, @a;
my $x = [max] map &f, @a;
return grep { f($^e) eqv $x }, @a;
return @a.grep: { f($^e) eqv $x };
}
}


Line 43: Line 43:
loop {
loop {
print 'For what do you ask? (', join(', ', @shortpips[@choices]), '): ';
print 'For what do you ask? (', join(', ', @shortpips[@choices]), '): ';
my $in = substr uc($*IN.get or next), 0, 1;
my $in = substr ($*IN.get.uc or next), 0, 1;

my $pip = find $in, @shortpips;
my $pip = find $in, @shortpips;
if defined $pip {
if defined $pip {
Line 75: Line 76:


class Player {
class Player {
has Int @.h;
has @.h;
# @h[$n] is number of cards of pip $n in this player's hand.
# @h[$n] is number of cards of pip $n in this player's hand.
has $.deck;
has $.deck;
Line 83: Line 84:
has Knowledge @.know;
has Knowledge @.know;


method new ($cpu, @deck is rw) {
method new ( $cpu, @deck ) {
my Int @h = 0 xx @pips;
my @h = 0 xx @pips;
++@h[$_] for @deck[^HANDSIZE];
++@h[$_] for @deck[^HANDSIZE];
@deck = @deck[HANDSIZE ..^ @deck];
@deck = @deck[HANDSIZE ..^ @deck];
Player.bless(*,
Player.bless(
h => @h, cpu => $cpu,
h => @h, cpu => $cpu,
deck => \@deck,
deck => @deck,
know => ($cpu ?? map { Knowledge.new() }, @pips !! ())
know => ($cpu ?? map { Knowledge.new() }, @pips !! ())
);
);
Line 111: Line 112:
}
}


method getcards (Int $quantity, Int $pip) {
method getcards (Int $quantity, $pip) {
@!h[$pip] += $quantity;
@!h[$pip] += $quantity;
@.h[$pip] == BOOKSIZE or return;
@.h[$pip] == BOOKSIZE or return;
Line 123: Line 124:
}
}


method losecards (Int $pip) {
method losecards ($pip) {
@.h[$pip] = 0;
@.h[$pip] = 0;
while none @.h and $.deck.elems {
while none @.h and $.deck.elems {
Line 133: Line 134:
}
}


method learn (Int $pip, Maybe $m) { @.know[$pip].set($m) }
method learn ($pip, Maybe $m) { @.know[$pip].set($m) }


method notice_draw () { .incr for @.know }
method notice_draw () { .incr for @.know }


method choose_request () returns Int {
method choose_request () {
#self.showhand;
#self.showhand;
#say 'Know: ', join ', ', map
#say 'Know: ', join ', ', map
Line 143: Line 144:
# @.know;
# @.know;
my @ps = map { .key }, grep { .value }, pairs @.h;
my @ps = map { .key }, grep { .value }, pairs @.h;

return pick 1, maxes { @.h[$^p] }, do
return ( maxes { @.h[$^p] },
# Most of all we should ask for cards we know the
# Most of all we should ask for cards we know the
# user has.
# user has.
grep { @.know[$^p].maybe ~~ Yes }, @ps or
@ps.grep({ @.know[$^p].maybe ~~ Yes }).flat ||
# Then try asking for one we haven't requested
# Then try asking for one we haven't requested
# before.
# before.
grep { @.know[$^p].maybe ~~ Dunno }, @ps or
@ps.grep({ @.know[$^p].maybe ~~ Dunno }).flat ||
# Then try asking for one we least recently
# Then try asking for one we least recently
# asked about.
# asked about.
maxes { @.know[$^p].n }, @ps;
maxes { @.know[$^p].n }, @ps ).roll;
}
}
}
}
Line 158: Line 160:
sub play () {
sub play () {


my Int @deck;
my @deck;
# Shuffle the deck until the first two hands contain no books.
# Shuffle the deck until the first two hands contain no books.
# (If BOOKSIZE is greater than 2 and HANDSIZE is reasonably
# (If BOOKSIZE is greater than 2 and HANDSIZE is reasonably
# small, this'll probably take only one shuffle.)
# small, this'll probably take only one shuffle.)
repeat { @deck = pick *, ^@pips xx BOOKSIZE }
repeat { @deck = (flat ^@pips xx BOOKSIZE).pick(*) }
until none(map { count $^x, @deck[^HANDSIZE] }, ^@pips) >= BOOKSIZE and
until none(map { count $^x, @deck[^HANDSIZE] }, ^@pips) >= BOOKSIZE and
none(map { count $^x, @deck[HANDSIZE ..^ 2*HANDSIZE] }, ^@pips) >= BOOKSIZE;
none(map { count $^x, @deck[HANDSIZE ..^ 2*HANDSIZE] }, ^@pips) >= BOOKSIZE;
Line 168: Line 170:
my Player $user .= new(False, @deck);
my Player $user .= new(False, @deck);
my Player $foe .= new(True, @deck);
my Player $foe .= new(True, @deck);

while any |$user.h or any |$foe.h {
while any |$user.h or any |$foe.h {

# The user goes first.
# The user goes first.
while any |$user.h {
while any |$user.h {