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: specials.c                                     EmpireMUD AD 1.0 *
*  Usage: houses special procedures and their protocols                   *
*                                                                         *
*  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 "db.h"
#include "comm.h"
#include "handler.h"
#include "interpreter.h"
#include "skills.h"
#include "empire.h"
#include "vnums.h"


/* ** Introduction ****************************************************** *

    This file is used for handling functions for special procedures, and
 the procedures themselves for mobs and objects.  While they resemble
 those standard to CircleMUD, they are not the same.  I have written them
 in a way which I feel is more economical for EmpireMUD because it is
 designed to have a much greater number of creatures and objects.

 * ********************************************************************** */


/* ** Definitions ******************************************************* */

#define MOB_SPECIAL		Creature mob = (Creature) me
#define OBJ_SPECIAL		Object obj = (Object) me


/* ** Prototypes ******************************************************** */

SPECIAL(spec_bee_hive);

LOOK_SPECIAL(lspec_bee_hive);
LOOK_SPECIAL(lspec_ship_window);
LOOK_SPECIAL(lspec_bad_mirror);
LOOK_SPECIAL(lspec_mirror);


/* ** Tables ************************************************************ */

struct special_procedure_table obj_spec[] = {
	{  0,	"none",			NULL,				NULL	},
	{  1,	"bee hive",		spec_bee_hive,		lspec_bee_hive	},
	{  2,	"ship window",	NULL,				lspec_ship_window	},
	{  3,	"bad mirror",	NULL,				lspec_bad_mirror	},
	{  4,	"mirror",		NULL,				lspec_mirror	},

	/* this entry must be last */
	{ -1,	"none",			NULL,				NULL		}
	};


struct special_procedure_table mob_spec[] = {
	{  0,	"none",			NULL,				NULL		},

	/* this entry must be last */
	{ -1,	"none",			NULL,				NULL		}
	};


/* ** Handlers ********************************************************** */

/* updates object spec proc: called from point_update */
void update_object_special(Object obj) {
	if (GET_OBJ_RNUM(obj) != NOTHING && obj_index[GET_OBJ_RNUM(obj)].spec_proc)
		(obj_index[GET_OBJ_RNUM(obj)].spec_proc) (obj);
	}


/* updates mobile spec proc: called from point_update */
void update_mobile_special(Creature mob) {
	if (GET_MOB_RNUM(mob) != NOTHING && obj_index[GET_MOB_RNUM(mob)].spec_proc)
		(mob_index[GET_MOB_RNUM(mob)].spec_proc) (mob);
	}


/* functions for accessing the tables */
int find_obj_special_by_number(int number) {
	int i;

	for (i = 0; obj_spec[i].number != -1; i++)
		if (obj_spec[i].number == number)
			return i;

	return -1;
	}

int find_mob_special_by_number(int number) {
	int i;

	for (i = 0; mob_spec[i].number != -1; i++)
		if (mob_spec[i].number == number)
			return i;

	return -1;
	}

int find_obj_spec_by_function(SPECIAL(*func)) {
	int i;

	for (i = 0; obj_spec[i].number != -1; i++)
		if (obj_spec[i].spec_proc == func)
			return i;

	return -1;
	}

int find_obj_look_spec_by_function(LOOK_SPECIAL(*func)) {
	int i;

	for (i = 0; obj_spec[i].number != -1; i++)
		if (obj_spec[i].look_spec == func)
			return i;

	return -1;
	}

int find_mob_spec_by_function(SPECIAL(*func)) {
	int i;

	for (i = 0; mob_spec[i].number != -1; i++)
		if (mob_spec[i].spec_proc == func)
			return i;

	return -1;
	}

int find_mob_look_spec_by_function(LOOK_SPECIAL(*func)) {
	int i;

	for (i = 0; mob_spec[i].number != -1; i++)
		if (mob_spec[i].look_spec == func)
			return i;

	return -1;
	}


