Source:NetHack 3.6.0/src/sp lev.c

From NetHackWiki
Jump to: navigation, search

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

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.

Contents

Top of file

  1.  /* NetHack 3.6	sp_lev.c	$NHDT-Date: 1449269920 2015/12/04 22:58:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.77 $ */
  2.  /*      Copyright (c) 1989 by Jean-Christophe Collet */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  /*
  6.   * This file contains the various functions that are related to the special
  7.   * levels.
  8.   *
  9.   * It contains also the special level loader.
  10.   */
  11.  
  12.  #include "hack.h"
  13.  #include "dlb.h"
  14.  #include "sp_lev.h"
  15.  
  16.  #ifdef _MSC_VER
  17.   #pragma warning(push)
  18.   #pragma warning(disable : 4244)
  19.  #endif
  20.  
  21.  typedef void FDECL((*select_iter_func), (int, int, genericptr));
  22.  
  23.  extern void FDECL(mkmap, (lev_init *));
  24.  
  25.  STATIC_DCL void NDECL(solidify_map);
  26.  STATIC_DCL void FDECL(splev_stack_init, (struct splevstack *));
  27.  STATIC_DCL void FDECL(splev_stack_done, (struct splevstack *));
  28.  STATIC_DCL void FDECL(splev_stack_push, (struct splevstack *,
  29.                                           struct opvar *));
  30.  STATIC_DCL struct opvar *FDECL(splev_stack_pop, (struct splevstack *));
  31.  STATIC_DCL struct splevstack *FDECL(splev_stack_reverse,
  32.                                      (struct splevstack *));
  33.  STATIC_DCL struct opvar *FDECL(opvar_new_str, (char *));
  34.  STATIC_DCL struct opvar *FDECL(opvar_new_int, (long));
  35.  STATIC_DCL struct opvar *FDECL(opvar_new_coord, (int, int));
  36.  #if 0
  37.  STATIC_DCL struct opvar * FDECL(opvar_new_region, (int,int, int,int));
  38.  #endif /*0*/
  39.  STATIC_DCL void FDECL(opvar_free_x, (struct opvar *));
  40.  STATIC_DCL struct opvar *FDECL(opvar_clone, (struct opvar *));
  41.  STATIC_DCL struct opvar *FDECL(opvar_var_conversion, (struct sp_coder *,
  42.                                                        struct opvar *));
  43.  STATIC_DCL struct splev_var *FDECL(opvar_var_defined, (struct sp_coder *,
  44.                                                         char *));
  45.  STATIC_DCL struct opvar *FDECL(splev_stack_getdat, (struct sp_coder *,
  46.                                                      XCHAR_P));
  47.  STATIC_DCL struct opvar *FDECL(splev_stack_getdat_any, (struct sp_coder *));
  48.  STATIC_DCL void FDECL(variable_list_del, (struct splev_var *));
  49.  STATIC_DCL void FDECL(lvlfill_maze_grid, (int, int, int, int, SCHAR_P));
  50.  STATIC_DCL void FDECL(lvlfill_solid, (SCHAR_P, SCHAR_P));
  51.  STATIC_DCL void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
  52.                                            int));
  53.  STATIC_DCL void NDECL(shuffle_alignments);
  54.  STATIC_DCL void NDECL(count_features);
  55.  STATIC_DCL void NDECL(remove_boundary_syms);
  56.  STATIC_DCL void FDECL(maybe_add_door, (int, int, struct mkroom *));
  57.  STATIC_DCL void NDECL(link_doors_rooms);
  58.  STATIC_DCL void NDECL(fill_rooms);
  59.  STATIC_DCL int NDECL(rnddoor);
  60.  STATIC_DCL int NDECL(rndtrap);
  61.  STATIC_DCL void FDECL(get_location, (schar *, schar *, int, struct mkroom *));
  62.  STATIC_DCL boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
  63.  STATIC_DCL unpacked_coord FDECL(get_unpacked_coord, (long, int));
  64.  STATIC_DCL void FDECL(get_location_coord, (schar *, schar *, int,
  65.                                             struct mkroom *, long));
  66.  STATIC_DCL void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
  67.  STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *,
  68.                                            struct mkroom *, packed_coord));
  69.  STATIC_DCL boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
  70.                                            XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
  71.  STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
  72.  STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *));
  73.  STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P));
  74.  STATIC_DCL boolean FDECL(m_bad_boulder_spot, (int, int));
  75.  STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *));
  76.  STATIC_DCL void FDECL(create_object, (object *, struct mkroom *));
  77.  STATIC_DCL void FDECL(create_altar, (altar *, struct mkroom *));
  78.  STATIC_DCL void FDECL(replace_terrain, (replaceterrain *, struct mkroom *));
  79.  STATIC_DCL boolean FDECL(search_door, (struct mkroom *,
  80.                                         xchar *, xchar *, XCHAR_P, int));
  81.  STATIC_DCL void NDECL(fix_stair_rooms);
  82.  STATIC_DCL void FDECL(create_corridor, (corridor *));
  83.  STATIC_DCL struct mkroom *FDECL(build_room, (room *, struct mkroom *));
  84.  STATIC_DCL void FDECL(light_region, (region *));
  85.  STATIC_DCL void FDECL(wallify_map, (int, int, int, int));
  86.  STATIC_DCL void FDECL(maze1xy, (coord *, int));
  87.  STATIC_DCL void NDECL(fill_empty_maze);
  88.  STATIC_DCL boolean FDECL(sp_level_loader, (dlb *, sp_lev *));
  89.  STATIC_DCL boolean FDECL(sp_level_free, (sp_lev *));
  90.  STATIC_DCL void FDECL(splev_initlev, (lev_init *));
  91.  STATIC_DCL struct sp_frame *FDECL(frame_new, (long));
  92.  STATIC_DCL void FDECL(frame_del, (struct sp_frame *));
  93.  STATIC_DCL void FDECL(spo_frame_push, (struct sp_coder *));
  94.  STATIC_DCL void FDECL(spo_frame_pop, (struct sp_coder *));
  95.  STATIC_DCL long FDECL(sp_code_jmpaddr, (long, long));
  96.  STATIC_DCL void FDECL(spo_call, (struct sp_coder *));
  97.  STATIC_DCL void FDECL(spo_return, (struct sp_coder *));
  98.  STATIC_DCL void FDECL(spo_end_moninvent, (struct sp_coder *));
  99.  STATIC_DCL void FDECL(spo_pop_container, (struct sp_coder *));
  100.  STATIC_DCL void FDECL(spo_message, (struct sp_coder *));
  101.  STATIC_DCL void FDECL(spo_monster, (struct sp_coder *));
  102.  STATIC_DCL void FDECL(spo_object, (struct sp_coder *));
  103.  STATIC_DCL void FDECL(spo_level_flags, (struct sp_coder *));
  104.  STATIC_DCL void FDECL(spo_initlevel, (struct sp_coder *));
  105.  STATIC_DCL void FDECL(spo_engraving, (struct sp_coder *));
  106.  STATIC_DCL void FDECL(spo_mineralize, (struct sp_coder *));
  107.  STATIC_DCL void FDECL(spo_room, (struct sp_coder *));
  108.  STATIC_DCL void FDECL(spo_endroom, (struct sp_coder *));
  109.  STATIC_DCL void FDECL(spo_stair, (struct sp_coder *));
  110.  STATIC_DCL void FDECL(spo_ladder, (struct sp_coder *));
  111.  STATIC_DCL void FDECL(spo_grave, (struct sp_coder *));
  112.  STATIC_DCL void FDECL(spo_altar, (struct sp_coder *));
  113.  STATIC_DCL void FDECL(spo_trap, (struct sp_coder *));
  114.  STATIC_DCL void FDECL(spo_gold, (struct sp_coder *));
  115.  STATIC_DCL void FDECL(spo_corridor, (struct sp_coder *));
  116.  STATIC_DCL struct opvar *FDECL(selection_opvar, (char *));
  117.  STATIC_DCL xchar FDECL(selection_getpoint, (int, int, struct opvar *));
  118.  STATIC_DCL void FDECL(selection_setpoint, (int, int, struct opvar *, XCHAR_P));
  119.  STATIC_DCL struct opvar *FDECL(selection_not, (struct opvar *));
  120.  STATIC_DCL struct opvar *FDECL(selection_logical_oper, (struct opvar *,
  121.                                                       struct opvar *, CHAR_P));
  122.  STATIC_DCL struct opvar *FDECL(selection_filter_mapchar, (struct opvar *,
  123.                                                            struct opvar *));
  124.  STATIC_DCL void FDECL(selection_filter_percent, (struct opvar *, int));
  125.  STATIC_DCL int FDECL(selection_rndcoord, (struct opvar *, schar *, schar *,
  126.                                            BOOLEAN_P));
  127.  STATIC_DCL void FDECL(selection_do_grow, (struct opvar *, int));
  128.  STATIC_DCL void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int))));
  129.  STATIC_DCL int FDECL(floodfillchk_match_under, (int, int));
  130.  STATIC_DCL int FDECL(floodfillchk_match_accessible, (int, int));
  131.  STATIC_DCL void FDECL(selection_floodfill, (struct opvar *, int, int,
  132.                                              BOOLEAN_P));
  133.  STATIC_DCL void FDECL(selection_do_ellipse, (struct opvar *, int, int,
  134.                                               int, int, int));
  135.  STATIC_DCL long FDECL(line_dist_coord, (long, long, long, long, long, long));
  136.  STATIC_DCL void FDECL(selection_do_gradient, (struct opvar *, long, long, long,
  137.                                                long, long, long, long, long));
  138.  STATIC_DCL void FDECL(selection_do_line, (SCHAR_P, SCHAR_P, SCHAR_P, SCHAR_P,
  139.                                            struct opvar *));
  140.  STATIC_DCL void FDECL(selection_do_randline, (SCHAR_P, SCHAR_P, SCHAR_P,
  141.                                                SCHAR_P, SCHAR_P, SCHAR_P,
  142.                                                struct opvar *));
  143.  STATIC_DCL void FDECL(selection_iterate, (struct opvar *, select_iter_func,
  144.                                            genericptr_t));
  145.  STATIC_DCL void FDECL(sel_set_ter, (int, int, genericptr_t));
  146.  STATIC_DCL void FDECL(sel_set_feature, (int, int, genericptr_t));
  147.  STATIC_DCL void FDECL(sel_set_door, (int, int, genericptr_t));
  148.  STATIC_DCL void FDECL(spo_door, (struct sp_coder *));
  149.  STATIC_DCL void FDECL(spo_feature, (struct sp_coder *));
  150.  STATIC_DCL void FDECL(spo_terrain, (struct sp_coder *));
  151.  STATIC_DCL void FDECL(spo_replace_terrain, (struct sp_coder *));
  152.  STATIC_DCL boolean FDECL(generate_way_out_method, (int, int, struct opvar *));
  153.  STATIC_DCL void NDECL(ensure_way_out);
  154.  STATIC_DCL void FDECL(spo_levregion, (struct sp_coder *));
  155.  STATIC_DCL void FDECL(spo_region, (struct sp_coder *));
  156.  STATIC_DCL void FDECL(spo_drawbridge, (struct sp_coder *));
  157.  STATIC_DCL void FDECL(spo_mazewalk, (struct sp_coder *));
  158.  STATIC_DCL void FDECL(spo_wall_property, (struct sp_coder *));
  159.  STATIC_DCL void FDECL(spo_room_door, (struct sp_coder *));
  160.  STATIC_DCL void FDECL(sel_set_wallify, (int, int, genericptr_t));
  161.  STATIC_DCL void FDECL(spo_wallify, (struct sp_coder *));
  162.  STATIC_DCL void FDECL(spo_map, (struct sp_coder *));
  163.  STATIC_DCL void FDECL(spo_jmp, (struct sp_coder *, sp_lev *));
  164.  STATIC_DCL void FDECL(spo_conditional_jump, (struct sp_coder *, sp_lev *));
  165.  STATIC_DCL void FDECL(spo_var_init, (struct sp_coder *));
  166.  #if 0
  167.  STATIC_DCL long FDECL(opvar_array_length, (struct sp_coder *));
  168.  #endif /*0*/
  169.  STATIC_DCL void FDECL(spo_shuffle_array, (struct sp_coder *));
  170.  STATIC_DCL boolean FDECL(sp_level_coder, (sp_lev *));
  171.  
  172.  #define LEFT 1
  173.  #define H_LEFT 2
  174.  #define CENTER 3
  175.  #define H_RIGHT 4
  176.  #define RIGHT 5
  177.  
  178.  #define TOP 1
  179.  #define BOTTOM 5
  180.  
  181.  #define sq(x) ((x) * (x))
  182.  
  183.  #define XLIM 4
  184.  #define YLIM 3
  185.  
  186.  #define Fread (void) dlb_fread
  187.  #define Fgetc (schar) dlb_fgetc
  188.  #define New(type) (type *) alloc(sizeof(type))
  189.  #define NewTab(type, size) (type **) alloc(sizeof(type *) * (unsigned) size)
  190.  #define Free(ptr) if (ptr) free((genericptr_t) (ptr))
  191.  
  192.  extern struct engr *head_engr;
  193.  
  194.  extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
  195.  
  196.  /* positions touched by level elements explicitly defined in the des-file */
  197.  static char SpLev_Map[COLNO][ROWNO];
  198.  
  199.  static aligntyp ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
  200.  static NEARDATA xchar xstart, ystart;
  201.  static NEARDATA char xsize, ysize;
  202.  
  203.  char *lev_message = 0;
  204.  lev_region *lregions = 0;
  205.  int num_lregions = 0;
  206.  boolean splev_init_present = FALSE;
  207.  boolean icedpools = FALSE;
  208.  
  209.  struct obj *container_obj[MAX_CONTAINMENT];
  210.  int container_idx = 0;
  211.  
  212.  struct monst *invent_carrying_monster = NULL;
  213.  
  214.  #define SPLEV_STACK_RESERVE 128
  215.  

solidify_map

  1.  void
  2.  solidify_map()
  3.  {
  4.      xchar x, y;
  5.  
  6.      for (x = 0; x < COLNO; x++)
  7.          for (y = 0; y < ROWNO; y++)
  8.              if (IS_STWALL(levl[x][y].typ) && !SpLev_Map[x][y])
  9.                  levl[x][y].wall_info |= (W_NONDIGGABLE | W_NONPASSWALL);
  10.  }
  11.  

splev_stack_init

  1.  void
  2.  splev_stack_init(st)
  3.  struct splevstack *st;
  4.  {
  5.      if (st) {
  6.          st->depth = 0;
  7.          st->depth_alloc = SPLEV_STACK_RESERVE;
  8.          st->stackdata =
  9.              (struct opvar **) alloc(st->depth_alloc * sizeof(struct opvar *));
  10.      }
  11.  }
  12.  

splev_stack_done

  1.  void
  2.  splev_stack_done(st)
  3.  struct splevstack *st;
  4.  {
  5.      if (st) {
  6.          int i;
  7.  
  8.          if (st->stackdata && st->depth) {
  9.              for (i = 0; i < st->depth; i++) {
  10.                  switch (st->stackdata[i]->spovartyp) {
  11.                  default:
  12.                  case SPOVAR_NULL:
  13.                  case SPOVAR_COORD:
  14.                  case SPOVAR_REGION:
  15.                  case SPOVAR_MAPCHAR:
  16.                  case SPOVAR_MONST:
  17.                  case SPOVAR_OBJ:
  18.                  case SPOVAR_INT:
  19.                      break;
  20.                  case SPOVAR_VARIABLE:
  21.                  case SPOVAR_STRING:
  22.                  case SPOVAR_SEL:
  23.                      Free(st->stackdata[i]->vardata.str);
  24.                      st->stackdata[i]->vardata.str = NULL;
  25.                      break;
  26.                  }
  27.                  Free(st->stackdata[i]);
  28.                  st->stackdata[i] = NULL;
  29.              }
  30.          }
  31.          Free(st->stackdata);
  32.          st->stackdata = NULL;
  33.          st->depth = st->depth_alloc = 0;
  34.          Free(st);
  35.      }
  36.  }
  37.  

splev_stack_push

  1.  void
  2.  splev_stack_push(st, v)
  3.  struct splevstack *st;
  4.  struct opvar *v;
  5.  {
  6.      if (!st || !v)
  7.          return;
  8.      if (!st->stackdata)
  9.          panic("splev_stack_push: no stackdata allocated?");
  10.  
  11.      if (st->depth >= st->depth_alloc) {
  12.          struct opvar **tmp = (struct opvar **) alloc(
  13.              (st->depth_alloc + SPLEV_STACK_RESERVE) * sizeof(struct opvar *));
  14.  
  15.          (void) memcpy(tmp, st->stackdata,
  16.                        st->depth_alloc * sizeof(struct opvar *));
  17.          Free(st->stackdata);
  18.          st->stackdata = tmp;
  19.          st->depth_alloc += SPLEV_STACK_RESERVE;
  20.      }
  21.  
  22.      st->stackdata[st->depth] = v;
  23.      st->depth++;
  24.  }
  25.  

splev_stack_pop

  1.  struct opvar *
  2.  splev_stack_pop(st)
  3.  struct splevstack *st;
  4.  {
  5.      struct opvar *ret = NULL;
  6.  
  7.      if (!st)
  8.          return ret;
  9.      if (!st->stackdata)
  10.          panic("splev_stack_pop: no stackdata allocated?");
  11.  
  12.      if (st->depth) {
  13.          st->depth--;
  14.          ret = st->stackdata[st->depth];
  15.          st->stackdata[st->depth] = NULL;
  16.          return ret;
  17.      } else
  18.          impossible("splev_stack_pop: empty stack?");
  19.      return ret;
  20.  }
  21.  

splev_stack_reverse

  1.  struct splevstack *
  2.  splev_stack_reverse(st)
  3.  struct splevstack *st;
  4.  {
  5.      long i;
  6.      struct opvar *tmp;
  7.  
  8.      if (!st)
  9.          return NULL;
  10.      if (!st->stackdata)
  11.          panic("splev_stack_reverse: no stackdata allocated?");
  12.      for (i = 0; i < (st->depth / 2); i++) {
  13.          tmp = st->stackdata[i];
  14.          st->stackdata[i] = st->stackdata[st->depth - i - 1];
  15.          st->stackdata[st->depth - i - 1] = tmp;
  16.      }
  17.      return st;
  18.  }
  19.  


  1.  #define OV_typ(o) (o->spovartyp)
  2.  #define OV_i(o) (o->vardata.l)
  3.  #define OV_s(o) (o->vardata.str)
  4.  
  5.  #define OV_pop_i(x) (x = splev_stack_getdat(coder, SPOVAR_INT))
  6.  #define OV_pop_c(x) (x = splev_stack_getdat(coder, SPOVAR_COORD))
  7.  #define OV_pop_r(x) (x = splev_stack_getdat(coder, SPOVAR_REGION))
  8.  #define OV_pop_s(x) (x = splev_stack_getdat(coder, SPOVAR_STRING))
  9.  #define OV_pop(x) (x = splev_stack_getdat_any(coder))
  10.  #define OV_pop_typ(x, typ) (x = splev_stack_getdat(coder, typ))
  11.  

opvar_new_str

  1.  struct opvar *
  2.  opvar_new_str(s)
  3.  char *s;
  4.  {
  5.      struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
  6.  
  7.      tmpov->spovartyp = SPOVAR_STRING;
  8.      if (s) {
  9.          int len = strlen(s);
  10.          tmpov->vardata.str = (char *) alloc(len + 1);
  11.          (void) memcpy((genericptr_t) tmpov->vardata.str, (genericptr_t) s,
  12.                        len);
  13.          tmpov->vardata.str[len] = '\0';
  14.      } else
  15.          tmpov->vardata.str = NULL;
  16.      return tmpov;
  17.  }
  18.  

opvar_new_int

  1.  struct opvar *
  2.  opvar_new_int(i)
  3.  long i;
  4.  {
  5.      struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
  6.  
  7.      tmpov->spovartyp = SPOVAR_INT;
  8.      tmpov->vardata.l = i;
  9.      return tmpov;
  10.  }
  11.  

opvar_new_coord

  1.  struct opvar *
  2.  opvar_new_coord(x, y)
  3.  int x, y;
  4.  {
  5.      struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
  6.  
  7.      tmpov->spovartyp = SPOVAR_COORD;
  8.      tmpov->vardata.l = SP_COORD_PACK(x, y);
  9.      return tmpov;
  10.  }
  11.  

opvar_new_region

  1.  #if 0
  2.  struct opvar *
  3.  opvar_new_region(x1,y1,x2,y2)
  4.       int x1,y1,x2,y2;
  5.  {
  6.      struct opvar *tmpov = (struct opvar *)alloc(sizeof (struct opvar));
  7.  
  8.      tmpov->spovartyp = SPOVAR_REGION;
  9.      tmpov->vardata.l = SP_REGION_PACK(x1,y1,x2,y2);
  10.      return tmpov;
  11.  }
  12.  #endif /*0*/
  13.  

opvar_free_x

  1.  void
  2.  opvar_free_x(ov)
  3.  struct opvar *ov;
  4.  {
  5.      if (!ov)
  6.          return;
  7.      switch (ov->spovartyp) {
  8.      case SPOVAR_COORD:
  9.      case SPOVAR_REGION:
  10.      case SPOVAR_MAPCHAR:
  11.      case SPOVAR_MONST:
  12.      case SPOVAR_OBJ:
  13.      case SPOVAR_INT:
  14.          break;
  15.      case SPOVAR_VARIABLE:
  16.      case SPOVAR_STRING:
  17.      case SPOVAR_SEL:
  18.          Free(ov->vardata.str);
  19.          break;
  20.      default:
  21.          impossible("Unknown opvar value type (%i)!", ov->spovartyp);
  22.      }
  23.      Free(ov);
  24.  }
  25.  

opvar_clone

  1.  /*
  2.   * Name of current function for use in messages:
  3.   * __func__     -- C99 standard;
  4.   * __FUNCTION__ -- gcc extension, starting before C99 and continuing after;
  5.   *                 picked up by other compilers (or vice versa?);
  6.   * __FUNC__     -- supported by Borland;
  7.   * nhFunc       -- slightly intrusive but fully portable nethack construct
  8.   *                 for any version of any compiler.
  9.   */
  10.  #define opvar_free(ov)                                    \
  11.      do {                                                  \
  12.          if (ov) {                                         \
  13.              opvar_free_x(ov);                             \
  14.              ov = NULL;                                    \
  15.          } else                                            \
  16.              impossible("opvar_free(), %s", nhFunc);       \
  17.      } while (0)
  18.  
  19.  struct opvar *
  20.  opvar_clone(ov)
  21.  struct opvar *ov;
  22.  {
  23.      struct opvar *tmpov;
  24.  
  25.      if (!ov)
  26.          panic("no opvar to clone");
  27.      tmpov = (struct opvar *) alloc(sizeof(struct opvar));
  28.      tmpov->spovartyp = ov->spovartyp;
  29.      switch (ov->spovartyp) {
  30.      case SPOVAR_COORD:
  31.      case SPOVAR_REGION:
  32.      case SPOVAR_MAPCHAR:
  33.      case SPOVAR_MONST:
  34.      case SPOVAR_OBJ:
  35.      case SPOVAR_INT:
  36.          tmpov->vardata.l = ov->vardata.l;
  37.          break;
  38.      case SPOVAR_VARIABLE:
  39.      case SPOVAR_STRING:
  40.      case SPOVAR_SEL:
  41.          tmpov->vardata.str = dupstr(ov->vardata.str);
  42.          break;
  43.      default:
  44.          impossible("Unknown push value type (%i)!", ov->spovartyp);
  45.      }
  46.      return tmpov;
  47.  }
  48.  

opvar_var_conversion

  1.  struct opvar *
  2.  opvar_var_conversion(coder, ov)
  3.  struct sp_coder *coder;
  4.  struct opvar *ov;
  5.  {
  6.      static const char nhFunc[] = "opvar_var_conversion";
  7.      struct splev_var *tmp;
  8.      struct opvar *tmpov;
  9.      struct opvar *array_idx = NULL;
  10.  
  11.      if (!coder || !ov)
  12.          return NULL;
  13.      if (ov->spovartyp != SPOVAR_VARIABLE)
  14.          return ov;
  15.      tmp = coder->frame->variables;
  16.      while (tmp) {
  17.          if (!strcmp(tmp->name, OV_s(ov))) {
  18.              if ((tmp->svtyp & SPOVAR_ARRAY)) {
  19.                  array_idx = opvar_var_conversion(coder,
  20.                                                 splev_stack_pop(coder->stack));
  21.                  if (!array_idx || OV_typ(array_idx) != SPOVAR_INT)
  22.                      panic("array idx not an int");
  23.                  if (tmp->array_len < 1)
  24.                      panic("array len < 1");
  25.                  OV_i(array_idx) = (OV_i(array_idx) % tmp->array_len);
  26.                  tmpov = opvar_clone(tmp->data.arrayvalues[OV_i(array_idx)]);
  27.                  opvar_free(array_idx);
  28.                  return tmpov;
  29.              } else {
  30.                  tmpov = opvar_clone(tmp->data.value);
  31.                  return tmpov;
  32.              }
  33.          }
  34.          tmp = tmp->next;
  35.      }
  36.      return NULL;
  37.  }
  38.  

