@@ -3,7 +3,7 @@ use strict;
use warnings;

use Test::More;
use AI::Pathfinding::OptimizeMultiple::App::CmdLine;
use AI::Pathfinding::OptimizeMultiple::App::CmdLine ();

use vars qw($trap);

@@ -9,9 +9,9 @@ use Test::More tests => 4;

use Test::Differences qw(eq_or_diff);

use PDL;
use PDL (qw/ pdl /);

use AI::Pathfinding::OptimizeMultiple;
use AI::Pathfinding::OptimizeMultiple ();

# TEST:$c=0;
sub test_based_on_data
@@ -1,7 +1,28 @@
Revision history for Games-Solitaire-Verify

0.2101 Unknown
0.2302 2020-04-20
- Try to Fix "You tried to plan twice" error in t/exception-newline.t .
- https://github.com/shlomif/fc-solve/issues/39
- Thanks to SREZIC !

0.2301 2020-04-20
- Emit trailing newline in Exception::Class errors so the shell
will not swallow them, and instead display them.

0.2300 2020-03-06
- Avoid implicit symbol imports
- https://perl-begin.org/tutorials/bad-elements/#non_explicitly_imported_symbols
- Convert weaver.ini to @SHLOMIF .

0.2202 2019-07-19
- Add --help flag.

0.2201 2019-05-19
- Add tests for some Golf variants.

0.2200 2019-05-15
- Add POD to lib/Games/Solitaire/Verify/HorneAutomovePrune.pm .
- Add support for verifying black_hole solutions.

0.2100 2019-04-29
- Add lib/Games/Solitaire/Verify/Golf.pm and
@@ -3,11 +3,9 @@
use strict;
use warnings;

use Games::Solitaire::Verify::App::CmdLine;
use Games::Solitaire::Verify::App::CmdLine ();

my $app = Games::Solitaire::Verify::App::CmdLine->new({argv => \@ARGV});

$app->run();
Games::Solitaire::Verify::App::CmdLine->new({argv => \@ARGV})->run;

=head1 NAME
@@ -30,7 +28,7 @@ L<Games::Solitaire::Verify>.
=head2 -g [variant]
Picks up a variant.
Selects a solitaire variant.
=head2 --decks-num [1|2]
@@ -96,7 +94,7 @@ L<http://cpanratings.perl.org/d/Games-Solitaire-Verify>
=head1 AUTHORS
Shlomi Fish, L<http://www.shlomifish.org/> .
Shlomi Fish, L<https://www.shlomifish.org/> .
=head1 COPYRIGHT & LICENSE
@@ -3,7 +3,7 @@ author = Shlomi Fish <shlomif@cpan.org>
license = MIT
copyright_holder = Shlomi Fish
copyright_year = 2014
version = 0.2100
version = 0.2302

[@Filter]
-bundle = @SHLOMIF
@@ -20,3 +20,4 @@ Getopt::Long = 2.36
[Test::TrailingSpace]
filename_regex = (?:(?:\.(?:t|pm|pl|PL|yml|json|arc|vim))|README|Changes|LICENSE)\z
[Test::TidyAll]
;authordep Test::Kwalitee
@@ -5,12 +5,12 @@

package Games::Solitaire::Verify::App::From_DBM_FC_Solver;

use base 'Games::Solitaire::Verify::Base';
use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::VariantsMap;
use Games::Solitaire::Verify::Solution;
use Games::Solitaire::Verify::State;
use Games::Solitaire::Verify::Move;
use Games::Solitaire::Verify::VariantsMap ();
use Games::Solitaire::Verify::Solution ();
use Games::Solitaire::Verify::State ();
use Games::Solitaire::Verify::Move ();

use Getopt::Long qw(GetOptionsFromArray);

