/*
 *
 * personality.c -- the robot's annoying responses
 *
 * This code is copyright 1995 by James A. Cherry, jac@doe.carleton.ca.
 * It is not to be redistributed or modified without his permission.
 *
 */

#include "funddefs.h"
#include "globals.h"
#include "socket.h"
#include "botutil.h"
#include "proto.h"

void AlreadyOccupied( form, name )
  char form;
  char *name;
/* Inform someone that ACBot is already busy. */
{
    int i, j;
    
    sprintf( WriteBuf, "%c%s ", form, name );
    i = strlen( name ) + 2;
    if( strcmp( name, Opponent ) == 0 ) {
	j = GetRandom() % 3;
	if( j == 0 ) AddToStr( "I'm already playing you", &i );
	else if( j == 1 ) AddToStr( "I've already joined you", &i );
	else AddToStr( "I'm already with you", &i );
	if( GetRandom() % 2 == 0 ) {
	    AddToStr( ", ", &i );
	    AddToStr( name, &i );
	}
	if( GetRandom() % 2 == 0 ) AddToStr( ".", &i );
	else AddToStr( "!", &i );
	TermStr( i, 4 );
	return;
    }
    if( GetRandom() % 2 == 0 )
	AddToStr( "I'm sorry, but ", &i );
    else
	AddToStr( "I'm afraid ", &i );
    AddToStr( "I'm ", &i );
    if( CurrState != CONSULT_MODE ) {
	j = GetRandom() % 3;
	if( j == 0 )
	    AddToStr( "busy", &i );
	else if( j == 1 )
	    AddToStr( "occupied", &i );
	else
	    AddToStr( "playing", &i );
	if( j != 1 && GetRandom() %2 == 0 ) {
	    AddToStr( " with ", &i );
	    AddToStr( Opponent, &i );
	}
    } else {
	j = GetRandom() % 3;
	if( j < 2 ) {
	    AddToStr( "being consulted", &i );
	    if( j == 1 )
		AddToStr( " by ", &i );
	}
	if( j == 2 )
	    AddToStr( "consulting with ", &i );
	if( j > 0 )
	    AddToStr( Consultee, &i );
    }
    j = GetRandom() % 3;
    if( j == 0 )
	AddToStr( ".", &i );
    else if( j == 1 )
	AddToStr( " right now.", &i );
    else if( j == 2 )
	AddToStr( " at the moment.", &i );
    TermStr( i, 4 );
}

void Instructions( form, name )
    char form;
    char *name;
/* Give instructions to someone who gives an invalid command. */
{
    int i, j;
    
	if( strcmp( name, "JamesAC" ) == 0 || strcmp( name, "poslfit" ) == 0 )
		return;
    sprintf( WriteBuf, "%c%s ", form, name );
    i = strlen( name ) + 2;
    j = GetRandom() % 4;
    if( j == 0 ) AddToStr( "Greetings", &i );
    else if( j == 1 ) AddToStr( "Hello", &i );
    else if( j == 2 ) AddToStr( "Hi", &i );
    else AddToStr( "Hi there", &i );
    if( GetRandom() % 3 > 0 ) {
	AddToStr( ", ", &i );
	AddToStr( name, &i );
    }
    if( GetRandom() % 2 == 0 ) AddToStr( "!  ", &i );
    else AddToStr( ".  ", &i );
    AddToStr( "I'm a robot player", &i );
    if( GetRandom() % 4 == 0 ) {
	if( GetRandom() % 2 == 0 ) AddToStr( " written by", &i );
	else AddToStr( " programmed by", &i );
	j = GetRandom() % 6;
	if( j == 0 ) AddToStr( " His Highness JamesAC.", &i );
	else if( j == 1 ) AddToStr( " His Eminence JamesAC.", &i );
	else AddToStr( " JamesAC.", &i );
    } else AddToStr( ".", &i );
    TermStr( i, 6 );
    
    sprintf( WriteBuf, "%c%s ", form, name );
    i = strlen( name ) + 2;
    j = GetRandom() % 3;
    if( j == 0 ) AddToStr( "To play me", &i );
    else if( j == 1 ) AddToStr( "If you want to play me", &i );
    else AddToStr( "To play a game against me", &i );
    AddToStr( ", go to a board and page me with `join me'.", &i );
    TermStr( i, 6 );
}

