home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume12
/
mdg
/
part03
/
magic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-04
|
17KB
|
940 lines
/*
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;
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 */
pseg->p[indx].ma_count += rnd(300);
pseg->p[indx].m_armor += rnd(5);
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. */