[comp.sources.games] v12i040: mdg - multiuser dungeon game, Part04/06

billr@saab.CNA.TEK.COM (Bill Randle) (02/20/91)

Submitted-by: jcg@tree.uucp (Chris Gonnerman)
Posting-number: Volume 12, Issue 40
Archive-name: mdg/Part04
Environment: System V, SunOS 4.1, curses



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 6)."
# Contents:  cmain.c effect.c godpower.c mdg.doc seg.c show.c struct.h
# Wrapped by billr@saab on Tue Feb 19 14:49:44 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cmain.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cmain.c'\"
else
echo shar: Extracting \"'cmain.c'\" \(9691 characters\)
sed "s/^X//" >'cmain.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- mdg_char
X	
X	MDG is Copyright 1990 John C. Gonnerman
X	This program is subject to the general MDG 
X	copyright statement (see enclosed file, Copyright).
X*/
X
Xstatic char *sccsx = "@(#) MDG_CHAR Copyright 1990 John C. Gonnerman";
Xstatic char *sccsvers = "@(#) cmain.c\t(1.4)\tcreated 1/4/91";
X
X#include <curses.h>
X#include <signal.h>
X#include <string.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <time.h>
X
X#include "setup.h"
X#include "show.h"
X#include "files.h"
X#include "struct.h"
X#include "messages.h"
X#include "effect.h"
X
Xchar *progname;
X
Xextern int errno;
Xextern char *sys_errlist[];
X
Xextern char *spell_names[];
Xextern int spell_dd[];
X
Xstruct player edit_buf;
X
Xint playernum;
Xchar handle[20];
X
Xlong time_log;
Xtime_t time();
X
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	int ch, sel, save_flag;
X
X
X	if((progname = strrchr(argv[0], '/')) != NULL)
X		progname++;
X	else
X		progname = argv[0];
X
X	umask(0007);
X
X	chdir(GAME_HOME);
X
X	if(argc != 1) {
X		fprintf(stderr, ARGCOUNT, progname, argc);
X		exit(1);
X	}
X
X	if((playernum = get_player(handle)) == -1) {
X		fprintf(stderr, "%s: %s\n", progname, UNKPLAYER);
X		exit(1);
X	}
X
X	/* find and load player file */
X
X	chdir(PLAYERDIR);
X
X	if(load_a_player(&edit_buf, playernum) == -1) {
X		fprintf(stderr, CANTERR, progname, "read player file", 
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	/* set key interrupt traps */
X
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X
X	/* set up the terminal */
X
X	initscr();
X	cbreak();
X	noecho();
X
X	/* initialize screen */
X
X	show_title();
X	show_spells(&edit_buf);
X	show_stats(&edit_buf);
X	show_commands();
X	park_csr();
X
X	/* we got it, let's do it! */
X
X	sel = '\0';
X
X	random();
X
X	while(sel != 'q') {
X		sel = tolower(getch());
X
X		switch(sel) {
X		case '\f' : /* redraw */
X			clearok(stdscr, TRUE);
X			break;
X
X		case 'q' : /* quit */
X			park_csr();
X			clrtoeol();
X			addstr(" Save changes? (y/n) ");
X
X			while((ch = tolower(getch())) != 'n' && ch != 'y');
X
X			save_flag = (ch == 'y');
X			addch(ch);
X			park_csr();
X			refresh();
X
X			break;
X
X		case 'b' : /* buy lives */
X			add_a_life(&edit_buf);
X			break;
X
X		case 's' : /* study */
X			study(&edit_buf);
X			break;
X
X		case 'n' : /* name */
X			newname(&edit_buf);
X			break;
X
X		case 'a' : /* alignment change */
X			alchange(&edit_buf);
X			break;
X
X		default : /* huh? */
X			beep();
X			break;
X		}
X	}
X
X	erase();
X	refresh();
X	endwin();
X
X	if(save_flag && save_a_player(&edit_buf, playernum) == -1) {
X		fprintf(stderr, CANTERR, progname, "write player file", 
X			sys_errlist[errno]);
X		exit(1);
X	}
X}
X
X
Xalchange(p)
Xstruct player *p;
X{
X	if(p->alignment == AL_GOOD)
X		p->alignment = AL_EVIL;
X	else
X		p->alignment = AL_GOOD;
X
X	show_stats(p);
X	park_csr();
X	clrtoeol();
X}
X
X
Xadd_a_life(p)
Xstruct player *p;
X{
X	int yesno, bucks;
X
X	park_csr();
X	clrtoeol();
X
X	bucks = 5000 + p->lives * 2000;
X
X	printw(" Cost to add a life is %d", bucks);
X
X	if(p->gold < bucks) {
X		addstr("; you don't have it.");
X		park_csr();
X		return;
X	}
X
X	addstr("; do it? (y/n) ");
X	while((yesno = tolower(getch())) != 'n' && yesno != 'y');
X
X	addch(yesno);
X
X	if(yesno == 'n') {
X		park_csr();
X		return;
X	}
X
X	p->lives++;
X
X	p->gold -= bucks;
X
X	show_stats(p);
X	park_csr();
X}
X
X
Xint getnum()
X{
X	int ch, pos;
X	char buf[3];
X
X	pos = 0;
X	buf[0] = '\0';
X
X	while(ch != '\n' && ch != '\r') {
X		ch = getch();
X
X		switch(ch) {
X		case '\b' :
X			if(pos) {
X				pos--;
X				buf[pos] = '\0';
X				addstr("\b \b");
X			}
X			break;
X		case '\n' :
X		case '\r' :
X		case '\f' :
X		case '\t' :
X			break;
X		case '\033' :
X			return 0;
X		default :
X			if(isdigit(ch) && pos < 2) {
X				buf[pos++] = ch;
X				buf[pos] = '\0';
X				addch(ch);
X			}
X			break;
X		}
X	}
X
X	return atoi(buf);
X}
X
X
Xstudy(p)
Xstruct player *p;
X{
X	int bucks, ch, yesno;
X
X	park_csr();
X	clrtoeol();
X	addstr(" Select Spell to Study: ");
X
X	while((ch = tolower(getch())) != '\033' && (ch > 'z' || ch < 'a'));
X
X	if(ch == '\033') {
X		park_csr();
X		clrtoeol();
X		return;
X	}
X
X	bucks = study_cost(p->spells[ch - 'a'], spell_dd[ch - 'a']);
X
X	park_csr();
X	clrtoeol();
X
X	printw(" Cost to study %s is %d", spell_names[ch - 'a'], bucks);
X
X	if(p->gold < bucks) {
X		addstr("; you don't have it.");
X		park_csr();
X		return;
X	}
X
X	addstr("; do it? (y/n) ");
X	while((yesno = tolower(getch())) != 'n' && yesno != 'y');
X
X	addch(yesno);
X
X	if(yesno == 'n') {
X		park_csr();
X		return;
X	}
X
X	p->gold -= bucks;
X		
X	p->spells[ch - 'a'] += rnd(increment(p->spells[ch - 'a']));
X
X	show_spells(p);
X	show_stats(p);
X	park_csr();
X}
X
X
Xint study_cost(percent, dd)
Xint percent, dd;
X{
X	return 50 * (dd * cat_cost(percent));
X}
X
X
Xint cat_cost(percent)
Xint percent;
X{
X	if(percent == 0) return 4;
X
X	if(percent < 26) return 1;
X
X	if(percent < 51) return 3;
X
X	if(percent < 70) return 4;
X
X	if(percent < 86) return 7;
X
X	if(percent < 96) return 9;
X
X	if(percent < 101) return 14;
X
X	if(percent < 101) return 18;
X
X	return 25;
X}
X
X
Xint increment(percent)
Xint percent;
X{
X	if(percent == 0) return 20;
X
X	if(percent < 26) return 10;
X
X	if(percent < 51) return 7;
X
X	if(percent < 70) return 5;
X
X	if(percent < 86) return 3;
X
X	if(percent < 96) return 2;
X
X	return 1;
X}
X
X
Xshow_title()
X{
X	move(0, 0);
X	addstr("-+- MDG Multiuser Dungeon Game -- Character Editor -+-");
X}
X
X
Xshow_spells(p)
Xstruct player *p;
X{
X	int i, j, odds;
X	char buf[20], nbuf[10];
X
X	for(i = 0; i < 13; i++)
X	for(j = 0; j < 2; j++) {
X		move(i + 4, j * 25);
X		odds = spell_percent(i + (13 * j), p);
X		sprintf(nbuf, "(%d%%)", odds);
X		sprintf(buf, "%-12.12s %3d %6s", 
X			spell_names[i + (13 * j)],
X			(int)p->spells[i + (13 * j)],
X			nbuf);
X		addstr(buf);
X	}
X}
X
X
Xint spell_percent(spell, p)
Xint spell;
Xstruct player *p;
X{
X	int dd, chance;
X
X	dd = spell_dd[spell];
X	chance = p->spells[spell] * 100;
X
X	if(chance < 1)
X		return 0;
X
X	return chance / (90 + (10 * dd));
X}
X
X
Xshow_stats(p)
Xstruct player *p;
X{
X	char buf[40];
X
X	move(2, 0);
X	addstr("Name: ");
X	addstr(p->name);
X	if(p->alignment == AL_GOOD)
X		addstr(" (Good)");
X	else
X		addstr(" (Evil)");
X	clrtoeol();
X
X	move(4, 54);
X	sprintf(buf, "HP: %hd (%hd)    ", p->max_hp, p->hitpoints);
X	addstr(buf);
X
X	move(5, 54);
X	sprintf(buf, "Magic: %hd (%hd)     ", p->max_mp, p->magicpts);
X	addstr(buf);
X
X	move(6, 54);
X	sprintf(buf, "Gold: %ld     ", p->gold);
X	addstr(buf);
X
X	move(7, 54);
X	sprintf(buf, "Fighting: %hd   ", p->fighting);
X	addstr(buf);
X
X	move(8, 54);
X	sprintf(buf, "Lives: %d   ", p->lives);
X	addstr(buf);
X}
X
X
Xshow_commands()
X{
X	move(10, 54);
X	clrtoeol();
X	addstr("Options:");
X
X	move(11, 54);
X	clrtoeol();
X	addstr("A)lignment change");
X
X	move(12, 54);
X	clrtoeol();
X	addstr("S)tudy spell");
X
X	move(13, 54);
X	clrtoeol();
X	addstr("N)ame change");
X
X	move(14, 54);
X	clrtoeol();
X	addstr("B)uy a life");
X
X	move(16, 54);
X	clrtoeol();
X	addstr("Q)uit");
X}
X
X
Xnewname(p)
Xstruct player *p;
X{
X	park_csr();
X	clrtoeol();
X	addstr(" Enter new name: ");
X
X	getword(p->name, 20);
X
X	show_stats(p);
X	park_csr();
X	clrtoeol();
X}
X
X
Xpark_csr()
X{
X	move(PARK_Y, 0);
X}
X
X
Xint save_a_player(p, playernum)
Xstruct player *p;
Xint playernum;
X{
X	char profname[15], fname[15];
X	FILE *fp;
X	int i;
X
X	sprintf(fname, "pl%05d", playernum);
X	sprintf(profname, "pr%05d", playernum);
X
X	if((fp = fopen(profname, "w")) != NULL) {
X		fputs(p->name, fp);
X		putc('\n', fp);
X		fclose(fp);
X	}
X
X	/* save player's file */
X
X	if((fp = fopen(fname, "w")) == NULL)
X		return -1;
X		
X	fprintf(fp, "%s\n", p->name);
X	fprintf(fp, "%ld\n", p->gold);
X
X	for(i = 0; i < 26; i++) {
X		fprintf(fp, "%hd ", p->spells[i]);
X		if(((i + 1) % 13) == 0)
X			putc('\n', fp);
X	}
X
X	fprintf(fp, "%hd:%hd\n", p->max_hp, p->hitpoints);
X
X	fprintf(fp, "%hd:%hd\n", p->max_mp, p->magicpts);
X
X	fprintf(fp, "%hd\n", p->fighting);
X
X	fprintf(fp, "[%d/%d]\n", p->loc.sector, p->home);
X
X	fprintf(fp, "%d\n", p->lives);
X
X	fprintf(fp, "%ld\n", time(NULL) - DATE_OFFSET);
X
X	fprintf(fp, "%hd\n", p->createpts);
X
X	fprintf(fp, "al = %hd\n", p->alignment);
X
X	fclose(fp);
X
X	return 0;
X}
X
X
Xint load_a_player(p, playernum)
Xstruct player *p;
Xint playernum;
X{
X	char tmpname[PNAMELEN], profname[15], fname[15], *s;
X	FILE *fp;
X	int i;
X
X	sprintf(fname, "pl%05d", playernum);
X	sprintf(profname, "pr%05d", playernum);
X
X	if((fp = fopen(profname, "r")) == NULL)
X		p->name[0] = '\0';
X	else {
X		fgets(p->name, 20, fp);
X		fclose(fp);
X	}
X
X	if((fp = fopen(fname, "r")) == NULL 
X	&& (fp = fopen("default", "r")) == NULL)
X		return -1;
X
X	fgets(tmpname, 20, fp);
X
X	if(p->name[0] == '\0')
X		strcpy(p->name, tmpname);
X
X	for(s = p->name; *s; s++)
X		if(*s == '\n')
X			*s = '\0';
X
X	if(p->name[0] == '\0')
X		get_handle(p->name, playernum);
X
X	fscanf(fp, "%ld\n", &(p->gold));
X
X	for(i = 0; i < 26; i++)
X		fscanf(fp, "%hd", &(p->spells[i]));
X
X	fscanf(fp, "%hd:%hd\n", &(p->max_hp), &(p->hitpoints));
X
X	fscanf(fp, "%hd:%hd\n", &(p->max_mp), &(p->magicpts));
X
X	fscanf(fp, "%hd\n", &(p->fighting));
X
X	fscanf(fp, "[%d/%d]\n", &(p->loc.sector), &(p->home));
X
X	fscanf(fp, "%d\n", &(p->lives));
X
X	fscanf(fp, "%ld\n", &time_log);
X
X	fscanf(fp, "%hd\n", &(p->createpts));
X
X	fscanf(fp, "al = %hd\n", &(p->alignment));
X
X	fclose(fp);
X
X	time_log = (time(NULL) - DATE_OFFSET) - time_log;
X
X	if(time_log > 600)
X		time_log = 600;
X
X	time_log = time_log / TIME_TO_HEAL;
X
X	while(time_log--) {
X		if(p->hitpoints < p->max_hp)
X			p->hitpoints++;
X		if(p->hitpoints >= MIN_HPS
X		&& p->magicpts < p->max_mp)
X			p->magicpts++;
X	}
X
X	return 0;
X}
X
X
Xgetword(word, len)
Xchar *word;
Xint len;
X{
X	int ch, pos;
X	char buf[80];
X
X	pos = 0;
X	buf[0] = '\0';
X
X	while(ch != '\n' && ch != '\r') {
X		ch = getch();
X
X		switch(ch) {
X		case '\b' :
X			if(pos) {
X				pos--;
X				buf[pos] = '\0';
X				addstr("\b \b");
X			}
X			break;
X		case '\n' :
X		case '\r' :
X		case '\f' :
X		case '\t' :
X			break;
X		case '\033' :
X			return;
X		default :
X			if(isprint(ch) && pos < (len - 1)) {
X				buf[pos++] = ch;
X				buf[pos] = '\0';
X				addch(ch);
X			}
X			break;
X		}
X	}
X
X	strcpy(word, buf);
X}
X
X
X/* end of file. */
END_OF_FILE
if test 9691 -ne `wc -c <'cmain.c'`; then
    echo shar: \"'cmain.c'\" unpacked with wrong size!
fi
# end of 'cmain.c'
fi
if test -f 'effect.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'effect.c'\"
else
echo shar: Extracting \"'effect.c'\" \(3186 characters\)
sed "s/^X//" >'effect.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- effect.c effect handler
X	
X	MDG is Copyright 1990 John C. Gonnerman
X	This program is subject to the general MDG 
X	copyright statement (see enclosed file, Copyright).
X*/
X
X
Xstatic char *sccsvers = "@(#) effect.c\t(1.1)\tcreated 12/25/90";
X
X#include "setup.h"
X#include "struct.h"
X#include "effect.h"
X#include "spells.h"
X
Xextern struct player_seg *pseg;
Xextern struct map_seg *mseg;
X
Xextern struct note_tbl *note_table;
Xextern int n_notes;
X
Xextern char *spell_names[];
X
X
Xactivate_item(p_indx, mptr)
Xint p_indx;
Xstruct dmessage *mptr;
X{
X	int i_indx, dir;
X
X	i_indx = mptr->subcmd;
X	dir = mptr->arg;
X
X	if(pseg->itm[i_indx].type != POTION 
X	&& pseg->itm[i_indx].type != NOTE
X	&& pseg->itm[i_indx].type != OBJECT
X	&& pseg->itm[i_indx].type != MISSILE
X	&& pseg->itm[i_indx].type != SCROLL)
X		return;
X
X	if(pseg->itm[i_indx].type == MISSILE)
X		fire_missile(p_indx, i_indx, dir);
X	else if(pseg->itm[i_indx].type == NOTE) {
X		if(pseg->itm[i_indx].curse == 0)
X			read_note(p_indx, pseg->itm[i_indx].effect);
X		else
X			dmsg_add(p_indx, "It is illegible.");
X	} else {
X		if(pseg->itm[i_indx].curse == 0)
X			do_effect(p_indx, pseg->itm[i_indx].effect,
X				pseg->itm[i_indx].range, dir);
X		else {
X			ptakedamage(p_indx, rnd(20));
X			dmsg_add(p_indx, "POISON!");
X		}
X	}
X
X	if(pseg->itm[i_indx].max_uses < 1)
X		return;
X
X	pseg->itm[i_indx].rem_uses--;
X
X	if(pseg->itm[i_indx].rem_uses > 0)
X		return;
X
X	pseg->itm[i_indx].loc.sector = LOC_NONESUCH;
X	delete_item(p_indx, i_indx);
X
X	pseg->item_sem++;
X	tell_player(p_indx);
X}
X
X
Xread_note(p_indx, n_indx)
Xint p_indx, n_indx;
X{
X	char buf[40];
X
X	sprintf(buf, "%c%s%c", '"', note_table[n_indx].text, '"');
X	dmsg_add(p_indx, buf);
X}
X
X
Xdo_effect(p_indx, effect, range, dir)
Xint p_indx, effect, range, dir;
X{
X	char buf[35];
X	int spell;
X
X	switch(effect) {
X	case TELEPORT :
X		teleport(p_indx);
X		break;
X
X	case COLD :
X		visible(p_indx);
X		cast_a_spell(&(pseg->p[p_indx].loc), AS_COLD, dir, 
X			go2r(range));
X		break;
X
X	case FIREBALLS :
X		visible(p_indx);
X		cast_a_spell(&(pseg->p[p_indx].loc), AS_FIREBALL, dir, 
X			go2r(range));
X		break;
X
X	case LIGHTNING :
X		visible(p_indx);
X		cast_a_spell(&(pseg->p[p_indx].loc), AS_LIGHTNING, dir, 
X			go2r(range));
X		break;
X
X	case ZAP :
X		visible(p_indx);
X		cast_a_spell(&(pseg->p[p_indx].loc), AS_ZAP, L_EAST, 
X			go2r(range));
X		break;
X
X	case HEALING :
X		heal(p_indx);
X		tell_player(p_indx);
X		break;
X
X	case DETECT :
X		detect(p_indx);
X		tell_player(p_indx);
X		break;
X
X	case GLOW :
X		glow(p_indx);
X		tell_player(p_indx);
X		break;
X
X	case INVISIBLE :
X		invisible(p_indx);
X		tell_player(p_indx);
X		break;
X
X	case MAGICPTS :
X		if(pseg->p[p_indx].magicpts >= pseg->p[p_indx].max_mp) {
X			dmsg_add(p_indx, "nothing happens.");
X		} else {
X			dmsg_add(p_indx, "you feel energized!");
X
X			pseg->p[p_indx].magicpts += rnd(10);
X
X			if(pseg->p[p_indx].magicpts > pseg->p[p_indx].max_mp)
X				pseg->p[p_indx].magicpts = 
X					pseg->p[p_indx].max_mp;
X		}
X		pseg->player_sem++;
X		tell_player(p_indx);
X		break;
X
X	case LEARN_SPELL :
X		spell = rnd(26) - 1;
X		sprintf(buf, "you learn about %s", spell_names[spell]);
X		dmsg_add(p_indx, buf);
X		improve_s(p_indx, spell);
X		break;
X
X	default :
X		break;
X	}
X}
X
X
X/* end of file. */
END_OF_FILE
if test 3186 -ne `wc -c <'effect.c'`; then
    echo shar: \"'effect.c'\" unpacked with wrong size!
fi
# end of 'effect.c'
fi
if test -f 'godpower.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'godpower.c'\"
else
echo shar: Extracting \"'godpower.c'\" \(7695 characters\)
sed "s/^X//" >'godpower.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- godpower.c godlike power code
X	
X	MDG is Copyright 1990 John C. Gonnerman
X	This program is subject to the general MDG 
X	copyright statement (see enclosed file, Copyright).
X*/
X
Xstatic char *sccsvers = "@(#) godpower.c\t(1.1)\tcreated 12/25/90";
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X
X#include "setup.h"
X#include "struct.h"
X
Xextern char *progname;
X
Xextern struct map_seg *mseg;
Xextern struct player_seg *pseg;
X
Xextern int trap_adder[];
X
Xchar *mapspots = "={}:;-| 0123456789%#@^,<>~`+.";
X
Xstruct {
X	char type;
X	short limit;
X} mod_limits[] = {
X	POTION,		 1,
X	SCROLL,		 1,
X	ARMOR, 		 3,
X	SHIELD,		 2,
X	WEAPON,		 5,
X	MISSILE,	 5,
X	OBJECT, 	 1,
X	NOTE, 		 0,
X	CASH, 		 0,
X	CRYSTAL,	 0,
X	' ',		-1,
X};
X
Xint memory[MAX_PLAYERS];
X
X
Xint get_limit(type)
Xchar type;
X{
X	int i;
X
X	for(i = 0; mod_limits[i].limit >= 0; i++)
X		if(mod_limits[i].type == type)
X			return mod_limits[i].limit;
X
X	return -1;
X}
X
X
Xgod_power(p_indx, mptr)
Xint p_indx;
Xstruct dmessage *mptr;
X{
X	char buf[35];
X	int sector, dir, what, which, how, at_spot, points, mult;
X	struct location where;
X
X	switch(mptr->subcmd) {
X
X	case 'l' :
X		god_link(p_indx, mptr->arg, mptr->ext_arg);
X		break;
X
X	case 'm' :
X		dir = mptr->arg;
X		what = mptr->ext_arg;
X		where = pseg->p[p_indx].loc;
X		get_dest(&where, dir);
X
X		if((sector = where.sector) < 0) {
X			dmsg_add(p_indx, "Can't change that.");
X			return;
X		}
X
X		if(strchr(mapspots, what) == NULL) {
X			dmsg_add(p_indx, "Code invalid.");
X			return;
X		}
X
X		mult = 1;
X
X		if(what >= '0' && what <= '9')
X			mult += trap_adder[what-'0'];
X
X		if((points = checklimit(p_indx, sector, mult)) == -1)
X			return;
X
X		at_spot = mseg->m[sector].map[where.y][where.x];
X
X		if(is_item(at_spot) 
X		|| is_critter(at_spot) 
X		|| is_player(at_spot)) {
X			dmsg_add(p_indx, "Clear spot first.");
X			return;
X		}
X
X		mseg->m[sector].map[where.y][where.x] = what;
X		mseg->save_map = 1;
X		mseg->map_sem++;
X
X		pseg->p[p_indx].createpts -= points;
X
X		break;
X
X	case 's' :
X		sector = pseg->p[p_indx].loc.sector;
X
X		ch_stat(p_indx, sector, mptr->arg, mptr->ext_arg);
X
X		break;
X
X	case 't' :
X		sector = mptr->arg;
X
X		if((points = checklimit(p_indx, sector, 3)) == -1)
X			return;
X
X		if(mptr->text[0] == '\0')
X			return;
X
X		pseg->p[p_indx].createpts -= points;
X		pseg->player_sem++;
X		strcpy(mseg->m[sector].title, mptr->text);
X		mseg->save_map = 1;
X		mseg->map_sem++;
X		break;
X
X	case 'r' :
X		sector = pseg->p[p_indx].loc.sector;
X
X		sprintf(buf, "[ Light %d, Level %d ]",
X			mseg->m[sector].light, mseg->m[sector].level);
X		dmsg_add(p_indx, buf);
X
X		sprintf(buf, "[ Jump %d, God Limit %d, '%c' ]",
X			mseg->m[sector].jump_inhibit, 
X			mseg->m[sector].god_limit, 
X			mseg->m[sector].border_ch);
X		dmsg_add(p_indx, buf);
X
X		break;
X
X	case 'i' :
X		what = mptr->arg;
X
X		sprintf(buf, "[ %s '%c' ]", 
X			pseg->itm[what].name,
X			pseg->itm[what].type);
X		dmsg_add(p_indx, buf);
X
X		tell_about(what, p_indx);
X
X		break;
X
X	case 'n' :
X		what = mptr->arg;
X
X		if(pseg->p[p_indx].createpts < 3) {
X			dmsg_add(p_indx, "Need 3 CP to change item.");
X			break;
X		}
X
X		strncpy(pseg->itm[what].name, mptr->text, INAMELEN - 1);
X
X		pseg->p[p_indx].createpts -= 3;
X		pseg->player_sem++;
X
X		pseg->itm[what].name[INAMELEN-1] = '\0';
X		pseg->item_sem++;
X
X		dmsg_add(p_indx, "Item Changed.");
X		break;
X
X	case 'a' :
X		what = mptr->arg;
X		which = mptr->ext_arg;
X		ch_i_stat(p_indx, what, which);
X		break;
X	}
X}
X
X
Xch_i_stat(p_indx, i_indx, which)
Xint p_indx, i_indx, which;
X{
X	int m, need;
X	char buf[35];
X
X	need = 3;
X
X	if(which == 'c')
X		need = 9;
X
X	if(pseg->p[p_indx].createpts < need) {
X		sprintf(buf, "Need %d CP to change item.", need);
X		dmsg_add(p_indx, buf);
X		return;
X	}
X
X	if(which == 'c') {
X		switch(pseg->itm[i_indx].curse) {
X		case 0 :
X			pseg->itm[i_indx].curse = 1;
X			dmsg_add(p_indx, "Item Cursed.");
X			break;
X		default :
X			pseg->itm[i_indx].curse = 0;
X			dmsg_add(p_indx, "Item Uncursed.");
X			break;
X		}
X	} else {
X		if((m = get_limit(pseg->itm[i_indx].type)) == -1
X		|| pseg->itm[i_indx].mod_count == -1) {
X			dmsg_add(p_indx, "Can't change that.");
X			return;
X		}
X
X		if(pseg->itm[i_indx].mod_count >= m) {
X			dmsg_add(p_indx, "Can't change that.");
X			return;
X		}
X
X		switch(pseg->itm[i_indx].type) {
X		case ARMOR :
X		case SHIELD :
X		case WEAPON :
X			if(which == 'r') {
X				dmsg_add(p_indx, "Can't change that.");
X				return;
X			}
X			break;
X
X		case MISSILE :
X			break;
X	
X		default:
X			dmsg_add(p_indx, "Can't change that.");
X			return;
X		}
X
X		switch(which) {
X		case 'v' : /* value */
X			pseg->itm[i_indx].effect++;
X			break;
X		case 'r' : /* range */
X			pseg->itm[i_indx].range++;
X			break;
X		}
X
X		pseg->itm[i_indx].value *= 1.5;
X		pseg->itm[i_indx].mod_count++;
X	}
X
X	pseg->p[p_indx].createpts -= need;
X	pseg->player_sem++;
X
X	pseg->item_sem++;
X
X	dmsg_add(p_indx, "Item Changed.");
X}
X
X
Xch_stat(p_indx, sector, what, how)
Xint p_indx, sector, what, how;
X{
X	int diff, points;
X	char buf[35];
X
X	if((points = checklimit(p_indx, sector, 4)) == -1)
X		return;
X
X	switch(how) {
X	case '+' :
X		diff = 1;
X		break;
X	case '-' :
X		diff = -1;
X		break;
X	default :
X		dmsg_add(p_indx, "Must specify + or -");
X		return;
X	}
X
X	switch(what) {
X	case 'l' : /* level */
X		if(mseg->m[sector].level == 0 && diff == -1) {
X			dmsg_add(p_indx, "Level is 0");
X			return;
X		}
X		mseg->m[sector].level += diff;
X		break;
X	case 'i' : /* illumination */
X		if(mseg->m[sector].light == -1 && diff == -1) {
X			dmsg_add(p_indx, "Light is -1");
X			return;
X		}
X		if(mseg->m[sector].light == 2 && diff == 1) {
X			dmsg_add(p_indx, "Light is 2");
X			return;
X		}
X		mseg->m[sector].light += diff;
X		break;
X	case 'j' : /* jump_inhibit */
X		if(mseg->m[sector].jump_inhibit == 0 && diff == -1) {
X			dmsg_add(p_indx, "Jump Inhibit is 0");
X			return;
X		}
X		mseg->m[sector].jump_inhibit += diff;
X		break;
X	}
X
X	mseg->save_map = 1;
X	mseg->map_sem++;
X	pseg->p[p_indx].createpts -= points;
X	pseg->player_sem++;
X	notify(sector);
X}
X
X
Xtell_about(i_indx, p_indx)
Xint i_indx, p_indx;
X{
X	char buf[35];
X
X	switch(pseg->itm[i_indx].type) {
X	case POTION :
X	case SCROLL :
X	case NOTE :
X	case OBJECT :
X		sprintf(buf, "[ M%hd %s]", 
X			pseg->itm[i_indx].mod_count,
X			(pseg->itm[i_indx].curse ? "C " : ""));
X		dmsg_add(p_indx, buf);
X		break;
X
X	case ARMOR :
X	case SHIELD :
X	case WEAPON :
X		sprintf(buf, "[ M%hd V%d %s]", 
X			pseg->itm[i_indx].mod_count,
X			pseg->itm[i_indx].effect,
X			(pseg->itm[i_indx].curse ? "C " : ""));
X		dmsg_add(p_indx, buf);
X		break;
X		
X	case MISSILE :
X		sprintf(buf, "[ M%hd V%d R%d %s]", 
X			pseg->itm[i_indx].mod_count,
X			pseg->itm[i_indx].effect,
X			pseg->itm[i_indx].range,
X			(pseg->itm[i_indx].curse ? "C " : ""));
X		dmsg_add(p_indx, buf);
X		break;
X	}
X}
X
X
Xgod_link(p_indx, how, which)
Xint p_indx, how, which;
X{
X	int points, sector;
X
X	sector = pseg->p[p_indx].loc.sector;
X
X	switch(how) {
X	case 'r' : /* remember */
X		memory[p_indx] = sector;
X		dmsg_add(p_indx, "Sector memorized.");
X		break;
X
X	case 'c' : /* create */
X
X		if((points = checklimit(p_indx, sector, 5)) == -1)
X			return;
X
X		if(memory[p_indx] < 0) {
X			dmsg_add(p_indx, "No sector memorized.");
X			return;
X		}
X
X		mseg->m[sector].links[L_GATE+which] = memory[p_indx];
X
X		pseg->p[p_indx].createpts -= points;
X		pseg->player_sem++;
X
X		mseg->save_map = 1;
X		mseg->map_sem++;
X
X		dmsg_add(p_indx, "Linked!");
X
X		break;
X
X	default :
X		dmsg_add(p_indx, "Huh?");
X		break;
X	}
X}
X
X
Xint checklimit(p_indx, sector, mult)
Xint p_indx, sector, mult;
X{
X	char buf[35];
X	int points;
X
X	if(mseg->m[sector].god_limit < 1) {
X		dmsg_add(p_indx, "Can't change that.");
X		return -1;
X	}
X
X	points = mseg->m[sector].god_limit * mult;
X
X	if(pseg->p[p_indx].createpts < points) {
X		sprintf(buf, "Need %d CP.", points);
X		dmsg_add(p_indx, buf);
X		return -1;
X	}
X
X	return points;
X}
X
X
X/* end of file. */
END_OF_FILE
if test 7695 -ne `wc -c <'godpower.c'`; then
    echo shar: \"'godpower.c'\" unpacked with wrong size!
fi
# end of 'godpower.c'
fi
if test -f 'mdg.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mdg.doc'\"
else
echo shar: Extracting \"'mdg.doc'\" \(10988 characters\)
sed "s/^X//" >'mdg.doc' <<'END_OF_FILE'
X                          ----------------------
X			       Solomoriah's
X                          Multiuser Dungeon Game
X                          ----------------------
X                                Release 0
X                          ----------------------
X
X                     Copyright 1990 John C. Gonnerman
X
X
XStarting MDG
X
XIn order to play MDG, you must execute the command "mdg" from any shell 
Xcommand line.  The mdg program communicates with the central game server; 
Xtherefore, you may not be able to play the game due to the server program 
Xbeing "down".
X
XWhen you start the game, your character will be placed in a space in the 
Xstarting location.  An example is given below:
X
X
X   . HOME HOME HOME HOME HOME HOME HOME .    -+-   - Items -  -+-
X  ~~ %  %   % % %    %  % % %  % % %   %     0 - Gold: 205
X  ~~   %  %   %     % % %  % ?%   %   %      1 - Sword
X  ~~~ %  %  %  %  %    /      %        %     2 - Chainmail
X  ~~~~ ! % %  %    %  %  %                   3 - Scroll of Teleport
X  ~~~~~        2  %    %     %  %      %
X  ~~~~~~   %   %   %  %
X  ~~~~~~~~~)    %   %            1
X  ~~~~~~~~~~   %     %!   %
X  ~~~~~~~~~~~~~  % %  %      %
X  ~~~~~~~~~~~~~~~~~~~~   %                   
X  ~~~~~~~~~~~~~~~~~~~~~~~~~  % %             HP: 25 (25)    Armor: 0
X  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        Magic: 5 (5)
X  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   Extra Lives: 1
X   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    Modes:
X  The woods.
X
X  1 + Shockwave               2 = Solomoriah
X
X
X  _ Welcome, Solomoriah... press ? for Help.
X
X
XThe displayed character, Solomoriah, has played this game before; note that
Xhe has several items.  Each character can carry as many as seven items at a
Xtime.  The gold total listed does not count toward this limit.
X
XThe HP display shows the characters maximum, normal hit points, and his
Xcurrent hit points in parentheses.  The magic points counter works the same 
Xway.  He has a suit of armor (in the item list) but has not yet "activated" 
Xit, so his armor value is still 0.  Each time you start the game, you must 
Xactivate any weapon, armor and/or shield you may have.
X
XThe count of extra lives indicates how many times Solomoriah may die and
Xstill retain his skills.  Note that each time you die, you DO lose your
Xequipment and money!
X
XAt the bottom of the screen display, the symbols and handles of all players
Xcurrently in the game may be shown.  Shockwave is player 1 (this time) and
XSolomoriah is 2.  The character between the letter and the name may be
X"-", "+", or "=";  the "=" appears by the name of the character playing
Xat this terminal, Solomoriah.  The "+" by Shockwave indicates that
XSolomoriah is partnered toward Shockwave.  If "-" is shown, then the
Xcurrent player (Solomoriah) is NOT partnered toward that character.  See
Xthe Partner command, below, for details about what this means.
X
XNote that both Shockwave and Solomoriah are on the screen at the same
Xtime.  If they were not, their names would not appear to each other.  Thus,
Xother players could be in the game at the same time, but their names
Xonly show under certain circumstances.  You can see a name of a player
Xin the game if you are in the same sector, or if you have cast the Users
Xspell.  The name will NOT show under these circumstances if the other
Xplayer is Invisible (by the use of an Invisible spell or item).
X
XThe top line of this map display is "home".  Any map edge with that "HOME"
Xstring in it will save your character and exit the game.  
X
XIf you lose carrier for some reason while playing MDG, your
Xcharacter will not be saved; rather, your previous game-save will be used 
Xthe next time you play.  Items you pick up during a game session will also 
Xbe lost if you lose carrier, but items you had in the previous save will 
Xstill be there (unless you dropped them after entering the game).
X
XBasically, this means that you aren't "killed" by losing carrier, but you
Xalso have some very good reasons not to do so intentionally.
X
X
XGame Commands
X
XMDG commands are single characters.  Some commands may need one or two 
Xpieces of additional information, like the item number of an item to drop 
Xand the direction to drop it in.  The commands are described below:
X
XMovement:  Either the letter keys or the numeric keypad may be used, as
Xshown below:
X
X               y  k  u      7  8  9
X                \ | /        \ | /
X              h - + - l    4 - + - 6
X                / | \        / | \
X               b  j  n      1  2  3
X
XTime of Day:  Press the semicolon (";") key to find out what time of day
Xit is.  At night, most map sectors are dark and require you to have a
Xlight source to see.
X
XOther Commands:  Each command below is listed with it's arguments.  The
Xcommands are actually typed in lowercase.  The arguments are:
X
X   <Item> is an item number, from 1 to 7, as shown on the item list.
X   <Player> is a player number, from 1 to 9, as shown in the player display.
X   <Direction> is a direction, entered using the move command keys, above.
X   <Spell> is a single letter, from a to z, indicating which spell to cast.
X   <Text> is up to 30 characters of message.
X
XActivate <Item> is used to select your Weapon, Armor, and/or Shield, or to 
Xuse an expendable item (Potion, Scroll, or Object).  The selected Weapon is 
Xshown with the "Weapon" symbol after it; the Armor is likewise shown with 
Xthe Armor symbol after it.  An expendable item disappears from the player's 
Xlist when activated.
X 
XDrop <Item> <Direction> is used to put an item back on the map.  You can stack
Xitems in a given sector, but note that the game has it's own idea as to what
Xitem to put on top.
X
XCast <Spell> [ <Direction> ] attempts to cast one of the 26 spells; see the
XMagic section, below, for more details.
X
XEnter is used to traverse stairs.  Step on top of the stair symbol and press
Xthe 'e' key.
X
XPartner <Player> allows you to change which players are your "partners."  
XWhenever you enter the game, you start out with all other players as your 
Xpartners.  This command lets you "toggle" that setting; each time you enter
XMDG you are automatically set to Partner with everyone.  Anyone
Xyou are partnered toward is safe from being accidentally attacked by you.
X
XSay <Text> allows your character to speak.  Only characters in the same sector 
Xwith you can "hear" you... unless you "yell" by typing an exclamation point 
X(!) as the first character of <text>.
X
XTake is used to pick up items.  Step on top of the item, and press the 't' key.
XNote that several items may be piled in one place.
X
XWrite <Item> <Text> is used to write on a note item.
X
X
XMap Symbols
X
XMonsters are shown on the map as letters; adventurers are shown as numerals.  
XThe other symbols are shown below:
X
X    Items                Terrain
X      )  Weapon            #  Wall
X      (  Missile weapon    %  Vegetation
X      ]  Armor             ~  Water
X      [  Shield            :  Open Air (the first step is a doozy!)
X      "  Note
X      ?  Scroll        
X      !  Potion
X      /  Object          (Blank spaces are normally "clear terrain")
X      $  Treasure
X
XNotes: 
X
XVegetation and Water spaces can be entered in a limited fashion; adventurers
Xcannot normally advance from one space of vegetation to another, or from one
Xspace of water to another.
X
XTreasure items ($) add to your gold value when picked up.
X
X
XCombat
X
XTo attack a monster or another player, simply move to the target's symbol,
Xand then try to move into it's space.  Each such move counts as one attack.  
XIf you do not have a weapon activated, you will use "unarmed" combat.
X
X
XMagic
X
XThere are 26 spells possible in MDG (from a to z); they are described 
Xbelow:
X
XArmor - adds to your armor rating.
X
XBlock - prevents others from using Seek (see below) to find you.
X
XCold - casts a cloud of freezing mist in the indicated direction.  (See
Xbelow.)
X
XDetect - if this spell is successfully cast, traps, pits, and hidden doors
Xon the map will be shown.
X
XEscape - this spell takes you to your starting space.
X
XFireball - casts a fireball in the indicated direction.  (See below.)
X
XGlow - illuminates the area around you.
X
XHeal - heals you.
X
XInvisible - makes you disappear.  You will reappear if you attack anyone.
X
XJump Back - reverses the last teleport-type spell you used.
X
XLightning - casts a bolt of lightning in the indicated direction.  (See below.)
X
XMissile - casts a slow-moving missile of energy... which can demolish
Xvegetation.
X
XObscure - makes an object invisible.
X
XPartners - reveals who is partnered toward you.
X
XQuit - saves your character right where he or she is.
X
XRay of Death - casts a cone of energy in the indicated direction.
X
XSeek - teleports you to a specific players location.  Block will stop it.
X
XTeleport - transports you to a random location.
X
XUsers - makes all (visible) players show in the names display area.
X
XVerify - identifies whether or not an item is cursed.
X
XWhisper - send a message to another player in the game, regardless of distance.
X
XSpell X - attack all enemies in the current sector.
X
XYank - teleports another player to you.  Block will stop this too.
X
XZap - projects a field of energy around you.  (See below.)
X
X
XAttack Spells:
X
XThe five attack spells (described above) have the following areas of effect:
X
X                  **
XCold:           1****
X                  **
X 
X                     *
XFireball:       1******
X                     *
X
XLightning:      1********
X
X                  *   
X                 **
XRay of Death:   1**      this spell will pass thru walls.
X                 **
X                  *
X
X               ***
XZap:           *1*
X               ***
X
X("1" represents the player; the area of effect will be modified by direction,
Xexcept for the Zap spell.)
X
XNote that if you are surrounded by monsters Zap is real handy.  
X
X
XGod Powers:
X
XA character who is near or at the maximums for HP and MP is called
X"godlike" and wields the God Powers.  The God Powers are accessed
Xthrough the 'g' command, and allow the player to change the map, or to
Xalter items in his or her inventory.  These powers require Creation
XPoints, which are accumulated by killing the very toughest monsters and
Xcollecting Magic Crystals from them.
X
XThe details of the God Powers will not be discussed here, except to list
Xthe possible map codes that map spaces may be set to:
X
X	%   Vegetation		0   Pit
X	#   Wall		1-9 Traps
X	@   Invisible Wall	+   Secret Way
X	~   Water		`   Shallow Water
X	^   Open Air		=   Teleporting Gate
X	,   Fake Air		.   Anti-Monster Barrier
X
Xand of course the space character, to clear a spot.
X
X
XCredits:
X
X@(#) MDG Multi-user Dungeon Game, Copyright 1990 John C. Gonnerman.
XSee the file "Copyright" distributed with the game for restrictions.
X
XThe author would like to thank the playtesters for their able
Xassistance (listed by character name):
X
X	Sir Asmo 		ALAN_the_Terrible
X	Turk 			Dammerschlaf
X	Antilles 		Hyder Terriha IV
X	Warrior Jon		Firestorm
X	Wintermute 		killer
X	Sexual Chocolate 	SLADE
X	The Cav 		The Wiz
X	Singleton		Mazer
X	lasertag the great	Foxx
X	Rex
X
END_OF_FILE
if test 10988 -ne `wc -c <'mdg.doc'`; then
    echo shar: \"'mdg.doc'\" unpacked with wrong size!
fi
# end of 'mdg.doc'
fi
if test -f 'seg.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'seg.c'\"
else
echo shar: Extracting \"'seg.c'\" \(13327 characters\)
sed "s/^X//" >'seg.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- seg.c segment code
X	
X	MDG is Copyright 1990 John C. Gonnerman
X	This program is subject to the general MDG 
X	copyright statement (see enclosed file, Copyright).
X*/
X
Xstatic char *sccsvers = "@(#) seg.c\t\t(1.5)\tcreated 1/4/91";
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/ipc.h>
X#include <sys/shm.h>
X#include "setup.h"
X#include "files.h"
X#include "struct.h"
X#include "messages.h"
X
X#define MREADF \
X	"%c [%d] %d, %d %hd:%hd %hd %hd/%hd:%hd L%hd D%hd IQ=%hd"
X
X#define MWRITEF	\
X	"%s\n%c [%d] %d, %d %hd:%hd %hd %hd/%hd:%hd L%hd D%hd IQ=%hd\n"
X
X#define MAPFMTR \
X	"%hd %hd %hd %hd / %hd %hd / %hd %hd %hd %hd %hd %hd %hd"
X
X#define MAPFMTW \
X	"%hd %hd %hd %hd / %hd %hd / %hd %hd %hd %hd %hd %hd %hd\n"
X
XFILE *saveopen();
X
Xextern char *progname;
Xextern int dqid, pid;
X
Xextern int errno;
Xextern char *sys_errlist[];
X
Xextern long mapkey, playerkey;
Xextern long max_mps;
X
Xstruct map_seg *mseg;
Xstruct player_seg *pseg;
X
Xint map_size, player_size;
X
Xstruct monster_tbl *m_table;
X
Xint n_monster;
X
Xstruct note_tbl *note_table;
X
Xint n_notes;
X
X
Xload_pseg(fp)
XFILE *fp;
X{
X	char lbuf[128];
X	int len, i, seg_id, n_items;
X
X	if(fgets(lbuf, 128, fp) == NULL) {
X		fprintf(stderr, READERROR, progname, "item file", 
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	n_items = atoi(lbuf);
X
X	if(n_items < 1) {
X		fprintf(stderr, FORMERROR, progname, "item file");
X		exit(1);
X	}
X
X	/* create and map in the player segment */
X
X	player_size = sizeof(struct player_seg) + 
X		((n_items - 1) * sizeof(struct item));
X
X	seg_id = shmget(playerkey, player_size, IPC_CREAT | 0744);
X
X	if(seg_id == -1) {
X		fprintf(stderr, CANTERR, progname, "create player segment",
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	pseg = (struct player_seg *) shmat(seg_id, (char *)0, 0);
X
X	pseg->in_trader = -1;
X	pseg->item_sem = 0;
X	pseg->player_sem = 0;
X	pseg->item_count = n_items;
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		pseg->p[i].playernum = -1;
X
X	for(i = 0; i < n_items; i++) {
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"item file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		strncpy(pseg->itm[i].name, lbuf, INAMELEN - 1);
X		pseg->itm[i].name[INAMELEN - 1] = '\0';
X		rmnl(pseg->itm[i].name);
X
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"item file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		parse_item(&(pseg->itm[i]), lbuf);
X	}
X
X	/* detach segment */
X
X	shmdt((char *)pseg);
X}
X
X
Xload_notes(fp)
XFILE *fp;
X{
X	char lbuf[128];
X	int len, i;
X
X	/* allocate and load the note table */
X
X	if(fgets(lbuf, 128, fp) == NULL) {
X		fprintf(stderr, READERROR, progname, "note file", 
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	n_notes = atoi(lbuf);
X
X	/* if n_notes < 1, make up a note. */
X
X	if(n_notes < 1) {
X		n_notes = 1;
X		note_table = (struct note_tbl *)
X			malloc(sizeof(struct note_tbl));
X		note_table[0].text[0] = '\0';
X	}
X
X	note_table = (struct note_tbl *)
X		malloc(sizeof(struct note_tbl) * n_notes);
X
X	for(i = 0; i < n_notes; i++) {
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"note file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		strncpy(note_table[i].text, lbuf, 34);
X		note_table[i].text[34] = '\0';
X		rmnl(note_table[i].text);
X	}
X}
X
X
Xload_monsters(fp)
XFILE *fp;
X{
X	char lbuf[128];
X	int len, i;
X
X	/* allocate and load the monster table */
X
X	if(fgets(lbuf, 128, fp) == NULL) {
X		fprintf(stderr, READERROR, progname, "monster file", 
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	n_monster = atoi(lbuf);
X
X	if(n_monster < 1) {
X		fprintf(stderr, FORMERROR, progname, "monster file");
X		exit(1);
X	}
X
X	m_table = (struct monster_tbl *)
X		malloc(sizeof(struct monster_tbl) * n_monster);
X
X	if(m_table == NULL) {
X		fprintf(stderr, CANTERR, progname, 
X			"malloc() m_table", sys_errlist[errno]);
X		exit(1);
X	}
X
X	for(i = 0; i < n_monster; i++) {
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"monster file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		strncpy(m_table[i].name, lbuf, MNAMELEN - 1);
X		m_table[i].name[MNAMELEN - 1] = '\0';
X		rmnl(m_table[i].name);
X
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"monster file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		sscanf(lbuf, MREADF, 
X			&(m_table[i].m_sym),
X			&(m_table[i].loc.sector),
X			&(m_table[i].loc.x),
X			&(m_table[i].loc.y),
X			&(m_table[i].max_hp),
X			&(m_table[i].hp),
X			&(m_table[i].mv),
X			&(m_table[i].attack),
X			&(m_table[i].fight),
X			&(m_table[i].max_dam),
X			&(m_table[i].level),
X			&(m_table[i].danger),
X			&(m_table[i].iq));
X
X		m_table[i].mv_used = 0;
X	}
X}
X
X
Xplace_monsters()
X{
X	int i;
X	int sector, x, y;
X
X	for(i = 0; i < n_monster; i++) {
X		sector = m_table[i].loc.sector;
X		if(sector >= 0) {
X			if(sector >= mseg->max_areas) {
X				m_table[i].loc.sector = LOC_NONESUCH;
X			} else {
X				x = m_table[i].loc.x;
X				y = m_table[i].loc.y;
X				m_table[i].loc.under = 
X					mseg->m[sector].map[y][x];
X				mseg->m[sector].map[y][x] = m_table[i].m_sym;
X			}
X		}
X	}
X}
X
X
Xload_mseg(fp)
XFILE *fp;
X{
X	char lbuf[128];
X	int i, j, k;
X	int seg_id, n_maps;
X
X	if(fgets(lbuf, 128, fp) == NULL) {
X		fprintf(stderr, READERROR, progname, "map file", 
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	n_maps = atoi(lbuf);
X
X	if(n_maps < 1) {
X		fprintf(stderr, FORMERROR, progname, "map file");
X		exit(1);
X	}
X
X	/* create and map in the map segment */
X
X	map_size = sizeof(struct map_seg) + 
X		((n_maps - 1) * sizeof(struct area));
X
X	seg_id = shmget(mapkey, map_size, IPC_CREAT | 0744);
X
X	if(seg_id == -1) {
X		fprintf(stderr, CANTERR, progname, "create map segment",
X			sys_errlist[errno]);
X		exit(1);
X	}
X
X	mseg = (struct map_seg *) shmat(seg_id, (char *)0, 0);
X
X	mseg->map_sem = 0;
X	mseg->dayclock = 0;
X	mseg->save_map = 0;
X	mseg->max_areas = n_maps;
X
X	for(i = 0; i < n_maps; i++) {
X		for(j = 0; j < MAPROWS; j++) {
X			if(fgets(lbuf, 128, fp) == NULL) {
X				fprintf(stderr, READERROR, progname, 
X					"map file", sys_errlist[errno]);
X				exit(1);
X			}
X
X			if(strlen(lbuf) < MAPCOLS) {
X				fprintf(stderr, FORMERROR, progname, 
X					"map file");
X				exit(1);
X			}
X
X			for(k = 0; k < MAPCOLS; k++)
X				mseg->m[i].map[j][k] = lbuf[k];
X		}
X
X		if(fgets(mseg->m[i].title, 39, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"map file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		rmnl(mseg->m[i].title);
X
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"map file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		sscanf(lbuf, MAPFMTR,
X			&(mseg->m[i].links[L_NORTH]),
X			&(mseg->m[i].links[L_SOUTH]),
X			&(mseg->m[i].links[L_EAST]),
X			&(mseg->m[i].links[L_WEST]),
X			&(mseg->m[i].links[L_UP]),
X			&(mseg->m[i].links[L_DOWN]),
X			&(mseg->m[i].links[L_GATE+0]),
X			&(mseg->m[i].links[L_GATE+1]),
X			&(mseg->m[i].links[L_GATE+2]),
X			&(mseg->m[i].links[L_GATE+3]),
X			&(mseg->m[i].links[L_GATE+4]),
X			&(mseg->m[i].links[L_GATE+5]),
X			&(mseg->m[i].links[L_GATE+6]));
X
X		if(fgets(lbuf, 128, fp) == NULL) {
X			fprintf(stderr, READERROR, progname, 
X				"map file", sys_errlist[errno]);
X			exit(1);
X		}
X
X		sscanf(lbuf, "%hd %hd %hd '%c' G%hd",
X			&(mseg->m[i].level),
X			&(mseg->m[i].light),
X			&(mseg->m[i].jump_inhibit),
X			&(mseg->m[i].border_ch),
X			&(mseg->m[i].god_limit));
X
X	}
X
X	/* detach segment */
X
X	shmdt((char *)mseg);
X}
X
X
Xint is_players()
X{
X	int i;
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(pseg->p[i].playernum >= 0)
X			return 1;
X
X	return 0;
X}
X
X
Xlift_monsters()
X{
X	int i;
X	int sector, x, y;
X
X	for(i = 0; i < n_monster; i++) 
X		if(m_table[i].loc.sector >= 0) {
X			sector = m_table[i].loc.sector;
X			x = m_table[i].loc.x;
X			y = m_table[i].loc.y;
X			mseg->m[sector].map[y][x] = 
X				m_table[i].loc.under;
X		}
X}
X
X
Xlift_items()
X{
X	int i;
X	int sector, x, y;
X
X	for(i = pseg->item_count - 1; i >= 0; i--)
X		if(pseg->itm[i].loc.sector >= 0) {
X			sector = pseg->itm[i].loc.sector;
X			x = pseg->itm[i].loc.x;
X			y = pseg->itm[i].loc.y;
X			mseg->m[sector].map[y][x] = 
X				pseg->itm[i].loc.under;
X		}
X}
X
X
Xwrite_row(fp, sector, row)
XFILE *fp;
Xint sector, row;
X{
X	int i, ch;
X
X	for(i = 0; i < MAPCOLS; i++) {
X		ch = mseg->m[sector].map[row][i];
X
X		/* kludge here... should really find out why     */
X		/* player codes occasionally get saved with map. */
X
X		if(is_player(ch))
X			ch = mseg->m[sector].map[row][i] = ' ';
X
X		putc(ch, fp);
X	}
X
X	putc('.', fp);
X
X	if(row == 0)
X		fprintf(fp, "  %d\n", sector);
X	else
X		putc('\n', fp);
X}
X
X
Xsavemap()
X{
X	FILE *fp;
X	int i, j, k;
X
X	if(mseg->save_map == 0 || is_players())
X		return;
X
X	lift_monsters();
X	lift_items();
X
X	mseg->save_map = 0;
X
X	if((fp = saveopen(MAP, "w")) != NULL) {
X		fprintf(fp, "%d\n", mseg->max_areas);
X
X		for(i = 0; i < mseg->max_areas; i++) {
X			for(j = 0; j < MAPROWS; j++)
X				write_row(fp, i, j);
X			fprintf(fp, "%s\n", mseg->m[i].title);
X			fprintf(fp, MAPFMTW,
X				mseg->m[i].links[L_NORTH],
X				mseg->m[i].links[L_SOUTH],
X				mseg->m[i].links[L_EAST],
X				mseg->m[i].links[L_WEST],
X				mseg->m[i].links[L_UP],
X				mseg->m[i].links[L_DOWN],
X				mseg->m[i].links[L_GATE+0],
X				mseg->m[i].links[L_GATE+1],
X				mseg->m[i].links[L_GATE+2],
X				mseg->m[i].links[L_GATE+3],
X				mseg->m[i].links[L_GATE+4],
X				mseg->m[i].links[L_GATE+5],
X				mseg->m[i].links[L_GATE+6]);
X			fprintf(fp, "%d %d %d '%c' G%d\n",
X				mseg->m[i].level,
X				mseg->m[i].light,
X				mseg->m[i].jump_inhibit,
X				mseg->m[i].border_ch,
X				mseg->m[i].god_limit);
X		}
X
X		fclose(fp);
X	} else
X		fprintf(stderr, CANTERR, progname, "write map file",
X			sys_errlist[errno]);
X
X	place_items();
X	place_monsters();
X}
X
X
Xseg_attach()
X{
X	int seg_id;
X
X	seg_id = shmget(playerkey, player_size, 0744);
X	pseg = (struct player_seg *) shmat(seg_id, (char *)0, 0);
X
X	seg_id = shmget(mapkey, map_size, 0744);
X	mseg = (struct map_seg *) shmat(seg_id, (char *)0, 0);
X}
X
X
Xvoid shutdown()
X{
X	int i, seg_id;
X	int sector, x, y;
X	FILE *stat_fp;
X
X	fputs("Shutdown called...\n", stderr);
X
X	unlink(LOCKFILE);
X
X	msgctl(dqid, IPC_RMID, NULL);
X
X	for(i = 0; i < MAX_PLAYERS; i++) {
X		if(pseg->p[i].playernum != -1) {
X			sector = pseg->p[i].loc.sector;
X			x = pseg->p[i].loc.x;
X			y = pseg->p[i].loc.y;
X			if(sector >= 0) {
X				mseg->m[sector].map[y][x] = 
X					pseg->p[i].loc.under;
X			}
X			pseg->p[i].loc.sector = LOC_HOME;
X			pseg->p[i].loc.x = sector;
X			saveplayer(i);
X			pseg->p[i].playernum = -1;
X		}
X	}
X
X	semctl(pseg->sid, 0, IPC_RMID, NULL);
X
X	savegame();
X
X	mseg->save_map = 1;
X	savemap();
X
X	seg_id = shmget(mapkey, map_size, 0744);
X	shmdt((char *)mseg);
X	shmctl(seg_id, IPC_RMID, NULL);
X
X	seg_id = shmget(playerkey, player_size, 0744);
X	shmdt((char *)pseg);
X	shmctl(seg_id, IPC_RMID, NULL);
X
X	kill(pid, SIGHUP);
X
X	/* write stats */
X
X	if((stat_fp = fopen(STATFILE, "a")) != NULL) {
X		fprintf(stat_fp, "PMpS: %ld\n", max_mps);
X		fclose(stat_fp);
X	}
X
X	exit(0);
X}
X
X
Xsavegame()
X{
X	int i;
X	FILE *fp;
X
X	fputs("writing game save...\n", stderr);
X
X	if((fp = saveopen(ITEMS, "w")) == NULL) {
X		fprintf(stderr, CANTERR, progname, 
X			"write item file", sys_errlist[errno]);
X	} else {
X		fprintf(fp, "%d\n", pseg->item_count);
X		
X		for(i = 0; i < pseg->item_count; i++)
X			write_item(&(pseg->itm[i]), fp);
X
X		fclose(fp);
X	}
X
X	if((fp = saveopen(MONSTERS, "w")) == NULL) {
X		fprintf(stderr, CANTERR, progname, 
X			"write monster file", sys_errlist[errno]);
X	} else {
X		fprintf(fp, "%d\n", n_monster);
X
X		for(i = 0; i < n_monster; i++) {
X			fprintf(fp, MWRITEF,
X				m_table[i].name,
X				m_table[i].m_sym,
X				m_table[i].loc.sector,
X				m_table[i].loc.x,
X				m_table[i].loc.y,
X				m_table[i].max_hp,
X				m_table[i].hp,
X				m_table[i].mv,
X				m_table[i].attack,
X				m_table[i].fight,
X				m_table[i].max_dam,
X				m_table[i].level,
X				m_table[i].danger,
X				m_table[i].iq);
X		}
X
X		fclose(fp);
X	}
X
X	if((fp = saveopen(NOTES, "w")) == NULL) {
X		fprintf(stderr, CANTERR, progname, 
X			"write note file", sys_errlist[errno]);
X	} else {
X		fprintf(fp, "%d\n", n_notes);
X
X		for(i = 0; i < n_notes; i++)
X			fprintf(fp, "%s\n", note_table[i].text);
X
X		fclose(fp);
X	}
X}
X
X
Xwrite_item(it, fp)
Xstruct item *it;
XFILE *fp;
X{
X	fprintf(fp, "%s\n[%d] %d, %d <%c%c, %d, %d> %d:%d %ld $%d (%hd) C%d\n",
X		it->name, it->loc.sector, it->loc.x, it->loc.y,
X		it->type, it->symbol, it->effect, it->range,
X		it->max_uses, it->rem_uses,
X		it->decay_cnt, it->value, 
X		it->mod_count, (int)it->curse);
X}
X
X
Xparse_item(it, buf)
Xstruct item *it;
Xchar *buf;
X{
X	int curse_t;
X
X	it->type = ' ';
X	it->symbol = ' ';
X	it->effect = -1;
X	it->range = 0;
X	it->curse = 0;
X	it->max_uses = 0;
X	it->rem_uses = 0;
X	it->loc.sector = LOC_NONESUCH;
X	it->loc.x = 0;
X	it->loc.y = 0;
X	it->decay_cnt = 0;
X	it->mod_count = 0;
X	it->value = 1;
X
X	sscanf(buf, "[%d] %d, %d <%c%c, %d, %d> %d:%d %ld $%d (%hd) C%d",
X		&(it->loc.sector), &(it->loc.x), &(it->loc.y),
X		&(it->type), &(it->symbol), &(it->effect), &(it->range),
X		&(it->max_uses), &(it->rem_uses),
X		&(it->decay_cnt), &(it->value), 
X		&(it->mod_count), &curse_t);
X
X	it->curse = curse_t;
X}
X
X
Xplace_items()
X{
X	int i, sector, x, y;
X
X	for(i = 0; i < pseg->item_count; i++)
X		if(pseg->itm[i].loc.sector >= 0) {
X			if(pseg->itm[i].loc.sector >= mseg->max_areas) {
X				pseg->itm[i].loc.sector = LOC_NONESUCH;
X			} else {
X				sector = pseg->itm[i].loc.sector;
X				x = pseg->itm[i].loc.x;
X				y = pseg->itm[i].loc.y;
X				pseg->itm[i].loc.under = 
X					mseg->m[sector].map[y][x];
X				mseg->m[sector].map[y][x] = 
X					pseg->itm[i].symbol;
X			}
X		}
X}
X
X
Xrmnl(s)
Xchar *s;
X{
X	for(; *s; s++)
X		if(*s == '\n')
X			*s = '\0';
X}
X
X
X/* end of file */
END_OF_FILE
if test 13327 -ne `wc -c <'seg.c'`; then
    echo shar: \"'seg.c'\" unpacked with wrong size!
fi
# end of 'seg.c'
fi
if test -f 'show.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'show.c'\"
else
echo shar: Extracting \"'show.c'\" \(10550 characters\)
sed "s/^X//" >'show.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- show.c display procedures
X	
X	MDG is Copyright 1990 John C. Gonnerman
X	This program is subject to the general MDG 
X	copyright statement (see enclosed file, Copyright).
X*/
X
X
Xstatic char *sccsvers = "@(#) show.c\t\t(1.4)\tcreated 1/2/91";
X
X#include <curses.h>
X#include <ctype.h>
X
X#include "setup.h"
X#include "struct.h"
X#include "show.h"
X
Xextern struct player_seg *pseg;
Xextern struct map_seg *mseg;
Xextern struct game_msg *gseg;
X
Xextern int playernum, player_indx;
X
Xchar *homestr   = ". HOME HOME HOME HOME HOME HOME HOME .";
Xchar *traderstr = ". TRADER TRADER TRADER TRADER TRADER .";
X
X
Xshow_gmsg()
X{
X	move(PARK_Y, PARK_X + 2);
X	clrtoeol();
X	move(PARK_Y, PARK_X + 2);
X	addstr(gseg->buf);
X	park_csr();
X}
X
X
Xshow_dark()
X{
X	int row;
X
X	for(row = 0; row <= MAPROWS + 2; row++) {
X		move(row, 1);
X		addstr("                                         ");
X	}
X
X	move(6, 1);
X	addstr("            << It's DARK! >>             ");
X}
X
X
Xshow_trader()
X{
X	short i;
X	int t_item_indx;
X
X	move(0, 1);
X	addstr(" -------------------------------------- ");
X
X	for(i = 1; i <= 10; i++) {
X		move(i, 1);
X		addstr("|                                      |");
X	}
X
X	move(11, 1);
X	addstr(" -------------------------------------- ");
X
X	move(12, 1);
X	addstr("Trader's Store -- Options:              ");
X
X	move(13, 1);
X	addstr("b)uy item   v)alue of item  s)ell item  ");
X
X	move(14, 1);
X	addstr("n)ext page  p)revious page  l)eave      ");
X
X	move(15, 1);
X	addstr("                                        ");
X
X	for(i = 0; i < 10; i++) 
X		if((t_item_indx = trader_item(i)) >= 0) {
X			move(i + 1, 3);
X			printw("%d - %-20.20s  $%d", i, 
X				pseg->itm[t_item_indx].name,
X				pseg->itm[t_item_indx].value * 3 / 2);
X		}
X}
X
X
Xshow_map()
X{
X	int x, y, sector, o_sector;
X	char buf[35];
X	void game_over();
X
X	if((sector = pseg->p[player_indx].loc.sector) == LOC_NONESUCH
X	|| sector == LOC_HOME) {
X		game_over();
X		return;
X	}
X
X	if(sector == LOC_TRADER)
X		return;
X
X	if(!is_light(sector)) {
X		show_dark();
X		return;
X	}
X
X	move(0, 1);   addch(' ');
X	move(14, 1);  addch(' ');
X	move(0, 40);  addch(' ');
X	move(14, 40); addch(' ');
X
X	for(x = 0; x < MAPCOLS; x++) {
X		o_sector = mseg->m[sector].links[L_NORTH];
X
X		switch(o_sector) {
X		case LOC_HOME :
X			move(0, x + 2);
X			addch((int)homestr[x]);
X			break;
X		case LOC_PLAYER :
X		case LOC_NONESUCH :
X			move(0, x + 2);
X			mapcode((int)mseg->m[sector].border_ch, sector);
X			break;
X		case LOC_TRADER :
X			move(0, x + 2);
X			addch((int)traderstr[x]);
X			break;
X		default :
X			move(0, x + 2);
X			mapcode((int)mseg->m[o_sector].map[MAPROWS - 1][x],
X				o_sector);
X			break;
X		}
X	}
X
X	for(y = 0; y < MAPROWS; y++) {
X		o_sector = mseg->m[sector].links[L_WEST];
X
X		switch(o_sector) {
X		case LOC_HOME :
X			move(y + 1, 1);
X			addch((int)homestr[y]);
X			break;
X		case LOC_PLAYER :
X		case LOC_NONESUCH :
X			move(y + 1, 1);
X			mapcode((int)mseg->m[sector].border_ch, sector);
X			break;
X		case LOC_TRADER :
X			move(y + 1, 1);
X			addch((int)traderstr[y]);
X			break;
X		default :
X			move(y + 1, 1);
X			mapcode((int)mseg->m[o_sector].map[y][MAPCOLS - 1],
X				o_sector);
X			break;
X		}
X
X		for(x = 0; x < MAPCOLS; x++) {
X			move(y + 1, x + 2);
X			mapcode((int)mseg->m[sector].map[y][x],
X				sector);
X		}
X
X		o_sector = mseg->m[sector].links[L_EAST];
X
X		switch(o_sector) {
X		case LOC_HOME :
X			move(y + 1, MAPCOLS + 2);
X			addch((int)homestr[y]);
X			break;
X		case LOC_PLAYER :
X		case LOC_NONESUCH :
X			move(y + 1, MAPCOLS + 2);
X			mapcode((int)mseg->m[sector].border_ch, sector);
X			break;
X		case LOC_TRADER :
X			move(y + 1, MAPCOLS + 2);
X			addch((int)traderstr[y]);
X			break;
X		default :
X			move(y + 1, MAPCOLS + 2);
X			mapcode((int)mseg->m[o_sector].map[y][0],
X				o_sector);
X			break;
X		}
X	}
X
X	for(x = 0; x < MAPCOLS; x++) {
X		o_sector = mseg->m[sector].links[L_SOUTH];
X
X		switch(o_sector) {
X		case LOC_HOME :
X			move(MAPROWS + 1, x + 2);
X			addch((int)homestr[x]);
X			break;
X		case LOC_PLAYER :
X		case LOC_NONESUCH :
X			move(MAPROWS + 1, x + 2);
X			mapcode((int)mseg->m[sector].border_ch, sector);
X			break;
X		case LOC_TRADER :
X			move(MAPROWS + 1, x + 2);
X			addch((int)traderstr[x]);
X			break;
X		default :
X			move(MAPROWS + 1, x + 2);
X			mapcode((int)mseg->m[o_sector].map[0][x],
X				o_sector);
X			break;
X		}
X	}
X
X	move(MAPROWS + 2, 1);
X	clrtoeol();
X	move(MAPROWS + 2, 1);
X	addstr(mseg->m[sector].title);
X
X	park_csr();
X}
X
X
Xint is_light(sector)
Xint sector;
X{
X	int i;
X
X	if(sector == 0)
X		return 1;
X
X	if(mseg->m[sector].light == 2)
X		return 1;
X
X	if(mseg->m[sector].light == 1 && timeofday())
X		return 1;
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(pseg->p[i].playernum >= 0
X		&& pseg->p[i].loc.sector == sector
X		&& pseg->p[i].light > 0)
X			return 1;
X
X	return 0;
X}
X
X
Xmapcode(ch, sector)
Xint ch, sector;
X{
X	if(sector < 0) {
X		addch((int)'#');
X	} else if(!is_light(sector)
X	&& pseg->p[player_indx].light < 1) {
X		/* it's dark */
X		addch((int)'#');
X	} else if(pseg->p[player_indx].detect)
X		switch(ch) {
X		case '^' : /* pit */
X		case '0' : /* 0-9 are traps */
X		case '1' :
X		case '2' :
X		case '3' :
X		case '4' :
X		case '5' :
X		case '6' :
X		case '7' :
X		case '8' :
X		case '9' :
X			addch((int)'^');
X			break;
X		case '+' :
X		case '`' :
X			addch((int)' ');
X			break;
X		case '=' :
X		case '{' :
X		case '}' :
X		case ':' :
X		case ';' :
X			if(pseg->p[player_indx].detect >= DETECT_L3)
X				addch((int)'=');
X			else
X				addch((int)' ');
X			break;
X		case '-' :
X			if(pseg->p[player_indx].detect >= DETECT_L3)
X				addch((int)'=');
X			else
X				addch((int)'~');
X			break;
X		case '|' :
X			if(pseg->p[player_indx].detect >= DETECT_L3)
X				addch((int)'=');
X			else
X				addch((int)':');
X			break;
X		case '@' :
X			addch((int)'#');
X			break;
X		case 20 :
X			addch((int)'+');
X			break;
X		case 21 :
X			addch((int)'*');
X			break;
X		case HIDDEN :
X			if(pseg->p[player_indx].detect >= DETECT_L2)
X				addch((int)OBJECT);
X			else
X				addch((int)' ');
X			break;
X		default :
X			if(ch >= 11 && ch <= 19)
X				addch(ch - 10 + '0');
X			else if(ch >= 1 && ch <= 9)
X				addch(ch + '0');
X			else
X				addch(ch);
X			break;
X		}
X	else
X		switch(ch) {
X		case '.' : /* monster limit */
X		case '0' : /* 0-9 are traps */
X		case '1' :
X		case '2' :
X		case '3' :
X		case '4' : /* pit */
X		case '@' :
X		case '=' :
X		case '{' :
X		case '}' :
X		case ':' :
X		case ';' :
X		case '&' :
X		case HIDDEN :
X			addch((int)' ');
X			break;
X		case '^' : /* air */
X		case ',' : /* false air */
X		case '|' : /* flying gate */
X			addch((int)':');
X			break;
X		case '5' :
X		case '6' :
X			addch((int)'%');
X			break;
X		case '7' :
X		case '8' :
X		case '+' :
X			addch((int)'#');
X			break;
X		case 20 :
X			addch((int)'+');
X			break;
X		case 21 :
X			addch((int)'*');
X			break;
X		case '9' : /* acid trap */
X		case '`' : /* shallow water */
X		case '-' : /* watergate :-) */
X			addch((int)'~');
X			break;
X		default :
X			if(ch >= 11 && ch <= 19) {
X				if(ch - 11 == player_indx)
X					addch(ch - 10 + '0');
X				else
X					addch(' ');
X			} else if(ch >= 1 && ch <= 9)
X				addch(ch + '0');
X			else
X				addch(ch);
X			break;
X		}
X}
X
X
Xshow_player()
X{
X	int indx, temp, sector;
X	char buf[35];
X	void game_over();
X
X	if((sector = pseg->p[player_indx].loc.sector) == LOC_NONESUCH
X	|| sector == LOC_HOME) {
X		game_over();
X		return;
X	}
X
X	for(indx = 0; indx < MAX_PLAYERS; indx++) {
X		move(PSTART + (indx / 3), 25 * (indx % 3) + 1);
X		show_a_player(indx);
X	}
X
X	temp = pseg->p[player_indx].dmsg_loc;
X
X	move(10, 44);
X	printw("%c%s", (temp == 0 ? '>' : ' '), 
X		pseg->p[player_indx].dmsg[0]);
X	clrtoeol();
X
X	move(11, 44);
X	printw("%c%s", (temp == 1 ? '>' : ' '), 
X		pseg->p[player_indx].dmsg[1]);
X	clrtoeol();
X
X	move(12, 44);
X	sprintf(buf, "HP: %hd (%hd)    ",
X		pseg->p[player_indx].max_hp,
X		pseg->p[player_indx].hitpoints);
X	addstr(buf);
X
X	move(12, 62);
X	temp = pseg->armor[player_indx] != -1 
X		? abs(pseg->itm[pseg->armor[player_indx]].effect)
X		: 0;
X	temp += pseg->shield[player_indx] != -1 
X		? abs(pseg->itm[pseg->shield[player_indx]].effect)
X		: 0;
X	sprintf(buf, "Armor: %d ", temp);
X	addstr(buf);
X
X	temp = pseg->p[player_indx].ma_count > 0 
X		? pseg->p[player_indx].m_armor 
X		: 0;
X	if(temp) 
X		sprintf(buf, "+ %d ", temp);
X	else
X		strcpy(buf, "     ");
X	addstr(buf);
X
X	move(13, 44);
X	sprintf(buf, "Magic: %hd (%hd)  ",
X		pseg->p[player_indx].max_mp,
X		pseg->p[player_indx].magicpts);
X	addstr(buf);
X
X	move(13, 62);
X	clrtoeol();
X	if(pseg->p[player_indx].createpts > 0)
X		printw("CP: %hd", pseg->p[player_indx].createpts);
X
X	move(1, 44);
X	sprintf(buf, "0 - Gold: %ld  %c", 
X		pseg->p[player_indx].gold,
X		(pseg->p[player_indx].gold_hidden ? '*' : ' '));
X	clrtoeol();
X	addstr(buf);
X
X	move(14, 44);
X	sprintf(buf, "Extra Lives: %-7d ", pseg->p[player_indx].lives);
X	addstr(buf);
X
X	park_csr();
X}
X
X
Xshow_a_player(indx)
Xint indx;
X{
X	if(pseg->p[indx].playernum == -1
X	|| pseg->p[indx].invis > 0) {
X		addstr("                         ");
X		return;
X	}
X
X	if(pseg->p[indx].loc.sector != pseg->p[player_indx].loc.sector
X	&& pseg->p[player_indx].user_spell < 1) {
X		addstr("                         ");
X		return;
X	}
X
X	addch('1' + indx);
X
X	if(indx == player_indx)
X		addstr(" = ");
X	else if(pseg->p[player_indx].partners[indx])
X		addstr(" + ");
X	else
X		addstr(" - ");
X
X	addstr(pseg->p[indx].name);
X}
X
X
Xshow_items()
X{
X	int i, i_indx;
X	char showbuf[40], ready_flag, hidden_flag;
X
X	move(0, 44);
X	addstr("-+-   - Items -  -+-");
X
X	for(i = 0; i < PMAX_ITEMS; i++) {
X
X		move(i + 2, 44);
X		clrtoeol();
X		i_indx = pseg->p[player_indx].items[i];
X
X		if(i_indx != -1) {
X			move(i + 2, 44);
X			ready_flag = ' ';
X			hidden_flag = ' ';
X
X			if(pseg->itm[i_indx].type == ARMOR 
X			&& pseg->armor[player_indx] == i_indx) 
X				ready_flag = ARMOR;
X
X			if(pseg->itm[i_indx].type == SHIELD 
X			&& pseg->shield[player_indx] == i_indx) 
X				ready_flag = SHIELD;
X
X			if(pseg->itm[i_indx].type == WEAPON 
X			&& pseg->weapon[player_indx] == i_indx) 
X				ready_flag = WEAPON;
X
X			if(pseg->itm[i_indx].symbol == HIDDEN)
X				hidden_flag = '*';
X
X			sprintf(showbuf, "%d - %s %c%c", 
X				i + 1, pseg->itm[i_indx].name, 
X				ready_flag, hidden_flag);
X
X			addstr(showbuf);
X		}
X	}
X
X	park_csr();
X}
X
X
Xpark_csr()
X{
X	move(PARK_Y, PARK_X);
X}
X
X
Xshow_modes()
X{
X	char buf[40];
X
X	strcpy(buf, "Modes: ");
X
X	if(pseg->p[player_indx].light)
X		strcat(buf, "L ");
X		
X	if(pseg->p[player_indx].detect >= DETECT_L3)
X		strcat(buf, "DDD ");
X	else if(pseg->p[player_indx].detect >= DETECT_L2)
X		strcat(buf, "DD ");
X	else if(pseg->p[player_indx].detect)
X		strcat(buf, "D ");
X		
X	if(pseg->p[player_indx].invis)
X		strcat(buf, "I ");
X		
X	if(pseg->p[player_indx].blocked)
X		strcat(buf, "B ");
X
X	if(pseg->p[player_indx].knight)
X		strcat(buf, "K ");
X
X	move(15, 44);
X	addstr(buf);
X	clrtoeol();
X
X	park_csr();
X}
X
X
X/* end of file. */
END_OF_FILE
if test 10550 -ne `wc -c <'show.c'`; then
    echo shar: \"'show.c'\" unpacked with wrong size!
fi
# end of 'show.c'
fi
if test -f 'struct.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'struct.h'\"
else
echo shar: Extracting \"'struct.h'\" \(414 characters\)
sed "s/^X//" >'struct.h' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- master structure include file
X	
X	MDG is Copyright 1990 John C. Gonnerman
X	This file is subject to the general MDG 
X	copyright statement (see enclosed file, Copyright).
X
X	SCCSID @(#) struct.h (1.1) created 12/25/90
X*/
X
X
X#include "defstruct.h"
X
X#include "msgstruct.h"
X#include "genstruct.h"
X
X#include "mapstruct.h"
X#include "plrstruct.h"
X#include "monstruct.h"
X
X
X/* end of file. */
END_OF_FILE
if test 414 -ne `wc -c <'struct.h'`; then
    echo shar: \"'struct.h'\" unpacked with wrong size!
fi
# end of 'struct.h'
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0