@@ -218,19 +218,17 @@ sub run
if ( $running_state->get_foundation_value( $card->suit(), $deck ) ==
$card->rank() - 1 )
{
my $other_deck_idx;

for $other_deck_idx (
for my $other_suit_idx (
0 .. ( ( $running_state->num_decks() << 2 ) - 1 ) )
{
if (
$running_state->get_foundation_value(
$card->get_suits_seq->[ $other_deck_idx % 4 ],
( $other_deck_idx >> 2 ),
$card->get_suits_seq->[ $other_suit_idx % 4 ],
( $other_suit_idx >> 2 ),
) < $card->rank() - 2 - (
(
$card->color_for_suit(
$card->get_suits_seq->[ $other_deck_idx %
$card->get_suits_seq->[ $other_suit_idx %
4 ]
) eq $card->color()
) ? 1 : 0
@@ -13,7 +13,7 @@ Games::Solitaire::Verify - verify solutions for solitaire games.

=head1 SYNOPSIS
use Games::Solitaire::Verify::Solution;
use Games::Solitaire::Verify::Solution ();
my $verifier = Games::Solitaire::Verify::Solution->new();
@@ -8,9 +8,10 @@ use parent 'Games::Solitaire::Verify::Base';
use Data::Dumper qw(Dumper);

use Getopt::Long qw(GetOptionsFromArray);
use Pod::Usage qw/ pod2usage /;

use Games::Solitaire::Verify::VariantsMap;
use Games::Solitaire::Verify::Solution;
use Games::Solitaire::Verify::VariantsMap ();
use Games::Solitaire::Verify::Solution ();

__PACKAGE__->mk_acc_ref(
[
@@ -35,6 +36,9 @@ sub _init

GetOptionsFromArray(
$argv,
'help|h' => sub {
pod2usage(1);
},
'g|game|variant=s' => sub {
my ( undef, $game ) = @_;

@@ -9,8 +9,8 @@ use Data::Dumper qw(Dumper);

use Getopt::Long qw(GetOptionsFromArray);

use Games::Solitaire::Verify::VariantsMap;
use Games::Solitaire::Verify::Solution::ExpandMultiCardMoves;
use Games::Solitaire::Verify::VariantsMap ();
use Games::Solitaire::Verify::Solution::ExpandMultiCardMoves ();

__PACKAGE__->mk_acc_ref(
[
@@ -2,16 +2,14 @@ package Games::Solitaire::Verify::App::CmdLine::From_Patsolve;

use strict;
use warnings;

use autodie;

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::VariantsMap;
use Games::Solitaire::Verify::Solution;
use Games::Solitaire::Verify::State;
use Games::Solitaire::Verify::State::LaxParser;
use Games::Solitaire::Verify::Move;
use Games::Solitaire::Verify::VariantsMap ();
use Games::Solitaire::Verify::Solution ();
use Games::Solitaire::Verify::State::LaxParser ();
use Games::Solitaire::Verify::Move ();

use List::MoreUtils qw(firstidx);

@@ -14,7 +14,7 @@ Solitaire card.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Exception ();

__PACKAGE__->mk_acc_ref(
[
@@ -12,8 +12,8 @@ columns that are composed of a sequence of cards.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Card;
use Games::Solitaire::Verify::Exception ();
use Games::Solitaire::Verify::Card ();

__PACKAGE__->mk_acc_ref(
[
@@ -130,6 +130,15 @@ use Exception::Class (

);

package Games::Solitaire::Verify::Exception;

use overload q#""# => sub {
my $self = shift;
my $err = $self->error();
$err =~ s/([^\n])\z/$1\n/ms;
return $err;
};

=head1 SYNOPSIS
use Games::Solitaire::Verify::Exception;
@@ -12,8 +12,8 @@ foundations (or home-cells) in a Solitaire game.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Card;
use Games::Solitaire::Verify::Exception ();
use Games::Solitaire::Verify::Card ();

use List::Util qw(first);

@@ -12,8 +12,8 @@ Freecells in games such as Freecell, Baker's Game, or Seahaven Towers

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Card;
use Games::Solitaire::Verify::Exception ();
use Games::Solitaire::Verify::Card ();

use List::Util qw(first);

@@ -26,7 +26,7 @@ of black-hole-solve (or a similar solver)
=head1 METHODS
=head2 Games::Solitaire::Verify::Golf->new({board_string=>$str, variant =>"golf"|"all_in_a_row"})
=head2 Games::Solitaire::Verify::Golf->new({board_string=>$str, variant =>"golf"|"all_in_a_row"|"black_hole"})
Construct a new validator / verifier for the variant and the initial board string.
@@ -47,7 +47,7 @@ Process the solution with the line iterator. Throws an exception if there is an
=cut

use Carp ();
use List::Util qw/ all /;
use List::Util qw/ sum /;

use Games::Solitaire::Verify::Card ();
use Games::Solitaire::Verify::Column ();
@@ -83,7 +83,9 @@ sub _init
my ( $self, $args ) = @_;

my $variant = $self->_variant( $args->{variant} );
if ( not exists { golf => 1, all_in_a_row => 1 }->{$variant} )
if (
not
exists { golf => 1, all_in_a_row => 1, black_hole => 1, }->{$variant} )
{
Carp::confess("Unknown variant '$variant'!");
}
@@ -95,6 +97,19 @@ sub _init

my @lines = split( /\n/, $board_string );

my $_set_found_line = sub {
my $foundation_str = shift;
if ( my ($card_s) = $foundation_str =~ m#\AFoundations: (\S{2})\z# )
{
$self->_set_found(
Games::Solitaire::Verify::Card->new( { string => $card_s } ) );
}
else
{
Carp::confess("Foundations str is '$foundation_str'");
}
return;
};
my $foundation_str = shift(@lines);
if ( $self->_variant eq 'golf' )
{
@@ -111,25 +126,23 @@ sub _init
);

$foundation_str = shift(@lines);
if ( my ($card_s) = $foundation_str =~ m#\AFoundations: (\S{2})\z# )
{
$self->_set_found(
Games::Solitaire::Verify::Card->new( { string => $card_s } ) );
}
else
{
Carp::confess("Foundations str is '$foundation_str'");
}
$_set_found_line->($foundation_str);

}
else
{
$self->_talon( [] );
if ( $foundation_str ne "Foundations: -" )
if ( $self->_variant eq "all_in_a_row" )
{
Carp::confess("Foundations str is '$foundation_str'");
if ( $foundation_str ne "Foundations: -" )
{
Carp::confess("Foundations str is '$foundation_str'");
}
}
else
{
$_set_found_line->($foundation_str);
}

}

$self->_columns(
@@ -161,8 +174,10 @@ sub _set_found
sub process_solution
{
my ( $self, $next_line_iter ) = @_;

my $line_num = 0;
my $columns = $self->_columns;
my $NUM_COLUMNS = @$columns;
my $line_num = 0;
my $remaining_cards = sum( map { $_->len } @$columns );

my $get_line = sub {
my $ret = $next_line_iter->();
@@ -186,6 +201,8 @@ sub process_solution
{
die "First line is '$l' instead of 'Solved!'";
}
my $IS_GOLF = $self->_is_golf;
my $CHECK_EMPTY = ( $IS_GOLF or $self->_variant eq "black_hole" );

# As many moves as the number of cards.
MOVES:
@@ -194,7 +211,7 @@ MOVES:
my ( $move_line, $move_line_idx ) = $get_line->();

my $card;
if ( $self->_is_golf
if ( $IS_GOLF
and $move_line =~ m/\ADeal talon\z/ )
{
if ( !@{ $self->_talon } )
@@ -214,7 +231,7 @@ MOVES:

if ( !defined $card )
{
if ( ( $col_idx < 0 ) or ( $col_idx >= $MAX_RANK ) )
if ( ( $col_idx < 0 ) or ( $col_idx >= $NUM_COLUMNS ) )
{
die "Invalid column index '$col_idx' at $move_line_idx";
}
@@ -256,7 +273,7 @@ MOVES:
}
else
{
my $col = $self->_columns->[$col_idx];
my $col = $columns->[$col_idx];
my $top_card = $col->top();
my $top_card_moved_str = $top_card->to_string();

@@ -276,7 +293,7 @@ MOVES:
if (
not( $delta == 1 or $delta == ( $MAX_RANK - 1 ) )
or (
$self->_is_golf
$IS_GOLF
and ( !$self->_wrap_ranks )
and (
(
@@ -289,19 +306,19 @@ MOVES:
)
)
{
die "Cannot put "
. $top_card->to_string()
. " in the foundations that contain "
die
"Cannot put $top_card_moved_str in the foundations that contain "
. $found_card->to_string();
}
}
$card = $col->pop;
--$remaining_cards;
}

$self->_set_found($card);
if ( $self->_is_golf )
if ($CHECK_EMPTY)
{
if ( all { $_->len == 0 } @{ $self->_columns } )
if ( $remaining_cards == 0 )
{
last MOVES;
}
@@ -12,8 +12,8 @@ talon of Klondike-like games.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Card;
use Games::Solitaire::Verify::Exception ();
use Games::Solitaire::Verify::Card ();

use List::Util qw(first);

@@ -68,7 +68,7 @@ sub _init
$self->_num_redeals_so_far(0);

$self->_undealt_cards( [] );
$self->_waste( [] );
$self->_waste( [] );

if ( exists( $args->{string} ) )
{
@@ -12,7 +12,7 @@ Solitaire move.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Exception ();

__PACKAGE__->mk_acc_ref(
[
@@ -14,11 +14,11 @@ of Freecell Solver (or a similar solver)

use parent 'Games::Solitaire::Verify::Solution::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Card;
use Games::Solitaire::Verify::Column;
use Games::Solitaire::Verify::Move;
use Games::Solitaire::Verify::State;
use Games::Solitaire::Verify::Exception ();
use Games::Solitaire::Verify::Card ();
use Games::Solitaire::Verify::Column ();
use Games::Solitaire::Verify::Move ();
use Games::Solitaire::Verify::State ();

=head1 SYNOPSIS
@@ -12,14 +12,14 @@ states (or positions) of the entire board.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Card;
use Games::Solitaire::Verify::Column;
use Games::Solitaire::Verify::Move;
use Games::Solitaire::Verify::Freecells;
use Games::Solitaire::Verify::Foundations;
use Games::Solitaire::Verify::VariantParams;
use Games::Solitaire::Verify::VariantsMap;
use Games::Solitaire::Verify::Exception ();
use Games::Solitaire::Verify::Card ();
use Games::Solitaire::Verify::Column ();
use Games::Solitaire::Verify::Move ();
use Games::Solitaire::Verify::Freecells ();
use Games::Solitaire::Verify::Foundations ();
use Games::Solitaire::Verify::VariantParams ();
use Games::Solitaire::Verify::VariantsMap ();

use List::Util qw(first);
use POSIX qw();
@@ -12,7 +12,7 @@ the parameters of the variant.

use parent 'Games::Solitaire::Verify::Base';

use Games::Solitaire::Verify::Exception;
use Games::Solitaire::Verify::Exception ();

__PACKAGE__->mk_acc_ref(
[
@@ -3,7 +3,7 @@ package Games::Solitaire::Verify::VariantsMap;
use strict;
use warnings;

use Games::Solitaire::Verify::VariantParams;
use Games::Solitaire::Verify::VariantParams ();

use parent 'Games::Solitaire::Verify::Base';

@@ -3,7 +3,7 @@
use strict;
use warnings;

use IO::All;
use IO::All qw/ io /;

my ($version) =
( map { m{\Aversion *= *(\S+)\n?\z} ? ($1) : () }
@@ -1,5 +1,8 @@
#!perl -T

use strict;
use warnings;

use Test::More tests => 4;

BEGIN
@@ -7,7 +7,7 @@ use Test::More tests => 4;

package MyTest::Package;

use base 'Games::Solitaire::Verify::Base';
use parent 'Games::Solitaire::Verify::Base';

__PACKAGE__->mk_accessors(qw(_bold));

@@ -0,0 +1,31 @@
-=-=-=-=-=-=-=-=-=-=-=-

H-0 C-0 D-0 S-0
--- --- ---


-- -- -- -- -- -- -- --
JD 2D 9H JC 5D 7H 7C 5H
KD KC 9S 5S AD QC KH 3H
2S KS 9D QD JS AS AH 3C
4C 5C 10S QH 4H AC 4D 7S
3S 10D 4S 10H 8H 2C JH 7D
6D 8S 8D QS 6C 3D 8C 10C
6S 9C 2H 6H


====================

6H H-0 C-0 D-0 S-0
--- --- ---


-- -- -- -- -- -- -- --
JD 2D 9H JC 5D 7H 7C 5H
KD KC 9S 5S AD QC KH 3H
2S KS 9D QD JS AS AH 3C
4C 5C 10S QH 4H AC 4D 7S
3S 10D 4S 10H 8H 2C JH 7D
6D 8S 8D QS 6C 3D 8C 10C
6S 9C 2H

@@ -1,2 +1,8 @@
3.all_in_a_row.board
3.all_in_a_row.sol
4.golf-wrap-ranks.sol
4.golf.board
5.golf.board
5.golf.sol
6.black_hole.board
6.black_hole.sol
@@ -0,0 +1,356 @@
Solved!
Move a card from stack 1 to the foundations

Info: Card moved is 4C


====================

Move a card from stack 3 to the foundations

Info: Card moved is 3C


====================

Deal talon

Info: Card moved is 7H


====================

Move a card from stack 0 to the foundations

Info: Card moved is 8D


====================

Move a card from stack 6 to the foundations

Info: Card moved is 7C


====================

Move a card from stack 6 to the foundations

Info: Card moved is 8H


====================

Move a card from stack 3 to the foundations

Info: Card moved is 9S


====================

Move a card from stack 5 to the foundations

Info: Card moved is TH


====================

Deal talon

Info: Card moved is 2H


====================

Move a card from stack 5 to the foundations

Info: Card moved is AS


====================

Move a card from stack 0 to the foundations

Info: Card moved is 2S


====================

Deal talon

Info: Card moved is JH


====================

Move a card from stack 4 to the foundations

Info: Card moved is TC


====================

Deal talon

Info: Card moved is TD


====================

Deal talon

Info: Card moved is JC


====================

Move a card from stack 3 to the foundations

Info: Card moved is TS


====================

Deal talon

Info: Card moved is QD


====================

Move a card from stack 3 to the foundations

Info: Card moved is KH


====================

Move a card from stack 1 to the foundations

Info: Card moved is QH


====================

Move a card from stack 3 to the foundations

Info: Card moved is JS


====================

Deal talon

Info: Card moved is KC


====================

Deal talon

Info: Card moved is 2D


====================

Deal talon

Info: Card moved is 8S


====================

Deal talon

Info: Card moved is 6H


====================

Move a card from stack 4 to the foundations

Info: Card moved is 5S


====================

Move a card from stack 6 to the foundations

Info: Card moved is 4H


====================

Move a card from stack 2 to the foundations

Info: Card moved is 5H


====================

Move a card from stack 0 to the foundations

Info: Card moved is 6C


====================

Move a card from stack 2 to the foundations

Info: Card moved is 7S


====================

Move a card from stack 2 to the foundations

Info: Card moved is 6D


====================

Move a card from stack 1 to the foundations

Info: Card moved is 5C


====================

Move a card from stack 5 to the foundations

Info: Card moved is 4D


====================

Move a card from stack 0 to the foundations

Info: Card moved is 3S


====================

Move a card from stack 1 to the foundations

Info: Card moved is 2C


====================

Move a card from stack 5 to the foundations

Info: Card moved is AH


====================

Move a card from stack 5 to the foundations

Info: Card moved is KD


====================

Move a card from stack 4 to the foundations

Info: Card moved is QS


====================

Move a card from stack 0 to the foundations

Info: Card moved is KS


====================

Move a card from stack 2 to the foundations

Info: Card moved is AC


====================

Deal talon

Info: Card moved is 9H


====================

Move a card from stack 4 to the foundations

Info: Card moved is 8C


====================

Move a card from stack 6 to the foundations

Info: Card moved is 9D


====================

Deal talon

Info: Card moved is JD


====================

Move a card from stack 1 to the foundations

Info: Card moved is QC


====================

Deal talon

Info: Card moved is 9C


====================

Deal talon

Info: Card moved is 7D


====================

Move a card from stack 6 to the foundations

Info: Card moved is 6S


====================

Move a card from stack 4 to the foundations

Info: Card moved is 5D


====================

Deal talon

Info: Card moved is 4S


====================

Move a card from stack 2 to the foundations

Info: Card moved is 3D


====================



--------------------
Total number of states checked is 1742.
This scan generated 1794 states.
@@ -0,0 +1,9 @@
Talon: 7H 2H JH TD JC QD KC 2D 8S 6H 9H JD 9C 7D 4S AD
Foundations: 3H
KS 3S 6C 2S 8D
QC 2C 5C QH 4C
3D AC 6D 7S 5H
JS KH TS 9S 3C
5D 8C QS 5S TC
KD AH 4D AS TH
6S 9D 4H 8H 7C
@@ -0,0 +1,9 @@
Talon: KS QD 4H AC 2H TC TH 6D 6H 6C QC JS 9S AD 7C TS
Foundations: 9D
AH 3D 3C 5H 8H
8S 5C 4S 6S JH
2D AS 3S 8D JC
QS 9C 5D TD 7D
4C KH KC 7S 5S
9H 4D 3H JD QH
2S 2C KD 7H 8C
@@ -0,0 +1,349 @@
Solved!
Move a card from stack 6 to the foundations

Info: Card moved is 8C


====================

Move a card from stack 6 to the foundations

Info: Card moved is 7H


====================

Move a card from stack 0 to the foundations

Info: Card moved is 8H


====================

Move a card from stack 3 to the foundations

Info: Card moved is 7D


====================

Deal talon

Info: Card moved is KS


====================

Deal talon

Info: Card moved is QD


====================

Move a card from stack 6 to the foundations

Info: Card moved is KD


====================

Deal talon

Info: Card moved is 4H


====================

Move a card from stack 4 to the foundations

Info: Card moved is 5S


====================

Deal talon

Info: Card moved is AC


====================

Deal talon

Info: Card moved is 2H


====================

Deal talon

Info: Card moved is TC


====================

Move a card from stack 2 to the foundations

Info: Card moved is JC


====================

Move a card from stack 5 to the foundations

Info: Card moved is QH


====================

Move a card from stack 5 to the foundations

Info: Card moved is JD


====================

Move a card from stack 3 to the foundations

Info: Card moved is TD


====================

Move a card from stack 1 to the foundations

Info: Card moved is JH


====================

Deal talon

Info: Card moved is TH


====================

Deal talon

Info: Card moved is 6D


====================

Move a card from stack 3 to the foundations

Info: Card moved is 5D


====================

Move a card from stack 1 to the foundations

Info: Card moved is 6S


====================

Move a card from stack 4 to the foundations

Info: Card moved is 7S


====================

Move a card from stack 2 to the foundations

Info: Card moved is 8D


====================

Move a card from stack 3 to the foundations

Info: Card moved is 9C


====================

Deal talon

Info: Card moved is 6H


====================

Move a card from stack 0 to the foundations

Info: Card moved is 5H


====================

Move a card from stack 1 to the foundations

Info: Card moved is 4S


====================

Move a card from stack 5 to the foundations

Info: Card moved is 3H


====================

Move a card from stack 5 to the foundations

Info: Card moved is 4D


====================

Move a card from stack 2 to the foundations

Info: Card moved is 3S


====================

Move a card from stack 6 to the foundations

Info: Card moved is 2C


====================

Move a card from stack 2 to the foundations

Info: Card moved is AS


====================

Deal talon

Info: Card moved is 6C


====================

Move a card from stack 1 to the foundations

Info: Card moved is 5C


====================

Deal talon

Info: Card moved is QC


====================

Move a card from stack 4 to the foundations

Info: Card moved is KC


====================

Deal talon

Info: Card moved is JS


====================

Move a card from stack 3 to the foundations

Info: Card moved is QS


====================

Move a card from stack 4 to the foundations

Info: Card moved is KH


====================

Deal talon

Info: Card moved is 9S


====================

Move a card from stack 1 to the foundations

Info: Card moved is 8S


====================

Move a card from stack 5 to the foundations

Info: Card moved is 9H


====================

Deal talon

Info: Card moved is AD


====================

Move a card from stack 6 to the foundations

Info: Card moved is 2S


====================

Move a card from stack 0 to the foundations

Info: Card moved is 3C


====================

Move a card from stack 4 to the foundations

Info: Card moved is 4C


====================

Move a card from stack 0 to the foundations

Info: Card moved is 3D


====================

Move a card from stack 2 to the foundations

Info: Card moved is 2D


====================

Move a card from stack 0 to the foundations

Info: Card moved is AH


====================



--------------------
Total number of states checked is 76951.
This scan generated 76997 states.
@@ -0,0 +1,18 @@
Foundations: AS
2H TS 5D
JS QD 4D
5S KS 8C
5C 8D 3D
6H 8H TD
2C TC 2D
TH QS 4C
2S 4S 7H
JC 9D 6S
QH KH 7D
3H 7S 9S
9H KD KC
7C JD 6D
QC 4H 9C
3C 8S 6C
AC 3S JH
AD 5H AH
@@ -0,0 +1,363 @@
Solved!
Move a card from stack 11 to the foundations

Info: Card moved is KC


====================

Move a card from stack 16 to the foundations

Info: Card moved is AH


====================

Move a card from stack 5 to the foundations

Info: Card moved is 2D


====================

Move a card from stack 3 to the foundations

Info: Card moved is 3D


====================

Move a card from stack 6 to the foundations

Info: Card moved is 4C


====================

Move a card from stack 16 to the foundations

Info: Card moved is 5H


====================

Move a card from stack 14 to the foundations

Info: Card moved is 6C


====================

Move a card from stack 9 to the foundations

Info: Card moved is 7D


====================

Move a card from stack 14 to the foundations

Info: Card moved is 8S


====================

Move a card from stack 13 to the foundations

Info: Card moved is 9C


====================

Move a card from stack 5 to the foundations

Info: Card moved is TC


====================

Move a card from stack 15 to the foundations

Info: Card moved is JH


====================

Move a card from stack 6 to the foundations

Info: Card moved is QS


====================

Move a card from stack 11 to the foundations

Info: Card moved is KD


====================

Move a card from stack 16 to the foundations

Info: Card moved is AD


====================

Move a card from stack 5 to the foundations

Info: Card moved is 2C


====================

Move a card from stack 15 to the foundations

Info: Card moved is 3S


====================

Move a card from stack 13 to the foundations

Info: Card moved is 4H


====================

Move a card from stack 0 to the foundations

Info: Card moved is 5D


====================

Move a card from stack 12 to the foundations

Info: Card moved is 6D


====================

Move a card from stack 7 to the foundations

Info: Card moved is 7H


====================

Move a card from stack 3 to the foundations

Info: Card moved is 8D


====================

Move a card from stack 11 to the foundations

Info: Card moved is 9H


====================

Move a card from stack 0 to the foundations

Info: Card moved is TS


====================

Move a card from stack 12 to the foundations

Info: Card moved is JD


====================

Move a card from stack 13 to the foundations

Info: Card moved is QC


====================

Move a card from stack 9 to the foundations

Info: Card moved is KH


====================

Move a card from stack 15 to the foundations

Info: Card moved is AC


====================

Move a card from stack 0 to the foundations

Info: Card moved is 2H


====================

Move a card from stack 14 to the foundations

Info: Card moved is 3C


====================

Move a card from stack 1 to the foundations

Info: Card moved is 4D


====================

Move a card from stack 3 to the foundations

Info: Card moved is 5C


====================

Move a card from stack 8 to the foundations

Info: Card moved is 6S


====================

Move a card from stack 12 to the foundations

Info: Card moved is 7C


====================

Move a card from stack 2 to the foundations

Info: Card moved is 8C


====================

Move a card from stack 8 to the foundations

Info: Card moved is 9D


====================

Move a card from stack 6 to the foundations

Info: Card moved is TH


====================

Move a card from stack 8 to the foundations

Info: Card moved is JC


====================

Move a card from stack 9 to the foundations

Info: Card moved is QH


====================

Move a card from stack 2 to the foundations

Info: Card moved is KS


====================

Move a card from stack 1 to the foundations

Info: Card moved is QD


====================

Move a card from stack 1 to the foundations

Info: Card moved is JS


====================

Move a card from stack 4 to the foundations

Info: Card moved is TD


====================

Move a card from stack 10 to the foundations

Info: Card moved is 9S


====================

Move a card from stack 4 to the foundations

Info: Card moved is 8H


====================

Move a card from stack 10 to the foundations

Info: Card moved is 7S


====================

Move a card from stack 4 to the foundations

Info: Card moved is 6H


====================

Move a card from stack 2 to the foundations

Info: Card moved is 5S


====================

Move a card from stack 7 to the foundations

Info: Card moved is 4S


====================

Move a card from stack 10 to the foundations

Info: Card moved is 3H


====================

Move a card from stack 7 to the foundations

Info: Card moved is 2S


====================



--------------------
Total number of states checked is 12461.
This scan generated 12492 states.
@@ -0,0 +1,37 @@
#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;

use vars qw/ $trap /;
eval
"use Test::Trap qw( trap \$trap :flow:stderr(systemsafe):stdout(systemsafe):warn );";

if ($@)
{
plan 'skip_all' => "Failed to load Test::Trap . Skipping.";
}
else
{
plan tests => 2;
}

{
my $exit_code;
trap(
sub {
$exit_code = system( $^X, "-I", "lib",
"bin/verify-solitaire-solution",
"t/data/sample-solutions/1.fc-wrong.sol.txt"
);
}
);

# TEST
ok( $exit_code, "Non zero (failure) process exit code." );

# TEST
like( $trap->stderr(), qr#\AWrong.*\n\z#, "Trailing newline in error line.",
);
}
@@ -3,13 +3,12 @@
use strict;
use warnings;

use Test::More tests => 1;
use Path::Tiny qw/ cwd path /;
use Test::More tests => 5;
use Path::Tiny qw/ cwd /;
use Dir::Manifest ();
use Games::Solitaire::Verify::Golf ();

my $data_dir = cwd()->child( 't', 'data' );
my $texts_dir = $data_dir->child('texts');
my $texts_dir = cwd()->child( 't', 'data', 'texts' );

my $mani = Dir::Manifest->new(
{
@@ -18,6 +17,14 @@ my $mani = Dir::Manifest->new(
}
);

sub _sol_iter
{
my ($fn) = @_;
my $fh = $mani->get_obj($fn)->fh->openr;

return sub { my $l = <$fh>; chomp $l; return $l; };
}

{
my $verifier = Games::Solitaire::Verify::Golf->new(
{
@@ -26,9 +33,71 @@ my $mani = Dir::Manifest->new(
}
);

my $fh = $mani->get_obj("3.all_in_a_row.sol")->fh->openr;
$verifier->process_solution( sub { my $l = <$fh>; chomp $l; return $l; } );
$verifier->process_solution( _sol_iter("3.all_in_a_row.sol") );

# TEST
pass("No error on verifying pysol fc 3 sol");
}

{
my $verifier = Games::Solitaire::Verify::Golf->new(
{
variant => "black_hole",
board_string => $mani->text("6.black_hole.board"),
}
);

$verifier->process_solution( _sol_iter("6.black_hole.sol") );

# TEST
pass("No error on verifying black_hole pysol fc 6 sol");
}

{
my $verifier = Games::Solitaire::Verify::Golf->new(
{
variant => "golf",
board_string => $mani->text("5.golf.board"),
queens_on_kings => 0,
wrap_ranks => 0,
}
);

$verifier->process_solution( _sol_iter("5.golf.sol") );

# TEST
pass("No error on verifying golf pysol fc 5 sol");
}

{
my $verifier = Games::Solitaire::Verify::Golf->new(
{
variant => "golf",
board_string => $mani->text("4.golf.board"),
wrap_ranks => 1,
}
);

$verifier->process_solution( _sol_iter("4.golf-wrap-ranks.sol") );

# TEST
pass("No error on verifying golf wrap ranks pysol fc 4 sol");
}

{
my $verifier = Games::Solitaire::Verify::Golf->new(
{
variant => "golf",
board_string => $mani->text("4.golf.board"),
queens_on_kings => 0,
wrap_ranks => 0,
}
);

eval { $verifier->process_solution( _sol_iter("4.golf-wrap-ranks.sol") ); };

my $err = $@;

# TEST
like( $err, qr#\ACannot put \S{2} in the foundations#, "error thrown" );
}
@@ -1,39 +1 @@
[@CorePrep]

[-SingleEncoding]

[Generic / NAME]

[Version]

[Region / prelude]


[Generic / SYNOPSIS]
[Generic / DESCRIPTION]
[Generic / OVERVIEW]

[Collect / ATTRIBUTES]
command = attr

[Collect / METHODS]
command = method

[Leftovers]

[Region / postlude]

[Authors]
[Legal]

; [Generic / DESCRIPTION]
; required = 1

; [Generic / BUGS]

; [Generic / Section::Bugs]
; [Generic / Section::License]
;
[Bugs]
[Support]
all_modules = 1
[@SHLOMIF]
@@ -0,0 +1,65 @@
package FC_Solve::PreSanityCheck;

use strict;
use warnings;
use 5.024;

use lib '.';
use FC_Solve::Solve ();

use lib '../Games-Solitaire-Verify/lib';

use parent 'Exporter';

# our @EXPORT_OK = qw(solve fc_solve_init);

use autodie;

use List::MoreUtils qw/ true /;

sub verify
{
#my ( $game_params, $board_idx ) = @_;

# my $fc_solve_output = `pi-make-microsoft-freecell-board -t $board_idx | fc-solve -p -t -sam -sel @fc_solve_args`;
my $board_idx = 1;
FC_Solve::Solve::fc_solve_init( [qw(-l lg)] );
my $fc_solve_output = FC_Solve::Solve::fc_solve_solve($board_idx);
if ( $fc_solve_output =~ /\b10[CDHS]\b/ )
{
say $fc_solve_output;
die "no t in fc_solve_output";
}

if ( $fc_solve_output =~ /---/ )
{
say $fc_solve_output;
die "no parsable sol";
}
my $_line_found = sub {
my ($s) = @_;

return ( index( $fc_solve_output, $s ) >= 0 );
};

my $is_solvable = $_line_found->('This game is solveable');
my $unsolved = $_line_found->('I could not solve');
my $intractable = $_line_found->('Iterations count exceeded');

if ( 1 != true { $_ } ( $is_solvable, $unsolved, $intractable ) )
{
die "Game is more than one of solved, unsolvable or intractable!";
}

if ( !$is_solvable )
{
die "not solveable";
}

say "All ok";
return;
}

verify();

1;
@@ -9,7 +9,7 @@ use Inline (
C => 'DATA',
CLEAN_AFTER_BUILD => 0,
INC =>
"-I$ENV{FCS_PATH} -I$ENV{FCS_SRC_PATH} -I$ENV{FCS_SRC_PATH}/patsolve/patsolve",
"-I$ENV{FCS_PATH}/include -I$ENV{FCS_PATH} -I$ENV{FCS_SRC_PATH}/include -I$ENV{FCS_SRC_PATH} -I$ENV{FCS_SRC_PATH}/patsolve/patsolve/include -I$ENV{FCS_SRC_PATH}/patsolve/patsolve",
LIBS => "-L" . $ENV{FCS_PATH} . " -lfreecell-solver",
CCFLAGS => "-std=gnu99",

@@ -24,10 +24,10 @@ our @EXPORT_OK = qw(solve fc_solve_init);

use autodie;

use List::MoreUtils qw(true);
use List::MoreUtils qw/ true /;

use Games::Solitaire::Verify::Solution;
use Games::Solitaire::Verify::App::CmdLine;
use Games::Solitaire::Verify::Solution ();
use Games::Solitaire::Verify::App::CmdLine ();

sub solve
{
@@ -41,7 +41,7 @@ sub solve
my $_line_found = sub {
my ($s) = @_;

return ( ( $fc_solve_output =~ m{^\Q$s\E}ms ) ? 1 : 0 );
return ( index( $fc_solve_output, $s ) >= 0 );
};

my $is_solvable = $_line_found->('This game is solveable');
@@ -83,7 +83,7 @@ sub solve
die "Invalid solution!";
}

$sol_len = () = ( $fc_solve_output =~ m{^Move}msg );
$sol_len = () = ( $fc_solve_output =~ m{\nMove}gms );
}

my ($num_iters) = (
@@ -103,6 +103,7 @@ __C__
#include <string.h>
#include <stdio.h>
#include "freecell-solver/fcs_conf.h"
#include "freecell-solver/fcs_cl.h"
#include "output_to_file.h"
#include "range_solvers_gen_ms_boards.h"
@@ -162,13 +163,20 @@ void fc_solve_init(AV * args)
-1,
NULL
);
get_board__setup_string(board_buf);
}
SV * fc_solve_solve(int board_num)
{
get_board(board_num, board_buf);
get_board_l__without_setup(board_num, board_buf);
const int err_code = freecell_solver_user_solve_board(fcs, board_buf);
#ifdef WRITE_TO_FILE
char fn[100];
sprintf(fn, "/tmp/fcs%d.sol", board_num);
FILE * const output_fh = fopen(fn, "wt");
#else
FILE * const output_fh = fmemopen(buffer , COUNT(buffer), "wt");
#endif
#if 1
fc_solve_output_result_to_file(output_fh, fcs, err_code, &my_context);
@@ -180,6 +188,12 @@ SV * fc_solve_solve(int board_num)
freecell_solver_user_recycle(fcs);
#ifdef WRITE_TO_FILE
FILE * readfh = fopen(fn, "rt");
memset(buffer, '\0', COUNT(buffer));
fread(buffer, 1, COUNT(buffer), readfh);
fclose(readfh);
#endif
SV * const ret = newSVpv(buffer, 0);
return ret;
@@ -4,14 +4,12 @@
use warnings;
use autodie;

use lib '.';
use lib '../Games-Solitaire-Verify/lib';

use FC_Solve::Solve (qw/fc_solve_init solve/);
use FC_Solve::Solve qw/ fc_solve_init solve /;

use List::MoreUtils qw(first_index true);

use Games::Solitaire::Verify::Solution;
use Games::Solitaire::Verify::App::CmdLine;
use List::MoreUtils qw/ first_index /;

my @args = @ARGV;

@@ -3,42 +3,38 @@
use strict;
use warnings;

use IO::All;
use Template;
use Template ();

my $MIN = 1;
my $MAX = 32_000;
my $STEP = 100;

my $ARGS = +{
min => $MIN,
max => ( $MAX / $STEP ),
step => $STEP,
res => sub {
cmd => qq#perl benchmark-no-backticks.pl -- -l lg -ni -l fg#,
min => $MIN,
max => ( $MAX / $STEP ),
res => sub {
return "Results/" . shift . ".res";
},
step => $STEP,
};

my $template = Template->new(
{
EVAL_PERL => 1, # evaluate Perl code blocks
}
);
my $template = Template->new( {} );

my $TEXT = <<'EOF';
all:[% FOREACH i = [min .. max] %] [% res(i) %][% END %]
[% FOREACH i = [min .. max] %]
[% res(i) %]:
[% "\t" %]F=[% min + (i - 1) * step %] L=[% min + i * step - 1 %] perl benchmark-no-backticks.pl -- -l as -ni -l fg > [% res(i) %]
[% "\t" %]F=[% min + (i - 1) * step %] L=[% min + i * step - 1 %] [% cmd %] > [% res(i) %]
[% END %]
EOF

$template->process( \$TEXT, $ARGS, 'par2.mak', ) or die $template->error;

my $NINJA_TEXT = <<'EOF';
rule b
command = F=$f L=$l perl benchmark-no-backticks.pl -- -l as -ni -l fg > $out
command = F=$f L=$l [% cmd %] > $out
[% FOREACH i = [min .. max] %]
build [% res(i) %]: b
@@ -1 +1,6 @@
sudo_renice bash -c "export FCS_PATH=\"$b\"; export FCS_SRC_PATH=\"$c_src\"; PATH=\"\$HOME/apps/perl/bleadperl/bin:\$PATH\"; time make -j4 -f par.mak"
rm -f Results/*.res
if perl FC_Solve/PreSanityCheck.pm
then
# sudo_renice bash -c "export FCS_PATH=\"$b\"; export FCS_SRC_PATH=\"$c_src\"; time make -j4 -f par.mak"
sudo_renice bash -c "export FCS_PATH=\"$b\"; export FCS_SRC_PATH=\"$c_src\"; export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\" ; PATH=\"\$HOME/apps/perl/bleadperl/bin:\$PATH\"; time ninja -j4"
fi
@@ -1,2 +1,10 @@
rm -f Results/*.res
sudo_renice bash -c "export FCS_PATH=\"$b\"; export FCS_SRC_PATH=\"$c_src\"; time make -j4 -f par.mak"
( rm -f Results/*.res ) 2> /dev/null
if ! test -e build.ninja
then
perl gen-par-mak.pl
fi
if perl FC_Solve/PreSanityCheck.pm
then
# sudo_renice bash -c "export FCS_PATH=\"$b\"; export FCS_SRC_PATH=\"$c_src\"; time make -j4 -f par.mak"
sudo_renice bash -c "export FCS_PATH=\"$b\"; export FCS_SRC_PATH=\"$c_src\"; export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\" ; time ninja -j4"
fi
@@ -6,7 +6,7 @@ RESULTS = $(patsubst %,Results/%.res,$(INDEXES))
all: $(RESULTS)

$(RESULTS): %:
i="$(patsubst Results/%.res,%,$@)"; F="$$i" L="$$((i + 99))" perl -I. benchmark-no-backticks.pl -- -l cm -ni -l fg > $@
i="$(patsubst Results/%.res,%,$@)"; F="$$i" L="$$((i + 99))" perl -I. benchmark-no-backticks.pl -- -l lg -ni -l fg > $@

cat: $(RESULTS)
cat $(RESULTS)
@@ -0,0 +1,60 @@
#!/usr/bin/perl

use strict;
use warnings;
use autodie;
use FindBin qw/ $Bin /;
use File::Path qw/ rmtree /;
use Env::Path;

Env::Path->LD_LIBRARY_PATH->Prepend( $ENV{FCS_PATH} );

chdir($Bin);

sub do_system
{
my ($args) = @_;

my $cmd = $args->{cmd};
print "Running [@$cmd]\n";
if ( system(@$cmd) )
{
die "Running [@$cmd] failed!";
}
}
do_system( { cmd => [ $^X, "gen-par-mak.pl" ] } );

sub _cleanup
{
rmtree( ["_Inline"] );
unlink( grep { -f $_ } glob("Results/*.res") );
return;
}

_cleanup();

do_system( { cmd => [ "gmake", "-f", "par2.mak", "-j1", "Results/1.res", ] } );
do_system( { cmd => [ "gmake", "-f", "par2.mak", "-j1", "Results/2.res", ] } );

use Path::Tiny qw/ path tempdir tempfile cwd /;

my @l = path("Results/1.res")->lines_utf8;
chomp @l;
my $i = 1;
while (@l)
{
my $l = shift(@l);
if ( $l ne "== $i ==" )
{
die $l;
}
$l = shift(@l);
if ( $l !~ /\AVerdict: Solved ; Iters: [0-9]+ ; Length: [0-9]+\z/ )
{
die $l;
}
}
continue { ++$i; }
die if $i ne 101;
_cleanup();
unlink( "build.ninja", "par2.mak" );
@@ -1,4 +1,7 @@
Revision history for Task-FreecellSolver-Testing-MultiConfig

0.0.2 2020-03-05
Add some newer deps

0.0.1 2018-06-26
First version, released on an unsuspecting world.
@@ -3,7 +3,7 @@ author = Shlomi Fish <shlomif@cpan.org>
license = MIT
copyright_holder = Shlomi Fish
copyright_year = 2018
version = 0.0.1
version = 0.0.2

[@Filter]
-bundle = @SHLOMIF
@@ -12,14 +12,24 @@ the Freecell Solver multi-config test suite.
=pkgroup Freecell Solver deps
=pkg App::Deps::Verify
=pkg App::Docmake
=pkg Code::TidyAll::Plugin::ClangFormat
=pkg Code::TidyAll::Plugin::ESLint
=pkg Code::TidyAll::Plugin::TSLint
=pkg Dist::Zilla::Plugin::Test::Kwalitee
=pkg Dist::Zilla::Plugin::Test::TidyAll
=pkg Dist::Zilla::PluginBundle::SHLOMIF
=pkg Pod::Weaver::PluginBundle::SHLOMIF
=pkg Pod::Weaver::Section::Support
=pkg HTML::Spelling::Site::Whitelist
@@ -1,39 +1 @@
[@CorePrep]

[-SingleEncoding]

[Generic / NAME]

[Version]

[Region / prelude]


[Generic / SYNOPSIS]
[Generic / DESCRIPTION]
[Generic / OVERVIEW]

[Collect / ATTRIBUTES]
command = attr

[Collect / METHODS]
command = method

[Leftovers]

[Region / postlude]

[Authors]
[Legal]

; [Generic / DESCRIPTION]
; required = 1

; [Generic / BUGS]

; [Generic / Section::Bugs]
; [Generic / Section::License]
;
[Bugs]
[Support]
all_modules = 1
[@SHLOMIF]
@@ -13,35 +13,35 @@ Freecell Solver test suite.
=cut

# Load the dependencies so we'll be sure they are installed.
use Carp;
use Cwd;
use Data::Dumper;
use Digest::SHA;
use Env::Path;
use File::Path;
use File::Spec;
use File::Which ();
use Games::Solitaire::Verify;
use Inline;
use Inline::C ();
use List::MoreUtils;
use List::Util;
use Moo;
use Carp ();
use Cwd ();
use Data::Dumper ();
use Digest::SHA ();
use Env::Path ();
use File::Path ();
use File::Spec ();
use File::Which ();
use Games::Solitaire::Verify ();
use Inline ();
use Inline::C ();
use List::MoreUtils ();
use List::Util ();
use Moo ();
use MooX qw(late);
use Path::Tiny 0.077;
use Storable;
use String::ShellQuote;
use Task::Test::Run::AllPlugins;
use Template;
use Test::Code::TidyAll;
use Test::Data::Split;
use Test::Differences;
use Test::More;
use Test::PerlTidy ();
use Test::Run::CmdLine::Plugin::TrimDisplayedFilenames;
use Test::RunValgrind;
use Test::TrailingSpace ();
use YAML::XS;
use Storable ();
use String::ShellQuote ();
use Task::Test::Run::AllPlugins ();
use Template ();
use Test::Code::TidyAll ();
use Test::Data::Split ();
use Test::Differences ();
use Test::More ();
use Test::PerlTidy ();
use Test::Run::CmdLine::Plugin::TrimDisplayedFilenames ();
use Test::RunValgrind ();
use Test::TrailingSpace ();
use YAML::XS ();

=head1 SYNOPSIS
@@ -3,8 +3,7 @@
use strict;
use warnings;

use IO::File;
use List::Util qw(first);
use List::Util qw( first );

my $log_fn = "iters-by-quotas.txt";

@@ -3,8 +3,8 @@
use strict;
use warnings;

use Getopt::Long;
use IO::All;
use Getopt::Long qw / GetOptions /;
use IO::All qw/ io /;

use List::Util qw(min);

@@ -14,7 +14,7 @@

my $with_len = 0;

GetOptions( "l!" => \$with_len, );
GetOptions( "l!" => \$with_len, ) or die $!;

my ( $scan_id, $board_idx ) = @ARGV;

@@ -3,7 +3,7 @@
use strict;
use warnings;

use MyInput;
use MyInput ();

my $opt = ( ( $ARGV[0] eq "--gen-bat" ) ? shift : "" );

@@ -21,7 +21,7 @@
$layout = ( lc join '', @cards ) . " -- -- -- -- --\n$layout";

my ( $deck, $over, $spades, $hearts, $diamonds, $clubs, @stacks );
my %found = ( S => \$spades, H => \$hearts, D => \$diamonds, C => \$clubs );
my %found = ( S => \$spades, H => \$hearts, D => \$diamonds, C => \$clubs );
my %wantsuit = ( S => '[HD]', H => '[SC]', D => '[SC]', C => '[HD]' );
my ( %rank, %state, $moves );
@rank{qw(-A A2 23 34 45 56 67 78 89 9T TJ JQ QK)} = ();
@@ -349,9 +349,7 @@
An optimised hash implementations. This hash maps keys to
values. It stores the hash function values next to the
keys, so two keys can be first compared with their hash
values, before the costly full comparison is done. It also
uses a secondary hash to speed up the detection of two
keys with identical primary hash values.
values, before the costly full comparison is done.
</para>
<para>
Not all the functions of the hash Abstract Data Type (ADT)
@@ -69,11 +69,6 @@ Reparent - let's suppose state DEST has been derived from state SRC. If
the SRC.depth+1 is less than DEST.depth than DEST's parent will be reassigned
to SRC. (if reparenting is enabled)

Secondary Hash - a hash value that is calculated for every state that is not
used to determine the location of the element in the hash table, but that is
used for comparison. That is done in order to avoid needlessly comparing two
different states with the same hash value.

Soft DFS - A depth-first search scan that does not utilize procedural
recursion. In Freecell Solver, this utilizes a stack of records, each
containing the current state, the current test, the list of derived states,
@@ -1668,3 +1668,193 @@ Finished at 1528824800.544410 (total_num_iters=5948108)
</DUMP>

( DUMPS-1528824796-p/dump004 )

---------------------------------------------------------

export FCS_PGO_THEME="-l lg"
ARGS="--worker-step 25 " bash scripts/time-threads-num.bash 4 4 x Several Times
forking solver and threaded solver
commit bc743e9d30d9a5e75796ab556f9fc629fdf2ae69
(commit Date: Sat May 25 16:35:13 2019 +0300 )
Without (!) Profile Guided Optimisation (PGO).
../source/Tatzer -l extra_speed2
(With -flto and -fwhole-program).
Without (!) Makefile.gnu
sudo_renice.
-O3
gcc-8.3.1-0.20190517.1.mga7
tcmalloc from mageia.
With strip.

2.95781707763672s

Highlight: xxHash-0.7.0's XXH3

<DUMP>
Started at 1558788986.935696
Reached Board No. 4000 at 1558788987.293328
Reached Board No. 8000 at 1558788987.643669
Reached Board No. 12000 at 1558788988.001898
Reached Board No. 16000 at 1558788988.458833
Unsolved Board No. 11982 at 1558788988.627253
Reached Board No. 20000 at 1558788988.849039
Reached Board No. 24000 at 1558788989.173243
Reached Board No. 28000 at 1558788989.515773
Reached Board No. 32000 at 1558788989.889027
Finished at 1558788989.893513 (total_num_iters=5886704)
</DUMP>

( DUMPS-1558788985-t/dump004 )

---------------------------------------------------------

export FCS_PGO_THEME="-l lg"
ARGS="--worker-step 25 " bash scripts/time-threads-num.bash 4 4 x Several Times
forking solver and threaded solver
commit a75f830df57e0b3f4b69442c278b01d7bcf2409e
(commit Date: Tue Jan 7 15:24:03 2020 +0200 )
Without (!) Profile Guided Optimisation (PGO).
../source/Tatzer -l extra_speed2
(With -flto and -fwhole-program).
Without (!) Makefile.gnu
sudo_renice.
-O3
gcc 9.2.0 ( /home/shlomif/apps/prog/gcc-9.2.0/bin/gcc )
tcmalloc from mageia.
Without strip.

2.93454504013062s

Highlight: the corrected stack_compare optimisation.

<DUMP>
Started at 1578409934.503910
Reached Board No. 4000 at 1578409934.857714
Reached Board No. 8000 at 1578409935.205428
Reached Board No. 12000 at 1578409935.561337
Reached Board No. 16000 at 1578409936.014925
Unsolved Board No. 11982 at 1578409936.181964
Reached Board No. 20000 at 1578409936.403463
Reached Board No. 24000 at 1578409936.724039
Reached Board No. 28000 at 1578409937.063669
Reached Board No. 32000 at 1578409937.435151
Finished at 1578409937.438455 (total_num_iters=5886704)
</DUMP>

( DUMPS-1578409933-t/dump004 )

---------------------------------------------------------

export FCS_PGO_THEME="-l lg"
ARGS="--worker-step 25 " bash scripts/time-threads-num.bash 4 4 x Several Times
forking solver and threaded solver
commit 0f3662cf7576e860dd6271a156390102e2665234
(commit Date: Sun Feb 9 19:20:31 2020 +0200 )
Without (!) Profile Guided Optimisation (PGO).
../source/Tatzer -l extra_speed2
(With -flto and -fwhole-program).
Without (!) Makefile.gnu
sudo_renice.
-O3
/usr/bin/gcc
tcmalloc from mageia.
Without strip.

2.90572094917297s

Highlight: change the int width of game_type_limit.h

<DUMP>
Started at 1581268654.208853
Reached Board No. 4000 at 1581268654.558971
Reached Board No. 8000 at 1581268654.902648
Reached Board No. 12000 at 1581268655.255234
Reached Board No. 16000 at 1581268655.704662
Unsolved Board No. 11982 at 1581268655.875459
Reached Board No. 20000 at 1581268656.090102
Reached Board No. 24000 at 1581268656.407606
Reached Board No. 28000 at 1581268656.743964
Reached Board No. 32000 at 1581268657.111305
Finished at 1581268657.114574 (total_num_iters=5886704)
</DUMP>

( DUMPS-1581268653-t/dump004 )

---------------------------------------------------------

export FCS_PGO_THEME="-l lg"
ARGS="--worker-step 25 " bash scripts/time-threads-num.bash 4 4 x Several Times
forking solver and threaded solver
commit 47d92571f9f10487253ca3360d254f5732add197
(commit Date: Sun Feb 9 19:49:32 2020 +0200 )
Without (!) Profile Guided Optimisation (PGO).
../source/Tatzer -l extra_speed2
(With -flto and -fwhole-program).
Without (!) Makefile.gnu
sudo_renice.
-O3
gcc 9.2.0 ( /home/shlomif/apps/prog/gcc-9.2.0/bin/gcc )
tcmalloc from mageia.
Without strip.

2.88306212425232s

Highlight: change the int width of game_type_limit.h & gcc9.2.0

<DUMP>
Started at 1581270651.030736
Unsolved Board No. 11982 at 1581270652.686524
Started at 1581270651.030736
Started at 1581270651.030736
Started at 1581270651.030736
Started at 1581270651.030736
Reached Board No. 4000 at 1581270651.380751 (total_num_iters=712094)
Reached Board No. 8000 at 1581270651.721421 (total_num_iters=1429370)
Reached Board No. 12000 at 1581270652.066771 (total_num_iters=2152005)
Reached Board No. 16000 at 1581270652.511171 (total_num_iters=2856277)
Reached Board No. 20000 at 1581270652.895865 (total_num_iters=3772186)
Reached Board No. 24000 at 1581270653.209845 (total_num_iters=4435931)
Reached Board No. 28000 at 1581270653.543833 (total_num_iters=5134085)
Reached Board No. 32000 at 1581270653.913271 (total_num_iters=5886704)
Finished at 1581270653.913798 (total_num_iters=5886704)
</DUMP>

( DUMPS-1581270650-p/dump004 )

---------------------------------------------------------

export FCS_PGO_THEME="-l lg"
ARGS="--worker-step 25 " bash scripts/time-threads-num.bash 4 4 x Several Times
forking solver and threaded solver
commit f213d60f3fe282222156b6cf0855a40fb5e1b167
(commit Date: Mon Apr 20 23:23:57 2020 +0300 )
Without (!) Profile Guided Optimisation (PGO).
../source/Tatzer -l extra_speed2
(With -flto and -fwhole-program).
Without (!) Makefile.gnu
sudo_renice.
-O3
gcc 7.3.0 ( /home/shlomif/apps/prog/gcc-7.3.0/bin/gcc )
tcmalloc from mageia.
Without strip.

2.52526593208313s

Highlight: converting the fc-only "Tatzer" themes to use
COMPACT_STATES instead of INDIRECT_STACK_STATES .

<DUMP>
Started at 1587386659.786149
Reached Board No. 4000 at 1587386660.090267
Reached Board No. 8000 at 1587386660.388812
Reached Board No. 12000 at 1587386660.694323
Reached Board No. 16000 at 1587386661.083330
Unsolved Board No. 11982 at 1587386661.239350
Reached Board No. 20000 at 1587386661.422504
Reached Board No. 24000 at 1587386661.698053
Reached Board No. 28000 at 1587386661.989522
Reached Board No. 32000 at 1587386662.306795
Finished at 1587386662.311415 (total_num_iters=5886704)
</DUMP>

( DUMPS-1587386658-t/dump004 )
@@ -8,7 +8,7 @@ Shlomi Fish <shlomif@cpan.org>
Update: The split-FCC improvement
----------------------------------

First of all see link:split-fully-connected-components-based-solver-planning.asciidoc[the split fully connect components ("FCC") spec]. Thereby we keep a fingerprint of
First of all see link:split-fully-connected-components-based-solver-planning.asciidoc[the split fully connected components ("FCC") spec]. Thereby we keep a fingerprint of
the game state using 52 enums of three states (= { ORIG_POS = 0, ABOVE_PARENT_CARD_OR_EMPTY_SPACE = 1, IN_FOUNDATIONS = 2 } ) each.

Now, if card is at ORIG_POS or IN_FOUNDATIONS then its deBondt encoding is
@@ -0,0 +1,13 @@
Apparently, in recent versions of Microsoft Windows FreeCell on Windows 10, the
deal number display there is misleading for the "Random" deals. This appears to
be a bug in MS FreeCell. One can instruct it to deal a numbered deal, or
alternatively input the cards' layout into the web-based solver manually using
the text notation.

We apologise for the inconvenience, but note that it is not our fault and it is
up to Microsoft to fix it.

We can recommend that you try PySol FC ( https://pysolfc.sourceforge.io/ )
instead, which shares some maintainers with Freecell Solver, and which is FOSS
(see https://en.wikipedia.org/wiki/Free_and_open-source_software ) and gratis
and should run fine on Windows and other platforms.
@@ -0,0 +1,50 @@
I am using [QUnit](https://github.com/qunitjs/qunit/) in an MIT-licensed
project written in part in TypeScript. I have some TS functions that
accept the QUnit as a parameter and wish to type them as its interface
from [the typing](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/qunit)

E.g:

```typescript
import { QUnit } from "qunit";


export function run_tests(q: QUnit)
{
q.module((a) => { ... });
}
```

However, when I try, I am getting this error:

```
tsc --project lib/typescript/www/tsconfig.json
src/ts/web-fc-solve-tests.ts(12,23): error TS2306: File '/home/shlomif/progs/fre
ecell/git/fc-solve/fc-solve/site/wml/node_modules/@types/qunit/index.d.ts' is no
t a module.
```

Here is my code (note the branch): https://github.com/shlomif/fc-solve/tree/qunit-typescript - it is under the `fc-solve/site/wml` sub directory.

My `tsconfig.json` is:

```json
{
"compilerOptions": {
"baseUrl": ".",
"esModuleInterop": true,
"module": "amd",
"moduleResolution": "node",
"noImplicitReturns": true,
"outDir": "../../../lib/out-babel/js",
"paths": {
"big-integer": ["node_modules/big-integer/BigInteger.d.ts"],
"qunit": ["node_modules/@types/qunit"]
},
"target":"es6"
},
"include": ["../../../src/ts/**/*.ts"]
}
```

Thanks for any help.
@@ -105,12 +105,12 @@

my $recs = $max_scan->{r};
my $iters_count = max(
map { $_->[$ITERS_IDX] }
map { $_->[$ITERS_IDX] }
grep { $_->[$STATUS_IDX] && ( $_->[$TIME_DELTA_IDX] < $quota ) }
@{$recs}
);
my $time_delta = max(
map { $_->[$TIME_DELTA_IDX] }
map { $_->[$TIME_DELTA_IDX] }
grep { $_->[$STATUS_IDX] && ( $_->[$TIME_DELTA_IDX] < $quota ) }
@{$recs}
);
@@ -63,5 +63,5 @@ sub read_state

print "Counts:\n";
print map { "$_ => $encoded_counts{$_}\n" }
sort { $a <=> $b } keys(%encoded_counts);
sort { $a <=> $b } keys(%encoded_counts);
}
@@ -1,2 +1,2 @@
#!/bin/bash
sudo_renice bash ../scripts/run-variant-sequence.sh 1 1000
sudo_renice bash ../scripts/run-variant-sequence.sh 1 2500
@@ -25,7 +25,7 @@ use MooX qw/late/;

has 'deal' => ( is => 'ro' );
has 'output' => ( is => 'ro', lazy => 1 );
has 'iters' => (
has 'iters' => (
is => 'ro',
lazy => 1,
default => sub { my $self = shift; return FindSeed::f( $self->output ); },
@@ -1,7 +1,7 @@
DEBUG = 0
PROFILE = 0
WITH_TRACES = 0
FREECELL_ONLY = 1
FREECELL_ONLY = 0
DISABLE_PATSOLVE = 1
DISABLE_SIMPLE_SIMON := 0
OPT_FOR_SIZE = 0
@@ -20,7 +20,7 @@ ifeq ($(FREECELL_ONLY),1)
DISABLE_SIMPLE_SIMON := 1
endif

CFLAGS := -I$(PWD) -I$(PWD)/include -I$(SRC_DIR)/include -I$(SRC_DIR) -I$(SRC_DIR)/patsolve/patsolve/include -I$(SRC_DIR)/patsolve/patsolve -I$(SRC_DIR)/xxHash-wrapper -I$(SRC_DIR)/xxHash-wrapper/xxHash-0.6.5 -D_GNU_SOURCE
CFLAGS := -I$(PWD) -I$(PWD)/include -I$(SRC_DIR)/include -I$(SRC_DIR) -I$(SRC_DIR)/patsolve/patsolve/include -I$(SRC_DIR)/patsolve/patsolve -I$(SRC_DIR)/xxHash-wrapper -I$(SRC_DIR)/xxHash-wrapper/xxHash-0.7.2 -D_GNU_SOURCE
GCC_COMPAT :=
INIT_CFLAGS := -Wp,-MD,.deps/$(*F).pp

@@ -213,22 +213,26 @@ THR_MAIN_OBJECT := threaded_range_solver.o
FORK_MAIN_OBJECT := forking_range_solver.o
#>>>OBJECTS.END

OBJECTS := $(GEN_C_OBJECTS) $(SOURCE_OBJECTS)

PAT_OBJECTS = \
param.o \
patsolve.o \
pat.o \
tree.o \

ifeq ($(DISABLE_SIMPLE_SIMON),0)
OBJECTS += simpsim.o
GEN_C_OBJECTS += fcs_is_ss_false_parent.o
GEN_C_OBJECTS += fcs_is_ss_true_parent.o
SOURCE_OBJECTS += simpsim.o
endif

ifeq ($(FREECELL_ONLY),0)
OBJECTS += preset.o
SOURCE_OBJECTS += card.o
SOURCE_OBJECTS += fc_pro_iface.o
SOURCE_OBJECTS += preset.o
endif

OBJECTS := $(GEN_C_OBJECTS) $(SOURCE_OBJECTS)

# MYOBJ.o ==> .deps/MYOBJ.P
DEP_FILES = $(addprefix .deps/,$(addsuffix .pp,$(basename $(OBJECTS))))

@@ -248,7 +252,7 @@ $(PAT_OBJECTS): %.o: $(SRC_DIR)/patsolve/patsolve/%.c
STATIC_LIB_BASE = fcs
STATIC_LIB = lib$(STATIC_LIB_BASE).a

FCS_OBJECTS = $(OBJECTS)
FCS_OBJECTS := $(OBJECTS)

ifeq ($(DISABLE_PATSOLVE),0)
FCS_OBJECTS += $(PAT_OBJECTS)
@@ -19,7 +19,6 @@ endif
DATA_DESTDIR ?= __DESTDIR
RESULT_NODE_JS_EXE = fc-solve.js
RESULT_JS_LIB = libfreecell-solver$(LIBSUF).js
RESULT_HTML = fc-solve-test.html
PROCESS_PL = $(SRC_DIR)/scripts/process-js-html.pl
EMBED_FILE_MUNGE_PL = $(SRC_DIR)/../scripts/emscripten-embed-munge.pl

@@ -47,6 +46,7 @@ state.c \
$(PATS_C_FILES)

CMAKE_C_FILES = \
fcs_is_ss_true_parent.c \
is_king.c \
is_parent.c \
move_funcs_maps.c \
@@ -64,9 +64,10 @@ LLVM_BITCODE_FILES = $(patsubst %.c,%.bc,$(C_FILES))
LLVM_BITCODE_LIB_FILES = $(patsubst %.c,%.bc,$(LIB_C_FILES))
LLVM_BITCODE_CMAKE_FILES = $(patsubst %.c,%.bc,$(CMAKE_C_FILES))

all: $(RESULT_NODE_JS_EXE) $(RESULT_JS_LIB)
all: $(RESULT_JS_LIB)

NEEDED_FUNCTIONS = \
fc_solve__hll_ms_rand__get_singleton \
fc_solve__hll_ms_rand__init \
fc_solve__hll_ms_rand__mod_rand \
fc_solve_user__find_deal__alloc \
@@ -75,6 +76,10 @@ NEEDED_FUNCTIONS = \
fc_solve_user__find_deal__run \
free \
freecell_solver_user_alloc \
freecell_solver_user_args_man_argc \
freecell_solver_user_args_man_argv \
freecell_solver_user_args_man_chop \
freecell_solver_user_args_man_free \
freecell_solver_user_cmd_line_parse_args_with_file_nesting_count \
freecell_solver_user_cmd_line_read_cmd_line_preset \
freecell_solver_user_current_state_stringify \
@@ -83,12 +88,14 @@ NEEDED_FUNCTIONS = \
freecell_solver_user_get_next_move \
freecell_solver_user_get_num_freecells \
freecell_solver_user_get_num_stacks \
freecell_solver_user_get_unrecognized_cmd_line_flag \
freecell_solver_user_get_unrecognized_cmd_line_flag_status \
freecell_solver_user_limit_iterations_long \
freecell_solver_user_resume_solution \
freecell_solver_user_solve_board \
freecell_solver_user_stringify_move_ptr \
malloc \
fc_solve__hll_ms_rand__get_singleton \


NEEDED_FUNCTIONS_STR := $(shell perl -e 'print join(", ", map { chr(0x27) . "_" . $$_ . chr(0x27) } @ARGV)' $(NEEDED_FUNCTIONS))

@@ -99,9 +106,14 @@ OPT_FLAGS = -O3
# OPT_FLAGS =
# OPT_FLAGS = -g

CFLAGS = $(OPT_FLAGS) -I $(DATA_DESTDIR)/fc-solve/include -I ./include -I . -I $(SRC_DIR)/include -I $(SRC_DIR) -I $(SRC_DIR)/asprintf-1.0 -I $(SRC_DIR)/patsolve/patsolve/include -I $(SRC_DIR)/patsolve/patsolve/ -I $(SRC_DIR)/xxHash-wrapper -I $(SRC_DIR)/xxHash-wrapper/xxHash-0.6.5 -I $(CMAKE_DIR) -m32 -std=gnu99 -DFC_SOLVE_JAVASCRIPT_QUERYING=1
RINUTILS_BASE_DIR ?= $(CMAKE_DIR)
RINUTILS_DIR ?= $(RINUTILS_BASE_DIR)/rinutils-include
RINUTILS_INCLUDE_DIR := $(RINUTILS_DIR)/include
RINUTILS_PIVOT = $(RINUTILS_INCLUDE_DIR)/rinutils/rinutils.h

ASSERT_FLAGS = -s ASSERTIONS=1
CFLAGS = $(OPT_FLAGS) -I $(DATA_DESTDIR)/fc-solve/include -I ./include -I $(RINUTILS_INCLUDE_DIR) -I . -I $(SRC_DIR)/include -I $(SRC_DIR) -I $(SRC_DIR)/asprintf-1.0 -I $(SRC_DIR)/patsolve/patsolve/include -I $(SRC_DIR)/patsolve/patsolve/ -I $(SRC_DIR)/xxHash-wrapper -I $(SRC_DIR)/xxHash-wrapper/xxHash-0.7.2 -I $(CMAKE_DIR) -I $(CMAKE_DIR)/include -m32 -std=gnu99 -DFC_SOLVE_JAVASCRIPT_QUERYING=1

# ASSERT_FLAGS = -s ASSERTIONS=1
ASSERT_FLAGS =

EMCC_CFLAGS = -s WASM=$(WASM) -s TOTAL_MEMORY="$$((128 * 1024 * 1024))" -s EXPORTED_FUNCTIONS="[$(NEEDED_FUNCTIONS_STR)]" -s EXTRA_EXPORTED_RUNTIME_METHODS="['allocate', 'cwrap', 'getValue', 'intArrayFromString', 'setValue', 'ALLOC_STACK', 'FS', 'UTF8ToString']" $(WASM_FLAGS) -s MODULARIZE=1 $(CFLAGS) $(ASSERT_FLAGS)
@@ -122,8 +134,10 @@ $(LLVM_BITCODE_FILES): %.bc: $(SRC_DIR)/%.c

LLVM_AND_FILES_TARGETS = $(LLVM_BITCODE_FILES) $(LLVM_BITCODE_CMAKE_FILES)

$(RESULT_HTML): $(LLVM_AND_FILES_TARGETS)
emcc $(EMCC_CFLAGS) -o $@ $(LLVM_BITCODE_FILES) $(LLVM_BITCODE_CMAKE_FILES) $(EMCC_POST_FLAGS)
$(LLVM_AND_FILES_TARGETS): $(RINUTILS_PIVOT)

$(RINUTILS_PIVOT):
rin="$$(perl -MPath::Tiny -e 'print path(shift)->absolute' "$(RINUTILS_DIR)")"; unset CFLAGS ; (git clone https://github.com/shlomif/rinutils && cd rinutils && mkdir b && cd b && cmake -DWITH_TEST_SUITE=OFF -DCMAKE_INSTALL_PREFIX="$$rin" .. && make && make install && cd ../.. && rm -fr rinutils)

$(RESULT_NODE_JS_EXE): $(LLVM_AND_FILES_TARGETS)
emcc $(EMCC_CFLAGS) -o $@ $(LLVM_BITCODE_FILES) $(LLVM_BITCODE_CMAKE_FILES) $(EMCC_POST_FLAGS)
@@ -137,7 +151,7 @@ $(RESULT_JS_LIB): $(LLVM_AND_FILES_TARGETS)
mv -f temp.$@ $@

clean:
rm -f $(LLVM_BITCODE_FILES) $(RESULT_HTML) $(RESULT_NODE_JS_EXE)
rm -f $(LLVM_BITCODE_FILES) $(RESULT_NODE_JS_EXE)

%.show:
@echo "$* = $($*)"