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