[net.sources.games] vms extended rogue part 2 of 4

rich@sdcsvax.UUCP (rich) (08/04/86)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	macros.h
#	main.c
#	make.com
#	message.c
#	monster.c
#	monster.h
#	move.c
#	move.h
# This archive created: Mon Aug  4 11:41:45 1986
# By:	rich ( lack of)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'macros.h'
then
	echo shar: "will not over-write existing file 'macros.h'"
else
cat << \SHAR_EOF > 'macros.h'
#define swap(x,y) {int t; t = x; x = y; y = t;}
#define two_sort(x,y) if (x > y) {int t; t = x; x = y; y = t;}
#define swap_string(x,y) {char *t; t = x; x = y; y = t;}
SHAR_EOF
fi
if test -f 'main.c'
then
	echo shar: "will not over-write existing file 'main.c'"
else
cat << \SHAR_EOF > 'main.c'

#include curses.h
#include "object.h"
short chan;

main()
{
	init();

	for (;;) {
		clear_level();
		make_level();
		put_objects();
		put_stairs();
		put_monsters();
		put_player();
		light_up_room();
		print_stats();
		play_level();
		free_stuff(&level_objects);
		free_stuff(&level_monsters);
		clear();
	}
}
SHAR_EOF
fi
if test -f 'make.com'
then
	echo shar: "will not over-write existing file 'make.com'"
else
cat << \SHAR_EOF > 'make.com'
$set noon
$define lnk$library sys$library:vaxccurse
$define lnk$library_1 sys$library:vaxcrtl
$cc DOORCOU.C
$cc help.c
$cc HIT.C
$cc INIT.C
$cc INVENTOR.C
$cc IO.C
$cc LEVEL.C
$cc MESSAGE.C
$cc MONSTER.C
$cc MOVE.C
$cc OBJECT.C
$cc PACK.C
$cc PLAY.C
$cc RANDOM.C
$cc ROOM.C
$cc SCORE.C
$cc SPECIAL.C
$cc THROW.C
$cc USE.C
$cc ZAP.C
$library/create  rogue  HIT
$library/replace rogue  help
$library/replace rogue  INIT
$library/replace rogue  INVENTOR
$library/replace rogue  doorcou
$library/replace rogue  IO
$library/replace rogue  LEVEL
$library/replace rogue  MESSAGE
$library/replace rogue  MONSTER
$library/replace rogue  MOVE
$library/replace rogue  OBJECT
$library/replace rogue  PACK
$library/replace rogue  PLAY
$library/replace rogue  RANDOM
$library/replace rogue  ROOM
$library/replace rogue  SCORE
$library/replace rogue  SPECIAL
$library/replace rogue  THROW
$library/replace rogue  USE
$library/replace rogue  ZAP
$cc      MAIN
$link main,rogue/lib
SHAR_EOF
fi
if test -f 'message.c'
then
	echo shar: "will not over-write existing file 'message.c'"
else
cat << \SHAR_EOF > 'message.c'
#include curses.h
#include "object.h"
#include "move.h"

char message_cleared = 1;
char message_line[SCOLS] = "";
short message_col;

extern short cant_int, did_int;

extern short interrupted;

message(msg, intrpt)
char *msg;
short intrpt;
{
	if (intrpt) {
		interrupted = 1;
	}
	cant_int = 1;
	/* slurp(); */

	if (!message_cleared) {
		mvaddstr(MIN_ROW-1, message_col, MORE);
		refresh_vms();
		wait_for_ack(0);
		check_message();
	}
	strcpy(message_line, msg);
	mvaddstr(MIN_ROW-1, 0, msg);
	addch(' ');
	refresh_vms();
	message_cleared = 0;
	message_col = strlen(msg);

	if (did_int) {
/*		onintr(); */
	}
	cant_int = 0;
}

remessage()
{
	if (message_line[0]) {
		message(message_line, 0);
	}
}

check_message()
{
	register i;

	if (message_cleared) {
		return;
	}
	move(MIN_ROW-1, 0);
	clrtoeol();
	move(rogue.row, rogue.col);
	refresh_vms();
	message_cleared = 1;
}

get_input_line(buf, if_cancelled)
char *buf;
char *if_cancelled;
{
	short ch;
	short i = 0;

	message("call it:", 0);

	while (((ch = getchar()) != '\n') && (ch != CANCEL)) {
		if ((ch >= ' ') && (ch <= '~') && (i < MAX_TITLE_LENGTH-2)) {
			buf[i++] = ch;
			addch(ch);
		}
		if ((ch == '\b') && (i > 0)) {
			mvaddch(0, --i + 9, ' ');
			move(MIN_ROW-1, i+9);
		}
		refresh_vms();
	}
	check_message();
	if (ch == CANCEL) {
		if (if_cancelled) {
			message(if_cancelled, 0);
		}
		return(0);
	}
	buf[i++] = ' ';
	buf[i] = 0;
	return(1);
}

/*
slurp()
{
	long ln;
	short i, n;

	do {
		ioctl(0, FIONREAD, &ln);
		n = stdin->_cnt + ln;

		for (i = 0; i < ln; i++) getchar();
	} while (ln > 0L);
}
*/
SHAR_EOF
fi
if test -f 'monster.c'
then
	echo shar: "will not over-write existing file 'monster.c'"
