File Coverage

blib/lib/Games/Solitaire/BlackHole/Solver/Golf/App.pm
Criterion Covered Total %
statement 49 56 87.5
branch 11 18 61.1
condition 1 3 33.3
subroutine 4 4 100.0
pod 1 1 100.0
total 66 82 80.4


line stmt bran cond sub pod time code
1             package Games::Solitaire::BlackHole::Solver::Golf::App;
2             $Games::Solitaire::BlackHole::Solver::Golf::App::VERSION = '0.18.0';
3 2     2   270653 use 5.014;
  2         9  
4 2     2   1435 use Moo;
  2         18522  
  2         11  
5              
6             extends('Games::Solitaire::BlackHole::Solver::App::Base');
7 2     2   4360 use Games::Solitaire::BlackHole::Solver::App::Base qw/ $card_re /;
  2         9  
  2         1637  
8              
9              
10             sub run
11             {
12 1     1 1 4960 my $self = shift;
13 1         11 my $RANK_KING = $self->_RANK_KING;
14              
15             # A boolean
16 1         3 my $place_queens_on_kings = '';
17              
18             # A boolean
19 1         2 my $wrap_ranks = '';
20 1         15 $self->_process_cmd_line(
21             {
22             extra_flags => {
23             "queens-on-kings!" => \$place_queens_on_kings,
24             "wrap-ranks!" => \$wrap_ranks,
25             }
26             }
27             );
28 1 50       7 if ($wrap_ranks)
29             {
30 0         0 $place_queens_on_kings = 1;
31             }
32 1         9 $self->_calc_lines( shift(@ARGV), );
33              
34 1         2 my $talon_line = shift( @{ $self->_board_lines } );
  1         5  
35 1         3 my @talon_values;
36 1         2 my $talon_ptr = 0;
37 1 50       69 if ( my ($cards) = $talon_line =~ m{\ATalon:((?: $card_re){16})\z} )
38             {
39 16         41 @talon_values = map { $self->_get_rank($_) }
40 1         3 @{ $self->_talon_cards( [ $cards =~ /($card_re)/g ] ) };
  1         67  
41             }
42             else
43             {
44 0         0 die "Could not match first talon line!";
45             }
46              
47 1 50       13 $self->_set_up_solver( $talon_ptr,
48             [ 1, ( $wrap_ranks ? ($RANK_KING) : () ) ] );
49              
50 1         2 my $positions = $self->_positions;
51 1         8 my $board_values = $self->_board_values;
52              
53 1         2 my $verdict = 0;
54              
55 1         6 $self->_next_task;
56              
57             QUEUE_LOOP:
58 1         5 while ( my $state = $self->_get_next_state_wrapper )
59             {
60             # The foundation
61 953         1443 my $fnd = vec( $state, 0, 8 );
62 953         1246 my $no_cards = 1;
63 953         1230 my $tln = vec( $state, 1, 8 );
64 953         1346 my @sub_queue;
65              
66             my @_pending;
67              
68 953 50 33     1917 if ( $place_queens_on_kings || ( $fnd != $RANK_KING ) )
69             {
70 953         1899 $self->_find_moves( \@sub_queue, $state, \$no_cards );
71             }
72             else
73             {
74             COL:
75 0         0 foreach my $col_idx ( keys @$board_values )
76             {
77 0         0 my $pos = vec( $state, 4 + $col_idx, 4 );
78              
79 0 0       0 if ($pos)
80             {
81 0         0 $no_cards = 0;
82 0         0 last COL;
83             }
84             }
85             }
86              
87 953 100       1821 if ($no_cards)
88             {
89 1         32 $self->_trace_solution( $state, );
90 1         2 $verdict = 1;
91 1         2 last QUEUE_LOOP;
92             }
93              
94 952 100       1658 if ( $tln < @talon_values )
95             {
96 833         1178 my $next_s = $state;
97 833         1630 vec( $next_s, 0, 8 ) = $talon_values[$tln];
98 833         1637 ++vec( $next_s, 1, 8 );
99 833 100       1716 if ( !exists( $positions->{$next_s} ) )
100             {
101 586         1851 $positions->{$next_s} =
102             [ $state, scalar(@$board_values), 1, 0 ];
103 586         1407 push @_pending, [ $next_s, 0 ];
104             }
105             }
106              
107             # Give preference to non-talon moves
108 952         1528 push @_pending, @sub_queue;
109             last QUEUE_LOOP
110 952 50       2050 if not $self->_process_pending_items( \@_pending, $state );
111             }
112              
113 1         9 return $self->_my_exit( $verdict, );
114             }
115              
116              
117             1;
118              
119             __END__