#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 56;
use Test::Differences qw/ eq_or_diff /;

use FC_Solve::DeltaStater             ();
use FC_Solve::DeltaStater::BitReader  ();
use FC_Solve::DeltaStater::BitWriter  ();
use FC_Solve::DeltaStater::DeBondt    ();
use FC_Solve::VarBaseDigitsReader     ();
use FC_Solve::VarBaseDigitsReader::XS ();
use FC_Solve::VarBaseDigitsWriter     ();
use FC_Solve::VarBaseDigitsWriter::XS ();

package main;

my $RANK_J = 11;
my $RANK_Q = 12;
my $RANK_K = 13;

{
    my @suits       = (qw(H C D S));
    my %suit_to_idx = do
    {
        my $s = Games::Solitaire::Verify::Card->get_suits_seq();
        ( map { $s->[$_] => $_ } ( 0 .. $#$s ) );
    };

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

        my $suit = $args->{suit};
        my $rank = $args->{rank};

        if ( !exists( $suit_to_idx{$suit} ) )
        {
            die "Unknown suit '$suit'.";
        }
        return ( $suit_to_idx{$suit} | ( $rank << 2 ) );
    }

}

{
    # MS Freecell No. 982 Initial state.
    my $delta = FC_Solve::DeltaStater->new(
        {
            init_state_str => <<"EOF"
Foundations: H-0 C-0 D-A S-0
Freecells:
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 4S JC 6H 5H
: 2H 2D 3S 5D 9D QS KS
: 6S TD QC KH AS AH 7C
: KC 4H TH 7S 2C 9S
: AC QD 8D QH 3D 8S
: 7H 7D JD JH TS 6C
: 4C 4D 5S 2S JS 8H
EOF
        }
    );

    # TEST
    ok( $delta, 'Object was initialized correctly.' );

    $delta->set_derived(
        {
            state_str => <<"EOF"
Foundations: H-0 C-2 D-A S-0
Freecells:  8D  QD
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 8S
: 2H 2D 3S 5D 9D QS KS QH JC
: 6S TD QC KH AS AH 7C 6H
: KC 4H TH 7S
: 9S
: 7H 7D JD JH TS 6C 5H 4S 3D
: 4C 4D 5S 2S JS 8H
EOF
        }
    );

    # TEST
    eq_or_diff(
        $delta->get_foundations_bits(),

        # Given as an array reference of $num_bits => $bits array refs.
        [
            [ 4 => 0, ],    # Hearts
            [ 4 => 2, ],    # Clubs
            [ 4 => 1, ],    # Diamonds
            [ 4 => 0, ],    # Spades
        ],
        'get_foundations_bits works',
    );

    # TEST
    eq_or_diff(
        $delta->get_column_encoding(0),
        [
            [ 3 => 6 ],     # Orig len.
            [ 4 => 0 ],     # Derived len.
        ],
        'get_column_lengths_bits() works',
    );

    my $HC = [ 1 => 0, ];
    my $DS = [ 1 => 1, ];

    # TEST
    eq_or_diff(
        $delta->get_column_encoding(1),
        [
            [ 3 => 3 ],     # Orig len.
            [ 4 => 1 ],     # Derived len.
            $DS,            # 8S
        ],
        'get_column_lengths_bits() works',
    );

    # TEST
    eq_or_diff(
        $delta->get_column_encoding(5),
        [
            [ 3 => 0 ],                                           # Orig len.
            [ 4 => 1 ],                                           # Derived len.
            [ 6 => _card_to_bin( { suit => 'S', rank => 9, } ) ], # 9S
        ],
        'get_column_lengths_bits() works',
    );

    # TEST
    eq_or_diff(
        $delta->get_freecells_encoding(),
        [
            [ 6 => _card_to_bin( { suit => 'D', rank => 8 } ), ],          # 8D
            [ 6 => _card_to_bin( { suit => 'D', rank => $RANK_Q } ), ],    # QD
        ],
        'Freecells',
    );
}

{
    my $bit_writer = FC_Solve::DeltaStater::BitWriter->new;

    # TEST
    ok( $bit_writer, 'Init bit_writer' );

    $bit_writer->write( 4 => 5 );
    $bit_writer->write( 2 => 1 );

    # TEST
    eq_or_diff(
        $bit_writer->get_bits(),
        chr( 5 | ( 1 << 4 ) ),
        "write() test",
    );
}

{
    my $bit_reader = FC_Solve::DeltaStater::BitReader->new(
        { bits => chr( 3 | ( 4 << 3 ) ) } );

    # TEST
    ok( $bit_reader, 'Init bit_reader' );

    # TEST
    is( $bit_reader->read(3), 3, 'bit_reader->read(3)' );

    # TEST
    is( $bit_reader->read(4), 4, 'bit_reader->read(4)' );
}

{
    # MS Freecell No. 982 Initial state.
    my $delta = FC_Solve::DeltaStater->new(
        {
            init_state_str => <<"EOF"
Foundations: H-0 C-0 D-A S-0
Freecells:
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 4S JC 6H 5H
: 2H 2D 3S 5D 9D QS KS
: 6S TD QC KH AS AH 7C
: KC 4H TH 7S 2C 9S
: AC QD 8D QH 3D 8S
: 7H 7D JD JH TS 6C
: 4C 4D 5S 2S JS 8H
EOF
        }
    );

    # TEST
    ok( $delta, 'Object was initialized correctly.' );

    $delta->set_derived(
        {
            state_str => <<"EOF"
Foundations: H-0 C-2 D-A S-0
Freecells:  8D  QD
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 8S
: 2H 2D 3S 5D 9D QS KS QH JC
: 6S TD QC KH AS AH 7C 6H
: KC 4H TH 7S
: 9S
: 7H 7D JD JH TS 6C 5H 4S 3D
: 4C 4D 5S 2S JS 8H
EOF
        }
    );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode() )->to_string() ),
        <<"EOF",
