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

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

This is an extended version of the public domain version of rogue.
the game is slowly trying to look a bit like srogue. this version
will only run on vms systems. hacking io.c to death should make it
run on unix. like all public domain source do what you wish, just
dont sell it .
    enjoy,

		rich

#! /bin/sh
ihnp4--\                                        
decvax--\	
akgua----\
dcdwest---\
somewhere--\
ucbvax-------- sdcsvax -- rich
# 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:
#	doorcou.c
#	help.c
#	hit.c
#	init.c
#	inventor.c
#	io.c
#	level.c
# This archive created: Mon Aug  4 11:41:18 1986
# By:	rich ( lack of)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'doorcou.c'
then
	echo shar: "will not over-write existing file 'doorcou.c'"
else
cat << \SHAR_EOF > 'doorcou.c'
#include "object.h"
#include "monster.h"
#include "room.h"
#include "move.h"

door_course(monster, entering, row, col)
object *monster;
short entering, row, col;
{
	short trow, tcol, i, j, rn;
	short rrow, ccol;

	monster->row = row;
	monster->col = col;

	if (monster_can_see(monster, rogue.row, rogue.col)) {
		monster->trow = -1;
		return;
	}
	rn = get_room_number(row, col);

	if (entering) {		/* entering room */
		for (i = 0; i < MAXROOMS; i++) {
			if (!rooms[i].is_room || (i == rn)) continue;
			for (j = 0; j < 4; j++) {
				if (rooms[i].doors[j].other_room == rn) {
				monster->trow = rooms[i].doors[j].other_row;
				monster->tcol = rooms[i].doors[j].other_col;
				if ((monster->trow == row) &&
				    (monster->tcol == col)) {
					continue;
				}
				return;
				}
			}
		}
	} else {		/* exiting room */
		rrow = row;
		ccol = col;
		if (get_other_room(rn, &rrow, &ccol)) {
			monster->trow = rrow;
			monster->tcol = ccol;
		} else {
			monster->trow = -1;
		}
	}
}

get_other_room(rn, row, col)
short rn, *row, *col;
{
	short d = -1;

	if ((screen[*row][(*col)-1]&HORWALL)&&(screen[*row][(*col)+1]&HORWALL)){
		if (screen[(*row)+1][*col] & FLOOR) {
			d = UP/2;
		} else {
			d = DOWN/2;
		}
	} else {
		if (screen[*row][(*col)+1] & FLOOR) {
			d = LEFT/2;
		} else {
			d = RIGHT/2;
		}
	}
	if ((d != -1) && (rooms[rn].doors[d].other_room > 0)) {
		*row = rooms[rn].doors[d].other_row;
		*col = rooms[rn].doors[d].other_col;
		return(1);
	}
	return(0);
}
SHAR_EOF
fi
if test -f 'help.c'
then
	echo shar: "will not over-write existing file 'help.c'"
else
cat << \SHAR_EOF > 'help.c'
help(what)
int what;{

	switch(what){

	case '\003'  : message(" quit",1);
			break;
	case '.'     : message(" rest a turn",1);
			break;
	case 'i'     : message(" inventory rogue pack",1);
			break;
	case 'f'     : message(" fight",1);
			break;
	case 'F'     : message(" fight harder",1);
			break;
	case 'h'     : message(" move left",1);
			break;
	case 'j'     : message(" move down",1);
			break;
	case 'k'     : message(" move up",1);
			break;
	case 'l'     : message(" move right",1);
			break;
	case 'y'     : message(" move up and to the left",1);
			break;
	case 'u'     : message(" move up and to the right",1);
			break;
	case 'n'     : message(" move down and to the left",1);
			break;
	case 'b'     : message(" move down and to the right",1);
			break;
	case 'H'     : message(" run left",1);
			break;
	case 'J'     : message(" run down",1);
			break;
	case 'K'     : message(" run up",1);
			break;
	case 'L'     : message(" run right",1);
			break;
	case 'Y'     : message(" run up and to the left",1);
			break;
	case 'U'     : message(" run up and to the right",1);
			break;
	case 'N'     : message(" run down and to the left",1);
			break;
	case 'B'     : message(" run down and to the right",1);
			break;
	case '\010'  : message(" move left, until adjacent",1);
			break;
	case '\012'  : message(" move down, until adjacent",1);
			break;
	case '\013'  : message(" move up, until adjacent",1);
			break;
	case '\014'  : message(" move right, until adjacent",1);
			break;
	case '\031'  : message(" move up and to the left,until adjacent",1);
			break;
	case '\025'  : message(" move up and to the right,until adjacent",1);
			break;
	case '\006'  : message(" move down and to the left, until adjacent",1);
			break;
	case '\002'  : message(" move down and to the right,until adjacent",1);
			break;
	case 'e'     : message(" eat",1);
			break;
	case 'q'     : message(" quaff potion",1);
			break;
	case 'r'     : message(" read scroll",1);
			break;
	case 'm'     : message(" move onto",1);
			break;
	case 'd'     : message(" drop",1);
			break;
	case '\020'  : message(" recall last message",1);
			break;
	case '>'     : message(" go down stairs",1);
			break;
	case '<'     : message(" go up stairs",1);
			break;
	case 'I'     : message(" inventory a single item",1);
			break;
	case 'R'     : message(" redaw screen",1);
			break;
	case 'T'     : message(" take off armor",1);
			break;
	case 'W'     : message(" put on armor",1);
			break;
	case 'P'     : message(" put on armor",1);
			break;
	case 'w'     : message(" wield",1);
			break;
	case 'c'     : message(" call an item",1);
			break;
	case 'z'     : message(" zap a wand",1);
			break;
	case 't'     : message(" throw a weapon",1);
			break;
	case '\032'  : message(" suspend process ",1);
			break;
	case '!'     : message(" spawn a command",1);
			break;
	case 'v'     : message(" version number",1);
			break;
	case 'Q'     : message(" quit",1);
			break;
	case '/'     : message(" identify monster",1);
			break;
	case '?'     : message(" help on a command",1);
			break;
	default      : message(" Unknown command",1);
	}
}

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

object *fight_monster = 0;
short detect_monster;
char hit_message[80] = "";

extern short halluc, blind, being_held, interrupted;

monster_hit(monster, other)
register object *monster;
char *other;
{
	short damage, hit_chance;
	char *mn, *monster_name();
	float minus;

	if (fight_monster && (monster != fight_monster)) {
		fight_monster = 0;
	}
	monster->trow = -1;
	hit_chance = monster->class;
	hit_chance -= (rogue.exp + rogue.exp);
	if (rogue.armor) hit_chance -= 3*(rogue.armor->damage_enchantment);
	if (hit_chance < 0) hit_chance = 0;

	if (!fight_monster) {
		interrupted = 1;
	}

	mn = monster_name(monster);

	if (!rand_percent(hit_chance)) {
		if (!fight_monster) {
			sprintf(hit_message + strlen(hit_message),
			"the %s misses", (other ? other : mn));
			message(hit_message, 0);
			hit_message[0] = 0;
		}
		return;
	}
	if (!fight_monster) {
		sprintf(hit_message + strlen(hit_message), "the %s hit", (other ? other : mn));
		message(hit_message, 0);
		hit_message[0] = 0;
	}

	if (monster->ichar != 'F') {
	   damage = get_damage(monster->damage, 1);
	   if (rogue.armor) minus = (float) (rogue.armor->class * 3.00 
					     + rogue.armor->damage_enchantment);
	   minus = minus/100.00 * (float) damage;
	   damage -= (short) minus;
	} else {
		damage = monster->identified++;
	}
	if (damage > 0) {
		rogue_damage(damage, monster);
	}
	special_hit(monster);
}

rogue_hit(monster)
register object *monster;
{
	short damage, hit_chance;
	char mbuf[80], *monster_name();
	float minus;
	short cx;

	if (check_xeroc(monster)) {
		return;
	}
	hit_chance = get_hit_chance(rogue.weapon);

	if (!rand_percent(hit_chance)) {
		if (!fight_monster) {
			strcpy(hit_message, "you miss  ");
		}
		goto RET;
	}
	damage = get_weapon_damage(rogue.weapon);

	if (monster_damage(monster, damage)) {	/* still alive? */
		if (!fight_monster) {
			strcpy(hit_message, "you hit  ");
		}
	}
RET:	check_orc(monster);
	wake_up(monster);
}

rogue_damage(d, monster)
short d;
object *monster;
{
extern char *player_name;
static char byebye[80];

	if (d >= rogue.hp_current) {
		rogue.hp_current = 0;
		print_stats();
		killed_by(monster, 0);
	}

	rogue.hp_current -= d;
	print_stats();
	if (rogue.hp_current <  ((short)(rogue.hp_max*0.1+1))) {
		sprintf(byebye,"%s is about to die... ", player_name);
		message(byebye, 1);
	 }
}

get_damage(ds, r)
char *ds;
{
	register short i = 0, j, n, d, total = 0;

	while (ds[i]) {
		n = get_number(ds+i);
		while (ds[i++] != 'd') ;
		d = get_number(ds+i);
		while ((ds[i] != '/') && ds[i]) i++;

		for (j = 0; j < n; j++) {
			if (r) {
				total += get_rand(1, d);
			} else {
				total += d;
			}
		}
		if (ds[i] == '/') {
			i++;
		}
	}
	return(total);
}

get_w_damage(obj)
object *obj;
{
	char new_damage[12];
	register short to_hit, damage;
	register short i = 0;

	if (!obj) {
		return(-1);
	}
	to_hit = get_number(obj->damage) + obj->to_hit_enchantment;
	while (obj->damage[i++] != 'd') ;
	damage = get_number(obj->damage + i) + obj->damage_enchantment;

	sprintf(new_damage, "%dd%d", to_hit, damage);

	return(get_damage(new_damage, 1));
}

get_number(s)
register char *s;
{
	register short i = 0;
	register short total = 0;

	while ((s[i] >= '0') && (s[i] <= '9')) {
		total = (10 * total) + (s[i] - '0');
		i++;
	}
	return(total);
}

to_hit(obj)
object *obj;
{
	short tohit = 0;
	short i = 0;

	if (!obj) {
		return(1);
	}
	return(get_number(obj->damage) + obj->to_hit_enchantment);
}

damage_for_strength(s)
{
	if (s <= 6) {
		return(s-5);
	}
	if (s <= 14) {
		return(1);
	}
	if (s <= 17) {
		return(3);
	}
	if (s <= 18) {
		return(4);
	}
	if (s <= 20) {
		return(5);
	}
	if (s <= 21) {
		return(6);
	}
	if (s <= 30) {
		return(7);
	}
	return(8);
}

monster_damage(monster, damage)
object *monster;
{
	char *mn, *monster_name();
	short row, col;

	monster->quantity -= damage;

	if (monster->quantity <= 0) {
		row = monster->row;
		col = monster->col;
		remove_mask(row, col, MONSTER);
		mvaddch(row, col, get_room_char(screen[row][col]));
		refresh_vms();

		fight_monster = 0;
		cough_up(monster);
		mn = monster_name(monster);
		sprintf(hit_message+strlen(hit_message), "defeated the %s", mn);
		message(hit_message, 1);
		hit_message[0] = 0;
		add_exp(monster->kill_exp);
		print_stats();
		remove_from_pack(monster, &level_monsters);

		if (monster->ichar == 'F') {
			being_held = 0;
		}
		free(monster);
		return(0);
	}
	return(1);
}

fight(to_the_death)
short to_the_death;
{
	short ch;
	short row, col;
	short first_miss = 1;
	short possible_damage;
	object *object_at();

	while (!is_direction(ch = getchartt())) {
		putchar(7);
		fflush(stdout);
		if (first_miss) {
			message("direction?", 0);
			first_miss = 0;
		}
	}
	check_message();
	if (ch == CANCEL) {
		return;
	}
	row = rogue.row; col = rogue.col;
	get_dir_rc(ch, &row, &col);

	if (!(screen[row][col] & MONSTER) || blind || hiding_xeroc(row, col)) {
NM:		message("I see no monster there", 0);
		return;
	}
	fight_monster = object_at(&level_monsters, row, col);
	if ((fight_monster->m_flags & IS_INVIS) && !detect_monster) {
		goto NM;
	}

	possible_damage = ((get_damage(fight_monster->damage, 0) * 2) / 3);

	while (fight_monster) {
		single_move_rogue(ch, 0);
		if (!to_the_death && rogue.hp_current <= possible_damage) {
			fight_monster = 0;
		}
		if (!(screen[row][col] & MONSTER) || interrupted) {
			fight_monster = 0;
		}
	}
}

get_dir_rc(dir, row, col)
short dir;
short *row, *col;
{
	switch(dir) {
	case 'h':
		if (*col > 0) {
			(*col)--;
		}
		break;
	case 'j':
		if (*row < (LINES-2)) {
			(*row)++;
		}
		break;
	case 'k':
		if (*row > MIN_ROW) {
			(*row)--;
		}
		break;
	case 'l':
		if (*col < (COLS-1)) {
			(*col)++;
		}
		break;
	case 'y':
		if ((*row > MIN_ROW) && (*col > 0)) {
			(*row)--;
			(*col)--;
		}
		break;
	case 'u':
		if ((*row > MIN_ROW) && (*col < (COLS-1))) {
			(*row)--;
			(*col)++;
		}
		break;
	case 'n':
		if ((*row < (LINES-2)) && (*col < (COLS-1))) {
			(*row)++;
			(*col)++;
		}
		break;
	case 'b':
		if ((*row < (LINES-2)) && (*col > 0)) {
			(*row)++;
			(*col)--;
		}
		break;
	}
}

get_hit_chance(weapon)
object *weapon;
{
	short hit_chance;

	hit_chance = 40;
	hit_chance += 3 * to_hit(weapon);
	hit_chance += (rogue.exp + rogue.exp);
	if (hit_chance > 100) hit_chance = 100;
	return(hit_chance);
}

get_weapon_damage(weapon)
object *weapon;
{
	short damage;

	damage = get_w_damage(weapon);
	damage += damage_for_strength(rogue.strength_current);
	damage += ((rogue.exp + 1) / 2);
	return(damage);
}
SHAR_EOF
fi
if test -f 'init.c'
then
	echo shar: "will not over-write existing file 'init.c'"
else
cat << \SHAR_EOF > 'init.c'
#include stdio.h
#include curses.h
#include "object.h"
#include "room.h"

char player[32];
char *player_name;
short cant_int = 0, did_int = 0;

extern char ichars[];
extern short party_room;
extern short chan;
extern short AMULET_LEVEL;

init()
{
	char *cuserid(); 
	short i;
	int byebye();


	if (!(player_name = cuserid(player))) {
		fprintf(stderr, "Hey!  Who are you?");
		ttclose();
		exit(2);
		}
/*
 * cheat for now
 */
	printf("Hello %s, just a moment while I dig the dungeon...",
	player_name);
	fflush(stdout);
/*	lib$disable_ctrl(0x1000000, &old_mask); */
	ttopen();
	sleep(1); /* emulate Unix */

	initscr();
	for (i = 0; i < 26; i++) {
		ichars[i] = 0;
	}
	start_window();
	if ((LINES < 24) || (COLS < 80)) {
		clean_up("must be played on 24 x 80 screen");
	}
	LINES = SROWS;

	srand(time());
	shuffle_colors();
	mix_metals();
	make_scroll_titles();

	level_objects.next_object = 0;
	level_monsters.next_object = 0;
	player_init();
}

player_init()
{
	object *get_an_object(), *obj;

	rogue.pack.next_object = 0;

	obj = get_an_object();
	get_food(obj);
	add_to_pack(obj, &rogue.pack, 1);

	obj = get_an_object();		/* initial armor */
	get_rand_armor2(obj);
	obj->what_is = ARMOR;
	obj->identified = 1;
	add_to_pack(obj, &rogue.pack, 1);
	rogue.armor = obj;
	AMULET_LEVEL = get_rand(25,39) + obj->class;

	obj = get_an_object();		/* initial weapons */
	obj->what_is = WEAPON;
	get_rand_weapon2(obj);
	obj->identified = 1;
	add_to_pack(obj, &rogue.pack, 1);
	rogue.weapon = obj;

	obj = get_an_object();
	obj->what_is = WEAPON;
	obj->which_kind = SHORT_BOW;
	get_weapon_thd(obj);
	obj->is_cursed = 0;
	obj->damage = "1d8";
	obj->to_hit_enchantment = 1;
	obj->damage_enchantment = 0;
	obj->identified = 1;
	add_to_pack(obj, &rogue.pack, 1);

	obj = get_an_object();
	obj->what_is = WEAPON;
	obj->which_kind = ARROW;
	obj->quantity = get_rand(25, 35);
	get_weapon_thd(obj);
	obj->is_cursed = 0;
	obj->damage = "1d2";
	obj->to_hit_enchantment = 0;
	obj->damage_enchantment = 0;
	obj->identified = 1;
	add_to_pack(obj, &rogue.pack, 1);
}

clean_up(estr)
char *estr;
{
	move(LINES-1, 0);
	refresh_vms();
	stop_window();
	printf("\n%s\n", estr);
	ttclose();
	exit(1);
}

start_window()
{
	crmode();
	noecho();
	nonl();
}

stop_window()
{
	endwin();
}

byebye()
{
	clean_up("Okay, bye bye!");
}

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

char *metals[MAXMETALS] = {
	"steel ",
	"bronze ",
	"gold ",
	"silver ",
	"copper ",
	"nickel ",
	"cobalt ",
	"tin ",
	"iron ",
	"magnesium ",
	"chrome ",
	"carbon ",
	"platinum ",
	"silicon ",
	"titanium "
};

char *syllables[MAXSYLLABLES] = {
	"blech ",
	"foo ",
	"barf ",
	"rech ",
	"bar ",
	"blech ",
	"quo ",
	"bloto ",
	"woh ",
	"caca ",
	"blorp ",
	"erp ",
	"festr ",
	"rot ",
	"slie ",
	"snorf ",
	"iky ",
	"yuky ",
	"ooze ",
	"ah ",
	"bahl ",
	"zep ",
	"druhl ",
	"flem ",
	"behil ",
	"arek ",
	"mep ",
	"zihr ",
	"grit ",
	"kona ",
	"kini ",
	"ichi ",
	"niah ",
	"ogr ",
	"ooh ",
	"ighr ",
	"coph ",
	"swerr ",
	"mihln ",
	"poxi "
};

inventory(pack, mask)
object *pack;
unsigned short mask;
{
	object *obj;
	short i = 0, j, maxlen = 0, n;
	char descriptions[MAX_PACK_COUNT+1][SCOLS];
	short row, col;

	obj = pack->next_object;
	while (obj) {
		if (obj->what_is & mask) {
			descriptions[i][0] = ' ';
			descriptions[i][1] = obj->ichar;
			descriptions[i][2] = ')';
			descriptions[i][3] = ' ';
			get_description(obj, descriptions[i]+4);
			if ((n = strlen(descriptions[i])) > maxlen) {
				maxlen = n;
			}
		i++;
		}
		obj = obj->next_object;
	}
	strcpy(descriptions[i++], " --press space to continue--");
	if (maxlen < 27) maxlen = 27;
	col = COLS - (maxlen + 2);

	for (row = 0; ((row < i) && (row < SROWS)); row++) {
		if (row > 0) {
			for (j = col; j < COLS; j++) {
				descriptions[row-1][j-col] = mvinch(row, j);
			}
			descriptions[row-1][j-col] = 0;
		}
		mvaddstr(row, col, descriptions[row]);
		clrtoeol();
	}
	refresh_vms();
	wait_for_ack(0);

	move(0, 0);
	clrtoeol();

	for (j = 1; j < i; j++) {
		mvaddstr(j, col, descriptions[j-1]);
	}
}

shuffle_colors()
{
	short i, j, k;

	for (i = 0; i <= POTIONS; i++) {
		j = get_rand(0, (POTIONS - 1));
		k = get_rand(0, (POTIONS - 1));
		swap_string(id_potions[j].title, id_potions[k].title);
	}
}

make_scroll_titles()
{
	short i, j, n;
	short sylls, s;

	for (i = 0; i < SCROLLS; i++) {
		sylls = get_rand(2, 5);
		strcpy(id_scrolls[i].title, "'");

		for (j = 0; j < sylls; j++) {
			s = get_rand(1, (MAXSYLLABLES-1));
			strcat(id_scrolls[i].title, syllables[s]);
		}
		n = strlen(id_scrolls[i].title);
		strcpy(id_scrolls[i].title+(n-1), "' ");
	}
}

get_description(obj, description)
object *obj;
char *description;
{
	char *name_of(), *item_name;
	struct identify *id_table, *get_id_table();
	char more_info[32];

	if (obj->what_is == AMULET) {
		strcpy(description, "the amulet of Yendor ");
		return;
	}
	item_name = name_of(obj);

	if (obj->what_is == GOLD) {
		sprintf(description, "%d pieces of gold", obj->quantity);
		return;
	}

	if (obj->what_is != ARMOR) {
		if (obj->quantity == 1) {
			strcpy(description, "a ");
		} else {
			sprintf(description, "%d ", obj->quantity);
		}
	}
	if (obj->what_is == FOOD) {
		strcat(description, item_name);
		strcat(description, "of food ");
		return;
	}
	id_table = get_id_table(obj);

	if (obj->what_is & (WEAPON | ARMOR | WAND)) goto CHECK;

	switch(id_table[obj->which_kind].id_status) {
	case UNIDENTIFIED:
CHECK:		switch(obj->what_is) {
		case SCROLL:
			strcat(description, item_name);
			strcat(description, "entitled: ");
			strcat(description, id_table[obj->which_kind].title);
			break;
		case POTION:
			strcat(description, id_table[obj->which_kind].title);
			strcat(description, item_name);
			break;
		case WAND:
			if (obj->identified ||
			(id_table[obj->which_kind].id_status == IDENTIFIED)) {
				goto ID;
			}
			if (id_table[obj->which_kind].id_status == CALLED) {
				goto CALL;
			}
			strcat(description, id_table[obj->which_kind].title);
			strcat(description, item_name);
			break;
		case ARMOR:
			if (obj->identified) {
				goto ID;
			}
			strcpy(description, id_table[obj->which_kind].title);
			break;
		case WEAPON:
			if (obj->identified) {
				goto ID;
			}
			strcat(description, name_of(obj));
			if (obj == rogue.weapon) {
				strcat(description, "in hand");
			}
			break;
		}
		break;
	case CALLED:
CALL:		switch(obj->what_is) {
		case SCROLL:
		case POTION:
		case WAND:
			strcat(description, item_name);
			strcat(description, "called ");
			strcat(description, id_table[obj->which_kind].title);
			goto MI;
			break;
		}
		break;
	case IDENTIFIED:
ID:		switch(obj->what_is) {
		case SCROLL:
		case POTION:
			strcat(description, item_name);
			strcat(description, id_table[obj->which_kind].real);
			break;
		case WAND:
			strcat(description, item_name);
			strcat(description, id_table[obj->which_kind].real);
MI:			if (obj->identified) {
				sprintf(more_info, "[%d]", obj->class);
				strcat(description, more_info);
			}
			break;
		case ARMOR:
			sprintf(description, "%s%d ",
			((obj->damage_enchantment >= 0) ? "+" : ""),
			obj->damage_enchantment);
			strcat(description, id_table[obj->which_kind].title);
			sprintf(more_info, "[%d] ", get_armor_class(obj));
			strcat(description, more_info);
			if (obj == rogue.armor) {
				strcat(description, "being worn");
			}
			break;
		case WEAPON:
			sprintf(description+strlen(description), "%s%d,%s%d ",
			((obj->to_hit_enchantment >= 0) ? "+" : ""),
			obj->to_hit_enchantment,
			((obj->damage_enchantment >= 0) ? "+" : ""),
			obj->damage_enchantment);
			strcat(description, name_of(obj));
			if (obj == rogue.weapon) {
				strcat(description, "in hand");
			}
			break;
		}
		break;
	}
}

mix_metals()
{
	short i, j, k;

	for (i = 0; i <= MAXMETALS; i++) {
		j = get_rand(0, MAXMETALS-1);
		k = get_rand(0, MAXMETALS-1);
		swap_string(metals[j], metals[k]);
	}
	for (i = 0; i < WANDS; i++) {
		strcpy(id_wands[i].title, metals[i]);
	}
}

single_inventory()
{
	short ch;
	char description[SCOLS];
	object *obj, *get_letter_object();

	ch = get_pack_letter("inventory what? ", IS_OBJECT);

	if (ch == CANCEL) {
		return;
	}
	if (!(obj = get_letter_object(ch))) {
		message("No such item.", 0);
		return;
	}
	strcpy(description, "x) ");
	description[0] = ch;
	get_description(obj, description+3);
	message(description, 0);
}

