# Source:NetHack 3.6.1/src/sp lev.c
Below is the full text to sp_lev.c from the source code of NetHack 3.6.1. To link to a particular line, write [[Source:NetHack 3.6.1/src/sp_lev.c#line123]], for example.

Contents

1 Top of file
2 solidify_map
3 splev_stack_init
4 splev_stack_done
5 splev_stack_push
6 splev_stack_pop
7 splev_stack_reverse
8 opvar_new_str
9 opvar_new_int
10 opvar_new_coord
11 opvar_free_x
12 opvar_clone
13 opvar_var_conversion
14 opvar_var_defined
15 splev_stack_getdat
16 splev_stack_getdat_any
17 variable_list_del
18 lvlfill_maze_grid
19 lvlfill_solid
20 set_wall_property
21 shuffle_alignments
22 count_features
23 remove_boundary_syms
24 set_door_orientation
25 maybe_add_door
26 link_doors_rooms
27 fill_rooms
28 rnddoor
29 rndtrap
30 get_location
31 is_ok_location
32 get_unpacked_coord
33 get_location_coord
34 get_room_loc
35 get_free_room_loc
36 check_room
37 create_room
38 create_subroom
39 create_door
40 create_secret_door
41 create_trap
42 noncoalignment
43 m_bad_boulder_spot
44 pm_to_humidity
45 create_monster
46 create_object
47 create_altar
48 replace_terrain
49 search_door
50 dig_corridor
51 fix_stair_rooms
52 create_corridor
53 fill_room
54 build_room
55 light_region
56 wallify_map
57 maze1xy
58 fill_empty_maze
59 sp_level_loader
60 sp_level_free
61 splev_initlev
62 frame_new
63 frame_del
64 spo_frame_push
65 spo_frame_pop
66 sp_code_jmpaddr
67 spo_call
68 spo_return
69 spo_end_moninvent
70 spo_pop_container
71 spo_message
72 spo_monster
73 spo_object
74 spo_level_flags
75 spo_initlevel
76 spo_engraving
77 spo_mineralize
78 spo_room
79 spo_endroom
80 spo_stair
81 spo_ladder
82 spo_grave
83 spo_altar
84 spo_trap
85 spo_gold
86 spo_corridor
87 selection_opvar
88 selection_getpoint
89 selection_setpoint
90 selection_not
91 selection_logical_oper
92 selection_filter_mapchar
93 selection_filter_percent
94 selection_rndcoord
95 selection_do_grow
96 set_selection_floodfillchk
97 floodfillchk_match_under
98 floodfillchk_match_accessible
99 selection_floodfill
100 selection_do_ellipse
101 line_dist_coord
102 selection_do_gradient
103 selection_do_line
104 selection_do_randline
105 selection_iterate
106 sel_set_ter
107 sel_set_feature
108 sel_set_door
109 spo_door
110 spo_feature
111 spo_terrain
112 spo_replace_terrain
113 generate_way_out_method
114 ensure_way_out
115 spo_levregion
116 spo_region
117 spo_drawbridge
118 spo_mazewalk
119 spo_wall_property
120 spo_room_door
121 sel_set_wallify
122 spo_wallify
123 spo_map
124 spo_jmp
125 spo_conditional_jump
126 spo_var_init
127 spo_shuffle_array
128 sp_level_coder
129 load_special

Top of file
&nbsp;/* NetHack 3.6	sp_lev.c	$NHDT-Date: 1524287226 2018/04/21 05:07:06 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
&nbsp;/*      Copyright (c) 1989 by Jean-Christophe Collet */
&nbsp;/* NetHack may be freely redistributed.  See license for details. */

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

&nbsp;
&nbsp;/*
&nbsp; * This file contains the various functions that are related to the special
&nbsp; * levels.
&nbsp; *
&nbsp; * It contains also the special level loader.
&nbsp; */
&nbsp;
&nbsp;#include "hack.h"
&nbsp;#include "dlb.h"
&nbsp;#include "sp_lev.h"
&nbsp;
&nbsp;#ifdef _MSC_VER
&nbsp; #pragma warning(push)
&nbsp; #pragma warning(disable : 4244)
&nbsp;#endif
&nbsp;
&nbsp;typedef void FDECL((*select_iter_func), (int, int, genericptr));
&nbsp;
&nbsp;extern void FDECL(mkmap, (lev_init *));
&nbsp;
&nbsp;STATIC_DCL void NDECL(solidify_map);
&nbsp;STATIC_DCL void FDECL(splev_stack_init, (struct splevstack *));
&nbsp;STATIC_DCL void FDECL(splev_stack_done, (struct splevstack *));
&nbsp;STATIC_DCL void FDECL(splev_stack_push, (struct splevstack *,
&nbsp;                                         struct opvar *));
&nbsp;STATIC_DCL struct opvar *FDECL(splev_stack_pop, (struct splevstack *));
&nbsp;STATIC_DCL struct splevstack *FDECL(splev_stack_reverse,
&nbsp;                                    (struct splevstack *));
&nbsp;STATIC_DCL struct opvar *FDECL(opvar_new_str, (char *));
&nbsp;STATIC_DCL struct opvar *FDECL(opvar_new_int, (long));
&nbsp;STATIC_DCL struct opvar *FDECL(opvar_new_coord, (int, int));
&nbsp;#if 0
&nbsp;STATIC_DCL struct opvar * FDECL(opvar_new_region, (int,int, int,int));
&nbsp;#endif /*0*/
&nbsp;STATIC_DCL struct opvar *FDECL(opvar_clone, (struct opvar *));
&nbsp;STATIC_DCL struct opvar *FDECL(opvar_var_conversion, (struct sp_coder *,
&nbsp;                                                      struct opvar *));
&nbsp;STATIC_DCL struct splev_var *FDECL(opvar_var_defined, (struct sp_coder *,
&nbsp;                                                       char *));
&nbsp;STATIC_DCL struct opvar *FDECL(splev_stack_getdat, (struct sp_coder *,
&nbsp;                                                    XCHAR_P));
&nbsp;STATIC_DCL struct opvar *FDECL(splev_stack_getdat_any, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(variable_list_del, (struct splev_var *));
&nbsp;STATIC_DCL void FDECL(lvlfill_maze_grid, (int, int, int, int, SCHAR_P));
&nbsp;STATIC_DCL void FDECL(lvlfill_solid, (SCHAR_P, SCHAR_P));
&nbsp;STATIC_DCL void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
&nbsp;                                          int));
&nbsp;STATIC_DCL void NDECL(shuffle_alignments);
&nbsp;STATIC_DCL void NDECL(count_features);
&nbsp;STATIC_DCL void NDECL(remove_boundary_syms);
&nbsp;STATIC_DCL void FDECL(set_door_orientation, (int, int));
&nbsp;STATIC_DCL void FDECL(maybe_add_door, (int, int, struct mkroom *));
&nbsp;STATIC_DCL void NDECL(link_doors_rooms);
&nbsp;STATIC_DCL void NDECL(fill_rooms);
&nbsp;STATIC_DCL int NDECL(rnddoor);
&nbsp;STATIC_DCL int NDECL(rndtrap);
&nbsp;STATIC_DCL void FDECL(get_location, (schar *, schar *, int, struct mkroom *));
&nbsp;STATIC_DCL boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
&nbsp;STATIC_DCL unpacked_coord FDECL(get_unpacked_coord, (long, int));
&nbsp;STATIC_DCL void FDECL(get_location_coord, (schar *, schar *, int,
&nbsp;                                           struct mkroom *, long));
&nbsp;STATIC_DCL void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
&nbsp;STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *,
&nbsp;                                          struct mkroom *, packed_coord));
&nbsp;STATIC_DCL boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
&nbsp;                                          XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
&nbsp;STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
&nbsp;STATIC_DCL void FDECL(create_trap, (spltrap *, struct mkroom *));
&nbsp;STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P));
&nbsp;STATIC_DCL boolean FDECL(m_bad_boulder_spot, (int, int));
&nbsp;STATIC_DCL int FDECL(pm_to_humidity, (struct permonst *));
&nbsp;STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *));
&nbsp;STATIC_DCL void FDECL(create_object, (object *, struct mkroom *));
&nbsp;STATIC_DCL void FDECL(create_altar, (altar *, struct mkroom *));
&nbsp;STATIC_DCL void FDECL(replace_terrain, (replaceterrain *, struct mkroom *));
&nbsp;STATIC_DCL boolean FDECL(search_door, (struct mkroom *,
&nbsp;                                       xchar *, xchar *, XCHAR_P, int));
&nbsp;STATIC_DCL void NDECL(fix_stair_rooms);
&nbsp;STATIC_DCL void FDECL(create_corridor, (corridor *));
&nbsp;STATIC_DCL struct mkroom *FDECL(build_room, (room *, struct mkroom *));
&nbsp;STATIC_DCL void FDECL(light_region, (region *));
&nbsp;STATIC_DCL void FDECL(wallify_map, (int, int, int, int));
&nbsp;STATIC_DCL void FDECL(maze1xy, (coord *, int));
&nbsp;STATIC_DCL void NDECL(fill_empty_maze);
&nbsp;STATIC_DCL boolean FDECL(sp_level_loader, (dlb *, sp_lev *));
&nbsp;STATIC_DCL boolean FDECL(sp_level_free, (sp_lev *));
&nbsp;STATIC_DCL void FDECL(splev_initlev, (lev_init *));
&nbsp;STATIC_DCL struct sp_frame *FDECL(frame_new, (long));
&nbsp;STATIC_DCL void FDECL(frame_del, (struct sp_frame *));
&nbsp;STATIC_DCL void FDECL(spo_frame_push, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_frame_pop, (struct sp_coder *));
&nbsp;STATIC_DCL long FDECL(sp_code_jmpaddr, (long, long));
&nbsp;STATIC_DCL void FDECL(spo_call, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_return, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_end_moninvent, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_pop_container, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_message, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_monster, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_object, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_level_flags, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_initlevel, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_engraving, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_mineralize, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_room, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_endroom, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_stair, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_ladder, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_grave, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_altar, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_trap, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_gold, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_corridor, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(selection_setpoint, (int, int, struct opvar *, XCHAR_P));
&nbsp;STATIC_DCL struct opvar *FDECL(selection_not, (struct opvar *));
&nbsp;STATIC_DCL struct opvar *FDECL(selection_logical_oper, (struct opvar *,
&nbsp;                                                     struct opvar *, CHAR_P));
&nbsp;STATIC_DCL struct opvar *FDECL(selection_filter_mapchar, (struct opvar *,
&nbsp;                                                          struct opvar *));
&nbsp;STATIC_DCL void FDECL(selection_filter_percent, (struct opvar *, int));
&nbsp;STATIC_DCL int FDECL(selection_rndcoord, (struct opvar *, schar *, schar *,
&nbsp;                                          BOOLEAN_P));
&nbsp;STATIC_DCL void FDECL(selection_do_grow, (struct opvar *, int));
&nbsp;STATIC_DCL int FDECL(floodfillchk_match_under, (int, int));
&nbsp;STATIC_DCL int FDECL(floodfillchk_match_accessible, (int, int));
&nbsp;STATIC_DCL void FDECL(selection_do_ellipse, (struct opvar *, int, int,
&nbsp;                                             int, int, int));
&nbsp;STATIC_DCL long FDECL(line_dist_coord, (long, long, long, long, long, long));
&nbsp;STATIC_DCL void FDECL(selection_do_gradient, (struct opvar *, long, long, long,
&nbsp;                                              long, long, long, long, long));
&nbsp;STATIC_DCL void FDECL(selection_do_line, (SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P,
&nbsp;                                          struct opvar *));
&nbsp;STATIC_DCL void FDECL(selection_do_randline, (SCHAR_P, SCHAR_P, SCHAR_P,
&nbsp;                                              SCHAR_P, SCHAR_P, SCHAR_P,
&nbsp;                                              struct opvar *));
&nbsp;STATIC_DCL void FDECL(selection_iterate, (struct opvar *, select_iter_func,
&nbsp;                                          genericptr_t));
&nbsp;STATIC_DCL void FDECL(sel_set_ter, (int, int, genericptr_t));
&nbsp;STATIC_DCL void FDECL(sel_set_feature, (int, int, genericptr_t));
&nbsp;STATIC_DCL void FDECL(sel_set_door, (int, int, genericptr_t));
&nbsp;STATIC_DCL void FDECL(spo_door, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_feature, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_terrain, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_replace_terrain, (struct sp_coder *));
&nbsp;STATIC_DCL boolean FDECL(generate_way_out_method, (int, int, struct opvar *));
&nbsp;STATIC_DCL void NDECL(ensure_way_out);
&nbsp;STATIC_DCL void FDECL(spo_levregion, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_region, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_drawbridge, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_mazewalk, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_wall_property, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_room_door, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(sel_set_wallify, (int, int, genericptr_t));
&nbsp;STATIC_DCL void FDECL(spo_wallify, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_map, (struct sp_coder *));
&nbsp;STATIC_DCL void FDECL(spo_jmp, (struct sp_coder *, sp_lev *));
&nbsp;STATIC_DCL void FDECL(spo_conditional_jump, (struct sp_coder *, sp_lev *));
&nbsp;STATIC_DCL void FDECL(spo_var_init, (struct sp_coder *));
&nbsp;#if 0
&nbsp;STATIC_DCL long FDECL(opvar_array_length, (struct sp_coder *));
&nbsp;#endif /*0*/
&nbsp;STATIC_DCL void FDECL(spo_shuffle_array, (struct sp_coder *));
&nbsp;STATIC_DCL boolean FDECL(sp_level_coder, (sp_lev *));
&nbsp;
&nbsp;#define LEFT 1
&nbsp;#define H_LEFT 2
&nbsp;#define CENTER 3
&nbsp;#define H_RIGHT 4
&nbsp;#define RIGHT 5
&nbsp;
&nbsp;#define TOP 1
&nbsp;#define BOTTOM 5
&nbsp;
&nbsp;#define sq(x) ((x) * (x))
&nbsp;
&nbsp;#define XLIM 4
&nbsp;#define YLIM 3
&nbsp;
&nbsp;#define Fread (void) dlb_fread
&nbsp;#define Fgetc (schar) dlb_fgetc
&nbsp;#define New(type) (type *) alloc(sizeof(type))
&nbsp;#define NewTab(type, size) (type **) alloc(sizeof(type *) * (unsigned) size)
&nbsp;#define Free(ptr) if (ptr) free((genericptr_t) (ptr))
&nbsp;
&nbsp;extern struct engr *head_engr;
&nbsp;
&nbsp;extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
&nbsp;
&nbsp;/* positions touched by level elements explicitly defined in the des-file */
&nbsp;static char SpLev_Map[COLNO][ROWNO];
&nbsp;
&nbsp;static aligntyp ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
&nbsp;static NEARDATA xchar xstart, ystart;
&nbsp;static NEARDATA char xsize, ysize;
&nbsp;
&nbsp;char *lev_message = 0;
&nbsp;lev_region *lregions = 0;
&nbsp;int num_lregions = 0;
&nbsp;
&nbsp;static boolean splev_init_present = FALSE;
&nbsp;static boolean icedpools = FALSE;
&nbsp;static int mines_prize_count = 0, soko_prize_count = 0; /* achievements */
&nbsp;
&nbsp;static struct obj *container_obj[MAX_CONTAINMENT];
&nbsp;static int container_idx = 0;
&nbsp;static struct monst *invent_carrying_monster = NULL;
&nbsp;
&nbsp;#define SPLEV_STACK_RESERVE 128
&nbsp;
solidify_map
&nbsp;void
&nbsp;solidify_map()
&nbsp;{
&nbsp;    xchar x, y;
&nbsp;
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++)
&nbsp;            if (IS_STWALL(levl[x][y].typ) &amp;&amp; !SpLev_Map[x][y])
&nbsp;                levl[x][y].wall_info |= (W_NONDIGGABLE | W_NONPASSWALL);
&nbsp;}
&nbsp;
splev_stack_init
&nbsp;void
&nbsp;splev_stack_init(st)
&nbsp;struct splevstack *st;
&nbsp;{
&nbsp;    if (st) {
&nbsp;        st-&gt;depth = 0;
&nbsp;        st-&gt;depth_alloc = SPLEV_STACK_RESERVE;
&nbsp;        st-&gt;stackdata =
&nbsp;            (struct opvar **) alloc(st-&gt;depth_alloc * sizeof(struct opvar *));
&nbsp;    }
&nbsp;}
&nbsp;
splev_stack_done
&nbsp;void
&nbsp;splev_stack_done(st)
&nbsp;struct splevstack *st;
&nbsp;{
&nbsp;    if (st) {
&nbsp;        int i;
&nbsp;
&nbsp;        if (st-&gt;stackdata &amp;&amp; st-&gt;depth) {
&nbsp;            for (i = 0; i &lt; st-&gt;depth; i++) {
&nbsp;                switch (st-&gt;stackdata[i]-&gt;spovartyp) {
&nbsp;                default:
&nbsp;                case SPOVAR_NULL:
&nbsp;                case SPOVAR_COORD:
&nbsp;                case SPOVAR_REGION:
&nbsp;                case SPOVAR_MAPCHAR:
&nbsp;                case SPOVAR_MONST:
&nbsp;                case SPOVAR_OBJ:
&nbsp;                case SPOVAR_INT:
&nbsp;                    break;
&nbsp;                case SPOVAR_VARIABLE:
&nbsp;                case SPOVAR_STRING:
&nbsp;                case SPOVAR_SEL:
&nbsp;                    Free(st-&gt;stackdata[i]-&gt;vardata.str);
&nbsp;                    st-&gt;stackdata[i]-&gt;vardata.str = NULL;
&nbsp;                    break;
&nbsp;                }
&nbsp;                Free(st-&gt;stackdata[i]);
&nbsp;                st-&gt;stackdata[i] = NULL;
&nbsp;            }
&nbsp;        }
&nbsp;        Free(st-&gt;stackdata);
&nbsp;        st-&gt;stackdata = NULL;
&nbsp;        st-&gt;depth = st-&gt;depth_alloc = 0;
&nbsp;        Free(st);
&nbsp;    }
&nbsp;}
&nbsp;
splev_stack_push
&nbsp;void
&nbsp;splev_stack_push(st, v)
&nbsp;struct splevstack *st;
&nbsp;struct opvar *v;
&nbsp;{
&nbsp;    if (!st || !v)
&nbsp;        return;
&nbsp;    if (!st-&gt;stackdata)
&nbsp;        panic("splev_stack_push: no stackdata allocated?");
&nbsp;
&nbsp;    if (st-&gt;depth &gt;= st-&gt;depth_alloc) {
&nbsp;        struct opvar **tmp = (struct opvar **) alloc(
&nbsp;            (st-&gt;depth_alloc + SPLEV_STACK_RESERVE) * sizeof(struct opvar *));
&nbsp;
&nbsp;        (void) memcpy(tmp, st-&gt;stackdata,
&nbsp;                      st-&gt;depth_alloc * sizeof(struct opvar *));
&nbsp;        Free(st-&gt;stackdata);
&nbsp;        st-&gt;stackdata = tmp;
&nbsp;        st-&gt;depth_alloc += SPLEV_STACK_RESERVE;
&nbsp;    }
&nbsp;
&nbsp;    st-&gt;stackdata[st-&gt;depth] = v;
&nbsp;    st-&gt;depth++;
&nbsp;}
&nbsp;
splev_stack_pop
&nbsp;struct opvar *
&nbsp;splev_stack_pop(st)
&nbsp;struct splevstack *st;
&nbsp;{
&nbsp;    struct opvar *ret = NULL;
&nbsp;
&nbsp;    if (!st)
&nbsp;        return ret;
&nbsp;    if (!st-&gt;stackdata)
&nbsp;        panic("splev_stack_pop: no stackdata allocated?");
&nbsp;
&nbsp;    if (st-&gt;depth) {
&nbsp;        st-&gt;depth--;
&nbsp;        ret = st-&gt;stackdata[st-&gt;depth];
&nbsp;        st-&gt;stackdata[st-&gt;depth] = NULL;
&nbsp;        return ret;
&nbsp;    } else
&nbsp;        impossible("splev_stack_pop: empty stack?");
&nbsp;    return ret;
&nbsp;}
&nbsp;
splev_stack_reverse
&nbsp;struct splevstack *
&nbsp;splev_stack_reverse(st)
&nbsp;struct splevstack *st;
&nbsp;{
&nbsp;    long i;
&nbsp;    struct opvar *tmp;
&nbsp;
&nbsp;    if (!st)
&nbsp;        return NULL;
&nbsp;    if (!st-&gt;stackdata)
&nbsp;        panic("splev_stack_reverse: no stackdata allocated?");
&nbsp;    for (i = 0; i &lt; (st-&gt;depth / 2); i++) {
&nbsp;        tmp = st-&gt;stackdata[i];
&nbsp;        st-&gt;stackdata[i] = st-&gt;stackdata[st-&gt;depth - i - 1];
&nbsp;        st-&gt;stackdata[st-&gt;depth - i - 1] = tmp;
&nbsp;    }
&nbsp;    return st;
&nbsp;}
&nbsp;
&nbsp;#define OV_typ(o) (o-&gt;spovartyp)
&nbsp;#define OV_i(o) (o-&gt;vardata.l)
&nbsp;#define OV_s(o) (o-&gt;vardata.str)
&nbsp;
&nbsp;#define OV_pop_i(x) (x = splev_stack_getdat(coder, SPOVAR_INT))
&nbsp;#define OV_pop_c(x) (x = splev_stack_getdat(coder, SPOVAR_COORD))
&nbsp;#define OV_pop_r(x) (x = splev_stack_getdat(coder, SPOVAR_REGION))
&nbsp;#define OV_pop_s(x) (x = splev_stack_getdat(coder, SPOVAR_STRING))
&nbsp;#define OV_pop(x) (x = splev_stack_getdat_any(coder))
&nbsp;#define OV_pop_typ(x, typ) (x = splev_stack_getdat(coder, typ))
&nbsp;
opvar_new_str
&nbsp;struct opvar *
&nbsp;opvar_new_str(s)
&nbsp;char *s;
&nbsp;{
&nbsp;    struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
&nbsp;
&nbsp;    tmpov-&gt;spovartyp = SPOVAR_STRING;
&nbsp;    if (s) {
&nbsp;        int len = strlen(s);
&nbsp;        tmpov-&gt;vardata.str = (char *) alloc(len + 1);
&nbsp;        (void) memcpy((genericptr_t) tmpov-&gt;vardata.str, (genericptr_t) s,
&nbsp;                      len);
&nbsp;        tmpov-&gt;vardata.str[len] = '\0';
&nbsp;    } else
&nbsp;        tmpov-&gt;vardata.str = NULL;
&nbsp;    return tmpov;
&nbsp;}
&nbsp;
opvar_new_int
&nbsp;struct opvar *
&nbsp;opvar_new_int(i)
&nbsp;long i;
&nbsp;{
&nbsp;    struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
&nbsp;
&nbsp;    tmpov-&gt;spovartyp = SPOVAR_INT;
&nbsp;    tmpov-&gt;vardata.l = i;
&nbsp;    return tmpov;
&nbsp;}
&nbsp;
opvar_new_coord
&nbsp;struct opvar *
&nbsp;opvar_new_coord(x, y)
&nbsp;int x, y;
&nbsp;{
&nbsp;    struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
&nbsp;
&nbsp;    tmpov-&gt;spovartyp = SPOVAR_COORD;
&nbsp;    tmpov-&gt;vardata.l = SP_COORD_PACK(x, y);
&nbsp;    return tmpov;
&nbsp;}
&nbsp;
&nbsp;#if 0
&nbsp;struct opvar *
&nbsp;opvar_new_region(x1,y1,x2,y2)
&nbsp;     int x1,y1,x2,y2;
&nbsp;{
&nbsp;    struct opvar *tmpov = (struct opvar *)alloc(sizeof (struct opvar));
&nbsp;
&nbsp;    tmpov-&gt;spovartyp = SPOVAR_REGION;
&nbsp;    tmpov-&gt;vardata.l = SP_REGION_PACK(x1,y1,x2,y2);
&nbsp;    return tmpov;
&nbsp;}
&nbsp;#endif /*0*/
&nbsp;
opvar_free_x
&nbsp;void
&nbsp;opvar_free_x(ov)
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    if (!ov)
&nbsp;        return;
&nbsp;    switch (ov-&gt;spovartyp) {
&nbsp;    case SPOVAR_COORD:
&nbsp;    case SPOVAR_REGION:
&nbsp;    case SPOVAR_MAPCHAR:
&nbsp;    case SPOVAR_MONST:
&nbsp;    case SPOVAR_OBJ:
&nbsp;    case SPOVAR_INT:
&nbsp;        break;
&nbsp;    case SPOVAR_VARIABLE:
&nbsp;    case SPOVAR_STRING:
&nbsp;    case SPOVAR_SEL:
&nbsp;        Free(ov-&gt;vardata.str);
&nbsp;        break;
&nbsp;    default:
&nbsp;        impossible("Unknown opvar value type (%i)!", ov-&gt;spovartyp);
&nbsp;    }
&nbsp;    Free(ov);
&nbsp;}
&nbsp;
&nbsp;/*
&nbsp; * Name of current function for use in messages:
&nbsp; * __func__     -- C99 standard;
&nbsp; * __FUNCTION__ -- gcc extension, starting before C99 and continuing after;
&nbsp; *                 picked up by other compilers (or vice versa?);
&nbsp; * __FUNC__     -- supported by Borland;
&nbsp; * nhFunc       -- slightly intrusive but fully portable nethack construct
&nbsp; *                 for any version of any compiler.
&nbsp; */
&nbsp;#define opvar_free(ov)                                    \
&nbsp;    do {                                                  \
&nbsp;        if (ov) {                                         \
&nbsp;            opvar_free_x(ov);                             \
&nbsp;            ov = NULL;                                    \
&nbsp;        } else                                            \
&nbsp;            impossible("opvar_free(), %s", nhFunc);       \
&nbsp;    } while (0)
&nbsp;
opvar_clone
&nbsp;struct opvar *
&nbsp;opvar_clone(ov)
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    struct opvar *tmpov;
&nbsp;
&nbsp;    if (!ov)
&nbsp;        panic("no opvar to clone");
&nbsp;    tmpov = (struct opvar *) alloc(sizeof(struct opvar));
&nbsp;    tmpov-&gt;spovartyp = ov-&gt;spovartyp;
&nbsp;    switch (ov-&gt;spovartyp) {
&nbsp;    case SPOVAR_COORD:
&nbsp;    case SPOVAR_REGION:
&nbsp;    case SPOVAR_MAPCHAR:
&nbsp;    case SPOVAR_MONST:
&nbsp;    case SPOVAR_OBJ:
&nbsp;    case SPOVAR_INT:
&nbsp;        tmpov-&gt;vardata.l = ov-&gt;vardata.l;
&nbsp;        break;
&nbsp;    case SPOVAR_VARIABLE:
&nbsp;    case SPOVAR_STRING:
&nbsp;    case SPOVAR_SEL:
&nbsp;        tmpov-&gt;vardata.str = dupstr(ov-&gt;vardata.str);
&nbsp;        break;
&nbsp;    default:
&nbsp;        impossible("Unknown push value type (%i)!", ov-&gt;spovartyp);
&nbsp;    }
&nbsp;    return tmpov;
&nbsp;}
&nbsp;
opvar_var_conversion
&nbsp;struct opvar *
&nbsp;opvar_var_conversion(coder, ov)
&nbsp;struct sp_coder *coder;
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    static const char nhFunc[] = "opvar_var_conversion";
&nbsp;    struct splev_var *tmp;
&nbsp;    struct opvar *tmpov;
&nbsp;    struct opvar *array_idx = NULL;
&nbsp;
&nbsp;    if (!coder || !ov)
&nbsp;        return NULL;
&nbsp;    if (ov-&gt;spovartyp != SPOVAR_VARIABLE)
&nbsp;        return ov;
&nbsp;    tmp = coder-&gt;frame-&gt;variables;
&nbsp;    while (tmp) {
&nbsp;        if (!strcmp(tmp-&gt;name, OV_s(ov))) {
&nbsp;            if ((tmp-&gt;svtyp &amp; SPOVAR_ARRAY)) {
&nbsp;                array_idx = opvar_var_conversion(coder,
&nbsp;                                               splev_stack_pop(coder-&gt;stack));
&nbsp;                if (!array_idx || OV_typ(array_idx) != SPOVAR_INT)
&nbsp;                    panic("array idx not an int");
&nbsp;                if (tmp-&gt;array_len &lt; 1)
&nbsp;                    panic("array len &lt; 1");
&nbsp;                OV_i(array_idx) = (OV_i(array_idx) % tmp-&gt;array_len);
&nbsp;                tmpov = opvar_clone(tmp-&gt;data.arrayvalues[OV_i(array_idx)]);
&nbsp;                opvar_free(array_idx);
&nbsp;                return tmpov;
&nbsp;            } else {
&nbsp;                tmpov = opvar_clone(tmp-&gt;data.value);
&nbsp;                return tmpov;
&nbsp;            }
&nbsp;        }
&nbsp;        tmp = tmp-&gt;next;
&nbsp;    }
&nbsp;    return NULL;
&nbsp;}
&nbsp;
opvar_var_defined
&nbsp;struct splev_var *
&nbsp;opvar_var_defined(coder, name)
&nbsp;struct sp_coder *coder;
&nbsp;char *name;
&nbsp;{
&nbsp;    struct splev_var *tmp;
&nbsp;
&nbsp;    if (!coder)
&nbsp;        return NULL;
&nbsp;    tmp = coder-&gt;frame-&gt;variables;
&nbsp;    while (tmp) {
&nbsp;        if (!strcmp(tmp-&gt;name, name))
&nbsp;            return tmp;
&nbsp;        tmp = tmp-&gt;next;
&nbsp;    }
&nbsp;    return NULL;
&nbsp;}
&nbsp;
splev_stack_getdat
&nbsp;struct opvar *
&nbsp;splev_stack_getdat(coder, typ)
&nbsp;struct sp_coder *coder;
&nbsp;xchar typ;
&nbsp;{
&nbsp;    static const char nhFunc[] = "splev_stack_getdat";
&nbsp;    if (coder &amp;&amp; coder-&gt;stack) {
&nbsp;        struct opvar *tmp = splev_stack_pop(coder-&gt;stack);
&nbsp;        struct opvar *ret = NULL;
&nbsp;
&nbsp;        if (!tmp)
&nbsp;            panic("no value type %i in stack.", typ);
&nbsp;        if (tmp-&gt;spovartyp == SPOVAR_VARIABLE) {
&nbsp;            ret = opvar_var_conversion(coder, tmp);
&nbsp;            opvar_free(tmp);
&nbsp;            tmp = ret;
&nbsp;        }
&nbsp;        if (tmp-&gt;spovartyp == typ)
&nbsp;            return tmp;
&nbsp;        else opvar_free(tmp);
&nbsp;    }
&nbsp;    return NULL;
&nbsp;}
&nbsp;
splev_stack_getdat_any
&nbsp;struct opvar *
&nbsp;splev_stack_getdat_any(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "splev_stack_getdat_any";
&nbsp;    if (coder &amp;&amp; coder-&gt;stack) {
&nbsp;        struct opvar *tmp = splev_stack_pop(coder-&gt;stack);
&nbsp;        if (tmp &amp;&amp; tmp-&gt;spovartyp == SPOVAR_VARIABLE) {
&nbsp;            struct opvar *ret = opvar_var_conversion(coder, tmp);
&nbsp;            opvar_free(tmp);
&nbsp;            return ret;
&nbsp;        }
&nbsp;        return tmp;
&nbsp;    }
&nbsp;    return NULL;
&nbsp;}
&nbsp;
variable_list_del
&nbsp;void
&nbsp;variable_list_del(varlist)
&nbsp;struct splev_var *varlist;
&nbsp;{
&nbsp;    static const char nhFunc[] = "variable_list_del";
&nbsp;    struct splev_var *tmp = varlist;
&nbsp;
&nbsp;    if (!tmp)
&nbsp;        return;
&nbsp;    while (tmp) {
&nbsp;        Free(tmp-&gt;name);
&nbsp;        if ((tmp-&gt;svtyp &amp; SPOVAR_ARRAY)) {
&nbsp;            long idx = tmp-&gt;array_len;
&nbsp;
&nbsp;            while (idx-- &gt; 0) {
&nbsp;                opvar_free(tmp-&gt;data.arrayvalues[idx]);
&nbsp;            };
&nbsp;            Free(tmp-&gt;data.arrayvalues);
&nbsp;        } else {
&nbsp;            opvar_free(tmp-&gt;data.value);
&nbsp;        }
&nbsp;        tmp = varlist-&gt;next;
&nbsp;        Free(varlist);
&nbsp;        varlist = tmp;
&nbsp;    }
&nbsp;}
&nbsp;
lvlfill_maze_grid
&nbsp;void
&nbsp;lvlfill_maze_grid(x1, y1, x2, y2, filling)
&nbsp;int x1, y1, x2, y2;
&nbsp;schar filling;
&nbsp;{
&nbsp;    int x, y;
&nbsp;
&nbsp;    for (x = x1; x &lt;= x2; x++)
&nbsp;        for (y = y1; y &lt;= y2; y++) {
&nbsp;            if (level.flags.corrmaze)
&nbsp;                levl[x][y].typ = STONE;
&nbsp;            else
&nbsp;                levl[x][y].typ = (y &lt; 2 || ((x % 2) &amp;&amp; (y % 2))) ? STONE
&nbsp;                                                                 : filling;
&nbsp;        }
&nbsp;}
&nbsp;
lvlfill_solid
&nbsp;void
&nbsp;lvlfill_solid(filling, lit)
&nbsp;schar filling;
&nbsp;schar lit;
&nbsp;{
&nbsp;    int x, y;
&nbsp;    for (x = 2; x &lt;= x_maze_max; x++)
&nbsp;        for (y = 0; y &lt;= y_maze_max; y++) {
&nbsp;            SET_TYPLIT(x, y, filling, lit);
&nbsp;        }
&nbsp;}
&nbsp;
set_wall_property
&nbsp;/*
&nbsp; * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;set_wall_property(x1, y1, x2, y2, prop)
&nbsp;xchar x1, y1, x2, y2;
&nbsp;int prop;
&nbsp;{
&nbsp;    register xchar x, y;
&nbsp;
&nbsp;    for (y = max(y1, 0); y &lt;= min(y2, ROWNO - 1); y++)
&nbsp;        for (x = max(x1, 0); x &lt;= min(x2, COLNO - 1); x++)
&nbsp;            if (IS_STWALL(levl[x][y].typ) || IS_TREE(levl[x][y].typ))
&nbsp;                levl[x][y].wall_info |= prop;
&nbsp;}
&nbsp;
shuffle_alignments
&nbsp;STATIC_OVL void
&nbsp;shuffle_alignments()
&nbsp;{
&nbsp;    int i;
&nbsp;    aligntyp atmp;
&nbsp;
&nbsp;    /* shuffle 3 alignments */
&nbsp;    i = rn2(3);
&nbsp;    atmp = ralign[2];
&nbsp;    ralign[2] = ralign[i];
&nbsp;    ralign[i] = atmp;
&nbsp;    if (rn2(2)) {
&nbsp;        atmp = ralign[1];
&nbsp;        ralign[1] = ralign[0];
&nbsp;        ralign[0] = atmp;
&nbsp;    }
&nbsp;}
&nbsp;
count_features
&nbsp;/*
&nbsp; * Count the different features (sinks, fountains) in the level.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;count_features()
&nbsp;{
&nbsp;    xchar x, y;
&nbsp;
&nbsp;    level.flags.nfountains = level.flags.nsinks = 0;
&nbsp;    for (y = 0; y &lt; ROWNO; y++)
&nbsp;        for (x = 0; x &lt; COLNO; x++) {
&nbsp;            int typ = levl[x][y].typ;
&nbsp;            if (typ == FOUNTAIN)
&nbsp;                level.flags.nfountains++;
&nbsp;            else if (typ == SINK)
&nbsp;                level.flags.nsinks++;
&nbsp;        }
&nbsp;}
&nbsp;
remove_boundary_syms
&nbsp;void
&nbsp;remove_boundary_syms()
&nbsp;{
&nbsp;    /*
&nbsp;     * If any CROSSWALLs are found, must change to ROOM after REGION's
&nbsp;     * are laid out.  CROSSWALLS are used to specify "invisible"
&nbsp;     * boundaries where DOOR syms look bad or aren't desirable.
&nbsp;     */
&nbsp;    xchar x, y;
&nbsp;    boolean has_bounds = FALSE;
&nbsp;
&nbsp;    for (x = 0; x &lt; COLNO - 1; x++)
&nbsp;        for (y = 0; y &lt; ROWNO - 1; y++)
&nbsp;            if (levl[x][y].typ == CROSSWALL) {
&nbsp;                has_bounds = TRUE;
&nbsp;                break;
&nbsp;            }
&nbsp;    if (has_bounds) {
&nbsp;        for (x = 0; x &lt; x_maze_max; x++)
&nbsp;            for (y = 0; y &lt; y_maze_max; y++)
&nbsp;                if ((levl[x][y].typ == CROSSWALL) &amp;&amp; SpLev_Map[x][y])
&nbsp;                    levl[x][y].typ = ROOM;
&nbsp;    }
&nbsp;}
&nbsp;
set_door_orientation
&nbsp;/* used by sel_set_door() and link_doors_rooms() */
&nbsp;STATIC_OVL void
&nbsp;set_door_orientation(x, y)
&nbsp;int x, y;
&nbsp;{
&nbsp;    boolean wleft, wright, wup, wdown;
&nbsp;
&nbsp;    /* If there's a wall or door on either the left side or right
&nbsp;     * side (or both) of this secret door, make it be horizontal.
&nbsp;     *
&nbsp;     * It is feasible to put SDOOR in a corner, tee, or crosswall
&nbsp;     * position, although once the door is found and opened it won't
&nbsp;     * make a lot sense (diagonal access required).  Still, we try to
&nbsp;     * handle that as best as possible.  For top or bottom tee, using
&nbsp;     * horizontal is the best we can do.  For corner or crosswall,
&nbsp;     * either horizontal or vertical are just as good as each other;
&nbsp;     * we produce horizontal for corners and vertical for crosswalls.
&nbsp;     * For left or right tee, using vertical is best.
&nbsp;     *
&nbsp;     * A secret door with no adjacent walls is also feasible and makes
&nbsp;     * even less sense.  It will be displayed as a vertical wall while
&nbsp;     * hidden and become a vertical door when found.  Before resorting
&nbsp;     * to that, we check for solid rock which hasn't been wallified
&nbsp;     * yet (cf lower leftside of leader's room in Cav quest).
&nbsp;     */
&nbsp;    wleft  = (isok(x - 1, y) &amp;&amp; (IS_WALL(levl[x - 1][y].typ)
&nbsp;                                 || IS_DOOR(levl[x - 1][y].typ)
&nbsp;                                 || levl[x - 1][y].typ == SDOOR));
&nbsp;    wright = (isok(x + 1, y) &amp;&amp; (IS_WALL(levl[x + 1][y].typ)
&nbsp;                                 || IS_DOOR(levl[x + 1][y].typ)
&nbsp;                                 || levl[x + 1][y].typ == SDOOR));
&nbsp;    wup    = (isok(x, y - 1) &amp;&amp; (IS_WALL(levl[x][y - 1].typ)
&nbsp;                                 || IS_DOOR(levl[x][y - 1].typ)
&nbsp;                                 || levl[x][y - 1].typ == SDOOR));
&nbsp;    wdown  = (isok(x, y + 1) &amp;&amp; (IS_WALL(levl[x][y + 1].typ)
&nbsp;                                 || IS_DOOR(levl[x][y + 1].typ)
&nbsp;                                 || levl[x][y + 1].typ == SDOOR));
&nbsp;    if (!wleft &amp;&amp; !wright &amp;&amp; !wup &amp;&amp; !wdown) {
&nbsp;        /* out of bounds is treated as implicit wall; should be academic
&nbsp;           because we don't expect to have doors so near the level's edge */
&nbsp;        wleft  = (!isok(x - 1, y) || IS_DOORJOIN(levl[x - 1][y].typ));
&nbsp;        wright = (!isok(x + 1, y) || IS_DOORJOIN(levl[x + 1][y].typ));
&nbsp;        wup    = (!isok(x, y - 1) || IS_DOORJOIN(levl[x][y - 1].typ));
&nbsp;        wdown  = (!isok(x, y + 1) || IS_DOORJOIN(levl[x][y + 1].typ));
&nbsp;    }
&nbsp;    levl[x][y].horizontal = ((wleft || wright) &amp;&amp; !(wup &amp;&amp; wdown)) ? 1 : 0;
&nbsp;}
&nbsp;
maybe_add_door
&nbsp;STATIC_OVL void
&nbsp;maybe_add_door(x, y, droom)
&nbsp;int x, y;
&nbsp;struct mkroom *droom;
&nbsp;{
&nbsp;    if (droom-&gt;hx &gt;= 0 &amp;&amp; doorindex &lt; DOORMAX &amp;&amp; inside_room(droom, x, y))
&nbsp;        add_door(x, y, droom);
&nbsp;}
&nbsp;
link_doors_rooms
&nbsp;STATIC_OVL void
&nbsp;link_doors_rooms()
&nbsp;{
&nbsp;    int x, y;
&nbsp;    int tmpi, m;
&nbsp;
&nbsp;    for (y = 0; y &lt; ROWNO; y++)
&nbsp;        for (x = 0; x &lt; COLNO; x++)
&nbsp;            if (IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR) {
&nbsp;                /* in case this door was a '+' or 'S' from the
&nbsp;                   MAP...ENDMAP section without an explicit DOOR
&nbsp;                   directive, set/clear levl[][].horizontal for it */
&nbsp;                set_door_orientation(x, y);
&nbsp;
&nbsp;                for (tmpi = 0; tmpi &lt; nroom; tmpi++) {
&nbsp;                    maybe_add_door(x, y, &amp;rooms[tmpi]);
&nbsp;                    for (m = 0; m &lt; rooms[tmpi].nsubrooms; m++) {
&nbsp;                        maybe_add_door(x, y, rooms[tmpi].sbrooms[m]);
&nbsp;                    }
&nbsp;                }
&nbsp;            }
&nbsp;}
&nbsp;
fill_rooms
&nbsp;void
&nbsp;fill_rooms()
&nbsp;{
&nbsp;    int tmpi;
&nbsp;
&nbsp;    for (tmpi = 0; tmpi &lt; nroom; tmpi++) {
&nbsp;        int m;
&nbsp;        if (rooms[tmpi].needfill)
&nbsp;            fill_room(&amp;rooms[tmpi], (rooms[tmpi].needfill == 2));
&nbsp;        for (m = 0; m &lt; rooms[tmpi].nsubrooms; m++)
&nbsp;            if (rooms[tmpi].sbrooms[m]-&gt;needfill)
&nbsp;                fill_room(rooms[tmpi].sbrooms[m], FALSE);
&nbsp;    }
&nbsp;}
&nbsp;
rnddoor
&nbsp;/*
&nbsp; * Choose randomly the state (nodoor, open, closed or locked) for a door
&nbsp; */
&nbsp;STATIC_OVL int
&nbsp;rnddoor()
&nbsp;{
&nbsp;    int i = 1 &lt;&lt; rn2(5);
&nbsp;
&nbsp;    i &gt;&gt;= 1;
&nbsp;    return i;
&nbsp;}
&nbsp;
rndtrap
&nbsp;/*
&nbsp; * Select a random trap
&nbsp; */
&nbsp;STATIC_OVL int
&nbsp;rndtrap()
&nbsp;{
&nbsp;    int rtrap;
&nbsp;
&nbsp;    do {
&nbsp;        rtrap = rnd(TRAPNUM - 1);
&nbsp;        switch (rtrap) {
&nbsp;        case HOLE: /* no random holes on special levels */
&nbsp;        case VIBRATING_SQUARE:
&nbsp;        case MAGIC_PORTAL:
&nbsp;            rtrap = NO_TRAP;
&nbsp;            break;
&nbsp;        case TRAPDOOR:
&nbsp;            if (!Can_dig_down(&amp;u.uz))
&nbsp;                rtrap = NO_TRAP;
&nbsp;            break;
&nbsp;        case LEVEL_TELEP:
&nbsp;        case TELEP_TRAP:
&nbsp;            if (level.flags.noteleport)
&nbsp;                rtrap = NO_TRAP;
&nbsp;            break;
&nbsp;        case ROLLING_BOULDER_TRAP:
&nbsp;        case ROCKTRAP:
&nbsp;            if (In_endgame(&amp;u.uz))
&nbsp;                rtrap = NO_TRAP;
&nbsp;            break;
&nbsp;        }
&nbsp;    } while (rtrap == NO_TRAP);
&nbsp;    return rtrap;
&nbsp;}
&nbsp;
get_location
&nbsp;/*
&nbsp; * Coordinates in special level files are handled specially:
&nbsp; *
&nbsp; *      if x or y is &lt; 0, we generate a random coordinate.
&nbsp; *      The "humidity" flag is used to insure that engravings aren't
&nbsp; *      created underwater, or eels on dry land.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;get_location(x, y, humidity, croom)
&nbsp;schar *x, *y;
&nbsp;int humidity;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    int cpt = 0;
&nbsp;    int mx, my, sx, sy;
&nbsp;
&nbsp;    if (croom) {
&nbsp;        mx = croom-&gt;lx;
&nbsp;        my = croom-&gt;ly;
&nbsp;        sx = croom-&gt;hx - mx + 1;
&nbsp;        sy = croom-&gt;hy - my + 1;
&nbsp;    } else {
&nbsp;        mx = xstart;
&nbsp;        my = ystart;
&nbsp;        sx = xsize;
&nbsp;        sy = ysize;
&nbsp;    }
&nbsp;
&nbsp;    if (*x &gt;= 0) { /* normal locations */
&nbsp;        *x += mx;
&nbsp;        *y += my;
&nbsp;    } else { /* random location */
&nbsp;        do {
&nbsp;            if (croom) { /* handle irregular areas */
&nbsp;                coord tmpc;
&nbsp;                somexy(croom, &amp;tmpc);
&nbsp;                *x = tmpc.x;
&nbsp;                *y = tmpc.y;
&nbsp;            } else {
&nbsp;                *x = mx + rn2((int) sx);
&nbsp;                *y = my + rn2((int) sy);
&nbsp;            }
&nbsp;            if (is_ok_location(*x, *y, humidity))
&nbsp;                break;
&nbsp;        } while (++cpt &lt; 100);
&nbsp;        if (cpt &gt;= 100) {
&nbsp;            register int xx, yy;
&nbsp;
&nbsp;            /* last try */
&nbsp;            for (xx = 0; xx &lt; sx; xx++)
&nbsp;                for (yy = 0; yy &lt; sy; yy++) {
&nbsp;                    *x = mx + xx;
&nbsp;                    *y = my + yy;
&nbsp;                    if (is_ok_location(*x, *y, humidity))
&nbsp;                        goto found_it;
&nbsp;                }
&nbsp;            if (!(humidity &amp; NO_LOC_WARN)) {
&nbsp;                impossible("get_location:  can't find a place!");
&nbsp;            } else {
&nbsp;                *x = *y = -1;
&nbsp;            }
&nbsp;        }
&nbsp;    }
&nbsp;found_it:
&nbsp;    ;
&nbsp;
&nbsp;    if (!(humidity &amp; ANY_LOC) &amp;&amp; !isok(*x, *y)) {
&nbsp;        if (!(humidity &amp; NO_LOC_WARN)) {
&nbsp;            /*warning("get_location:  (%d,%d) out of bounds", *x, *y);*/
&nbsp;            *x = x_maze_max;
&nbsp;            *y = y_maze_max;
&nbsp;        } else {
&nbsp;            *x = *y = -1;
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
is_ok_location
&nbsp;STATIC_OVL boolean
&nbsp;is_ok_location(x, y, humidity)
&nbsp;register schar x, y;
&nbsp;register int humidity;
&nbsp;{
&nbsp;    register int typ;
&nbsp;
&nbsp;    if (Is_waterlevel(&amp;u.uz))
&nbsp;        return TRUE; /* accept any spot */
&nbsp;
&nbsp;    /* TODO: Should perhaps check if wall is diggable/passwall? */
&nbsp;    if (humidity &amp; ANY_LOC)
&nbsp;        return TRUE;
&nbsp;
&nbsp;    if ((humidity &amp; SOLID) &amp;&amp; IS_ROCK(levl[x][y].typ))
&nbsp;        return TRUE;
&nbsp;
&nbsp;    if (humidity &amp; DRY) {
&nbsp;        typ = levl[x][y].typ;
&nbsp;        if (typ == ROOM || typ == AIR || typ == CLOUD || typ == ICE
&nbsp;            || typ == CORR)
&nbsp;            return TRUE;
&nbsp;    }
&nbsp;    if ((humidity &amp; SPACELOC) &amp;&amp; SPACE_POS(levl[x][y].typ))
&nbsp;        return TRUE;
&nbsp;    if ((humidity &amp; WET) &amp;&amp; is_pool(x, y))
&nbsp;        return TRUE;
&nbsp;    if ((humidity &amp; HOT) &amp;&amp; is_lava(x, y))
&nbsp;        return TRUE;
&nbsp;    return FALSE;
&nbsp;}
&nbsp;
get_unpacked_coord
&nbsp;unpacked_coord
&nbsp;get_unpacked_coord(loc, defhumidity)
&nbsp;long loc;
&nbsp;int defhumidity;
&nbsp;{
&nbsp;    static unpacked_coord c;
&nbsp;
&nbsp;    if (loc &amp; SP_COORD_IS_RANDOM) {
&nbsp;        c.x = c.y = -1;
&nbsp;        c.is_random = 1;
&nbsp;        c.getloc_flags = (loc &amp; ~SP_COORD_IS_RANDOM);
&nbsp;        if (!c.getloc_flags)
&nbsp;            c.getloc_flags = defhumidity;
&nbsp;    } else {
&nbsp;        c.is_random = 0;
&nbsp;        c.getloc_flags = defhumidity;
&nbsp;        c.x = SP_COORD_X(loc);
&nbsp;        c.y = SP_COORD_Y(loc);
&nbsp;    }
&nbsp;    return c;
&nbsp;}
&nbsp;
get_location_coord
&nbsp;STATIC_OVL void
&nbsp;get_location_coord(x, y, humidity, croom, crd)
&nbsp;schar *x, *y;
&nbsp;int humidity;
&nbsp;struct mkroom *croom;
&nbsp;long crd;
&nbsp;{
&nbsp;    unpacked_coord c;
&nbsp;
&nbsp;    c = get_unpacked_coord(crd, humidity);
&nbsp;    *x = c.x;
&nbsp;    *y = c.y;
&nbsp;    get_location(x, y, c.getloc_flags | (c.is_random ? NO_LOC_WARN : 0),
&nbsp;                 croom);
&nbsp;    if (*x == -1 &amp;&amp; *y == -1 &amp;&amp; c.is_random)
&nbsp;        get_location(x, y, humidity, croom);
&nbsp;}
&nbsp;
get_room_loc
&nbsp;/*
&nbsp; * Get a relative position inside a room.
&nbsp; * negative values for x or y means RANDOM!
&nbsp; */
&nbsp;
&nbsp;STATIC_OVL void
&nbsp;get_room_loc(x, y, croom)
&nbsp;schar *x, *y;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    coord c;
&nbsp;
&nbsp;    if (*x &lt; 0 &amp;&amp; *y &lt; 0) {
&nbsp;        if (somexy(croom, &amp;c)) {
&nbsp;            *x = c.x;
&nbsp;            *y = c.y;
&nbsp;        } else
&nbsp;            panic("get_room_loc : can't find a place!");
&nbsp;    } else {
&nbsp;        if (*x &lt; 0)
&nbsp;            *x = rn2(croom-&gt;hx - croom-&gt;lx + 1);
&nbsp;        if (*y &lt; 0)
&nbsp;            *y = rn2(croom-&gt;hy - croom-&gt;ly + 1);
&nbsp;        *x += croom-&gt;lx;
&nbsp;        *y += croom-&gt;ly;
&nbsp;    }
&nbsp;}
&nbsp;
get_free_room_loc
&nbsp;/*
&nbsp; * Get a relative position inside a room.
&nbsp; * negative values for x or y means RANDOM!
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;get_free_room_loc(x, y, croom, pos)
&nbsp;schar *x, *y;
&nbsp;struct mkroom *croom;
&nbsp;packed_coord pos;
&nbsp;{
&nbsp;    schar try_x, try_y;
&nbsp;    register int trycnt = 0;
&nbsp;
&nbsp;    get_location_coord(&amp;try_x, &amp;try_y, DRY, croom, pos);
&nbsp;    if (levl[try_x][try_y].typ != ROOM) {
&nbsp;        do {
&nbsp;            try_x = *x, try_y = *y;
&nbsp;            get_room_loc(&amp;try_x, &amp;try_y, croom);
&nbsp;        } while (levl[try_x][try_y].typ != ROOM &amp;&amp; ++trycnt &lt;= 100);
&nbsp;
&nbsp;        if (trycnt &gt; 100)
&nbsp;            panic("get_free_room_loc:  can't find a place!");
&nbsp;    }
&nbsp;    *x = try_x, *y = try_y;
&nbsp;}
&nbsp;
check_room
&nbsp;boolean
&nbsp;check_room(lowx, ddx, lowy, ddy, vault)
&nbsp;xchar *lowx, *ddx, *lowy, *ddy;
&nbsp;boolean vault;
&nbsp;{
&nbsp;    register int x, y, hix = *lowx + *ddx, hiy = *lowy + *ddy;
&nbsp;    register struct rm *lev;
&nbsp;    int xlim, ylim, ymax;
&nbsp;
&nbsp;    xlim = XLIM + (vault ? 1 : 0);
&nbsp;    ylim = YLIM + (vault ? 1 : 0);
&nbsp;
&nbsp;    if (*lowx &lt; 3)
&nbsp;        *lowx = 3;
&nbsp;    if (*lowy &lt; 2)
&nbsp;        *lowy = 2;
&nbsp;    if (hix &gt; COLNO - 3)
&nbsp;        hix = COLNO - 3;
&nbsp;    if (hiy &gt; ROWNO - 3)
&nbsp;        hiy = ROWNO - 3;
&nbsp;chk:
&nbsp;    if (hix &lt;= *lowx || hiy &lt;= *lowy)
&nbsp;        return FALSE;
&nbsp;
&nbsp;    /* check area around room (and make room smaller if necessary) */
&nbsp;    for (x = *lowx - xlim; x &lt;= hix + xlim; x++) {
&nbsp;        if (x &lt;= 0 || x &gt;= COLNO)
&nbsp;            continue;
&nbsp;        y = *lowy - ylim;
&nbsp;        ymax = hiy + ylim;
&nbsp;        if (y &lt; 0)
&nbsp;            y = 0;
&nbsp;        if (ymax &gt;= ROWNO)
&nbsp;            ymax = (ROWNO - 1);
&nbsp;        lev = &amp;levl[x][y];
&nbsp;        for (; y &lt;= ymax; y++) {
&nbsp;            if (lev++-&gt;typ) {
&nbsp;                if (!vault) {
&nbsp;                    debugpline2("strange area [%d,%d] in check_room.", x, y);
&nbsp;                }
&nbsp;                if (!rn2(3))
&nbsp;                    return FALSE;
&nbsp;                if (x &lt; *lowx)
&nbsp;                    *lowx = x + xlim + 1;
&nbsp;                else
&nbsp;                    hix = x - xlim - 1;
&nbsp;                if (y &lt; *lowy)
&nbsp;                    *lowy = y + ylim + 1;
&nbsp;                else
&nbsp;                    hiy = y - ylim - 1;
&nbsp;                goto chk;
&nbsp;            }
&nbsp;        }
&nbsp;    }
&nbsp;    *ddx = hix - *lowx;
&nbsp;    *ddy = hiy - *lowy;
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
create_room
&nbsp;/*
&nbsp; * Create a new room.
&nbsp; * This is still very incomplete...
&nbsp; */
&nbsp;boolean
&nbsp;create_room(x, y, w, h, xal, yal, rtype, rlit)
&nbsp;xchar x, y;
&nbsp;xchar w, h;
&nbsp;xchar xal, yal;
&nbsp;xchar rtype, rlit;
&nbsp;{
&nbsp;    xchar xabs, yabs;
&nbsp;    int wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
&nbsp;    NhRect *r1 = 0, r2;
&nbsp;    int trycnt = 0;
&nbsp;    boolean vault = FALSE;
&nbsp;    int xlim = XLIM, ylim = YLIM;
&nbsp;
&nbsp;    if (rtype == -1) /* Is the type random ? */
&nbsp;        rtype = OROOM;
&nbsp;
&nbsp;    if (rtype == VAULT) {
&nbsp;        vault = TRUE;
&nbsp;        xlim++;
&nbsp;        ylim++;
&nbsp;    }
&nbsp;
&nbsp;    /* on low levels the room is lit (usually) */
&nbsp;    /* some other rooms may require lighting */
&nbsp;
&nbsp;    /* is light state random ? */
&nbsp;    if (rlit == -1)
&nbsp;        rlit = (rnd(1 + abs(depth(&amp;u.uz))) &lt; 11 &amp;&amp; rn2(77)) ? TRUE : FALSE;
&nbsp;
&nbsp;    /*
&nbsp;     * Here we will try to create a room. If some parameters are
&nbsp;     * random we are willing to make several try before we give
&nbsp;     * it up.
&nbsp;     */
&nbsp;    do {
&nbsp;        xchar xborder, yborder;
&nbsp;        wtmp = w;
&nbsp;        htmp = h;
&nbsp;        xtmp = x;
&nbsp;        ytmp = y;
&nbsp;        xaltmp = xal;
&nbsp;        yaltmp = yal;
&nbsp;
&nbsp;        /* First case : a totally random room */
&nbsp;
&nbsp;        if ((xtmp &lt; 0 &amp;&amp; ytmp &lt; 0 &amp;&amp; wtmp &lt; 0 &amp;&amp; xaltmp &lt; 0 &amp;&amp; yaltmp &lt; 0)
&nbsp;            || vault) {
&nbsp;            xchar hx, hy, lx, ly, dx, dy;
&nbsp;            r1 = rnd_rect(); /* Get a random rectangle */
&nbsp;
&nbsp;            if (!r1) { /* No more free rectangles ! */
&nbsp;                debugpline0("No more rects...");
&nbsp;                return FALSE;
&nbsp;            }
&nbsp;            hx = r1-&gt;hx;
&nbsp;            hy = r1-&gt;hy;
&nbsp;            lx = r1-&gt;lx;
&nbsp;            ly = r1-&gt;ly;
&nbsp;            if (vault)
&nbsp;                dx = dy = 1;
&nbsp;            else {
&nbsp;                dx = 2 + rn2((hx - lx &gt; 28) ? 12 : 8);
&nbsp;                dy = 2 + rn2(4);
&nbsp;                if (dx * dy &gt; 50)
&nbsp;                    dy = 50 / dx;
&nbsp;            }
&nbsp;            xborder = (lx &gt; 0 &amp;&amp; hx &lt; COLNO - 1) ? 2 * xlim : xlim + 1;
&nbsp;            yborder = (ly &gt; 0 &amp;&amp; hy &lt; ROWNO - 1) ? 2 * ylim : ylim + 1;
&nbsp;            if (hx - lx &lt; dx + 3 + xborder || hy - ly &lt; dy + 3 + yborder) {
&nbsp;                r1 = 0;
&nbsp;                continue;
&nbsp;            }
&nbsp;            xabs = lx + (lx &gt; 0 ? xlim : 3)
&nbsp;                   + rn2(hx - (lx &gt; 0 ? lx : 3) - dx - xborder + 1);
&nbsp;            yabs = ly + (ly &gt; 0 ? ylim : 2)
&nbsp;                   + rn2(hy - (ly &gt; 0 ? ly : 2) - dy - yborder + 1);
&nbsp;            if (ly == 0 &amp;&amp; hy &gt;= (ROWNO - 1) &amp;&amp; (!nroom || !rn2(nroom))
&nbsp;                &amp;&amp; (yabs + dy &gt; ROWNO / 2)) {
&nbsp;                yabs = rn1(3, 2);
&nbsp;                if (nroom &lt; 4 &amp;&amp; dy &gt; 1)
&nbsp;                    dy--;
&nbsp;            }
&nbsp;            if (!check_room(&amp;xabs, &amp;dx, &amp;yabs, &amp;dy, vault)) {
&nbsp;                r1 = 0;
&nbsp;                continue;
&nbsp;            }
&nbsp;            wtmp = dx + 1;
&nbsp;            htmp = dy + 1;
&nbsp;            r2.lx = xabs - 1;
&nbsp;            r2.ly = yabs - 1;
&nbsp;            r2.hx = xabs + wtmp;
&nbsp;            r2.hy = yabs + htmp;
&nbsp;        } else { /* Only some parameters are random */
&nbsp;            int rndpos = 0;
&nbsp;            if (xtmp &lt; 0 &amp;&amp; ytmp &lt; 0) { /* Position is RANDOM */
&nbsp;                xtmp = rnd(5);
&nbsp;                ytmp = rnd(5);
&nbsp;                rndpos = 1;
&nbsp;            }
&nbsp;            if (wtmp &lt; 0 || htmp &lt; 0) { /* Size is RANDOM */
&nbsp;                wtmp = rn1(15, 3);
&nbsp;                htmp = rn1(8, 2);
&nbsp;            }
&nbsp;            if (xaltmp == -1) /* Horizontal alignment is RANDOM */
&nbsp;                xaltmp = rnd(3);
&nbsp;            if (yaltmp == -1) /* Vertical alignment is RANDOM */
&nbsp;                yaltmp = rnd(3);
&nbsp;
&nbsp;            /* Try to generate real (absolute) coordinates here! */
&nbsp;
&nbsp;            xabs = (((xtmp - 1) * COLNO) / 5) + 1;
&nbsp;            yabs = (((ytmp - 1) * ROWNO) / 5) + 1;
&nbsp;            switch (xaltmp) {
&nbsp;            case LEFT:
&nbsp;                break;
&nbsp;            case RIGHT:
&nbsp;                xabs += (COLNO / 5) - wtmp;
&nbsp;                break;
&nbsp;            case CENTER:
&nbsp;                xabs += ((COLNO / 5) - wtmp) / 2;
&nbsp;                break;
&nbsp;            }
&nbsp;            switch (yaltmp) {
&nbsp;            case TOP:
&nbsp;                break;
&nbsp;            case BOTTOM:
&nbsp;                yabs += (ROWNO / 5) - htmp;
&nbsp;                break;
&nbsp;            case CENTER:
&nbsp;                yabs += ((ROWNO / 5) - htmp) / 2;
&nbsp;                break;
&nbsp;            }
&nbsp;
&nbsp;            if (xabs + wtmp - 1 &gt; COLNO - 2)
&nbsp;                xabs = COLNO - wtmp - 3;
&nbsp;            if (xabs &lt; 2)
&nbsp;                xabs = 2;
&nbsp;            if (yabs + htmp - 1 &gt; ROWNO - 2)
&nbsp;                yabs = ROWNO - htmp - 3;
&nbsp;            if (yabs &lt; 2)
&nbsp;                yabs = 2;
&nbsp;
&nbsp;            /* Try to find a rectangle that fit our room ! */
&nbsp;
&nbsp;            r2.lx = xabs - 1;
&nbsp;            r2.ly = yabs - 1;
&nbsp;            r2.hx = xabs + wtmp + rndpos;
&nbsp;            r2.hy = yabs + htmp + rndpos;
&nbsp;            r1 = get_rect(&amp;r2);
&nbsp;        }
&nbsp;    } while (++trycnt &lt;= 100 &amp;&amp; !r1);
&nbsp;    if (!r1) { /* creation of room failed ? */
&nbsp;        return FALSE;
&nbsp;    }
&nbsp;    split_rects(r1, &amp;r2);
&nbsp;
&nbsp;    if (!vault) {
&nbsp;        smeq[nroom] = nroom;
&nbsp;        add_room(xabs, yabs, xabs + wtmp - 1, yabs + htmp - 1, rlit, rtype,
&nbsp;                 FALSE);
&nbsp;    } else {
&nbsp;        rooms[nroom].lx = xabs;
&nbsp;        rooms[nroom].ly = yabs;
&nbsp;    }
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
create_subroom
&nbsp;/*
&nbsp; * Create a subroom in room proom at pos x,y with width w &amp; height h.
&nbsp; * x &amp; y are relative to the parent room.
&nbsp; */
&nbsp;STATIC_OVL boolean
&nbsp;create_subroom(proom, x, y, w, h, rtype, rlit)
&nbsp;struct mkroom *proom;
&nbsp;xchar x, y;
&nbsp;xchar w, h;
&nbsp;xchar rtype, rlit;
&nbsp;{
&nbsp;    xchar width, height;
&nbsp;
&nbsp;    width = proom-&gt;hx - proom-&gt;lx + 1;
&nbsp;    height = proom-&gt;hy - proom-&gt;ly + 1;
&nbsp;
&nbsp;    /* There is a minimum size for the parent room */
&nbsp;    if (width &lt; 4 || height &lt; 4)
&nbsp;        return FALSE;
&nbsp;
&nbsp;    /* Check for random position, size, etc... */
&nbsp;
&nbsp;    if (w == -1)
&nbsp;        w = rnd(width - 3);
&nbsp;    if (h == -1)
&nbsp;        h = rnd(height - 3);
&nbsp;    if (x == -1)
&nbsp;        x = rnd(width - w - 1) - 1;
&nbsp;    if (y == -1)
&nbsp;        y = rnd(height - h - 1) - 1;
&nbsp;    if (x == 1)
&nbsp;        x = 0;
&nbsp;    if (y == 1)
&nbsp;        y = 0;
&nbsp;    if ((x + w + 1) == width)
&nbsp;        x++;
&nbsp;    if ((y + h + 1) == height)
&nbsp;        y++;
&nbsp;    if (rtype == -1)
&nbsp;        rtype = OROOM;
&nbsp;    if (rlit == -1)
&nbsp;        rlit = (rnd(1 + abs(depth(&amp;u.uz))) &lt; 11 &amp;&amp; rn2(77)) ? TRUE : FALSE;
&nbsp;    add_subroom(proom, proom-&gt;lx + x, proom-&gt;ly + y, proom-&gt;lx + x + w - 1,
&nbsp;                proom-&gt;ly + y + h - 1, rlit, rtype, FALSE);
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
create_door
&nbsp;/*
&nbsp; * Create a new door in a room.
&nbsp; * It's placed on a wall (north, south, east or west).
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;create_door(dd, broom)
&nbsp;room_door *dd;
&nbsp;struct mkroom *broom;
&nbsp;{
&nbsp;    int x = 0, y = 0;
&nbsp;    int trycnt = 0, wtry = 0;
&nbsp;
&nbsp;    if (dd-&gt;secret == -1)
&nbsp;        dd-&gt;secret = rn2(2);
&nbsp;
&nbsp;    if (dd-&gt;mask == -1) {
&nbsp;        /* is it a locked door, closed, or a doorway? */
&nbsp;        if (!dd-&gt;secret) {
&nbsp;            if (!rn2(3)) {
&nbsp;                if (!rn2(5))
&nbsp;                    dd-&gt;mask = D_ISOPEN;
&nbsp;                else if (!rn2(6))
&nbsp;                    dd-&gt;mask = D_LOCKED;
&nbsp;                else
&nbsp;                    dd-&gt;mask = D_CLOSED;
&nbsp;                if (dd-&gt;mask != D_ISOPEN &amp;&amp; !rn2(25))
&nbsp;                    dd-&gt;mask |= D_TRAPPED;
&nbsp;            } else
&nbsp;                dd-&gt;mask = D_NODOOR;
&nbsp;        } else {
&nbsp;            if (!rn2(5))
&nbsp;                dd-&gt;mask = D_LOCKED;
&nbsp;            else
&nbsp;                dd-&gt;mask = D_CLOSED;
&nbsp;
&nbsp;            if (!rn2(20))
&nbsp;                dd-&gt;mask |= D_TRAPPED;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    do {
&nbsp;        register int dwall, dpos;
&nbsp;
&nbsp;        dwall = dd-&gt;wall;
&nbsp;        if (dwall == -1) /* The wall is RANDOM */
&nbsp;            dwall = 1 &lt;&lt; rn2(4);
&nbsp;
&nbsp;        dpos = dd-&gt;pos;
&nbsp;
&nbsp;        /* Convert wall and pos into an absolute coordinate! */
&nbsp;        wtry = rn2(4);
&nbsp;        switch (wtry) {
&nbsp;        case 0:
&nbsp;            if (!(dwall &amp; W_NORTH))
&nbsp;                goto redoloop;
&nbsp;            y = broom-&gt;ly - 1;
&nbsp;            x = broom-&gt;lx
&nbsp;                + ((dpos == -1) ? rn2(1 + (broom-&gt;hx - broom-&gt;lx)) : dpos);
&nbsp;            if (IS_ROCK(levl[x][y - 1].typ))
&nbsp;                goto redoloop;
&nbsp;            goto outdirloop;
&nbsp;        case 1:
&nbsp;            if (!(dwall &amp; W_SOUTH))
&nbsp;                goto redoloop;
&nbsp;            y = broom-&gt;hy + 1;
&nbsp;            x = broom-&gt;lx
&nbsp;                + ((dpos == -1) ? rn2(1 + (broom-&gt;hx - broom-&gt;lx)) : dpos);
&nbsp;            if (IS_ROCK(levl[x][y + 1].typ))
&nbsp;                goto redoloop;
&nbsp;            goto outdirloop;
&nbsp;        case 2:
&nbsp;            if (!(dwall &amp; W_WEST))
&nbsp;                goto redoloop;
&nbsp;            x = broom-&gt;lx - 1;
&nbsp;            y = broom-&gt;ly
&nbsp;                + ((dpos == -1) ? rn2(1 + (broom-&gt;hy - broom-&gt;ly)) : dpos);
&nbsp;            if (IS_ROCK(levl[x - 1][y].typ))
&nbsp;                goto redoloop;
&nbsp;            goto outdirloop;
&nbsp;        case 3:
&nbsp;            if (!(dwall &amp; W_EAST))
&nbsp;                goto redoloop;
&nbsp;            x = broom-&gt;hx + 1;
&nbsp;            y = broom-&gt;ly
&nbsp;                + ((dpos == -1) ? rn2(1 + (broom-&gt;hy - broom-&gt;ly)) : dpos);
&nbsp;            if (IS_ROCK(levl[x + 1][y].typ))
&nbsp;                goto redoloop;
&nbsp;            goto outdirloop;
&nbsp;        default:
&nbsp;            x = y = 0;
&nbsp;            panic("create_door: No wall for door!");
&nbsp;            goto outdirloop;
&nbsp;        }
&nbsp;    outdirloop:
&nbsp;        if (okdoor(x, y))
&nbsp;            break;
&nbsp;    redoloop:
&nbsp;        ;
&nbsp;    } while (++trycnt &lt;= 100);
&nbsp;    if (trycnt &gt; 100) {
&nbsp;        impossible("create_door: Can't find a proper place!");
&nbsp;        return;
&nbsp;    }
&nbsp;    levl[x][y].typ = (dd-&gt;secret ? SDOOR : DOOR);
&nbsp;    levl[x][y].doormask = dd-&gt;mask;
&nbsp;}
&nbsp;
create_secret_door
&nbsp;/*
&nbsp; * Create a secret door in croom on any one of the specified walls.
&nbsp; */
&nbsp;void
&nbsp;create_secret_door(croom, walls)
&nbsp;struct mkroom *croom;
&nbsp;xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
&nbsp;{
&nbsp;    xchar sx, sy; /* location of the secret door */
&nbsp;    int count;
&nbsp;
&nbsp;    for (count = 0; count &lt; 100; count++) {
&nbsp;        sx = rn1(croom-&gt;hx - croom-&gt;lx + 1, croom-&gt;lx);
&nbsp;        sy = rn1(croom-&gt;hy - croom-&gt;ly + 1, croom-&gt;ly);
&nbsp;
&nbsp;        switch (rn2(4)) {
&nbsp;        case 0: /* top */
&nbsp;            if (!(walls &amp; W_NORTH))
&nbsp;                continue;
&nbsp;            sy = croom-&gt;ly - 1;
&nbsp;            break;
&nbsp;        case 1: /* bottom */
&nbsp;            if (!(walls &amp; W_SOUTH))
&nbsp;                continue;
&nbsp;            sy = croom-&gt;hy + 1;
&nbsp;            break;
&nbsp;        case 2: /* left */
&nbsp;            if (!(walls &amp; W_EAST))
&nbsp;                continue;
&nbsp;            sx = croom-&gt;lx - 1;
&nbsp;            break;
&nbsp;        case 3: /* right */
&nbsp;            if (!(walls &amp; W_WEST))
&nbsp;                continue;
&nbsp;            sx = croom-&gt;hx + 1;
&nbsp;            break;
&nbsp;        }
&nbsp;
&nbsp;        if (okdoor(sx, sy)) {
&nbsp;            levl[sx][sy].typ = SDOOR;
&nbsp;            levl[sx][sy].doormask = D_CLOSED;
&nbsp;            return;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    impossible("couldn't create secret door on any walls 0x%x", walls);
&nbsp;}
&nbsp;
create_trap
&nbsp;/*
&nbsp; * Create a trap in a room.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;create_trap(t, croom)
&nbsp;spltrap *t;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    schar x = -1, y = -1;
&nbsp;    coord tm;
&nbsp;
&nbsp;    if (croom)
&nbsp;        get_free_room_loc(&amp;x, &amp;y, croom, t-&gt;coord);
&nbsp;    else {
&nbsp;        int trycnt = 0;
&nbsp;        do {
&nbsp;            get_location_coord(&amp;x, &amp;y, DRY, croom, t-&gt;coord);
&nbsp;        } while ((levl[x][y].typ == STAIRS || levl[x][y].typ == LADDER)
&nbsp;                 &amp;&amp; ++trycnt &lt;= 100);
&nbsp;        if (trycnt &gt; 100)
&nbsp;            return;
&nbsp;    }
&nbsp;
&nbsp;    tm.x = x;
&nbsp;    tm.y = y;
&nbsp;
&nbsp;    mktrap(t-&gt;type, 1, (struct mkroom *) 0, &amp;tm);
&nbsp;}
&nbsp;
noncoalignment
&nbsp;/*
&nbsp; * Create a monster in a room.
&nbsp; */
&nbsp;STATIC_OVL int
&nbsp;noncoalignment(alignment)
&nbsp;aligntyp alignment;
&nbsp;{
&nbsp;    int k;
&nbsp;
&nbsp;    k = rn2(2);
&nbsp;    if (!alignment)
&nbsp;        return (k ? -1 : 1);
&nbsp;    return (k ? -alignment : 0);
&nbsp;}
&nbsp;
m_bad_boulder_spot
&nbsp;/* attempt to screen out locations where a mimic-as-boulder shouldn't occur */
&nbsp;STATIC_OVL boolean
&nbsp;m_bad_boulder_spot(x, y)
&nbsp;int x, y;
&nbsp;{
&nbsp;    struct rm *lev;
&nbsp;
&nbsp;    /* avoid trap locations */
&nbsp;    if (t_at(x, y))
&nbsp;        return TRUE;
&nbsp;    /* try to avoid locations which already have a boulder (this won't
&nbsp;       actually work; we get called before objects have been placed...) */
&nbsp;    if (sobj_at(BOULDER, x, y))
&nbsp;        return TRUE;
&nbsp;    /* avoid closed doors */
&nbsp;    lev = &amp;levl[x][y];
&nbsp;    if (IS_DOOR(lev-&gt;typ) &amp;&amp; (lev-&gt;doormask &amp; (D_CLOSED | D_LOCKED)) != 0)
&nbsp;        return TRUE;
&nbsp;    /* spot is ok */
&nbsp;    return FALSE;
&nbsp;}
&nbsp;
pm_to_humidity
&nbsp;STATIC_OVL int
&nbsp;pm_to_humidity(pm)
&nbsp;struct permonst *pm;
&nbsp;{
&nbsp;    int loc = DRY;
&nbsp;    if (!pm)
&nbsp;        return loc;
&nbsp;    if (pm-&gt;mlet == S_EEL || amphibious(pm) || is_swimmer(pm))
&nbsp;        loc = WET;
&nbsp;    if (is_flyer(pm) || is_floater(pm))
&nbsp;        loc |= (HOT | WET);
&nbsp;    if (passes_walls(pm) || noncorporeal(pm))
&nbsp;        loc |= SOLID;
&nbsp;    if (flaming(pm))
&nbsp;        loc |= HOT;
&nbsp;    return loc;
&nbsp;}
&nbsp;
create_monster
&nbsp;STATIC_OVL void
&nbsp;create_monster(m, croom)
&nbsp;monster *m;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    struct monst *mtmp;
&nbsp;    schar x, y;
&nbsp;    char class;
&nbsp;    aligntyp amask;
&nbsp;    coord cc;
&nbsp;    struct permonst *pm;
&nbsp;    unsigned g_mvflags;
&nbsp;
&nbsp;    if (m-&gt;class &gt;= 0)
&nbsp;        class = (char) def_char_to_monclass((char) m-&gt;class);
&nbsp;    else
&nbsp;        class = 0;
&nbsp;
&nbsp;    if (class == MAXMCLASSES)
&nbsp;        panic("create_monster: unknown monster class '%c'", m-&gt;class);
&nbsp;
&nbsp;    amask = (m-&gt;align == AM_SPLEV_CO)
&nbsp;               ? Align2amask(u.ualignbase[A_ORIGINAL])
&nbsp;               : (m-&gt;align == AM_SPLEV_NONCO)
&nbsp;                  ? Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL]))
&nbsp;                  : (m-&gt;align &lt;= -(MAX_REGISTERS + 1))
&nbsp;                     ? induced_align(80)
&nbsp;                     : (m-&gt;align &lt; 0 ? ralign[-m-&gt;align - 1] : m-&gt;align);
&nbsp;
&nbsp;    if (!class)
&nbsp;        pm = (struct permonst *) 0;
&nbsp;    else if (m-&gt;id != NON_PM) {
&nbsp;        pm = &amp;mons[m-&gt;id];
&nbsp;        g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
&nbsp;        if ((pm-&gt;geno &amp; G_UNIQ) &amp;&amp; (g_mvflags &amp; G_EXTINCT))
&nbsp;            return;
&nbsp;        else if (g_mvflags &amp; G_GONE)    /* genocided or extinct */
&nbsp;            pm = (struct permonst *) 0; /* make random monster */
&nbsp;    } else {
&nbsp;        pm = mkclass(class, G_NOGEN);
&nbsp;        /* if we can't get a specific monster type (pm == 0) then the
&nbsp;           class has been genocided, so settle for a random monster */
&nbsp;    }
&nbsp;    if (In_mines(&amp;u.uz) &amp;&amp; pm &amp;&amp; your_race(pm)
&nbsp;        &amp;&amp; (Race_if(PM_DWARF) || Race_if(PM_GNOME)) &amp;&amp; rn2(3))
&nbsp;        pm = (struct permonst *) 0;
&nbsp;
&nbsp;    if (pm) {
&nbsp;        int loc = pm_to_humidity(pm);
&nbsp;        /* If water-liking monster, first try is without DRY */
&nbsp;        get_location_coord(&amp;x, &amp;y, loc | NO_LOC_WARN, croom, m-&gt;coord);
&nbsp;        if (x == -1 &amp;&amp; y == -1) {
&nbsp;            loc |= DRY;
&nbsp;            get_location_coord(&amp;x, &amp;y, loc, croom, m-&gt;coord);
&nbsp;        }
&nbsp;    } else {
&nbsp;        get_location_coord(&amp;x, &amp;y, DRY, croom, m-&gt;coord);
&nbsp;    }
&nbsp;
&nbsp;    /* try to find a close place if someone else is already there */
&nbsp;    if (MON_AT(x, y) &amp;&amp; enexto(&amp;cc, x, y, pm))
&nbsp;        x = cc.x, y = cc.y;
&nbsp;
&nbsp;    if (m-&gt;align != -(MAX_REGISTERS + 2))
&nbsp;        mtmp = mk_roamer(pm, Amask2align(amask), x, y, m-&gt;peaceful);
&nbsp;    else if (PM_ARCHEOLOGIST &lt;= m-&gt;id &amp;&amp; m-&gt;id &lt;= PM_WIZARD)
&nbsp;        mtmp = mk_mplayer(pm, x, y, FALSE);
&nbsp;    else
&nbsp;        mtmp = makemon(pm, x, y, NO_MM_FLAGS);
&nbsp;
&nbsp;    if (mtmp) {
&nbsp;        x = mtmp-&gt;mx, y = mtmp-&gt;my; /* sanity precaution */
&nbsp;        m-&gt;x = x, m-&gt;y = y;
&nbsp;        /* handle specific attributes for some special monsters */
&nbsp;        if (m-&gt;name.str)
&nbsp;            mtmp = christen_monst(mtmp, m-&gt;name.str);
&nbsp;
&nbsp;        /*
&nbsp;         * This doesn't complain if an attempt is made to give a
&nbsp;         * non-mimic/non-shapechanger an appearance or to give a
&nbsp;         * shapechanger a non-monster shape, it just refuses to comply.
&nbsp;         */
&nbsp;        if (m-&gt;appear_as.str
&nbsp;            &amp;&amp; ((mtmp-&gt;data-&gt;mlet == S_MIMIC)
&nbsp;                /* shapechanger (chameleons, et al, and vampires) */
&nbsp;                || (mtmp-&gt;cham &gt;= LOW_PM &amp;&amp; m-&gt;appear == M_AP_MONSTER))
&nbsp;            &amp;&amp; !Protection_from_shape_changers) {
&nbsp;            int i;
&nbsp;
&nbsp;            switch (m-&gt;appear) {
&nbsp;            case M_AP_NOTHING:
&nbsp;                impossible(
&nbsp;                 "create_monster: mon has an appearance, \"%s\", but no type",
&nbsp;                           m-&gt;appear_as.str);
&nbsp;                break;
&nbsp;
&nbsp;            case M_AP_FURNITURE:
&nbsp;                for (i = 0; i &lt; MAXPCHARS; i++)
&nbsp;                    if (!strcmp(defsyms[i].explanation, m-&gt;appear_as.str))
&nbsp;                        break;
&nbsp;                if (i == MAXPCHARS) {
&nbsp;                    impossible("create_monster: can't find feature \"%s\"",
&nbsp;                               m-&gt;appear_as.str);
&nbsp;                } else {
&nbsp;                    mtmp-&gt;m_ap_type = M_AP_FURNITURE;
&nbsp;                    mtmp-&gt;mappearance = i;
&nbsp;                }
&nbsp;                break;
&nbsp;
&nbsp;            case M_AP_OBJECT:
&nbsp;                for (i = 0; i &lt; NUM_OBJECTS; i++)
&nbsp;                    if (OBJ_NAME(objects[i])
&nbsp;                        &amp;&amp; !strcmp(OBJ_NAME(objects[i]), m-&gt;appear_as.str))
&nbsp;                        break;
&nbsp;                if (i == NUM_OBJECTS) {
&nbsp;                    impossible("create_monster: can't find object \"%s\"",
&nbsp;                               m-&gt;appear_as.str);
&nbsp;                } else {
&nbsp;                    mtmp-&gt;m_ap_type = M_AP_OBJECT;
&nbsp;                    mtmp-&gt;mappearance = i;
&nbsp;                    /* try to avoid placing mimic boulder on a trap */
&nbsp;                    if (i == BOULDER &amp;&amp; m-&gt;x &lt; 0
&nbsp;                        &amp;&amp; m_bad_boulder_spot(x, y)) {
&nbsp;                        int retrylimit = 10;
&nbsp;
&nbsp;                        remove_monster(x, y);
&nbsp;                        do {
&nbsp;                            x = m-&gt;x;
&nbsp;                            y = m-&gt;y;
&nbsp;                            get_location(&amp;x, &amp;y, DRY, croom);
&nbsp;                            if (MON_AT(x, y) &amp;&amp; enexto(&amp;cc, x, y, pm))
&nbsp;                                x = cc.x, y = cc.y;
&nbsp;                        } while (m_bad_boulder_spot(x, y)
&nbsp;                                 &amp;&amp; --retrylimit &gt; 0);
&nbsp;                        place_monster(mtmp, x, y);
&nbsp;                        /* if we didn't find a good spot
&nbsp;                           then mimic something else */
&nbsp;                        if (!retrylimit)
&nbsp;                            set_mimic_sym(mtmp);
&nbsp;                    }
&nbsp;                }
&nbsp;                break;
&nbsp;
&nbsp;            case M_AP_MONSTER: {
&nbsp;                int mndx;
&nbsp;
&nbsp;                if (!strcmpi(m-&gt;appear_as.str, "random"))
&nbsp;                    mndx = select_newcham_form(mtmp);
&nbsp;                else
&nbsp;                    mndx = name_to_mon(m-&gt;appear_as.str);
&nbsp;
&nbsp;                if (mndx == NON_PM || (is_vampshifter(mtmp)
&nbsp;                                       &amp;&amp; !validvamp(mtmp, &amp;mndx, S_HUMAN))) {
&nbsp;                    impossible("create_monster: invalid %s (\"%s\")",
&nbsp;                               (mtmp-&gt;data-&gt;mlet == S_MIMIC)
&nbsp;                                 ? "mimic appearance"
&nbsp;                                 : (mtmp-&gt;data == &amp;mons[PM_WIZARD_OF_YENDOR])
&nbsp;                                     ? "Wizard appearance"
&nbsp;                                     : is_vampshifter(mtmp)
&nbsp;                                         ? "vampire shape"
&nbsp;                                         : "chameleon shape",
&nbsp;                               m-&gt;appear_as.str);
&nbsp;                } else if (&amp;mons[mndx] == mtmp-&gt;data) {
&nbsp;                    /* explicitly forcing a mimic to appear as itself */
&nbsp;                    mtmp-&gt;m_ap_type = M_AP_NOTHING;
&nbsp;                    mtmp-&gt;mappearance = 0;
&nbsp;                } else if (mtmp-&gt;data-&gt;mlet == S_MIMIC
&nbsp;                           || mtmp-&gt;data == &amp;mons[PM_WIZARD_OF_YENDOR]) {
&nbsp;                    /* this is ordinarily only used for Wizard clones
&nbsp;                       and hasn't been exhaustively tested for mimics */
&nbsp;                    mtmp-&gt;m_ap_type = M_AP_MONSTER;
&nbsp;                    mtmp-&gt;mappearance = mndx;
&nbsp;                } else { /* chameleon or vampire */
&nbsp;                    struct permonst *mdat = &amp;mons[mndx];
&nbsp;                    struct permonst *olddata = mtmp-&gt;data;
&nbsp;
&nbsp;                    mgender_from_permonst(mtmp, mdat);
&nbsp;                    set_mon_data(mtmp, mdat, 0);
&nbsp;                    if (emits_light(olddata) != emits_light(mtmp-&gt;data)) {
&nbsp;                        /* used to give light, now doesn't, or vice versa,
&nbsp;                           or light's range has changed */
&nbsp;                        if (emits_light(olddata))
&nbsp;                            del_light_source(LS_MONSTER, (genericptr_t) mtmp);
&nbsp;                        if (emits_light(mtmp-&gt;data))
&nbsp;                            new_light_source(mtmp-&gt;mx, mtmp-&gt;my,
&nbsp;                                             emits_light(mtmp-&gt;data),
&nbsp;                                             LS_MONSTER, (genericptr_t) mtmp);
&nbsp;                    }
&nbsp;                    if (!mtmp-&gt;perminvis || pm_invisible(olddata))
&nbsp;                        mtmp-&gt;perminvis = pm_invisible(mdat);
&nbsp;                }
&nbsp;                break;
&nbsp;            }
&nbsp;            default:
&nbsp;                impossible(
&nbsp;                  "create_monster: unimplemented mon appear type [%d,\"%s\"]",
&nbsp;                           m-&gt;appear, m-&gt;appear_as.str);
&nbsp;                break;
&nbsp;            }
&nbsp;            if (does_block(x, y, &amp;levl[x][y]))
&nbsp;                block_point(x, y);
&nbsp;        }
&nbsp;
&nbsp;        if (m-&gt;peaceful &gt;= 0) {
&nbsp;            mtmp-&gt;mpeaceful = m-&gt;peaceful;
&nbsp;            /* changed mpeaceful again; have to reset malign */
&nbsp;            set_malign(mtmp);
&nbsp;        }
&nbsp;        if (m-&gt;asleep &gt;= 0) {
&nbsp;#ifdef UNIXPC
&nbsp;            /* optimizer bug strikes again */
&nbsp;            if (m-&gt;asleep)
&nbsp;                mtmp-&gt;msleeping = 1;
&nbsp;            else
&nbsp;                mtmp-&gt;msleeping = 0;
&nbsp;#else
&nbsp;            mtmp-&gt;msleeping = m-&gt;asleep;
&nbsp;#endif
&nbsp;        }
&nbsp;        if (m-&gt;seentraps)
&nbsp;            mtmp-&gt;mtrapseen = m-&gt;seentraps;
&nbsp;        if (m-&gt;female)
&nbsp;            mtmp-&gt;female = 1;
&nbsp;        if (m-&gt;cancelled)
&nbsp;            mtmp-&gt;mcan = 1;
&nbsp;        if (m-&gt;revived)
&nbsp;            mtmp-&gt;mrevived = 1;
&nbsp;        if (m-&gt;avenge)
&nbsp;            mtmp-&gt;mavenge = 1;
&nbsp;        if (m-&gt;stunned)
&nbsp;            mtmp-&gt;mstun = 1;
&nbsp;        if (m-&gt;confused)
&nbsp;            mtmp-&gt;mconf = 1;
&nbsp;        if (m-&gt;invis) {
&nbsp;            mtmp-&gt;minvis = mtmp-&gt;perminvis = 1;
&nbsp;        }
&nbsp;        if (m-&gt;blinded) {
&nbsp;            mtmp-&gt;mcansee = 0;
&nbsp;            mtmp-&gt;mblinded = (m-&gt;blinded % 127);
&nbsp;        }
&nbsp;        if (m-&gt;paralyzed) {
&nbsp;            mtmp-&gt;mcanmove = 0;
&nbsp;            mtmp-&gt;mfrozen = (m-&gt;paralyzed % 127);
&nbsp;        }
&nbsp;        if (m-&gt;fleeing) {
&nbsp;            mtmp-&gt;mflee = 1;
&nbsp;            mtmp-&gt;mfleetim = (m-&gt;fleeing % 127);
&nbsp;        }
&nbsp;
&nbsp;        if (m-&gt;has_invent) {
&nbsp;            discard_minvent(mtmp);
&nbsp;            invent_carrying_monster = mtmp;
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
create_object
&nbsp;/*
&nbsp; * Create an object in a room.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;create_object(o, croom)
&nbsp;object *o;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    struct obj *otmp;
&nbsp;    schar x, y;
&nbsp;    char c;
&nbsp;    boolean named; /* has a name been supplied in level description? */
&nbsp;
&nbsp;    named = o-&gt;name.str ? TRUE : FALSE;
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY, croom, o-&gt;coord);
&nbsp;
&nbsp;    if (o-&gt;class &gt;= 0)
&nbsp;        c = o-&gt;class;
&nbsp;    else
&nbsp;        c = 0;
&nbsp;
&nbsp;    if (!c)
&nbsp;        otmp = mkobj_at(RANDOM_CLASS, x, y, !named);
&nbsp;    else if (o-&gt;id != -1)
&nbsp;        otmp = mksobj_at(o-&gt;id, x, y, TRUE, !named);
&nbsp;    else {
&nbsp;        /*
&nbsp;         * The special levels are compiled with the default "text" object
&nbsp;         * class characters.  We must convert them to the internal format.
&nbsp;         */
&nbsp;        char oclass = (char) def_char_to_objclass(c);
&nbsp;
&nbsp;        if (oclass == MAXOCLASSES)
&nbsp;            panic("create_object:  unexpected object class '%c'", c);
&nbsp;
&nbsp;        /* KMH -- Create piles of gold properly */
&nbsp;        if (oclass == COIN_CLASS)
&nbsp;            otmp = mkgold(0L, x, y);
&nbsp;        else
&nbsp;            otmp = mkobj_at(oclass, x, y, !named);
&nbsp;    }
&nbsp;
&nbsp;    if (o-&gt;spe != -127) /* That means NOT RANDOM! */
&nbsp;        otmp-&gt;spe = (schar) o-&gt;spe;
&nbsp;
&nbsp;    switch (o-&gt;curse_state) {
&nbsp;    case 1:
&nbsp;        bless(otmp);
&nbsp;        break; /* BLESSED */
&nbsp;    case 2:
&nbsp;        unbless(otmp);
&nbsp;        uncurse(otmp);
&nbsp;        break; /* uncursed */
&nbsp;    case 3:
&nbsp;        curse(otmp);
&nbsp;        break; /* CURSED */
&nbsp;    default:
&nbsp;        break; /* Otherwise it's random and we're happy
&nbsp;                * with what mkobj gave us! */
&nbsp;    }
&nbsp;
&nbsp;    /* corpsenm is "empty" if -1, random if -2, otherwise specific */
&nbsp;    if (o-&gt;corpsenm != NON_PM) {
&nbsp;        if (o-&gt;corpsenm == NON_PM - 1)
&nbsp;            set_corpsenm(otmp, rndmonnum());
&nbsp;        else
&nbsp;            set_corpsenm(otmp, o-&gt;corpsenm);
&nbsp;    }
&nbsp;    /* set_corpsenm() took care of egg hatch and corpse timers */
&nbsp;
&nbsp;    if (named)
&nbsp;        otmp = oname(otmp, o-&gt;name.str);
&nbsp;
&nbsp;    if (o-&gt;eroded) {
&nbsp;        if (o-&gt;eroded &lt; 0) {
&nbsp;            otmp-&gt;oerodeproof = 1;
&nbsp;        } else {
&nbsp;            otmp-&gt;oeroded = (o-&gt;eroded % 4);
&nbsp;            otmp-&gt;oeroded2 = ((o-&gt;eroded &gt;&gt; 2) % 4);
&nbsp;        }
&nbsp;    }
&nbsp;    if (o-&gt;recharged)
&nbsp;        otmp-&gt;recharged = (o-&gt;recharged % 8);
&nbsp;    if (o-&gt;locked) {
&nbsp;        otmp-&gt;olocked = 1;
&nbsp;    } else if (o-&gt;broken) {
&nbsp;        otmp-&gt;obroken = 1;
&nbsp;        otmp-&gt;olocked = 0; /* obj generation may set */
&nbsp;    }
&nbsp;    if (o-&gt;trapped == 0 || o-&gt;trapped == 1)
&nbsp;        otmp-&gt;otrapped = o-&gt;trapped;
&nbsp;    if (o-&gt;greased)
&nbsp;        otmp-&gt;greased = 1;
&nbsp;#ifdef INVISIBLE_OBJECTS
&nbsp;    if (o-&gt;invis)
&nbsp;        otmp-&gt;oinvis = 1;
&nbsp;#endif
&nbsp;
&nbsp;    if (o-&gt;quan &gt; 0 &amp;&amp; objects[otmp-&gt;otyp].oc_merge) {
&nbsp;        otmp-&gt;quan = o-&gt;quan;
&nbsp;        otmp-&gt;owt = weight(otmp);
&nbsp;    }
&nbsp;
&nbsp;    /* contents */
&nbsp;    if (o-&gt;containment &amp; SP_OBJ_CONTENT) {
&nbsp;        if (!container_idx) {
&nbsp;            if (!invent_carrying_monster) {
&nbsp;                /*impossible("create_object: no container");*/
&nbsp;                /* don't complain, the monster may be gone legally
&nbsp;                   (eg. unique demon already generated)
&nbsp;                   TODO: In the case of unique demon lords, they should
&nbsp;                   get their inventories even when they get generated
&nbsp;                   outside the des-file.  Maybe another data file that
&nbsp;                   determines what inventories monsters get by default?
&nbsp;                 */
&nbsp;            } else {
&nbsp;                int ci;
&nbsp;                struct obj *objcheck = otmp;
&nbsp;                int inuse = -1;
&nbsp;
&nbsp;                for (ci = 0; ci &lt; container_idx; ci++)
&nbsp;                    if (container_obj[ci] == objcheck)
&nbsp;                        inuse = ci;
&nbsp;                remove_object(otmp);
&nbsp;                if (mpickobj(invent_carrying_monster, otmp)) {
&nbsp;                    if (inuse &gt; -1) {
&nbsp;                        impossible(
&nbsp;                     "container given to monster was merged or deallocated.");
&nbsp;                        for (ci = inuse; ci &lt; container_idx - 1; ci++)
&nbsp;                            container_obj[ci] = container_obj[ci + 1];
&nbsp;                        container_obj[container_idx] = NULL;
&nbsp;                        container_idx--;
&nbsp;                    }
&nbsp;                    /* we lost track of it. */
&nbsp;                    return;
&nbsp;                }
&nbsp;            }
&nbsp;        } else {
&nbsp;            struct obj *cobj = container_obj[container_idx - 1];
&nbsp;
&nbsp;            remove_object(otmp);
&nbsp;            if (cobj) {
&nbsp;                (void) add_to_container(cobj, otmp);
&nbsp;                cobj-&gt;owt = weight(cobj);
&nbsp;            } else {
&nbsp;                obj_extract_self(otmp);
&nbsp;                obfree(otmp, NULL);
&nbsp;                return;
&nbsp;            }
&nbsp;        }
&nbsp;    }
&nbsp;    /* container */
&nbsp;    if (o-&gt;containment &amp; SP_OBJ_CONTAINER) {
&nbsp;        delete_contents(otmp);
&nbsp;        if (container_idx &lt; MAX_CONTAINMENT) {
&nbsp;            container_obj[container_idx] = otmp;
&nbsp;            container_idx++;
&nbsp;        } else
&nbsp;            impossible("create_object: too deeply nested containers.");
&nbsp;    }
&nbsp;
&nbsp;    /* Medusa level special case: statues are petrified monsters, so they
&nbsp;     * are not stone-resistant and have monster inventory.  They also lack
&nbsp;     * other contents, but that can be specified as an empty container.
&nbsp;     */
&nbsp;    if (o-&gt;id == STATUE &amp;&amp; Is_medusa_level(&amp;u.uz) &amp;&amp; o-&gt;corpsenm == NON_PM) {
&nbsp;        struct monst *was;
&nbsp;        struct obj *obj;
&nbsp;        int wastyp;
&nbsp;        int i = 0; /* prevent endless loop in case makemon always fails */
&nbsp;
&nbsp;        /* Named random statues are of player types, and aren't stone-
&nbsp;         * resistant (if they were, we'd have to reset the name as well as
&nbsp;         * setting corpsenm).
&nbsp;         */
&nbsp;        for (wastyp = otmp-&gt;corpsenm; i &lt; 1000; i++, wastyp = rndmonnum()) {
&nbsp;            /* makemon without rndmonst() might create a group */
&nbsp;            was = makemon(&amp;mons[wastyp], 0, 0, MM_NOCOUNTBIRTH);
&nbsp;            if (was) {
&nbsp;                if (!resists_ston(was)) {
&nbsp;                    (void) propagate(wastyp, TRUE, FALSE);
&nbsp;                    break;
&nbsp;                }
&nbsp;                mongone(was);
&nbsp;                was = NULL;
&nbsp;            }
&nbsp;        }
&nbsp;        if (was) {
&nbsp;            set_corpsenm(otmp, wastyp);
&nbsp;            while (was-&gt;minvent) {
&nbsp;                obj = was-&gt;minvent;
&nbsp;                obj-&gt;owornmask = 0;
&nbsp;                obj_extract_self(obj);
&nbsp;                (void) add_to_container(otmp, obj);
&nbsp;            }
&nbsp;            otmp-&gt;owt = weight(otmp);
&nbsp;            mongone(was);
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    if (o-&gt;id != -1) {
&nbsp;        static const char prize_warning[] = "multiple prizes on %s level";
&nbsp;
&nbsp;        /* if this is a specific item of the right type and it is being
&nbsp;           created on the right level, flag it as the designated item
&nbsp;           used to detect a special achievement (to whit, reaching and
&nbsp;           exploring the target level, although the exploration part
&nbsp;           might be short-circuited if a monster brings object to hero) */
&nbsp;        if (Is_mineend_level(&amp;u.uz)) {
&nbsp;            if (otmp-&gt;otyp == iflags.mines_prize_type) {
&nbsp;                otmp-&gt;record_achieve_special = MINES_PRIZE;
&nbsp;                if (++mines_prize_count &gt; 1)
&nbsp;                    impossible(prize_warning, "mines end");
&nbsp;            }
&nbsp;        } else if (Is_sokoend_level(&amp;u.uz)) {
&nbsp;            if (otmp-&gt;otyp == iflags.soko_prize_type1) {
&nbsp;                otmp-&gt;record_achieve_special = SOKO_PRIZE1;
&nbsp;                if (++soko_prize_count &gt; 1)
&nbsp;                    impossible(prize_warning, "sokoban end");
&nbsp;            } else if (otmp-&gt;otyp == iflags.soko_prize_type2) {
&nbsp;                otmp-&gt;record_achieve_special = SOKO_PRIZE2;
&nbsp;                if (++soko_prize_count &gt; 1)
&nbsp;                    impossible(prize_warning, "sokoban end");
&nbsp;            }
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    stackobj(otmp);
&nbsp;
&nbsp;    if (o-&gt;lit) {
&nbsp;        begin_burn(otmp, FALSE);
&nbsp;    }
&nbsp;
&nbsp;    if (o-&gt;buried) {
&nbsp;        boolean dealloced;
&nbsp;
&nbsp;        (void) bury_an_obj(otmp, &amp;dealloced);
&nbsp;        if (dealloced &amp;&amp; container_idx) {
&nbsp;            container_obj[container_idx - 1] = NULL;
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
create_altar
&nbsp;/*
&nbsp; * Create an altar in a room.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;create_altar(a, croom)
&nbsp;altar *a;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    schar sproom, x = -1, y = -1;
&nbsp;    aligntyp amask;
&nbsp;    boolean croom_is_temple = TRUE;
&nbsp;    int oldtyp;
&nbsp;
&nbsp;    if (croom) {
&nbsp;        get_free_room_loc(&amp;x, &amp;y, croom, a-&gt;coord);
&nbsp;        if (croom-&gt;rtype != TEMPLE)
&nbsp;            croom_is_temple = FALSE;
&nbsp;    } else {
&nbsp;        get_location_coord(&amp;x, &amp;y, DRY, croom, a-&gt;coord);
&nbsp;        if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
&nbsp;            croom = &amp;rooms[sproom - ROOMOFFSET];
&nbsp;        else
&nbsp;            croom_is_temple = FALSE;
&nbsp;    }
&nbsp;
&nbsp;    /* check for existing features */
&nbsp;    oldtyp = levl[x][y].typ;
&nbsp;    if (oldtyp == STAIRS || oldtyp == LADDER)
&nbsp;        return;
&nbsp;
&nbsp;    /* Is the alignment random ?
&nbsp;     * If so, it's an 80% chance that the altar will be co-aligned.
&nbsp;     *
&nbsp;     * The alignment is encoded as amask values instead of alignment
&nbsp;     * values to avoid conflicting with the rest of the encoding,
&nbsp;     * shared by many other parts of the special level code.
&nbsp;     */
&nbsp;    amask = (a-&gt;align == AM_SPLEV_CO)
&nbsp;               ? Align2amask(u.ualignbase[A_ORIGINAL])
&nbsp;               : (a-&gt;align == AM_SPLEV_NONCO)
&nbsp;                  ? Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL]))
&nbsp;                  : (a-&gt;align == -(MAX_REGISTERS + 1))
&nbsp;                     ? induced_align(80)
&nbsp;                     : (a-&gt;align &lt; 0 ? ralign[-a-&gt;align - 1] : a-&gt;align);
&nbsp;
&nbsp;    levl[x][y].typ = ALTAR;
&nbsp;    levl[x][y].altarmask = amask;
&nbsp;
&nbsp;    if (a-&gt;shrine &lt; 0)
&nbsp;        a-&gt;shrine = rn2(2); /* handle random case */
&nbsp;
&nbsp;    if (!croom_is_temple || !a-&gt;shrine)
&nbsp;        return;
&nbsp;
&nbsp;    if (a-&gt;shrine) { /* Is it a shrine  or sanctum? */
&nbsp;        priestini(&amp;u.uz, croom, x, y, (a-&gt;shrine &gt; 1));
&nbsp;        levl[x][y].altarmask |= AM_SHRINE;
&nbsp;        level.flags.has_temple = TRUE;
&nbsp;    }
&nbsp;}
&nbsp;
replace_terrain
&nbsp;void
&nbsp;replace_terrain(terr, croom)
&nbsp;replaceterrain *terr;
&nbsp;struct mkroom *croom;
&nbsp;{
&nbsp;    schar x, y, x1, y1, x2, y2;
&nbsp;
&nbsp;    if (terr-&gt;toter &gt;= MAX_TYPE)
&nbsp;        return;
&nbsp;
&nbsp;    x1 = terr-&gt;x1;
&nbsp;    y1 = terr-&gt;y1;
&nbsp;    get_location(&amp;x1, &amp;y1, ANY_LOC, croom);
&nbsp;
&nbsp;    x2 = terr-&gt;x2;
&nbsp;    y2 = terr-&gt;y2;
&nbsp;    get_location(&amp;x2, &amp;y2, ANY_LOC, croom);
&nbsp;
&nbsp;    for (x = max(x1, 0); x &lt;= min(x2, COLNO - 1); x++)
&nbsp;        for (y = max(y1, 0); y &lt;= min(y2, ROWNO - 1); y++)
&nbsp;            if (levl[x][y].typ == terr-&gt;fromter &amp;&amp; rn2(100) &lt; terr-&gt;chance) {
&nbsp;                SET_TYPLIT(x, y, terr-&gt;toter, terr-&gt;tolit);
&nbsp;            }
&nbsp;}
&nbsp;
search_door
&nbsp;/*
&nbsp; * Search for a door in a room on a specified wall.
&nbsp; */
&nbsp;STATIC_OVL boolean
&nbsp;search_door(croom, x, y, wall, cnt)
&nbsp;struct mkroom *croom;
&nbsp;xchar *x, *y;
&nbsp;xchar wall;
&nbsp;int cnt;
&nbsp;{
&nbsp;    int dx, dy;
&nbsp;    int xx, yy;
&nbsp;
&nbsp;    switch (wall) {
&nbsp;    case W_NORTH:
&nbsp;        dy = 0;
&nbsp;        dx = 1;
&nbsp;        xx = croom-&gt;lx;
&nbsp;        yy = croom-&gt;hy + 1;
&nbsp;        break;
&nbsp;    case W_SOUTH:
&nbsp;        dy = 0;
&nbsp;        dx = 1;
&nbsp;        xx = croom-&gt;lx;
&nbsp;        yy = croom-&gt;ly - 1;
&nbsp;        break;
&nbsp;    case W_EAST:
&nbsp;        dy = 1;
&nbsp;        dx = 0;
&nbsp;        xx = croom-&gt;hx + 1;
&nbsp;        yy = croom-&gt;ly;
&nbsp;        break;
&nbsp;    case W_WEST:
&nbsp;        dy = 1;
&nbsp;        dx = 0;
&nbsp;        xx = croom-&gt;lx - 1;
&nbsp;        yy = croom-&gt;ly;
&nbsp;        break;
&nbsp;    default:
&nbsp;        dx = dy = xx = yy = 0;
&nbsp;        panic("search_door: Bad wall!");
&nbsp;        break;
&nbsp;    }
&nbsp;    while (xx &lt;= croom-&gt;hx + 1 &amp;&amp; yy &lt;= croom-&gt;hy + 1) {
&nbsp;        if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
&nbsp;            *x = xx;
&nbsp;            *y = yy;
&nbsp;            if (cnt-- &lt;= 0)
&nbsp;                return TRUE;
&nbsp;        }
&nbsp;        xx += dx;
&nbsp;        yy += dy;
&nbsp;    }
&nbsp;    return FALSE;
&nbsp;}
&nbsp;
dig_corridor
&nbsp;/*
&nbsp; * Dig a corridor between two points.
&nbsp; */
&nbsp;boolean
&nbsp;dig_corridor(org, dest, nxcor, ftyp, btyp)
&nbsp;coord *org, *dest;
&nbsp;boolean nxcor;
&nbsp;schar ftyp, btyp;
&nbsp;{
&nbsp;    int dx = 0, dy = 0, dix, diy, cct;
&nbsp;    struct rm *crm;
&nbsp;    int tx, ty, xx, yy;
&nbsp;
&nbsp;    xx = org-&gt;x;
&nbsp;    yy = org-&gt;y;
&nbsp;    tx = dest-&gt;x;
&nbsp;    ty = dest-&gt;y;
&nbsp;    if (xx &lt;= 0 || yy &lt;= 0 || tx &lt;= 0 || ty &lt;= 0 || xx &gt; COLNO - 1
&nbsp;        || tx &gt; COLNO - 1 || yy &gt; ROWNO - 1 || ty &gt; ROWNO - 1) {
&nbsp;        debugpline4("dig_corridor: bad coords &lt;%d,%d&gt; &lt;%d,%d&gt;.",
&nbsp;                    xx, yy, tx, ty);
&nbsp;        return FALSE;
&nbsp;    }
&nbsp;    if (tx &gt; xx)
&nbsp;        dx = 1;
&nbsp;    else if (ty &gt; yy)
&nbsp;        dy = 1;
&nbsp;    else if (tx &lt; xx)
&nbsp;        dx = -1;
&nbsp;    else
&nbsp;        dy = -1;
&nbsp;
&nbsp;    xx -= dx;
&nbsp;    yy -= dy;
&nbsp;    cct = 0;
&nbsp;    while (xx != tx || yy != ty) {
&nbsp;        /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
&nbsp;        if (cct++ &gt; 500 || (nxcor &amp;&amp; !rn2(35)))
&nbsp;            return FALSE;
&nbsp;
&nbsp;        xx += dx;
&nbsp;        yy += dy;
&nbsp;
&nbsp;        if (xx &gt;= COLNO - 1 || xx &lt;= 0 || yy &lt;= 0 || yy &gt;= ROWNO - 1)
&nbsp;            return FALSE; /* impossible */
&nbsp;
&nbsp;        crm = &amp;levl[xx][yy];
&nbsp;        if (crm-&gt;typ == btyp) {
&nbsp;            if (ftyp != CORR || rn2(100)) {
&nbsp;                crm-&gt;typ = ftyp;
&nbsp;                if (nxcor &amp;&amp; !rn2(50))
&nbsp;                    (void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE);
&nbsp;            } else {
&nbsp;                crm-&gt;typ = SCORR;
&nbsp;            }
&nbsp;        } else if (crm-&gt;typ != ftyp &amp;&amp; crm-&gt;typ != SCORR) {
&nbsp;            /* strange ... */
&nbsp;            return FALSE;
&nbsp;        }
&nbsp;
&nbsp;        /* find next corridor position */
&nbsp;        dix = abs(xx - tx);
&nbsp;        diy = abs(yy - ty);
&nbsp;
&nbsp;        if ((dix &gt; diy) &amp;&amp; diy &amp;&amp; !rn2(dix-diy+1)) {
&nbsp;            dix = 0;
&nbsp;        } else if ((diy &gt; dix) &amp;&amp; dix &amp;&amp; !rn2(diy-dix+1)) {
&nbsp;            diy = 0;
&nbsp;        }
&nbsp;
&nbsp;        /* do we have to change direction ? */
&nbsp;        if (dy &amp;&amp; dix &gt; diy) {
&nbsp;            register int ddx = (xx &gt; tx) ? -1 : 1;
&nbsp;
&nbsp;            crm = &amp;levl[xx + ddx][yy];
&nbsp;            if (crm-&gt;typ == btyp || crm-&gt;typ == ftyp || crm-&gt;typ == SCORR) {
&nbsp;                dx = ddx;
&nbsp;                dy = 0;
&nbsp;                continue;
&nbsp;            }
&nbsp;        } else if (dx &amp;&amp; diy &gt; dix) {
&nbsp;            register int ddy = (yy &gt; ty) ? -1 : 1;
&nbsp;
&nbsp;            crm = &amp;levl[xx][yy + ddy];
&nbsp;            if (crm-&gt;typ == btyp || crm-&gt;typ == ftyp || crm-&gt;typ == SCORR) {
&nbsp;                dy = ddy;
&nbsp;                dx = 0;
&nbsp;                continue;
&nbsp;            }
&nbsp;        }
&nbsp;
&nbsp;        /* continue straight on? */
&nbsp;        crm = &amp;levl[xx + dx][yy + dy];
&nbsp;        if (crm-&gt;typ == btyp || crm-&gt;typ == ftyp || crm-&gt;typ == SCORR)
&nbsp;            continue;
&nbsp;
&nbsp;        /* no, what must we do now?? */
&nbsp;        if (dx) {
&nbsp;            dx = 0;
&nbsp;            dy = (ty &lt; yy) ? -1 : 1;
&nbsp;        } else {
&nbsp;            dy = 0;
&nbsp;            dx = (tx &lt; xx) ? -1 : 1;
&nbsp;        }
&nbsp;        crm = &amp;levl[xx + dx][yy + dy];
&nbsp;        if (crm-&gt;typ == btyp || crm-&gt;typ == ftyp || crm-&gt;typ == SCORR)
&nbsp;            continue;
&nbsp;        dy = -dy;
&nbsp;        dx = -dx;
&nbsp;    }
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
fix_stair_rooms
&nbsp;/*
&nbsp; * Disgusting hack: since special levels have their rooms filled before
&nbsp; * sorting the rooms, we have to re-arrange the speed values upstairs_room
&nbsp; * and dnstairs_room after the rooms have been sorted.  On normal levels,
&nbsp; * stairs don't get created until _after_ sorting takes place.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;fix_stair_rooms()
&nbsp;{
&nbsp;    int i;
&nbsp;    struct mkroom *croom;
&nbsp;
&nbsp;    if (xdnstair
&nbsp;        &amp;&amp; !((dnstairs_room-&gt;lx &lt;= xdnstair &amp;&amp; xdnstair &lt;= dnstairs_room-&gt;hx)
&nbsp;             &amp;&amp; (dnstairs_room-&gt;ly &lt;= ydnstair
&nbsp;                 &amp;&amp; ydnstair &lt;= dnstairs_room-&gt;hy))) {
&nbsp;        for (i = 0; i &lt; nroom; i++) {
&nbsp;            croom = &amp;rooms[i];
&nbsp;            if ((croom-&gt;lx &lt;= xdnstair &amp;&amp; xdnstair &lt;= croom-&gt;hx)
&nbsp;                &amp;&amp; (croom-&gt;ly &lt;= ydnstair &amp;&amp; ydnstair &lt;= croom-&gt;hy)) {
&nbsp;                dnstairs_room = croom;
&nbsp;                break;
&nbsp;            }
&nbsp;        }
&nbsp;        if (i == nroom)
&nbsp;            panic("Couldn't find dnstair room in fix_stair_rooms!");
&nbsp;    }
&nbsp;    if (xupstair
&nbsp;        &amp;&amp; !((upstairs_room-&gt;lx &lt;= xupstair &amp;&amp; xupstair &lt;= upstairs_room-&gt;hx)
&nbsp;             &amp;&amp; (upstairs_room-&gt;ly &lt;= yupstair
&nbsp;                 &amp;&amp; yupstair &lt;= upstairs_room-&gt;hy))) {
&nbsp;        for (i = 0; i &lt; nroom; i++) {
&nbsp;            croom = &amp;rooms[i];
&nbsp;            if ((croom-&gt;lx &lt;= xupstair &amp;&amp; xupstair &lt;= croom-&gt;hx)
&nbsp;                &amp;&amp; (croom-&gt;ly &lt;= yupstair &amp;&amp; yupstair &lt;= croom-&gt;hy)) {
&nbsp;                upstairs_room = croom;
&nbsp;                break;
&nbsp;            }
&nbsp;        }
&nbsp;        if (i == nroom)
&nbsp;            panic("Couldn't find upstair room in fix_stair_rooms!");
&nbsp;    }
&nbsp;}
&nbsp;
create_corridor
&nbsp;/*
&nbsp; * Corridors always start from a door. But it can end anywhere...
&nbsp; * Basically we search for door coordinates or for endpoints coordinates
&nbsp; * (from a distance).
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;create_corridor(c)
&nbsp;corridor *c;
&nbsp;{
&nbsp;    coord org, dest;
&nbsp;
&nbsp;    if (c-&gt;src.room == -1) {
&nbsp;        fix_stair_rooms();
&nbsp;        makecorridors(); /*makecorridors(c-&gt;src.door);*/
&nbsp;        return;
&nbsp;    }
&nbsp;
&nbsp;    if (!search_door(&amp;rooms[c-&gt;src.room], &amp;org.x, &amp;org.y, c-&gt;src.wall,
&nbsp;                     c-&gt;src.door))
&nbsp;        return;
&nbsp;
&nbsp;    if (c-&gt;dest.room != -1) {
&nbsp;        if (!search_door(&amp;rooms[c-&gt;dest.room], &amp;dest.x, &amp;dest.y, c-&gt;dest.wall,
&nbsp;                         c-&gt;dest.door))
&nbsp;            return;
&nbsp;        switch (c-&gt;src.wall) {
&nbsp;        case W_NORTH:
&nbsp;            org.y--;
&nbsp;            break;
&nbsp;        case W_SOUTH:
&nbsp;            org.y++;
&nbsp;            break;
&nbsp;        case W_WEST:
&nbsp;            org.x--;
&nbsp;            break;
&nbsp;        case W_EAST:
&nbsp;            org.x++;
&nbsp;            break;
&nbsp;        }
&nbsp;        switch (c-&gt;dest.wall) {
&nbsp;        case W_NORTH:
&nbsp;            dest.y--;
&nbsp;            break;
&nbsp;        case W_SOUTH:
&nbsp;            dest.y++;
&nbsp;            break;
&nbsp;        case W_WEST:
&nbsp;            dest.x--;
&nbsp;            break;
&nbsp;        case W_EAST:
&nbsp;            dest.x++;
&nbsp;            break;
&nbsp;        }
&nbsp;        (void) dig_corridor(&amp;org, &amp;dest, FALSE, CORR, STONE);
&nbsp;    }
&nbsp;}
&nbsp;
fill_room
&nbsp;/*
&nbsp; * Fill a room (shop, zoo, etc...) with appropriate stuff.
&nbsp; */
&nbsp;void
&nbsp;fill_room(croom, prefilled)
&nbsp;struct mkroom *croom;
&nbsp;boolean prefilled;
&nbsp;{
&nbsp;    if (!croom || croom-&gt;rtype == OROOM)
&nbsp;        return;
&nbsp;
&nbsp;    if (!prefilled) {
&nbsp;        int x, y;
&nbsp;
&nbsp;        /* Shop ? */
&nbsp;        if (croom-&gt;rtype &gt;= SHOPBASE) {
&nbsp;            stock_room(croom-&gt;rtype - SHOPBASE, croom);
&nbsp;            level.flags.has_shop = TRUE;
&nbsp;            return;
&nbsp;        }
&nbsp;
&nbsp;        switch (croom-&gt;rtype) {
&nbsp;        case VAULT:
&nbsp;            for (x = croom-&gt;lx; x &lt;= croom-&gt;hx; x++)
&nbsp;                for (y = croom-&gt;ly; y &lt;= croom-&gt;hy; y++)
&nbsp;                    (void) mkgold((long) rn1(abs(depth(&amp;u.uz)) * 100, 51),
&nbsp;                                  x, y);
&nbsp;            break;
&nbsp;        case COURT:
&nbsp;        case ZOO:
&nbsp;        case BEEHIVE:
&nbsp;        case MORGUE:
&nbsp;        case BARRACKS:
&nbsp;            fill_zoo(croom);
&nbsp;            break;
&nbsp;        }
&nbsp;    }
&nbsp;    switch (croom-&gt;rtype) {
&nbsp;    case VAULT:
&nbsp;        level.flags.has_vault = TRUE;
&nbsp;        break;
&nbsp;    case ZOO:
&nbsp;        level.flags.has_zoo = TRUE;
&nbsp;        break;
&nbsp;    case COURT:
&nbsp;        level.flags.has_court = TRUE;
&nbsp;        break;
&nbsp;    case MORGUE:
&nbsp;        level.flags.has_morgue = TRUE;
&nbsp;        break;
&nbsp;    case BEEHIVE:
&nbsp;        level.flags.has_beehive = TRUE;
&nbsp;        break;
&nbsp;    case BARRACKS:
&nbsp;        level.flags.has_barracks = TRUE;
&nbsp;        break;
&nbsp;    case TEMPLE:
&nbsp;        level.flags.has_temple = TRUE;
&nbsp;        break;
&nbsp;    case SWAMP:
&nbsp;        level.flags.has_swamp = TRUE;
&nbsp;        break;
&nbsp;    }
&nbsp;}
&nbsp;
build_room
&nbsp;struct mkroom *
&nbsp;build_room(r, mkr)
&nbsp;room *r;
&nbsp;struct mkroom *mkr;
&nbsp;{
&nbsp;    boolean okroom;
&nbsp;    struct mkroom *aroom;
&nbsp;    xchar rtype = (!r-&gt;chance || rn2(100) &lt; r-&gt;chance) ? r-&gt;rtype : OROOM;
&nbsp;
&nbsp;    if (mkr) {
&nbsp;        aroom = &amp;subrooms[nsubroom];
&nbsp;        okroom = create_subroom(mkr, r-&gt;x, r-&gt;y, r-&gt;w, r-&gt;h, rtype, r-&gt;rlit);
&nbsp;    } else {
&nbsp;        aroom = &amp;rooms[nroom];
&nbsp;        okroom = create_room(r-&gt;x, r-&gt;y, r-&gt;w, r-&gt;h, r-&gt;xalign, r-&gt;yalign,
&nbsp;                             rtype, r-&gt;rlit);
&nbsp;    }
&nbsp;
&nbsp;    if (okroom) {
&nbsp;#ifdef SPECIALIZATION
&nbsp;        topologize(aroom, FALSE); /* set roomno */
&nbsp;#else
&nbsp;        topologize(aroom); /* set roomno */
&nbsp;#endif
&nbsp;        aroom-&gt;needfill = r-&gt;filled;
&nbsp;        aroom-&gt;needjoining = r-&gt;joined;
&nbsp;        return aroom;
&nbsp;    }
&nbsp;    return (struct mkroom *) 0;
&nbsp;}
&nbsp;
light_region
&nbsp;/*
&nbsp; * set lighting in a region that will not become a room.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;light_region(tmpregion)
&nbsp;region *tmpregion;
&nbsp;{
&nbsp;    register boolean litstate = tmpregion-&gt;rlit ? 1 : 0;
&nbsp;    register int hiy = tmpregion-&gt;y2;
&nbsp;    register int x, y;
&nbsp;    register struct rm *lev;
&nbsp;    int lowy = tmpregion-&gt;y1;
&nbsp;    int lowx = tmpregion-&gt;x1, hix = tmpregion-&gt;x2;
&nbsp;
&nbsp;    if (litstate) {
&nbsp;        /* adjust region size for walls, but only if lighted */
&nbsp;        lowx = max(lowx - 1, 1);
&nbsp;        hix = min(hix + 1, COLNO - 1);
&nbsp;        lowy = max(lowy - 1, 0);
&nbsp;        hiy = min(hiy + 1, ROWNO - 1);
&nbsp;    }
&nbsp;    for (x = lowx; x &lt;= hix; x++) {
&nbsp;        lev = &amp;levl[x][lowy];
&nbsp;        for (y = lowy; y &lt;= hiy; y++) {
&nbsp;            if (lev-&gt;typ != LAVAPOOL) /* this overrides normal lighting */
&nbsp;                lev-&gt;lit = litstate;
&nbsp;            lev++;
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
wallify_map
&nbsp;void
&nbsp;wallify_map(x1, y1, x2, y2)
&nbsp;int x1, y1, x2, y2;
&nbsp;{
&nbsp;    int x, y, xx, yy, lo_xx, lo_yy, hi_xx, hi_yy;
&nbsp;
&nbsp;    for (y = y1; y &lt;= y2; y++) {
&nbsp;        lo_yy = (y &gt; 0) ? y - 1 : 0;
&nbsp;        hi_yy = (y &lt; y2) ? y + 1 : y2;
&nbsp;        for (x = x1; x &lt;= x2; x++) {
&nbsp;            if (levl[x][y].typ != STONE)
&nbsp;                continue;
&nbsp;            lo_xx = (x &gt; 0) ? x - 1 : 0;
&nbsp;            hi_xx = (x &lt; x2) ? x + 1 : x2;
&nbsp;            for (yy = lo_yy; yy &lt;= hi_yy; yy++)
&nbsp;                for (xx = lo_xx; xx &lt;= hi_xx; xx++)
&nbsp;                    if (IS_ROOM(levl[xx][yy].typ)
&nbsp;                        || levl[xx][yy].typ == CROSSWALL) {
&nbsp;                        levl[x][y].typ = (yy != y) ? HWALL : VWALL;
&nbsp;                        yy = hi_yy; /* end `yy' loop */
&nbsp;                        break;      /* end `xx' loop */
&nbsp;                    }
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
maze1xy
&nbsp;/*
&nbsp; * Select a random coordinate in the maze.
&nbsp; *
&nbsp; * We want a place not 'touched' by the loader.  That is, a place in
&nbsp; * the maze outside every part of the special level.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;maze1xy(m, humidity)
&nbsp;coord *m;
&nbsp;int humidity;
&nbsp;{
&nbsp;    register int x, y, tryct = 2000;
&nbsp;    /* tryct:  normally it won't take more than ten or so tries due
&nbsp;       to the circumstances under which we'll be called, but the
&nbsp;       `humidity' screening might drastically change the chances */
&nbsp;
&nbsp;    do {
&nbsp;        x = rn1(x_maze_max - 3, 3);
&nbsp;        y = rn1(y_maze_max - 3, 3);
&nbsp;        if (--tryct &lt; 0)
&nbsp;            break; /* give up */
&nbsp;    } while (!(x % 2) || !(y % 2) || SpLev_Map[x][y]
&nbsp;             || !is_ok_location((schar) x, (schar) y, humidity));
&nbsp;
&nbsp;    m-&gt;x = (xchar) x, m-&gt;y = (xchar) y;
&nbsp;}
&nbsp;
fill_empty_maze
&nbsp;/*
&nbsp; * If there's a significant portion of maze unused by the special level,
&nbsp; * we don't want it empty.
&nbsp; *
&nbsp; * Makes the number of traps, monsters, etc. proportional
&nbsp; * to the size of the maze.
&nbsp; */
&nbsp;STATIC_OVL void
&nbsp;fill_empty_maze()
&nbsp;{
&nbsp;    int mapcountmax, mapcount, mapfact;
&nbsp;    xchar x, y;
&nbsp;    coord mm;
&nbsp;
&nbsp;    mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
&nbsp;    mapcountmax = mapcountmax / 2;
&nbsp;
&nbsp;    for (x = 2; x &lt; x_maze_max; x++)
&nbsp;        for (y = 0; y &lt; y_maze_max; y++)
&nbsp;            if (SpLev_Map[x][y])
&nbsp;                mapcount--;
&nbsp;
&nbsp;    if ((mapcount &gt; (int) (mapcountmax / 10))) {
&nbsp;        mapfact = (int) ((mapcount * 100L) / mapcountmax);
&nbsp;        for (x = rnd((int) (20 * mapfact) / 100); x; x--) {
&nbsp;            maze1xy(&amp;mm, DRY);
&nbsp;            (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS, mm.x, mm.y,
&nbsp;                            TRUE);
&nbsp;        }
&nbsp;        for (x = rnd((int) (12 * mapfact) / 100); x; x--) {
&nbsp;            maze1xy(&amp;mm, DRY);
&nbsp;            (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE);
&nbsp;        }
&nbsp;        for (x = rn2(2); x; x--) {
&nbsp;            maze1xy(&amp;mm, DRY);
&nbsp;            (void) makemon(&amp;mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS);
&nbsp;        }
&nbsp;        for (x = rnd((int) (12 * mapfact) / 100); x; x--) {
&nbsp;            maze1xy(&amp;mm, DRY);
&nbsp;            (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS);
&nbsp;        }
&nbsp;        for (x = rn2((int) (15 * mapfact) / 100); x; x--) {
&nbsp;            maze1xy(&amp;mm, DRY);
&nbsp;            (void) mkgold(0L, mm.x, mm.y);
&nbsp;        }
&nbsp;        for (x = rn2((int) (15 * mapfact) / 100); x; x--) {
&nbsp;            int trytrap;
&nbsp;
&nbsp;            maze1xy(&amp;mm, DRY);
&nbsp;            trytrap = rndtrap();
&nbsp;            if (sobj_at(BOULDER, mm.x, mm.y))
&nbsp;                while (trytrap == PIT || trytrap == SPIKED_PIT
&nbsp;                       || trytrap == TRAPDOOR || trytrap == HOLE)
&nbsp;                    trytrap = rndtrap();
&nbsp;            (void) maketrap(mm.x, mm.y, trytrap);
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
sp_level_loader
&nbsp;/*
&nbsp; * special level loader
&nbsp; */
&nbsp;STATIC_OVL boolean
&nbsp;sp_level_loader(fd, lvl)
&nbsp;dlb *fd;
&nbsp;sp_lev *lvl;
&nbsp;{
&nbsp;    long n_opcode = 0;
&nbsp;    struct opvar *opdat;
&nbsp;    int opcode;
&nbsp;
&nbsp;    Fread((genericptr_t) &amp; (lvl-&gt;n_opcodes), 1, sizeof(lvl-&gt;n_opcodes), fd);
&nbsp;    lvl-&gt;opcodes = (_opcode *) alloc(sizeof(_opcode) * (lvl-&gt;n_opcodes));
&nbsp;
&nbsp;    while (n_opcode &lt; lvl-&gt;n_opcodes) {
&nbsp;        Fread((genericptr_t) &amp;lvl-&gt;opcodes[n_opcode].opcode, 1,
&nbsp;              sizeof(lvl-&gt;opcodes[n_opcode].opcode), fd);
&nbsp;        opcode = lvl-&gt;opcodes[n_opcode].opcode;
&nbsp;
&nbsp;        opdat = NULL;
&nbsp;
&nbsp;        if (opcode &lt; SPO_NULL || opcode &gt;= MAX_SP_OPCODES)
&nbsp;            panic("sp_level_loader: impossible opcode %i.", opcode);
&nbsp;
&nbsp;        if (opcode == SPO_PUSH) {
&nbsp;            int nsize;
&nbsp;            struct opvar *ov = (struct opvar *) alloc(sizeof(struct opvar));
&nbsp;
&nbsp;            opdat = ov;
&nbsp;            ov-&gt;spovartyp = SPO_NULL;
&nbsp;            ov-&gt;vardata.l = 0;
&nbsp;            Fread((genericptr_t) &amp; (ov-&gt;spovartyp), 1, sizeof(ov-&gt;spovartyp),
&nbsp;                  fd);
&nbsp;
&nbsp;            switch (ov-&gt;spovartyp) {
&nbsp;            case SPOVAR_NULL:
&nbsp;                break;
&nbsp;            case SPOVAR_COORD:
&nbsp;            case SPOVAR_REGION:
&nbsp;            case SPOVAR_MAPCHAR:
&nbsp;            case SPOVAR_MONST:
&nbsp;            case SPOVAR_OBJ:
&nbsp;            case SPOVAR_INT:
&nbsp;                Fread((genericptr_t) &amp; (ov-&gt;vardata.l), 1,
&nbsp;                      sizeof(ov-&gt;vardata.l), fd);
&nbsp;                break;
&nbsp;            case SPOVAR_VARIABLE:
&nbsp;            case SPOVAR_STRING:
&nbsp;            case SPOVAR_SEL: {
&nbsp;                char *opd;
&nbsp;
&nbsp;                Fread((genericptr_t) &amp;nsize, 1, sizeof(nsize), fd);
&nbsp;                opd = (char *) alloc(nsize + 1);
&nbsp;
&nbsp;                if (nsize)
&nbsp;                    Fread(opd, 1, nsize, fd);
&nbsp;                opd[nsize] = 0;
&nbsp;                ov-&gt;vardata.str = opd;
&nbsp;                break;
&nbsp;            }
&nbsp;            default:
&nbsp;                panic("sp_level_loader: unknown opvar type %i",
&nbsp;                      ov-&gt;spovartyp);
&nbsp;            }
&nbsp;        }
&nbsp;
&nbsp;        lvl-&gt;opcodes[n_opcode].opdat = opdat;
&nbsp;        n_opcode++;
&nbsp;    } /*while*/
&nbsp;
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
sp_level_free
&nbsp;/* Frees the memory allocated for special level creation structs */
&nbsp;STATIC_OVL boolean
&nbsp;sp_level_free(lvl)
&nbsp;sp_lev *lvl;
&nbsp;{
&nbsp;    static const char nhFunc[] = "sp_level_free";
&nbsp;    long n_opcode = 0;
&nbsp;
&nbsp;    while (n_opcode &lt; lvl-&gt;n_opcodes) {
&nbsp;        int opcode = lvl-&gt;opcodes[n_opcode].opcode;
&nbsp;        struct opvar *opdat = lvl-&gt;opcodes[n_opcode].opdat;
&nbsp;
&nbsp;        if (opcode &lt; SPO_NULL || opcode &gt;= MAX_SP_OPCODES)
&nbsp;            panic("sp_level_free: unknown opcode %i", opcode);
&nbsp;
&nbsp;        if (opdat)
&nbsp;            opvar_free(opdat);
&nbsp;        n_opcode++;
&nbsp;    }
&nbsp;    Free(lvl-&gt;opcodes);
&nbsp;    lvl-&gt;opcodes = NULL;
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
splev_initlev
&nbsp;void
&nbsp;splev_initlev(linit)
&nbsp;lev_init *linit;
&nbsp;{
&nbsp;    switch (linit-&gt;init_style) {
&nbsp;    default:
&nbsp;        impossible("Unrecognized level init style.");
&nbsp;        break;
&nbsp;    case LVLINIT_NONE:
&nbsp;        break;
&nbsp;    case LVLINIT_SOLIDFILL:
&nbsp;        if (linit-&gt;lit == -1)
&nbsp;            linit-&gt;lit = rn2(2);
&nbsp;        lvlfill_solid(linit-&gt;filling, linit-&gt;lit);
&nbsp;        break;
&nbsp;    case LVLINIT_MAZEGRID:
&nbsp;        lvlfill_maze_grid(2, 0, x_maze_max, y_maze_max, linit-&gt;filling);
&nbsp;        break;
&nbsp;    case LVLINIT_ROGUE:
&nbsp;        makeroguerooms();
&nbsp;        break;
&nbsp;    case LVLINIT_MINES:
&nbsp;        if (linit-&gt;lit == -1)
&nbsp;            linit-&gt;lit = rn2(2);
&nbsp;        if (linit-&gt;filling &gt; -1)
&nbsp;            lvlfill_solid(linit-&gt;filling, 0);
&nbsp;        linit-&gt;icedpools = icedpools;
&nbsp;        mkmap(linit);
&nbsp;        break;
&nbsp;    }
&nbsp;}
&nbsp;
frame_new
&nbsp;struct sp_frame *
&nbsp;frame_new(execptr)
&nbsp;long execptr;
&nbsp;{
&nbsp;    struct sp_frame *frame =
&nbsp;        (struct sp_frame *) alloc(sizeof(struct sp_frame));
&nbsp;
&nbsp;    frame-&gt;next = NULL;
&nbsp;    frame-&gt;variables = NULL;
&nbsp;    frame-&gt;n_opcode = execptr;
&nbsp;    frame-&gt;stack = (struct splevstack *) alloc(sizeof(struct splevstack));
&nbsp;    splev_stack_init(frame-&gt;stack);
&nbsp;    return frame;
&nbsp;}
&nbsp;
frame_del
&nbsp;void
&nbsp;frame_del(frame)
&nbsp;struct sp_frame *frame;
&nbsp;{
&nbsp;    if (!frame)
&nbsp;        return;
&nbsp;    if (frame-&gt;stack) {
&nbsp;        splev_stack_done(frame-&gt;stack);
&nbsp;        frame-&gt;stack = NULL;
&nbsp;    }
&nbsp;    if (frame-&gt;variables) {
&nbsp;        variable_list_del(frame-&gt;variables);
&nbsp;        frame-&gt;variables = NULL;
&nbsp;    }
&nbsp;    Free(frame);
&nbsp;}
&nbsp;
spo_frame_push
&nbsp;void
&nbsp;spo_frame_push(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    struct sp_frame *tmpframe = frame_new(coder-&gt;frame-&gt;n_opcode);
&nbsp;
&nbsp;    tmpframe-&gt;next = coder-&gt;frame;
&nbsp;    coder-&gt;frame = tmpframe;
&nbsp;}
&nbsp;
spo_frame_pop
&nbsp;void
&nbsp;spo_frame_pop(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    if (coder-&gt;frame &amp;&amp; coder-&gt;frame-&gt;next) {
&nbsp;        struct sp_frame *tmpframe = coder-&gt;frame-&gt;next;
&nbsp;
&nbsp;        frame_del(coder-&gt;frame);
&nbsp;        coder-&gt;frame = tmpframe;
&nbsp;        coder-&gt;stack = coder-&gt;frame-&gt;stack;
&nbsp;    }
&nbsp;}
&nbsp;
sp_code_jmpaddr
&nbsp;long
&nbsp;sp_code_jmpaddr(curpos, jmpaddr)
&nbsp;long curpos, jmpaddr;
&nbsp;{
&nbsp;    return (curpos + jmpaddr);
&nbsp;}
&nbsp;
spo_call
&nbsp;void
&nbsp;spo_call(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_call";
&nbsp;    struct opvar *addr;
&nbsp;    struct opvar *params;
&nbsp;    struct sp_frame *tmpframe;
&nbsp;
&nbsp;    if (!OV_pop_i(addr) || !OV_pop_i(params))
&nbsp;        return;
&nbsp;    if (OV_i(params) &lt; 0)
&nbsp;        return;
&nbsp;
&nbsp;    tmpframe = frame_new(sp_code_jmpaddr(coder-&gt;frame-&gt;n_opcode,
&nbsp;                                         OV_i(addr) - 1));
&nbsp;
&nbsp;    while (OV_i(params)-- &gt; 0) {
&nbsp;        splev_stack_push(tmpframe-&gt;stack, splev_stack_getdat_any(coder));
&nbsp;    }
&nbsp;    splev_stack_reverse(tmpframe-&gt;stack);
&nbsp;
&nbsp;    /* push a frame */
&nbsp;    tmpframe-&gt;next = coder-&gt;frame;
&nbsp;    coder-&gt;frame = tmpframe;
&nbsp;
&nbsp;    opvar_free(addr);
&nbsp;    opvar_free(params);
&nbsp;}
&nbsp;
spo_return
&nbsp;void
&nbsp;spo_return(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_return";
&nbsp;    struct opvar *params;
&nbsp;
&nbsp;    if (!coder-&gt;frame || !coder-&gt;frame-&gt;next)
&nbsp;        panic("return: no frame.");
&nbsp;    if (!OV_pop_i(params))
&nbsp;        return;
&nbsp;    if (OV_i(params) &lt; 0)
&nbsp;        return;
&nbsp;
&nbsp;    while (OV_i(params)-- &gt; 0) {
&nbsp;        splev_stack_push(coder-&gt;frame-&gt;next-&gt;stack,
&nbsp;                         splev_stack_pop(coder-&gt;stack));
&nbsp;    }
&nbsp;
&nbsp;    /* pop the frame */
&nbsp;    if (coder-&gt;frame-&gt;next) {
&nbsp;        struct sp_frame *tmpframe = coder-&gt;frame-&gt;next;
&nbsp;        frame_del(coder-&gt;frame);
&nbsp;        coder-&gt;frame = tmpframe;
&nbsp;        coder-&gt;stack = coder-&gt;frame-&gt;stack;
&nbsp;    }
&nbsp;
&nbsp;    opvar_free(params);
&nbsp;}
&nbsp;
&nbsp;/*ARGUSED*/
spo_end_moninvent
&nbsp;void
&nbsp;spo_end_moninvent(coder)
&nbsp;struct sp_coder *coder UNUSED;
&nbsp;{
&nbsp;    if (invent_carrying_monster)
&nbsp;        m_dowear(invent_carrying_monster, TRUE);
&nbsp;    invent_carrying_monster = NULL;
&nbsp;}
&nbsp;
&nbsp;/*ARGUSED*/
spo_pop_container
&nbsp;void
&nbsp;spo_pop_container(coder)
&nbsp;struct sp_coder *coder UNUSED;
&nbsp;{
&nbsp;    if (container_idx &gt; 0) {
&nbsp;        container_idx--;
&nbsp;        container_obj[container_idx] = NULL;
&nbsp;    }
&nbsp;}
&nbsp;
spo_message
&nbsp;void
&nbsp;spo_message(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_message";
&nbsp;    struct opvar *op;
&nbsp;    char *msg, *levmsg;
&nbsp;    int old_n, n;
&nbsp;
&nbsp;    if (!OV_pop_s(op))
&nbsp;        return;
&nbsp;    msg = OV_s(op);
&nbsp;    if (!msg)
&nbsp;        return;
&nbsp;
&nbsp;    old_n = lev_message ? (strlen(lev_message) + 1) : 0;
&nbsp;    n = strlen(msg);
&nbsp;
&nbsp;    levmsg = (char *) alloc(old_n + n + 1);
&nbsp;    if (old_n)
&nbsp;        levmsg[old_n - 1] = '\n';
&nbsp;    if (lev_message)
&nbsp;        (void) memcpy((genericptr_t) levmsg, (genericptr_t) lev_message,
&nbsp;                      old_n - 1);
&nbsp;    (void) memcpy((genericptr_t) &amp;levmsg[old_n], msg, n);
&nbsp;    levmsg[old_n + n] = '\0';
&nbsp;    Free(lev_message);
&nbsp;    lev_message = levmsg;
&nbsp;    opvar_free(op);
&nbsp;}
&nbsp;
spo_monster
&nbsp;void
&nbsp;spo_monster(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_monster";
&nbsp;    int nparams = 0;
&nbsp;    struct opvar *varparam;
&nbsp;    struct opvar *id, *mcoord, *has_inv;
&nbsp;    monster tmpmons;
&nbsp;
&nbsp;    tmpmons.peaceful = -1;
&nbsp;    tmpmons.asleep = -1;
&nbsp;    tmpmons.name.str = (char *) 0;
&nbsp;    tmpmons.appear = 0;
&nbsp;    tmpmons.appear_as.str = (char *) 0;
&nbsp;    tmpmons.align = -MAX_REGISTERS - 2;
&nbsp;    tmpmons.female = 0;
&nbsp;    tmpmons.invis = 0;
&nbsp;    tmpmons.cancelled = 0;
&nbsp;    tmpmons.revived = 0;
&nbsp;    tmpmons.avenge = 0;
&nbsp;    tmpmons.fleeing = 0;
&nbsp;    tmpmons.blinded = 0;
&nbsp;    tmpmons.paralyzed = 0;
&nbsp;    tmpmons.stunned = 0;
&nbsp;    tmpmons.confused = 0;
&nbsp;    tmpmons.seentraps = 0;
&nbsp;    tmpmons.has_invent = 0;
&nbsp;
&nbsp;    if (!OV_pop_i(has_inv))
&nbsp;        return;
&nbsp;
&nbsp;    if (!OV_pop_i(varparam))
&nbsp;        return;
&nbsp;
&nbsp;    while ((nparams++ &lt; (SP_M_V_END + 1)) &amp;&amp; (OV_typ(varparam) == SPOVAR_INT)
&nbsp;           &amp;&amp; (OV_i(varparam) &gt;= 0) &amp;&amp; (OV_i(varparam) &lt; SP_M_V_END)) {
&nbsp;        struct opvar *parm = NULL;
&nbsp;
&nbsp;        OV_pop(parm);
&nbsp;        switch (OV_i(varparam)) {
&nbsp;        case SP_M_V_NAME:
&nbsp;            if ((OV_typ(parm) == SPOVAR_STRING) &amp;&amp; !tmpmons.name.str)
&nbsp;                tmpmons.name.str = dupstr(OV_s(parm));
&nbsp;            break;
&nbsp;        case SP_M_V_APPEAR:
&nbsp;            if ((OV_typ(parm) == SPOVAR_INT) &amp;&amp; !tmpmons.appear_as.str) {
&nbsp;                tmpmons.appear = OV_i(parm);
&nbsp;                opvar_free(parm);
&nbsp;                OV_pop(parm);
&nbsp;                tmpmons.appear_as.str = dupstr(OV_s(parm));
&nbsp;            }
&nbsp;            break;
&nbsp;        case SP_M_V_ASLEEP:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.asleep = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_ALIGN:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.align = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_PEACEFUL:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.peaceful = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_FEMALE:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.female = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_INVIS:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.invis = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_CANCELLED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.cancelled = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_REVIVED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.revived = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_AVENGE:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.avenge = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_FLEEING:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.fleeing = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_BLINDED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.blinded = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_PARALYZED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.paralyzed = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_STUNNED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.stunned = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_CONFUSED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.confused = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_SEENTRAPS:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpmons.seentraps = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_M_V_END:
&nbsp;            nparams = SP_M_V_END + 1;
&nbsp;            break;
&nbsp;        default:
&nbsp;            impossible("MONSTER with unknown variable param type!");
&nbsp;            break;
&nbsp;        }
&nbsp;        opvar_free(parm);
&nbsp;        if (OV_i(varparam) != SP_M_V_END) {
&nbsp;            opvar_free(varparam);
&nbsp;            OV_pop(varparam);
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    if (!OV_pop_c(mcoord))
&nbsp;        panic("no monster coord?");
&nbsp;
&nbsp;    if (!OV_pop_typ(id, SPOVAR_MONST))
&nbsp;        panic("no mon type");
&nbsp;
&nbsp;    tmpmons.id = SP_MONST_PM(OV_i(id));
&nbsp;    tmpmons.class = SP_MONST_CLASS(OV_i(id));
&nbsp;    tmpmons.coord = OV_i(mcoord);
&nbsp;    tmpmons.has_invent = OV_i(has_inv);
&nbsp;
&nbsp;    create_monster(&amp;tmpmons, coder-&gt;croom);
&nbsp;
&nbsp;    Free(tmpmons.name.str);
&nbsp;    Free(tmpmons.appear_as.str);
&nbsp;    opvar_free(id);
&nbsp;    opvar_free(mcoord);
&nbsp;    opvar_free(has_inv);
&nbsp;    opvar_free(varparam);
&nbsp;}
&nbsp;
spo_object
&nbsp;void
&nbsp;spo_object(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_object";
&nbsp;    int nparams = 0;
&nbsp;    long quancnt;
&nbsp;    struct opvar *varparam;
&nbsp;    struct opvar *id, *containment;
&nbsp;    object tmpobj;
&nbsp;
&nbsp;    tmpobj.spe = -127;
&nbsp;    tmpobj.curse_state = -1;
&nbsp;    tmpobj.corpsenm = NON_PM;
&nbsp;    tmpobj.name.str = (char *) 0;
&nbsp;    tmpobj.quan = -1;
&nbsp;    tmpobj.buried = 0;
&nbsp;    tmpobj.lit = 0;
&nbsp;    tmpobj.eroded = 0;
&nbsp;    tmpobj.locked = 0;
&nbsp;    tmpobj.trapped = -1;
&nbsp;    tmpobj.recharged = 0;
&nbsp;    tmpobj.invis = 0;
&nbsp;    tmpobj.greased = 0;
&nbsp;    tmpobj.broken = 0;
&nbsp;    tmpobj.coord = SP_COORD_PACK_RANDOM(0);
&nbsp;
&nbsp;    if (!OV_pop_i(containment))
&nbsp;        return;
&nbsp;
&nbsp;    if (!OV_pop_i(varparam))
&nbsp;        return;
&nbsp;
&nbsp;    while ((nparams++ &lt; (SP_O_V_END + 1)) &amp;&amp; (OV_typ(varparam) == SPOVAR_INT)
&nbsp;           &amp;&amp; (OV_i(varparam) &gt;= 0) &amp;&amp; (OV_i(varparam) &lt; SP_O_V_END)) {
&nbsp;        struct opvar *parm;
&nbsp;
&nbsp;        OV_pop(parm);
&nbsp;        switch (OV_i(varparam)) {
&nbsp;        case SP_O_V_NAME:
&nbsp;            if ((OV_typ(parm) == SPOVAR_STRING) &amp;&amp; !tmpobj.name.str)
&nbsp;                tmpobj.name.str = dupstr(OV_s(parm));
&nbsp;            break;
&nbsp;        case SP_O_V_CORPSENM:
&nbsp;            if (OV_typ(parm) == SPOVAR_MONST) {
&nbsp;                char monclass = SP_MONST_CLASS(OV_i(parm));
&nbsp;                int monid = SP_MONST_PM(OV_i(parm));
&nbsp;
&nbsp;                if (monid &gt;= LOW_PM &amp;&amp; monid &lt; NUMMONS) {
&nbsp;                    tmpobj.corpsenm = monid;
&nbsp;                    break; /* we're done! */
&nbsp;                } else {
&nbsp;                    struct permonst *pm = (struct permonst *) 0;
&nbsp;
&nbsp;                    if (def_char_to_monclass(monclass) != MAXMCLASSES) {
&nbsp;                        pm = mkclass(def_char_to_monclass(monclass), G_NOGEN);
&nbsp;                    } else {
&nbsp;                        pm = rndmonst();
&nbsp;                    }
&nbsp;                    if (pm)
&nbsp;                        tmpobj.corpsenm = monsndx(pm);
&nbsp;                }
&nbsp;            }
&nbsp;            break;
&nbsp;        case SP_O_V_CURSE:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.curse_state = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_SPE:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.spe = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_QUAN:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.quan = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_BURIED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.buried = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_LIT:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.lit = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_ERODED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.eroded = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_LOCKED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.locked = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_TRAPPED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.trapped = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_RECHARGED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.recharged = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_INVIS:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.invis = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_GREASED:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.greased = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_BROKEN:
&nbsp;            if (OV_typ(parm) == SPOVAR_INT)
&nbsp;                tmpobj.broken = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_COORD:
&nbsp;            if (OV_typ(parm) != SPOVAR_COORD)
&nbsp;                panic("no coord for obj?");
&nbsp;            tmpobj.coord = OV_i(parm);
&nbsp;            break;
&nbsp;        case SP_O_V_END:
&nbsp;            nparams = SP_O_V_END + 1;
&nbsp;            break;
&nbsp;        default:
&nbsp;            impossible("OBJECT with unknown variable param type!");
&nbsp;            break;
&nbsp;        }
&nbsp;        opvar_free(parm);
&nbsp;        if (OV_i(varparam) != SP_O_V_END) {
&nbsp;            opvar_free(varparam);
&nbsp;            OV_pop(varparam);
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    if (!OV_pop_typ(id, SPOVAR_OBJ))
&nbsp;        panic("no obj type");
&nbsp;
&nbsp;    tmpobj.id = SP_OBJ_TYP(OV_i(id));
&nbsp;    tmpobj.class = SP_OBJ_CLASS(OV_i(id));
&nbsp;    tmpobj.containment = OV_i(containment);
&nbsp;
&nbsp;    quancnt = (tmpobj.id &gt; STRANGE_OBJECT) ? tmpobj.quan : 0;
&nbsp;
&nbsp;    do {
&nbsp;        create_object(&amp;tmpobj, coder-&gt;croom);
&nbsp;        quancnt--;
&nbsp;    } while ((quancnt &gt; 0) &amp;&amp; ((tmpobj.id &gt; STRANGE_OBJECT)
&nbsp;                               &amp;&amp; !objects[tmpobj.id].oc_merge));
&nbsp;
&nbsp;    Free(tmpobj.name.str);
&nbsp;    opvar_free(varparam);
&nbsp;    opvar_free(id);
&nbsp;    opvar_free(containment);
&nbsp;}
&nbsp;
spo_level_flags
&nbsp;void
&nbsp;spo_level_flags(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_level_flags";
&nbsp;    struct opvar *flagdata;
&nbsp;    long lflags;
&nbsp;
&nbsp;    if (!OV_pop_i(flagdata))
&nbsp;        return;
&nbsp;    lflags = OV_i(flagdata);
&nbsp;
&nbsp;    if (lflags &amp; NOTELEPORT)
&nbsp;        level.flags.noteleport = 1;
&nbsp;    if (lflags &amp; HARDFLOOR)
&nbsp;        level.flags.hardfloor = 1;
&nbsp;    if (lflags &amp; NOMMAP)
&nbsp;        level.flags.nommap = 1;
&nbsp;    if (lflags &amp; SHORTSIGHTED)
&nbsp;        level.flags.shortsighted = 1;
&nbsp;    if (lflags &amp; ARBOREAL)
&nbsp;        level.flags.arboreal = 1;
&nbsp;    if (lflags &amp; MAZELEVEL)
&nbsp;        level.flags.is_maze_lev = 1;
&nbsp;    if (lflags &amp; PREMAPPED)
&nbsp;        coder-&gt;premapped = TRUE;
&nbsp;    if (lflags &amp; SHROUD)
&nbsp;        level.flags.hero_memory = 0;
&nbsp;    if (lflags &amp; GRAVEYARD)
&nbsp;        level.flags.graveyard = 1;
&nbsp;    if (lflags &amp; ICEDPOOLS)
&nbsp;        icedpools = TRUE;
&nbsp;    if (lflags &amp; SOLIDIFY)
&nbsp;        coder-&gt;solidify = TRUE;
&nbsp;    if (lflags &amp; CORRMAZE)
&nbsp;        level.flags.corrmaze = TRUE;
&nbsp;    if (lflags &amp; CHECK_INACCESSIBLES)
&nbsp;        coder-&gt;check_inaccessibles = TRUE;
&nbsp;
&nbsp;    opvar_free(flagdata);
&nbsp;}
&nbsp;
spo_initlevel
&nbsp;void
&nbsp;spo_initlevel(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_initlevel";
&nbsp;    lev_init init_lev;
&nbsp;    struct opvar *init_style, *fg, *bg, *smoothed, *joined, *lit, *walled,
&nbsp;        *filling;
&nbsp;
&nbsp;    if (!OV_pop_i(fg) || !OV_pop_i(bg) || !OV_pop_i(smoothed)
&nbsp;        || !OV_pop_i(joined) || !OV_pop_i(lit) || !OV_pop_i(walled)
&nbsp;        || !OV_pop_i(filling) || !OV_pop_i(init_style))
&nbsp;        return;
&nbsp;
&nbsp;    splev_init_present = TRUE;
&nbsp;
&nbsp;    init_lev.init_style = OV_i(init_style);
&nbsp;    init_lev.fg = OV_i(fg);
&nbsp;    init_lev.bg = OV_i(bg);
&nbsp;    init_lev.smoothed = OV_i(smoothed);
&nbsp;    init_lev.joined = OV_i(joined);
&nbsp;    init_lev.lit = OV_i(lit);
&nbsp;    init_lev.walled = OV_i(walled);
&nbsp;    init_lev.filling = OV_i(filling);
&nbsp;
&nbsp;    coder-&gt;lvl_is_joined = OV_i(joined);
&nbsp;
&nbsp;    splev_initlev(&amp;init_lev);
&nbsp;
&nbsp;    opvar_free(init_style);
&nbsp;    opvar_free(fg);
&nbsp;    opvar_free(bg);
&nbsp;    opvar_free(smoothed);
&nbsp;    opvar_free(joined);
&nbsp;    opvar_free(lit);
&nbsp;    opvar_free(walled);
&nbsp;    opvar_free(filling);
&nbsp;}
&nbsp;
spo_engraving
&nbsp;void
&nbsp;spo_engraving(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_engraving";
&nbsp;    struct opvar *etyp, *txt, *ecoord;
&nbsp;    xchar x, y;
&nbsp;
&nbsp;    if (!OV_pop_i(etyp) || !OV_pop_s(txt) || !OV_pop_c(ecoord))
&nbsp;        return;
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY, coder-&gt;croom, OV_i(ecoord));
&nbsp;    make_engr_at(x, y, OV_s(txt), 0L, OV_i(etyp));
&nbsp;
&nbsp;    opvar_free(etyp);
&nbsp;    opvar_free(txt);
&nbsp;    opvar_free(ecoord);
&nbsp;}
&nbsp;
spo_mineralize
&nbsp;void
&nbsp;spo_mineralize(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_mineralize";
&nbsp;    struct opvar *kelp_pool, *kelp_moat, *gold_prob, *gem_prob;
&nbsp;
&nbsp;    if (!OV_pop_i(gem_prob) || !OV_pop_i(gold_prob) || !OV_pop_i(kelp_moat)
&nbsp;        || !OV_pop_i(kelp_pool))
&nbsp;        return;
&nbsp;
&nbsp;    mineralize(OV_i(kelp_pool), OV_i(kelp_moat), OV_i(gold_prob),
&nbsp;               OV_i(gem_prob), TRUE);
&nbsp;
&nbsp;    opvar_free(gem_prob);
&nbsp;    opvar_free(gold_prob);
&nbsp;    opvar_free(kelp_moat);
&nbsp;    opvar_free(kelp_pool);
&nbsp;}
&nbsp;
spo_room
&nbsp;void
&nbsp;spo_room(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_room";
&nbsp;
&nbsp;    if (coder-&gt;n_subroom &gt; MAX_NESTED_ROOMS) {
&nbsp;        panic("Too deeply nested rooms?!");
&nbsp;    } else {
&nbsp;        struct opvar *rflags, *h, *w, *yalign, *xalign, *y, *x, *rlit,
&nbsp;            *chance, *rtype;
&nbsp;        room tmproom;
&nbsp;        struct mkroom *tmpcr;
&nbsp;
&nbsp;        if (!OV_pop_i(h) || !OV_pop_i(w) || !OV_pop_i(y) || !OV_pop_i(x)
&nbsp;            || !OV_pop_i(yalign) || !OV_pop_i(xalign) || !OV_pop_i(rflags)
&nbsp;            || !OV_pop_i(rlit) || !OV_pop_i(chance) || !OV_pop_i(rtype))
&nbsp;            return;
&nbsp;
&nbsp;        tmproom.x = OV_i(x);
&nbsp;        tmproom.y = OV_i(y);
&nbsp;        tmproom.w = OV_i(w);
&nbsp;        tmproom.h = OV_i(h);
&nbsp;        tmproom.xalign = OV_i(xalign);
&nbsp;        tmproom.yalign = OV_i(yalign);
&nbsp;        tmproom.rtype = OV_i(rtype);
&nbsp;        tmproom.chance = OV_i(chance);
&nbsp;        tmproom.rlit = OV_i(rlit);
&nbsp;        tmproom.filled = (OV_i(rflags) &amp; (1 &lt;&lt; 0));
&nbsp;        /*tmproom.irregular = (OV_i(rflags) &amp; (1 &lt;&lt; 1));*/
&nbsp;        tmproom.joined = !(OV_i(rflags) &amp; (1 &lt;&lt; 2));
&nbsp;
&nbsp;        opvar_free(x);
&nbsp;        opvar_free(y);
&nbsp;        opvar_free(w);
&nbsp;        opvar_free(h);
&nbsp;        opvar_free(xalign);
&nbsp;        opvar_free(yalign);
&nbsp;        opvar_free(rtype);
&nbsp;        opvar_free(chance);
&nbsp;        opvar_free(rlit);
&nbsp;        opvar_free(rflags);
&nbsp;
&nbsp;        if (!coder-&gt;failed_room[coder-&gt;n_subroom - 1]) {
&nbsp;            tmpcr = build_room(&amp;tmproom, coder-&gt;croom);
&nbsp;            if (tmpcr) {
&nbsp;                coder-&gt;tmproomlist[coder-&gt;n_subroom] = tmpcr;
&nbsp;                coder-&gt;failed_room[coder-&gt;n_subroom] = FALSE;
&nbsp;                coder-&gt;n_subroom++;
&nbsp;                return;
&nbsp;            }
&nbsp;        } /* failed to create parent room, so fail this too */
&nbsp;    }
&nbsp;    coder-&gt;tmproomlist[coder-&gt;n_subroom] = (struct mkroom *) 0;
&nbsp;    coder-&gt;failed_room[coder-&gt;n_subroom] = TRUE;
&nbsp;    coder-&gt;n_subroom++;
&nbsp;}
&nbsp;
spo_endroom
&nbsp;void
&nbsp;spo_endroom(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    if (coder-&gt;n_subroom &gt; 1) {
&nbsp;        coder-&gt;n_subroom--;
&nbsp;        coder-&gt;tmproomlist[coder-&gt;n_subroom] = NULL;
&nbsp;        coder-&gt;failed_room[coder-&gt;n_subroom] = TRUE;
&nbsp;    } else {
&nbsp;        /* no subroom, get out of top-level room */
&nbsp;        /* Need to ensure xstart/ystart/xsize/ysize have something sensible,
&nbsp;           in case there's some stuff to be created outside the outermost
&nbsp;           room,
&nbsp;           and there's no MAP.
&nbsp;        */
&nbsp;        if (xsize &lt;= 1 &amp;&amp; ysize &lt;= 1) {
&nbsp;            xstart = 1;
&nbsp;            ystart = 0;
&nbsp;            xsize = COLNO - 1;
&nbsp;            ysize = ROWNO;
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
spo_stair
&nbsp;void
&nbsp;spo_stair(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_stair";
&nbsp;    xchar x, y;
&nbsp;    struct opvar *up, *scoord;
&nbsp;    struct trap *badtrap;
&nbsp;
&nbsp;    if (!OV_pop_i(up) || !OV_pop_c(scoord))
&nbsp;        return;
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY, coder-&gt;croom, OV_i(scoord));
&nbsp;    if ((badtrap = t_at(x, y)) != 0)
&nbsp;        deltrap(badtrap);
&nbsp;    mkstairs(x, y, (char) OV_i(up), coder-&gt;croom);
&nbsp;    SpLev_Map[x][y] = 1;
&nbsp;
&nbsp;    opvar_free(scoord);
&nbsp;    opvar_free(up);
&nbsp;}
&nbsp;
spo_ladder
&nbsp;void
&nbsp;spo_ladder(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_ladder";
&nbsp;    xchar x, y;
&nbsp;    struct opvar *up, *lcoord;
&nbsp;
&nbsp;    if (!OV_pop_i(up) || !OV_pop_c(lcoord))
&nbsp;        return;
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY, coder-&gt;croom, OV_i(lcoord));
&nbsp;
&nbsp;    levl[x][y].typ = LADDER;
&nbsp;    SpLev_Map[x][y] = 1;
&nbsp;    if (OV_i(up)) {
&nbsp;        xupladder = x;
&nbsp;        yupladder = y;
&nbsp;        levl[x][y].ladder = LA_UP;
&nbsp;    } else {
&nbsp;        xdnladder = x;
&nbsp;        ydnladder = y;
&nbsp;        levl[x][y].ladder = LA_DOWN;
&nbsp;    }
&nbsp;    opvar_free(lcoord);
&nbsp;    opvar_free(up);
&nbsp;}
&nbsp;
spo_grave
&nbsp;void
&nbsp;spo_grave(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_grave";
&nbsp;    struct opvar *gcoord, *typ, *txt;
&nbsp;    schar x, y;
&nbsp;
&nbsp;    if (!OV_pop_i(typ) || !OV_pop_s(txt) || !OV_pop_c(gcoord))
&nbsp;        return;
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY, coder-&gt;croom, OV_i(gcoord));
&nbsp;
&nbsp;    if (isok(x, y) &amp;&amp; !t_at(x, y)) {
&nbsp;        levl[x][y].typ = GRAVE;
&nbsp;        switch (OV_i(typ)) {
&nbsp;        case 2:
&nbsp;            make_grave(x, y, OV_s(txt));
&nbsp;            break;
&nbsp;        case 1:
&nbsp;            make_grave(x, y, NULL);
&nbsp;            break;
&nbsp;        default:
&nbsp;            del_engr_at(x, y);
&nbsp;            break;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    opvar_free(gcoord);
&nbsp;    opvar_free(typ);
&nbsp;    opvar_free(txt);
&nbsp;}
&nbsp;
spo_altar
&nbsp;void
&nbsp;spo_altar(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_altar";
&nbsp;    struct opvar *al, *shrine, *acoord;
&nbsp;    altar tmpaltar;
&nbsp;
&nbsp;    if (!OV_pop_i(al) || !OV_pop_i(shrine) || !OV_pop_c(acoord))
&nbsp;        return;
&nbsp;
&nbsp;    tmpaltar.coord = OV_i(acoord);
&nbsp;    tmpaltar.align = OV_i(al);
&nbsp;    tmpaltar.shrine = OV_i(shrine);
&nbsp;
&nbsp;    create_altar(&amp;tmpaltar, coder-&gt;croom);
&nbsp;
&nbsp;    opvar_free(acoord);
&nbsp;    opvar_free(shrine);
&nbsp;    opvar_free(al);
&nbsp;}
&nbsp;
spo_trap
&nbsp;void
&nbsp;spo_trap(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_trap";
&nbsp;    struct opvar *type;
&nbsp;    struct opvar *tcoord;
&nbsp;    spltrap tmptrap;
&nbsp;
&nbsp;    if (!OV_pop_i(type) || !OV_pop_c(tcoord))
&nbsp;        return;
&nbsp;
&nbsp;    tmptrap.coord = OV_i(tcoord);
&nbsp;    tmptrap.type = OV_i(type);
&nbsp;
&nbsp;    create_trap(&amp;tmptrap, coder-&gt;croom);
&nbsp;    opvar_free(tcoord);
&nbsp;    opvar_free(type);
&nbsp;}
&nbsp;
spo_gold
&nbsp;void
&nbsp;spo_gold(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_gold";
&nbsp;    struct opvar *gcoord, *amt;
&nbsp;    schar x, y;
&nbsp;    long amount;
&nbsp;
&nbsp;    if (!OV_pop_c(gcoord) || !OV_pop_i(amt))
&nbsp;        return;
&nbsp;    amount = OV_i(amt);
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY, coder-&gt;croom, OV_i(gcoord));
&nbsp;    if (amount == -1)
&nbsp;        amount = rnd(200);
&nbsp;    mkgold(amount, x, y);
&nbsp;    opvar_free(gcoord);
&nbsp;    opvar_free(amt);
&nbsp;}
&nbsp;
spo_corridor
&nbsp;void
&nbsp;spo_corridor(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_corridor";
&nbsp;    struct opvar *deswall, *desdoor, *desroom, *srcwall, *srcdoor, *srcroom;
&nbsp;    corridor tc;
&nbsp;
&nbsp;    if (!OV_pop_i(deswall) || !OV_pop_i(desdoor) || !OV_pop_i(desroom)
&nbsp;        || !OV_pop_i(srcwall) || !OV_pop_i(srcdoor) || !OV_pop_i(srcroom))
&nbsp;        return;
&nbsp;
&nbsp;    tc.src.room = OV_i(srcroom);
&nbsp;    tc.src.door = OV_i(srcdoor);
&nbsp;    tc.src.wall = OV_i(srcwall);
&nbsp;    tc.dest.room = OV_i(desroom);
&nbsp;    tc.dest.door = OV_i(desdoor);
&nbsp;    tc.dest.wall = OV_i(deswall);
&nbsp;
&nbsp;    create_corridor(&amp;tc);
&nbsp;
&nbsp;    opvar_free(deswall);
&nbsp;    opvar_free(desdoor);
&nbsp;    opvar_free(desroom);
&nbsp;    opvar_free(srcwall);
&nbsp;    opvar_free(srcdoor);
&nbsp;    opvar_free(srcroom);
&nbsp;}
&nbsp;
selection_opvar
&nbsp;struct opvar *
&nbsp;selection_opvar(nbuf)
&nbsp;char *nbuf;
&nbsp;{
&nbsp;    struct opvar *ov;
&nbsp;    char buf[(COLNO * ROWNO) + 1];
&nbsp;
&nbsp;    if (!nbuf) {
&nbsp;        (void) memset(buf, 1, sizeof(buf));
&nbsp;        buf[(COLNO * ROWNO)] = '\0';
&nbsp;        ov = opvar_new_str(buf);
&nbsp;    } else {
&nbsp;        ov = opvar_new_str(nbuf);
&nbsp;    }
&nbsp;    ov-&gt;spovartyp = SPOVAR_SEL;
&nbsp;    return ov;
&nbsp;}
&nbsp;
selection_getpoint
&nbsp;xchar
&nbsp;selection_getpoint(x, y, ov)
&nbsp;int x, y;
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    if (!ov || ov-&gt;spovartyp != SPOVAR_SEL)
&nbsp;        return 0;
&nbsp;    if (x &lt; 0 || y &lt; 0 || x &gt;= COLNO || y &gt;= ROWNO)
&nbsp;        return 0;
&nbsp;
&nbsp;    return (ov-&gt;vardata.str[COLNO * y + x] - 1);
&nbsp;}
&nbsp;
selection_setpoint
&nbsp;void
&nbsp;selection_setpoint(x, y, ov, c)
&nbsp;int x, y;
&nbsp;struct opvar *ov;
&nbsp;xchar c;
&nbsp;{
&nbsp;    if (!ov || ov-&gt;spovartyp != SPOVAR_SEL)
&nbsp;        return;
&nbsp;    if (x &lt; 0 || y &lt; 0 || x &gt;= COLNO || y &gt;= ROWNO)
&nbsp;        return;
&nbsp;
&nbsp;    ov-&gt;vardata.str[COLNO * y + x] = (char) (c + 1);
&nbsp;}
&nbsp;
selection_not
&nbsp;struct opvar *
&nbsp;selection_not(s)
&nbsp;struct opvar *s;
&nbsp;{
&nbsp;    struct opvar *ov;
&nbsp;    int x, y;
&nbsp;
&nbsp;    ov = selection_opvar((char *) 0);
&nbsp;    if (!ov)
&nbsp;        return NULL;
&nbsp;
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++)
&nbsp;            if (!selection_getpoint(x, y, s))
&nbsp;                selection_setpoint(x, y, ov, 1);
&nbsp;
&nbsp;    return ov;
&nbsp;}
&nbsp;
selection_logical_oper
&nbsp;struct opvar *
&nbsp;selection_logical_oper(s1, s2, oper)
&nbsp;struct opvar *s1, *s2;
&nbsp;char oper;
&nbsp;{
&nbsp;    struct opvar *ov;
&nbsp;    int x, y;
&nbsp;
&nbsp;    ov = selection_opvar((char *) 0);
&nbsp;    if (!ov)
&nbsp;        return NULL;
&nbsp;
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++) {
&nbsp;            switch (oper) {
&nbsp;            default:
&nbsp;            case '|':
&nbsp;                if (selection_getpoint(x, y, s1)
&nbsp;                    || selection_getpoint(x, y, s2))
&nbsp;                    selection_setpoint(x, y, ov, 1);
&nbsp;                break;
&nbsp;            case '&amp;':
&nbsp;                if (selection_getpoint(x, y, s1)
&nbsp;                    &amp;&amp; selection_getpoint(x, y, s2))
&nbsp;                    selection_setpoint(x, y, ov, 1);
&nbsp;                break;
&nbsp;            }
&nbsp;        }
&nbsp;
&nbsp;    return ov;
&nbsp;}
&nbsp;
selection_filter_mapchar
&nbsp;struct opvar *
&nbsp;selection_filter_mapchar(ov, mc)
&nbsp;struct opvar *ov;
&nbsp;struct opvar *mc;
&nbsp;{
&nbsp;    int x, y;
&nbsp;    schar mapc;
&nbsp;    xchar lit;
&nbsp;    struct opvar *ret = selection_opvar((char *) 0);
&nbsp;
&nbsp;    if (!ov || !mc || !ret)
&nbsp;        return NULL;
&nbsp;    mapc = SP_MAPCHAR_TYP(OV_i(mc));
&nbsp;    lit = SP_MAPCHAR_LIT(OV_i(mc));
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++)
&nbsp;            if (selection_getpoint(x, y, ov) &amp;&amp; (levl[x][y].typ == mapc)) {
&nbsp;                switch (lit) {
&nbsp;                default:
&nbsp;                case -2:
&nbsp;                    selection_setpoint(x, y, ret, 1);
&nbsp;                    break;
&nbsp;                case -1:
&nbsp;                    selection_setpoint(x, y, ret, rn2(2));
&nbsp;                    break;
&nbsp;                case 0:
&nbsp;                case 1:
&nbsp;                    if (levl[x][y].lit == lit)
&nbsp;                        selection_setpoint(x, y, ret, 1);
&nbsp;                    break;
&nbsp;                }
&nbsp;            }
&nbsp;    return ret;
&nbsp;}
&nbsp;
selection_filter_percent
&nbsp;void
&nbsp;selection_filter_percent(ov, percent)
&nbsp;struct opvar *ov;
&nbsp;int percent;
&nbsp;{
&nbsp;    int x, y;
&nbsp;
&nbsp;    if (!ov)
&nbsp;        return;
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++)
&nbsp;            if (selection_getpoint(x, y, ov) &amp;&amp; (rn2(100) &gt;= percent))
&nbsp;                selection_setpoint(x, y, ov, 0);
&nbsp;}
&nbsp;
selection_rndcoord
&nbsp;STATIC_OVL int
&nbsp;selection_rndcoord(ov, x, y, removeit)
&nbsp;struct opvar *ov;
&nbsp;schar *x, *y;
&nbsp;boolean removeit;
&nbsp;{
&nbsp;    int idx = 0;
&nbsp;    int c;
&nbsp;    int dx, dy;
&nbsp;
&nbsp;    for (dx = 0; dx &lt; COLNO; dx++)
&nbsp;        for (dy = 0; dy &lt; ROWNO; dy++)
&nbsp;            if (isok(dx, dy) &amp;&amp; selection_getpoint(dx, dy, ov))
&nbsp;                idx++;
&nbsp;
&nbsp;    if (idx) {
&nbsp;        c = rn2(idx);
&nbsp;        for (dx = 0; dx &lt; COLNO; dx++)
&nbsp;            for (dy = 0; dy &lt; ROWNO; dy++)
&nbsp;                if (isok(dx, dy) &amp;&amp; selection_getpoint(dx, dy, ov)) {
&nbsp;                    if (!c) {
&nbsp;                        *x = dx;
&nbsp;                        *y = dy;
&nbsp;                        if (removeit) selection_setpoint(dx, dy, ov, 0);
&nbsp;                        return 1;
&nbsp;                    }
&nbsp;                    c--;
&nbsp;                }
&nbsp;    }
&nbsp;    *x = *y = -1;
&nbsp;    return 0;
&nbsp;}
&nbsp;
selection_do_grow
&nbsp;void
&nbsp;selection_do_grow(ov, dir)
&nbsp;struct opvar *ov;
&nbsp;int dir;
&nbsp;{
&nbsp;    int x, y, c;
&nbsp;    char tmp[COLNO][ROWNO];
&nbsp;
&nbsp;    if (ov-&gt;spovartyp != SPOVAR_SEL)
&nbsp;        return;
&nbsp;    if (!ov)
&nbsp;        return;
&nbsp;
&nbsp;    (void) memset(tmp, 0, sizeof(tmp));
&nbsp;
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++) {
&nbsp;            c = 0;
&nbsp;            if ((dir &amp; W_WEST) &amp;&amp; (x &gt; 0)
&nbsp;                &amp;&amp; (selection_getpoint(x - 1, y, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; (W_WEST | W_NORTH)) &amp;&amp; (x &gt; 0) &amp;&amp; (y &gt; 0)
&nbsp;                &amp;&amp; (selection_getpoint(x - 1, y - 1, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; W_NORTH) &amp;&amp; (y &gt; 0)
&nbsp;                &amp;&amp; (selection_getpoint(x, y - 1, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; (W_NORTH | W_EAST)) &amp;&amp; (y &gt; 0) &amp;&amp; (x &lt; COLNO - 1)
&nbsp;                &amp;&amp; (selection_getpoint(x + 1, y - 1, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; W_EAST) &amp;&amp; (x &lt; COLNO - 1)
&nbsp;                &amp;&amp; (selection_getpoint(x + 1, y, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; (W_EAST | W_SOUTH)) &amp;&amp; (x &lt; COLNO - 1)
&nbsp;                &amp;&amp; (y &lt; ROWNO - 1) &amp;&amp; (selection_getpoint(x + 1, y + 1, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; W_SOUTH) &amp;&amp; (y &lt; ROWNO - 1)
&nbsp;                &amp;&amp; (selection_getpoint(x, y + 1, ov)))
&nbsp;                c++;
&nbsp;            if ((dir &amp; (W_SOUTH | W_WEST)) &amp;&amp; (y &lt; ROWNO - 1) &amp;&amp; (x &gt; 0)
&nbsp;                &amp;&amp; (selection_getpoint(x - 1, y + 1, ov)))
&nbsp;                c++;
&nbsp;            if (c)
&nbsp;                tmp[x][y] = 1;
&nbsp;        }
&nbsp;
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++)
&nbsp;            if (tmp[x][y])
&nbsp;                selection_setpoint(x, y, ov, 1);
&nbsp;}
&nbsp;
&nbsp;STATIC_VAR int FDECL((*selection_flood_check_func), (int, int));
&nbsp;STATIC_VAR schar floodfillchk_match_under_typ;
&nbsp;
set_selection_floodfillchk
&nbsp;void
&nbsp;set_selection_floodfillchk(f)
&nbsp;int FDECL((*f), (int, int));
&nbsp;{
&nbsp;    selection_flood_check_func = f;
&nbsp;}
&nbsp;
floodfillchk_match_under
&nbsp;STATIC_OVL int
&nbsp;floodfillchk_match_under(x,y)
&nbsp;int x,y;
&nbsp;{
&nbsp;    return (floodfillchk_match_under_typ == levl[x][y].typ);
&nbsp;}
&nbsp;
floodfillchk_match_accessible
&nbsp;STATIC_OVL int
&nbsp;floodfillchk_match_accessible(x, y)
&nbsp;int x, y;
&nbsp;{
&nbsp;    return (ACCESSIBLE(levl[x][y].typ)
&nbsp;            || levl[x][y].typ == SDOOR
&nbsp;            || levl[x][y].typ == SCORR);
&nbsp;}
&nbsp;
selection_floodfill
&nbsp;void
&nbsp;selection_floodfill(ov, x, y, diagonals)
&nbsp;struct opvar *ov;
&nbsp;int x, y;
&nbsp;boolean diagonals;
&nbsp;{
&nbsp;    static const char nhFunc[] = "selection_floodfill";
&nbsp;    struct opvar *tmp = selection_opvar((char *) 0);
&nbsp;#define SEL_FLOOD_STACK (COLNO * ROWNO)
&nbsp;#define SEL_FLOOD(nx, ny)                     \
&nbsp;    do {                                      \
&nbsp;        if (idx &lt; SEL_FLOOD_STACK) {          \
&nbsp;            dx[idx] = (nx);                   \
&nbsp;            dy[idx] = (ny);                   \
&nbsp;            idx++;                            \
&nbsp;        } else                                \
&nbsp;            panic(floodfill_stack_overrun);   \
&nbsp;    } while (0)
&nbsp;#define SEL_FLOOD_CHKDIR(mx,my,sel)                  \
&nbsp;    if (isok((mx), (my))                             \
&nbsp;        &amp;&amp; (*selection_flood_check_func)((mx), (my)) \
&nbsp;        &amp;&amp; !selection_getpoint((mx), (my), (sel)))   \
&nbsp;        SEL_FLOOD((mx), (my))
&nbsp;    static const char floodfill_stack_overrun[] = "floodfill stack overrun";
&nbsp;    int idx = 0;
&nbsp;    xchar dx[SEL_FLOOD_STACK];
&nbsp;    xchar dy[SEL_FLOOD_STACK];
&nbsp;
&nbsp;    if (selection_flood_check_func == NULL) {
&nbsp;        opvar_free(tmp);
&nbsp;        return;
&nbsp;    }
&nbsp;    SEL_FLOOD(x, y);
&nbsp;    do {
&nbsp;        idx--;
&nbsp;        x = dx[idx];
&nbsp;        y = dy[idx];
&nbsp;        if (isok(x, y)) {
&nbsp;            selection_setpoint(x, y, ov, 1);
&nbsp;            selection_setpoint(x, y, tmp, 1);
&nbsp;        }
&nbsp;        SEL_FLOOD_CHKDIR((x + 1), y, tmp);
&nbsp;        SEL_FLOOD_CHKDIR((x - 1), y, tmp);
&nbsp;        SEL_FLOOD_CHKDIR(x, (y + 1), tmp);
&nbsp;        SEL_FLOOD_CHKDIR(x, (y - 1), tmp);
&nbsp;        if (diagonals) {
&nbsp;            SEL_FLOOD_CHKDIR((x + 1), (y + 1), tmp);
&nbsp;            SEL_FLOOD_CHKDIR((x - 1), (y - 1), tmp);
&nbsp;            SEL_FLOOD_CHKDIR((x - 1), (y + 1), tmp);
&nbsp;            SEL_FLOOD_CHKDIR((x + 1), (y - 1), tmp);
&nbsp;        }
&nbsp;    } while (idx &gt; 0);
&nbsp;#undef SEL_FLOOD
&nbsp;#undef SEL_FLOOD_STACK
&nbsp;#undef SEL_FLOOD_CHKDIR
&nbsp;    opvar_free(tmp);
&nbsp;}
&nbsp;
selection_do_ellipse
&nbsp;/* McIlroy's Ellipse Algorithm */
&nbsp;void
&nbsp;selection_do_ellipse(ov, xc, yc, a, b, filled)
&nbsp;struct opvar *ov;
&nbsp;int xc, yc, a, b, filled;
&nbsp;{ /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
&nbsp;    int x = 0, y = b;
&nbsp;    long a2 = (long) a * a, b2 = (long) b * b;
&nbsp;    long crit1 = -(a2 / 4 + a % 2 + b2);
&nbsp;    long crit2 = -(b2 / 4 + b % 2 + a2);
&nbsp;    long crit3 = -(b2 / 4 + b % 2);
&nbsp;    long t = -a2 * y; /* e(x+1/2,y-1/2) - (a^2+b^2)/4 */
&nbsp;    long dxt = 2 * b2 * x, dyt = -2 * a2 * y;
&nbsp;    long d2xt = 2 * b2, d2yt = 2 * a2;
&nbsp;    long width = 1;
&nbsp;    long i;
&nbsp;
&nbsp;    if (!ov)
&nbsp;        return;
&nbsp;
&nbsp;    filled = !filled;
&nbsp;
&nbsp;    if (!filled) {
&nbsp;        while (y &gt;= 0 &amp;&amp; x &lt;= a) {
&nbsp;            selection_setpoint(xc + x, yc + y, ov, 1);
&nbsp;            if (x != 0 || y != 0)
&nbsp;                selection_setpoint(xc - x, yc - y, ov, 1);
&nbsp;            if (x != 0 &amp;&amp; y != 0) {
&nbsp;                selection_setpoint(xc + x, yc - y, ov, 1);
&nbsp;                selection_setpoint(xc - x, yc + y, ov, 1);
&nbsp;            }
&nbsp;            if (t + b2 * x &lt;= crit1       /* e(x+1,y-1/2) &lt;= 0 */
&nbsp;                || t + a2 * y &lt;= crit3) { /* e(x+1/2,y) &lt;= 0 */
&nbsp;                x++;
&nbsp;                dxt += d2xt;
&nbsp;                t += dxt;
&nbsp;            } else if (t - a2 * y &gt; crit2) { /* e(x+1/2,y-1) &gt; 0 */
&nbsp;                y--;
&nbsp;                dyt += d2yt;
&nbsp;                t += dyt;
&nbsp;            } else {
&nbsp;                x++;
&nbsp;                dxt += d2xt;
&nbsp;                t += dxt;
&nbsp;                y--;
&nbsp;                dyt += d2yt;
&nbsp;                t += dyt;
&nbsp;            }
&nbsp;        }
&nbsp;    } else {
&nbsp;        while (y &gt;= 0 &amp;&amp; x &lt;= a) {
&nbsp;            if (t + b2 * x &lt;= crit1       /* e(x+1,y-1/2) &lt;= 0 */
&nbsp;                || t + a2 * y &lt;= crit3) { /* e(x+1/2,y) &lt;= 0 */
&nbsp;                x++;
&nbsp;                dxt += d2xt;
&nbsp;                t += dxt;
&nbsp;                width += 2;
&nbsp;            } else if (t - a2 * y &gt; crit2) { /* e(x+1/2,y-1) &gt; 0 */
&nbsp;                for (i = 0; i &lt; width; i++)
&nbsp;                    selection_setpoint(xc - x + i, yc - y, ov, 1);
&nbsp;                if (y != 0)
&nbsp;                    for (i = 0; i &lt; width; i++)
&nbsp;                        selection_setpoint(xc - x + i, yc + y, ov, 1);
&nbsp;                y--;
&nbsp;                dyt += d2yt;
&nbsp;                t += dyt;
&nbsp;            } else {
&nbsp;                for (i = 0; i &lt; width; i++)
&nbsp;                    selection_setpoint(xc - x + i, yc - y, ov, 1);
&nbsp;                if (y != 0)
&nbsp;                    for (i = 0; i &lt; width; i++)
&nbsp;                        selection_setpoint(xc - x + i, yc + y, ov, 1);
&nbsp;                x++;
&nbsp;                dxt += d2xt;
&nbsp;                t += dxt;
&nbsp;                y--;
&nbsp;                dyt += d2yt;
&nbsp;                t += dyt;
&nbsp;                width += 2;
&nbsp;            }
&nbsp;        }
&nbsp;    }
&nbsp;}
&nbsp;
line_dist_coord
&nbsp;/* distance from line segment (x1,y1, x2,y2) to point (x3,y3) */
&nbsp;long
&nbsp;line_dist_coord(x1, y1, x2, y2, x3, y3)
&nbsp;long x1, y1, x2, y2, x3, y3;
&nbsp;{
&nbsp;    long px = x2 - x1;
&nbsp;    long py = y2 - y1;
&nbsp;    long s = px * px + py * py;
&nbsp;    long x, y, dx, dy, dist = 0;
&nbsp;    float lu = 0;
&nbsp;
&nbsp;    if (x1 == x2 &amp;&amp; y1 == y2)
&nbsp;        return isqrt(dist2(x1, y1, x3, y3));
&nbsp;
&nbsp;    lu = ((x3 - x1) * px + (y3 - y1) * py) / (float) s;
&nbsp;    if (lu &gt; 1)
&nbsp;        lu = 1;
&nbsp;    else if (lu &lt; 0)
&nbsp;        lu = 0;
&nbsp;
&nbsp;    x = x1 + lu * px;
&nbsp;    y = y1 + lu * py;
&nbsp;    dx = x - x3;
&nbsp;    dy = y - y3;
&nbsp;    dist = isqrt(dx * dx + dy * dy);
&nbsp;
&nbsp;    return dist;
&nbsp;}
&nbsp;
selection_do_gradient
&nbsp;void
&nbsp;selection_do_gradient(ov, x, y, x2, y2, gtyp, mind, maxd, limit)
&nbsp;struct opvar *ov;
&nbsp;long x, y, x2, y2, gtyp, mind, maxd, limit;
&nbsp;{
&nbsp;    long dx, dy, dofs;
&nbsp;
&nbsp;    if (mind &gt; maxd) {
&nbsp;        long tmp = mind;
&nbsp;        mind = maxd;
&nbsp;        maxd = tmp;
&nbsp;    }
&nbsp;
&nbsp;    dofs = maxd - mind;
&nbsp;    if (dofs &lt; 1)
&nbsp;        dofs = 1;
&nbsp;
&nbsp;    switch (gtyp) {
&nbsp;    default:
&nbsp;    case SEL_GRADIENT_RADIAL: {
&nbsp;        for (dx = 0; dx &lt; COLNO; dx++)
&nbsp;            for (dy = 0; dy &lt; ROWNO; dy++) {
&nbsp;                long d0 = line_dist_coord(x, y, x2, y2, dx, dy);
&nbsp;                if (d0 &gt;= mind &amp;&amp; (!limit || d0 &lt;= maxd)) {
&nbsp;                    if (d0 - mind &gt; rn2(dofs))
&nbsp;                        selection_setpoint(dx, dy, ov, 1);
&nbsp;                }
&nbsp;            }
&nbsp;        break;
&nbsp;    }
&nbsp;    case SEL_GRADIENT_SQUARE: {
&nbsp;        for (dx = 0; dx &lt; COLNO; dx++)
&nbsp;            for (dy = 0; dy &lt; ROWNO; dy++) {
&nbsp;                long d1 = line_dist_coord(x, y, x2, y2, x, dy);
&nbsp;                long d2 = line_dist_coord(x, y, x2, y2, dx, y);
&nbsp;                long d3 = line_dist_coord(x, y, x2, y2, x2, dy);
&nbsp;                long d4 = line_dist_coord(x, y, x2, y2, dx, y2);
&nbsp;                long d5 = line_dist_coord(x, y, x2, y2, dx, dy);
&nbsp;                long d0 = min(d5, min(max(d1, d2), max(d3, d4)));
&nbsp;
&nbsp;                if (d0 &gt;= mind &amp;&amp; (!limit || d0 &lt;= maxd)) {
&nbsp;                    if (d0 - mind &gt; rn2(dofs))
&nbsp;                        selection_setpoint(dx, dy, ov, 1);
&nbsp;                }
&nbsp;            }
&nbsp;        break;
&nbsp;    } /*case*/
&nbsp;    } /*switch*/
&nbsp;}
&nbsp;
selection_do_line
&nbsp;/* bresenham line algo */
&nbsp;void
&nbsp;selection_do_line(x1, y1, x2, y2, ov)
&nbsp;schar x1, y1, x2, y2;
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    int d0, dx, dy, ai, bi, xi, yi;
&nbsp;
&nbsp;    if (x1 &lt; x2) {
&nbsp;        xi = 1;
&nbsp;        dx = x2 - x1;
&nbsp;    } else {
&nbsp;        xi = -1;
&nbsp;        dx = x1 - x2;
&nbsp;    }
&nbsp;
&nbsp;    if (y1 &lt; y2) {
&nbsp;        yi = 1;
&nbsp;        dy = y2 - y1;
&nbsp;    } else {
&nbsp;        yi = -1;
&nbsp;        dy = y1 - y2;
&nbsp;    }
&nbsp;
&nbsp;    selection_setpoint(x1, y1, ov, 1);
&nbsp;
&nbsp;    if (dx &gt; dy) {
&nbsp;        ai = (dy - dx) * 2;
&nbsp;        bi = dy * 2;
&nbsp;        d0 = bi - dx;
&nbsp;        do {
&nbsp;            if (d0 &gt;= 0) {
&nbsp;                y1 += yi;
&nbsp;                d0 += ai;
&nbsp;            } else
&nbsp;                d0 += bi;
&nbsp;            x1 += xi;
&nbsp;            selection_setpoint(x1, y1, ov, 1);
&nbsp;        } while (x1 != x2);
&nbsp;    } else {
&nbsp;        ai = (dx - dy) * 2;
&nbsp;        bi = dx * 2;
&nbsp;        d0 = bi - dy;
&nbsp;        do {
&nbsp;            if (d0 &gt;= 0) {
&nbsp;                x1 += xi;
&nbsp;                d0 += ai;
&nbsp;            } else
&nbsp;                d0 += bi;
&nbsp;            y1 += yi;
&nbsp;            selection_setpoint(x1, y1, ov, 1);
&nbsp;        } while (y1 != y2);
&nbsp;    }
&nbsp;}
&nbsp;
selection_do_randline
&nbsp;void
&nbsp;selection_do_randline(x1, y1, x2, y2, rough, rec, ov)
&nbsp;schar x1, y1, x2, y2, rough, rec;
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    int mx, my;
&nbsp;    int dx, dy;
&nbsp;
&nbsp;    if (rec &lt; 1) {
&nbsp;        return;
&nbsp;    }
&nbsp;
&nbsp;    if ((x2 == x1) &amp;&amp; (y2 == y1)) {
&nbsp;        selection_setpoint(x1, y1, ov, 1);
&nbsp;        return;
&nbsp;    }
&nbsp;
&nbsp;    if (rough &gt; max(abs(x2 - x1), abs(y2 - y1)))
&nbsp;        rough = max(abs(x2 - x1), abs(y2 - y1));
&nbsp;
&nbsp;    if (rough &lt; 2) {
&nbsp;        mx = ((x1 + x2) / 2);
&nbsp;        my = ((y1 + y2) / 2);
&nbsp;    } else {
&nbsp;        do {
&nbsp;            dx = rn2(rough) - (rough / 2);
&nbsp;            dy = rn2(rough) - (rough / 2);
&nbsp;            mx = ((x1 + x2) / 2) + dx;
&nbsp;            my = ((y1 + y2) / 2) + dy;
&nbsp;        } while ((mx &gt; COLNO - 1 || mx &lt; 0 || my &lt; 0 || my &gt; ROWNO - 1));
&nbsp;    }
&nbsp;
&nbsp;    selection_setpoint(mx, my, ov, 1);
&nbsp;
&nbsp;    rough = (rough * 2) / 3;
&nbsp;
&nbsp;    rec--;
&nbsp;
&nbsp;    selection_do_randline(x1, y1, mx, my, rough, rec, ov);
&nbsp;    selection_do_randline(mx, my, x2, y2, rough, rec, ov);
&nbsp;}
&nbsp;
selection_iterate
&nbsp;void
&nbsp;selection_iterate(ov, func, arg)
&nbsp;struct opvar *ov;
&nbsp;select_iter_func func;
&nbsp;genericptr_t arg;
&nbsp;{
&nbsp;    int x, y;
&nbsp;
&nbsp;    /* yes, this is very naive, but it's not _that_ expensive. */
&nbsp;    for (x = 0; x &lt; COLNO; x++)
&nbsp;        for (y = 0; y &lt; ROWNO; y++)
&nbsp;            if (selection_getpoint(x, y, ov))
&nbsp;                (*func)(x, y, arg);
&nbsp;}
&nbsp;
sel_set_ter
&nbsp;void
&nbsp;sel_set_ter(x, y, arg)
&nbsp;int x, y;
&nbsp;genericptr_t arg;
&nbsp;{
&nbsp;    terrain terr;
&nbsp;
&nbsp;    terr = *(terrain *) arg;
&nbsp;    SET_TYPLIT(x, y, terr.ter, terr.tlit);
&nbsp;    /* handle doors and secret doors */
&nbsp;    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
&nbsp;        if (levl[x][y].typ == SDOOR)
&nbsp;            levl[x][y].doormask = D_CLOSED;
&nbsp;        if (x &amp;&amp; (IS_WALL(levl[x - 1][y].typ) || levl[x - 1][y].horizontal))
&nbsp;            levl[x][y].horizontal = 1;
&nbsp;    }
&nbsp;}
&nbsp;
sel_set_feature
&nbsp;void
&nbsp;sel_set_feature(x, y, arg)
&nbsp;int x, y;
&nbsp;genericptr_t arg;
&nbsp;{
&nbsp;    if (IS_FURNITURE(levl[x][y].typ))
&nbsp;        return;
&nbsp;    levl[x][y].typ = (*(int *) arg);
&nbsp;}
&nbsp;
sel_set_door
&nbsp;void
&nbsp;sel_set_door(dx, dy, arg)
&nbsp;int dx, dy;
&nbsp;genericptr_t arg;
&nbsp;{
&nbsp;    xchar typ = *(xchar *) arg;
&nbsp;    xchar x = dx, y = dy;
&nbsp;
&nbsp;    if (!IS_DOOR(levl[x][y].typ) &amp;&amp; levl[x][y].typ != SDOOR)
&nbsp;        levl[x][y].typ = (typ &amp; D_SECRET) ? SDOOR : DOOR;
&nbsp;    if (typ &amp; D_SECRET) {
&nbsp;        typ &amp;= ~D_SECRET;
&nbsp;        if (typ &lt; D_CLOSED)
&nbsp;            typ = D_CLOSED;
&nbsp;    }
&nbsp;    set_door_orientation(x, y); /* set/clear levl[x][y].horizontal */
&nbsp;    levl[x][y].doormask = typ;
&nbsp;    SpLev_Map[x][y] = 1;
&nbsp;}
&nbsp;
spo_door
&nbsp;void
&nbsp;spo_door(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_door";
&nbsp;    struct opvar *msk, *sel;
&nbsp;    xchar typ;
&nbsp;
&nbsp;    if (!OV_pop_i(msk) || !OV_pop_typ(sel, SPOVAR_SEL))
&nbsp;        return;
&nbsp;
&nbsp;    typ = OV_i(msk) == -1 ? rnddoor() : (xchar) OV_i(msk);
&nbsp;
&nbsp;    selection_iterate(sel, sel_set_door, (genericptr_t) &amp;typ);
&nbsp;
&nbsp;    opvar_free(sel);
&nbsp;    opvar_free(msk);
&nbsp;}
&nbsp;
spo_feature
&nbsp;void
&nbsp;spo_feature(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_feature";
&nbsp;    struct opvar *sel;
&nbsp;    int typ;
&nbsp;
&nbsp;    if (!OV_pop_typ(sel, SPOVAR_SEL))
&nbsp;        return;
&nbsp;
&nbsp;    switch (coder-&gt;opcode) {
&nbsp;    default:
&nbsp;        impossible("spo_feature called with wrong opcode %i.", coder-&gt;opcode);
&nbsp;        break;
&nbsp;    case SPO_FOUNTAIN:
&nbsp;        typ = FOUNTAIN;
&nbsp;        break;
&nbsp;    case SPO_SINK:
&nbsp;        typ = SINK;
&nbsp;        break;
&nbsp;    case SPO_POOL:
&nbsp;        typ = POOL;
&nbsp;        break;
&nbsp;    }
&nbsp;    selection_iterate(sel, sel_set_feature, (genericptr_t) &amp;typ);
&nbsp;    opvar_free(sel);
&nbsp;}
&nbsp;
spo_terrain
&nbsp;void
&nbsp;spo_terrain(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_terrain";
&nbsp;    terrain tmpterrain;
&nbsp;    struct opvar *ter, *sel;
&nbsp;
&nbsp;    if (!OV_pop_typ(ter, SPOVAR_MAPCHAR) || !OV_pop_typ(sel, SPOVAR_SEL))
&nbsp;        return;
&nbsp;
&nbsp;    tmpterrain.ter = SP_MAPCHAR_TYP(OV_i(ter));
&nbsp;    tmpterrain.tlit = SP_MAPCHAR_LIT(OV_i(ter));
&nbsp;    selection_iterate(sel, sel_set_ter, (genericptr_t) &amp;tmpterrain);
&nbsp;
&nbsp;    opvar_free(ter);
&nbsp;    opvar_free(sel);
&nbsp;}
&nbsp;
spo_replace_terrain
&nbsp;void
&nbsp;spo_replace_terrain(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_replace_terrain";
&nbsp;    replaceterrain rt;
&nbsp;    struct opvar *reg, *from_ter, *to_ter, *chance;
&nbsp;
&nbsp;    if (!OV_pop_i(chance) || !OV_pop_typ(to_ter, SPOVAR_MAPCHAR)
&nbsp;        || !OV_pop_typ(from_ter, SPOVAR_MAPCHAR) || !OV_pop_r(reg))
&nbsp;        return;
&nbsp;
&nbsp;    rt.chance = OV_i(chance);
&nbsp;    rt.tolit = SP_MAPCHAR_LIT(OV_i(to_ter));
&nbsp;    rt.toter = SP_MAPCHAR_TYP(OV_i(to_ter));
&nbsp;    rt.fromter = SP_MAPCHAR_TYP(OV_i(from_ter));
&nbsp;    /* TODO: use SP_MAPCHAR_LIT(OV_i(from_ter)) too */
&nbsp;    rt.x1 = SP_REGION_X1(OV_i(reg));
&nbsp;    rt.y1 = SP_REGION_Y1(OV_i(reg));
&nbsp;    rt.x2 = SP_REGION_X2(OV_i(reg));
&nbsp;    rt.y2 = SP_REGION_Y2(OV_i(reg));
&nbsp;
&nbsp;    replace_terrain(&amp;rt, coder-&gt;croom);
&nbsp;
&nbsp;    opvar_free(reg);
&nbsp;    opvar_free(from_ter);
&nbsp;    opvar_free(to_ter);
&nbsp;    opvar_free(chance);
&nbsp;}
&nbsp;
generate_way_out_method
&nbsp;STATIC_OVL boolean
&nbsp;generate_way_out_method(nx,ny, ov)
&nbsp;int nx,ny;
&nbsp;struct opvar *ov;
&nbsp;{
&nbsp;    static const char nhFunc[] = "generate_way_out_method";
&nbsp;    const int escapeitems[] = { PICK_AXE,
&nbsp;                                DWARVISH_MATTOCK,
&nbsp;                                WAN_DIGGING,
&nbsp;                                WAN_TELEPORTATION,
&nbsp;                                SCR_TELEPORTATION,
&nbsp;                                RIN_TELEPORTATION };
&nbsp;    struct opvar *ov2 = selection_opvar((char *) 0), *ov3;
&nbsp;    schar x, y;
&nbsp;    boolean res = TRUE;
&nbsp;
&nbsp;    selection_floodfill(ov2, nx, ny, TRUE);
&nbsp;    ov3 = opvar_clone(ov2);
&nbsp;
&nbsp;    /* try to make a secret door */
&nbsp;    while (selection_rndcoord(ov3, &amp;x, &amp;y, TRUE)) {
&nbsp;        if (isok(x+1, y) &amp;&amp; !selection_getpoint(x+1, y, ov)
&nbsp;            &amp;&amp; IS_WALL(levl[x+1][y].typ)
&nbsp;            &amp;&amp; isok(x+2, y) &amp;&amp;  selection_getpoint(x+2, y, ov)
&nbsp;            &amp;&amp; ACCESSIBLE(levl[x+2][y].typ)) {
&nbsp;            levl[x+1][y].typ = SDOOR;
&nbsp;            goto gotitdone;
&nbsp;        }
&nbsp;        if (isok(x-1, y) &amp;&amp; !selection_getpoint(x-1, y, ov)
&nbsp;            &amp;&amp; IS_WALL(levl[x-1][y].typ)
&nbsp;            &amp;&amp; isok(x-2, y) &amp;&amp;  selection_getpoint(x-2, y, ov)
&nbsp;            &amp;&amp; ACCESSIBLE(levl[x-2][y].typ)) {
&nbsp;            levl[x-1][y].typ = SDOOR;
&nbsp;            goto gotitdone;
&nbsp;        }
&nbsp;        if (isok(x, y+1) &amp;&amp; !selection_getpoint(x, y+1, ov)
&nbsp;            &amp;&amp; IS_WALL(levl[x][y+1].typ)
&nbsp;            &amp;&amp; isok(x, y+2) &amp;&amp;  selection_getpoint(x, y+2, ov)
&nbsp;            &amp;&amp; ACCESSIBLE(levl[x][y+2].typ)) {
&nbsp;            levl[x][y+1].typ = SDOOR;
&nbsp;            goto gotitdone;
&nbsp;        }
&nbsp;        if (isok(x, y-1) &amp;&amp; !selection_getpoint(x, y-1, ov)
&nbsp;            &amp;&amp; IS_WALL(levl[x][y-1].typ)
&nbsp;            &amp;&amp; isok(x, y-2) &amp;&amp;  selection_getpoint(x, y-2, ov)
&nbsp;            &amp;&amp; ACCESSIBLE(levl[x][y-2].typ)) {
&nbsp;            levl[x][y-1].typ = SDOOR;
&nbsp;            goto gotitdone;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    /* try to make a hole or a trapdoor */
&nbsp;    if (Can_fall_thru(&amp;u.uz)) {
&nbsp;        opvar_free(ov3);
&nbsp;        ov3 = opvar_clone(ov2);
&nbsp;        while (selection_rndcoord(ov3, &amp;x, &amp;y, TRUE)) {
&nbsp;            if (maketrap(x,y, rn2(2) ? HOLE : TRAPDOOR))
&nbsp;                goto gotitdone;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    /* generate one of the escape items */
&nbsp;    if (selection_rndcoord(ov2, &amp;x, &amp;y, FALSE)) {
&nbsp;        mksobj_at(escapeitems[rn2(SIZE(escapeitems))], x, y, TRUE, FALSE);
&nbsp;        goto gotitdone;
&nbsp;    }
&nbsp;
&nbsp;    res = FALSE;
&nbsp; gotitdone:
&nbsp;    opvar_free(ov2);
&nbsp;    opvar_free(ov3);
&nbsp;    return res;
&nbsp;}
&nbsp;
ensure_way_out
&nbsp;STATIC_OVL void
&nbsp;ensure_way_out()
&nbsp;{
&nbsp;    static const char nhFunc[] = "ensure_way_out";
&nbsp;    struct opvar *ov = selection_opvar((char *) 0);
&nbsp;    struct trap *ttmp = ftrap;
&nbsp;    int x,y;
&nbsp;    boolean ret = TRUE;
&nbsp;
&nbsp;    set_selection_floodfillchk(floodfillchk_match_accessible);
&nbsp;
&nbsp;    if (xupstair &amp;&amp; !selection_getpoint(xupstair, yupstair, ov))
&nbsp;        selection_floodfill(ov, xupstair, yupstair, TRUE);
&nbsp;    if (xdnstair &amp;&amp; !selection_getpoint(xdnstair, ydnstair, ov))
&nbsp;        selection_floodfill(ov, xdnstair, ydnstair, TRUE);
&nbsp;    if (xupladder &amp;&amp; !selection_getpoint(xupladder, yupladder, ov))
&nbsp;        selection_floodfill(ov, xupladder, yupladder, TRUE);
&nbsp;    if (xdnladder &amp;&amp; !selection_getpoint(xdnladder, ydnladder, ov))
&nbsp;        selection_floodfill(ov, xdnladder, ydnladder, TRUE);
&nbsp;
&nbsp;    while (ttmp) {
&nbsp;        if ((ttmp-&gt;ttyp == MAGIC_PORTAL || ttmp-&gt;ttyp == VIBRATING_SQUARE
&nbsp;             || ttmp-&gt;ttyp == HOLE || ttmp-&gt;ttyp == TRAPDOOR)
&nbsp;            &amp;&amp; !selection_getpoint(ttmp-&gt;tx, ttmp-&gt;ty, ov))
&nbsp;            selection_floodfill(ov, ttmp-&gt;tx, ttmp-&gt;ty, TRUE);
&nbsp;        ttmp = ttmp-&gt;ntrap;
&nbsp;    }
&nbsp;
&nbsp;    do {
&nbsp;        ret = TRUE;
&nbsp;        for (x = 0; x &lt; COLNO; x++)
&nbsp;            for (y = 0; y &lt; ROWNO; y++)
&nbsp;                if (ACCESSIBLE(levl[x][y].typ)
&nbsp;                    &amp;&amp; !selection_getpoint(x, y, ov)) {
&nbsp;                    if (generate_way_out_method(x,y, ov))
&nbsp;                        selection_floodfill(ov, x,y, TRUE);
&nbsp;                    ret = FALSE;
&nbsp;                    goto outhere;
&nbsp;                }
&nbsp;    outhere: ;
&nbsp;    } while (!ret);
&nbsp;    opvar_free(ov);
&nbsp;}
&nbsp;
spo_levregion
&nbsp;void
&nbsp;spo_levregion(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_levregion";
&nbsp;    struct opvar *rname, *padding, *rtype, *del_islev, *dy2, *dx2, *dy1, *dx1,
&nbsp;        *in_islev, *iy2, *ix2, *iy1, *ix1;
&nbsp;
&nbsp;    lev_region *tmplregion;
&nbsp;
&nbsp;    if (!OV_pop_s(rname) || !OV_pop_i(padding) || !OV_pop_i(rtype)
&nbsp;        || !OV_pop_i(del_islev) || !OV_pop_i(dy2) || !OV_pop_i(dx2)
&nbsp;        || !OV_pop_i(dy1) || !OV_pop_i(dx1) || !OV_pop_i(in_islev)
&nbsp;        || !OV_pop_i(iy2) || !OV_pop_i(ix2) || !OV_pop_i(iy1)
&nbsp;        || !OV_pop_i(ix1))
&nbsp;        return;
&nbsp;
&nbsp;    tmplregion = (lev_region *) alloc(sizeof(lev_region));
&nbsp;
&nbsp;    tmplregion-&gt;inarea.x1 = OV_i(ix1);
&nbsp;    tmplregion-&gt;inarea.y1 = OV_i(iy1);
&nbsp;    tmplregion-&gt;inarea.x2 = OV_i(ix2);
&nbsp;    tmplregion-&gt;inarea.y2 = OV_i(iy2);
&nbsp;
&nbsp;    tmplregion-&gt;delarea.x1 = OV_i(dx1);
&nbsp;    tmplregion-&gt;delarea.y1 = OV_i(dy1);
&nbsp;    tmplregion-&gt;delarea.x2 = OV_i(dx2);
&nbsp;    tmplregion-&gt;delarea.y2 = OV_i(dy2);
&nbsp;
&nbsp;    tmplregion-&gt;in_islev = OV_i(in_islev);
&nbsp;    tmplregion-&gt;del_islev = OV_i(del_islev);
&nbsp;    tmplregion-&gt;rtype = OV_i(rtype);
&nbsp;    tmplregion-&gt;padding = OV_i(padding);
&nbsp;    tmplregion-&gt;rname.str = dupstr(OV_s(rname));
&nbsp;
&nbsp;    if (!tmplregion-&gt;in_islev) {
&nbsp;        get_location(&amp;tmplregion-&gt;inarea.x1, &amp;tmplregion-&gt;inarea.y1, ANY_LOC,
&nbsp;                     (struct mkroom *) 0);
&nbsp;        get_location(&amp;tmplregion-&gt;inarea.x2, &amp;tmplregion-&gt;inarea.y2, ANY_LOC,
&nbsp;                     (struct mkroom *) 0);
&nbsp;    }
&nbsp;
&nbsp;    if (!tmplregion-&gt;del_islev) {
&nbsp;        get_location(&amp;tmplregion-&gt;delarea.x1, &amp;tmplregion-&gt;delarea.y1,
&nbsp;                     ANY_LOC, (struct mkroom *) 0);
&nbsp;        get_location(&amp;tmplregion-&gt;delarea.x2, &amp;tmplregion-&gt;delarea.y2,
&nbsp;                     ANY_LOC, (struct mkroom *) 0);
&nbsp;    }
&nbsp;    if (num_lregions) {
&nbsp;        /* realloc the lregion space to add the new one */
&nbsp;        lev_region *newl = (lev_region *) alloc(
&nbsp;            sizeof(lev_region) * (unsigned) (1 + num_lregions));
&nbsp;
&nbsp;        (void) memcpy((genericptr_t) (newl), (genericptr_t) lregions,
&nbsp;                      sizeof(lev_region) * num_lregions);
&nbsp;        Free(lregions);
&nbsp;        num_lregions++;
&nbsp;        lregions = newl;
&nbsp;    } else {
&nbsp;        num_lregions = 1;
&nbsp;        lregions = (lev_region *) alloc(sizeof(lev_region));
&nbsp;    }
&nbsp;    (void) memcpy(&amp;lregions[num_lregions - 1], tmplregion,
&nbsp;                  sizeof(lev_region));
&nbsp;    free(tmplregion);
&nbsp;
&nbsp;    opvar_free(dx1);
&nbsp;    opvar_free(dy1);
&nbsp;    opvar_free(dx2);
&nbsp;    opvar_free(dy2);
&nbsp;
&nbsp;    opvar_free(ix1);
&nbsp;    opvar_free(iy1);
&nbsp;    opvar_free(ix2);
&nbsp;    opvar_free(iy2);
&nbsp;
&nbsp;    opvar_free(del_islev);
&nbsp;    opvar_free(in_islev);
&nbsp;    opvar_free(rname);
&nbsp;    opvar_free(rtype);
&nbsp;    opvar_free(padding);
&nbsp;}
&nbsp;
spo_region
&nbsp;void
&nbsp;spo_region(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_region";
&nbsp;    struct opvar *rtype, *rlit, *rflags, *area;
&nbsp;    xchar dx1, dy1, dx2, dy2;
&nbsp;    register struct mkroom *troom;
&nbsp;    boolean prefilled, room_not_needed, irregular, joined;
&nbsp;
&nbsp;    if (!OV_pop_i(rflags) || !OV_pop_i(rtype) || !OV_pop_i(rlit)
&nbsp;        || !OV_pop_r(area))
&nbsp;        return;
&nbsp;
&nbsp;    prefilled = !(OV_i(rflags) &amp; (1 &lt;&lt; 0));
&nbsp;    irregular = (OV_i(rflags) &amp; (1 &lt;&lt; 1));
&nbsp;    joined = !(OV_i(rflags) &amp; (1 &lt;&lt; 2));
&nbsp;
&nbsp;    if (OV_i(rtype) &gt; MAXRTYPE) {
&nbsp;        OV_i(rtype) -= MAXRTYPE + 1;
&nbsp;        prefilled = TRUE;
&nbsp;    } else
&nbsp;        prefilled = FALSE;
&nbsp;
&nbsp;    if (OV_i(rlit) &lt; 0)
&nbsp;        OV_i(rlit) =
&nbsp;            (rnd(1 + abs(depth(&amp;u.uz))) &lt; 11 &amp;&amp; rn2(77)) ? TRUE : FALSE;
&nbsp;
&nbsp;    dx1 = SP_REGION_X1(OV_i(area));
&nbsp;    dy1 = SP_REGION_Y1(OV_i(area));
&nbsp;    dx2 = SP_REGION_X2(OV_i(area));
&nbsp;    dy2 = SP_REGION_Y2(OV_i(area));
&nbsp;
&nbsp;    get_location(&amp;dx1, &amp;dy1, ANY_LOC, (struct mkroom *) 0);
&nbsp;    get_location(&amp;dx2, &amp;dy2, ANY_LOC, (struct mkroom *) 0);
&nbsp;
&nbsp;    /* for an ordinary room, `prefilled' is a flag to force
&nbsp;       an actual room to be created (such rooms are used to
&nbsp;       control placement of migrating monster arrivals) */
&nbsp;    room_not_needed = (OV_i(rtype) == OROOM &amp;&amp; !irregular &amp;&amp; !prefilled);
&nbsp;    if (room_not_needed || nroom &gt;= MAXNROFROOMS) {
&nbsp;        region tmpregion;
&nbsp;        if (!room_not_needed)
&nbsp;            impossible("Too many rooms on new level!");
&nbsp;        tmpregion.rlit = OV_i(rlit);
&nbsp;        tmpregion.x1 = dx1;
&nbsp;        tmpregion.y1 = dy1;
&nbsp;        tmpregion.x2 = dx2;
&nbsp;        tmpregion.y2 = dy2;
&nbsp;        light_region(&amp;tmpregion);
&nbsp;
&nbsp;        opvar_free(area);
&nbsp;        opvar_free(rflags);
&nbsp;        opvar_free(rlit);
&nbsp;        opvar_free(rtype);
&nbsp;
&nbsp;        return;
&nbsp;    }
&nbsp;
&nbsp;    troom = &amp;rooms[nroom];
&nbsp;
&nbsp;    /* mark rooms that must be filled, but do it later */
&nbsp;    if (OV_i(rtype) != OROOM)
&nbsp;        troom-&gt;needfill = (prefilled ? 2 : 1);
&nbsp;
&nbsp;    troom-&gt;needjoining = joined;
&nbsp;
&nbsp;    if (irregular) {
&nbsp;        min_rx = max_rx = dx1;
&nbsp;        min_ry = max_ry = dy1;
&nbsp;        smeq[nroom] = nroom;
&nbsp;        flood_fill_rm(dx1, dy1, nroom + ROOMOFFSET, OV_i(rlit), TRUE);
&nbsp;        add_room(min_rx, min_ry, max_rx, max_ry, FALSE, OV_i(rtype), TRUE);
&nbsp;        troom-&gt;rlit = OV_i(rlit);
&nbsp;        troom-&gt;irregular = TRUE;
&nbsp;    } else {
&nbsp;        add_room(dx1, dy1, dx2, dy2, OV_i(rlit), OV_i(rtype), TRUE);
&nbsp;#ifdef SPECIALIZATION
&nbsp;        topologize(troom, FALSE); /* set roomno */
&nbsp;#else
&nbsp;        topologize(troom); /* set roomno */
&nbsp;#endif
&nbsp;    }
&nbsp;
&nbsp;    if (!room_not_needed) {
&nbsp;        if (coder-&gt;n_subroom &gt; 1)
&nbsp;            impossible("region as subroom");
&nbsp;        else {
&nbsp;            coder-&gt;tmproomlist[coder-&gt;n_subroom] = troom;
&nbsp;            coder-&gt;failed_room[coder-&gt;n_subroom] = FALSE;
&nbsp;            coder-&gt;n_subroom++;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    opvar_free(area);
&nbsp;    opvar_free(rflags);
&nbsp;    opvar_free(rlit);
&nbsp;    opvar_free(rtype);
&nbsp;}
&nbsp;
spo_drawbridge
&nbsp;void
&nbsp;spo_drawbridge(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_drawbridge";
&nbsp;    xchar x, y;
&nbsp;    struct opvar *dir, *db_open, *dcoord;
&nbsp;
&nbsp;    if (!OV_pop_i(dir) || !OV_pop_i(db_open) || !OV_pop_c(dcoord))
&nbsp;        return;
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, DRY | WET | HOT, coder-&gt;croom, OV_i(dcoord));
&nbsp;    if (!create_drawbridge(x, y, OV_i(dir), OV_i(db_open)))
&nbsp;        impossible("Cannot create drawbridge.");
&nbsp;    SpLev_Map[x][y] = 1;
&nbsp;
&nbsp;    opvar_free(dcoord);
&nbsp;    opvar_free(db_open);
&nbsp;    opvar_free(dir);
&nbsp;}
&nbsp;
spo_mazewalk
&nbsp;void
&nbsp;spo_mazewalk(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_mazewalk";
&nbsp;    xchar x, y;
&nbsp;    struct opvar *ftyp, *fstocked, *fdir, *mcoord;
&nbsp;    int dir;
&nbsp;
&nbsp;    if (!OV_pop_i(ftyp) || !OV_pop_i(fstocked) || !OV_pop_i(fdir)
&nbsp;        || !OV_pop_c(mcoord))
&nbsp;        return;
&nbsp;
&nbsp;    dir = OV_i(fdir);
&nbsp;
&nbsp;    get_location_coord(&amp;x, &amp;y, ANY_LOC, coder-&gt;croom, OV_i(mcoord));
&nbsp;    if (!isok(x, y))
&nbsp;        return;
&nbsp;
&nbsp;    if (OV_i(ftyp) &lt; 1) {
&nbsp;        OV_i(ftyp) = level.flags.corrmaze ? CORR : ROOM;
&nbsp;    }
&nbsp;
&nbsp;    /* don't use move() - it doesn't use W_NORTH, etc. */
&nbsp;    switch (dir) {
&nbsp;    case W_NORTH:
&nbsp;        --y;
&nbsp;        break;
&nbsp;    case W_SOUTH:
&nbsp;        y++;
&nbsp;        break;
&nbsp;    case W_EAST:
&nbsp;        x++;
&nbsp;        break;
&nbsp;    case W_WEST:
&nbsp;        --x;
&nbsp;        break;
&nbsp;    default:
&nbsp;        impossible("spo_mazewalk: Bad MAZEWALK direction");
&nbsp;    }
&nbsp;
&nbsp;    if (!IS_DOOR(levl[x][y].typ)) {
&nbsp;        levl[x][y].typ = OV_i(ftyp);
&nbsp;        levl[x][y].flags = 0;
&nbsp;    }
&nbsp;
&nbsp;    /*
&nbsp;     * We must be sure that the parity of the coordinates for
&nbsp;     * walkfrom() is odd.  But we must also take into account
&nbsp;     * what direction was chosen.
&nbsp;     */
&nbsp;    if (!(x % 2)) {
&nbsp;        if (dir == W_EAST)
&nbsp;            x++;
&nbsp;        else
&nbsp;            x--;
&nbsp;
&nbsp;        /* no need for IS_DOOR check; out of map bounds */
&nbsp;        levl[x][y].typ = OV_i(ftyp);
&nbsp;        levl[x][y].flags = 0;
&nbsp;    }
&nbsp;
&nbsp;    if (!(y % 2)) {
&nbsp;        if (dir == W_SOUTH)
&nbsp;            y++;
&nbsp;        else
&nbsp;            y--;
&nbsp;    }
&nbsp;
&nbsp;    walkfrom(x, y, OV_i(ftyp));
&nbsp;    if (OV_i(fstocked))
&nbsp;        fill_empty_maze();
&nbsp;
&nbsp;    opvar_free(mcoord);
&nbsp;    opvar_free(fdir);
&nbsp;    opvar_free(fstocked);
&nbsp;    opvar_free(ftyp);
&nbsp;}
&nbsp;
spo_wall_property
&nbsp;void
&nbsp;spo_wall_property(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_wall_property";
&nbsp;    struct opvar *r;
&nbsp;    xchar dx1, dy1, dx2, dy2;
&nbsp;    int wprop = (coder-&gt;opcode == SPO_NON_DIGGABLE)
&nbsp;                   ? W_NONDIGGABLE
&nbsp;                   : W_NONPASSWALL;
&nbsp;
&nbsp;    if (!OV_pop_r(r))
&nbsp;        return;
&nbsp;
&nbsp;    dx1 = SP_REGION_X1(OV_i(r));
&nbsp;    dy1 = SP_REGION_Y1(OV_i(r));
&nbsp;    dx2 = SP_REGION_X2(OV_i(r));
&nbsp;    dy2 = SP_REGION_Y2(OV_i(r));
&nbsp;
&nbsp;    get_location(&amp;dx1, &amp;dy1, ANY_LOC, (struct mkroom *) 0);
&nbsp;    get_location(&amp;dx2, &amp;dy2, ANY_LOC, (struct mkroom *) 0);
&nbsp;
&nbsp;    set_wall_property(dx1, dy1, dx2, dy2, wprop);
&nbsp;
&nbsp;    opvar_free(r);
&nbsp;}
&nbsp;
spo_room_door
&nbsp;void
&nbsp;spo_room_door(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_room_door";
&nbsp;    struct opvar *wall, *secret, *mask, *pos;
&nbsp;    room_door tmpd;
&nbsp;
&nbsp;    if (!OV_pop_i(wall) || !OV_pop_i(secret) || !OV_pop_i(mask)
&nbsp;        || !OV_pop_i(pos) || !coder-&gt;croom)
&nbsp;        return;
&nbsp;
&nbsp;    tmpd.secret = OV_i(secret);
&nbsp;    tmpd.mask = OV_i(mask);
&nbsp;    tmpd.pos = OV_i(pos);
&nbsp;    tmpd.wall = OV_i(wall);
&nbsp;
&nbsp;    create_door(&amp;tmpd, coder-&gt;croom);
&nbsp;
&nbsp;    opvar_free(wall);
&nbsp;    opvar_free(secret);
&nbsp;    opvar_free(mask);
&nbsp;    opvar_free(pos);
&nbsp;}
&nbsp;
&nbsp;/*ARGSUSED*/
sel_set_wallify
&nbsp;void
&nbsp;sel_set_wallify(x, y, arg)
&nbsp;int x, y;
&nbsp;genericptr_t arg UNUSED;
&nbsp;{
&nbsp;    wallify_map(x, y, x, y);
&nbsp;}
&nbsp;
spo_wallify
&nbsp;void
&nbsp;spo_wallify(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_wallify";
&nbsp;    struct opvar *typ, *r;
&nbsp;    int dx1, dy1, dx2, dy2;
&nbsp;
&nbsp;    if (!OV_pop_i(typ))
&nbsp;        return;
&nbsp;    switch (OV_i(typ)) {
&nbsp;    default:
&nbsp;    case 0:
&nbsp;        if (!OV_pop_r(r))
&nbsp;            return;
&nbsp;        dx1 = (xchar) SP_REGION_X1(OV_i(r));
&nbsp;        dy1 = (xchar) SP_REGION_Y1(OV_i(r));
&nbsp;        dx2 = (xchar) SP_REGION_X2(OV_i(r));
&nbsp;        dy2 = (xchar) SP_REGION_Y2(OV_i(r));
&nbsp;        wallify_map(dx1 &lt; 0 ? (xstart - 1) : dx1,
&nbsp;                    dy1 &lt; 0 ? (ystart - 1) : dy1,
&nbsp;                    dx2 &lt; 0 ? (xstart + xsize + 1) : dx2,
&nbsp;                    dy2 &lt; 0 ? (ystart + ysize + 1) : dy2);
&nbsp;        break;
&nbsp;    case 1:
&nbsp;        if (!OV_pop_typ(r, SPOVAR_SEL))
&nbsp;            return;
&nbsp;        selection_iterate(r, sel_set_wallify, NULL);
&nbsp;        break;
&nbsp;    }
&nbsp;    opvar_free(r);
&nbsp;    opvar_free(typ);
&nbsp;}
&nbsp;
spo_map
&nbsp;void
&nbsp;spo_map(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_map";
&nbsp;    mazepart tmpmazepart;
&nbsp;    struct opvar *mpxs, *mpys, *mpmap, *mpa, *mpkeepr, *mpzalign;
&nbsp;    xchar halign, valign;
&nbsp;    xchar tmpxstart, tmpystart, tmpxsize, tmpysize;
&nbsp;    unpacked_coord upc;
&nbsp;
&nbsp;    if (!OV_pop_i(mpxs) || !OV_pop_i(mpys) || !OV_pop_s(mpmap)
&nbsp;        || !OV_pop_i(mpkeepr) || !OV_pop_i(mpzalign) || !OV_pop_c(mpa))
&nbsp;        return;
&nbsp;
&nbsp;    tmpmazepart.xsize = OV_i(mpxs);
&nbsp;    tmpmazepart.ysize = OV_i(mpys);
&nbsp;    tmpmazepart.zaligntyp = OV_i(mpzalign);
&nbsp;
&nbsp;    upc = get_unpacked_coord(OV_i(mpa), ANY_LOC);
&nbsp;    tmpmazepart.halign = upc.x;
&nbsp;    tmpmazepart.valign = upc.y;
&nbsp;
&nbsp;    tmpxsize = xsize;
&nbsp;    tmpysize = ysize;
&nbsp;    tmpxstart = xstart;
&nbsp;    tmpystart = ystart;
&nbsp;
&nbsp;    halign = tmpmazepart.halign;
&nbsp;    valign = tmpmazepart.valign;
&nbsp;    xsize = tmpmazepart.xsize;
&nbsp;    ysize = tmpmazepart.ysize;
&nbsp;    switch (tmpmazepart.zaligntyp) {
&nbsp;    default:
&nbsp;    case 0:
&nbsp;        break;
&nbsp;    case 1:
&nbsp;        switch ((int) halign) {
&nbsp;        case LEFT:
&nbsp;            xstart = splev_init_present ? 1 : 3;
&nbsp;            break;
&nbsp;        case H_LEFT:
&nbsp;            xstart = 2 + ((x_maze_max - 2 - xsize) / 4);
&nbsp;            break;
&nbsp;        case CENTER:
&nbsp;            xstart = 2 + ((x_maze_max - 2 - xsize) / 2);
&nbsp;            break;
&nbsp;        case H_RIGHT:
&nbsp;            xstart = 2 + ((x_maze_max - 2 - xsize) * 3 / 4);
&nbsp;            break;
&nbsp;        case RIGHT:
&nbsp;            xstart = x_maze_max - xsize - 1;
&nbsp;            break;
&nbsp;        }
&nbsp;        switch ((int) valign) {
&nbsp;        case TOP:
&nbsp;            ystart = 3;
&nbsp;            break;
&nbsp;        case CENTER:
&nbsp;            ystart = 2 + ((y_maze_max - 2 - ysize) / 2);
&nbsp;            break;
&nbsp;        case BOTTOM:
&nbsp;            ystart = y_maze_max - ysize - 1;
&nbsp;            break;
&nbsp;        }
&nbsp;        if (!(xstart % 2))
&nbsp;            xstart++;
&nbsp;        if (!(ystart % 2))
&nbsp;            ystart++;
&nbsp;        break;
&nbsp;    case 2:
&nbsp;        if (!coder-&gt;croom) {
&nbsp;            xstart = 1;
&nbsp;            ystart = 0;
&nbsp;            xsize = COLNO - 1 - tmpmazepart.xsize;
&nbsp;            ysize = ROWNO - tmpmazepart.ysize;
&nbsp;        }
&nbsp;        get_location_coord(&amp;halign, &amp;valign, ANY_LOC, coder-&gt;croom,
&nbsp;                           OV_i(mpa));
&nbsp;        xsize = tmpmazepart.xsize;
&nbsp;        ysize = tmpmazepart.ysize;
&nbsp;        xstart = halign;
&nbsp;        ystart = valign;
&nbsp;        break;
&nbsp;    }
&nbsp;    if (ystart &lt; 0 || ystart + ysize &gt; ROWNO) {
&nbsp;        /* try to move the start a bit */
&nbsp;        ystart += (ystart &gt; 0) ? -2 : 2;
&nbsp;        if (ysize == ROWNO)
&nbsp;            ystart = 0;
&nbsp;        if (ystart &lt; 0 || ystart + ysize &gt; ROWNO)
&nbsp;            panic("reading special level with ysize too large");
&nbsp;    }
&nbsp;    if (xsize &lt;= 1 &amp;&amp; ysize &lt;= 1) {
&nbsp;        xstart = 1;
&nbsp;        ystart = 0;
&nbsp;        xsize = COLNO - 1;
&nbsp;        ysize = ROWNO;
&nbsp;    } else {
&nbsp;        xchar x, y, mptyp;
&nbsp;
&nbsp;        /* Load the map */
&nbsp;        for (y = ystart; y &lt; ystart + ysize; y++)
&nbsp;            for (x = xstart; x &lt; xstart + xsize; x++) {
&nbsp;                mptyp = (mpmap-&gt;vardata.str[(y - ystart) * xsize
&nbsp;                                                  + (x - xstart)] - 1);
&nbsp;                if (mptyp &gt;= MAX_TYPE)
&nbsp;                    continue;
&nbsp;                levl[x][y].typ = mptyp;
&nbsp;                levl[x][y].lit = FALSE;
&nbsp;                /* clear out levl: load_common_data may set them */
&nbsp;                levl[x][y].flags = 0;
&nbsp;                levl[x][y].horizontal = 0;
&nbsp;                levl[x][y].roomno = 0;
&nbsp;                levl[x][y].edge = 0;
&nbsp;                SpLev_Map[x][y] = 1;
&nbsp;                /*
&nbsp;                 *  Set secret doors to closed (why not trapped too?).  Set
&nbsp;                 *  the horizontal bit.
&nbsp;                 */
&nbsp;                if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
&nbsp;                    if (levl[x][y].typ == SDOOR)
&nbsp;                        levl[x][y].doormask = D_CLOSED;
&nbsp;                    /*
&nbsp;                     *  If there is a wall to the left that connects to a
&nbsp;                     *  (secret) door, then it is horizontal.  This does
&nbsp;                     *  not allow (secret) doors to be corners of rooms.
&nbsp;                     */
&nbsp;                    if (x != xstart &amp;&amp; (IS_WALL(levl[x - 1][y].typ)
&nbsp;                                        || levl[x - 1][y].horizontal))
&nbsp;                        levl[x][y].horizontal = 1;
&nbsp;                } else if (levl[x][y].typ == HWALL
&nbsp;                           || levl[x][y].typ == IRONBARS)
&nbsp;                    levl[x][y].horizontal = 1;
&nbsp;                else if (levl[x][y].typ == LAVAPOOL)
&nbsp;                    levl[x][y].lit = 1;
&nbsp;                else if (splev_init_present &amp;&amp; levl[x][y].typ == ICE)
&nbsp;                    levl[x][y].icedpool = icedpools ? ICED_POOL : ICED_MOAT;
&nbsp;            }
&nbsp;        if (coder-&gt;lvl_is_joined)
&nbsp;            remove_rooms(xstart, ystart, xstart + xsize, ystart + ysize);
&nbsp;    }
&nbsp;    if (!OV_i(mpkeepr)) {
&nbsp;        xstart = tmpxstart;
&nbsp;        ystart = tmpystart;
&nbsp;        xsize = tmpxsize;
&nbsp;        ysize = tmpysize;
&nbsp;    }
&nbsp;
&nbsp;    opvar_free(mpxs);
&nbsp;    opvar_free(mpys);
&nbsp;    opvar_free(mpmap);
&nbsp;    opvar_free(mpa);
&nbsp;    opvar_free(mpkeepr);
&nbsp;    opvar_free(mpzalign);
&nbsp;}
&nbsp;
spo_jmp
&nbsp;void
&nbsp;spo_jmp(coder, lvl)
&nbsp;struct sp_coder *coder;
&nbsp;sp_lev *lvl;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_jmp";
&nbsp;    struct opvar *tmpa;
&nbsp;    long a;
&nbsp;
&nbsp;    if (!OV_pop_i(tmpa))
&nbsp;        return;
&nbsp;    a = sp_code_jmpaddr(coder-&gt;frame-&gt;n_opcode, (OV_i(tmpa) - 1));
&nbsp;    if ((a &gt;= 0) &amp;&amp; (a &lt; lvl-&gt;n_opcodes) &amp;&amp; (a != coder-&gt;frame-&gt;n_opcode))
&nbsp;        coder-&gt;frame-&gt;n_opcode = a;
&nbsp;    opvar_free(tmpa);
&nbsp;}
&nbsp;
spo_conditional_jump
&nbsp;void
&nbsp;spo_conditional_jump(coder, lvl)
&nbsp;struct sp_coder *coder;
&nbsp;sp_lev *lvl;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_conditional_jump";
&nbsp;    struct opvar *oa, *oc;
&nbsp;    long a, c;
&nbsp;    int test = 0;
&nbsp;
&nbsp;    if (!OV_pop_i(oa) || !OV_pop_i(oc))
&nbsp;        return;
&nbsp;
&nbsp;    a = sp_code_jmpaddr(coder-&gt;frame-&gt;n_opcode, (OV_i(oa) - 1));
&nbsp;    c = OV_i(oc);
&nbsp;
&nbsp;    switch (coder-&gt;opcode) {
&nbsp;    default:
&nbsp;        impossible("spo_conditional_jump: illegal opcode");
&nbsp;        break;
&nbsp;    case SPO_JL:
&nbsp;        test = (c &amp; SP_CPUFLAG_LT);
&nbsp;        break;
&nbsp;    case SPO_JLE:
&nbsp;        test = (c &amp; (SP_CPUFLAG_LT | SP_CPUFLAG_EQ));
&nbsp;        break;
&nbsp;    case SPO_JG:
&nbsp;        test = (c &amp; SP_CPUFLAG_GT);
&nbsp;        break;
&nbsp;    case SPO_JGE:
&nbsp;        test = (c &amp; (SP_CPUFLAG_GT | SP_CPUFLAG_EQ));
&nbsp;        break;
&nbsp;    case SPO_JE:
&nbsp;        test = (c &amp; SP_CPUFLAG_EQ);
&nbsp;        break;
&nbsp;    case SPO_JNE:
&nbsp;        test = (c &amp; ~SP_CPUFLAG_EQ);
&nbsp;        break;
&nbsp;    }
&nbsp;
&nbsp;    if ((test) &amp;&amp; (a &gt;= 0) &amp;&amp; (a &lt; lvl-&gt;n_opcodes)
&nbsp;        &amp;&amp; (a != coder-&gt;frame-&gt;n_opcode))
&nbsp;        coder-&gt;frame-&gt;n_opcode = a;
&nbsp;
&nbsp;    opvar_free(oa);
&nbsp;    opvar_free(oc);
&nbsp;}
&nbsp;
spo_var_init
&nbsp;void
&nbsp;spo_var_init(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_var_init";
&nbsp;    struct opvar *vname;
&nbsp;    struct opvar *arraylen;
&nbsp;    struct opvar *vvalue;
&nbsp;    struct splev_var *tmpvar;
&nbsp;    struct splev_var *tmp2;
&nbsp;    long idx;
&nbsp;
&nbsp;    OV_pop_s(vname);
&nbsp;    OV_pop_i(arraylen);
&nbsp;
&nbsp;    if (!vname || !arraylen)
&nbsp;        panic("no values for SPO_VAR_INIT");
&nbsp;
&nbsp;    tmpvar = opvar_var_defined(coder, OV_s(vname));
&nbsp;
&nbsp;    if (tmpvar) {
&nbsp;        /* variable redefinition */
&nbsp;        if (OV_i(arraylen) &lt; 0) {
&nbsp;            /* copy variable */
&nbsp;            if (tmpvar-&gt;array_len) {
&nbsp;                idx = tmpvar-&gt;array_len;
&nbsp;                while (idx-- &gt; 0) {
&nbsp;                    opvar_free(tmpvar-&gt;data.arrayvalues[idx]);
&nbsp;                }
&nbsp;                Free(tmpvar-&gt;data.arrayvalues);
&nbsp;            } else {
&nbsp;                opvar_free(tmpvar-&gt;data.value);
&nbsp;            }
&nbsp;            tmpvar-&gt;data.arrayvalues = NULL;
&nbsp;            goto copy_variable;
&nbsp;        } else if (OV_i(arraylen)) {
&nbsp;            /* redefined array */
&nbsp;            idx = tmpvar-&gt;array_len;
&nbsp;            while (idx-- &gt; 0) {
&nbsp;                opvar_free(tmpvar-&gt;data.arrayvalues[idx]);
&nbsp;            }
&nbsp;            Free(tmpvar-&gt;data.arrayvalues);
&nbsp;            tmpvar-&gt;data.arrayvalues = NULL;
&nbsp;            goto create_new_array;
&nbsp;        } else {
&nbsp;            /* redefined single value */
&nbsp;            OV_pop(vvalue);
&nbsp;            if (tmpvar-&gt;svtyp != vvalue-&gt;spovartyp)
&nbsp;                panic("redefining variable as different type");
&nbsp;            opvar_free(tmpvar-&gt;data.value);
&nbsp;            tmpvar-&gt;data.value = vvalue;
&nbsp;            tmpvar-&gt;array_len = 0;
&nbsp;        }
&nbsp;    } else {
&nbsp;        /* new variable definition */
&nbsp;        tmpvar = (struct splev_var *) alloc(sizeof(struct splev_var));
&nbsp;        tmpvar-&gt;next = coder-&gt;frame-&gt;variables;
&nbsp;        tmpvar-&gt;name = dupstr(OV_s(vname));
&nbsp;        coder-&gt;frame-&gt;variables = tmpvar;
&nbsp;
&nbsp;        if (OV_i(arraylen) &lt; 0) {
&nbsp;        /* copy variable */
&nbsp;        copy_variable:
&nbsp;            OV_pop(vvalue);
&nbsp;            tmp2 = opvar_var_defined(coder, OV_s(vvalue));
&nbsp;            if (!tmp2)
&nbsp;                panic("no copyable var");
&nbsp;            tmpvar-&gt;svtyp = tmp2-&gt;svtyp;
&nbsp;            tmpvar-&gt;array_len = tmp2-&gt;array_len;
&nbsp;            if (tmpvar-&gt;array_len) {
&nbsp;                idx = tmpvar-&gt;array_len;
&nbsp;                tmpvar-&gt;data.arrayvalues =
&nbsp;                    (struct opvar **) alloc(sizeof(struct opvar *) * idx);
&nbsp;                while (idx-- &gt; 0) {
&nbsp;                    tmpvar-&gt;data.arrayvalues[idx] =
&nbsp;                        opvar_clone(tmp2-&gt;data.arrayvalues[idx]);
&nbsp;                }
&nbsp;            } else {
&nbsp;                tmpvar-&gt;data.value = opvar_clone(tmp2-&gt;data.value);
&nbsp;            }
&nbsp;            opvar_free(vvalue);
&nbsp;        } else if (OV_i(arraylen)) {
&nbsp;        /* new array */
&nbsp;        create_new_array:
&nbsp;            idx = OV_i(arraylen);
&nbsp;            tmpvar-&gt;array_len = idx;
&nbsp;            tmpvar-&gt;data.arrayvalues =
&nbsp;                (struct opvar **) alloc(sizeof(struct opvar *) * idx);
&nbsp;            while (idx-- &gt; 0) {
&nbsp;                OV_pop(vvalue);
&nbsp;                if (!vvalue)
&nbsp;                    panic("no value for arrayvariable");
&nbsp;                tmpvar-&gt;data.arrayvalues[idx] = vvalue;
&nbsp;            }
&nbsp;            tmpvar-&gt;svtyp = SPOVAR_ARRAY;
&nbsp;        } else {
&nbsp;            /* new single value */
&nbsp;            OV_pop(vvalue);
&nbsp;            if (!vvalue)
&nbsp;                panic("no value for variable");
&nbsp;            tmpvar-&gt;svtyp = OV_typ(vvalue);
&nbsp;            tmpvar-&gt;data.value = vvalue;
&nbsp;            tmpvar-&gt;array_len = 0;
&nbsp;        }
&nbsp;    }
&nbsp;
&nbsp;    opvar_free(vname);
&nbsp;    opvar_free(arraylen);
&nbsp;
&nbsp;}
&nbsp;
&nbsp;#if 0
&nbsp;STATIC_OVL long
&nbsp;opvar_array_length(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "opvar_array_length";
&nbsp;    struct opvar *vname;
&nbsp;    struct splev_var *tmp;
&nbsp;    long len = 0;
&nbsp;
&nbsp;    if (!coder)
&nbsp;        return 0;
&nbsp;
&nbsp;    vname = splev_stack_pop(coder-&gt;stack);
&nbsp;    if (!vname)
&nbsp;        return 0;
&nbsp;    if (vname-&gt;spovartyp != SPOVAR_VARIABLE)
&nbsp;        goto pass;
&nbsp;
&nbsp;    tmp = coder-&gt;frame-&gt;variables;
&nbsp;    while (tmp) {
&nbsp;        if (!strcmp(tmp-&gt;name, OV_s(vname))) {
&nbsp;            if ((tmp-&gt;svtyp &amp; SPOVAR_ARRAY)) {
&nbsp;                len = tmp-&gt;array_len;
&nbsp;                if (len &lt; 1)
&nbsp;                    len = 0;
&nbsp;            }
&nbsp;            goto pass;
&nbsp;        }
&nbsp;        tmp = tmp-&gt;next;
&nbsp;    }
&nbsp;
&nbsp;pass:
&nbsp;    opvar_free(vname);
&nbsp;    return len;
&nbsp;}
&nbsp;#endif /*0*/
&nbsp;
spo_shuffle_array
&nbsp;void
&nbsp;spo_shuffle_array(coder)
&nbsp;struct sp_coder *coder;
&nbsp;{
&nbsp;    static const char nhFunc[] = "spo_shuffle_array";
&nbsp;    struct opvar *vname;
&nbsp;    struct splev_var *tmp;
&nbsp;    struct opvar *tmp2;
&nbsp;    long i, j;
&nbsp;
&nbsp;    if (!OV_pop_s(vname))
&nbsp;        return;
&nbsp;
&nbsp;    tmp = opvar_var_defined(coder, OV_s(vname));
&nbsp;    if (!tmp || (tmp-&gt;array_len &lt; 1)) {
&nbsp;        opvar_free(vname);
&nbsp;        return;
&nbsp;    }
&nbsp;    for (i = tmp-&gt;array_len - 1; i &gt; 0; i--) {
&nbsp;        if ((j = rn2(i + 1)) == i)
&nbsp;            continue;
&nbsp;        tmp2 = tmp-&gt;data.arrayvalues[j];
&nbsp;        tmp-&gt;data.arrayvalues[j] = tmp-&gt;data.arrayvalues[i];
&nbsp;        tmp-&gt;data.arrayvalues[i] = tmp2;
&nbsp;    }
&nbsp;
&nbsp;    opvar_free(vname);
&nbsp;}
&nbsp;
sp_level_coder
&nbsp;/* Special level coder, creates the special level from the sp_lev codes.
&nbsp; * Does not free the allocated memory.
&nbsp; */
&nbsp;STATIC_OVL boolean
&nbsp;sp_level_coder(lvl)
&nbsp;sp_lev *lvl;
&nbsp;{
&nbsp;    static const char nhFunc[] = "sp_level_coder";
&nbsp;    unsigned long exec_opcodes = 0;
&nbsp;    int tmpi;
&nbsp;    long room_stack = 0;
&nbsp;    unsigned long max_execution = SPCODER_MAX_RUNTIME;
&nbsp;    struct sp_coder *coder =
&nbsp;        (struct sp_coder *) alloc(sizeof (struct sp_coder));
&nbsp;
&nbsp;    coder-&gt;frame = frame_new(0);
&nbsp;    coder-&gt;stack = NULL;
&nbsp;    coder-&gt;premapped = FALSE;
&nbsp;    coder-&gt;solidify = FALSE;
&nbsp;    coder-&gt;check_inaccessibles = FALSE;
&nbsp;    coder-&gt;croom = NULL;
&nbsp;    coder-&gt;n_subroom = 1;
&nbsp;    coder-&gt;exit_script = FALSE;
&nbsp;    coder-&gt;lvl_is_joined = 0;
&nbsp;
&nbsp;    splev_init_present = FALSE;
&nbsp;    icedpools = FALSE;
&nbsp;    /* achievement tracking; static init would suffice except we need to
&nbsp;       reset if #wizmakemap is used to recreate mines' end or sokoban end;
&nbsp;       once either level is created, these values can be forgotten */
&nbsp;    mines_prize_count = soko_prize_count = 0;
&nbsp;
&nbsp;    if (wizard) {
&nbsp;        char *met = nh_getenv("SPCODER_MAX_RUNTIME");
&nbsp;
&nbsp;        if (met &amp;&amp; met[0] == '1')
&nbsp;            max_execution = (1 &lt;&lt; 30) - 1;
&nbsp;    }
&nbsp;
&nbsp;    for (tmpi = 0; tmpi &lt;= MAX_NESTED_ROOMS; tmpi++) {
&nbsp;        coder-&gt;tmproomlist[tmpi] = (struct mkroom *) 0;
&nbsp;        coder-&gt;failed_room[tmpi] = FALSE;
&nbsp;    }
&nbsp;
&nbsp;    shuffle_alignments();
&nbsp;
&nbsp;    for (tmpi = 0; tmpi &lt; MAX_CONTAINMENT; tmpi++)
&nbsp;        container_obj[tmpi] = NULL;
&nbsp;    container_idx = 0;
&nbsp;
&nbsp;    invent_carrying_monster = NULL;
&nbsp;
&nbsp;    (void) memset((genericptr_t) &amp;SpLev_Map[0][0], 0, sizeof SpLev_Map);
&nbsp;
&nbsp;    level.flags.is_maze_lev = 0;
&nbsp;
&nbsp;    xstart = 1;
&nbsp;    ystart = 0;
&nbsp;    xsize = COLNO - 1;
&nbsp;    ysize = ROWNO;
&nbsp;
&nbsp;    while (coder-&gt;frame-&gt;n_opcode &lt; lvl-&gt;n_opcodes &amp;&amp; !coder-&gt;exit_script) {
&nbsp;        coder-&gt;opcode = lvl-&gt;opcodes[coder-&gt;frame-&gt;n_opcode].opcode;
&nbsp;        coder-&gt;opdat = lvl-&gt;opcodes[coder-&gt;frame-&gt;n_opcode].opdat;
&nbsp;
&nbsp;        coder-&gt;stack = coder-&gt;frame-&gt;stack;
&nbsp;
&nbsp;        if (exec_opcodes++ &gt; max_execution) {
&nbsp;            impossible("Level script is taking too much time, stopping.");
&nbsp;            coder-&gt;exit_script = TRUE;
&nbsp;        }
&nbsp;
&nbsp;        if (coder-&gt;failed_room[coder-&gt;n_subroom - 1]
&nbsp;            &amp;&amp; coder-&gt;opcode != SPO_ENDROOM &amp;&amp; coder-&gt;opcode != SPO_ROOM
&nbsp;            &amp;&amp; coder-&gt;opcode != SPO_SUBROOM)
&nbsp;            goto next_opcode;
&nbsp;
&nbsp;        coder-&gt;croom = coder-&gt;tmproomlist[coder-&gt;n_subroom - 1];
&nbsp;
&nbsp;        switch (coder-&gt;opcode) {
&nbsp;        case SPO_NULL:
&nbsp;            break;
&nbsp;        case SPO_EXIT:
&nbsp;            coder-&gt;exit_script = TRUE;
&nbsp;            break;
&nbsp;        case SPO_FRAME_PUSH:
&nbsp;            spo_frame_push(coder);
&nbsp;            break;
&nbsp;        case SPO_FRAME_POP:
&nbsp;            spo_frame_pop(coder);
&nbsp;            break;
&nbsp;        case SPO_CALL:
&nbsp;            spo_call(coder);
&nbsp;            break;
&nbsp;        case SPO_RETURN:
&nbsp;            spo_return(coder);
&nbsp;            break;
&nbsp;        case SPO_END_MONINVENT:
&nbsp;            spo_end_moninvent(coder);
&nbsp;            break;
&nbsp;        case SPO_POP_CONTAINER:
&nbsp;            spo_pop_container(coder);
&nbsp;            break;
&nbsp;        case SPO_POP: {
&nbsp;            struct opvar *ov = splev_stack_pop(coder-&gt;stack);
&nbsp;
&nbsp;            opvar_free(ov);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_PUSH:
&nbsp;            splev_stack_push(coder-&gt;stack, opvar_clone(coder-&gt;opdat));
&nbsp;            break;
&nbsp;        case SPO_MESSAGE:
&nbsp;            spo_message(coder);
&nbsp;            break;
&nbsp;        case SPO_MONSTER:
&nbsp;            spo_monster(coder);
&nbsp;            break;
&nbsp;        case SPO_OBJECT:
&nbsp;            spo_object(coder);
&nbsp;            break;
&nbsp;        case SPO_LEVEL_FLAGS:
&nbsp;            spo_level_flags(coder);
&nbsp;            break;
&nbsp;        case SPO_INITLEVEL:
&nbsp;            spo_initlevel(coder);
&nbsp;            break;
&nbsp;        case SPO_ENGRAVING:
&nbsp;            spo_engraving(coder);
&nbsp;            break;
&nbsp;        case SPO_MINERALIZE:
&nbsp;            spo_mineralize(coder);
&nbsp;            break;
&nbsp;        case SPO_SUBROOM:
&nbsp;        case SPO_ROOM:
&nbsp;            if (!coder-&gt;failed_room[coder-&gt;n_subroom - 1]) {
&nbsp;                spo_room(coder);
&nbsp;            } else
&nbsp;                room_stack++;
&nbsp;            break;
&nbsp;        case SPO_ENDROOM:
&nbsp;            if (coder-&gt;failed_room[coder-&gt;n_subroom - 1]) {
&nbsp;                if (!room_stack)
&nbsp;                    spo_endroom(coder);
&nbsp;                else
&nbsp;                    room_stack--;
&nbsp;            } else {
&nbsp;                spo_endroom(coder);
&nbsp;            }
&nbsp;            break;
&nbsp;        case SPO_DOOR:
&nbsp;            spo_door(coder);
&nbsp;            break;
&nbsp;        case SPO_STAIR:
&nbsp;            spo_stair(coder);
&nbsp;            break;
&nbsp;        case SPO_LADDER:
&nbsp;            spo_ladder(coder);
&nbsp;            break;
&nbsp;        case SPO_GRAVE:
&nbsp;            spo_grave(coder);
&nbsp;            break;
&nbsp;        case SPO_ALTAR:
&nbsp;            spo_altar(coder);
&nbsp;            break;
&nbsp;        case SPO_SINK:
&nbsp;        case SPO_POOL:
&nbsp;        case SPO_FOUNTAIN:
&nbsp;            spo_feature(coder);
&nbsp;            break;
&nbsp;        case SPO_TRAP:
&nbsp;            spo_trap(coder);
&nbsp;            break;
&nbsp;        case SPO_GOLD:
&nbsp;            spo_gold(coder);
&nbsp;            break;
&nbsp;        case SPO_CORRIDOR:
&nbsp;            spo_corridor(coder);
&nbsp;            break;
&nbsp;        case SPO_TERRAIN:
&nbsp;            spo_terrain(coder);
&nbsp;            break;
&nbsp;        case SPO_REPLACETERRAIN:
&nbsp;            spo_replace_terrain(coder);
&nbsp;            break;
&nbsp;        case SPO_LEVREGION:
&nbsp;            spo_levregion(coder);
&nbsp;            break;
&nbsp;        case SPO_REGION:
&nbsp;            spo_region(coder);
&nbsp;            break;
&nbsp;        case SPO_DRAWBRIDGE:
&nbsp;            spo_drawbridge(coder);
&nbsp;            break;
&nbsp;        case SPO_MAZEWALK:
&nbsp;            spo_mazewalk(coder);
&nbsp;            break;
&nbsp;        case SPO_NON_PASSWALL:
&nbsp;        case SPO_NON_DIGGABLE:
&nbsp;            spo_wall_property(coder);
&nbsp;            break;
&nbsp;        case SPO_ROOM_DOOR:
&nbsp;            spo_room_door(coder);
&nbsp;            break;
&nbsp;        case SPO_WALLIFY:
&nbsp;            spo_wallify(coder);
&nbsp;            break;
&nbsp;        case SPO_COPY: {
&nbsp;            struct opvar *a = splev_stack_pop(coder-&gt;stack);
&nbsp;
&nbsp;            splev_stack_push(coder-&gt;stack, opvar_clone(a));
&nbsp;            splev_stack_push(coder-&gt;stack, opvar_clone(a));
&nbsp;            opvar_free(a);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_DEC: {
&nbsp;            struct opvar *a;
&nbsp;
&nbsp;            if (!OV_pop_i(a))
&nbsp;                break;
&nbsp;            OV_i(a)--;
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_INC: {
&nbsp;            struct opvar *a;
&nbsp;
&nbsp;            if (!OV_pop_i(a))
&nbsp;                break;
&nbsp;            OV_i(a)++;
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MATH_SIGN: {
&nbsp;            struct opvar *a;
&nbsp;
&nbsp;            if (!OV_pop_i(a))
&nbsp;                break;
&nbsp;            OV_i(a) = ((OV_i(a) &lt; 0) ? -1 : ((OV_i(a) &gt; 0) ? 1 : 0));
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MATH_ADD: {
&nbsp;            struct opvar *a, *b;
&nbsp;
&nbsp;            if (!OV_pop(b) || !OV_pop(a))
&nbsp;                break;
&nbsp;            if (OV_typ(b) == OV_typ(a)) {
&nbsp;                if (OV_typ(a) == SPOVAR_INT) {
&nbsp;                    OV_i(a) = OV_i(a) + OV_i(b);
&nbsp;                    splev_stack_push(coder-&gt;stack, a);
&nbsp;                    opvar_free(b);
&nbsp;                } else if (OV_typ(a) == SPOVAR_STRING) {
&nbsp;                    struct opvar *c;
&nbsp;                    char *tmpbuf = (char *) alloc(strlen(OV_s(a))
&nbsp;                                                  + strlen(OV_s(b)) + 1);
&nbsp;
&nbsp;                    (void) sprintf(tmpbuf, "%s%s", OV_s(a), OV_s(b));
&nbsp;                    c = opvar_new_str(tmpbuf);
&nbsp;                    splev_stack_push(coder-&gt;stack, c);
&nbsp;                    opvar_free(a);
&nbsp;                    opvar_free(b);
&nbsp;                    Free(tmpbuf);
&nbsp;                } else {
&nbsp;                    splev_stack_push(coder-&gt;stack, a);
&nbsp;                    opvar_free(b);
&nbsp;                    impossible("adding weird types");
&nbsp;                }
&nbsp;            } else {
&nbsp;                splev_stack_push(coder-&gt;stack, a);
&nbsp;                opvar_free(b);
&nbsp;                impossible("adding different types");
&nbsp;            }
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MATH_SUB: {
&nbsp;            struct opvar *a, *b;
&nbsp;
&nbsp;            if (!OV_pop_i(b) || !OV_pop_i(a))
&nbsp;                break;
&nbsp;            OV_i(a) = OV_i(a) - OV_i(b);
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            opvar_free(b);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MATH_MUL: {
&nbsp;            struct opvar *a, *b;
&nbsp;
&nbsp;            if (!OV_pop_i(b) || !OV_pop_i(a))
&nbsp;                break;
&nbsp;            OV_i(a) = OV_i(a) * OV_i(b);
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            opvar_free(b);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MATH_DIV: {
&nbsp;            struct opvar *a, *b;
&nbsp;
&nbsp;            if (!OV_pop_i(b) || !OV_pop_i(a))
&nbsp;                break;
&nbsp;            if (OV_i(b) &gt;= 1) {
&nbsp;                OV_i(a) = OV_i(a) / OV_i(b);
&nbsp;            } else {
&nbsp;                OV_i(a) = 0;
&nbsp;            }
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            opvar_free(b);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MATH_MOD: {
&nbsp;            struct opvar *a, *b;
&nbsp;
&nbsp;            if (!OV_pop_i(b) || !OV_pop_i(a))
&nbsp;                break;
&nbsp;            if (OV_i(b) &gt; 0) {
&nbsp;                OV_i(a) = OV_i(a) % OV_i(b);
&nbsp;            } else {
&nbsp;                OV_i(a) = 0;
&nbsp;            }
&nbsp;            splev_stack_push(coder-&gt;stack, a);
&nbsp;            opvar_free(b);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_CMP: {
&nbsp;            struct opvar *a;
&nbsp;            struct opvar *b;
&nbsp;            struct opvar *c;
&nbsp;            long val = 0;
&nbsp;
&nbsp;            OV_pop(b);
&nbsp;            OV_pop(a);
&nbsp;            if (!a || !b) {
&nbsp;                impossible("spo_cmp: no values in stack");
&nbsp;                break;
&nbsp;            }
&nbsp;            if (OV_typ(a) != OV_typ(b)) {
&nbsp;                impossible("spo_cmp: trying to compare differing datatypes");
&nbsp;                break;
&nbsp;            }
&nbsp;            switch (OV_typ(a)) {
&nbsp;            case SPOVAR_COORD:
&nbsp;            case SPOVAR_REGION:
&nbsp;            case SPOVAR_MAPCHAR:
&nbsp;            case SPOVAR_MONST:
&nbsp;            case SPOVAR_OBJ:
&nbsp;            case SPOVAR_INT:
&nbsp;                if (OV_i(b) &gt; OV_i(a))
&nbsp;                    val |= SP_CPUFLAG_LT;
&nbsp;                if (OV_i(b) &lt; OV_i(a))
&nbsp;                    val |= SP_CPUFLAG_GT;
&nbsp;                if (OV_i(b) == OV_i(a))
&nbsp;                    val |= SP_CPUFLAG_EQ;
&nbsp;                c = opvar_new_int(val);
&nbsp;                break;
&nbsp;            case SPOVAR_STRING:
&nbsp;                c = opvar_new_int(!strcmp(OV_s(b), OV_s(a))
&nbsp;                                     ? SP_CPUFLAG_EQ
&nbsp;                                     : 0);
&nbsp;                break;
&nbsp;            default:
&nbsp;                c = opvar_new_int(0);
&nbsp;                break;
&nbsp;            }
&nbsp;            splev_stack_push(coder-&gt;stack, c);
&nbsp;            opvar_free(a);
&nbsp;            opvar_free(b);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_JMP:
&nbsp;            spo_jmp(coder, lvl);
&nbsp;            break;
&nbsp;        case SPO_JL:
&nbsp;        case SPO_JLE:
&nbsp;        case SPO_JG:
&nbsp;        case SPO_JGE:
&nbsp;        case SPO_JE:
&nbsp;        case SPO_JNE:
&nbsp;            spo_conditional_jump(coder, lvl);
&nbsp;            break;
&nbsp;        case SPO_RN2: {
&nbsp;            struct opvar *tmpv;
&nbsp;            struct opvar *t;
&nbsp;
&nbsp;            if (!OV_pop_i(tmpv))
&nbsp;                break;
&nbsp;            t = opvar_new_int((OV_i(tmpv) &gt; 1) ? rn2(OV_i(tmpv)) : 0);
&nbsp;            splev_stack_push(coder-&gt;stack, t);
&nbsp;            opvar_free(tmpv);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_DICE: {
&nbsp;            struct opvar *a, *b, *t;
&nbsp;
&nbsp;            if (!OV_pop_i(b) || !OV_pop_i(a))
&nbsp;                break;
&nbsp;            if (OV_i(b) &lt; 1)
&nbsp;                OV_i(b) = 1;
&nbsp;            if (OV_i(a) &lt; 1)
&nbsp;                OV_i(a) = 1;
&nbsp;            t = opvar_new_int(d(OV_i(a), OV_i(b)));
&nbsp;            splev_stack_push(coder-&gt;stack, t);
&nbsp;            opvar_free(a);
&nbsp;            opvar_free(b);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_MAP:
&nbsp;            spo_map(coder);
&nbsp;            break;
&nbsp;        case SPO_VAR_INIT:
&nbsp;            spo_var_init(coder);
&nbsp;            break;
&nbsp;        case SPO_SHUFFLE_ARRAY:
&nbsp;            spo_shuffle_array(coder);
&nbsp;            break;
&nbsp;        case SPO_SEL_ADD: /* actually, logical or */
&nbsp;        {
&nbsp;            struct opvar *sel1, *sel2, *pt;
&nbsp;
&nbsp;            if (!OV_pop_typ(sel1, SPOVAR_SEL))
&nbsp;                panic("no sel1 for add");
&nbsp;            if (!OV_pop_typ(sel2, SPOVAR_SEL))
&nbsp;                panic("no sel2 for add");
&nbsp;            pt = selection_logical_oper(sel1, sel2, '|');
&nbsp;            opvar_free(sel1);
&nbsp;            opvar_free(sel2);
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_COMPLEMENT: {
&nbsp;            struct opvar *sel, *pt;
&nbsp;
&nbsp;            if (!OV_pop_typ(sel, SPOVAR_SEL))
&nbsp;                panic("no sel for not");
&nbsp;            pt = selection_not(sel);
&nbsp;            opvar_free(sel);
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_FILTER: /* sorta like logical and */
&nbsp;        {
&nbsp;            struct opvar *filtertype;
&nbsp;
&nbsp;            if (!OV_pop_i(filtertype))
&nbsp;                panic("no sel filter type");
&nbsp;            switch (OV_i(filtertype)) {
&nbsp;            case SPOFILTER_PERCENT: {
&nbsp;                struct opvar *tmp1, *sel;
&nbsp;
&nbsp;                if (!OV_pop_i(tmp1))
&nbsp;                    panic("no sel filter percent");
&nbsp;                if (!OV_pop_typ(sel, SPOVAR_SEL))
&nbsp;                    panic("no sel filter");
&nbsp;                selection_filter_percent(sel, OV_i(tmp1));
&nbsp;                splev_stack_push(coder-&gt;stack, sel);
&nbsp;                opvar_free(tmp1);
&nbsp;                break;
&nbsp;            }
&nbsp;            case SPOFILTER_SELECTION: /* logical and */
&nbsp;            {
&nbsp;                struct opvar *pt, *sel1, *sel2;
&nbsp;
&nbsp;                if (!OV_pop_typ(sel1, SPOVAR_SEL))
&nbsp;                    panic("no sel filter sel1");
&nbsp;                if (!OV_pop_typ(sel2, SPOVAR_SEL))
&nbsp;                    panic("no sel filter sel2");
&nbsp;                pt = selection_logical_oper(sel1, sel2, '&amp;');
&nbsp;                splev_stack_push(coder-&gt;stack, pt);
&nbsp;                opvar_free(sel1);
&nbsp;                opvar_free(sel2);
&nbsp;                break;
&nbsp;            }
&nbsp;            case SPOFILTER_MAPCHAR: {
&nbsp;                struct opvar *pt, *tmp1, *sel;
&nbsp;
&nbsp;                if (!OV_pop_typ(sel, SPOVAR_SEL))
&nbsp;                    panic("no sel filter");
&nbsp;                if (!OV_pop_typ(tmp1, SPOVAR_MAPCHAR))
&nbsp;                    panic("no sel filter mapchar");
&nbsp;                pt = selection_filter_mapchar(sel, tmp1);
&nbsp;                splev_stack_push(coder-&gt;stack, pt);
&nbsp;                opvar_free(tmp1);
&nbsp;                opvar_free(sel);
&nbsp;                break;
&nbsp;            }
&nbsp;            default:
&nbsp;                panic("unknown sel filter type");
&nbsp;            }
&nbsp;            opvar_free(filtertype);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_POINT: {
&nbsp;            struct opvar *tmp;
&nbsp;            struct opvar *pt = selection_opvar((char *) 0);
&nbsp;            schar x, y;
&nbsp;
&nbsp;            if (!OV_pop_c(tmp))
&nbsp;                panic("no ter sel coord");
&nbsp;            get_location_coord(&amp;x, &amp;y, ANY_LOC, coder-&gt;croom, OV_i(tmp));
&nbsp;            selection_setpoint(x, y, pt, 1);
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            opvar_free(tmp);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_RECT:
&nbsp;        case SPO_SEL_FILLRECT: {
&nbsp;            struct opvar *tmp, *pt = selection_opvar((char *) 0);
&nbsp;            schar x, y, x1, y1, x2, y2;
&nbsp;
&nbsp;            if (!OV_pop_r(tmp))
&nbsp;                panic("no ter sel region");
&nbsp;            x1 = min(SP_REGION_X1(OV_i(tmp)), SP_REGION_X2(OV_i(tmp)));
&nbsp;            y1 = min(SP_REGION_Y1(OV_i(tmp)), SP_REGION_Y2(OV_i(tmp)));
&nbsp;            x2 = max(SP_REGION_X1(OV_i(tmp)), SP_REGION_X2(OV_i(tmp)));
&nbsp;            y2 = max(SP_REGION_Y1(OV_i(tmp)), SP_REGION_Y2(OV_i(tmp)));
&nbsp;            get_location(&amp;x1, &amp;y1, ANY_LOC, coder-&gt;croom);
&nbsp;            get_location(&amp;x2, &amp;y2, ANY_LOC, coder-&gt;croom);
&nbsp;            x1 = (x1 &lt; 0) ? 0 : x1;
&nbsp;            y1 = (y1 &lt; 0) ? 0 : y1;
&nbsp;            x2 = (x2 &gt;= COLNO) ? COLNO - 1 : x2;
&nbsp;            y2 = (y2 &gt;= ROWNO) ? ROWNO - 1 : y2;
&nbsp;            if (coder-&gt;opcode == SPO_SEL_RECT) {
&nbsp;                for (x = x1; x &lt;= x2; x++) {
&nbsp;                    selection_setpoint(x, y1, pt, 1);
&nbsp;                    selection_setpoint(x, y2, pt, 1);
&nbsp;                }
&nbsp;                for (y = y1; y &lt;= y2; y++) {
&nbsp;                    selection_setpoint(x1, y, pt, 1);
&nbsp;                    selection_setpoint(x2, y, pt, 1);
&nbsp;                }
&nbsp;            } else {
&nbsp;                for (x = x1; x &lt;= x2; x++)
&nbsp;                    for (y = y1; y &lt;= y2; y++)
&nbsp;                        selection_setpoint(x, y, pt, 1);
&nbsp;            }
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            opvar_free(tmp);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_LINE: {
&nbsp;            struct opvar *tmp = NULL, *tmp2 = NULL,
&nbsp;                *pt = selection_opvar((char *) 0);
&nbsp;            schar x1, y1, x2, y2;
&nbsp;
&nbsp;            if (!OV_pop_c(tmp))
&nbsp;                panic("no ter sel linecoord1");
&nbsp;            if (!OV_pop_c(tmp2))
&nbsp;                panic("no ter sel linecoord2");
&nbsp;            get_location_coord(&amp;x1, &amp;y1, ANY_LOC, coder-&gt;croom, OV_i(tmp));
&nbsp;            get_location_coord(&amp;x2, &amp;y2, ANY_LOC, coder-&gt;croom, OV_i(tmp2));
&nbsp;            x1 = (x1 &lt; 0) ? 0 : x1;
&nbsp;            y1 = (y1 &lt; 0) ? 0 : y1;
&nbsp;            x2 = (x2 &gt;= COLNO) ? COLNO - 1 : x2;
&nbsp;            y2 = (y2 &gt;= ROWNO) ? ROWNO - 1 : y2;
&nbsp;            selection_do_line(x1, y1, x2, y2, pt);
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            opvar_free(tmp);
&nbsp;            opvar_free(tmp2);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_RNDLINE: {
&nbsp;            struct opvar *tmp = NULL, *tmp2 = NULL, *tmp3,
&nbsp;                *pt = selection_opvar((char *) 0);
&nbsp;            schar x1, y1, x2, y2;
&nbsp;
&nbsp;            if (!OV_pop_i(tmp3))
&nbsp;                panic("no ter sel randline1");
&nbsp;            if (!OV_pop_c(tmp))
&nbsp;                panic("no ter sel randline2");
&nbsp;            if (!OV_pop_c(tmp2))
&nbsp;                panic("no ter sel randline3");
&nbsp;            get_location_coord(&amp;x1, &amp;y1, ANY_LOC, coder-&gt;croom, OV_i(tmp));
&nbsp;            get_location_coord(&amp;x2, &amp;y2, ANY_LOC, coder-&gt;croom, OV_i(tmp2));
&nbsp;            x1 = (x1 &lt; 0) ? 0 : x1;
&nbsp;            y1 = (y1 &lt; 0) ? 0 : y1;
&nbsp;            x2 = (x2 &gt;= COLNO) ? COLNO - 1 : x2;
&nbsp;            y2 = (y2 &gt;= ROWNO) ? ROWNO - 1 : y2;
&nbsp;            selection_do_randline(x1, y1, x2, y2, OV_i(tmp3), 12, pt);
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            opvar_free(tmp);
&nbsp;            opvar_free(tmp2);
&nbsp;            opvar_free(tmp3);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_GROW: {
&nbsp;            struct opvar *dirs, *pt;
&nbsp;
&nbsp;            if (!OV_pop_i(dirs))
&nbsp;                panic("no dirs for grow");
&nbsp;            if (!OV_pop_typ(pt, SPOVAR_SEL))
&nbsp;                panic("no selection for grow");
&nbsp;            selection_do_grow(pt, OV_i(dirs));
&nbsp;            splev_stack_push(coder-&gt;stack, pt);
&nbsp;            opvar_free(dirs);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_FLOOD: {
&nbsp;            struct opvar *tmp;
&nbsp;            schar x, y;
&nbsp;
&nbsp;            if (!OV_pop_c(tmp))
&nbsp;                panic("no ter sel flood coord");
&nbsp;            get_location_coord(&amp;x, &amp;y, ANY_LOC, coder-&gt;croom, OV_i(tmp));
&nbsp;            if (isok(x, y)) {
&nbsp;                struct opvar *pt = selection_opvar((char *) 0);
&nbsp;
&nbsp;                set_selection_floodfillchk(floodfillchk_match_under);
&nbsp;                floodfillchk_match_under_typ = levl[x][y].typ;
&nbsp;                selection_floodfill(pt, x, y, FALSE);
&nbsp;                splev_stack_push(coder-&gt;stack, pt);
&nbsp;            }
&nbsp;            opvar_free(tmp);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_RNDCOORD: {
&nbsp;            struct opvar *pt;
&nbsp;            schar x, y;
&nbsp;
&nbsp;            if (!OV_pop_typ(pt, SPOVAR_SEL))
&nbsp;                panic("no selection for rndcoord");
&nbsp;            if (selection_rndcoord(pt, &amp;x, &amp;y, FALSE)) {
&nbsp;                x -= xstart;
&nbsp;                y -= ystart;
&nbsp;            }
&nbsp;            splev_stack_push(coder-&gt;stack, opvar_new_coord(x, y));
&nbsp;            opvar_free(pt);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_ELLIPSE: {
&nbsp;            struct opvar *filled, *xaxis, *yaxis, *pt;
&nbsp;            struct opvar *sel = selection_opvar((char *) 0);
&nbsp;            schar x, y;
&nbsp;
&nbsp;            if (!OV_pop_i(filled))
&nbsp;                panic("no filled for ellipse");
&nbsp;            if (!OV_pop_i(yaxis))
&nbsp;                panic("no yaxis for ellipse");
&nbsp;            if (!OV_pop_i(xaxis))
&nbsp;                panic("no xaxis for ellipse");
&nbsp;            if (!OV_pop_c(pt))
&nbsp;                panic("no pt for ellipse");
&nbsp;            get_location_coord(&amp;x, &amp;y, ANY_LOC, coder-&gt;croom, OV_i(pt));
&nbsp;            selection_do_ellipse(sel, x, y, OV_i(xaxis), OV_i(yaxis),
&nbsp;                                 OV_i(filled));
&nbsp;            splev_stack_push(coder-&gt;stack, sel);
&nbsp;            opvar_free(filled);
&nbsp;            opvar_free(yaxis);
&nbsp;            opvar_free(xaxis);
&nbsp;            opvar_free(pt);
&nbsp;            break;
&nbsp;        }
&nbsp;        case SPO_SEL_GRADIENT: {
&nbsp;            struct opvar *gtyp, *glim, *mind, *maxd, *gcoord, *coord2;
&nbsp;            struct opvar *sel;
&nbsp;            schar x, y, x2, y2;
&nbsp;
&nbsp;            if (!OV_pop_i(gtyp))
&nbsp;                panic("no gtyp for grad");
&nbsp;            if (!OV_pop_i(glim))
&nbsp;                panic("no glim for grad");
&nbsp;            if (!OV_pop_c(coord2))
&nbsp;                panic("no coord2 for grad");
&nbsp;            if (!OV_pop_c(gcoord))
&nbsp;                panic("no coord for grad");
&nbsp;            if (!OV_pop_i(maxd))
&nbsp;                panic("no maxd for grad");
&nbsp;            if (!OV_pop_i(mind))
&nbsp;                panic("no mind for grad");
&nbsp;            get_location_coord(&amp;x, &amp;y, ANY_LOC, coder-&gt;croom, OV_i(gcoord));
&nbsp;            get_location_coord(&amp;x2, &amp;y2, ANY_LOC, coder-&gt;croom, OV_i(coord2));
&nbsp;
&nbsp;            sel = selection_opvar((char *) 0);
&nbsp;            selection_do_gradient(sel, x, y, x2, y2, OV_i(gtyp), OV_i(mind),
&nbsp;                                  OV_i(maxd), OV_i(glim));
&nbsp;            splev_stack_push(coder-&gt;stack, sel);
&nbsp;
&nbsp;            opvar_free(gtyp);
&nbsp;            opvar_free(glim);
&nbsp;            opvar_free(gcoord);
&nbsp;            opvar_free(coord2);
&nbsp;            opvar_free(maxd);
&nbsp;            opvar_free(mind);
&nbsp;            break;
&nbsp;        }
&nbsp;        default:
&nbsp;            panic("sp_level_coder: Unknown opcode %i", coder-&gt;opcode);
&nbsp;        }
&nbsp;
&nbsp;    next_opcode:
&nbsp;        coder-&gt;frame-&gt;n_opcode++;
&nbsp;    } /*while*/
&nbsp;
&nbsp;    link_doors_rooms();
&nbsp;    fill_rooms();
&nbsp;    remove_boundary_syms();
&nbsp;
&nbsp;    if (coder-&gt;check_inaccessibles)
&nbsp;        ensure_way_out();
&nbsp;    /* FIXME: Ideally, we want this call to only cover areas of the map
&nbsp;     * which were not inserted directly by the special level file (see
&nbsp;     * the insect legs on Baalzebub's level, for instance). Since that
&nbsp;     * is currently not possible, we overload the corrmaze flag for this
&nbsp;     * purpose.
&nbsp;     */
&nbsp;    if (!level.flags.corrmaze)
&nbsp;        wallification(1, 0, COLNO - 1, ROWNO - 1);
&nbsp;
&nbsp;    count_features();
&nbsp;
&nbsp;    if (coder-&gt;solidify)
&nbsp;        solidify_map();
&nbsp;
&nbsp;    /* This must be done before sokoban_detect(),
&nbsp;     * otherwise branch stairs won't be premapped. */
&nbsp;    fixup_special();
&nbsp;
&nbsp;    if (coder-&gt;premapped)
&nbsp;        sokoban_detect();
&nbsp;
&nbsp;    if (coder-&gt;frame) {
&nbsp;        struct sp_frame *tmpframe;
&nbsp;        do {
&nbsp;            tmpframe = coder-&gt;frame-&gt;next;
&nbsp;            frame_del(coder-&gt;frame);
&nbsp;            coder-&gt;frame = tmpframe;
&nbsp;        } while (coder-&gt;frame);
&nbsp;    }
&nbsp;    Free(coder);
&nbsp;
&nbsp;    return TRUE;
&nbsp;}
&nbsp;
load_special
&nbsp;/*
&nbsp; * General loader
&nbsp; */
&nbsp;boolean
&nbsp;load_special(name)
&nbsp;const char *name;
&nbsp;{
&nbsp;    dlb *fd;
&nbsp;    sp_lev *lvl = NULL;
&nbsp;    boolean result = FALSE;
&nbsp;    struct version_info vers_info;
&nbsp;
&nbsp;    fd = dlb_fopen(name, RDBMODE);
&nbsp;    if (!fd)
&nbsp;        return FALSE;
&nbsp;    Fread((genericptr_t) &amp;vers_info, sizeof vers_info, 1, fd);
&nbsp;    if (!check_version(&amp;vers_info, name, TRUE)) {
&nbsp;        (void) dlb_fclose(fd);
&nbsp;        goto give_up;
&nbsp;    }
&nbsp;
&nbsp;    lvl = (sp_lev *) alloc(sizeof (sp_lev));
&nbsp;    result = sp_level_loader(fd, lvl);
&nbsp;    (void) dlb_fclose(fd);
&nbsp;    if (result)
&nbsp;        result = sp_level_coder(lvl);
&nbsp;    sp_level_free(lvl);
&nbsp;    Free(lvl);
&nbsp;
&nbsp;give_up:
&nbsp;    return result;
&nbsp;}
&nbsp;
&nbsp;#ifdef _MSC_VER
&nbsp; #pragma warning(pop)
&nbsp;#endif
&nbsp;
&nbsp;/*sp_lev.c*/