/***************************************************************************
 *  file: act_soc.c , Implementation of commands.          Part of DIKUMUD *
 *  Usage : Social commands.                                               *
 *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
 *                                                                         *
 *  Copyright (C) 1992, 1993 Michael Chastain, Michael Quan, Mitchell Tse  *
 *  Performance optimization and bug fixes by MERC Industries.             *
 *  You can use our stuff in any way you like whatsoever so long as this   *
 *  copyright notice remains intact.  If you like it please drop a line    *
 *  to mec@garnet.berkeley.edu.                                            *
 *                                                                         *
 *  This is free software and you are benefitting.  We hope that you       *
 *  share your changes too.  What goes around, comes around.               *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>

#include "structs.h"
#include "mob.h"
#include "obj.h"
#include "utils.h"
#include "interp.h"
#include "handler.h"
#include "db.h"
#include "spells.h"

/* extern variables */

extern struct room_data *world;
extern struct descriptor_data *descriptor_list;

/* extern functions */

void parse_string(char *input, char *output, struct char_data *ch1,
    struct char_data *ch2, struct char_data *to);
int action(int cmd);
char *fread_action(FILE *fl);

#define MAX_SOCIAL  256

struct social_messg
{
    char *name;
    int hide;
    int min_victim_position; /* Position of victim */

    /* No argument was supplied */
    char *char_no_arg;
    char *others_no_arg;

    /* An argument was there, and a victim was found */
    char *char_found;       /* if NULL, read no further, ignore args */
    char *others_found;
    char *vict_found;

    /* An argument was there, but no victim was found */
    char *not_found;

    /* The victim turned out to be the character */
    char *char_auto;
    char *others_auto;
} soc_mess_list[MAX_SOCIAL];



struct pose_type
{
    int level;          /* minimum level for poser */
    char *poser_msg[4];  /* message to poser        */
    char *room_msg[4];   /* message to room         */
} pose_messages[MAX_MESSAGES];

static int list_top = -1;


char *fread_action(FILE *fl)
{
    char buf[MAX_STRING_LENGTH], *rslt;

    for (;;)
    {
	fgets(buf, MAX_STRING_LENGTH, fl);
	if (feof(fl))
	{
	    log("Fread_action - unexpected EOF.");
	    exit(0);
	}

	if (*buf == '#')
	    return(0);
	{
	    *(buf + strlen(buf) - 1) = '\0';
	    CREATE(rslt, char, strlen(buf) + 1);
	    strcpy(rslt, buf);
	    return(rslt);
	}
    }
}



void boot_social_messages(void)
{
    FILE *fl;
    char tmp[MAX_INPUT_LENGTH];
    int hide, min_pos;

    if (!(fl = fopen(SOCIAL_FILE, "r")))
    {
	perror("boot_social_messages");
	exit(0);
    }

    for (;;)
    {
	fscanf(fl, " %s ", tmp);
	if ( feof(fl) )
	    break;
	fscanf(fl, " %d ", &hide);
	fscanf(fl, " %d \n", &min_pos);

	list_top++;
	if ( list_top >= MAX_SOCIAL )
	{
	    perror( "Too many socials.\n" );
	    exit( 0 );
	}

	/* read the stuff */
	soc_mess_list[list_top].name                = str_dup(tmp);
	soc_mess_list[list_top].hide                = hide;
	soc_mess_list[list_top].min_victim_position = min_pos;
	soc_mess_list[list_top].char_no_arg         = fread_action(fl);
	soc_mess_list[list_top].others_no_arg       = fread_action(fl);
	soc_mess_list[list_top].char_found          = fread_action(fl);

	/* if no char_found, the rest is to be ignored */
	if (!soc_mess_list[list_top].char_found)
	    continue;

	soc_mess_list[list_top].others_found        = fread_action(fl); 
	soc_mess_list[list_top].vict_found          = fread_action(fl);
	soc_mess_list[list_top].not_found           = fread_action(fl);
	soc_mess_list[list_top].char_auto           = fread_action(fl);
	soc_mess_list[list_top].others_auto         = fread_action(fl);
    }
    fclose(fl);
}



