[comp.sources.games.bugs] Unofficial mdg changes, 1 of 3

michael@stb.info.com (Michael Gersten) (04/06/91)

cat > Changes <<  SHAR_EOF_Fixes
Magic armor cannot give you an extra point of damage
Magic armor goes to 0 strength when it wears off (instead of
	staying stuck to whatever value you had it last at)
Monster speed can be slowed down without affecting other game timers
Extra lines of messages
Monsters may be generated when you move into areas
Monsters do not destroy items just by walking on them
	(theif still destroys by touching)
Item given is proportional to strength of creature killed (like gold)
Anyone can get CP's, but you still have to be godlike to use them
SHAR_EOF_Fixes
cat > setup.h <<  SHAR_EOF_setup.h
/*
	MDG Multiuser Dungeon Game -- setup include file
	
	MDG is Copyright 1990 John C. Gonnerman
	This file is subject to the general MDG 
	copyright statement (see enclosed file, Copyright).

	SCCSID @(#) setup.h (1.6) created 1/12/91
*/


#define DATE_OFFSET	(20L * 365L * 24L * 3600L)

#define NUM_MSG		6

#define NICEVAL		0

#define CHECKP_LEVEL	3000
#define MAX_MARMOR	6

#define MAX_RANGED	9
#define R_SPEED		2

/* minimum to be considered "functional" */

#define MIN_HPS		10

#define MAX_HPS		60
#define MAX_MPS		25

#define HP_CUTOFF	56
#define MP_CUTOFF	23

#define DANGER_CUT	10

#define CRYSTAL_ODDS	4

#define HEAL_DIV	15
#define CHARGE_INC	1

#define TICKSPERPACE	1	/* Was: 8. Max msg of 11, 1/4 would be 3 */

#define P_ATTACKS	1
#define M_ATTACKS	1

#define TIME_TO_HEAL	15

#define RESURRECTION	2   /* Monsters are put in empty sectors when entered */
#define MAX_MONSTERS	6

#define MON_TIME	3	/* number of seconds per monster cycle time */
#define MINUTE		60

/* Note: There are MINUTE ticks per minute, and GAMEDAY minutes per
game day. Minutes 0-G_MORNING are morning. Think of 0 as 6 am. */
/* At this scale, a count of 3 is one hour. 18 is 6 hours. This gives
a 20 hour day (short nights). */

#define GAMEDAY		60
#define G_MORNING	18	/* 6 am - noon */
#define G_AFTERNOON	36	/* noon - 6 pm */
#define G_EVENING	54	/* Was: 43 (2:20), now 6 pm */

/* Keep MONSTER > MAP */
/* Monster decay when sector ignored (not yet implemented) */
#define DECAY_MONSTER	(3 * 24 * 60)	
/* something on ground decays */
#define DECAY_MAP	(2 * 24 * 60)
/* something on a person decays */
#define DECAY_PLAYER	(9 * 24 * 60)
/* Something in the trading post */
#define DECAY_TRADER	(4 * 24 * 60)
/* Hidden objects, whether on person or not */
#define DECAY_OBSCURE	(5 * 24 * 60)
/* Crystals evaporate after 5 minutes. Pick them up quickly */
#define DECAY_CRYSTAL	(5)

#define TELE_TRYS	3

#define KNIGHT_DUR	150

#define USER_DUR	30

#define DETECT_DUR	20
#define DETECT_L2	40	/* See hidden objects */
#define DETECT_L3	55	/* See teleport gates */

#define MAPROWS		13
#define MAPCOLS		38

#define TRUE	1
#define FALSE	0

#define MAYADD		/* add new monsters when you move */
/* #define ONLYADDEMPTY	/* movement adds only if no monsters currently */

#define ALWAYSCP	/* Are CP's always displayed, or only when >0? */

/*#define	MONSTER_PUNT	/* Do monsters destroy what they walk over? */
/* end of file */
SHAR_EOF_setup.h
cat > msghandler.c <<  SHAR_EOF_msghandler.c
/*
	MDG Multiuser Dungeon Game -- msghandler.c message code
	
	MDG is Copyright 1990 John C. Gonnerman
	This program is subject to the general MDG 
	copyright statement (see enclosed file, Copyright).

	Unfortunately, most of the daemon is in this file
	somewhere...
*/

static char *sccsvers = "@(#) msghandler.c\t(1.7)\tcreated 1/7/91";

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>

#include "setup.h"
#include "struct.h"

extern char *progname;

extern int errno;
extern char *sys_errlist[];

extern struct map_seg *mseg;
extern struct player_seg *pseg;

extern int dqid, map_size, player_size;

extern struct monster_tbl *m_table;
extern int n_monster;

extern struct note_tbl *note_table;
extern int n_notes;

int save_count = 0;
int minutes = 0;


msg_handler(mbuf)
struct dmessage mbuf;
{
	int indx, symbol, act_val;
	static int ticker = 0;

	if(mbuf.cmd == '@') /* stop daemon */
		shutdown();
	
	if(mbuf.cmd == '$') { /* checkpoint game */
		savegame();
		save_count = 0;
		return;
	}

	if(mbuf.cmd == '{') { /* tell all */
		dmsg_all(mbuf.text);
		return;
	}

	if(mbuf.playernum == -1) { /* "heartbeat" */
		move_monsters();  /* Q: Should we do this if nothing */
		heal_players();	  /* has happened at all? (no other input) */
		update_timer();
		move_ranged();
		notify_all();
		minute_clock();
		savemap();
		return;
	}

	switch(mbuf.cmd) {
	case 'J' : /* Join game */
		if(find_player(mbuf.playernum) != -1)
			break;
		if((indx = getfree()) == -1)
			break;
		loadplayer(indx, mbuf.playernum);
		break;

	case 'Q' : /* Quit game */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		saveplayer(indx);
		savegame();
		save_count = 0;
		break;

	case 'A' : /* Abort game */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		abortplayer(indx);
		savegame();
		save_count = 0;
		break;

	case 'e' : /* enter */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		enter_cmd(indx);
		break;
		
	case 's' : /* speak */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		speak(indx, mbuf.text);
		break;
		
	case 'S' : /* sell */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;

		if(delete_item(indx, mbuf.arg) == -1)
			break;

		deselect(indx, mbuf.arg);

		pseg->itm[mbuf.arg].loc.sector = LOC_TRADER;
		pseg->item_sem++;

		pseg->p[indx].gold += pseg->itm[mbuf.arg].value;
		pseg->player_sem++;

		tell_player(indx);

		break;

	case 'B' : /* buy */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;

		if(item_cnt(indx) >= PMAX_ITEMS) {
			dmsg_add(indx, "You are overloaded.");
			break;
		}

		act_val = pseg->itm[mbuf.arg].value * 3 / 2;

		if(act_val > pseg->p[indx].gold) {
			dmsg_add(indx, "You can't afford it!");
			break;
		}

		insert_item(indx, mbuf.arg);

		pseg->p[indx].gold -= act_val;
		pseg->player_sem++;

		pseg->itm[mbuf.arg].decay_cnt = 0;
		pseg->itm[mbuf.arg].loc.sector = LOC_PLAYER;
		pseg->itm[mbuf.arg].loc.x = pseg->p[indx].playernum;
		pseg->itm[mbuf.arg].symbol = pseg->itm[mbuf.arg].type;
		pseg->itm[mbuf.arg].loc.y = ITEM_NEW;

		pseg->item_sem++;

		tell_player(indx);

		break;

	case 'L' : /* leave */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		if(pseg->p[indx].loc.sector != LOC_TRADER)
			break;

		if(place(indx, pseg->p[indx].loc.x) == -1) {
			saveplayer(indx);
			pseg->p[indx].loc.sector = LOC_HOME;
			pseg->player_sem++;
		}

		move_sym(&(pseg->p[indx].loc), 1 + indx);

		pseg->in_trader = -1;
		tell_player(indx);
		break;

	case 'p' : /* partner */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		if(mbuf.subcmd < 0 || mbuf.subcmd >= MAX_PLAYERS)
			break;
		pseg->p[indx].partners[mbuf.subcmd] =
			(pseg->p[indx].partners[mbuf.subcmd] ? 0 : 1);
		break;
		
	case 't' : /* take */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		take_item(indx);
		break;

	case 'm' : /* move */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		symbol = pseg->p[indx].invis ? indx + 11 : indx + 1;
		move_cmd(&(pseg->p[indx].loc), mbuf.subcmd, symbol, indx);
		break;

	case 'D' : /* drop cash */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		drop_cash(indx, mbuf.subcmd, mbuf.arg);
		break;

	case 'd' : /* drop item */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		drop_cmd(indx, mbuf.subcmd, mbuf.arg);
		break;

	case 'u' : /* use item */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		use_cmd(indx, &mbuf);
		break;

	case 'v' : /* verbose */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		if(pseg->p[indx].brief) {
			pseg->p[indx].brief = 0;
			dmsg_add(indx, "Verbose ON");
		} else {
			pseg->p[indx].brief = 1;
			dmsg_add(indx, "Verbose OFF");
		}
		break;

	case 'w' : /* write */
		write_cmd(mbuf.arg, mbuf.text);
		break;

	case 'c' : /* cast spell */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		cast_spell(indx, &mbuf);
		break;

	case 'g' : /* god power */
		if((indx = find_player(mbuf.playernum)) == -1)
			break;
		if(pseg->p[indx].max_hp < HP_CUTOFF
		|| pseg->p[indx].max_mp < MP_CUTOFF) 
		{
			dmsg_add(indx, "You are not a demigod");
			break;
		}
		god_power(indx, &mbuf);
		break;

	default:
		break;
	}

	if(++ticker == TICKSPERPACE) {
		pace_monsters();
		ticker = 0;
	}

	pace_ranged();
}


notify_all()
{
	int i;

	mseg->map_sem++;
	pseg->player_sem++;
	pseg->item_sem++;

	for(i = 0; i < MAX_PLAYERS; i++)
		if(pseg->p[i].playernum >= 0)
			tell_player(i);
}


enter_cmd(indx)
int indx;
{
	struct location *l;
	int symbol;

	l = &(pseg->p[indx].loc);

	symbol = pseg->p[indx].invis ? indx + 11 : indx + 1;

	if(pseg->p[indx].loc.under == '<')  /* down */
		move_cmd(l, L_DOWN, symbol, indx);
	else if(pseg->p[indx].loc.under == '>')  /* up */
		move_cmd(l, L_UP, symbol, indx);
}


int player_online(p_num)
int p_num;
{
	int i;

	for(i = 0; i < MAX_PLAYERS; i++)
		if(pseg->p[i].playernum == p_num)
			return 1;

	return 0;
}


minute_clock()
{
	if(minutes++ < MINUTE)
		return;

	minutes = 0;

	if(++(mseg->dayclock) > GAMEDAY)
		mseg->dayclock = 0;

	switch(mseg->dayclock) {
	case 0 :
		dmsg_all("It's morning.");
		break;
	case G_MORNING :
		dmsg_all("It's noon.");
		break;
	case G_AFTERNOON :
		dmsg_all("It's evening.");
		break;
	case G_EVENING :
		dmsg_all("It's night.");
		break;
	}

	decay_items();
	decay_monsters();
}

decay_monsters()
{
	int i;
	for (i=0; i< n_monster; i++)
		if(m_table[i].decay_cnt++ > DECAY_MONSTER)
			clearm(i, FALSE);	/* no treasure */
}

decay_items()
{
	int i, sector, x;

	for(i = pseg->item_count - 1; i >= 0; i--) {
		sector = pseg->itm[i].loc.sector;
		x = pseg->itm[i].loc.x;

		if(sector > 0 
		|| (sector == LOC_PLAYER && !player_online(x))
		|| (sector == LOC_TRADER)
		|| (sector == LOC_NONESUCH))
			pseg->itm[i].decay_cnt++;
		else
			pseg->itm[i].decay_cnt = 0;

		if(pseg->itm[i].type == NOTE)
			pseg->itm[i].decay_cnt = 0;

/* Original order: Crystal, hidden, player, map, trader */
/*		     5 min,   7,      9      2     4    */
/* Modified: Something on a player will not go away unless
the player times out. Hidden items on the map will take the hidden
time, not the map time. Trader decay ignores hidden or not hidden */

		if(pseg->itm[i].type == CRYSTAL
		&& pseg->itm[i].decay_cnt > DECAY_CRYSTAL)
			recycle(i);
		else if(sector == LOC_PLAYER 
		&& pseg->itm[i].decay_cnt > DECAY_PLAYER)
			recycle(i);
		else if(sector == LOC_TRADER 
		&& pseg->itm[i].decay_cnt > DECAY_TRADER
		&& pseg->in_trader < 0)
			recycle(i); 
		else if(pseg->itm[i].symbol == HIDDEN
		&& pseg->itm[i].decay_cnt > DECAY_OBSCURE)
			recycle(i);
		else if(sector > 0 
		&& pseg->itm[i].decay_cnt > DECAY_MAP)
			recycle(i);
	}
}


freshen_item(indx)
int indx;
{
	pseg->itm[indx].decay_cnt = 0;
}


recycle(indx)
int indx;
{
	int sector, x, y;

	if(!top_item(indx)) {
		pseg->itm[indx].decay_cnt /= 2;
		return;	
	}

	sector = pseg->itm[indx].loc.sector;
	x = pseg->itm[indx].loc.x;
	y = pseg->itm[indx].loc.y;
 
	if(sector >= 0) {
		mseg->m[sector].map[y][x] = pseg->itm[indx].loc.under;
		mseg->map_sem++;
		notify(sector);
	}

	pseg->itm[indx].loc.sector = LOC_NONESUCH;
	pseg->itm[indx].decay_cnt = 0;

	pseg->item_sem++;
}


