-+-+-+-+-+-+-+-+ START OF PART 29 -+-+-+-+-+-+-+-+ X cursor( objx+1, objy+1 ); X/* make cursor visible. X*/ X while (1) X `7B X switch(ttgetch()) X `7B X case '?': X cursors(); X lprcat("\nUse `5Bhjklnbyu`5D to move the cursor to the unkno Vwn object."); X lprcat("\nType a . when the cursor is at the desired place." V); X lprcat("\nType q, Return, or Escape to exit."); X cursor( objx+1, objy+1); X break; X X case '\33': X case 'q': X case '\n': X/* reset cursor X*/ X cursor( playerx+1, playery+1); X return; X case '.': X/* reset cursor X*/ X cursor( playerx+1, playery+1); X cursors(); X X if ((objx == playerx) && X (objy == playery)) X `7B X lprintf("\n@: %s", logname ); X return; X `7D X X i = mitem`5Bobjx`5D`5Bobjy`5D; X if ( i && ( know`5Bobjx`5D`5Bobjy`5D & KNOWHERE)) X X /* check for invisible monsters and not display X */ X if ( monstnamelist`5Bi`5D != floorc ) X `7B X lprintf("\n%c: %s", monstnamelist`5Bi`5D, monster`5B Vi`5D.name); X return; X `7D X X /* handle floor separately so as not to display traps, etc. X */ X i = item`5Bobjx`5D`5Bobjy`5D; X if ( i == 0 ) X `7B X lprc('\n'); X lprc(floorc); X lprintf(": the floor of the dungeon"); X return; X `7D X X if ( know`5Bobjx`5D`5Bobjy`5D & HAVESEEN ) X `7B X lprc('\n'); X if (boldobjects) X `7B X setbold(); X lprc(objnamelist`5Bi`5D); X resetbold(); X `7D X else X lprc(objnamelist`5Bi`5D); X lprintf(": %s", objectname`5Bi`5D); X return; X `7D X X lprintf("\n : An as-yet-unseen place in the dungeon" ); X return; X X case 'H': X case 'h': X move_cursor( &objx, &objy, 4); X break; X case 'J': X case 'j': X move_cursor( &objx, &objy, 1); X break; X case 'K': X case 'k': X move_cursor( &objx, &objy, 3); X break; X case 'L': X case 'l': X move_cursor( &objx, &objy, 2); X break; X case 'B': X case 'b': X move_cursor( &objx, &objy, 8); X break; X case 'N': X case 'n': X move_cursor( &objx, &objy, 7); X break; X case 'Y': X case 'y': X move_cursor( &objx, &objy, 6); X break; X case 'U': X case 'u': X move_cursor( &objx, &objy, 5); X break; X default: X break; X `7D X `7D X `7D X Xstatic void move_cursor( xx, yy, cdir ) X#if __STDC__ Xsigned char *xx ; Xsigned char *yy ; X#else Xchar *xx ; Xchar *yy ; X#endif Xunsigned char cdir ; X `7B X *xx += diroffx`5Bcdir`5D; X *yy += diroffy`5Bcdir`5D; X if ( *yy < 0 ) *yy = MAXY-1; X if ( *yy > MAXY-1 ) *yy = 0; X if ( *xx < 0 ) *xx = MAXX-1; X if ( *xx > MAXX-1 ) *xx = 0; X cursor( *xx+1, *yy+1 ); X `7D $ CALL UNPACK MOREOBJ.C;1 307844005 $ create 'f' X/* X * movem.c (move monster) X * X * movemonst() Routine to move the monsters toward the player X * build_proximity_ripple() Build proximity ripple for smart monster move X * move_scared() Move scared monsters X * move_smart() Move smart monsters X * move_dumb() Move dumb monsters X * mmove(x,y,xd,yd) Function to actually perform the monster movement X */ X#include "header.h" X#include "larndefs.h" X#include "monsters.h" X#include "objects.h" X#include "player.h" X X#define min(x,y) (((x)>(y))?(y):(x)) X#define max(x,y) (((x)>(y))?(x):(y)) X X void movemonst(); Xstatic void build_proximity_ripple(); Xstatic void move_scared(); Xstatic void move_smart(); Xstatic void move_dumb(); Xstatic void mmove(); X X#if 0 X# define IDISTNORM 8 /* was 17 - dgk */ X# define IDISTAGGR 20 /* was 40 - dgk */ X#endif X# define IDISTNORM 17 /* was 17 - dgk */ X# define IDISTAGGR 40 /* was 40 - dgk */ X Xstatic short w1x`5B9`5D,w1y`5B9`5D; Xstatic int tmp1,tmp2,tmp3,tmp4,distance; X X/* list of monsters to move */ Xstatic struct foo `7B char x ; char y; char smart; `7D movelist`5B250`5D ; X X/* X * movemonst() Routine to move the monsters toward the player X * X * This routine has the responsibility to determine which monsters are to X * move, and call movemt() to do the move. X * Returns no value. X */ Xvoid movemonst() X `7B X register int i,j,movecnt=0, smart_count, min_int ; X if (c`5BHOLDMONST`5D) return; /* no action if monsters are held */ X X if (c`5BAGGRAVATE`5D) /* determine window of monsters to move */ X `7B X tmp1=playery-5; tmp2=playery+6; tmp3=playerx-10; tmp4=playerx+11; X distance=IDISTAGGR; /* depth of intelligent monster movement */ X `7D X else X `7B X tmp1=playery-3; tmp2=playery+4; tmp3=playerx-5; tmp4=playerx+6; X distance=IDISTNORM; /* depth of intelligent monster movement */ X `7D X X if (level == 0) /* if on outside level monsters can move in perimeter */ X `7B X if (tmp1 < 0) tmp1=0; if (tmp2 > MAXY) tmp2=MAXY; X if (tmp3 < 0) tmp3=0; if (tmp4 > MAXX) tmp4=MAXX; X `7D X else /* if in a dungeon monsters can't be on the perimeter (wall there) V */ X `7B X if (tmp1 < 1) tmp1=1; if (tmp2 > MAXY-1) tmp2=MAXY-1; X if (tmp3 < 1) tmp3=1; if (tmp4 > MAXX-1) tmp4=MAXX-1; X `7D X X /* We now have a window in which to move monsters. First find all X monsters in the window, then decide whether or not to move them. X Its faster that way since the size of the window is usually larger X than the # of monsters in that window. X X Find all monsters in the window. The only time a monster cannot X move is if: monsters are not aggrevated, AND player is stealthed, X AND the monster is asleep due to stealth. Split into two X separate loops in order to simplify the if statement inside the X loop for the most common case. X X Also count # of smart monsters. X */ X smart_count = 0 ; X min_int = 10 - c`5BHARDGAME`5D ; /* minimum monster intelligence to m Vove smart */ X if ( c`5BAGGRAVATE`5D `7C`7C !c`5BSTEALTH`5D ) X `7B X for ( j = tmp1 ; j < tmp2 ; j++ ) X for ( i = tmp3 ; i < tmp4 ; i++ ) X if (mitem`5Bi`5D`5Bj`5D) X `7B X movelist`5Bmovecnt`5D.x = i; X movelist`5Bmovecnt`5D.y = j ; X if ( monster`5Bmitem`5Bi`5D`5Bj`5D`5D.intelligence > min V_int ) X `7B X movelist`5Bmovecnt`5D.smart = TRUE ; X smart_count++; X `7D X else X movelist`5Bmovecnt`5D.smart = FALSE ; X movecnt++; X `7D X `7D X else X `7B X for ( j = tmp1; j < tmp2 ; j++ ) X for ( i = tmp3 ; i < tmp4 ; i++ ) X if ( mitem`5Bi`5D`5Bj`5D && stealth`5Bi`5D`5Bj`5D ) /* ste Valth`5Bx`5D`5By`5D = 1 when AWAKE! */ X `7B X movelist`5Bmovecnt`5D.x = i; X movelist`5Bmovecnt`5D.y = j ; X if ( monster`5Bmitem`5Bi`5D`5Bj`5D`5D.intelligence > min V_int ) X `7B X movelist`5Bmovecnt`5D.smart = TRUE ; X smart_count++; X `7D X else X movelist`5Bmovecnt`5D.smart = FALSE ; X movecnt++; X `7D X `7D X X /* now move the monsters in the movelist. If we have at least one X smart monster, build a proximity ripple and use it for all smart X monster movement. X */ X if (movecnt > 0 ) X `7B X if ( c`5BSCAREMONST`5D ) X for ( i = 0 ; i < movecnt ; i++ ) X move_scared( movelist`5Bi`5D.x, movelist`5Bi`5D.y ); X else X `7B X if ( smart_count > 0 ) X `7B X /* I was going to put in code that prevented the rebuilding X of the proximity ripple if the player had not moved since X the last turn. Unfortunately, this permits the player to X blast down doors to treasure rooms and not have a single X intelligent monster move. X */ X build_proximity_ripple(); X for ( i = 0 ; i < movecnt ; i++ ) X if ( movelist`5Bi`5D.smart ) X move_smart( movelist`5Bi`5D.x, movelist`5Bi`5D.y ); X else X move_dumb( movelist`5Bi`5D.x, movelist`5Bi`5D.y ); X `7D X else X for ( i = 0 ; i < movecnt ; i++ ) X move_dumb( movelist`5Bi`5D.x, movelist`5Bi`5D.y ); X `7D X `7D X X /* Also check for the last monster hit. This is necessary to prevent X the player from getting free hits on a monster with long range X spells or when stealthed. X */ X if ( c`5BAGGRAVATE`5D `7C`7C !c`5BSTEALTH`5D ) X `7B X /* If the last monster hit is within the move window, its already X been moved. X */ X if ( ( ( lasthx < tmp3 `7C`7C lasthx >= tmp4 ) `7C`7C X ( lasthy < tmp1 `7C`7C lasthy >= tmp2 ) ) && X mitem`5Blasthx`5D`5Blasthy`5D ) X `7B X if ( c`5BSCAREMONST`5D ) X move_scared( lasthx, lasthy ); X else X if ( monster`5Bmitem`5Blasthx`5D`5Blasthy`5D`5D.intelligence > min_i Vnt ) X `7B X if ( smart_count == 0 ) X build_proximity_ripple( ); X move_smart( lasthx, lasthy ); X `7D X else X move_dumb( lasthx, lasthy ); X lasthx = w1x`5B0`5D; /* make sure the monster gets moved again V */ X lasthy = w1y`5B0`5D; X `7D X `7D X else X `7B X /* If the last monster hit is within the move window, and not X asleep due to stealth, then it has already been moved. X Otherwise (monster outside window, asleep due to stealth), X move the monster and update the lasthit x,y position. X */ X if ( ( lasthx < tmp3 `7C`7C lasthx >= tmp4 ) `7C`7C X ( lasthy < tmp1 `7C`7C lasthy >= tmp2 ) && X mitem`5Blasthx`5D`5Blasthy`5D `7C`7C !stealth`5Blasthx`5D`5Blasthy`5D V ) X `7B X if ( c`5BSCAREMONST`5D ) X move_scared( lasthx, lasthy ); X else X if ( monster`5Bmitem`5Blasthx`5D`5Blasthy`5D`5D.intelligence > min_i Vnt ) X `7B X if ( smart_count == 0 ) X build_proximity_ripple( ); X move_smart( lasthx, lasthy ); X `7D X else X move_dumb( lasthx, lasthy ); X lasthx = w1x`5B0`5D; /* make sure the monster gets moved again V */ X lasthy = w1y`5B0`5D; X `7D X `7D X `7D X Xstatic char screen`5BMAXX`5D`5BMAXY`5D; /* proximity ripple storage */ X X/* queue for breadth-first 'search' build of proximity ripple. X*/ X#define MAX_QUEUE 100 Xstatic struct queue_entry X `7B X char x ; X char y ; X char distance ; X `7D queue`5BMAX_QUEUE`5D; Xstatic int queue_head = 0 ; Xstatic int queue_tail = 0 ; X X/* put a location on the proximity ripple queue X*/ X#define PUTQUEUE( _x, _y, _d ) \ X `7B \ X queue`5Bqueue_tail`5D.x = (_x) ; \ X queue`5Bqueue_tail`5D.y = (_y) ; \ X queue`5Bqueue_tail`5D.distance = (_d); \ X queue_tail++; \ X if (queue_tail == MAX_QUEUE) \ X queue_tail = 0 ; \ X `7D X X/* take a location from the proximity ripple queue X*/ X#define GETQUEUE( _x, _y, _d ) \ X `7B \ X (_x) = queue`5Bqueue_head`5D.x ; \ X (_y) = queue`5Bqueue_head`5D.y ; \ X (_d) = queue`5Bqueue_head`5D.distance ; \ X queue_head++; \ X if (queue_head == MAX_QUEUE) \ X queue_head = 0 ; \ X `7D X X/* check for the proximity ripple queue being empty X*/ X#define QUEUEEMPTY() (queue_head == queue_tail) X X/* X For smart monster movement, build a proximity ripple from the player's X position, out to a 'distance' of 20. For example: X X W 5 4 4 W W X Player is at position marked 1 X W 5 W 3 3 W W W is a wall. Monsters will attempt X W 6 W 2 W 4 W to move to a location with a smaller X W 7 W 1 W 5 W value than their current position. X W 8 W W W 6 W Note that a monster at location X X W 9 9 8 7 7 7 will not move at all. X W W W 8 W W W X*/ Xstatic void build_proximity_ripple() X `7B X int xl, yl, xh, yh ; X int k, m, z, tmpx, tmpy; X int curx, cury, curdist; X X xl=tmp3-2; yl=tmp1-2; xh=tmp4+2; yh=tmp2+2; X vxy(&xl,&yl); vxy(&xh,&yh); X for (k=yl; k<=yh; k++) X for (m=xl; m<=xh; m++) X `7B X switch(item`5Bm`5D`5Bk`5D) X `7B +-+-+-+-+-+-+-+- END OF PART 29 +-+-+-+-+-+-+-+-