1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#!/usr/bin/perl
package Bot::Games::Game::24;
use Bot::Games::OO;
extends 'Bot::Games::Game';
has '+help' => (
default => '24 help',
);
has state => (
is => 'rw',
isa => 'Str',
);
has _solution => (
is => 'rw',
isa => 'Str',
);
sub _init {
my $self = shift;
return $self->_generate_24;
}
sub turn {
my $self = shift;
my ($player, $expr) = @_;
my $numbers = join ',', sort split(/[-\+\*\/\(\)]+/, $expr);
my $solution = join ',', sort split(' ', $self->state);
return "invalid numbers" unless $numbers eq $solution;
my $eval = $self->_evaluate($expr);
if ($eval == 24) {
$self->is_over("$player wins!");
return;
}
else {
return $eval;
}
}
sub give_up {
my $self = shift;
$self->is_over($self->_solution);
return;
}
my @ops = ('+', '-', '*', '/');
sub _generate_24 {
my $self = shift;
my @nums = (24);
for (1..3) {
my $index = int rand @nums;
my $val = $nums[$index];
redo unless $val =~ /\d/;
redo if $val < 4;
my $op = @ops[int rand @ops];
my $n1 = 2 + int rand($val - 3);
my $n2;
if ($op eq '+') {
$n2 = $val - $n1;
}
elsif ($op eq '-') {
$n1 += $val;
$n2 = $n1 - $val;
}
elsif ($op eq '*') {
$n2 = $val / $n1;
while ($n2 != int($n2)) {
$n1 = 2 + int rand($val - 3);
$n2 = $val / $n1;
}
}
elsif ($op eq '/') {
$n1 *= $val;
$n2 = $n1 / $val;
}
splice @nums, $index, 1, ('(', $n1, $op, $n2, ')');
}
pop @nums;
shift @nums;
$self->_solution(join '', @nums);
$self->state(join ' ', (grep { /\d/ } @nums));
return $self->state;
}
sub _evaluate {
my $self = shift;
my ($expr) = @_;
return 0 unless $expr =~ /^[-\d\+\*\/\(\)]+$/;
return eval $expr;
}
__PACKAGE__->meta->make_immutable;
no Bot::Games::OO;
1;
|