opvar_var_defined

  1.  struct splev_var *
  2.  opvar_var_defined(coder, name)
  3.  struct sp_coder *coder;
  4.  char *name;
  5.  {
  6.      struct splev_var *tmp;
  7.  
  8.      if (!coder)
  9.          return NULL;
  10.      tmp = coder->frame->variables;
  11.      while (tmp) {
  12.          if (!strcmp(tmp->name, name))
  13.              return tmp;
  14.          tmp = tmp->next;
  15.      }
  16.      return NULL;
  17.  }
  18.  

splev_stack_getdat

  1.  struct opvar *
  2.  splev_stack_getdat(coder, typ)
  3.  struct sp_coder *coder;
  4.  xchar typ;
  5.  {
  6.      static const char nhFunc[] = "splev_stack_getdat";
  7.      if (coder && coder->stack) {
  8.          struct opvar *tmp = splev_stack_pop(coder->stack);
  9.          struct opvar *ret = NULL;
  10.  
  11.          if (!tmp)
  12.              panic("no value type %i in stack.", typ);
  13.          if (tmp->spovartyp == SPOVAR_VARIABLE) {
  14.              ret = opvar_var_conversion(coder, tmp);
  15.              opvar_free(tmp);
  16.              tmp = ret;
  17.          }
  18.          if (tmp->spovartyp == typ)
  19.              return tmp;
  20.          else opvar_free(tmp);
  21.      }
  22.      return NULL;
  23.  }
  24.  

splev_stack_getdat_any

  1.  struct opvar *
  2.  splev_stack_getdat_any(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "splev_stack_getdat_any";
  6.      if (coder && coder->stack) {
  7.          struct opvar *tmp = splev_stack_pop(coder->stack);
  8.          if (tmp && tmp->spovartyp == SPOVAR_VARIABLE) {
  9.              struct opvar *ret = opvar_var_conversion(coder, tmp);
  10.              opvar_free(tmp);
  11.              return ret;
  12.          }
  13.          return tmp;
  14.      }
  15.      return NULL;
  16.  }
  17.  

variable_list_del

  1.  void
  2.  variable_list_del(varlist)
  3.  struct splev_var *varlist;
  4.  {
  5.      static const char nhFunc[] = "variable_list_del";
  6.      struct splev_var *tmp = varlist;
  7.  
  8.      if (!tmp)
  9.          return;
  10.      while (tmp) {
  11.          Free(tmp->name);
  12.          if ((tmp->svtyp & SPOVAR_ARRAY)) {
  13.              long idx = tmp->array_len;
  14.  
  15.              while (idx-- > 0) {
  16.                  opvar_free(tmp->data.arrayvalues[idx]);
  17.              };
  18.              Free(tmp->data.arrayvalues);
  19.          } else {
  20.              opvar_free(tmp->data.value);
  21.          }
  22.          tmp = varlist->next;
  23.          Free(varlist);
  24.          varlist = tmp;
  25.      }
  26.  }
  27.  

lvlfill_maze_grid

  1.  void
  2.  lvlfill_maze_grid(x1, y1, x2, y2, filling)
  3.  int x1, y1, x2, y2;
  4.  schar filling;
  5.  {
  6.      int x, y;
  7.  
  8.      for (x = x1; x <= x2; x++)
  9.          for (y = y1; y <= y2; y++) {
  10.              if (level.flags.corrmaze)
  11.                  levl[x][y].typ = STONE;
  12.              else
  13.                  levl[x][y].typ =
  14.                      (y < 2 || ((x % 2) && (y % 2))) ? STONE : filling;
  15.          }
  16.  }
  17.  

lvlfill_solid

  1.  void
  2.  lvlfill_solid(filling, lit)
  3.  schar filling;
  4.  schar lit;
  5.  {
  6.      int x, y;
  7.      for (x = 2; x <= x_maze_max; x++)
  8.          for (y = 0; y <= y_maze_max; y++) {
  9.              SET_TYPLIT(x, y, filling, lit);
  10.          }
  11.  }
  12.  

set_wall_property

  1.  /*
  2.   * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able
  3.   */
  4.  STATIC_OVL void
  5.  set_wall_property(x1, y1, x2, y2, prop)
  6.  xchar x1, y1, x2, y2;
  7.  int prop;
  8.  {
  9.      register xchar x, y;
  10.  
  11.      for (y = max(y1, 0); y <= min(y2, ROWNO - 1); y++)
  12.          for (x = max(x1, 0); x <= min(x2, COLNO - 1); x++)
  13.              if (IS_STWALL(levl[x][y].typ) || IS_TREE(levl[x][y].typ))
  14.                  levl[x][y].wall_info |= prop;
  15.  }
  16.  

shuffle_alignments

  1.  STATIC_OVL void
  2.  shuffle_alignments()
  3.  {
  4.      int i;
  5.      aligntyp atmp;
  6.  
  7.      /* shuffle 3 alignments */
  8.      i = rn2(3);
  9.      atmp = ralign[2];
  10.      ralign[2] = ralign[i];
  11.      ralign[i] = atmp;
  12.      if (rn2(2)) {
  13.          atmp = ralign[1];
  14.          ralign[1] = ralign[0];
  15.          ralign[0] = atmp;
  16.      }
  17.  }
  18.  

count_features

  1.  /*
  2.   * Count the different features (sinks, fountains) in the level.
  3.   */
  4.  STATIC_OVL void
  5.  count_features()
  6.  {
  7.      xchar x, y;
  8.  
  9.      level.flags.nfountains = level.flags.nsinks = 0;
  10.      for (y = 0; y < ROWNO; y++)
  11.          for (x = 0; x < COLNO; x++) {
  12.              int typ = levl[x][y].typ;
  13.              if (typ == FOUNTAIN)
  14.                  level.flags.nfountains++;
  15.              else if (typ == SINK)
  16.                  level.flags.nsinks++;
  17.          }
  18.  }
  19.  

remove_boundary_syms

  1.  void
  2.  remove_boundary_syms()
  3.  {
  4.      /*
  5.       * If any CROSSWALLs are found, must change to ROOM after REGION's
  6.       * are laid out.  CROSSWALLS are used to specify "invisible"
  7.       * boundaries where DOOR syms look bad or aren't desirable.
  8.       */
  9.      xchar x, y;
  10.      boolean has_bounds = FALSE;
  11.  
  12.      for (x = 0; x < COLNO - 1; x++)
  13.          for (y = 0; y < ROWNO - 1; y++)
  14.              if (levl[x][y].typ == CROSSWALL) {
  15.                  has_bounds = TRUE;
  16.                  break;
  17.              }
  18.      if (has_bounds) {
  19.          for (x = 0; x < x_maze_max; x++)
  20.              for (y = 0; y < y_maze_max; y++)
  21.                  if ((levl[x][y].typ == CROSSWALL) && SpLev_Map[x][y])
  22.                      levl[x][y].typ = ROOM;
  23.      }
  24.  }
  25.  

maybe_add_door

  1.  void
  2.  maybe_add_door(x, y, droom)
  3.  int x, y;
  4.  struct mkroom *droom;
  5.  {
  6.      if (droom->hx >= 0 && doorindex < DOORMAX && inside_room(droom, x, y))
  7.          add_door(x, y, droom);
  8.  }
  9.  

link_doors_rooms

  1.  void
  2.  link_doors_rooms()
  3.  {
  4.      int x, y;
  5.      int tmpi, m;
  6.  
  7.      for (y = 0; y < ROWNO; y++)
  8.          for (x = 0; x < COLNO; x++)
  9.              if (IS_DOOR(levl[x][y].typ) || levl[x][y].typ == SDOOR) {
  10.                  for (tmpi = 0; tmpi < nroom; tmpi++) {
  11.                      maybe_add_door(x, y, &rooms[tmpi]);
  12.                      for (m = 0; m < rooms[tmpi].nsubrooms; m++) {
  13.                          maybe_add_door(x, y, rooms[tmpi].sbrooms[m]);
  14.                      }
  15.                  }
  16.              }
  17.  }
  18.  

fill_rooms

  1.  void
  2.  fill_rooms()
  3.  {
  4.      int tmpi;
  5.  
  6.      for (tmpi = 0; tmpi < nroom; tmpi++) {
  7.          int m;
  8.          if (rooms[tmpi].needfill)
  9.              fill_room(&rooms[tmpi], (rooms[tmpi].needfill == 2));
  10.          for (m = 0; m < rooms[tmpi].nsubrooms; m++)
  11.              if (rooms[tmpi].sbrooms[m]->needfill)
  12.                  fill_room(rooms[tmpi].sbrooms[m], FALSE);
  13.      }
  14.  }
  15.  

rnddoor

  1.  /*
  2.   * Choose randomly the state (nodoor, open, closed or locked) for a door
  3.   */
  4.  STATIC_OVL int
  5.  rnddoor()
  6.  {
  7.      int i = 1 << rn2(5);
  8.  
  9.      i >>= 1;
  10.      return i;
  11.  }
  12.  

rndtrap

  1.  /*
  2.   * Select a random trap
  3.   */
  4.  STATIC_OVL int
  5.  rndtrap()
  6.  {
  7.      int rtrap;
  8.  
  9.      do {
  10.          rtrap = rnd(TRAPNUM - 1);
  11.          switch (rtrap) {
  12.          case HOLE: /* no random holes on special levels */
  13.          case VIBRATING_SQUARE:
  14.          case MAGIC_PORTAL:
  15.              rtrap = NO_TRAP;
  16.              break;
  17.          case TRAPDOOR:
  18.              if (!Can_dig_down(&u.uz))
  19.                  rtrap = NO_TRAP;
  20.              break;
  21.          case LEVEL_TELEP:
  22.          case TELEP_TRAP:
  23.              if (level.flags.noteleport)
  24.                  rtrap = NO_TRAP;
  25.              break;
  26.          case ROLLING_BOULDER_TRAP:
  27.          case ROCKTRAP:
  28.              if (In_endgame(&u.uz))
  29.                  rtrap = NO_TRAP;
  30.              break;
  31.          }
  32.      } while (rtrap == NO_TRAP);
  33.      return rtrap;
  34.  }
  35.  

get_location

  1.  /*
  2.   * Coordinates in special level files are handled specially:
  3.   *
  4.   *      if x or y is < 0, we generate a random coordinate.
  5.   *      The "humidity" flag is used to insure that engravings aren't
  6.   *      created underwater, or eels on dry land.
  7.   */
  8.  STATIC_OVL void
  9.  get_location(x, y, humidity, croom)
  10.  schar *x, *y;
  11.  int humidity;
  12.  struct mkroom *croom;
  13.  {
  14.      int cpt = 0;
  15.      int mx, my, sx, sy;
  16.  
  17.      if (croom) {
  18.          mx = croom->lx;
  19.          my = croom->ly;
  20.          sx = croom->hx - mx + 1;
  21.          sy = croom->hy - my + 1;
  22.      } else {
  23.          mx = xstart;
  24.          my = ystart;
  25.          sx = xsize;
  26.          sy = ysize;
  27.      }
  28.  
  29.      if (*x >= 0) { /* normal locations */
  30.          *x += mx;
  31.          *y += my;
  32.      } else { /* random location */
  33.          do {
  34.              if (croom) { /* handle irregular areas */
  35.                  coord tmpc;
  36.                  somexy(croom, &tmpc);
  37.                  *x = tmpc.x;
  38.                  *y = tmpc.y;
  39.              } else {
  40.                  *x = mx + rn2((int) sx);
  41.                  *y = my + rn2((int) sy);
  42.              }
  43.              if (is_ok_location(*x, *y, humidity))
  44.                  break;
  45.          } while (++cpt < 100);
  46.          if (cpt >= 100) {
  47.              register int xx, yy;
  48.  
  49.              /* last try */
  50.              for (xx = 0; xx < sx; xx++)
  51.                  for (yy = 0; yy < sy; yy++) {
  52.                      *x = mx + xx;
  53.                      *y = my + yy;
  54.                      if (is_ok_location(*x, *y, humidity))
  55.                          goto found_it;
  56.                  }
  57.              if (!(humidity & NO_LOC_WARN)) {
  58.                  impossible("get_location:  can't find a place!");
  59.              } else {
  60.                  *x = *y = -1;
  61.              }
  62.          }
  63.      }
  64.  found_it:
  65.      ;
  66.  
  67.      if (!(humidity & ANY_LOC) && !isok(*x, *y)) {
  68.          if (!(humidity & NO_LOC_WARN)) {
  69.              /*warning("get_location:  (%d,%d) out of bounds", *x, *y);*/
  70.              *x = x_maze_max;
  71.              *y = y_maze_max;
  72.          } else {
  73.              *x = *y = -1;
  74.          }
  75.      }
  76.  }
  77.  

is_ok_location

  1.  STATIC_OVL boolean
  2.  is_ok_location(x, y, humidity)
  3.  register schar x, y;
  4.  register int humidity;
  5.  {
  6.      register int typ;
  7.  
  8.      if (Is_waterlevel(&u.uz))
  9.          return TRUE; /* accept any spot */
  10.  
  11.      /* TODO: Should perhaps check if wall is diggable/passwall? */
  12.      if (humidity & ANY_LOC)
  13.          return TRUE;
  14.  
  15.      if ((humidity & SOLID) && IS_ROCK(levl[x][y].typ))
  16.          return TRUE;
  17.  
  18.      if (humidity & DRY) {
  19.          typ = levl[x][y].typ;
  20.          if (typ == ROOM || typ == AIR || typ == CLOUD || typ == ICE
  21.              || typ == CORR)
  22.              return TRUE;
  23.      }
  24.      if ((humidity & WET) && is_pool(x, y))
  25.          return TRUE;
  26.      if ((humidity & HOT) && is_lava(x, y))
  27.          return TRUE;
  28.      return FALSE;
  29.  }
  30.  

get_unpacked_coord

  1.  unpacked_coord
  2.  get_unpacked_coord(loc, defhumidity)
  3.  long loc;
  4.  int defhumidity;
  5.  {
  6.      static unpacked_coord c;
  7.  
  8.      if (loc & SP_COORD_IS_RANDOM) {
  9.          c.x = c.y = -1;
  10.          c.is_random = 1;
  11.          c.getloc_flags = (loc & ~SP_COORD_IS_RANDOM);
  12.          if (!c.getloc_flags)
  13.              c.getloc_flags = defhumidity;
  14.      } else {
  15.          c.is_random = 0;
  16.          c.getloc_flags = defhumidity;
  17.          c.x = SP_COORD_X(loc);
  18.          c.y = SP_COORD_Y(loc);
  19.      }
  20.      return c;
  21.  }
  22.  

get_location_coord

  1.  STATIC_OVL void
  2.  get_location_coord(x, y, humidity, croom, crd)
  3.  schar *x, *y;
  4.  int humidity;
  5.  struct mkroom *croom;
  6.  long crd;
  7.  {
  8.      unpacked_coord c;
  9.  
  10.      c = get_unpacked_coord(crd, humidity);
  11.      *x = c.x;
  12.      *y = c.y;
  13.      get_location(x, y, c.getloc_flags | (c.is_random ? NO_LOC_WARN : 0),
  14.                   croom);
  15.      if (*x == -1 && *y == -1 && c.is_random)
  16.          get_location(x, y, humidity, croom);
  17.  }
  18.  

get_room_loc

  1.  /*
  2.   * Get a relative position inside a room.
  3.   * negative values for x or y means RANDOM!
  4.   */
  5.  
  6.  STATIC_OVL void
  7.  get_room_loc(x, y, croom)
  8.  schar *x, *y;
  9.  struct mkroom *croom;
  10.  {
  11.      coord c;
  12.  
  13.      if (*x < 0 && *y < 0) {
  14.          if (somexy(croom, &c)) {
  15.              *x = c.x;
  16.              *y = c.y;
  17.          } else
  18.              panic("get_room_loc : can't find a place!");
  19.      } else {
  20.          if (*x < 0)
  21.              *x = rn2(croom->hx - croom->lx + 1);
  22.          if (*y < 0)
  23.              *y = rn2(croom->hy - croom->ly + 1);
  24.          *x += croom->lx;
  25.          *y += croom->ly;
  26.      }
  27.  }
  28.  

get_free_room_loc

  1.  /*
  2.   * Get a relative position inside a room.
  3.   * negative values for x or y means RANDOM!
  4.   */
  5.  STATIC_OVL void
  6.  get_free_room_loc(x, y, croom, pos)
  7.  schar *x, *y;
  8.  struct mkroom *croom;
  9.  packed_coord pos;
  10.  {
  11.      schar try_x, try_y;
  12.      register int trycnt = 0;
  13.  
  14.      get_location_coord(&try_x, &try_y, DRY, croom, pos);
  15.      if (levl[try_x][try_y].typ != ROOM) {
  16.          do {
  17.              try_x = *x, try_y = *y;
  18.              get_room_loc(&try_x, &try_y, croom);
  19.          } while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100);
  20.  
  21.          if (trycnt > 100)
  22.              panic("get_free_room_loc:  can't find a place!");
  23.      }
  24.      *x = try_x, *y = try_y;
  25.  }
  26.  

check_room

  1.  boolean
  2.  check_room(lowx, ddx, lowy, ddy, vault)
  3.  xchar *lowx, *ddx, *lowy, *ddy;
  4.  boolean vault;
  5.  {
  6.      register int x, y, hix = *lowx + *ddx, hiy = *lowy + *ddy;
  7.      register struct rm *lev;
  8.      int xlim, ylim, ymax;
  9.  
  10.      xlim = XLIM + (vault ? 1 : 0);
  11.      ylim = YLIM + (vault ? 1 : 0);
  12.  
  13.      if (*lowx < 3)
  14.          *lowx = 3;
  15.      if (*lowy < 2)
  16.          *lowy = 2;
  17.      if (hix > COLNO - 3)
  18.          hix = COLNO - 3;
  19.      if (hiy > ROWNO - 3)
  20.          hiy = ROWNO - 3;
  21.  chk:
  22.      if (hix <= *lowx || hiy <= *lowy)
  23.          return FALSE;
  24.  
  25.      /* check area around room (and make room smaller if necessary) */
  26.      for (x = *lowx - xlim; x <= hix + xlim; x++) {
  27.          if (x <= 0 || x >= COLNO)
  28.              continue;
  29.          y = *lowy - ylim;
  30.          ymax = hiy + ylim;
  31.          if (y < 0)
  32.              y = 0;
  33.          if (ymax >= ROWNO)
  34.              ymax = (ROWNO - 1);
  35.          lev = &levl[x][y];
  36.          for (; y <= ymax; y++) {
  37.              if (lev++->typ) {
  38.                  if (!vault) {
  39.                      debugpline2("strange area [%d,%d] in check_room.", x, y);
  40.                  }
  41.                  if (!rn2(3))
  42.                      return FALSE;
  43.                  if (x < *lowx)
  44.                      *lowx = x + xlim + 1;
  45.                  else
  46.                      hix = x - xlim - 1;
  47.                  if (y < *lowy)
  48.                      *lowy = y + ylim + 1;
  49.                  else
  50.                      hiy = y - ylim - 1;
  51.                  goto chk;
  52.              }
  53.          }
  54.      }
  55.      *ddx = hix - *lowx;
  56.      *ddy = hiy - *lowy;
  57.      return TRUE;
  58.  }
  59.  

create_room

  1.  /*
  2.   * Create a new room.
  3.   * This is still very incomplete...
  4.   */
  5.  boolean
  6.  create_room(x, y, w, h, xal, yal, rtype, rlit)
  7.  xchar x, y;
  8.  xchar w, h;
  9.  xchar xal, yal;
  10.  xchar rtype, rlit;
  11.  {
  12.      xchar xabs, yabs;
  13.      int wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
  14.      NhRect *r1 = 0, r2;
  15.      int trycnt = 0;
  16.      boolean vault = FALSE;
  17.      int xlim = XLIM, ylim = YLIM;
  18.  
  19.      if (rtype == -1) /* Is the type random ? */
  20.          rtype = OROOM;
  21.  
  22.      if (rtype == VAULT) {
  23.          vault = TRUE;
  24.          xlim++;
  25.          ylim++;
  26.      }
  27.  
  28.      /* on low levels the room is lit (usually) */
  29.      /* some other rooms may require lighting */
  30.  
  31.      /* is light state random ? */
  32.      if (rlit == -1)
  33.          rlit = (rnd(1 + abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  34.  
  35.      /*
  36.       * Here we will try to create a room. If some parameters are
  37.       * random we are willing to make several try before we give
  38.       * it up.
  39.       */
  40.      do {
  41.          xchar xborder, yborder;
  42.          wtmp = w;
  43.          htmp = h;
  44.          xtmp = x;
  45.          ytmp = y;
  46.          xaltmp = xal;
  47.          yaltmp = yal;
  48.  
  49.          /* First case : a totally random room */
  50.  
  51.          if ((xtmp < 0 && ytmp < 0 && wtmp < 0 && xaltmp < 0 && yaltmp < 0)
  52.              || vault) {
  53.              xchar hx, hy, lx, ly, dx, dy;
  54.              r1 = rnd_rect(); /* Get a random rectangle */
  55.  
  56.              if (!r1) { /* No more free rectangles ! */
  57.                  debugpline0("No more rects...");
  58.                  return FALSE;
  59.              }
  60.              hx = r1->hx;
  61.              hy = r1->hy;
  62.              lx = r1->lx;
  63.              ly = r1->ly;
  64.              if (vault)
  65.                  dx = dy = 1;
  66.              else {
  67.                  dx = 2 + rn2((hx - lx > 28) ? 12 : 8);
  68.                  dy = 2 + rn2(4);
  69.                  if (dx * dy > 50)
  70.                      dy = 50 / dx;
  71.              }
  72.              xborder = (lx > 0 && hx < COLNO - 1) ? 2 * xlim : xlim + 1;
  73.              yborder = (ly > 0 && hy < ROWNO - 1) ? 2 * ylim : ylim + 1;
  74.              if (hx - lx < dx + 3 + xborder || hy - ly < dy + 3 + yborder) {
  75.                  r1 = 0;
  76.                  continue;
  77.              }
  78.              xabs = lx + (lx > 0 ? xlim : 3)
  79.                     + rn2(hx - (lx > 0 ? lx : 3) - dx - xborder + 1);
  80.              yabs = ly + (ly > 0 ? ylim : 2)
  81.                     + rn2(hy - (ly > 0 ? ly : 2) - dy - yborder + 1);
  82.              if (ly == 0 && hy >= (ROWNO - 1) && (!nroom || !rn2(nroom))
  83.                  && (yabs + dy > ROWNO / 2)) {
  84.                  yabs = rn1(3, 2);
  85.                  if (nroom < 4 && dy > 1)
  86.                      dy--;
  87.              }
  88.              if (!check_room(&xabs, &dx, &yabs, &dy, vault)) {
  89.                  r1 = 0;
  90.                  continue;
  91.              }
  92.              wtmp = dx + 1;
  93.              htmp = dy + 1;
  94.              r2.lx = xabs - 1;
  95.              r2.ly = yabs - 1;
  96.              r2.hx = xabs + wtmp;
  97.              r2.hy = yabs + htmp;
  98.          } else { /* Only some parameters are random */
  99.              int rndpos = 0;
  100.              if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
  101.                  xtmp = rnd(5);
  102.                  ytmp = rnd(5);
  103.                  rndpos = 1;
  104.              }
  105.              if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */
  106.                  wtmp = rn1(15, 3);
  107.                  htmp = rn1(8, 2);
  108.              }
  109.              if (xaltmp == -1) /* Horizontal alignment is RANDOM */
  110.                  xaltmp = rnd(3);
  111.              if (yaltmp == -1) /* Vertical alignment is RANDOM */
  112.                  yaltmp = rnd(3);
  113.  
  114.              /* Try to generate real (absolute) coordinates here! */
  115.  
  116.              xabs = (((xtmp - 1) * COLNO) / 5) + 1;
  117.              yabs = (((ytmp - 1) * ROWNO) / 5) + 1;
  118.              switch (xaltmp) {
  119.              case LEFT:
  120.                  break;
  121.              case RIGHT:
  122.                  xabs += (COLNO / 5) - wtmp;
  123.                  break;
  124.              case CENTER:
  125.                  xabs += ((COLNO / 5) - wtmp) / 2;
  126.                  break;
  127.              }
  128.              switch (yaltmp) {
  129.              case TOP:
  130.                  break;
  131.              case BOTTOM:
  132.                  yabs += (ROWNO / 5) - htmp;
  133.                  break;
  134.              case CENTER:
  135.                  yabs += ((ROWNO / 5) - htmp) / 2;
  136.                  break;
  137.              }
  138.  
  139.              if (xabs + wtmp - 1 > COLNO - 2)
  140.                  xabs = COLNO - wtmp - 3;
  141.              if (xabs < 2)
  142.                  xabs = 2;
  143.              if (yabs + htmp - 1 > ROWNO - 2)
  144.                  yabs = ROWNO - htmp - 3;
  145.              if (yabs < 2)
  146.                  yabs = 2;
  147.  
  148.              /* Try to find a rectangle that fit our room ! */
  149.  
  150.              r2.lx = xabs - 1;
  151.              r2.ly = yabs - 1;
  152.              r2.hx = xabs + wtmp + rndpos;
  153.              r2.hy = yabs + htmp + rndpos;
  154.              r1 = get_rect(&r2);
  155.          }
  156.      } while (++trycnt <= 100 && !r1);
  157.      if (!r1) { /* creation of room failed ? */
  158.          return FALSE;
  159.      }
  160.      split_rects(r1, &r2);
  161.  
  162.      if (!vault) {
  163.          smeq[nroom] = nroom;
  164.          add_room(xabs, yabs, xabs + wtmp - 1, yabs + htmp - 1, rlit, rtype,
  165.                   FALSE);
  166.      } else {
  167.          rooms[nroom].lx = xabs;
  168.          rooms[nroom].ly = yabs;
  169.      }
  170.      return TRUE;
  171.  }
  172.  

create_subroom

  1.  /*
  2.   * Create a subroom in room proom at pos x,y with width w & height h.
  3.   * x & y are relative to the parent room.
  4.   */
  5.  STATIC_OVL boolean
  6.  create_subroom(proom, x, y, w, h, rtype, rlit)
  7.  struct mkroom *proom;
  8.  xchar x, y;
  9.  xchar w, h;
  10.  xchar rtype, rlit;
  11.  {
  12.      xchar width, height;
  13.  
  14.      width = proom->hx - proom->lx + 1;
  15.      height = proom->hy - proom->ly + 1;
  16.  
  17.      /* There is a minimum size for the parent room */
  18.      if (width < 4 || height < 4)
  19.          return FALSE;
  20.  
  21.      /* Check for random position, size, etc... */
  22.  
  23.      if (w == -1)
  24.          w = rnd(width - 3);
  25.      if (h == -1)
  26.          h = rnd(height - 3);
  27.      if (x == -1)
  28.          x = rnd(width - w - 1) - 1;
  29.      if (y == -1)
  30.          y = rnd(height - h - 1) - 1;
  31.      if (x == 1)
  32.          x = 0;
  33.      if (y == 1)
  34.          y = 0;
  35.      if ((x + w + 1) == width)
  36.          x++;
  37.      if ((y + h + 1) == height)
  38.          y++;
  39.      if (rtype == -1)
  40.          rtype = OROOM;
  41.      if (rlit == -1)
  42.          rlit = (rnd(1 + abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  43.      add_subroom(proom, proom->lx + x, proom->ly + y, proom->lx + x + w - 1,
  44.                  proom->ly + y + h - 1, rlit, rtype, FALSE);
  45.      return TRUE;
  46.  }
  47.  

create_door

  1.  /*
  2.   * Create a new door in a room.
  3.   * It's placed on a wall (north, south, east or west).
  4.   */
  5.  STATIC_OVL void
  6.  create_door(dd, broom)
  7.  room_door *dd;
  8.  struct mkroom *broom;
  9.  {
  10.      int x = 0, y = 0;
  11.      int trycnt = 0, wtry = 0;
  12.  
  13.      if (dd->secret == -1)
  14.          dd->secret = rn2(2);
  15.  
  16.      if (dd->mask == -1) {
  17.          /* is it a locked door, closed, or a doorway? */
  18.          if (!dd->secret) {
  19.              if (!rn2(3)) {
  20.                  if (!rn2(5))
  21.                      dd->mask = D_ISOPEN;
  22.                  else if (!rn2(6))
  23.                      dd->mask = D_LOCKED;
  24.                  else
  25.                      dd->mask = D_CLOSED;
  26.                  if (dd->mask != D_ISOPEN && !rn2(25))
  27.                      dd->mask |= D_TRAPPED;
  28.              } else
  29.                  dd->mask = D_NODOOR;
  30.          } else {
  31.              if (!rn2(5))
  32.                  dd->mask = D_LOCKED;
  33.              else
  34.                  dd->mask = D_CLOSED;
  35.  
  36.              if (!rn2(20))
  37.                  dd->mask |= D_TRAPPED;
  38.          }
  39.      }
  40.  
  41.      do {
  42.          register int dwall, dpos;
  43.  
  44.          dwall = dd->wall;
  45.          if (dwall == -1) /* The wall is RANDOM */
  46.              dwall = 1 << rn2(4);
  47.  
  48.          dpos = dd->pos;
  49.  
  50.          /* Convert wall and pos into an absolute coordinate! */
  51.          wtry = rn2(4);
  52.          switch (wtry) {
  53.          case 0:
  54.              if (!(dwall & W_NORTH))
  55.                  goto redoloop;
  56.              y = broom->ly - 1;
  57.              x = broom->lx
  58.                  + ((dpos == -1) ? rn2(1 + (broom->hx - broom->lx)) : dpos);
  59.              if (IS_ROCK(levl[x][y - 1].typ))
  60.                  goto redoloop;
  61.              goto outdirloop;
  62.          case 1:
  63.              if (!(dwall & W_SOUTH))
  64.                  goto redoloop;
  65.              y = broom->hy + 1;
  66.              x = broom->lx
  67.                  + ((dpos == -1) ? rn2(1 + (broom->hx - broom->lx)) : dpos);
  68.              if (IS_ROCK(levl[x][y + 1].typ))
  69.                  goto redoloop;
  70.              goto outdirloop;
  71.          case 2:
  72.              if (!(dwall & W_WEST))
  73.                  goto redoloop;
  74.              x = broom->lx - 1;
  75.              y = broom->ly
  76.                  + ((dpos == -1) ? rn2(1 + (broom->hy - broom->ly)) : dpos);
  77.              if (IS_ROCK(levl[x - 1][y].typ))
  78.                  goto redoloop;
  79.              goto outdirloop;
  80.          case 3:
  81.              if (!(dwall & W_EAST))
  82.                  goto redoloop;
  83.              x = broom->hx + 1;
  84.              y = broom->ly
  85.                  + ((dpos == -1) ? rn2(1 + (broom->hy - broom->ly)) : dpos);
  86.              if (IS_ROCK(levl[x + 1][y].typ))
  87.                  goto redoloop;
  88.              goto outdirloop;
  89.          default:
  90.              x = y = 0;
  91.              panic("create_door: No wall for door!");
  92.              goto outdirloop;
  93.          }
  94.      outdirloop:
  95.          if (okdoor(x, y))
  96.              break;
  97.      redoloop:
  98.          ;
  99.      } while (++trycnt <= 100);
  100.      if (trycnt > 100) {
  101.          impossible("create_door: Can't find a proper place!");
  102.          return;
  103.      }
  104.      levl[x][y].typ = (dd->secret ? SDOOR : DOOR);
  105.      levl[x][y].doormask = dd->mask;
  106.  }
  107.  

create_secret_door

  1.  /*
  2.   * Create a secret door in croom on any one of the specified walls.
  3.   */
  4.  void
  5.  create_secret_door(croom, walls)
  6.  struct mkroom *croom;
  7.  xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
  8.  {
  9.      xchar sx, sy; /* location of the secret door */
  10.      int count;
  11.  
  12.      for (count = 0; count < 100; count++) {
  13.          sx = rn1(croom->hx - croom->lx + 1, croom->lx);
  14.          sy = rn1(croom->hy - croom->ly + 1, croom->ly);
  15.  
  16.          switch (rn2(4)) {
  17.          case 0: /* top */
  18.              if (!(walls & W_NORTH))
  19.                  continue;
  20.              sy = croom->ly - 1;
  21.              break;
  22.          case 1: /* bottom */
  23.              if (!(walls & W_SOUTH))
  24.                  continue;
  25.              sy = croom->hy + 1;
  26.              break;
  27.          case 2: /* left */
  28.              if (!(walls & W_EAST))
  29.                  continue;
  30.              sx = croom->lx - 1;
  31.              break;
  32.          case 3: /* right */
  33.              if (!(walls & W_WEST))
  34.                  continue;
  35.              sx = croom->hx + 1;
  36.              break;
  37.          }
  38.  
  39.          if (okdoor(sx, sy)) {
  40.              levl[sx][sy].typ = SDOOR;
  41.              levl[sx][sy].doormask = D_CLOSED;
  42.              return;
  43.          }
  44.      }
  45.  
  46.      impossible("couldn't create secret door on any walls 0x%x", walls);
  47.  }
  48.  

create_trap

  1.  /*
  2.   * Create a trap in a room.
  3.   */
  4.  STATIC_OVL void
  5.  create_trap(t, croom)
  6.  trap *t;
  7.  struct mkroom *croom;
  8.  {
  9.      schar x, y;
  10.      coord tm;
  11.  
  12.      if (croom)
  13.          get_free_room_loc(&x, &y, croom, t->coord);
  14.      else {
  15.          int trycnt = 0;
  16.          do {
  17.              get_location_coord(&x, &y, DRY, croom, t->coord);
  18.          } while ((levl[x][y].typ == STAIRS || levl[x][y].typ == LADDER)
  19.                   && ++trycnt <= 100);
  20.          if (trycnt > 100)
  21.              return;
  22.      }
  23.  
  24.      tm.x = x;
  25.      tm.y = y;
  26.  
  27.      mktrap(t->type, 1, (struct mkroom *) 0, &tm);
  28.  }
  29.  

noncoalignment

  1.  /*
  2.   * Create a monster in a room.
  3.   */
  4.  STATIC_OVL int
  5.  noncoalignment(alignment)
  6.  aligntyp alignment;
  7.  {
  8.      int k;
  9.  
  10.      k = rn2(2);
  11.      if (!alignment)
  12.          return (k ? -1 : 1);
  13.      return (k ? -alignment : 0);
  14.  }
  15.  

m_bad_boulder_spot

  1.  /* attempt to screen out locations where a mimic-as-boulder shouldn't occur */
  2.  STATIC_OVL boolean
  3.  m_bad_boulder_spot(x, y)
  4.  int x, y;
  5.  {
  6.      struct rm *lev;
  7.  
  8.      /* avoid trap locations */
  9.      if (t_at(x, y))
  10.          return TRUE;
  11.      /* try to avoid locations which already have a boulder (this won't
  12.         actually work; we get called before objects have been placed...) */
  13.      if (sobj_at(BOULDER, x, y))
  14.          return TRUE;
  15.      /* avoid closed doors */
  16.      lev = &levl[x][y];
  17.      if (IS_DOOR(lev->typ) && (lev->doormask & (D_CLOSED | D_LOCKED)) != 0)
  18.          return TRUE;
  19.      /* spot is ok */
  20.      return FALSE;
  21.  }
  22.  

create_monster

  1.  STATIC_OVL void
  2.  create_monster(m, croom)
  3.  monster *m;
  4.  struct mkroom *croom;
  5.  {
  6.      struct monst *mtmp;
  7.      schar x, y;
  8.      char class;
  9.      aligntyp amask;
  10.      coord cc;
  11.      struct permonst *pm;
  12.      unsigned g_mvflags;
  13.  
  14.      if (m->class >= 0)
  15.          class = (char) def_char_to_monclass((char) m->class);
  16.      else
  17.          class = 0;
  18.  
  19.      if (class == MAXMCLASSES)
  20.          panic("create_monster: unknown monster class '%c'", m->class);
  21.  
  22.      amask = (m->align == AM_SPLEV_CO)
  23.                 ? Align2amask(u.ualignbase[A_ORIGINAL])
  24.                 : (m->align == AM_SPLEV_NONCO)
  25.                    ? Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL]))
  26.                    : (m->align <= -(MAX_REGISTERS + 1))
  27.                       ? induced_align(80)
  28.                       : (m->align < 0 ? ralign[-m->align - 1] : m->align);
  29.  
  30.      if (!class)
  31.          pm = (struct permonst *) 0;
  32.      else if (m->id != NON_PM) {
  33.          pm = &mons[m->id];
  34.          g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
  35.          if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT))
  36.              return;
  37.          else if (g_mvflags & G_GONE)    /* genocided or extinct */
  38.              pm = (struct permonst *) 0; /* make random monster */
  39.      } else {
  40.          pm = mkclass(class, G_NOGEN);
  41.          /* if we can't get a specific monster type (pm == 0) then the
  42.             class has been genocided, so settle for a random monster */
  43.      }
  44.      if (In_mines(&u.uz) && pm && your_race(pm)
  45.          && (Race_if(PM_DWARF) || Race_if(PM_GNOME)) && rn2(3))
  46.          pm = (struct permonst *) 0;
  47.  
  48.      if (pm) {
  49.          int loc = DRY;
  50.          if (pm->mlet == S_EEL || amphibious(pm) || is_swimmer(pm))
  51.              loc = WET;
  52.          if (is_flyer(pm) || is_floater(pm))
  53.              loc |= (HOT | WET);
  54.          if (passes_walls(pm) || noncorporeal(pm))
  55.              loc |= SOLID;
  56.          if (flaming(pm))
  57.              loc |= HOT;
  58.          /* If water-liking monster, first try is without DRY */
  59.          get_location_coord(&x, &y, loc | NO_LOC_WARN, croom, m->coord);
  60.          if (x == -1 && y == -1) {
  61.              loc |= DRY;
  62.              get_location_coord(&x, &y, loc, croom, m->coord);
  63.          }
  64.      } else {
  65.          get_location_coord(&x, &y, DRY, croom, m->coord);
  66.      }
  67.  
  68.      /* try to find a close place if someone else is already there */
  69.      if (MON_AT(x, y) && enexto(&cc, x, y, pm))
  70.          x = cc.x, y = cc.y;
  71.  
  72.      if (m->align != -(MAX_REGISTERS + 2))
  73.          mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
  74.      else if (PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
  75.          mtmp = mk_mplayer(pm, x, y, FALSE);
  76.      else
  77.          mtmp = makemon(pm, x, y, NO_MM_FLAGS);
  78.  
  79.      if (mtmp) {
  80.          x = mtmp->mx, y = mtmp->my; /* sanity precaution */
  81.          m->x = x, m->y = y;
  82.          /* handle specific attributes for some special monsters */
  83.          if (m->name.str)
  84.              mtmp = christen_monst(mtmp, m->name.str);
  85.  
  86.          /*
  87.           * This is currently hardwired for mimics only.  It should
  88.           * eventually be expanded.
  89.           */
  90.          if (m->appear_as.str
  91.              && ((mtmp->data->mlet == S_MIMIC) || mtmp->cham)) {
  92.              int i;
  93.  
  94.              switch (m->appear) {
  95.              case M_AP_NOTHING:
  96.                  impossible(
  97.                   "create_monster: mon has an appearance, \"%s\", but no type",
  98.                             m->appear_as.str);
  99.                  break;
  100.  
  101.              case M_AP_FURNITURE:
  102.                  for (i = 0; i < MAXPCHARS; i++)
  103.                      if (!strcmp(defsyms[i].explanation, m->appear_as.str))
  104.                          break;
  105.                  if (i == MAXPCHARS) {
  106.                      impossible("create_monster: can't find feature \"%s\"",
  107.                                 m->appear_as.str);
  108.                  } else {
  109.                      mtmp->m_ap_type = M_AP_FURNITURE;
  110.                      mtmp->mappearance = i;
  111.                  }
  112.                  break;
  113.  
  114.              case M_AP_OBJECT:
  115.                  for (i = 0; i < NUM_OBJECTS; i++)
  116.                      if (OBJ_NAME(objects[i])
  117.                          && !strcmp(OBJ_NAME(objects[i]), m->appear_as.str))
  118.                          break;
  119.                  if (i == NUM_OBJECTS) {
  120.                      impossible("create_monster: can't find object \"%s\"",
  121.                                 m->appear_as.str);
  122.                  } else {
  123.                      mtmp->m_ap_type = M_AP_OBJECT;
  124.                      mtmp->mappearance = i;
  125.                      /* try to avoid placing mimic boulder on a trap */
  126.                      if (i == BOULDER && m->x < 0
  127.                          && m_bad_boulder_spot(x, y)) {
  128.                          int retrylimit = 10;
  129.  
  130.                          remove_monster(x, y);
  131.                          do {
  132.                              x = m->x;
  133.                              y = m->y;
  134.                              get_location(&x, &y, DRY, croom);
  135.                              if (MON_AT(x, y) && enexto(&cc, x, y, pm))
  136.                                  x = cc.x, y = cc.y;
  137.                          } while (m_bad_boulder_spot(x, y)
  138.                                   && --retrylimit > 0);
  139.                          place_monster(mtmp, x, y);
  140.                          /* if we didn't find a good spot
  141.                             then mimic something else */
  142.                          if (!retrylimit)
  143.                              set_mimic_sym(mtmp);
  144.                      }
  145.                  }
  146.                  break;
  147.  
  148.              case M_AP_MONSTER: {
  149.                  int mndx;
  150.  
  151.                  if (!strcmpi(m->appear_as.str, "random"))
  152.                      mndx = select_newcham_form(mtmp);
  153.                  else
  154.                      mndx = name_to_mon(m->appear_as.str);
  155.                  if ((mndx != NON_PM) && (&mons[mndx] != mtmp->data)) {
  156.                      struct permonst *mdat = &mons[mndx];
  157.                      struct permonst *olddata = mtmp->data;
  158.  
  159.                      mgender_from_permonst(mtmp, mdat);
  160.                      set_mon_data(mtmp, mdat, 0);
  161.                      if (emits_light(olddata) != emits_light(mtmp->data)) {
  162.                          /* used to give light, now doesn't, or vice versa,
  163.                             or light's range has changed */
  164.                          if (emits_light(olddata))
  165.                              del_light_source(LS_MONSTER, (genericptr_t) mtmp);
  166.                          if (emits_light(mtmp->data))
  167.                              new_light_source(mtmp->mx, mtmp->my,
  168.                                               emits_light(mtmp->data),
  169.                                               LS_MONSTER, (genericptr_t) mtmp);
  170.                      }
  171.                      if (!mtmp->perminvis || pm_invisible(olddata))
  172.                          mtmp->perminvis = pm_invisible(mdat);
  173.                  }
  174.                  break;
  175.              }
  176.              default:
  177.                  impossible(
  178.                    "create_monster: unimplemented mon appear type [%d,\"%s\"]",
  179.                             m->appear, m->appear_as.str);
  180.                  break;
  181.              }
  182.              if (does_block(x, y, &levl[x][y]))
  183.                  block_point(x, y);
  184.          }
  185.  
  186.          if (m->peaceful >= 0) {
  187.              mtmp->mpeaceful = m->peaceful;
  188.              /* changed mpeaceful again; have to reset malign */
  189.              set_malign(mtmp);
  190.          }
  191.          if (m->asleep >= 0) {
  192.  #ifdef UNIXPC
  193.              /* optimizer bug strikes again */
  194.              if (m->asleep)
  195.                  mtmp->msleeping = 1;
  196.              else
  197.                  mtmp->msleeping = 0;
  198.  #else
  199.              mtmp->msleeping = m->asleep;
  200.  #endif
  201.          }
  202.          if (m->seentraps)
  203.              mtmp->mtrapseen = m->seentraps;
  204.          if (m->female)
  205.              mtmp->female = 1;
  206.          if (m->cancelled)
  207.              mtmp->mcan = 1;
  208.          if (m->revived)
  209.              mtmp->mrevived = 1;
  210.          if (m->avenge)
  211.              mtmp->mavenge = 1;
  212.          if (m->stunned)
  213.              mtmp->mstun = 1;
  214.          if (m->confused)
  215.              mtmp->mconf = 1;
  216.          if (m->invis) {
  217.              mtmp->minvis = mtmp->perminvis = 1;
  218.          }
  219.          if (m->blinded) {
  220.              mtmp->mcansee = 0;
  221.              mtmp->mblinded = (m->blinded % 127);
  222.          }
  223.          if (m->paralyzed) {
  224.              mtmp->mcanmove = 0;
  225.              mtmp->mfrozen = (m->paralyzed % 127);
  226.          }
  227.          if (m->fleeing) {
  228.              mtmp->mflee = 1;
  229.              mtmp->mfleetim = (m->fleeing % 127);
  230.          }
  231.  
  232.          if (m->has_invent) {
  233.              discard_minvent(mtmp);
  234.              invent_carrying_monster = mtmp;
  235.          }
  236.      }
  237.  }
  238.  