else
cat << \SHAR_EOF > 'monster.c'
#include curses.h
#include ctype.h
#include "monster.h"
#include "object.h"
#include "room.h"
#include "move.h"
#define TROLLMAX 64

extern short AMULET_LEVEL;
extern short current_level;
extern short current_room, party_room;
extern short detect_monster;
extern short blind, halluc;

char *monster_names[] = {
	"ant lion",
	"aquatar",
	"bat",
	"blood hawk",
	"centaur",
	"cloud giant",
	"baby dragon",
	"dragon",
	"emu",
	"ettin",
	"venus fly-trap",
	"frost giant",
	"griffin",
	"ghost",
	"grimlock",
	"hill giant",
	"hobgoblin",
	"ice monster",
	"imp",
	"jabberwock",
	"jackal",
	"kestrel",
	"kobold",
	"leopard",
	"leprechaun",
	"meazel",
	"medusa",
	"nightmare",
	"nymph",
	"orc",
	"ogre",
	"phantom",
	"pheonix",
	"quaggoth",
	"quasit",
	"ram",
	"rattlesnake",
	"snake",
	"spider",
	"storm giant",
	"titan",
	"troll",
	"umber hulk",
	"black unicorn",
	"vampire",
	"vilstrak",
	"wolf",
	"wraith",
	"xeroc",
	"xvart",
	"yeth hound",
	"yeti",
	"zombie"
};

