File Coverage

blib/lib/Games/Cellulo/Game/Particle.pm
Criterion Covered Total %
statement 18 77 23.3
branch 0 32 0.0
condition n/a
subroutine 6 21 28.5
pod 0 8 0.0
total 24 138 17.3


line stmt bran cond sub pod time code
1             package Games::Cellulo::Game::Particle;
2             $Games::Cellulo::Game::Particle::VERSION = '0.2_01';
3 1     1   4 use strict;
  1         1  
  1         27  
4 1     1   3 use warnings FATAL => 'all';
  1         1  
  1         37  
5              
6 1     1   3 use Moo;
  1         1  
  1         6  
7 1     1   818 use Term::ANSIColor;
  1         4266  
  1         72  
8 1     1   7 use List::Util qw[ min ];
  1         1  
  1         83  
9              
10             use constant {
11 1         823 R => 1,
12             B => 2,
13             G => 3,
14             Y => 4,
15 1     1   4 };
  1         1  
16             has x => ( is => 'rw', required => 1 );
17             has y => ( is => 'rw', required => 1 );
18             has type => ( is => 'rw', required => 1 );
19              
20             has xdir => ( is => 'lazy', clearer => 1 );
21             has ydir => ( is => 'lazy', clearer => 1 );
22             has char => ( is => 'lazy', clearer => 1 );
23              
24             sub _build_xdir {
25 0     0     for( $_[0]->type ) {
26 0 0         return -1 if $_ eq R;
27 0 0         return 1 if $_ eq B;
28 0           return 0;
29             }
30             }
31              
32             sub _build_ydir {
33 0     0     for ( $_[0]->type ) {
34 0 0         return -1 if $_ eq G;
35 0 0         return 1 if $_ eq Y;
36 0           return 0;
37             }
38             }
39              
40             has dir => (
41             is => 'lazy',
42             );
43              
44             sub _build_dir {
45 0     0     return [ $_[0]->xdir,$_->[0]->ydir ];
46             }
47             sub _cc {
48 0     0     my($color,$str) = @_;
49 0           colored($str,$color);
50             }
51              
52             sub _build_char {
53 0     0     my $self = shift;
54 0 0         return _cc( 'blue', 'o' ) if $self->type eq B;
55 0 0         return _cc( 'red', 'o' ) if $self->type eq R;
56 0 0         return _cc( 'green', 'o' ) if $self->type eq G;
57 0 0         return _cc( 'yellow', 'o' ) if $self->type eq Y;
58             }
59              
60              
61              
62              
63             sub move {
64 0     0 0   my $self = shift;
65 0           my $wantx = $self->xpos( $self->x + $self->xdir );
66 0           my $wanty = $self->ypos( $self->y + $self->ydir );
67 0           $self->x( $wantx );
68 0           $self->y( $wanty );
69             }
70              
71             my @possible_directions = (
72             "-1,-1", "-1,0", "-1,1",
73             "0,-1", "0,1", #skip 0,0, its a noop
74             "1,-1", "1,0", "1,1",
75             );
76              
77             my @possible_direction_refs = map { [ split ',', $_ ] } @possible_directions;
78             has tries_in_direction => (
79             is => 'ro',
80             default => sub { +{
81             map { $_ => 0 } @possible_directions
82             };
83             }
84             );
85              
86             has successes_in_direction => (
87             is => 'ro',
88             default => sub { +{
89             map { $_ => 0 } @possible_directions
90             };
91             }
92             );
93              
94             has num_avoid_tries => (
95             is => 'rw',
96             default => sub { 0 },
97             );
98              
99             has num_successes => (
100             is => 'rw',
101             default => sub { 0 },
102             );
103              
104             sub p_found_free_path {
105 0     0 0   my $self = shift;
106 0           my $num_tries = $self->num_avoid_tries;
107 0           my $num_successes = $self->num_successes;
108 0 0         return .5 unless $num_successes;
109 0           return $num_tries / $num_successes;
110             }
111              
112             sub p_went_in_direction {
113 0     0 0   my( $self, $direction ) = @_;
114 0           my $num_tries_in_direction = $self->tries_in_direction->{$direction};
115 0           my $num_tries = $self->num_avoid_tries;
116 0 0         return .5 unless $num_tries;
117 0           return $num_tries_in_direction / $num_tries;
118             }
119              
120             sub p_found_free_path_went_in_direction_x {
121 0     0 0   my( $self, $direction ) = @_;
122 0           my $num_avoid_successes = $self->num_successes;
123 0           my $num_avoid_successes_in_direction = $self->successes_in_direction->{$direction};
124 0 0         return .5 unless $num_avoid_successes;
125 0           return $num_avoid_successes_in_direction / $num_avoid_successes;
126             }
127             sub p_went_in_direction_x_found_free_path {
128 0     0 0   my( $self, $direction ) = @_;
129 0           my $p_found_free_path = $self->p_found_free_path;
130 0           my $p_went_in_direction = $self->p_went_in_direction( $direction );
131 0           my $p_found_free_path_went_in_direction_x = $self->p_found_free_path_went_in_direction_x( $direction );
132 0 0         return .5 unless $p_found_free_path;
133 0 0         return .5 unless $p_found_free_path_went_in_direction_x;
134 0 0         return .5 unless $p_went_in_direction;
135 0           return ( $p_found_free_path_went_in_direction_x * $p_went_in_direction ) / $p_found_free_path;
136              
137             }
138             sub avoidx {
139 0     0 0   my $self = shift;
140             # return 0 if $self->xdir;
141 0           int( rand(3) ) - 1;
142             }
143              
144             sub avoidy {
145 0     0 0   my $self = shift;
146             # return 0 if $self->ydir;
147 0           int( rand(3) ) - 1;
148             }
149              
150             has initial_avoidx => ( is => 'lazy' );
151             has initial_avoidy => ( is => 'lazy' );
152              
153 0     0     sub _build_initial_avoidx { shift->avoidy }
154 0     0     sub _build_initial_avoidy { shift->avoidx }
155              
156             sub avoid_dir {
157 0     0 0   my $self = shift;
158             # return [ $_->avoidx, $_->avoidy ];
159 0           my @p = map { $self->p_went_in_direction_x_found_free_path( $_ ) } @possible_directions;
  0            
160 0           my $min = min @p;
161 0           my @possibles;
162 0           for( my $i = 0; $i < @p; $i++) {
163 0 0         push @possibles, $possible_direction_refs[$i] if $p[$i] == $min;
164             }
165 0 0         return $possibles[ int( rand( @possibles ) ) ] if @possibles;
166 0           return;
167             }
168              
169             1;
170             __END__