create_object

  1.  /*
  2.   * Create an object in a room.
  3.   */
  4.  STATIC_OVL void
  5.  create_object(o, croom)
  6.  object *o;
  7.  struct mkroom *croom;
  8.  {
  9.      struct obj *otmp;
  10.      schar x, y;
  11.      char c;
  12.      boolean named; /* has a name been supplied in level description? */
  13.  
  14.      named = o->name.str ? TRUE : FALSE;
  15.  
  16.      get_location_coord(&x, &y, DRY, croom, o->coord);
  17.  
  18.      if (o->class >= 0)
  19.          c = o->class;
  20.      else
  21.          c = 0;
  22.  
  23.      if (!c)
  24.          otmp = mkobj_at(RANDOM_CLASS, x, y, !named);
  25.      else if (o->id != -1)
  26.          otmp = mksobj_at(o->id, x, y, TRUE, !named);
  27.      else {
  28.          /*
  29.           * The special levels are compiled with the default "text" object
  30.           * class characters.  We must convert them to the internal format.
  31.           */
  32.          char oclass = (char) def_char_to_objclass(c);
  33.  
  34.          if (oclass == MAXOCLASSES)
  35.              panic("create_object:  unexpected object class '%c'", c);
  36.  
  37.          /* KMH -- Create piles of gold properly */
  38.          if (oclass == COIN_CLASS)
  39.              otmp = mkgold(0L, x, y);
  40.          else
  41.              otmp = mkobj_at(oclass, x, y, !named);
  42.      }
  43.  
  44.      if (o->spe != -127) /* That means NOT RANDOM! */
  45.          otmp->spe = (schar) o->spe;
  46.  
  47.      switch (o->curse_state) {
  48.      case 1:
  49.          bless(otmp);
  50.          break; /* BLESSED */
  51.      case 2:
  52.          unbless(otmp);
  53.          uncurse(otmp);
  54.          break; /* uncursed */
  55.      case 3:
  56.          curse(otmp);
  57.          break; /* CURSED */
  58.      default:
  59.          break; /* Otherwise it's random and we're happy
  60.                  * with what mkobj gave us! */
  61.      }
  62.  
  63.      /* corpsenm is "empty" if -1, random if -2, otherwise specific */
  64.      if (o->corpsenm != NON_PM) {
  65.          if (o->corpsenm == NON_PM - 1)
  66.              set_corpsenm(otmp, rndmonnum());
  67.          else
  68.              set_corpsenm(otmp, o->corpsenm);
  69.      }
  70.      /* set_corpsenm() took care of egg hatch and corpse timers */
  71.  
  72.      if (named)
  73.          otmp = oname(otmp, o->name.str);
  74.  
  75.      if (o->eroded) {
  76.          if (o->eroded < 0) {
  77.              otmp->oerodeproof = 1;
  78.          } else {
  79.              otmp->oeroded = (o->eroded % 4);
  80.              otmp->oeroded2 = ((o->eroded >> 2) % 4);
  81.          }
  82.      }
  83.      if (o->recharged)
  84.          otmp->recharged = (o->recharged % 8);
  85.      if (o->locked) {
  86.          otmp->olocked = 1;
  87.      } else if (o->broken) {
  88.          otmp->obroken = 1;
  89.          otmp->olocked = 0; /* obj generation may set */
  90.      }
  91.      if (o->trapped)
  92.          otmp->otrapped = 1;
  93.      if (o->greased)
  94.          otmp->greased = 1;
  95.  #ifdef INVISIBLE_OBJECTS
  96.      if (o->invis)
  97.          otmp->oinvis = 1;
  98.  #endif
  99.  
  100.      if (o->quan > 0 && objects[otmp->otyp].oc_merge) {
  101.          otmp->quan = o->quan;
  102.          otmp->owt = weight(otmp);
  103.      }
  104.  
  105.      /* contents */
  106.      if (o->containment & SP_OBJ_CONTENT) {
  107.          if (!container_idx) {
  108.              if (!invent_carrying_monster) {
  109.                  /*impossible("create_object: no container");*/
  110.                  /* don't complain, the monster may be gone legally
  111.                     (eg. unique demon already generated)
  112.                     TODO: In the case of unique demon lords, they should
  113.                     get their inventories even when they get generated
  114.                     outside the des-file.  Maybe another data file that
  115.                     determines what inventories monsters get by default?
  116.                   */
  117.              } else {
  118.                  int ci;
  119.                  struct obj *objcheck = otmp;
  120.                  int inuse = -1;
  121.  
  122.                  for (ci = 0; ci < container_idx; ci++)
  123.                      if (container_obj[ci] == objcheck)
  124.                          inuse = ci;
  125.                  remove_object(otmp);
  126.                  if (mpickobj(invent_carrying_monster, otmp)) {
  127.                      if (inuse > -1) {
  128.                          impossible(
  129.                       "container given to monster was merged or deallocated.");
  130.                          for (ci = inuse; ci < container_idx - 1; ci++)
  131.                              container_obj[ci] = container_obj[ci + 1];
  132.                          container_obj[container_idx] = NULL;
  133.                          container_idx--;
  134.                      }
  135.                      /* we lost track of it. */
  136.                      return;
  137.                  }
  138.              }
  139.          } else {
  140.              remove_object(otmp);
  141.              if (container_obj[container_idx - 1])
  142.                  (void) add_to_container(container_obj[container_idx - 1],
  143.                                          otmp);
  144.              else {
  145.                  obj_extract_self(otmp);
  146.                  obfree(otmp, NULL);
  147.                  return;
  148.              }
  149.          }
  150.      }
  151.      /* container */
  152.      if (o->containment & SP_OBJ_CONTAINER) {
  153.          delete_contents(otmp);
  154.          if (container_idx < MAX_CONTAINMENT) {
  155.              container_obj[container_idx] = otmp;
  156.              container_idx++;
  157.          } else
  158.              impossible("create_object: too deeply nested containers.");
  159.      }
  160.  
  161.      /* Medusa level special case: statues are petrified monsters, so they
  162.       * are not stone-resistant and have monster inventory.  They also lack
  163.       * other contents, but that can be specified as an empty container.
  164.       */
  165.      if (o->id == STATUE && Is_medusa_level(&u.uz) && o->corpsenm == NON_PM) {
  166.          struct monst *was;
  167.          struct obj *obj;
  168.          int wastyp;
  169.          int i = 0; /* prevent endless loop in case makemon always fails */
  170.  
  171.          /* Named random statues are of player types, and aren't stone-
  172.           * resistant (if they were, we'd have to reset the name as well as
  173.           * setting corpsenm).
  174.           */
  175.          for (wastyp = otmp->corpsenm; i < 1000; i++, wastyp = rndmonnum()) {
  176.              /* makemon without rndmonst() might create a group */
  177.              was = makemon(&mons[wastyp], 0, 0, MM_NOCOUNTBIRTH);
  178.              if (was) {
  179.                  if (!resists_ston(was)) {
  180.                      (void) propagate(wastyp, TRUE, FALSE);
  181.                      break;
  182.                  }
  183.                  mongone(was);
  184.                  was = NULL;
  185.              }
  186.          }
  187.          if (was) {
  188.              set_corpsenm(otmp, wastyp);
  189.              while (was->minvent) {
  190.                  obj = was->minvent;
  191.                  obj->owornmask = 0;
  192.                  obj_extract_self(obj);
  193.                  (void) add_to_container(otmp, obj);
  194.              }
  195.              otmp->owt = weight(otmp);
  196.              mongone(was);
  197.          }
  198.      }
  199.  
  200.      /* Nasty hack here: try to determine if this is the Mines or Sokoban
  201.       * "prize" and then set record_achieve_special (maps to corpsenm)
  202.       * for the object.  That field will later be checked to find out if
  203.       * the player obtained the prize. */
  204.      if (otmp->otyp == LUCKSTONE && Is_mineend_level(&u.uz)) {
  205.          otmp->record_achieve_special = 1;
  206.      } else if ((otmp->otyp == AMULET_OF_REFLECTION
  207.                  || otmp->otyp == BAG_OF_HOLDING)
  208.                 && Is_sokoend_level(&u.uz)) {
  209.          otmp->record_achieve_special = 1;
  210.      }
  211.  
  212.      stackobj(otmp);
  213.  
  214.      if (o->lit) {
  215.          begin_burn(otmp, FALSE);
  216.      }
  217.  
  218.      if (o->buried) {
  219.          boolean dealloced;
  220.  
  221.          (void) bury_an_obj(otmp, &dealloced);
  222.          if (dealloced && container_idx) {
  223.              container_obj[container_idx - 1] = NULL;
  224.          }
  225.      }
  226.  }
  227.  

create_altar

  1.  /*
  2.   * Create an altar in a room.
  3.   */
  4.  STATIC_OVL void
  5.  create_altar(a, croom)
  6.  altar *a;
  7.  struct mkroom *croom;
  8.  {
  9.      schar sproom, x, y;
  10.      aligntyp amask;
  11.      boolean croom_is_temple = TRUE;
  12.      int oldtyp;
  13.  
  14.      if (croom) {
  15.          get_free_room_loc(&x, &y, croom, a->coord);
  16.          if (croom->rtype != TEMPLE)
  17.              croom_is_temple = FALSE;
  18.      } else {
  19.          get_location_coord(&x, &y, DRY, croom, a->coord);
  20.          if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
  21.              croom = &rooms[sproom - ROOMOFFSET];
  22.          else
  23.              croom_is_temple = FALSE;
  24.      }
  25.  
  26.      /* check for existing features */
  27.      oldtyp = levl[x][y].typ;
  28.      if (oldtyp == STAIRS || oldtyp == LADDER)
  29.          return;
  30.  
  31.      /* Is the alignment random ?
  32.       * If so, it's an 80% chance that the altar will be co-aligned.
  33.       *
  34.       * The alignment is encoded as amask values instead of alignment
  35.       * values to avoid conflicting with the rest of the encoding,
  36.       * shared by many other parts of the special level code.
  37.       */
  38.      amask = (a->align == AM_SPLEV_CO)
  39.                 ? Align2amask(u.ualignbase[A_ORIGINAL])
  40.                 : (a->align == AM_SPLEV_NONCO)
  41.                    ? Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL]))
  42.                    : (a->align == -(MAX_REGISTERS + 1))
  43.                       ? induced_align(80)
  44.                       : (a->align < 0 ? ralign[-a->align - 1] : a->align);
  45.  
  46.      levl[x][y].typ = ALTAR;
  47.      levl[x][y].altarmask = amask;
  48.  
  49.      if (a->shrine < 0)
  50.          a->shrine = rn2(2); /* handle random case */
  51.  
  52.      if (!croom_is_temple || !a->shrine)
  53.          return;
  54.  
  55.      if (a->shrine) { /* Is it a shrine  or sanctum? */
  56.          priestini(&u.uz, croom, x, y, (a->shrine > 1));
  57.          levl[x][y].altarmask |= AM_SHRINE;
  58.          level.flags.has_temple = TRUE;
  59.      }
  60.  }
  61.  

replace_terrain

  1.  void
  2.  replace_terrain(terr, croom)
  3.  replaceterrain *terr;
  4.  struct mkroom *croom;
  5.  {
  6.      schar x, y, x1, y1, x2, y2;
  7.  
  8.      if (terr->toter >= MAX_TYPE)
  9.          return;
  10.  
  11.      x1 = terr->x1;
  12.      y1 = terr->y1;
  13.      get_location(&x1, &y1, ANY_LOC, croom);
  14.  
  15.      x2 = terr->x2;
  16.      y2 = terr->y2;
  17.      get_location(&x2, &y2, ANY_LOC, croom);
  18.  
  19.      for (x = max(x1, 0); x <= min(x2, COLNO - 1); x++)
  20.          for (y = max(y1, 0); y <= min(y2, ROWNO - 1); y++)
  21.              if (levl[x][y].typ == terr->fromter && rn2(100) < terr->chance) {
  22.                  SET_TYPLIT(x, y, terr->toter, terr->tolit);
  23.              }
  24.  }
  25.  

search_door

  1.  /*
  2.   * Search for a door in a room on a specified wall.
  3.   */
  4.  STATIC_OVL boolean
  5.  search_door(croom, x, y, wall, cnt)
  6.  struct mkroom *croom;
  7.  xchar *x, *y;
  8.  xchar wall;
  9.  int cnt;
  10.  {
  11.      int dx, dy;
  12.      int xx, yy;
  13.  
  14.      switch (wall) {
  15.      case W_NORTH:
  16.          dy = 0;
  17.          dx = 1;
  18.          xx = croom->lx;
  19.          yy = croom->hy + 1;
  20.          break;
  21.      case W_SOUTH:
  22.          dy = 0;
  23.          dx = 1;
  24.          xx = croom->lx;
  25.          yy = croom->ly - 1;
  26.          break;
  27.      case W_EAST:
  28.          dy = 1;
  29.          dx = 0;
  30.          xx = croom->hx + 1;
  31.          yy = croom->ly;
  32.          break;
  33.      case W_WEST:
  34.          dy = 1;
  35.          dx = 0;
  36.          xx = croom->lx - 1;
  37.          yy = croom->ly;
  38.          break;
  39.      default:
  40.          dx = dy = xx = yy = 0;
  41.          panic("search_door: Bad wall!");
  42.          break;
  43.      }
  44.      while (xx <= croom->hx + 1 && yy <= croom->hy + 1) {
  45.          if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
  46.              *x = xx;
  47.              *y = yy;
  48.              if (cnt-- <= 0)
  49.                  return TRUE;
  50.          }
  51.          xx += dx;
  52.          yy += dy;
  53.      }
  54.      return FALSE;
  55.  }
  56.  

dig_corridor

  1.  /*
  2.   * Dig a corridor between two points.
  3.   */
  4.  boolean
  5.  dig_corridor(org, dest, nxcor, ftyp, btyp)
  6.  coord *org, *dest;
  7.  boolean nxcor;
  8.  schar ftyp, btyp;
  9.  {
  10.      int dx = 0, dy = 0, dix, diy, cct;
  11.      struct rm *crm;
  12.      int tx, ty, xx, yy;
  13.  
  14.      xx = org->x;
  15.      yy = org->y;
  16.      tx = dest->x;
  17.      ty = dest->y;
  18.      if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 || xx > COLNO - 1
  19.          || tx > COLNO - 1 || yy > ROWNO - 1 || ty > ROWNO - 1) {
  20.          debugpline4("dig_corridor: bad coords <%d,%d> <%d,%d>.",
  21.                      xx, yy, tx, ty);
  22.          return FALSE;
  23.      }
  24.      if (tx > xx)
  25.          dx = 1;
  26.      else if (ty > yy)
  27.          dy = 1;
  28.      else if (tx < xx)
  29.          dx = -1;
  30.      else
  31.          dy = -1;
  32.  
  33.      xx -= dx;
  34.      yy -= dy;
  35.      cct = 0;
  36.      while (xx != tx || yy != ty) {
  37.          /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
  38.          if (cct++ > 500 || (nxcor && !rn2(35)))
  39.              return FALSE;
  40.  
  41.          xx += dx;
  42.          yy += dy;
  43.  
  44.          if (xx >= COLNO - 1 || xx <= 0 || yy <= 0 || yy >= ROWNO - 1)
  45.              return FALSE; /* impossible */
  46.  
  47.          crm = &levl[xx][yy];
  48.          if (crm->typ == btyp) {
  49.              if (ftyp != CORR || rn2(100)) {
  50.                  crm->typ = ftyp;
  51.                  if (nxcor && !rn2(50))
  52.                      (void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE);
  53.              } else {
  54.                  crm->typ = SCORR;
  55.              }
  56.          } else if (crm->typ != ftyp && crm->typ != SCORR) {
  57.              /* strange ... */
  58.              return FALSE;
  59.          }
  60.  
  61.          /* find next corridor position */
  62.          dix = abs(xx - tx);
  63.          diy = abs(yy - ty);
  64.  
  65.          if ((dix > diy) && diy && !rn2(dix-diy+1)) {
  66.              dix = 0;
  67.          } else if ((diy > dix) && dix && !rn2(diy-dix+1)) {
  68.              diy = 0;
  69.          }
  70.  
  71.          /* do we have to change direction ? */
  72.          if (dy && dix > diy) {
  73.              register int ddx = (xx > tx) ? -1 : 1;
  74.  
  75.              crm = &levl[xx + ddx][yy];
  76.              if (crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
  77.                  dx = ddx;
  78.                  dy = 0;
  79.                  continue;
  80.              }
  81.          } else if (dx && diy > dix) {
  82.              register int ddy = (yy > ty) ? -1 : 1;
  83.  
  84.              crm = &levl[xx][yy + ddy];
  85.              if (crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
  86.                  dy = ddy;
  87.                  dx = 0;
  88.                  continue;
  89.              }
  90.          }
  91.  
  92.          /* continue straight on? */
  93.          crm = &levl[xx + dx][yy + dy];
  94.          if (crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
  95.              continue;
  96.  
  97.          /* no, what must we do now?? */
  98.          if (dx) {
  99.              dx = 0;
  100.              dy = (ty < yy) ? -1 : 1;
  101.          } else {
  102.              dy = 0;
  103.              dx = (tx < xx) ? -1 : 1;
  104.          }
  105.          crm = &levl[xx + dx][yy + dy];
  106.          if (crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
  107.              continue;
  108.          dy = -dy;
  109.          dx = -dx;
  110.      }
  111.      return TRUE;
  112.  }
  113.  

fix_stair_rooms

  1.  /*
  2.   * Disgusting hack: since special levels have their rooms filled before
  3.   * sorting the rooms, we have to re-arrange the speed values upstairs_room
  4.   * and dnstairs_room after the rooms have been sorted.  On normal levels,
  5.   * stairs don't get created until _after_ sorting takes place.
  6.   */
  7.  STATIC_OVL void
  8.  fix_stair_rooms()
  9.  {
  10.      int i;
  11.      struct mkroom *croom;
  12.  
  13.      if (xdnstair
  14.          && !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx)
  15.               && (dnstairs_room->ly <= ydnstair
  16.                   && ydnstair <= dnstairs_room->hy))) {
  17.          for (i = 0; i < nroom; i++) {
  18.              croom = &rooms[i];
  19.              if ((croom->lx <= xdnstair && xdnstair <= croom->hx)
  20.                  && (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
  21.                  dnstairs_room = croom;
  22.                  break;
  23.              }
  24.          }
  25.          if (i == nroom)
  26.              panic("Couldn't find dnstair room in fix_stair_rooms!");
  27.      }
  28.      if (xupstair
  29.          && !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx)
  30.               && (upstairs_room->ly <= yupstair
  31.                   && yupstair <= upstairs_room->hy))) {
  32.          for (i = 0; i < nroom; i++) {
  33.              croom = &rooms[i];
  34.              if ((croom->lx <= xupstair && xupstair <= croom->hx)
  35.                  && (croom->ly <= yupstair && yupstair <= croom->hy)) {
  36.                  upstairs_room = croom;
  37.                  break;
  38.              }
  39.          }
  40.          if (i == nroom)
  41.              panic("Couldn't find upstair room in fix_stair_rooms!");
  42.      }
  43.  }
  44.  

create_corridor

  1.  /*
  2.   * Corridors always start from a door. But it can end anywhere...
  3.   * Basically we search for door coordinates or for endpoints coordinates
  4.   * (from a distance).
  5.   */
  6.  STATIC_OVL void
  7.  create_corridor(c)
  8.  corridor *c;
  9.  {
  10.      coord org, dest;
  11.  
  12.      if (c->src.room == -1) {
  13.          fix_stair_rooms();
  14.          makecorridors(); /*makecorridors(c->src.door);*/
  15.          return;
  16.      }
  17.  
  18.      if (!search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall,
  19.                       c->src.door))
  20.          return;
  21.  
  22.      if (c->dest.room != -1) {
  23.          if (!search_door(&rooms[c->dest.room], &dest.x, &dest.y, c->dest.wall,
  24.                           c->dest.door))
  25.              return;
  26.          switch (c->src.wall) {
  27.          case W_NORTH:
  28.              org.y--;
  29.              break;
  30.          case W_SOUTH:
  31.              org.y++;
  32.              break;
  33.          case W_WEST:
  34.              org.x--;
  35.              break;
  36.          case W_EAST:
  37.              org.x++;
  38.              break;
  39.          }
  40.          switch (c->dest.wall) {
  41.          case W_NORTH:
  42.              dest.y--;
  43.              break;
  44.          case W_SOUTH:
  45.              dest.y++;
  46.              break;
  47.          case W_WEST:
  48.              dest.x--;
  49.              break;
  50.          case W_EAST:
  51.              dest.x++;
  52.              break;
  53.          }
  54.          (void) dig_corridor(&org, &dest, FALSE, CORR, STONE);
  55.      }
  56.  }
  57.  

fill_room

  1.  /*
  2.   * Fill a room (shop, zoo, etc...) with appropriate stuff.
  3.   */
  4.  void
  5.  fill_room(croom, prefilled)
  6.  struct mkroom *croom;
  7.  boolean prefilled;
  8.  {
  9.      if (!croom || croom->rtype == OROOM)
  10.          return;
  11.  
  12.      if (!prefilled) {
  13.          int x, y;
  14.  
  15.          /* Shop ? */
  16.          if (croom->rtype >= SHOPBASE) {
  17.              stock_room(croom->rtype - SHOPBASE, croom);
  18.              level.flags.has_shop = TRUE;
  19.              return;
  20.          }
  21.  
  22.          switch (croom->rtype) {
  23.          case VAULT:
  24.              for (x = croom->lx; x <= croom->hx; x++)
  25.                  for (y = croom->ly; y <= croom->hy; y++)
  26.                      (void) mkgold((long) rn1(abs(depth(&u.uz)) * 100, 51),
  27.                                    x, y);
  28.              break;
  29.          case COURT:
  30.          case ZOO:
  31.          case BEEHIVE:
  32.          case MORGUE:
  33.          case BARRACKS:
  34.              fill_zoo(croom);
  35.              break;
  36.          }
  37.      }
  38.      switch (croom->rtype) {
  39.      case VAULT:
  40.          level.flags.has_vault = TRUE;
  41.          break;
  42.      case ZOO:
  43.          level.flags.has_zoo = TRUE;
  44.          break;
  45.      case COURT:
  46.          level.flags.has_court = TRUE;
  47.          break;
  48.      case MORGUE:
  49.          level.flags.has_morgue = TRUE;
  50.          break;
  51.      case BEEHIVE:
  52.          level.flags.has_beehive = TRUE;
  53.          break;
  54.      case BARRACKS:
  55.          level.flags.has_barracks = TRUE;
  56.          break;
  57.      case TEMPLE:
  58.          level.flags.has_temple = TRUE;
  59.          break;
  60.      case SWAMP:
  61.          level.flags.has_swamp = TRUE;
  62.          break;
  63.      }
  64.  }
  65.  

build_room

  1.  struct mkroom *
  2.  build_room(r, mkr)
  3.  room *r;
  4.  struct mkroom *mkr;
  5.  {
  6.      boolean okroom;
  7.      struct mkroom *aroom;
  8.      xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
  9.  
  10.      if (mkr) {
  11.          aroom = &subrooms[nsubroom];
  12.          okroom = create_subroom(mkr, r->x, r->y, r->w, r->h, rtype, r->rlit);
  13.      } else {
  14.          aroom = &rooms[nroom];
  15.          okroom = create_room(r->x, r->y, r->w, r->h, r->xalign, r->yalign,
  16.                               rtype, r->rlit);
  17.      }
  18.  
  19.      if (okroom) {
  20.  #ifdef SPECIALIZATION
  21.          topologize(aroom, FALSE); /* set roomno */
  22.  #else
  23.          topologize(aroom); /* set roomno */
  24.  #endif
  25.          aroom->needfill = r->filled;
  26.          aroom->needjoining = r->joined;
  27.          return aroom;
  28.      }
  29.      return (struct mkroom *) 0;
  30.  }
  31.  

light_region

  1.  /*
  2.   * set lighting in a region that will not become a room.
  3.   */
  4.  STATIC_OVL void
  5.  light_region(tmpregion)
  6.  region *tmpregion;
  7.  {
  8.      register boolean litstate = tmpregion->rlit ? 1 : 0;
  9.      register int hiy = tmpregion->y2;
  10.      register int x, y;
  11.      register struct rm *lev;
  12.      int lowy = tmpregion->y1;
  13.      int lowx = tmpregion->x1, hix = tmpregion->x2;
  14.  
  15.      if (litstate) {
  16.          /* adjust region size for walls, but only if lighted */
  17.          lowx = max(lowx - 1, 1);
  18.          hix = min(hix + 1, COLNO - 1);
  19.          lowy = max(lowy - 1, 0);
  20.          hiy = min(hiy + 1, ROWNO - 1);
  21.      }
  22.      for (x = lowx; x <= hix; x++) {
  23.          lev = &levl[x][lowy];
  24.          for (y = lowy; y <= hiy; y++) {
  25.              if (lev->typ != LAVAPOOL) /* this overrides normal lighting */
  26.                  lev->lit = litstate;
  27.              lev++;
  28.          }
  29.      }
  30.  }
  31.  

wallify_map

  1.  void
  2.  wallify_map(x1, y1, x2, y2)
  3.  int x1, y1, x2, y2;
  4.  {
  5.      int x, y, xx, yy, lo_xx, lo_yy, hi_xx, hi_yy;
  6.  
  7.      for (y = y1; y <= y2; y++) {
  8.          lo_yy = (y > 0) ? y - 1 : 0;
  9.          hi_yy = (y < y2) ? y + 1 : y2;
  10.          for (x = x1; x <= x2; x++) {
  11.              if (levl[x][y].typ != STONE)
  12.                  continue;
  13.              lo_xx = (x > 0) ? x - 1 : 0;
  14.              hi_xx = (x < x2) ? x + 1 : x2;
  15.              for (yy = lo_yy; yy <= hi_yy; yy++)
  16.                  for (xx = lo_xx; xx <= hi_xx; xx++)
  17.                      if (IS_ROOM(levl[xx][yy].typ)
  18.                          || levl[xx][yy].typ == CROSSWALL) {
  19.                          levl[x][y].typ = (yy != y) ? HWALL : VWALL;
  20.                          yy = hi_yy; /* end `yy' loop */
  21.                          break;      /* end `xx' loop */
  22.                      }
  23.          }
  24.      }
  25.  }
  26.  

maze1xy

  1.  /*
  2.   * Select a random coordinate in the maze.
  3.   *
  4.   * We want a place not 'touched' by the loader.  That is, a place in
  5.   * the maze outside every part of the special level.
  6.   */
  7.  STATIC_OVL void
  8.  maze1xy(m, humidity)
  9.  coord *m;
  10.  int humidity;
  11.  {
  12.      register int x, y, tryct = 2000;
  13.      /* tryct:  normally it won't take more than ten or so tries due
  14.         to the circumstances under which we'll be called, but the
  15.         `humidity' screening might drastically change the chances */
  16.  
  17.      do {
  18.          x = rn1(x_maze_max - 3, 3);
  19.          y = rn1(y_maze_max - 3, 3);
  20.          if (--tryct < 0)
  21.              break; /* give up */
  22.      } while (!(x % 2) || !(y % 2) || SpLev_Map[x][y]
  23.               || !is_ok_location((schar) x, (schar) y, humidity));
  24.  
  25.      m->x = (xchar) x, m->y = (xchar) y;
  26.  }
  27.  