update_timer()
{
	int indx;

	if(++save_count > CHECKP_LEVEL) {
		savegame();
		save_count = 0;
	}
	
	for(indx = 0; indx < MAX_PLAYERS; indx++) {

		if(pseg->p[indx].blocked > 0)
			pseg->p[indx].blocked--;

		if(pseg->p[indx].user_spell > 0)
			pseg->p[indx].user_spell--;

		if(pseg->p[indx].ma_count > 0)
			if (--pseg->p[indx].ma_count <= 0)
				pseg->p[indx].m_armor = 0;

		if(pseg->p[indx].knight > 0)
			pseg->p[indx].knight--;

		if(pseg->p[indx].invis > 0) {
			pseg->p[indx].invis--;

			if(pseg->p[indx].invis == 0)
				visible(indx);
		}

		if(pseg->p[indx].detect > 0)
			pseg->p[indx].detect--;

		if(pseg->p[indx].light > 0) {
			pseg->p[indx].light--;

			if(pseg->p[indx].playernum >= 0
			&& pseg->p[indx].light == 10)
				dmsg_add(indx, "it's getting dark...");
		}
		pseg->p[indx].attacks = P_ATTACKS;
	}
}


write_cmd(i_indx, text)
int i_indx;
char *text;
{
	int n_indx;

	if((n_indx = pseg->itm[i_indx].effect) < 0 || n_indx >= n_notes)
		return;

	strncpy(note_table[n_indx].text, text, 34);
	note_table[n_indx].text[34] = '\0';
}


use_cmd(p_indx, mptr)
int p_indx;
struct dmessage *mptr;
{
	int playernum, item_indx, dir;

	playernum = mptr->playernum;
	item_indx = mptr->subcmd;

	if(item_indx < 0
	|| item_indx >= pseg->item_count)
		return;

	if(pseg->itm[item_indx].loc.sector != LOC_PLAYER 
	|| pseg->itm[item_indx].loc.x != playernum)
		return;

	switch(pseg->itm[item_indx].type) {
	case WEAPON :
		pseg->weapon[p_indx] = item_indx;
		pseg->item_sem++;
		tell_player(p_indx);
		break;

	case SHIELD :
		pseg->shield[p_indx] = item_indx;
		pseg->item_sem++;
		pseg->player_sem++;
		tell_player(p_indx);
		break;

	case ARMOR :
		pseg->armor[p_indx] = item_indx;
		pseg->item_sem++;
		pseg->player_sem++;
		tell_player(p_indx);
		break;

	case SCROLL :
	case POTION :
	case OBJECT :
	case MISSILE :
	case NOTE :
		activate_item(p_indx, mptr);
		break;
	}
}


tell_player(p_indx)
int p_indx;
{
	struct sembuf ops[1];

	ops[0].sem_num = p_indx;
	ops[0].sem_op = 1;
	ops[0].sem_flg = 0;

	semop(pseg->sid, ops, 1);
}

notify(sector)
int sector;
{
	int i;

	for(i = 0; i < MAX_PLAYERS; i++) 
		if(pseg->p[i].loc.sector == sector) 
			tell_player(i);
}


drop_cash(p_indx, dir, amount)
int p_indx, dir, amount;
{
	int i;

	if(amount < 1 || amount > pseg->p[p_indx].gold)
		return;

	for(i = 0; i < pseg->item_count; i++) {
		if(pseg->itm[i].loc.sector == LOC_NONESUCH
		&& pseg->itm[i].type == CASH) {
			pseg->itm[i].value = amount;
			pseg->itm[i].decay_cnt = 0;
			pseg->itm[i].symbol = pseg->itm[i].type;

			if(pseg->p[p_indx].gold_hidden) {
				pseg->p[p_indx].gold_hidden = 0;
				pseg->itm[i].symbol = HIDDEN;
			}

			if(drop_it(p_indx, dir, i) != -1)
				pseg->p[p_indx].gold -= amount;

			pseg->player_sem++;
			tell_player(p_indx);
			return;
		}
	}

	dmsg_add(p_indx, "No treasure slots free...");
}


drop_cmd(p_indx, dir, indx)
int p_indx, dir, indx;
{
	pseg->itm[indx].decay_cnt = 0;

	if(drop_it(p_indx, dir, indx) != -1) {
		delete_item(p_indx, indx);
		deselect(p_indx, indx);
	}
}


int drop_it(p_indx, dir, indx)
int p_indx, dir, indx;
{
	int dest_x, dest_y, dest_a;

	dest_a = pseg->p[p_indx].loc.sector;
	dest_x = pseg->p[p_indx].loc.x;
	dest_y = pseg->p[p_indx].loc.y;

	switch(dir) {
	case L_NORTH :
		dest_y--;
		if(dest_y < 0) {
			dest_y = MAPROWS - 1;
			dest_a = mseg->m[dest_a].links[L_NORTH];
		}
		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_SOUTH :
		dest_y++;
		if(dest_y >= MAPROWS) {
			dest_y = 0;
			dest_a = mseg->m[dest_a].links[L_SOUTH];
		}
		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_EAST :
		dest_x++;
		if(dest_x >= MAPCOLS) {
			dest_x = 0;
			dest_a = mseg->m[dest_a].links[L_EAST];
		}
		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_WEST :
		dest_x--;
		if(dest_x < 0) {
			dest_x = MAPCOLS - 1;
			dest_a = mseg->m[dest_a].links[L_WEST];
		}
		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_NEAST :
		dest_x++;
		dest_y--;

		if(dest_y < 0 && dest_x >= MAPCOLS)
			return -1;

		if(dest_x >= MAPCOLS) {
			dest_x = 0;
			dest_a = mseg->m[dest_a].links[L_EAST];
		}

		if(dest_y < 0) {
			dest_y = MAPROWS - 1;
			dest_a = mseg->m[dest_a].links[L_NORTH];
		}

		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_SEAST :
		dest_x++;
		dest_y++;

		if(dest_y >= MAPROWS && dest_x >= MAPCOLS)
			return -1;

		if(dest_x >= MAPCOLS) {
			dest_x = 0;
			dest_a = mseg->m[dest_a].links[L_EAST];
		}

		if(dest_y >= MAPROWS) {
			dest_y = 0;
			dest_a = mseg->m[dest_a].links[L_SOUTH];
		}

		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_NWEST :
		dest_x--;
		dest_y--;

		if(dest_y < 0 && dest_x < 0)
			return -1;

		if(dest_x < 0) {
			dest_x = MAPCOLS - 1;
			dest_a = mseg->m[dest_a].links[L_WEST];
		}

		if(dest_y < 0) {
			dest_y = MAPROWS - 1;
			dest_a = mseg->m[dest_a].links[L_NORTH];
		}

		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;

	case L_SWEST :
		dest_x--;
		dest_y++;

		if(dest_y >= MAPROWS && dest_x < 0)
			return -1;

		if(dest_x < 0) {
			dest_x = MAPCOLS - 1;
			dest_a = mseg->m[dest_a].links[L_WEST];
		}

		if(dest_y > MAPROWS) {
			dest_y = 0;
			dest_a = mseg->m[dest_a].links[L_SOUTH];
		}

		if(dest_a < 0)
			return -1;

		if(is_clear(mseg->m[dest_a].map[dest_y][dest_x]) 
		|| is_item(mseg->m[dest_a].map[dest_y][dest_x]))
			return put_item(indx, dest_a, dest_x, dest_y);

		return -1;
		break;
	}
}


