From 346b1f05a77e69eead1c4dc7a6a9221c42d1ff35 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sat, 3 Dec 2011 15:37:45 +0100 Subject: [PATCH] Add example Perl client --- client/example.pl | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100755 client/example.pl diff --git a/client/example.pl b/client/example.pl new file mode 100755 index 0000000..ab67494 --- /dev/null +++ b/client/example.pl @@ -0,0 +1,154 @@ +#!/usr/bin/perl -w +# +# Example brmlife client. +# Partially based on the btraptor. +# +# To run e.g. 15 instances of this client, run this command inside screen: +# +# for i in `seq 1 15`; do screen ./example.pl; done + +use strict; +use warnings; + +use Switch; +use IO::Socket; + +$/ = "\r\n"; + +sub tick($) { + my ($socket) = @_; + + # read message from socket and parse it + my $line = ''; + my %state = (); + print "\n"; + while ( chomp($line = <$socket>) ) { + print "# $line\n"; + last if $line eq ''; + if ($line eq 'DEAD') { + print "[ii] im dead\n"; + exit(-2); + return; + } + + if ($line eq 'BUMP') { + print "[ii] bump\n"; + next; + } + + $line =~ m/^([^ ]+) (.*)$/; + my ($type, $value) = ($1, $2); + + if ($type eq 'energy') { + if ($value =~ /\D/) { + print "[ee] type energy wrong value\n"; + print $value . "\n"; + exit(-1); + } + $state{energy} = $value; + + } elsif ($type eq 'visual') { + if ($value !~ /^([^ ][^ ] )+([^ ][^ ])$/) { + print "[ee] type visual wrong value\n"; + print $value . "\n"; + exit(-1); + } + $state{visual} = [ split(" ", $value) ]; + } + } + + %state; +} + +sub take_action($%) { + my ($socket, %state) = @_; + + # Relative x,y coordinates for each movement/attack direction. + my @dirs = ([0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1]); + + # Move/attack desires for each direction. + my @move = ((0, 0, 0), (0, 0, 0), (0, 0, 0)); + my @attack = ((0, 0, 0), (0, 0, 0), (0, 0, 0)); + + # dirindex($x) returns @move, $attack index for given @dirs item. + sub dirindex { my ($dir) = @_; $dir->[0]+1 + 3*($dir->[1]+1) } + + # Relative x,y coordinates for each visual input, in order. + my @vdirs = ( + @dirs, + [0, -2], [1, -2], [2, -2], [2, -1], [2, 0], [2, 1], [2, 2], [1, 2], [0, 2], [-1, 2], [-2, 2], [-2, 1], [-2, 0], [-2, -1], [-2, -2], [-1, -2], + ); + + # Default direction in case of nothing interesting in the vicinity. + my $max = $dirs[1]; + + for my $i (0..$#{$state{visual}}) { + my ($type, $agent) = split(//, $state{visual}->[$i]); + my $dir = $vdirs[$i]; + + if (abs($dir->[0]) > 1 or abs($dir->[1]) > 1) { + # We do not support processing visual information + # for inputs two tiles away. + next; + } + + if ($agent eq 'x') { + # Herp + $move[dirindex($dir)] += 2; + } + + if ($agent eq 'a') { + # Corpse + $move[dirindex($dir)] += 4; + } + + if ($agent eq 'A') { + # Agent + $move[dirindex($dir)] += 7; + $attack[dirindex($dir)] += 1; + } + + if ($move[dirindex($dir)] > $move[dirindex($max)] or + ($move[dirindex($dir)] == $move[dirindex($max)]) and (int rand(2))) { + $max = $dir; + } + } + + if ($attack[dirindex($max)]) { + print $socket "attack_dir $max->[0] $max->[1]\r\n"; + } else { + print $socket "move_dir $max->[0] $max->[1]\r\n"; + } + print $socket "\r\n"; +} + + +# connect +my ($remote_host, $remote_port, $socket); +$remote_host = "localhost"; +$remote_port = 27753; + +$socket = IO::Socket::INET->new( + PeerAddr => $remote_host, + PeerPort => $remote_port, + Proto => "tcp", + Type => SOCK_STREAM +) or die "Couldn't connect to $remote_host:$remote_port : $@\n"; +print "[ii] connected\r\n"; + +# negotiate attributs +print $socket "move 1.0\r\n"; +print $socket "attack 1.0\r\n"; +print $socket "defense 1.0\r\n"; +print $socket "\r\n"; +print "[ii] agent created\r\n"; + +my %state = (); +while (%state = tick($socket)) { + print $state{energy} . "\n"; + print "[", join('], [', @{$state{visual}}), "]\n"; + + take_action($socket, %state); +} + +shutdown($socket, 2);