empiremud/cnf/
empiremud/doc/
empiremud/lib/boards/
empiremud/lib/etc/
empiremud/lib/misc/
empiremud/lib/plralias/F-J/
empiremud/lib/plralias/K-O/
empiremud/lib/plralias/P-T/
empiremud/lib/plralias/U-Z/
empiremud/lib/plrobjs/
empiremud/lib/plrobjs/F-J/
empiremud/lib/plrobjs/K-O/
empiremud/lib/plrobjs/P-T/
empiremud/lib/plrobjs/U-Z/
empiremud/lib/world/
empiremud/lib/world/mob/
empiremud/lib/world/obj/
empiremud/log/
/* ************************************************************************
*   File: act.social.c                                   EmpireMUD AD 1.0 *
*  Usage: Functions to handle socials                                     *
*                                                                         *
*  This file contains TBG code which is used under license from tbgMUD.   *
*  See tbgc.lic in this directory for details.                            *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Code base by Paul Clarke.  EmpireMUD Project, a tbgMUD Production.     *
*  Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"

void perform_action(Creature ch, int act_nr, char *argument);


#define MAX_SOCIALS		350

/*
 * Today I'm rewriting act.social.c using the stock CircleMUD file more as
 * a template than anything.  I like the idea of being able to add socials
 * without having to add to interpreter.c.  It should be as simple as adding
 * lines in a text file.  I don't have a snippet or anything to work with,
 * and despite the fact that I've chickened out every other time I've tried
 * to do this, I'm confident it'll work this time.  -Paul, 1/27/99
 */

/* extern functions */
extern char *fread_action(FILE * fl, int nr);

/* local globals */
static int list_top = -1;

struct social_messg {
	char *name;

	int hide;
	int min_char_position;		/* Position of the character */
	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_SOCIALS];



int find_action(char *name) {
	int i;

	if (list_top < 0)
		return -1;

	for (i = 0; i < list_top; i++)
		if (is_abbrev(name, soc_mess_list[i].name))
			return (i);

	return -1;
	}


int check_social(Creature ch, char *string) {
	char arg1[MAX_STRING_LENGTH];
	int action;
	
	skip_spaces(&string);
	half_chop(string, arg, arg1);
	
	if (!*arg)
		return FALSE;
	
	if ((action = find_action(arg)) < 0)
		return FALSE;

	if (DSC_FLAGGED(ch, DSC_EARTHMELD | DSC_BITUMENOUS_FLESH)) {
		msg_to_char(ch, "You can't do that right now!\r\n");
		return TRUE;
		}
	
	perform_action(ch, action, arg1);
	return TRUE;
	}


