📄 monster.c
字号:
/* * monster.c Larn is copyrighted 1986 by Noah Morgan. * * This file contains the following functions: * ---------------------------------------------------------------------------- * * createmonster(monstno) Function to create a monster next to the player * int monstno; * * int cgood(x,y,itm,monst) Function to check location for emptiness * int x,y,itm,monst; * * createitem(it,arg) Routine to place an item next to the player * int it,arg; * * cast() Subroutine called by parse to cast a spell for the user * * speldamage(x) Function to perform spell functions cast by the player * int x; * * loseint() Routine to decrement your int (intelligence) if > 3 * * isconfuse() Routine to check to see if player is confused * * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster * int x,monst; * * fullhit(xx) Function to return full damage against a monst (aka web) * int xx; * * direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir * int spnum,dam,arg; * char *str; * * godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks * int spnum,dam,delay; * char *str,cshow; * * ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt * int x,y; * * tdirect(spnum) Routine to teleport away a monster * int spnum; * * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player * int sp,dam; * char *str; * * dirsub(x,y) Routine to ask for direction, then modify x,y for it * int *x,*y; * * vxy(x,y) Routine to verify/fix (*x,*y) for being within bounds * int *x,*y; * * dirpoly(spnum) Routine to ask for a direction and polymorph a monst * int spnum; * * hitmonster(x,y) Function to hit a monster at the designated coordinates * int x,y; * * hitm(x,y,amt) Function to just hit a monster at a given coordinates * int x,y,amt; * * hitplayer(x,y) Function for the monster to hit the player from (x,y) * int x,y; * * dropsomething(monst) Function to create an object when a monster dies * int monst; * * dropgold(amount) Function to drop some gold around player * int amount; * * something(level) Function to create a random item around player * int level; * * newobject(lev,i) Routine to return a randomly selected new object * int lev,*i; * * spattack(atckno,xx,yy) Function to process special attacks from monsters * int atckno,xx,yy; * * checkloss(x) Routine to subtract hp from user and flag bottomline display * int x; * * annihilate() Routine to annihilate monsters around player, playerx,playery * * newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation * int x,y,dir,lifetime; * * rmsphere(x,y) Function to delete a sphere of annihilation from list * int x,y; * * sphboom(x,y) Function to perform the effects of a sphere detonation * int x,y; * * genmonst() Function to ask for monster and genocide from game * */#include "header.h"struct isave /* used for altar reality */ { char type; /* 0=item, 1=monster */ char id; /* item number or monster number */ short arg; /* the type of item or hitpoints of monster */ };/* * createmonster(monstno) Function to create a monster next to the player * int monstno; * * Enter with the monster number (1 to MAXMONST+8) * Returns no value. */createmonster(mon) int mon; { register int x,y,k,i; if (mon<1 || mon>MAXMONST+8) /* check for monster number out of bounds */ { beep(); lprintf("\ncan't createmonst(%d)\n",(long)mon); nap(3000); return; } while (monster[mon].genocided && mon<MAXMONST) mon++; /* genocided? */ for (k=rnd(8), i= -8; i<0; i++,k++) /* choose direction, then try all */ { if (k>8) k=1; /* wraparound the diroff arrays */ x = playerx + diroffx[k]; y = playery + diroffy[k]; if (cgood(x,y,0,1)) /* if we can create here */ { mitem[x][y] = mon; hitp[x][y] = monster[mon].hitpoints; stealth[x][y]=know[x][y]=0; switch(mon) { case ROTHE: case POLTERGEIST: case VAMPIRE: stealth[x][y]=1; }; return; } } }/* * int cgood(x,y,itm,monst) Function to check location for emptiness * int x,y,itm,monst; * * Routine to return TRUE if a location does not have itm or monst there * returns FALSE (0) otherwise * Enter with itm or monst TRUE or FALSE if checking it * Example: if itm==TRUE check for no item at this location * if monst==TRUE check for no monster at this location * This routine will return FALSE if at a wall or the dungeon exit on level 1 */int cgood(x,y,itm,monst) register int x,y; int itm,monst; { if ((y>=0) && (y<=MAXY-1) && (x>=0) && (x<=MAXX-1)) /* within bounds? */ if (item[x][y]!=OWALL) /* can't make anything on walls */ if (itm==0 || (item[x][y]==0)) /* is it free of items? */ if (monst==0 || (mitem[x][y]==0)) /* is it free of monsters? */ if ((level!=1) || (x!=33) || (y!=MAXY-1)) /* not exit to level 1 */ return(1); return(0); }/* * createitem(it,arg) Routine to place an item next to the player * int it,arg; * * Enter with the item number and its argument (iven[], ivenarg[]) * Returns no value, thus we don't know about createitem() failures. */createitem(it,arg) int it,arg; { register int x,y,k,i; if (it >= MAXOBJ) return; /* no such object */ for (k=rnd(8), i= -8; i<0; i++,k++) /* choose direction, then try all */ { if (k>8) k=1; /* wraparound the diroff arrays */ x = playerx + diroffx[k]; y = playery + diroffy[k]; if (cgood(x,y,1,0)) /* if we can create here */ { item[x][y] = it; know[x][y]=0; iarg[x][y]=arg; return; } } }/* * cast() Subroutine called by parse to cast a spell for the user * * No arguments and no return value. */static char eys[] = "\nEnter your spell: ";cast() { register int i,j,a,b,d; cursors(); if (c[SPELLS]<=0) { lprcat("\nYou don't have any spells!"); return; } lprcat(eys); --c[SPELLS]; while ((a=getchar())=='D') { seemagic(-1); cursors(); lprcat(eys); } if (a=='\33') goto over; /* to escape casting a spell */ if ((b=getchar())=='\33') goto over; /* to escape casting a spell */ if ((d=getchar())=='\33') { over: lprcat(aborted); c[SPELLS]++; return; } /* to escape casting a spell */#ifdef EXTRA c[SPELLSCAST]++;#endif for (lprc('\n'),j= -1,i=0; i<SPNUM; i++) /*seq search for his spell, hash?*/ if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d)) if (spelknow[i]) { speldamage(i); j = 1; i=SPNUM; } if (j == -1) lprcat(" Nothing Happened "); bottomline(); }static int dirsub();/* * speldamage(x) Function to perform spell functions cast by the player * int x; * * Enter with the spell number, returns no value. * Please insure that there are 2 spaces before all messages here */speldamage(x) int x; { register int i,j,clev; int xl,xh,yl,yh; register char *p,*kn,*pm; if (x>=SPNUM) return; /* no such spell */ if (c[TIMESTOP]) { lprcat(" It didn't seem to work"); return; } /* not if time stopped */ clev = c[LEVEL]; if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE])) { lprcat(" It didn't work!"); return; } if (clev*3+2 < x) { lprcat(" Nothing happens. You seem inexperienced at this"); return; } switch(x) {/* ----- LEVEL 1 SPELLS ----- */ case 0: if (c[PROTECTIONTIME]==0) c[MOREDEFENSES]+=2; /* protection field +2 */ c[PROTECTIONTIME] += 250; return; case 1: i = rnd(((clev+1)<<1)) + clev + 3; godirect(x,i,(clev>=2)?" Your missiles hit the %s":" Your missile hit the %s",100,'+'); /* magic missile */ return; case 2: if (c[DEXCOUNT]==0) c[DEXTERITY]+=3; /* dexterity */ c[DEXCOUNT] += 400; return; case 3: i=rnd(3)+1; p=" While the %s slept, you smashed it %d times"; ws: direct(x,fullhit(i),p,i); /* sleep */ return; case 4: /* charm monster */ c[CHARMCOUNT] += c[CHARISMA]<<1; return; case 5: godirect(x,rnd(10)+15+clev," The sound damages the %s",70,'@'); /* sonic spear */ return;/* ----- LEVEL 2 SPELLS ----- */ case 6: i=rnd(3)+2; p=" While the %s is entangled, you hit %d times"; goto ws; /* web */ case 7: if (c[STRCOUNT]==0) c[STREXTRA]+=3; /* strength */ c[STRCOUNT] += 150+rnd(100); return; case 8: yl = playery-5; /* enlightenment */ yh = playery+6; xl = playerx-15; xh = playerx+16; vxy(&xl,&yl); vxy(&xh,&yh); /* check bounds */ for (i=yl; i<=yh; i++) /* enlightenment */ for (j=xl; j<=xh; j++) know[j][i]=1; draws(xl,xh+1,yl,yh+1); return; case 9: raisehp(20+(clev<<1)); return; /* healing */ case 10: c[BLINDCOUNT]=0; return; /* cure blindness */ case 11: createmonster(makemonst(level+1)+8); return; case 12: if (rnd(11)+7 <= c[WISDOM]) direct(x,rnd(20)+20+clev," The %s believed!",0); else lprcat(" It didn't believe the illusions!"); return; case 13: /* if he has the amulet of invisibility then add more time */ for (j=i=0; i<26; i++) if (iven[i]==OAMULET) j+= 1+ivenarg[i]; c[INVISIBILITY] += (j<<7)+12; return;/* ----- LEVEL 3 SPELLS ----- */ case 14: godirect(x,rnd(25+clev)+25+clev," The fireball hits the %s",40,'*'); return; /* fireball */ case 15: godirect(x,rnd(25)+20+clev," Your cone of cold strikes the %s",60,'O'); /* cold */ return; case 16: dirpoly(x); return; /* polymorph */ case 17: c[CANCELLATION]+= 5+clev; return; /* cancellation */ case 18: c[HASTESELF]+= 7+clev; return; /* haste self */ case 19: omnidirect(x,30+rnd(10)," The %s gasps for air"); /* cloud kill */ return; case 20: xh = min(playerx+1,MAXX-2); yh = min(playery+1,MAXY-2); for (i=max(playerx-1,1); i<=xh; i++) /* vaporize rock */ for (j=max(playery-1,1); j<=yh; j++) { kn = &know[i][j]; pm = &mitem[i][j]; switch(*(p= &item[i][j])) { case OWALL: if (level < MAXLEVEL+MAXVLEVEL-1) *p = *kn = 0; break; case OSTATUE: if (c[HARDGAME]<3) { *p=OBOOK; iarg[i][j]=level; *kn=0; } break; case OTHRONE: *pm=GNOMEKING; *kn=0; *p= OTHRONE2; hitp[i][j]=monster[GNOMEKING].hitpoints; break; case OALTAR: *pm=DEMONPRINCE; *kn=0; hitp[i][j]=monster[DEMONPRINCE].hitpoints; break; }; switch(*pm) { case XORN: ifblind(i,j); hitm(i,j,200); break; /* Xorn takes damage from vpr */ } } return;/* ----- LEVEL 4 SPELLS ----- */ case 21: direct(x,100+clev," The %s shrivels up",0); /* dehydration */ return; case 22: godirect(x,rnd(25)+20+(clev<<1)," A lightning bolt hits the %s",1,'~'); /* lightning */ return; case 23: i=min(c[HP]-1,c[HPMAX]/2); /* drain life */ direct(x,i+i,"",0); c[HP] -= i; return; case 24: if (c[GLOBE]==0) c[MOREDEFENSES] += 10; c[GLOBE] += 200; loseint(); /* globe of invulnerability */ return; case 25: omnidirect(x,32+clev," The %s struggles for air in your flood!"); /* flood */ return; case 26: if (rnd(151)==63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000); died(270); return; } if (c[WISDOM]>rnd(10)+10) direct(x,2000," The %s's heart stopped",0); /* finger of death */ else lprcat(" It didn't work"); return;/* ----- LEVEL 5 SPELLS ----- */ case 27: c[SCAREMONST] += rnd(10)+clev; return; /* scare monster */ case 28: c[HOLDMONST] += rnd(10)+clev; return; /* hold monster */ case 29: c[TIMESTOP] += rnd(20)+(clev<<1); return; /* time stop */ case 30: tdirect(x); return; /* teleport away */ case 31: omnidirect(x,35+rnd(10)+clev," The %s cringes from the flame"); /* magic fire */ return;/* ----- LEVEL 6 SPELLS ----- */ case 32: if ((rnd(23)==5) && (wizard==0)) /* sphere of annihilation */ { beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n"); nap(4000); died(258); return; } xl=playerx; yl=playery; loseint(); i=dirsub(&xl,&yl); /* get direction of sphere */ newsphere(xl,yl,i,rnd(20)+11); /* make a sphere */ return; case 33: genmonst(); spelknow[33]=0; /* genocide */ loseint(); return; case 34: /* summon demon */ if (rnd(100) > 30) { direct(x,150," The demon strikes at the %s",0); return; } if (rnd(100) > 15) { lprcat(" Nothing seems to have happened"); return; } lprcat(" The demon turned on you and vanished!"); beep(); i=rnd(40)+30; lastnum=277; losehp(i); /* must say killed by a demon */ return; case 35: /* walk through walls */ c[WTW] += rnd(10)+5; return; case 36: /* alter reality */ { struct isave *save; /* pointer to item save structure */ int sc; sc=0; /* # items saved */ save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2); for (j=0; j<MAXY; j++) for (i=0; i<MAXX; i++) /* save all items and monsters */ { xl = item[i][j]; if (xl && xl!=OWALL && xl!=OANNIHILATION) { save[sc].type=0; save[sc].id=item[i][j]; save[sc++].arg=iarg[i][j]; } if (mitem[i][j]) { save[sc].type=1; save[sc].id=mitem[i][j]; save[sc++].arg=hitp[i][j]; } item[i][j]=OWALL; mitem[i][j]=0; if (wizard) know[i][j]=1; else know[i][j]=0; } eat(1,1); if (level==1) item[33][MAXY-1]=0; for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0; while (sc>0) /* put objects back in level */ { --sc; if (save[sc].type == 0) { int trys; for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1)); if (trys) { item[i][j]=save[sc].id; iarg[i][j]=save[sc].arg; } } else { /* put monsters back in */ int trys; for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1)); if (trys) { mitem[i][j]=save[sc].id; hitp[i][j]=save[sc].arg; } } } loseint(); draws(0,MAXX,0,MAXY); if (wizard==0) spelknow[36]=0; free((char*)save); positionplayer(); return; } case 37: /* permanence */ adjtime(-99999L); spelknow[37]=0; /* forget */ loseint(); return; default: lprintf(" spell %d not available!",(long)x); beep(); return; }; }/* * loseint() Routine to subtract 1 from your int (intelligence) if > 3 * * No arguments and no return value */loseint() { if (--c[INTELLIGENCE]<3) c[INTELLIGENCE]=3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -