[comp.sources.games] v07i075: NetHack3 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 75
Archive-name: NetHack3/Part20



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 20 (of 38)."
# Contents:  include/attrib.h src/lev_comp.y src/mklev.c
# Wrapped by billr@saab on Sun Jul 23 21:33:03 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'include/attrib.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'include/attrib.h'\"
else
echo shar: Extracting \"'include/attrib.h'\" \(786 characters\)
sed "s/^X//" >'include/attrib.h' <<'END_OF_FILE'
X/*
X *	attrib.h - Header file for character class processing.
X *
X *	Copyright 1988, M. Stephenson
X */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#ifndef ATTRIB_H
X#define ATTRIB_H
X
X#define	A_STR	0
X#define	A_INT	1
X#define	A_WIS	2
X#define	A_DEX	3
X#define	A_CON	4
X#define	A_CHA	5
X
X#define A_MAX	6	/* used in rn2() selection of attrib */
X
X#define	ABASE(x)	(u.acurr.a[x])
X#define ABON(x)		(u.abon.a[x])
X#define ACURR(x)	(schar) acurr(x)
X/* should be: */
X/* #define	ACURR(x)	(ABON(x) + ATEMP(x) + (u.umonnum == -1) ? ABASE(x) : MBASE(x)) */
X#define	MCURR(x)	(u.macurr.a[x])
X#define	AMAX(x)		(u.amax.a[x])
X#define	MMAX(x)		(u.mamax.a[x])
X
X#define	ATEMP(x)	(u.atemp.a[x])
X#define	ATIME(x)	(u.atime.a[x])
X
Xstruct	attribs {
X
X	schar	a[A_MAX];
X};
X
X#endif /* ATTRIB_H /* */
END_OF_FILE
if test 786 -ne `wc -c <'include/attrib.h'`; then
    echo shar: \"'include/attrib.h'\" unpacked with wrong size!