Foundations: H-0 C-2 D-A S-0
Freecells:  8D  QD
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 8S
: 2H 2D 3S 5D 9D QS KS QH JC
: 6S TD QC KH AS AH 7C 6H
: KC 4H TH 7S
: 9S
: 7H 7D JD JH TS 6C 5H 4S 3D
: 4C 4D 5S 2S JS 8H
EOF
        'decode() works.',
    );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        <<"EOF",
Foundations: H-0 C-2 D-A S-0
Freecells:  8D  QD
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 8S
: 2H 2D 3S 5D 9D QS KS QH JC
: 6S TD QC KH AS AH 7C 6H
: KC 4H TH 7S
: 9S
: 7H 7D JD JH TS 6C 5H 4S 3D
: 4C 4D 5S 2S JS 8H
EOF
        'encode_composite() test No. 1.',
    );
}

# More encode_composite tests - this time from the output of:
# pi-make-microsoft-freecell-board -t 24 | ./fc-solve -to 01ABCDE --freecells-num 2 -s -i -p -t

{
    my $delta = FC_Solve::DeltaStater->new(
        {
            init_state_str => <<"EOF"
Foundations: H-0 C-0 D-0 S-0
Freecells:
: 4C 2C 9C 8C QS 4S 2H
: 5H QH 3C AC 3H 4H QD
: QC 9S 6H 9H 3S KS 3D
: 5D 2S JC 5C JH 6D AS
: 2D KD TH TC TD 8D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: 7S 6C 7D 4D 8S 9D
EOF
        }
    );

    # TEST
    ok( $delta, 'Object was initialized correctly.' );

    $delta->set_derived(
        {
            state_str => <<"EOF"
Foundations: H-0 C-0 D-0 S-4
Freecells:  KS  TD
: 2C
: 5H QH 3C AC 3H 4H QD JC TH 9C 8D 7S
: QC 9S 6H 9H 8C 7D 6C 5D 4C 3D
:
: 2D KD QS JH TC 9D 8S
: 7H JS KH TS KC 7C 6D 5C 4D
: AH 5S 6S AD 8H JD
: 2H

EOF
        }
    );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        <<"EOF",
Foundations: H-0 C-0 D-0 S-4
Freecells:  KS  TD
:
: 5H QH 3C AC 3H 4H QD JC TH 9C 8D 7S
: QC 9S 6H 9H 8C 7D 6C 5D 4C 3D
: 2H
: 2D KD QS JH TC 9D 8S
: 7H JS KH TS KC 7C 6D 5C 4D
: AH 5S 6S AD 8H JD
: 2C
EOF
        'encode_composite() test No. 2.',
    );

    $delta->set_derived(
        {
            state_str => <<"EOF"
Foundations: H-0 C-0 D-0 S-2
Freecells:  TD  4C
: 8S
: 5H QH 3C AC 3H 4H 3S 2H
: QC 9S 6H 9H 8C 7D 6C 5D 4S 3D 2C
: 5C 4D
: 2D KD QS JH TC 9D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: KS QD JC TH 9C 8D 7S 6D
EOF
        }
    );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        <<"EOF",
