-+-+-+-+-+-+-+-+ START OF PART 30 -+-+-+-+-+-+-+-+ X case OWALL: X case OPIT: X case OTRAPARROW: X case ODARTRAP: X case OCLOSEDDOOR: X case OTRAPDOOR: X case OTELEPORTER: X screen`5Bm`5D`5Bk`5D=127; X break; X case OENTRANCE: X if (level==1) X screen`5Bm`5D`5Bk`5D = 127; X else X screen`5Bm`5D`5Bk`5D = 0; X break; X default: X screen`5Bm`5D`5Bk`5D = 0; X break; X `7D; X `7D X screen`5Bplayerx`5D`5Bplayery`5D=1; X X/* now perform proximity ripple from playerx,playery to monster */ X xl=tmp3-1; yl=tmp1-1; xh=tmp4+1; yh=tmp2+1; X vxy(&xl,&yl); vxy(&xh,&yh); X X PUTQUEUE( playerx, playery, 1 ); X do X `7B X GETQUEUE( curx, cury, curdist ); X X /* test all spots around the current one being looked at. X */ X if ( ( curx >= xl && curx <= xh ) && X ( cury >= yl && cury <= yh ) ) X `7B X for (z=1; z<9; z++) X `7B X tmpx = curx + diroffx`5Bz`5D ; X tmpy = cury + diroffy`5Bz`5D ; X vxy( &tmpx, &tmpy ); X if (screen`5Btmpx`5D`5Btmpy`5D == 0 ) X `7B X screen`5Btmpx`5D`5Btmpy`5D = curdist + 1; X PUTQUEUE( tmpx, tmpy, curdist + 1 ); X `7D X `7D X `7D X `7D X while (!QUEUEEMPTY()); X X `7D X X/* X Move scared monsters randomly away from the player position. X*/ Xstatic void move_scared( i, j ) Xint i, j ; X `7B X int xl, yl, tmp, tmpitem ; X X /* check for a half-speed monster, and check if not to move. Could be X done in the monster list build. X */ X switch(mitem`5Bi`5D`5Bj`5D) X `7B X case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART: X case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return V; X `7D; X X if ((xl = i+rnd(3)-2) < 0) X xl=0; X if (xl >= MAXX) X xl=MAXX-1; X if ((yl = j+rnd(3)-2) < 0) X yl=0; X if (yl >= MAXY) X yl=MAXY-1; X X if ((tmp=item`5Bxl`5D`5Byl`5D) != OWALL) X if (mitem`5Bxl`5D`5Byl`5D == 0) X if ((mitem`5Bi`5D`5Bj`5D != VAMPIRE) `7C`7C (tmp != OMIRROR)) X if (tmp != OCLOSEDDOOR) X mmove(i,j,xl,yl); X `7D X X/* X Move monsters that are moving intelligently, using the proximity X ripple. Attempt to move to a position in the proximity ripple X that is closer to the player. X X Parameters: the X,Y position of the monster to be moved. X*/ Xstatic void move_smart( i, j ) Xint i,j ; X `7B X int x,y,z ; X X /* check for a half-speed monster, and check if not to move. Could be X done in the monster list build. X */ X switch(mitem`5Bi`5D`5Bj`5D) X `7B X case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART: X case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return V; X `7D; X X /* find an adjoining location in the proximity ripple that is X closer to the player (has a lower value) than the monster's X current position. X */ X if (mitem`5Bi`5D`5Bj`5D != VAMPIRE) X for (z=1; z<9; z++) /* go around in a circle */ X `7B X x = i + diroffx`5Bz`5D ; X y = j + diroffy`5Bz`5D ; X if ( screen`5Bx`5D`5By`5D < screen`5Bi`5D`5Bj`5D ) X if ( !mitem`5Bx`5D`5By`5D ) X `7B X mmove(i,j,w1x`5B0`5D=x,w1y`5B0`5D=y); X return; X `7D X `7D X else X /* prevent vampires from moving onto mirrors X */ X for (z=1; z<9; z++) /* go around in a circle */ X `7B X x = i + diroffx`5Bz`5D ; X y = j + diroffy`5Bz`5D ; X if (( screen`5Bx`5D`5By`5D < screen`5Bi`5D`5Bj`5D ) && X ( item`5Bx`5D`5By`5D != OMIRROR )) X if ( !mitem`5Bx`5D`5By`5D ) X `7B X mmove(i,j,w1x`5B0`5D=x,w1y`5B0`5D=y); X return; X `7D X `7D X X `7D X X/* X For monsters that are not moving in an intelligent fashion. Move X in a direct fashion toward the player's current position. X X Parameters: the X,Y position of the monster to move. X*/ Xstatic void move_dumb( i, j ) Xint i, j ; X `7B X int xl, yl, xh, yh ; X int k, m, tmp, tmpd, tmpx, tmpy ; X X /* check for a half-speed monster, and check if not to move. Could be X done in the monster list build. X */ X switch(mitem`5Bi`5D`5Bj`5D) X `7B X case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART: X case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return V; X `7D; X X /* dumb monsters move here */ X /* set up range of spots to check. instead of checking all points X around the monster, only check those closest to the player. For X example, if the player is up and right of the monster, check only X the three spots up and right of the monster. X */ X xl=i-1; yl=j-1; xh=i+2; yh=j+2; X if (iplayerx) --xh; X if (jplayery) --yh; X X if (xl < 0) xl = 0; X if (yl < 0) yl = 0; X if (xh > MAXX) xh = MAXX; /* MAXX OK; loop check below is <, not <= */ X if (yh > MAXY) yh = MAXY; /* MAXY OK; loop check below is <, not <= */ X X /* check all spots in the range. find the one that is closest to X the player. if the monster is already next to the player, exit X the check immediately. X */ X tmpd = 10000 ; X tmpx = i ; tmpy = j ; X for ( k = xl ; k < xh ; k++ ) X for ( m = yl ; m < yh ; m++ ) X if ( k == playerx && m == playery ) X `7B X tmpd = 1 ; X tmpx = k ; X tmpy = m ; X break; /* exitloop */ X `7D X else if ((item`5Bk`5D`5Bm`5D != OWALL) && X (item`5Bk`5D`5Bm`5D != OCLOSEDDOOR) && X ((mitem`5Bk`5D`5Bm`5D == 0 ) `7C`7C (( k == i ) && ( m == j ))) V && X ((mitem`5Bi`5D`5Bj`5D != VAMPIRE) `7C`7C (item`5Bk`5D`5Bm`5D != V OMIRROR))) X `7B X tmp = (playerx-k)*(playerx-k)+(playery-m)*(playery-m); X if (tmp < tmpd) X `7B X tmpd = tmp; X tmpx = k; X tmpy = m; X `7D /* end if */ X `7D /* end if */ X X /* we have finished checking the spaces around the monster. if X any can be moved on and are closer to the player than the X current location, move the monster. X */ X if ((tmpd < 10000) && ((tmpx != i) `7C`7C (tmpy != j))) X `7B X mmove( i, j, tmpx, tmpy ); X w1x`5B0`5D = tmpx ; /* for last monster hit */ X w1y`5B0`5D = tmpy ; X `7D X else X `7B X w1x`5B0`5D = i ; /* for last monster hit */ X w1y`5B0`5D = j ; X `7D X `7D /* end move_dumb() */ X X/* X * mmove(x,y,xd,yd) Function to actually perform the monster movement X * int x,y,xd,yd; X * X * Enter with the from coordinates in (x,y) and the destination coordinates X * in (xd,yd). X */ Xstatic void mmove(aa,bb,cc,dd) X int aa,bb,cc,dd; X `7B X register int tmp,i,flag; X char *who,*p; X flag=0; /* set to 1 if monster hit by arrow trap */ X if ((cc==playerx) && (dd==playery)) X `7B X hitplayer(aa,bb); X return; X `7D X i=item`5Bcc`5D`5Bdd`5D; X if ((i==OPIT) `7C`7C (i==OTRAPDOOR)) X switch(mitem`5Baa`5D`5Bbb`5D) X `7B X case BAT: case EYE: X case SPIRITNAGA: case PLATINUMDRAGON: case WRAITH: X case VAMPIRE: case SILVERDRAGON: case POLTERGEIST: X case DEMONLORD: case DEMONLORD+1: case DEMONLORD+2: X case DEMONLORD+3: case DEMONLORD+4: case DEMONLORD+5: X case DEMONLORD+6: case DEMONPRINCE: break; X X default: mitem`5Baa`5D`5Bbb`5D=0; /* fell in a pit or trapdoor */ X `7D; X tmp = mitem`5Baa`5D`5Bbb`5D; X mitem`5Bcc`5D`5Bdd`5D = tmp; X if (i==OANNIHILATION) X `7B X if (tmp>=DEMONLORD+3) /* demons dispel spheres */ X `7B X cursors(); X lprintf("\nThe %s dispels the sphere!",monster`5Btmp`5D.name); X rmsphere(cc,dd); /* delete the sphere */ X `7D X else mitem`5Bcc`5D`5Bdd`5D=i=tmp=0; X `7D X stealth`5Bcc`5D`5Bdd`5D=1; X if ((hitp`5Bcc`5D`5Bdd`5D = hitp`5Baa`5D`5Bbb`5D) < 0) hitp`5Bcc`5D`5Bdd V`5D=1; X mitem`5Baa`5D`5Bbb`5D = 0; `20 X if (tmp == LEPRECHAUN) X switch(i) X `7B X case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD: X case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: X item`5Bcc`5D`5Bdd`5D = 0; /* leprechaun takes gold */ X `7D; X X if (tmp == TROLL) /* if a troll regenerate him */ X if ((gtime & 1) == 0) X if (monster`5Btmp`5D.hitpoints > hitp`5Bcc`5D`5Bdd`5D) hitp`5Bc Vc`5D`5Bdd`5D++; X X if (i==OTRAPARROW) /* arrow hits monster */ X `7B who = "An arrow"; if ((hitp`5Bcc`5D`5Bdd`5D -= rnd(10)+level) < V= 0) X `7B mitem`5Bcc`5D`5Bdd`5D=0; flag=2; `7D else flag=1; `7D X if (i==ODARTRAP) /* dart hits monster */ X `7B who = "A dart"; if ((hitp`5Bcc`5D`5Bdd`5D -= rnd(6)) <= 0) X `7B mitem`5Bcc`5D`5Bdd`5D=0; flag=2; `7D else flag=1; `7D X if (i==OTELEPORTER) /* monster hits teleport trap */ X `7B flag=3; fillmonst(mitem`5Bcc`5D`5Bdd`5D); mitem`5Bcc`5D`5Bdd`5D V=0; `7D X if (c`5BBLINDCOUNT`5D) return; /* if blind don't show where monsters ar Ve */ X if (know`5Bcc`5D`5Bdd`5D & HAVESEEN) X `7B X p=0; X if (flag) cursors(); X switch(flag) X `7B X case 1: p="\n%s hits the %s"; break; X case 2: p="\n%s hits and kills the %s"; break; X case 3: p="\nThe %s%s gets teleported"; who=""; break; X `7D; X if (p) `7B lprintf(p,who,monster`5Btmp`5D.name); beep(); `7D X `7D X/* if (yrepcount>1) `7B know`5Baa`5D`5Bbb`5D &= 2; know`5Bcc`5D`5Bdd`5D &= V 2; return; `7D */ X if (know`5Baa`5D`5Bbb`5D & HAVESEEN) show1cell(aa,bb); X if (know`5Bcc`5D`5Bdd`5D & HAVESEEN) show1cell(cc,dd); X `7D $ CALL UNPACK MOVEM.C;1 1900664959 $ create 'f' X#ifdef MSDOS X# include X# include X# include X# include X# include X# include X# include "header.h" X# include "larndefs.h" X X# define DEVICE 0x80 X# define RAW 0x20 X# define IOCTL 0x44 X# define STDIN 0 X# define STDOUT 1 X# define GETBITS 0 X# define SETBITS 1 X# define PATHSEP ';' X X/* Normal characters are output when the shift key is not pushed. X * Shift characters are output when either shift key is pushed. X */ X# define KEYPADHI 83 X# define KEYPADLOW 71 X# define iskeypad(x) (KEYPADLOW <= (x) && (x) <= KEYPADHI) Xstatic struct `7B X char normal, shift; X `7D pad`5BKEYPADHI - KEYPADLOW + 1`5D = `7B X `7B'y', 'Y'`7D, /* 7 */ X `7B'k', 'K'`7D, /* 8 */ X `7B'u', 'U'`7D, /* 9 */ X `7B' ', ' '`7D, /* - */ X `7B'h', 'H'`7D, /* 4 */ X `7B' ', ' '`7D, /* 5 */ X `7B'l', 'L'`7D, /* 6 */ X `7B' ', ' '`7D, /* + */ X `7B'b', 'B'`7D, /* 1 */ X `7B'j', 'J'`7D, /* 2 */ X `7B'n', 'N'`7D, /* 3 */ X `7B'i', 'i'`7D, /* Ins */ X `7B'.', '.'`7D /* Del */ X`7D; X X/* BIOSgetch gets keys directly with a BIOS call. X */ X#ifdef OS2LARN X# define SHIFT (RIGHTSHIFT `7C LEFTSHIFT) X#else X# define SHIFT (0x1 `7C 0x2) X#endif X# define KEYBRD_BIOS 0x16 X Xstatic char XBIOSgetch() `7B X unsigned char scan, shift, ch; X union REGS regs; X X#ifdef OS2LARN X KBDKEYINFO kbd; X X KbdCharIn(&kbd,IO_WAIT,(HKBD) 0); X ch = kbd.chChar; X scan = kbd.chScan; X shift = kbd.fsState; X#else X /* Get scan code. X */ X regs.h.ah = 0; X int86(KEYBRD_BIOS, ®s, ®s); X ch = regs.h.al; X scan = regs.h.ah; X X /* Get shift status. X */ X regs.h.ah = 2; X int86(KEYBRD_BIOS, ®s, ®s); X shift = regs.h.al; X#endif X X /* If scan code is for the keypad, translate it. X */ X if (iskeypad(scan)) `7B X if (shift & SHIFT) X ch = pad`5Bscan - KEYPADLOW`5D.shift; X else X ch = pad`5Bscan - KEYPADLOW`5D.normal; X `7D X return ch; X`7D X Xkgetch() X`7B X /* BIOSgetch can use the numeric key pad on IBM compatibles. */ X if (keypad) X return BIOSgetch(); X else X return getch(); X`7D X Xdoshell() X`7B X char *comspec = getenv("COMSPEC"); X X clear(); X lflush(); X if (comspec == NULL X `7C`7C (spawnl(P_WAIT, comspec, comspec, NULL) < 0)) `7B X write(2, "A> ", 3); X while (getche() != '\r') X ; X `7D X`7D X Xstatic unsigned old_stdin, old_stdout, ioctl(); X Xstatic unsigned Xioctl(handle, mode, setvalue) Xunsigned setvalue; X`7B X#ifndef OS2LARN X union REGS regs; X X regs.h.ah = IOCTL; X regs.h.al = mode; X regs.x.bx = handle; X regs.h.dl = setvalue; X regs.h.dh = 0; /* Zero out dh */ X intdos(®s, ®s); X return (regs.x.dx); X#endif X`7D X Xint rawio; Xvoid Xsetraw() X`7B X if (!rawio) X return; X old_stdin = ioctl(STDIN, GETBITS, 0); X old_stdout = ioctl(STDOUT, GETBITS, 0); X if (old_stdin & DEVICE) X (void) ioctl(STDIN, SETBITS, old_stdin `7C RAW); X if (old_stdout & DEVICE) X (void) ioctl(STDOUT, SETBITS, old_stdout `7C RAW); X`7D X Xvoid Xunsetraw() X`7B X if (!rawio) X return; X if (old_stdin) X (void) ioctl(STDIN, SETBITS, old_stdin); X if (old_stdout) X (void) ioctl(STDOUT, SETBITS, old_stdout); X`7D X X X/* Add a backslash to any name not ending in /, \ or : There must X * be room for the \ X */ Xvoid Xappend_slash(name) Xchar *name; X`7B X char *ptr; X X if (!*name) X return; X ptr = name + (strlen(name) - 1); +-+-+-+-+-+-+-+- END OF PART 30 +-+-+-+-+-+-+-+-