object monster_tab[MONSTERS] = {
/* antlion*/	{(WANDERS),"5d4",64,'a',60,11,22,75,0,45},
/* aquatar*/	{(IS_ASLEEP|WAKENS|WANDERS),"1d5",25,'A',20,AQUATAR1,AQUATAR2,100,0,0},
/* bat    */	{(IS_ASLEEP|WANDERS|FLITS),"1d3",10,'B',2,1,8,60,0,0},
/* b. hawk*/	{(FLIES),"3d4/1d6",25,'b',15,6,17,85,0,25},
/* centaur*/	{(IS_ASLEEP|WANDERS),"3d4/2d6",30,'C',30,7,16,85,0,10},
/* c giant*/	{(IS_ASLEEP|WAKENS|WANDERS),"4d6/3d10",120,'c',900,15,126,85,0,80},
/* b.dragn*/	{(IS_ASLEEP|WAKENS|FLIES),"3d5/2d9",90,'d',2000,19,126,90,0,60},
/* dragon */	{(IS_ASLEEP|WAKENS),"4d5/3d9",128,'D',5000,21,126,100,0,90},
/* emu    */	{(IS_ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0},
/* ettin  */	{(WANDERS),"2d8/3d6",80,'e',500,14,126,75,0,60},
/* fly trp*/	{(0),"1d3",32,'F',31,FLYTRAP1,FLYTRAP2,80,0,0},
/* f giant*/	{(IS_ASLEEP|WAKENS),"4d6/2d10",100,'f',700,14,126,85,0,60},
/* griffin*/	{(IS_ASLEEP|WAKENS|WANDERS|FLIES),"5d4/4d5",92,'G',2000,20,126,85,0,10},
/* ghost  */	{(0),"1d10",70,'.',75,12,126,85,0,50},
/* grimlck*/	{(WANDERS|FLIES),"3d10/6d3",105,'g',2000,15,126,100,0,70},
/* h giant*/	{(IS_ASLEEP|WANDERS),"2d8/2d8",80,'h',500,12,126,75,0,60},
/* hgoblin*/	{(IS_ASLEEP|WAKENS|WANDERS),"1d3/1d3",17,'H',3,1,10,67,0,0},
/* icemstr*/	{(IS_ASLEEP),"0d0",15,'I',5,ICEMSTR1,ICEMSTR2,68,0,0},
/* imp    */	{(WANDERS),"1d4",28,'i',3,1,7,50,0,0},
/* jabrwck*/	{(IS_ASLEEP|WANDERS),"3d10/3d4",125,'J',3000,21,126,100,0,0},
/* jackal */	{(WANDERS),"1d2",4,'j',2,1,4,50,0,0},
/* kestrel*/	{(IS_ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0},
/* kobold */ 	{(IS_ASLEEP|WAKENS|WANDERS),"2d4",8,'k',2,1,4,50,0,20},
/* leopard*/	{(WANDERS),"4d3/2d4",26,'l',20,8,17,75,0,20},
/* lepchan*/	{(IS_ASLEEP),"0d0",25,'L',18,LEPCHAN1,LEPCHAN2,75,0,0},
/* meazel */	{(IS_ASLEEP|WAKENS|WANDERS),"3d6",50,'m',50,7,20,75,0,10},
/* medusa */	{(IS_ASLEEP|WAKENS|WANDERS),"4d4/3d7",92,'M',250,18,126,85,0,25},
/* n. mare*/	{(WANDERS|FLIES),"2d4/3d4",54,'n',50,10,22,80,0,0},
/* nymph  */	{(IS_ASLEEP),"0d0",25,'N',37,NYMPH1,NYMPH2,75,0,100},
/* orc    */	{(IS_ASLEEP|WANDERS|WAKENS),"1d6",25,'O',10,4,13,70,0,10},
/* ogre   */	{(IS_ASLEEP|WANDERS|WAKENS),"2d5",41,'o',25,7,16,85,0,35},
/* phantom*/	{(IS_ASLEEP|IS_INVIS|WANDERS|FLITS),"5d4",76,'P',120,15,23,80,0,50},
/* pheonix*/	{(FLIES),"2d12/3d8",160,'p',2500,26,126,100,0,95},
/* quagoth*/	{(WANDERS),"2d10/3d4",100,'q',1000,14,126,100,0,60},
/* quasit */	{(IS_ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20},
/* ram	  */	{(IS_ASLEEP|WAKENS),"2d6",25,'r',10,4,12,65,0,0},
/* r snake*/	{(IS_ASLEEP|WAKENS|WANDERS),"2d5",19,'R',10,RSNAKE1,RSNAKE2,70,0,0},
/* snake  */	{(IS_ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0},
/* spider */	{(IS_ASLEEP|WAKENS|FLITS),"1d2",9,'s',3,SPIDER1,SPIDER2,75,0,0},
/* s giant*/	{(WANDERS),"6d6/2d12",140,'s',1000,20,126,95,0,70},
/* titan  */	{(IS_ASLEEP|WAKENS|WANDERS),"6d10",150,'t',2500,24,126,97,0,80},
/* troll  */	{(IS_ASLEEP|WAKENS|WANDERS),"4d6",TROLLMAX,'T',300,13,126,75,0,33},
/* u hulk */	{(IS_ASLEEP|WAKENS),"3d4/2d5",64,'u',60,12,30,60,0,70},
/* unicorn*/	{(IS_ASLEEP|WAKENS|WANDERS),"4d9",88,'U',200,17,26,85,0,33},
/* vampire*/	{(IS_ASLEEP|WAKENS|WANDERS),"1d14",60,'V',350,VAMPIRE1,VAMPIRE2,85,0,18},
/* vilstrk*/	{(WANDERS),"2d5",15,'v',4,1,9,65,0,20},
/* wolf   */    {(IS_ASLEEP|WAKENS|WANDERS|FLIES),"1d4/2d3",16,'w',5,1,11,80,0,0},
/* wraith */	{(IS_ASLEEP|WANDERS),"2d7",42,'W',75,WRAITH1,WRAITH2,75,0,0},
/* xeroc  */	{(IS_ASLEEP),"4d6",42,'X',110,XEROC1,XEROC2,75,0,0},
/* xvart  */	{(IS_ASLEEP|WANDERS|FLITS),"1d8",20,'x',3,1,11,69,0,10},
/* yeth h.*/	{(WANDERS|FLIES),"2d8",27,'y',40,9,18,80,0,10},
/* yeti   */	{(IS_ASLEEP|WANDERS),"3d6",33,'Y',50,11,20,80,0,20},
/* zombie */	{(IS_ASLEEP|WAKENS|WANDERS),"1d7",20,'Z',8,5,14,69,0,0}
};

object level_monsters;

identify_monst(monst)
char monst;{
int i;

for(i=0;i!=MONSTERS;i++)
	if(monster_tab[i].ichar==monst

	 && 
	current_level >= monster_tab[i].is_protected && 
	current_level <= monster_tab[i].is_cursed ){ 

		message(monster_names[i],1);
		return;
	}	
}

put_monsters()
{
	short i;
	short n;
	object *monster, *get_rand_monster();

	n = get_rand(3, 7);

	for (i = 0; i < n; i++) {
		monster = get_rand_monster();
		if ((monster->m_flags & WANDERS) && rand_percent(50)) {
			wake_up(monster);
		}
		put_monster_rand_location(monster);
		add_to_pack(monster, &level_monsters, 0);
	}
}

object *get_rand_monster()
{
	object *monster, *get_an_object();
	short mn;

	monster = get_an_object();

	for (;;) {
		mn = get_rand(0, MAXMONSTER-1);
		if ((current_level >= monster_tab[mn].is_protected) &&
		(current_level <= monster_tab[mn].is_cursed)) {
			break;
		}
	}
	*monster = monster_tab[mn];
	monster->what_is = MONSTER;
	if (monster->ichar == 'X') {
		monster->identified = get_rand_obj_char();
	}
	if (monster->ichar == 'D'|| monster->ichar=='d') {
		monster->to_hit_enchantment= rand()%6;
	}
	if (current_level > (AMULET_LEVEL + 2)) {
		monster->m_flags |= HASTED;
	}
	monster->trow = -1;
	return(monster);
}

move_monsters()
{
	object *monster;
	short flew;

	monster = level_monsters.next_object;

	while (monster) {
		if (monster->m_flags & HASTED) {
			mv_monster(monster, rogue.row, rogue.col);
		} else if (monster->m_flags & SLOWED) {
			monster->quiver = !monster->quiver;
			if (monster->quiver) {
				goto NM;
			}
		}
		flew = 0;
		if ((monster->m_flags & FLIES) &&
		     !monster_can_go(monster, rogue.row, rogue.col)) {
			flew = 1;
			mv_monster(monster, rogue.row, rogue.col);
		}
		if (!flew || !monster_can_go(monster, rogue.row, rogue.col)) {
			mv_monster(monster, rogue.row, rogue.col);
		}
NM:		monster = monster->next_object;
	}
}

fill_room_with_monsters(rn, n)
{
	short i;
	short row, col;
	object *monster, *get_rand_monster();

	n += n/2;

	for (i = 0; i < n; i++) {
		if (no_room_for_monster(rn)) break;
		do {
			row = get_rand(rooms[rn].top_row+1,
				       rooms[rn].bottom_row-1);
			col = get_rand(rooms[rn].left_col+1,
				       rooms[rn].right_col-1);
		} while (screen[row][col] & MONSTER);

		monster = get_rand_monster();
		put_monster_at(row, col, monster);
	}
}

get_monster_char_row_col(row, col)
{
	object *monster, *object_at();
	short retval;

	monster = object_at(&level_monsters, row, col);
	if ((!detect_monster && (monster->m_flags & IS_INVIS)) || blind) {
		retval = get_room_char((screen[row][col] & ~MONSTER),row,col);
		return(retval);
	}
	if ((monster->ichar == 'X') && monster->identified) {
		return(monster->identified);
	}
	return(monster->ichar);
}

get_monster_char(monster)
object *monster;
{
	short retval;

	if ((!detect_monster && (monster->m_flags & IS_INVIS)) || blind) {
		retval = get_room_char((screen[monster->row][monster->col] & ~MONSTER), monster->row, monster->col);
		return(retval);
	}
	if ((monster->ichar == 'X') && monster->identified) {
		return(monster->identified);
	}
	return(monster->ichar);
}

mv_monster(monster, row, col)
register object *monster;
short row, col;
{
	short i, n;
	char tried[6];

	if (monster->m_flags & IS_ASLEEP) {
		if ((monster->m_flags & WAKENS) &&
		     rogue_is_around(monster->row, monster->col) &&
		     rand_percent(WAKE_PERCENT)) {
			wake_up(monster);
		}
		return;
	}
	if ((monster->m_flags & FLITS) && flit(monster)) {
		return;
	}
	if (((current_level >= FLYTRAP1) && (current_level <= FLYTRAP2) &&
	     (monster->ichar == 'F')) && 
	     !monster_can_go(monster, rogue.row, rogue.col)) {
		return;
	}
	if (((current_level >= ICEMSTR1) && (current_level <= ICEMSTR2) &&
	     (monster->ichar == 'I')) && monster->identified) {
		return;
	}
	if ((monster->ichar == 'M') && paralyze(monster)) {
		return;
	}
	if (monster->ichar =='T') {
		monster->quantity+= 10;
		if (monster->quantity > TROLLMAX) 
			monster->quantity = TROLLMAX;
	}
	if ((monster->ichar == 'u') && m_confuse(monster)) {
		return;
	}
	if (monster_can_go(monster, rogue.row, rogue.col)) {
		monster_hit(monster, 0);
		return;
	}
	if (((monster->ichar == 'd') || (monster->ichar == 'D')) 
			     && breath(monster,monster->to_hit_enchantment)) {
		return;
	}
	if ((monster->ichar == 'O') && orc_gold(monster)) {
		return;
	}
	if ((monster->trow == monster->row) &&
		   (monster->tcol == monster->col)) {
		monster->trow = -1;
	} else if (monster->trow != -1) {
		row = monster->trow;
		col = monster->tcol;
	}
	if (monster->row > row) {
		row = monster->row - 1;
	} else if (monster->row < row) {
		row = monster->row + 1;
	}
	if ((screen[row][monster->col] & DOOR) &&
	     mtry(monster, row, monster->col)) {
		return;
	}
	if (monster->col > col) {
		col = monster->col - 1;
	} else if (monster->col < col) {
		col = monster->col + 1;
	}
	if ((screen[monster->row][col] & DOOR) &&
	     mtry(monster, monster->row, col)) {
		return;
	}
	if (mtry(monster, row, col)) {
		return;
	}
	for (i = 0; i <= 5; i++) tried[i] = 0;

	for (i = 0; i < 6; i++) {
NEXT_TRY:	n = get_rand(0, 5);
		switch(n) {
		case 0:
			if (!tried[n] && mtry(monster, row, monster->col-1)) {
				return;
			}
			break;
		case 1:
			if (!tried[n] && mtry(monster, row, monster->col)) {
				return;
			}
			break;
		case 2:
			if (!tried[n] && mtry(monster, row, monster->col+1)) {
				return;
			}
			break;
		case 3:
			if (!tried[n] && mtry(monster, monster->row-1, col)) {
				return;
			}
			break;
		case 4:
			if (!tried[n] && mtry(monster, monster->row, col)) {
				return;
			}
			break;
		case 5:
			if (!tried[n] && mtry(monster, monster->row+1, col)) {
				return;
			}
			break;
		}
		if (!tried[n]) {
			tried[n] = 1;
		} else {
			goto NEXT_TRY;
		}
	}
}

mtry(monster, row, col)
register object *monster;
register short row, col;
{
	if (monster_can_go(monster, row, col)) {
		move_monster_to(monster, row, col);
		return(1);
	}
	return(0);
}

move_monster_to(monster, row, col)
register object *monster;
register short row, col;
{
	short c;

	add_mask(row, col, MONSTER);
	remove_mask(monster->row, monster->col, MONSTER);

	c = mvinch(monster->row, monster->col);

	if (isupper(c)||islower(c)) {
		mvaddch(monster->row, monster->col,
		get_room_char(screen[monster->row][monster->col],
		monster->row, monster->col));
	}
	if (!blind && (detect_monster || can_see(row, col))) {
		if ((!(monster->m_flags & IS_INVIS) || detect_monster)) {
			mvaddch(row, col, get_monster_char(monster));
		}
	}
	if ((screen[row][col] & DOOR) &&
	    (get_room_number(row, col) != current_room) &&
	    (screen[monster->row][monster->col] == FLOOR)) {
		if (!blind)
			mvaddch(monster->row, monster->col, ' ');
	}
	if (screen[row][col] & DOOR) {
			door_course(monster,
			(screen[monster->row][monster->col] & TUNNEL),
			row, col);
	} else {
		monster->row = row;
		monster->col = col;
	}
}

monster_can_go(monster, row, col)
register object *monster;
register short row, col;
{
	object *obj, *object_at();
	short dr, dc;

	dr = monster->row - row;	/* check if move distance > 1 */
	if ((dr >= 2) || (dr <= -2)) return(0);
	dc = monster->col - col;
	if ((dc >= 2) || (dc <= -2)) return(0);

	if ((!screen[monster->row][col]) || (!screen[row][monster->col])) {
		return(0);
	}

	if ((!is_passable(row, col)) || (screen[row][col] & MONSTER)) {
		return(0);
	}
	if ((monster->row!=row)&&(monster->col!=col)&&((screen[row][col]&DOOR)
	|| (screen[monster->row][monster->col]&DOOR))) {
		return(0);
	}
	if (!(monster->m_flags & FLITS) && !(monster->m_flags & CAN_GO) &&
	     (monster->trow == -1)) {
	if ((monster->row < rogue.row) && (row < monster->row)) return(0);
	if ((monster->row > rogue.row) && (row > monster->row)) return(0);
	if ((monster->col < rogue.col) && (col < monster->col)) return(0);
	if ((monster->col > rogue.col) && (col > monster->col)) return(0);
	}

	if (screen[row][col] & SCROLL) {
		obj = object_at(&level_objects, row, col);
		if (obj->which_kind == SCARE_MONSTER) {
			return(0);
		}
	}

	return(1);
}

wake_up(monster)
object *monster;
{
	monster->m_flags &= (~IS_ASLEEP);
}

wake_room(rn, entering, row, col)
{
	object *monster;
	short wake_percent;

	wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT;

	monster = level_monsters.next_object;

	while (monster) {
		if (((monster->m_flags & WAKENS) || (rn == party_room)) &&
		   (rn == get_room_number(monster->row, monster->col))) {
			if ((monster->ichar != 'X') && (rn == party_room)) {
				monster->m_flags |= WAKENS;
			}
			if (entering) {
				monster->trow = -1;
			} else {
				monster->trow = row;
				monster->tcol = col;
			}
			if (rand_percent(wake_percent) &&
			   (monster->m_flags & WAKENS)) {
				if (monster->ichar != 'X') {
					wake_up(monster);
				}
			}
		}
		monster = monster->next_object;
	}
}

char *monster_name(monster)
object *monster;
{
	int i;

	if (blind || ((monster->m_flags & IS_INVIS) && !detect_monster)) {
		return("something");
	}
	if (halluc) {
		i=rand()%MONSTERS;
		return(monster_names[i]);
	}
for(i=0;i!=MONSTERS;i++)
	if(monster_tab[i].ichar==monster->ichar

	 && 
	current_level >= monster_tab[i].is_protected && 
	current_level <= monster_tab[i].is_cursed )
			return(monster_names[i]);

/*	for(i=0;i!=MONSTERS;i++)
		if(monster_tab[i].ichar==monster->ichar)
			return(monster_names[i]);
*/
}

rogue_is_around(row, col)
{
	short rdif, cdif, retval;

	rdif = row - rogue.row;
	cdif = col - rogue.col;

	retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
	return(retval);
}

start_wanderer()
{
	object *monster, *get_rand_monster();
	short row, col, i;
ANOTHER:
	monster = get_rand_monster();
	if ((!(monster->m_flags & WAKENS)) &&
	    (!(monster->m_flags & WANDERS))) {
		free(monster);
		goto ANOTHER;
	}
	wake_up(monster);

	for (i = 0; i < 12; i++) {
		get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT));
		if (!can_see(row, col)) {
			put_monster_at(row, col, monster);
			return;
		}
	}
}

show_monsters()
{
	object *monster;

	if (blind) return;

	monster = level_monsters.next_object;

	while (monster) {
		mvaddch(monster->row, monster->col, monster->ichar);
		if (monster->ichar == 'X') {
			monster->identified = 0;
		}
		monster = monster->next_object;
	}
}

create_monster()
{
	short row, col;
	short i, j, inc1, inc2;
	short found = 0;
	object *monster;

	inc1 = get_rand(0, 1) ? 1 : -1;
	inc2 = get_rand(0, 1) ? 1 : -1;

	for (i = inc1; i != (2 * -inc1); i -= inc1) {
		for (j = inc2; j != (2 * -inc2); j -= inc2) {
			if (!i && !j) continue;
			row = rogue.row + i;
			col = rogue.col + j;
			if ((row < MIN_ROW) || (row > (LINES-2)) ||
			    (col < 0) || (col > (COLS-1))) {
				continue;
			}
			if ((!(screen[row][col] & MONSTER)) &&
			      (screen[row][col] & (FLOOR|TUNNEL|STAIRS))) {
				found = 1;
				goto FOUND;
			}
		}
	}
FOUND:
	if (found) {
		monster = get_rand_monster();
		put_monster_at(row, col, monster);
		mvaddch(row, col, get_monster_char(monster));
		if (monster->m_flags & WANDERS) {
			wake_up(monster);
		}
	} else {
		message("you hear a faint cry of anguish in the distance",0);
	}
}

put_monster_at(row, col, monster)
object *monster;
{
		monster->row = row; monster->col = col;
		add_mask(row, col, MONSTER);
		add_to_pack(monster, &level_monsters, 0);
}

can_see(row, col)
{
	short retval;

	retval = !blind && ((get_room_number(row, col) == current_room) ||
	   (rogue_is_around(row, col)));

	return(retval);
}

flit(monster)
object *monster;
{
	short inc1, inc2;
	short i, j, row, col;

	if (!rand_percent(FLIT_PERCENT)) {
		return(0);
	}
	inc1 = get_rand(0, 1) ? 1 : -1;
	inc2 = get_rand(0, 1) ? 1 : -1;

	if (rand_percent(10)) {
		return(1);
	}
	for (i = inc1; i != (2*(0-inc1)); i+=(0-inc1)) {
		for (j = inc2; j != (2*(0-inc2)); j+=(0-inc2)) {

			row = monster->row + i;
			col = monster->col + j;
			if ((row == rogue.row) && (col == rogue.col)) {
				continue;
			}

			if (mtry(monster, row, col)) {
				return(1);
			}
		}
	}
	return(1);
}

put_monster_rand_location(monster)
object *monster;
{
	short row, col;

	get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT));
	add_mask(row, col, MONSTER);
	monster->row = row;
	monster->col = col;

}

