Go Fish/Raku: Difference between revisions
Content added Content deleted
m (remove unneeded parens and 'do') |
Thundergnat (talk | contribs) (→{{header|Perl 6}}: Update to work with modern Rakudo) |
||
Line 1: | Line 1: | ||
{{collection|Go Fish}} |
{{collection|Go Fish}} |
||
{{works with|Rakudo| |
{{works with|Rakudo|2017.02}} |
||
<lang perl6>constant BOOKSIZE = 4; |
<lang perl6>constant BOOKSIZE = 4; |
||
constant HANDSIZE = 9; |
constant HANDSIZE = 9; |
||
constant |
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 |
constant @piparticles = <a a a a a a an a a a a a an>; |
||
constant |
constant @ppips = <deuces threes fours fives sixes sevens eights nines tens jacks queens kings aces>; |
||
constant |
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 |
$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 } |
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 |
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 |
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 |
method new ( $cpu, @deck ) { |
||
my |
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, |
||
know => ($cpu ?? map { Knowledge.new() }, @pips !! ()) |
know => ($cpu ?? map { Knowledge.new() }, @pips !! ()) |
||
); |
); |
||
Line 111: | Line 112: | ||
} |
} |
||
method getcards (Int $quantity, |
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 ( |
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 ( |
method learn ($pip, Maybe $m) { @.know[$pip].set($m) } |
||
method notice_draw () { .incr for @.know } |
method notice_draw () { .incr for @.know } |
||
method choose_request () |
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 |
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 |
@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 |
@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 |
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 = |
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 { |