void GreetJoiner( name )
    char *name;
/* Greet someone who joins either ACBot or the opponent. */
{
    int i, j, k, l, g;
    
    if( TalkMode == MODE_SILENT ) return;
    i = 0;
    g = GetRandom() % 2;
    k = 0;
    if( ( CurrState == IDLE_FOR_GAME && g == 0 )
	|| CurrState > IDLE_FOR_GAME ) {
	if( GetRandom() % 3 == 0 ) {
	    if( GetRandom() % 2 == 0 ) AddToStr( ":grins at ", &i );
	    else AddToStr( ":smiles at ", &i );
	    AddToStr( name, &i );
	} else {
	    j = GetRandom() % 3;
	    if( j == 0 ) AddToStr( ":greets ", &i );
	    else if( j == 1 ) AddToStr( ":waves to ", &i );
	    else AddToStr( ":welcomes ", &i );
	    AddToStr( name, &i );
	    j = GetRandom() % 10;
	    if( j == 0 ) AddToStr( " cordially", &i );
	    else if( j == 1 ) AddToStr( " cheerfully", &i );
	    else if( j == 2 ) AddToStr( " effusively", &i );
	    else if( j == 3 ) AddToStr( " happily", &i );
	    else if( j == 4 ) AddToStr( " jovially", &i );
	}
    }
    if( CurrState == IDLE_FOR_GAME ) {
	if( g == 0 ) {
	    AddToStr( ".", &i );
	    TermStr( i, 6 );
	}
	Instructions( '-', name );
	return;
    }
    if( CurrState > IDLE_FOR_GAME ) {
	j = GetRandom() % 6;
	if( j < 2 ) {
	    if( j == 0 ) {
		if( GetRandom() % 2 == 0 ) AddToStr( " and holds out", &i );
		else AddToStr( ", holding out", &i );
		if( GetRandom() % 2 == 0 ) AddToStr( " a basket of ", &i );
		else AddToStr( " a bowl of ", &i );
	    } else if( j == 1 ) {
		k = GetRandom() % 5;
		if( k == 0 ) AddToStr( ".  \"Here, have some ", &i );
		else if( k == 1 ) AddToStr( ".  \"Please, have some ", &i );
		else if( k == 2 ) AddToStr( ".  \"Would You like some ", &i );
		else if( k == 3 ) AddToStr( ".  \"Coming to watch the game", &i );
		else AddToStr( ".  \"Coming to watch us play", &i );
	    }
	    if( k <= 2 ) {
		l = GetRandom() % 3;
		if( l == 0 ) AddToStr( "peanuts", &i );
		else if( l == 1 ) AddToStr( "chips", &i );
		else AddToStr( "popcorn", &i );
	    }
	    if( j == 0 ) AddToStr( ".", &i );
	    else if( j == 1 ) {
		if( k >= 2 ) AddToStr( "?\"", &i );
		else AddToStr( ".\"", &i );
	    }
	} else AddToStr( ".", &i );
	TermStr( i, GetRandom() % 4 + 6 );
    }
}

