1209 lines
30 KiB
C
1209 lines
30 KiB
C
/*
|
||
* interplayer.c - player to player routines for Phantasia
|
||
*/
|
||
|
||
#include "include.h"
|
||
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: checkbattle()
|
||
/
|
||
/ FUNCTION: check to see if current player should battle another
|
||
/
|
||
/ AUTHOR: E. A. Estes, 12/4/85
|
||
/
|
||
/ ARGUMENTS: none
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: battleplayer(), fread(), fseek()
|
||
/
|
||
/ GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
|
||
/
|
||
/ GLOBAL OUTPUTS: Users
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Seach player file for a foe at the same coordinates as the
|
||
/ current player.
|
||
/ Also update user count.
|
||
/
|
||
*************************************************************************/
|
||
|
||
checkbattle()
|
||
{
|
||
long foeloc = 0L; /* location in file of person to fight */
|
||
|
||
Users = 0;
|
||
fseek(Playersfp, 0L, 0);
|
||
|
||
while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
|
||
{
|
||
if (Other.p_status != S_OFF
|
||
&& Other.p_status != S_NOTUSED
|
||
&& Other.p_status != S_HUNGUP
|
||
&& (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
|
||
/* player is on and not a cloaked valar */
|
||
{
|
||
++Users;
|
||
|
||
if (Player.p_x == Other.p_x
|
||
&& Player.p_y == Other.p_y
|
||
/* same coordinates */
|
||
&& foeloc != Fileloc
|
||
/* not self */
|
||
&& Player.p_status == S_PLAYING
|
||
&& (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
|
||
/* both are playing */
|
||
&& Other.p_specialtype != SC_VALAR
|
||
&& Player.p_specialtype != SC_VALAR)
|
||
/* neither is valar */
|
||
{
|
||
battleplayer(foeloc);
|
||
return;
|
||
}
|
||
}
|
||
foeloc += SZ_PLAYERSTRUCT;
|
||
}
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: battleplayer()
|
||
/
|
||
/ FUNCTION: inter-terminal battle with another player
|
||
/
|
||
/ AUTHOR: E. A. Estes, 2/15/86
|
||
/
|
||
/ ARGUMENTS:
|
||
/ long foeplace - location in player file of person to battle
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(),
|
||
/ displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(),
|
||
/ myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(),
|
||
/ getanswer(), wclrtoeol(), wclrtobot()
|
||
/
|
||
/ GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr,
|
||
/ Fileloc, *Enemyname
|
||
/
|
||
/ GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Inter-terminal battle is a very fragile and slightly klugy thing.
|
||
/ At any time, one player is master and the other is slave.
|
||
/ We pick who is master first by speed and level. After that,
|
||
/ the slave waits for the master to relinquish its turn, and
|
||
/ the slave becomes master, and so on.
|
||
/
|
||
/ The items in the player structure which control the handshake are:
|
||
/ p_tampered:
|
||
/ master increments this to relinquish control
|
||
/ p_istat:
|
||
/ master sets this to specify particular action
|
||
/ p_1scratch:
|
||
/ set to total damage inflicted so far; changes to indicate action
|
||
/
|
||
*************************************************************************/
|
||
|
||
battleplayer(foeplace)
|
||
long foeplace;
|
||
{
|
||
double dtemp; /* for temporary calculations */
|
||
double oldhits = 0.0; /* previous damage inflicted by foe */
|
||
register int loop; /* for timing out */
|
||
int ch; /* input */
|
||
short oldtampered; /* old value of foe's p_tampered */
|
||
|
||
Lines = 8;
|
||
Luckout = FALSE;
|
||
mvaddstr(4, 0, "Preparing for battle!\n");
|
||
refresh();
|
||
|
||
#ifdef SYS5
|
||
flushinp();
|
||
#endif
|
||
|
||
/* set up variables, file, etc. */
|
||
Player.p_status = S_INBATTLE;
|
||
Shield = Player.p_energy;
|
||
|
||
/* if p_tampered is not 0, someone else may try to change it (king, etc.) */
|
||
Player.p_tampered = oldtampered = 1;
|
||
Player.p_1scratch = 0.0;
|
||
Player.p_istat = I_OFF;
|
||
|
||
readrecord(&Other, foeplace);
|
||
if (fabs(Player.p_level - Other.p_level) > 20.0)
|
||
/* see if players are greatly mismatched */
|
||
{
|
||
dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
|
||
if (dtemp < -0.5)
|
||
/* foe outweighs this one */
|
||
Player.p_speed *= 2.0;
|
||
}
|
||
|
||
writerecord(&Player, Fileloc); /* write out all our info */
|
||
|
||
if (Player.p_blindness)
|
||
Enemyname = "someone";
|
||
else
|
||
Enemyname = Other.p_name;
|
||
|
||
mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level);
|
||
refresh();
|
||
|
||
for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
|
||
/* wait for foe to respond */
|
||
{
|
||
readrecord(&Other, foeplace);
|
||
sleep(1);
|
||
}
|
||
|
||
if (Other.p_status != S_INBATTLE)
|
||
/* foe did not respond */
|
||
{
|
||
mvprintw(5, 0, "%s is not responding.\n", Enemyname);
|
||
goto LEAVE;
|
||
}
|
||
/* else, we are ready to battle */
|
||
|
||
move(4, 0);
|
||
clrtoeol();
|
||
|
||
/*
|
||
* determine who is first master
|
||
* if neither player is faster, check level
|
||
* if neither level is greater, battle is not allowed
|
||
* (this should never happen, but we have to handle it)
|
||
*/
|
||
if (Player.p_speed > Other.p_speed)
|
||
Foestrikes = FALSE;
|
||
else if (Other.p_speed > Player.p_speed)
|
||
Foestrikes = TRUE;
|
||
else if (Player.p_level > Other.p_level)
|
||
Foestrikes = FALSE;
|
||
else if (Other.p_level > Player.p_level)
|
||
Foestrikes = TRUE;
|
||
else
|
||
/* no one is faster */
|
||
{
|
||
printw("You can't fight %s yet.", Enemyname);
|
||
goto LEAVE;
|
||
}
|
||
|
||
for (;;)
|
||
{
|
||
displaystats();
|
||
readmessage();
|
||
mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */
|
||
|
||
if (!Foestrikes)
|
||
/* take action against foe */
|
||
myturn();
|
||
else
|
||
/* wait for foe to take action */
|
||
{
|
||
mvaddstr(4, 0, "Waiting...\n");
|
||
clrtoeol();
|
||
refresh();
|
||
|
||
for (loop = 0; loop < 20; ++loop)
|
||
/* wait for foe to act */
|
||
{
|
||
readrecord(&Other, foeplace);
|
||
if (Other.p_1scratch != oldhits)
|
||
/* p_1scratch changes to indicate action */
|
||
break;
|
||
else
|
||
/* wait and try again */
|
||
{
|
||
sleep(1);
|
||
addch('.');
|
||
refresh();
|
||
}
|
||
}
|
||
|
||
if (Other.p_1scratch == oldhits)
|
||
{
|
||
/* timeout */
|
||
mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
|
||
ch = getanswer("NY", FALSE);
|
||
move(22, 0);
|
||
clrtobot();
|
||
if (ch == 'Y')
|
||
continue;
|
||
else
|
||
break;
|
||
}
|
||
else
|
||
/* foe took action */
|
||
{
|
||
switch (Other.p_istat)
|
||
{
|
||
case I_RAN: /* foe ran away */
|
||
mvprintw(Lines++, 0, "%s ran away!", Enemyname);
|
||
break;
|
||
|
||
case I_STUCK: /* foe tried to run, but couldn't */
|
||
mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
|
||
break;
|
||
|
||
case I_BLEWIT: /* foe tried to luckout, but didn't */
|
||
mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
|
||
break;
|
||
|
||
default:
|
||
dtemp = Other.p_1scratch - oldhits;
|
||
mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
|
||
Shield -= dtemp;
|
||
break;
|
||
}
|
||
|
||
oldhits = Other.p_1scratch; /* keep track of old hits */
|
||
|
||
if (Other.p_tampered != oldtampered)
|
||
/* p_tampered changes to relinquish turn */
|
||
{
|
||
oldtampered = Other.p_tampered;
|
||
Foestrikes = FALSE;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* decide what happens next */
|
||
refresh();
|
||
if (Lines > LINES - 2)
|
||
{
|
||
more(Lines);
|
||
move(Lines = 8, 0);
|
||
clrtobot();
|
||
}
|
||
|
||
if (Other.p_istat == I_KILLED || Shield < 0.0)
|
||
/* we died */
|
||
{
|
||
Shield = -2.0; /* insure this value is negative */
|
||
break;
|
||
}
|
||
|
||
if (Player.p_istat == I_KILLED)
|
||
/* we killed foe; award treasre */
|
||
{
|
||
mvprintw(Lines++, 0, "You killed %s!", Enemyname);
|
||
Player.p_experience += Other.p_experience;
|
||
Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
|
||
Player.p_amulets += Other.p_amulets;
|
||
Player.p_charms += Other.p_charms;
|
||
collecttaxes(Other.p_gold, Other.p_gems);
|
||
Player.p_sword = MAX(Player.p_sword, Other.p_sword);
|
||
Player.p_shield = MAX(Player.p_shield, Other.p_shield);
|
||
Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
|
||
if (Other.p_virgin && !Player.p_virgin)
|
||
{
|
||
mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? ");
|
||
if ((ch = getanswer("YN", FALSE)) == 'Y')
|
||
Player.p_virgin = TRUE;
|
||
else
|
||
{
|
||
++Player.p_sin;
|
||
Player.p_experience += 8000.0;
|
||
}
|
||
}
|
||
sleep(3); /* give other person time to die */
|
||
break;
|
||
}
|
||
else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
|
||
/* either player ran away */
|
||
break;
|
||
}
|
||
|
||
LEAVE:
|
||
/* clean up things and leave */
|
||
writerecord(&Player, Fileloc); /* update a final time */
|
||
altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
|
||
Player.p_energy = Shield; /* set energy to actual value */
|
||
Player.p_tampered = T_OFF; /* clear p_tampered */
|
||
|
||
more(Lines); /* pause */
|
||
|
||
move(4, 0);
|
||
clrtobot(); /* clear bottom area of screen */
|
||
|
||
if (Player.p_energy < 0.0)
|
||
/* we are dead */
|
||
death("Interterminal battle");
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: myturn()
|
||
/
|
||
/ FUNCTION: process players action against foe in battle
|
||
/
|
||
/ AUTHOR: E. A. Estes, 2/7/86
|
||
/
|
||
/ ARGUMENTS: none
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), drandom(),
|
||
/ waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot()
|
||
/
|
||
/ GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout,
|
||
/ *Enemyname
|
||
/
|
||
/ GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Take action action against foe, and decide who is master
|
||
/ for next iteration.
|
||
/
|
||
*************************************************************************/
|
||
|
||
myturn()
|
||
{
|
||
double dtemp; /* for temporary calculations */
|
||
int ch; /* input */
|
||
|
||
mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
|
||
if (Luckout)
|
||
clrtoeol();
|
||
else
|
||
addstr("4:Luckout ");
|
||
|
||
ch = inputoption();
|
||
move(Lines = 8, 0);
|
||
clrtobot();
|
||
|
||
switch (ch)
|
||
{
|
||
default: /* fight */
|
||
dtemp = ROLL(2.0, Player.p_might);
|
||
HIT:
|
||
mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
|
||
Player.p_sin += 0.5;
|
||
Player.p_1scratch += dtemp;
|
||
Player.p_istat = I_OFF;
|
||
break;
|
||
|
||
case '2': /* run away */
|
||
Player.p_1scratch -= 1.0; /* change this to indicate action */
|
||
if (drandom() > 0.25)
|
||
{
|
||
mvaddstr(Lines++, 0, "You got away!");
|
||
Player.p_istat = I_RAN;
|
||
}
|
||
else
|
||
{
|
||
mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
|
||
Player.p_istat = I_STUCK;
|
||
}
|
||
break;
|
||
|
||
case '3': /* power blast */
|
||
dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
|
||
Player.p_mana -= dtemp;
|
||
dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
|
||
mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
|
||
goto HIT;
|
||
|
||
case '4': /* luckout */
|
||
if (Luckout || drandom() > 0.1)
|
||
{
|
||
if (Luckout)
|
||
mvaddstr(Lines++, 0, "You already tried that!");
|
||
else
|
||
{
|
||
mvaddstr(Lines++, 0, "Not this time . . .");
|
||
Luckout = TRUE;
|
||
}
|
||
|
||
Player.p_1scratch -= 1.0;
|
||
Player.p_istat = I_BLEWIT;
|
||
}
|
||
else
|
||
{
|
||
mvaddstr(Lines++, 0, "You just lucked out!");
|
||
Player.p_1scratch = Other.p_energy * 1.1;
|
||
}
|
||
break;
|
||
}
|
||
|
||
refresh();
|
||
Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */
|
||
|
||
if (Player.p_1scratch > Other.p_energy)
|
||
Player.p_istat = I_KILLED;
|
||
else if (drandom() * Player.p_speed < drandom() * Other.p_speed)
|
||
/* relinquish control */
|
||
{
|
||
++Player.p_tampered;
|
||
Foestrikes = TRUE;
|
||
}
|
||
|
||
writerecord(&Player, Fileloc); /* let foe know what we did */
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: checktampered()
|
||
/
|
||
/ FUNCTION: check if current player has been tampered with
|
||
/
|
||
/ AUTHOR: E. A. Estes, 12/4/85
|
||
/
|
||
/ ARGUMENTS: none
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid()
|
||
/
|
||
/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
|
||
/
|
||
/ GLOBAL OUTPUTS: Enrgyvoid
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Check for energy voids, holy grail, and tampering by other
|
||
/ players.
|
||
/
|
||
*************************************************************************/
|
||
|
||
checktampered()
|
||
{
|
||
long loc = 0L; /* location in energy void file */
|
||
|
||
/* first check for energy voids */
|
||
fseek(Energyvoidfp, 0L, 0);
|
||
while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
|
||
if (Enrgyvoid.ev_active
|
||
&& Enrgyvoid.ev_x == Player.p_x
|
||
&& Enrgyvoid.ev_y == Player.p_y)
|
||
/* sitting on one */
|
||
{
|
||
if (loc > 0L)
|
||
/* not the holy grail; inactivate energy void */
|
||
{
|
||
Enrgyvoid.ev_active = FALSE;
|
||
writevoid(&Enrgyvoid, loc);
|
||
tampered(T_NRGVOID, 0.0, 0.0);
|
||
}
|
||
else if (Player.p_status != S_CLOAKED)
|
||
/* holy grail */
|
||
tampered(T_GRAIL, 0.0, 0.0);
|
||
break;
|
||
}
|
||
else
|
||
loc += SZ_VOIDSTRUCT;
|
||
|
||
/* now check for other things */
|
||
readrecord(&Other, Fileloc);
|
||
if (Other.p_tampered != T_OFF)
|
||
tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: tampered()
|
||
/
|
||
/ FUNCTION: take care of tampering by other players
|
||
/
|
||
/ AUTHOR: E. A. Estes, 12/4/85
|
||
/
|
||
/ ARGUMENTS:
|
||
/ int what - what type of tampering
|
||
/ double arg1, arg2 - rest of tampering info
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(),
|
||
/ floor(), wmove(), waddch(), drandom(), printw(), altercoordinates(),
|
||
/ waddstr(), wrefresh(), encounter(), writevoid()
|
||
/
|
||
/ GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
|
||
/
|
||
/ GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Take care of energy voids, holy grail, decree and intervention
|
||
/ action on current player.
|
||
/
|
||
*************************************************************************/
|
||
|
||
tampered(what, arg1, arg2)
|
||
int what;
|
||
double arg1;
|
||
double arg2;
|
||
{
|
||
long loc; /* location in file of other players */
|
||
|
||
Changed = TRUE;
|
||
move(4,0);
|
||
|
||
Player.p_tampered = T_OFF; /* no longer tampered with */
|
||
|
||
switch (what)
|
||
{
|
||
case T_NRGVOID:
|
||
addstr("You've hit an energy void !\n");
|
||
Player.p_mana /= 3.0;
|
||
Player.p_energy /= 2.0;
|
||
Player.p_gold = floor(Player.p_gold/1.25) + 0.1;
|
||
altercoordinates(0.0, 0.0, A_NEAR);
|
||
break;
|
||
|
||
case T_TRANSPORT:
|
||
addstr("The king transported you ! ");
|
||
if (Player.p_charms > 0)
|
||
{
|
||
addstr("But your charm saved you. . .\n");
|
||
--Player.p_charms;
|
||
}
|
||
else
|
||
{
|
||
altercoordinates(0.0, 0.0, A_FAR);
|
||
addch('\n');
|
||
}
|
||
break;
|
||
|
||
case T_BESTOW:
|
||
printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
|
||
Player.p_gold += arg1;
|
||
break;
|
||
|
||
case T_CURSED:
|
||
addstr("You've been cursed ! ");
|
||
if (Player.p_blessing)
|
||
{
|
||
addstr("But your blessing saved you. . .\n");
|
||
Player.p_blessing = FALSE;
|
||
}
|
||
else
|
||
{
|
||
addch('\n');
|
||
Player.p_poison += 2.0;
|
||
Player.p_energy = 10.0;
|
||
Player.p_maxenergy *= 0.95;
|
||
Player.p_status = S_PLAYING; /* no longer cloaked */
|
||
}
|
||
break;
|
||
|
||
case T_VAPORIZED:
|
||
addstr("You have been vaporized!\n");
|
||
more(7);
|
||
death("Vaporization");
|
||
break;
|
||
|
||
case T_MONSTER:
|
||
addstr("The Valar zapped you with a monster!\n");
|
||
more(7);
|
||
encounter((int) arg1);
|
||
return;
|
||
|
||
case T_BLESSED:
|
||
addstr("The Valar has blessed you!\n");
|
||
Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
|
||
Player.p_mana += 500.0;
|
||
Player.p_strength += 0.5;
|
||
Player.p_brains += 0.5;
|
||
Player.p_magiclvl += 0.5;
|
||
Player.p_poison = MIN(0.5, Player.p_poison);
|
||
break;
|
||
|
||
case T_RELOCATE:
|
||
addstr("You've been relocated. . .\n");
|
||
altercoordinates(arg1, arg2, A_FORCED);
|
||
break;
|
||
|
||
case T_HEAL:
|
||
addstr("You've been healed!\n");
|
||
Player.p_poison -= 0.25;
|
||
Player.p_energy = Player.p_maxenergy + Player.p_shield;
|
||
break;
|
||
|
||
case T_EXVALAR:
|
||
addstr("You are no longer Valar!\n");
|
||
Player.p_specialtype = SC_COUNCIL;
|
||
break;
|
||
|
||
case T_GRAIL:
|
||
addstr("You have found The Holy Grail!!\n");
|
||
if (Player.p_specialtype < SC_COUNCIL)
|
||
/* must be council of wise to behold grail */
|
||
{
|
||
addstr("However, you are not experienced enough to behold it.\n");
|
||
Player.p_sin *= Player.p_sin;
|
||
Player.p_mana += 1000;
|
||
}
|
||
else if (Player.p_specialtype == SC_VALAR
|
||
|| Player.p_specialtype == SC_EXVALAR)
|
||
{
|
||
addstr("You have made it to the position of Valar once already.\n");
|
||
addstr("The Grail is of no more use to you now.\n");
|
||
}
|
||
else
|
||
{
|
||
addstr("It is now time to see if you are worthy to behold it. . .\n");
|
||
refresh();
|
||
sleep(4);
|
||
|
||
if (drandom() / 2.0 < Player.p_sin)
|
||
{
|
||
addstr("You have failed!\n");
|
||
Player.p_strength =
|
||
Player.p_mana =
|
||
Player.p_energy =
|
||
Player.p_maxenergy =
|
||
Player.p_magiclvl =
|
||
Player.p_brains =
|
||
Player.p_experience =
|
||
Player.p_quickness = 1.0;
|
||
|
||
altercoordinates(1.0, 1.0, A_FORCED);
|
||
Player.p_level = 0.0;
|
||
}
|
||
else
|
||
{
|
||
addstr("You made to position of Valar!\n");
|
||
Player.p_specialtype = SC_VALAR;
|
||
Player.p_lives = 5;
|
||
fseek(Playersfp, 0L, 0);
|
||
loc = 0L;
|
||
while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
|
||
/* search for existing valar */
|
||
if (Other.p_specialtype == SC_VALAR
|
||
&& Other.p_status != S_NOTUSED)
|
||
/* found old valar */
|
||
{
|
||
Other.p_tampered = T_EXVALAR;
|
||
writerecord(&Other, loc);
|
||
break;
|
||
}
|
||
else
|
||
loc += SZ_PLAYERSTRUCT;
|
||
}
|
||
}
|
||
|
||
/* move grail to new location */
|
||
Enrgyvoid.ev_active = TRUE;
|
||
Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6);
|
||
Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6);
|
||
writevoid(&Enrgyvoid, 0L);
|
||
break;
|
||
}
|
||
refresh();
|
||
sleep(2);
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: userlist()
|
||
/
|
||
/ FUNCTION: print list of players and locations
|
||
/
|
||
/ AUTHOR: E. A. Estes, 2/28/86
|
||
/
|
||
/ ARGUMENTS:
|
||
/ bool ingameflag - set if called while playing
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(),
|
||
/ floor(), wmove(), printw(), waddstr(), distance(), wrefresh(),
|
||
/ descrtype(), wclrtobot()
|
||
/
|
||
/ GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
|
||
/
|
||
/ GLOBAL OUTPUTS: none
|
||
/
|
||
/ DESCRIPTION:
|
||
/ We can only see the coordinate of those closer to the origin
|
||
/ from us.
|
||
/ Kings and council of the wise can see and can be seen by everyone.
|
||
/ Palantirs are good for seeing everyone; and the valar can use
|
||
/ one to see through a 'cloak' spell.
|
||
/ The valar has no coordinates, and is completely invisible if
|
||
/ cloaked.
|
||
/
|
||
*************************************************************************/
|
||
|
||
userlist(ingameflag)
|
||
bool ingameflag;
|
||
{
|
||
register int numusers = 0; /* number of users on file */
|
||
|
||
if (ingameflag && Player.p_blindness)
|
||
{
|
||
mvaddstr(8, 0, "You cannot see anyone.\n");
|
||
return;
|
||
}
|
||
|
||
fseek(Playersfp, 0L, 0);
|
||
mvaddstr(8, 0,
|
||
"Name X Y Lvl Type Login Status\n");
|
||
|
||
while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
|
||
{
|
||
if (Other.p_status == S_NOTUSED
|
||
/* record is unused */
|
||
|| (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
|
||
/* cloaked valar */
|
||
{
|
||
if (!Wizard)
|
||
/* wizard can see everything on file */
|
||
continue;
|
||
}
|
||
|
||
++numusers;
|
||
|
||
if (ingameflag &&
|
||
/* must be playing for the rest of these conditions */
|
||
(Player.p_specialtype >= SC_KING
|
||
/* kings and higher can see others */
|
||
|| Other.p_specialtype >= SC_KING
|
||
/* kings and higher can be seen by others */
|
||
|| Circle >= CIRCLE(Other.p_x, Other.p_y)
|
||
/* those nearer the origin can be seen */
|
||
|| Player.p_palantir)
|
||
/* palantir enables one to see others */
|
||
&& (Other.p_status != S_CLOAKED
|
||
|| (Player.p_specialtype == SC_VALAR && Player.p_palantir))
|
||
/* not cloaked; valar can see through cloak with a palantir */
|
||
&& Other.p_specialtype != SC_VALAR)
|
||
/* not a valar */
|
||
/* coordinates should be printed */
|
||
printw("%-20s %8.0f %8.0f ",
|
||
Other.p_name, Other.p_x, Other.p_y);
|
||
else
|
||
/* cannot see player's coordinates */
|
||
printw("%-20s %19.19s ",
|
||
Other.p_name, descrlocation(&Other, TRUE));
|
||
|
||
printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
|
||
Other.p_login, descrstatus(&Other));
|
||
|
||
if ((numusers % (LINES - 10)) == 0)
|
||
{
|
||
more(LINES - 1);
|
||
move(9, 0);
|
||
clrtobot();
|
||
}
|
||
}
|
||
|
||
printw("Total players on file = %d\n", numusers);
|
||
refresh();
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: throneroom()
|
||
/
|
||
/ FUNCTION: king stuff upon entering throne
|
||
/
|
||
/ AUTHOR: E. A. Estes, 12/16/85
|
||
/
|
||
/ ARGUMENTS: none
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(),
|
||
/ fwrite(), altercoordinates(), waddstr(), fprintf()
|
||
/
|
||
/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr,
|
||
/ Enrgyvoid, *Playersfp
|
||
/
|
||
/ GLOBAL OUTPUTS: Other, Player, Changed
|
||
/
|
||
/ DESCRIPTION:
|
||
/ If player is not already king, make him/her so if the old king
|
||
/ is not playing.
|
||
/ Clear energy voids with new king.
|
||
/ Print 'decree' prompt.
|
||
/
|
||
*************************************************************************/
|
||
|
||
throneroom()
|
||
{
|
||
FILE *fp; /* to clear energy voids */
|
||
long loc = 0L; /* location of old king in player file */
|
||
|
||
if (Player.p_specialtype < SC_KING)
|
||
/* not already king -- assumes crown */
|
||
{
|
||
fseek(Playersfp, 0L, 0);
|
||
while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
|
||
if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
|
||
/* found old king */
|
||
{
|
||
if (Other.p_status != S_OFF)
|
||
/* old king is playing */
|
||
{
|
||
mvaddstr( 4, 0, "The king is playing, so you cannot steal his throne\n");
|
||
altercoordinates(0.0, 0.0, A_NEAR);
|
||
move(6, 0);
|
||
return;
|
||
}
|
||
else
|
||
/* old king is not playing - remove him/her */
|
||
{
|
||
Other.p_specialtype = SC_NONE;
|
||
if (Other.p_crowns)
|
||
--Other.p_crowns;
|
||
writerecord(&Other, loc);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
loc += SZ_PLAYERSTRUCT;
|
||
|
||
/* make player new king */
|
||
Changed = TRUE;
|
||
Player.p_specialtype = SC_KING;
|
||
mvaddstr(4, 0, "You have become king!\n");
|
||
|
||
/* let everyone else know */
|
||
fp = fopen(_PATH_MESS, "w");
|
||
fprintf(fp, "All hail the new king!");
|
||
fclose(fp);
|
||
|
||
/* clear all energy voids; retain location of holy grail */
|
||
fseek(Energyvoidfp, 0L, 0);
|
||
fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
|
||
fp = fopen(_PATH_VOID, "w");
|
||
fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
|
||
fclose(fp);
|
||
}
|
||
|
||
mvaddstr(6, 0, "0:Decree ");
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: dotampered()
|
||
/
|
||
/ FUNCTION: king and valar special options
|
||
/
|
||
/ AUTHOR: E. A. Estes, 2/28/86
|
||
/
|
||
/ ARGUMENTS: none
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(),
|
||
/ floor(), wmove(), drandom(), fclose(), fwrite(), sscanf(), strcmp(),
|
||
/ infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(),
|
||
/ allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid()
|
||
/
|
||
/ GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr,
|
||
/ Databuf[], Enrgyvoid
|
||
/
|
||
/ GLOBAL OUTPUTS: Other, Player, Enrgyvoid
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Tamper with other players. Handle king/valar specific options.
|
||
/
|
||
*************************************************************************/
|
||
|
||
dotampered()
|
||
{
|
||
short tamper; /* value for tampering with other players */
|
||
char *option; /* pointer to option description */
|
||
double temp1 = 0.0, temp2 = 0.0; /* other tampering values */
|
||
int ch; /* input */
|
||
long loc; /* location in energy void file */
|
||
FILE *fp; /* for opening gold file */
|
||
|
||
move(6, 0);
|
||
clrtoeol();
|
||
if (Player.p_specialtype < SC_COUNCIL && !Wizard)
|
||
/* king options */
|
||
{
|
||
addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
|
||
|
||
ch = getanswer(" ", TRUE);
|
||
move(6, 0);
|
||
clrtoeol();
|
||
move(4, 0);
|
||
switch (ch)
|
||
{
|
||
case '1': /* transport someone */
|
||
tamper = T_TRANSPORT;
|
||
option = "transport";
|
||
break;
|
||
|
||
case '2': /* curse another */
|
||
tamper = T_CURSED;
|
||
option = "curse";
|
||
break;
|
||
|
||
case '3': /* create energy void */
|
||
if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT)
|
||
/* can only have 20 void active at once */
|
||
mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
|
||
else
|
||
{
|
||
addstr("Enter the X Y coordinates of void ? ");
|
||
getstring(Databuf, SZ_DATABUF);
|
||
sscanf(Databuf, "%lf %lf", &temp1, &temp2);
|
||
Enrgyvoid.ev_x = floor(temp1);
|
||
Enrgyvoid.ev_y = floor(temp2);
|
||
Enrgyvoid.ev_active = TRUE;
|
||
writevoid(&Enrgyvoid, loc);
|
||
mvaddstr(5, 0, "It is done.\n");
|
||
}
|
||
return;
|
||
|
||
case '4': /* bestow gold to subject */
|
||
tamper = T_BESTOW;
|
||
addstr("How much gold to bestow ? ");
|
||
temp1 = infloat();
|
||
if (temp1 > Player.p_gold || temp1 < 0)
|
||
{
|
||
mvaddstr(5, 0, "You don't have that !\n");
|
||
return;
|
||
}
|
||
|
||
/* adjust gold after we are sure it will be given to someone */
|
||
option = "give gold to";
|
||
break;
|
||
|
||
case '5': /* collect accumulated taxes */
|
||
if ((fp = fopen(_PATH_GOLD, "r+")) != NULL)
|
||
/* collect taxes */
|
||
{
|
||
fread((char *) &temp1, sizeof(double), 1, fp);
|
||
fseek(fp, 0L, 0);
|
||
/* clear out value */
|
||
temp2 = 0.0;
|
||
fwrite((char *) &temp2, sizeof(double), 1, fp);
|
||
fclose(fp);
|
||
}
|
||
|
||
mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
|
||
Player.p_gold += floor(temp1);
|
||
return;
|
||
|
||
default:
|
||
return;
|
||
}
|
||
/* end of king options */
|
||
}
|
||
else
|
||
/* council of wise, valar, wizard options */
|
||
{
|
||
addstr("1:Heal ");
|
||
if (Player.p_palantir || Wizard)
|
||
addstr("2:Seek Grail ");
|
||
if (Player.p_specialtype == SC_VALAR || Wizard)
|
||
addstr("3:Throw Monster 4:Relocate 5:Bless ");
|
||
if (Wizard)
|
||
addstr("6:Vaporize ");
|
||
|
||
ch = getanswer(" ", TRUE);
|
||
if (!Wizard)
|
||
{
|
||
if (ch > '2' && Player.p_specialtype != SC_VALAR)
|
||
{
|
||
ILLCMD();
|
||
return;
|
||
}
|
||
|
||
if (Player.p_mana < MM_INTERVENE)
|
||
{
|
||
mvaddstr(5, 0, "No mana left.\n");
|
||
return;
|
||
}
|
||
else
|
||
Player.p_mana -= MM_INTERVENE;
|
||
}
|
||
|
||
switch (ch)
|
||
{
|
||
case '1': /* heal another */
|
||
tamper = T_HEAL;
|
||
option = "heal";
|
||
break;
|
||
|
||
case '2': /* seek grail */
|
||
if (Player.p_palantir)
|
||
/* need a palantir to seek */
|
||
{
|
||
fseek(Energyvoidfp, 0L, 0);
|
||
fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
|
||
temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
|
||
temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
|
||
mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
|
||
}
|
||
else
|
||
/* no palantir */
|
||
mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
|
||
return;
|
||
|
||
case '3': /* lob monster at someone */
|
||
mvaddstr(4, 0, "Which monster [0-99] ? ");
|
||
temp1 = infloat();
|
||
temp1 = MAX(0.0, MIN(99.0, temp1));
|
||
tamper = T_MONSTER;
|
||
option = "throw a monster at";
|
||
break;
|
||
|
||
case '4': /* move another player */
|
||
mvaddstr(4, 0, "New X Y coordinates ? ");
|
||
getstring(Databuf, SZ_DATABUF);
|
||
sscanf(Databuf, "%lf %lf", &temp1, &temp2);
|
||
tamper = T_RELOCATE;
|
||
option = "relocate";
|
||
break;
|
||
|
||
case '5': /* bless a player */
|
||
tamper = T_BLESSED;
|
||
option = "bless";
|
||
break;
|
||
|
||
case '6': /* kill off a player */
|
||
if (Wizard)
|
||
{
|
||
tamper = T_VAPORIZED;
|
||
option = "vaporize";
|
||
break;
|
||
}
|
||
else
|
||
return;
|
||
|
||
default:
|
||
return;
|
||
}
|
||
|
||
/* adjust age after we are sure intervention will be done */
|
||
/* end of valar, etc. options */
|
||
}
|
||
|
||
for (;;)
|
||
/* prompt for player to affect */
|
||
{
|
||
mvprintw(4, 0, "Who do you want to %s ? ", option);
|
||
getstring(Databuf, SZ_DATABUF);
|
||
truncstring(Databuf);
|
||
|
||
if (Databuf[0] == '\0')
|
||
userlist(TRUE);
|
||
else
|
||
break;
|
||
}
|
||
|
||
if (strcmp(Player.p_name, Databuf) != 0)
|
||
/* name other than self */
|
||
{
|
||
if ((loc = findname(Databuf, &Other)) >= 0L)
|
||
{
|
||
if (Other.p_tampered != T_OFF)
|
||
{
|
||
mvaddstr(5, 0, "That person has something pending already.\n");
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
if (tamper == T_RELOCATE
|
||
&& CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
|
||
&& !Wizard)
|
||
mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
|
||
else
|
||
{
|
||
if (tamper == T_BESTOW) Player.p_gold -= floor(temp1);
|
||
if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER ||
|
||
tamper == T_RELOCATE || tamper == T_BLESSED))
|
||
Player.p_age += N_AGE; /* age penalty */
|
||
Other.p_tampered = tamper;
|
||
Other.p_1scratch = floor(temp1);
|
||
Other.p_2scratch = floor(temp2);
|
||
writerecord(&Other, loc);
|
||
mvaddstr(5, 0, "It is done.\n");
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
/* player not found */
|
||
mvaddstr(5, 0, "There is no one by that name.\n");
|
||
}
|
||
else
|
||
/* self */
|
||
mvaddstr(5, 0, "You may not do it to yourself!\n");
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: writevoid()
|
||
/
|
||
/ FUNCTION: update energy void entry in energy void file
|
||
/
|
||
/ AUTHOR: E. A. Estes, 12/4/85
|
||
/
|
||
/ ARGUMENTS:
|
||
/ struct energyvoid *vp - pointer to structure to write to file
|
||
/ long loc - location in file to update
|
||
/
|
||
/ RETURN VALUE: none
|
||
/
|
||
/ MODULES CALLED: fseek(), fwrite(), fflush()
|
||
/
|
||
/ GLOBAL INPUTS: *Energyvoidfp
|
||
/
|
||
/ GLOBAL OUTPUTS: none
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Write out energy void structure at specified location.
|
||
/
|
||
*************************************************************************/
|
||
|
||
writevoid(vp, loc)
|
||
register struct energyvoid *vp;
|
||
long loc;
|
||
{
|
||
|
||
fseek(Energyvoidfp, loc, 0);
|
||
fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
|
||
fflush(Energyvoidfp);
|
||
fseek(Energyvoidfp, 0L, 0);
|
||
}
|
||
/**/
|
||
/************************************************************************
|
||
/
|
||
/ FUNCTION NAME: allocvoid()
|
||
/
|
||
/ FUNCTION: allocate space for a new energy void
|
||
/
|
||
/ AUTHOR: E. A. Estes, 12/4/85
|
||
/
|
||
/ ARGUMENTS: none
|
||
/
|
||
/ RETURN VALUE: location of new energy void space
|
||
/
|
||
/ MODULES CALLED: fread(), fseek()
|
||
/
|
||
/ GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
|
||
/
|
||
/ GLOBAL OUTPUTS: none
|
||
/
|
||
/ DESCRIPTION:
|
||
/ Search energy void file for an inactive entry and return its
|
||
/ location.
|
||
/ If no inactive ones are found, return one more than last location.
|
||
/
|
||
*************************************************************************/
|
||
|
||
long
|
||
allocvoid()
|
||
{
|
||
long loc = 0L; /* location of new energy void */
|
||
|
||
fseek(Energyvoidfp, 0L, 0);
|
||
while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
|
||
if (Enrgyvoid.ev_active)
|
||
loc += SZ_VOIDSTRUCT;
|
||
else
|
||
break;
|
||
|
||
return(loc);
|
||
}
|