Foundations: H-0 C-0 D-0 S-2
Freecells:  TD  4C
: 5C 4D
: 5H QH 3C AC 3H 4H 3S 2H
: QC 9S 6H 9H 8C 7D 6C 5D 4S 3D 2C
: 8S
: 2D KD QS JH TC 9D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: KS QD JC TH 9C 8D 7S 6D
EOF
        'encode_composite() test No. 2.',
    );

}

# Make sure encode_composite avoids permutations of empty columns
# and completely-non-original states.
{
    my $delta = FC_Solve::DeltaStater->new(
        {
            init_state_str => <<"EOF",
Foundations: H-K C-K D-J S-Q
Freecells:  KD
:
:
:
: KS QD
:
:
:
:
EOF
        },
    );

    $delta->set_derived(
        {
            state_str => <<"EOF",
Foundations: H-K C-K D-J S-Q
Freecells:  QD  KD
:
:
:
:
:
: KS
:
:
EOF
        },
    );

    my $calc_enc_state = sub {
        return join '', unpack( "H*", $delta->encode_composite() );
    };

    my $first_state = $calc_enc_state->();

    $delta->set_derived(
        {
            state_str => <<"EOF",
Foundations: H-K C-K D-J S-Q
Freecells:  QD  KD
:
:
:
:
:
:
:
: KS
EOF
        }
    );

    my $second_state = $calc_enc_state->();

    # TEST
    is(
        $first_state,
        $second_state,
"Make sure encode_composite avoids permutations of empty columns and completely-non-original states.",
    );
}

# Make sure encode_composite avoids permutations of empty columns
# and completely-non-original states.
#
# Another edge-case.
{
    my $delta = FC_Solve::DeltaStater->new(
        {
            init_state_str => <<"EOF",
Foundations: H-K C-K D-J S-Q
Freecells:  KD
:
:
:
: KS QD
:
:
:
:
EOF
        },
    );

    $delta->set_derived(
        {
            state_str => <<"EOF",
Foundations: H-K C-K D-J S-Q
Freecells:  QD  KD
: KS
:
:
:
:
:
:
:
EOF
        },
    );

    my $calc_enc_state = sub {
        return join '', unpack( "H*", $delta->encode_composite() );
    };

    my $first_state = $calc_enc_state->();

    $delta->set_derived(
        {
            state_str => <<"EOF",
Foundations: H-K C-K D-J S-Q
Freecells:  QD  KD
:
:
:
:
:
:
:
: KS
EOF
        }
    );

    my $second_state = $calc_enc_state->();

    # TEST
    is( $first_state, $second_state,
        "encode_composite avoids permutations - #2",
    );
}

{
    my $reader =
        FC_Solve::VarBaseDigitsReader->new( { data => ( 3 | ( 12 << 3 ) ) } );

    # TEST
    ok( $reader, 'Init var_reader' );

    # TEST
    is( $reader->read( 1 << 3 ), 3, 'reader->read(1 << 3)' );

    # TEST
    is( $reader->read( 1 << 4 ), 8 + 4, 'reader->read(1 << 4)' );
}