/* ** Object Procedures ************************************************ */
SPECIAL(spec_bee_hive) {
	OBJ_SPECIAL;

	/*
	 * This spec controls the flow of a bee hive object, which is used
	 * to grow wax and honey.  To be as realistic as possible, it will
	 * keep track of its population and other factors, and use seasons
	 * so that the bees will die if you steal all their honey.
	 */

	#define Population		GET_OBJ_VAL(obj, 0)
	#define Honey			GET_OBJ_VAL(obj, 1)
	#define Wax				GET_OBJ_VAL(obj, 2)

	/* only work if in a room */
	if (obj->in_room == NOWHERE)
		return;

	if (number(0, 23))
		return;

	switch (get_season()) {
		case SEASON_WINTER:
			if (Population > Honey)
				Population -= 5;

			Honey -= Population / 25;
			break;

		case SEASON_SPRING:
			Population += 2;

			Honey -= Population / 25;
			break;

		case SEASON_SUMMER:
			Population += 5;

			Honey += Population / 25;
			Wax += Population / 25;
			break;

		case SEASON_AUTUMN:
			Honey += Population / 5;
			Wax += Population / 5;
			break;
		}

	/* idiot checks */
	Population = MAX(0, MIN(Population, 200));
	Honey = MAX(0, MIN(Honey, 1000));
	Wax = MAX(0, MIN(Wax, 1000));
	}


LOOK_SPECIAL(lspec_bee_hive) {
	OBJ_SPECIAL;

	/*
	 * This spec displays the status of a beehive.
	 */

	#define Population		GET_OBJ_VAL(obj, 0)
	#define Honey			GET_OBJ_VAL(obj, 1)
	#define Wax				GET_OBJ_VAL(obj, 2)

	switch (Population / 40) {
		case 0:
			sprintf(buf, "The hive seems strangely vacant.");
			break;
		case 1:
			sprintf(buf, "A few bees swarm around the hive.");
			break;
		case 2:
			sprintf(buf, "Bees swarm around the hive.");
			break;
		case 3:
			sprintf(buf, "The hive is swarming with bees.");
			break;
		case 4:
			sprintf(buf, "Bees swarm all over this hive!");
			break;
		case 5:
			sprintf(buf, "As you approach the hive, you find yourself overwhelmed with bees!");
			break;
		}

	msg_to_char(ch, "%s  You find it to be %d%% full of honey and %d%% full of wax.\r\n", buf, (int) (Honey * 100 / 1000), (int) (Wax * 100 / 1000));

	return TRUE;
	}


LOOK_SPECIAL(lspec_ship_window) {
	OBJ_SPECIAL;

	/*
	 * This spec shows what's outside of a ship to a person on deck when
	 * he looks at the window.
	 */

	Object ship;

	if (!(ship = world[HOME_ROOM(obj->in_room)].boat))
		msg_to_char(ch, "Unable to find ship associated with this window!\r\n");
	else
		look_at_room_by_rnum(ch, ship->in_room);

	return TRUE;
	}


LOOK_SPECIAL(lspec_bad_mirror) {
	OBJ_SPECIAL;

	/*
	 * This spec is for tarnished, low-quality mirrors.
	 */

	act("$p is too tarnished to see a good reflection.", FALSE, ch, obj, 0, TO_CHAR);
	return TRUE;
	}


LOOK_SPECIAL(lspec_mirror) {
	OBJ_SPECIAL;

	/*
	 * This spec is used to look at your own description, and to see Lasombra.
	 */

	void look_at_char(Creature i, Creature ch, bool eq, bool self);
	Creature i;

	/* Clan weakness: Lasombra */
	if (GET_CLAN(ch) == CLAN_LASOMBRA)
		msg_to_char(ch, "You have no reflection!\r\n");
	else {
		act("You at your reflection in $p.", FALSE, ch, obj, 0, TO_CHAR);
		look_at_char(ch, ch, FALSE, TRUE);
		}

	/* Clan weakness: Lasombra */
	for (i = world[ch->in_room].people; i; i = i->next_in_room)
		if (GET_CLAN(i) == CLAN_LASOMBRA && ch != i && CAN_SEE(ch, i) && ww_dice(GET_PERCEPTION(ch) + GET_ALERTNESS(ch), GET_WITS(i) + GET_STEALTH(i) - SENSES_BONUS(ch)) > 0)
			act("Looking over your shoulder, you notice that $N has no reflection!", TRUE, ch, 0, i, TO_CHAR);

	/* Oops */
	act("$n looks into $p.", TRUE, ch, obj, 0, TO_ROOM);
	return TRUE;
	}


/* ** Mobile Procedures ************************************************ */