📄 monster.c
字号:
}/* * isconfuse() Routine to check to see if player is confused * * This routine prints out a message saying "You can't aim your magic!" * returns 0 if not confused, non-zero (time remaining confused) if confused */isconfuse() { if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); } return(c[CONFUSE]); }/* * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster * int x,monst; * * Subroutine to return 1 if the spell can't affect the monster * otherwise returns 0 * Enter with the spell number in x, and the monster number in monst. */nospell(x,monst) int x,monst; { register int tmp; if (x>=SPNUM || monst>=MAXMONST+8 || monst<0 || x<0) return(0); /* bad spell or monst */ if ((tmp=spelweird[monst-1][x])==0) return(0); cursors(); lprc('\n'); lprintf(spelmes[tmp],monster[monst].name); return(1); }/* * fullhit(xx) Function to return full damage against a monster (aka web) * int xx; * * Function to return hp damage to monster due to a number of full hits * Enter with the number of full hits being done */fullhit(xx) int xx; { register int i; if (xx<0 || xx>20) return(0); /* fullhits are out of range */ if (c[LANCEDEATH]) return(10000); /* lance of death */ i = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]); return( (i>=1) ? i : xx ); }/* * direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir * int spnum,dam,arg; * char *str; * * Routine to ask for a direction to a spell and then hit the monster * Enter with the spell number in spnum, the damage to be done in dam, * lprintf format string in str, and lprintf's argument in arg. * Returns no value. */direct(spnum,dam,str,arg) int spnum,dam,arg; char *str; { int x,y; register int m; if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */ if (isconfuse()) return; dirsub(&x,&y); m = mitem[x][y]; if (item[x][y]==OMIRROR) { if (spnum==3) /* sleep */ { lprcat("You fall asleep! "); beep(); fool: arg += 2; while (arg-- > 0) { parse2(); nap(1000); } return; } else if (spnum==6) /* web */ { lprcat("You get stuck in your own web! "); beep(); goto fool; } else { lastnum=278; lprintf(str,"spell caster (thats you)",(long)arg); beep(); losehp(dam); return; } } if (m==0) { lprcat(" There wasn't anything there!"); return; } ifblind(x,y); if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; } lprintf(str,lastmonst,(long)arg); hitm(x,y,dam); }/* * godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks * int spnum,dam,delay; * char *str,cshow; * * Function to hit in a direction from a missile weapon and have it keep * on going in that direction until its power is exhausted * Enter with the spell number in spnum, the power of the weapon in hp, * lprintf format string in str, the # of milliseconds to delay between * locations in delay, and the character to represent the weapon in cshow. * Returns no value. */godirect(spnum,dam,str,delay,cshow) int spnum,dam,delay; char *str,cshow; { register char *p; register int x,y,m; int dx,dy; if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */ if (isconfuse()) return; dirsub(&dx,&dy); x=dx; y=dy; dx = x-playerx; dy = y-playery; x = playerx; y = playery; while (dam>0) { x += dx; y += dy; if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0)) { dam=0; break; /* out of bounds */ } if ((x==playerx) && (y==playery)) /* if energy hits player */ { cursors(); lprcat("\nYou are hit my your own magic!"); beep(); lastnum=278; losehp(dam); return; } if (c[BLINDCOUNT]==0) /* if not blind show effect */ { cursor(x+1,y+1); lprc(cshow); nap(delay); show1cell(x,y); } if ((m=mitem[x][y])) /* is there a monster there? */ { ifblind(x,y); if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; } cursors(); lprc('\n'); lprintf(str,lastmonst); dam -= hitm(x,y,dam); show1cell(x,y); nap(1000); x -= dx; y -= dy; } else switch (*(p= &item[x][y])) { case OWALL: cursors(); lprc('\n'); lprintf(str,"wall"); if (dam>=50+c[HARDGAME]) /* enough damage? */ if (level<MAXLEVEL+MAXVLEVEL-1) /* not on V3 */ if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y)) { lprcat(" The wall crumbles"); god3: *p=0; god: know[x][y]=0; show1cell(x,y); } god2: dam = 0; break; case OCLOSEDDOOR: cursors(); lprc('\n'); lprintf(str,"door"); if (dam>=40) { lprcat(" The door is blasted apart"); goto god3; } goto god2; case OSTATUE: cursors(); lprc('\n'); lprintf(str,"statue"); if (c[HARDGAME]<3) if (dam>44) { lprcat(" The statue crumbles"); *p=OBOOK; iarg[x][y]=level; goto god; } goto god2; case OTHRONE: cursors(); lprc('\n'); lprintf(str,"throne"); if (dam>39) { mitem[x][y]=GNOMEKING; hitp[x][y]=monster[GNOMEKING].hitpoints; *p = OTHRONE2; goto god; } goto god2; case OMIRROR: dx *= -1; dy *= -1; break; }; dam -= 3 + (c[HARDGAME]>>1); } }/* * ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt * int x,y; * * Subroutine to copy the word "monster" into lastmonst if the player is blind * Enter with the coordinates (x,y) of the monster * Returns no value. */ifblind(x,y) int x,y; { char *p; vxy(&x,&y); /* verify correct x,y coordinates */ if (c[BLINDCOUNT]) { lastnum=279; p="monster"; } else { lastnum=mitem[x][y]; p=monster[lastnum].name; } strcpy(lastmonst,p); }/* * tdirect(spnum) Routine to teleport away a monster * int spnum; * * Routine to ask for a direction to a spell and then teleport away monster * Enter with the spell number that wants to teleport away * Returns no value. */tdirect(spnum) int spnum; { int x,y; register int m; if (spnum<0 || spnum>=SPNUM) return; /* bad args */ if (isconfuse()) return; dirsub(&x,&y); if ((m=mitem[x][y])==0) { lprcat(" There wasn't anything there!"); return; } ifblind(x,y); if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; } fillmonst(m); mitem[x][y]=know[x][y]=0; }/* * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player * int sp,dam; * char *str; * * Routine to cast a spell and then hit the monster in all directions * Enter with the spell number in sp, the damage done to wach square in dam, * and the lprintf string to identify the spell in str. * Returns no value. */omnidirect(spnum,dam,str) int spnum,dam; char *str; { register int x,y,m; if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */ for (x=playerx-1; x<playerx+2; x++) for (y=playery-1; y<playery+2; y++) { if (m=mitem[x][y]) if (nospell(spnum,m) == 0) { ifblind(x,y); cursors(); lprc('\n'); lprintf(str,lastmonst); hitm(x,y,dam); nap(800); } else { lasthx=x; lasthy=y; } } }/* * static dirsub(x,y) Routine to ask for direction, then modify x,y for it * int *x,*y; * * Function to ask for a direction and modify an x,y for that direction * Enter with the origination coordinates in (x,y). * Returns index into diroffx[] (0-8). */static intdirsub(x,y) int *x,*y; { register int i; lprcat("\nIn What Direction? "); for (i=0; ; ) switch(getchar()) { case 'b': i++; case 'n': i++; case 'y': i++; case 'u': i++; case 'h': i++; case 'k': i++; case 'l': i++; case 'j': i++; goto out; };out: *x = playerx+diroffx[i]; *y = playery+diroffy[i]; vxy(x,y); return(i); }/* * vxy(x,y) Routine to verify/fix coordinates for being within bounds * int *x,*y; * * Function to verify x & y are within the bounds for a level * If *x or *y is not within the absolute bounds for a level, fix them so that * they are on the level. * Returns TRUE if it was out of bounds, and the *x & *y in the calling * routine are affected. */vxy(x,y) int *x,*y; { int flag=0; if (*x<0) { *x=0; flag++; } if (*y<0) { *y=0; flag++; } if (*x>=MAXX) { *x=MAXX-1; flag++; } if (*y>=MAXY) { *y=MAXY-1; flag++; } return(flag); }/* * dirpoly(spnum) Routine to ask for a direction and polymorph a monst * int spnum; * * Subroutine to polymorph a monster and ask for the direction its in * Enter with the spell number in spmun. * Returns no value. */dirpoly(spnum) int spnum; { int x,y,m; if (spnum<0 || spnum>=SPNUM) return; /* bad args */ if (isconfuse()) return; /* if he is confused, he can't aim his magic */ dirsub(&x,&y); if (mitem[x][y]==0) { lprcat(" There wasn't anything there!"); return; } ifblind(x,y); if (nospell(spnum,mitem[x][y])) { lasthx=x; lasthy=y; return; } while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided ); hitp[x][y] = monster[m].hitpoints; show1cell(x,y); /* show the new monster */ }/* * hitmonster(x,y) Function to hit a monster at the designated coordinates * int x,y; * * This routine is used for a bash & slash type attack on a monster * Enter with the coordinates of the monster in (x,y). * Returns no value. */hitmonster(x,y) int x,y; { register int tmp,monst,damag,flag; if (c[TIMESTOP]) return; /* not if time stopped */ vxy(&x,&y); /* verify coordinates are within range */ if ((monst = mitem[x][y]) == 0) return; hit3flag=1; ifblind(x,y); tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS]/4 - 12; cursors(); if ((rnd(20) < tmp-c[HARDGAME]) || (rnd(71) < 5)) /* need at least random chance to hit */ { lprcat("\nYou hit"); flag=1; damag = fullhit(1); if (damag<9999) damag=rnd(damag)+1; } else { lprcat("\nYou missed"); flag=0; } lprcat(" the "); lprcat(lastmonst); if (flag) /* if the monster was hit */ if ((monst==RUSTMONSTER) || (monst==DISENCHANTRESS) || (monst==CUBE)) if (c[WIELD]>0) if (ivenarg[c[WIELD]] > -10) { lprintf("\nYour weapon is dulled by the %s",lastmonst); beep(); --ivenarg[c[WIELD]]; } if (flag) hitm(x,y,damag); if (monst == VAMPIRE) if (hitp[x][y]<25) { mitem[x][y]=BAT; know[x][y]=0; } }/* * hitm(x,y,amt) Function to just hit a monster at a given coordinates * int x,y,amt; * * Returns the number of hitpoints the monster absorbed * This routine is used to specifically damage a monster at a location (x,y) * Called by hitmonster(x,y) */hitm(x,y,amt) int x,y; register amt; { register int monst; int hpoints,amt2; vxy(&x,&y); /* verify coordinates are within range */ amt2 = amt; /* save initial damage so we can return it */ monst = mitem[x][y]; if (c[HALFDAM]) amt >>= 1; /* if half damage curse adjust damage points */ if (amt<=0) amt2 = amt = 1; lasthx=x; lasthy=y; stealth[x][y]=1; /* make sure hitting monst breaks stealth condition */ c[HOLDMONST]=0; /* hit a monster breaks hold monster spell */ switch(monst) /* if a dragon and orb(s) of dragon slaying */ { case WHITEDRAGON: case REDDRAGON: case GREENDRAGON: case BRONZEDRAGON: case PLATINUMDRAGON: case SILVERDRAGON: amt *= 1+(c[SLAYING]<<1); break; }/* invincible monster fix is here */ if (hitp[x][y] > monster[monst].hitpoints) hitp[x][y] = monster[monst].hitpoints; if ((hpoints = hitp[x][y]) <= amt) {#ifdef EXTRA c[MONSTKILLED]++;#endif lprintf("\nThe %s died!",lastmonst); raiseexperience((long)monster[monst].experience); amt = monster[monst].gold; if (amt>0) dropgold(rnd(amt)+amt); dropsomething(monst); disappear(x,y); bottomline(); return(hpoints); } hitp[x][y] = hpoints-amt; return(amt2); }/* * hitplayer(x,y) Function for the monster to hit the player from (x,y) * int x,y; * * Function for the monster to hit the player with monster at location x,y * Returns nothing of value. */hitplayer(x,y) int x,y; { register int dam,tmp,mster,bias; vxy(&x,&y); /* verify coordinates are within range */ lastnum = mster = mitem[x][y];/* spirit naga's and poltergeist's do nothing if scarab of negate spirit */ if (c[NEGATESPIRIT] || c[SPIRITPRO]) if ((mster ==POLTERGEIST) || (mster ==SPIRITNAGA)) return;/* if undead and cube of undead control */ if (c[CUBEofUNDEAD] || c[UNDEADPRO]) if ((mster ==VAMPIRE) || (mster ==WRAITH) || (mster ==ZOMBIE)) return; if ((know[x][y]&1) == 0) { know[x][y]=1; show1cell(x,y); } bias = (c[HARDGAME]) + 1; hitflag = hit2flag = hit3flag = 1; yrepcount=0; cursors(); ifblind(x,y); if (c[INVISIBILITY]) if (rnd(33)<20) { lprintf("\nThe %s misses wildly",lastmonst); return; } if (c[CHARMCOUNT]) if (rnd(30)+5*monster[mster].level-c[CHARISMA]<30) { lprintf("\nThe %s is awestruck at your magnificence!",lastmonst); return; } if (mster==BAT) dam=1; else { dam = monster[mster].damage; dam += rnd((int)((dam<1)?1:dam)) + monster[mster].level;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -