[comp.sources.games] v12i039: mdg - multiuser dungeon game, Part03/06

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

Submitted-by: jcg@tree.uucp (Chris Gonnerman)
Posting-number: Volume 12, Issue 39
Archive-name: mdg/Part03
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 3 (of 6)."
# Contents:  Copyright combat.c input.c magic.c players.c
# Wrapped by billr@saab on Tue Feb 19 14:49:42 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Copyright' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Copyright'\"
else
echo shar: Extracting \"'Copyright'\" \(1226 characters\)
sed "s/^X//" >'Copyright' <<'END_OF_FILE'
X
XCOPYRIGHT for MDG (Multiuser Dungeon Game)
X
X@(#) MDG Multiuser Dungeon Game is Copyright 1990 John C. Gonnerman.  
X
XPermission is granted to use, modify, or distribute this code, limited as
Xfollows:
X
XYou may not distribute this program as part of any package over which you claim
Xa distribution right, except if that right is limited to components of the
Xpackage which you own or for which the distribution right has been explicitly
Xassigned to you, and not over the package as a collection.
X
XYou may not make money from sale of this code.
X
XYou may not create, from this program, any derivative work over which you claim
Xa distribution right.
X
XYou may use this program, and any derivative works that you create, internally 
Xwithin your own organization free of charge.  You may distribute such derivative
Xworks outside your organization provided you indicate that it is a derivative
Xwork, and not the original code.
X
X
XDISCLAIMER
X
XThe original author makes no claims as to the usability, suitability,
Xeffectiveness, or efficiency of this program.  You, as the user, accept all
Xresponsibility and risk for this program's behavior.  The original author is
Xnot responsible in any way if this program causes damages of any sort.
X
END_OF_FILE
if test 1226 -ne `wc -c <'Copyright'`; then
    echo shar: \"'Copyright'\" unpacked with wrong size!
fi
# end of 'Copyright'
fi
if test -f 'combat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'combat.c'\"
else
echo shar: Extracting \"'combat.c'\" \(14990 characters\)
sed "s/^X//" >'combat.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- combat.c battle handlers
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 = "@(#) combat.c\t(1.5)\tcreated 1/13/91";
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#include "combat.h"
X
Xextern struct map_seg *mseg;
Xextern struct player_seg *pseg;
X
Xextern int dqid, map_size, player_size;
X
Xextern struct monster_tbl *m_table;
X
Xextern int n_monster;
X
X
Xattack(p_indx, dest_a, dest_x, dest_y)
Xint p_indx, dest_a, dest_x, dest_y;
X{
X	int i, attacker_indx;
X
X	attacker_indx = p_indx;
X
X	if(pseg->p[attacker_indx].attacks == 0)
X		return;
X
X	pseg->p[attacker_indx].attacks--;
X
X	if(is_player(mseg->m[dest_a].map[dest_y][dest_x])) {
X		for(i = 0; i < MAX_PLAYERS; i++)
X			if(pseg->p[i].loc.sector == dest_a 
X			&& pseg->p[i].loc.x == dest_x 
X			&& pseg->p[i].loc.y == dest_y)
X				pattackp(attacker_indx, i);
X	} else {
X		for(i = 0; i < n_monster; i++)
X			if(m_table[i].loc.sector == dest_a 
X			&& m_table[i].loc.x == dest_x 
X			&& m_table[i].loc.y == dest_y)
X				pattackm(attacker_indx, i);
X		pace_monsters();
X	}
X}
X
X
Xmattack(m_indx, dest_a, dest_x, dest_y)
Xint m_indx, dest_a, dest_x, dest_y;
X{
X	int i;
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(pseg->p[i].loc.sector == dest_a 
X		&& pseg->p[i].loc.x == dest_x 
X		&& pseg->p[i].loc.y == dest_y)
X			switch(m_table[m_indx].attack) {
X			case ATT_BREATH :
X				/* not done yet. */
X			case ATT_HITS :
X				mattackp(m_indx, i);
X				break;
X			case ATT_STEALS :
X				mstealp(m_indx, i);
X				break;
X			case ATT_DRAINS :
X				mdrainp(m_indx, i);
X				break;
X			case ATT_DRAINMP :
X				mdrainmp(m_indx, i);
X				break;
X			case ATT_DRAINHP :
X				mdrainhp(m_indx, i);
X				break;
X			case ATT_DRAINLIFE :
X				mdrainl(m_indx, i);
X				break;
X			}
X}
X
X
Xint mhit(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	int chance;
X
X	chance = 50 + m_table[a_indx].fight - pseg->p[v_indx].fighting;
X	chance = (chance + 51) / 2;
X
X	if(chance < MIN_CHANCE)
X		chance = MIN_CHANCE;
X
X	if(chance > MAX_CHANCE)
X		chance = MAX_CHANCE;
X
X	return rnd(100) <= chance;
X}
X
X
Xint ccomp(odds, a_indx)
Xint odds, a_indx;
X{
X	odds = (odds + 51) / 2;
X
X	if(pseg->p[a_indx].knight)
X		odds += 30;
X
X	if(odds < MIN_CHANCE)
X		odds = MIN_CHANCE;
X
X	if(odds < MAX_CHANCE)
X		odds = MAX_CHANCE;
X
X	return odds;
X}
X
X
Xint phitm(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	int chance, real_chance;
X
X	real_chance = 50 + pseg->p[a_indx].fighting - m_table[v_indx].fight;
X	chance = ccomp(real_chance, a_indx);
X
X	if(rnd(100) <= chance) {
X		improve_f(a_indx, real_chance);
X		return 1;
X	}
X
X	return 0;
X}
X
X
Xint phitp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	int chance, real_chance;
X
X	real_chance = 50 + pseg->p[a_indx].fighting - pseg->p[v_indx].fighting;
X	chance = ccomp(real_chance, a_indx);
X
X	if(rnd(100) <= chance) {
X		improve_f(a_indx, real_chance);
X		return 1;
X	}
X
X	return 0;
X}
X
X
Xint mdamage(a_indx)
Xint a_indx;
X{
X	return rnd(m_table[a_indx].max_dam);
X}
X
X
Xint pdamage(a_indx)
Xint a_indx;
X{
X	int wpn, eff;
X
X	wpn = pseg->weapon[a_indx];
X
X	if(wpn < 0)
X		return rnd(pseg->p[a_indx].fighting / 20);
X	else if(wpn < pseg->item_count) {
X		eff = pseg->itm[wpn].effect;
X		if(pseg->itm[wpn].curse)
X			eff = 0;
X		return rnd(eff);
X	} else {
X		fprintf(stderr, 
X			"weapon range error, pnum = %d, wpn = %d\n",
X			pseg->p[a_indx].playernum, wpn);
X		pseg->weapon[a_indx] = -1;
X	}
X
X	return 0;
X}
X
X
Xint ptakedamage(v_indx, damage)
Xint v_indx, damage;
X{
X	if(damage < 0)
X		damage = 0;
X
X	pseg->p[v_indx].hitpoints -= damage;
X
X	pseg->player_sem++;
X	tell_player(v_indx);
X
X	if(pseg->p[v_indx].hitpoints < 1) {
X		killp(v_indx);
X		return -1;
X	}
X
X	return 0;
X}
X
X
Xint pgetzapped(v_indx, damage)
Xint v_indx, damage;
X{
X	if(pseg->p[v_indx].ma_count > 0)
X		damage = dcomp(damage, pseg->p[v_indx].m_armor);
X		
X	return(ptakedamage(v_indx, damage));
X}
X
X
Xint pgethit(v_indx, damage)
Xint v_indx, damage;
X{
X	int armor, ai, si;
X
X	armor = 0;
X
X	ai = pseg->armor[v_indx];
X
X	if(ai >= 0) {
X		if(ai >= pseg->item_count) {
X			fprintf(stderr, 
X				"Armor index out of range (%d)\n", ai);
X			pseg->armor[v_indx] = -1;
X		} else if(pseg->itm[ai].curse == 0) {
X			armor += pseg->itm[ai].effect;
X		}
X	}
X
X	si = pseg->shield[v_indx];
X
X	if(si >= 0) {
X		if(si >= pseg->item_count) {
X			fprintf(stderr, 
X				"Shield index out of range (%d)\n", si);
X			pseg->shield[v_indx] = -1;
X		} else if(pseg->itm[si].curse == 0) {
X			armor += pseg->itm[si].effect;
X		}
X	}
X
X	damage -= armor;
X
X	return(pgetzapped(v_indx, damage));
X}
X
X
Xint mgethit(v_indx, damage)
Xint v_indx, damage;
X{
X	if(damage < 1)
X		damage = 1;
X
X	if(m_table[v_indx].hp > m_table[v_indx].max_hp)
X		m_table[v_indx].hp = m_table[v_indx].max_hp;
X
X	m_table[v_indx].hp -= damage;
X
X	if(m_table[v_indx].hp < 1) {
X		killm(v_indx);
X		return -1;
X	}
X
X	return 0;
X}
X
X
Xpattackp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X	int damage;
X
X	if(pseg->p[v_indx].loc.sector == 0)
X		return;
X
X	if(pseg->p[a_indx].partners[v_indx] == 1)
X		return;
X
X	visible(a_indx);
X
X	sprintf(buf, "%c attacked you!", '1' + a_indx);
X	dmsg_add(v_indx, buf);
X
X	if(!phitp(a_indx, v_indx)) {
X		if(pseg->p[a_indx].brief)
X			dmsg_add(a_indx, "You missed");
X		else
X			dmsg_add(a_indx, "You missed the player");
X		return;
X	}
X
X	damage = pdamage(a_indx);
X
X	if(pseg->p[a_indx].brief)
X		dmsg_add(a_indx, "Hit player!");
X	else {
X		dmsg_add(a_indx, "You hit the player!");
X		sprintf(buf, "Damage: %d", damage);
X		dmsg_add(a_indx, buf);
X	}
X
X	sprintf(buf, "%c HIT you!", '1' + a_indx);
X	dmsg_add(v_indx, buf);
X
X	if(pgethit(v_indx, damage) == -1) {
X		dmsg_add(a_indx, "You KILLED the player!");
X		pseg->p[a_indx].lives++;
X		pseg->player_sem++;
X		improve_h(a_indx, d_level(v_indx));
X	}
X}
X
X
Xpattackm(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X	int damage;
X
X	visible(a_indx);
X
X	if(!phitm(a_indx, v_indx)) {
X		if(pseg->p[a_indx].brief) {
X			sprintf(buf, "Missed %s", m_table[v_indx].name);
X			dmsg_add(a_indx, buf);
X		} else {
X			sprintf(buf, "You missed the %s", m_table[v_indx].name);
X			dmsg_add(a_indx, buf);
X		}
X		return;
X	}
X
X	damage = pdamage(a_indx);
X
X	if(pseg->p[a_indx].brief) {
X		sprintf(buf, "Hit %s!", m_table[v_indx].name, damage);
X		dmsg_add(a_indx, buf);
X	} else {
X		sprintf(buf, "You hit the %s!", m_table[v_indx].name, damage);
X		dmsg_add(a_indx, buf);
X		sprintf(buf, "Damage: %d", damage);
X		dmsg_add(a_indx, buf);
X	}
X
X	if(mgethit(v_indx, damage) == -1) {
X		sprintf(buf, "You KILLED the %s", m_table[v_indx].name);
X		dmsg_add(a_indx, buf);
X		improve_h(a_indx, m_table[v_indx].danger);
X	}
X}
X
X
Xmattackp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X
X	if(m_table[a_indx].att_used >= M_ATTACKS)
X		return;
X
X	m_table[a_indx].att_used++;
X
X	if(!mhit(a_indx, v_indx)) {
X		if(!pseg->p[v_indx].brief) {
X			sprintf(buf, "%s missed you!", m_table[a_indx].name);
X			dmsg_add(v_indx, buf);
X		}
X		return;
X	} 
X
X	if(!pseg->p[v_indx].brief) {
X		sprintf(buf, "%s HIT you!", m_table[a_indx].name);
X		dmsg_add(v_indx, buf);
X	}
X
X	(void)pgethit(v_indx, mdamage(a_indx));
X}
X
X
Xmdrainp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X
X	if(m_table[a_indx].att_used >= M_ATTACKS)
X		return;
X
X	m_table[a_indx].att_used++;
X
X	if(!mhit(a_indx, v_indx)) {
X		if(!pseg->p[v_indx].brief) {
X			sprintf(buf, "%s missed you!", m_table[a_indx].name);
X			dmsg_add(v_indx, buf);
X		}
X		return;
X	} 
X
X	if(!pseg->p[v_indx].brief) {
X		sprintf(buf, "%s HIT you!", m_table[a_indx].name);
X		dmsg_add(v_indx, buf);
X	}
X
X	pseg->p[v_indx].magicpts -= mdamage(a_indx);
X
X	if(pseg->p[v_indx].magicpts < 0) {
X		pseg->p[v_indx].magicpts = 0;
X		(void)pgetzapped(v_indx, mdamage(a_indx));
X	}
X}
X
X
Xmdrainl(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X
X	if(m_table[a_indx].att_used >= M_ATTACKS)
X		return;
X
X	m_table[a_indx].att_used++;
X
X	if(!mhit(a_indx, v_indx)) {
X		if(!pseg->p[v_indx].brief) {
X			sprintf(buf, "%s missed you!", m_table[a_indx].name);
X			dmsg_add(v_indx, buf);
X		}
X		return;
X	} 
X
X	if(!pseg->p[v_indx].brief) {
X		sprintf(buf, "%s HIT you!", m_table[a_indx].name);
X		dmsg_add(v_indx, buf);
X	}
X
X	pseg->p[v_indx].lives--;
X
X	if(pseg->p[v_indx].lives < 0) {
X		pseg->p[v_indx].lives = 0;
X		(void)pgetzapped(v_indx, mdamage(a_indx));
X	}
X
X	clearm(a_indx, 0);
X}
X
X
Xmdrainhp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X	int damage;
X
X	if(m_table[a_indx].att_used >= M_ATTACKS)
X		return;
X
X	m_table[a_indx].att_used++;
X
X	if(!mhit(a_indx, v_indx)) {
X		if(!pseg->p[v_indx].brief) {
X			sprintf(buf, "%s missed you!", m_table[a_indx].name);
X			dmsg_add(v_indx, buf);
X		}
X		return;
X	} 
X
X	if(!pseg->p[v_indx].brief) {
X		sprintf(buf, "%s HIT you!", m_table[a_indx].name);
X		dmsg_add(v_indx, buf);
X	}
X
X	if(pseg->p[v_indx].ma_count > 0)
X		damage = dcomp(mdamage(a_indx), pseg->p[v_indx].m_armor);
X	else
X		damage = mdamage(a_indx);
X		
X	pseg->p[v_indx].max_hp -= damage;
X
X	if(pseg->p[v_indx].max_hp < 2) {
X		pseg->p[v_indx].max_hp = 2;
X		(void)pgetzapped(v_indx, mdamage(a_indx));
X	}
X
X	if(pseg->p[v_indx].hitpoints > pseg->p[v_indx].max_hp)
X		pseg->p[v_indx].hitpoints = pseg->p[v_indx].max_hp;
X
X	clearm(a_indx, 0);
X}
X
X
Xmdrainmp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	char buf[35];
X	int damage;
X
X	if(m_table[a_indx].att_used >= M_ATTACKS)
X		return;
X
X	m_table[a_indx].att_used++;
X
X	if(!mhit(a_indx, v_indx)) {
X		if(!pseg->p[v_indx].brief) {
X			sprintf(buf, "%s missed you!", m_table[a_indx].name);
X			dmsg_add(v_indx, buf);
X		}
X		return;
X	} 
X
X	if(!pseg->p[v_indx].brief) {
X		sprintf(buf, "%s HIT you!", m_table[a_indx].name);
X		dmsg_add(v_indx, buf);
X	}
X
X	if(pseg->p[v_indx].ma_count > 0)
X		damage = dcomp(mdamage(a_indx), pseg->p[v_indx].m_armor);
X	else
X		damage = mdamage(a_indx);
X		
X	pseg->p[v_indx].max_mp -= damage;
X
X	if(pseg->p[v_indx].max_mp < 2) {
X		pseg->p[v_indx].max_mp = 2;
X		(void)pgetzapped(v_indx, mdamage(a_indx));
X	}
X
X	if(pseg->p[v_indx].magicpts > pseg->p[v_indx].max_mp)
X		pseg->p[v_indx].magicpts = pseg->p[v_indx].max_mp;
X
X	clearm(a_indx, 0);
X}
X
X
Xint dcomp(damage, armor)
Xint damage, armor;
X{
X	int final_damage;
X
X	final_damage = damage - armor;
X
X	if(damage > 10) {
X		if(final_damage < -20)
X			final_damage = 0;
X		else if(final_damage < 1)
X			final_damage = 1;
X	} else {
X		if(final_damage < -10)
X			final_damage = 0;
X		else if(final_damage < 1)
X			final_damage = 1;
X	}
X
X	return final_damage;
X}
X
X
Xmstealp(a_indx, v_indx)
Xint a_indx, v_indx;
X{
X	int trys, item, i;
X	char buf[35];
X
X	if(m_table[a_indx].att_used >= M_ATTACKS)
X		return;
X
X	m_table[a_indx].att_used++;
X
X	if(!mhit(a_indx, v_indx)) {
X		if(!pseg->p[v_indx].brief) {
X			sprintf(buf, "%s missed you!", m_table[a_indx].name);
X			dmsg_add(v_indx, buf);
X		}
X		return;
X	} 
X
X	if(!pseg->p[v_indx].brief) {
X		sprintf(buf, "%s HIT you!", m_table[a_indx].name);
X		dmsg_add(v_indx, buf);
X	}
X
X	if(rnd(PMAX_ITEMS) == 1) {
X		pseg->p[v_indx].gold -= go2r(pseg->p[v_indx].gold);
X		pseg->player_sem++;
X		return;
X	}
X
X	for(trys = 0; trys < 3; trys++) {
X
X		item = rnd(PMAX_ITEMS) - 1;
X
X		if((i = pseg->p[v_indx].items[item]) != -1) {
X			pseg->itm[i].loc.sector = LOC_NONESUCH;
X			delete_item(v_indx, i);
X			deselect(v_indx, i);
X			pseg->item_sem++;
X			pseg->player_sem++;
X			return;
X		}
X	}
X}
X
X
Xkillp(v_indx)
Xint v_indx;
X{
X	int sector, x, y;
X
X	sector = pseg->p[v_indx].loc.sector;
X	x = pseg->p[v_indx].loc.x;
X	y = pseg->p[v_indx].loc.y;
X
X	mseg->m[sector].map[y][x] = pseg->p[v_indx].loc.under;
X	drop_all(v_indx, sector, x, y);
X
X	mseg->map_sem++;
X
X	del_player(v_indx);
X
X	pseg->p[v_indx].loc.sector = LOC_NONESUCH;
X
X	notify(sector);
X
X	pseg->player_sem++;
X
X	tell_player(v_indx);
X}
X
X
Xclearm(v_indx, t_flag)
Xint v_indx, t_flag;
X{
X	int sector, x, y;
X
X	sector = m_table[v_indx].loc.sector;
X	x = m_table[v_indx].loc.x;
X	y = m_table[v_indx].loc.y;
X
X	mseg->m[sector].map[y][x] = m_table[v_indx].loc.under;
X
X	if(t_flag)
X		do_treasure(v_indx);
X
X	mseg->map_sem++;
X
X	m_table[v_indx].loc.sector = LOC_NONESUCH;
X}
X
X
Xkillm(v_indx)
Xint v_indx;
X{
X	int sector;
X
X	sector = m_table[v_indx].loc.sector;
X
X	clearm(v_indx, 1);
X
X	notify(sector);
X}
X
X
Xdo_treasure(v_indx)
Xint v_indx;
X{
X	int tval, danger;
X	int sector, x, y;
X
X	sector = m_table[v_indx].loc.sector;
X	x = m_table[v_indx].loc.x;
X	y = m_table[v_indx].loc.y;
X
X	danger = m_table[v_indx].danger;
X
X	if(danger >= DANGER_CUT && rnd(CRYSTAL_ODDS) == 1) {
X		put_crystal(sector, x, y); 
X		return;
X	}
X
X	tval = (m_table[v_indx].max_hp + (danger * 10)) / 2;
X
X	if(rnd(100) > tval)
X		return;
X
X	switch(rnd(2)) {
X	case 1 :
X		put_item_tr(sector, x, y); 
X		break;
X	case 2 :
X		put_treasure(tval * 20, sector, x, y); 
X		break;
X	}
X}
X
X
Xput_treasure(max_cash, sector, x, y)
Xint max_cash, sector, x, y;
X{
X	int i;
X
X	for(i = 0; i < pseg->item_count; i++) {
X		if(pseg->itm[i].loc.sector == LOC_NONESUCH
X		&& pseg->itm[i].type == CASH) {
X			pseg->itm[i].decay_cnt = 0;
X			pseg->itm[i].loc.under = mseg->m[sector].map[y][x];
X			pseg->itm[i].value = rnd(max_cash);
X			(void)put_item(i, sector, x, y);
X			return;
X		}
X	}
X}
X
X
Xput_crystal(sector, x, y)
Xint sector, x, y;
X{
X	int i;
X
X	for(i = 0; i < pseg->item_count; i++) {
X		if(pseg->itm[i].loc.sector == LOC_NONESUCH
X		&& pseg->itm[i].type == CRYSTAL) {
X			pseg->itm[i].decay_cnt = 0;
X			pseg->itm[i].loc.under = mseg->m[sector].map[y][x];
X			pseg->itm[i].effect = 3 - go2r(2);
X			(void)put_item(i, sector, x, y);
X			return;
X		}
X	}
X}
X
X
Xput_item_tr(sector, x, y)
Xint sector, x, y;
X{
X	int i, choice;
X
X	choice = -1;
X
X	for(i = 0; i < pseg->item_count; i++) {
X		if(pseg->itm[i].loc.sector == LOC_NONESUCH
X		&& pseg->itm[i].type != CRYSTAL
X		&& pseg->itm[i].type != CASH) {
X			if(choice == -1 || rnd(2) == 1)
X				choice = i;
X		}
X	}
X
X	if(choice == -1)
X		return;
X
X	pseg->itm[choice].decay_cnt = 0;
X	pseg->itm[choice].loc.under = mseg->m[sector].map[y][x];
X	pseg->itm[choice].rem_uses = pseg->itm[choice].max_uses;
X	(void)put_item(choice, sector, x, y);
X}
X
X
Xdrop_all(p_indx, sector, x, y)
Xint p_indx, sector, x, y;
X{
X	int i, playernum;
X
X	playernum = pseg->p[p_indx].playernum;
X
X	for(i = 0; i < pseg->item_count; i++) {
X		if(pseg->itm[i].loc.sector == LOC_PLAYER
X		&& pseg->itm[i].loc.x == playernum)
X			if(put_item(i, sector, x, y) == -1)
X				pseg->itm[i].loc.sector = LOC_NONESUCH;
X
X		if(pseg->p[p_indx].gold > 0
X		&& pseg->itm[i].loc.sector == LOC_NONESUCH
X		&& pseg->itm[i].type == CASH) {
X			pseg->itm[i].value = pseg->p[p_indx].gold;
X			pseg->p[p_indx].gold = 0;
X			put_item(i, sector, x, y);
X		}
X	}
X
X	notify(sector);
X}
X
X
Xdamage_it(damage, t_a, t_x, t_y)
Xint damage, t_a, t_x, t_y;
X{
X	int i;
X
X	if(is_player(mseg->m[t_a].map[t_y][t_x])) {
X		for(i = 0; i < MAX_PLAYERS; i++)
X			if(pseg->p[i].loc.sector == t_a 
X			&& pseg->p[i].loc.x == t_x 
X			&& pseg->p[i].loc.y == t_y)
X				(void)pgethit(i, damage);
X	} else {
X		for(i = 0; i < n_monster; i++)
X			if(m_table[i].loc.sector == t_a 
X			&& m_table[i].loc.x == t_x 
X			&& m_table[i].loc.y == t_y)
X				mgethit(i, damage);
X	}
X}
X
X
X/* tune the following if you make major changes  */
X/* to MAX_HP or allow monsters with greater than */
X/* 200 fighting scores.                          */
X
Xint d_level(p_indx)
Xint p_indx;
X{
X	int danger;
X
X	danger = pseg->p[p_indx].fighting / 30;
X	danger += pseg->p[p_indx].max_hp / 20;
X
X	return danger;
X}
X
X
X/* end of file. */
END_OF_FILE
if test 14990 -ne `wc -c <'combat.c'`; then
    echo shar: \"'combat.c'\" unpacked with wrong size!