bool check_social( struct char_data *ch, char *pcomm, int length, char *arg )
{
    char buf[MAX_INPUT_LENGTH];
    struct social_messg *action;
    struct char_data *vict;
    int cmd;

    for ( cmd = 0; cmd <= list_top; cmd++ )
    {
	if ( memcmp( pcomm, soc_mess_list[cmd].name, length ) == 0 )
	    goto LCmdFound;
    }
    return FALSE;

 LCmdFound:
    if ( !IS_NPC(ch) && IS_SET(ch->specials.act, PLR_NOEMOTE) )
    {
	send_to_char( "You are anti-social!\n\r", ch );
	return TRUE;
    }

    switch( GET_POS(ch) )
    {
    case POSITION_DEAD:
	send_to_char( "Lie still; you are DEAD.\n\r", ch );
	return TRUE;

    case POSITION_INCAP:
    case POSITION_MORTALLYW:
	send_to_char( "You are hurt far too bad for that.\n\r", ch );
	return TRUE;

    case POSITION_STUNNED:
	send_to_char( "You are too stunned to do that.\n\r", ch );
	return TRUE;

    case POSITION_SLEEPING:
	send_to_char( "In your dreams, or what?\n\r", ch );
	return TRUE;
    }

    action = &soc_mess_list[cmd];

    if (action->char_found)
	one_argument(arg, buf);
    else
	*buf = '\0';

    if (!*buf)
    {
	send_to_char(action->char_no_arg, ch);
	send_to_char("\n\r", ch);
	act(action->others_no_arg, action->hide, ch, 0, 0, TO_ROOM);
	return TRUE;
    }

    if (!(vict = get_char_room_vis(ch, buf)))
    {
	send_to_char(action->not_found, ch);
	send_to_char("\n\r", ch);
    }
    else if (vict == ch)
    {
	send_to_char(action->char_auto, ch);
	send_to_char("\n\r", ch);
	act(action->others_auto, action->hide, ch, 0, 0, TO_ROOM);
    }
    else if (GET_POS(vict) < action->min_victim_position)
    {
	act("$N is not in a proper position for that.",
	    FALSE,ch,0,vict,TO_CHAR);
    }
    else
    {
	act(action->char_found, 0, ch, 0, vict, TO_CHAR);
	act(action->others_found, action->hide, ch, 0, vict, TO_NOTVICT);
	act(action->vict_found, action->hide, ch, 0, vict, TO_VICT);
    }

    return TRUE;
}



void do_insult(struct char_data *ch, char *argument, int cmd)
{
    char buf[100];
    char arg[MAX_STRING_LENGTH];
    struct char_data *victim;

    one_argument(argument, arg);

    if(*arg) {
	if(!(victim = get_char_room_vis(ch, arg))) {
	    send_to_char("Can't hear you!\n\r", ch);
	} else {
	    if(victim != ch) { 
		sprintf(buf, "You insult %s.\n\r",GET_NAME(victim) );
		send_to_char(buf,ch);

		switch(number(0,2)) {
		    case 0 : {
			if (GET_SEX(ch) == SEX_MALE) {
			    if (GET_SEX(victim) == SEX_MALE)
				act(
				"$n accuses you of fighting like a woman!",
				    FALSE, ch, 0, victim, TO_VICT);
			else
				act("$n says that women can't fight.",
				  FALSE, ch, 0, victim, TO_VICT);
			} else { /* Ch == Woman */
			    if (GET_SEX(victim) == SEX_MALE)
				act(
			"$n accuses you of having the smallest.... (brain?)",
				FALSE, ch, 0, victim, TO_VICT );
			else
				act(
	    "$n tells you that you'd loose a beauty contest against a troll.",
				FALSE, ch, 0, victim, TO_VICT );
			}
		    } break;
		    case 1 : {
			act("$n calls your mother a bitch!",
			FALSE, ch, 0, victim, TO_VICT );
		    } break;
		    default : {
			act("$n tells you to get lost!",
			FALSE,ch,0,victim,TO_VICT);
		    } break;
		} /* end switch */

		act("$n insults $N.", TRUE, ch, 0, victim, TO_NOTVICT);
	    } else { /* ch == victim */
		send_to_char("You feel insulted.\n\r", ch);
	    }
	}
    } else send_to_char("Sure you don't want to insult everybody?\n\r", ch);
}



void boot_pose_messages(void)
{
  FILE *fl;
  int counter;
  int class;

  if (!(fl = fopen(POSEMESS_FILE, "r")))
  {
    perror("boot_pose_messages");
    exit(0);
  }

  for (counter = 0;;counter++)
  {
    fscanf(fl, " %d ", &pose_messages[counter].level);
    if (pose_messages[counter].level < 0)
      break;
	for (class = 0;class < 4;class++)
	{
	    pose_messages[counter].poser_msg[class] = fread_action(fl);
	    pose_messages[counter].room_msg[class] = fread_action(fl);
	}
    }
  
    fclose(fl);
}


void do_pose(struct char_data *ch, char *argument, int cmd)
{
    int to_pose;
    int counter;

    if ((GET_LEVEL(ch) < pose_messages[0].level) || IS_NPC(ch))
    {
	send_to_char("You can't do that.\n\r", ch);
	return;
    }

    for (counter = 0; (pose_messages[counter].level <= GET_LEVEL(ch)) && 
		     (pose_messages[counter].level >= 0); counter++);
    counter--;
  
    to_pose = number(0, counter);
    
    act(pose_messages[to_pose].poser_msg[GET_CLASS(ch)-1],
	0, ch, 0, 0, TO_CHAR);
    act(pose_messages[to_pose].room_msg[GET_CLASS(ch)-1],
   	 0, ch, 0, 0, TO_ROOM);
}