int is_app_clear(ch)
char ch;
{
	if(is_clear(ch) || is_item(ch))
		return 1;

	switch(ch) {
	case '~' :
	case '%' :
		return 1;
	default :
		return 0;
	}
}


int is_clear(ch)
char ch;
{
	switch(ch) {

	/* gates */
	case '=' :
	case '{' :
	case '}' :
	case ':' :
	case ';' :

	case ' ' :
	case '`' :
	case '.' :
	case ',' :
	case '+' :
	case '^' :
	case '0' :
	case '1' :
	case '2' :
	case '3' :
	case '4' :
	case '5' :
	case '6' :
	case '7' :
	case '8' :
	case '9' :
		return 1;
	default :
		return 0;
	}
}


int put_item(indx, dest_a, dest_x, dest_y)
int indx, dest_a, dest_x, dest_y;
{
	int i, over_indx, code;
	static int depth = 0;

	if(indx < 0
	|| indx >= pseg->item_count)
		return -1;

	if(dest_a < 0)
		return -1;

	if(is_clear(mseg->m[dest_a].map[dest_y][dest_x])) {
		if(isdrop(mseg->m[dest_a].map[dest_y][dest_x])
		&& depth < 10) {
			depth++;
			code = put_item(indx, mseg->m[dest_a].links[L_DOWN],
				dest_x, dest_y);
			depth--;
			return code;
		} else {
			/* simple case. */
			pseg->itm[indx].loc.under = 
				mseg->m[dest_a].map[dest_y][dest_x];
			mseg->m[dest_a].map[dest_y][dest_x] = 
				pseg->itm[indx].symbol;
		}
	} else {
		/* find the item that will be over this one. */
		over_indx = -1;

		for(i = pseg->item_count - 1; i > indx; i--) {
			if(pseg->itm[i].loc.sector == dest_a
			&& pseg->itm[i].loc.x == dest_x
			&& pseg->itm[i].loc.y == dest_y)
				over_indx = i;
		}
			
		if(over_indx == -1) {
			/* new item is on top. */
			pseg->itm[indx].loc.under = 
				mseg->m[dest_a].map[dest_y][dest_x];
			mseg->m[dest_a].map[dest_y][dest_x] = 
				pseg->itm[indx].symbol;
		} else {
			/* new item is under over_indx */
			pseg->itm[indx].loc.under = 
				pseg->itm[over_indx].loc.under;
			pseg->itm[over_indx].loc.under = 
				pseg->itm[indx].symbol;
		}
	}

	pseg->itm[indx].loc.sector = dest_a;
	pseg->itm[indx].loc.x = dest_x;
	pseg->itm[indx].loc.y = dest_y;

	mseg->map_sem++;
	pseg->item_sem++;

	notify(dest_a);

	return 0;
}


move_cmd(locptr, dir, symbol, p_indx)
struct location *locptr;
int dir;
char symbol;
int p_indx;
{
	struct location loc;
	int sector;
	char buf[35];

	if((sector = locptr->sector) < 0)
		return;

	mseg->m[sector].map[locptr->y][locptr->x] = locptr->under;

	loc.x = locptr->x;
	loc.y = locptr->y;
	loc.sector = locptr->sector;

	if(get_dest(&loc, dir) != -1)
		move_subcmd(locptr, loc.sector, loc.x, loc.y, p_indx);

	if(pseg->p[p_indx].brief == 0)
		if(locptr->under == '>' || locptr->under == '<') {
			sprintf(buf, "stairs going %s", 
				(locptr->under == '<' ? "down" : "up" ));
			dmsg_add(p_indx, buf);
		}

	move_sym(locptr, symbol);
}


int get_dest(lptr, dir)
struct location *lptr;
int dir;
{
	switch(dir) {
	case L_UP :
		lptr->sector = mseg->m[lptr->sector].links[L_UP];
		return 0;

	case L_DOWN :
		lptr->sector = mseg->m[lptr->sector].links[L_DOWN];
		return 0;

	case L_NORTH :
		lptr->y--;

		if(lptr->y < 0) {
			lptr->y = MAPROWS - 1;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_NORTH];
		}
		return 0;

	case L_SOUTH :
		lptr->y++;

		if(lptr->y >= MAPROWS) {
			lptr->y = 0;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_SOUTH];
		}
		return 0;

	case L_EAST :
		lptr->x++;

		if(lptr->x >= MAPCOLS) {
			lptr->x = 0;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_EAST];
		}
		return 0;

	case L_WEST :
		lptr->x--;

		if(lptr->x < 0) {
			lptr->x = MAPCOLS - 1;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_WEST];
		}
		return 0;

	case L_NEAST :
		lptr->x++;
		lptr->y--;

		if(lptr->y < 0 && lptr->x >= MAPCOLS)
			return -1;

		if(lptr->y < 0) {
			lptr->y = MAPROWS - 1;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_NORTH];
		}

		if(lptr->x >= MAPCOLS) {
			lptr->x = 0;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_EAST];
		}
		return 0;

	case L_NWEST :
		lptr->x--;
		lptr->y--;

		if(lptr->y < 0 && lptr->x < 0)
			return -1;

		if(lptr->y < 0) {
			lptr->y = MAPROWS - 1;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_NORTH];
		}

		if(lptr->x < 0) {
			lptr->x = MAPCOLS - 1;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_WEST];
		}
		return 0;

	case L_SEAST :
		lptr->x++;
		lptr->y++;

		if(lptr->y >= MAPROWS && lptr->x >= MAPCOLS)
			return -1;

		if(lptr->y >= MAPROWS) {
			lptr->y = 0;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_SOUTH];
		}

		if(lptr->x >= MAPCOLS) {
			lptr->x = 0;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_EAST];
		}
		return 0;

	case L_SWEST :
		lptr->x--;
		lptr->y++;

		if(lptr->y >= MAPROWS && lptr->x < 0)
			return -1;

		if(lptr->y >= MAPROWS) {
			lptr->y = 0;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_SOUTH];
		}

		if(lptr->x < 0) {
			lptr->x = MAPCOLS - 1;
			lptr->sector = 
				mseg->m[lptr->sector].links[L_WEST];
		}
		return 0;
	}

	return -1;
}


/* If sector changes, consider adding a new monster */