fi
# end of 'combat.c'
fi
if test -f 'input.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'input.c'\"
else
echo shar: Extracting \"'input.c'\" \(14884 characters\)
sed "s/^X//" >'input.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- input.c reader-task
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 = "@(#) input.c\t(1.5)\tcreated 1/3/91";
X
X#include <curses.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <string.h>
X#include <ctype.h>
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/ipc.h>
X#include <sys/msg.h>
X#include <sys/sem.h>
X
X#include "setup.h"
X#include "struct.h"
X#include "messages.h"
X#include "effect.h"
X
X#define GOD1PROMPT \
X	"God Power: r)eveal, m)ap, s)tats, t)itle, l)ink, or i)tem? "
X
Xchar *gates = "={}:;-|";
X
Xchar *progname;
X
Xstruct player_seg *pseg;
Xstruct map_seg *mseg;
X
Xextern int errno;
Xextern char *sys_errlist[];
X
Xextern char *spell_names[];
X
Xint pid, dqid, gseg_id, playernum, player_indx;
Xchar handle[20];
X
Xchar old_buf[35] = "";
X
Xstruct game_msg *gseg;
X
X
Xinput_process()
X{
X	int ch;
X	void input_exit();
X
X	strcpy(gseg->buf, WELCOME);
X	tell_viewer();
X
X	signal(SIGHUP, input_exit);
X
X	while((ch = getchar()) != EOF)
X		send_message(ch);
X}
X
X
Xvoid input_exit(sig)
Xint sig;
X{
X	shmdt(gseg);
X
X	exit(0);
X}
X
X
Xsend_t_message(ch)
Xint ch;
X{
X	struct dmessage msg_buf;
X	int in_ch, item_indx;
X
X	msg_buf.msg_type = 1L;
X	msg_buf.playernum = playernum;
X
X	switch(ch) {
X
X	case '\f' :
X		redraw_scr();
X		break;
X
X	case 'n' : /* next */
X		gseg->trader_offset += 10;
X		tell_viewer();
X		break;
X
X	case 'p' : /* previous */
X		if(gseg->trader_offset > 0)
X			gseg->trader_offset -= 10;
X		tell_viewer();
X		break;
X
X	case 'b' : /* buy */
X		msg_buf.cmd = 'B';
X
X		strcpy(gseg->buf, "buy what? (0-9) ");
X		tell_viewer();
X
X		in_ch = getchar() - '0';
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		if(in_ch < 0 || in_ch > 9)
X			break;
X
X		if((msg_buf.arg = trader_item(in_ch)) == -1)
X			break;
X
X		tell_daemon(&msg_buf);
X
X		break;
X
X	case 'v' : /* value */
X		strcpy(gseg->buf, "value what? (1-7) ");
X		tell_viewer();
X
X		in_ch = getchar() - '0';
X
X		if((item_indx = find_item(player_indx, in_ch)) >= 0) {
X			sprintf(gseg->buf, "%s is worth %d\n",
X				pseg->itm[item_indx].name,
X				pseg->itm[item_indx].value);
X			tell_viewer();
X		}
X
X		break;
X
X	case 's' : /* sell */
X		strcpy(gseg->buf, "sell what? (1-7) ");
X		tell_viewer();
X
X		in_ch = getchar() - '0';
X
X		if((item_indx = find_item(player_indx, in_ch)) >= 0) {
X			msg_buf.cmd = 'S';
X			msg_buf.arg = item_indx;
X			tell_daemon(&msg_buf);
X		}
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		break;
X
X	case 'l' : /* leave */
X		msg_buf.cmd = 'L';
X		tell_daemon(&msg_buf);
X		break;
X	}
X}
X
X
Xsend_message(ch)
Xint ch;
X{
X	struct dmessage msg_buf;
X	int in_ch, item_indx;
X
X	if(gseg->trader_offset >= 0) {
X		send_t_message(ch);
X		return;
X	}
X
X	msg_buf.msg_type = 1L;
X	msg_buf.playernum = playernum;
X
X	if(isupper(ch)) {
X		msg_buf.cmd = 'c';
X		msg_buf.subcmd = ch - 'A';
X		if((msg_buf.arg = get_spell_arg(tolower(ch))) == -1) {
X			strcpy(gseg->buf, "* aborted *");
X			tell_viewer();
X			return;
X		}
X		get_spell_text(tolower(ch), msg_buf.text);
X		tell_daemon(&msg_buf);
X
X	} else switch(ch) {
X
X	case '\n' :
X	case '\r' :
X		gseg->buf[0] = '\0';
X		tell_viewer();
X		break;
X
X	case '\f' :
X		redraw_scr();
X		break;
X
X	case '*' :
X	case '?' :
X		help();
X		break;
X
X	case ';' :
X		telltime();
X		break;
X
X	case 't' : /* take */
X	case '0' :
X		msg_buf.cmd = 't';
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'k' :
X	case '8' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_NORTH;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'j' :
X	case '2' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_SOUTH;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'l' :
X	case '6' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_EAST;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'h' :
X	case '4' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_WEST;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'y' :
X	case '7' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_NWEST;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'u' :
X	case '9' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_NEAST;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'b' :
X	case '1' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_SWEST;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'n' :
X	case '3' :
X		msg_buf.cmd = 'm';
X		msg_buf.subcmd = L_SEAST;
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'e' : /* enter */
X	case '5' :
X		msg_buf.cmd = 'e';
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'd' : /* drop */
X	case '/' : /* drop */
X		strcpy(gseg->buf, "drop what? (0-7) ");
X		tell_viewer();
X
X		in_ch = getchar() - '0';
X
X		if(in_ch == 0) {
X			strcpy(gseg->buf, "drop gold where? (hjkl) ");
X			tell_viewer();
X			if((msg_buf.subcmd = get_dir()) != -1
X			&& (msg_buf.arg = get_amount()) > 0) {
X				msg_buf.cmd = 'D';
X				tell_daemon(&msg_buf);
X			}
X		} else if(in_ch > 0 && in_ch <= PMAX_ITEMS)
X			if((item_indx = find_item(player_indx, in_ch)) >= 0) {
X				sprintf(gseg->buf, 
X					"drop %d where? (hjkl) ", in_ch);
X				tell_viewer();
X				if((msg_buf.subcmd = get_dir()) != -1) {
X					msg_buf.cmd = 'd';
X					msg_buf.arg = item_indx;
X					tell_daemon(&msg_buf);
X				}
X			}
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		break;
X
X	case ')' : /* cast */
X	case 'c' : /* cast */
X		strcpy(gseg->buf, "cast which spell? (a-z) ");
X		tell_viewer();
X
X		in_ch = tolower(getchar());
X
X		if(in_ch >= 'a' && in_ch <= 'z') {
X			msg_buf.cmd = 'c';
X			msg_buf.subcmd = in_ch - 'a';
X			if((msg_buf.arg = get_spell_arg(in_ch)) == -1) {
X				strcpy(gseg->buf, "* aborted *");
X				tell_viewer();
X				return;
X			}
X			get_spell_text(in_ch, msg_buf.text);
X			tell_daemon(&msg_buf);
X		}
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		break;
X
X	case 'g' : /* god power */
X		if(pseg->p[player_indx].createpts < 1)
X			break;
X
X		strcpy(gseg->buf, GOD1PROMPT);
X		tell_viewer();
X
X		in_ch = tolower(getchar());
X
X		get_god_cmd(in_ch);
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		break;
X
X	case 'v' : /* verbose */
X		
X		msg_buf.cmd = 'v';
X		tell_daemon(&msg_buf);
X
X		break;
X
X	case '(' : /* activate */
X	case 'a' : /* activate */
X		strcpy(gseg->buf, "activate what? (1-7) ");
X		tell_viewer();
X
X		in_ch = getchar() - '0';
X
X		activate_it(in_ch);
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		break;
X
X	case '!' : /* activate 1 */
X
X		activate_it(1);
X		break;
X
X	case '@' : /* activate 2 */
X
X		activate_it(2);
X		break;
X
X	case '#' : /* activate 3 */
X
X		activate_it(3);
X		break;
X
X	case '$' : /* activate 4 */
X
X		activate_it(4);
X		break;
X
X	case '%' : /* activate 5 */
X
X		activate_it(5);
X		break;
X
X	case '^' : /* activate 6 */
X
X		activate_it(6);
X		break;
X
X	case '&' : /* activate 7 */
X
X		activate_it(7);
X		break;
X
X	case 'w' : /* write */
X		strcpy(gseg->buf, "write what? (1-7) ");
X		tell_viewer();
X
X		in_ch = getchar() - '1';
X
X		write_it(in_ch);
X
X		gseg->buf[0] = '\0';
X		tell_viewer();
X
X		break;
X
X	case '.' : /* say */
X	case 's' : /* say */
X		say_it();
X		break;
X
X	case '+' : /* partner */
X	case 'p' : /* partner */
X		partner();
X		break;
X	}
X}
X
X
Xactivate_it(in_ch)
Xint in_ch;
X{
X	struct dmessage msg_buf;
X	int item_indx;
X
X	if(in_ch > 0 && in_ch <= PMAX_ITEMS) {
X		item_indx = find_item(player_indx, in_ch);
X
X		if(item_indx >= 0) {
X			msg_buf.msg_type = 1L;
X			msg_buf.playernum = playernum;
X			msg_buf.cmd = 'u';
X			msg_buf.subcmd = item_indx;
X			msg_buf.arg = get_use_dir(item_indx);
X			tell_daemon(&msg_buf);
X		}
X	}
X}
X
X
Xpartner()
X{
X	struct dmessage msg_buf;
X	int pard;
X
X	strcpy(gseg->buf, "partner with who? ");
X	tell_viewer();
X
X	pard = toupper(getchar()) - '1';
X
X	gseg->buf[0] = '\0';
X	tell_viewer();
X
X	msg_buf.msg_type = 1L;
X	msg_buf.playernum = playernum;
X	msg_buf.cmd = 'p';
X	msg_buf.subcmd = pard;
X	tell_daemon(&msg_buf);
X}
X
X
Xwrite_it(ch)
Xint ch;
X{
X	struct dmessage msg_buf;
X	int i_indx;
X
X	if(ch < 0 || ch > 6)
X		return;
X
X	i_indx = pseg->p[player_indx].items[ch];
X
X	if(i_indx < 0 || pseg->itm[i_indx].type != NOTE)
X		return;
X
X	msg_buf.msg_type = 1L;
X	msg_buf.playernum = playernum;
X
X	msg_buf.cmd = 'w';
X	msg_buf.arg = i_indx;
X	get_message(msg_buf.text);
X
X	if(msg_buf.text[0] != '\0')
X		tell_daemon(&msg_buf);
X}
X
X
Xsay_it()
X{
X	struct dmessage msg_buf;
X
X	msg_buf.msg_type = 1L;
X	msg_buf.playernum = playernum;
X
X	msg_buf.cmd = 's';
X	get_message(msg_buf.text);
X
X	if(msg_buf.text[0] != '\0')
X		tell_daemon(&msg_buf);
X}
X
X
Xget_message(text)
Xchar *text;
X{
X	char inbuf[35];
X	int pos, ch;
X
X	pos = 0;
X	ch = '\0';
X	inbuf[0] = '\0';
X	text[0] = '\0';
X
X	while(ch != '\n' && ch != '\r') {
X		strcpy(gseg->buf, "Message (^R = Recall, ESC = Cancel) : ");
X		strcat(gseg->buf, inbuf);
X		strcat(gseg->buf, "_");
X		tell_viewer();
X
X		ch = getchar();
X
X		switch(ch) {
X		case '\033' :
X			inbuf[pos] = '\0';
X			gseg->buf[0] = '\0';
X			tell_viewer();
X			return;
X		case '\b' :
X			if(pos)
X				pos--;
X			inbuf[pos] = '\0';
X			break;
X		case '\n' :
X		case '\r' :
X		case '\f' :
X		case '\t' :
X			break;
X		case '\022' :
X			strcpy(inbuf, old_buf);
X			pos = strlen(inbuf);
X			break;
X		default :
X			if(isprint(ch) && pos < 30) {
X				inbuf[pos++] = ch;
X				inbuf[pos] = '\0';
X			}
X			break;
X		}
X	}
X
X	gseg->buf[0] = '\0';
X	tell_viewer();
X
X	strcpy(text, inbuf);
X	strcpy(old_buf, inbuf);
X}
X
X
Xint get_amount()
X{
X	char inbuf[9];
X	int pos, ch;
X
X	pos = 0;
X	ch = '\0';
X	inbuf[0] = '\0';
X
X	while(ch != '\n' && ch != '\r') {
X		sprintf(gseg->buf, "How much? (ESC to cancel): %s_", inbuf);
X		tell_viewer();
X
X		ch = getchar();
X
X		switch(ch) {
X		case '\033' :
X			gseg->buf[0] = '\0';
X			tell_viewer();
X			return;
X		case '\b' :
X			if(pos)
X				pos--;
X			inbuf[pos] = '\0';
X			break;
X		case '\n' :
X		case '\r' :
X		case '\f' :
X		case '\t' :
X			break;
X		default :
X			if(isdigit(ch) && pos < 7) {
X				inbuf[pos++] = ch;
X				inbuf[pos] = '\0';
X			}
X			break;
X		}
X	}
X
X	return atoi(inbuf);
X}
X
X
Xint get_dir()
X{
X	switch(tolower(getchar())) {
X	case 'h' :
X	case '4' :
X		return L_WEST;
X	case 'j' :
X	case '2' :
X		return L_SOUTH;
X	case 'k' :
X	case '8' :
X		return L_NORTH;
X	case 'l' :
X	case '6' :
X		return L_EAST;
X	case 'y' :
X	case '7' :
X		return L_NWEST;
X	case 'b' :
X	case '1' :
X		return L_SWEST;
X	case 'n' :
X	case '3' :
X		return L_SEAST;
X	case 'u' :
X	case '9' :
X		return L_NEAST;
X	}
X
X	return -1;
X}
X
X
Xget_use_dir(indx)
Xint indx;
X{
X	if(pseg->itm[indx].type == WEAPON
X	|| pseg->itm[indx].type == SHIELD
X	|| pseg->itm[indx].type == ARMOR
X	|| pseg->itm[indx].type == NOTE)
X		return 0;
X
X	if(pseg->itm[indx].type == MISSILE) {
X		sprintf(gseg->buf, "fire %s which way? (hjkl) ",
X			pseg->itm[indx].name);
X		tell_viewer();
X		return get_dir();
X	}
X
X	switch(pseg->itm[indx].effect) {
X	case TELEPORT :
X	case HEALING :
X		return 0;
X	case FIREBALLS : /* fireball */
X	case LIGHTNING : /* lightning */
X	case COLD : /* cold */
X		sprintf(gseg->buf, "activate %s which way? (hjkl) ",
X			pseg->itm[indx].name);
X		tell_viewer();
X		return get_dir();
X	default :
X		return 0;
X	}
X}
X
X
Xget_spell_text(spell, text)
Xint spell;
Xchar *text;
X{
X	switch(spell) {
X	case 'w' :
X		get_message(text);
X		break;
X	}
X}
X
X
Xint get_spell_arg(spell)
Xint spell;
X{
X	int in_ch, item_indx;
X
X	switch(spell) {
X	case 'c' : /* cold */
X	case 'f' : /* fireball */
X	case 'l' : /* lightning */
X	case 'm' : /* missile */
X	case 'r' : /* death ray */
X		sprintf(gseg->buf, "cast %s which way? (hjkl) ",
X			spell_names[spell - 'a']);
X		tell_viewer();
X		return get_dir();
X
X	case 'n' : /* nightmare */
X	case 's' : /* seek */
X	case 'y' : /* yank */
X		sprintf(gseg->buf, "%s who? ",
X			spell_names[spell - 'a']);
X		tell_viewer();
X		in_ch = getchar();
X		return (isdigit(in_ch) ? in_ch - '1' : -1);
X
X	case 'o' : /* obscure */
X		strcpy(gseg->buf, "obscure what item? (0-7) ");
X		tell_viewer();
X		in_ch = getchar() - '0';
X		if(in_ch == 0)
X			return -1;
X		if(in_ch > 0 && in_ch <= PMAX_ITEMS)
X			item_indx = find_item(player_indx, in_ch);
X		return item_indx;
X
X	case 'v' : /* verify */
X		strcpy(gseg->buf, "verify what item? (0-7) ");
X		tell_viewer();
X		in_ch = getchar() - '0';
X		if(in_ch == 0)
X			return -1;
X		if(in_ch > 0 && in_ch <= PMAX_ITEMS)
X			item_indx = find_item(player_indx, in_ch);
X		return item_indx;
X
X	case 'w' : /* whisper */
X		strcpy(gseg->buf, "whisper to who? ");
X		tell_viewer();
X		in_ch = getchar();
X		return (isdigit(in_ch) ? in_ch - '1' : -1);
X
X	default :
X		return 0;
X	}
X}
X
X
Xredraw_scr()
X{
X	gseg->clear_ok = 1;
X
X	tell_viewer();
X}
X
X
Xtell_daemon(mptr)
Xstruct dmessage *mptr;
X{
X	msgsnd(dqid, mptr, DMSGSIZ, IPC_NOWAIT);
X}
X
X
Xtell_viewer()
X{
X	struct sembuf ops[1];
X
X	ops[0].sem_num = player_indx;
X	ops[0].sem_op = 1;
X	ops[0].sem_flg = 0;
X
X	semop(pseg->sid, ops, 1);
X}
X
X
Xint find_item(p_indx, p_item_indx)
Xint p_indx, p_item_indx;
X{
X	int i, cnt;
X
X	cnt = 0;
X
X	if(p_item_indx < 1 || p_item_indx > PMAX_ITEMS)
X		return -1;
X
X	return pseg->p[p_indx].items[p_item_indx - 1];
X}
X
X
Xget_god_cmd(ch)
Xint ch;
X{
X	struct dmessage msg_buf;
X	char in_ch;
X	int item_indx;
X
X	msg_buf.msg_type = 1L;
X	msg_buf.playernum = playernum;
X	msg_buf.cmd = 'g';
X	msg_buf.subcmd = ch;
X
X	switch(ch) {
X	case 'l' :
X		strcpy(gseg->buf, "God Power: r)emember or c)reate? ");
X		tell_viewer();
X		msg_buf.arg = tolower(getchar());
X		if(msg_buf.arg == 'c') {
X			strcpy(gseg->buf, "God Power: select link 1-7? ");
X			tell_viewer();
X			msg_buf.ext_arg = getchar() - '1';
X			if(msg_buf.ext_arg > 6 || msg_buf.ext_arg < 0)
X				msg_buf.ext_arg = 0;
X		}
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'm' :
X		strcpy(gseg->buf, "God Power: which way? (hjkl) ");
X		tell_viewer();
X		msg_buf.arg = get_dir();
X		strcpy(gseg->buf, "God Power: change to what code? ");
X		tell_viewer();
X		if((msg_buf.ext_arg = getchar()) == '=')
X			msg_buf.ext_arg = get_gate();
X		tell_daemon(&msg_buf);
X		break;
X
X	case 's' :
X		strcpy(gseg->buf, 
X			"God Power: l)evel, j)ump inhibit, i)llumination? ");
X		tell_viewer();
X		msg_buf.arg = tolower(getchar());
X		strcpy(gseg->buf, "God Power: + (more) or - (less)? ");
X		msg_buf.ext_arg = getchar();
X		tell_daemon(&msg_buf);
X		break;
X
X	case 't' :
X		msg_buf.arg = pseg->p[player_indx].loc.sector;
X		get_message(msg_buf.text);
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'r' :
X		tell_daemon(&msg_buf);
X		break;
X
X	case 'i' :
X		strcpy(gseg->buf, "God Power: which item? ");
X		tell_viewer();
X		in_ch = getchar() - '0';
X		if((item_indx = find_item(player_indx, in_ch)) < 0)
X			break;
X		msg_buf.arg = item_indx;
X		strcpy(gseg->buf, 
X			"God Power: n)ame, r)eveal, a)lter, or c)urse item? ");
X		tell_viewer();
X		in_ch = tolower(getchar());
X
X		if(in_ch == 'a') {
X			msg_buf.subcmd = in_ch;
X			msg_buf.ext_arg = get_item_stat(item_indx);
X			tell_daemon(&msg_buf);
X		} else if(in_ch == 'n') {
X			msg_buf.subcmd = in_ch;
X			get_message(msg_buf.text);
X			tell_daemon(&msg_buf);
X		} else if(in_ch == 'r') {
X			tell_daemon(&msg_buf);
X		} else if(in_ch == 'c') {
X			msg_buf.subcmd = 'a';
X			msg_buf.ext_arg = 'c';
X			tell_daemon(&msg_buf);
X		}
X
X		break;
X	}
X}
X
X
Xint get_item_stat(i_indx)
Xint i_indx;
X{
X	strcpy(gseg->buf, "God Power: alter v)alue or r)ange? ");
X	tell_viewer();
X
X	return tolower(getchar());
X}
X
X
Xint get_gate()
X{
X	strcpy(gseg->buf, "God Power: select gate number 1-7 > ");
X	tell_viewer();
X
X	switch(getchar()) {
X	case '2' :
X		return '{';
X	case '3' :
X		return '}';
X	case '4' :
X		return ':';
X	case '5' :
X		return ';';
X	case '6' :
X		return '-';
X	case '7' :
X		return '|';
X	default :
X		return '=';
X	}
X}
X
X
X/* end of file. */
END_OF_FILE
if test 14884 -ne `wc -c <'input.c'`; then
    echo shar: \"'input.c'\" unpacked with wrong size!
fi
# end of 'input.c'
fi
if test -f 'magic.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'magic.c'\"
else
echo shar: Extracting \"'magic.c'\" \(17087 characters\)
sed "s/^X//" >'magic.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- magic.c magic 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 = "@(#) magic.c\t(1.2)\tcreated 1/2/91";
X
X#include <stdio.h>
X
X#include "setup.h"
X#include "struct.h"
X#include "spells.h"
X
X#define NOSPELL(x)	dmsg_add(x, "spell not available")
X
Xextern struct player_seg *pseg;
Xextern struct map_seg *mseg;
X
Xextern struct monster_tbl *m_table;
Xextern int n_monster;
X
Xextern char *spell_names[];
Xextern int spell_dd[];
X
Xextern struct ast a_spell_table[];
X
Xchar under[8];
Xint n_sectors[4];
X
X
Xcast_spell(indx, mptr)
Xint indx;
Xstruct dmessage *mptr;
X{
X	int spell, who, what, dir, max_damage, rc;
X	char buf[35];
X	char *text;
X
X	spell = mptr->subcmd;
X	what = who = dir = mptr->arg;
X	text = mptr->text;
X
X	sprintf(buf, "cast %s...", spell_names[spell]);
X	dmsg_add(indx, buf);
X
X	if(cast_it(spell, indx) == -1) {
X		pseg->p[indx].magicpts -= (pseg->p[indx].magicpts ? 1 : 0);
X		sprintf(buf, "%s failed", spell_names[spell]);
X		dmsg_add(indx, buf);
X		return;
X	}
X
X	switch(spell + 'a') {
X	case 'a' : /* armor */
X		pseg->p[indx].ma_count += rnd(300);
X		pseg->p[indx].m_armor += rnd(5);
X		if(pseg->p[indx].m_armor > MAX_MARMOR)
X			pseg->p[indx].m_armor = MAX_MARMOR;
X		pseg->player_sem++;
X		tell_player(indx);
X		break;
X		
X	case 'b' : /* block */
X		pseg->p[indx].blocked += go2r(100);
X		dmsg_add(indx, "Seeks now blocked.");
X		break;
X		
X	case 'c' : /* cold */
X		dmsg_add(indx, "Whoosh!");
X		visible(indx);
X		max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
X		cast_a_spell(&(pseg->p[indx].loc), AS_COLD, dir, 
X			go2r(max_damage));
X		break;
X
X	case 'd' : /* detect */
X		detect(indx);
X		tell_player(indx);
X		break;
X
X	case 'e' : /* escape */
X		if((rc = jump_to(indx, pseg->p[indx].home)) == -1)
X			dmsg_add(indx, "escape bounced");
X		else if(rc == -2)
X			dmsg_add(indx, "escape fizzled");
X		else
X			dmsg_add(indx, "escaped!");
X		break;
X
X	case 'f' : /* fireball */
X		visible(indx);
X		dmsg_add(indx, "Boom!");
X		max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
X		cast_a_spell(&(pseg->p[indx].loc), AS_FIREBALL, dir, 
X			go2r(max_damage));
X		break;
X
X	case 'g' : /* glow */
X		glow(indx);
X		tell_player(indx);
X		break;
X
X	case 'h' : /* heal */
X		heal(indx);
X		tell_player(indx);
X		break;
X
X	case 'i' : /* invisible */
X		invisible(indx);
X		tell_player(indx);
X		break;
X
X	case 'j' : /* jump back */
X		jump_back(indx);
X		break;
X
X	case 'k' : /* knight */
X		knight(indx);
X		break;
X
X	case 'l' : /* lightning */
X		visible(indx);
X		dmsg_add(indx, "Crackle!");
X		max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
X		cast_a_spell(&(pseg->p[indx].loc), AS_LIGHTNING, dir, 
X			go2r(max_damage));
X		break;
X
X	case 'm' : /* missile */
X		visible(indx);
X		dmsg_add(indx, "A fiery missile appears!");
X		max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
X		ranged_spell(indx, dir, 'm' - 'a', go2r(10), max_damage);
X		break;
X
X	case 'n' : /* n */
X		nightmare(indx, who);
X		break;
X
X	case 'o' : /* obscure */
X		if(what >= 0) {
X			toggle_obscure(what);
X			dmsg_add(indx, "The object shimmers...");
X		} else if(what == -1) {
X			pseg->p[indx].gold_hidden = 
X				(pseg->p[indx].gold_hidden ? 0 : 1);
X			dmsg_add(indx, "Your gold shimmers...");
X		} else
X			dmsg_add(indx, "obscure what?");
X		break;
X
X	case 'p' : /* partners */
X		show_partners(indx);
X		break;
X
X	case 'q' : /* quit */
X		quit_spell(indx);
X		break;
X
X	case 'r' : /* death ray */
X		visible(indx);
X		dmsg_add(indx, "Bzzzzzt!");
X		max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
X		cast_a_spell(&(pseg->p[indx].loc), AS_DEATHRAY, dir, 
X			go2r(max_damage));
X		break;
X
X	case 's' : /* seek */
X		seek_s(indx, who);
X		break;
X
X	case 't' : /* teleport */
X		teleport(indx);
X		break;
X
X	case 'u' : /* user */
X		pseg->p[indx].user_spell += go2r(USER_DUR);
X		pseg->player_sem++;
X		break;
X
X	case 'v' : /* verify */
X		verify_item(indx, what);
X		break;
X
X	case 'w' : /* whisper */
X		whisper(indx, who, text);
X		break;
X
X	case 'x' : /* spell x */
X		spell_x(indx);
X		break;
X
X	case 'y' : /* yank */
X		yank(indx, who);
X		break;
X
X	case 'z' : /* zap */
X		visible(indx);
X		dmsg_add(indx, "Zap!");
X		max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
X		cast_a_spell(&(pseg->p[indx].loc), AS_ZAP, L_EAST, 
X			go2r(max_damage));
X		break;
X
X	default :
X		break;
X	}
X}
X
X
Xquit_spell(indx)
Xint indx;
X{
X	int sector, x, y;
X
X	sector = pseg->p[indx].loc.sector;
X
X	if(sector < 0)
X		return;
X
X	x = pseg->p[indx].loc.x;
X	y = pseg->p[indx].loc.y;
X
X	mseg->m[sector].map[y][x] = pseg->p[indx].loc.under;
X	mseg->map_sem++;
X
X	pseg->p[indx].loc.x = sector;
X	pseg->p[indx].loc.sector = LOC_HOME;
X}
X
X
Xshow_partners(p_indx)
Xint p_indx;
X{
X	int i, len;
X	char o_buf[35];
X
X	strcpy(o_buf, "Partners:");
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(i != p_indx
X		&& pseg->p[i].playernum >= 0
X		&& pseg->p[i].partners[p_indx] == 1) {
X			len = strlen(o_buf);
X			o_buf[len] = ' ';
X			o_buf[len + 1] = i + '1';
X			o_buf[len + 2] = '\0';
X		}
X
X	dmsg_add(p_indx, o_buf);
X}
X
X
Xint cast_it(spell, indx)
Xint spell, indx;
X{
X	if(pseg->p[indx].magicpts < (spell_dd[spell] + 1)
X	|| rnd(90 + (10 * spell_dd[spell])) > pseg->p[indx].spells[spell])
X		return -1;
X
X	improve_s(indx, spell);
X
X	pseg->p[indx].magicpts -= (spell_dd[spell] + 1);
X	pseg->player_sem++;
X	tell_player(indx);
X
X	return 0;
X}
X
X
Xspell_x(p_indx)
Xint p_indx;
X{
X	int max_damage, i, sector;
X
X	sector = pseg->p[p_indx].loc.sector;
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(pseg->p[i].loc.sector == sector)
X			dmsg_add(i, "KA-BOOM!!!");
X
X	max_damage = 5 * pseg->p[p_indx].magicpts;
X
X	if(max_damage < 1)
X		max_damage = 5;
X
X	pseg->p[p_indx].magicpts = 0;
X
X	for(i = 0; i < n_monster; i++)
X		if(m_table[i].loc.sector == sector)
X			mgethit(i, go2r(max_damage));
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(pseg->p[i].loc.sector == sector
X		&& i != p_indx
X		&& pseg->p[p_indx].partners[i] == 0)
X			pgethit(i, rnd(max_damage));
X
X	pseg->player_sem++;
X	mseg->map_sem++;
X
X	notify(sector);
X}
X
X
Xyank(p_indx, v_indx)
Xint p_indx, v_indx;
X{
X	int dest_a, rc;
X	char buf[35];
X
X	if(v_indx < 0 || v_indx >= MAX_PLAYERS)
X		return;
X
X	dest_a = pseg->p[p_indx].loc.sector;
X
X	if(pseg->p[v_indx].loc.sector < 0
X	|| pseg->p[v_indx].playernum < 0
X	|| pseg->p[v_indx].blocked > 0) {
X		sprintf(buf, "%c not found.", (char)('1' + v_indx));
X		dmsg_add(p_indx, buf);
X	} else if((rc = jump_to(v_indx, dest_a)) == -1)
X		dmsg_add(p_indx, "yank bounced");
X	else if(rc == -2)
X		dmsg_add(p_indx, "yank fizzled");
X	else {
X		sprintf(buf, "%c yanked!", (char)('1' + v_indx));
X		dmsg_add(p_indx, buf);
X		dmsg_add(v_indx, "you've been yanked!");
X	}
X}
X
X
Xjump_back(indx)
Xint indx;
X{
X	int dest_a, rc;
X
X	dest_a = pseg->p[indx].prev_sect;
X
X	if((rc = jump_to(indx, dest_a)) == -1)
X		dmsg_add(indx, "jump back bounced");
X	else if(rc == -2)
X		dmsg_add(indx, "jump back fizzled");
X	else
X		dmsg_add(indx, "returned");
X}
X
X
Xteleport(indx)
Xint indx;
X{
X	int dest_a, rc;
X
X	dest_a = rnd(mseg->max_areas) - 1;
X
X	if((rc = jump_to(indx, dest_a)) == -1)
X		dmsg_add(indx, "teleport bounced");
X	else if(rc == -2)
X		dmsg_add(indx, "teleport fizzled");
X	else
X		dmsg_add(indx, "teleported");
X}
X
X
Xint jump_to(indx, sector)
Xint indx, sector;
X{
X	int cnt, rc, symbol, link_dd;
X	int old_s, x, y, dest_x, dest_y;
X
X	old_s = pseg->p[indx].loc.sector;
X	x = pseg->p[indx].loc.x;
X	y = pseg->p[indx].loc.y;
X
X	link_dd = mseg->m[old_s].jump_inhibit + mseg->m[sector].jump_inhibit;
X
X	if(rnd(10) < link_dd)
X		return -2;
X
X	for(cnt = 0; cnt < TELE_TRYS; cnt++) {
X		mseg->m[old_s].map[y][x] = pseg->p[indx].loc.under;
X		mseg->map_sem++;
X
X		dest_x = rnd(MAPCOLS) - 1;
X		dest_y = rnd(MAPROWS) - 1;
X
X		rc = t_move_to(&(pseg->p[indx].loc), 
X			sector, dest_x, dest_y, indx);
X		
X		symbol = pseg->p[indx].invis ? indx + 11 : indx + 1;
X
X		move_sym(&(pseg->p[indx].loc), symbol);
X		mseg->map_sem++;
X
X		if(rc == 0) {
X			pseg->p[indx].prev_sect = old_s;
X			notify(sector);
X			notify(old_s);
X			return 0;
X		}
X	}
X
X	return -1;
X}
X
X
Xint send_monster(m_indx, sector)
Xint m_indx, sector;
X{
X	int rc;
X
X	lift_a_monster(m_indx);
X
X	rc = move_to(&(m_table[m_indx].loc), sector, 
X		m_table[m_indx].loc.x, m_table[m_indx].loc.y, -1);
X
X	move_sym(&(m_table[m_indx].loc), m_table[m_indx].m_sym);
X
X	mseg->map_sem++;
X
X	if(rc == 0) {
X		notify(sector);
X		return 0;
X	}
X
X	return -1;
X}
X
X
Xvisible(p_indx)
Xint p_indx;
X{
X	int sector, x, y;
X
X	pseg->p[p_indx].invis = 0;
X
X	sector = pseg->p[p_indx].loc.sector;
X	x = pseg->p[p_indx].loc.x;
X	y = pseg->p[p_indx].loc.y;
X
X	if(sector < 0)
X		return;
X
X	mseg->m[sector].map[y][x] = 1 + p_indx;
X	mseg->map_sem++;
X}
X
X
Xinvisible(p_indx)
Xint p_indx;
X{
X	int sector, x, y;
X
X	pseg->p[p_indx].invis += rnd(100);
X	dmsg_add(p_indx, "you disappear!");
X
X	sector = pseg->p[p_indx].loc.sector;
X	x = pseg->p[p_indx].loc.x;
X	y = pseg->p[p_indx].loc.y;
X
X	if(sector < 0)
X		return;
X
X	mseg->m[sector].map[y][x] = 11 + p_indx;
X	mseg->map_sem++;
X
X	notify(sector);
X}
X
X
Xheal(p_indx)
Xint p_indx;
X{
X	pseg->p[p_indx].hitpoints += rnd(10);
X
X	if(pseg->p[p_indx].hitpoints > pseg->p[p_indx].max_hp)
X		pseg->p[p_indx].hitpoints = pseg->p[p_indx].max_hp;
X
X	dmsg_add(p_indx, "you feel better");
X}
X
X
Xglow(p_indx)
Xint p_indx;
X{
X	pseg->p[p_indx].light += (6 * rnd(100));
X
X	mseg->map_sem++;
X
X	dmsg_add(p_indx, "it's brighter now");
X}
X
X
Xdetect(indx)
Xint indx;
X{
X	pseg->p[indx].detect += go2r(DETECT_DUR);
X
X	mseg->map_sem++;
X
X	dmsg_add(indx, "your vision sharpens");
X}
X
X
Xranged_spell(p_indx, dir, spell, range, damage)
Xint p_indx, dir, spell, range, damage;
X{
X	char buf[35];
X
X	if(rspell_start(p_indx, 21, range, damage, dir) == -1) {
X		sprintf(buf, "%s failed", spell_names[spell]);
X		dmsg_add(p_indx, buf);
X	} 
X}
X
X
Xint rspell_start(indx, symbol, range, damage, dir)
Xint indx, symbol, range, damage, dir;
X{
X	return start_ranged(symbol, 5, damage, 
X		pseg->p[indx].loc.sector, pseg->p[indx].loc.x, 
X		pseg->p[indx].loc.y, dir);
X}
X
X
Xint t_move_to(locptr, dest_a, dest_x, dest_y, p_indx)
Xstruct location *locptr;
Xint dest_a, dest_x, dest_y, p_indx;
X{
X	char at_loc;
X
X	if(dest_a < 0)
X		return -1;
X
X	at_loc = mseg->m[dest_a].map[dest_y][dest_x];
X
X	switch(at_loc) {
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		do_trap(p_indx, at_loc);
X		locptr->sector = dest_a;
X		locptr->x = dest_x;
X		locptr->y = dest_y;
X		locptr->under = at_loc;
X		mseg->map_sem++;
X		return 0;
X
X	case '.' :
X	case ' ' :
X	case '`' : /* shallow water */
X	case '+' : /* secret door */
X	case '<' : /* down */
X	case '>' : /* up */
X		locptr->sector = dest_a;
X		locptr->x = dest_x;
X		locptr->y = dest_y;
X		locptr->under = at_loc;
X		mseg->map_sem++;
X		return 0;
X
X	default :
X		return (int)at_loc;
X	}
X}
X
X
Xclear_n_sectors()
X{
X	int i;
X
X	for(i = 0; i < 4; i++)
X		n_sectors[i] = LOC_NONESUCH;
X}
X
X
Xadd_n_sector(sector)
Xint sector;
X{
X	int i;
X
X	for(i = 0; i < 4; i++)
X		if(n_sectors[i] == LOC_NONESUCH) {
X			n_sectors[i] = sector;
X			return;
X		}
X}
X
X
Xnotify_n_sectors()
X{
X	int i;
X
X	for(i = 0; i < 4; i++)
X		if(n_sectors[i] != LOC_NONESUCH) 
X			notify(n_sectors[i]);
X}
X
X
Xcast_a_spell(loc, a_spell, dir, effect)
Xstruct location *loc;
Xint a_spell, dir, effect;
X{
X	int i, limit;
X	char at_spot;
X	struct location t_loc;
X
X	switch(dir) {
X	case L_NORTH :
X	case L_SOUTH :
X	case L_EAST :
X	case L_WEST :
X	case L_NEAST :
X	case L_NWEST :
X	case L_SEAST :
X	case L_SWEST :
X		break;
X	default :
X		return;
X	}
X	
X	clear_n_sectors();
X	limit = 99;
X
X	for(i = 0; i < 8; i++) {
X		t_loc.sector = loc->sector;
X		t_loc.x = loc->x;
X		t_loc.y = loc->y;
X
X		loc_a_spell(&t_loc, a_spell, i, dir);
X
X		if(correct_loc(&t_loc) != -1) {
X			at_spot = mseg->m[t_loc.sector].map[t_loc.y][t_loc.x];
X
X			if(a_spell_table[a_spell].advance[i] <= limit
X			&& at_spot != '#') {
X				add_n_sector(t_loc.sector);
X				under[i] = at_spot;
X				mseg->m[t_loc.sector].map[t_loc.y][t_loc.x] = 
X					'*';
X			} else if(at_spot == '#'
X			&& a_spell_table[a_spell].advance[i] < limit
X			&& a_spell_table[a_spell].flag == ASF_LIMITED) {
X				limit = a_spell_table[a_spell].advance[i];
X			}
X		}
X	}
X
X	mseg->map_sem++;
X	notify_n_sectors();
X
X	busy_wait(600000L);
X
X	clear_n_sectors();
X
X	for(i = 0; i < 8; i++) {
X		t_loc.sector = loc->sector;
X		t_loc.x = loc->x;
X		t_loc.y = loc->y;
X
X		loc_a_spell(&t_loc, a_spell, i, dir);
X
X		if(a_spell_table[a_spell].advance[i] <= limit
X		&& correct_loc(&t_loc) != -1 
X		&& mseg->m[t_loc.sector].map[t_loc.y][t_loc.x] == '*') {
X			add_n_sector(t_loc.sector);
X			mseg->m[t_loc.sector].map[t_loc.y][t_loc.x] = under[i];
X		}
X	}
X
X	mseg->map_sem++;
X	notify_n_sectors();
X
X	for(i = 0; i < 8; i++) {
X		t_loc.sector = loc->sector;
X		t_loc.x = loc->x;
X		t_loc.y = loc->y;
X
X		loc_a_spell(&t_loc, a_spell, i, dir);
X
X		if(correct_loc(&t_loc) != -1
X		&& a_spell_table[a_spell].advance[i] <= limit)
X			zap_spot(t_loc.sector, t_loc.x, t_loc.y, effect);
X	}
X}
X
X
Xzap_spot(sector, x, y, effect)
Xint sector, x, y, effect;
X{
X	int i;
X
X	if(is_player(mseg->m[sector].map[y][x])) {
X		for(i = 0; i < MAX_PLAYERS; i++)
X			if(pseg->p[i].loc.sector == sector 
X			&& pseg->p[i].loc.x == x 
X			&& pseg->p[i].loc.y == y)
X				pgetzapped(i, effect);
X	} else {
X		for(i = 0; i < n_monster; i++)
X			if(m_table[i].loc.sector == sector 
X			&& m_table[i].loc.x == x 
X			&& m_table[i].loc.y == y)
X				mgethit(i, effect);
X	}
X}
X
X
Xloc_a_spell(loc, spell, pos, dir)
Xstruct location *loc;
Xint spell, pos, dir;
X{
X	int off, adv;
X
X	off = a_spell_table[spell].offset[pos];
X	adv = a_spell_table[spell].advance[pos];
X
X	switch(dir) {
X	case L_NORTH :
X		loc->y -= adv;
X		loc->x += off;
X		break;
X	case L_SOUTH :
X		loc->y += adv;
X		loc->x -= off;
X		break;
X	case L_EAST :
X		loc->x += adv;
X		loc->y += off;
X		break;
X	case L_WEST :
X		loc->x -= adv;
X		loc->y -= off;
X		break;
X	case L_NEAST :
X		loc->y += (-1 * adv) + off - (off > 0);
X		loc->x += off + adv + (off < 0);
X		break;
X	case L_NWEST :
X		loc->y += (-1 * adv) + (-1 * off) - (off < 0);
X		loc->x += off + (-1 * adv) - (off > 0);
X		break;
X	case L_SEAST :
X		loc->y += adv + off + (off < 0);
X		loc->x += (-1 * off) + adv + (off > 0);
X		break;
X	case L_SWEST :
X		loc->y += adv + (-1 * off) + (off > 0);
X		loc->x += (-1 * off) + (-1 * adv) - (off < 0);
X		break;
X	}
X}
X
X
Xint correct_loc(loc)
Xstruct location *loc;
X{
X	if(loc->y < 0 && loc->x >= MAPCOLS)
X		return -1;
X	if(loc->y < 0 && loc->x < 0)
X		return -1;
X	if(loc->y >= MAPROWS && loc->x < 0)
X		return -1;
X	if(loc->y >= MAPROWS && loc->x >= MAPCOLS)
X		return -1;
X
X	if(loc->x >= MAPCOLS) {
X		loc->x -= MAPCOLS;
X		loc->sector = mseg->m[loc->sector].links[L_EAST];
X	}
X
X	if(loc->x < 0) {
X		loc->x += MAPCOLS;
X		loc->sector = mseg->m[loc->sector].links[L_WEST];
X	}
X
X	if(loc->y >= MAPROWS) {
X		loc->y -= MAPROWS;
X		loc->sector = mseg->m[loc->sector].links[L_SOUTH];
X	}
X
X	if(loc->y < 0) {
X		loc->y += MAPROWS;
X		loc->sector = mseg->m[loc->sector].links[L_NORTH];
X	}
X
X	if(loc->sector < 0)
X		return -1;
X
X	return 0;
X}
X
X
Xbusy_wait(delay)
Xlong delay;
X{
X	for(; delay; delay--);
X}
X
X
Xseek_s(p_indx, v_indx)
Xint p_indx, v_indx;
X{
X	char buf[35];
X	int rc;
X
X	if(v_indx < 0 || v_indx >= MAX_PLAYERS)
X		return;
X
X	if(pseg->p[v_indx].loc.sector < 0
X	|| pseg->p[v_indx].playernum < 0
X	|| pseg->p[v_indx].blocked > 0) {
X		sprintf(buf, "%c not found.", (char)('1' + v_indx));
X		dmsg_add(p_indx, buf);
X	} else if((rc = jump_to(p_indx, pseg->p[v_indx].loc.sector)) == -1)
X		dmsg_add(p_indx, "seek bounced.");
X	else if(rc == -2)
X		dmsg_add(p_indx, "seek fizzled.");
X	else {
X		sprintf(buf, "%c found!", (char)('1' + v_indx));
X		dmsg_add(p_indx, buf);
X	}
X}
X
X
Xtoggle_obscure(item_indx)
Xint item_indx;
X{
X	if(item_indx < 0
X	|| item_indx >= pseg->item_count
X	|| pseg->itm[item_indx].loc.sector > -1)
X		return;
X
X	if(pseg->itm[item_indx].type == pseg->itm[item_indx].symbol)
X		pseg->itm[item_indx].symbol = HIDDEN;
X	else
X		pseg->itm[item_indx].symbol = pseg->itm[item_indx].type;
X
X	pseg->item_sem++;
X}
X
X
Xverify_item(indx, what)
Xint indx, what;
X{
X	char buf[35];
X
X	if(what < 0 || what >= pseg->item_count)
X		return;
X
X	if(pseg->itm[what].curse == 0)
X		sprintf(buf, "%s is OK", pseg->itm[what].name);
X	else
X		sprintf(buf, "%s is CURSED", pseg->itm[what].name);
X
X	dmsg_add(indx, buf);
X}
X
X
Xknight(p_indx)
Xint p_indx;
X{
X	dmsg_add(p_indx, "You feel more confident.");
X	pseg->p[p_indx].knight += rnd(KNIGHT_DUR);
X}
X
X
Xnightmare(p_indx, v_indx)
Xint p_indx, v_indx;
X{
X	char buf[35];
X	int choice;
X
X	if(v_indx < 0 || v_indx >= MAX_PLAYERS)
X		return;
X
X	if(pseg->p[v_indx].loc.sector < 0
X	|| pseg->p[v_indx].playernum < 0
X	|| pseg->p[v_indx].blocked > 0) {
X		sprintf(buf, "%c not found.", (char)('1' + v_indx));
X		dmsg_add(p_indx, buf);
X		return;
X	}
X
X	if((choice = nearestm(p_indx)) == -1) {
X		dmsg_add(p_indx, "No monster.");
X		return;
X	}
X
X	if(send_monster(choice, pseg->p[v_indx].loc.sector) == -1) {
X		dmsg_add(p_indx, "Can't send monster.");
X		return;
X	}
X
X	dmsg_add(p_indx, "Monster sent...");
X	dmsg_add(v_indx, "A Nightmare!!!");
X}
X
X
Xint nearestm(p_indx)
Xint p_indx;
X{
X	int result, dist, n_dist, i;
X	int dest_a, m_a, m_x, m_y;
X
X	result = -1;
X	dist = 100;
X
X	dest_a = pseg->p[p_indx].loc.sector;
X
X	for(i = 0; i < n_monster; i++) {
X		m_a = m_table[i].loc.sector;
X		m_x = m_table[i].loc.x;
X		m_y = m_table[i].loc.y;
X
X		if(m_a == dest_a
X		&& (n_dist = distance(p_indx, m_x, m_y)) < dist) {
X			dist = n_dist;
X			result = i;
X		}
X	}
X
X	return result;
X}
X
X
X/* end of file. */
END_OF_FILE
if test 17087 -ne `wc -c <'magic.c'`; then
    echo shar: \"'magic.c'\" unpacked with wrong size!