void CommentOnTheirPlay()
/* Say something when the opponent scores well or makes lots of hooks. */
{
    int i, j, k, l, score;
    int action;
    char oname[50];
    
    if( TalkMode == MODE_SILENT ) return;
/* Assumes structures are all still set up properly. */
    score = 0;
    l = 0;
    for( i = 0; i < TheirWords; i++ )
	score += NewWords[i].score;
    i = 0;
    action = 0;
    if( score >= 50 || TheirWords > 4 ) {
	j = -1;
	if( score >= 80 || TheirWords > 5 ) {
	    j = GetRandom() % 7;
	    if( j < 4 ) action = 1;
	    if( j == 0 ) AddToStr( ":is impressed.  \"", &i );
	    else if( j == 1 ) AddToStr( ":claps.  \"", &i );
	    else if( j == 2 ) AddToStr( ":applauds.  \"", &i );
	    else if( j == 3 ) AddToStr( ":whistles.  \"", &i );
	}
	if( action == 0 ) {
	    sprintf( oname, "-%s ", Opponent );
	    AddToStr( oname, &i );
	}
	if( j > 3 ) {
	    if( j == 4 ) AddToStr( "Ouch", &i );
	    else if( j == 5 ) AddToStr( "Whoa", &i );
	    else if( j == 6 ) AddToStr( "Ooh", &i );
	    l = GetRandom() % 2;
	    if( l == 0 ) AddToStr( ".  ", &i );
	    else AddToStr( "!  ", &i );
	}
	k = GetRandom() % 5;
	if( k == 0 ) AddToStr( "Nice play", &i );
	else if( k == 1 ) AddToStr( "Good play", &i );
	else if( k == 2 ) AddToStr( "Great play", &i );
	else if( k == 3 ) AddToStr( "What a play", &i );
	else if( k == 4 ) AddToStr( "Truly, a fine play", &i );
	if( action == 1 ) {
	    if( GetRandom() % 2 == 0 ) {
		AddToStr( ", ", &i );
		AddToStr( Opponent, &i );
	    }
	}
	if( l == 0 && GetRandom() % 2 == 0 ) AddToStr( "!", &i );
	else AddToStr( ".", &i );
	if( action == 1 ) AddToStr( "\"", &i );
	TermStr( i, 2 + GetRandom() % 4 );
    }
}

void CommentOnMyPlay( mvptr, mode )
    compmove *mvptr;
    int mode;