move_subcmd(locptr, dest_a, dest_x, dest_y, p_indx)
struct location *locptr;
int dest_a, dest_x, dest_y, p_indx;
{
	int rc, newsector, oldsector;

	/* move_to does not always move a player to the sector */
	/* stored in dest_a due to pits, etc. */

	oldsector = pseg->p[p_indx].loc.sector;

	rc = move_to(locptr, dest_a, dest_x, dest_y, p_indx);

	newsector = pseg->p[p_indx].loc.sector;

	if (newsector != oldsector
	   && newsector > 0)
		mayAddNewMonster (newsector);

	if(rc == 0 
	&& newsector >= 0
	&& oldsector != newsector
	&& mseg->m[newsector].light < 0) {
		pseg->p[p_indx].light -= rnd(500);
		if(pseg->p[p_indx].light < 0)
			pseg->p[p_indx].light = 0;
		dmsg_add(p_indx, "Your light dims...");
	}

	if(p_indx >= 0 && (is_critter(rc) || is_player(rc)))
		attack(p_indx, dest_a, dest_x, dest_y);

	if(oldsector != newsector)
		notify(oldsector);
}

mayAddNewMonster(newsector)
{
#ifdef MAYADD
	if (rnd(4) == 1
#ifdef ONLYADDEMPTY
	&& count_monsters(newsector) == 0
#endif ONLYADDEMPTY
	&& num_player_here(newsector) == 1  /* just the one that moved in */
	)
		addMonster(newsector);
#endif MAYADD
}

move_sym(locptr, symbol)
struct location *locptr;
char symbol;
{
	if(locptr->sector >= 0) {
		mseg->m[locptr->sector].map[locptr->y][locptr->x] = symbol;
		mseg->map_sem++;
		notify(locptr->sector);
	}
}


int move_to(locptr, dest_a, dest_x, dest_y, p_indx)
struct location *locptr;
int dest_a, dest_x, dest_y, p_indx;
{
	char at_loc;
	int prev_s, temp_a, code, gatenum;
	static int depth = 0;

	if(dest_a == LOC_HOME && p_indx >= 0) {
		mseg->map_sem++;
		pseg->p[p_indx].home = locptr->sector;
		locptr->x = locptr->sector;
		locptr->sector = dest_a;
		tell_player(p_indx);
		return 0;
	}

	if(dest_a == LOC_TRADER && p_indx >= 0) {
		if(pseg->in_trader >= 0) {
			dmsg_add(p_indx, "Trader is busy.");
			return -1;
		}
		pseg->in_trader = p_indx;
		mseg->map_sem++;
		tell_player(p_indx);
		locptr->x = locptr->sector;
		locptr->sector = dest_a;
		return 0;
	}

	if(dest_a < 0)
		return -1;

	at_loc = mseg->m[dest_a].map[dest_y][dest_x];

	switch(at_loc) {
	case '^' : /* air */
	case '0' : /* pit */

		if(p_indx < 0 && at_loc == '^') 
			return '^';

		if(p_indx >= 0
		&& (temp_a = mseg->m[dest_a].links[L_DOWN]) >= 0
		&& is_app_clear(mseg->m[temp_a].map[dest_y][dest_x])) {
			dmsg_add(p_indx, "You fell!");
			pgetzapped(p_indx, rnd(10));
			if(locptr->sector == LOC_NONESUCH)
				break;
			if(isdrop(mseg->m[temp_a].map[dest_y][dest_x])
			&& depth < 10) {
				depth++;
				code = move_to(locptr, temp_a, 
					dest_x, dest_y, p_indx);
				depth--;
				return code;
			}
			locptr->sector = mseg->m[dest_a].links[L_DOWN];
		} else 
			locptr->sector = dest_a;

		locptr->x = dest_x;
		locptr->y = dest_y;
		locptr->under = mseg->m[locptr->sector].map[dest_y][dest_x];
		mseg->map_sem++;
		return 0;

	case '=' : /* gateway 1 */
	case '{' : /* gateway 2 */
	case '}' : /* gateway 3 */
	case ':' : /* gateway 4 */
	case ';' : /* gateway 5 */
	case '-' : /* gateway 6 */
	case '|' : /* gateway 7 */

/* TARGET: If you teleport, the code currently does not change your X
and Y co-ordinate. This results in some strange things on the default
map. Should we go to a "random" legal location in the sector? Only if
the default location is non-passable (like air)? Other? */

		prev_s = locptr->sector;
		locptr->sector = dest_a;

		if(p_indx >= 0) {
			gatenum = gate_id(at_loc);

			temp_a = mseg->m[dest_a].links[L_GATE+gatenum];

			if(temp_a == LOC_HOME) {
				locptr->x = prev_s;
				locptr->sector = temp_a;
				mseg->map_sem++;
				return 0;
			} else if(temp_a >= 0) {
				at_loc = mseg->m[temp_a].map[dest_y][dest_x];
				if(is_clear(at_loc)) {
					pseg->p[p_indx].prev_sect = prev_s;
					locptr->sector = temp_a;
				} else if(is_critter(at_loc))
					knockoffm(temp_a, dest_x, dest_y);
			} 
		}

		locptr->x = dest_x;
		locptr->y = dest_y;
		locptr->under = 
			mseg->m[locptr->sector].map[dest_y][dest_x];
		mseg->map_sem++;
		return 0;

	case '1' : /* 1-9 are traps */
	case '2' :
	case '3' :
	case '4' :
	case '5' :
	case '6' :
	case '7' :
	case '8' :
	case '9' :
		if(p_indx >= 0) {
			do_trap(p_indx, at_loc);
			if(locptr->sector == LOC_NONESUCH)
				break;
		}
		locptr->sector = dest_a;
		locptr->x = dest_x;
		locptr->y = dest_y;
		locptr->under = at_loc;
		mseg->map_sem++;
		return 0;

	case '.' :
		if(p_indx < 0)
			return (int)at_loc;
		/* fall through here. */
	case ' ' :
	case ',' :
	case '`' : /* shallow water */
	case '+' : /* secret door */
	case '<' : /* down */
	case '>' : /* up */
	case POTION :
	case SCROLL :
	case ARMOR :
	case SHIELD :
	case WEAPON :
	case MISSILE :
	case OBJECT :
	case CASH :
	case CRYSTAL :
	case NOTE :
	case HIDDEN :
		if(p_indx < 0 && is_item(at_loc))
			punt_item(dest_a, dest_x, dest_y);

		locptr->sector = dest_a;
		locptr->x = dest_x;
		locptr->y = dest_y;
		locptr->under = mseg->m[dest_a].map[dest_y][dest_x];
		mseg->map_sem++;
		return 0;

	case '%' :
	case '~' :
	      	if(locptr->under == at_loc)
			return (int)at_loc;
		else {
			locptr->sector = dest_a;
			locptr->x = dest_x;
			locptr->y = dest_y;
			locptr->under = at_loc;
			mseg->map_sem++;
			return 0;
		}

	default :
		return (int)at_loc;
	}

}