fi
# end of 'include/attrib.h'
fi
if test -f 'src/lev_comp.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/lev_comp.y'\"
else
echo shar: Extracting \"'src/lev_comp.y'\" \(23359 characters\)
sed "s/^X//" >'src/lev_comp.y' <<'END_OF_FILE'
X%{ 
X/*	SCCS Id: @(#)lev_comp.c	3.0	89/07/02
X/*	Copyright (c) 1989 by Jean-Christophe Collet */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/*
X * This file contains the Level Compiler code
X * It may handle special mazes & special room-levels
X */
X
X/* block some unused #defines to avoid overloading some cpp's */
X#define MONDATA_H
X#include "hack.h"
X#include "sp_lev.h"
X#include <fcntl.h>
X
X#ifdef AMIGA
Xchar *fgets();
X# define    alloc   malloc
X# undef     fopen
X# undef     printf
X# undef     Printf
X# define    Printf  printf
X# define    memset(addr,val,len)    setmem(addr,len,val)
X#endif
X
X#ifdef MSDOS
X# undef exit
X#endif
X
X#define MAX_REGISTERS	10
X#define ERR		(-1)
X
Xstruct reg {
X	int x1, y1;
X	int x2, y2;
X}		current_region;
X
Xstruct coord {
X	int x;
X	int y;
X}		current_coord;
X
Xstruct {
X	char *name;
X	short type;
X} trap_types[TRAPNUM-1] = {
X	"monster",	MONST_TRAP,
X	"statue",	STATUE_TRAP,
X	"bear",		BEAR_TRAP,
X	"arrow",	ARROW_TRAP,
X	"dart",		DART_TRAP,
X	"trapdoor",	TRAPDOOR,
X	"teleport",	TELEP_TRAP,
X	"pit",		PIT,
X	"sleeping gas",	SLP_GAS_TRAP,
X	"magic",	MGTRP,
X	"board",	SQBRD,
X	"web",		WEB,
X	"spiked pit",	SPIKED_PIT,
X	"level teleport",LEVEL_TELEP,
X#ifdef SPELLS
X	"anti magic",	ANTI_MAGIC,
X#endif
X	"rust",		RUST_TRAP
X#ifdef POLYSELF
X	, "polymorph",	POLY_TRAP
X#endif
X#ifdef ARMY
X	, "land mine",	LANDMINE
X#endif
X  };
X
Xstruct {
X	char *name;
X	int type;
X} room_types[SHOPBASE-1] = {
X	/* for historical reasons, room types are not contiguous numbers */
X	/* (type 1 is skipped) */
X	"ordinary",	OROOM,
X#ifdef THRONES
X	"throne",	COURT,
X#endif
X	"swamp",	SWAMP,
X	"vault",	VAULT,
X	"beehive",	BEEHIVE,
X	"morgue",	MORGUE,
X#ifdef ARMY
X	"barracks",	BARRACKS,
X#endif
X	"zoo",		ZOO,
X	"temple",	TEMPLE,
X	"shop",		SHOPBASE,
X};
X
Xshort db_dirs[4] = {
X	DB_NORTH,
X	DB_EAST,
X	DB_SOUTH,
X	DB_WEST
X};
X
X#ifdef ALTARS
Xstatic altar *tmpaltar[256];
X#endif /* ALTARS /**/
Xstatic lad *tmplad[256];
Xstatic dig *tmpdig[256];
Xstatic char *tmpmap[ROWNO];
Xstatic region *tmpreg[16];
Xstatic door *tmpdoor[256];
Xstatic trap *tmptrap[256];
Xstatic monster *tmpmonst[256];
Xstatic object *tmpobj[256];
Xstatic drawbridge *tmpdb[256];
Xstatic walk *tmpwalk[256];
Xstatic mazepart *tmppart[10];
Xstatic room *tmproom[MAXNROFROOMS];
Xstatic specialmaze maze;
X
Xstatic char olist[MAX_REGISTERS], mlist[MAX_REGISTERS];
Xstatic struct coord plist[MAX_REGISTERS];
Xstatic int n_olist = 0, n_mlist = 0, n_plist = 0;
X
Xunsigned int nreg = 0, ndoor = 0, ntrap = 0, nmons = 0, nobj = 0;
Xunsigned int ndb = 0, nwalk = 0, npart = 0, ndig = 0, nlad = 0;
X#ifdef ALTARS
Xunsigned int naltar = 0;
X#endif /* ALTARS /*/
X
Xunsigned int max_x_map, max_y_map;
X
Xextern int fatal_error;
Xextern char* fname;
X
Xboolean check_monster_char(), check_object_char();
Xvoid scan_map(), store_part(), write_maze();
X
X%}
X
X%union
X{
X	int	i;
X	char*	map;
X}
X
X
X%token	<i> CHAR INTEGER
X%token	<i> MAZE_ID LEVEL_ID GEOMETRY_ID
X%token	<i> OBJECT_ID MONSTER_ID TRAP_ID DOOR_ID DRAWBRIDGE_ID MAZEWALK_ID
X%token	<i> REGION_ID RANDOM_OBJECTS_ID RANDOM_MONSTERS_ID RANDOM_PLACES_ID
X%token	<i> ALTAR_ID LADDER_ID NON_DIGGABLE_ID ROOM_ID 
X%token	<i> DOOR_STATE LIGHT_STATE
X%token	<i> DIRECTION RANDOM_TYPE O_REGISTER M_REGISTER P_REGISTER A_REGISTER
X%token	<i> ALIGNMENT LEFT_OR_RIGHT CENTER TOP_OR_BOT ALTAR_TYPE UP_OR_DOWN
X%token  <i> ',' ':' '(' ')' '[' ']'
X%token	<map> STRING MAP_ID
X%type	<map> string maze_def m_name o_name
X%start	file
X
X%%
Xfile		: /* notthing */
X		| levels ;
X
Xlevels		: level
X		| levels level ;
X
Xlevel		: maze_level ;
X
Xmaze_level	: maze_def regions
X		  {
X			  int fout, i;
X
X			  if (fatal_error > 0)
X				  fprintf(stderr,"%s : %d errors detected. No output created!\n", fname, fatal_error);
X			  else {
X				  fout = open($1, O_WRONLY | O_CREAT
X#ifdef MSDOS
X					      | O_BINARY
X#endif /* MSDOS */
X					      , 0644);
X				  if (fout < 0) {
X					  yyerror("Can't open output file!!");
X					  exit(1);
X				  }
X				  maze.numpart = npart;
X				  maze.parts = (mazepart**) alloc(sizeof(mazepart*)*npart);
X				  for(i=0;i<npart;i++)
X				      maze.parts[i] = tmppart[i];
X				  write_maze(fout, &maze);
X				  (void) close(fout);
X				  npart = 0;
X			  }
X		  }
X
Xmaze_def	: MAZE_ID ':' string
X		  {
X			  $$ = $3;
X		  }
X
Xregions		: aregion
X		| regions aregion;
X
Xaregion		: map_definition reg_init map_details
X		  {
X			store_part();
X		  }
X
Xmap_definition	: map_geometry MAP_ID
X		  {
X			tmppart[npart] = (mazepart *) alloc(sizeof(mazepart));
X			tmppart[npart]->halign = $<i>1 % 10;
X			tmppart[npart]->valign = $<i>1 / 10;
X			tmppart[npart]->nrobjects = 0;
X			tmppart[npart]->nloc = 0;
X			tmppart[npart]->nrmonst = 0;
X			scan_map($2);
X		  }
X
Xmap_geometry	: GEOMETRY_ID ':' h_justif ',' v_justif
X		  {
X			  $<i>$ = $<i>3 + ( $<i>5 * 10 );
X		  }
X
Xh_justif	: LEFT_OR_RIGHT
X		| CENTER ;
X
Xv_justif	: TOP_OR_BOT
X		| CENTER ;
X
Xreg_init	: /* nothing */
X		| reg_init init_reg ;
X
Xinit_reg	: RANDOM_OBJECTS_ID ':' object_list
X		  {
X			  if (tmppart[npart]->nrobjects)
X			      yyerror("Object registers already initialized!");
X			  else {
X				  tmppart[npart]->robjects = (char *) alloc(n_olist);
X				  memcpy(tmppart[npart]->robjects, olist, n_olist);
X				  tmppart[npart]->nrobjects = n_olist;
X			  }
X		  }
X		| RANDOM_PLACES_ID ':' place_list
X		  {
X			  if (tmppart[npart]->nloc)
X			      yyerror("Location registers already initialized!");
X			  else {
X				  register int i;
X				  tmppart[npart]->rloc_x = (char *) alloc(n_plist);
X				  tmppart[npart]->rloc_y = (char *) alloc(n_plist);
X				  for(i=0;i<n_plist;i++) {
X					  tmppart[npart]->rloc_x[i] = plist[i].x;
X					  tmppart[npart]->rloc_y[i] = plist[i].y;
X				  }
X				  tmppart[npart]->nloc = n_plist;
X			  }
X		  }
X		| RANDOM_MONSTERS_ID ':' monster_list
X		  {
X			  if (tmppart[npart]->nrmonst)
X			      yyerror("Monster registers already initialized!");
X			  else {
X				  tmppart[npart]->rmonst = (char *) alloc(n_mlist);
X				  memcpy(tmppart[npart]->rmonst, mlist, n_mlist);
X				  tmppart[npart]->nrmonst = n_mlist;
X			  }
X		  }
X
Xobject_list	: object
X		  {
X			  if (n_olist < MAX_REGISTERS)
X			      olist[n_olist++] = $<i>1;
X			  else
X			      yyerror("Object list too long!");
X		  }
X		| object_list ',' object
X		  {
X			  if (n_olist < MAX_REGISTERS)
X			      olist[n_olist++] = $<i>3;
X			  else
X			      yyerror("Object list too long!");
X		  }
X
Xmonster_list	: monster
X		  {
X			  if (n_mlist < MAX_REGISTERS)
X			      mlist[n_mlist++] = $<i>1;
X			  else
X			      yyerror("Monster list too long!");
X		  }
X		| monster_list ',' monster
X		  {
X			  if (n_mlist < MAX_REGISTERS)
X			      mlist[n_mlist++] = $<i>3;
X			  else
X			      yyerror("Monster list too long!");
X		  }
X
Xplace_list	: place
X		  {
X			  if (n_plist < MAX_REGISTERS)
X			      plist[n_plist++] = current_coord;
X			  else
X			      yyerror("Location list too long!");
X		  }
X		| place_list ',' place
X		  {
X			  if (n_plist < MAX_REGISTERS)
X			      plist[n_plist++] = current_coord;
X			  else
X			      yyerror("Location list too long!");
X		  }
X
Xmap_details	: /* nothing */
X		| map_details map_detail ;
X
Xmap_detail	: monster_detail
X		| object_detail
X		| door_detail
X		| trap_detail
X		| drawbridge_detail
X		| region_detail
X		| altar_detail
X		| mazewalk_detail
X		| ladder_detail
X		| diggable_detail ;
X
Xmonster_detail	: MONSTER_ID ':' monster_c ',' m_name ',' coordinate
X		  {
X			  int token;
X
X			  tmpmonst[nmons] = (monster *) alloc(sizeof(monster));
X			  tmpmonst[nmons]->x = current_coord.x;
X			  tmpmonst[nmons]->y = current_coord.y;
X			  tmpmonst[nmons]->class = $<i>3;
X			  if (!$5)
X			      tmpmonst[nmons]->id = -1;
X			  else {
X				  token = get_monster_id($5, (char) $<i>3);  
X				  if (token == ERR) {
X				      yywarning("Illegal monster name!  Making random monster.");
X				      tmpmonst[nmons]->id = -1;
X				  } else
X				      tmpmonst[nmons]->id = token;
X			  }
X			  nmons++;
X		  }
X
Xobject_detail	: OBJECT_ID ':' object_c ',' o_name ',' coordinate
X		  {
X			  int token;
X
X			  tmpobj[nobj] = (object *) alloc(sizeof(object));
X			  tmpobj[nobj]->x = current_coord.x;
X			  tmpobj[nobj]->y = current_coord.y;
X			  tmpobj[nobj]->class = $<i>3;
X			  if (!$5)
X			      tmpobj[nobj]->id = -1;
X			  else {
X				  token = get_object_id($5, (char) $<i>3);
X				  if (token == ERR) {
X				      yywarning("Illegal object name!  Making random object.");
X				      tmpobj[nobj]->id = -1;
X				  } else
X				      tmpobj[nobj]->id = token;
X			  }
X			  nobj++;
X		  }
X
Xdoor_detail	: DOOR_ID ':' door_state ',' coordinate
X		  {
X			tmpdoor[ndoor] = (door *) alloc(sizeof(door));
X			tmpdoor[ndoor]->x = current_coord.x;
X			tmpdoor[ndoor]->y = current_coord.y;
X			tmpdoor[ndoor]->mask = $<i>3;
X			ndoor++;
X		  }
X
Xtrap_detail	: TRAP_ID ':' trap_name ',' coordinate
X		  {
X			tmptrap[ntrap] = (trap *) alloc(sizeof(trap));
X			tmptrap[ntrap]->x = current_coord.x;
X			tmptrap[ntrap]->y = current_coord.y;
X			tmptrap[ntrap]->type = $<i>3;
X			ntrap++;
X		  }
X
Xdrawbridge_detail: DRAWBRIDGE_ID ':' coordinate ',' DIRECTION ',' door_state
X		   {
X			tmpdb[ndb] = (drawbridge *) alloc(sizeof(drawbridge));
X			tmpdb[ndb]->x = current_coord.x;
X			tmpdb[ndb]->y = current_coord.y;
X			tmpdb[ndb]->dir = db_dirs[$5];
X			if ( $<i>7 == D_ISOPEN )
X			  tmpdb[ndb]->open = 1;
X			else if ( $<i>7 == D_CLOSED )
X			  tmpdb[ndb]->open = 0;
X			else
X			  yyerror("A drawbridge can only be open or closed!");
X			ndb++;
X		   }
X
Xmazewalk_detail	: MAZEWALK_ID ':' coordinate ',' DIRECTION
X		  {
X			tmpwalk[nwalk] = (walk *) alloc(sizeof(walk));
X			tmpwalk[nwalk]->x = current_coord.x;
X			tmpwalk[nwalk]->y = current_coord.y;
X			tmpwalk[nwalk]->dir = $5;
X			nwalk++;
X		  }
X
Xladder_detail	: LADDER_ID ':' coordinate ',' UP_OR_DOWN
X		  {
X			tmplad[nlad] = (lad *) alloc(sizeof(lad));
X			tmplad[nlad]->x = current_coord.x;
X			tmplad[nlad]->y = current_coord.y;
X			tmplad[nlad]->up = $<i>5;
X			nlad++;
X		  }
X
Xdiggable_detail	: NON_DIGGABLE_ID ':' region
X		  {
X			tmpdig[ndig] = (dig *) alloc(sizeof(dig));
X			tmpdig[ndig]->x1 = current_region.x1;
X			tmpdig[ndig]->y1 = current_region.y1;
X			tmpdig[ndig]->x2 = current_region.x2;
X			tmpdig[ndig]->y2 = current_region.y2;
X			ndig++;
X		  }
X
Xregion_detail	: REGION_ID ':' region ',' light_state ',' room_type
X		  {
X			tmpreg[nreg] = (region *) alloc(sizeof(region));
X			tmpreg[nreg]->x1 = current_region.x1;
X			tmpreg[nreg]->y1 = current_region.y1;
X			tmpreg[nreg]->x2 = current_region.x2;
X			tmpreg[nreg]->y2 = current_region.y2;
X			tmpreg[nreg]->rlit = $<i>5;
X			tmpreg[nreg]->rtype = $<i>7;
X			nreg++;
X		  }
X
Xaltar_detail	: ALTAR_ID ':' coordinate ',' alignment ',' altar_type
X		  {
X#ifndef ALTARS
X			yywarning("Altars are not allowed in this version!  Ignoring...");
X#else
X			tmpaltar[naltar] = (altar *) alloc(sizeof(altar));
X			tmpaltar[naltar]->x = current_coord.x;
X			tmpaltar[naltar]->y = current_coord.y;
X			tmpaltar[naltar]->align = $<i>5;
X			tmpaltar[naltar]->shrine = $<i>7;
X			naltar++;
X#endif /* ALTARS */
X		  }
X
Xmonster_c	: monster
X		| RANDOM_TYPE
X		  {
X			  $<i>$ = - MAX_REGISTERS - 1;
X		  }
X		| m_register ;
X
Xobject_c	: object
X		| RANDOM_TYPE
X		  {
X			  $<i>$ = - MAX_REGISTERS - 1;
X		  }
X		| o_register;
X
Xm_name		: string
X		| RANDOM_TYPE
X		  {
X			  $$ = (char *) 0;
X		  }
X
Xo_name		: string
X		| RANDOM_TYPE
X		  {
X			  $$ = (char *) 0;
X		  }
X
Xtrap_name	: string
X		  {
X		  	int token = get_trap_type($1);
X			if (token == ERR)
X				yyerror("unknown trap type!");
X			$<i>$ = token;
X		  }
X		| RANDOM_TYPE
X
Xroom_type	: string
X		  {
X			int token = get_room_type($1);
X			if (token == ERR) {
X				yywarning("Unknown room type!  Making ordinary room...");
X				$<i>$ = OROOM;
X			} else
X				$<i>$ = token;
X		  }
X		| RANDOM_TYPE
X
Xcoordinate	: coord
X		| p_register
X		| RANDOM_TYPE
X		  {
X			  current_coord.x = current_coord.y = -MAX_REGISTERS-1;
X		  }
X
Xdoor_state	: DOOR_STATE
X		| RANDOM_TYPE
X
Xlight_state	: LIGHT_STATE
X		| RANDOM_TYPE
X
Xalignment	: ALIGNMENT
X		| a_register
X		| RANDOM_TYPE
X		  {
X			  $<i>$ = - MAX_REGISTERS - 1;
X		  }
X
Xaltar_type	: ALTAR_TYPE
X		| RANDOM_TYPE
X
Xp_register	: P_REGISTER '[' INTEGER ']'
X		  {
X			if ( $3 >= MAX_REGISTERS ) {
X				yyerror("Register Index overflow!");
X			} else {
X				current_coord.x = current_coord.y = - $3 - 1;
X			}
X		  }
X
Xo_register	: O_REGISTER '[' INTEGER ']' 
X		  {
X			if ( $3 >= MAX_REGISTERS ) {
X				yyerror("Register Index overflow!");
X			} else {
X				$<i>$ = - $3 - 1;
X			}
X		  }
X
Xm_register	: M_REGISTER '[' INTEGER ']'
X		  {
X			if ( $3 >= MAX_REGISTERS ) {
X				yyerror("Register Index overflow!");
X			} else {
X				$<i>$ = - $3 - 1;
X			}
X		  }
X
Xa_register	: A_REGISTER '[' INTEGER ']'
X		  {
X			if ( $3 >= 3 ) {
X				yyerror("Register Index overflow!");
X			} else {
X				$<i>$ = - $3 - 1;
X			}
X		  }
X
Xplace		: coord
X
Xmonster		: CHAR
X		  {
X			if (check_monster_char($1))
X				$<i>$ = $1 ;
X			else {
X				yyerror("unknown monster class!");
X				$<i>$ = ERR;
X			}
X		  }
X
Xobject		: CHAR
X		  {
X			char c;
X
X			c = $1;
X#ifndef SPELLS
X			if ( c == '+') {
X				c = '?';
X				yywarning("Spellbooks are not allowed in this version! (converted into scroll)");
X			}
X#endif
X			if (check_object_char(c))
X				$<i>$ = c;
X			else {
X				yyerror("Unknown char class!");
X				$<i>$ = ERR;
X			}
X		  }
Xstring		: STRING
X
Xcoord		: '(' INTEGER ',' INTEGER ')'
X		  {
X		        if ($2 < 0 || $2 > max_x_map ||
X			    $4 < 0 || $4 > max_y_map)
X			    yyerror("Coordinates out of map range!");
X			current_coord.x = $2;
X			current_coord.y = $4;
X		  }
X
Xregion		: '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
X		  {
X		        if ($2 < 0 || $2 > max_x_map ||
X			    $4 < 0 || $4 > max_y_map ||
X			    $6 < 0 || $6 > max_x_map ||
X			    $8 < 0 || $8 > max_y_map)
X			    yyerror("Region out of map range!");
X			current_region.x1 = $2;
X			current_region.y1 = $4;
X			current_region.x2 = $6;
X			current_region.y2 = $8;
X		  }
X
X
X%%
X
X/* 
X * Find the type of a room in the table, knowing its name.
X */
X
Xint
Xget_room_type(s)
Xchar *s;
X{
X	register int i;
X	
X	for(i=0; i < SHOPBASE -1; i++)
X	    if (!strcmp(s, room_types[i].name))
X		return room_types[i].type;
X	return ERR;
X}
X
X/* 
X * Find the type of a trap in the table, knowing its name.
X */
X
Xint
Xget_trap_type(s)
Xchar *s;
X{
X	register int i;
X	
X	for(i=0; i < TRAPNUM - 1; i++)
X	    if(!strcmp(s,trap_types[i].name))
X		return(trap_types[i].type);
X	return ERR;
X}
X
X/* 
X * Find the index of a monster in the table, knowing its name.
X */
X
Xint
Xget_monster_id(s, c)
Xchar *s;
Xchar c;
X{
X	register int i;
X	
X	for(i=0; mons[i].mname[0]; i++)
X	    if(!strncmp(s, mons[i].mname, strlen(mons[i].mname))
X	       && c == mons[i].mlet)
X		return i;
X	return ERR;
X}
X
X/* 
X * Find the index of an object in the table, knowing its name.
X */
X
Xint
Xget_object_id(s, c)
Xchar *s;
Xchar c;
X{
X	register int i;
X	
X	for(i=0; i<=NROFOBJECTS;i++)
X	    if(objects[i].oc_name &&
X	       !strncmp(s, objects[i].oc_name, strlen(objects[i].oc_name))
X	       && c == objects[i].oc_olet)
X		return i;
X	return ERR;
X}
X
X/* 
X * Is the character 'c' a valid monster class ?
X */
X
Xboolean
Xcheck_monster_char(c)
Xchar c;
X{
X	register int i;
X	
X	for(i=0; mons[i].mname[0]; i++)
X	    if( c ==  mons[i].mlet)
X		return 1;
X	return(0);
X}
X
X/* 
X * Is the character 'c' a valid object class ?
X */
X
Xboolean
Xcheck_object_char(c)
Xchar c;
X{
X	register int i;
X	
X	for(i=0; i<=NROFOBJECTS;i++)
X	    if( c == objects[i].oc_olet)
X		return 1;
X	return 0;
X}
X
X/* 
X * Yep! LEX gives us the map in a raw mode.
X * Just analyze it here.
X */
X
Xvoid scan_map(map)
Xchar *map;
X{
X	register int i, len;
X	register char *s1, *s2;
X	int max_len = 0;
X	int max_hig = 0;
X	
X	/* First : find the max width of the map */
X
X	s1 = map;
X	while (s1 && *s1) {
X		s2 = index(s1, '\n');
X		if (s2) {
X			if (s2-s1 > max_len)
X			    max_len = s2-s1;
X			s1 = s2 + 1;
X		} else {
X			if (strlen(s1) > max_len)
X			    max_len = strlen(s1);
X			s1 = (char *) 0;
X		}
X	}
X
X	/* Then parse it now */
X
X	while (map && *map) {
X		tmpmap[max_hig] = (char *) alloc(max_len);
X		s1 = index(map, '\n');
X		if (s1) {
X			len = s1 - map;
X			s1++;
X		} else {
X			len = strlen(map);
X			s1 = map + len;
X		}
X		for(i=0; i<len; i++)
X		    switch(map[i]) {
X			  case '-' : tmpmap[max_hig][i] = HWALL; break;
X			  case '|' : tmpmap[max_hig][i] = VWALL; break;
X			  case '+' : tmpmap[max_hig][i] = DOOR; break;
X			  case 'S' : tmpmap[max_hig][i] = SDOOR; break;
X			  case '{' : 
X#ifdef FOUNTAINS
X			      tmpmap[max_hig][i] = FOUNTAIN;
X#else
X			      tmpmap[max_hig][i] = ROOM;
X			      yywarning("Fountains are not allowed in this version!  Ignoring...");
X#endif
X			      break;
X			  case '\\' : 
X#ifdef THRONES
X			      tmpmap[max_hig][i] = THRONE;
X#else
X			      tmpmap[max_hig][i] = ROOM;
X			      yywarning("Thrones are not allowed in this version!  Ignoring...");
X#endif
X			      break;
X			  case 'K' : 
X#ifdef SINKS
X			      tmpmap[max_hig][i] = SINK;
X#else
X			      tmpmap[max_hig][i] = ROOM;
X			      yywarning("Sinks are not allowed in this version!  Ignoring...");
X#endif
X			      break;
X			  case '}' : tmpmap[max_hig][i] = MOAT; break;
X			  case '#' : tmpmap[max_hig][i] = CORR; break;
X			  default  : tmpmap[max_hig][i] = ROOM; break;
X		    }
X		while(i < max_len)
X		    tmpmap[max_hig][i++] = ROOM;
X		map = s1;
X		max_hig++;
X	}
X
X	/* Memorize boundaries */
X
X	max_x_map = max_len - 1;
X	max_y_map = max_hig - 1;
X
X	/* Store the map into the mazepart structure */
X
X	tmppart[npart]->xsize = max_len;
X	tmppart[npart]->ysize = max_hig;
X	tmppart[npart]->map = (char **) alloc(max_hig*sizeof(char *));
X	for(i = 0; i< max_hig; i++)
X	    tmppart[npart]->map[i] = tmpmap[i];
X}
X
X/* 
X * Here we want to store the maze part we just got.
X */
X
Xvoid
Xstore_part()
X{
X	register int i;
X
X	/* Ok, We got the whole part, now we store it. */
X	
X	/* The Regions */
X
X	if(tmppart[npart]->nreg = nreg) {
X		tmppart[npart]->regions = (region**)alloc(sizeof(region*) * nreg);
X		for(i=0;i<nreg;i++)
X		    tmppart[npart]->regions[i] = tmpreg[i];
X	}
X	nreg = 0;
X
X	/* the doors */
X
X	if(tmppart[npart]->ndoor = ndoor) {
X		tmppart[npart]->doors = (door **)alloc(sizeof(door *) * ndoor);
X		for(i=0;i<ndoor;i++)
X		    tmppart[npart]->doors[i] = tmpdoor[i];
X	}
X	ndoor = 0;
X
X	/* the traps */
X
X	if(tmppart[npart]->ntraps = ntrap) {
X		tmppart[npart]->traps = (trap **)alloc(sizeof(trap*) * ntrap);
X		for(i=0;i<ntrap;i++)
X		    tmppart[npart]->traps[i] = tmptrap[i];
X	}
X	ntrap = 0;
X
X	/* the monsters */
X
X	if(tmppart[npart]->nmonster = nmons) {
X		tmppart[npart]->monsters = (monster**)alloc(sizeof(monster*)*nmons);
X		for(i=0;i<nmons;i++)
X		    tmppart[npart]->monsters[i] = tmpmonst[i];
X	}
X	nmons = 0;
X
X	/* the objects */
X
X	if(tmppart[npart]->nobjects = nobj) {
X		tmppart[npart]->objects = (object**)alloc(sizeof(object*)*nobj);
X		for(i=0;i<nobj;i++)
X		    tmppart[npart]->objects[i] = tmpobj[i];
X	}
X	nobj = 0;
X
X	/* the drawbridges */
X
X	if(tmppart[npart]->ndrawbridge = ndb) {
X		tmppart[npart]->drawbridges = (drawbridge**)alloc(sizeof(drawbridge*)*ndb);
X		for(i=0;i<ndb;i++)
X		    tmppart[npart]->drawbridges[i] = tmpdb[i];
X	}
X	ndb = 0;
X
X	/* The walkmaze directives */
X
X	if(tmppart[npart]->nwalk = nwalk) {
X		tmppart[npart]->walks = (walk**)alloc(sizeof(walk*)*nwalk);
X		for(i=0;i<nwalk;i++)
X		    tmppart[npart]->walks[i] = tmpwalk[i];
X	}
X	nwalk = 0;
X
X	/* The non_diggable directives */
X
X	if(tmppart[npart]->ndig = ndig) {
X		tmppart[npart]->digs = (dig **) alloc(sizeof(dig*) * ndig);
X		for(i=0;i<ndig;i++)
X		    tmppart[npart]->digs[i] = tmpdig[i];
X	}
X	ndig = 0;
X
X	/* The ladders */
X
X	if(tmppart[npart]->nlad = nlad) {
X		tmppart[npart]->lads = (lad **) alloc(sizeof(lad*) * nlad);
X		for(i=0;i<nlad;i++)
X		    tmppart[npart]->lads[i] = tmplad[i];
X	}
X	nlad = 0;
X#ifdef ALTARS
X	/* The altars */
X
X	if(tmppart[npart]->naltar = naltar) {
X		tmppart[npart]->altars = (altar**)alloc(sizeof(altar*) * naltar);
X		for(i=0;i<naltar;i++)
X		    tmppart[npart]->altars[i] = tmpaltar[i];
X	}
X	naltar = 0;
X#endif /* ALTARS /**/
X	npart++;
X	n_plist = n_mlist = n_olist = 0;
X}
X
X/* 
X * Here we write the structure of the maze in the specified file (fd).
X * Also, we have to free the memory allocated via alloc()
X */
X
Xvoid
Xwrite_maze(fd, maze)
Xint fd;
Xspecialmaze *maze;
X{
X	char c;
X	short i,j;
X	mazepart *pt;
X
X	c = 2;
X	(void) write(fd, &c, 1);	/* Header for special mazes */
X	(void) write(fd, &(maze->numpart), 1);	/* Number of parts */
X	for(i=0;i<maze->numpart;i++) {
X	    pt = maze->parts[i];
X
X	    /* First, write the map */
X
X	    (void) write(fd, &(pt->halign), 1);
X	    (void) write(fd, &(pt->valign), 1);
X	    (void) write(fd, &(pt->xsize), 1);
X	    (void) write(fd, &(pt->ysize), 1);
X	    for(j=0;j<pt->ysize;j++) {
X		    (void) write(fd, pt->map[j], pt->xsize);
X		    free(pt->map[j]);
X	    }
X	    free(pt->map);
X
X	    /* The random registers */
X	    (void) write(fd, &(pt->nrobjects), 1);
X	    if(pt->nrobjects) {
X		    (void) write(fd, pt->robjects, pt->nrobjects);
X		    free(pt->robjects);
X	    }
X	    (void) write(fd, &(pt->nloc), 1);
X	    if(pt->nloc) {
X		(void) write(fd,pt->rloc_x, pt->nloc);
X		(void) write(fd,pt->rloc_y, pt->nloc);
X		free(pt->rloc_x);
X		free(pt->rloc_y);
X	    }
X	    (void) write(fd,&(pt->nrmonst), 1);
X	    if(pt->nrmonst) {
X		    (void) write(fd, pt->rmonst, pt->nrmonst);
X		    free(pt->rmonst);
X	    }
X
X	    /* subrooms */
X	    (void) write(fd, &(pt->nreg), 1);
X	    for(j=0;j<pt->nreg;j++) {
X		    (void) write(fd,(genericptr_t) pt->regions[j], sizeof(region));
X		    free(pt->regions[j]);
X	    }
X	    if(pt->nreg > 0)
X		free(pt->regions);
X
X	    /* the doors */
X	    (void) write(fd,&(pt->ndoor),1);
X	    for(j=0;j<pt->ndoor;j++) {
X		    (void) write(fd,(genericptr_t) pt->doors[j], sizeof(door));
X		    free(pt->doors[j]);
X	    }
X	    if (pt->ndoor > 0)
X		free(pt->doors);
X
X	    /* The traps */
X	    (void) write(fd,&(pt->ntraps), 1);
X	    for(j=0;j<pt->ntraps;j++) {
X		    (void) write(fd,(genericptr_t) pt->traps[j], sizeof(trap));
X		    free(pt->traps[j]);
X	    }
X	    if (pt->ntraps)
X		free(pt->traps);
X
X	    /* The monsters */
X	    (void) write(fd, &(pt->nmonster), 1);
X	    for(j=0;j<pt->nmonster;j++) {
X		    (void) write(fd,(genericptr_t) pt->monsters[j], sizeof(monster));
X		    free(pt->monsters[j]);
X	    }
X	    if (pt->nmonster > 0)
X		free(pt->monsters);
X
X	    /* The objects */
X	    (void) write(fd, &(pt->nobjects), 1);
X	    for(j=0;j<pt->nobjects;j++) {
X		    (void) write(fd,(genericptr_t) pt->objects[j], sizeof(object));
X		    free(pt->objects[j]);
X	    }
X	    if(pt->nobjects > 0)
X		free(pt->objects);
X
X	    /* The drawbridges */
X	    (void) write(fd, &(pt->ndrawbridge),1);
X	    for(j=0;j<pt->ndrawbridge;j++) {
X		    (void) write(fd,(genericptr_t) pt->drawbridges[j], sizeof(drawbridge));
X		    free(pt->drawbridges[j]);
X	    }
X	    if(pt->ndrawbridge > 0)
X		free(pt->drawbridges);
X
X	    /* The mazewalk directives */
X	    (void) write(fd, &(pt->nwalk), 1);
X	    for(j=0; j<pt->nwalk; j++) {
X		    (void) write(fd,(genericptr_t) pt->walks[j], sizeof(walk));
X		    free(pt->walks[j]);
X	    }
X	    if (pt->nwalk > 0)
X		free(pt->walks);
X
X	    /* The non_diggable directives */
X	    (void) write(fd, &(pt->ndig), 1);
X	    for(j=0;j<pt->ndig;j++) {
X		    (void) write(fd,(genericptr_t) pt->digs[j], sizeof(dig));
X		    free(pt->digs[j]);
X	    }
X	    if (pt->ndig > 0)
X		free(pt->digs);
X
X	    /* The ladders */
X	    (void) write(fd, &(pt->nlad), 1);
X	    for(j=0;j<pt->nlad;j++) {
X		    (void) write(fd,(genericptr_t) pt->lads[j], sizeof(lad));
X		    free(pt->lads[j]);
X	    }
X	    if (pt->nlad > 0)
X		free(pt->lads);
X#ifdef ALTARS
X	    /* The altars */
X	    (void) write(fd, &(pt->naltar), 1);
X	    for(j=0;j<pt->naltar;j++) {
X		    (void) write(fd,(genericptr_t) pt->altars[j], sizeof(altar));
X		    free(pt->altars[j]);
X	    }
X	    if (pt->naltar > 0)
X		free(pt->altars);
X#endif /* ALTARS /**/
X	    free(pt);
X	}
X}
END_OF_FILE
if test 23359 -ne `wc -c <'src/lev_comp.y'`; then
    echo shar: \"'src/lev_comp.y'\" unpacked with wrong size!
