/* * PLAYER.C: * * Player routines. * * Copyright (C) 1991, 1992, 1993 Brett J. Vickers * */ #include "mstruct.h" #include "mextern.h" /**********************************************************************/ /* 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; otag *op, *otemp; long t, tdiff; int n, wf, i; F_CLR(ply_ptr, PSPYON); F_CLR(ply_ptr, PREADI); if(ply_ptr->class == DM && strcmp(ply_ptr->name, DMNAME) && strcmp(ply_ptr->name, DMNAME2) && strcmp(ply_ptr->name, DMNAME3) && strcmp(ply_ptr->name, DMNAME4) && strcmp(ply_ptr->name, DMNAME5) && strcmp(ply_ptr->name, DMNAME6) && strcmp(ply_ptr->name, DMNAME7)) ply_ptr->class = CARETAKER; if(!strcmp(ply_ptr->name, DMNAME) || !strcmp(ply_ptr->name, DMNAME2) || !strcmp(ply_ptr->name, DMNAME3) || !strcmp(ply_ptr->name, DMNAME4) || !strcmp(ply_ptr->name, DMNAME5) || !strcmp(ply_ptr->name, DMNAME6) || !strcmp(ply_ptr->name, DMNAME7)) 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(3, 3 + (ply_ptr->level-5)/4); ply_ptr->daily[DL_DEFEC].max = 1; } F_SET(ply_ptr, PNOSUM); if(ply_ptr->class < CARETAKER) F_SET(ply_ptr, PPROMP); if(!F_ISSET(ply_ptr, PDMINV)) broadcast("### %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; logf("%s: %s (%s) logged on.\n", str, ply_ptr->name, Ply[ply_ptr->fd].io->address); ply_ptr->lasttime[LT_PSAVE].ltime = t; ply_ptr->lasttime[LT_PSAVE].interval = SAVEINTERVAL; if(load_rom(ply_ptr->rom_num, &rom_ptr) < 0) 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); } op = ply_ptr->first_obj; while(op) { otemp = op->next_tag; obj_ptr = op->obj; if(F_ISSET(obj_ptr, OWEARS)) { wf = obj_ptr->wearflag; if(wf == FINGER) { for(i=FINGER1-1; i<=FINGER8-1; i++) if(!ply_ptr->ready[i]) { ply_ptr->ready[i] = obj_ptr; del_obj_crt(obj_ptr, ply_ptr); break; } } else if(wf == NECK) { for(i=NECK1-1; i<=NECK2-1; i++) if(!ply_ptr->ready[i]) { ply_ptr->ready[i] = obj_ptr; del_obj_crt(obj_ptr, ply_ptr); break; } } else { if(!ply_ptr->ready[wf-1]) { ply_ptr->ready[wf-1] = obj_ptr; del_obj_crt(obj_ptr, ply_ptr); } } } op = otemp; } compute_ac(ply_ptr); compute_thaco(ply_ptr); update_ply(ply_ptr); sprintf(file, "%s/dialin", DOCPATH); if (!strcmp(Ply[ply_ptr->fd].io->address, "128.200.142.2")) view_file(ply_ptr->fd, 1, file); 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; if(ply_ptr->parent_rom) del_ply_rom(ply_ptr, ply_ptr->parent_rom); cp = ply_ptr->first_fol; while(cp) { cp->crt->following = 0; 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(!F_ISSET(ply_ptr, PDMINV)) 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("### %s just logged off.", 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; int item; char ill, prot = 1; /*character is prot in a pharm room */ t = time(0); ply_ptr->lasttime[LT_HOURS].interval += (t - ply_ptr->lasttime[LT_HOURS].ltime); ply_ptr->lasttime[LT_HOURS].ltime = t; 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)) { 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, "You 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)) 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 ? 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)){ 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); } 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,4)-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,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, 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,3); else if (!ill) { ply_ptr->mpcur += MAX(1, 2+(ply_ptr->intelligence > 17 ? 1:0)+ (ply_ptr->class == MAGE ? 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 -= 8 - 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; } } } /**********************************************************************/ /* 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; } } /**********************************************************************/ /* 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(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 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 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 CLERIC: 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 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; } 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: 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: 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 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, pick; cp = rom_ptr->first_ply; totalpiety = 0; 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)) 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; 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); }