#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
#BEGIN#
# 			Evolvotron_complexity
#	http://freaknet.org/alpt/src/misc/evolvotron_complexity
#
# 
# This script is based on `evolvotron' a wonderful program which mutates
# algorithmically generated images. You can get it here:
# http://www.bottlenose.demon.co.uk/share/evolvotron/index.htm
#
# This script mutates an initial random image in only one direction, that of
# the minimum redundancy, or in another words that of the maximum complexity.
#
# *** Usage
#		
#	evolvotron_complexity [new [function.xml]]
#	evolvotron_complexity [frame_number]
#
# 1) Copy the script into an empty directory and go there
#
#	mkdir ev; cp evolvotron_complexity ev/ ; cd ev/
#      
# 2) Launch the script for the first time
#
#	./evolvotron_complexity new
#
#    In this way it starts from a random function and runs forever (until you
#    kill it).
#    The evolution can also start from an existing function, f.e. a function
#    generated by evolvotron:
#
#	./evolvotron_complexity new function.xml
#  
#    All the generate images and function will be saved in the current
#    directory with the good_NUMBER.xml and good_NUMBER.ppm file name.
#
# 3) If you've halted the script, you can continue from the previous mutation
#    by simply running:
#	./evolvotron_complexity. 
#    If you want to continue from a specific frame (let's say good_17.xml),
#    specify it:
#	./evolvotron_complexity 17
#
# 4) Render the final high quality image
#      		
#	 cat good_NUMBER.xml | evolvotron_render -s 1024 1024 rendered_image.ppm
#    Where good_NUMBER.xml is the function of the final image
#
# 5) Enjoy ^_^
#
# Note:  After some time you'll see that the output images will degenerate. If
# 	 you let the degenerated images evolve, they will be more and
#        more like a /dev/urandom image:
#        cat /dev/urandom | rawtoppm 1024 768 > TEST.ppm; display TEST.ppm
#
#	 When you've reached this point, you won't go further very much, so
#	 it's better to stop the script, choose the really last good frame,
#	 increasing resolution and continuing from there. Ex:
#		- We are at good_37.xml, but it is already degenerated. Let's
#		  continue from good_20.xml
#		- ./evolvotron_complexity 20
#	For more info on this problem, read the "Parameters" section below.
# 
# 
# AlpT (@freaknet.org)
#
#END#

##
#### Parameters 
##

# With higher resolutions the measurement of the complexity is more accurate
# but the rendering times increase.
#
# With inaccurate measurement the evolutions won't happen often, because the
# script cannot distinguish well the complexity of two images, f.e. in the
# extreme case, if you set the 1x1 (one pixel) resolution, it won't ever
# mutate.
#
# High resolution give awesome result (try for example 2048 2048).
# In the other hand, high resolution requires high computational power to
# render each mutated image.
#
# If the evolution is blocked try doubling the resolution.

#resolution="4096x4096"
#resolution="2048x2048"
resolution="1024x1024"
#resolution="512x512"
#resolution="256x256"

# Retrieve the resolution from the `resolution' file
[ -f resolution ] && resolution=$(< resolution)
echo "Resolution is set to $resolution"
####


abort()
{
	echo aborted
	exit 1
}
trap "abort" SIGINT SIGQUIT

check() {
        while [ 0 ] ; do if [ -f xxx.ppm ]; then display xxx.ppm; fi done
}

# get_complexity function.xml output.ppm
get_complexity() {
	cat $1 | evolvotron_render -s $resolution -o $2; bzip2 -f $2
	stat -c %s $2.bz2
}

if test "$1" = "help" -o "$1" = "-h" -o "$1" = "--help"
then
        echo "Usage:"
        echo "        evolvotron_complexity [new [function.xml]]"
        echo ""
        cat $0 | sed -ne '/\#BEGIN\#/,/\#END\#/p' | less
        exit 1
fi


##
####	New evolution
##
if [ "$1" == "new" ]
then
	if [ -f fn_ok.xml ]
	then
		echo "fn_ok.xml already exists. Remove it and retry."
		exit 1
	fi

	if [ ! -z "$2" ]
	then
		if [ -f "$2" ]
		then
			echo "Starting the evolution from $2"
			cp $2 fn_ok.xml
		else
			echo "$2 doesn't exist"
			exit 1
		fi
	else
		evolvotron_mutate -g > fn_ok.xml
	fi

	echo 0 > last_frame

elif [ ! -z "$1" ]
then
	if [ -f "$1" ] && echo $1 | grep -q '\.xml$'
	then
		echo "Continuing evolution from $1"
		cp $1 fn_ok.xml
	else
		last_frame="$1"
	fi
fi

best_size=0
frame=0

#
# Start from the last frame (if any)
#
if [ -f last_frame ]
then
	frame=`cat last_frame`
else
	echo 0 > last_frame
fi

if [ ! -z "$last_frame" ]
then
	frame=$last_frame
fi

if [ "$frame" -gt 0 ]
then
	echo "Continuing from the $frame-th frame"
	cp good_$frame.xml fn_ok.xml

	if [ -f good_$frame.ppm ]
	then
		echo "Reading good_$frame.ppm size"
		bzip2 -fk good_$frame.ppm
		best_size="`stat -c %s good_$frame.ppm.bz2`"
		rm good_$frame.ppm.bz2
	elif [ -f good_$frame.xml ]
	then
		echo "Calculating good_$frame.xml size"
		best_size="`get_complexity good_$frame.xml xxx.ppm`"
	fi
elif [ -f fn_ok.xml ]
then
	echo "Calculating fn_ok size"
	best_size="`get_complexity fn_ok.xml xxx.ppm`"
else
	echo "fn_ok.xml and good_$frame.xml don't exist."
	echo "Maybe you want to use:"
	echo "     ./evolvotron_complexity new"
	exit 1
fi

#check &

##
####  The core of evolvotron_complexity
#  loop:
#        mutate_and_render
#        compress
#	 if compressed_size > best_size
#		best_size=compressed_size
#		goto loop
##
while [ 0 ]
do
	cat fn_ok.xml  | evolvotron_mutate > fn_new.xml
	size="`get_complexity fn_new.xml xxx.ppm`"

	if [ $size -gt $best_size ]
	then
		best_size=$size
		cp fn_new.xml fn_ok.xml
		
		echo ""
		echo $((++frame)) > last_frame
		echo "new $frame"
		cp fn_new.xml good_$frame.xml
		cp xxx.ppm.bz2 good_$frame.ppm.bz2
		bunzip2 -f good_$frame.ppm.bz2
	fi
	
	printf "."
done