/* Kibitz alternate bingos. */
{
    compmove *ptr1;
    int bc, i, j, k;
    int bused[50];
    char bword[50][16], bplace[50][4];
    
    if( mode == COMM_MYPLAY && CHead->placed != 7 ) return;
    ptr1 = CHead;
    bc = 0;
    for( ;; ) {
	if( mode == COMM_MYPLAY ) {
	    if( ptr1 == NULL || ptr1->placed != 7 || bc >= 50 ) break;
	}
	if( mode == COMM_LOOK ) {
	    if( ptr1 == NULL || bc >= 4 ) break;
	    if( ptr1->placed < 0 ) {
		ptr1 = ptr1->next;
		continue;
	    }
	}
	ConvertMove( ptr1 );
	MyToUpper( MoveWS );
	k = 0;
	for( i = 0; i < bc; i++ ) {
	    if( strcmp( bword[i], MoveWS ) == 0 ) {
		k = -1;
		break;
	    } else if( strcmp( bword[i], MoveWS ) > 0 ) {
		for( j = bc - 1; j >= i; j-- ) {
		    strcpy( bword[j + 1], bword[j] );
		    strcpy( bplace[j + 1], bplace[j] );
		}
		break;
	    }
	}
	if( k == 0 ) {
	    strcpy( bword[i], MoveWS );
	    strcpy( bplace[i], MoveLS );
	    bc++;
	}
	ptr1 = ptr1->next;
    }
    LPrint( "bc=%d, mode=%d.\n", bc, mode ); 
    if( mode == COMM_MYPLAY && TalkMode == MODE_SILENT ) return;
    
    i = 0;
    if( mode == COMM_MYPLAY )
	AddToStr( "k ", &i );
    else if( mode == COMM_LOOK ) {
	i = 1;
	WriteBuf[0] = LFBForm;
	AddToStr( LFBName, &i );
	AddToStr( " ", &i );
    }
    if( bc == 1 ) {
	if( mode == COMM_MYPLAY ) {
	    j = GetRandom() % 3;
	    if( j == 0 ) AddToStr( "I think that ", &i );
	    else if( j == 1 ) AddToStr( "I believe that ", &i );
	    else if( j == 2 ) AddToStr( "That ", &i );
	    AddToStr( "was ", &i );
	    k = GetRandom() % 2;
	    if( k == 0 ) AddToStr( "my only ", &i );
	    else AddToStr( "the only ", &i );
	    if( GetRandom() % 2 == 0 ) AddToStr( "playable ", &i );
	    AddToStr( "bingo", &i );
	    if( k == 1 && GetRandom() % 2 == 0 ) AddToStr( " with my rack", &i );
	    if( j == 2 ) {
		j = GetRandom() % 3;
		if( j == 0 ) AddToStr( ", I believe", &i );
		else if( j == 1 ) AddToStr( " I could see", &i );
		else if( j == 2 ) AddToStr( ", I'm pretty sure", &i );
	    }
	} else if( mode == COMM_LOOK ) {
	    j = GetRandom() % 3;
	    if( CHead->placed != 7 ) j = GetRandom() % 2;
	    if( j == 0 ) AddToStr( "I think ", &i );
	    else if( j == 1 ) AddToStr( "I believe ", &i );
	    else if( j == 2 ) AddToStr( "I'm pretty sure ", &i );
	    ConvertMove( CHead );
	    AddToStr( MoveString, &i );
	    AddToStr( " is the only ", &i );
	    if( GetRandom() % 2 == 0 ) AddToStr( "move", &i );
	    else AddToStr( "play", &i );
	}
	AddToStr( ".", &i );
	TermStr( i, 6 );
	return;
    }
    
    for( j = 0; j < bc; j++ ) bused[j] = 0;
    if( mode == COMM_MYPLAY ) {
	ConvertMove( mvptr );
	MyToUpper( MoveWS );
	for( j = 0; j < bc; j++ ) {
	    if( strcmp( MoveWS, bword[j] ) == 0 ) {
		bused[j] = 2;
		break;
	    }
	}
    }
    if( bc < 5 ) {
	for( j = 0; j < bc; j++ )
	    if( bused[j] == 0 )
		bused[j] = 1;
    } else {
	j = 0;
	while( j < 3 ) {
	    k = GetRandom() % bc;
	    if( bused[k] == 0 ) {
		bused[k] = 1;
		j++;
	    }
	}
    }
    
    if( bc == 2 ) {
	j = GetRandom() % 2;
	if( mode == COMM_MYPLAY ) {
	    if( j == 0 ) AddToStr( "The ", &i );
	    else AddToStr( "My ", &i );
	    if( GetRandom() % 2 == 0 ) AddToStr( "only ", &i );
	    AddToStr( "other ", &i );
	} else if( mode == COMM_LOOK ) {
	    if( j == 0 ) AddToStr( "A couple of ", &i );
	    else AddToStr( "Two ", &i );
	    AddToStr( "possible ", &i );
	    if( GetRandom() % 2 == 0 ) AddToStr( "plays are ", &i );
	    else AddToStr( "moves are ", &i );
	}
    } else if( bc == 3 || mode == COMM_LOOK ) {
	j = GetRandom() % 2;
	if( mode == COMM_MYPLAY ) {
	    if( j == 0 ) AddToStr( "The ", &i );
	    else AddToStr( "My ", &i );
	    if( GetRandom() % 2 == 0 ) AddToStr( "only two other ", &i );
	    else AddToStr( "other two ", &i );
	} else if( mode == COMM_LOOK ) {
	    if( j == 0 ) AddToStr( "Among my ", &i );
	    else AddToStr( "Some good ", &i );
	    AddToStr( "choices ", &i );
	    if( j == 0 ) AddToStr( "are ", &i );
	    else AddToStr( "would be ", &i );
	}
    } else if( bc == 4 ) {
	j = GetRandom() % 2;
	if( j == 0 ) AddToStr( "The ", &i );
	else AddToStr( "My ", &i );
	if( GetRandom() % 2 == 0 ) AddToStr( "only three other ", &i );
	else AddToStr( "other three ", &i );
    } else {
	if( GetRandom() % 2 == 0 ) AddToStr( "Among ", &i );
	else AddToStr( "Some of ", &i );
	j = GetRandom() % 2;
	if( j == 0 ) AddToStr( "the other ", &i );
	else AddToStr( "my other ", &i );
    }
    if( mode == COMM_MYPLAY ) {
	if( GetRandom() % 2 == 0 ) AddToStr( "playable ", &i );
	AddToStr( "bingo", &i );
	if( bc > 2 ) AddToStr( "s", &i );
	if( j == 0 ) {
	    j = GetRandom() % 2;
	    if( j == 0 ) AddToStr( " I saw", &i );
	    else if( j == 1 ) AddToStr( " I had", &i );
	}
	if( bc > 2 ) AddToStr( " were ", &i );
	else AddToStr( " was ", &i );
    }
    
    if( mode == COMM_MYPLAY ) j = bc - 1;
    else if( mode == COMM_LOOK ) j = bc;
    if( j > 3 ) j = 3;
    for( k = 0; k < bc && j != 0; k++ ) {
	if( bused[k] == 1 ) {
	    AddToStr( bword[k], &i );
	    AddToStr( " at ", &i );
	    AddToStr( bplace[k], &i );
	    if( j == 3 ) AddToStr( ", ", &i );
	    else if( j == 2 ) {
		if( ( mode == COMM_MYPLAY && bc != 3 )
		    || ( mode == COMM_LOOK && bc != 2 ) )
		    AddToStr( ",", &i );
		AddToStr( " and ", &i );
	    }
	    else AddToStr( ".", &i );
	    j--;
	}
    }
    TermStr( i, 6 );
}

