#!/usr/bin/perl -w

######################################################################
#                                                                    #
# (c) Anthony G. Basile, Oct. 20, 2001                               #
#                                                                    #
# Description: Fido for OV                                           #
#                                                                    #
######################################################################
#
# Packages
#

use Socket ;
use POSIX ;


#
# Configuration
#

$master = "DrB" ;
$dog    = "Tux"   ;
$woof   = "Quack!" ;


#
# Get the arguments.
#

if ( $ARGV[0] ne "" ) { $host = $ARGV[0] ; } else { $host = 'localhost'; }
if ( $ARGV[1] ne "" ) { $port = $ARGV[1] ; } else { $port = 7000 ; }


#
# Get the av data
#
 
%avatars = () ;
 
open( AVDATA, "<avatars/avs.dat" ) ;
while (<AVDATA>) {
	$line = $_ ;
	chomp($line) ;
	$name = $line ;
	$name =~ s/\s+.*// ;
	$line =~ s/^$name\s+// ;
	$avatars{$name} = $line ;
}
close(AVDATA) ;


#
# Prepare a socket for connection
#

$server = gethostbyname($host) ;
$proto  = getprotobyname('tcp') ;
$lsock  = sockaddr_in( $port, $server ) ;
socket ( CSOCK, PF_INET, SOCK_STREAM, $proto ) ;
connect( CSOCK, $lsock ) ;


#
# Start the communication
#

%users = () ;

$currentav = 'basic' . 'penguin' . 'mr' ;

$messout = "AUTH $dog 350 200 $avatars{$currentav}\n" ;
print "-> " . $messout ;
syswrite( CSOCK, $messout, length($messout) ) ; 

while(1) {
	sysread ( CSOCK, $messin, 32767 ) ;
	print "<- " . $messin ;

	if( length($messin) == 0 ) { byebye() ; }

	@lines = split( /\n/, $messin ) ;

	$messout = "" ;

	for( $i = 0 ; $i <= $#lines ; $i++ ) {

		if ( $lines[$i] =~ /^PING/ ) {
			pinged(\$response) ;
			$messout .= $response ;
		}

		if ( $lines[$i] =~ /^DCCSENDAV/ ) {
			$dcc = $lines[$i] ;
			$dcc =~ s/^DCCSENDAV\s+// ;
			dccsendav( $dcc ) ;
			$messout .= "AVATAR $avatars{$currentav}\n" ;          # AVATAR file.gif x-av y-av size x-bubble y-bubble
		}

		if ( $lines[$i] =~ /^CHAT/ ) {
			$chat = $lines[$i] ;
			$chat =~ s/^CHAT\s+// ;
			chatted( $chat, \$response ) ;
			$messout .= $response ;
		}

		if ( $lines[$i] =~ /^SCHAT/ ) {
			$chat =  $lines[$i] ;
			$chat =~ s/^SCHAT\s+\w+\s+// ;
			chatted( $chat, \$response ) ;
			$messout .= $response ;
		}

		if ( $lines[$i] =~ /^NEW/ ) {
			$new = $lines[$i] ;
			$new =~ s/^NEW\s+// ;
			newed( $new, \$response ) ;
			$messout .= $response ;
		}

		if ( $lines[$i] =~ /^NOMORE/ ) {
			$nomore = $lines[$i] ;
			$nomore =~ s/^NOMORE\s+// ;
			nomored( $nomore ) ;
		}

		if ( $lines[$i] =~ /^MOVE/ ) {
			$move = $lines[$i] ;
			$move =~ s/^MOVE\s+// ;
			moved( $move, \$response ) ;
			$messout .= $response ;
		}
	}

	if ( length($messout) > 0 ) {
		print "-> " . $messout ;
		syswrite( CSOCK, $messout, length($messout) ) ;
	}
}




#
# Subtroutines
#

sub pinged {
	my ( $response ) = @_ ;
	$$response = "PONG\n" ;
}



sub dccsendav {
	my ( $dcc ) = @_ ;
	my ( $server, $port, $proto, $lsock, $file, $data ) ;
 
	$port = $dcc ; $port =~ s/^(\d+)\s+.*$/$1/ ;
	$file = $dcc ; $file =~ s/^\d+\s+(.*)$/$1/ ;
 
	$server = gethostbyname($host) ;
	$proto  = getprotobyname('tcp') ;
	$lsock  = sockaddr_in( $port, $server ) ;
	socket ( DSOCK, PF_INET, SOCK_STREAM, $proto ) or die "no socket\n" ;
	connect( DSOCK, $lsock ) or die "no connection\n" ;
 
	open( FILE, "<avatars/$file" ) ;
	while(1) {
		sysread ( FILE, $data, 256 ) ;
		if ( length($data) > 0 ) {
			syswrite( DSOCK, $data, length($data) ) ;
		} else {
			goto EXIT ;
		}
	}
 
EXIT:
	sleep(5) ;
	close(FILE) ;
	close(DSOCK) ;
}