fi
# end of 'magic.c'
fi
if test -f 'players.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'players.c'\"
else
echo shar: Extracting \"'players.c'\" \(7711 characters\)
sed "s/^X//" >'players.c' <<'END_OF_FILE'
X/*
X	MDG Multiuser Dungeon Game -- players.c player 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 = "@(#) players.c\t(1.5)\tcreated 1/3/91";
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include <sys/types.h>
X#include <time.h>
X#include "setup.h"
X#include "files.h"
X#include "struct.h"
X
Xextern char *progname;
X
Xextern int errno;
Xextern char *sys_errlist[];
X
Xextern struct player_seg *pseg;
Xextern struct map_seg *mseg;
X
Xextern int player_size;
X
Xextern int memory[];
X
X
Xsaveplayer(indx)
Xint indx;
X{
X	char fname[128];
X	FILE *fp;
X	int i;
X	time_t time();
X
X	if(pseg->p[indx].playernum == -1) /* no such player */
X		return;
X
X	if(pseg->p[indx].loc.sector == LOC_NONESUCH 
X	&& pseg->p[indx].lives < 0) {	/* he died */
X		pseg->p[indx].playernum = -1;
X		pseg->player_sem++;
X		return;
X	}
X
X	sprintf(fname, "%s/pl%05d", PLAYERDIR, pseg->p[indx].playernum);
X
X	/* mark player's items as old */
X
X	for(i = 0; i < pseg->item_count; i++)
X		if(pseg->itm[i].loc.sector == LOC_PLAYER
X		&& pseg->itm[i].loc.x == pseg->p[indx].playernum)
X			pseg->itm[i].loc.y = ITEM_OLD;
X
X	/* save player's file */
X
X	if((fp = fopen(fname, "w")) == NULL)
X		return;
X		
X	fprintf(fp, "%s\n", pseg->p[indx].name);
X	fprintf(fp, "%ld\n", pseg->p[indx].gold);
X
X	for(i = 0; i < 26; i++) {
X		fprintf(fp, "%hd ", pseg->p[indx].spells[i]);
X		if(((i + 1) % 13) == 0)
X			putc('\n', fp);
X	}
X
X	fprintf(fp, "%hd:%hd\n", pseg->p[indx].max_hp, 
X		pseg->p[indx].hitpoints);
X
X	fprintf(fp, "%hd:%hd\n", pseg->p[indx].max_mp, 
X		pseg->p[indx].magicpts);
X
X	fprintf(fp, "%hd\n", pseg->p[indx].fighting);
X
X	fprintf(fp, "[%d/%d]\n", pseg->p[indx].loc.x, pseg->p[indx].home);
X
X	fprintf(fp, "%d\n", pseg->p[indx].lives);
X
X	fprintf(fp, "%ld\n", time(NULL) - DATE_OFFSET);
X
X	fprintf(fp, "%hd\n", pseg->p[indx].createpts);
X
X	fprintf(fp, "al = %hd\n", pseg->p[indx].alignment);
X
X	fclose(fp);
X
X	pseg->p[indx].playernum = -1;
X
X	pseg->player_sem++;
X}
X
X
Xdmsg_all(msg)
Xchar *msg;
X{
X	int i;
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		if(pseg->p[i].playernum >= 0)
X			dmsg_add(i, msg);
X}
X
X
Xint loadplayer(indx, playernum)
Xint indx, playernum;
X{
X	char fname[128], altfname[128], profname[128], *p;
X	char tmpname[PNAMELEN];
X	long time_out, time_old, time_diff;
X	time_t time();
X	FILE *fp;
X	int i, startsect;
X
X	sprintf(fname, "%s/pl%05d", PLAYERDIR, playernum);
X	sprintf(altfname, "%s/default", PLAYERDIR);
X	sprintf(profname, "%s/pr%05d", PLAYERDIR, playernum);
X
X	pseg->weapon[indx] = -1;
X	pseg->armor[indx] = -1;
X	pseg->shield[indx] = -1;
X	pseg->p[indx].dmsg[0][0] = '\0';
X	pseg->p[indx].dmsg[1][0] = '\0';
X	pseg->p[indx].dmsg_loc = -1;
X	pseg->p[indx].brief = 0;
X	pseg->p[indx].clock = 0;
X	pseg->p[indx].detect = 0;
X	pseg->p[indx].light = 0;
X	pseg->p[indx].blocked = 0;
X	pseg->p[indx].invis = 0;
X	pseg->p[indx].knight = 0;
X	pseg->p[indx].user_spell = 0;
X	pseg->p[indx].gold_hidden = 0;
X	pseg->p[indx].ma_count = 0;
X	pseg->p[indx].m_armor = 0;
X	pseg->p[indx].createpts = 0;
X
X	memory[indx] = LOC_NONESUCH;
X
X	if((fp = fopen(profname, "r")) == NULL)
X		pseg->p[indx].name[0] = '\0';
X	else {
X		fgets(pseg->p[indx].name, 20, fp);
X		fclose(fp);
X	}
X
X	if((fp = fopen(fname, "r")) == NULL 
X	&& (fp = fopen(altfname, "r")) == NULL)
X		return;
X
X	fgets(tmpname, 20, fp);
X
X	if(pseg->p[indx].name[0] == '\0')
X		strcpy(pseg->p[indx].name, tmpname);
X
X	for(p = pseg->p[indx].name; *p; p++)
X		if(*p == '\n')
X			*p = '\0';
X
X	if(pseg->p[indx].name[0] == '\0')
X		get_handle(pseg->p[indx].name, playernum);
X
X	fscanf(fp, "%ld\n", &(pseg->p[indx].gold));
X
X	for(i = 0; i < 26; i++)
X		fscanf(fp, "%hd", &(pseg->p[indx].spells[i]));
X
X	fscanf(fp, "%hd:%hd\n", &(pseg->p[indx].max_hp),
X		&(pseg->p[indx].hitpoints));
X
X	fscanf(fp, "%hd:%hd\n", &(pseg->p[indx].max_mp),
X		&(pseg->p[indx].magicpts));
X
X	fscanf(fp, "%hd\n", &(pseg->p[indx].fighting));
X
X	fscanf(fp, "[%d/%d]\n", &startsect, &(pseg->p[indx].home));
X
X	fscanf(fp, "%d\n", &(pseg->p[indx].lives));
X
X	fscanf(fp, "%ld\n", &time_old);
X
X	fscanf(fp, "%hd\n", &(pseg->p[indx].createpts));
X
X	fscanf(fp, "al = %hd\n", &(pseg->p[indx].alignment));
X
X	fclose(fp);
X
X	for(i = 0; i < MAX_PLAYERS; i++)
X		pseg->p[indx].partners[i] = pseg->p[indx].alignment;
X
X	time_diff = (time(NULL) - DATE_OFFSET) - time_old;
X
X	if(time_diff > 600)
X		time_diff = 600;
X
X	time_out = time_diff / TIME_TO_HEAL;
X
X	while(time_out--)
X		heal_a_player(indx);
X
X	if(startsect < 0 || startsect >= mseg->max_areas)
X		startsect = 0;
X
X	if(place(indx, startsect) == -1
X	&& place(indx, 0) == -1)
X		return;
X
X	pseg->p[indx].prev_sect = startsect;
X
X	pseg->p[indx].playernum = playernum;
X
X	for(i = 0; i < PMAX_ITEMS; i++)
X		pseg->p[indx].items[i] = -1;
X
X	for(i = 0; i < pseg->item_count; i++)
X		if(pseg->itm[i].loc.sector == LOC_PLAYER
X		&& pseg->itm[i].loc.x == pseg->p[indx].playernum) {
X			insert_item(indx, i);
X			freshen_item(i);
X		}
X
X	move_sym(&(pseg->p[indx].loc), 1 + indx);
X
X	pseg->player_sem++;
X}
X
X
Xplace(p_indx, startsect)
Xint p_indx, startsect;
X{
X	int rc, x, y;
X
X	for(x = MAPCOLS / 3; x < (2 * (MAPCOLS / 3)); x++)
X	for(y = MAPROWS / 3; y < 2 * (MAPROWS / 3); y++) {
X		if(try_spot(p_indx, startsect, x, y) == 0)
X			return 0;
X	}
X
X	return -1;
X}
X
X
Xint try_spot(p_indx, startsect, x, y)
Xint p_indx, startsect, x, y;
X{
X	if(isdigit(mseg->m[startsect].map[y][x]))
X		return -1;
X
X	if(mseg->m[startsect].map[y][x] == '~'
X	|| mseg->m[startsect].map[y][x] == '%'
X	|| mseg->m[startsect].map[y][x] == '^')
X		return -1;
X
X	if(move_to(&(pseg->p[p_indx].loc), startsect, x, y, p_indx) == 0)
X		return 0;
X
X	return -1;
X}
X
X
Xabortplayer(indx)
Xint indx;
X{
X	int sector, x, y, under;
X
X	sector = pseg->p[indx].loc.sector;
X	x = pseg->p[indx].loc.x;
X	y = pseg->p[indx].loc.y;
X	under = pseg->p[indx].loc.under;
X
X	if(sector < 0)
X		return;
X
X	mseg->m[sector].map[y][x] = under;
X
X	drop_new(indx, sector, x, y);
X
X	pseg->p[indx].playernum = -1;
X
X	pseg->player_sem++;
X
X	mseg->map_sem++;
X
X	notify(sector);
X}
X
X
Xdrop_new(p_indx, sector, x, y)
Xint p_indx, sector, x, y;
X{
X	int i, playernum;
X
X	playernum = pseg->p[p_indx].playernum;
X
X	for(i = 0; i < pseg->item_count; i++)
X		if(pseg->itm[i].loc.sector == LOC_PLAYER
X		&& pseg->itm[i].loc.x == playernum
X		&& pseg->itm[i].loc.y == ITEM_NEW)
X			if(put_item(i, sector, x, y) == -1)
X				pseg->itm[i].loc.sector = LOC_NONESUCH;
X
X	notify(sector);
X}
X
X
Xdel_player(p_indx)
Xint p_indx;
X{
X	char fname[128];
X	int temp_x;
X
X	pseg->p[p_indx].lives--;
X
X	if(pseg->p[p_indx].lives >= 0) {
X		pseg->p[p_indx].hitpoints = 1;
X		temp_x = pseg->p[p_indx].loc.x;
X		pseg->p[p_indx].loc.x = 0;
X		pseg->p[p_indx].gold = 0;
X		pseg->player_sem++;
X		saveplayer(p_indx);
X		pseg->p[p_indx].loc.x = temp_x;
X		pseg->p[p_indx].hitpoints = 0;
X		pseg->player_sem++;
X		tell_player(p_indx);
X	} else {
X		sprintf(fname, "%s/pl%05d", PLAYERDIR, 
X			pseg->p[p_indx].playernum);
X		unlink(fname);
X	}
X}
X
X
Xheal_players()
X{
X	int indx;
X
X	for(indx = 0; indx < MAX_PLAYERS; indx++) {
X		if(pseg->p[indx].playernum >= 0 
X		&& pseg->p[indx].loc.sector >= 0
X		&& ++pseg->p[indx].clock > TIME_TO_HEAL) 
X			heal_a_player(indx);
X		if(pseg->p[indx].playernum >= 0
X		&& (pseg->p[indx].loc.sector == LOC_NONESUCH
X		|| pseg->p[indx].loc.sector == LOC_HOME)) {
X			pseg->player_sem++;
X			tell_player(indx);
X		}
X	}
X}
X
X
Xheal_a_player(indx)
Xint indx;
X{
X	pseg->p[indx].clock = 0;
X
X	if(pseg->p[indx].hitpoints < pseg->p[indx].max_hp) {
X		pseg->p[indx].hitpoints += 
X			rnd(pseg->p[indx].max_hp / HEAL_DIV);
X		if(pseg->p[indx].hitpoints > pseg->p[indx].max_hp)
X			pseg->p[indx].hitpoints = pseg->p[indx].max_hp;
X		pseg->player_sem++;
X	} 
X	
X	if(pseg->p[indx].hitpoints > MIN_HPS
X	&& pseg->p[indx].magicpts < pseg->p[indx].max_mp) {
X		pseg->p[indx].magicpts += CHARGE_INC;
X		pseg->player_sem++;
X	}
X
X	tell_player(indx);
X}
X
X
X/* end of file. */
END_OF_FILE
if test 7711 -ne `wc -c <'players.c'`; then
    echo shar: \"'players.c'\" unpacked with wrong size!
fi
# end of 'players.c'
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
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