1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Test::More tests => 56;
7use Test::Differences qw/ eq_or_diff /;
8
9use FC_Solve::DeltaStater             ();
10use FC_Solve::DeltaStater::BitReader  ();
11use FC_Solve::DeltaStater::BitWriter  ();
12use FC_Solve::DeltaStater::DeBondt    ();
13use FC_Solve::VarBaseDigitsReader     ();
14use FC_Solve::VarBaseDigitsReader::XS ();
15use FC_Solve::VarBaseDigitsWriter     ();
16use FC_Solve::VarBaseDigitsWriter::XS ();
17
18my $RANK_Q = 12;
19
20{
21    my @suits       = (qw(H C D S));
22    my %suit_to_idx = do
23    {
24        my $s = Games::Solitaire::Verify::Card->get_suits_seq();
25        ( map { $s->[$_] => $_ } ( 0 .. $#$s ) );
26    };
27
28    sub _card_to_bin
29    {
30        my ($args) = @_;
31
32        my $suit = $args->{suit};
33        my $rank = $args->{rank};
34
35        if ( !exists( $suit_to_idx{$suit} ) )
36        {
37            die "Unknown suit '$suit'.";
38        }
39        return ( $suit_to_idx{$suit} | ( $rank << 2 ) );
40    }
41
42}
43
44{
45    # MS Freecell No. 982 Initial state.
46    my $delta = FC_Solve::DeltaStater->new(
47        {
48            init_state_str => <<"EOF"
49Foundations: H-0 C-0 D-A S-0
50Freecells:
51: 6D 3C 3H KD 8C 5C
52: TC 9C 9H 4S JC 6H 5H
53: 2H 2D 3S 5D 9D QS KS
54: 6S TD QC KH AS AH 7C
55: KC 4H TH 7S 2C 9S
56: AC QD 8D QH 3D 8S
57: 7H 7D JD JH TS 6C
58: 4C 4D 5S 2S JS 8H
59EOF
60        }
61    );
62
63    # TEST
64    ok( $delta, 'Object was initialized correctly.' );
65
66    $delta->set_derived(
67        {
68            state_str => <<"EOF"
69Foundations: H-0 C-2 D-A S-0
70Freecells:  8D  QD
71: 6D 3C 3H KD 8C 5C
72: TC 9C 9H 8S
73: 2H 2D 3S 5D 9D QS KS QH JC
74: 6S TD QC KH AS AH 7C 6H
75: KC 4H TH 7S
76: 9S
77: 7H 7D JD JH TS 6C 5H 4S 3D
78: 4C 4D 5S 2S JS 8H
79EOF
80        }
81    );
82
83    # TEST
84    eq_or_diff(
85        $delta->get_foundations_bits(),
86
87        # Given as an array reference of $num_bits => $bits array refs.
88        [
89            [ 4 => 0, ],    # Hearts
90            [ 4 => 2, ],    # Clubs
91            [ 4 => 1, ],    # Diamonds
92            [ 4 => 0, ],    # Spades
93        ],
94        'get_foundations_bits works',
95    );
96
97    # TEST
98    eq_or_diff(
99        $delta->get_column_encoding(0),
100        [
101            [ 3 => 6 ],     # Orig len.
102            [ 4 => 0 ],     # Derived len.
103        ],
104        'get_column_lengths_bits() works',
105    );
106
107    my $HC = [ 1 => 0, ];
108    my $DS = [ 1 => 1, ];
109
110    # TEST
111    eq_or_diff(
112        $delta->get_column_encoding(1),
113        [
114            [ 3 => 3 ],     # Orig len.
115            [ 4 => 1 ],     # Derived len.
116            $DS,            # 8S
117        ],
118        'get_column_lengths_bits() works',
119    );
120
121    # TEST
122    eq_or_diff(
123        $delta->get_column_encoding(5),
124        [
125            [ 3 => 0 ],                                           # Orig len.
126            [ 4 => 1 ],                                           # Derived len.
127            [ 6 => _card_to_bin( { suit => 'S', rank => 9, } ) ], # 9S
128        ],
129        'get_column_lengths_bits() works',
130    );
131
132    # TEST
133    eq_or_diff(
134        $delta->get_freecells_encoding(),
135        [
136            [ 6 => _card_to_bin( { suit => 'D', rank => 8 } ), ],          # 8D
137            [ 6 => _card_to_bin( { suit => 'D', rank => $RANK_Q } ), ],    # QD
138        ],
139        'Freecells',
140    );
141}
142
143{
144    my $bit_writer = FC_Solve::DeltaStater::BitWriter->new;
145
146    # TEST
147    ok( $bit_writer, 'Init bit_writer' );
148
149    $bit_writer->write( 4 => 5 );
150    $bit_writer->write( 2 => 1 );
151
152    # TEST
153    eq_or_diff(
154        $bit_writer->get_bits(),
155        chr( 5 | ( 1 << 4 ) ),
156        "write() test",
157    );
158}
159
160{
161    my $bit_reader = FC_Solve::DeltaStater::BitReader->new(
162        { bits => chr( 3 | ( 4 << 3 ) ) } );
163
164    # TEST
165    ok( $bit_reader, 'Init bit_reader' );
166
167    # TEST
168    is( $bit_reader->read(3), 3, 'bit_reader->read(3)' );
169
170    # TEST
171    is( $bit_reader->read(4), 4, 'bit_reader->read(4)' );
172}
173
174{
175    # MS Freecell No. 982 Initial state.
176    my $delta = FC_Solve::DeltaStater->new(
177        {
178            init_state_str => <<"EOF"
179Foundations: H-0 C-0 D-A S-0
180Freecells:
181: 6D 3C 3H KD 8C 5C
182: TC 9C 9H 4S JC 6H 5H
183: 2H 2D 3S 5D 9D QS KS
184: 6S TD QC KH AS AH 7C
185: KC 4H TH 7S 2C 9S
186: AC QD 8D QH 3D 8S
187: 7H 7D JD JH TS 6C
188: 4C 4D 5S 2S JS 8H
189EOF
190        }
191    );
192
193    # TEST
194    ok( $delta, 'Object was initialized correctly.' );
195
196    $delta->set_derived(
197        {
198            state_str => <<"EOF"
199Foundations: H-0 C-2 D-A S-0
200Freecells:  8D  QD
201: 6D 3C 3H KD 8C 5C
202: TC 9C 9H 8S
203: 2H 2D 3S 5D 9D QS KS QH JC
204: 6S TD QC KH AS AH 7C 6H
205: KC 4H TH 7S
206: 9S
207: 7H 7D JD JH TS 6C 5H 4S 3D
208: 4C 4D 5S 2S JS 8H
209EOF
210        }
211    );
212
213    # TEST
214    eq_or_diff(
215        scalar( $delta->decode( $delta->encode() )->to_string() ),
216        <<"EOF",
217Foundations: H-0 C-2 D-A S-0
218Freecells:  8D  QD
219: 6D 3C 3H KD 8C 5C
220: TC 9C 9H 8S
221: 2H 2D 3S 5D 9D QS KS QH JC
222: 6S TD QC KH AS AH 7C 6H
223: KC 4H TH 7S
224: 9S
225: 7H 7D JD JH TS 6C 5H 4S 3D
226: 4C 4D 5S 2S JS 8H
227EOF
228        'decode() works.',
229    );
230
231    # TEST
232    eq_or_diff(
233        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
234        <<"EOF",
235Foundations: H-0 C-2 D-A S-0
236Freecells:  8D  QD
237: 6D 3C 3H KD 8C 5C
238: TC 9C 9H 8S
239: 2H 2D 3S 5D 9D QS KS QH JC
240: 6S TD QC KH AS AH 7C 6H
241: KC 4H TH 7S
242: 9S
243: 7H 7D JD JH TS 6C 5H 4S 3D
244: 4C 4D 5S 2S JS 8H
245EOF
246        'encode_composite() test No. 1.',
247    );
248}
249
250# More encode_composite tests - this time from the output of:
251# pi-make-microsoft-freecell-board -t 24 | ./fc-solve -to 01ABCDE --freecells-num 2 -s -i -p -t
252
253{
254    my $delta = FC_Solve::DeltaStater->new(
255        {
256            init_state_str => <<"EOF"
257Foundations: H-0 C-0 D-0 S-0
258Freecells:
259: 4C 2C 9C 8C QS 4S 2H
260: 5H QH 3C AC 3H 4H QD
261: QC 9S 6H 9H 3S KS 3D
262: 5D 2S JC 5C JH 6D AS
263: 2D KD TH TC TD 8D
264: 7H JS KH TS KC 7C
265: AH 5S 6S AD 8H JD
266: 7S 6C 7D 4D 8S 9D
267EOF
268        }
269    );
270
271    # TEST
272    ok( $delta, 'Object was initialized correctly.' );
273
274    $delta->set_derived(
275        {
276            state_str => <<"EOF"
277Foundations: H-0 C-0 D-0 S-4
278Freecells:  KS  TD
279: 2C
280: 5H QH 3C AC 3H 4H QD JC TH 9C 8D 7S
281: QC 9S 6H 9H 8C 7D 6C 5D 4C 3D
282:
283: 2D KD QS JH TC 9D 8S
284: 7H JS KH TS KC 7C 6D 5C 4D
285: AH 5S 6S AD 8H JD
286: 2H
287
288EOF
289        }
290    );
291
292    # TEST
293    eq_or_diff(
294        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
295        <<"EOF",
296Foundations: H-0 C-0 D-0 S-4
297Freecells:  KS  TD
298:
299: 5H QH 3C AC 3H 4H QD JC TH 9C 8D 7S
300: QC 9S 6H 9H 8C 7D 6C 5D 4C 3D
301: 2H
302: 2D KD QS JH TC 9D 8S
303: 7H JS KH TS KC 7C 6D 5C 4D
304: AH 5S 6S AD 8H JD
305: 2C
306EOF
307        'encode_composite() test No. 2.',
308    );
309
310    $delta->set_derived(
311        {
312            state_str => <<"EOF"
313Foundations: H-0 C-0 D-0 S-2
314Freecells:  TD  4C
315: 8S
316: 5H QH 3C AC 3H 4H 3S 2H
317: QC 9S 6H 9H 8C 7D 6C 5D 4S 3D 2C
318: 5C 4D
319: 2D KD QS JH TC 9D
320: 7H JS KH TS KC 7C
321: AH 5S 6S AD 8H JD
322: KS QD JC TH 9C 8D 7S 6D
323EOF
324        }
325    );
326
327    # TEST
328    eq_or_diff(
329        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
330        <<"EOF",
331Foundations: H-0 C-0 D-0 S-2
332Freecells:  TD  4C
333: 5C 4D
334: 5H QH 3C AC 3H 4H 3S 2H
335: QC 9S 6H 9H 8C 7D 6C 5D 4S 3D 2C
336: 8S
337: 2D KD QS JH TC 9D
338: 7H JS KH TS KC 7C
339: AH 5S 6S AD 8H JD
340: KS QD JC TH 9C 8D 7S 6D
341EOF
342        'encode_composite() test No. 2.',
343    );
344
345}
346
347# Make sure encode_composite avoids permutations of empty columns
348# and completely-non-original states.
349{
350    my $delta = FC_Solve::DeltaStater->new(
351        {
352            init_state_str => <<"EOF",
353Foundations: H-K C-K D-J S-Q
354Freecells:  KD
355:
356:
357:
358: KS QD
359:
360:
361:
362:
363EOF
364        },
365    );
366
367    $delta->set_derived(
368        {
369            state_str => <<"EOF",
370Foundations: H-K C-K D-J S-Q
371Freecells:  QD  KD
372:
373:
374:
375:
376:
377: KS
378:
379:
380EOF
381        },
382    );
383
384    my $calc_enc_state = sub {
385        return join '', unpack( "H*", $delta->encode_composite() );
386    };
387
388    my $first_state = $calc_enc_state->();
389
390    $delta->set_derived(
391        {
392            state_str => <<"EOF",
393Foundations: H-K C-K D-J S-Q
394Freecells:  QD  KD
395:
396:
397:
398:
399:
400:
401:
402: KS
403EOF
404        }
405    );
406
407    my $second_state = $calc_enc_state->();
408
409    # TEST
410    is(
411        $first_state,
412        $second_state,
413"Make sure encode_composite avoids permutations of empty columns and completely-non-original states.",
414    );
415}
416
417# Make sure encode_composite avoids permutations of empty columns
418# and completely-non-original states.
419#
420# Another edge-case.
421{
422    my $delta = FC_Solve::DeltaStater->new(
423        {
424            init_state_str => <<"EOF",
425Foundations: H-K C-K D-J S-Q
426Freecells:  KD
427:
428:
429:
430: KS QD
431:
432:
433:
434:
435EOF
436        },
437    );
438
439    $delta->set_derived(
440        {
441            state_str => <<"EOF",
442Foundations: H-K C-K D-J S-Q
443Freecells:  QD  KD
444: KS
445:
446:
447:
448:
449:
450:
451:
452EOF
453        },
454    );
455
456    my $calc_enc_state = sub {
457        return join '', unpack( "H*", $delta->encode_composite() );
458    };
459
460    my $first_state = $calc_enc_state->();
461
462    $delta->set_derived(
463        {
464            state_str => <<"EOF",
465Foundations: H-K C-K D-J S-Q
466Freecells:  QD  KD
467:
468:
469:
470:
471:
472:
473:
474: KS
475EOF
476        }
477    );
478
479    my $second_state = $calc_enc_state->();
480
481    # TEST
482    is( $first_state, $second_state,
483        "encode_composite avoids permutations - #2",
484    );
485}
486
487{
488    my $reader =
489        FC_Solve::VarBaseDigitsReader->new(
490        { data => chr( 3 | ( 12 << 3 ) ) } );
491
492    # TEST
493    ok( $reader, 'Init var_reader' );
494
495    # TEST
496    is( $reader->read( 1 << 3 ), 3, 'reader->read(1 << 3)' );
497
498    # TEST
499    is( $reader->read( 1 << 4 ), 8 + 4, 'reader->read(1 << 4)' );
500}
501
502{
503    my $reader = FC_Solve::VarBaseDigitsReader->new(
504        {
505            data => FC_Solve::VarBaseDigitsWriter::int_to_buf(
506                24 + 8 * 52 + 7 * 11 * 52
507            )
508        }
509    );
510
511    # TEST
512    ok( $reader, 'Init var_reader' );
513
514    # TEST
515    is( $reader->read(52), 24, 'reader->read(24)' );
516
517    # TEST
518    is( $reader->read(11), 8, 'reader->read(11)' );
519
520    # TEST
521    is( $reader->read(10), 7, 'reader->read(10)' );
522}
523
524# TEST:$c=2;
525foreach my $classes_rec (
526    {
527        type => 'perl',
528        w    => 'FC_Solve::VarBaseDigitsWriter',
529        r    => 'FC_Solve::VarBaseDigitsReader',
530    },
531    {
532        type => 'XS',
533        w    => 'FC_Solve::VarBaseDigitsWriter::XS',
534        r    => 'FC_Solve::VarBaseDigitsReader::XS',
535    },
536    )
537{
538    my $type   = $classes_rec->{type};
539    my $writer = $classes_rec->{w}->new;
540
541    # TEST*$c
542    ok( $writer, "Init var_writer - $type" );
543
544    $writer->write( { item => 24, base => 52, } );
545    $writer->write( { item => 8,  base => 11, } );
546    $writer->write( { item => 7,  base => 10, } );
547
548    my $reader = $classes_rec->{r}->new(
549        {
550            data => $writer->get_data(),
551        }
552    );
553
554    # TEST*$c
555    ok( $reader, "Init var_reader - $type" );
556
557    # TEST*$c
558    is( $reader->read(52), 24, "writer-to-reader->read(24) - $type" );
559
560    # TEST*$c
561    is( $reader->read(11), 8, "writer-to-reader->read(11) - $type" );
562
563    # TEST*$c
564    is( $reader->read(10), 7, "writer-to-reader->read(10) - $type" );
565}
566
567{
568    # MS Freecell No. 982 Initial state.
569    my $delta = FC_Solve::DeltaStater::DeBondt->new(
570        {
571            init_state_str => <<"EOF"
572Foundations: H-0 C-0 D-A S-0
573Freecells:
574: 6D 3C 3H KD 8C 5C
575: TC 9C 9H 4S JC 6H 5H
576: 2H 2D 3S 5D 9D QS KS
577: 6S TD QC KH AS AH 7C
578: KC 4H TH 7S 2C 9S
579: AC QD 8D QH 3D 8S
580: 7H 7D JD JH TS 6C
581: 4C 4D 5S 2S JS 8H
582EOF
583        }
584    );
585
586    # TEST
587    ok( $delta, 'Object was initialized correctly.' );
588
589    $delta->set_derived(
590        {
591            state_str => <<"EOF"
592Foundations: H-0 C-2 D-A S-0
593Freecells:  8D  QD
594: 6D 3C 3H KD 8C 5C
595: TC 9C 9H 8S
596: 2H 2D 3S 5D 9D QS KS QH JC
597: 6S TD QC KH AS AH 7C 6H
598: KC 4H TH 7S
599: 9S
600: 7H 7D JD JH TS 6C 5H 4S 3D
601: 4C 4D 5S 2S JS 8H
602EOF
603        }
604    );
605
606    # TEST
607    ok( $delta->encode_composite(), "->encode_composite runs fine." );
608
609    # TEST
610    eq_or_diff(
611        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
612        <<"EOF",
613Foundations: H-0 C-2 D-A S-0
614Freecells:  8D  QD
615: 6D 3C 3H KD 8C 5C
616: TC 9C 9H 8S
617: 2H 2D 3S 5D 9D QS KS QH JC
618: 6S TD QC KH AS AH 7C 6H
619: KC 4H TH 7S
620: 9S
621: 7H 7D JD JH TS 6C 5H 4S 3D
622: 4C 4D 5S 2S JS 8H
623EOF
624        'DeBondt encode_composite()+decode() test No. 1.',
625    );
626}
627
628{
629
630    my $init_state = <<"EOF";
631Foundations: H-0 C-0 D-A S-0
632Freecells:
633: AH 5C 3S TD 5S 2H 9S
634: 8S AS 5D 7S QH TC
635: 2D 9C KC JD 8C TH 7C
636: QS KH 3H 7H 9D 6D TS
637: 4C 4D KD 8H KS 6H
638: 9H 2C 5H JH QD 6C
639: 2S 3C 6S JC 4H QC
640: 3D 4S 8D 7D AC JS
641EOF
642
643    # MS Freecell No. 5 Initial state. - chosen because it has
644    # an Ace at the topmost position in the stack.
645    my $delta = FC_Solve::DeltaStater::DeBondt->new(
646        {
647            init_state_str => $init_state,
648        }
649    );
650
651    # TEST
652    ok( $delta, 'Object was initialized correctly.' );
653
654    $delta->set_derived( { state_str => $init_state, } );
655
656    # TEST
657    eq_or_diff(
658        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
659        $init_state,
660        'DeBondt encode_composite()+decode() test for leading Aces',
661    );
662}
663
664{
665    # PySol Baker's Dozen deal No. 24
666    my $delta = FC_Solve::DeltaStater::DeBondt->new(
667        {
668            variant        => "bakers_dozen",
669            init_state_str => <<"EOF",
670Foundations: H-A C-2 D-0 S-A
671Freecells:
672: 2H JH 6S QH
673: 4H TC 6C QC
674: 4S 5C 5S 5H
675: 6D AD 3C 2D
676: 7C QS JC
677: 8D 4D 6H 7H
678: 8S 9H JS 4C
679: JD 3H TH 7S
680: QD TD 7D 9S
681: KH 3S 9D
682: KC 3D 8C 2S
683: KD 8H
684: KS TS 9C 5D
685EOF
686        }
687    );
688
689    # TEST
690    ok( $delta, 'Baker Dozen Object was initialized correctly.' );
691
692    my $derived_str = <<"EOF";
693Foundations: H-A C-5 D-5 S-2
694Freecells:
695: 2H JH
696: 4H TC 6C QC
697: 4S
698: 6D
699: 7C
700: 8D
701: 8S
702: JD 3H TH 9H
703: QD TD 7D 9S 8C 7H 6H 5H
704: KH 3S 9D
705: KC QS JS
706: KD QH JC
707: KS TS 9C 8H 7S 6S 5S
708EOF
709
710    $delta->set_derived(
711        {
712            state_str => $derived_str,
713        }
714    );
715
716    # TEST
717    ok( $delta->encode_composite(),
718        "Baker's Dozen ->encode_composite runs fine." );
719
720    # TEST
721    eq_or_diff(
722        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
723        $derived_str,
724        "Baker's Dozen DeBondt encode_composite()+decode() test No. 1.",
725    );
726}
727
728{
729    # PySol Baker's Dozen deal No. 86
730    my $delta = FC_Solve::DeltaStater::DeBondt->new(
731        {
732            variant        => "bakers_dozen",
733            init_state_str => <<"EOF",
734Foundations: H-0 C-2 D-A S-0
735Freecells:
736: QH TD QD JH
737: 4C 4D 3D 9C
738: KH 2D QC 8D
739: 4S 8H 6C 6H
740: 6S JC 5D TS
741: 9H AH 6D 5C
742: KC 7S 4H
743: 9S AS 7C 3C
744: KS 8S 9D TC
745: JD TH
746: QS 8C 7D 3S
747: 3H 7H 5S JS
748: KD 5H 2H 2S
749EOF
750        }
751    );
752
753    # TEST
754    ok( $delta, 'Baker Dozen Object was initialized correctly.' );
755
756    my $derived_str = <<"EOF";
757Foundations: H-0 C-2 D-A S-0
758Freecells:
759: QH TD QD JH
760: 4C 4D 3D 9C
761: KH 2D QC 8D
762: 4S 8H 6C 6H
763: 6S JC 5D TS
764: 9H AH 6D 5C
765: KC 7S 4H
766: 9S AS 7C 3C
767: KS 8S 9D TC
768: JD TH
769: QS 8C 7D 3S
770: 3H 7H 5S JS
771: KD 5H 2H 2S
772EOF
773
774    $delta->set_derived(
775        {
776            state_str => $derived_str,
777        }
778    );
779
780    # TEST
781    ok( $delta->encode_composite(),
782        "Baker's Dozen ->encode_composite (No. 2) runs fine." );
783
784    # TEST
785    eq_or_diff(
786        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
787        $derived_str,
788        "Baker's Dozen DeBondt encode_composite()+decode() test No. 2.",
789    );
790}
791
792{
793    # PySol Baker's Dozen deal No. 86
794    my $delta = FC_Solve::DeltaStater::DeBondt->new(
795        {
796            variant        => "bakers_dozen",
797            init_state_str => <<"EOF",
798Foundations: H-0 C-2 D-A S-0
799Freecells:
800: QH TD QD JH
801: 4C 4D 3D 9C
802: KH 2D QC 8D
803: 4S 8H 6C 6H
804: 6S JC 5D TS
805: 9H AH 6D 5C
806: KC 7S 4H
807: 9S AS 7C 3C
808: KS 8S 9D TC
809: JD TH
810: QS 8C 7D 3S
811: 3H 7H 5S JS
812: KD 5H 2H 2S
813EOF
814        }
815    );
816
817    # TEST
818    ok( $delta, 'Baker Dozen Object was initialized correctly.' );
819
820    my $derived_str = <<"EOF";
821Foundations: H-0 C-4 D-4 S-2
822Freecells:
823: QH TD QD JH TS
824:
825: KH
826: 4S 8H 6C 5D
827: 6S JC
828: 9H AH 6D 5C
829: KC 7S 4H 3S 2H
830: 9S
831: KS 8S 9D TC 9C 8D 7C
832: JD TH
833: QS 8C 7D 6H 5H
834: 3H 7H 5S JS
835: KD QC
836EOF
837
838    $delta->set_derived(
839        {
840            state_str => $derived_str,
841        }
842    );
843
844    # TEST
845    ok( $delta->encode_composite(),
846        "Baker's Dozen ->encode_composite (No. 3) runs fine." );
847
848    # TEST
849    eq_or_diff(
850        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
851        $derived_str,
852        "Baker's Dozen DeBondt encode_composite()+decode() test No. 3.",
853    );
854}
855
856{
857    # PySol Baker's Dozen deal No. 281
858    my $delta = FC_Solve::DeltaStater::DeBondt->new(
859        {
860            variant        => "bakers_dozen",
861            init_state_str => <<"EOF",
862Foundations: H-2 C-0 D-0 S-2
863Freecells:
864: JC 3S 9D 4H
865: KC QC 6D QS
866: QH JH TS
867: 4C 2D 3H 5H
868: KS 5D TC JS
869: AC 4D 8D 8S
870: KH 3D 9C TH
871: 3C 9S AD 4S
872: 8C QD 2C
873: 9H 6H TD
874: KD 7C 6S 5C
875: JD 8H 7D
876: 7S 5S 7H 6C
877EOF
878        }
879    );
880
881    # TEST
882    ok( $delta, 'Baker Dozen Object was initialized correctly.' );
883
884    my $derived_str = <<"EOF";
885Foundations: H-2 C-0 D-0 S-2
886Freecells:
887: JC 3S 9D 4H
888: KC QC 6D QS
889: QH JH TS
890: 4C 2D 3H 5H
891: KS 5D TC JS
892: AC 4D 8D 8S
893: KH 3D 9C TH
894: 3C 9S AD 4S
895: 8C QD 2C
896: 9H 6H TD
897: KD 7C 6S 5C
898: JD 8H 7D
899: 7S 5S 7H 6C
900EOF
901
902    $delta->set_derived(
903        {
904            state_str => $derived_str,
905        }
906    );
907
908    # TEST
909    ok( $delta->encode_composite(),
910        "Baker's Dozen ->encode_composite (No. 4) runs fine." );
911
912    # TEST
913    eq_or_diff(
914        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
915        $derived_str,
916        "Baker's Dozen DeBondt encode_composite()+decode() test No. 4.",
917    );
918}
919
920{
921    # PySol Baker's Dozen deal No. 26698
922    my $init_state_str = <<"EOF";
923Foundations: H-0 C-2 D-2 S-2
924Freecells:
925: 9C 7D TC 8D
926: JS 9D JC 4S
927: 5H 3H 6H 5C
928: 5D 6C 4H 8S
929:
930: JD TD QS 9S
931: QC QH 6S 4C
932: 3C AH 9H
933: KS QD 4D 2H
934: KD TS 7C 6D
935: KH KC 3S 3D
936: 7S TH 8H 5S
937: 7H JH 8C
938EOF
939    my $delta = FC_Solve::DeltaStater::DeBondt->new(
940        {
941            variant        => "bakers_dozen",
942            init_state_str => $init_state_str,
943        }
944    );
945
946    # TEST
947    ok( $delta, 'Baker Dozen Object was initialized correctly.' );
948
949    my $derived_str = $init_state_str;
950
951    $delta->set_derived(
952        {
953            state_str => $derived_str,
954        }
955    );
956
957    # TEST
958    ok( $delta->encode_composite(),
959        "Baker's Dozen ->encode_composite (No. 5) runs fine." );
960
961    # TEST
962    eq_or_diff(
963        scalar( $delta->decode( $delta->encode_composite() )->to_string() ),
964        $derived_str,
965        "Baker's Dozen DeBondt encode_composite()+decode() test No. 5.",
966    );
967}
968
969__END__
970
971=head1 COPYRIGHT AND LICENSE
972
973This file is part of Freecell Solver. It is subject to the license terms in
974the COPYING.txt file found in the top-level directory of this distribution
975and at http://fc-solve.shlomifish.org/docs/distro/COPYING.html . No part of
976Freecell Solver, including this file, may be copied, modified, propagated,
977or distributed except according to the terms contained in the COPYING file.
978
979Copyright (c) 2011 Shlomi Fish
980
981=cut
982