sub chatted {
	my ( $chat, $response ) = @_ ;
	my ( $name, $msg, $string, $user, $pos, $x, $y, $speed, $av ) ;

	$name = $chat ; $name =~ s/\s+.*// ;
	$msg  = $chat ; $msg  =~ s/^$name // ; $msg = ' ' . $msg . ' ' ;  # white pad the msg

	$$response = "" ;

	#DOG's name must be said to trigger a command
	if ( $name =~ /$dog/i  or $msg !~ /\s$dog\s/i ) { return   ; }

	#Only the master can ask the dog to quit
	if ( $name eq $master and $msg =~ /\squit\s/i ) { byebye() ; }

	#HELP
	if ( $msg =~ /\shelp\s/i ) {
		$$response .= "PRIVMSG $name Just say my name and any of the following words in the same sentence: " .
		"sit, good, bad, jump, shiver, speak, fortune, beg, move, dance, play, count to <number>, come, heel (off), " .
		"go to <username>, hug <username>, kiss <username>\n" ;
	}

	#SIT
	if ( $msg =~ /\ssit\s/i ) {
		$$response .= "CHAT $woof\n" ;
		$currentav = 'basic' . 'penguin' . 'mr' ;
		$$response .= "AVATAR $avatars{$currentav}\n" ;
	}

	#GOOD
	if ( $msg =~ /\sgood\s/i ) {
		$$response .= "CHAT $woof\n" ;
		$currentav = 'angel' . 'penguin' . 'mr' ;
		$$response .= "AVATAR $avatars{$currentav}\n" ;
	}

	#BAD
	if ( $msg =~ /\sbad\s/i ) {
		$$response .= "CHAT $woof\n" ;
		$currentav = 'devil' . 'penguin' . 'mr' ;
		$$response .= "AVATAR $avatars{$currentav}\n" ;
	}

	#JUMP
	if ( $msg =~ /\sjump\s/i )    { $$response .= "CHAT $woof\nEFFECT jump\n"   ; }

	#SHIVER
	if ( $msg =~ /\sshiver\s/i )  { $$response .= "CHAT $woof\nEFFECT shiver\n" ; }

	#SPEAK
	if ( $msg =~ /\sspeak\s/i )   { $$response .= "CHAT $woof $name $woof $woof\n" ; }

	#FORTUNE
	if ( $msg =~ /\sfortune\s/i ) {
		$string = `/usr/bin/fortune` ;	#Change this to wherever your fortune executable is
		$string =~ s/\n/ /g ;
		$$response .= "CHAT " . $string . "\n" ;
	}

	#BEG
	if ( $msg =~ /\sbeg\s/i )     {
		$pos = $users{$name} ;
		position( $pos, \$x, \$y ) ;
		$y += 50 ;
		$$response .= "MOVE $dog $x $y 1\nEFFECT jump\nCHAT $woof $woof $woof\n" ;
	}

	#MOVE
	if ( $msg =~ /\smove\s/i ) {
		$pos = $users{$dog} ;
		position( $pos, \$x, \$y ) ;
		$x += int(100*(2*rand()-1)) ;
		$y += int(100*(2*rand()-1)) ;
		$$response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
	}

	#DANCE
	if ( $msg =~ /\sdance\s/i ) {
		$pos = $users{$dog} ;
		position( $pos, \$x, \$y ) ;
		$$response .= "CHAT $woof\n" ;
		$y += 50 ;
		$$response .= "EFFECT jump\nMOVE $dog $x $y 1\n" ;
		$x += 50 ;
		$$response .= "EFFECT shiver\nMOVE $dog $x $y 1\n" ;
		$y -= 50 ;
		$$response .= "EFFECT jump\nMOVE $dog $x $y 1\n" ;
		$x -= 50 ;
		$$response .= "EFFECT shiver\nMOVE $dog $x $y 1\n" ;
		$$response .= "EFFECT jump\n" ;
	}

	#PLAY
	if ( $msg =~ /\splay\s/i ) {
		$$response .= "CHAT $woof\n" ;
		for ($i=0;$i<5;$i++) {
			$x = int(640*rand()) ;
			$y = int(480*rand()) ;
			$speed = int(8*rand()) + 1 ;
			$$response .= "MOVE $dog $x $y $speed\n" ;
		}
	}

	#COUNT
	if ( $msg =~ /\scount\s+to\s/i ) {
		$x = $msg ;
		$x =~ s/^.*count\s+to\s+(\d+).*$/$1/ ;
		$$response .= "CHAT" ;
		if ( 0 < $x and $x <= 10 ) {
			for( $i=1 ; $i<=$x ; $i++ ) { $$response .= " $woof" ; }
		} else {
			$$response .= " eh?" ;
		}
		$$response .= "\n" ;
	}

	#COME
	if ( $msg =~ /\scome\s/i ) {
		$pos = $users{$name} ;
		position( $pos, \$x, \$y ) ;
		$x += 50 ;
		$y += 50 ;
		$$response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
	}

	#HEEL
	if ( $msg =~ /\sheel\s/i ) {
		if ( $msg =~ /\soff\s/i ) {
			undef($heel) ;
		} else {
			$heel = $name ;
			$pos = $users{$name} ;
			position( $pos, \$x, \$y ) ;
			$x += 50 ;
			$y += 50 ;
			$$response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
		}
	}

	#GO TO
	if ( $msg =~ /\sgo\s+to\s/i ) {
		$target = $msg ;
		$target =~ s/.*\sgo\s+to\s+(\S+)\s.*\s/$1/ ;
		foreach $user ( keys(%users) ) {
			if ( $target =~ /$user/i or $user =~ /$target/i ) {
				$pos = $users{$user} ;
				position( $pos, \$x, \$y ) ;
				$x += 50 ;
				$y += 50 ;
				$$response .= "CHAT $woof\nMOVE $dog $x $y 1\n" ;
			}
		}
	}

	#HUG
	if ( $msg =~ /\shug\s/i ) {
		$target = $msg ;
		$target =~ s/.*\shug\s+(\S+)\s.*\s/$1/ ;
		foreach $user ( keys(%users) ) {
			if ( $target =~ /$user/i or $user =~ /$target/i ) {
				$pos = $users{$user} ;
				position( $pos, \$x, \$y ) ;
				$$response .= "MOVE $dog $x $y 1\nEFFECT shiver\nSCHAT LOVE $woof\n" ;
				$x -= 50 ;
				$y += 50 ;
				$$response .= "MOVE $dog $x $y 1\n" ;
			}
		}
	}

	#KISS
	if ( $msg =~ /\skiss\s/i ) {
		$target = $msg ;
		$target =~ s/.*\skiss\s+(\S+)\s.*\s/$1/ ;
		foreach $user ( keys(%users) ) {
			if ( $target =~ /$user/i or $user =~ /$target/i ) {
				$pos = $users{$user} ;
				position( $pos, \$x, \$y ) ;
				$y += 50 ;
				$$response .= "MOVE $dog $x $y 1\nEFFECT jump\nSCHAT LOVE Smoooches!\n" ;
				$x += 50 ;
				$$response .= "MOVE $dog $x $y 1\n" ;
			}
		}
	}
      

#
#   The 'who', 'where', 'avatars' and 'wear' command are used mostly for development
#
	#WHO
	if ( $msg =~ /\swho\s/i )    {
		$$response .= "CHAT The users here are :" ;
		foreach $user ( keys(%users) ) {
			$$response .= " $user " ;
		}
		$$response .= "\n" ;
	}

	#WHERE
	if ( $msg =~ /\swhere\s/i )  {
		foreach $user ( keys(%users) ) {
			$pos = $users{$user} ;
			position( $pos, \$x, \$y ) ;
			$$response .= "CHAT $user is at $x $y\n" ;
		}
	}

	#AVATARS
	if ( $msg =~ /\savatars\s/i ) {
		$$response .= "CHAT " ;
		foreach $av ( keys(%avatars) ) {
			$$response .= $av . " " ;
		}
		$$response .= "\n" ;
	}

	#WEAR
	if ( $msg =~ /\swear\s/i ) {
		$av = $msg ;
		$av =~ s/.*\swear\s+(\S+)\s.*/$1/ ;
		if ( exists($avatars{$av}) ) {
			$currentav = $av ;
			$$response .= "AVATAR $avatars{$currentav}\n" ;
		}
	}
}