void perform_action(Creature ch, int act_nr, char *argument) {
	struct social_messg *action;
	Creature vict;

	action = &soc_mess_list[act_nr];

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

	if (GET_POS(ch) < action->min_char_position) {
		switch (GET_POS(ch)) {
			case POS_DEAD:
				send_to_char("Lie still; you are DEAD!!! :-(\r\n", ch);
				break;
			case POS_INCAP:
			case POS_MORTALLYW:
				send_to_char("You are in a pretty bad shape, unable to do anything!\r\n", ch);
				break;
			case POS_STUNNED:
				send_to_char("All you can do right now is think about the stars!\r\n", ch);
				break;
			case POS_SLEEPING:
				send_to_char("In your dreams, or what?\r\n", ch);
				break;
			case POS_RESTING:
				send_to_char("Nah... You feel too relaxed to do that..\r\n", ch);
				break;
			case POS_SITTING:
				send_to_char("Maybe you should get on your feet first?\r\n", ch);
				break;
			case POS_FIGHTING:
				send_to_char("No way!  You're fighting for your life!\r\n", ch);
				break;
			}
		return;
		}

	if (!*buf) {
		send_to_char(action->char_no_arg, ch);
		send_to_char("\r\n", ch);
		act(action->others_no_arg, action->hide, ch, 0, 0, TO_ROOM);
		return;
		}
	if (!(vict = get_char_room_vis(ch, buf))) {
		send_to_char(action->not_found, ch);
		send_to_char("\r\n", ch);
		}
	else if (vict == ch) {
		send_to_char(action->char_auto, ch);
		send_to_char("\r\n", ch);
		act(action->others_auto, action->hide, ch, 0, 0, TO_ROOM);
		}
	else {
		if (GET_POS(vict) < action->min_victim_position) {
			switch (GET_POS(vict)) {
				case POS_DEAD:
					act("$E's dead and you can't do much with $M.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				case POS_INCAP:
				case POS_MORTALLYW:
					act("$E's in pretty bad shape.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				case POS_STUNNED:
					act("$E's stunned right now.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				case POS_SLEEPING:
					act("$E's too busy sleeping to bother with you.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				case POS_RESTING:
					act("$E's resting right now.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				case POS_SITTING:
					act("$E needs to be standing for that action.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				case POS_FIGHTING:
					act("$E's too busy fighting.", FALSE, ch, 0, vict, TO_CHAR);
					break;
				}
			}
		else {
			act(action->char_found, 0, ch, 0, vict, TO_CHAR | TO_SLEEP);
			act(action->others_found, action->hide, ch, 0, vict, TO_NOTVICT);
			act(action->vict_found, action->hide, ch, 0, vict, TO_VICT);
			}
		}
	}


ACMD(do_insult) {
	Creature victim;

	skip_spaces(&argument);
	one_argument(argument, arg);

	if (*arg) {
		if (!(victim = get_char_room_vis(ch, arg)))
			send_to_char(NOPERSON, ch);
		else {
			if (victim != ch) {
				sprintf(buf, "You insult %s.\r\n", PERS(victim, ch, 0));
				send_to_char(buf, ch);

				switch (number(0, 2)) {
					case 0:
						if (GET_SEX(ch) == SEX_MALE) {
							if (GET_SEX(victim) == SEX_FEMALE)
								act("$n says that women can't fight.", FALSE, ch, 0, victim, TO_VICT);
							else
								act("$n accuses you of fighting like a woman!", FALSE, ch, 0, victim, TO_VICT);
							}
						else {
							if (GET_SEX(victim) != SEX_FEMALE)
								act("$n accuses you of having the smallest... (brain?)", FALSE, ch, 0, victim, TO_VICT);
							else
								act("$n tells you that you'd lose 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;
					}
				act("$n insults $N.", TRUE, ch, 0, victim, TO_NOTVICT);
				}
			else {
				send_to_char("You feel insulted.\r\n", ch);
				}
			}
		}
	else
		send_to_char("I'm sure you don't want to insult *everybody*...\r\n", ch);
	}


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

	fgets(buf, MAX_STRING_LENGTH, fl);
	if (feof(fl)) {
		log("SYSERR: fread_action - unexpected EOF near action #%d", nr+1);
		exit(1);
		}
	if (*buf == '#')
		return (NULL);
	else {
		*(buf + strlen(buf) - 1) = '\0';
		CREATE(rslt, char, strlen(buf) + 1);
		strcpy(rslt, buf);
		return (rslt);
		}
	}


void boot_social_messages(void) {
	FILE *fl;
	int nr, hide, min_vpos, min_cpos, curr_soc = -1;
	char next_soc[100];

	/* open social file */
	if (!(fl = fopen(SOCMESS_FILE, "r"))) {
		sprintf(buf, "SYSERR: Can't open socials file '%s'", SOCMESS_FILE);
		perror(buf);
		exit(1);
		}

	/* now read 'em */
	for (nr = 0; nr < MAX_SOCIALS; nr++) {
		fscanf(fl, " %s ", next_soc);

		if (*next_soc == '*') {
			fscanf(fl, "%s\n", next_soc);
			continue;
			}
		if (*next_soc == '$')
			break;

		if (fscanf(fl, " %d %d %d \n", &hide, &min_cpos, &min_vpos) != 3) {
			log("SYSERR: Format error in social file near social '%s'", next_soc);
			exit(1);
			}
		/* read the stuff */
		curr_soc++;
		soc_mess_list[curr_soc].name = strdup(next_soc);
		soc_mess_list[curr_soc].hide = hide;
		soc_mess_list[curr_soc].min_char_position = min_cpos;
		soc_mess_list[curr_soc].min_victim_position = min_vpos;

		soc_mess_list[curr_soc].char_no_arg = fread_action(fl, nr);
		soc_mess_list[curr_soc].others_no_arg = fread_action(fl, nr);
		soc_mess_list[curr_soc].char_found = fread_action(fl, nr);

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

		soc_mess_list[curr_soc].others_found = fread_action(fl, nr);
		soc_mess_list[curr_soc].vict_found = fread_action(fl, nr);
		soc_mess_list[curr_soc].not_found = fread_action(fl, nr);
		soc_mess_list[curr_soc].char_auto = fread_action(fl, nr);
		soc_mess_list[curr_soc].others_auto = fread_action(fl, nr);
		}

	/* close file & set top */
	fclose(fl);
	list_top = curr_soc;
	}


int social_sort_info[MAX_SOCIALS];

void sort_socials(void) {
	int a, b, tmp;

	/* initialize array */
	for (a = 0; a < list_top; a++)
		social_sort_info[a] = a;

	for (a = 0; a < list_top - 1; a++)
		for (b = a + 1; b < list_top; b++)
			if (strcmp(soc_mess_list[social_sort_info[a]].name, soc_mess_list[social_sort_info[b]].name) > 0) {
				tmp = social_sort_info[a];
				social_sort_info[a] = social_sort_info[b];
				social_sort_info[b] = tmp;
				}
	}


ACMD(do_socials) {
	int sortpos, j = 0;

	/* Ugh, don't forget to sort... */
	sort_socials();

	sprintf(buf, "The following social commands are available:\r\n");

	for (sortpos = 0; sortpos < list_top; sortpos++)
		sprintf(buf+strlen(buf), "%-11.11s%s", soc_mess_list[social_sort_info[sortpos]].name, (!(++j % 7)) ? "\r\n" : "");
	strcat(buf, "\r\n");
	page_string(ch->desc, buf, 1);
	}