fi
# end of 'src/lev_comp.y'
fi
if test -f 'src/mklev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/mklev.c'\"
else
echo shar: Extracting \"'src/mklev.c'\" \(27014 characters\)
sed "s/^X//" >'src/mklev.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)mklev.c	3.0	88/11/24
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
X/* for UNIX, Rand #def'd to (long)lrand48() or (long)random() */
X/* croom->lx etc are schar (width <= int), so % arith ensures that */
X/* conversion of result to int is reasonable */
X
X#ifdef SINKS
Xstatic void mksink();
X#endif
X#ifdef ALTARS
Xstatic void mkaltar();
X#endif
X
Xint
Xsomex(croom)
Xregister struct mkroom *croom;
X{
X	return rn2(croom->hx-croom->lx+1) + croom->lx;
X}
X
Xint
Xsomey(croom)
Xregister struct mkroom *croom;
X{
X	return rn2(croom->hy-croom->ly+1) + croom->ly;
X}
X
X#define	XLIM	4	/* define minimum required space around a room */
X#define	YLIM	3
Xboolean secret;		/* TRUE while making a vault: increase [XY]LIM */
Xstruct rm zerorm;
Xschar nxcor;
Xboolean goldseen;
X
X/* Definitions used by makerooms() and addrs() */
X#define	MAXRS	50	/* max lth of temp rectangle table - arbitrary */
Xstruct rectangle {
X	xchar rlx,rly,rhx,rhy;
X} rs[MAXRS+1];
Xint rscnt,rsmax;	/* 0..rscnt-1: currently under consideration */
X			/* rscnt..rsmax: discarded */
X
Xstatic void
Xaddrsx(lx,ly,hx,hy,discarded)
Xregister int lx,ly,hx,hy;
Xboolean discarded;		/* piece of a discarded area */
X{
X	register struct rectangle *rsp;
X
X	/* check inclusions */
X	for(rsp = rs; rsp < &rs[rsmax]; rsp++) {
X		if(lx >= rsp->rlx && hx <= rsp->rhx &&
X		   ly >= rsp->rly && hy <= rsp->rhy)
X			return;
X	}
X
X	/* make a new entry */
X	if(rsmax >= MAXRS) {
X#ifdef WIZARD
X		if(wizard) pline("MAXRS may be too small.");
X#endif
X		return;
X	}
X	rsmax++;
X	if(!discarded) {
X		*rsp = rs[rscnt];
X		rsp = &rs[rscnt];
X		rscnt++;
X	}
X	rsp->rlx = lx;
X	rsp->rly = ly;
X	rsp->rhx = hx;
X	rsp->rhy = hy;
X}
X
Xstatic void
Xaddrs(lowx,lowy,hix,hiy)
Xregister int lowx,lowy,hix,hiy;
X{
X	register struct rectangle *rsp;
X	register int lx,ly,hx,hy,xlim,ylim;
X	boolean discarded;
X
X	xlim = XLIM + secret;
X	ylim = YLIM + secret;
X
X	/* walk down since rscnt and rsmax change */
X	for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) {
X
X		if((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy ||
X		   (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy)
X			continue;
X		if((discarded = (rsp >= &rs[rscnt]))) {
X			*rsp = rs[--rsmax];
X		} else {
X			rsmax--;
X			rscnt--;
X			*rsp = rs[rscnt];
X			if(rscnt != rsmax)
X				rs[rscnt] = rs[rsmax];
X		}
X		if(lowy - ly > 2*ylim + 4)
X			addrsx(lx,ly,hx,lowy-2,discarded);
X		if(lowx - lx > 2*xlim + 4)
X			addrsx(lx,ly,lowx-2,hy,discarded);
X		if(hy - hiy > 2*ylim + 4)
X			addrsx(lx,hiy+2,hx,hy,discarded);
X		if(hx - hix > 2*xlim + 4)
X			addrsx(hix+2,ly,hx,hy,discarded);
X	}
X}
X
Xstatic int
Xcomp(x,y)
Xregister struct mkroom *x,*y;
X{
X	if(x->lx < y->lx) return(-1);
X	return(x->lx > y->lx);
X}
X
Xstatic void
Xfinddpos(cc, xl,yl,xh,yh)
Xcoord	*cc;
Xxchar	xl,yl,xh,yh;
X{
X	register xchar x, y;
X
X	x = (xl == xh) ? xl : (xl + rn2(xh-xl+1));
X	y = (yl == yh) ? yl : (yl + rn2(yh-yl+1));
X	if(okdoor(x, y))
X		goto gotit;
X
X	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
X		if(okdoor(x, y))
X			goto gotit;
X
X	for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++)
X		if(IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR)
X			goto gotit;
X	/* cannot find something reasonable -- strange */
X	x = xl;
X	y = yh;
Xgotit:
X	cc->x = x;
X	cc->y = y;
X	return;
X}
X
X/* Only called from makerooms() and makebigroom() */
Xstatic int
Xmaker(lowx,ddx,lowy,ddy,lit)
Xschar lowx,ddx,lowy,ddy;
Xboolean lit;
X{
X	register struct mkroom *croom;
X	register int x, y, hix = lowx+ddx, hiy = lowy+ddy;
X	register int xlim = XLIM + secret, ylim = YLIM + secret;
X
X	if(nroom >= MAXNROFROOMS) return(0);
X	if(lowx < XLIM) lowx = XLIM;
X	if(lowy < YLIM) lowy = YLIM;
X	if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1;
X	if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1;
Xchk:
X	if(hix <= lowx || hiy <= lowy) return(0);
X
X	/* check area around room (and make room smaller if necessary) */
X	for(x = lowx - xlim; x <= hix + xlim; x++) {
X		for(y = lowy - ylim; y <= hiy + ylim; y++) {
X			if(levl[x][y].typ) {
X#ifdef WIZARD
X			    if(wizard && !secret)
X				pline("Strange area [%d,%d] in maker().",x,y);
X#endif
X				if(!rn2(3)) return(0);
X				if(x < lowx)
X					lowx = x+xlim+1;
X				else
X					hix = x-xlim-1;
X				if(y < lowy)
X					lowy = y+ylim+1;
X				else
X					hiy = y-ylim-1;
X				goto chk;
X			}
X		}
X	}
X
X	croom = &rooms[nroom];
X
X	/* on low levels the room is lit (usually) */
X	/* secret vaults are always lit */
X	/* some other rooms may require lighting */
X	if((rnd(dlevel) < 10 && rn2(77)) || secret || lit) {
X		for(x = lowx-1; x <= hix+1; x++)
X			for(y = lowy-1; y <= hiy+1; y++)
X				levl[x][y].lit = 1;
X		croom->rlit = 1;
X	} else
X		croom->rlit = 0;
X	croom->lx = lowx;
X	croom->hx = hix;
X	croom->ly = lowy;
X	croom->hy = hiy;
X	croom->rtype = OROOM;
X	croom->doorct = 0;
X	/* if we're not making a vault, doorindex will still be 0
X	 * if we are, we'll have problems adding niches to the previous room
X	 * unless fdoor is at least doorindex
X	 */
X	croom->fdoor = doorindex;
X
X	for(x = lowx-1; x <= hix+1; x++)
X	    for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) {
X		levl[x][y].typ = HWALL;
X		levl[x][y].scrsym = HWALL_SYM;
X	    }
X	for(x = lowx-1; x <= hix+1; x += (hix-lowx+2))
X	    for(y = lowy; y <= hiy; y++) {
X		levl[x][y].typ = VWALL;
X		levl[x][y].scrsym = VWALL_SYM;
X	    }
X	for(x = lowx; x <= hix; x++)
X	    for(y = lowy; y <= hiy; y++) {
X		levl[x][y].typ = ROOM;
X		levl[x][y].scrsym = ROOM_SYM;
X	    }
X	levl[lowx-1][lowy-1].typ = TLCORNER;
X	levl[hix+1][lowy-1].typ = TRCORNER;
X	levl[lowx-1][hiy+1].typ = BLCORNER;
X	levl[hix+1][hiy+1].typ = BRCORNER;
X	levl[lowx-1][lowy-1].scrsym = TLCORN_SYM;
X	levl[hix+1][lowy-1].scrsym = TRCORN_SYM;
X	levl[lowx-1][hiy+1].scrsym = BLCORN_SYM;
X	levl[hix+1][hiy+1].scrsym = BRCORN_SYM;
X
X	smeq[nroom] = nroom;
X	croom++;
X	croom->hx = -1;
X	nroom++;
X	return(1);
X}
X
Xstatic int
Xmakerooms() {
Xregister struct rectangle *rsp;
Xregister int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy;
Xint tryct = 0, xlim, ylim;
X
X	/* init */
X	xlim = XLIM + secret;
X	ylim = YLIM + secret;
X	if(nroom == 0) {
X		rsp = rs;
X		rsp->rlx = rsp->rly = 0;
X		rsp->rhx = COLNO-1;
X		rsp->rhy = ROWNO-1;
X		rsmax = 1;
X	}
X	rscnt = rsmax;
X
X	/* make rooms until satisfied */
X	while(rscnt > 0 && nroom < MAXNROFROOMS-1) {
X		if(!secret && nroom > (MAXNROFROOMS/4) &&
X		   !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom)))
X			return 0;
X
X		/* pick a rectangle */
X		rsp = &rs[rn2(rscnt)];
X		hx = rsp->rhx;
X		hy = rsp->rhy;
X		lx = rsp->rlx;
X		ly = rsp->rly;
X
X		/* find size of room */
X		if(secret)
X			dx = dy = 1;
X		else {
X			dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8);
X			dy = 2 + rn2(4);
X			if(dx*dy > 50)
X				dy = 50/dx;
X		}
X
X		/* look whether our room will fit */
X		if(hx-lx < dx + (dx>>1) + 2*xlim ||
X		   hy-ly < dy + dy/3 + 2*ylim) {
X					/* no, too small */
X					/* maybe we throw this area out */
X			if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) {
X				rscnt--;
X				rs[rsmax] = *rsp;
X				*rsp = rs[rscnt];
X				rs[rscnt] = rs[rsmax];
X				tryct = 0;
X			} else
X				tryct++;
X			continue;
X		}
X
X		lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1);
X		lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1);
X		hix = lowx + dx;
X		hiy = lowy + dy;
X
X		if(maker(lowx, dx, lowy, dy, FALSE)) {
X			if(secret) return(1);
X			addrs(lowx-1, lowy-1, hix+1, hiy+1);
X			tryct = 0;
X		} else
X			if(tryct++ > 100)
X				break;
X	}
X	return(0);	/* failed to make vault - very strange */
X}
X
Xstatic void
Xjoin(a,b)
Xregister int a, b;
X{
X	coord cc,tt;
X	register int tx, ty, xx, yy;
X	register struct rm *crm;
X	register struct mkroom *croom, *troom;
X	register int dx, dy, dix, diy, cct;
X
X	croom = &rooms[a];
X	troom = &rooms[b];
X
X	/* find positions cc and tt for doors in croom and troom
X	   and direction for a corridor between them */
X
X	if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return;
X	if(troom->lx > croom->hx) {
X		dx = 1;
X		dy = 0;
X		xx = croom->hx+1;
X		tx = troom->lx-1;
X		finddpos(&cc, xx, croom->ly, xx, croom->hy);
X		finddpos(&tt, tx, troom->ly, tx, troom->hy);
X	} else if(troom->hy < croom->ly) {
X		dy = -1;
X		dx = 0;
X		yy = croom->ly-1;
X		finddpos(&cc, croom->lx, yy, croom->hx, yy);
X		ty = troom->hy+1;
X		finddpos(&tt, troom->lx, ty, troom->hx, ty);
X	} else if(troom->hx < croom->lx) {
X		dx = -1;
X		dy = 0;
X		xx = croom->lx-1;
X		tx = troom->hx+1;
X		finddpos(&cc, xx, croom->ly, xx, croom->hy);
X		finddpos(&tt, tx, troom->ly, tx, troom->hy);
X	} else {
X		dy = 1;
X		dx = 0;
X		yy = croom->hy+1;
X		ty = troom->ly-1;
X		finddpos(&cc, croom->lx, yy, croom->hx, yy);
X		finddpos(&tt, troom->lx, ty, troom->hx, ty);
X	}
X	xx = cc.x;
X	yy = cc.y;
X	tx = tt.x - dx;
X	ty = tt.y - dy;
X	if(nxcor && levl[xx+dx][yy+dy].typ)
X		return;
X	dodoor(xx,yy,croom);
X
X	cct = 0;
X	while(xx != tx || yy != ty) {
X	    xx += dx;
X	    yy += dy;
X
X	    /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
X	    if(cct++ > 500 || (nxcor && !rn2(35)))
X		return;
X
X	    if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1)
X		return;		/* impossible */
X
X	    crm = &levl[xx][yy];
X	    if(!(crm->typ)) {
X		if(rn2(100)) {
X			crm->typ = CORR;
X			crm->scrsym = CORR_SYM;
X			if(nxcor && !rn2(50))
X				(void) mksobj_at(BOULDER, xx, yy);
X		} else {
X			crm->typ = SCORR;
X			crm->scrsym = STONE_SYM;
X		}
X	    } else
X	    if(crm->typ != CORR && crm->typ != SCORR) {
X		/* strange ... */
X		return;
X	    }
X
X	    /* find next corridor position */
X	    dix = abs(xx-tx);
X	    diy = abs(yy-ty);
X
X	    /* do we have to change direction ? */
X	    if(dy && dix > diy) {
X		register int ddx = (xx > tx) ? -1 : 1;
X
X		crm = &levl[xx+ddx][yy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
X		    dx = ddx;
X		    dy = 0;
X		    continue;
X		}
X	    } else if(dx && diy > dix) {
X		register int ddy = (yy > ty) ? -1 : 1;
X
X		crm = &levl[xx][yy+ddy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) {
X		    dy = ddy;
X		    dx = 0;
X		    continue;
X		}
X	    }
X
X	    /* continue straight on? */
X	    crm = &levl[xx+dx][yy+dy];
X	    if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X		continue;
X
X	    /* no, what must we do now?? */
X	    if(dx) {
X		dx = 0;
X		dy = (ty < yy) ? -1 : 1;
X		crm = &levl[xx+dx][yy+dy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X		    continue;
X		dy = -dy;
X		continue;
X	    } else {
X		dy = 0;
X		dx = (tx < xx) ? -1 : 1;
X		crm = &levl[xx+dx][yy+dy];
X		if(!crm->typ || crm->typ == CORR || crm->typ == SCORR)
X		    continue;
X		dx = -dx;
X		continue;
X	    }
X	}
X
X	/* we succeeded in digging the corridor */
X	dodoor(tt.x, tt.y, troom);
X
X	if(smeq[a] < smeq[b])
X		smeq[b] = smeq[a];
X	else
X		smeq[a] = smeq[b];
X}
X
Xstatic void
Xmakecorridors() {
X	register int a, b;
X
X	nxcor = 0;
X	for(a = 0; a < nroom-1; a++)
X		join(a, a+1);
X	for(a = 0; a < nroom-2; a++)
X	    if(smeq[a] != smeq[a+2])
X		join(a, a+2);
X	for(a = 0; a < nroom; a++)
X	    for(b = 0; b < nroom; b++)
X		if(smeq[a] != smeq[b])
X		    join(a, b);
X	if(nroom > 2)
X	    for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) {
X		a = rn2(nroom);
X		b = rn2(nroom-2);
X		if(b >= a) b += 2;
X		join(a, b);
X	    }
X}
X
Xstatic void
Xdosdoor(x,y,aroom,type)
Xregister int x, y;
Xregister struct mkroom *aroom;
Xregister int type;
X{
X	register struct mkroom *broom;
X	register int tmp;
X	boolean shdoor = in_shop(x, y);
X
X	if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with DOOR_SYM as scrsym */
X		type = DOOR;
X	levl[x][y].typ = type;
X	if(type == DOOR) {
X	    levl[x][y].scrsym = DOOR_SYM;
X	    if(!rn2(3)) {      /* is it a locked door, closed, or a doorway? */
X		if(!rn2(5))
X		    levl[x][y].doormask = D_ISOPEN;
X		else if(!rn2(4))
X		    levl[x][y].doormask = D_LOCKED;
X		else
X		    levl[x][y].doormask = D_CLOSED;
X
X		if (levl[x][y].doormask != D_ISOPEN && !shdoor && !rn2(25))
X		    levl[x][y].doormask |= D_TRAPPED;
X	    } else {
X		if(shdoor)	levl[x][y].doormask = D_ISOPEN;
X		else		levl[x][y].doormask = D_NODOOR;
X	    }
X	} else { /* SDOOR */
X		if(shdoor || !rn2(5))	levl[x][y].doormask = D_LOCKED;
X		else			levl[x][y].doormask = D_CLOSED;
X
X		if(!shdoor && !rn2(20)) levl[x][y].doormask |= D_TRAPPED;
X	}
X	aroom->doorct++;
X	broom = aroom+1;
X	if(broom->hx < 0) tmp = doorindex; else
X	for(tmp = doorindex; tmp > broom->fdoor; tmp--)
X		doors[tmp] = doors[tmp-1];
X	doorindex++;
X	doors[tmp].x = x;
X	doors[tmp].y = y;
X	for( ; broom->hx >= 0; broom++) broom->fdoor++;
X}
X
Xstatic boolean
Xplace_niche(aroom,dy,xx,yy)
Xregister struct mkroom *aroom;
Xint *dy, *xx, *yy;
X{
X	coord dd;
X
X	if(rn2(2)) {
X	    *dy = 1;
X	    finddpos(&dd, aroom->lx, aroom->hy+1, aroom->hx, aroom->hy+1);
X	} else {
X	    *dy = -1;
X	    finddpos(&dd, aroom->lx, aroom->ly-1, aroom->hx, aroom->ly-1);
X	}
X	*xx = dd.x;
X	*yy = dd.y;
X	return(levl[*xx][(*yy)+(*dy)].typ == STONE);
X}
X
X#ifdef ORACLE
Xboolean
Xplace_oracle(aroom,dy,xx,yy)
Xregister struct mkroom *aroom;
Xint *dy, *xx, *yy;
X{
X	if(!place_niche(aroom,dy,xx,yy)) return FALSE;
X
X	dosdoor(*xx,*yy,aroom,DOOR);
X	levl[*xx][*yy].doormask = D_NODOOR;
X	return TRUE;
X}
X#endif
X
X/* there should be one of these per trap */
Xconst char *engravings[] = {	"", "", "", "", "", "",
X				"?la? ?as ?er?", "ad ae?ar um",
X				"", "", "", "" ,""
X				, "", "ad ae?ar um"
X#ifdef SPELLS
X				,""
X#endif
X				,""
X#ifdef POLYSELF
X				,""
X#endif
X				,""
X				};
X
Xstatic void
Xmakeniche(trap_type)
Xint trap_type;
X{
X	register struct mkroom *aroom;
X	register struct rm *rm;
X	register int vct = 8;
X	int dy, xx, yy;
X	register struct trap *ttmp;
X
X	if(doorindex < DOORMAX)
X	  while(vct--) {
X	    aroom = &rooms[rn2(nroom)];
X	    if(aroom->rtype != OROOM) continue;	/* not an ordinary room */
X	    if(aroom->doorct == 1 && rn2(5)) continue;
X	    if(!place_niche(aroom,&dy,&xx,&yy)) continue;
X
X	    rm = &levl[xx][yy+dy];
X	    if(trap_type || !rn2(4)) {
X
X		rm->typ = SCORR;
X		rm->scrsym = STONE_SYM;
X		if(trap_type) {
X		    ttmp = maketrap(xx, yy+dy, trap_type);
X		    ttmp->once = 1;
X		    if (strlen(engravings[trap_type]) > 0)
X			make_engr_at(xx, yy-dy, engravings[trap_type]);
X		}
X		dosdoor(xx, yy, aroom, SDOOR);
X	    } else {
X		rm->typ = CORR;
X		rm->scrsym = CORR_SYM;
X		if(rn2(7))
X		    dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
X		else {
X		    (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy);
X		    if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy);
X		}
X	    }
X	    return;
X	}
X}
X
Xstatic void
Xmake_niches()
X{
X	register int ct = rnd((nroom>>1) + 1);
X	boolean	ltptr = TRUE,
X		vamp = TRUE;
X
X	while(ct--) {
X
X		if(dlevel > 15 && !rn2(6) && ltptr) {
X
X			ltptr = FALSE;
X			makeniche(LEVEL_TELEP);
X		} else if (dlevel > 5 && dlevel < 25
X			   && !rn2(6) && vamp) {
X
X			vamp = FALSE;
X			makeniche(TRAPDOOR);
X		} else	makeniche(NO_TRAP);
X	}
X}
X
Xstatic void
Xmakebigroom()
X{
X	register int x,y,n;
X	register struct mkroom *croom;
X	register struct monst *tmonst;
X
X	/* make biggest possible room; make sure it's lit */
X	(void) maker(XLIM, COLNO - 2*XLIM - 1, YLIM, ROWNO - 2*YLIM - 1, TRUE);
X	croom = &rooms[0];
X
X	/* add extra monsters and goodies */
X	n = 10 + rn2(15);
X	while (n--) {
X		x = somex(croom);
X		y = somey(croom);
X		tmonst = makemon((struct permonst *) 0,x,y);
X		if (tmonst && tmonst->data==&mons[PM_GIANT_SPIDER])
X			(void) maketrap(x,y,WEB);
X		if (tmonst && rn2(2))
X			tmonst->msleep = 1;
X	}
X	n = 6 + rn2(10);
X	while (n--)
X		(void) mkobj_at(0,somex(croom),somey(croom));
X}
X
Xstatic void
Xmakevtele()
X{
X	makeniche(TELEP_TRAP);
X}
X
X#define rntwixt(L1,L2)	rn1((L2)-(L1),L1)
X
Xstatic void
Xinit_levels()
X{
X#if defined(STRONGHOLD) && defined(MUSIC)
X	register int x;
X#endif
X
X#ifdef LINT	/* handle constant in conditional context */
X	medusa_level = 0;
X#else
X	medusa_level = rn1(3, HELLLEVEL - 5);
X#endif /* LINT */
X#ifdef STRONGHOLD
X	stronghold_level = rn1(5, medusa_level)+1;
X# ifdef MUSIC
X	for (x=0; x<5; x++)
X		tune[x] = 'A' + rn2(7);
X	tune[5] = 0;
X# endif
X	/* The tower will be on 3 levels */
X	tower_level = rntwixt(stronghold_level, MAXLEVEL-2)+1;
X	/* We don't want the wizard in Vlad's tower */
X	do
X		wiz_level = rntwixt(stronghold_level, MAXLEVEL)+1;
X	while (wiz_level >= tower_level && wiz_level <= tower_level + 2);
X#else
X	wiz_level	 = rntwixt(medusa_level, MAXLEVEL)+1;
X#endif /* STRONGHOLD /**/
X#ifdef WIZARD
X	if (!rn2(15) || wizard)
X#else
X	if (!rn2(15))
X#endif
X		/* between the middle of the dungeon and the medusa level */
X		bigroom_level = rntwixt(HELLLEVEL>>1, medusa_level);
X#ifdef REINCARNATION
X# ifdef WIZARD
X	if (!rn2(3) || wizard)
X# else
X	if (!rn2(3))
X# endif
X		rogue_level = rn1(5,10);
X#endif
X#ifdef ORACLE
X	oracle_level = rn1(4,5);
X#endif
X}
X
X#undef rntwixt
X
Xstatic void
Xmakelevel() {
X	register struct mkroom *croom, *troom;
X	register unsigned int tryct;
X	register int x,y;
X	struct monst *tmonst;	/* always put a web with a spider */
X
X	nroom = 0;
X	doorindex = 0;
X	rooms[0].hx = -1;	/* in case we are in a maze */
X
X	for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
X		levl[x][y] = zerorm;
X
X	oinit();	/* assign level dependent obj probabilities */
X	fountsound = 0;
X	sinksound = 0;
X
X	if (wiz_level == 0)
X		init_levels();
X	if (
X#ifndef STRONGHOLD
X	    Inhell
X#else
X	    dlevel >= stronghold_level || dlevel < 0
X#endif
X	    || (dlevel > medusa_level && rn2(5))
X	   ) {
X	    makemaz();
X	    return;
X	}
X
X	/* construct the rooms */
X	nroom = 0;
X	secret = FALSE;
X
X#ifdef REINCARNATION
X	if (dlevel == rogue_level) {
X	    makeroguerooms();
X	    makerogueghost();
X	} else
X#endif
X	if (dlevel == bigroom_level)
X	    makebigroom();
X	else
X	    (void) makerooms();
X
X	/* construct stairs (up and down in different rooms if possible) */
X	croom = &rooms[rn2(nroom)];
X	xdnstair = somex(croom);
X	ydnstair = somey(croom);
X	levl[xdnstair][ydnstair].scrsym = DN_SYM;
X	levl[xdnstair][ydnstair].typ = STAIRS;
X#ifdef MEDUSA
X	if (dlevel == medusa_level) {
X		struct monst *mtmp;
X
X		if (mtmp = makemon(&mons[PM_MEDUSA], xdnstair, ydnstair))
X			mtmp->msleep = 1;
X		for (tryct = rn1(1,3); tryct; tryct--) {
X			x = somex(croom); y = somey(croom);
X			if (goodpos(x,y))
X				(void) mk_tt_statue(x, y);
X		}
X	}
X#endif
X	if(nroom > 1) {
X		troom = croom;
X		croom = &rooms[rn2(nroom-1)];
X		if(croom >= troom) croom++;
X	}
X	xupstair = somex(croom);    /* %% < and > might be in the same place */
X	yupstair = somey(croom);
X	levl[xupstair][yupstair].scrsym = UP_SYM;
X	levl[xupstair][yupstair].typ = STAIRS;
X#ifdef STRONGHOLD
X	xdnladder = ydnladder = xupladder = yupladder = 0;
X#endif
X	is_maze_lev = FALSE;
X
X#ifdef SYSV
X	qsort((genericptr_t) rooms, (unsigned)nroom, sizeof(struct mkroom), comp);
X#else
X	qsort((genericptr_t) rooms, nroom, sizeof(struct mkroom), comp);
X#endif
X#ifdef REINCARNATION
X	if (dlevel == rogue_level) {
X	   You("feel as though you were here in a previous lifetime.");
X	   return;
X	}
X#endif
X	makecorridors();
X	make_niches();
X
X	/* make a secret treasure vault, not connected to the rest */
X	if(nroom <= (MAXNROFROOMS/2)) if(rn2(3)) {
X
X		troom = &rooms[nroom];
X		secret = TRUE;
X		if(makerooms()) {
X			troom->rtype = VAULT;		/* treasure vault */
X			for(x = troom->lx; x <= troom->hx; x++)
X			for(y = troom->ly; y <= troom->hy; y++)
X				mkgold((long)(rnd(dlevel*100) + 50), x, y);
X			if(!rn2(3))
X				makevtele();
X		}
X	}
X
X#ifdef WIZARD
X	if(wizard && getenv("SHOPTYPE")) mkroom(SHOPBASE); else
X#endif
X#ifdef ORACLE
X	if(dlevel == oracle_level) mkroom(DELPHI);
X	/*  It is possible that we find no good place to set up Delphi.
X	 *  It is also possible to get more than one Delphi using bones levels.
X	 *  The first is not a problem; the second is a minor nuisance.
X	 */
X	else
X#endif
X	if(dlevel > 1 && dlevel < medusa_level && rn2(dlevel) < 3) mkroom(SHOPBASE);
X	else
X#ifdef THRONES
X	if(dlevel > 4 && !rn2(6)) mkroom(COURT);
X	else
X#endif
X	if(dlevel > 6 && !rn2(7)) mkroom(ZOO);
X	else
X#ifdef ALTARS
X	if(dlevel > 8 && !rn2(5)) mkroom(TEMPLE);
X	else
X#endif
X	if(dlevel > 9 && !rn2(5) && !(mons[PM_KILLER_BEE].geno & G_GENOD))
X		mkroom(BEEHIVE);
X	else
X	if(dlevel > 11 && !rn2(6)) mkroom(MORGUE);
X	else
X#ifdef ARMY
X	if(dlevel > 14 && !rn2(4) && !(mons[PM_SOLDIER].geno & G_GENOD))
X		mkroom(BARRACKS);
X	else
X#endif
X	if(dlevel > 18 && !rn2(6)) mkroom(SWAMP);
X
X
X	/* for each room: put things inside */
X	for(croom = rooms; croom->hx > 0; croom++) {
X		register boolean boxinlev = FALSE;
X
X		if(croom->rtype != OROOM) continue;
X
X		/* put a sleeping monster inside */
X		/* Note: monster may be on the stairs. This cannot be
X		   avoided: maybe the player fell through a trapdoor
X		   while a monster was on the stairs. Conclusion:
X		   we have to check for monsters on the stairs anyway. */
X
X		if(u.uhave_amulet || !rn2(3)) {
X		    x = somex(croom); y = somey(croom);
X#ifdef REINCARNATION
X		    if (dlevel == rogue_level)
X			tmonst = makemon(roguemon(), x, y);
X		    else
X#endif
X		    tmonst = makemon((struct permonst *) 0, x,y);
X		    if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER])
X			(void) maketrap (x,y,WEB);
X		}
X		/* put traps and mimics inside */
X		goldseen = FALSE;
X		while(!rn2(8-(dlevel/6))) mktrap(0,0,croom);
X		if(!goldseen && !rn2(3)) mkgold(0L, somex(croom), somey(croom));
X#ifdef REINCARNATION
X		if (dlevel == rogue_level) goto skip_nonrogue;
X#endif
X#ifdef FOUNTAINS
X		if(!rn2(10)) mkfount(0,croom);
X#endif
X#ifdef SINKS
X		if(!rn2(60)) mksink(croom);
X#endif
X#ifdef ALTARS
X		if(!rn2(60)) mkaltar(croom);
X#endif
X		/* put statues inside */
X#ifdef MEDUSA
X		if(!rn2(dlevel == medusa_level ? 1 : 20)) {
X			if (!rn2(dlevel == medusa_level ? 2 : 50))
X				(void) mk_tt_statue(somex(croom), somey(croom));
X			else {
X				struct obj *otmp =
X					mkstatue((struct permonst *)0,
X						somex(croom), somey(croom));
X				if (dlevel == medusa_level && otmp) 
X					otmp->spe = 0;
X				/* Medusa statues don't contain books */
X			}
X		}
X#else
X		if(!rn2(20))
X				(void) mkstatue((struct permonst *)0,
X						somex(croom), somey(croom));
X#endif
X
X		/* put box/chest inside */
X		if(!rn2(20) && !boxinlev) {
X
X		    boxinlev = TRUE;
X		    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
X				     somex(croom), somey(croom));
X		}
X
X#ifdef REINCARNATION
X	skip_nonrogue:
X#endif
X		if(!rn2(3)) {
X			(void) mkobj_at(0, somex(croom), somey(croom));
X			tryct = 0;
X			while(!rn2(5)) {
X				if(++tryct > 100){
X					Printf("tryct overflow4\n");
X					break;
X				}
X				(void) mkobj_at(0, somex(croom), somey(croom));
X			}
X		}
X	}
X}
X
Xvoid
Xmklev()
X{
X	if(getbones()) return;
X
X	in_mklev = TRUE;
X	makelevel();
X	bound_digging();
X	in_mklev = FALSE;
X}
X
Xstatic boolean
Xbydoor(x, y)
Xregister xchar x, y;
X{
X	register boolean tmp1, tmp2;
X
X	/* break up large expression to help some compilers */
X	tmp1 = (IS_DOOR(levl[x+1][y].typ) || levl[x+1][y].typ == SDOOR ||
X		IS_DOOR(levl[x-1][y].typ) || levl[x-1][y].typ == SDOOR);
X	tmp2 = (IS_DOOR(levl[x][y+1].typ) || levl[x][y+1].typ == SDOOR ||
X		IS_DOOR(levl[x][y-1].typ) || levl[x][y-1].typ == SDOOR);
X	return(tmp1 || tmp2);
X}
X
X/* see whether it is allowable to create a door at [x,y] */
Xint
Xokdoor(x,y)
Xregister xchar x, y;
X{
X	register boolean near_door = bydoor(x, y);
X
X	return((levl[x][y].typ == HWALL || levl[x][y].typ == VWALL) &&
X	   		doorindex < DOORMAX && !near_door);
X}
X
Xvoid
Xdodoor(x,y,aroom)
Xregister int x, y;
Xregister struct mkroom *aroom;
X{
X	if(doorindex >= DOORMAX) {
X		impossible("DOORMAX exceeded?");
X		return;
X	}
X	if(!okdoor(x,y) && nxcor)
X		return;
X	dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR);
X}
X
Xstatic boolean
Xoccupied(x, y)
Xregister xchar x, y;
X{
X	return(t_at(x, y) || levl[x][y].typ == STAIRS
X#ifdef FOUNTAINS
X		|| IS_FOUNTAIN(levl[x][y].typ)
X#endif
X#ifdef THRONES
X		|| IS_THRONE(levl[x][y].typ)
X#endif
X#ifdef SINKS
X		|| IS_SINK(levl[x][y].typ)
X#endif
X#ifdef ALTARS
X		|| levl[x][y].typ == ALTAR
X#endif
X		);
X}
X
X/* make a trap somewhere (in croom if mazeflag = 0) */
Xvoid
Xmktrap(num, mazeflag, croom)
Xregister int num, mazeflag;
Xregister struct mkroom *croom;
X{
X	register struct trap *ttmp;
X	register int kind,nomonst,nomimic,nospider,
X#ifdef POLYSELF
X		    nopoly,
X#endif
X		    nospikes, nolevltp,
X		    nolandmine,
X		    tryct = 0;
X
X	xchar mx,my;
X
X	if(!num || num >= TRAPNUM) {
X		nomonst = (dlevel < 4) ? 1 : 0;
X		nolevltp = (dlevel < 5) ? 1 : 0;
X		nospikes = (dlevel < 6) ? 1 : 0;
X		nospider = (dlevel < 7) ? 1 : 0;
X#ifdef POLYSELF
X		nopoly = (dlevel < 6) ? 1 : 0;
X#endif
X		nolandmine = (dlevel < 5) ? 1 : 0;
X		nomimic = (dlevel < 9 || goldseen ) ? 1 : 0;
X		if((mons[PM_SMALL_MIMIC].geno & G_GENOD) &&
X		   (mons[PM_LARGE_MIMIC].geno & G_GENOD) &&
X		   (mons[PM_GIANT_MIMIC].geno & G_GENOD))
X			nomimic = 1;
X		if(mons[PM_GIANT_SPIDER].geno & G_GENOD)
X			nospider = 1;
X
X		do {
X#ifdef REINCARNATION
X		    if (dlevel==rogue_level) {
X			switch(rn2(7)) {
X			     case 0: kind = BEAR_TRAP; break;
X			     case 1: kind = ARROW_TRAP; break;
X			     case 2: kind = DART_TRAP; break;
X			     case 3: kind = TRAPDOOR; break;
X			     case 4: kind = PIT; break;
X			     case 5: kind = SLP_GAS_TRAP; break;
X			     case 6: kind = RUST_TRAP; break;
X			}
X		    } else
X#endif
X			    kind = rnd(TRAPNUM-1);
X		    if((kind == MONST_TRAP && (nomonst && nomimic))
X			|| ((kind == WEB) && nospider)
X			|| (kind == SPIKED_PIT && nospikes)
X			|| (kind == LEVEL_TELEP && nolevltp)
X#ifdef POLYSELF
X			|| (kind == POLY_TRAP && nopoly)
X#endif
X			|| (kind == LANDMINE && nolandmine)
X			)  kind = NO_TRAP;
X		} while(kind == NO_TRAP);
X	} else kind = num;
X
X	if(kind == MONST_TRAP && !nomimic && !rn2(4) && !mazeflag) {
X		register struct monst *mtmp;
X
X		do {
X			if(++tryct > 200) return;
X			/* note: fakedoor maybe on actual door */
X			if(rn2(2)){
X			    if(rn2(2))	mx = croom->hx+1;
X			    else	mx = croom->lx-1;
X			    my = somey(croom);
X			} else {
X			    if(rn2(2))	my = croom->hy+1;
X			    else	my = croom->ly-1;
X			    mx = somex(croom);
X			}
X		} while(levl[mx][my].mmask);
X
X		if((mtmp = makemon(mkclass(S_MIMIC), mx, my))) {
X		    mtmp->mimic = 1;
X		    mtmp->mappearance = DOOR_SYM;
X		}
X		return;
X	}
X
X	do {
X		if(++tryct > 200)
X			return;
X		if(mazeflag){
X			coord mm;
X			mazexy(&mm);
X			mx = mm.x;
X			my = mm.y;
X		} else {
X			mx = somex(croom);
X			my = somey(croom);
X		}
X	} while(occupied(mx, my));
X
X	ttmp = maketrap(mx, my, kind);
X	if (kind == WEB) (void) makemon(&mons[PM_GIANT_SPIDER], mx, my);
X	if(mazeflag && !rn2(10) && ttmp->ttyp < MONST_TRAP)
X		ttmp->tseen = 1;
X}
X
X#ifdef FOUNTAINS
Xvoid
Xmkfount(mazeflag,croom)
Xregister struct mkroom *croom;
Xregister int mazeflag;
X{
X	register xchar mx,my;
X	register int tryct = 0;
X
X	do {
X	    if(++tryct > 200) return;
X	    if(mazeflag) {
X		 coord mm;
X		 mazexy(&mm);
X		 mx = mm.x;
X		 my = mm.y;
X	    } else {
X		 mx = somex(croom);
X		 my = somey(croom);
X	    }
X	} while(occupied(mx, my) || bydoor(mx, my));
X
X	/* Put a fountain at mx, my */
X	levl[mx][my].typ = FOUNTAIN;
X	levl[mx][my].scrsym = FOUNTAIN_SYM;
X
X	fountsound++;
X}
X#endif /* FOUNTAINS /**/
X
X#ifdef SINKS
Xstatic void
Xmksink(croom)
Xregister struct mkroom *croom;
X{
X	register xchar mx,my;
X	register int tryct = 0;
X
X	do {
X	    if(++tryct > 200) return;
X	    mx = somex(croom);
X	    my = somey(croom);
X	} while(occupied(mx, my) || bydoor(mx, my));
X
X	/* Put a sink at mx, my */
X	levl[mx][my].typ = SINK;
X	levl[mx][my].scrsym = SINK_SYM;
X
X	sinksound++;
X}
X#endif /* SINKS /**/
X
X
X#ifdef ALTARS
Xstatic void
Xmkaltar(croom)
Xregister struct mkroom *croom;
X{
X	register xchar mx,my;
X	register int tryct = 0;
X
X	if(croom->rtype != OROOM) return;
X
X	do {
X	    if(++tryct > 200) return;
X	    mx = somex(croom);
X	    my = somey(croom);
X	} while(occupied(mx, my) || bydoor(mx, my));
X
X	/* Put an altar at mx, my */
X	levl[mx][my].typ = ALTAR;
X	levl[mx][my].scrsym = ALTAR_SYM;
X	/* 0 - A_CHAOS, 1 - A_NEUTRAL, 2 - A_LAW */
X	levl[mx][my].altarmask = rn2((int)A_LAW+1);
X}
X#endif /* ALTARS /**/
END_OF_FILE
if test 27014 -ne `wc -c <'src/mklev.c'`; then
    echo shar: \"'src/mklev.c'\" unpacked with wrong size!
fi
# end of 'src/mklev.c'
fi
echo shar: End of archive 20 \(of 38\).
cp /dev/null ark20isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 38 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0