knockoffm(dest_a, dest_x, dest_y)
int dest_a, dest_x, dest_y;
{
	int i;

	for(i = 0; i < n_monster; i++)
		if(m_table[i].loc.sector == dest_a 
		&& m_table[i].loc.x == dest_x 
		&& m_table[i].loc.y == dest_y) {
			clearm(i, 0);
			m_table[i].loc.sector = LOC_NONESUCH;
			return;
		}
}


int is_player(val)
int val;
{
	return (val >= 1 && val <= 19);
}


int is_critter(val)
int val;
{
	return (val == '&') 
		|| (val >= 'a' && val <= 'z') 
		||  (val >= 'A' && val <= 'Z');
}


int is_item(val)
int val;
{
	switch(val) {
	case POTION :
	case SCROLL :
	case ARMOR :
	case SHIELD :
	case WEAPON :
	case MISSILE :
	case OBJECT :
	case CASH :
	case CRYSTAL :
	case NOTE :
	case HIDDEN :
		return 1;
	default :
		return 0;
	}
}


int top_item(indx)
int indx;
{
	int i;

	for(i = pseg->item_count - 1; i > indx; i--)
		if(pseg->itm[i].loc.sector == pseg->itm[indx].loc.sector
		&& pseg->itm[i].loc.x == pseg->itm[indx].loc.x
		&& pseg->itm[i].loc.y == pseg->itm[indx].loc.y)
			return 0;

	return 1;
}


take_item(indx)
int indx;
{
	int i;

	if(indx < 0 
	|| pseg->p[indx].playernum < 0)
		return;

	for(i = pseg->item_count - 1; i >= 0; i--)
		if(pseg->itm[i].loc.sector == pseg->p[indx].loc.sector
		&& pseg->itm[i].loc.x == pseg->p[indx].loc.x
		&& pseg->itm[i].loc.y == pseg->p[indx].loc.y) {

			if(pseg->itm[i].type == CASH) {
				pseg->p[indx].gold += 
					pseg->itm[i].value;
				pseg->itm[i].loc.sector = LOC_NONESUCH;
				pseg->itm[i].symbol = pseg->itm[i].type;
				pseg->player_sem++;
			} else if(pseg->itm[i].type == CRYSTAL) {
			/* We prefer that anyone can pick up crystals 
				if(pseg->p[indx].max_hp >= HP_CUTOFF
				&& pseg->p[indx].max_mp >= MP_CUTOFF) */
					pseg->p[indx].createpts +=
						pseg->itm[i].effect;
				pseg->itm[i].loc.sector = LOC_NONESUCH;
				pseg->itm[i].symbol = pseg->itm[i].type;
				pseg->player_sem++;
			} else {
				if(insert_item(indx, i) == -1)
					return;

				pseg->item_sem++;

				pseg->itm[i].decay_cnt = 0;
				pseg->itm[i].loc.sector = LOC_PLAYER;
				pseg->itm[i].loc.x = 
					pseg->p[indx].playernum;
				pseg->itm[i].symbol = pseg->itm[i].type;
				pseg->itm[i].loc.y = ITEM_NEW;
			}

			pseg->p[indx].loc.under = pseg->itm[i].loc.under;

			tell_player(indx);

			return;
		}

	/* if we got here, it is an item but we can't find it! */
	/* so, clear the space. */

	if(is_item(pseg->p[indx].loc.under))
		pseg->p[indx].loc.under = ' ';
	dmsg_add(indx, "Error-- item lost");
}


/* This is the routine that kills items that monsters walk on. */
/* TARGET : Make monsters pick things up for later dropping */

punt_item(sector, x, y)
int sector, x, y;
{
#ifdef MONSTER_PUNT
	int i;
	char buf[50];

	for(i = pseg->item_count - 1; i >= 0; i--)
		if(pseg->itm[i].loc.sector == sector
		&& pseg->itm[i].loc.x == x
		&& pseg->itm[i].loc.y == y) {

			pseg->itm[i].loc.sector = LOC_NONESUCH;
			pseg->itm[i].symbol = pseg->itm[i].type;

			mseg->m[sector].map[y][x] = pseg->itm[i].loc.under;
			mseg->map_sem++;

			notify(sector);

			return;
		}
#endif
}


int item_cnt(p_indx)
int p_indx;
{
	int i, cnt;

	cnt = 0;

	for(i = 0; i < pseg->item_count; i++) {
		if(pseg->itm[i].loc.sector == LOC_PLAYER
		&& pseg->itm[i].loc.x == pseg->p[p_indx].playernum)
			cnt++;
	}

	return cnt;
}


int insert_item(p_indx, i_indx)
int p_indx, i_indx;
{
	int i;

	for(i = 0; i < PMAX_ITEMS; i++)
		if(pseg->p[p_indx].items[i] == -1) {
			pseg->p[p_indx].items[i] = i_indx;
			return i;
		}

	return -1;
}


deselect(p_indx, i_indx)
int p_indx, i_indx;
{
	if(pseg->armor[p_indx] == i_indx)
		pseg->armor[p_indx] = -1;

	if(pseg->shield[p_indx] == i_indx)
		pseg->shield[p_indx] = -1;

	if(pseg->weapon[p_indx] == i_indx)
		pseg->weapon[p_indx] = -1;
}


int delete_item(p_indx, i_indx)
int p_indx, i_indx;
{
	int i;

	for(i = 0; i < PMAX_ITEMS; i++)
		if(pseg->p[p_indx].items[i] == i_indx) {
			pseg->p[p_indx].items[i] = -1;
			return i;
		}

	return -1;
}


int gate_id(ch)
int ch;
{
	switch(ch) {
	case '=' : /* gateway 1 */
		return 0;
	case '{' : /* gateway 2 */
		return 1;
	case '}' : /* gateway 3 */
		return 2;
	case ':' : /* gateway 4 */
		return 3;
	case ';' : /* gateway 5 */
		return 4;
	case '-' : /* gateway 6 */
		return 5;
	case '|' : /* gateway 7 */
		return 6;
	default :
		return 0;
	}
}


int isdrop(ch)
int ch;
{
	switch(ch) {
	case '^' :
	case '0' :
		return 1;
	}

	return 0;
}


/* end of file. */
SHAR_EOF_msghandler.c
cat > show.c <<  SHAR_EOF_show.c
/*
	MDG Multiuser Dungeon Game -- show.c display procedures
	
	MDG is Copyright 1990 John C. Gonnerman
	This program is subject to the general MDG 
	copyright statement (see enclosed file, Copyright).
*/


static char *sccsvers = "@(#) show.c\t\t(1.4)\tcreated 1/2/91";

#include <curses.h>
#include <ctype.h>

#include "setup.h"
#include "struct.h"
#include "show.h"

extern struct player_seg *pseg;
extern struct map_seg *mseg;
extern struct game_msg *gseg;

extern int playernum, player_indx;

char *homestr   = ". HOME HOME HOME HOME HOME HOME HOME .";
char *traderstr = ". TRADER TRADER TRADER TRADER TRADER .";


