|
|
1.1 ! root 1: /* ! 2: * movem.c (move monster) Larn is copyrighted 1986 by Noah Morgan. ! 3: * ! 4: * Here are the functions in this file: ! 5: * ! 6: * movemonst() Routine to move the monsters toward the player ! 7: * movemt(x,y) Function to move a monster at (x,y) -- must determine where ! 8: * mmove(x,y,xd,yd) Function to actually perform the monster movement ! 9: * movsphere() Function to look for and move spheres of annihilation ! 10: */ ! 11: #include "header.h" ! 12: ! 13: /* ! 14: * movemonst() Routine to move the monsters toward the player ! 15: * ! 16: * This routine has the responsibility to determine which monsters are to ! 17: * move, and call movemt() to do the move. ! 18: * Returns no value. ! 19: */ ! 20: static short w1[9],w1x[9],w1y[9]; ! 21: static int tmp1,tmp2,tmp3,tmp4,distance; ! 22: movemonst() ! 23: { ! 24: register int i,j; ! 25: if (c[TIMESTOP]) return; /* no action if time is stopped */ ! 26: if (c[HASTESELF]) if ((c[HASTESELF]&1)==0) return; ! 27: if (spheres) movsphere(); /* move the spheres of annihilation if any */ ! 28: if (c[HOLDMONST]) return; /* no action if monsters are held */ ! 29: ! 30: if (c[AGGRAVATE]) /* determine window of monsters to move */ ! 31: { ! 32: tmp1=playery-5; tmp2=playery+6; tmp3=playerx-10; tmp4=playerx+11; ! 33: distance=40; /* depth of intelligent monster movement */ ! 34: } ! 35: else ! 36: { ! 37: tmp1=playery-3; tmp2=playery+4; tmp3=playerx-5; tmp4=playerx+6; ! 38: distance=17; /* depth of intelligent monster movement */ ! 39: } ! 40: ! 41: if (level == 0) /* if on outside level monsters can move in perimeter */ ! 42: { ! 43: if (tmp1 < 0) tmp1=0; if (tmp2 > MAXY) tmp2=MAXY; ! 44: if (tmp3 < 0) tmp3=0; if (tmp4 > MAXX) tmp4=MAXX; ! 45: } ! 46: else /* if in a dungeon monsters can't be on the perimeter (wall there) */ ! 47: { ! 48: if (tmp1 < 1) tmp1=1; if (tmp2 > MAXY-1) tmp2=MAXY-1; ! 49: if (tmp3 < 1) tmp3=1; if (tmp4 > MAXX-1) tmp4=MAXX-1; ! 50: } ! 51: ! 52: for (j=tmp1; j<tmp2; j++) /* now reset monster moved flags */ ! 53: for (i=tmp3; i<tmp4; i++) ! 54: moved[i][j] = 0; ! 55: moved[lasthx][lasthy]=0; ! 56: ! 57: if (c[AGGRAVATE] || !c[STEALTH]) /* who gets moved? split for efficiency */ ! 58: { ! 59: for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */ ! 60: for (i=tmp3; i<tmp4; i++) ! 61: if (mitem[i][j]) /* if there is a monster to move */ ! 62: if (moved[i][j]==0) /* if it has not already been moved */ ! 63: movemt(i,j); /* go and move the monster */ ! 64: } ! 65: else /* not aggravated and not stealth */ ! 66: { ! 67: for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */ ! 68: for (i=tmp3; i<tmp4; i++) ! 69: if (mitem[i][j]) /* if there is a monster to move */ ! 70: if (moved[i][j]==0) /* if it has not already been moved */ ! 71: if (stealth[i][j]) /* if it is asleep due to stealth */ ! 72: movemt(i,j); /* go and move the monster */ ! 73: } ! 74: ! 75: if (mitem[lasthx][lasthy]) /* now move monster last hit by player if not already moved */ ! 76: { ! 77: if (moved[lasthx][lasthy]==0) /* if it has not already been moved */ ! 78: { ! 79: movemt(lasthx,lasthy); ! 80: lasthx = w1x[0]; lasthy = w1y[0]; ! 81: } ! 82: } ! 83: } ! 84: ! 85: /* ! 86: * movemt(x,y) Function to move a monster at (x,y) -- must determine where ! 87: * int x,y; ! 88: * ! 89: * This routine is responsible for determining where one monster at (x,y) will ! 90: * move to. Enter with the monsters coordinates in (x,y). ! 91: * Returns no value. ! 92: */ ! 93: static int tmpitem,xl,xh,yl,yh; ! 94: movemt(i,j) ! 95: int i,j; ! 96: { ! 97: register int k,m,z,tmp,xtmp,ytmp,monst; ! 98: switch(monst=mitem[i][j]) /* for half speed monsters */ ! 99: { ! 100: case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART: ! 101: case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return; ! 102: }; ! 103: ! 104: if (c[SCAREMONST]) /* choose destination randomly if scared */ ! 105: { ! 106: if ((xl = i+rnd(3)-2) < 0) xl=0; if (xl >= MAXX) xl=MAXX-1; ! 107: if ((yl = j+rnd(3)-2) < 0) yl=0; if (yl >= MAXY) yl=MAXY-1; ! 108: if ((tmp=item[xl][yl]) != OWALL) ! 109: if (mitem[xl][yl] == 0) ! 110: if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR)) ! 111: if (tmp != OCLOSEDDOOR) mmove(i,j,xl,yl); ! 112: return; ! 113: } ! 114: ! 115: if (monster[monst].intelligence > 10-c[HARDGAME]) /* if smart monster */ ! 116: /* intelligent movement here -- first setup screen array */ ! 117: { ! 118: xl=tmp3-2; yl=tmp1-2; xh=tmp4+2; yh=tmp2+2; ! 119: vxy(&xl,&yl); vxy(&xh,&yh); ! 120: for (k=yl; k<yh; k++) ! 121: for (m=xl; m<xh; m++) ! 122: { ! 123: switch(item[m][k]) ! 124: { ! 125: case OWALL: case OPIT: case OTRAPARROW: case ODARTRAP: ! 126: case OCLOSEDDOOR: case OTRAPDOOR: case OTELEPORTER: ! 127: smm: screen[m][k]=127; break; ! 128: case OMIRROR: if (mitem[m][k]==VAMPIRE) goto smm; ! 129: default: screen[m][k]= 0; break; ! 130: }; ! 131: } ! 132: screen[playerx][playery]=1; ! 133: ! 134: /* now perform proximity ripple from playerx,playery to monster */ ! 135: xl=tmp3-1; yl=tmp1-1; xh=tmp4+1; yh=tmp2+1; ! 136: vxy(&xl,&yl); vxy(&xh,&yh); ! 137: for (tmp=1; tmp<distance; tmp++) /* only up to 20 squares away */ ! 138: for (k=yl; k<yh; k++) ! 139: for (m=xl; m<xh; m++) ! 140: if (screen[m][k]==tmp) /* if find proximity n advance it */ ! 141: for (z=1; z<9; z++) /* go around in a circle */ ! 142: { ! 143: if (screen[xtmp=m+diroffx[z]][ytmp=k+diroffy[z]]==0) ! 144: screen[xtmp][ytmp]=tmp+1; ! 145: if (xtmp==i && ytmp==j) goto out; ! 146: } ! 147: ! 148: out: if (tmp<distance) /* did find connectivity */ ! 149: /* now select lowest value around playerx,playery */ ! 150: for (z=1; z<9; z++) /* go around in a circle */ ! 151: if (screen[xl=i+diroffx[z]][yl=j+diroffy[z]]==tmp) ! 152: if (!mitem[xl][yl]) { mmove(i,j,w1x[0]=xl,w1y[0]=yl); return; } ! 153: } ! 154: ! 155: /* dumb monsters move here */ ! 156: xl=i-1; yl=j-1; xh=i+2; yh=j+2; ! 157: if (i<playerx) xl++; else if (i>playerx) --xh; ! 158: if (j<playery) yl++; else if (j>playery) --yh; ! 159: for (k=0; k<9; k++) w1[k] = 10000; ! 160: ! 161: for (k=xl; k<xh; k++) ! 162: for (m=yl; m<yh; m++) /* for each square compute distance to player */ ! 163: { ! 164: tmp = k-i+4+3*(m-j); ! 165: tmpitem = item[k][m]; ! 166: if (tmpitem!=OWALL || (k==playerx && m==playery)) ! 167: if (mitem[k][m]==0) ! 168: if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR)) ! 169: if (tmpitem!=OCLOSEDDOOR) ! 170: { ! 171: w1[tmp] = (playerx-k)*(playerx-k)+(playery-m)*(playery-m); ! 172: w1x[tmp] = k; w1y[tmp] = m; ! 173: } ! 174: } ! 175: ! 176: tmp = 0; ! 177: for (k=1; k<9; k++) if (w1[tmp] > w1[k]) tmp=k; ! 178: ! 179: if (w1[tmp] < 10000) ! 180: if ((i!=w1x[tmp]) || (j!=w1y[tmp])) ! 181: mmove(i,j,w1x[tmp],w1y[tmp]); ! 182: } ! 183: ! 184: /* ! 185: * mmove(x,y,xd,yd) Function to actually perform the monster movement ! 186: * int x,y,xd,yd; ! 187: * ! 188: * Enter with the from coordinates in (x,y) and the destination coordinates ! 189: * in (xd,yd). ! 190: */ ! 191: mmove(aa,bb,cc,dd) ! 192: int aa,bb,cc,dd; ! 193: { ! 194: register int tmp,i,flag; ! 195: char *who,*p; ! 196: flag=0; /* set to 1 if monster hit by arrow trap */ ! 197: if ((cc==playerx) && (dd==playery)) ! 198: { ! 199: hitplayer(aa,bb); moved[aa][bb] = 1; return; ! 200: } ! 201: i=item[cc][dd]; ! 202: if ((i==OPIT) || (i==OTRAPDOOR)) ! 203: switch(mitem[aa][bb]) ! 204: { ! 205: case SPIRITNAGA: case PLATINUMDRAGON: case WRAITH: ! 206: case VAMPIRE: case SILVERDRAGON: case POLTERGEIST: ! 207: case DEMONLORD: case DEMONLORD+1: case DEMONLORD+2: ! 208: case DEMONLORD+3: case DEMONLORD+4: case DEMONLORD+5: ! 209: case DEMONLORD+6: case DEMONPRINCE: break; ! 210: ! 211: default: mitem[aa][bb]=0; /* fell in a pit or trapdoor */ ! 212: }; ! 213: tmp = mitem[cc][dd] = mitem[aa][bb]; ! 214: if (i==OANNIHILATION) ! 215: { ! 216: if (tmp>=DEMONLORD+3) /* demons dispel spheres */ ! 217: { ! 218: cursors(); ! 219: lprintf("\nThe %s dispels the sphere!",monster[tmp].name); ! 220: rmsphere(cc,dd); /* delete the sphere */ ! 221: } ! 222: else i=tmp=mitem[cc][dd]=0; ! 223: } ! 224: stealth[cc][dd]=1; ! 225: if ((hitp[cc][dd] = hitp[aa][bb]) < 0) hitp[cc][dd]=1; ! 226: mitem[aa][bb] = 0; moved[cc][dd] = 1; ! 227: if (tmp == LEPRECHAUN) ! 228: switch(i) ! 229: { ! 230: case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD: ! 231: case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: ! 232: item[cc][dd] = 0; /* leprechaun takes gold */ ! 233: }; ! 234: ! 235: if (tmp == TROLL) /* if a troll regenerate him */ ! 236: if ((gtime & 1) == 0) ! 237: if (monster[tmp].hitpoints > hitp[cc][dd]) hitp[cc][dd]++; ! 238: ! 239: if (i==OTRAPARROW) /* arrow hits monster */ ! 240: { who = "An arrow"; if ((hitp[cc][dd] -= rnd(10)+level) <= 0) ! 241: { mitem[cc][dd]=0; flag=2; } else flag=1; } ! 242: if (i==ODARTRAP) /* dart hits monster */ ! 243: { who = "A dart"; if ((hitp[cc][dd] -= rnd(6)) <= 0) ! 244: { mitem[cc][dd]=0; flag=2; } else flag=1; } ! 245: if (i==OTELEPORTER) /* monster hits teleport trap */ ! 246: { flag=3; fillmonst(mitem[cc][dd]); mitem[cc][dd]=0; } ! 247: if (c[BLINDCOUNT]) return; /* if blind don't show where monsters are */ ! 248: if (know[cc][dd] & 1) ! 249: { ! 250: p=0; ! 251: if (flag) cursors(); ! 252: switch(flag) ! 253: { ! 254: case 1: p="\n%s hits the %s"; break; ! 255: case 2: p="\n%s hits and kills the %s"; break; ! 256: case 3: p="\nThe %s%s gets teleported"; who=""; break; ! 257: }; ! 258: if (p) { lprintf(p,who,monster[tmp].name); beep(); } ! 259: } ! 260: /* if (yrepcount>1) { know[aa][bb] &= 2; know[cc][dd] &= 2; return; } */ ! 261: if (know[aa][bb] & 1) show1cell(aa,bb); ! 262: if (know[cc][dd] & 1) show1cell(cc,dd); ! 263: } ! 264: ! 265: /* ! 266: * movsphere() Function to look for and move spheres of annihilation ! 267: * ! 268: * This function works on the sphere linked list, first duplicating the list ! 269: * (the act of moving changes the list), then processing each sphere in order ! 270: * to move it. They eat anything in their way, including stairs, volcanic ! 271: * shafts, potions, etc, except for upper level demons, who can dispel ! 272: * spheres. ! 273: * No value is returned. ! 274: */ ! 275: #define SPHMAX 20 /* maximum number of spheres movsphere can handle */ ! 276: movsphere() ! 277: { ! 278: register int x,y,dir,len; ! 279: register struct sphere *sp,*sp2; ! 280: struct sphere sph[SPHMAX]; ! 281: ! 282: /* first duplicate sphere list */ ! 283: for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p) /* look through sphere list */ ! 284: if (sp2->lev == level) /* only if this level */ ! 285: { ! 286: sph[x] = *sp2; sph[x++].p = 0; /* copy the struct */ ! 287: if (x>1) sph[x-2].p = &sph[x-1]; /* link pointers */ ! 288: } ! 289: if (x) sp= sph; /* if any spheres, point to them */ ! 290: else return; /* no spheres */ ! 291: ! 292: for (sp=sph; sp; sp=sp->p) /* look through sphere list */ ! 293: { ! 294: x = sp->x; y = sp->y; ! 295: if (item[x][y]!=OANNIHILATION) continue; /* not really there */ ! 296: if (--(sp->lifetime) < 0) /* has sphere run out of gas? */ ! 297: { ! 298: rmsphere(x,y); /* delete sphere */ ! 299: continue; ! 300: } ! 301: switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) /* time to move the sphere */ ! 302: { ! 303: case 1: ! 304: case 2: /* change direction to a random one */ ! 305: sp->dir = rnd(8); ! 306: default: /* move in normal direction */ ! 307: dir = sp->dir; len = sp->lifetime; ! 308: rmsphere(x,y); ! 309: newsphere(x+diroffx[dir],y+diroffy[dir],dir,len); ! 310: }; ! 311: } ! 312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.