Guest User

NetHack secret doors patch + related DevTeam bugfix

a guest
Nov 24th, 2018
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 16.25 KB | None | 0 0
  1. diff --git i/include/extern.h w/include/extern.h
  2. index b6f4825..399c940 100644
  3. --- i/include/extern.h
  4. +++ w/include/extern.h
  5. @@ -355,6 +355,7 @@ E int FDECL(back_to_glyph, (XCHAR_P, XCHAR_P));
  6.  E int FDECL(zapdir_to_glyph, (int, int, int));
  7.  E int FDECL(glyph_at, (XCHAR_P, XCHAR_P));
  8.  E void NDECL(set_wall_state);
  9. +E int FDECL(set_wall, (int, int, int));
  10.  E void FDECL(unset_seenv, (struct rm *, int, int, int, int));
  11.  E int FDECL(warning_of, (struct monst *));
  12.  
  13. @@ -2283,6 +2284,7 @@ E void FDECL(fill_room, (struct mkroom *, BOOLEAN_P));
  14.  E boolean FDECL(load_special, (const char *));
  15.  E xchar FDECL(selection_getpoint, (int, int, struct opvar *));
  16.  E struct opvar *FDECL(selection_opvar, (char *));
  17. +E void FDECL(set_door_orientation, (int, int));
  18.  E void FDECL(opvar_free_x, (struct opvar *));
  19.  E void FDECL(set_selection_floodfillchk, (int FDECL((*), (int,int))));
  20.  E void FDECL(selection_floodfill, (struct opvar *, int, int, BOOLEAN_P));
  21. diff --git i/src/display.c w/src/display.c
  22. index 5c98c8a..1c6b6f7 100644
  23. --- i/src/display.c
  24. +++ w/src/display.c
  25. @@ -131,7 +131,6 @@ STATIC_DCL boolean FDECL(more_than_one, (int, int, int, int, int));
  26.  #endif
  27.  
  28.  STATIC_DCL int FDECL(set_twall, (int, int, int, int, int, int, int, int));
  29. -STATIC_DCL int FDECL(set_wall, (int, int, int));
  30.  STATIC_DCL int FDECL(set_corn, (int, int, int, int, int, int, int, int));
  31.  STATIC_DCL int FDECL(set_crosswall, (int, int));
  32.  STATIC_DCL void FDECL(set_seenv, (struct rm *, int, int, int, int));
  33. @@ -1921,7 +1920,7 @@ int x1, y1, x2, y2, x3, y3;
  34.  }
  35.  
  36.  /* Return wall mode for a horizontal or vertical wall. */
  37. -STATIC_OVL int
  38. +int
  39.  set_wall(x, y, horiz)
  40.  int x, y, horiz;
  41.  {
  42. diff --git i/src/lock.c w/src/lock.c
  43. index 067eb6c..60ce3d6 100644
  44. --- i/src/lock.c
  45. +++ w/src/lock.c
  46. @@ -1031,6 +1031,35 @@ int x, y;
  47.          } else
  48.              res = FALSE;
  49.          break;
  50. +    case WAN_MAKE_INVISIBLE:
  51. +        if (door->doormask & (D_LOCKED | D_CLOSED)) {
  52. +            /* Riders shall not be blocked */
  53. +            if (Is_astralevel(&u.uz))
  54. +              {
  55. +                msg = "The door momentarily fades.";
  56. +                res = FALSE;
  57. +                break;
  58. +              }
  59. +            /* Probably should not count as vandalism,
  60. +             * but the original shop door will still reappear */
  61. +            if (*in_rooms(x, y, SHOPBASE))
  62. +                add_damage(x, y, 0L);
  63. +            /* BUG: secret doors can only pretend to be straight walls,
  64. +             * so a door created with wizard lock in a room corner
  65. +             * or other weird position will display as a wrong kind
  66. +             * of wall when made invisible.  This is not noticeable
  67. +             * with the default symset, but all others will glitch.
  68. +             * There's no easy way to fix it short of arbitrarily refusing
  69. +             * to vanish doors at weird positions, which is also ugly. */
  70. +            door->typ = SDOOR;
  71. +            set_door_orientation(x, y);
  72. +            door->doormask &= ~WM_MASK;
  73. +            door->wall_info |= set_wall(x, y, door->horizontal);
  74. +            newsym(x, y);
  75. +            msg = "The door vanishes!";
  76. +        } else
  77. +            res = FALSE;
  78. +        break;
  79.      default:
  80.          impossible("magic (%d) attempted on door.", otmp->otyp);
  81.          break;
  82. diff --git i/src/shk.c w/src/shk.c
  83. index 1b42f27..e0b7cae 100644
  84. --- i/src/shk.c
  85. +++ w/src/shk.c
  86. @@ -3303,8 +3303,8 @@ long cost;
  87.  
  88.          /* Don't schedule for repair unless it's a real shop entrance */
  89.          for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++)
  90. -            if ((mtmp = shop_keeper(*shops)) != 0 && x == ESHK(mtmp)->shd.x
  91. -                && y == ESHK(mtmp)->shd.y)
  92. +            if ((mtmp = shop_keeper(*shops)) != 0
  93. +                && x == ESHK(mtmp)->shd.x && y == ESHK(mtmp)->shd.y)
  94.                  break;
  95.          if (!*shops)
  96.              return;
  97. @@ -3312,10 +3312,11 @@ long cost;
  98.      for (tmp_dam = level.damagelist; tmp_dam; tmp_dam = tmp_dam->next)
  99.          if (tmp_dam->place.x == x && tmp_dam->place.y == y) {
  100.              tmp_dam->cost += cost;
  101. +            tmp_dam->when = monstermoves; /* needed by pay_for_damage() */
  102.              return;
  103.          }
  104. -    tmp_dam = (struct damage *) alloc((unsigned) sizeof(struct damage));
  105. -    (void) memset((genericptr_t)tmp_dam, 0, sizeof(struct damage));
  106. +    tmp_dam = (struct damage *) alloc((unsigned) sizeof *tmp_dam);
  107. +    (void) memset((genericptr_t) tmp_dam, 0, sizeof *tmp_dam);
  108.      tmp_dam->when = monstermoves;
  109.      tmp_dam->place.x = x;
  110.      tmp_dam->place.y = y;
  111. @@ -3362,11 +3363,11 @@ boolean croaked;
  112.              if (IS_DOOR(levl[x][y].typ))
  113.                  old_doormask = levl[x][y].doormask;
  114.  
  115. -            if (croaked)
  116. +            if (croaked) {
  117.                  disposition = (shops[1]) ? 0 : 1;
  118. -            else if (stop_picking)
  119. +            } else if (stop_picking) {
  120.                  disposition = repair_damage(shkp, tmp_dam, FALSE);
  121. -            else {
  122. +            } else {
  123.                  /* Defer the stop_occupation() until after repair msgs */
  124.                  if (closed_door(x, y))
  125.                      stop_picking = picking_at(x, y);
  126. @@ -3461,15 +3462,16 @@ boolean croaked;
  127.   */
  128.  int
  129.  repair_damage(shkp, tmp_dam, catchup)
  130. -register struct monst *shkp;
  131. -register struct damage *tmp_dam;
  132. +struct monst *shkp;
  133. +struct damage *tmp_dam;
  134.  boolean catchup; /* restoring a level */
  135.  {
  136. -    register xchar x, y, i;
  137. +    xchar x, y;
  138.      xchar litter[9];
  139. -    register struct monst *mtmp;
  140. -    register struct obj *otmp;
  141. -    register struct trap *ttmp;
  142. +    struct monst *mtmp;
  143. +    struct obj *otmp;
  144. +    struct trap *ttmp;
  145. +    int i, k, ix, iy, disposition = 1;
  146.  
  147.      if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
  148.          return 0;
  149. @@ -3478,18 +3480,14 @@ boolean catchup; /* restoring a level */
  150.      x = tmp_dam->place.x;
  151.      y = tmp_dam->place.y;
  152.      if (!IS_ROOM(tmp_dam->typ)) {
  153. -        if (x == u.ux && y == u.uy)
  154. -            if (!Passes_walls)
  155. -                return 0;
  156. -        if (x == shkp->mx && y == shkp->my)
  157. -            return 0;
  158. -        if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
  159. +        if ((x == u.ux && y == u.uy && !Passes_walls)
  160. +            || (x == shkp->mx && y == shkp->my)
  161. +            || ((mtmp = m_at(x, y)) && !passes_walls(mtmp->data)))
  162.              return 0;
  163.      }
  164.      if ((ttmp = t_at(x, y)) != 0) {
  165. -        if (x == u.ux && y == u.uy)
  166. -            if (!Passes_walls)
  167. -                return 0;
  168. +        if (x == u.ux && y == u.uy && !Passes_walls)
  169. +            return 0;
  170.          if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) {
  171.              /* convert to an object */
  172.              otmp = mksobj((ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP,
  173. @@ -3499,48 +3497,60 @@ boolean catchup; /* restoring a level */
  174.              (void) mpickobj(shkp, otmp);
  175.          }
  176.          deltrap(ttmp);
  177. -        if (IS_DOOR(tmp_dam->typ) && !(levl[x][y].doormask & D_ISOPEN)) {
  178. -            levl[x][y].doormask = D_CLOSED;
  179. -            block_point(x, y);
  180. -        } else if (IS_WALL(tmp_dam->typ)) {
  181. -            levl[x][y].typ = tmp_dam->typ;
  182. -            block_point(x, y);
  183. -        }
  184. -        newsym(x, y);
  185. -        return 3;
  186. +        if (cansee(x, y))
  187. +            newsym(x, y);
  188. +        if (!catchup)
  189. +            disposition = 3;
  190.      }
  191. -    if (IS_ROOM(tmp_dam->typ)) {
  192. -        /* No messages, because player already filled trap door */
  193. -        return 1;
  194. -    }
  195. -    if ((tmp_dam->typ == levl[x][y].typ)
  196. -        && (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
  197. -        /* No messages if player already replaced shop door */
  198. -        return 1;
  199. +    if (IS_ROOM(tmp_dam->typ)
  200. +        || (tmp_dam->typ == levl[x][y].typ
  201. +            && (!IS_DOOR(tmp_dam->typ) || levl[x][y].doormask > D_BROKEN)))
  202. +        /* no terrain fix necessary (trap removal or manually repaired) */
  203. +        return disposition;
  204. +
  205. +    /* door or wall repair; trap, if any, is now gone;
  206. +       restore original terrain type and move any items away */
  207.      levl[x][y].typ = tmp_dam->typ;
  208. -    (void) memset((genericptr_t) litter, 0, sizeof(litter));
  209. -    if ((otmp = level.objects[x][y]) != 0) {
  210. -/* Scatter objects haphazardly into the shop */
  211. +    if (IS_DOOR(tmp_dam->typ))
  212. +        levl[x][y].doormask = D_CLOSED; /* arbitrary */
  213. +
  214. +    (void) memset((genericptr_t) litter, 0, sizeof litter);
  215.  #define NEED_UPDATE 1
  216.  #define OPEN 2
  217.  #define INSHOP 4
  218.  #define horiz(i) ((i % 3) - 1)
  219.  #define vert(i) ((i / 3) - 1)
  220. +    k = 0; /* number of adjacent shop spots */
  221. +    if (level.objects[x][y] && !IS_ROOM(levl[x][y].typ)) {
  222.          for (i = 0; i < 9; i++) {
  223. -            if ((i == 4) || (!ZAP_POS(levl[x + horiz(i)][y + vert(i)].typ)))
  224. +            ix = x + horiz(i);
  225. +            iy = y + vert(i);
  226. +            if (i == 4 || !isok(ix, iy) || !ZAP_POS(levl[ix][iy].typ))
  227.                  continue;
  228.              litter[i] = OPEN;
  229. -            if (inside_shop(x + horiz(i), y + vert(i))
  230. -                == ESHK(shkp)->shoproom)
  231. +            if (inside_shop(ix, iy) == ESHK(shkp)->shoproom) {
  232.                  litter[i] |= INSHOP;
  233. +                ++k;
  234. +            }
  235.          }
  236. +    }
  237. +    /* placement below assumes there is always at least one adjacent
  238. +       spot; the 'k' check guards against getting stuck in an infinite
  239. +       loop if some irregularly shaped room breaks that assumption */
  240. +    if (k > 0) {
  241. +        /* Scatter objects haphazardly into the shop */
  242.          if (Punished && !u.uswallow
  243.              && ((uchain->ox == x && uchain->oy == y)
  244.                  || (uball->ox == x && uball->oy == y))) {
  245.              /*
  246.               * Either the ball or chain is in the repair location.
  247. -             *
  248.               * Take the easy way out and put ball&chain under hero.
  249. +             *
  250. +             * FIXME: message should be reworded; this might be the
  251. +             * shop's doorway rather than a wall, there might be some
  252. +             * other stuff here which isn't junk, and "your junk" has
  253. +             * a slang connotation which could be applicable if hero
  254. +             * has Passes_walls ability.
  255.               */
  256.              if (!Deaf && !muteshk(shkp))
  257.                  verbalize("Get your junk out of my wall!");
  258. @@ -3549,40 +3559,48 @@ boolean catchup; /* restoring a level */
  259.          }
  260.          while ((otmp = level.objects[x][y]) != 0)
  261.              /* Don't mess w/ boulders -- just merge into wall */
  262. -            if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
  263. +            if (otmp->otyp == BOULDER || otmp->otyp == ROCK) {
  264.                  obj_extract_self(otmp);
  265.                  obfree(otmp, (struct obj *) 0);
  266.              } else {
  267. -                while (!(litter[i = rn2(9)] & INSHOP))
  268. -                    ;
  269. +                int trylimit = 50;
  270. +
  271. +                /* otmp must be moved otherwise level.objects[x][y] will
  272. +                   never become Null and while-loop won't terminate */
  273. +                do {
  274. +                    i = rn2(9);
  275. +                } while (--trylimit && !(litter[i] & INSHOP));
  276. +                if ((litter[i] & (OPEN | INSHOP)) != 0) {
  277. +                    ix = x + horiz(i);
  278. +                    iy = y + vert(i);
  279. +                } else {
  280. +                    /* we know shk isn't at <x,y> because repair
  281. +                       is deferred in that situation */
  282. +                    ix = shkp->mx;
  283. +                    iy = shkp->my;
  284. +                }
  285.                  remove_object(otmp);
  286. -                place_object(otmp, x + horiz(i), y + vert(i));
  287. +                place_object(otmp, ix, iy);
  288.                  litter[i] |= NEED_UPDATE;
  289.              }
  290.      }
  291.      if (catchup)
  292. -        return 1; /* repair occurred while off level */
  293. +        return 1; /* repair occurred while off level so no messages */
  294.  
  295.      block_point(x, y);
  296. -    if (IS_DOOR(tmp_dam->typ)) {
  297. -        levl[x][y].doormask = D_CLOSED; /* arbitrary */
  298. -        newsym(x, y);
  299. -    } else {
  300. -        /* don't set doormask  - it is (hopefully) the same as it was
  301. -           if not, perhaps save it with the damage array... */
  302. -
  303. -        if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
  304. -            /* Player sees actual repair process, so they KNOW it's a wall */
  305. +    if (cansee(x, y)) {
  306. +        if (IS_WALL(tmp_dam->typ))
  307. +            /* player sees actual repair process, so KNOWS it's a wall */
  308.              levl[x][y].seenv = SVALL;
  309. -            newsym(x, y);
  310. -        }
  311. -        /* Mark this wall as "repaired".  There currently is no code
  312. -           to do anything about repaired walls, so don't do it. */
  313. +        newsym(x, y);
  314.      }
  315.      for (i = 0; i < 9; i++)
  316.          if (litter[i] & NEED_UPDATE)
  317.              newsym(x + horiz(i), y + vert(i));
  318. -    return 2;
  319. +
  320. +    if (disposition < 3)
  321. +        disposition = 2;
  322. +    return disposition;
  323.  #undef NEED_UPDATE
  324.  #undef OPEN
  325.  #undef INSHOP
  326. @@ -3595,12 +3613,12 @@ boolean catchup; /* restoring a level */
  327.   */
  328.  int
  329.  shk_move(shkp)
  330. -register struct monst *shkp;
  331. +struct monst *shkp;
  332.  {
  333. -    register xchar gx, gy, omx, omy;
  334. -    register int udist;
  335. -    register schar appr;
  336. -    register struct eshk *eshkp = ESHK(shkp);
  337. +    xchar gx, gy, omx, omy;
  338. +    int udist;
  339. +    schar appr;
  340. +    struct eshk *eshkp = ESHK(shkp);
  341.      int z;
  342.      boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
  343.  
  344. @@ -3858,24 +3876,22 @@ boolean cant_mollify;
  345.  {
  346.      register struct monst *shkp = (struct monst *) 0;
  347.      char shops_affected[5];
  348. -    register boolean uinshp = (*u.ushops != '\0');
  349. +    boolean uinshp = (*u.ushops != '\0');
  350.      char qbuf[80];
  351. -    register xchar x, y;
  352. +    xchar x, y;
  353.      boolean dugwall = (!strcmp(dmgstr, "dig into")    /* wand */
  354.                         || !strcmp(dmgstr, "damage")); /* pick-axe */
  355.      boolean animal, pursue;
  356.      struct damage *tmp_dam, *appear_here = 0;
  357. -    /* any number >= (80*80)+(24*24) would do, actually */
  358.      long cost_of_damage = 0L;
  359. -    unsigned int nearest_shk = 7000, nearest_damage = 7000;
  360. +    unsigned int nearest_shk = (ROWNO * ROWNO) + (COLNO * COLNO),
  361. +                 nearest_damage = nearest_shk;
  362.      int picks = 0;
  363.  
  364. -    for (tmp_dam = level.damagelist;
  365. -         (tmp_dam && (tmp_dam->when == monstermoves));
  366. -         tmp_dam = tmp_dam->next) {
  367. +    for (tmp_dam = level.damagelist; tmp_dam; tmp_dam = tmp_dam->next) {
  368.          char *shp;
  369.  
  370. -        if (!tmp_dam->cost)
  371. +        if (tmp_dam->when != monstermoves || !tmp_dam->cost)
  372.              continue;
  373.          cost_of_damage += tmp_dam->cost;
  374.          Strcpy(shops_affected,
  375. diff --git i/src/sp_lev.c w/src/sp_lev.c
  376. index a1b1f6d..800b0aa 100644
  377. --- i/src/sp_lev.c
  378. +++ w/src/sp_lev.c
  379. @@ -52,7 +52,6 @@ STATIC_DCL void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
  380.  STATIC_DCL void NDECL(shuffle_alignments);
  381.  STATIC_DCL void NDECL(count_features);
  382.  STATIC_DCL void NDECL(remove_boundary_syms);
  383. -STATIC_DCL void FDECL(set_door_orientation, (int, int));
  384.  STATIC_DCL void FDECL(maybe_add_door, (int, int, struct mkroom *));
  385.  STATIC_DCL void NDECL(link_doors_rooms);
  386.  STATIC_DCL void NDECL(fill_rooms);
  387. @@ -704,7 +703,7 @@ remove_boundary_syms()
  388.  }
  389.  
  390.  /* used by sel_set_door() and link_doors_rooms() */
  391. -STATIC_OVL void
  392. +void
  393.  set_door_orientation(x, y)
  394.  int x, y;
  395.  {
  396. diff --git i/src/zap.c w/src/zap.c
  397. index 5750b27..5af1a8c 100644
  398. --- i/src/zap.c
  399. +++ w/src/zap.c
  400. @@ -3297,6 +3297,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
  401.              case WAN_OPENING:
  402.              case WAN_LOCKING:
  403.              case WAN_STRIKING:
  404. +            case WAN_MAKE_INVISIBLE:
  405.              case SPE_KNOCK:
  406.              case SPE_WIZARD_LOCK:
  407.              case SPE_FORCE_BOLT:
  408. @@ -3304,7 +3305,8 @@ struct obj **pobj; /* object tossed/used, set to NULL
  409.                      if (cansee(bhitpos.x, bhitpos.y)
  410.                          || (obj->otyp == WAN_STRIKING && !Deaf))
  411.                          learnwand(obj);
  412. -                    if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
  413. +                    if (IS_DOOR(levl[bhitpos.x][bhitpos.y].typ)
  414. +                        && levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
  415.                          && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
  416.                          shopdoor = TRUE;
  417.                          add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
Add Comment
Please, Sign In to add comment