get_rand_obj_char()
{
	short r;
	char *rs = "%!?]/):*";

	r = get_rand(0, 7);

	return(rs[r]);
}

no_room_for_monster(rn)
{
	short i, j;

	for (i = rooms[rn].left_col+1; i < rooms[rn].right_col; i++) {
		for (j = rooms[rn].top_row+1; j < rooms[rn].bottom_row; j++) {
			if (!(screen[i][j] & MONSTER)) {
				return(0);
			}
		}
	}
	return(1);
}

aggravate()
{
	struct object *monster;

	message("you hear a high pitched humming noise");

	monster = level_monsters.next_object;

	while (monster) {
		wake_up(monster);
		if (monster->ichar == 'X') {
			monster->identified = 0;
		}
		monster = monster->next_object;
	}
}

monster_can_see(monster, row, col)
object *monster;
{
	short rn, rdif, cdif, retval;

	rn = get_room_number(row, col);

	if ((rn != NO_ROOM) && (rn ==
	    get_room_number(monster->row, monster->col))) {
		return(1);
	}
	rdif = row - monster->row;
	cdif = col - monster->col;

	retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
	return(retval);
}

mv_aquatars()
{
	object *monster;

	monster = level_monsters.next_object;

	while (monster) {
		if (monster->ichar == 'A') {
			mv_monster(monster, rogue.row, rogue.col);
		}
		monster = monster->next_object;
	}
}
SHAR_EOF
fi
if test -f 'monster.h'
then
	echo shar: "will not over-write existing file 'monster.h'"
else
cat << \SHAR_EOF > 'monster.h'
#define MONSTERS 53

#define HASTED ((unsigned short)001)
#define SLOWED ((unsigned short)002)
#define IS_INVIS ((unsigned short)004)
#define IS_ASLEEP ((unsigned short)010)
#define WAKENS ((unsigned short)020)
#define WANDERS ((unsigned short)040)
#define FLIES ((unsigned short)0100)
#define FLITS ((unsigned short)0200)
#define CAN_GO ((unsigned short)0400)

#define MAXMONSTER 53

#define WAKE_PERCENT 45
#define FLIT_PERCENT 33
#define PARTY_WAKE_PERCENT 75

#define AQUATAR1   7	/* levels in which the aquatar appears */
#define AQUATAR2  18
#define FLYTRAP1  14	/* levels in which the venus fly trap appears */
#define FLYTRAP2 126
#define ICEMSTR1   2	/* levels in which the ice monster appears */
#define ICEMSTR2  11
#define LEPCHAN1   6	/* levels in which the leprechan appears */
#define LEPCHAN2  16
#define NYMPH1     8	/* levels in which the nymph appears */
#define NYMPH2	  19
#define RSNAKE1	   3	/* levels in which the rattlesnake appears */
#define RSNAKE2   12
#define SPIDER1    1	/* levels in which the spider appears */
#define SPIDER2   11
#define VAMPIRE1  19	/* levels in which the vampire appears */
#define VAMPIRE2 126
#define WRAITH1   14	/* levels in which the wraith appears */
#define WRAITH2   28
#define XEROC1    16	/* levels in which the xeroc appears */
#define XEROC2    25