{
    my $reader = FC_Solve::VarBaseDigitsReader->new(
        {
            data => ( 24 + 8 * 52 + 7 * 11 * 52 )
        }
    );

    # TEST
    ok( $reader, 'Init var_reader' );

    # TEST
    is( $reader->read(52), 24, 'reader->read(24)' );

    # TEST
    is( $reader->read(11), 8, 'reader->read(11)' );

    # TEST
    is( $reader->read(10), 7, 'reader->read(10)' );
}

# TEST:$c=2;
foreach my $classes_rec (
    {
        type => 'perl',
        w    => 'FC_Solve::VarBaseDigitsWriter',
        r    => 'FC_Solve::VarBaseDigitsReader',
    },
    {
        type => 'XS',
        w    => 'FC_Solve::VarBaseDigitsWriter::XS',
        r    => 'FC_Solve::VarBaseDigitsReader::XS',
    },
    )
{
    my $type   = $classes_rec->{type};
    my $writer = $classes_rec->{w}->new;

    # TEST*$c
    ok( $writer, "Init var_writer - $type" );

    $writer->write( { item => 24, base => 52, } );
    $writer->write( { item => 8,  base => 11, } );
    $writer->write( { item => 7,  base => 10, } );

    my $reader = $classes_rec->{r}->new(
        {
            data => $writer->get_data(),
        }
    );

    # TEST*$c
    ok( $reader, "Init var_reader - $type" );

    # TEST*$c
    is( $reader->read(52), 24, "writer-to-reader->read(24) - $type" );

    # TEST*$c
    is( $reader->read(11), 8, "writer-to-reader->read(11) - $type" );

    # TEST*$c
    is( $reader->read(10), 7, "writer-to-reader->read(10) - $type" );
}

{
    # MS Freecell No. 982 Initial state.
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            init_state_str => <<"EOF"
Foundations: H-0 C-0 D-A S-0
Freecells:
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 4S JC 6H 5H
: 2H 2D 3S 5D 9D QS KS
: 6S TD QC KH AS AH 7C
: KC 4H TH 7S 2C 9S
: AC QD 8D QH 3D 8S
: 7H 7D JD JH TS 6C
: 4C 4D 5S 2S JS 8H
EOF
        }
    );

    # TEST
    ok( $delta, 'Object was initialized correctly.' );

    $delta->set_derived(
        {
            state_str => <<"EOF"
Foundations: H-0 C-2 D-A S-0
Freecells:  8D  QD
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 8S
: 2H 2D 3S 5D 9D QS KS QH JC
: 6S TD QC KH AS AH 7C 6H
: KC 4H TH 7S
: 9S
: 7H 7D JD JH TS 6C 5H 4S 3D
: 4C 4D 5S 2S JS 8H
EOF
        }
    );

    # TEST
    ok( $delta->encode_composite(), "->encode_composite runs fine." );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        <<"EOF",
Foundations: H-0 C-2 D-A S-0
Freecells:  8D  QD
: 6D 3C 3H KD 8C 5C
: TC 9C 9H 8S
: 2H 2D 3S 5D 9D QS KS QH JC
: 6S TD QC KH AS AH 7C 6H
: KC 4H TH 7S
: 9S
: 7H 7D JD JH TS 6C 5H 4S 3D
: 4C 4D 5S 2S JS 8H
EOF
        'DeBondt encode_composite()+decode() test No. 1.',
    );
}

{

    my $init_state = <<"EOF";
Foundations: H-0 C-0 D-A S-0
Freecells:
: AH 5C 3S TD 5S 2H 9S
: 8S AS 5D 7S QH TC
: 2D 9C KC JD 8C TH 7C
: QS KH 3H 7H 9D 6D TS
: 4C 4D KD 8H KS 6H
: 9H 2C 5H JH QD 6C
: 2S 3C 6S JC 4H QC
: 3D 4S 8D 7D AC JS
EOF

    # MS Freecell No. 5 Initial state. - chosen because it has
    # an Ace at the topmost position in the stack.
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            init_state_str => $init_state,
        }
    );

    # TEST
    ok( $delta, 'Object was initialized correctly.' );

    $delta->set_derived( { state_str => $init_state, } );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        $init_state,
        'DeBondt encode_composite()+decode() test for leading Aces',
    );
}

