michael@stb.info.com (Michael Gersten) (04/06/91)
cat > monsters.c << SHAR_EOF_monsters.c
/*
MDG Multiuser Dungeon Game -- monsters.c monster code
MDG is Copyright 1990 John C. Gonnerman
This program is subject to the general MDG
copyright statement (see enclosed file, Copyright).
*/
static char *sccsvers = "@(#) monsters.c\t(1.2)\tcreated 1/12/91";
#include <stdio.h>
#include "setup.h"
#include "struct.h"
extern char *progname;
extern int errno;
extern char *sys_errlist[];
extern struct map_seg *mseg;
extern struct player_seg *pseg;
extern int map_size, player_size;
extern struct monster_tbl *m_table;
extern int n_monster;
int mon_count = 0;
move_monsters()
{
int i, j;
if (++mon_count < MON_TIME)
return;
mon_count = 0;
for(i = 0; i < n_monster; i++) {
if(m_table[i].loc.sector == LOC_NONESUCH)
resurrect(i);
else if(player_here(m_table[i].loc.sector))
for(j = m_table[i].mv_used; j < m_table[i].mv; j++)
do_a_monster(i);
else
roll_over(i);
m_table[i].mv_used = 0;
m_table[i].att_used = 0;
}
}
pace_monsters()
{
int i;
for(i = 0; i < n_monster; i++)
if(m_table[i].mv_used < m_table[i].mv
&& player_here(m_table[i].loc.sector)) {
m_table[i].mv_used++;
do_a_monster(i);
}
}
roll_over(m_indx)
int m_indx;
{
int dir;
if((dir = at_edge(m_indx)) < 0)
return;
if(player_here(mseg->m[m_table[m_indx].loc.sector].links[dir]))
move_a_monster(m_indx, dir);
}
int at_edge(m_indx)
int m_indx;
{
switch(m_table[m_indx].loc.x) {
case 0 :
return L_WEST;
case MAPCOLS - 1 :
return L_EAST;
}
switch(m_table[m_indx].loc.y) {
case 0 :
return L_NORTH;
case MAPROWS - 1 :
return L_SOUTH;
}
return -1;
}
move_a_monster(m_indx, dir)
int m_indx;
unsigned char dir;
{
struct location loc;
int sector;
if((sector = m_table[m_indx].loc.sector) < 0)
return;
loc.sector = m_table[m_indx].loc.sector;
loc.x = m_table[m_indx].loc.x;
loc.y = m_table[m_indx].loc.y;
mseg->m[loc.sector].map[loc.y][loc.x] = m_table[m_indx].loc.under;
if(get_dest(&loc, dir) != -1)
mmove_subcmd(m_indx, loc.sector, loc.x, loc.y);
move_sym(&(m_table[m_indx].loc), m_table[m_indx].m_sym);
mseg->map_sem++;
}
mmove_subcmd(m_indx, dest_a, dest_x, dest_y)
int m_indx, dest_a, dest_x, dest_y;
{
int rc;
rc = move_to(&(m_table[m_indx].loc), dest_a, dest_x, dest_y, -1);
if(is_player(rc))
mattack(m_indx, dest_a, dest_x, dest_y);
if(rc == 0) {
if(dest_a != m_table[m_indx].loc.sector)
notify(m_table[m_indx].loc.sector);
notify(dest_a);
}
}
int player_here(sector)
int sector;
{
int i;
if(sector < 0)
return 0;
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].playernum >= 0
&& pseg->p[i].loc.sector == sector)
return 1;
return 0;
}
int num_player_here(sector)
int sector;
{
int i, j;
j = 0;
if(sector < 0)
return 0;
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].playernum >= 0
&& pseg->p[i].loc.sector == sector)
j++;
return j;
}
do_a_monster(m_indx)
int m_indx;
{
int target_indx, rc;
int m_x, m_y, m_a, p_x, p_y, p_a;
if(m_table[m_indx].loc.sector < 0)
return;
m_table[m_indx].decay_cnt = 0;
m_x = m_table[m_indx].loc.x;
m_y = m_table[m_indx].loc.y;
m_a = m_table[m_indx].loc.sector;
if((target_indx = nearest(m_a, m_x, m_y)) == -1)
return;
p_x = pseg->p[target_indx].loc.x;
p_y = pseg->p[target_indx].loc.y;
p_a = pseg->p[target_indx].loc.sector;
mseg->m[m_a].map[m_y][m_x] = m_table[m_indx].loc.under;
if(m_x == p_x)
app_m_move(m_indx, (m_y < p_y ? L_SOUTH : L_NORTH ));
else if(m_y == p_y)
app_m_move(m_indx, (m_x < p_x ? L_EAST : L_WEST ));
else if(m_x < p_x)
app_m_move(m_indx, (m_y < p_y ? L_SEAST : L_NEAST ));
else if(m_x > p_x)
app_m_move(m_indx, (m_y < p_y ? L_SWEST : L_NWEST ));
move_sym(&(m_table[m_indx].loc), m_table[m_indx].m_sym);
mseg->map_sem++;
notify(m_a);
}
app_m_move(m_indx, dir)
int m_indx, dir;
{
if(rnd(100) <= m_table[m_indx].iq)
dir = smart_dir(m_indx, dir);
else
dir = stupid_dir(dir);
move_a_monster(m_indx, dir);
}
int smart_dir(m_indx, dir)
int m_indx, dir;
{
int ndir, mdir, nturn, mturn;
mturn = rnd(2) - 1;
nturn = mturn == 1 ? 0 : 1;
if(test_dir(m_indx, dir))
return dir;
if(test_dir(m_indx, (ndir = turn_it(dir, nturn))))
return ndir;
if(test_dir(m_indx, (mdir = turn_it(dir, mturn))))
return mdir;
if(test_dir(m_indx, (ndir = turn_it(ndir, nturn))))
return ndir;
return turn_it(mdir, mturn);
}
int test_dir(m_indx, dir)
int m_indx, dir;
{
struct location loc;
int at_spot;
loc = m_table[m_indx].loc;
if(get_dest(&loc, dir) == -1
|| loc.sector < 0)
return 0;
at_spot = mseg->m[loc.sector].map[loc.y][loc.x];
if(is_clear(at_spot) || is_player(at_spot))
return 1;
return 0;
}
int stupid_dir(dir)
int dir;
{
switch(rnd(7)) {
case 1 :
case 2 :
return turn_it(dir, 0);
case 3 :
case 4 :
case 5 :
return dir;
case 6 :
case 7 :
return turn_it(dir, 1);
}
}
int turn_it(dir, rot)
int dir, rot;
{
switch(dir) {
case L_NORTH :
return (rot ? L_NEAST : L_NWEST);
case L_NEAST :
return (rot ? L_EAST : L_NORTH);
case L_EAST :
return (rot ? L_SEAST : L_NEAST);
case L_SEAST :
return (rot ? L_SOUTH : L_EAST);
case L_SOUTH :
return (rot ? L_SWEST : L_SEAST);
case L_SWEST :
return (rot ? L_WEST : L_SOUTH);
case L_WEST :
return (rot ? L_NWEST : L_SWEST);
case L_NWEST :
return (rot ? L_NORTH : L_WEST);
}
}
int nearest(dest_a, dest_x, dest_y)
int dest_a, dest_x, dest_y;
{
int result, dist, n_dist, i;
result = -1;
dist = 100;
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].playernum != -1
&& pseg->p[i].loc.sector == dest_a
&& !pseg->p[i].invis
&& (n_dist = distance(i, dest_x, dest_y)) < dist) {
dist = n_dist;
result = i;
}
return result;
}
int distance(indx, dest_x, dest_y)
int indx, dest_x, dest_y;
{
int x_off, y_off;
x_off = pseg->p[indx].loc.x - dest_x;
y_off = pseg->p[indx].loc.y - dest_y;
if(x_off < 0)
x_off *= -1;
if(y_off < 0)
y_off *= -1;
return x_off + y_off;
}
int count_monsters(sector)
{
int i, cnt;
cnt = 0;
for(i = 0; i < n_monster; i++)
if(m_table[i].loc.sector == sector)
cnt++;
return cnt;
}
addMonster(sector)
{
/* Take a monster from the dead list, and put it
in the sector. (Idea is to normally not resurrect
monsters, but to add them instead). Future: Increase
the number of living monsters */
int lev, mon;
lev = mseg->m[sector].level;
mon = find_monster(lev);
if (mon != -1)
place_a_monster (sector, mon);
}
find_monster(lev)
{
/* Look through the monster table for a monster of
level lev-4 to lev */
static int last_mon = -1;
int i, n, last_choice, mon;
for(i = last_choice +1, n=n_monster-1;
n >= 0; i++, n--)
{
if (i >= n_monster)
i = 0;
if (m_table[i].level > lev-4
&& m_table[i].level < lev+1
&& m_table[i].loc.sector == LOC_NONESUCH)
{
mon=i;
if (rnd(4) == 1)
return mon;
}
}
return -1;
}
resurrect(m_indx)
int m_indx;
{
int rc;
int dest_a, dest_x, dest_y, at_loc;
if(rnd(100) > RESURRECTION)
return;
dest_a = rnd(mseg->max_areas - 1); /* never at sector 0 */
if (dest_a == 0)
dest_a = mseg->max_areas - 1;
if(player_here(dest_a)
|| mseg->m[dest_a].level < m_table[m_indx].level
|| count_monsters(dest_a) >= MAX_MONSTERS
|| m_table[m_indx].level < (mseg->m[dest_a].level - 4))
return;
if (count_monsters(dest_a) > MAX_MONSTERS/2
&& rnd(4) != 1)
return;
place_a_monster(dest_a, m_indx);
}
place_a_monster(dest_a, m_indx)
{
int rc;
int dest_x, dest_y, at_loc;
dest_x = rnd(MAPCOLS) - 1;
dest_y = rnd(MAPROWS) - 1;
at_loc = mseg->m[dest_a].map[dest_y][dest_x];
if(at_loc == '%' || at_loc == '~' || at_loc == '^')
return;
rc = move_to(&(m_table[m_indx].loc), dest_a, dest_x, dest_y, -1);
m_table[m_indx].decay_cnt = 0;
if(rc == 0) {
move_sym(&(m_table[m_indx].loc), m_table[m_indx].m_sym);
m_table[m_indx].hp = m_table[m_indx].max_hp;
mseg->map_sem++;
notify(dest_a);
}
}
lift_a_monster(m_indx)
int m_indx;
{
int sector, x, y;
sector = m_table[m_indx].loc.sector;
x = m_table[m_indx].loc.x;
y = m_table[m_indx].loc.y;
mseg->m[sector].map[y][x] = m_table[m_indx].loc.under;
}
/* end of file. */
SHAR_EOF_monsters.c
cat > combat.c << SHAR_EOF_combat.c
/*
MDG Multiuser Dungeon Game -- combat.c battle handlers
MDG is Copyright 1990 John C. Gonnerman
This program is subject to the general MDG
copyright statement (see enclosed file, Copyright).
*/
static char *sccsvers = "@(#) combat.c\t(1.5)\tcreated 1/13/91";
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "setup.h"
#include "struct.h"
#include "combat.h"
extern struct map_seg *mseg;
extern struct player_seg *pseg;
extern int dqid, map_size, player_size;
extern struct monster_tbl *m_table;
extern int n_monster;
attack(p_indx, dest_a, dest_x, dest_y)
int p_indx, dest_a, dest_x, dest_y;
{
int i, attacker_indx;
attacker_indx = p_indx;
if(pseg->p[attacker_indx].attacks == 0)
return;
pseg->p[attacker_indx].attacks--;
if(is_player(mseg->m[dest_a].map[dest_y][dest_x])) {
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].loc.sector == dest_a
&& pseg->p[i].loc.x == dest_x
&& pseg->p[i].loc.y == dest_y)
pattackp(attacker_indx, i);
} else {
for(i = 0; i < n_monster; i++)
if(m_table[i].loc.sector == dest_a
&& m_table[i].loc.x == dest_x
&& m_table[i].loc.y == dest_y)
pattackm(attacker_indx, i);
pace_monsters();
}
}
mattack(m_indx, dest_a, dest_x, dest_y)
int m_indx, dest_a, dest_x, dest_y;
{
int i;
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].loc.sector == dest_a
&& pseg->p[i].loc.x == dest_x
&& pseg->p[i].loc.y == dest_y)
switch(m_table[m_indx].attack) {
case ATT_BREATH :
/* not done yet. */
case ATT_HITS :
mattackp(m_indx, i);
break;
case ATT_STEALS :
mstealp(m_indx, i);
break;
case ATT_DRAINS :
mdrainp(m_indx, i);
break;
case ATT_DRAINMP :
mdrainmp(m_indx, i);
break;
case ATT_DRAINHP :
mdrainhp(m_indx, i);
break;
case ATT_DRAINLIFE :
mdrainl(m_indx, i);
break;
}
}
int mhit(a_indx, v_indx)
int a_indx, v_indx;
{
int chance;
chance = 50 + m_table[a_indx].fight - pseg->p[v_indx].fighting;
chance = (chance + 51) / 2;
if(chance < MIN_CHANCE)
chance = MIN_CHANCE;
if(chance > MAX_CHANCE)
chance = MAX_CHANCE;
return rnd(100) <= chance;
}
int ccomp(odds, a_indx)
int odds, a_indx;
{
odds = (odds + 51) / 2;
if(pseg->p[a_indx].knight)
odds += 30;
if(odds < MIN_CHANCE)
odds = MIN_CHANCE;
if(odds > MAX_CHANCE)
odds = MAX_CHANCE;
return odds;
}
int phitm(a_indx, v_indx)
int a_indx, v_indx;
{
int chance, real_chance;
real_chance = 50 + pseg->p[a_indx].fighting - m_table[v_indx].fight;
chance = ccomp(real_chance, a_indx);
if(rnd(100) <= chance) {
improve_f(a_indx, real_chance);
return 1;
}
return 0;
}
int phitp(a_indx, v_indx)
int a_indx, v_indx;
{
int chance, real_chance;
real_chance = 50 + pseg->p[a_indx].fighting - pseg->p[v_indx].fighting;
chance = ccomp(real_chance, a_indx);
if(rnd(100) <= chance) {
improve_f(a_indx, real_chance);
return 1;
}
return 0;
}
int mdamage(a_indx)
int a_indx;
{
return rnd(m_table[a_indx].max_dam);
}
int pdamage(a_indx)
int a_indx;
{
int wpn, eff;
wpn = pseg->weapon[a_indx];
if(wpn < 0)
return rnd(pseg->p[a_indx].fighting / 20);
else if(wpn < pseg->item_count) {
eff = pseg->itm[wpn].effect;
if(pseg->itm[wpn].curse)
eff = 0;
return rnd(eff);
} else {
fprintf(stderr,
"weapon range error, pnum = %d, wpn = %d\n",
pseg->p[a_indx].playernum, wpn);
pseg->weapon[a_indx] = -1;
}
return 0;
}
int ptakedamage(v_indx, damage)
int v_indx, damage;
{
if(damage < 0)
damage = 0;
pseg->p[v_indx].hitpoints -= damage;
pseg->player_sem++;
tell_player(v_indx);
if(pseg->p[v_indx].hitpoints < 1) {
killp(v_indx);
return -1;
}
return 0;
}
int pgetzapped(v_indx, damage)
int v_indx, damage;
{
if(pseg->p[v_indx].ma_count > 0)
damage = dcomp(damage, pseg->p[v_indx].m_armor);
return(ptakedamage(v_indx, damage));
}
int pgethit(v_indx, damage)
int v_indx, damage;
{
int armor, ai, si;
armor = 0;
ai = pseg->armor[v_indx];
if(ai >= 0) {
if(ai >= pseg->item_count) {
fprintf(stderr,
"Armor index out of range (%d)\n", ai);
pseg->armor[v_indx] = -1;
} else if(pseg->itm[ai].curse == 0) {
armor += pseg->itm[ai].effect;
}
}
si = pseg->shield[v_indx];
if(si >= 0) {
if(si >= pseg->item_count) {
fprintf(stderr,
"Shield index out of range (%d)\n", si);
pseg->shield[v_indx] = -1;
} else if(pseg->itm[si].curse == 0) {
armor += pseg->itm[si].effect;
}
}
damage -= armor;
return(pgetzapped(v_indx, damage));
}
int mgethit(v_indx, damage)
int v_indx, damage;
{
if(damage < 1)
damage = 1;
if(m_table[v_indx].hp > m_table[v_indx].max_hp)
m_table[v_indx].hp = m_table[v_indx].max_hp;
m_table[v_indx].hp -= damage;
if(m_table[v_indx].hp < 1) {
killm(v_indx);
return -1;
}
return 0;
}
pattackp(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
int damage;
if(pseg->p[v_indx].loc.sector == 0)
return;
if(pseg->p[a_indx].partners[v_indx] == 1)
return;
visible(a_indx);
sprintf(buf, "%c attacked you!", '1' + a_indx);
dmsg_add(v_indx, buf);
if(!phitp(a_indx, v_indx)) {
if(pseg->p[a_indx].brief)
dmsg_add(a_indx, "You missed");
else
dmsg_add(a_indx, "You missed the player");
return;
}
damage = pdamage(a_indx);
if(pseg->p[a_indx].brief)
dmsg_add(a_indx, "Hit player!");
else {
dmsg_add(a_indx, "You hit the player!");
sprintf(buf, "Damage: %d", damage);
dmsg_add(a_indx, buf);
}
sprintf(buf, "%c HIT you!", '1' + a_indx);
dmsg_add(v_indx, buf);
if(pgethit(v_indx, damage) == -1) {
dmsg_add(a_indx, "You KILLED the player!");
pseg->p[a_indx].lives++;
pseg->player_sem++;
improve_h(a_indx, d_level(v_indx));
}
}
pattackm(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
int damage;
visible(a_indx);
if(!phitm(a_indx, v_indx)) {
if(pseg->p[a_indx].brief) {
sprintf(buf, "Missed %s", m_table[v_indx].name);
dmsg_add(a_indx, buf);
} else {
sprintf(buf, "You missed the %s", m_table[v_indx].name);
dmsg_add(a_indx, buf);
}
return;
}
damage = pdamage(a_indx);
if(pseg->p[a_indx].brief) {
sprintf(buf, "Hit %s!", m_table[v_indx].name, damage);
dmsg_add(a_indx, buf);
} else {
sprintf(buf, "You hit the %s!", m_table[v_indx].name, damage);
dmsg_add(a_indx, buf);
sprintf(buf, "Damage: %d", damage);
dmsg_add(a_indx, buf);
}
if(mgethit(v_indx, damage) == -1) {
sprintf(buf, "You KILLED the %s", m_table[v_indx].name);
dmsg_add(a_indx, buf);
improve_h(a_indx, m_table[v_indx].danger);
}
}
mattackp(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
if(m_table[a_indx].att_used >= M_ATTACKS)
return;
m_table[a_indx].att_used++;
if(!mhit(a_indx, v_indx)) {
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s missed you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
return;
}
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s HIT you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
(void)pgethit(v_indx, mdamage(a_indx));
}
mdrainp(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
if(m_table[a_indx].att_used >= M_ATTACKS)
return;
m_table[a_indx].att_used++;
if(!mhit(a_indx, v_indx)) {
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s missed you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
return;
}
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s HIT you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
pseg->p[v_indx].magicpts -= mdamage(a_indx);
if(pseg->p[v_indx].magicpts < 0) {
pseg->p[v_indx].magicpts = 0;
(void)pgetzapped(v_indx, mdamage(a_indx));
}
}
mdrainl(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
if(m_table[a_indx].att_used >= M_ATTACKS)
return;
m_table[a_indx].att_used++;
if(!mhit(a_indx, v_indx)) {
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s missed you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
return;
}
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s HIT you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
pseg->p[v_indx].lives--;
if(pseg->p[v_indx].lives < 0) {
pseg->p[v_indx].lives = 0;
(void)pgetzapped(v_indx, mdamage(a_indx));
}
clearm(a_indx, 0);
}
mdrainhp(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
int damage;
if(m_table[a_indx].att_used >= M_ATTACKS)
return;
m_table[a_indx].att_used++;
if(!mhit(a_indx, v_indx)) {
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s missed you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
return;
}
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s HIT you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
if(pseg->p[v_indx].ma_count > 0)
damage = dcomp(mdamage(a_indx), pseg->p[v_indx].m_armor);
else
damage = mdamage(a_indx);
pseg->p[v_indx].max_hp -= damage;
if(pseg->p[v_indx].max_hp < 2) {
pseg->p[v_indx].max_hp = 2;
(void)pgetzapped(v_indx, mdamage(a_indx));
}
if(pseg->p[v_indx].hitpoints > pseg->p[v_indx].max_hp)
pseg->p[v_indx].hitpoints = pseg->p[v_indx].max_hp;
clearm(a_indx, 0);
}
mdrainmp(a_indx, v_indx)
int a_indx, v_indx;
{
char buf[35];
int damage;
if(m_table[a_indx].att_used >= M_ATTACKS)
return;
m_table[a_indx].att_used++;
if(!mhit(a_indx, v_indx)) {
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s missed you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
return;
}
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s HIT you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
if(pseg->p[v_indx].ma_count > 0)
damage = dcomp(mdamage(a_indx), pseg->p[v_indx].m_armor);
else
damage = mdamage(a_indx);
pseg->p[v_indx].max_mp -= damage;
if(pseg->p[v_indx].max_mp < 2) {
pseg->p[v_indx].max_mp = 2;
(void)pgetzapped(v_indx, mdamage(a_indx));
}
if(pseg->p[v_indx].magicpts > pseg->p[v_indx].max_mp)
pseg->p[v_indx].magicpts = pseg->p[v_indx].max_mp;
clearm(a_indx, 0);
}
#ifdef BUGGED_CODE_DO_NOT_USE
int dcomp(damage, armor)
int damage, armor;
{
int final_damage;
final_damage = damage - armor;
/* This routine is called with the magic armor value in armor.
It can never be more than 6, so if damage is > 10 this section
does nothing */
if(damage > 10) {
if(final_damage < -20)
final_damage = 0;
else if(final_damage < 1)
final_damage = 1;
} else {
/* Now this section allows the possibility of taking a point
of damage with magic armor that would not have been taken without
the magic armor */
if(final_damage < -10)
final_damage = 0;
else if(final_damage < 1)
final_damage = 1;
}
return final_damage;
}
#else
int dcomp(damage, armor)
{
if (damage < 0)
return 0;
if (damage < armor)
return 1; /* magic armor can't stop everything */
return damage-armor;
}
#endif
mstealp(a_indx, v_indx)
int a_indx, v_indx;
{
int trys, item, i;
char buf[35];
if(m_table[a_indx].att_used >= M_ATTACKS)
return;
m_table[a_indx].att_used++;
if(!mhit(a_indx, v_indx)) {
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s missed you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
return;
}
if(!pseg->p[v_indx].brief) {
sprintf(buf, "%s HIT you!", m_table[a_indx].name);
dmsg_add(v_indx, buf);
}
if(rnd(PMAX_ITEMS) == 1) {
pseg->p[v_indx].gold -= go2r(pseg->p[v_indx].gold);
pseg->player_sem++;
return;
}
for(trys = 0; trys < 3; trys++) {
item = rnd(PMAX_ITEMS) - 1;
if((i = pseg->p[v_indx].items[item]) != -1) {
pseg->itm[i].loc.sector = LOC_NONESUCH;
delete_item(v_indx, i);
deselect(v_indx, i);
pseg->item_sem++;
pseg->player_sem++;
return;
}
}
}
killp(v_indx)
int v_indx;
{
int sector, x, y;
sector = pseg->p[v_indx].loc.sector;
x = pseg->p[v_indx].loc.x;
y = pseg->p[v_indx].loc.y;
mseg->m[sector].map[y][x] = pseg->p[v_indx].loc.under;
drop_all(v_indx, sector, x, y);
mseg->map_sem++;
del_player(v_indx);
pseg->p[v_indx].loc.sector = LOC_NONESUCH;
notify(sector);
pseg->player_sem++;
tell_player(v_indx);
}
clearm(v_indx, t_flag)
int v_indx, t_flag;
{
int sector, x, y;
sector = m_table[v_indx].loc.sector;
x = m_table[v_indx].loc.x;
y = m_table[v_indx].loc.y;
if (sector < 0) return;
mseg->m[sector].map[y][x] = m_table[v_indx].loc.under;
if(t_flag)
do_treasure(v_indx);
mseg->map_sem++;
m_table[v_indx].loc.sector = LOC_NONESUCH;
m_table[v_indx].decay_cnt = 0;
}
killm(v_indx)
int v_indx;
{
int sector;
sector = m_table[v_indx].loc.sector;
clearm(v_indx, 1);
notify(sector);
}
do_treasure(v_indx)
int v_indx;
{
int tval, danger;
int sector, x, y;
sector = m_table[v_indx].loc.sector;
x = m_table[v_indx].loc.x;
y = m_table[v_indx].loc.y;
danger = m_table[v_indx].danger;
if(danger >= DANGER_CUT && rnd(CRYSTAL_ODDS) == 1) {
put_crystal(sector, x, y);
return;
}
tval = (m_table[v_indx].max_hp + (danger * 10)) / 2;
#ifdef OLD_CODE_0
/* Used to be: Weak monsters had small chance of treasure, could
be anything. */
if(rnd(100) > tval)
return;
#else
/* Now: Chance of treasure is nearly flat. Stronger monsters have bigger
treasure */
if (rnd(100) > tval && rnd(4) == 1)
return;
switch(rnd(2)) {
case 1 :
put_item_tr(sector, x, y, tval * 20);
break;
case 2 :
put_treasure(tval * 20, sector, x, y);
break;
}
}
put_treasure(max_cash, sector, x, y)
int max_cash, sector, x, y;
{
int i;
for(i = 0; i < pseg->item_count; i++) {
if(pseg->itm[i].loc.sector == LOC_NONESUCH
&& pseg->itm[i].type == CASH) {
pseg->itm[i].decay_cnt = 0;
pseg->itm[i].loc.under = mseg->m[sector].map[y][x];
pseg->itm[i].value = rnd(max_cash);
(void)put_item(i, sector, x, y);
return;
}
}
/* If we got here, we are out of treasure spots. */
/* TARGET: Need to make new ones */
dmsg_all("Out Of Treasure Slots!");
}
put_crystal(sector, x, y)
int sector, x, y;
{
int i;
for(i = 0; i < pseg->item_count; i++) {
if(pseg->itm[i].loc.sector == LOC_NONESUCH
&& pseg->itm[i].type == CRYSTAL) {
pseg->itm[i].decay_cnt = 0;
pseg->itm[i].loc.under = mseg->m[sector].map[y][x];
pseg->itm[i].effect = 3 - go2r(2);
(void)put_item(i, sector, x, y);
return;
}
}
}
put_item_tr(sector, x, y, max_val)
int sector, x, y, max_val;
{
int i, n;
long min_val;
static int choice = -1;
static int last_choice = 0;
/* Previously the award was based solely on danger. This made
it impossible to award the top of the line prizes. */
/* Now give 1/3 to 2/3 the cash value in prizes. Winners pay
all income tax themselves. Void where prohibited. */
max_val = max_val * 2 / 3;
min_val = max_val / 2;
for(i = last_choice +1, n=pseg->item_count-1;
n >= 0; i++, n--) {
if (i >= pseg->item_count)
i = 0;
if(pseg->itm[i].loc.sector == LOC_NONESUCH
&& pseg->itm[i].type != CRYSTAL
&& pseg->itm[i].type != CASH
&& pseg->itm[i].value >= min_val
&& pseg->itm[i].value < max_val) {
if(choice == -1 || rnd(2) == 1)
choice = i;
if(rnd(4) == 1)
break;
}
}
if(choice == -1)
return;
last_choice = choice;
pseg->itm[choice].decay_cnt = 0;
pseg->itm[choice].loc.under = mseg->m[sector].map[y][x];
pseg->itm[choice].rem_uses = pseg->itm[choice].max_uses;
(void)put_item(choice, sector, x, y);
}
drop_all(p_indx, sector, x, y)
int p_indx, sector, x, y;
{
int i, playernum;
playernum = pseg->p[p_indx].playernum;
for(i = 0; i < pseg->item_count; i++) {
if(pseg->itm[i].loc.sector == LOC_PLAYER
&& pseg->itm[i].loc.x == playernum)
if(put_item(i, sector, x, y) == -1)
pseg->itm[i].loc.sector = LOC_NONESUCH;
if(pseg->p[p_indx].gold > 0
&& pseg->itm[i].loc.sector == LOC_NONESUCH
&& pseg->itm[i].type == CASH) {
pseg->itm[i].value = pseg->p[p_indx].gold;
pseg->p[p_indx].gold = 0;
put_item(i, sector, x, y);
}
}
notify(sector);
}
damage_it(damage, t_a, t_x, t_y)
int damage, t_a, t_x, t_y;
{
int i;
if(is_player(mseg->m[t_a].map[t_y][t_x])) {
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].loc.sector == t_a
&& pseg->p[i].loc.x == t_x
&& pseg->p[i].loc.y == t_y)
(void)pgethit(i, damage);
} else {
for(i = 0; i < n_monster; i++)
if(m_table[i].loc.sector == t_a
&& m_table[i].loc.x == t_x
&& m_table[i].loc.y == t_y)
mgethit(i, damage);
}
}
/* tune the following if you make major changes */
/* to MAX_HP or allow monsters with greater than */
/* 200 fighting scores. */
int d_level(p_indx)
int p_indx;
{
int danger;
danger = pseg->p[p_indx].fighting / 30;
danger += pseg->p[p_indx].max_hp / 20;
return danger;
}
/* end of file. */
SHAR_EOF_combat.c
cat > magic.c << SHAR_EOF_magic.c
/*
MDG Multiuser Dungeon Game -- magic.c magic handler
MDG is Copyright 1990 John C. Gonnerman
This program is subject to the general MDG
copyright statement (see enclosed file, Copyright).
*/
static char *sccsvers = "@(#) magic.c\t(1.2)\tcreated 1/2/91";
#include <stdio.h>
#include "setup.h"
#include "struct.h"
#include "spells.h"
#define NOSPELL(x) dmsg_add(x, "spell not available")
extern struct player_seg *pseg;
extern struct map_seg *mseg;
extern struct monster_tbl *m_table;
extern int n_monster;
extern char *spell_names[];
extern int spell_dd[];
extern struct ast a_spell_table[];
char under[8];
int n_sectors[4];
cast_spell(indx, mptr)
int indx;
struct dmessage *mptr;
{
int spell, who, what, dir, max_damage, rc;
int x, y; /* debug */
char buf[35];
char *text;
spell = mptr->subcmd;
what = who = dir = mptr->arg;
text = mptr->text;
sprintf(buf, "cast %s...", spell_names[spell]);
dmsg_add(indx, buf);
if(cast_it(spell, indx) == -1) {
pseg->p[indx].magicpts -= (pseg->p[indx].magicpts ? 1 : 0);
sprintf(buf, "%s failed", spell_names[spell]);
dmsg_add(indx, buf);
return;
}
switch(spell + 'a') {
case 'a' : /* armor */
/* debug
pseg->p[indx].ma_count += rnd(300);
pseg->p[indx].m_armor += rnd(5);
*/
x = rnd(300);
y = rnd(5);
pseg->p[indx].ma_count += x;
pseg->p[indx].m_armor += y;
if(pseg->p[indx].m_armor > MAX_MARMOR)
pseg->p[indx].m_armor = MAX_MARMOR;
pseg->player_sem++;
tell_player(indx);
break;
case 'b' : /* block */
pseg->p[indx].blocked += go2r(100);
dmsg_add(indx, "Seeks now blocked.");
break;
case 'c' : /* cold */
dmsg_add(indx, "Whoosh!");
visible(indx);
max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
cast_a_spell(&(pseg->p[indx].loc), AS_COLD, dir,
go2r(max_damage));
break;
case 'd' : /* detect */
detect(indx);
tell_player(indx);
break;
case 'e' : /* escape */
if((rc = jump_to(indx, pseg->p[indx].home)) == -1)
dmsg_add(indx, "escape bounced");
else if(rc == -2)
dmsg_add(indx, "escape fizzled");
else
dmsg_add(indx, "escaped!");
break;
case 'f' : /* fireball */
visible(indx);
dmsg_add(indx, "Boom!");
max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
cast_a_spell(&(pseg->p[indx].loc), AS_FIREBALL, dir,
go2r(max_damage));
break;
case 'g' : /* glow */
glow(indx);
tell_player(indx);
break;
case 'h' : /* heal */
heal(indx);
tell_player(indx);
break;
case 'i' : /* invisible */
invisible(indx);
tell_player(indx);
break;
case 'j' : /* jump back */
jump_back(indx);
break;
case 'k' : /* knight */
knight(indx);
break;
case 'l' : /* lightning */
visible(indx);
dmsg_add(indx, "Crackle!");
max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
cast_a_spell(&(pseg->p[indx].loc), AS_LIGHTNING, dir,
go2r(max_damage));
break;
case 'm' : /* missile */
visible(indx);
dmsg_add(indx, "A fiery missile appears!");
max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
ranged_spell(indx, dir, 'm' - 'a', go2r(10), max_damage);
break;
case 'n' : /* n */
nightmare(indx, who);
break;
case 'o' : /* obscure */
if(what >= 0) {
toggle_obscure(what);
dmsg_add(indx, "The object shimmers...");
} else if(what == -1) {
pseg->p[indx].gold_hidden =
(pseg->p[indx].gold_hidden ? 0 : 1);
dmsg_add(indx, "Your gold shimmers...");
} else
dmsg_add(indx, "obscure what?");
break;
case 'p' : /* partners */
show_partners(indx);
break;
case 'q' : /* quit */
quit_spell(indx);
break;
case 'r' : /* death ray */
visible(indx);
dmsg_add(indx, "Bzzzzzt!");
max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
cast_a_spell(&(pseg->p[indx].loc), AS_DEATHRAY, dir,
go2r(max_damage));
break;
case 's' : /* seek */
seek_s(indx, who);
break;
case 't' : /* teleport */
teleport(indx);
break;
case 'u' : /* user */
pseg->p[indx].user_spell += go2r(USER_DUR);
pseg->player_sem++;
break;
case 'v' : /* verify */
verify_item(indx, what);
break;
case 'w' : /* whisper */
whisper(indx, who, text);
break;
case 'x' : /* spell x */
spell_x(indx);
break;
case 'y' : /* yank */
yank(indx, who);
break;
case 'z' : /* zap */
visible(indx);
dmsg_add(indx, "Zap!");
max_damage = (pseg->p[indx].spells[spell] + 50) / 3;
cast_a_spell(&(pseg->p[indx].loc), AS_ZAP, L_EAST,
go2r(max_damage));
break;
default :
break;
}
}
quit_spell(indx)
int indx;
{
int sector, x, y;
sector = pseg->p[indx].loc.sector;
if(sector < 0)
return;
x = pseg->p[indx].loc.x;
y = pseg->p[indx].loc.y;
mseg->m[sector].map[y][x] = pseg->p[indx].loc.under;
mseg->map_sem++;
pseg->p[indx].loc.x = sector;
pseg->p[indx].loc.sector = LOC_HOME;
}
show_partners(p_indx)
int p_indx;
{
int i, len;
char o_buf[35];
strcpy(o_buf, "Partners:");
for(i = 0; i < MAX_PLAYERS; i++)
if(i != p_indx
&& pseg->p[i].playernum >= 0
&& pseg->p[i].partners[p_indx] == 1) {
len = strlen(o_buf);
o_buf[len] = ' ';
o_buf[len + 1] = i + '1';
o_buf[len + 2] = '\0';
}
dmsg_add(p_indx, o_buf);
}
int cast_it(spell, indx)
int spell, indx;
{
if(pseg->p[indx].magicpts < (spell_dd[spell] + 1)
|| rnd(90 + (10 * spell_dd[spell])) > pseg->p[indx].spells[spell])
return -1;
improve_s(indx, spell);
pseg->p[indx].magicpts -= (spell_dd[spell] + 1);
pseg->player_sem++;
tell_player(indx);
return 0;
}
spell_x(p_indx)
int p_indx;
{
int max_damage, i, sector;
sector = pseg->p[p_indx].loc.sector;
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].loc.sector == sector)
dmsg_add(i, "KA-BOOM!!!");
max_damage = 5 * pseg->p[p_indx].magicpts;
if(max_damage < 1)
max_damage = 5;
pseg->p[p_indx].magicpts = 0;
for(i = 0; i < n_monster; i++)
if(m_table[i].loc.sector == sector)
mgethit(i, go2r(max_damage));
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].loc.sector == sector
&& i != p_indx
&& pseg->p[p_indx].partners[i] == 0)
pgethit(i, rnd(max_damage));
pseg->player_sem++;
mseg->map_sem++;
notify(sector);
}
yank(p_indx, v_indx)
int p_indx, v_indx;
{
int dest_a, rc;
char buf[35];
if(v_indx < 0 || v_indx >= MAX_PLAYERS)
return;
dest_a = pseg->p[p_indx].loc.sector;
if(pseg->p[v_indx].loc.sector < 0
|| pseg->p[v_indx].playernum < 0
|| pseg->p[v_indx].blocked > 0) {
sprintf(buf, "%c not found.", (char)('1' + v_indx));
dmsg_add(p_indx, buf);
} else if((rc = jump_to(v_indx, dest_a)) == -1)
dmsg_add(p_indx, "yank bounced");
else if(rc == -2)
dmsg_add(p_indx, "yank fizzled");
else {
sprintf(buf, "%c yanked!", (char)('1' + v_indx));
dmsg_add(p_indx, buf);
dmsg_add(v_indx, "you've been yanked!");
}
}
jump_back(indx)
int indx;
{
int dest_a, rc;
dest_a = pseg->p[indx].prev_sect;
if((rc = jump_to(indx, dest_a)) == -1)
dmsg_add(indx, "jump back bounced");
else if(rc == -2)
dmsg_add(indx, "jump back fizzled");
else
dmsg_add(indx, "returned");
}
teleport(indx)
int indx;
{
int dest_a, rc;
dest_a = rnd(mseg->max_areas) - 1;
if((rc = jump_to(indx, dest_a)) == -1)
dmsg_add(indx, "teleport bounced");
else if(rc == -2)
dmsg_add(indx, "teleport fizzled");
else
dmsg_add(indx, "teleported");
}
int jump_to(indx, sector)
int indx, sector;
{
int cnt, rc, symbol, link_dd;
int old_s, x, y, dest_x, dest_y;
old_s = pseg->p[indx].loc.sector;
x = pseg->p[indx].loc.x;
y = pseg->p[indx].loc.y;
link_dd = mseg->m[old_s].jump_inhibit + mseg->m[sector].jump_inhibit;
if(rnd(10) < link_dd)
return -2;
for(cnt = 0; cnt < TELE_TRYS; cnt++) {
mseg->m[old_s].map[y][x] = pseg->p[indx].loc.under;
mseg->map_sem++;
dest_x = rnd(MAPCOLS) - 1;
dest_y = rnd(MAPROWS) - 1;
rc = t_move_to(&(pseg->p[indx].loc),
sector, dest_x, dest_y, indx);
symbol = pseg->p[indx].invis ? indx + 11 : indx + 1;
move_sym(&(pseg->p[indx].loc), symbol);
mseg->map_sem++;
if(rc == 0) {
pseg->p[indx].prev_sect = old_s;
notify(sector);
notify(old_s);
return 0;
}
}
return -1;
}
int send_monster(m_indx, sector)
int m_indx, sector;
{
int rc;
lift_a_monster(m_indx);
rc = move_to(&(m_table[m_indx].loc), sector,
m_table[m_indx].loc.x, m_table[m_indx].loc.y, -1);
move_sym(&(m_table[m_indx].loc), m_table[m_indx].m_sym);
mseg->map_sem++;
if(rc == 0) {
notify(sector);
return 0;
}
return -1;
}
visible(p_indx)
int p_indx;
{
int sector, x, y;
pseg->p[p_indx].invis = 0;
sector = pseg->p[p_indx].loc.sector;
x = pseg->p[p_indx].loc.x;
y = pseg->p[p_indx].loc.y;
if(sector < 0)
return;
mseg->m[sector].map[y][x] = 1 + p_indx;
mseg->map_sem++;
}
invisible(p_indx)
int p_indx;
{
int sector, x, y;
pseg->p[p_indx].invis += rnd(100);
dmsg_add(p_indx, "you disappear!");
sector = pseg->p[p_indx].loc.sector;
x = pseg->p[p_indx].loc.x;
y = pseg->p[p_indx].loc.y;
if(sector < 0)
return;
mseg->m[sector].map[y][x] = 11 + p_indx;
mseg->map_sem++;
notify(sector);
}
heal(p_indx)
int p_indx;
{
pseg->p[p_indx].hitpoints += rnd(10);
if(pseg->p[p_indx].hitpoints > pseg->p[p_indx].max_hp)
pseg->p[p_indx].hitpoints = pseg->p[p_indx].max_hp;
dmsg_add(p_indx, "you feel better");
}
glow(p_indx)
int p_indx;
{
pseg->p[p_indx].light += (6 * rnd(100));
mseg->map_sem++;
dmsg_add(p_indx, "it's brighter now");
}
detect(indx)
int indx;
{
pseg->p[indx].detect += go2r(DETECT_DUR);
mseg->map_sem++;
dmsg_add(indx, "your vision sharpens");
}
ranged_spell(p_indx, dir, spell, range, damage)
int p_indx, dir, spell, range, damage;
{
char buf[35];
if(rspell_start(p_indx, 21, range, damage, dir) == -1) {
sprintf(buf, "%s failed", spell_names[spell]);
dmsg_add(p_indx, buf);
}
}
int rspell_start(indx, symbol, range, damage, dir)
int indx, symbol, range, damage, dir;
{
return start_ranged(symbol, 5, damage,
pseg->p[indx].loc.sector, pseg->p[indx].loc.x,
pseg->p[indx].loc.y, dir);
}
int t_move_to(locptr, dest_a, dest_x, dest_y, p_indx)
struct location *locptr;
int dest_a, dest_x, dest_y, p_indx;
{
char at_loc;
if(dest_a < 0)
return -1;
at_loc = mseg->m[dest_a].map[dest_y][dest_x];
switch(at_loc) {
case '0' : /* 0-9 are traps */
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
do_trap(p_indx, at_loc);
locptr->sector = dest_a;
locptr->x = dest_x;
locptr->y = dest_y;
locptr->under = at_loc;
mseg->map_sem++;
return 0;
case '.' :
case ' ' :
case '`' : /* shallow water */
case '+' : /* secret door */
case '<' : /* down */
case '>' : /* up */
locptr->sector = dest_a;
locptr->x = dest_x;
locptr->y = dest_y;
locptr->under = at_loc;
mseg->map_sem++;
return 0;
default :
return (int)at_loc;
}
}
clear_n_sectors()
{
int i;
for(i = 0; i < 4; i++)
n_sectors[i] = LOC_NONESUCH;
}
add_n_sector(sector)
int sector;
{
int i;
for(i = 0; i < 4; i++)
if(n_sectors[i] == LOC_NONESUCH) {
n_sectors[i] = sector;
return;
}
}
notify_n_sectors()
{
int i;
for(i = 0; i < 4; i++)
if(n_sectors[i] != LOC_NONESUCH)
notify(n_sectors[i]);
}
cast_a_spell(loc, a_spell, dir, effect)
struct location *loc;
int a_spell, dir, effect;
{
int i, limit;
char at_spot;
struct location t_loc;
switch(dir) {
case L_NORTH :
case L_SOUTH :
case L_EAST :
case L_WEST :
case L_NEAST :
case L_NWEST :
case L_SEAST :
case L_SWEST :
break;
default :
return;
}
clear_n_sectors();
limit = 99;
for(i = 0; i < 8; i++) {
t_loc.sector = loc->sector;
t_loc.x = loc->x;
t_loc.y = loc->y;
loc_a_spell(&t_loc, a_spell, i, dir);
if(correct_loc(&t_loc) != -1) {
at_spot = mseg->m[t_loc.sector].map[t_loc.y][t_loc.x];
if(a_spell_table[a_spell].advance[i] <= limit
&& at_spot != '#') {
add_n_sector(t_loc.sector);
under[i] = at_spot;
mseg->m[t_loc.sector].map[t_loc.y][t_loc.x] =
'*';
} else if(at_spot == '#'
&& a_spell_table[a_spell].advance[i] < limit
&& a_spell_table[a_spell].flag == ASF_LIMITED) {
limit = a_spell_table[a_spell].advance[i];
}
}
}
mseg->map_sem++;
notify_n_sectors();
busy_wait(600000L);
clear_n_sectors();
for(i = 0; i < 8; i++) {
t_loc.sector = loc->sector;
t_loc.x = loc->x;
t_loc.y = loc->y;
loc_a_spell(&t_loc, a_spell, i, dir);
if(a_spell_table[a_spell].advance[i] <= limit
&& correct_loc(&t_loc) != -1
&& mseg->m[t_loc.sector].map[t_loc.y][t_loc.x] == '*') {
add_n_sector(t_loc.sector);
mseg->m[t_loc.sector].map[t_loc.y][t_loc.x] = under[i];
}
}
mseg->map_sem++;
notify_n_sectors();
for(i = 0; i < 8; i++) {
t_loc.sector = loc->sector;
t_loc.x = loc->x;
t_loc.y = loc->y;
loc_a_spell(&t_loc, a_spell, i, dir);
if(correct_loc(&t_loc) != -1
&& a_spell_table[a_spell].advance[i] <= limit)
zap_spot(t_loc.sector, t_loc.x, t_loc.y, effect);
}
}
zap_spot(sector, x, y, effect)
int sector, x, y, effect;
{
int i;
if(is_player(mseg->m[sector].map[y][x])) {
for(i = 0; i < MAX_PLAYERS; i++)
if(pseg->p[i].loc.sector == sector
&& pseg->p[i].loc.x == x
&& pseg->p[i].loc.y == y)
pgetzapped(i, effect);
} else {
for(i = 0; i < n_monster; i++)
if(m_table[i].loc.sector == sector
&& m_table[i].loc.x == x
&& m_table[i].loc.y == y)
mgethit(i, effect);
}
}
loc_a_spell(loc, spell, pos, dir)
struct location *loc;
int spell, pos, dir;
{
int off, adv;
off = a_spell_table[spell].offset[pos];
adv = a_spell_table[spell].advance[pos];
switch(dir) {
case L_NORTH :
loc->y -= adv;
loc->x += off;
break;
case L_SOUTH :
loc->y += adv;
loc->x -= off;
break;
case L_EAST :
loc->x += adv;
loc->y += off;
break;
case L_WEST :
loc->x -= adv;
loc->y -= off;
break;
case L_NEAST :
loc->y += (-1 * adv) + off - (off > 0);
loc->x += off + adv + (off < 0);
break;
case L_NWEST :
loc->y += (-1 * adv) + (-1 * off) - (off < 0);
loc->x += off + (-1 * adv) - (off > 0);
break;
case L_SEAST :
loc->y += adv + off + (off < 0);
loc->x += (-1 * off) + adv + (off > 0);
break;
case L_SWEST :
loc->y += adv + (-1 * off) + (off > 0);
loc->x += (-1 * off) + (-1 * adv) - (off < 0);
break;
}
}
int correct_loc(loc)
struct location *loc;
{
if(loc->y < 0 && loc->x >= MAPCOLS)
return -1;
if(loc->y < 0 && loc->x < 0)
return -1;
if(loc->y >= MAPROWS && loc->x < 0)
return -1;
if(loc->y >= MAPROWS && loc->x >= MAPCOLS)
return -1;
if(loc->x >= MAPCOLS) {
loc->x -= MAPCOLS;
loc->sector = mseg->m[loc->sector].links[L_EAST];
}
if(loc->x < 0) {
loc->x += MAPCOLS;
loc->sector = mseg->m[loc->sector].links[L_WEST];
}
if(loc->y >= MAPROWS) {
loc->y -= MAPROWS;
loc->sector = mseg->m[loc->sector].links[L_SOUTH];
}
if(loc->y < 0) {
loc->y += MAPROWS;
loc->sector = mseg->m[loc->sector].links[L_NORTH];
}
if(loc->sector < 0)
return -1;
return 0;
}
busy_wait(delay)
long delay;
{
for(; delay; delay--);
}
seek_s(p_indx, v_indx)
int p_indx, v_indx;
{
char buf[35];
int rc;
if(v_indx < 0 || v_indx >= MAX_PLAYERS)
return;
if(pseg->p[v_indx].loc.sector < 0
|| pseg->p[v_indx].playernum < 0
|| pseg->p[v_indx].blocked > 0) {
sprintf(buf, "%c not found.", (char)('1' + v_indx));
dmsg_add(p_indx, buf);
} else if((rc = jump_to(p_indx, pseg->p[v_indx].loc.sector)) == -1)
dmsg_add(p_indx, "seek bounced.");
else if(rc == -2)
dmsg_add(p_indx, "seek fizzled.");
else {
sprintf(buf, "%c found!", (char)('1' + v_indx));
dmsg_add(p_indx, buf);
}
}
toggle_obscure(item_indx)
int item_indx;
{
if(item_indx < 0
|| item_indx >= pseg->item_count
|| pseg->itm[item_indx].loc.sector > -1)
return;
if(pseg->itm[item_indx].type == pseg->itm[item_indx].symbol)
pseg->itm[item_indx].symbol = HIDDEN;
else
pseg->itm[item_indx].symbol = pseg->itm[item_indx].type;
pseg->item_sem++;
}
verify_item(indx, what)
int indx, what;
{
char buf[35];
if(what < 0 || what >= pseg->item_count)
return;
if(pseg->itm[what].curse == 0)
sprintf(buf, "%s is OK", pseg->itm[what].name);
else
sprintf(buf, "%s is CURSED", pseg->itm[what].name);
dmsg_add(indx, buf);
}
knight(p_indx)
int p_indx;
{
dmsg_add(p_indx, "You feel more confident.");
pseg->p[p_indx].knight += rnd(KNIGHT_DUR);
}
nightmare(p_indx, v_indx)
int p_indx, v_indx;
{
char buf[35];
int choice;
if(v_indx < 0 || v_indx >= MAX_PLAYERS)
return;
if(pseg->p[v_indx].loc.sector < 0
|| pseg->p[v_indx].playernum < 0
|| pseg->p[v_indx].blocked > 0) {
sprintf(buf, "%c not found.", (char)('1' + v_indx));
dmsg_add(p_indx, buf);
return;
}
if((choice = nearestm(p_indx)) == -1) {
dmsg_add(p_indx, "No monster.");
return;
}
if(send_monster(choice, pseg->p[v_indx].loc.sector) == -1) {
dmsg_add(p_indx, "Can't send monster.");
return;
}
dmsg_add(p_indx, "Monster sent...");
dmsg_add(v_indx, "A Nightmare!!!");
}
int nearestm(p_indx)
int p_indx;
{
int result, dist, n_dist, i;
int dest_a, m_a, m_x, m_y;
result = -1;
dist = 100;
dest_a = pseg->p[p_indx].loc.sector;
for(i = 0; i < n_monster; i++) {
m_a = m_table[i].loc.sector;
m_x = m_table[i].loc.x;
m_y = m_table[i].loc.y;
if(m_a == dest_a
&& (n_dist = distance(p_indx, m_x, m_y)) < dist) {
dist = n_dist;
result = i;
}
}
return result;
}
/* end of file. */
SHAR_EOF_magic.c
cat > clock.c << SHAR_EOF_clock.c
/*
MDG Multiuser Dungeon Game -- clock task
MDG is Copyright 1990 John C. Gonnerman
This program is subject to the general MDG
copyright statement (see enclosed file, Copyright).
*/
static char *sccsx = "@(#) MDG_CLOCK Copyright 1990 John C. Gonnerman";
static char *sccsvers = "@(#) clock.c\t(1.2)\tcreated 1/2/91";
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "setup.h"
#include "files.h"
#include "struct.h"
#include "messages.h"
extern long dmsgkey, gsemkey, mapkey, playerkey;
char *progname;
int dqid;
extern int errno;
extern char *sys_errlist[];
main(argc, argv)
int argc;
char **argv;
{
struct dmessage msg_buf;
char *strrchr(), *strstr();
int mode;
if((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;
fputs("clock started.\n", stderr);
if(argc != 1) {
fprintf(stderr, ARGCOUNT, progname, argc);
exit(1);
}
chdir(GAME_HOME);
/* load keys from config file */
loadconfig();
/* set signal handlers */
/*
signal(SIGHUP, exit);
signal(SIGTERM, exit);
*/
/* open message queue */
if((dqid = msgget(dmsgkey, 0)) == -1) {
fprintf(stderr, CANTERR, progname, "open queue",
sys_errlist[errno]);
exit(1);
}
/* actual monster packet driver */
while(1) {
sleep(1);
msg_buf.msg_type = 1L;
msg_buf.cmd = ' ';
msg_buf.playernum = -1;
msgsnd(dqid, &msg_buf, DMSGSIZ, IPC_NOWAIT);
}
}
/* end of file */
SHAR_EOF_clock.c
cat > dmain.c << SHAR_EOF_dmain.c
/*
MDG Multiuser Dungeon Game -- mdg_daemon
MDG is Copyright 1990 John C. Gonnerman
This program is subject to the general MDG
copyright statement (see enclosed file, Copyright).
*/
static char *sccsx = "@(#) MDG_DAEMON Copyright 1990 John C. Gonnerman";
static char *sccsvers = "@(#) dmain.c\t(1.5)\tcreated 1/4/91";
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include "setup.h"
#include "files.h"
#include "struct.h"
#include "messages.h"
char *progname;
int dqid, pid;
time_t mark_time;
long max_mps, msg_count;
/* flag for debugging */
int in_msgrcv;
FILE *saveopen();
extern long dmsgkey, gsemkey, mapkey, playerkey;
extern struct player_seg *pseg;
extern struct map_seg *mseg;
extern int errno;
extern char *sys_errlist[];
main(argc, argv)
int argc;
char **argv;
{
int i, rc, xx, dfd, tmp;
FILE *gfp;
void shutdown();
struct dmessage msg_buf;
struct msqid_ds qbuf;
progname = argv[0];
/* arrange for file creation to be limited. */
umask(0007);
if(argc != 1) {
fprintf(stderr, ARGCOUNT, progname, argc);
exit(1);
}
fputs(DTITLE, stderr);
fputs(DCOPYRIGHT, stderr);
fputs(LOADMSG, stderr);
if(chdir(GAME_HOME) == -1) {
fprintf(stderr, CANTERR, progname, "chdir()",
sys_errlist[errno]);
exit(1);
}
if((tmp = creat(LOCKFILE, 0)) == -1) {
fprintf(stderr, "%s: daemon lock found, aborting...\n",
progname);
exit(99);
}
close(tmp);
if((dfd = open(ERRLOGFILE, O_WRONLY|O_CREAT|O_TRUNC, 0660)) == -1) {
fprintf(stderr, CANTERR, progname, "open error log",
sys_errlist[errno]);
exit(1);
}
close(2);
dup(dfd);
close(dfd);
setbuf(stderr, NULL);
close(0);
close(1);
fputs(LOADMSG, stderr);
if((rc = fork()) == -1) {
fprintf(stderr, CANTERR, progname, "fork()",
sys_errlist[errno]);
exit(1);
}
if(rc != 0)
exit(0);
setpgrp();
/* load keys from config file */
loadconfig();
/* load the player segment */
if((gfp = saveopen(ITEMS, "r")) == NULL) {
fprintf(stderr, CANTERR, progname, "open item file",
sys_errlist[errno]);
exit(1);
}
load_pseg(gfp);
fclose(gfp);
/* load the monster table */
if((gfp = saveopen(MONSTERS, "r")) == NULL) {
fprintf(stderr, CANTERR, progname, "open monster file",
sys_errlist[errno]);
exit(1);
}
load_monsters(gfp);
fclose(gfp);
/* load the notes table */
if((gfp = saveopen(NOTES, "r")) == NULL) {
fprintf(stderr, CANTERR, progname, "open note file",
sys_errlist[errno]);
exit(1);
}
load_notes(gfp);
fclose(gfp);
/* load the map segment */
if((gfp = saveopen(MAP, "r")) == NULL) {
fprintf(stderr, CANTERR, progname, "open map file",
sys_errlist[errno]);
exit(1);
}
load_mseg(gfp);
fclose(gfp);
/* initialize ranged table */
init_ranged();
/* attach the segments. */
seg_attach();
/* create message queues (if needed) and open them */
if((dqid = msgget(dmsgkey, IPC_CREAT | 0666)) == -1) {
fprintf(stderr, CANTERR, progname, "open daemon queue",
sys_errlist[errno]);
exit(1);
}
msgctl(dqid, IPC_STAT, &qbuf);
qbuf.msg_qbytes = DQSIZ;
msgctl(dqid, IPC_SET, &qbuf);
if((pseg->sid = semget(gsemkey, MAX_PLAYERS, IPC_CREAT|0777)) == -1) {
fprintf(stderr, CANTERR, progname, "open game semset",
sys_errlist[errno]);
exit(1);
}
/* ready to run, so set signal traps */
signal(SIGTERM, shutdown);
signal(SIGHUP, shutdown);
/* lower our priority ... */
nice(NICEVAL);
/* ... start the monster packet driver ... */
if((pid = fork()) == 0) {
if(execl(CLOCKTASK, CLOCKTASK, (char *)0) == -1) {
fprintf(stderr, CANTERR, progname, "execl()",
sys_errlist[errno]);
exit(1);
}
} else if(pid == -1) {
fprintf(stderr, CANTERR, progname, "fork()",
sys_errlist[errno]);
exit(1);
}
/* ... seed the random number generator ... */
random();
/* ... and place the stuff. */
place_items();
place_monsters();
/* we got it, let's do it! */
mark_time = time(NULL);
max_mps = 0;
msg_count = 0;
while(1) {
in_msgrcv = 1;
if((xx = msgrcv(dqid, &msg_buf, DMSGSIZ, 0L, 0)) == DMSGSIZ) {
msg_count++;
msg_handler(msg_buf);
}
in_msgrcv = 0;
if(mark_time != time(NULL)) {
if(msg_count > max_mps)
max_mps = msg_count;
msg_count = 0;
mark_time = time(NULL);
}
}
}
int rename(oldname, newname)
char *oldname, *newname;
{
unlink(newname);
if(link(oldname, newname) != -1)
return unlink(oldname);
else
return -1;
}
FILE *saveopen(file, mode)
char *file, *mode;
{
FILE *fp;
char savefile[128], altfile[128];
strcpy(savefile, file);
strcat(savefile, SAVEEXT);
strcpy(altfile, file);
if(mode[0] == 'r') {
strcat(altfile, STARTEXT);
if((fp = fopen(savefile, "r")) == NULL)
return fopen(altfile, "r");
else
return fp;
} else if(mode[0] == 'w') {
strcat(altfile, OLDEXT);
rename(savefile, altfile);
return fopen(savefile, "w");
}
}
/* end of file */
SHAR_EOF_dmain.c
--
Michael
michael@stb.info.com denwa!stb!michael anes.ucla.edu!stb!michael
"Space is an illusion; disk space doubly so"