#define HYPOTHERMIA 1
#define STARVATION 2
#define QUIT 3
#define WIN 4

#define MAX_ODORS 6
#define B_FLAME 0
#define B_LIGHTNING 1
#define B_COLD 2
#define B_ACID 3
#define B_SLEEP 4
#define B_CONFUSION 5

SHAR_EOF
fi
if test -f 'move.c'
then
	echo shar: "will not over-write existing file 'move.c'"
else
cat << \SHAR_EOF > 'move.c'
#include curses.h
#include "object.h"
#include "room.h"
#include "move.h"
#include "monster.h"

extern short current_room, halluc, detect_monster, blind, being_held;
extern short confused, interrupted, has_amulet;
extern char *hunger_str;

single_move_rogue(dirch, pickup)
{
	short row, col;
	object *obj, *object_at(), *pick_up();
	char description[SCOLS];
	short n, status;

	row = rogue.row;
	col = rogue.col;

	if (being_held) {
		get_dir_rc(dirch, &row, &col);

		if (!(screen[row][col] & MONSTER)) {
			message("you are being held", 1);
			return(MOVE_FAILED);
		}
	}
	row = rogue.row;
	col = rogue.col;

	if (confused) {
		dirch = get_rand_dir();
	}

	switch(dirch) {
	case 'h':
		col--;
		break;
	case 'j':
		row++;
		break;
	case 'k':
		row--;
		break;
	case 'l':
		col++;
		break;
	case 'b':
		col--;
		row++;
		break;
	case 'y':
		col--;
		row--;
		break;
	case 'u':
		col++;
		row--;
		break;
	case 'n':
		col++;
		row++;
		break;
	}
	if (screen[row][col] & MONSTER) {
		rogue_hit(object_at(&level_monsters, row, col));
		register_move();
		return(MOVE_FAILED);
	}
	if (!can_move(rogue.row, rogue.col, row, col)) {
		return(MOVE_FAILED);
	}
	if (screen[row][col] & DOOR) {
		if (current_room == PASSAGE) {
			current_room = get_room_number(row, col);
			light_up_room();
			wake_room(current_room, 1, row, col);
		} else {
			light_passage(row, col);
		}
	} else if ((screen[rogue.row][rogue.col] & DOOR) &&
		   (screen[row][col] & TUNNEL)) {
		light_passage(row, col);
		wake_room(current_room, 0, row, col);
		darken_room(current_room);
		current_room = PASSAGE;
	} else if (screen[row][col] & TUNNEL) {
			light_passage(row, col);
	}
	mvaddch(rogue.row, rogue.col,
	get_room_char(screen[rogue.row][rogue.col], rogue.row, rogue.col));
	mvaddch(row, col, rogue.fchar);
	rogue.row = row; rogue.col = col;
	if (screen[row][col] & CAN_PICK_UP) {
		if (pickup) {
			if (obj = pick_up(row, col, &status)) {
				get_description(obj, description);
				if (obj->what_is == GOLD) {
					free(obj);
					goto NOT_IN_PACK;
				}
			} else if (!status) {
				goto MVED;
			} else {
				goto MOVE_ON;
			}
		} else {
MOVE_ON:		obj = object_at(&level_objects, row, col);
			strcpy(description, "moved onto ");
			get_description(obj, description+11);
			goto NOT_IN_PACK;
		}
		n = strlen(description);
		description[n] = '(';
		description[n+1] = obj->ichar;
		description[n+2] = ')';
		description[n+3] = 0;
NOT_IN_PACK:	message(description, 1);
		register_move();
		return(STOPPED_ON_SOMETHING);
	}
	if ((screen[row][col] & DOOR) || (screen[row][col] & STAIRS)) {
		register_move();
		return(STOPPED_ON_SOMETHING);
	}
MVED:	if (register_move()) {			/* fainted from hunger */
		return(STOPPED_ON_SOMETHING);
	}
	return((confused ? STOPPED_ON_SOMETHING : MOVED));
}

