#!/bin/bash

lsss=target/release/life_slice_ship_search

# Set data variable to an empty directory with plenty of space for
# storing slices.
# To interrupt the search "echo 0000 > data/stopafter",
# and the script will exit after some time.
# To resume the search "echo 9000 > data/stopafter",
# and run this script. It will resume from where it was stopped.
# Partial results will be saved in the data directory.
# The partials will need to be mirrored.

data=data

margin=18

#midline=--even_midline
midline=--odd_midline
#midline=--gutter
#midline=--zero # use for Asymmetric, add 1 to margin.

parms="--velocity (4,0)c/5 --rule B27/S137"

# For an exhaustive search re-run the search with seedcolumn changed to all
# the values from 00 to the margin.
# Note however that if a spaceship is found it will not be possible to
# continue the search for that seed as the disk space will blow up.

seedcolumn=02

declare -a exclude

# The exclude parameter can be used to exclude results that are not wanted.
# This could be useful for excluding repeating patterns or lower-period
# spaceships. It is a manual process.

# Usage:
#
# 1. Find the partial that contains the pattern to exclude.
# 2. Pick a slice (two columns) near the middle of the pattern.
# 3. Trim off excess from the tail of the pattern.
# 4. Pass the two columns to --exclude separated by a /. The "left" column
#    goes first.
#
# Notes:
#
# * Trailing spaces in the exclude pattern are significant.
#
# * The results in the partial files are rotated and sometimes flipped. So the
#   left column (that goes first) is the lower row in the odd-numbered
#   partials and the higher row in the even-numbered partials.
#
# * The amount of information to specify what to exclude is fairly limited
#   (Two columns of the pattern for one phase.) To avoid excluding more
#   patterns you do not intend to do not be aggressive in trimming the
#   tail.

#exclude+=(--exclude)
#exclude+=(" **   **    *** ***  ***          *   **               **        ****          **     **        *  *     ****   * /  *    ****   **        *   * *          **  *         *         *  *  * **     *               *  *   *    **** *")


grey_start_row=00
grey_end_row=00
grey_margin=02

flush=4000000000
mem=4000000000
threads=
max_width=100

if [ ! -e $data/token ]
then
    echo init >> $data/token
    echo 9000 > $data/stopafter
fi

read token < $data/token

if [ "$token" = "init" ]
then
    mkdir $data/0010
    mkdir $data/0010/00

    if [ $seedcolumn -eq 0 ]
    then
        case $midline in
            --even_midline)
                seed=89;;
            --odd_midline)
                seed=ef;;
            --gutter)
                seed=23;; # search will fail immediately.
            --zero)
                seed=21;; # search will fail immediately.
        esac
        $lsss init $parms --seed $seed --slice_rows 10 --sort left \
        --out_dir $data/0010/00
    else
        case $midline in
            --even_midline)
                seed=19;;
            --odd_midline)
                seed=1f;;
            --gutter)
                seed=13;;
            --zero)
                seed=11;;
        esac
        $lsss init $parms --seed $seed --slice_rows 10 --sort left \
        --out_dir $data/0010/00
    fi

    for s in `seq -w 1 29`
    do
        mkdir $data/0010/$s
        if [ $s -eq $seedcolumn ]
        then
            $lsss init $parms --seed 2f --slice_rows 10 \
            --sort right --out_dir $data/0010/$s
        else
            if [ $s -gt $margin ]
            then
                $lsss init $parms --seed 11 --slice_rows 10 \
                --sort right --out_dir $data/0010/$s
            else
               if [ $s -lt $seedcolumn ]
               then
                  $lsss init $parms --seed 1f --slice_rows 10 \
                   --sort right --out_dir $data/0010/$s
               else
                  $lsss init $parms --seed ff --slice_rows 10 \
                   --sort right --out_dir $data/0010/$s
               fi
            fi
        fi
    done
    token=0010/done
    echo $token > $data/token || exit 1
fi

pass=right
prevlvl=0010
for lvl in `seq -w 11 9999`
do
    test $lvl -le `cat $data/stopafter` || exit
    if [ $pass = right ]
    then
        if [ "$token" = "$prevlvl/done" ]
        then
            date >> $data/search.log
            du $data/ >> $data/search.log
            echo $token
            test $lvl -le `cat $data/stopafter` || exit
            mkdir $data/$lvl
            mkdir $data/$lvl/00
            $lsss join $parms $threads \
                --in_left $data/$prevlvl/00 --in_right $data/$prevlvl/01 \
                --out_left $data/$lvl/00 \
                --left_rows $lvl \
                --left_sort left \
                --flush_left_after $flush \
                --mem $mem \
                --max_width $max_width \
                "${exclude[@]}" \
                $midline || exit 1


            if [ ! -e $data/$lvl/00/l_000.slice ]
            then
                echo "No spaceship found for seedcolumn $seedcolumn"
                exit 2
            fi
            echo -n $lvl,00, >> $data/slice_counts.csv
            echo `$lsss info --slice_count --in_left $data/$lvl/00` \
                >> $data/slice_counts.csv

            token=$lvl/00
            echo $token > $data/token || exit 1
            rm $data/$prevlvl/00/*.slice
            rmdir $data/$prevlvl/00
        fi
        prevslice=00
        for slice in `seq -w 01 28`
        do
            if [ "$token" = "$lvl/$prevslice" ]
            then
                echo $token
                test $lvl -le `cat $data/stopafter` || exit
                mkdir $data/$lvl/$slice
                if [ $slice -gt $margin ]
                then
                    zero="--zero"
                else
                    zero=
                fi

                if [ $lvl -ge $grey_start_row \
                    -a $lvl -lt $grey_end_row \
                    -a $slice -le $grey_margin ]
                then
                    if [ $((slice % 2)) -eq 0 ]
                    then
                        extend_mask="--extend_mask=2"
                    else
                        extend_mask="--extend_mask=4"
                    fi
                else
                    extend_mask=
                fi

                $lsss join $parms $threads \
                    --in_left $data/$lvl/$prevslice \
                    --in_right $data/$prevlvl/$slice \
                    --out_right $data/$lvl/$slice \
                    --right_rows $lvl \
                    --right_sort left \
                    --flush_right_after $flush \
                    --mem $mem \
                    --max_width $max_width \
                    "${exclude[@]}" \
                    $extend_mask \
                    $zero || exit 1

                if [ ! -e $data/$lvl/$slice/l_000.slice ]
                then
                    echo "No spaceship found for seedcolumn $seedcolumn"
                    exit 2
                fi

                echo -n $lvl,$slice, >> $data/slice_counts.csv
                echo `$lsss info --slice_count --in_left $data/$lvl/$slice` \
                    >> $data/slice_counts.csv

                token=$lvl/$slice
                echo $token > $data/token || exit 1
                rm $data/$prevlvl/$slice/*.slice
                rmdir $data/$prevlvl/$slice
            fi
            prevslice=$slice
        done
        if [ "$token" = "$lvl/28" ]
        then
            echo $token
            mkdir $data/$lvl/29
            $lsss join $parms $threads \
                --in_left $data/$lvl/28 --in_right $data/$prevlvl/29 \
                --out_right $data/$lvl/29 \
                --right_rows $lvl \
                --right_sort right \
                --flush_right_after $flush \
                --mem $mem \
                --max_width $max_width \
                --zero || exit 1

            if [ ! -e $data/$lvl/29/r_000.slice ]
            then
                echo "No spaceship found for seedcolumn $seedcolumn"
                exit 2
            fi

            date >> $data/search.log
            du $data/ >> $data/search.log

            echo > $data/${lvl}.partial.txt

            mkdir $data/$lvl/28p
            $lsss join $parms --partial \
                --in_left $data/$lvl/28 --in_right $data/$lvl/29 \
                --out_left $data/$lvl/28p \
                --left_rows $lvl \
                --left_sort right \
                --flush_left_after $flush \
                >> $data/${lvl}.partial.txt

            prevslice=28
            for slice in `seq -w 27 -1 0`
            do
                mkdir $data/$lvl/${slice}p
                $lsss join $parms --partial \
                    --in_left $data/$lvl/$slice \
                    --in_right $data/$lvl/${prevslice}p \
                    --out_left $data/$lvl/${slice}p \
                    --left_rows $lvl \
                    --left_sort right \
                    --flush_left_after $flush \
                    >> $data/${lvl}.partial.txt

                rm $data/$lvl/${prevslice}p/*.slice
                rmdir $data/$lvl/${prevslice}p
                prevslice=$slice
            done


            rm $data/$lvl/00p/*.slice
            rmdir $data/$lvl/00p


            token=$lvl/done
            echo $token > $data/token || exit 1
            rm $data/$prevlvl/29/*.slice
            rmdir $data/$prevlvl/29
            rmdir $data/$prevlvl
        fi
        pass=left
    else
        if [ "$token" = "$prevlvl/done" ]
        then
            echo $token
            test $lvl -le `cat $data/stopafter` || exit
            mkdir $data/$lvl
            mkdir $data/$lvl/29
            $lsss join $parms $threads \
                --in_left $data/$prevlvl/28 --in_right $data/$prevlvl/29 \
                --out_right $data/$lvl/29 \
                --right_rows $lvl \
                --right_sort right \
                --flush_right_after $flush \
                --mem $mem \
                --max_width $max_width \
                --zero || exit 1

            if [ ! -e $data/$lvl/29/r_000.slice ]
            then
                echo "No spaceship found for seedcolumn $seedcolumn"
                exit 2
            fi

            token=$lvl/29
            echo $token > $data/token
            rm $data/$prevlvl/29/*.slice
            rmdir $data/$prevlvl/29
        fi
        prevslice=29
        for slice in `seq -w 28 -1 1`
        do
            if [ "$token" = "$lvl/$prevslice" ]
            then
                echo $token
                test $lvl -le `cat $data/stopafter` || exit
                mkdir $data/$lvl/$slice
                if [ $slice -gt $margin ]
                then
                    zero="--zero"
                else
                    zero=
                fi

                if [ $lvl -ge $grey_start_row \
                    -a $lvl -lt $grey_end_row \
                    -a $slice -le $grey_margin ]
                then
                    if [ $((slice % 2)) -eq 0 ]
                    then
                        extend_mask="--extend_mask=2"
                    else
                        extend_mask="--extend_mask=4"
                    fi
                else
                    extend_mask=
                fi

                $lsss join $parms $threads \
                    --in_left $data/$prevlvl/$slice \
                    --in_right $data/$lvl/$prevslice \
                    --out_left $data/$lvl/$slice \
                    --left_rows $lvl \
                    --left_sort right \
                    --flush_left_after $flush \
                    --mem $mem \
                    --max_width $max_width \
                    "${exclude[@]}" \
                    $extend_mask \
                    $zero || exit 1

                if [ ! -e $data/$lvl/$slice/r_000.slice ]
                then
                    echo "No spaceship found for seedcolumn $seedcolumn"
                    exit 2
                fi

                echo -n $lvl,$slice, >> $data/slice_counts.csv
                echo `$lsss info --slice_count --in_right $data/$lvl/$slice` \
                    >> $data/slice_counts.csv

                token=$lvl/$slice
                echo $token > $data/token || exit 1
                rm $data/$prevlvl/$slice/*.slice
                rmdir $data/$prevlvl/$slice
            fi
            prevslice=$slice
        done
        if [ "$token" = "$lvl/01" ]
        then
            echo $token
            mkdir $data/$lvl/00

            $lsss join $parms $threads \
                --in_left $data/$prevlvl/00 --in_right $data/$lvl/01 \
                --out_left $data/$lvl/00 \
                --left_rows $lvl \
                --left_sort left \
                --flush_left_after $flush \
                --mem $mem \
                --max_width $max_width \
                "${exclude[@]}" \
                $midline || exit 1

            if [ ! -e $data/$lvl/00/l_000.slice ]
            then
                echo "No spaceship found for seedcolumn $seedcolumn"
                exit 2
            fi

            echo -n $lvl,00, >> $data/slice_counts.csv
            echo `$lsss info --slice_count --in_left $data/$lvl/00` \
                >> $data/slice_counts.csv

            if [ `$lsss info --slice_count --in_left $data/$lvl/00` -eq 1 ]
            then
                # for an asymmetric midline the 0 column has only one
                # slice so we can calculate the partial from the center
                # out as well.

                echo > $data/${lvl}.partial.txt

                mkdir $data/$lvl/00p
                $lsss join $parms --partial \
                    --in_left $data/$lvl/00 --in_right $data/$lvl/01 \
                    --out_left $data/$lvl/00p \
                    --left_rows $lvl \
                    --left_sort left \
                    --flush_left_after $flush \
                    >> $data/${lvl}.partial.txt

                prevslice=00
                for slice in `seq -w 1 29`
                do
                    mkdir $data/$lvl/${slice}p
                    $lsss join $parms --partial \
                        --in_left $data/$lvl/${prevslice}p \
                        --in_right $data/$lvl/$slice \
                        --out_right $data/$lvl/${slice}p \
                        --right_rows $lvl \
                        --right_sort left \
                        --flush_right_after $flush \
                        >> $data/${lvl}.partial.txt

                    rm $data/$lvl/${prevslice}p/*.slice
                    rmdir $data/$lvl/${prevslice}p
                    prevslice=$slice
                done

                rm $data/$lvl/29p/*.slice
                rmdir $data/$lvl/29p

            fi

            token=$lvl/done
            echo $token > $data/token || exit 1
            rm $data/$prevlvl/00/*.slice
            rmdir $data/$prevlvl/00
            rmdir $data/$prevlvl
        fi


        pass=right
    fi
    prevlvl=$lvl
done