struct identify *get_id_table(obj)
object *obj;
{
	switch(obj->what_is) {
	case SCROLL:
		return(id_scrolls);
		break;
	case POTION:
		return(id_potions);
		break;
	case WAND:
		return(id_wands);
		break;
	case WEAPON:
		return(id_weapons);
		break;
	case ARMOR:
		return(id_armors);
		break;
	}
}
SHAR_EOF
fi
if test -f 'io.c'
then
	echo shar: "will not over-write existing file 'io.c'"
else
cat << \SHAR_EOF > 'io.c'
/*
Hi Rich.  Here is the new io.c I told you about.  Now every character is
returned straight from the keyboard (except ^S and ^Q) so you don't need
the interrupt catching routines.  What you *do* need is to make sure that
every exit from the program is covered by the ttclose() routine, otherwise
you will end up in DCL without echo (you can just do a set term, but why?)
Anyway, I am slowly (after work) making some progress in improving the
game.  First, I wanted to split up the modules more naturally to make future
expansion easier (all potion effects in one module, all scroll effects in
another, etc.).  Anyway, pass any ideas along this way.  BTW, this account
will expire on 6/30/86 and will be replaced by 'donovan'.  My *own*
account is u557676751ea and will be up after 7/1.  Good luck!

                                                    - Mark Nagel

------------------------------- cut here ----------------------------------

*/

#include stsdef.h
#include ssdef.h
#include descrip.h
#include iodef.h
#include ttdef.h
#include tt2def.h
#include jpidef.h


#define	NIBUF	128			/* Size of input buffer */
#define	EFN	0			/* Event flag number */

char	ibuf[NIBUF];			/* Input buffer */
int	nibuf = 0;			/* # of bytes in above */
int	ibufi = 0;			/* Read index */
int	oldmode[3];			/* Old TTY mode bits */
int	newmode[3];			/* New TTY mode bits */
short	iochan;				/* TTY I/O channel */


void ttopen()
{
    struct dsc$descriptor	idsc;
    struct dsc$descriptor	odsc;
    char			oname[40];
    int				iosb[2];
    int				status;

    odsc.dsc$a_pointer = "SYS$INPUT";
    odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
    odsc.dsc$b_dtype   = DSC$K_DTYPE_T;
    odsc.dsc$b_class   = DSC$K_CLASS_S;
    idsc.dsc$b_dtype   = DSC$K_DTYPE_T;
    idsc.dsc$b_class   = DSC$K_CLASS_S;
    do {
        idsc.dsc$a_pointer = odsc.dsc$a_pointer;
        idsc.dsc$w_length  = odsc.dsc$w_length;
        odsc.dsc$a_pointer = &oname[0];
        odsc.dsc$w_length  = sizeof(oname);
        status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
        if (status != SS$_NORMAL && status != SS$_NOTRAN)
            exit(status);
            if (oname[0] == 0x1B) {
                odsc.dsc$a_pointer += 4;
                odsc.dsc$w_length  -= 4;
        }
    } while (status == SS$_NORMAL);
    status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
    if (status != SS$_NORMAL)
        exit(status);
    status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
                      oldmode, sizeof(oldmode), 0, 0, 0, 0);
    if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
        exit(status);
    newmode[0] = oldmode[0];		/* Only in version 4.	*/
    newmode[1] = oldmode[1] | TT$M_NOECHO | TT$M_TTSYNC;
    newmode[2] = oldmode[2] | TT2$M_PASTHRU;
    status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                      newmode, sizeof(newmode), 0, 0, 0, 0);
    if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
        exit(status);
}


char getchartt()
{
    int status;
    int iosb[2];
    int term[2];

    term[0] = 0;
    term[1] = 0;
    while (ibufi >= nibuf) {
        ibufi = 0;
        status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
                          iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
        if (status != SS$_NORMAL)
            continue;
        status = iosb[0] & 0xFFFF;
        if (status != SS$_NORMAL && status != SS$_TIMEOUT)
            continue;
        nibuf = (iosb[0]>>16) + (iosb[1]>>16);
        if (nibuf == 0) {
            status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
                              iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
        if (status != SS$_NORMAL)
            continue;
        if ((iosb[0]&0xFFFF) != SS$_NORMAL)
            continue;
        nibuf = (iosb[0]>>16) + (iosb[1]>>16);
        }
    }
    if (ibuf[ibufi] == '\r')
        ibuf[ibufi] = '\n';
    return (ibuf[ibufi++]);
}


void ttclose()
{
    int status;
    int iosb[1];

    status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                      oldmode, sizeof(oldmode), 0, 0, 0, 0);
    if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL)
        exit(status);
    status = SYS$DASSGN(iochan);
    if (status != SS$_NORMAL)
        exit(status);
}


spawn_command(command)
char *command;
{

    struct dsc$descriptor descr_command;
               
    /*
     * make the character strings
     */
               
    char the_command[40];

    if((!strcmp("sh",command)) || command[0]=='!' || command[0]=='\0'){

        lib$spawn(0,0,0,0,0,0,0,0,0,0,0,0);
	return;
    }

    sprintf(the_command,"%s",command);
                
    /*
     * Give descriptors the number of printable ascii  
     * characters
     */
                
    descr_command.dsc$w_length=strlen(the_command);
            
    /*
     * Give descriptors the addresses of the strings
     */
            
    descr_command.dsc$a_pointer=the_command;
                    
    /*
     * Define the string descriptor class
     */
             
    descr_command.dsc$b_class=DSC$K_CLASS_S;
                    
    /*
     * Explain that it is an ascii string.
     */
             
    descr_command.dsc$b_dtype=DSC$K_DTYPE_T;


    lib$spawn(&descr_command,0,0,0,0,0,0,0,0,0,0,0);

}


/*
 * this is here because vms curses sucks.
 * the curser was following hidden monsters about.
 */

#include curses
refresh_vms()
{
    static int old_x,old_y;
    static int odd=0;

    getyx(stdscr,old_y,old_x);
    move(LINES -2,COLS-1);
    if (odd == 0){
        odd = 1;
        addch(' ');
    } else {
        odd = 0;
        addch('.');
    } 
    refresh();
    move(old_y,old_x);
}



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