{
    # PySol Baker's Dozen deal No. 24
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            variant        => "bakers_dozen",
            init_state_str => <<"EOF",
Foundations: H-A C-2 D-0 S-A
Freecells:
: 2H JH 6S QH
: 4H TC 6C QC
: 4S 5C 5S 5H
: 6D AD 3C 2D
: 7C QS JC
: 8D 4D 6H 7H
: 8S 9H JS 4C
: JD 3H TH 7S
: QD TD 7D 9S
: KH 3S 9D
: KC 3D 8C 2S
: KD 8H
: KS TS 9C 5D
EOF
        }
    );

    # TEST
    ok( $delta, 'Baker Dozen Object was initialized correctly.' );

    my $derived_str = <<"EOF";
Foundations: H-A C-5 D-5 S-2
Freecells:
: 2H JH
: 4H TC 6C QC
: 4S
: 6D
: 7C
: 8D
: 8S
: JD 3H TH 9H
: QD TD 7D 9S 8C 7H 6H 5H
: KH 3S 9D
: KC QS JS
: KD QH JC
: KS TS 9C 8H 7S 6S 5S
EOF

    $delta->set_derived(
        {
            state_str => $derived_str,
        }
    );

    # TEST
    ok( $delta->encode_composite(),
        "Baker's Dozen ->encode_composite runs fine." );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        $derived_str,
        "Baker's Dozen DeBondt encode_composite()+decode() test No. 1.",
    );
}

{
    # PySol Baker's Dozen deal No. 86
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            variant        => "bakers_dozen",
            init_state_str => <<"EOF",
Foundations: H-0 C-2 D-A S-0
Freecells:
: QH TD QD JH
: 4C 4D 3D 9C
: KH 2D QC 8D
: 4S 8H 6C 6H
: 6S JC 5D TS
: 9H AH 6D 5C
: KC 7S 4H
: 9S AS 7C 3C
: KS 8S 9D TC
: JD TH
: QS 8C 7D 3S
: 3H 7H 5S JS
: KD 5H 2H 2S
EOF
        }
    );

    # TEST
    ok( $delta, 'Baker Dozen Object was initialized correctly.' );

    my $derived_str = <<"EOF";
Foundations: H-0 C-2 D-A S-0
Freecells:
: QH TD QD JH
: 4C 4D 3D 9C
: KH 2D QC 8D
: 4S 8H 6C 6H
: 6S JC 5D TS
: 9H AH 6D 5C
: KC 7S 4H
: 9S AS 7C 3C
: KS 8S 9D TC
: JD TH
: QS 8C 7D 3S
: 3H 7H 5S JS
: KD 5H 2H 2S
EOF

    $delta->set_derived(
        {
            state_str => $derived_str,
        }
    );

    # TEST
    ok( $delta->encode_composite(),
        "Baker's Dozen ->encode_composite (No. 2) runs fine." );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        $derived_str,
        "Baker's Dozen DeBondt encode_composite()+decode() test No. 2.",
    );
}

{
    # PySol Baker's Dozen deal No. 86
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            variant        => "bakers_dozen",
            init_state_str => <<"EOF",
Foundations: H-0 C-2 D-A S-0
Freecells:
: QH TD QD JH
: 4C 4D 3D 9C
: KH 2D QC 8D
: 4S 8H 6C 6H
: 6S JC 5D TS
: 9H AH 6D 5C
: KC 7S 4H
: 9S AS 7C 3C
: KS 8S 9D TC
: JD TH
: QS 8C 7D 3S
: 3H 7H 5S JS
: KD 5H 2H 2S
EOF
        }
    );

    # TEST
    ok( $delta, 'Baker Dozen Object was initialized correctly.' );

    my $derived_str = <<"EOF";