multiple_move_rogue(dirch)
{
	short row, col;
	short m;

	switch(dirch) {
	case '':
	case '\012':
	case '':
	case '':
	case '\031':
	case '\025':
	case '\016':
	case '\002':
		do {
			row = rogue.row;
			col = rogue.col;
			if (((m = single_move_rogue((dirch + 96), 1)) ==
			MOVE_FAILED) || (m == STOPPED_ON_SOMETHING) ||
			interrupted) {
				break;
			}
		} while (!next_to_something(row, col));
		break;
	case 'H':
	case 'J':
	case 'K':
	case 'L':
	case 'B':
	case 'Y':
	case 'U':
	case 'N':
		while (!interrupted &&
			single_move_rogue((dirch + 32), 1) == MOVED) ;
		break;
	}
}

is_passable(row, col)
{
	if ((row < MIN_ROW) || (row > (LINES - 2)) || (col < 0) ||
	    (col > (COLS-1))) {
		return(0);
	}
	return(screen[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS));
}

next_to_something(drow, dcol)
{
	short i, j, i_end, j_end, row, col;
	short pass_count = 0;

	if (confused) {
		return(1);
	}
	if (blind) {
		return(0);
	}
	i_end = (rogue.row < (LINES-2)) ? 1 : 0;
	j_end = (rogue.col < (COLS-1)) ? 1 : 0;

	for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
		for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
			if ((i == 0) && (j == 0)) continue;
			if (((rogue.row+i)==drow)&&((rogue.col+j)==dcol)) {
				continue;
			}
			if(screen[rogue.row+i][rogue.col+j]&(MONSTER|IS_OBJECT))return(1);
			if ((((i - j) == 1) || ((i - j) == -1)) &&
			(screen[rogue.row+i][rogue.col+j] & TUNNEL)) {
				if (++pass_count > 1) {
					return(1);
				}
			}
			row = rogue.row+i; col = rogue.col+j;
			if ((screen[row][col] & DOOR)||(is_object(row,col))) {
				if (i == 0 || j == 0) {
					return(1);
				}
			}
		}
	}
	return(0);
}