short current_level = 0, max_level = 1;
extern short AMULET_LEVEL;
extern short current_room;
char *hunger_str = "";
short party_room;
extern short being_held;
extern short detect_monster, has_amulet;

int level_points[] = {
	      10,
	      20,
	      40,
	      80,
	     160,
	     320,
	     640,
	    1300,
	    2600,
	    5200,
	   10000,
	   20000,
	   40000,
	   80000,
	  160000,
	  320000,
	 1000000,
	10000000
};

make_level()
{
	short i;
	short must_exist1, must_exist2;

	party_room = -1;

	if (current_level < 126) {
		current_level++;
	}
	if (current_level > max_level) max_level = current_level;

	if (rand_percent(50)) {
		must_exist1 = 1;
		must_exist2 = 7;
	} else {
		must_exist1 = 3;
		must_exist2 = 5;
	}

	for (i = 0; i < MAXROOMS; i++) {
		make_room(i, must_exist1, must_exist2, 4);
	}

	try_rooms(0, 1, 2);
	try_rooms(0, 3, 6);
	try_rooms(2, 5, 8);
	try_rooms(6, 7, 8);

	for (i = 0; i < (MAXROOMS); i++) {
		connect_rooms(i, i+1, must_exist1, must_exist2, 4);
		if (i < (MAXROOMS-3)) {
			connect_rooms(i, i+3, must_exist1, must_exist2, 4);
		}
	}
	add_dead_ends();

	if (!has_amulet && (current_level >= AMULET_LEVEL)) {
		put_amulet();
	}
}

make_room(n, r1, r2, r3)
{
	short left_col, right_col, top_row, bottom_row;
	short width, height;
	short row_offset, col_offset;
	short i, j;
	short ch;

	switch(n) {
	case 0:
		left_col = 0;
		right_col = COL1-1;
		top_row = MIN_ROW;
		bottom_row = ROW1-1;
		break;
	case 1:
		left_col = COL1+1;
		right_col = COL2-1;
		top_row = MIN_ROW;
		bottom_row = ROW1-1;
		break;
	case 2:
		left_col = COL2+1;
		right_col = COLS-1;
		top_row = MIN_ROW;
		bottom_row = ROW1-1;
		break;
	case 3:
		left_col = 0;
		right_col = COL1-1;
		top_row = ROW1+1;
		bottom_row = ROW2-1;
		break;
	case 4:
		left_col = COL1+1;
		right_col = COL2-1;
		top_row = ROW1+1;
		bottom_row = ROW2-1;
		break;
	case 5:
		left_col = COL2+1;
		right_col = COLS-1;
		top_row = ROW1+1;
		bottom_row = ROW2-1;
		break;
	case 6:
		left_col = 0;
		right_col = COL1-1;
		top_row = ROW2+1;
		bottom_row = LINES - 2;
		break;
	case 7:
		left_col = COL1+1;
		right_col = COL2-1;
		top_row = ROW2+1;
		bottom_row = LINES - 2;
		break;
	case 8:
		left_col = COL2+1;
		right_col = COLS-1;
		top_row = ROW2+1;
		bottom_row = LINES - 2;
		break;
	}

	if ((n != r1) && (n != r2) && (n != r3) && rand_percent(45)) {
		goto END;
	}
	height = get_rand(4, (bottom_row-top_row+1));
	width = get_rand(7, (right_col-left_col-2));

	row_offset = get_rand(0, ((bottom_row-top_row)-height+1));
	col_offset = get_rand(0, ((right_col-left_col)-width+1));

	top_row += row_offset;
	bottom_row = top_row + height - 1;

	left_col += col_offset;
	right_col = left_col + width - 1;

	rooms[n].is_room = 1;

	for (i = top_row; i <= bottom_row; i++) {
		for (j = left_col; j <= right_col; j++) {
			if ((i == top_row) || (i == bottom_row)) {
				ch = HORWALL;
			} else if (((i != top_row) && (i != bottom_row)) &&
			((j == left_col) || (j == right_col))) {
				ch = VERTWALL;
			} else {
				ch = FLOOR;
			}
			add_mask(i, j, ch);
		}
	}
END:	rooms[n].top_row = top_row;
	rooms[n].bottom_row = bottom_row;
	rooms[n].left_col = left_col;
	rooms[n].right_col = right_col;
	rooms[n].height = height;
	rooms[n].width = width;
}

connect_rooms(room1, room2, m1, m2, m3)
{
	if ((room1 != m1) && (room1 != m2) && (room1 != m3) && (room2 != m1) &&
	    (room2 != m2) && (room2 != m3)) {
		if (rand_percent(80)) {
			return;
		}
	}

	if (adjascent(room1, room2)) {
		do_connect(room1, room2);
	}
}

do_connect(room1, room2)
{
	short row1, col1, row2, col2, dir;

	if ((rooms[room1].left_col > rooms[room2].right_col) &&
	(on_same_row(room1, room2))) {
		put_door(room1, LEFT, &row1, &col1);
		put_door(room2, RIGHT, &row2, &col2);
		dir = LEFT;
	} else if ((rooms[room2].left_col > rooms[room1].right_col) &&
	(on_same_row(room1, room2))) {
		put_door(room1, RIGHT, &row1, &col1);
		put_door(room2, LEFT, &row2, &col2);
		dir = RIGHT;
	} else if ((rooms[room1].top_row > rooms[room2].bottom_row) &&
	(on_same_col(room1, room2))) {
		put_door(room1, UP, &row1, &col1);
		put_door(room2, DOWN, &row2, &col2);
		dir = UP;
	} else if ((rooms[room2].top_row > rooms[room1].bottom_row) &&
	(on_same_col(room1, room2))) {
		put_door(room1, DOWN, &row1, &col1);
		put_door(room2, UP, &row2, &col2);
		dir = DOWN;
	} else {
		return;
	}
	draw_simple_passage(row1, col1, row2, col2, dir);
	if (rand_percent(10)) {
		draw_simple_passage(row1, col1, row2, col2, dir);
	}
	rooms[room1].doors[dir/2].other_room = room2;
	rooms[room1].doors[dir/2].other_row = row2;
	rooms[room1].doors[dir/2].other_col = col2;

	rooms[room2].doors[(((dir+4)%8)/2)].other_room = room1;
	rooms[room2].doors[(((dir+4)%8)/2)].other_row = row1;
	rooms[room2].doors[(((dir+4)%8)/2)].other_col = col1;
}

