#!/usr/bin/perl
#!/usr/bin/perl -w

# copyright 2002 John Hazen.  All rights reserved, with the following
#  exceptions:
#   The ICFP contest administration is granted the use of this code
#   and the right to publish it on the contest website, and at the 
#   ICFP conference.

# This is pretty ugly code -- a hazard of not getting enough sleep,
# and wanting to put in more time adding "features".

require 5.002;
use Socket;

my $verbose = 1;	# higher number == more verbose. 0= server responses only.
my $interactive = 0;	# if set, prints map and allows stepping thru.
my $turns_to_print = 1;	# for interactive use.
my $min_big_bid = 4;	# if we get in traffic, use at least this bid.

my %packs;
my %location;
my @words;
my ($loc,$last_command);
my $big_bid = $min_big_bid;
my $dist_compiled_multi = 2; # assure the distances get compiled the first time

my $turns = 0;
my $nop = 0;
my ($remote,$port, $line);

$remote  = shift || 'icfp1.cse.ogi.edu';
$port    = shift || 22001;  # random port
$start_x = shift;
$start_y = shift;
$start_command = "Player";
$start_command = "Login $start_x $start_y" if ($start_x);

use IO::Socket;
my $sock = new IO::Socket::INET (
                                 PeerAddr => $remote,
                                 PeerPort => $port,
                                 Proto => 'tcp',
                                );
die "Could not create socket: $!\n" unless $sock;

