/*
* PLAYER.C:
*
* Player routines.
*
* Copyright (C) 1991, 1992, 1993, 1997 Brooke Paul & Brett Vickers
*
*/
#include <math.h>
#include "mstruct.h"
#include "mextern.h"
#ifdef DMALLOC
#include "/usr/local/include/dmalloc.h"
#endif
/**********************************************************************/
/* init_ply */
/**********************************************************************/
/* This function initializes a player's stats and loads up the room he */
/* should be in. This should only be called when the player first */
/* logs on. */
void init_ply(ply_ptr)
creature *ply_ptr;
{
char file[80], str[50];
room *rom_ptr;
object *obj_ptr, *obj_ptr2, *cnt_ptr;
otag *op, *otemp, *cop;
long t, tdiff;
int n, i, cantwear=0,class;
F_CLR(ply_ptr, PSPYON);
F_CLR(ply_ptr, PREADI);
F_CLR(ply_ptr, PSECOK);
if(ply_ptr->class == DM && strcmp(ply_ptr->name, dmname[0]) &&
strcmp(ply_ptr->name, dmname[1]) && strcmp(ply_ptr->name, dmname[2]) &&
strcmp(ply_ptr->name, dmname[3]) && strcmp(ply_ptr->name, dmname[4]) &&
strcmp(ply_ptr->name, dmname[5]) && strcmp(ply_ptr->name, dmname[6]))
ply_ptr->class = CARETAKER;
if(!strcmp(ply_ptr->name, dmname[0]) || !strcmp(ply_ptr->name, dmname[1]) ||
!strcmp(ply_ptr->name, dmname[2]) || !strcmp(ply_ptr->name, dmname[3]) ||
!strcmp(ply_ptr->name, dmname[4]) || !strcmp(ply_ptr->name, dmname[5]) ||
!strcmp(ply_ptr->name, dmname[6]))
ply_ptr->class = DM;
if(ply_ptr->class < CARETAKER) {
ply_ptr->daily[DL_BROAD].max = 5 + ply_ptr->level/2;
ply_ptr->daily[DL_ENCHA].max = 3;
ply_ptr->daily[DL_FHEAL].max = MAX(3, 3 + (ply_ptr->level-5)/3);
ply_ptr->daily[DL_TRACK].max = MAX(7, 3 + (ply_ptr->level-5)/4);
ply_ptr->daily[DL_DEFEC].max = 1;
ply_ptr->daily[DL_CHARM].max = MAX(5, 3 + ply_ptr->level/4);
ply_ptr->daily[DL_RCHRG].max = MAX(7, 2 + ply_ptr->level/4);
ply_ptr->daily[DL_TELEP].max = 2;
ply_ptr->daily[DL_BROAE].max = 10 + ply_ptr->level/2;
}
else {
ply_ptr->daily[DL_BROAD].cur = 20;
ply_ptr->daily[DL_BROAD].max = 200;
ply_ptr->daily[DL_DEFEC].max = 10;
ply_ptr->daily[DL_DEFEC].cur = 1;
}
if(ply_ptr->class==ALCHEMIST)
F_SET(ply_ptr, PDMAGI);
F_SET(ply_ptr, PNOSUM);
F_CLR(ply_ptr, PALIAS);
if(ply_ptr->class < CARETAKER)
F_SET(ply_ptr, PPROMP);
if(ply_ptr->gold < 0) {
loge("%s (%s) logged on with - gold.\n",ply_ptr->name,
Ply[ply_ptr->fd].io->address);
ply_ptr->gold = 0;
}
if(!F_ISSET(ply_ptr, PDMINV))
broadcast_login("### %s the %s %s just logged in.", ply_ptr->name,
race_adj[ply_ptr->race], title_ply(ply_ptr));
t = time(0);
strcpy(str, (char *)ctime(&t));
str[strlen(str)-1] = 0;
loge("%s: %s (%s) logged on.\n", str, ply_ptr->name,
Ply[ply_ptr->fd].io->address);
if(ply_ptr->class == DM || ply_ptr->class == CARETAKER)
logn("log.imm", "%s: %s (%s@%s) logged on.\n", str,
ply_ptr->name,Ply[ply_ptr->fd].io->userid, Ply[ply_ptr->fd].io->address);
ply_ptr->lasttime[LT_PSAVE].ltime = t;
ply_ptr->lasttime[LT_PSAVE].interval = SAVEINTERVAL;
ply_ptr->lasttime[LT_SECCK].ltime = t;
if(load_rom(ply_ptr->rom_num, &rom_ptr) < 0) {
loge("%s: %s (%s) Attempted logon to bad or missing room().\n", str, ply_ptr->name,
Ply[ply_ptr->fd].io->address);
load_rom(1, &rom_ptr);
}
n = count_vis_ply(rom_ptr);
if((F_ISSET(rom_ptr, RONEPL) && n > 0) ||
(F_ISSET(rom_ptr, RTWOPL) && n > 1) ||
(F_ISSET(rom_ptr, RTHREE) && n > 2) ||
(F_ISSET(rom_ptr, RNOLOG)))
load_rom(1, &rom_ptr);
add_ply_rom(ply_ptr, rom_ptr);
tdiff = t - ply_ptr->lasttime[LT_HOURS].ltime;
for(i=0; i<45; i++) {
ply_ptr->lasttime[i].ltime += tdiff;
ply_ptr->lasttime[i].ltime =
MIN(t, ply_ptr->lasttime[i].ltime);
}
/* delete quest scrolls */
op = ply_ptr->first_obj;
while(op) {
if(op->obj->type == CONTAINER) {
cnt_ptr = op->obj;
cop = cnt_ptr->first_obj;
while(cop) {
obj_ptr2 = cop->obj;
if(obj_ptr2->questnum && obj_ptr2->type == SCROLL) {
cop = cop->next_tag;
cnt_ptr->shotscur--;
del_obj_obj(obj_ptr2, cnt_ptr);
free_obj(obj_ptr2);
}
else
cop = cop->next_tag;
}
}
if(op->obj->questnum && op->obj->type == SCROLL) {
obj_ptr = op->obj;
op = op->next_tag;
del_obj_crt(obj_ptr, ply_ptr);
free_obj(obj_ptr);
}
else
op = op->next_tag;
}
/* Beginning of new wear code */
/* Make sure those cursed items stay on! */
op = ply_ptr->first_obj;
while(op) {
otemp = op->next_tag;
if(F_ISSET(op->obj, OCURSW)){
obj_ptr = op->obj;
ply_ptr->ready[obj_ptr->wearflag-1] = obj_ptr;
F_SET(obj_ptr, OWEARS);
del_obj_crt(obj_ptr, ply_ptr);
}
op=otemp;
}
op = ply_ptr->first_obj;
while(op) {
otemp = op->next_tag;
if((F_ISSET(ply_ptr, PDINVI) ? 1:!F_ISSET(op->obj, OINVIS)) && op->obj->wearflag &&
op->obj->wearflag != HELD && op->obj->wearflag != WIELD) {
obj_ptr = op->obj;
if(obj_ptr->type == ARMOR && F_ISSET(obj_ptr, ONOMAG) && ply_ptr->class == MAGE) {
op = otemp;
continue;
}
if(obj_ptr->type == ARMOR && F_ISSET(obj_ptr, ONOFEM) && !F_ISSET(ply_ptr,PMALES)) {
op = otemp;
continue;
}
if(obj_ptr->type == ARMOR && F_ISSET(obj_ptr, ONOMAL) && F_ISSET(ply_ptr,PMALES)) {
op = otemp;
continue;
}
if(obj_ptr->wearflag == NECK &&
ply_ptr->ready[NECK1-1] &&
ply_ptr->ready[NECK2-1]) {
op = otemp;
continue;
}
if(obj_ptr->wearflag == FINGER &&
ply_ptr->ready[FINGER1-1] &&
ply_ptr->ready[FINGER2-1] &&
ply_ptr->ready[FINGER3-1] &&
ply_ptr->ready[FINGER4-1] &&
ply_ptr->ready[FINGER5-1] &&
ply_ptr->ready[FINGER6-1] &&
ply_ptr->ready[FINGER7-1] &&
ply_ptr->ready[FINGER8-1]) {
op = otemp;
continue;
}
if(obj_ptr->wearflag != NECK &&
obj_ptr->wearflag != FINGER &&
ply_ptr->ready[obj_ptr->wearflag-1]) {
op = otemp;
continue;
}
if(obj_ptr->shotscur < 1) {
op = otemp;
continue;
}
if (F_ISSET(obj_ptr,OPLDGK) &&
(BOOL(F_ISSET(obj_ptr,OKNGDM)) != BOOL(F_ISSET(ply_ptr,PKNGDM)))){
op = otemp;
continue;
}
if(ply_ptr->class > 10)
class = ply_ptr->class + 11;
else
class = ply_ptr->class;
if(F_ISSET(obj_ptr,OCLSEL))
if(!F_ISSET(obj_ptr,OCLSEL + class) && ( ply_ptr->class < CARETAKER)){
op = otemp;
continue;
}
if(!F_ISSET(obj_ptr,OCLSEL + class) && (ply_ptr->class== MONK || ply_ptr->class == MAGE) && obj_ptr->armor >5){
op = otemp;
continue;
}
if((obj_ptr->wearflag == FINGER||obj_ptr->wearflag ==SHIELD) && ply_ptr->class == MONK){
op=otemp;
continue;
}
if(F_ISSET(obj_ptr, OGOODO) && ply_ptr->alignment < -50) {
op = otemp;
continue;
}
if(F_ISSET(obj_ptr, OEVILO) && ply_ptr->alignment > 50) {
op = otemp;
continue;
}
i = (F_ISSET(obj_ptr, OSIZE1) ? 1:0) * 2 + (F_ISSET(obj_ptr, OSIZE2) ? 1:0);
switch(i) {
case 1:
if(ply_ptr->race != GNOME &&
ply_ptr->race != HOBBIT &&
ply_ptr->race != DWARF) cantwear = 1;
break;
case 2:
if(ply_ptr->race != HUMAN &&
ply_ptr->race != ELF &&
ply_ptr->race != HALFELF &&
ply_ptr->race != HALFORC &&
ply_ptr->race != DARKELF &&
ply_ptr->race != GOBLIN &&
ply_ptr->race != ORC) cantwear = 1;
break;
case 3:
if(ply_ptr->race != HALFGIANT && ply_ptr->race != OGRE && ply_ptr->race != TROLL) cantwear = 1;
break;
}
if(cantwear) {
op = otemp;
cantwear = 0;
continue;
}
if(obj_ptr->wearflag == NECK) {
if(ply_ptr->ready[NECK1-1] && !ply_ptr->ready[NECK2-1]) {
F_SET(obj_ptr, OWEARS);
ply_ptr->ready[NECK2-1] = obj_ptr;
}
else if(!ply_ptr->ready[NECK1-1]) {
ply_ptr->ready[NECK1-1] = obj_ptr;
F_SET(obj_ptr, OWEARS);
}
}
else if(obj_ptr->wearflag == FINGER && ply_ptr->class != MONK) {
for(i=FINGER1; i<FINGER8+1; i++) {
if(!ply_ptr->ready[i-1]) {
ply_ptr->ready[i-1] = obj_ptr;
F_SET(obj_ptr, OWEARS);
break;
}
}
}
else {
if(!ply_ptr->ready[obj_ptr->wearflag-1] && !F_ISSET(obj_ptr, OCURSE)) {
ply_ptr->ready[obj_ptr->wearflag-1] = obj_ptr;
F_SET(obj_ptr, OWEARS);
}
}
if(F_ISSET(obj_ptr, OWEARS))
del_obj_crt(obj_ptr, ply_ptr);
}
op = otemp;
}
/* End of new wear code */
compute_ac(ply_ptr);
compute_thaco(ply_ptr);
luck(ply_ptr);
update_ply(ply_ptr);
sprintf(file, "%s/dialin", DOCPATH);
/* Just so we know who to mail */
/* Remove it if you are that paranoid. */
/*
if (!strcmp(Ply[ply_ptr->fd].io->address, "128.200.21.105")|| !strcmp(Ply[ply_ptr->fd].io->address, "mordor.bio.uci.edu"))
print(ply_ptr->fd, "DMs here are: %s, %s, %s, %s, %s, %s.\n", dmname[0], dmname[1], dmname[2], dmname[3], dmname[4], dmname[5]);
if (ply_ptr->class = DM)
print(ply_ptr->fd, "DMs here are: %s, %s, %s, %s, %s, %s.\n", dmname[0], dmname[1], dmname[2], dmname[3], dmname[4], dmname[5]);
*/
if (ply_ptr->class < DM) {
sprintf(file, "%s/news", LOGPATH);
view_file(ply_ptr->fd, 1, file);
}
sprintf(str, "%s/%s", POSTPATH, ply_ptr->name);
if(file_exists(str))
print(ply_ptr->fd, "\n*** You have mail in the post office.\n");
}
/**********************************************************************/
/* uninit_ply */
/**********************************************************************/
/* This function de-initializes a player who has left the game. This */
/* is called whenever a player quits or disconnects, right before save */
/* is called. */
void uninit_ply(ply_ptr)
creature *ply_ptr;
{
creature *crt_ptr;
ctag *cp, *prev;
int i;
long t;
char str[50];
if(ply_ptr->parent_rom)
del_ply_rom(ply_ptr, ply_ptr->parent_rom);
courageous(ply_ptr);
cp = ply_ptr->first_fol;
while(cp) {
cp->crt->following = 0;
if(cp->crt->type == PLAYER)
print(cp->crt->fd, "You stop following %s.\n", ply_ptr->name);
prev = cp->next_tag;
free(cp);
cp = prev;
}
ply_ptr->first_fol = 0;
if(ply_ptr->following) {
crt_ptr = ply_ptr->following;
cp = crt_ptr->first_fol;
if(cp->crt == ply_ptr) {
crt_ptr->first_fol = cp->next_tag;
free(cp);
}
else while(cp) {
if(cp->crt == ply_ptr) {
prev->next_tag = cp->next_tag;
free(cp);
break;
}
prev = cp;
cp = cp->next_tag;
}
ply_ptr->following = 0;
if(ply_ptr->class < CARETAKER)
print(crt_ptr->fd, "%s stops following you.\n",
ply_ptr->name);
}
for(i=0; i<MAXWEAR; i++)
if(ply_ptr->ready[i]) {
add_obj_crt(ply_ptr->ready[i], ply_ptr);
ply_ptr->ready[i] = 0;
}
update_ply(ply_ptr);
if(!F_ISSET(ply_ptr, PDMINV))
broadcast_login("### %s just logged off.", ply_ptr->name);
t = time(0);
strcpy(str, (char *)ctime(&t));
str[strlen(str)-1] = 0;
loge("%s: %s logged off.\n", str, ply_ptr->name);
}
/**********************************************************************/
/* update_ply */
/**********************************************************************/
/* This function checks up on all a player's time-expiring flags to see */
/* if some of them have expired. If so, flags are set accordingly. */
void update_ply(ply_ptr)
creature *ply_ptr;
{
long t, ltime;
int item, badprep=0, i, dur;
char ill, prot=1;
object *obj_ptr;
otag *op, *cop;
t = time(0);
ply_ptr->lasttime[LT_HOURS].interval +=
(t - ply_ptr->lasttime[LT_HOURS].ltime);
ply_ptr->lasttime[LT_HOURS].ltime = t;
if(EATNDRINK){
if(ply_ptr->lasttime[LT_SUSTN].interval+ply_ptr->lasttime[LT_SUSTN].ltime < t) {
ply_ptr->lasttime[LT_SUSTN].interval=ply_ptr->constitution*144-mrand(3,200);
ply_ptr->lasttime[LT_SUSTN].ltime=t;
switch(ply_ptr->talk[5]) {
case 0:
ply_ptr->talk[5]+=1;
break;
case 1:
if(mrand(1,100) > 50)
ply_ptr->talk[5]+=1;
break;
case 2:
print(ply_ptr->fd, "You're getting thirsty.\n");
ply_ptr->talk[5]+=1;
break;
case 3:
F_CLR(ply_ptr, PNSUSN);
ply_ptr->talk[5]+=1;
break;
case 4:
F_SET(ply_ptr, PNSUSN);
print(ply_ptr->fd, "Your mouth is dry.\n");
ply_ptr->talk[5]+=1;
break;
case 5:
F_SET(ply_ptr, PNSUSN);
ply_ptr->hpcur-=5;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[5]+=1;
break;
case 6:
F_SET(ply_ptr, PNSUSN);
ply_ptr->talk[5]+=1;
break;
case 7:
F_SET(ply_ptr, PNSUSN);
print(ply_ptr->fd, "Your thirst is unbearable.\n");
ply_ptr->hpcur-=5;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[5]+=1;
break;
case 8:
F_SET(ply_ptr, PNSUSN);
ply_ptr->hpcur-=10;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[5]+=1;
break;
case 9:
F_SET(ply_ptr, PNSUSN);
ANSI(ply_ptr->fd, RED);
print(ply_ptr->fd, "You need water badly!");
ANSI(ply_ptr->fd, WHITE);
ply_ptr->hpcur-=20;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[5]=9;
break;
default:
if(ply_ptr->talk[5])
ply_ptr->talk[5]-=1;
break;
}
switch(ply_ptr->talk[6]) {
case 0:
if(mrand(1,100) > 50)
ply_ptr->talk[6]+=1;
break;
case 1:
ply_ptr->talk[6]+=1;
break;
case 2:
print(ply_ptr->fd, "You're getting hungry.\n");
ply_ptr->talk[6]+=1;
break;
case 3:
F_CLR(ply_ptr, PNSUSN);
if(mrand(1,100) > 50)
ply_ptr->talk[6]+=1;
break;
case 4:
F_SET(ply_ptr, PNSUSN);
print(ply_ptr->fd, "Your stomach growls.\n");
broadcast_rom(ply_ptr->fd, ply_ptr->rom_num, "%M's stomach growls.", ply_ptr);
ply_ptr->talk[6]+=1;
break;
case 5:
F_SET(ply_ptr, PNSUSN);
print(ply_ptr->fd, "You better get food soon.\n");
ply_ptr->hpcur-=5;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[6]+=1;
break;
case 6:
F_SET(ply_ptr, PNSUSN);
ply_ptr->talk[6]+=1;
break;
case 7:
F_SET(ply_ptr, PNSUSN);
print(ply_ptr->fd, "Your stomach begins to ache.\n");
ply_ptr->hpcur-=5;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[6]+=1;
break;
case 8:
F_SET(ply_ptr, PNSUSN);
print(ply_ptr->fd, "You need food badly!.\n");
ply_ptr->hpcur-=10;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[6]+=1;
break;
case 9:
F_SET(ply_ptr, PNSUSN);
ANSI(ply_ptr->fd, RED);
print(ply_ptr->fd, "You're starving!\n");
ANSI(ply_ptr->fd, WHITE);
broadcast_rom(ply_ptr->fd, ply_ptr->rom_num, "%M looks faint from lack of food.\n", ply_ptr);
ply_ptr->hpcur-=20;
if(ply_ptr->hpcur<1) {
ply_ptr->hpcur=0;
die(ply_ptr,ply_ptr);
break;
}
ply_ptr->talk[6]=9;
break;
default:
if(ply_ptr->talk[6])
ply_ptr->talk[6]-=1;
break;
}
}
}
/* Check for herb preparation */
if(F_ISSET(ply_ptr, PPREPN)) {
if(t > LT(ply_ptr, LT_PREPN)) {
obj_ptr=ply_ptr->ready[HELD-1];
F_CLR(ply_ptr, PPREPN);
if(!obj_ptr || !F_ISSET(obj_ptr, ONPREP)|| ply_ptr->ready[WIELD-1]) {
if(obj_ptr)
F_CLR(obj_ptr, ONPREP);
badprep=1;
}
if(ply_ptr->intelligence*3+ply_ptr->level*3-(100-Ply[ply_ptr->fd].extr->luck)<mrand(1,100)) {
badprep=1;
print(ply_ptr->fd,"Your preparation of %i fails.\n", obj_ptr);
F_CLR(obj_ptr, ONPREP);
obj_ptr->shotscur-=1;
if(obj_ptr->shotscur < 0)
obj_ptr->shotscur=0;
}
if(!badprep) {
print(ply_ptr->fd,"You finish preparing %i.\n", obj_ptr);
F_CLR(obj_ptr, ONPREP);
F_SET(obj_ptr, ODPREP);
broadcast_rom(ply_ptr->fd,ply_ptr->rom_num,
"%M has finished preparing %i.",ply_ptr, obj_ptr);
}
}
}
/* Check for temp enchant items carried/inventory/in containers */
if(ply_ptr->lasttime[LT_MSCAV].interval+ply_ptr->lasttime[LT_MSCAV].ltime<t){
ply_ptr->lasttime[LT_MSCAV].ltime=t;
ply_ptr->lasttime[LT_MSCAV].interval=40;
op=ply_ptr->first_obj;
while(op) {
if(op->obj->type == CONTAINER) {
cop=op->obj->first_obj;
while(cop) {
if(cop->obj && F_ISSET(cop->obj, OTMPEN)) {
dur=(int)(cop->obj->magicrealm);
ltime=(int)(cop->obj->magicpower);
if(!dur && !ltime) {
cop->obj->pdice=0;
cop->obj->adjustment=0;
F_CLR(cop->obj, OTMPEN);
F_CLR(cop->obj, ORENCH);
F_CLR(cop->obj, OENCHA);
if(F_ISSET(ply_ptr, PDMAGI))
print(ply_ptr->fd, "The enchantment fades on your %s.\n", cop->obj->name);
break;
}
if(!dur) {
ltime-=1;
cop->obj->magicpower=(char)ltime;
}
else {
dur-=1;
cop->obj->magicrealm=(char)dur;
}
}
cop=cop->next_tag;
}
}
if(op->obj && F_ISSET(op->obj, OTMPEN)) {
dur=(int)(op->obj->magicrealm);
ltime=(int)(op->obj->magicpower);
if(!dur && !ltime) {
op->obj->pdice=0;
op->obj->adjustment=0;
F_CLR(op->obj, OTMPEN);
F_CLR(op->obj, ORENCH);
F_CLR(op->obj, OENCHA);
if(F_ISSET(ply_ptr, PDMAGI))
print(ply_ptr->fd, "The enchantment fades on your %s.\n", op->obj->name);
break;
}
if(!dur) {
ltime-=1;
op->obj->magicpower=(char)ltime;
}
else {
dur-=1;
op->obj->magicrealm=(char)dur;
}
}
op=op->next_tag;
}
/* Check held/readied eq */
for(i=0; i<MAXWEAR; i++) {
/* ASSUMPTION: we will only find containers at the HELD
position */
if(i==(HELD-1) && ply_ptr->ready[i] && ply_ptr->ready[i]->type==CONTAINER) {
cop=ply_ptr->ready[i]->first_obj;
while(cop) {
if(cop->obj && F_ISSET(cop->obj, OTMPEN)) {
dur=(int)(cop->obj->magicrealm);
ltime=(int)(cop->obj->magicpower);
if(!dur && !ltime) {
cop->obj->pdice=0;
cop->obj->adjustment=0;
F_CLR(cop->obj, OTMPEN);
F_CLR(cop->obj, ORENCH);
F_CLR(cop->obj, OENCHA);
if(F_ISSET(ply_ptr, PDMAGI))
print(ply_ptr->fd, "The enchantment on your %s fades.\n", cop->obj->name);
break;
}
if(!dur) {
ltime-=1;
cop->obj->magicpower=(char)ltime;
}
else {
dur-=1;
cop->obj->magicrealm=(char)dur;
}
}
cop=cop->next_tag;
}
}
if(ply_ptr->ready[i]&&F_ISSET(ply_ptr->ready[i], OTMPEN)){
ltime=(int)(ply_ptr->ready[i]->magicpower);
dur=(int)(ply_ptr->ready[i]->magicrealm);
if(!dur && !ltime) {
ply_ptr->ready[i]->pdice=0;
ply_ptr->ready[i]->adjustment=0;
F_CLR(ply_ptr->ready[i], OTMPEN);
F_CLR(ply_ptr->ready[i], ORENCH);
F_CLR(ply_ptr->ready[i], OENCHA);
if(F_ISSET(ply_ptr, PDMAGI))
print(ply_ptr->fd, "The enchantment fades on your %s.\n", ply_ptr->ready[i]->name);
break;
}
if(!dur) {
ltime-=1;
ply_ptr->ready[i]->magicpower=(char)ltime;
}
else
dur-=1;
ply_ptr->ready[i]->magicrealm=(char)dur;
}
}
}
if(F_ISSET(ply_ptr, PHASTE)) {
if(t > LT(ply_ptr, LT_HASTE)) {
ANSI(ply_ptr->fd, GREEN);
print(ply_ptr->fd, "You feel slower.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PHASTE);
ply_ptr->dexterity -= 5;
}
}
if(F_ISSET(ply_ptr, PPRAYD)) {
if(t > LT(ply_ptr, LT_PRAYD)) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "You feel less pious.\n");
F_CLR(ply_ptr, PPRAYD);
ANSI(ply_ptr->fd, WHITE);
ply_ptr->piety -= 5;
}
}
if(F_ISSET(ply_ptr, PINVIS)) {
if(t > LT(ply_ptr, LT_INVIS) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, MAGENTA);
print(ply_ptr->fd, "Your invisibility wears off.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PINVIS);
}
}
if(F_ISSET(ply_ptr, PDINVI)) {
if(t > LT(ply_ptr, LT_DINVI) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, MAGENTA);
print(ply_ptr->fd, "Your detect-invis wears off.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PDINVI);
}
}
if(F_ISSET(ply_ptr, PDMAGI)&&ply_ptr->class!=ALCHEMIST) {
if(t > LT(ply_ptr, LT_DMAGI) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, MAGENTA);
print(ply_ptr->fd, "Your detect-magic wears off.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PDMAGI);
}
}
if(F_ISSET(ply_ptr, PHIDDN)) {
if(t-ply_ptr->lasttime[LT_HIDES].ltime > 300L)
F_CLR(ply_ptr, PHIDDN);
}
if(F_ISSET(ply_ptr, PPROTE)) {
if(t > LT(ply_ptr, LT_PROTE)) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "You feel less protected.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PPROTE);
compute_ac(ply_ptr);
}
}
if(F_ISSET(ply_ptr, PLEVIT)) {
if(t > LT(ply_ptr, LT_LEVIT) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, MAGENTA);
print(ply_ptr->fd, "Your feet hit the ground.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PLEVIT);
}
}
if(F_ISSET(ply_ptr, PBLESS)) {
if(t > LT(ply_ptr, LT_BLESS)) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "You feel less holy.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PBLESS);
compute_thaco(ply_ptr);
}
}
if(F_ISSET(ply_ptr, PRFIRE)) {
if(t > LT(ply_ptr, LT_RFIRE)) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "Your skin returns to normal.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PRFIRE);
}
}
if(F_ISSET(ply_ptr, PRCOLD)) {
if(t > LT(ply_ptr, LT_RCOLD)) {
ANSI(ply_ptr->fd, BOLD);
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "A cold chill runs through your body.\n");
ANSI(ply_ptr->fd, NORMAL);
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PRCOLD);
}
}
if(F_ISSET(ply_ptr, PBRWAT)) {
if(t > LT(ply_ptr, LT_BRWAT)) {
ANSI(ply_ptr->fd, BOLD);
ANSI(ply_ptr->fd, BLUE);
print(ply_ptr->fd, "Your lungs contract in size.\n");
ANSI(ply_ptr->fd, WHITE);
ANSI(ply_ptr->fd, NORMAL);
F_CLR(ply_ptr, PBRWAT);
}
}
if(F_ISSET(ply_ptr, PSSHLD)) {
if(t > LT(ply_ptr, LT_SSHLD)) {
ANSI(ply_ptr->fd, BOLD);
ANSI(ply_ptr->fd, GREEN);
print(ply_ptr->fd, "Your skin softens.\n");
ANSI(ply_ptr->fd, WHITE);
ANSI(ply_ptr->fd, NORMAL);
F_CLR(ply_ptr, PSSHLD);
}
}
if(F_ISSET(ply_ptr, PFLYSP)) {
if(t > LT(ply_ptr, LT_FLYSP) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "You can no longer fly.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PFLYSP);
}
}
if(F_ISSET(ply_ptr, PRMAGI)) {
if(t > LT(ply_ptr, LT_RMAGI)) {
ANSI(ply_ptr->fd, BOLD);
ANSI(ply_ptr->fd, MAGENTA);
print(ply_ptr->fd,"Your magical shield dissipates.\n");
ANSI(ply_ptr->fd, WHITE);
ANSI(ply_ptr->fd, NORMAL);
F_CLR(ply_ptr, PRMAGI);
}
}
if(F_ISSET(ply_ptr, PSILNC)) {
if(t > LT(ply_ptr, LT_SILNC)) {
ANSI(ply_ptr->fd, GREEN);
print(ply_ptr->fd,"Your voice returns!\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PSILNC);
}
}
if(F_ISSET(ply_ptr, PFEARS)) {
if(t > LT(ply_ptr, LT_FEARS)) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd,"You feel your courage return.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PFEARS);
}
}
if(F_ISSET(ply_ptr, PKNOWA)) {
if(t > LT(ply_ptr, LT_KNOWA) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, CYAN);
print(ply_ptr->fd,"Your perception is diminshed.\n");
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PKNOWA);
}
}
if(F_ISSET(ply_ptr, PLIGHT)) {
if(t > LT(ply_ptr, LT_LIGHT) && ply_ptr->class < DM) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "Your magical light fades.\n");
broadcast_rom(ply_ptr->fd, ply_ptr->rom_num,"%M's magical light fades.", ply_ptr);
ANSI(ply_ptr->fd, WHITE);
F_CLR(ply_ptr, PLIGHT);
}
}
if(t > LT(ply_ptr, LT_CHRMD) && F_ISSET(ply_ptr, PCHARM)) {
ANSI(ply_ptr->fd, YELLOW);
print(ply_ptr->fd, "Your demeanor returns to normal.\n");
F_CLR(ply_ptr, PCHARM);
ANSI(ply_ptr->fd, WHITE);
}
/* check if player is suffering from any aliment */
if(F_ISSET(ply_ptr, PPOISN) || F_ISSET(ply_ptr, PDISEA) || F_ISSET(ply_ptr, PNSUSN))
ill = 1;
else
ill =0;
/* handle normal healing for non posioned or harm room */
if(ply_ptr->parent_rom && (t > LT(ply_ptr, LT_HEALS)))
if(!F_ISSET(ply_ptr->parent_rom, RPHARM) && (!ill)) {
ply_ptr->hpcur += MAX(1, 3 + bonus[ply_ptr->constitution] +
(ply_ptr->class == BARBARIAN ? 2:0));
ply_ptr->mpcur += MAX(1, 2+(ply_ptr->intelligence > 17 ? 1:0)+
((ply_ptr->class == MAGE || ply_ptr->class == ALCHEMIST) ? 2:0));
ply_ptr->lasttime[LT_HEALS].ltime = t;
ply_ptr->lasttime[LT_HEALS].interval = 45 -
5*bonus[ply_ptr->piety];
/* handle quick healing */
if(F_ISSET(ply_ptr->parent_rom, RHEALR)) {
ply_ptr->hpcur += 3;
ply_ptr->mpcur += 2;
ply_ptr->lasttime[LT_HEALS].interval /= 2;
}
ply_ptr->hpcur = MIN(ply_ptr->hpcur, ply_ptr->hpmax);
ply_ptr->mpcur = MIN(ply_ptr->mpcur, ply_ptr->mpmax);
}
/* handle poison */
else if(!F_ISSET(ply_ptr->parent_rom, RPHARM) && ill) {
if(F_ISSET(ply_ptr, PPOISN) && ply_ptr->class != DRUID){
ANSI(ply_ptr->fd, BLINK);
ANSI(ply_ptr->fd, RED);
print(ply_ptr->fd, "Poison courses through your veins.\n");
ply_ptr->hpcur -= MAX(1,mrand(1,4)-bonus[ply_ptr->constitution]);
ply_ptr->lasttime[LT_HEALS].ltime = t;
ply_ptr->lasttime[LT_HEALS].interval = 65 + 5*bonus[ply_ptr->constitution];
ANSI(ply_ptr->fd, WHITE);
ANSI(ply_ptr->fd, NORMAL);
if(ply_ptr->hpcur < 1)
die(ply_ptr, ply_ptr);
}
else if(F_ISSET(ply_ptr, PPOISN) && ply_ptr->class == DRUID)
F_CLR(ply_ptr, PPOISN);
if (F_ISSET(ply_ptr, PDISEA)){
ANSI(ply_ptr->fd, BLINK);
ANSI(ply_ptr->fd, RED);
print(ply_ptr->fd, "Fever grips your mind.\n");
ply_ptr->lasttime[LT_ATTCK].ltime = time(0);
ANSI(ply_ptr->fd, BLUE);
print(ply_ptr->fd, "You feel nauseous.\n");
ply_ptr->lasttime[LT_ATTCK].interval= dice(1,6,3);
ply_ptr->hpcur -= MAX(1,mrand(1,6)-bonus[ply_ptr->constitution]);
ply_ptr->lasttime[LT_HEALS].ltime = t;
ply_ptr->lasttime[LT_HEALS].interval = 65 + 5*bonus[ply_ptr->constitution];
ANSI(ply_ptr->fd, WHITE);
ANSI(ply_ptr->fd, NORMAL);
if(ply_ptr->hpcur < 1)
die(ply_ptr, ply_ptr);
}
}
/* handle player harm rooms */
else {
if (F_ISSET(ply_ptr->parent_rom, RPPOIS))
{
ANSI(ply_ptr->fd, BLINK);
ANSI(ply_ptr->fd, GREEN);
print(ply_ptr->fd, "The toxic air poisoned you.\n");
ANSI(ply_ptr->fd, WHITE);
ANSI(ply_ptr->fd, NORMAL);
F_SET(ply_ptr, PPOISN);
}
if (F_ISSET(ply_ptr->parent_rom, RPBEFU))
{
print(ply_ptr->fd, "The room starts to spin around you.\nYou feel confused.\n");
ply_ptr->lasttime[LT_ATTCK].ltime = time(0);
ply_ptr->lasttime[LT_ATTCK].interval= MAX(dice(2,6,0),6);
}
if (F_ISSET(ply_ptr, PPOISN)){
ANSI(ply_ptr->fd, BLINK);
ANSI(ply_ptr->fd, RED);
print(ply_ptr->fd, "Poison courses through your veins.\n");
ANSI(ply_ptr->fd, NORMAL);
ANSI(ply_ptr->fd, WHITE);
ply_ptr->hpcur -= MAX(1,mrand(1,6)-bonus[ply_ptr->constitution]);
if(ply_ptr->hpcur < 1) die(ply_ptr, ply_ptr);
}
if (F_ISSET(ply_ptr, PDISEA)){
ANSI(ply_ptr->fd, BLINK);
ANSI(ply_ptr->fd, RED);
print(ply_ptr->fd, "Fever grips your mind.\n");
ply_ptr->lasttime[LT_ATTCK].ltime = time(0);
ANSI(ply_ptr->fd, BLUE);
print(ply_ptr->fd, "You feel nauseous.\n");
ply_ptr->lasttime[LT_ATTCK].interval= dice(1,6,3);
ply_ptr->hpcur -= MAX(1,mrand(1,12)-bonus[ply_ptr->constitution]);
ply_ptr->lasttime[LT_HEALS].ltime = t;
ply_ptr->lasttime[LT_HEALS].interval = 65 +
5*bonus[ply_ptr->constitution];
ANSI(ply_ptr->fd, NORMAL);
ANSI(ply_ptr->fd, WHITE);
if(ply_ptr->hpcur < 1)
die(ply_ptr, ply_ptr);
}
if (F_ISSET(ply_ptr->parent_rom,RPMPDR))
ply_ptr->mpcur -= MIN(ply_ptr->mpcur,6);
else if (!ill) {
ply_ptr->mpcur += MAX(1, 2+(ply_ptr->intelligence > 17 ? 1:0)+
((ply_ptr->class == MAGE || ply_ptr->class ==ALCHEMIST) ? 2:0));
ply_ptr->mpcur = MIN(ply_ptr->mpcur, ply_ptr->mpmax);
}
if (F_ISSET(ply_ptr->parent_rom, RFIRER) && !F_ISSET(ply_ptr,PRFIRE)) {
print(ply_ptr->fd, "The searing heat burns your flesh.\n");
prot = 0;
}
else if (F_ISSET(ply_ptr->parent_rom, RWATER) && !F_ISSET(ply_ptr,PBRWAT)) {
print(ply_ptr->fd, "Water fills your lungs.\n");
prot = 0;
}
else if (F_ISSET(ply_ptr->parent_rom, REARTH) && !F_ISSET(ply_ptr,PSSHLD)) {
print(ply_ptr->fd, "The earth swells up around you and smothers you.\n");
prot = 0;
}
else if (F_ISSET(ply_ptr->parent_rom, RWINDR) && !F_ISSET(ply_ptr,PRCOLD)) {
ANSI(ply_ptr->fd, BLUE);
print(ply_ptr->fd, "The freezing air chills you to the bone.\n");
ANSI(ply_ptr->fd, WHITE);
prot = 0;
}
else if(!F_ISSET(ply_ptr->parent_rom, RWINDR) &&
!F_ISSET(ply_ptr->parent_rom, REARTH) &&
!F_ISSET(ply_ptr->parent_rom, RFIRER) &&
!F_ISSET(ply_ptr->parent_rom, RWATER) &&
!F_ISSET(ply_ptr->parent_rom, RPPOIS) &&
!F_ISSET(ply_ptr->parent_rom, RPBEFU) &&
!F_ISSET(ply_ptr->parent_rom, RPMPDR)) {
ANSI(ply_ptr->fd, BOLD);
ANSI(ply_ptr->fd, MAGENTA);
print(ply_ptr->fd, "An invisible force saps your life force.\n");
ANSI(ply_ptr->fd, NORMAL);
ANSI(ply_ptr->fd, WHITE);
prot = 0;
}
if (!prot) {
ply_ptr->hpcur -= 15 - MIN(bonus[ply_ptr->constitution],2);
if(ply_ptr->hpcur < 1) die(ply_ptr, ply_ptr);
}
else if (!ill)
{
ply_ptr->hpcur += MAX(1, 3 + bonus[ply_ptr->constitution] +
(ply_ptr->class == BARBARIAN ? 2:0));
ply_ptr->hpcur = MIN(ply_ptr->hpcur, ply_ptr->hpmax);
}
ply_ptr->lasttime[LT_HEALS].ltime = t;
ply_ptr->lasttime[LT_HEALS].interval = 45 + 5*bonus[ply_ptr->piety];
}
/*******************************/
if(t > LT(ply_ptr, LT_PSAVE)) {
ply_ptr->lasttime[LT_PSAVE].ltime = t;
savegame(ply_ptr, 0);
}
item = has_light(ply_ptr);
if(item && item != MAXWEAR+1) {
if(ply_ptr->ready[item-1]->type == LIGHTSOURCE)
if(--(ply_ptr->ready[item-1]->shotscur) < 1) {
print(ply_ptr->fd, "Your %s died out.\n",
ply_ptr->ready[item-1]->name);
broadcast_rom(ply_ptr->fd, ply_ptr->rom_num,
"%M's %s died out.",
ply_ptr,
ply_ptr->ready[item-1]->name);
}
}
}
/**********************************************************************/
/* up_level */
/**********************************************************************/
/* This function should be called whenever a player goes up a level. */
/* It raises her hit points and magic points appropriately, and if */
/* it is initializing a new character, it sets up the character. */
void up_level(ply_ptr)
creature *ply_ptr;
{
int index;
ply_ptr->level++;
ply_ptr->hpmax += class_stats[ply_ptr->class].hp;
ply_ptr->mpmax += class_stats[ply_ptr->class].mp;
if(ply_ptr->level == 1) {
ply_ptr->hpmax = class_stats[ply_ptr->class].hpstart;
ply_ptr->mpmax = class_stats[ply_ptr->class].mpstart;
ply_ptr->hpcur = ply_ptr->hpmax;
ply_ptr->mpcur = ply_ptr->mpmax;
ply_ptr->ndice = class_stats[ply_ptr->class].ndice;
ply_ptr->sdice = class_stats[ply_ptr->class].sdice;
ply_ptr->pdice = class_stats[ply_ptr->class].pdice;
}
else {
index = (ply_ptr->level-2) % 10;
switch(level_cycle[ply_ptr->class][index]) {
case STR: ply_ptr->strength++; break;
case DEX: ply_ptr->dexterity++; break;
case CON: ply_ptr->constitution++; break;
case INT: ply_ptr->intelligence++; break;
case PTY: ply_ptr->piety++; break;
}
/* MONK CODE */
/* Yeah, I know this is ugly */
/* Feel free to send a patch */
if(ply_ptr->class == MONK) {
switch(ply_ptr->level) {
case 1:
ply_ptr->ndice = class_stats[ply_ptr->class].ndice;
ply_ptr->sdice = class_stats[ply_ptr->class].sdice;
ply_ptr->pdice = class_stats[ply_ptr->class].pdice;
break;
case 2:
ply_ptr->ndice = 1;
ply_ptr->sdice = 5;
ply_ptr->pdice = 0;
break;
case 3:
ply_ptr->ndice = 1;
ply_ptr->sdice = 5;
ply_ptr->pdice = 1;
break;
case 4:
ply_ptr->ndice = 1;
ply_ptr->sdice = 6;
ply_ptr->pdice = 0;
break;
case 5:
ply_ptr->ndice = 1;
ply_ptr->sdice = 6;
ply_ptr->pdice = 1;
break;
case 6:
ply_ptr->ndice = 1;
ply_ptr->sdice = 6;
ply_ptr->pdice = 2;
break;
case 7:
ply_ptr->ndice = 2;
ply_ptr->sdice = 3;
ply_ptr->pdice = 1;
break;
case 8:
ply_ptr->ndice = 2;
ply_ptr->sdice = 4;
ply_ptr->pdice = 0;
break;
case 9:
ply_ptr->ndice = 2;
ply_ptr->sdice = 4;
ply_ptr->pdice = 1;
break;
case 10:
ply_ptr->ndice = 2;
ply_ptr->sdice = 5;
ply_ptr->pdice = 0;
break;
case 11:
ply_ptr->ndice = 2;
ply_ptr->sdice = 5;
ply_ptr->pdice = 2;
break;
case 12:
ply_ptr->ndice = 2;
ply_ptr->sdice = 6;
ply_ptr->pdice = 1;
break;
case 13:
ply_ptr->ndice = 2;
ply_ptr->sdice = 6;
ply_ptr->pdice = 2;
break;
case 14:
ply_ptr->ndice = 3;
ply_ptr->sdice = 6;
ply_ptr->pdice = 1;
break;
case 15:
ply_ptr->ndice = 3;
ply_ptr->sdice = 7;
ply_ptr->pdice = 1;
break;
case 16:
ply_ptr->ndice = 4;
ply_ptr->sdice = 7;
ply_ptr->pdice = 1;
break;
case 17:
ply_ptr->ndice = 5;
ply_ptr->sdice = 7;
ply_ptr->pdice = 0;
break;
case 18:
ply_ptr->ndice = 5;
ply_ptr->sdice = 8;
ply_ptr->pdice = 1;
break;
case 19:
ply_ptr->ndice = 6;
ply_ptr->sdice = 7;
ply_ptr->pdice = 0;
break;
case 20:
ply_ptr->ndice = 6;
ply_ptr->sdice = 7;
ply_ptr->pdice = 2;
break;
case 21:
ply_ptr->ndice = 6;
ply_ptr->sdice = 8;
ply_ptr->pdice = 0;
break;
case 22:
ply_ptr->ndice = 6;
ply_ptr->sdice = 8;
ply_ptr->pdice = 2;
break;
case 23:
ply_ptr->ndice = 6;
ply_ptr->sdice = 9;
ply_ptr->pdice = 0;
break;
case 24:
ply_ptr->ndice = 6;
ply_ptr->sdice = 8;
ply_ptr->pdice = 2;
break;
case 25:
ply_ptr->ndice = 6;
ply_ptr->sdice = 10;
ply_ptr->pdice = 0;
default:
ply_ptr->ndice = 1;
ply_ptr->sdice = 3;
ply_ptr->pdice = 0;
break;
}
}
/* END MONK */
}
}
/**********************************************************************/
/* down_level */
/**********************************************************************/
/* This function is called when a player loses a level due to dying or */
/* for some other reason. The appropriate stats are downgraded. */
void down_level(ply_ptr)
creature *ply_ptr;
{
int index;
ply_ptr->level--;
ply_ptr->hpmax -= class_stats[ply_ptr->class].hp;
ply_ptr->mpmax -= class_stats[ply_ptr->class].mp;
ply_ptr->hpcur = ply_ptr->hpmax;
ply_ptr->mpcur = ply_ptr->mpmax;
index = (ply_ptr->level-1) % 10;
switch(level_cycle[ply_ptr->class][index]) {
case STR: ply_ptr->strength--; break;
case DEX: ply_ptr->dexterity--; break;
case CON: ply_ptr->constitution--; break;
case INT: ply_ptr->intelligence--; break;
case PTY: ply_ptr->piety--; break;
}
/* MONK CODE */
/* Yeah, I know this is ugly */
if(ply_ptr->class == MONK) {
switch(ply_ptr->level) {
case 1:
ply_ptr->ndice = class_stats[ply_ptr->class].ndice;
ply_ptr->sdice = class_stats[ply_ptr->class].sdice;
ply_ptr->pdice = class_stats[ply_ptr->class].pdice;
break;
case 2:
ply_ptr->ndice = 1;
ply_ptr->sdice = 5;
ply_ptr->pdice = 0;
break;
case 3:
ply_ptr->ndice = 1;
ply_ptr->sdice = 5;
ply_ptr->pdice = 1;
break;
case 4:
ply_ptr->ndice = 1;
ply_ptr->sdice = 6;
ply_ptr->pdice = 0;
break;
case 5:
ply_ptr->ndice = 1;
ply_ptr->sdice = 6;
ply_ptr->pdice = 1;
break;
case 6:
ply_ptr->ndice = 1;
ply_ptr->sdice = 6;
ply_ptr->pdice = 2;
break;
case 7:
ply_ptr->ndice = 2;
ply_ptr->sdice = 3;
ply_ptr->pdice = 1;
break;
case 8:
ply_ptr->ndice = 2;
ply_ptr->sdice = 4;
ply_ptr->pdice = 0;
break;
case 9:
ply_ptr->ndice = 2;
ply_ptr->sdice = 4;
ply_ptr->pdice = 1;
break;
case 10:
ply_ptr->ndice = 2;
ply_ptr->sdice = 5;
ply_ptr->pdice = 0;
break;
case 11:
ply_ptr->ndice = 2;
ply_ptr->sdice = 5;
ply_ptr->pdice = 2;
break;
case 12:
ply_ptr->ndice = 2;
ply_ptr->sdice = 6;
ply_ptr->pdice = 1;
break;
case 13:
ply_ptr->ndice = 2;
ply_ptr->sdice = 6;
ply_ptr->pdice = 2;
break;
case 14:
ply_ptr->ndice = 3;
ply_ptr->sdice = 6;
ply_ptr->pdice = 1;
break;
case 15:
ply_ptr->ndice = 3;
ply_ptr->sdice = 7;
ply_ptr->pdice = 1;
break;
case 16:
ply_ptr->ndice = 4;
ply_ptr->sdice = 7;
ply_ptr->pdice = 1;
break;
case 17:
ply_ptr->ndice = 5;
ply_ptr->sdice = 7;
ply_ptr->pdice = 0;
break;
case 18:
ply_ptr->ndice = 5;
ply_ptr->sdice = 8;
ply_ptr->pdice = 1;
break;
case 19:
ply_ptr->ndice = 6;
ply_ptr->sdice = 7;
ply_ptr->pdice = 0;
break;
case 20:
ply_ptr->ndice = 6;
ply_ptr->sdice = 7;
ply_ptr->pdice = 2;
break;
case 21:
ply_ptr->ndice = 6;
ply_ptr->sdice = 8;
ply_ptr->pdice = 0;
break;
case 22:
ply_ptr->ndice = 6;
ply_ptr->sdice = 8;
ply_ptr->pdice = 2;
break;
case 23:
ply_ptr->ndice = 6;
ply_ptr->sdice = 9;
ply_ptr->pdice = 0;
break;
case 24:
ply_ptr->ndice = 6;
ply_ptr->sdice = 8;
ply_ptr->pdice = 2;
break;
case 25:
ply_ptr->ndice = 6;
ply_ptr->sdice = 10;
ply_ptr->pdice = 0;
default:
ply_ptr->ndice = 1;
ply_ptr->sdice = 3;
ply_ptr->pdice = 0;
break;
}
}
/* END MONK */
}
/**********************************************************************/
/* add_obj_crt */
/**********************************************************************/
/* This function adds the object pointer to by the first parameter to */
/* the inventory of the player pointed to by the second parameter. */
void add_obj_crt(obj_ptr, ply_ptr)
object *obj_ptr;
creature *ply_ptr;
{
otag *op, *temp, *prev;
obj_ptr->parent_crt = ply_ptr;
obj_ptr->parent_obj = 0;
obj_ptr->parent_rom = 0;
op = (otag *)malloc(sizeof(otag));
if(!op)
merror("add_obj_crt", FATAL);
op->obj = obj_ptr;
op->next_tag = 0;
if(!ply_ptr->first_obj) {
ply_ptr->first_obj = op;
return;
}
temp = ply_ptr->first_obj;
if(strcmp(temp->obj->name, obj_ptr->name) > 0 ||
(!strcmp(temp->obj->name, obj_ptr->name) &&
temp->obj->adjustment > obj_ptr->adjustment)) {
op->next_tag = temp;
ply_ptr->first_obj = op;
return;
}
while(temp) {
if(strcmp(temp->obj->name, obj_ptr->name) > 0 ||
(!strcmp(temp->obj->name, obj_ptr->name) &&
temp->obj->adjustment > obj_ptr->adjustment))
break;
prev = temp;
temp = temp->next_tag;
}
op->next_tag = prev->next_tag;
prev->next_tag = op;
}
/**********************************************************************/
/* del_obj_crt */
/**********************************************************************/
/* This function removes the object pointer to by the first parameter */
/* from the player pointed to by the second. */
void del_obj_crt(obj_ptr, ply_ptr)
object *obj_ptr;
creature *ply_ptr;
{
otag *temp, *prev;
if(!obj_ptr->parent_crt) {
ply_ptr->ready[obj_ptr->wearflag-1] = 0;
return;
}
obj_ptr->parent_crt = 0;
if(ply_ptr->first_obj->obj == obj_ptr) {
temp = ply_ptr->first_obj->next_tag;
free(ply_ptr->first_obj);
ply_ptr->first_obj = temp;
return;
}
prev = ply_ptr->first_obj;
temp = prev->next_tag;
while(temp) {
if(temp->obj == obj_ptr) {
prev->next_tag = temp->next_tag;
free(temp);
return;
}
prev = temp;
temp = temp->next_tag;
}
}
/**********************************************************************/
/* title_ply */
/**********************************************************************/
/* This function returns a string with the player's character title in */
/* it. The title is determined by looking at the player's class and */
/* level. */
char *title_ply(ply_ptr)
creature *ply_ptr;
{
int titlnum;
titlnum = (ply_ptr->level-1)/3;
if(titlnum > 7)
titlnum = 7;
return(lev_title[ply_ptr->class][titlnum]);
}
/**********************************************************************/
/* compute_ac */
/**********************************************************************/
/* This function computes a player's (or a monster's) armor class by */
/* examining its stats and the items it is holding. */
void compute_ac(ply_ptr)
creature *ply_ptr;
{
int ac, i;
ac = 100;
ac -= 5*bonus[ply_ptr->dexterity];
for(i=0; i<MAXWEAR; i++)
if(ply_ptr->ready[i])
ac -= ply_ptr->ready[i]->armor;
if(ply_ptr->class == MONK)
ac = 100-ply_ptr->level*7;
if(F_ISSET(ply_ptr, PPROTE))
ac -= 10;
ac = MAX(-127,MIN(127,ac));
ply_ptr->armor = ac;
}
/**********************************************************************/
/* compute_thaco */
/**********************************************************************/
/* This function computes a player's THAC0 by looking at his class, */
/* level, weapon adjustment and strength bonuses. */
void compute_thaco(ply_ptr)
creature *ply_ptr;
{
int thaco, n;
n = ply_ptr->level > 20 ? 19:ply_ptr->level-1;
thaco = thaco_list[ply_ptr->class][n];
if(ply_ptr->ready[WIELD-1])
thaco -= ply_ptr->ready[WIELD-1]->adjustment;
thaco -= mod_profic(ply_ptr);
thaco -= bonus[ply_ptr->strength];
if(F_ISSET(ply_ptr, PBLESS))
thaco -= 1;
ply_ptr->thaco = MAX(0, thaco);
}
/**********************************************************************/
/* mod_profic */
/**********************************************************************/
/* This function returns the player's currently-used proficiency div 20 */
int mod_profic(ply_ptr)
creature *ply_ptr;
{
int amt;
switch(ply_ptr->class) {
case FIGHTER:
case BARBARIAN:
amt = 20;
break;
case RANGER:
case PALADIN:
amt = 25;
break;
case THIEF:
case ASSASSIN:
case MONK:
case CLERIC:
amt = 30;
break;
default:
amt = 40;
break;
}
if(ply_ptr->ready[WIELD-1] &&
ply_ptr->ready[WIELD-1]->type <= MISSILE)
return(profic(ply_ptr, ply_ptr->ready[WIELD-1]->type)/amt);
else
return(profic(ply_ptr, BLUNT)/amt);
}
/**********************************************************************/
/* weight_ply */
/**********************************************************************/
/* This function calculates the total weight that a player (or monster) */
/* is carrying in his inventory. */
int weight_ply(ply_ptr)
creature *ply_ptr;
{
int i, n = 0;
otag *op;
op = ply_ptr->first_obj;
while(op) {
if(!F_ISSET(op->obj, OWTLES))
n += weight_obj(op->obj);
op = op->next_tag;
}
for(i=0; i<MAXWEAR; i++)
if(ply_ptr->ready[i])
n += weight_obj(ply_ptr->ready[i]);
return(n);
}
/**********************************************************************/
/* max_weight */
/**********************************************************************/
/* This function returns the maximum weight a player can be allowed to */
/* hold in his inventory. */
int max_weight(ply_ptr)
creature *ply_ptr;
{
int n;
n = 20 + ply_ptr->strength*10;
if(ply_ptr->class == BARBARIAN)
n += ply_ptr->level*10;
return(n);
}
/**********************************************************************/
/* profic */
/**********************************************************************/
/* This function determines a weapons proficiency percentage. The first */
/* parameter contains a pointer to the player whose percentage is being */
/* determined. The second is an integer containing the proficiency */
/* number. */
int profic(ply_ptr, index)
creature *ply_ptr;
int index;
{
long prof_array[12];
int i, n, prof;
switch (ply_ptr->class){
case FIGHTER:
prof_array[0] = 0L; prof_array[1] = 768L;
prof_array[2] = 1024L; prof_array[3] = 1440L;
prof_array[4] = 1910L; prof_array[5] = 16000L;
prof_array[6] = 31214L; prof_array[7] = 167000L;
prof_array[8] = 268488L; prof_array[9] = 695000L;
prof_array[10] = 934808L;
prof_array[11] = 500000000L;
break;
case BARBARIAN:
case PALADIN:
case RANGER:
case MONK:
case DM:
case CARETAKER:
prof_array[0] = 0L; prof_array[1] = 768L;
prof_array[2] = 1024L; prof_array[3] = 1800L;
prof_array[4] = 2388L; prof_array[5] = 20000L;
prof_array[6] = 37768L; prof_array[7] = 205000L;
prof_array[8] = 325610L; prof_array[9] = 895000L;
prof_array[10] = 1549760L;
prof_array[11] = 500000000L;
break;
case BARD:
case THIEF:
case ASSASSIN:
prof_array[0] = 0L; prof_array[1] = 768L;
prof_array[2] = 1024L; prof_array[3] = 1800L;
prof_array[4] = 2388L; prof_array[5] = 20000L;
prof_array[6] = 42768L; prof_array[7] = 220000L;
prof_array[8] = 355610L; prof_array[9] = 950000L;
prof_array[10] = 1949760L;
prof_array[11] = 500000000L;
break;
case ALCHEMIST:
case DRUID:
case CLERIC:
prof_array[0] = 0L; prof_array[1] = 768L;
prof_array[2] = 1024L; prof_array[3] = 1800L;
prof_array[4] = 2388L; prof_array[5] = 22000L;
prof_array[6] = 47768L; prof_array[7] = 215000L;
prof_array[8] = 370610L; prof_array[9] = 975000L;
prof_array[10] = 2044760L;
prof_array[11] = 500000000L;
break;
case MAGE:
prof_array[0] = 0L; prof_array[1] = 768L;
prof_array[2] = 1024L; prof_array[3] = 1800L;
prof_array[4] = 2388L; prof_array[5] = 25000L;
prof_array[6] = 50768L; prof_array[7] = 215000L;
prof_array[8] = 385610L; prof_array[9] = 1005000L;
prof_array[10] = 2344760L;
prof_array[11] = 500000000L;
break;
default:
return 0;
}
n = ply_ptr->proficiency[index];
for(i=0; i<11; i++)
if(n < prof_array[i+1]) {
prof = 10*i;
break;
}
prof += ((n - prof_array[i])*10) / (prof_array[i+1] - prof_array[i]);
return(prof);
}
/************************************************************************/
/* mprofic */
/************************************************************************/
/* This function returns the magical realm proficiency as a percentage */
int mprofic(ply_ptr, index)
creature *ply_ptr;
int index;
{
long prof_array[12];
int i, n, prof;
switch(ply_ptr->class){
case MAGE:
case ALCHEMIST:
prof_array[0] = 0L; prof_array[1] = 1024L;
prof_array[2] = 2048L; prof_array[3] = 4096L;
prof_array[4] = 8192L; prof_array[5] = 16384L;
prof_array[6] = 35768L; prof_array[7] = 85536L;
prof_array[8] = 140000L; prof_array[9] = 459410L;
prof_array[10] = 2073306L; prof_array[11] = 500000000L;
break;
case CLERIC:
case DRUID:
case BARD:
prof_array[0] = 0L; prof_array[1] = 1024L;
prof_array[2] = 4092L; prof_array[3] = 8192L;
prof_array[4] = 16384L; prof_array[5] = 32768L;
prof_array[6] = 70536L; prof_array[7] = 119000L;
prof_array[8] = 226410L; prof_array[9] = 709410L;
prof_array[10] = 2973307L; prof_array[11] = 500000000L;
break;
case PALADIN:
case MONK:
case RANGER:
prof_array[0] = 0L; prof_array[1] = 1024L;
prof_array[2] = 8192L; prof_array[3] = 16384L;
prof_array[4] = 32768L; prof_array[5] = 65536L;
prof_array[6] = 105000L; prof_array[7] = 165410L;
prof_array[8] = 287306L; prof_array[9] = 809410L;
prof_array[10] = 3538232L; prof_array[11] = 500000000L;
break;
default:
prof_array[0] = 0L; prof_array[1] = 1024L;
prof_array[2] = 40000L; prof_array[3] = 80000L;
prof_array[4] = 120000L; prof_array[5] = 160000L;
prof_array[6] = 205000L; prof_array[7] = 222000L;
prof_array[8] = 380000L; prof_array[9] = 965410L;
prof_array[10] = 5495000; prof_array[11] = 500000000L;
break;
}
n = ply_ptr->realm[index-1];
for(i=0; i<11; i++)
if(n < prof_array[i+1]) {
prof = 10*i;
break;
}
prof += ((n - prof_array[i])*10) / (prof_array[i+1] - prof_array[i]);
return(prof);
}
/**********************************************************************/
/* fall_ply */
/**********************************************************************/
/* This function computes a player's bonus (or susceptibility) to falling */
/* while climbing. */
int fall_ply(ply_ptr)
creature *ply_ptr;
{
int fall, j;
fall = bonus[ply_ptr->dexterity]*5;
for(j=0; j<MAXWEAR; j++)
if(ply_ptr->ready[j])
if(F_ISSET(ply_ptr->ready[j], OCLIMB))
fall += ply_ptr->ready[j]->pdice*3;
return(fall);
}
/**********************************************************************/
/* find_who */
/**********************************************************************/
/* This function searches through the players who are currently logged */
/* on for a given player name. If that player is on, a pointer to him */
/* is returned. */
creature *find_who(name)
char *name;
{
int i;
for(i=0; i<Tablesize; i++) {
if(!Ply[i].ply || !Ply[i].io || Ply[i].ply->fd < 0) continue;
if(!strcmp(Ply[i].ply->name, name))
return(Ply[i].ply);
}
return(0);
}
/**********************************************************************/
/* lowest_piety */
/**********************************************************************/
/* This function finds the player with the lowest piety in a given room. */
/* The pointer to that player is returned. In the case of a tie, one of */
/* them is randomly chosen. */
creature *lowest_piety(rom_ptr, invis)
room *rom_ptr;
int invis;
{
creature *ply_ptr = 0;
ctag *cp;
int totalpiety=0, pick=0;
cp = rom_ptr->first_ply;
if(!cp)
return(0);
while(cp) {
if(F_ISSET(cp->crt, PHIDDN) ||
(F_ISSET(cp->crt, PINVIS) && !invis) ||
F_ISSET(cp->crt, PDMINV)) {
cp = cp->next_tag;
continue;
}
totalpiety += MAX(1, (25 - cp->crt->piety));
cp = cp->next_tag;
}
if(!totalpiety)
return(0);
pick = mrand(1, totalpiety);
cp = rom_ptr->first_ply;
totalpiety = 0;
while(cp) {
if(F_ISSET(cp->crt, PHIDDN) ||
(F_ISSET(cp->crt, PINVIS) && !invis) ||
F_ISSET(cp->crt, PDMINV)) {
cp = cp->next_tag;
continue;
}
totalpiety += MAX(1, (25 - cp->crt->piety));
if(totalpiety >= pick) {
ply_ptr = cp->crt;
break;
}
cp = cp->next_tag;
}
return(ply_ptr);
}
/**********************************************************************/
/* has_light */
/**********************************************************************/
/* This function returns true if the player in the first parameter is */
/* holding or wearing anything that generates light. */
int has_light(crt_ptr)
creature *crt_ptr;
{
int i, light = 0;
for(i=0; i<MAXWEAR; i++) {
if(!crt_ptr->ready[i]) continue;
if(F_ISSET(crt_ptr->ready[i], OLIGHT)) {
if((crt_ptr->ready[i]->type == LIGHTSOURCE &&
crt_ptr->ready[i]->shotscur > 0) ||
crt_ptr->ready[i]->type != LIGHTSOURCE) {
light = 1;
break;
}
}
}
if(F_ISSET(crt_ptr, PLIGHT)) {
light = 1;
i = MAXWEAR;
}
if(light)
return(i+1);
else
return(0);
}
/************************************************************************/
/* ply_prompt */
/************************************************************************/
/* This function returns the prompt that the player should be seeing */
char *ply_prompt(ply_ptr)
creature *ply_ptr;
{
static char prompt[40];
int fd;
fd = ply_ptr->fd;
if(fd < 0 || F_ISSET(ply_ptr, PSPYON) || F_ISSET(ply_ptr, PREADI))
prompt[0] = 0;
else if(F_ISSET(ply_ptr, PPROMP) || F_ISSET(ply_ptr, PALIAS))
if(F_ISSET(ply_ptr, PALIAS))
sprintf(prompt, "(%d H %d M): ", Ply[fd].extr->alias_crt->hpcur,
Ply[fd].extr->alias_crt->mpcur);
else
sprintf(prompt, "(%d H %d M): ", ply_ptr->hpcur, ply_ptr->mpcur);
else
strcpy(prompt, ": ");
return(prompt);
}
/**********************************************************************/
/* low_piety_alg */
/**********************************************************************/
/* This function is a varation on the lowest piety function. The *
* searchs the given player list, totally up all the player's piety *
* (30 - ply piety), and then randomly picking a player from the *
* based on the player's piety. Players with lower piety have a *
* greater chance of being attacked. The alg, parameter tells the *
* whether to ignore a given player alignemnt (alg=1, only consider *
* good players, -1 only consider evil players). The invis param *
* tells if the monster can detect invisible. */
creature *low_piety_alg(rom_ptr, invis, alg,lvl)
room *rom_ptr;
int invis;
int alg;
int lvl;
{
creature *ply_ptr = 0;
ctag *cp;
int total, pick;
if(!rom_ptr)
return(NULL);
cp = rom_ptr->first_ply;
total = 0;
if(!cp)
return(NULL);
while(cp) {
if(F_ISSET(cp->crt, PHIDDN) ||
(F_ISSET(cp->crt, PINVIS) && !invis) ||
F_ISSET(cp->crt, PDMINV) ||
(cp->crt->level < lvl) ||
((alg == 1) && (cp->crt->alignment > -100)) ||
((alg == -1) && (cp->crt->alignment < 100))) {
cp = cp->next_tag;
continue;
}
total += MAX(1, (30 - cp->crt->piety));
cp = cp->next_tag;
}
if(!total)
return(NULL);
pick = mrand(1, total);
cp = rom_ptr->first_ply;
total = 0;
while(cp) {
if(F_ISSET(cp->crt, PHIDDN) ||
(F_ISSET(cp->crt, PINVIS) && !invis) ||
F_ISSET(cp->crt, PDMINV) ||
((alg == 1) && (cp->crt->alignment > -100)) ||
((alg == -1) && (cp->crt->alignment < 100))) {
cp = cp->next_tag;
continue;
}
total += MAX(1, (30 - cp->crt->piety));
if(total >= pick) {
ply_ptr = cp->crt;
break;
}
cp = cp->next_tag;
}
return(ply_ptr);
}
/****************************************************************/
/* luck */
/****************************************************************/
/* This sets the luck value for a given player */
int luck(ply_ptr)
creature *ply_ptr;
{
int num, alg, con, smrt;
if(!ply_ptr)
return(0);
if(ply_ptr->type != PLAYER)
return(0);
alg = abs(ply_ptr->alignment);
alg = alg+1;
#ifdef WIN32
alg = (int)(alg/10);
#else
alg = rint(alg/10);
#endif
if(!alg || (ply_ptr->class == PALADIN && ply_ptr->alignment > 0))
alg = 1;
con = ply_ptr->constitution;
smrt = ply_ptr->intelligence;
num = 100*(smrt+con);
num /= alg;
if(ply_ptr->ready[HELD-1] && F_ISSET(ply_ptr->ready[HELD-1], OLUCKY))
num += ply_ptr->ready[HELD-1]->ndice;
if(num>99)
num=99;
if(num<1)
num=1;
Ply[ply_ptr->fd].extr->luck = num;
return(num);
}