clear_level()
{
	int i, j;

	for (i = 0; i < MAXROOMS; i++) {
		rooms[i].is_room = 0;
		for (j = 0; j < 4; j++) {
			rooms[i].doors[j].other_room = NO_ROOM;
		}
	}
	for (i = 0; i < SROWS; i++) {
		for (j = 0; j < SCOLS; j++) {
			screen[i][j] = BLANK;
		}
	}
	detect_monster = 0;
	being_held = 0;
}

print_stats()
{
	char mbuf[100];

	sprintf(mbuf, 
	"Level: %d  Gold: %3d  Hp: %2d(%d)  Str: %2d(%d)  Arm: %2d  Exp: %d/%d %s", 
	current_level, rogue.gold, rogue.hp_current, rogue.hp_max, rogue.strength_current, 
	rogue.strength_max, get_armor_class(rogue.armor), rogue.exp, rogue.exp_points,
    hunger_str);
	mvaddstr(LINES-1, 0, mbuf);
	clrtoeol();
	refresh_vms();
}

add_mask(row, col, mask)
int row, col;
unsigned short mask;
{
	if (mask == DOOR) {
		remove_mask(row, col, HORWALL);
		remove_mask(row, col, VERTWALL);
	}
	screen[row][col] |= mask;
/*switch(mask) {
	case FLOOR:
		mvaddch(row, col, '.');
		break;
	case STAIRS:
		mvaddch(row, col, '%');
		break;
	case DOOR:
		mvaddch(row, col, '+');
		break;
	case VERTWALL:
		mvaddch(row, col, '|');
		break;
	case HORWALL:
		mvaddch(row, col, '-');
		break;
	case TUNNEL:
		mvaddch(row, col, '#');
		break;
}*/
}

remove_mask(row, col, mask)
{
	screen[row][col] &= (~mask);
}

adjascent(room1, room2)
{
	if ((!rooms[room1].is_room) || (!rooms[room2].is_room)) {
		return(0);
	}
	two_sort(room1, room2);
	return((on_same_col(room1,room2) || on_same_row(room1, room2))
	&& (((room2 - room1) == 1) || (((room2 - room1) == 3))));
}

put_door(rn, dir, row, col)
short *row, *col;
{
	switch(dir) {
	case UP:
	case DOWN:
		*row = ((dir == UP) ? rooms[rn].top_row :
				     rooms[rn].bottom_row);
		*col = get_rand(rooms[rn].left_col+1,
		rooms[rn].right_col-1);
		break;
	case RIGHT:
	case LEFT:
		*row = get_rand(rooms[rn].top_row+1,
		rooms[rn].bottom_row-1);
		*col = (dir == LEFT) ? rooms[rn].left_col :
				     rooms[rn].right_col;
		break;
	}
	add_mask(*row, *col, DOOR);
}

draw_simple_passage(row1, col1, row2, col2, dir)
{
	short i, middle;

	if ((dir == LEFT) || (dir == RIGHT)) {
		if (col2 < col1) {
			swap(row1, row2);
			swap(col1, col2);
		}
		middle = get_rand(col1+1, col2-1);
		for (i = col1+1; i != middle; i++) {
			add_mask(row1, i, TUNNEL);
		}
		for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) {
			add_mask(i, middle, TUNNEL);
		}
		for (i = middle; i != col2; i++) {
			add_mask(row2, i, TUNNEL);
		}
	} else {
		if (row2 < row1) {
			swap(row1, row2);
			swap(col1, col2);
		}
		middle = get_rand(row1+1, row2-1);
		for (i = row1+1; i != middle; i++) {
			add_mask(i, col1, TUNNEL);
		}
		for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) {
			add_mask(middle, i, TUNNEL);
		}
		for (i = middle; i != row2; i++) {
			add_mask(i, col2, TUNNEL);
		}
	}
}

on_same_row(room1, room2)
{
	return((room1 / 3) == (room2 / 3));
}

on_same_col(room1, room2)
{
	return((room1 % 3) == (room2 % 3));
}

add_dead_ends()
{
	short i, j;
	short start;
	short row, col, distance, dir;
	short found;
	short dead_end_percent;

	if (current_level <= 2) return;

	start = get_rand(0, (MAXROOMS-1));
	dead_end_percent = 12 + current_level + current_level;

	for (i = 0; i < MAXROOMS; i++) {
		j = ((start + i) % MAXROOMS);
		if (rooms[j].is_room) continue;
		if (!rand_percent(dead_end_percent)) continue;

		row = rooms[j].top_row + get_rand(0, 6);
		col = rooms[j].left_col + get_rand(0, 19);

		found = 0;
		while (!found) {
			distance = get_rand(8, 20);
			dir = get_rand(0, 3) * 2;

			for (j = 0; (j < distance) && !found; j++) {
				switch(dir) {
				case UP:
					if ((row - 1) >= MIN_ROW) {
						--row;
					}
					break;
				case RIGHT:
					if ((col + 1) < (COLS-1)) {
						++col;
					}
					break;
				case DOWN:
					if ((row + 1) < (LINES-2)) {
						++row;
					}
					break;
				case LEFT:
					if ((col - 1) > 0) {
						--col;
					}
					break;
				}
				if ((screen[row][col] & VERTWALL) ||
				(screen[row][col] & HORWALL) ||
				(screen[row][col] & DOOR)) {
					break_in(row, col, screen[row][col],
					dir);
					found = 1;
				} else {
					add_mask(row, col, TUNNEL);
				}
			}
		}
	}
}