fill_empty_maze

  1.  /*
  2.   * If there's a significant portion of maze unused by the special level,
  3.   * we don't want it empty.
  4.   *
  5.   * Makes the number of traps, monsters, etc. proportional
  6.   * to the size of the maze.
  7.   */
  8.  STATIC_OVL void
  9.  fill_empty_maze()
  10.  {
  11.      int mapcountmax, mapcount, mapfact;
  12.      xchar x, y;
  13.      coord mm;
  14.  
  15.      mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
  16.      mapcountmax = mapcountmax / 2;
  17.  
  18.      for (x = 2; x < x_maze_max; x++)
  19.          for (y = 0; y < y_maze_max; y++)
  20.              if (SpLev_Map[x][y])
  21.                  mapcount--;
  22.  
  23.      if ((mapcount > (int) (mapcountmax / 10))) {
  24.          mapfact = (int) ((mapcount * 100L) / mapcountmax);
  25.          for (x = rnd((int) (20 * mapfact) / 100); x; x--) {
  26.              maze1xy(&mm, DRY);
  27.              (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS, mm.x, mm.y,
  28.                              TRUE);
  29.          }
  30.          for (x = rnd((int) (12 * mapfact) / 100); x; x--) {
  31.              maze1xy(&mm, DRY);
  32.              (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE);
  33.          }
  34.          for (x = rn2(2); x; x--) {
  35.              maze1xy(&mm, DRY);
  36.              (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS);
  37.          }
  38.          for (x = rnd((int) (12 * mapfact) / 100); x; x--) {
  39.              maze1xy(&mm, DRY);
  40.              (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS);
  41.          }
  42.          for (x = rn2((int) (15 * mapfact) / 100); x; x--) {
  43.              maze1xy(&mm, DRY);
  44.              (void) mkgold(0L, mm.x, mm.y);
  45.          }
  46.          for (x = rn2((int) (15 * mapfact) / 100); x; x--) {
  47.              int trytrap;
  48.  
  49.              maze1xy(&mm, DRY);
  50.              trytrap = rndtrap();
  51.              if (sobj_at(BOULDER, mm.x, mm.y))
  52.                  while (trytrap == PIT || trytrap == SPIKED_PIT
  53.                         || trytrap == TRAPDOOR || trytrap == HOLE)
  54.                      trytrap = rndtrap();
  55.              (void) maketrap(mm.x, mm.y, trytrap);
  56.          }
  57.      }
  58.  }
  59.  

sp_level_loader

  1.  /*
  2.   * special level loader
  3.   */
  4.  STATIC_OVL boolean
  5.  sp_level_loader(fd, lvl)
  6.  dlb *fd;
  7.  sp_lev *lvl;
  8.  {
  9.      long n_opcode = 0;
  10.      struct opvar *opdat;
  11.      int opcode;
  12.  
  13.      Fread((genericptr_t) & (lvl->n_opcodes), 1, sizeof(lvl->n_opcodes), fd);
  14.      lvl->opcodes = (_opcode *) alloc(sizeof(_opcode) * (lvl->n_opcodes));
  15.  
  16.      while (n_opcode < lvl->n_opcodes) {
  17.          Fread((genericptr_t) &lvl->opcodes[n_opcode].opcode, 1,
  18.                sizeof(lvl->opcodes[n_opcode].opcode), fd);
  19.          opcode = lvl->opcodes[n_opcode].opcode;
  20.  
  21.          opdat = NULL;
  22.  
  23.          if (opcode < SPO_NULL || opcode >= MAX_SP_OPCODES)
  24.              panic("sp_level_loader: impossible opcode %i.", opcode);
  25.  
  26.          if (opcode == SPO_PUSH) {
  27.              int nsize;
  28.              struct opvar *ov = (struct opvar *) alloc(sizeof(struct opvar));
  29.  
  30.              opdat = ov;
  31.              ov->spovartyp = SPO_NULL;
  32.              ov->vardata.l = 0;
  33.              Fread((genericptr_t) & (ov->spovartyp), 1, sizeof(ov->spovartyp),
  34.                    fd);
  35.  
  36.              switch (ov->spovartyp) {
  37.              case SPOVAR_NULL:
  38.                  break;
  39.              case SPOVAR_COORD:
  40.              case SPOVAR_REGION:
  41.              case SPOVAR_MAPCHAR:
  42.              case SPOVAR_MONST:
  43.              case SPOVAR_OBJ:
  44.              case SPOVAR_INT:
  45.                  Fread((genericptr_t) & (ov->vardata.l), 1,
  46.                        sizeof(ov->vardata.l), fd);
  47.                  break;
  48.              case SPOVAR_VARIABLE:
  49.              case SPOVAR_STRING:
  50.              case SPOVAR_SEL: {
  51.                  char *opd;
  52.  
  53.                  Fread((genericptr_t) &nsize, 1, sizeof(nsize), fd);
  54.                  opd = (char *) alloc(nsize + 1);
  55.  
  56.                  if (nsize)
  57.                      Fread(opd, 1, nsize, fd);
  58.                  opd[nsize] = 0;
  59.                  ov->vardata.str = opd;
  60.                  break;
  61.              }
  62.              default:
  63.                  panic("sp_level_loader: unknown opvar type %i",
  64.                        ov->spovartyp);
  65.              }
  66.          }
  67.  
  68.          lvl->opcodes[n_opcode].opdat = opdat;
  69.          n_opcode++;
  70.      } /*while*/
  71.  
  72.      return TRUE;
  73.  }
  74.  

sp_level_free

  1.  /* Frees the memory allocated for special level creation structs */
  2.  STATIC_OVL boolean
  3.  sp_level_free(lvl)
  4.  sp_lev *lvl;
  5.  {
  6.      static const char nhFunc[] = "sp_level_free";
  7.      long n_opcode = 0;
  8.  
  9.      while (n_opcode < lvl->n_opcodes) {
  10.          int opcode = lvl->opcodes[n_opcode].opcode;
  11.          struct opvar *opdat = lvl->opcodes[n_opcode].opdat;
  12.  
  13.          if (opcode < SPO_NULL || opcode >= MAX_SP_OPCODES)
  14.              panic("sp_level_free: unknown opcode %i", opcode);
  15.  
  16.          if (opdat)
  17.              opvar_free(opdat);
  18.          n_opcode++;
  19.      }
  20.      Free(lvl->opcodes);
  21.      lvl->opcodes = NULL;
  22.      return TRUE;
  23.  }
  24.  

splev_initlev

  1.  void
  2.  splev_initlev(linit)
  3.  lev_init *linit;
  4.  {
  5.      switch (linit->init_style) {
  6.      default:
  7.          impossible("Unrecognized level init style.");
  8.          break;
  9.      case LVLINIT_NONE:
  10.          break;
  11.      case LVLINIT_SOLIDFILL:
  12.          if (linit->lit == -1)
  13.              linit->lit = rn2(2);
  14.          lvlfill_solid(linit->filling, linit->lit);
  15.          break;
  16.      case LVLINIT_MAZEGRID:
  17.          lvlfill_maze_grid(2, 0, x_maze_max, y_maze_max, linit->filling);
  18.          break;
  19.      case LVLINIT_ROGUE:
  20.          makeroguerooms();
  21.          break;
  22.      case LVLINIT_MINES:
  23.          if (linit->lit == -1)
  24.              linit->lit = rn2(2);
  25.          if (linit->filling > -1)
  26.              lvlfill_solid(linit->filling, 0);
  27.          linit->icedpools = icedpools;
  28.          mkmap(linit);
  29.          break;
  30.      }
  31.  }
  32.  

frame_new

  1.  struct sp_frame *
  2.  frame_new(execptr)
  3.  long execptr;
  4.  {
  5.      struct sp_frame *frame =
  6.          (struct sp_frame *) alloc(sizeof(struct sp_frame));
  7.  
  8.      frame->next = NULL;
  9.      frame->variables = NULL;
  10.      frame->n_opcode = execptr;
  11.      frame->stack = (struct splevstack *) alloc(sizeof(struct splevstack));
  12.      splev_stack_init(frame->stack);
  13.      return frame;
  14.  }
  15.  

frame_del

  1.  void
  2.  frame_del(frame)
  3.  struct sp_frame *frame;
  4.  {
  5.      if (!frame)
  6.          return;
  7.      if (frame->stack) {
  8.          splev_stack_done(frame->stack);
  9.          frame->stack = NULL;
  10.      }
  11.      if (frame->variables) {
  12.          variable_list_del(frame->variables);
  13.          frame->variables = NULL;
  14.      }
  15.      Free(frame);
  16.  }
  17.  

spo_frame_push

  1.  void
  2.  spo_frame_push(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      struct sp_frame *tmpframe = frame_new(coder->frame->n_opcode);
  6.  
  7.      tmpframe->next = coder->frame;
  8.      coder->frame = tmpframe;
  9.  }
  10.  

spo_frame_pop

  1.  void
  2.  spo_frame_pop(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      if (coder->frame && coder->frame->next) {
  6.          struct sp_frame *tmpframe = coder->frame->next;
  7.  
  8.          frame_del(coder->frame);
  9.          coder->frame = tmpframe;
  10.          coder->stack = coder->frame->stack;
  11.      }
  12.  }
  13.  

sp_code_jmpaddr

  1.  long
  2.  sp_code_jmpaddr(curpos, jmpaddr)
  3.  long curpos, jmpaddr;
  4.  {
  5.      return (curpos + jmpaddr);
  6.  }
  7.  

spo_call

  1.  void
  2.  spo_call(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_call";
  6.      struct opvar *addr;
  7.      struct opvar *params;
  8.      struct sp_frame *tmpframe;
  9.  
  10.      if (!OV_pop_i(addr) || !OV_pop_i(params))
  11.          return;
  12.      if (OV_i(params) < 0)
  13.          return;
  14.  
  15.      tmpframe = frame_new(sp_code_jmpaddr(coder->frame->n_opcode,
  16.                                           OV_i(addr) - 1));
  17.  
  18.      while (OV_i(params)-- > 0) {
  19.          splev_stack_push(tmpframe->stack, splev_stack_getdat_any(coder));
  20.      }
  21.      splev_stack_reverse(tmpframe->stack);
  22.  
  23.      /* push a frame */
  24.      tmpframe->next = coder->frame;
  25.      coder->frame = tmpframe;
  26.  
  27.      opvar_free(addr);
  28.      opvar_free(params);
  29.  }
  30.  

spo_return

  1.  void
  2.  spo_return(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_return";
  6.      struct opvar *params;
  7.  
  8.      if (!coder->frame || !coder->frame->next)
  9.          panic("return: no frame.");
  10.      if (!OV_pop_i(params))
  11.          return;
  12.      if (OV_i(params) < 0)
  13.          return;
  14.  
  15.      while (OV_i(params)-- > 0) {
  16.          splev_stack_push(coder->frame->next->stack,
  17.                           splev_stack_pop(coder->stack));
  18.      }
  19.  
  20.      /* pop the frame */
  21.      if (coder->frame->next) {
  22.          struct sp_frame *tmpframe = coder->frame->next;
  23.          frame_del(coder->frame);
  24.          coder->frame = tmpframe;
  25.          coder->stack = coder->frame->stack;
  26.      }
  27.  
  28.      opvar_free(params);
  29.  }
  30.  

spo_end_moninvent

  1.  /*ARGUSED*/
  2.  void
  3.  spo_end_moninvent(coder)
  4.  struct sp_coder *coder UNUSED;
  5.  {
  6.      if (invent_carrying_monster)
  7.          m_dowear(invent_carrying_monster, TRUE);
  8.      invent_carrying_monster = NULL;
  9.  }
  10.  

spo_pop_container

  1.  /*ARGUSED*/
  2.  void
  3.  spo_pop_container(coder)
  4.  struct sp_coder *coder UNUSED;
  5.  {
  6.      if (container_idx > 0) {
  7.          container_idx--;
  8.          container_obj[container_idx] = NULL;
  9.      }
  10.  }
  11.  

spo_message

  1.  void
  2.  spo_message(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_message";
  6.      struct opvar *op;
  7.      char *msg, *levmsg;
  8.      int old_n, n;
  9.  
  10.      if (!OV_pop_s(op))
  11.          return;
  12.      msg = OV_s(op);
  13.      if (!msg)
  14.          return;
  15.  
  16.      old_n = lev_message ? (strlen(lev_message) + 1) : 0;
  17.      n = strlen(msg);
  18.  
  19.      levmsg = (char *) alloc(old_n + n + 1);
  20.      if (old_n)
  21.          levmsg[old_n - 1] = '\n';
  22.      if (lev_message)
  23.          (void) memcpy((genericptr_t) levmsg, (genericptr_t) lev_message,
  24.                        old_n - 1);
  25.      (void) memcpy((genericptr_t) &levmsg[old_n], msg, n);
  26.      levmsg[old_n + n] = '\0';
  27.      Free(lev_message);
  28.      lev_message = levmsg;
  29.      opvar_free(op);
  30.  }
  31.  

spo_monster

  1.  void
  2.  spo_monster(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_monster";
  6.      int nparams = 0;
  7.      struct opvar *varparam;
  8.      struct opvar *id, *mcoord, *has_inv;
  9.      monster tmpmons;
  10.  
  11.      tmpmons.peaceful = -1;
  12.      tmpmons.asleep = -1;
  13.      tmpmons.name.str = (char *) 0;
  14.      tmpmons.appear = 0;
  15.      tmpmons.appear_as.str = (char *) 0;
  16.      tmpmons.align = -MAX_REGISTERS - 2;
  17.      tmpmons.female = 0;
  18.      tmpmons.invis = 0;
  19.      tmpmons.cancelled = 0;
  20.      tmpmons.revived = 0;
  21.      tmpmons.avenge = 0;
  22.      tmpmons.fleeing = 0;
  23.      tmpmons.blinded = 0;
  24.      tmpmons.paralyzed = 0;
  25.      tmpmons.stunned = 0;
  26.      tmpmons.confused = 0;
  27.      tmpmons.seentraps = 0;
  28.      tmpmons.has_invent = 0;
  29.  
  30.      if (!OV_pop_i(has_inv))
  31.          return;
  32.  
  33.      if (!OV_pop_i(varparam))
  34.          return;
  35.  
  36.      while ((nparams++ < (SP_M_V_END + 1)) && (OV_typ(varparam) == SPOVAR_INT)
  37.             && (OV_i(varparam) >= 0) && (OV_i(varparam) < SP_M_V_END)) {
  38.          struct opvar *parm = NULL;
  39.  
  40.          OV_pop(parm);
  41.          switch (OV_i(varparam)) {
  42.          case SP_M_V_NAME:
  43.              if ((OV_typ(parm) == SPOVAR_STRING) && !tmpmons.name.str)
  44.                  tmpmons.name.str = dupstr(OV_s(parm));
  45.              break;
  46.          case SP_M_V_APPEAR:
  47.              if ((OV_typ(parm) == SPOVAR_INT) && !tmpmons.appear_as.str) {
  48.                  tmpmons.appear = OV_i(parm);
  49.                  opvar_free(parm);
  50.                  OV_pop(parm);
  51.                  tmpmons.appear_as.str = dupstr(OV_s(parm));
  52.              }
  53.              break;
  54.          case SP_M_V_ASLEEP:
  55.              if (OV_typ(parm) == SPOVAR_INT)
  56.                  tmpmons.asleep = OV_i(parm);
  57.              break;
  58.          case SP_M_V_ALIGN:
  59.              if (OV_typ(parm) == SPOVAR_INT)
  60.                  tmpmons.align = OV_i(parm);
  61.              break;
  62.          case SP_M_V_PEACEFUL:
  63.              if (OV_typ(parm) == SPOVAR_INT)
  64.                  tmpmons.peaceful = OV_i(parm);
  65.              break;
  66.          case SP_M_V_FEMALE:
  67.              if (OV_typ(parm) == SPOVAR_INT)
  68.                  tmpmons.female = OV_i(parm);
  69.              break;
  70.          case SP_M_V_INVIS:
  71.              if (OV_typ(parm) == SPOVAR_INT)
  72.                  tmpmons.invis = OV_i(parm);
  73.              break;
  74.          case SP_M_V_CANCELLED:
  75.              if (OV_typ(parm) == SPOVAR_INT)
  76.                  tmpmons.cancelled = OV_i(parm);
  77.              break;
  78.          case SP_M_V_REVIVED:
  79.              if (OV_typ(parm) == SPOVAR_INT)
  80.                  tmpmons.revived = OV_i(parm);
  81.              break;
  82.          case SP_M_V_AVENGE:
  83.              if (OV_typ(parm) == SPOVAR_INT)
  84.                  tmpmons.avenge = OV_i(parm);
  85.              break;
  86.          case SP_M_V_FLEEING:
  87.              if (OV_typ(parm) == SPOVAR_INT)
  88.                  tmpmons.fleeing = OV_i(parm);
  89.              break;
  90.          case SP_M_V_BLINDED:
  91.              if (OV_typ(parm) == SPOVAR_INT)
  92.                  tmpmons.blinded = OV_i(parm);
  93.              break;
  94.          case SP_M_V_PARALYZED:
  95.              if (OV_typ(parm) == SPOVAR_INT)
  96.                  tmpmons.paralyzed = OV_i(parm);
  97.              break;
  98.          case SP_M_V_STUNNED:
  99.              if (OV_typ(parm) == SPOVAR_INT)
  100.                  tmpmons.stunned = OV_i(parm);
  101.              break;
  102.          case SP_M_V_CONFUSED:
  103.              if (OV_typ(parm) == SPOVAR_INT)
  104.                  tmpmons.confused = OV_i(parm);
  105.              break;
  106.          case SP_M_V_SEENTRAPS:
  107.              if (OV_typ(parm) == SPOVAR_INT)
  108.                  tmpmons.seentraps = OV_i(parm);
  109.              break;
  110.          case SP_M_V_END:
  111.              nparams = SP_M_V_END + 1;
  112.              break;
  113.          default:
  114.              impossible("MONSTER with unknown variable param type!");
  115.              break;
  116.          }
  117.          opvar_free(parm);
  118.          if (OV_i(varparam) != SP_M_V_END) {
  119.              opvar_free(varparam);
  120.              OV_pop(varparam);
  121.          }
  122.      }
  123.  
  124.      if (!OV_pop_c(mcoord))
  125.          panic("no monster coord?");
  126.  
  127.      if (!OV_pop_typ(id, SPOVAR_MONST))
  128.          panic("no mon type");
  129.  
  130.      tmpmons.id = SP_MONST_PM(OV_i(id));
  131.      tmpmons.class = SP_MONST_CLASS(OV_i(id));
  132.      tmpmons.coord = OV_i(mcoord);
  133.      tmpmons.has_invent = OV_i(has_inv);
  134.  
  135.      create_monster(&tmpmons, coder->croom);
  136.  
  137.      Free(tmpmons.name.str);
  138.      Free(tmpmons.appear_as.str);
  139.      opvar_free(id);
  140.      opvar_free(mcoord);
  141.      opvar_free(has_inv);
  142.      opvar_free(varparam);
  143.  }
  144.  

spo_object

  1.  void
  2.  spo_object(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_object";
  6.      int nparams = 0;
  7.      long quancnt;
  8.      struct opvar *varparam;
  9.      struct opvar *id, *containment;
  10.      object tmpobj;
  11.  
  12.      tmpobj.spe = -127;
  13.      tmpobj.curse_state = -1;
  14.      tmpobj.corpsenm = NON_PM;
  15.      tmpobj.name.str = (char *) 0;
  16.      tmpobj.quan = -1;
  17.      tmpobj.buried = 0;
  18.      tmpobj.lit = 0;
  19.      tmpobj.eroded = 0;
  20.      tmpobj.locked = 0;
  21.      tmpobj.trapped = 0;
  22.      tmpobj.recharged = 0;
  23.      tmpobj.invis = 0;
  24.      tmpobj.greased = 0;
  25.      tmpobj.broken = 0;
  26.      tmpobj.coord = SP_COORD_PACK_RANDOM(0);
  27.  
  28.      if (!OV_pop_i(containment))
  29.          return;
  30.  
  31.      if (!OV_pop_i(varparam))
  32.          return;
  33.  
  34.      while ((nparams++ < (SP_O_V_END + 1)) && (OV_typ(varparam) == SPOVAR_INT)
  35.             && (OV_i(varparam) >= 0) && (OV_i(varparam) < SP_O_V_END)) {
  36.          struct opvar *parm;
  37.          OV_pop(parm);
  38.          switch (OV_i(varparam)) {
  39.          case SP_O_V_NAME:
  40.              if ((OV_typ(parm) == SPOVAR_STRING) && !tmpobj.name.str)
  41.                  tmpobj.name.str = dupstr(OV_s(parm));
  42.              break;
  43.          case SP_O_V_CORPSENM:
  44.              if (OV_typ(parm) == SPOVAR_MONST) {
  45.                  char monclass = SP_MONST_CLASS(OV_i(parm));
  46.                  int monid = SP_MONST_PM(OV_i(parm));
  47.  
  48.                  if (monid >= 0 && monid < NUMMONS) {
  49.                      tmpobj.corpsenm = monid;
  50.                      break; /* we're done! */
  51.                  } else {
  52.                      struct permonst *pm = (struct permonst *) 0;
  53.                      if (def_char_to_monclass(monclass) != MAXMCLASSES) {
  54.                          pm = mkclass(def_char_to_monclass(monclass), G_NOGEN);
  55.                      } else {
  56.                          pm = rndmonst();
  57.                      }
  58.                      if (pm)
  59.                          tmpobj.corpsenm = monsndx(pm);
  60.                  }
  61.              }
  62.              break;
  63.          case SP_O_V_CURSE:
  64.              if (OV_typ(parm) == SPOVAR_INT)
  65.                  tmpobj.curse_state = OV_i(parm);
  66.              break;
  67.          case SP_O_V_SPE:
  68.              if (OV_typ(parm) == SPOVAR_INT)
  69.                  tmpobj.spe = OV_i(parm);
  70.              break;
  71.          case SP_O_V_QUAN:
  72.              if (OV_typ(parm) == SPOVAR_INT)
  73.                  tmpobj.quan = OV_i(parm);
  74.              break;
  75.          case SP_O_V_BURIED:
  76.              if (OV_typ(parm) == SPOVAR_INT)
  77.                  tmpobj.buried = OV_i(parm);
  78.              break;
  79.          case SP_O_V_LIT:
  80.              if (OV_typ(parm) == SPOVAR_INT)
  81.                  tmpobj.lit = OV_i(parm);
  82.              break;
  83.          case SP_O_V_ERODED:
  84.              if (OV_typ(parm) == SPOVAR_INT)
  85.                  tmpobj.eroded = OV_i(parm);
  86.              break;
  87.          case SP_O_V_LOCKED:
  88.              if (OV_typ(parm) == SPOVAR_INT)
  89.                  tmpobj.locked = OV_i(parm);
  90.              break;
  91.          case SP_O_V_TRAPPED:
  92.              if (OV_typ(parm) == SPOVAR_INT)
  93.                  tmpobj.trapped = OV_i(parm);
  94.              break;
  95.          case SP_O_V_RECHARGED:
  96.              if (OV_typ(parm) == SPOVAR_INT)
  97.                  tmpobj.recharged = OV_i(parm);
  98.              break;
  99.          case SP_O_V_INVIS:
  100.              if (OV_typ(parm) == SPOVAR_INT)
  101.                  tmpobj.invis = OV_i(parm);
  102.              break;
  103.          case SP_O_V_GREASED:
  104.              if (OV_typ(parm) == SPOVAR_INT)
  105.                  tmpobj.greased = OV_i(parm);
  106.              break;
  107.          case SP_O_V_BROKEN:
  108.              if (OV_typ(parm) == SPOVAR_INT)
  109.                  tmpobj.broken = OV_i(parm);
  110.              break;
  111.          case SP_O_V_COORD:
  112.              if (OV_typ(parm) != SPOVAR_COORD)
  113.                  panic("no coord for obj?");
  114.              tmpobj.coord = OV_i(parm);
  115.              break;
  116.          case SP_O_V_END:
  117.              nparams = SP_O_V_END + 1;
  118.              break;
  119.          default:
  120.              impossible("OBJECT with unknown variable param type!");
  121.              break;
  122.          }
  123.          opvar_free(parm);
  124.          if (OV_i(varparam) != SP_O_V_END) {
  125.              opvar_free(varparam);
  126.              OV_pop(varparam);
  127.          }
  128.      }
  129.  
  130.      if (!OV_pop_typ(id, SPOVAR_OBJ))
  131.          panic("no obj type");
  132.  
  133.      tmpobj.id = SP_OBJ_TYP(OV_i(id));
  134.      tmpobj.class = SP_OBJ_CLASS(OV_i(id));
  135.      tmpobj.containment = OV_i(containment);
  136.  
  137.      quancnt = (tmpobj.id > STRANGE_OBJECT) ? tmpobj.quan : 0;
  138.  
  139.      do {
  140.          create_object(&tmpobj, coder->croom);
  141.          quancnt--;
  142.      } while ((quancnt > 0) && ((tmpobj.id > STRANGE_OBJECT)
  143.                                 && !objects[tmpobj.id].oc_merge));
  144.  
  145.      Free(tmpobj.name.str);
  146.      opvar_free(varparam);
  147.      opvar_free(id);
  148.      opvar_free(containment);
  149.  }
  150.  