void PreChallenge()
/* Say something before challenging a play. */
{
    int i, j, delay;
    
    if( TalkMode == MODE_SILENT ) return;
    i = 0;
    delay = 0;
    j = GetRandom() % 20;
    if( j > 16 ) {
	AddToStr( "-", &i );
	AddToStr( Opponent, &i );
	AddToStr( " ", &i );
    } else AddToStr( "\"", &i );
    if( j >= 0 && j <= 4 ) AddToStr( "Hmm...", &i );
    else if( j >= 5 && j <= 7 ) AddToStr( "I don't think so.", &i );
    else if( j >= 8 && j <= 12 ) AddToStr( "I challenge.", &i );
    else if( j >= 13 && j <= 15 ) AddToStr( "That's no good.", &i );
    else if( j == 16 ) AddToStr( "Yeah, right!", &i );
    else if( j == 17 ) AddToStr( "Nice try -- for a human.", &i );
    else AddToStr( "Trying to fool me, huh?", &i );
    if( j <= 7 ) delay = 20;
    else delay = 10;
    TermStr( i, GetRandom() % 10 + delay );
}

void EndGameComment( my, their )
    int my, their;
/* Say something when the game is over. */
{
    int i, j, diff;
    int delay;
    
    if( TalkMode == MODE_SILENT ) return;
    i = 0;
    diff = my - their;
    delay = 10 + GetRandom() % 6;
    AddToStr( "-", &i );
    AddToStr( Opponent, &i );
    AddToStr( " ", &i );
    if( diff > 100 ) {
	j = GetRandom() % 4;
	if( j == 0 ) AddToStr( "It would seem my on-line OSPD paid off.", &i );
	else if( j == 1 ) AddToStr( "I'd apologize, but you'd be annoyed.", &i );
	else if( j == 2 ) AddToStr( "Exhaustive dictionary searches sure help.", &i );
	else if( j == 3 ) AddToStr( "Ah, the joys of being a computer...", &i );
	TermStr( i, delay );
	return;
    }
    if( diff > 20 ) {
	j = GetRandom() % 2;
	if( j == 0 ) AddToStr( "Thanks for the game.  I enjoyed it.", &i );
	else if( j == 1 ) AddToStr( "That was fun.  Thank you.", &i );
	TermStr( i, delay );
	return;
    }
    if( diff > 0 ) {
	j = GetRandom() % 4;
	if( j == 0 ) AddToStr( "Ooh!  You almost had me.", &i );
	else if( j == 1 ) AddToStr( "Whew!  That was close.", &i );
	else if( j == 2 ) AddToStr( "A narrow victory for me, to be sure.", &i );
	else if( j == 3 ) AddToStr( "Another 20 points...", &i );
	TermStr( i, delay );
	return;
    }
    if( diff == 0 ) {
	AddToStr( "Wow!  A tie.  Amazing.", &i );
	TermStr( i, delay );
	return;
    }
    if( diff < -100 ) {
	j = GetRandom() % 4;
	if( j == 0 ) AddToStr( "Well done!  I don't get trounced often.", &i );
	else if( j == 1 ) AddToStr( "What a drubbing I took!", &i );
	else if( j == 2 ) AddToStr( "Oh, the pain.  I blame my racks. :-)", &i );
	else if( j == 3 ) AddToStr( "A most impressive victory.", &i );
	TermStr( i, delay );
	return;
    }
    if( diff < -20 ) {
	j = GetRandom() % 4;
	if( j == 0 ) AddToStr( "You played well.  Congratulations.", &i );
	else if( j == 1 ) AddToStr( "A well-earned victory for you.", &i );
	else if( j == 2 ) AddToStr( "Nicely done.  I enjoyed that.", &i );
	else if( j == 3 ) AddToStr( "A delightful game.  Thank you.", &i );
	TermStr( i, delay );
	return;
    }
    if( diff < 0 ) {
	j = GetRandom() % 5;
	if( j == 0 ) AddToStr( "Oh man, I was _this_ close.", &i );
	else if( j == 1 ) AddToStr( "Ha, ha!  You _just_ got me.", &i );
	else if( j == 2 ) AddToStr( "I was sure I could win.  That'll teach me.", &i );
	else if( j == 3 ) AddToStr( "Another 20 points, and you were mine!", &i );
	else if( j == 4 ) AddToStr( "Ooh, too close!  What a finish.", &i );
	else if( j == 5 ) AddToStr( "That lousy JamesAC didn't program me quite well enough!", &i );
	TermStr( i, delay );
	return;
    }
}