Foundations: H-0 C-4 D-4 S-2
Freecells:
: QH TD QD JH TS
:
: KH
: 4S 8H 6C 5D
: 6S JC
: 9H AH 6D 5C
: KC 7S 4H 3S 2H
: 9S
: KS 8S 9D TC 9C 8D 7C
: JD TH
: QS 8C 7D 6H 5H
: 3H 7H 5S JS
: KD QC
EOF

    $delta->set_derived(
        {
            state_str => $derived_str,
        }
    );

    # TEST
    ok( $delta->encode_composite(),
        "Baker's Dozen ->encode_composite (No. 3) runs fine." );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        $derived_str,
        "Baker's Dozen DeBondt encode_composite()+decode() test No. 3.",
    );
}

{
    # PySol Baker's Dozen deal No. 281
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            variant        => "bakers_dozen",
            init_state_str => <<"EOF",
Foundations: H-2 C-0 D-0 S-2
Freecells:
: JC 3S 9D 4H
: KC QC 6D QS
: QH JH TS
: 4C 2D 3H 5H
: KS 5D TC JS
: AC 4D 8D 8S
: KH 3D 9C TH
: 3C 9S AD 4S
: 8C QD 2C
: 9H 6H TD
: KD 7C 6S 5C
: JD 8H 7D
: 7S 5S 7H 6C
EOF
        }
    );

    # TEST
    ok( $delta, 'Baker Dozen Object was initialized correctly.' );

    my $derived_str = <<"EOF";
Foundations: H-2 C-0 D-0 S-2
Freecells:
: JC 3S 9D 4H
: KC QC 6D QS
: QH JH TS
: 4C 2D 3H 5H
: KS 5D TC JS
: AC 4D 8D 8S
: KH 3D 9C TH
: 3C 9S AD 4S
: 8C QD 2C
: 9H 6H TD
: KD 7C 6S 5C
: JD 8H 7D
: 7S 5S 7H 6C
EOF

    $delta->set_derived(
        {
            state_str => $derived_str,
        }
    );

    # TEST
    ok( $delta->encode_composite(),
        "Baker's Dozen ->encode_composite (No. 4) runs fine." );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        $derived_str,
        "Baker's Dozen DeBondt encode_composite()+decode() test No. 4.",
    );
}

{
    # PySol Baker's Dozen deal No. 26698
    my $init_state_str = <<"EOF";
Foundations: H-0 C-2 D-2 S-2
Freecells:
: 9C 7D TC 8D
: JS 9D JC 4S
: 5H 3H 6H 5C
: 5D 6C 4H 8S
:
: JD TD QS 9S
: QC QH 6S 4C
: 3C AH 9H
: KS QD 4D 2H
: KD TS 7C 6D
: KH KC 3S 3D
: 7S TH 8H 5S
: 7H JH 8C
EOF
    my $delta = FC_Solve::DeltaStater::DeBondt->new(
        {
            variant        => "bakers_dozen",
            init_state_str => $init_state_str,
        }
    );

    # TEST
    ok( $delta, 'Baker Dozen Object was initialized correctly.' );

    my $derived_str = $init_state_str;

    $delta->set_derived(
        {
            state_str => $derived_str,
        }
    );

    # TEST
    ok( $delta->encode_composite(),
        "Baker's Dozen ->encode_composite (No. 5) runs fine." );

    # TEST
    eq_or_diff(
        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
        $derived_str,
        "Baker's Dozen DeBondt encode_composite()+decode() test No. 5.",
    );
}

__END__

=head1 COPYRIGHT AND LICENSE

This file is part of Freecell Solver. It is subject to the license terms in
the COPYING.txt file found in the top-level directory of this distribution
and at http://fc-solve.shlomifish.org/docs/distro/COPYING.html . No part of
Freecell Solver, including this file, may be copied, modified, propagated,
or distributed except according to the terms contained in the COPYING file.

Copyright (c) 2011 Shlomi Fish

=cut