spo_level_flags

  1.  void
  2.  spo_level_flags(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_level_flags";
  6.      struct opvar *flagdata;
  7.      long lflags;
  8.  
  9.      if (!OV_pop_i(flagdata))
  10.          return;
  11.      lflags = OV_i(flagdata);
  12.  
  13.      if (lflags & NOTELEPORT)
  14.          level.flags.noteleport = 1;
  15.      if (lflags & HARDFLOOR)
  16.          level.flags.hardfloor = 1;
  17.      if (lflags & NOMMAP)
  18.          level.flags.nommap = 1;
  19.      if (lflags & SHORTSIGHTED)
  20.          level.flags.shortsighted = 1;
  21.      if (lflags & ARBOREAL)
  22.          level.flags.arboreal = 1;
  23.      if (lflags & MAZELEVEL)
  24.          level.flags.is_maze_lev = 1;
  25.      if (lflags & PREMAPPED)
  26.          coder->premapped = TRUE;
  27.      if (lflags & SHROUD)
  28.          level.flags.hero_memory = 0;
  29.      if (lflags & GRAVEYARD)
  30.          level.flags.graveyard = 1;
  31.      if (lflags & ICEDPOOLS)
  32.          icedpools = TRUE;
  33.      if (lflags & SOLIDIFY)
  34.          coder->solidify = TRUE;
  35.      if (lflags & CORRMAZE)
  36.          level.flags.corrmaze = TRUE;
  37.      if (lflags & CHECK_INACCESSIBLES)
  38.          coder->check_inaccessibles = TRUE;
  39.  
  40.      opvar_free(flagdata);
  41.  }
  42.  

spo_initlevel

  1.  void
  2.  spo_initlevel(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_initlevel";
  6.      lev_init init_lev;
  7.      struct opvar *init_style, *fg, *bg, *smoothed, *joined, *lit, *walled,
  8.          *filling;
  9.  
  10.      if (!OV_pop_i(fg) || !OV_pop_i(bg) || !OV_pop_i(smoothed)
  11.          || !OV_pop_i(joined) || !OV_pop_i(lit) || !OV_pop_i(walled)
  12.          || !OV_pop_i(filling) || !OV_pop_i(init_style))
  13.          return;
  14.  
  15.      splev_init_present = TRUE;
  16.  
  17.      init_lev.init_style = OV_i(init_style);
  18.      init_lev.fg = OV_i(fg);
  19.      init_lev.bg = OV_i(bg);
  20.      init_lev.smoothed = OV_i(smoothed);
  21.      init_lev.joined = OV_i(joined);
  22.      init_lev.lit = OV_i(lit);
  23.      init_lev.walled = OV_i(walled);
  24.      init_lev.filling = OV_i(filling);
  25.  
  26.      coder->lvl_is_joined = OV_i(joined);
  27.  
  28.      splev_initlev(&init_lev);
  29.  
  30.      opvar_free(init_style);
  31.      opvar_free(fg);
  32.      opvar_free(bg);
  33.      opvar_free(smoothed);
  34.      opvar_free(joined);
  35.      opvar_free(lit);
  36.      opvar_free(walled);
  37.      opvar_free(filling);
  38.  }
  39.  

spo_engraving

  1.  void
  2.  spo_engraving(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_engraving";
  6.      struct opvar *etyp, *txt, *ecoord;
  7.      xchar x, y;
  8.  
  9.      if (!OV_pop_i(etyp) || !OV_pop_s(txt) || !OV_pop_c(ecoord))
  10.          return;
  11.  
  12.      get_location_coord(&x, &y, DRY, coder->croom, OV_i(ecoord));
  13.      make_engr_at(x, y, OV_s(txt), 0L, OV_i(etyp));
  14.  
  15.      opvar_free(etyp);
  16.      opvar_free(txt);
  17.      opvar_free(ecoord);
  18.  }
  19.  

spo_mineralize

  1.  void
  2.  spo_mineralize(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_mineralize";
  6.      struct opvar *kelp_pool, *kelp_moat, *gold_prob, *gem_prob;
  7.  
  8.      if (!OV_pop_i(gem_prob) || !OV_pop_i(gold_prob) || !OV_pop_i(kelp_moat)
  9.          || !OV_pop_i(kelp_pool))
  10.          return;
  11.  
  12.      mineralize(OV_i(kelp_pool), OV_i(kelp_moat), OV_i(gold_prob),
  13.                 OV_i(gem_prob), TRUE);
  14.  
  15.      opvar_free(gem_prob);
  16.      opvar_free(gold_prob);
  17.      opvar_free(kelp_moat);
  18.      opvar_free(kelp_pool);
  19.  }
  20.  

spo_room

  1.  void
  2.  spo_room(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_room";
  6.  
  7.      if (coder->n_subroom > MAX_NESTED_ROOMS) {
  8.          panic("Too deeply nested rooms?!");
  9.      } else {
  10.          struct opvar *rflags, *h, *w, *yalign, *xalign, *y, *x, *rlit,
  11.              *chance, *rtype;
  12.          room tmproom;
  13.          struct mkroom *tmpcr;
  14.  
  15.          if (!OV_pop_i(h) || !OV_pop_i(w) || !OV_pop_i(y) || !OV_pop_i(x)
  16.              || !OV_pop_i(yalign) || !OV_pop_i(xalign) || !OV_pop_i(rflags)
  17.              || !OV_pop_i(rlit) || !OV_pop_i(chance) || !OV_pop_i(rtype))
  18.              return;
  19.  
  20.          tmproom.x = OV_i(x);
  21.          tmproom.y = OV_i(y);
  22.          tmproom.w = OV_i(w);
  23.          tmproom.h = OV_i(h);
  24.          tmproom.xalign = OV_i(xalign);
  25.          tmproom.yalign = OV_i(yalign);
  26.          tmproom.rtype = OV_i(rtype);
  27.          tmproom.chance = OV_i(chance);
  28.          tmproom.rlit = OV_i(rlit);
  29.          tmproom.filled = (OV_i(rflags) & (1 << 0));
  30.          /*tmproom.irregular = (OV_i(rflags) & (1 << 1));*/
  31.          tmproom.joined = !(OV_i(rflags) & (1 << 2));
  32.  
  33.          opvar_free(x);
  34.          opvar_free(y);
  35.          opvar_free(w);
  36.          opvar_free(h);
  37.          opvar_free(xalign);
  38.          opvar_free(yalign);
  39.          opvar_free(rtype);
  40.          opvar_free(chance);
  41.          opvar_free(rlit);
  42.          opvar_free(rflags);
  43.  
  44.          if (!coder->failed_room[coder->n_subroom - 1]) {
  45.              tmpcr = build_room(&tmproom, coder->croom);
  46.              if (tmpcr) {
  47.                  coder->tmproomlist[coder->n_subroom] = tmpcr;
  48.                  coder->failed_room[coder->n_subroom] = FALSE;
  49.                  coder->n_subroom++;
  50.                  return;
  51.              }
  52.          } /* failed to create parent room, so fail this too */
  53.      }
  54.      coder->tmproomlist[coder->n_subroom] = (struct mkroom *) 0;
  55.      coder->failed_room[coder->n_subroom] = TRUE;
  56.      coder->n_subroom++;
  57.  }
  58.  

spo_endroom

  1.  void
  2.  spo_endroom(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      if (coder->n_subroom > 1) {
  6.          coder->n_subroom--;
  7.          coder->tmproomlist[coder->n_subroom] = NULL;
  8.          coder->failed_room[coder->n_subroom] = TRUE;
  9.      } else {
  10.          /* no subroom, get out of top-level room */
  11.          /* Need to ensure xstart/ystart/xsize/ysize have something sensible,
  12.             in case there's some stuff to be created outside the outermost
  13.             room,
  14.             and there's no MAP.
  15.          */
  16.          if (xsize <= 1 && ysize <= 1) {
  17.              xstart = 1;
  18.              ystart = 0;
  19.              xsize = COLNO - 1;
  20.              ysize = ROWNO;
  21.          }
  22.      }
  23.  }
  24.  

spo_stair

  1.  void
  2.  spo_stair(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_stair";
  6.      xchar x, y;
  7.      struct opvar *up, *scoord;
  8.      struct trap *badtrap;
  9.  
  10.      if (!OV_pop_i(up) || !OV_pop_c(scoord))
  11.          return;
  12.  
  13.      get_location_coord(&x, &y, DRY, coder->croom, OV_i(scoord));
  14.      if ((badtrap = t_at(x, y)) != 0)
  15.          deltrap(badtrap);
  16.      mkstairs(x, y, (char) OV_i(up), coder->croom);
  17.      SpLev_Map[x][y] = 1;
  18.  
  19.      opvar_free(scoord);
  20.      opvar_free(up);
  21.  }
  22.  

spo_ladder

  1.  void
  2.  spo_ladder(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_ladder";
  6.      xchar x, y;
  7.      struct opvar *up, *lcoord;
  8.  
  9.      if (!OV_pop_i(up) || !OV_pop_c(lcoord))
  10.          return;
  11.  
  12.      get_location_coord(&x, &y, DRY, coder->croom, OV_i(lcoord));
  13.  
  14.      levl[x][y].typ = LADDER;
  15.      SpLev_Map[x][y] = 1;
  16.      if (OV_i(up)) {
  17.          xupladder = x;
  18.          yupladder = y;
  19.          levl[x][y].ladder = LA_UP;
  20.      } else {
  21.          xdnladder = x;
  22.          ydnladder = y;
  23.          levl[x][y].ladder = LA_DOWN;
  24.      }
  25.      opvar_free(lcoord);
  26.      opvar_free(up);
  27.  }
  28.  

spo_grave

  1.  void
  2.  spo_grave(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_grave";
  6.      struct opvar *gcoord, *typ, *txt;
  7.      schar x, y;
  8.  
  9.      if (!OV_pop_i(typ) || !OV_pop_s(txt) || !OV_pop_c(gcoord))
  10.          return;
  11.  
  12.      get_location_coord(&x, &y, DRY, coder->croom, OV_i(gcoord));
  13.  
  14.      if (isok(x, y) && !t_at(x, y)) {
  15.          levl[x][y].typ = GRAVE;
  16.          switch (OV_i(typ)) {
  17.          case 2:
  18.              make_grave(x, y, OV_s(txt));
  19.              break;
  20.          case 1:
  21.              make_grave(x, y, NULL);
  22.              break;
  23.          default:
  24.              del_engr_at(x, y);
  25.              break;
  26.          }
  27.      }
  28.  
  29.      opvar_free(gcoord);
  30.      opvar_free(typ);
  31.      opvar_free(txt);
  32.  }
  33.  

spo_altar

  1.  void
  2.  spo_altar(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_altar";
  6.      struct opvar *al, *shrine, *acoord;
  7.      altar tmpaltar;
  8.  
  9.      if (!OV_pop_i(al) || !OV_pop_i(shrine) || !OV_pop_c(acoord))
  10.          return;
  11.  
  12.      tmpaltar.coord = OV_i(acoord);
  13.      tmpaltar.align = OV_i(al);
  14.      tmpaltar.shrine = OV_i(shrine);
  15.  
  16.      create_altar(&tmpaltar, coder->croom);
  17.  
  18.      opvar_free(acoord);
  19.      opvar_free(shrine);
  20.      opvar_free(al);
  21.  }
  22.  

spo_trap

  1.  void
  2.  spo_trap(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_trap";
  6.      struct opvar *type;
  7.      struct opvar *tcoord;
  8.      trap tmptrap;
  9.  
  10.      if (!OV_pop_i(type) || !OV_pop_c(tcoord))
  11.          return;
  12.  
  13.      tmptrap.coord = OV_i(tcoord);
  14.      tmptrap.type = OV_i(type);
  15.  
  16.      create_trap(&tmptrap, coder->croom);
  17.      opvar_free(tcoord);
  18.      opvar_free(type);
  19.  }
  20.  

spo_gold

  1.  void
  2.  spo_gold(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_gold";
  6.      struct opvar *gcoord, *amt;
  7.      schar x, y;
  8.      long amount;
  9.  
  10.      if (!OV_pop_c(gcoord) || !OV_pop_i(amt))
  11.          return;
  12.      amount = OV_i(amt);
  13.      get_location_coord(&x, &y, DRY, coder->croom, OV_i(gcoord));
  14.      if (amount == -1)
  15.          amount = rnd(200);
  16.      mkgold(amount, x, y);
  17.      opvar_free(gcoord);
  18.      opvar_free(amt);
  19.  }
  20.  

spo_corridor

  1.  void
  2.  spo_corridor(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_corridor";
  6.      struct opvar *deswall, *desdoor, *desroom, *srcwall, *srcdoor, *srcroom;
  7.      corridor tc;
  8.  
  9.      if (!OV_pop_i(deswall) || !OV_pop_i(desdoor) || !OV_pop_i(desroom)
  10.          || !OV_pop_i(srcwall) || !OV_pop_i(srcdoor) || !OV_pop_i(srcroom))
  11.          return;
  12.  
  13.      tc.src.room = OV_i(srcroom);
  14.      tc.src.door = OV_i(srcdoor);
  15.      tc.src.wall = OV_i(srcwall);
  16.      tc.dest.room = OV_i(desroom);
  17.      tc.dest.door = OV_i(desdoor);
  18.      tc.dest.wall = OV_i(deswall);
  19.  
  20.      create_corridor(&tc);
  21.  
  22.      opvar_free(deswall);
  23.      opvar_free(desdoor);
  24.      opvar_free(desroom);
  25.      opvar_free(srcwall);
  26.      opvar_free(srcdoor);
  27.      opvar_free(srcroom);
  28.  }
  29.  

selection_opvar

  1.  struct opvar *
  2.  selection_opvar(nbuf)
  3.  char *nbuf;
  4.  {
  5.      struct opvar *ov;
  6.      char buf[(COLNO * ROWNO) + 1];
  7.  
  8.      if (!nbuf) {
  9.          (void) memset(buf, 1, sizeof(buf));
  10.          buf[(COLNO * ROWNO)] = '\0';
  11.          ov = opvar_new_str(buf);
  12.      } else {
  13.          ov = opvar_new_str(nbuf);
  14.      }
  15.      ov->spovartyp = SPOVAR_SEL;
  16.      return ov;
  17.  }
  18.  

selection_getpoint

  1.  xchar
  2.  selection_getpoint(x, y, ov)
  3.  int x, y;
  4.  struct opvar *ov;
  5.  {
  6.      if (!ov || ov->spovartyp != SPOVAR_SEL)
  7.          return 0;
  8.      if (x < 0 || y < 0 || x >= COLNO || y >= ROWNO)
  9.          return 0;
  10.  
  11.      return (ov->vardata.str[COLNO * y + x] - 1);
  12.  }
  13.  

selection_setpoint

  1.  void
  2.  selection_setpoint(x, y, ov, c)
  3.  int x, y;
  4.  struct opvar *ov;
  5.  xchar c;
  6.  {
  7.      if (!ov || ov->spovartyp != SPOVAR_SEL)
  8.          return;
  9.      if (x < 0 || y < 0 || x >= COLNO || y >= ROWNO)
  10.          return;
  11.  
  12.      ov->vardata.str[COLNO * y + x] = (char) (c + 1);
  13.  }
  14.  

selection_not

  1.  struct opvar *
  2.  selection_not(s)
  3.  struct opvar *s;
  4.  {
  5.      struct opvar *ov;
  6.      int x, y;
  7.  
  8.      ov = selection_opvar((char *) 0);
  9.      if (!ov)
  10.          return NULL;
  11.  
  12.      for (x = 0; x < COLNO; x++)
  13.          for (y = 0; y < ROWNO; y++)
  14.              if (!selection_getpoint(x, y, s))
  15.                  selection_setpoint(x, y, ov, 1);
  16.  
  17.      return ov;
  18.  }
  19.  

selection_logical_oper

  1.  struct opvar *
  2.  selection_logical_oper(s1, s2, oper)
  3.  struct opvar *s1, *s2;
  4.  char oper;
  5.  {
  6.      struct opvar *ov;
  7.      int x, y;
  8.  
  9.      ov = selection_opvar((char *) 0);
  10.      if (!ov)
  11.          return NULL;
  12.  
  13.      for (x = 0; x < COLNO; x++)
  14.          for (y = 0; y < ROWNO; y++) {
  15.              switch (oper) {
  16.              default:
  17.              case '|':
  18.                  if (selection_getpoint(x, y, s1)
  19.                      || selection_getpoint(x, y, s2))
  20.                      selection_setpoint(x, y, ov, 1);
  21.                  break;
  22.              case '&':
  23.                  if (selection_getpoint(x, y, s1)
  24.                      && selection_getpoint(x, y, s2))
  25.                      selection_setpoint(x, y, ov, 1);
  26.                  break;
  27.              }
  28.          }
  29.  
  30.      return ov;
  31.  }
  32.  

selection_filter_mapchar

  1.  struct opvar *
  2.  selection_filter_mapchar(ov, mc)
  3.  struct opvar *ov;
  4.  struct opvar *mc;
  5.  {
  6.      int x, y;
  7.      schar mapc;
  8.      xchar lit;
  9.      struct opvar *ret = selection_opvar((char *) 0);
  10.  
  11.      if (!ov || !mc || !ret)
  12.          return NULL;
  13.      mapc = SP_MAPCHAR_TYP(OV_i(mc));
  14.      lit = SP_MAPCHAR_LIT(OV_i(mc));
  15.      for (x = 0; x < COLNO; x++)
  16.          for (y = 0; y < ROWNO; y++)
  17.              if (selection_getpoint(x, y, ov) && (levl[x][y].typ == mapc)) {
  18.                  switch (lit) {
  19.                  default:
  20.                  case -2:
  21.                      selection_setpoint(x, y, ret, 1);
  22.                      break;
  23.                  case -1:
  24.                      selection_setpoint(x, y, ret, rn2(2));
  25.                      break;
  26.                  case 0:
  27.                  case 1:
  28.                      if (levl[x][y].lit == lit)
  29.                          selection_setpoint(x, y, ret, 1);
  30.                      break;
  31.                  }
  32.              }
  33.      return ret;
  34.  }
  35.  

selection_filter_percent

  1.  void
  2.  selection_filter_percent(ov, percent)
  3.  struct opvar *ov;
  4.  int percent;
  5.  {
  6.      int x, y;
  7.  
  8.      if (!ov)
  9.          return;
  10.      for (x = 0; x < COLNO; x++)
  11.          for (y = 0; y < ROWNO; y++)
  12.              if (selection_getpoint(x, y, ov) && (rn2(100) >= percent))
  13.                  selection_setpoint(x, y, ov, 0);
  14.  }
  15.  

selection_rndcoord

  1.  STATIC_OVL int
  2.  selection_rndcoord(ov, x, y, removeit)
  3.  struct opvar *ov;
  4.  schar *x, *y;
  5.  boolean removeit;
  6.  {
  7.      int idx = 0;
  8.      int c;
  9.      int dx, dy;
  10.  
  11.      for (dx = 0; dx < COLNO; dx++)
  12.          for (dy = 0; dy < ROWNO; dy++)
  13.              if (isok(dx, dy) && selection_getpoint(dx, dy, ov))
  14.                  idx++;
  15.  
  16.      if (idx) {
  17.          c = rn2(idx);
  18.          for (dx = 0; dx < COLNO; dx++)
  19.              for (dy = 0; dy < ROWNO; dy++)
  20.                  if (isok(dx, dy) && selection_getpoint(dx, dy, ov)) {
  21.                      if (!c) {
  22.                          *x = dx;
  23.                          *y = dy;
  24.                          if (removeit) selection_setpoint(dx, dy, ov, 0);
  25.                          return 1;
  26.                      }
  27.                      c--;
  28.                  }
  29.      }
  30.      *x = *y = -1;
  31.      return 0;
  32.  }
  33.  

selection_do_grow

  1.  void
  2.  selection_do_grow(ov, dir)
  3.  struct opvar *ov;
  4.  int dir;
  5.  {
  6.      int x, y, c;
  7.      char tmp[COLNO][ROWNO];
  8.  
  9.      if (ov->spovartyp != SPOVAR_SEL)
  10.          return;
  11.      if (!ov)
  12.          return;
  13.  
  14.      (void) memset(tmp, 0, sizeof(tmp));
  15.  
  16.      for (x = 0; x < COLNO; x++)
  17.          for (y = 0; y < ROWNO; y++) {
  18.              c = 0;
  19.              if ((dir & W_WEST) && (x > 0)
  20.                  && (selection_getpoint(x - 1, y, ov)))
  21.                  c++;
  22.              if ((dir & (W_WEST | W_NORTH)) && (x > 0) && (y > 0)
  23.                  && (selection_getpoint(x - 1, y - 1, ov)))
  24.                  c++;
  25.              if ((dir & W_NORTH) && (y > 0)
  26.                  && (selection_getpoint(x, y - 1, ov)))
  27.                  c++;
  28.              if ((dir & (W_NORTH | W_EAST)) && (y > 0) && (x < COLNO - 1)
  29.                  && (selection_getpoint(x + 1, y - 1, ov)))
  30.                  c++;
  31.              if ((dir & W_EAST) && (x < COLNO - 1)
  32.                  && (selection_getpoint(x + 1, y, ov)))
  33.                  c++;
  34.              if ((dir & (W_EAST | W_SOUTH)) && (x < COLNO - 1)
  35.                  && (y < ROWNO - 1) && (selection_getpoint(x + 1, y + 1, ov)))
  36.                  c++;
  37.              if ((dir & W_SOUTH) && (y < ROWNO - 1)
  38.                  && (selection_getpoint(x, y + 1, ov)))
  39.                  c++;
  40.              if ((dir & (W_SOUTH | W_WEST)) && (y < ROWNO - 1) && (x > 0)
  41.                  && (selection_getpoint(x - 1, y + 1, ov)))
  42.                  c++;
  43.              if (c)
  44.                  tmp[x][y] = 1;
  45.          }
  46.  
  47.      for (x = 0; x < COLNO; x++)
  48.          for (y = 0; y < ROWNO; y++)
  49.              if (tmp[x][y])
  50.                  selection_setpoint(x, y, ov, 1);
  51.  }
  52.  

set_selection_floodfillchk

  1.  STATIC_VAR int FDECL((*selection_flood_check_func), (int, int));
  2.  STATIC_VAR schar floodfillchk_match_under_typ;
  3.  
  4.  STATIC_OVL void
  5.  set_selection_floodfillchk(f)
  6.  int FDECL((*f), (int, int));
  7.  {
  8.      selection_flood_check_func = f;
  9.  }
  10.  

floodfillchk_match_under

  1.  STATIC_OVL int
  2.  floodfillchk_match_under(x,y)
  3.  int x,y;
  4.  {
  5.      return (floodfillchk_match_under_typ == levl[x][y].typ);
  6.  }
  7.  

floodfillchk_match_accessible

  1.  STATIC_OVL int
  2.  floodfillchk_match_accessible(x, y)
  3.  int x, y;
  4.  {
  5.      return (ACCESSIBLE(levl[x][y].typ)
  6.              || levl[x][y].typ == SDOOR
  7.              || levl[x][y].typ == SCORR);
  8.  }
  9.  