break_in(row, col, ch, dir)
{
	short rn;
	short i, drow, dcol;

	if (ch == DOOR) {
		return;
	}
	rn = get_room_number(row, col);

	if (ch == VERTWALL) {
		if (col == rooms[rn].left_col) {
			if (rooms[rn].doors[LEFT/2].other_room != NO_ROOM) {
				drow = door_row(rn, LEFT);
				for (i = row; i != drow;
				i += (drow < row) ? -1 : 1) {
					add_mask(i, col-1, TUNNEL);
				}
			} else {
				rooms[rn].doors[LEFT/2].other_room = DEAD_END;
				add_mask(row, col, DOOR);
			}
		} else {
			if (rooms[rn].doors[RIGHT/2].other_room != NO_ROOM) {
				drow = door_row(rn, RIGHT);
				for (i = row; i != drow;
				i += (drow < row) ? -1 : 1) {
					add_mask(i, col+1, TUNNEL);
				}
			} else {
				rooms[rn].doors[RIGHT/2].other_room = DEAD_END;
				add_mask(row, col, DOOR);
			}
		}
	} else {		/* break in througt top or bottom --- */
		if (col == rooms[rn].left_col) {
			if (row == MIN_ROW) {
				add_mask(row+1, col-1, TUNNEL);
				break_in(row+1, col, VERTWALL, RIGHT);
			} else if (row == (LINES-2)) {
				add_mask(row-1, col-1, TUNNEL);
				break_in(row-1, col, VERTWALL, RIGHT);
			} else {
				if (row == rooms[rn].top_row) {
					if (dir == RIGHT) {
						add_mask(row-1, col-1, TUNNEL);
						add_mask(row-1, col, TUNNEL);
					}
					add_mask(row-1, col+1, TUNNEL);
					break_in(row, col+1, HORWALL, DOWN);
				} else {
					if (dir == RIGHT) {
						add_mask(row+1, col-1, TUNNEL);
						add_mask(row+1, col, TUNNEL);
					}
					add_mask(row+1, col+1, TUNNEL);
					break_in(row, col+1, HORWALL, UP);
				}
			}
			return;
		} else if (col == rooms[rn].right_col) {
			if (row == MIN_ROW) {
				add_mask(row+1, col+1, TUNNEL);
				break_in(row+1, col, VERTWALL, LEFT);
			} else if (row == (LINES-2)) {
				add_mask(row-1, col+1, TUNNEL);
				break_in(row-1, col, VERTWALL, LEFT);
			} else {
				if (row == rooms[rn].top_row) {
					if (dir == DOWN) {
						add_mask(row-1, col+1, TUNNEL);
						add_mask(row, col+1, TUNNEL);
					}
					add_mask(row+1, col+1, TUNNEL);
					break_in(row+1, col, VERTWALL, LEFT);
				} else {
					if (dir == UP) {
						add_mask(row+1, col+1, TUNNEL);
						add_mask(row, col+1, TUNNEL);
					}
					add_mask(row-1, col+1, TUNNEL);
					break_in(row-1, col, VERTWALL, LEFT);
				}
			}
			return;
		}
		if (row == rooms[rn].top_row) {
			if (rooms[rn].doors[UP/2].other_room != NO_ROOM) {
				dcol = door_col(rn, UP);
				for (i = col; i != dcol;
				i += (dcol < col) ? -1 : 1) {
					add_mask(row-1, i, TUNNEL);
				}
			} else {
				rooms[rn].doors[UP/2].other_room = DEAD_END;
				add_mask(row, col, DOOR);
			}
		} else {
			if (rooms[rn].doors[DOWN/2].other_room != NO_ROOM) {
				dcol = door_col(rn, DOWN);
				for (i = col; i != dcol;
				i += (dcol < col) ? -1 : 1) {
					add_mask(row+1, i, TUNNEL);
				}
			} else {
				rooms[rn].doors[DOWN/2].other_room = DEAD_END;
				add_mask(row, col, DOOR);
			}
		}
	}
	return(0);
}

door_row(rn, dir)
{
	short i, col, row;

	if (rooms[rn].doors[dir/2].other_room == NO_ROOM) {
		return(-1);
	}

	row = rooms[rn].top_row;

	switch(dir) {
	case LEFT:
		col = rooms[rn].left_col;
		for (i = row; !(screen[i][col] & DOOR); i++) ;
		break;
	case RIGHT:
		col = rooms[rn].right_col;
		for (i = row; !(screen[i][col] & DOOR); i++) ;
		break;
	}
	return(i);
}

door_col(rn, dir)
{
	short i, col, row;

	if (rooms[rn].doors[dir/2].other_room == NO_ROOM) {
		return(-1);
	}

	col = rooms[rn].left_col;

	switch(dir) {
	case UP:
		row = rooms[rn].top_row;
		for (i = col; !(screen[row][i] & DOOR); i++) ;
		break;
	case DOWN:
		row = rooms[rn].bottom_row;
		for (i = col; !(screen[row][i] & DOOR); i++) ;
		break;
	}
	return(i);
}

put_player()
{
	for (;;) {
		get_rand_row_col(&rogue.row, &rogue.col, (FLOOR | IS_OBJECT));

		current_room = get_room_number(rogue.row, rogue.col);

		if (current_room != party_room) {
			break;
		}
	}
}

check_down()
{
	if (screen[rogue.row][rogue.col] & STAIRS) {
		return(1);
	}
	message("I see no way down", 0);
	return(0);
}

check_up()
{
	if (!(screen[rogue.row][rogue.col] & STAIRS)) {
		message("I see no way up", 0);
		return(0);
	}
	if (!has_amulet) {
		message("your way is magically blocked", 0);
		return(0);
	}
	if (current_level == 1) {
		win();
	} else {
		current_level -= 2;
		return(1);
	}
}

add_exp(e)
{
	char mbuf[40];
	short new_exp;
	short i, hp;

	if (rogue.exp_points < MAX_EP)
	{
	   rogue.exp_points += e;

	   if (rogue.exp_points >= level_points[rogue.exp-1]) {
		new_exp = get_exp_level(rogue.exp_points);
		for (i = rogue.exp+1; i <= new_exp; i++) {
			sprintf(mbuf, "welcome to level %d", i);
			message(mbuf, 0);
			hp = get_rand(3, 10);
			rogue.hp_current += hp;
			rogue.hp_max += hp;
			print_stats();
		}
		rogue.exp = new_exp;
	   }
	}
	if (rogue.exp_points > MAX_EP) rogue.exp_points = MAX_EP;
	print_stats();
}

get_exp_level(e)
{
	short i;

	for (i = 0; i < 50; i++) {
		if (level_points[i] > e) {
			break;
		}
	}
	return(i+1);
}

try_rooms(r1, r2, r3)
{
	if (rooms[r1].is_room && !rooms[r2].is_room && rooms[r3].is_room) {
		if (rand_percent(75)) {
			do_connect(r1, r3);
		}
	}
}
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 
ihnp4--\                                        
decvax--\	
akgua----\
dcdwest---\
somewhere--\
ucbvax-------- sdcsvax -- rich