use strict;
#===== Copyright 2008, Webpraxis Consulting Ltd. - ALL RIGHTS RESERVED - Email: webpraxis@gmail.com ============================
# __bale.pl: Trek a bale around a checkerboard.
#===============================================================================================================================
# 0) INITIALIZE:
my $No_Rows	= 8;
my $No_Cols	= 8;
my @Bale	= ( { HEADING => 'S', X => 0,            Y => 0            },					#define turtle at top left corner
				{ HEADING => 'E', X => 0,            Y => $No_Rows - 1 },					#define turtle at bottom left corner
				{ HEADING => 'N', X => $No_Cols - 1, Y => $No_Rows - 1 },					#define turtle at bottom right corner
				{ HEADING => 'W', X => $No_Cols - 1, Y => 0            }					#define turtle at top right corner
			  );
my @Tracks;																					#array for recording bale's locations
my @No_Consecutive_Turns;																	#number of consecutive left turns by turtles
#-------------------------------------------------------------------------------------------------------------------------------
# 1) PUT TURTLES IN MOTION:
$Tracks[$Bale[$_]{X}][$Bale[$_]{Y}] = 1 for (0..$#Bale); 									#record turtles initial locations
until( &sumArray(@No_Consecutive_Turns) == 4 * @Bale ) {									#repeat
	for my $turtle ( 0..$#Bale ) {															# repeat for each turtle
		next if $No_Consecutive_Turns[$turtle] == 4;										#  skip if turtle has spun around
		if( &noTracksAhead($turtle) and &noBoundaryAhead($turtle) ) {						#  if next step forward is permitted
			&stepForward($turtle);															#   move forward one step
		} else {																			#  else
			&turnLeft($turtle);																#   turn left
		}																					#  end if-else
	}																						# until all turtles processed
}																							#until all turtles have spun around
exit;
#===== SUBROUTINES =============================================================================================================
sub noTracksAhead {
	my $turtle = shift;
	if   ( $Bale[$turtle]{HEADING} eq 'S' ) { return !$Tracks[$Bale[$turtle]{X}][$Bale[$turtle]{Y}+1]; }
	elsif( $Bale[$turtle]{HEADING} eq 'N' ) { return !$Tracks[$Bale[$turtle]{X}][$Bale[$turtle]{Y}-1]; }
	elsif( $Bale[$turtle]{HEADING} eq 'E' ) { return !$Tracks[$Bale[$turtle]{X}+1][$Bale[$turtle]{Y}]; }
	elsif( $Bale[$turtle]{HEADING} eq 'W' ) { return !$Tracks[$Bale[$turtle]{X}-1][$Bale[$turtle]{Y}]; }
}
#-------------------------------------------------------------------------------------------------------------------------------
sub noBoundaryAhead {
	my $turtle = shift;
	if   ( $Bale[$turtle]{HEADING} eq 'S' ) { return $Bale[$turtle]{Y} + 1 <  $No_Rows; }
	elsif( $Bale[$turtle]{HEADING} eq 'N' ) { return $Bale[$turtle]{Y} - 1 >= 0;        }
	elsif( $Bale[$turtle]{HEADING} eq 'E' ) { return $Bale[$turtle]{X} + 1 <  $No_Cols; }
	elsif( $Bale[$turtle]{HEADING} eq 'W' ) { return $Bale[$turtle]{X} - 1 >= 0;        }
}
#-------------------------------------------------------------------------------------------------------------------------------
sub stepForward {
	my $turtle = shift;
	if   ( $Bale[$turtle]{HEADING} eq 'S' ) { ++$Bale[$turtle]{Y}; }
	elsif( $Bale[$turtle]{HEADING} eq 'N' ) { --$Bale[$turtle]{Y}; }
	elsif( $Bale[$turtle]{HEADING} eq 'E' ) { ++$Bale[$turtle]{X}; }
	elsif( $Bale[$turtle]{HEADING} eq 'W' ) { --$Bale[$turtle]{X}; }
	$Tracks[$Bale[$turtle]{X}][$Bale[$turtle]{Y}]	= 1;									# update bale's accessed locations
	$No_Consecutive_Turns[$turtle]					= 0;									# reset turtle's turn count
	print "stepForward: Turtle #$turtle - $Bale[$turtle]{X}, $Bale[$turtle]{Y}\n";		# report location
}
#-------------------------------------------------------------------------------------------------------------------------------
sub turnLeft {
	my $turtle = shift;
	$Bale[$turtle]{HEADING} =~ tr/NSEW/WENS/;
	++$No_Consecutive_Turns[$turtle];														# update turtle's turn count
	print "turnLeft: Turtle #$turtle - $Bale[$turtle]{HEADING}\n";						# report new heading
}
#-------------------------------------------------------------------------------------------------------------------------------
sub sumArray {
	my $sum;
	
	$sum += $_ for @_;
	return $sum;
}
#===== Copyright 2008, Webpraxis Consulting Ltd. - ALL RIGHTS RESERVED - Email: webpraxis@gmail.com ============================
# end of __turtle.pl