selection_flood

  1.  STATIC_OVL void
  2.  selection_floodfill(ov, x, y, diagonals)
  3.  struct opvar *ov;
  4.  int x, y;
  5.  boolean diagonals;
  6.  {
  7.      static const char nhFunc[] = "selection_floodfill";
  8.      struct opvar *tmp = selection_opvar((char *) 0);
  9.  #define SEL_FLOOD_STACK (COLNO * ROWNO)
  10.  #define SEL_FLOOD(nx, ny)                     \
  11.      do {                                      \
  12.          if (idx < SEL_FLOOD_STACK) {          \
  13.              dx[idx] = (nx);                   \
  14.              dy[idx] = (ny);                   \
  15.              idx++;                            \
  16.          } else                                \
  17.              panic(floodfill_stack_overrun);   \
  18.      } while (0)
  19.  #define SEL_FLOOD_CHKDIR(mx,my,sel)                  \
  20.      if (isok((mx), (my))                             \
  21.          && (*selection_flood_check_func)((mx), (my)) \
  22.          && !selection_getpoint((mx), (my), (sel)))   \
  23.          SEL_FLOOD((mx), (my))
  24.      static const char floodfill_stack_overrun[] = "floodfill stack overrun";
  25.      int idx = 0;
  26.      xchar dx[SEL_FLOOD_STACK];
  27.      xchar dy[SEL_FLOOD_STACK];
  28.  
  29.      if (selection_flood_check_func == NULL) {
  30.          opvar_free(tmp);
  31.          return;
  32.      }
  33.      SEL_FLOOD(x, y);
  34.      do {
  35.          idx--;
  36.          x = dx[idx];
  37.          y = dy[idx];
  38.          if (isok(x, y)) {
  39.              selection_setpoint(x, y, ov, 1);
  40.              selection_setpoint(x, y, tmp, 1);
  41.          }
  42.          SEL_FLOOD_CHKDIR((x + 1), y, tmp);
  43.          SEL_FLOOD_CHKDIR((x - 1), y, tmp);
  44.          SEL_FLOOD_CHKDIR(x, (y + 1), tmp);
  45.          SEL_FLOOD_CHKDIR(x, (y - 1), tmp);
  46.          if (diagonals) {
  47.              SEL_FLOOD_CHKDIR((x + 1), (y + 1), tmp);
  48.              SEL_FLOOD_CHKDIR((x - 1), (y - 1), tmp);
  49.              SEL_FLOOD_CHKDIR((x - 1), (y + 1), tmp);
  50.              SEL_FLOOD_CHKDIR((x + 1), (y - 1), tmp);
  51.          }
  52.      } while (idx > 0);
  53.  #undef SEL_FLOOD
  54.  #undef SEL_FLOOD_STACK
  55.  #undef SEL_FLOOD_CHKDIR
  56.      opvar_free(tmp);
  57.  }
  58.  

selection_do_ellipse

  1.  /* McIlroy's Ellipse Algorithm */
  2.  void
  3.  selection_do_ellipse(ov, xc, yc, a, b, filled)
  4.  struct opvar *ov;
  5.  int xc, yc, a, b, filled;
  6.  { /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
  7.      int x = 0, y = b;
  8.      long a2 = (long) a * a, b2 = (long) b * b;
  9.      long crit1 = -(a2 / 4 + a % 2 + b2);
  10.      long crit2 = -(b2 / 4 + b % 2 + a2);
  11.      long crit3 = -(b2 / 4 + b % 2);
  12.      long t = -a2 * y; /* e(x+1/2,y-1/2) - (a^2+b^2)/4 */
  13.      long dxt = 2 * b2 * x, dyt = -2 * a2 * y;
  14.      long d2xt = 2 * b2, d2yt = 2 * a2;
  15.      long width = 1;
  16.      long i;
  17.  
  18.      if (!ov)
  19.          return;
  20.  
  21.      filled = !filled;
  22.  
  23.      if (!filled) {
  24.          while (y >= 0 && x <= a) {
  25.              selection_setpoint(xc + x, yc + y, ov, 1);
  26.              if (x != 0 || y != 0)
  27.                  selection_setpoint(xc - x, yc - y, ov, 1);
  28.              if (x != 0 && y != 0) {
  29.                  selection_setpoint(xc + x, yc - y, ov, 1);
  30.                  selection_setpoint(xc - x, yc + y, ov, 1);
  31.              }
  32.              if (t + b2 * x <= crit1       /* e(x+1,y-1/2) <= 0 */
  33.                  || t + a2 * y <= crit3) { /* e(x+1/2,y) <= 0 */
  34.                  x++;
  35.                  dxt += d2xt;
  36.                  t += dxt;
  37.              } else if (t - a2 * y > crit2) { /* e(x+1/2,y-1) > 0 */
  38.                  y--;
  39.                  dyt += d2yt;
  40.                  t += dyt;
  41.              } else {
  42.                  x++;
  43.                  dxt += d2xt;
  44.                  t += dxt;
  45.                  y--;
  46.                  dyt += d2yt;
  47.                  t += dyt;
  48.              }
  49.          }
  50.      } else {
  51.          while (y >= 0 && x <= a) {
  52.              if (t + b2 * x <= crit1       /* e(x+1,y-1/2) <= 0 */
  53.                  || t + a2 * y <= crit3) { /* e(x+1/2,y) <= 0 */
  54.                  x++;
  55.                  dxt += d2xt;
  56.                  t += dxt;
  57.                  width += 2;
  58.              } else if (t - a2 * y > crit2) { /* e(x+1/2,y-1) > 0 */
  59.                  for (i = 0; i < width; i++)
  60.                      selection_setpoint(xc - x + i, yc - y, ov, 1);
  61.                  if (y != 0)
  62.                      for (i = 0; i < width; i++)
  63.                          selection_setpoint(xc - x + i, yc + y, ov, 1);
  64.                  y--;
  65.                  dyt += d2yt;
  66.                  t += dyt;
  67.              } else {
  68.                  for (i = 0; i < width; i++)
  69.                      selection_setpoint(xc - x + i, yc - y, ov, 1);
  70.                  if (y != 0)
  71.                      for (i = 0; i < width; i++)
  72.                          selection_setpoint(xc - x + i, yc + y, ov, 1);
  73.                  x++;
  74.                  dxt += d2xt;
  75.                  t += dxt;
  76.                  y--;
  77.                  dyt += d2yt;
  78.                  t += dyt;
  79.                  width += 2;
  80.              }
  81.          }
  82.      }
  83.  }
  84.  

line_dist_coord

  1.  /* distance from line segment (x1,y1, x2,y2) to point (x3,y3) */
  2.  long
  3.  line_dist_coord(x1, y1, x2, y2, x3, y3)
  4.  long x1, y1, x2, y2, x3, y3;
  5.  {
  6.      long px = x2 - x1;
  7.      long py = y2 - y1;
  8.      long s = px * px + py * py;
  9.      long x, y, dx, dy, dist = 0;
  10.      float lu = 0;
  11.  
  12.      if (x1 == x2 && y1 == y2)
  13.          return isqrt(dist2(x1, y1, x3, y3));
  14.  
  15.      lu = ((x3 - x1) * px + (y3 - y1) * py) / (float) s;
  16.      if (lu > 1)
  17.          lu = 1;
  18.      else if (lu < 0)
  19.          lu = 0;
  20.  
  21.      x = x1 + lu * px;
  22.      y = y1 + lu * py;
  23.      dx = x - x3;
  24.      dy = y - y3;
  25.      dist = isqrt(dx * dx + dy * dy);
  26.  
  27.      return dist;
  28.  }
  29.  

selection_do_gradient

  1.  void
  2.  selection_do_gradient(ov, x, y, x2, y2, gtyp, mind, maxd, limit)
  3.  struct opvar *ov;
  4.  long x, y, x2, y2, gtyp, mind, maxd, limit;
  5.  {
  6.      long dx, dy, dofs;
  7.  
  8.      if (mind > maxd) {
  9.          long tmp = mind;
  10.          mind = maxd;
  11.          maxd = tmp;
  12.      }
  13.  
  14.      dofs = maxd - mind;
  15.      if (dofs < 1)
  16.          dofs = 1;
  17.  
  18.      switch (gtyp) {
  19.      default:
  20.      case SEL_GRADIENT_RADIAL: {
  21.          for (dx = 0; dx < COLNO; dx++)
  22.              for (dy = 0; dy < ROWNO; dy++) {
  23.                  long d0 = line_dist_coord(x, y, x2, y2, dx, dy);
  24.                  if (d0 >= mind && (!limit || d0 <= maxd)) {
  25.                      if (d0 - mind > rn2(dofs))
  26.                          selection_setpoint(dx, dy, ov, 1);
  27.                  }
  28.              }
  29.          break;
  30.      }
  31.      case SEL_GRADIENT_SQUARE: {
  32.          for (dx = 0; dx < COLNO; dx++)
  33.              for (dy = 0; dy < ROWNO; dy++) {
  34.                  long d1 = line_dist_coord(x, y, x2, y2, x, dy);
  35.                  long d2 = line_dist_coord(x, y, x2, y2, dx, y);
  36.                  long d3 = line_dist_coord(x, y, x2, y2, x2, dy);
  37.                  long d4 = line_dist_coord(x, y, x2, y2, dx, y2);
  38.                  long d5 = line_dist_coord(x, y, x2, y2, dx, dy);
  39.                  long d0 = min(d5, min(max(d1, d2), max(d3, d4)));
  40.  
  41.                  if (d0 >= mind && (!limit || d0 <= maxd)) {
  42.                      if (d0 - mind > rn2(dofs))
  43.                          selection_setpoint(dx, dy, ov, 1);
  44.                  }
  45.              }
  46.          break;
  47.      } /*case*/
  48.      } /*switch*/
  49.  }
  50.  

selection_do_line

  1.  /* bresenham line algo */
  2.  void
  3.  selection_do_line(x1, y1, x2, y2, ov)
  4.  schar x1, y1, x2, y2;
  5.  struct opvar *ov;
  6.  {
  7.      int d0, dx, dy, ai, bi, xi, yi;
  8.  
  9.      if (x1 < x2) {
  10.          xi = 1;
  11.          dx = x2 - x1;
  12.      } else {
  13.          xi = -1;
  14.          dx = x1 - x2;
  15.      }
  16.  
  17.      if (y1 < y2) {
  18.          yi = 1;
  19.          dy = y2 - y1;
  20.      } else {
  21.          yi = -1;
  22.          dy = y1 - y2;
  23.      }
  24.  
  25.      selection_setpoint(x1, y1, ov, 1);
  26.  
  27.      if (dx > dy) {
  28.          ai = (dy - dx) * 2;
  29.          bi = dy * 2;
  30.          d0 = bi - dx;
  31.          do {
  32.              if (d0 >= 0) {
  33.                  y1 += yi;
  34.                  d0 += ai;
  35.              } else
  36.                  d0 += bi;
  37.              x1 += xi;
  38.              selection_setpoint(x1, y1, ov, 1);
  39.          } while (x1 != x2);
  40.      } else {
  41.          ai = (dx - dy) * 2;
  42.          bi = dx * 2;
  43.          d0 = bi - dy;
  44.          do {
  45.              if (d0 >= 0) {
  46.                  x1 += xi;
  47.                  d0 += ai;
  48.              } else
  49.                  d0 += bi;
  50.              y1 += yi;
  51.              selection_setpoint(x1, y1, ov, 1);
  52.          } while (y1 != y2);
  53.      }
  54.  }
  55.  

selection_do_randline

  1.  void
  2.  selection_do_randline(x1, y1, x2, y2, rough, rec, ov)
  3.  schar x1, y1, x2, y2, rough, rec;
  4.  struct opvar *ov;
  5.  {
  6.      int mx, my;
  7.      int dx, dy;
  8.  
  9.      if (rec < 1) {
  10.          return;
  11.      }
  12.  
  13.      if ((x2 == x1) && (y2 == y1)) {
  14.          selection_setpoint(x1, y1, ov, 1);
  15.          return;
  16.      }
  17.  
  18.      if (rough > max(abs(x2 - x1), abs(y2 - y1)))
  19.          rough = max(abs(x2 - x1), abs(y2 - y1));
  20.  
  21.      if (rough < 2) {
  22.          mx = ((x1 + x2) / 2);
  23.          my = ((y1 + y2) / 2);
  24.      } else {
  25.          do {
  26.              dx = (Rand() % rough) - (rough / 2);
  27.              dy = (Rand() % rough) - (rough / 2);
  28.              mx = ((x1 + x2) / 2) + dx;
  29.              my = ((y1 + y2) / 2) + dy;
  30.          } while ((mx > COLNO - 1 || mx < 0 || my < 0 || my > ROWNO - 1));
  31.      }
  32.  
  33.      selection_setpoint(mx, my, ov, 1);
  34.  
  35.      rough = (rough * 2) / 3;
  36.  
  37.      rec--;
  38.  
  39.      selection_do_randline(x1, y1, mx, my, rough, rec, ov);
  40.      selection_do_randline(mx, my, x2, y2, rough, rec, ov);
  41.  }
  42.  

selection_iterate

  1.  void
  2.  selection_iterate(ov, func, arg)
  3.  struct opvar *ov;
  4.  select_iter_func func;
  5.  genericptr_t arg;
  6.  {
  7.      int x, y;
  8.  
  9.      /* yes, this is very naive, but it's not _that_ expensive. */
  10.      for (x = 0; x < COLNO; x++)
  11.          for (y = 0; y < ROWNO; y++)
  12.              if (selection_getpoint(x, y, ov))
  13.                  (*func)(x, y, arg);
  14.  }
  15.  

sel_set_ter

  1.  void
  2.  sel_set_ter(x, y, arg)
  3.  int x, y;
  4.  genericptr_t arg;
  5.  {
  6.      terrain terr;
  7.  
  8.      terr = *(terrain *) arg;
  9.      SET_TYPLIT(x, y, terr.ter, terr.tlit);
  10.      /* handle doors and secret doors */
  11.      if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
  12.          if (levl[x][y].typ == SDOOR)
  13.              levl[x][y].doormask = D_CLOSED;
  14.          if (x && (IS_WALL(levl[x - 1][y].typ) || levl[x - 1][y].horizontal))
  15.              levl[x][y].horizontal = 1;
  16.      }
  17.  }
  18.  

sel_set_feature

  1.  void
  2.  sel_set_feature(x, y, arg)
  3.  int x, y;
  4.  genericptr_t arg;
  5.  {
  6.      if (IS_FURNITURE(levl[x][y].typ))
  7.          return;
  8.      levl[x][y].typ = (*(int *) arg);
  9.  }
  10.  

sel_set_door

  1.  void
  2.  sel_set_door(dx, dy, arg)
  3.  int dx, dy;
  4.  genericptr_t arg;
  5.  {
  6.      xchar typ = *(xchar *) arg;
  7.      xchar x = dx;
  8.      xchar y = dy;
  9.  
  10.      if (!IS_DOOR(levl[x][y].typ) && levl[x][y].typ != SDOOR)
  11.          levl[x][y].typ = (typ & D_SECRET) ? SDOOR : DOOR;
  12.      if (typ & D_SECRET) {
  13.          typ &= ~D_SECRET;
  14.          if (typ < D_CLOSED)
  15.              typ = D_CLOSED;
  16.      }
  17.      levl[x][y].doormask = typ;
  18.      SpLev_Map[x][y] = 1;
  19.  }
  20.  

spo_door

  1.  void
  2.  spo_door(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_door";
  6.      struct opvar *msk, *sel;
  7.      xchar typ;
  8.  
  9.      if (!OV_pop_i(msk) || !OV_pop_typ(sel, SPOVAR_SEL))
  10.          return;
  11.  
  12.      typ = OV_i(msk) == -1 ? rnddoor() : (xchar) OV_i(msk);
  13.  
  14.      selection_iterate(sel, sel_set_door, (genericptr_t) &typ);
  15.  
  16.      opvar_free(sel);
  17.      opvar_free(msk);
  18.  }
  19.  

spo_feature

  1.  void
  2.  spo_feature(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_feature";
  6.      struct opvar *sel;
  7.      int typ;
  8.  
  9.      if (!OV_pop_typ(sel, SPOVAR_SEL))
  10.          return;
  11.  
  12.      switch (coder->opcode) {
  13.      default:
  14.          impossible("spo_feature called with wrong opcode %i.", coder->opcode);
  15.          break;
  16.      case SPO_FOUNTAIN:
  17.          typ = FOUNTAIN;
  18.          break;
  19.      case SPO_SINK:
  20.          typ = SINK;
  21.          break;
  22.      case SPO_POOL:
  23.          typ = POOL;
  24.          break;
  25.      }
  26.      selection_iterate(sel, sel_set_feature, (genericptr_t) &typ);
  27.      opvar_free(sel);
  28.  }
  29.  

spo_terrain

  1.  void
  2.  spo_terrain(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_terrain";
  6.      terrain tmpterrain;
  7.      struct opvar *ter, *sel;
  8.  
  9.      if (!OV_pop_typ(ter, SPOVAR_MAPCHAR) || !OV_pop_typ(sel, SPOVAR_SEL))
  10.          return;
  11.  
  12.      tmpterrain.ter = SP_MAPCHAR_TYP(OV_i(ter));
  13.      tmpterrain.tlit = SP_MAPCHAR_LIT(OV_i(ter));
  14.      selection_iterate(sel, sel_set_ter, (genericptr_t) &tmpterrain);
  15.  
  16.      opvar_free(ter);
  17.      opvar_free(sel);
  18.  }
  19.  

spo_replace_terrain

  1.  void
  2.  spo_replace_terrain(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_replace_terrain";
  6.      replaceterrain rt;
  7.      struct opvar *reg, *from_ter, *to_ter, *chance;
  8.  
  9.      if (!OV_pop_i(chance) || !OV_pop_typ(to_ter, SPOVAR_MAPCHAR)
  10.          || !OV_pop_typ(from_ter, SPOVAR_MAPCHAR) || !OV_pop_r(reg))
  11.          return;
  12.  
  13.      rt.chance = OV_i(chance);
  14.      rt.tolit = SP_MAPCHAR_LIT(OV_i(to_ter));
  15.      rt.toter = SP_MAPCHAR_TYP(OV_i(to_ter));
  16.      rt.fromter = SP_MAPCHAR_TYP(OV_i(from_ter));
  17.      /* TODO: use SP_MAPCHAR_LIT(OV_i(from_ter)) too */
  18.      rt.x1 = SP_REGION_X1(OV_i(reg));
  19.      rt.y1 = SP_REGION_Y1(OV_i(reg));
  20.      rt.x2 = SP_REGION_X2(OV_i(reg));
  21.      rt.y2 = SP_REGION_Y2(OV_i(reg));
  22.  
  23.      replace_terrain(&rt, coder->croom);
  24.  
  25.      opvar_free(reg);
  26.      opvar_free(from_ter);
  27.      opvar_free(to_ter);
  28.      opvar_free(chance);
  29.  }
  30.  

generate_way_out_method

  1.  STATIC_OVL boolean
  2.  generate_way_out_method(nx,ny, ov)
  3.  int nx,ny;
  4.  struct opvar *ov;
  5.  {
  6.      static const char nhFunc[] = "generate_way_out_method";
  7.      const int escapeitems[] = { PICK_AXE,
  8.                                  DWARVISH_MATTOCK,
  9.                                  WAN_DIGGING,
  10.                                  WAN_TELEPORTATION,
  11.                                  SCR_TELEPORTATION,
  12.                                  RIN_TELEPORTATION };
  13.      struct opvar *ov2 = selection_opvar((char *) 0), *ov3;
  14.      schar x, y;
  15.      boolean res = TRUE;
  16.  
  17.      selection_floodfill(ov2, nx, ny, TRUE);
  18.      ov3 = opvar_clone(ov2);
  19.  
  20.      /* try to make a secret door */
  21.      while (selection_rndcoord(ov3, &x, &y, TRUE)) {
  22.          if (isok(x+1, y) && !selection_getpoint(x+1, y, ov)
  23.              && IS_WALL(levl[x+1][y].typ)
  24.              && isok(x+2, y) &&  selection_getpoint(x+2, y, ov)
  25.              && ACCESSIBLE(levl[x+2][y].typ)) {
  26.              levl[x+1][y].typ = SDOOR;
  27.              goto gotitdone;
  28.          }
  29.          if (isok(x-1, y) && !selection_getpoint(x-1, y, ov)
  30.              && IS_WALL(levl[x-1][y].typ)
  31.              && isok(x-2, y) &&  selection_getpoint(x-2, y, ov)
  32.              && ACCESSIBLE(levl[x-2][y].typ)) {
  33.              levl[x-1][y].typ = SDOOR;
  34.              goto gotitdone;
  35.          }
  36.          if (isok(x, y+1) && !selection_getpoint(x, y+1, ov)
  37.              && IS_WALL(levl[x][y+1].typ)
  38.              && isok(x, y+2) &&  selection_getpoint(x, y+2, ov)
  39.              && ACCESSIBLE(levl[x][y+2].typ)) {
  40.              levl[x][y+1].typ = SDOOR;
  41.              goto gotitdone;
  42.          }
  43.          if (isok(x, y-1) && !selection_getpoint(x, y-1, ov)
  44.              && IS_WALL(levl[x][y-1].typ)
  45.              && isok(x, y-2) &&  selection_getpoint(x, y-2, ov)
  46.              && ACCESSIBLE(levl[x][y-2].typ)) {
  47.              levl[x][y-1].typ = SDOOR;
  48.              goto gotitdone;
  49.          }
  50.      }
  51.  
  52.      /* try to make a hole or a trapdoor */
  53.      if (Can_fall_thru(&u.uz)) {
  54.          opvar_free(ov3);
  55.          ov3 = opvar_clone(ov2);
  56.          while (selection_rndcoord(ov3, &x, &y, TRUE)) {
  57.              if (maketrap(x,y, rn2(2) ? HOLE : TRAPDOOR))
  58.                  goto gotitdone;
  59.          }
  60.      }
  61.  
  62.      /* generate one of the escape items */
  63.      if (selection_rndcoord(ov2, &x, &y, FALSE)) {
  64.          mksobj_at(escapeitems[rn2(SIZE(escapeitems))], x, y, TRUE, FALSE);
  65.          goto gotitdone;
  66.      }
  67.  
  68.      res = FALSE;
  69.   gotitdone:
  70.      opvar_free(ov2);
  71.      opvar_free(ov3);
  72.      return res;
  73.  }
  74.  

ensure_way_out

  1.  STATIC_OVL void
  2.  ensure_way_out()
  3.  {
  4.      static const char nhFunc[] = "ensure_way_out";
  5.      struct opvar *ov = selection_opvar((char *) 0);
  6.      struct trap *ttmp = ftrap;
  7.      int x,y;
  8.      boolean ret = TRUE;
  9.  
  10.      set_selection_floodfillchk(floodfillchk_match_accessible);
  11.  
  12.      if (xupstair && !selection_getpoint(xupstair, yupstair, ov))
  13.          selection_floodfill(ov, xupstair, yupstair, TRUE);
  14.      if (xdnstair && !selection_getpoint(xdnstair, ydnstair, ov))
  15.          selection_floodfill(ov, xdnstair, ydnstair, TRUE);
  16.      if (xupladder && !selection_getpoint(xupladder, yupladder, ov))
  17.          selection_floodfill(ov, xupladder, yupladder, TRUE);
  18.      if (xdnladder && !selection_getpoint(xdnladder, ydnladder, ov))
  19.          selection_floodfill(ov, xdnladder, ydnladder, TRUE);
  20.  
  21.      while (ttmp) {
  22.          if ((ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE
  23.               || ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR)
  24.              && !selection_getpoint(ttmp->tx, ttmp->ty, ov))
  25.              selection_floodfill(ov, ttmp->tx, ttmp->ty, TRUE);
  26.          ttmp = ttmp->ntrap;
  27.      }
  28.  
  29.      do {
  30.          ret = TRUE;
  31.          for (x = 0; x < COLNO; x++)
  32.              for (y = 0; y < ROWNO; y++)
  33.                  if (ACCESSIBLE(levl[x][y].typ)
  34.                      && !selection_getpoint(x, y, ov)) {
  35.                      if (generate_way_out_method(x,y, ov))
  36.                          selection_floodfill(ov, x,y, TRUE);
  37.                      ret = FALSE;
  38.                      goto outhere;
  39.                  }
  40.      outhere: ;
  41.      } while (!ret);
  42.      opvar_free(ov);
  43.  }
  44.  