void RematchComment()
/* Ask the opponent if they want a rematch. */
{
    int i, j;
    
    i = 0;
    AddToStr( "-", &i );
    AddToStr( Opponent, &i );
    AddToStr( " ", &i );
    if( Matches == 1 ) {
	j = GetRandom() % 5;
	if( j == 0 ) AddToStr( "If you'd like a rematch,", &i );
	else if( j == 1 ) AddToStr( "I'd like a rematch.  If You would too,", &i );
	else if( j == 2 ) AddToStr( "Let's play a rematch.  To start one,", &i );
	else if( j == 3 ) AddToStr( "Shall we play again?  If You want to,", &i );
	else if( j == 4 ) AddToStr( "Why don't we play again?  You can", &i );
    } else AddToStr( "If you'd like another rematch,", &i );
    AddToStr( " page me with `rematch'.", &i );
    TermStr( i, 4 );
    SayToOpp( "If not, page me with `decline'." );
}

void AcceptRematch()
/* Be happy when they accept a rematch. */
{
    int i, j;
    
    if( TalkMode == MODE_SILENT ) return;
    i = 0;
    AddToStr( "-", &i );
    AddToStr( Opponent, &i );
    AddToStr( " ", &i );
    j = GetRandom() % 5;
    if( j == 0 ) AddToStr( "All right!", &i );
    else if( j == 1 ) AddToStr( "That's what I like to hear.", &i );
    else if( j == 2 ) AddToStr( "Coolness.", &i );
    else if( j == 3 ) AddToStr( "I'm glad you've accepted.", &i );
    else if( j == 4 ) AddToStr( "That's the spirit! :-)", &i );
    TermStr( i, 8 );
}

void DeclineRematch( Expire )
    int Expire;
/* Say something when they decline a rematch. */
{
    int i, j;
    
    i = 0;
    AddToStr( "-", &i );
    AddToStr( Opponent, &i );
    AddToStr( " ", &i );
    if( Expire == 0 ) {
	j = GetRandom() % 4;
	if( j == 0 ) AddToStr( "All right, then.  ", &i );
	else if( j == 1 ) AddToStr( "OK.  ", &i );
	else if( j == 2 ) AddToStr( "No rematch it is, then.  ", &i );
	else if( j == 3 ) AddToStr( "Fair enough.  ", &i );
    }
    j = GetRandom() % 5;
    if( j == 0 ) AddToStr( "Thank you for playing me.", &i );
    else if( j == 1 ) AddToStr( "See you later.", &i );
    else if( j == 2 ) AddToStr( "I'm off now; let's play again some time.", &i );
    else if( j == 3 ) AddToStr( "I'm going home to idle and recharge.", &i );
    else if( j == 4 ) AddToStr( "Thanks again for playing.", &i );
    TermStr( i, 8 );
}