show_gmsg()
{
	move(PARK_Y, PARK_X + 2);
	clrtoeol();
	move(PARK_Y, PARK_X + 2);
	addstr(gseg->buf);
	park_csr();
}


show_dark()
{
	int row;

	for(row = 0; row <= MAPROWS + 2; row++) {
		move(row, 1);
		addstr("                                         ");
	}

	move(6, 1);
	addstr("            << It's DARK! >>             ");
}


show_trader()
{
	short i;
	int t_item_indx;

	move(0, 1);
	addstr(" -------------------------------------- ");

	for(i = 1; i <= 10; i++) {
		move(i, 1);
		addstr("|                                      |");
	}

	move(11, 1);
	addstr(" -------------------------------------- ");

	move(12, 1);
	addstr("Trader's Store -- Options:              ");

	move(13, 1);
	addstr("b)uy item   v)alue of item  s)ell item  ");

	move(14, 1);
	addstr("n)ext page  p)revious page  l)eave      ");

	move(15, 1);
	addstr("                                        ");

	for(i = 0; i < 10; i++) 
		if((t_item_indx = trader_item(i)) >= 0) {
			move(i + 1, 3);
			printw("%d - %-20.20s  $%d", i, 
				pseg->itm[t_item_indx].name,
				pseg->itm[t_item_indx].value * 3 / 2);
		}
}


show_map()
{
	int x, y, sector, o_sector;
	char buf[35];
	void game_over();

	if((sector = pseg->p[player_indx].loc.sector) == LOC_NONESUCH
	|| sector == LOC_HOME) {
		game_over();
		return;
	}

	if(sector == LOC_TRADER)
		return;

	if(!is_light(sector)) {
		show_dark();
		return;
	}

	move(0, 1);   addch(' ');
	move(14, 1);  addch(' ');
	move(0, 40);  addch(' ');
	move(14, 40); addch(' ');

	for(x = 0; x < MAPCOLS; x++) {
		o_sector = mseg->m[sector].links[L_NORTH];

		switch(o_sector) {
		case LOC_HOME :
			move(0, x + 2);
			addch((int)homestr[x]);
			break;
		case LOC_PLAYER :
		case LOC_NONESUCH :
			move(0, x + 2);
			mapcode((int)mseg->m[sector].border_ch, sector);
			break;
		case LOC_TRADER :
			move(0, x + 2);
			addch((int)traderstr[x]);
			break;
		default :
			move(0, x + 2);
			mapcode((int)mseg->m[o_sector].map[MAPROWS - 1][x],
				o_sector);
			break;
		}
	}

	for(y = 0; y < MAPROWS; y++) {
		o_sector = mseg->m[sector].links[L_WEST];

		switch(o_sector) {
		case LOC_HOME :
			move(y + 1, 1);
			addch((int)homestr[y]);
			break;
		case LOC_PLAYER :
		case LOC_NONESUCH :
			move(y + 1, 1);
			mapcode((int)mseg->m[sector].border_ch, sector);
			break;
		case LOC_TRADER :
			move(y + 1, 1);
			addch((int)traderstr[y]);
			break;
		default :
			move(y + 1, 1);
			mapcode((int)mseg->m[o_sector].map[y][MAPCOLS - 1],
				o_sector);
			break;
		}

		for(x = 0; x < MAPCOLS; x++) {
			move(y + 1, x + 2);
			mapcode((int)mseg->m[sector].map[y][x],
				sector);
		}

		o_sector = mseg->m[sector].links[L_EAST];

		switch(o_sector) {
		case LOC_HOME :
			move(y + 1, MAPCOLS + 2);
			addch((int)homestr[y]);
			break;
		case LOC_PLAYER :
		case LOC_NONESUCH :
			move(y + 1, MAPCOLS + 2);
			mapcode((int)mseg->m[sector].border_ch, sector);
			break;
		case LOC_TRADER :
			move(y + 1, MAPCOLS + 2);
			addch((int)traderstr[y]);
			break;
		default :
			move(y + 1, MAPCOLS + 2);
			mapcode((int)mseg->m[o_sector].map[y][0],
				o_sector);
			break;
		}
	}

	for(x = 0; x < MAPCOLS; x++) {
		o_sector = mseg->m[sector].links[L_SOUTH];

		switch(o_sector) {
		case LOC_HOME :
			move(MAPROWS + 1, x + 2);
			addch((int)homestr[x]);
			break;
		case LOC_PLAYER :
		case LOC_NONESUCH :
			move(MAPROWS + 1, x + 2);
			mapcode((int)mseg->m[sector].border_ch, sector);
			break;
		case LOC_TRADER :
			move(MAPROWS + 1, x + 2);
			addch((int)traderstr[x]);
			break;
		default :
			move(MAPROWS + 1, x + 2);
			mapcode((int)mseg->m[o_sector].map[0][x],
				o_sector);
			break;
		}
	}

	move(MAPROWS + 2, 1);
	/* clrtoeol();   only clear 40 characters */
	addstr ("                                      ");
	/*       1234567 10 234567 20 234567 30 234567 40 */
	move(MAPROWS + 2, 1);
	printw("%s L%d", mseg->m[sector].title, mseg->m[sector].level);

	park_csr();
}


int is_light(sector)
int sector;
{
	int i;

	if(sector == 0)
		return 1;

	if(mseg->m[sector].light == 2)
		return 1;

	if(mseg->m[sector].light == 1 && timeofday())
		return 1;

	for(i = 0; i < MAX_PLAYERS; i++)
		if(pseg->p[i].playernum >= 0
		&& pseg->p[i].loc.sector == sector
		&& pseg->p[i].light > 0)
			return 1;

	return 0;
}