can_move(row1, col1, row2, col2) 
{
	if (!is_passable(row2, col2)) {
		return(0);
	}
	if ((row1 != row2) && (col1 != col2)) {
		if ((screen[row1][col1]&DOOR)||(screen[row2][col2]&DOOR)) {
			return(0);
		}
		if ((!screen[row1][col2]) || (!screen[row2][col1])) {
			return(0);
		}
	}
	return(1);
}

is_object(row, col)
{
	return(screen[row][col] & IS_OBJECT);
}

move_onto()
{
	short ch;
	short first_miss = 1;
	char getchartt();

	while (!is_direction(ch = getchartt())) {
		putchar(7);
		fflush(stdout);
		if (first_miss) {
			message("direction? ", 0);
			first_miss = 0;
		}
	}
	check_message();
	if (ch != CANCEL) {
		single_move_rogue(ch, 0);
	}
}

is_direction(c)
{
	return( (c == 'h') ||
		(c == 'j') ||
		(c == 'k') ||
		(c == 'l') ||
		(c == 'b') ||
		(c == 'y') ||
		(c == 'u') ||
		(c == 'n') ||
		(c == CANCEL)
		);
}

is_pack_letter(c)
{
	return(((c >= 'a') && (c <= 'z')) || (c == CANCEL) || (c == LIST));
}

check_hunger()
{
	short i, n;
	short fainted = 0;

	if (rogue.moves_left == HUNGRY) {
		hunger_str = "hungry";
		message(hunger_str, 0);
		print_stats();
	}
	if (rogue.moves_left == WEAK) {
		hunger_str = "weak";
		message(hunger_str, 0);
		print_stats();
	}
	if ((rogue.moves_left) <= FAINT) {
		if (rogue.moves_left == FAINT) {
			hunger_str = "faint";
			message(hunger_str, 1);
			print_stats();
		}
		n = get_rand(0, (FAINT - rogue.moves_left));
		if (n > 0) {
			fainted = 1;
			if (rand_percent(40)) rogue.moves_left++;
			message("you faint", 1);
			for (i = 0; i < n; i++) {
				if (rand_percent(50)) {
					move_monsters();
				}
			}
			message("you can move again", 1);
		}
	}
	if (rogue.moves_left <= STARVE) {
		killed_by(0, STARVATION);
	}
	rogue.moves_left--;
	return(fainted);
}

register_move()
{
	static short moves = 0;
	short fainted;

	if ((rogue.moves_left <= HUNGRY) || !has_amulet) {
		fainted = check_hunger();
	} else {
		fainted = 0;
	}

	move_monsters();

	if (++moves >= 80) {
		moves = 0;
		start_wanderer();
	}
	if (halluc) {
		if (!(--halluc)) {
			unhallucinate();
		} else {
			hallucinate();
		}
	}
	if (blind) {
		if (!(--blind)) {
			unblind();
		}
	}
	if (confused) {
		if (!(--confused)) {
			unconfuse();
		}
	}
	heal();

	return(fainted);
}

rest(count)
{
	int i;

	for (i = 0; i < count; i++) {
		if (interrupted) break;
		register_move();
	}
}

get_rand_dir()
{
	short d;

	d = get_rand(1, 8);

	switch(d) {
		case 1:
			return('j');
		case 2:
			return('k');
		case 3:
			return('l');
		case 4:
			return('h');
		case 5:
			return('y');
		case 6:
			return('u');
		case 7:
			return('b');
		case 8:
			return('n');
	}
}

heal()
{
	static short exp = -1, n, c = 0;

	if (rogue.exp != exp) {
		exp = rogue.exp;

		switch(exp) {
		case 1:
			n = 20;
			break;
		case 2:
			n = 18;
			break;
		case 3:
			n = 17;
			break;
		case 4:
			n = 14;
			break;
		case 5:
			n = 13;
			break;
		case 6:
			n = 10;
			break;
		case 7:
			n = 9;
			break;
		case 8:
			n = 8;
			break;
		case 9:
			n = 7;
			break;
		case 10:
			n = 4;
			break;
		case 11:
			n = 3;
			break;
		case 12:
		default:
			n = 2;
		}
	}
	if (rogue.hp_current == rogue.hp_max) {
		c = 0;
		return;
	}

	if (++c >= n) {
		c = 0;
		rogue.hp_current++;
		if (rogue.hp_current < rogue.hp_max) {
			if (rand_percent(50)) {
				rogue.hp_current++;
			}
		}
		print_stats();
	}
}
SHAR_EOF
fi
if test -f 'move.h'
then
	echo shar: "will not over-write existing file 'move.h'"
else
cat << \SHAR_EOF > 'move.h'
#define UP 0
#define UPRIGHT 1
#define RIGHT 2
#define RIGHTDOWN 3
#define DOWN 4
#define DOWNLEFT 5
#define LEFT 6
#define LEFTUP 7

#define ROW1 7
#define ROW2 15

#define COL1 26
#define COL2 52

#define MOVED 0
#define MOVE_FAILED -1
#define STOPPED_ON_SOMETHING -2
#define CANCEL '\033'
#define LIST '*'

#define HUNGRY 300
#define WEAK 120
#define FAINT 20
#define STARVE 0

#define MIN_ROW 1
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 
ihnp4--\                                        
decvax--\	
akgua----\
dcdwest---\
somewhere--\
ucbvax-------- sdcsvax -- rich