print $sock "$start_command\n";
die "I died.\n" unless defined($line = <$sock>);
die "unexpected board size: $line" unless ($line =~ /^(\d+) (\d+)$/);
my ($max_x,$max_y)=($1,$2);
print "x/y = $max_x / $max_y \n";
for ($i=1;$i<=$max_y;$i++) {
	die "I died.\n" unless defined($line = <$sock>);
	die "unexpected map line: $line" unless ($line =~ /^([\.\@\#\~]{$max_x})$/);
	chomp $line;
	@chars = split //, $line;
	push @chars, '#';
	unshift @chars, '#';
	$map[$i] = [ @chars ];
}
$line = "#" x ($max_x +2);
@chars = split //, $line; 
$map[$i] = [ @chars ];
$map[0] = [ @chars ];

$homes{0} = 0;

for ($y=0;$y<=$max_y;$y++) {
	for ($x=0;$x<=$max_x;$x++) {
		if ($map[$y][$x] eq "@") {
			$homes{0}++;
			$homes{$homes{0}}->{active} = 1;
			$homes{$homes{0}}->{x} = $x;
			$homes{$homes{0}}->{y} = $y;
			$location{"$x,$y"}{h}{$homes{0}} = 1;
			#$homes{$homes{0}}->{dist} = distance($x,$y);
		}
	}
}

die "I died.\n" unless defined($line = <$sock>);
die "unexpected initialization: $line" unless ($line =~ /^(\d+) (\d+) (\d+)$/);
my ($id,$cap,$fuel)=($1,$2,$3);
my $orig_fuel = $fuel;
my $backoff = 0;
print "id = $id, cap= $cap, fuel=$fuel\n";
$robots{$id}->{cap} = $cap;
$robots{$id}->{fuel} = $fuel;
$robots{$id}->{packages} = [];
$robots{$id}->{dest_x} = 0;
$robots{$id}->{dest_y} = 0;
$robots{$id}->{packs} = ();

while (1) {
	die "I died.\n" unless defined($line = <$sock>);
	print "status:$line";
	death() if ($line =~ /died/);
	update_status($line);
	#print "my xy: ", $robots{$id}->{x}, ", ", $robots{$id}->{y}, "\n";

	die "I died.\n" unless defined($line = <$sock>);
	print "packs:$line" if ($line =~ /\S/);
	death() if ($line =~ /died/);
	undef(%local_packs);
	$loc = $robots{$id}->{x} . "," . $robots{$id}->{y};
	if ($line =~ /^$/) {
		foreach $key (keys %{$location{$loc}{h}}) {
			print "deleting home base at $key\n" if ($verbose >1);
			$map[$robots{$id}->{y}][$robots{$id}->{x}] = '.';
			delete $homes{$key};
		}
	}
	foreach $key (keys %{$location{$loc}{p}}) {
		delete $packs{$key};
	}
	delete $location{$loc}{p};
	while ($line =~ /(\d+) (\d+) (\d+) (\d+)/g) {
		$packs{$1}->{x} = $2;
		$packs{$1}->{y} = $3;
		# current location is here.
		$packs{$1}->{loc} = $loc;
		$packs{$1}->{w} = $4; #weight
		#push @{$packs{"$2,$3"}->{$4}}, $1;
		push @{$local_packs{"$2,$3"}->{$4}}, $1;
		#$location{"$2,$3"}{p}{$1} = 1;
		$location{$loc}{p}{$1} = 1;
		print "pack: $1 ($2,$3) w$4\n" if ($verbose >1);
	}

	print "fuel left: $fuel\n" if ($verbose >1);
	print_map(1) unless --$turns_to_print;
	$command = do_turn();
	@words = split ' ',$command;
	$fuel -= $words[0];
	print $sock "$command\n";
	print "SENT: $command\n" if ($verbose);
	$turns++;
	$backoff++;
	$nop-- if ($nop);
	if ($backoff >4) {
		# the backoff lets us conserve money once we get out of traffic.
		$backoff = 0;
		$big_bid-- if ($big_bid > $min_big_bid);
	}
}

close($sock);
exit;

sub get_max_packs {
	my ($ref) = @_;
	my ($key,$x,$y,$room,$dist,$max_dist);
	my @max = (0);
	my @packs;

	$room = $cap;	# eventually $cap-current packs
	foreach $key (@{$robots{$id}->{packs}}) {
		$room -= $packs{$key}->{w};
	}
	$max_dist = 1000000;

	foreach $key (keys(%{$ref})) {
		next unless ($key =~ /(\d+),(\d+)/);
		print "GMP: key is $key. room is $room\n" if ($verbose>1);
		$x = $1; $y=$2; # eventually score by distance and weight.
		$dist = total_distance($x,$y);
		$dist = 1 unless $dist;
		@packs = get_dest_packs($ref->{$key},$key,$room);
		print "GMP: pack for above key:", @packs, "\n" if ($verbose>1);
		if (($packs[0] / $dist) > ($max[0] / $max_dist)) {
			@max = @packs;
			$max_dist = $dist;
		}
		#return @max if ($max[0] >= $room);
	}
	return @max;
}

sub get_dest_packs {
	my ($ref,$key,$room) = @_;
	my @packs;
	my @max_packs = (0);
	my($i);

	for ($i=$room;$i>0;$i--) {
		print "GDP: i is $i\n" if ($verbose>2);
		@packs = get_rest_packs($ref,$key,$room,$i);
		#next unless (@packs[0]);
		if ($packs[0] > $max_packs[0]) {
			@max_packs = @packs;
			print "GDP: max_packs: ", @max_packs, "\n" if ($verbose>2);
			return @max_packs if ($max_packs[0] >= $room);
		}
	}
	return @max_packs;
}

sub get_rest_packs {
	my ($ref,$key,$room,$start) = @_;	#$ref is to hash of weight->id_list
	my($i,$id);
	#my @packs;
	#my %work_packs = %{$ref};
	my @packs = reverse %{$ref};
	my %work_packs = reverse @packs;

	$start = $room if ($room < $start);
	for ($i=$start;$i>0;$i--) {
		print "GRP: room is $room, i is $i\n" if ($verbose>2);
		$id = get_pack_id(\@{$work_packs{$i}});
		if (defined($id)) {
			print " GRP: found id $id\n" if ($verbose>2);
			@packs = get_rest_packs(\%work_packs,$key,$room-$i,$start);
			return @packs if ($packs[0] >= $room);
			push @packs, $id;
			$packs[0] += $i;
			print " GRP: returning array: ", @packs, "\n" if ($verbose>2);
			return @packs;
		}
	}
	return (0);
}

sub get_pack_id {
	my ($ref) = @_;
	return shift @{$ref};
}

sub do_turn {
	my ($ref,$x,$y,$pri,$dist,$dir,$cost,$i,$command,$pack_id,$bid,$robot);
	my @pack_list = ();
	my @symbols = split //, "0123456789abcdefghijklmnopqrstuvwxyz";

	print "entering do_turn\n" if ($verbose>2);

	if ($nop) {
		$last_command = "";
		return "1 Pick" if ($nop);
	}
	$bid = 1;
	#increase magnitude of bid if other robots are adjacent
	foreach $robot (keys(%robots)) {
		next if ($robot == $id);	# don't count self
		print "do_turn: adjacent robot is $robot. I am $id.\n" if ($verbose>2);
		if (adjacent($id,$robot)) {
			$bid = $big_bid;
			print "$robot is adjacent to ME. bid is $bid.\n" if ($verbose>0);
			if ($big_bid > 16) {
				$nop = $big_bid;
				$big_bid = $min_big_bid;
			}
			if ($big_bid > 12) {
				#move aside.
				if ($robots{$robot}{x} == $robots{$id}{x}) {
					# robot is north or south of me.
					$x = $robots{$id}{x};
					$y = $robots{$id}{y};
					unless 
						(($map[$y][$x+1] eq "~") or ($map[$y][$x+1] eq "#") or
						($map[$y][$x+2] eq "~")) {
						$last_command = "E";
						return "$bid Move E";
					}
					unless 
						(($map[$y][$x-1] eq "~") or ($map[$y][$x-1] eq "#") or
						($map[$y][$x-2] eq "~")) {
						$last_command = "W";
						return "$bid Move W";
					}
				}
				if ($robots{$robot}{y} == $robots{$id}{y}) {
					# robot is east or west of me.
					$x = $robots{$id}{x};
					$y = $robots{$id}{y};
					unless 
						(($map[$y+1][$x] eq "~") or ($map[$y+1][$x] eq "#") or
						($map[$y+2][$x] eq "~")) {
						$last_command = "N";
						return "$bid Move N";
					}
					unless 
						(($map[$y-1][$x] eq "~") or ($map[$y-1][$x] eq "#") or
						($map[$y-2][$x] eq "~")) {
						$last_command = "S";
						return "$bid Move S";
					}
				}
			}
		}
	}

	if ("I am next to water and another robot is near") {
		#move to safety
	}
	if (($robots{$id}->{dest_x} == $robots{$id}->{x}) and
			($robots{$id}->{dest_y} == $robots{$id}->{y}) and
			scalar(@{$robots{$id}->{packs}}) ) {
		#we are at our dest and we have packs...
		#drop all packs for this dest
		foreach $pack_id (@{$robots{$id}->{packs}}) {
			if (($packs{$pack_id}->{x} == $robots{$id}->{x}) and
					($packs{$pack_id}->{y} == $robots{$id}->{y})) {
				push @pack_list, $pack_id;
			}
		}
		$command = "$bid Drop " . join(' ',@pack_list);
		$last_command = "D " . join(' D ',@pack_list);
		print "$command\n" if ($verbose>0);
		return $command;
	}
	if (%local_packs) {
		print "calling get_max_packs\n" if ($verbose>1);
		@pack_list = get_max_packs(\%local_packs);
		if ($pack_list[0]) {
			shift @pack_list;	# first item is the weight, not an id.
			$command = "$bid Pick " . join(' ',@pack_list);
			$last_command = "P " . join(' P ',@pack_list);
			print "$command\n" if ($verbose>0);
			return $command;
		}
	}
	$cost = 1000000;
	if (!$target) {
		if (scalar(@{$robots{$id}->{packs}})) {
			#for now assume one dest, pick dest of first pack.
			$pack_id = $robots{$id}->{packs}->[0];
			print "pack_id is $pack_id\n" if ($verbose>2);
			$x = $packs{$pack_id}->{x};
			$y = $packs{$pack_id}->{y};
			$target = distance($x,$y);
			$robots{$id}->{dest_x} = $x;
			$robots{$id}->{dest_y} = $y;
		} else {
			foreach $i (keys(%homes)) {
				#($x,$y,$pri) = @{$ref};
				next if ($i == 0);	# zero is just used for a counter
				$x = $homes{$i}->{x};
				$y = $homes{$i}->{y};
				print "target at $x,$y with id $i\n" if ($verbose>1);
				$dist = $homes{$i}->{dist};
				if (lessthan($dist->[$robots{$id}->{y}+1][$robots{$id}->{x}], $cost)) {
					$cost = $dist->[$robots{$id}->{y}+1][$robots{$id}->{x}];
					$target = $i;
				}
				if (lessthan($dist->[$robots{$id}->{y}-1][$robots{$id}->{x}], $cost)) {
					$cost = $dist->[$robots{$id}->{y}-1][$robots{$id}->{x}];
					$target = $i;
				}
				if (lessthan($dist->[$robots{$id}->{y}][$robots{$id}->{x}+1], $cost)) {
					$cost = $dist->[$robots{$id}->{y}][$robots{$id}->{x}+1];
					$target = $i;
				}
				if (lessthan($dist->[$robots{$id}->{y}][$robots{$id}->{x}-1], $cost)) {
					$cost = $dist->[$robots{$id}->{y}][$robots{$id}->{x}-1];
					$target = $i;
				}
				print "target is $target\n" if ($verbose>1);
			}
			if (!$target) {
				print "OUT OF HOME BASES!\n" if (!$target);
				exit;
			}
			print "assigning new dest_x/y for target $target\n" if ($verbose >2);
			$robots{$id}->{dest_x} = $homes{$target}->{x};
			$robots{$id}->{dest_y} = $homes{$target}->{y};
		}
	}
	# check to see if we've reached our destination, and didn't notice
	# this would happen if the home that we were heading for didn't
	# have any pack left when we got there.
	if (($robots{$id}->{dest_x} == $robots{$id}->{x}) and
			($robots{$id}->{dest_y} == $robots{$id}->{y}) ) {
		#TODO: maybe other logic here?
		remove_home($robots{$id}->{x},$robots{$id}->{y});
		reset_target();
		$last_command = "";
		return "1 Pick";	# this should be a NOP
	}
	$cost = 1000000;
	if (ref($target) eq "ARRAY") {
		$dist = $target;
	} else {
		$dist = $homes{$target}->{dist};
	}
	if (lessthan($dist->[$robots{$id}->{y}+1][$robots{$id}->{x}], $cost)) {
		$cost = $dist->[$robots{$id}->{y}+1][$robots{$id}->{x}];
		$robots{-1}{x} = $robots{$id}->{x};
		$robots{-1}{y} = $robots{$id}->{y} + 1;
		$dir = 'N';
	}
	if (lessthan($dist->[$robots{$id}->{y}-1][$robots{$id}->{x}], $cost)) {
		$cost = $dist->[$robots{$id}->{y}-1][$robots{$id}->{x}];
		$robots{-1}{x} = $robots{$id}->{x};
		$robots{-1}{y} = $robots{$id}->{y} - 1;
		$dir = 'S';
	}
	if (lessthan($dist->[$robots{$id}->{y}][$robots{$id}->{x}+1], $cost)) {
		$cost = $dist->[$robots{$id}->{y}][$robots{$id}->{x}+1];
		$robots{-1}{x} = $robots{$id}->{x} + 1;
		$robots{-1}{y} = $robots{$id}->{y};
		$dir = 'E';
	}
	if (lessthan($dist->[$robots{$id}->{y}][$robots{$id}->{x}-1], $cost)) {
		$cost = $dist->[$robots{$id}->{y}][$robots{$id}->{x}-1];
		$robots{-1}{x} = $robots{$id}->{x} - 1;
		$robots{-1}{y} = $robots{$id}->{y};
		$dir = 'W';
	}
	#increase magnitude of bid if other robots are adjacent
	foreach $robot (keys(%robots)) {
		next if ($robot == $id);	# don't count self
		if (adjacent(-1,$robot)) {
			$bid = -1 * $big_bid;
			print "$robot is adjacent to my target. bid is $bid.\n" if ($verbose>0);
		}
	}
	delete $robots{-1}; # clean up tmp robot after computation
	print "distance to target: $cost\n" if ($verbose);
	$last_command = "$dir";
	return "$bid Move $dir";
}

close($sock);
exit;

# total distance figures distance from my current pos to the point
#  and then from the point to the nearest home to that point.
sub total_distance {
	my ($x,$y) = @_;
	my ($i,$tmp);
	my $cost = 1000000;
	my $dist = distance($x,$y);
	my $total = get_distance($robots{$id}->{x},$robots{$id}->{y},$dist);
	foreach $i (keys(%homes)) {
		next if ($i == 0);	# zero is just used for a counter
		$dist = $homes{$i}->{dist};
		$tmp = get_distance($x,$y,$dist);
		$cost = $tmp if (lessthan($tmp, $cost));
	}
	$total += $cost;
	return $total;
}

# gets distance from the point to the dest in the distance array
sub get_distance {
	my ($x,$y,$dist) = @_;
	my $cost = 1000000;

	$cost = $dist->[$y+1][$x] if (lessthan($dist->[$y+1][$x], $cost));
	$cost = $dist->[$y-1][$x] if (lessthan($dist->[$y-1][$x], $cost));
	$cost = $dist->[$y][$x+1] if (lessthan($dist->[$y][$x+1], $cost));
	$cost = $dist->[$y][$x-1] if (lessthan($dist->[$y][$x-1], $cost));
	return $cost;
}

sub remove_home {
	my ($x,$y) = @_;
	my ($key);
	
	foreach $key (keys(%homes)) {
		next if ($key == 0);
		if (($homes{$key}->{x} == $x) and ($homes{$key}->{y} == $y)) {
			print "deleting home base $key at $x,$y\n" if ($verbose >1);
			$map[$y][$x] = ".";
			delete $homes{$key};
			return;
		}
	}
}

sub lessthan {
	my ($a,$b) = @_;
	print "lessthan: $a < $b ?\n" if ($verbose>4);
	return 0 if (!defined($a));
	return 1 if (!defined($b));
	return 1 if ($a<$b);
	return 0;
}

sub update_status {
	my ($line) = @_;
	my ($token,$cur_id,$loc,$key,$command);
	my %robot_ids;

	my @tokens = $line =~ /\s?(\S+)/g;
	$others_present = 0;
	$cur_id = -1;
	while ($token = shift @tokens) {
		if ($token =~ /\#(\d+)/) {
			if ($cur_id == $id) {
				if ($last_command and ($command ne "$id $last_command")) {
					print "GOT PUSHED: $command vs $last_command\n" if ($verbose>1);
					print "-------------------------------------\n" if ($verbose>1);
					$big_bid++;	# increase size of bid for next time.
				}
			}
			$cur_id = $1;
			$robot_ids{$1} = 1;
			$command = "$1";
			$others_present = 1 if ($cur_id != $id);
			next;
		}
		$command .= " $token";
		if ($token =~ /^X/) {
			$robots{$cur_id}->{x} = shift @tokens;
			shift @tokens;
			$robots{$cur_id}->{y} = shift @tokens;
			$command .= $robots{$cur_id}->{x} . " Y " . $robots{$cur_id}->{y};
		}
		$robots{$cur_id}->{y}++ if ($token =~ /^N/);
		$robots{$cur_id}->{y}-- if ($token =~ /^S/);
		$robots{$cur_id}->{x}++ if ($token =~ /^E/);
		$robots{$cur_id}->{x}-- if ($token =~ /^W/);
		$loc = $robots{$cur_id}->{x} . "," . $robots{$cur_id}->{y};
		if ($token =~ /^P/) {
			$token = shift @tokens;
			$command .= " $token";
			push @{$robots{$cur_id}->{packs}}, $token;
			$packs{$token}->{loc} = $cur_id;
			delete $location{$loc}{p}{$token};
			#recompute target if we've picked up new packs.
			reset_target() if ($cur_id == $id);
		}
		if ($token =~ /^D/) {
			$token = shift @tokens;
			$command .= " $token";
			delete_id_from_list($robots{$cur_id}->{packs}, $token);
			$packs{$token}->{loc} = $loc;
			$location{$loc}{p}{$token} = 1;
			#recompute target if we've dropped packs.
			reset_target() if ($cur_id == $id);
		}
	}
	# if lose track of a robot, delete its packs...
	foreach $key (keys (%robots)) {
		unless ($robot_ids{$key}) {
			delete $robots{$key} unless $robot_ids{$key};
			print "robot $key died.\n" if ($verbose >1);
		}
	}
	if ($dist_compiled_multi != $others_present) {
		#recompile distances so we don't waste fuel when alone, but
		# we avoid the water when there are other players.
		foreach $key (keys(%homes)) {
			next if ($key == 0);
			$homes{$key}->{dist} = distance($homes{$key}->{x},$homes{$key}->{y});
		}
	}
}

# adjacent() - says whether two points, or two robots are adjacent
sub adjacent {
  my ($x1,$y1,$x2,$y2) = @_;
	if (!defined($x2)) {
		# if seconed point isn't there, then we're comparing robots.
		my $r1 = $x1;
		my $r2 = $y1;
		return 0 if ($r1 == $r2);	# for ease, a robot can't be adjacent to itself
		$x1 = $robots{$r1}->{x};
		$y1 = $robots{$r1}->{y};
		$x2 = $robots{$r2}->{x};
		$y2 = $robots{$r2}->{y};
	}
	
	return 1 if (($x1==$x2) and
							 (abs($y1 - $y2) == 1));
	return 1 if (($y1==$y2) and
							 (abs($x1 - $x2) == 1));
	return 0;
} 

sub reset_target {
	$target = 0;
	$robots{$id}->{dest_x} = 0;
	$robots{$id}->{dest_y} = 0;
}

sub delete_id_from_list {
	my ($ref,$id) = @_;
	my ($i);

	for ($i=0;$i<=$#{$ref};$i++) {
		if ($ref->[$i] == $id) {
			splice (@{$ref},$i,1);
			@{$ref} = () if (!defined(@{$ref}));
			return;
		}
	}
}

sub distance {
	my ($t_x,$t_y) = @_;	#target coords.
	my @distance;
	my ($x,$y,$d,$ref);
	my @coords = ([($t_x,$t_y,0)]);
		
	print "computing distance map for $t_x,$t_y\n" if ($verbose);

	for ($y=0;$y<=$max_y;$y++) {
		for ($x=0;$x<=$max_x;$x++) {
			$distance[$y][$x] = 1000000;
		}
	}

	while ($ref = shift @coords) {
		($x,$y,$d) = @{$ref};
		next if ($x<0 or $x>$max_x);
		next if ($y<0 or $y>$max_y);
		next if ($map[$y][$x] eq "#");
		next if ($map[$y][$x] eq "~");

		# should eventually only avoid water if other robots are in game.
		if ($others_present) {
			$d++ if ($map[$y][$x+1] eq "~");	#avoid water death
			$d++ if ($map[$y][$x-1] eq "~");	#avoid water death
			$d++ if ($map[$y+1][$x] eq "~");	#avoid water death
			$d++ if ($map[$y-1][$x] eq "~");	#avoid water death
			$dist_compiled_multi = 1;
		} else {
			$dist_compiled_multi = 0;
		}

		next if ($d >= $distance[$y][$x]);
		$distance[$y][$x]=$d;
		push @coords, [$x,$y-1,$d+1];
		push @coords, [$x,$y+1,$d+1];
		push @coords, [$x-1,$y,$d+1];
		push @coords, [$x+1,$y,$d+1];
	}

	return \@distance;
}

sub print_map {
	my ($clear) = @_;
	if ($clear) {
		for ($y=$max_y+1;$y>=0;$y--) {
			for ($x=0;$x<=$max_x+1;$x++) {
				$map[$y][$x] = "." unless (($map[$y][$x] eq "#") or
																	 ($map[$y][$x] eq "~") or 
																	 ($map[$y][$x] eq "@"));
			}
		}
	}
	foreach $key (keys(%robots)) {
		my $char = "x";
		$char = "*" if ($key == $id);
		$map[$robots{$key}->{y}][$robots{$key}->{x}] = $char unless
			($map[$robots{$key}->{y}][$robots{$key}->{x}] eq "@");
	}
	for ($y=$max_y+1;$y>=0;$y--) {
		for ($x=0;$x<=$max_x+1;$x++) {
			print $map[$y][$x];
		}
		print "\n";
	}
	return unless ($interactive);
	print "press enter to continue:";
	$foo = <STDIN>;
	if ($foo =~ /^(\d+)/) {
		$turns_to_print = $1;
	} else {
		$turns_to_print = 1;
	}
	$verbose = $1 if ($foo =~ /^[Vv].?(\d+)/);
	exit if ($foo =~ /^[Qq]/);
	if ($foo =~ /^[Dd]/) {
		#dump
		foreach $tmp (@{$robots{$id}->{packs}}) {
			print "pack id $tmp:", $packs{$tmp}->{x}, ",", $packs{$tmp}->{y},"\n";
		}
	}
	print "\n";
}

sub death() {
	while (defined($line = <$sock>)) {
		print "DEATH: $line";
	}
	print "used ", $orig_fuel-$fuel, " fuel in $turns turns.\n";
	close($sock);
	exit;
}