spo_levregion

  1.  void
  2.  spo_levregion(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spot_levregion";
  6.      struct opvar *rname, *padding, *rtype, *del_islev, *dy2, *dx2, *dy1, *dx1,
  7.          *in_islev, *iy2, *ix2, *iy1, *ix1;
  8.  
  9.      lev_region *tmplregion;
  10.  
  11.      if (!OV_pop_s(rname) || !OV_pop_i(padding) || !OV_pop_i(rtype)
  12.          || !OV_pop_i(del_islev) || !OV_pop_i(dy2) || !OV_pop_i(dx2)
  13.          || !OV_pop_i(dy1) || !OV_pop_i(dx1) || !OV_pop_i(in_islev)
  14.          || !OV_pop_i(iy2) || !OV_pop_i(ix2) || !OV_pop_i(iy1)
  15.          || !OV_pop_i(ix1))
  16.          return;
  17.  
  18.      tmplregion = (lev_region *) alloc(sizeof(lev_region));
  19.  
  20.      tmplregion->inarea.x1 = OV_i(ix1);
  21.      tmplregion->inarea.y1 = OV_i(iy1);
  22.      tmplregion->inarea.x2 = OV_i(ix2);
  23.      tmplregion->inarea.y2 = OV_i(iy2);
  24.  
  25.      tmplregion->delarea.x1 = OV_i(dx1);
  26.      tmplregion->delarea.y1 = OV_i(dy1);
  27.      tmplregion->delarea.x2 = OV_i(dx2);
  28.      tmplregion->delarea.y2 = OV_i(dy2);
  29.  
  30.      tmplregion->in_islev = OV_i(in_islev);
  31.      tmplregion->del_islev = OV_i(del_islev);
  32.      tmplregion->rtype = OV_i(rtype);
  33.      tmplregion->padding = OV_i(padding);
  34.      tmplregion->rname.str = dupstr(OV_s(rname));
  35.  
  36.      if (!tmplregion->in_islev) {
  37.          get_location(&tmplregion->inarea.x1, &tmplregion->inarea.y1, ANY_LOC,
  38.                       (struct mkroom *) 0);
  39.          get_location(&tmplregion->inarea.x2, &tmplregion->inarea.y2, ANY_LOC,
  40.                       (struct mkroom *) 0);
  41.      }
  42.  
  43.      if (!tmplregion->del_islev) {
  44.          get_location(&tmplregion->delarea.x1, &tmplregion->delarea.y1,
  45.                       ANY_LOC, (struct mkroom *) 0);
  46.          get_location(&tmplregion->delarea.x2, &tmplregion->delarea.y2,
  47.                       ANY_LOC, (struct mkroom *) 0);
  48.      }
  49.      if (num_lregions) {
  50.          /* realloc the lregion space to add the new one */
  51.          lev_region *newl = (lev_region *) alloc(
  52.              sizeof(lev_region) * (unsigned) (1 + num_lregions));
  53.  
  54.          (void) memcpy((genericptr_t) (newl), (genericptr_t) lregions,
  55.                        sizeof(lev_region) * num_lregions);
  56.          Free(lregions);
  57.          num_lregions++;
  58.          lregions = newl;
  59.      } else {
  60.          num_lregions = 1;
  61.          lregions = (lev_region *) alloc(sizeof(lev_region));
  62.      }
  63.      (void) memcpy(&lregions[num_lregions - 1], tmplregion,
  64.                    sizeof(lev_region));
  65.      free(tmplregion);
  66.  
  67.      opvar_free(dx1);
  68.      opvar_free(dy1);
  69.      opvar_free(dx2);
  70.      opvar_free(dy2);
  71.  
  72.      opvar_free(ix1);
  73.      opvar_free(iy1);
  74.      opvar_free(ix2);
  75.      opvar_free(iy2);
  76.  
  77.      opvar_free(del_islev);
  78.      opvar_free(in_islev);
  79.      opvar_free(rname);
  80.      opvar_free(rtype);
  81.      opvar_free(padding);
  82.  }
  83.  

spo_region

  1.  void
  2.  spo_region(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_region";
  6.      struct opvar *rtype, *rlit, *rflags, *area;
  7.      xchar dx1, dy1, dx2, dy2;
  8.      register struct mkroom *troom;
  9.      boolean prefilled, room_not_needed, irregular, joined;
  10.  
  11.      if (!OV_pop_i(rflags) || !OV_pop_i(rtype) || !OV_pop_i(rlit)
  12.          || !OV_pop_r(area))
  13.          return;
  14.  
  15.      prefilled = !(OV_i(rflags) & (1 << 0));
  16.      irregular = (OV_i(rflags) & (1 << 1));
  17.      joined = !(OV_i(rflags) & (1 << 2));
  18.  
  19.      if (OV_i(rtype) > MAXRTYPE) {
  20.          OV_i(rtype) -= MAXRTYPE + 1;
  21.          prefilled = TRUE;
  22.      } else
  23.          prefilled = FALSE;
  24.  
  25.      if (OV_i(rlit) < 0)
  26.          OV_i(rlit) =
  27.              (rnd(1 + abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
  28.  
  29.      dx1 = SP_REGION_X1(OV_i(area));
  30.      dy1 = SP_REGION_Y1(OV_i(area));
  31.      dx2 = SP_REGION_X2(OV_i(area));
  32.      dy2 = SP_REGION_Y2(OV_i(area));
  33.  
  34.      get_location(&dx1, &dy1, ANY_LOC, (struct mkroom *) 0);
  35.      get_location(&dx2, &dy2, ANY_LOC, (struct mkroom *) 0);
  36.  
  37.      /* for an ordinary room, `prefilled' is a flag to force
  38.         an actual room to be created (such rooms are used to
  39.         control placement of migrating monster arrivals) */
  40.      room_not_needed = (OV_i(rtype) == OROOM && !irregular && !prefilled);
  41.      if (room_not_needed || nroom >= MAXNROFROOMS) {
  42.          region tmpregion;
  43.          if (!room_not_needed)
  44.              impossible("Too many rooms on new level!");
  45.          tmpregion.rlit = OV_i(rlit);
  46.          tmpregion.x1 = dx1;
  47.          tmpregion.y1 = dy1;
  48.          tmpregion.x2 = dx2;
  49.          tmpregion.y2 = dy2;
  50.          light_region(&tmpregion);
  51.  
  52.          opvar_free(area);
  53.          opvar_free(rflags);
  54.          opvar_free(rlit);
  55.          opvar_free(rtype);
  56.  
  57.          return;
  58.      }
  59.  
  60.      troom = &rooms[nroom];
  61.  
  62.      /* mark rooms that must be filled, but do it later */
  63.      if (OV_i(rtype) != OROOM)
  64.          troom->needfill = (prefilled ? 2 : 1);
  65.  
  66.      troom->needjoining = joined;
  67.  
  68.      if (irregular) {
  69.          min_rx = max_rx = dx1;
  70.          min_ry = max_ry = dy1;
  71.          smeq[nroom] = nroom;
  72.          flood_fill_rm(dx1, dy1, nroom + ROOMOFFSET, OV_i(rlit), TRUE);
  73.          add_room(min_rx, min_ry, max_rx, max_ry, FALSE, OV_i(rtype), TRUE);
  74.          troom->rlit = OV_i(rlit);
  75.          troom->irregular = TRUE;
  76.      } else {
  77.          add_room(dx1, dy1, dx2, dy2, OV_i(rlit), OV_i(rtype), TRUE);
  78.  #ifdef SPECIALIZATION
  79.          topologize(troom, FALSE); /* set roomno */
  80.  #else
  81.          topologize(troom); /* set roomno */
  82.  #endif
  83.      }
  84.  
  85.      if (!room_not_needed) {
  86.          if (coder->n_subroom > 1)
  87.              impossible("region as subroom");
  88.          else {
  89.              coder->tmproomlist[coder->n_subroom] = troom;
  90.              coder->failed_room[coder->n_subroom] = FALSE;
  91.              coder->n_subroom++;
  92.          }
  93.      }
  94.  
  95.      opvar_free(area);
  96.      opvar_free(rflags);
  97.      opvar_free(rlit);
  98.      opvar_free(rtype);
  99.  }
  100.  

spo_drawbridge

  1.  void
  2.  spo_drawbridge(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_drawbridge";
  6.      xchar x, y;
  7.      struct opvar *dir, *db_open, *dcoord;
  8.  
  9.      if (!OV_pop_i(dir) || !OV_pop_i(db_open) || !OV_pop_c(dcoord))
  10.          return;
  11.  
  12.      get_location_coord(&x, &y, DRY | WET | HOT, coder->croom, OV_i(dcoord));
  13.      if (!create_drawbridge(x, y, OV_i(dir), OV_i(db_open)))
  14.          impossible("Cannot create drawbridge.");
  15.      SpLev_Map[x][y] = 1;
  16.  
  17.      opvar_free(dcoord);
  18.      opvar_free(db_open);
  19.      opvar_free(dir);
  20.  }
  21.  

spo_mazewalk

  1.  void
  2.  spo_mazewalk(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_mazewalk";
  6.      xchar x, y;
  7.      struct opvar *ftyp, *fstocked, *fdir, *mcoord;
  8.      int dir;
  9.  
  10.      if (!OV_pop_i(ftyp) || !OV_pop_i(fstocked) || !OV_pop_i(fdir)
  11.          || !OV_pop_c(mcoord))
  12.          return;
  13.  
  14.      dir = OV_i(fdir);
  15.  
  16.      get_location_coord(&x, &y, ANY_LOC, coder->croom, OV_i(mcoord));
  17.      if (!isok(x, y))
  18.          return;
  19.  
  20.      if (OV_i(ftyp) < 1) {
  21.          OV_i(ftyp) = level.flags.corrmaze ? CORR : ROOM;
  22.      }
  23.  
  24.      /* don't use move() - it doesn't use W_NORTH, etc. */
  25.      switch (dir) {
  26.      case W_NORTH:
  27.          --y;
  28.          break;
  29.      case W_SOUTH:
  30.          y++;
  31.          break;
  32.      case W_EAST:
  33.          x++;
  34.          break;
  35.      case W_WEST:
  36.          --x;
  37.          break;
  38.      default:
  39.          impossible("spo_mazewalk: Bad MAZEWALK direction");
  40.      }
  41.  
  42.      if (!IS_DOOR(levl[x][y].typ)) {
  43.          levl[x][y].typ = OV_i(ftyp);
  44.          levl[x][y].flags = 0;
  45.      }
  46.  
  47.      /*
  48.       * We must be sure that the parity of the coordinates for
  49.       * walkfrom() is odd.  But we must also take into account
  50.       * what direction was chosen.
  51.       */
  52.      if (!(x % 2)) {
  53.          if (dir == W_EAST)
  54.              x++;
  55.          else
  56.              x--;
  57.  
  58.          /* no need for IS_DOOR check; out of map bounds */
  59.          levl[x][y].typ = OV_i(ftyp);
  60.          levl[x][y].flags = 0;
  61.      }
  62.  
  63.      if (!(y % 2)) {
  64.          if (dir == W_SOUTH)
  65.              y++;
  66.          else
  67.              y--;
  68.      }
  69.  
  70.      walkfrom(x, y, OV_i(ftyp));
  71.      if (OV_i(fstocked))
  72.          fill_empty_maze();
  73.  
  74.      opvar_free(mcoord);
  75.      opvar_free(fdir);
  76.      opvar_free(fstocked);
  77.      opvar_free(ftyp);
  78.  }
  79.  

spo_wall_property

  1.  void
  2.  spo_wall_property(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_wall_property";
  6.      struct opvar *r;
  7.      xchar dx1, dy1, dx2, dy2;
  8.      int wprop = (coder->opcode == SPO_NON_DIGGABLE)
  9.                     ? W_NONDIGGABLE
  10.                     : W_NONPASSWALL;
  11.  
  12.      if (!OV_pop_r(r))
  13.          return;
  14.  
  15.      dx1 = SP_REGION_X1(OV_i(r));
  16.      dy1 = SP_REGION_Y1(OV_i(r));
  17.      dx2 = SP_REGION_X2(OV_i(r));
  18.      dy2 = SP_REGION_Y2(OV_i(r));
  19.  
  20.      get_location(&dx1, &dy1, ANY_LOC, (struct mkroom *) 0);
  21.      get_location(&dx2, &dy2, ANY_LOC, (struct mkroom *) 0);
  22.  
  23.      set_wall_property(dx1, dy1, dx2, dy2, wprop);
  24.  
  25.      opvar_free(r);
  26.  }
  27.  

spo_room_door

  1.  void
  2.  spo_room_door(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_room_door";
  6.      struct opvar *wall, *secret, *mask, *pos;
  7.      room_door tmpd;
  8.  
  9.      if (!OV_pop_i(wall) || !OV_pop_i(secret) || !OV_pop_i(mask)
  10.          || !OV_pop_i(pos) || !coder->croom)
  11.          return;
  12.  
  13.      tmpd.secret = OV_i(secret);
  14.      tmpd.mask = OV_i(mask);
  15.      tmpd.pos = OV_i(pos);
  16.      tmpd.wall = OV_i(wall);
  17.  
  18.      create_door(&tmpd, coder->croom);
  19.  
  20.      opvar_free(wall);
  21.      opvar_free(secret);
  22.      opvar_free(mask);
  23.      opvar_free(pos);
  24.  }
  25.  

sel_set_wallify

  1.  /*ARGSUSED*/
  2.  void
  3.  sel_set_wallify(x, y, arg)
  4.  int x, y;
  5.  genericptr_t arg UNUSED;
  6.  {
  7.      wallify_map(x, y, x, y);
  8.  }
  9.  

spo_wallify

  1.  void
  2.  spo_wallify(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_wallify";
  6.      struct opvar *typ, *r;
  7.      int dx1, dy1, dx2, dy2;
  8.  
  9.      if (!OV_pop_i(typ))
  10.          return;
  11.      switch (OV_i(typ)) {
  12.      default:
  13.      case 0:
  14.          if (!OV_pop_r(r))
  15.              return;
  16.          dx1 = (xchar) SP_REGION_X1(OV_i(r));
  17.          dy1 = (xchar) SP_REGION_Y1(OV_i(r));
  18.          dx2 = (xchar) SP_REGION_X2(OV_i(r));
  19.          dy2 = (xchar) SP_REGION_Y2(OV_i(r));
  20.          wallify_map(dx1 < 0 ? (xstart-1) : dx1, dy1 < 0 ? (ystart-1) : dy1,
  21.                      dx2 < 0 ? (xstart + xsize + 1) : dx2,
  22.                      dy2 < 0 ? (ystart + ysize + 1) : dy2);
  23.          break;
  24.      case 1:
  25.          if (!OV_pop_typ(r, SPOVAR_SEL))
  26.              return;
  27.          selection_iterate(r, sel_set_wallify, NULL);
  28.          break;
  29.      }
  30.      opvar_free(r);
  31.      opvar_free(typ);
  32.  }
  33.  

spo_map

  1.  void
  2.  spo_map(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_map";
  6.      mazepart tmpmazepart;
  7.      struct opvar *mpxs, *mpys, *mpmap, *mpa, *mpkeepr, *mpzalign;
  8.      xchar halign, valign;
  9.      xchar tmpxstart, tmpystart, tmpxsize, tmpysize;
  10.      unpacked_coord upc;
  11.  
  12.      if (!OV_pop_i(mpxs) || !OV_pop_i(mpys) || !OV_pop_s(mpmap)
  13.          || !OV_pop_i(mpkeepr) || !OV_pop_i(mpzalign) || !OV_pop_c(mpa))
  14.          return;
  15.  
  16.      tmpmazepart.xsize = OV_i(mpxs);
  17.      tmpmazepart.ysize = OV_i(mpys);
  18.      tmpmazepart.zaligntyp = OV_i(mpzalign);
  19.  
  20.      upc = get_unpacked_coord(OV_i(mpa), ANY_LOC);
  21.      tmpmazepart.halign = upc.x;
  22.      tmpmazepart.valign = upc.y;
  23.  
  24.      tmpxsize = xsize;
  25.      tmpysize = ysize;
  26.      tmpxstart = xstart;
  27.      tmpystart = ystart;
  28.  
  29.      halign = tmpmazepart.halign;
  30.      valign = tmpmazepart.valign;
  31.      xsize = tmpmazepart.xsize;
  32.      ysize = tmpmazepart.ysize;
  33.      switch (tmpmazepart.zaligntyp) {
  34.      default:
  35.      case 0:
  36.          break;
  37.      case 1:
  38.          switch ((int) halign) {
  39.          case LEFT:
  40.              xstart = splev_init_present ? 1 : 3;
  41.              break;
  42.          case H_LEFT:
  43.              xstart = 2 + ((x_maze_max - 2 - xsize) / 4);
  44.              break;
  45.          case CENTER:
  46.              xstart = 2 + ((x_maze_max - 2 - xsize) / 2);
  47.              break;
  48.          case H_RIGHT:
  49.              xstart = 2 + ((x_maze_max - 2 - xsize) * 3 / 4);
  50.              break;
  51.          case RIGHT:
  52.              xstart = x_maze_max - xsize - 1;
  53.              break;
  54.          }
  55.          switch ((int) valign) {
  56.          case TOP:
  57.              ystart = 3;
  58.              break;
  59.          case CENTER:
  60.              ystart = 2 + ((y_maze_max - 2 - ysize) / 2);
  61.              break;
  62.          case BOTTOM:
  63.              ystart = y_maze_max - ysize - 1;
  64.              break;
  65.          }
  66.          if (!(xstart % 2))
  67.              xstart++;
  68.          if (!(ystart % 2))
  69.              ystart++;
  70.          break;
  71.      case 2:
  72.          if (!coder->croom) {
  73.              xstart = 1;
  74.              ystart = 0;
  75.              xsize = COLNO - 1 - tmpmazepart.xsize;
  76.              ysize = ROWNO - tmpmazepart.ysize;
  77.          }
  78.          get_location_coord(&halign, &valign, ANY_LOC, coder->croom,
  79.                             OV_i(mpa));
  80.          xsize = tmpmazepart.xsize;
  81.          ysize = tmpmazepart.ysize;
  82.          xstart = halign;
  83.          ystart = valign;
  84.          break;
  85.      }
  86.      if ((ystart < 0) || (ystart + ysize > ROWNO)) {
  87.          /* try to move the start a bit */
  88.          ystart += (ystart > 0) ? -2 : 2;
  89.          if (ysize == ROWNO)
  90.              ystart = 0;
  91.          if (ystart < 0 || ystart + ysize > ROWNO)
  92.              panic("reading special level with ysize too large");
  93.      }
  94.      if (xsize <= 1 && ysize <= 1) {
  95.          xstart = 1;
  96.          ystart = 0;
  97.          xsize = COLNO - 1;
  98.          ysize = ROWNO;
  99.      } else {
  100.          xchar x, y;
  101.          /* Load the map */
  102.          for (y = ystart; y < ystart + ysize; y++)
  103.              for (x = xstart; x < xstart + xsize; x++) {
  104.                  xchar mptyp =
  105.                      (mpmap->vardata.str[(y - ystart) * xsize + (x - xstart)]
  106.                       - 1);
  107.                  if (mptyp >= MAX_TYPE)
  108.                      continue;
  109.                  levl[x][y].typ = mptyp;
  110.                  levl[x][y].lit = FALSE;
  111.                  /* clear out levl: load_common_data may set them */
  112.                  levl[x][y].flags = 0;
  113.                  levl[x][y].horizontal = 0;
  114.                  levl[x][y].roomno = 0;
  115.                  levl[x][y].edge = 0;
  116.                  SpLev_Map[x][y] = 1;
  117.                  /*
  118.                   *  Set secret doors to closed (why not trapped too?).  Set
  119.                   *  the horizontal bit.
  120.                   */
  121.                  if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
  122.                      if (levl[x][y].typ == SDOOR)
  123.                          levl[x][y].doormask = D_CLOSED;
  124.                      /*
  125.                       *  If there is a wall to the left that connects to a
  126.                       *  (secret) door, then it is horizontal.  This does
  127.                       *  not allow (secret) doors to be corners of rooms.
  128.                       */
  129.                      if (x != xstart && (IS_WALL(levl[x - 1][y].typ)
  130.                                          || levl[x - 1][y].horizontal))
  131.                          levl[x][y].horizontal = 1;
  132.                  } else if (levl[x][y].typ == HWALL
  133.                             || levl[x][y].typ == IRONBARS)
  134.                      levl[x][y].horizontal = 1;
  135.                  else if (levl[x][y].typ == LAVAPOOL)
  136.                      levl[x][y].lit = 1;
  137.                  else if (splev_init_present && levl[x][y].typ == ICE)
  138.                      levl[x][y].icedpool = icedpools ? ICED_POOL : ICED_MOAT;
  139.              }
  140.          if (coder->lvl_is_joined)
  141.              remove_rooms(xstart, ystart, xstart + xsize, ystart + ysize);
  142.      }
  143.      if (!OV_i(mpkeepr)) {
  144.          xstart = tmpxstart;
  145.          ystart = tmpystart;
  146.          xsize = tmpxsize;
  147.          ysize = tmpysize;
  148.      }
  149.  
  150.      opvar_free(mpxs);
  151.      opvar_free(mpys);
  152.      opvar_free(mpmap);
  153.      opvar_free(mpa);
  154.      opvar_free(mpkeepr);
  155.      opvar_free(mpzalign);
  156.  }
  157.  

spo_jmp

  1.  void
  2.  spo_jmp(coder, lvl)
  3.  struct sp_coder *coder;
  4.  sp_lev *lvl;
  5.  {
  6.      static const char nhFunc[] = "spo_jmp";
  7.      struct opvar *tmpa;
  8.      long a;
  9.  
  10.      if (!OV_pop_i(tmpa))
  11.          return;
  12.      a = sp_code_jmpaddr(coder->frame->n_opcode, (OV_i(tmpa) - 1));
  13.      if ((a >= 0) && (a < lvl->n_opcodes) && (a != coder->frame->n_opcode))
  14.          coder->frame->n_opcode = a;
  15.      opvar_free(tmpa);
  16.  }
  17.  

spo_conditional_jump

  1.  void
  2.  spo_conditional_jump(coder, lvl)
  3.  struct sp_coder *coder;
  4.  sp_lev *lvl;
  5.  {
  6.      static const char nhFunc[] = "spo_conditional_jump";
  7.      struct opvar *oa, *oc;
  8.      long a, c;
  9.      int test = 0;
  10.  
  11.      if (!OV_pop_i(oa) || !OV_pop_i(oc))
  12.          return;
  13.  
  14.      a = sp_code_jmpaddr(coder->frame->n_opcode, (OV_i(oa) - 1));
  15.      c = OV_i(oc);
  16.  
  17.      switch (coder->opcode) {
  18.      default:
  19.          impossible("spo_conditional_jump: illegal opcode");
  20.          break;
  21.      case SPO_JL:
  22.          test = (c & SP_CPUFLAG_LT);
  23.          break;
  24.      case SPO_JLE:
  25.          test = (c & (SP_CPUFLAG_LT | SP_CPUFLAG_EQ));
  26.          break;
  27.      case SPO_JG:
  28.          test = (c & SP_CPUFLAG_GT);
  29.          break;
  30.      case SPO_JGE:
  31.          test = (c & (SP_CPUFLAG_GT | SP_CPUFLAG_EQ));
  32.          break;
  33.      case SPO_JE:
  34.          test = (c & SP_CPUFLAG_EQ);
  35.          break;
  36.      case SPO_JNE:
  37.          test = (c & ~SP_CPUFLAG_EQ);
  38.          break;
  39.      }
  40.  
  41.      if ((test) && (a >= 0) && (a < lvl->n_opcodes)
  42.          && (a != coder->frame->n_opcode))
  43.          coder->frame->n_opcode = a;
  44.  
  45.      opvar_free(oa);
  46.      opvar_free(oc);
  47.  }
  48.  

spo_var_init

  1.  void
  2.  spo_var_init(coder)
  3.  struct sp_coder *coder;
  4.  {
  5.      static const char nhFunc[] = "spo_var_init";
  6.      struct opvar *vname;
  7.      struct opvar *arraylen;
  8.      struct opvar *vvalue;
  9.      struct splev_var *tmpvar;
  10.      struct splev_var *tmp2;
  11.      long idx;
  12.  
  13.      OV_pop_s(vname);
  14.      OV_pop_i(arraylen);
  15.  
  16.      if (!vname || !arraylen)
  17.          panic("no values for SPO_VAR_INIT");
  18.  
  19.      tmpvar = opvar_var_defined(coder, OV_s(vname));
  20.  
  21.      if (tmpvar) {
  22.          /* variable redefinition */
  23.          if (OV_i(arraylen) < 0) {
  24.              /* copy variable */
  25.              if (tmpvar->array_len) {
  26.                  idx = tmpvar->array_len;
  27.                  while (idx-- > 0) {
  28.                      opvar_free(tmpvar->data.arrayvalues[idx]);
  29.                  }
  30.                  Free(tmpvar->data.arrayvalues);
  31.              } else {
  32.                  opvar_free(tmpvar->data.value);
  33.              }
  34.              tmpvar->data.arrayvalues = NULL;
  35.              goto copy_variable;
  36.          } else if (OV_i(arraylen)) {
  37.              /* redefined array */
  38.              idx = tmpvar->array_len;
  39.              while (idx-- > 0) {
  40.                  opvar_free(tmpvar->data.arrayvalues[idx]);
  41.              }
  42.              Free(tmpvar->data.arrayvalues);
  43.              tmpvar->data.arrayvalues = NULL;
  44.              goto create_new_array;
  45.          } else {
  46.              /* redefined single value */
  47.              OV_pop(vvalue);
  48.              if (tmpvar->svtyp != vvalue->spovartyp)
  49.                  panic("redefining variable as different type");
  50.              opvar_free(tmpvar->data.value);
  51.              tmpvar->data.value = vvalue;
  52.              tmpvar->array_len = 0;
  53.          }
  54.      } else {