sub newed {
	my ( $new, $response ) = @_ ;
	my ( $name, $info ) ;

	$name = $new ; $name =~ s/\s+.*// ;
	$info = $new ; $info =~ s/^$name // ;

	$users{$name} = $info ;

	$$response = "" ;

	if ( $name ne $dog ) {
		$$response  = "PRIVMSG $name Hello, I am DrTony\'s bot.\n" ;
		$$response .= "PRIVMSG $name To find out how I work, just say \"$dog help\"\n" ;
	}
}



sub nomored {
	my ( $name ) = @_ ;
	$name =~ s/\s+.*// ;
	delete( $users{$name} ) ;
}



sub moved {
	my ( $move, $response ) = @_ ;
	my ( $name, $pos, $x, $y ) ;

	$name = $move ; $name =~ s/\s+.*// ;
	$pos  = $move ; $pos  =~ s/^$name\s+// ;

	position( $pos, \$x, \$y ) ;

	$users{$name} =~ s/^\d+ \d+/$x $y/ ;

	$$response = "" ;

	if ( defined($heel) ) {
		if ( $heel eq $name ) {
			$x += 50 ;
			$y += 50 ;
			$$response .= "MOVE $dog $x $y 1\n" ;
		}
	}
}



sub position {
	my ( $pos, $x, $y ) = @_ ;

	$pos =~ s/^(\d+)\s+(\d+).*$/$1 $2/ ;

	$$x = $pos ; $$x =~ s/ \d+$// ;
	$$y = $pos ; $$y =~ s/^\d+ // ;
}



sub byebye {
	close CSOCK ;
	exit ;
}



