#!/usr/bin/perl

# Conversation 2 Library
# 7-May-95 Aneel Nazareth
# 12-May-96 Aneel Nazareth

$conversion=0.7;

### Data Abstraction

undef %convdata;
undef %keysdata;

# get(keyword,field,index)
sub get {
    $name=$_[0]."\t".$_[1]."\t".$_[2];	
    # warn "getting $name = $convdata{$name}\n";	 
    return $convdata{$name};
}

# put(keyword,index,field,value)
sub put {
    $name=$_[0]."\t".$_[1]."\t".$_[2];	
    # warn "putting $name = $_[3]\n";	 
    $keysdata{$_[0]}=$_[0];
    return $convdata{$name}=$_[3];
}
    
### Files

# readcharacter(filename)
# read a character file
sub readcharacter {
    open(FILE, "<$_[0]");

    $_=<FILE>;
    s/\n//;
    &put(character,0,charname,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,charauthor,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,introline,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,charstyle,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,userstyle,$_);

    $/=";\n";

    while (<FILE>) {
	s/;//;
	@array=split(/\n/, $_);
	$first=shift(@array);
	($randomize, $firstkey, $synonyms)=split(/\t/,$first,3);

	&put($firstkey,0,randomize,$randomize);
	@synonyms=split(/\t/, $synonyms);
	pop @synonyms;
	&put($firstkey,0,synonyms,$firstkey."\t".join("\t",@synonyms));
	&put($firstkey,0,count,$#array);

	$second=shift(@array);
	&put($firstkey,0,leadin);

	for ($i=0; $i<=$#array; $i++) {
	    ($response, $repeatable, $stayontopic)
		=split(/\t/,$array[$i]);
	    &put($firstkey,$i,response,$response);
	    &put($firstkey,$i,repeatable,$repeatable);
	    &put($firstkey,$i,stayontopic,$stayontopic);
	    &put($firstkey,$i,used,0);
	}
    }

    $/="\n";
    close(FILE);
}
# readcharacter(filename)
# read a character file
sub readcharacter {
    open(FILE, "<$_[0]");

    $_=<FILE>;
    s/\n//;
    &put(character,0,charname,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,charauthor,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,introline,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,charstyle,$_);

    $_=<FILE>;
    s/\n//;
    &put(character,0,userstyle,$_);

    $/=";\n";

    while (<FILE>) {
	s/;//;
	@array=split(/\n/, $_);
	$first=shift(@array);
	($randomize, $firstkey, $synonyms)=split(/\t/,$first,3);

	&put($firstkey,0,randomize,$randomize);
	@synonyms=split(/\t/, $synonyms);
	pop @synonyms;
	&put($firstkey,0,synonyms,$firstkey."\t".join("\t",@synonyms));
	&put($firstkey,0,count,$#array);

	$second=shift(@array);
	&put($firstkey,0,leadin);

	for ($i=0; $i<=$#array; $i++) {
	    ($response, $repeatable, $stayontopic)
		=split(/\t/,$array[$i]);
	    &put($firstkey,$i,response,$response);
	    &put($firstkey,$i,repeatable,$repeatable);
	    &put($firstkey,$i,stayontopic,$stayontopic);
	    &put($firstkey,$i,used,0);
	}
    }

    $/="\n";
    close(FILE);
}

# writecharacter(filename)
# write a character file
sub writecharacter {
    open(FILE, ">$_[0]");
    select(FILE);

    print &get(character,0,charname)."\n";
    print &get(character,0,charauthor)."\n";
    print &get(character,0,introline)."\n";
    print &get(character,0,charstyle)."\n";
    print &get(character,0,userstyle)."\n";

    foreach $firstkey (sort keys %keysdata) {

	print &get($firstkey,0,randomize)."\t";
	print $firstkey."\t";

	print &get($firstkey,0,synonyms)."\t0\t\n";
	$count = &get($firstkey,0,count);

	print &get($firstkey,0,leadin);

	for ($i=0; $i<$count; $i++) {
	    print "\n".&get($firstkey,$i,response)."\t";
	    print &get($firstkey,$i,repeatable)."\t";
	    print &get($firstkey,$i,stayontopic,$stayontopic);
	}
	print ";\n";
    }

    $/="\n";
    close(FILE);
}

### Conversation

# match(input, key)
# tell if key or any of its synonyms are in input
sub match {
    ($input, $onkey)=@_;
    
    $matched=0;

    foreach $syn ( split(/\t/,&get($onkey,0,synonyms)) ) {
	$matched=($input=~/$syn/i);
	$matchtext=$& if $matched;
	# warn "$syn , $input -> $matched '$matchtext'\n";
	last if $matched;
    }
    return(0) unless $matched;
    return($matchtext) if $matched;
}
	
# useableresponses(keyword)
# make an array containing the indices of the responses that may be used
# sort it so that we don't use repeatable responses again if unused
# responses remain
sub useableresponses {
    $keyword=$_[0];
    undef @useable;
    for ($i=0; $i<&get($keyword,0,count); $i++) {
	push(@useable, $i)
	    unless (&get($keyword,$i,used) && !&get($keyword,$i,repeatable));
	#warn "i=$i useable=@useable $keyword $#useable";
    }
    @useable = sort {&get($keyword,$a,used) <=> &get($keyword,$b,used)} @useable;
    #warn "$#useable $keyword";
    return $#useable;
}

# respond(input)
# respond properly to input
sub respond {
    $input=$_[0];

    $key='';

    # first let's see if we can match on the last key
    # in order to try to stay on topic
    # making sure, of course, that useable responses still exist...
    if ( $lastkey && &match($input,$lastkey)
	&& (&useableresponses($lastkey) >= 0) ) {
	$key=$lastkey; #warn "matched last $key\n";
    }

    # next we shall try to match on any key
    # making sure useable responses exist
    else {
	foreach $keyword (keys %keysdata) {
	    if ( &match($input,$keyword) 
		&& (&useableresponses($keyword) >= 0) ) {
		$key=$keyword; warn #"matched any $key\n";
		last;
	    }
	}
    }

    # no dice? then check to see if we're supposed to stay on topic
    $key=$lastkey if ((!$key) && ($lastkey) &&
		      (&get($lastkey,$lastresp,stayontopic)) );

    # give up and choose a dummy response
    $key='@DUMMY@' unless $key;

    # so now we've got a key...
    &useableresponses($key); # warn "$key useable=@useable\n";
    if (&get($key,0,randomize)) {
	$choice=rand $#useable;	# choose randomly
    } else {
	$choice=0;		# choose first
    }
    &put($key,$useable[$choice],used,
	 &get($key,$useable[$choice],used) + 1);
				# mark as used
    #warn &get($key,$useable[$choice],used);
    $lastkey=$key;		# set variables for next time
    $lastresp=$useable[choice];
    return &get($key,$useable[$choice],response);

}

### Interface

# linebreak(string,maxlength)
# if string is longer than length (default 70) characters
# break it on a word boundary and print it
sub linebreak {
	#print "* linebreak @_\n";
	$maxlength = $_[1] if $_[1];
	$maxlength = 70 unless $_[1];
	if (length $_[0] > $maxlength) {
		@words=split(/\s/,$_[0]);
		while ($words[0]) {
			$line='';
			while (length ($line." $words[0]") < $maxlength
					&& $words[0]) {
				#warn $words[0];
				$line .= shift(@words) . ' ';
			}
			print "$line\n";
		}
	} else {
		print $_[0];
	}
}

# filpr(string)
# print string filtered of HTML tags (or anything that looks like one)
sub filpr {
	#print "* filpr @_\n";
    $_[0] =~ s/<[^<>]*>//g;
    #print("$_[0]");
    &linebreak("$_[0]");
}

22;