mapcode(ch, sector)
int ch, sector;
{
	if(sector < 0) {
		addch((int)'#');
	} else if(!is_light(sector)
	&& pseg->p[player_indx].light < 1) {
		/* it's dark */
		addch((int)'#');
	} else if(pseg->p[player_indx].detect)
		switch(ch) {
		case '^' : /* pit */
		case '0' : /* 0-9 are traps */
		case '1' :
		case '2' :
		case '3' :
		case '4' :
		case '5' :
		case '6' :
		case '7' :
		case '8' :
		case '9' :
			addch((int)'^');
			break;
		case '+' :
		case '`' :
			addch((int)' ');
			break;
		case '=' :
		case '{' :
		case '}' :
		case ':' :
		case ';' :
			if(pseg->p[player_indx].detect >= DETECT_L3)
				addch((int)'=');
			else
				addch((int)' ');
			break;
		case '-' :
			if(pseg->p[player_indx].detect >= DETECT_L3)
				addch((int)'=');
			else
				addch((int)'~');
			break;
		case '|' :
			if(pseg->p[player_indx].detect >= DETECT_L3)
				addch((int)'=');
			else
				addch((int)':');
			break;
		case '@' :
			addch((int)'#');
			break;
		case 20 :
			addch((int)'+');
			break;
		case 21 :
			addch((int)'*');
			break;
		case HIDDEN :
			if(pseg->p[player_indx].detect >= DETECT_L2)
				addch((int)OBJECT);
			else
				addch((int)' ');
			break;
		default :
			if(ch >= 11 && ch <= 19)
				addch(ch - 10 + '0');
			else if(ch >= 1 && ch <= 9)
				addch(ch + '0');
			else
				addch(ch);
			break;
		}
	else
		switch(ch) {
		case '.' : /* monster limit */
		case '0' : /* 0-9 are traps */
		case '1' :
		case '2' :
		case '3' :
		case '4' : /* pit */
		case '@' :
		case '=' :
		case '{' :
		case '}' :
		case ':' :
		case ';' :
		case '&' :
		case HIDDEN :
			addch((int)' ');
			break;
		case '^' : /* air */
		case ',' : /* false air */
		case '|' : /* flying gate */
			addch((int)':');
			break;
		case '5' :
		case '6' :
			addch((int)'%');
			break;
		case '7' :
		case '8' :
		case '+' :
			addch((int)'#');
			break;
		case 20 :
			addch((int)'+');
			break;
		case 21 :
			addch((int)'*');
			break;
		case '9' : /* acid trap */
		case '`' : /* shallow water */
		case '-' : /* watergate :-) */
			addch((int)'~');
			break;
		default :
			if(ch >= 11 && ch <= 19) {
				if(ch - 11 == player_indx)
					addch(ch - 10 + '0');
				else
					addch(' ');
			} else if(ch >= 1 && ch <= 9)
				addch(ch + '0');
			else
				addch(ch);
			break;
		}
}


show_player()
{
	int indx, i, temp, sector;
	char buf[35];

	for(indx = 0; indx < MAX_PLAYERS; indx++) {
		move(PSTART + (indx / 3), 14 * (indx % 3) + 1);
		show_a_player(indx);
	}

	temp = pseg->p[player_indx].dmsg_loc;

	for (i=0; i<NUM_MSG; i++)
	{
		move(10+i, 44);
		printw("%c%s", (temp == i ? '>' : ' '), 
			pseg->p[player_indx].dmsg[i]);
		clrtoeol();
	}

	move(0+10+NUM_MSG, 44);
	sprintf(buf, "HP: %hd (%hd)    ",
		pseg->p[player_indx].max_hp,
		pseg->p[player_indx].hitpoints);
	addstr(buf);

	move(0+10+NUM_MSG, 62);
	temp = pseg->armor[player_indx] != -1 
		? abs(pseg->itm[pseg->armor[player_indx]].effect)
		: 0;
	temp += pseg->shield[player_indx] != -1 
		? abs(pseg->itm[pseg->shield[player_indx]].effect)
		: 0;
	sprintf(buf, "Armor: %d ", temp);
	addstr(buf);

	temp = pseg->p[player_indx].ma_count > 0 
		? pseg->p[player_indx].m_armor 
		: 0;
	if(temp) 
		sprintf(buf, "+ %d ", temp);
	else
		strcpy(buf, "     ");
	addstr(buf);

	move(1+10+NUM_MSG, 44);
	sprintf(buf, "Magic: %hd (%hd)  ",
		pseg->p[player_indx].max_mp,
		pseg->p[player_indx].magicpts);
	addstr(buf);

	move(1+10+NUM_MSG, 62);
	clrtoeol();
#ifndef ALWAYSCP
	if(pseg->p[player_indx].createpts > 0)
#endif
		printw("CP: %hd", pseg->p[player_indx].createpts);

	move(1, 44);
	sprintf(buf, "0 - Gold: %ld  %c", 
		pseg->p[player_indx].gold,
		(pseg->p[player_indx].gold_hidden ? '*' : ' '));
	clrtoeol();
	addstr(buf);

	move(2+10+NUM_MSG, 44);
	sprintf(buf, "Extra Lives: %-7d ", pseg->p[player_indx].lives);
	addstr(buf);

	park_csr();
}


show_a_player(indx)
int indx;
{
	if(pseg->p[indx].playernum == -1
	|| pseg->p[indx].invis > 0) {
		addstr("               ");
		return;
	}

	if(pseg->p[indx].loc.sector != pseg->p[player_indx].loc.sector
	&& pseg->p[player_indx].user_spell < 1) {
		addstr("               ");
		return;
	}

	addch('1' + indx);

	if(indx == player_indx)
		addstr("=");
	else if(pseg->p[player_indx].partners[indx])
		addstr("+");
	else
		addstr("-");

	addstr(pseg->p[indx].name);
}


show_items()
{
	int i, i_indx;
	char showbuf[40], ready_flag, hidden_flag;

	move(0, 44);
	addstr("-+-   - Items -  -+-");

	for(i = 0; i < PMAX_ITEMS; i++) {

		move(i + 2, 44);
		clrtoeol();
		i_indx = pseg->p[player_indx].items[i];

		if(i_indx != -1) {
			move(i + 2, 44);
			ready_flag = ' ';
			hidden_flag = ' ';

			if(pseg->itm[i_indx].type == ARMOR 
			&& pseg->armor[player_indx] == i_indx) 
				ready_flag = ARMOR;

			if(pseg->itm[i_indx].type == SHIELD 
			&& pseg->shield[player_indx] == i_indx) 
				ready_flag = SHIELD;

			if(pseg->itm[i_indx].type == WEAPON 
			&& pseg->weapon[player_indx] == i_indx) 
				ready_flag = WEAPON;

			if(pseg->itm[i_indx].symbol == HIDDEN)
				hidden_flag = '*';

			sprintf(showbuf, "%d - %s %c%c", 
				i + 1, pseg->itm[i_indx].name, 
				ready_flag, hidden_flag);

			addstr(showbuf);
		}
	}

	park_csr();
}


park_csr()
{
	move(PARK_Y, PARK_X);
}


show_modes()
{
	char buf[40];

	strcpy(buf, "Modes: ");

	if(pseg->p[player_indx].light)
		strcat(buf, "L ");
		
	if(pseg->p[player_indx].detect >= DETECT_L3)
		strcat(buf, "DDD ");
	else if(pseg->p[player_indx].detect >= DETECT_L2)
		strcat(buf, "DD ");
	else if(pseg->p[player_indx].detect)
		strcat(buf, "D ");
		
	if(pseg->p[player_indx].invis)
		strcat(buf, "I ");
		
	if(pseg->p[player_indx].blocked)
		strcat(buf, "B ");

	if(pseg->p[player_indx].knight)
		strcat(buf, "K ");

	move(3+10+NUM_MSG, 44);
	addstr(buf);
	clrtoeol();

	park_csr();
}


/* end of file. */
SHAR_EOF_show.c
-- 
		Michael
michael@stb.info.com denwa!stb!michael anes.ucla.edu!stb!michael 
"Space is an illusion; disk space doubly so"