Merge branch 'master' into portal_branches
authorAdam Borowski <kilobyte@angband.pl>
Mon, 20 Feb 2012 04:07:00 +0000 (05:07 +0100)
committerAdam Borowski <kilobyte@angband.pl>
Mon, 20 Feb 2012 04:07:00 +0000 (05:07 +0100)
81 files changed:
1  2 
crawl-ref/source/abl-show.cc
crawl-ref/source/abyss.cc
crawl-ref/source/arena.cc
crawl-ref/source/artefact.cc
crawl-ref/source/beam.cc
crawl-ref/source/chardump.cc
crawl-ref/source/command.cc
crawl-ref/source/dat/des/branches/abyss.des
crawl-ref/source/dat/des/branches/pan.des
crawl-ref/source/dat/des/branches/zot.des
crawl-ref/source/dat/des/builder/uniques.des
crawl-ref/source/dat/des/portals/bailey.des
crawl-ref/source/dat/des/portals/bazaar.des
crawl-ref/source/dat/des/portals/icecave.des
crawl-ref/source/dat/des/portals/sewer.des
crawl-ref/source/dat/des/portals/trove.des
crawl-ref/source/dat/des/portals/wizlab.des
crawl-ref/source/dat/des/variable/float.des
crawl-ref/source/decks.cc
crawl-ref/source/dgn-labyrinth.cc
crawl-ref/source/dgn-shoals.cc
crawl-ref/source/directn.cc
crawl-ref/source/dungeon.cc
crawl-ref/source/dungeon.h
crawl-ref/source/effects.cc
crawl-ref/source/enum.h
crawl-ref/source/env.h
crawl-ref/source/externs.h
crawl-ref/source/files.cc
crawl-ref/source/files.h
crawl-ref/source/food.cc
crawl-ref/source/ghost.cc
crawl-ref/source/godpassive.cc
crawl-ref/source/godprayer.cc
crawl-ref/source/hints.cc
crawl-ref/source/hiscores.cc
crawl-ref/source/items.cc
crawl-ref/source/l_dgnmon.cc
crawl-ref/source/l_you.cc
crawl-ref/source/main.cc
crawl-ref/source/makeitem.cc
crawl-ref/source/mapdef.cc
crawl-ref/source/mapdef.h
crawl-ref/source/maps.cc
crawl-ref/source/melee_attack.cc
crawl-ref/source/mgen_data.h
crawl-ref/source/misc.cc
crawl-ref/source/mon-abil.cc
crawl-ref/source/mon-act.cc
crawl-ref/source/mon-cast.cc
crawl-ref/source/mon-gear.cc
crawl-ref/source/mon-pick.cc
crawl-ref/source/mon-place.cc
crawl-ref/source/mon-stuff.cc
crawl-ref/source/mon-transit.cc
crawl-ref/source/monster.cc
crawl-ref/source/ng-setup.cc
crawl-ref/source/notes.cc
crawl-ref/source/notes.h
crawl-ref/source/output.cc
crawl-ref/source/player.cc
crawl-ref/source/player.h
crawl-ref/source/religion.cc
crawl-ref/source/rltiles/dc-feat.txt
crawl-ref/source/shopping.cc
crawl-ref/source/spl-miscast.cc
crawl-ref/source/spl-transloc.cc
crawl-ref/source/stairs.cc
crawl-ref/source/startup.cc
crawl-ref/source/tag-version.h
crawl-ref/source/tags.cc
crawl-ref/source/terrain.cc
crawl-ref/source/tilepick.cc
crawl-ref/source/tileview.cc
crawl-ref/source/tileview.h
crawl-ref/source/traps.cc
crawl-ref/source/travel.cc
crawl-ref/source/travel.h
crawl-ref/source/viewmap.cc
crawl-ref/source/wiz-mon.cc
crawl-ref/source/xom.cc

Simple merge
@@@ -559,10 -563,10 +563,10 @@@ public
  static void _abyss_lose_monster(monster& mons)
  {
      if (mons.needs_abyss_transit())
 -        mons.set_transit(level_id(LEVEL_ABYSS));
 +        mons.set_transit(level_id(BRANCH_ABYSS));
  
      mons.destroy_inventory();
-     mons.reset();
+     monster_cleanup(&mons);
  }
  
  // If a sanctuary exists and is in LOS, moves it to keep it in the
@@@ -1319,15 -1374,32 +1378,32 @@@ retry
  
  void abyss_morph(double duration)
  {
 -    if (you.level_type != LEVEL_ABYSS)
 +    if (!player_in_branch(BRANCH_ABYSS))
          return;
  
-     abyssal_state.depth += you.time_taken * (you.abyss_speed + 40.0)
-                         / (you.religion == GOD_CHEIBRIADOS ? 40000.0 : 20000.0);
-     map_mask abyss_genlevel_mask;
-     _abyss_invert_mask(&abyss_genlevel_mask);
+     // Between .02 and .07 per ten ticks, half that for Chei worshippers.
+     double delta_t = you.time_taken * (you.abyss_speed + 40.0) / 20000.0;
+     if (you.religion == GOD_CHEIBRIADOS)
+         delta_t /= 2.0;
+     const double theta = abyssal_state.phase;
+     const double old_depth = abyssal_state.depth;
+     // Up to 3 times the old rate of change, as low as 1/5, with an average of
+     // 89%.  Period of 2*pi, so from 90 to 314 turns depending on abyss speed
+     // (double for Chei worshippers).  Starts in the middle of a cool period.
+     // Increasing the exponent reduces the lengths of the unstable periods.  It
+     // should be an even integer.
+     abyssal_state.depth += delta_t * (0.2 + 2.8 * pow(sin(theta/2), 10.0));
+     // Phase mod pi.
+     abyssal_state.phase += delta_t;
+     if (abyssal_state.phase > M_PI)
+         abyssal_state.phase -= M_PI;
+     map_mask abyss_genlevel_mask(1);
      dgn_erase_unused_vault_placements();
-     _abyss_apply_terrain(abyss_genlevel_mask, true);
+     _abyss_apply_terrain(abyss_genlevel_mask, true, old_depth);
      _place_displaced_monsters();
      _push_items();
      los_changed();
@@@ -1428,10 -1500,8 +1504,9 @@@ static bool _spawn_corrupted_servant_ne
  
          mgen_data mg(mons, beh, 0, 5, 0, p);
          mg.non_actor_summoner = "Lugonu's corruption";
 +        mg.place = BRANCH_ABYSS;
  
-         const int mid = create_monster(mg);
-         return !invalid_monster_index(mid);
+         return create_monster(mg);
      }
  
      return (false);
@@@ -200,9 -197,9 +197,9 @@@ namespace aren
                  if (!in_bounds(loc))
                      break;
  
-                 const int imon = dgn_place_monster(spec, -1,
-                                                    loc, false, true, false);
-                 if (imon == -1)
 -                const monster* mon = dgn_place_monster(spec, you.absdepth0,
++                const monster* mon = dgn_place_monster(spec, -1,
+                                                        loc, false, true, false);
+                 if (!mon)
                  {
                      game_ended_with_error(
                          make_stringf(
              if (fac.friendly)
                  spec.attitude = ATT_FRIENDLY;
  
-             int idx = dgn_place_monster(spec, -1, pos, false, true);
 -            monster *mon = dgn_place_monster(spec, you.absdepth0, pos,
 -                                             false, true);
++            monster *mon = dgn_place_monster(spec, -1, pos, false, true);
  
-             if (idx == -1 && fac.active_members == 0
-                 && monster_at(pos))
+             if (!mon && fac.active_members == 0 && monster_at(pos))
              {
                  // We have no members left, so to prevent the round
                  // from ending attempt to displace whatever is in
                      monster_teleport(other, true);
                  }
  
-                 idx = dgn_place_monster(spec, -1, pos, false, true);
 -                mon = dgn_place_monster(spec, you.absdepth0, pos, false,
 -                                        true);
++                mon = dgn_place_monster(spec, -1, pos, false, true);
              }
  
-             if (idx != -1)
+             if (mon)
              {
                  // We succeeded, so remove from list.
                  fac.respawn_list.erase(fac.respawn_list.begin() + i);
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -357,9 -357,11 +357,12 @@@ DEPTH:  Zo
  NAME:   uniq_ignacio
  DEPTH:  Pan
  CHANCE: 25%
 +# TODO: use regular unique code instead?
  TAGS:   pan transparent extra allow_dup luniq_ignacio
- {{
+ veto {{
+   if you.uniques("Ignacio") then
+     return true -- don't spam the list of vaults
+   end
    if not dgn.persist.ignacio_spawned then
      local runes = 0;
      for _, r in ipairs({"demonic","glowing","magical","fiery","dark"}) do
@@@ -400,8 -386,7 +400,7 @@@ ENDMA
  NAME:   bailey_axe_1
  WEIGHT: 10
  ORIENT: encompass
 -TAGS:   bailey_axe no_rotate no_item_gen no_monster_gen
 +TAGS:   bailey_axe no_rotate no_item_gen no_monster_gen no_pool_fixup
- LFLAGS: no_tele_control
  #
  ITEM:   any good_item w:10 / nothing w:5
  #
@@@ -517,8 -508,7 +516,7 @@@ ENDMA
  NAME:   bailey_axe_3
  WEIGHT: 10
  ORIENT: encompass
 -TAGS:   bailey_axe no_rotate no_item_gen no_monster_gen
 +TAGS:   bailey_axe no_rotate no_item_gen no_monster_gen no_pool_fixup
- LFLAGS: no_tele_control
  SUBST:  ' : +".
  SUBST:  " : wW"
  SUBST:  " = wwW
@@@ -581,8 -574,7 +579,7 @@@ ENDMA
  NAME:    bailey_axe_4
  WEIGHT:  10
  ORIENT:  encompass
 -TAGS:    bailey_axe no_rotate no_item_gen no_monster_gen
 +TAGS:    bailey_axe no_rotate no_item_gen no_monster_gen no_pool_fixup
- LFLAGS:  no_tele_control
  #
  ITEM:    any good_item
  ITEM:    potion of levitation ident:type
@@@ -737,8 -735,7 +734,7 @@@ ENDMA
  NAME:   bailey_polearm_1
  WEIGHT: 10
  ORIENT: encompass
 -TAGS:   bailey_polearm no_rotate
 +TAGS:   bailey_polearm no_rotate no_pool_fixup
- LFLAGS: no_tele_control
  NSUBST: D = 1:= / *:c
  NSUBST: E = 1:= / *:c
  : orc_with_polearm(_G)
@@@ -908,8 -914,7 +904,7 @@@ ENDMA
  NAME:   bailey_polearm_4
  WEIGHT: 10
  ORIENT: encompass
 -TAGS:   bailey_polearm no_rotate no_item_gen no_monster_gen
 +TAGS:   bailey_polearm no_rotate no_item_gen no_monster_gen no_pool_fixup
- LFLAGS: no_tele_control
  ITEM:   any good_item / nothing
  MONS:   orc warrior ; crossbow . bolt | halberd
  : orc_with_polearm(_G)
@@@ -1554,9 -1610,34 +1554,33 @@@ xxxxxxxxx.xxx.................xxxxxxxx
  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  ENDMAP
  
+ NAME:    bazaar_jpeg_triangle_bulge
 -TAGS:    bazaar no_rotate
++TAGS:    no_rotate
+ ORIENT:  encompass
+ WEIGHT:  10
+ SHUFFLE: AB
+ SUBST:   A = <, B = >
+ KFEAT:   C = any shop
 -: bazaar_epilogue(_G)
+ MAP
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxCxxxxxxxxxxxxxx
+ xxxxxxxxxxxx.....xxxxxxxxxxxx
+ xxxxxxxxxx.........xxxxxxxxxx
+ xxxxxxxx....B...B....xxxxxxxx
+ xxxxxx.................xxxxxx
+ xxxx....C.....B.....C....xxxx
+ xxA.......................Axx
+ xxxxxxxxxxxxx...xxxxxxxxxxxxx
+ xxxxxxxxxxxxx...xxxxxxxxxxxxx
+ xxxxxxxxxxxx.....xxxxxxxxxxxx
+ xxxxxxxxxxx...C...xxxxxxxxxxx
+ xxxxxxxxxxxx.....xxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ ENDMAP
  # ~3.75 shops
  NAME:     due_bazaar_butterfly
 -TAGS:     bazaar no_rotate
 +TAGS:     no_rotate
  ORIENT:   encompass
  WEIGHT:   10
  SHUFFLE:  AEST
@@@ -1742,33 -1828,9 +1766,9 @@@ ENDMA
  # Expect to never see them in regular games, but for long Nemelex games
  # they'll drown out the competition.
  
- NAME:    bazaar_jpeg_triangle_bulge
- TAGS:    no_rotate allow_dup
- ORIENT:  encompass
- WEIGHT:  1
- SHUFFLE: AB
- SUBST:   A = <, B = >
- KFEAT:   C = any shop
- MAP
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- xxxxxxxxxxxxxxCxxxxxxxxxxxxxx
- xxxxxxxxxxxx.....xxxxxxxxxxxx
- xxxxxxxxxx.........xxxxxxxxxx
- xxxxxxxx....B...B....xxxxxxxx
- xxxxxx.................xxxxxx
- xxxx....C.....B.....C....xxxx
- xxA.......................Axx
- xxxxxxxxxxxxx...xxxxxxxxxxxxx
- xxxxxxxxxxxxx...xxxxxxxxxxxxx
- xxxxxxxxxxxx.....xxxxxxxxxxxx
- xxxxxxxxxxx...C...xxxxxxxxxxx
- xxxxxxxxxxxx.....xxxxxxxxxxxx
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- ENDMAP
  # A generated bazaar map.
  NAME:   bazaar_kb_twisted_cavern
 -TAGS:   bazaar allow_dup
 +TAGS:   allow_dup
  ORIENT: encompass
  WEIGHT: 1
  {{
@@@ -34,31 -34,8 +34,10 @@@ function ice_cave_portal(e
                                 "$F{The} is almost completely melted.")
      }
  
-   -- There are actually two kinds of ice caves: easy and hard ones. Players
-   -- that enter the portal deeper in the dungeon end up in the hard ones.
-   -- Possible depths for easy ice caves are D:11-14, Lair:1-8, Orc:1-4.
-   -- Hard ice caves are in D:14-19, Elf:1-5 and Vault:1-7. Those depths are
-   -- set in the entry vault default-depth.
-   --
-   -- Now, first default to easy destinations.
-   local difficulty = "ice_cave_easy"
-   -- Handle overlapping depths for easy and hard maps with a coinflip.
-   if you.branch() == "D" and you.depth() == 14 or
-      you.branch() == "Elf" and you.depth() < 3 then
-       if crawl.coinflip() then
-           difficulty = "ice_cave_hard"
-       end
-   end
-   if you.branch() == "D" and you.depth() >= 15 or
-      you.branch() == "Elf" or
-      you.branch() == "Vault" then
-       difficulty = "ice_cave_hard"
-   end
+   local difficulty = ice_cave_difficulty()
  
 +  dgn.persist.ice_cave_type = difficulty
 +
    e.lua_marker('O',
        timed_marker {
          disappear = "The archway melts and disappears.",
@@@ -87,6 -68,36 +69,36 @@@ en
  }}
  
  {{
+ -- Figure out if an easy or a hard ice cave should be used. Players
+ -- that enter the portal deeper in the dungeon end up in the hard ones.
+ -- Possible depths for easy ice caves are D:11-14, Lair:1-8, Orc:1-4.
+ -- Hard ice caves are in D:14-19, Elf:1-5 and Vault:1-7. Those depths are
+ -- set in the entry vault default-depth.
+ function ice_cave_difficulty()
+   -- First default to easy destinations.
+   local difficulty = "ice_cave_easy"
+   -- Handle overlapping depths for easy and hard maps with a coinflip.
 -  if you.branch() == "D" and you.subdepth() == 14 or
 -     you.branch() == "Elf" and you.subdepth() < 3 then
++  if you.branch() == "D" and you.depth() == 14 or
++     you.branch() == "Elf" and you.depth() < 3 then
+       if crawl.coinflip() then
+           difficulty = "ice_cave_hard"
+       end
+   end
 -  if you.branch() == "D" and you.subdepth() >= 15 or
++  if you.branch() == "D" and you.depth() >= 15 or
+      you.branch() == "Elf" or
+      you.branch() == "Vault" then
+       difficulty = "ice_cave_hard"
+   end
+   return difficulty
+ end
+ }}
+ {{
  -- Find the slave of the teleporter and move to it.
  function callback.ice_cave_statue_garden_teleporter(data, triggerable,
                                                       triggerer, marker, ev)
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -2355,10 -2436,10 +2371,10 @@@ static void _prepare_water(
                      grd(*ri) = DNGN_SHALLOW_WATER;
                  }
                  else if (which_grid >= DNGN_FLOOR
 -                         && x_chance_in_y(80 - level_number * 4,
 +                         && x_chance_in_y(80 - absdepth0 * 4,
                                            100))
                  {
-                     grd(*ri) = DNGN_SHALLOW_WATER;
+                     _set_grd(*ri, DNGN_SHALLOW_WATER);
                  }
              }
          }
@@@ -3877,15 -4052,15 +3899,15 @@@ int dgn_item_corpse(const item_spec &is
      {
          if (tries > 200)
              return NON_ITEM;
-         int mindex = dgn_place_monster(mspec, -1, coord_def(), true);
-         if (invalid_monster_index(mindex))
 -        monster *mon = dgn_place_monster(mspec, you.absdepth0, coord_def(), true);
++        monster *mon = dgn_place_monster(mspec, -1, coord_def(), true);
+         if (!mon)
              continue;
-         menv[mindex].position = where;
-         if (mons_class_can_leave_corpse(menv[mindex].type))
-             corpse_index = place_monster_corpse(&menv[mindex], true, true);
+         mon->position = where;
+         if (mons_class_can_leave_corpse(mon->type))
+             corpse_index = place_monster_corpse(mon, true, true);
          // Dismiss the monster we used to place the corpse.
-         menv[mindex].flags |= MF_HARD_RESET;
-         monster_die(&menv[mindex], KILL_DISMISSED, NON_MONSTER, false, true);
+         mon->flags |= MF_HARD_RESET;
+         monster_die(mon, KILL_DISMISSED, NON_MONSTER, false, true);
  
          if (corpse_index != -1 && corpse_index != NON_ITEM)
              break;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -208,10 -209,10 +208,9 @@@ static int dgn_create_monster(lua_Stat
      for (int i = 0, size = mlist.size(); i < size; ++i)
      {
          mons_spec mspec = mlist.get_monster(i);
-         const int midx = dgn_place_monster(mspec, -1, c, false, false, false);
-         if (midx != -1)
 -        if (monster *mon = dgn_place_monster(mspec, you.absdepth0, c,
 -                                             false, false, false))
++        if (monster *mon = dgn_place_monster(mspec, -1, c, false, false, false))
          {
-             push_monster(ls, &menv[midx]);
+             push_monster(ls, mon);
              return (1);
          }
      }
Simple merge
@@@ -3017,8 -3036,12 +3016,12 @@@ static void _player_reacts(
          // this is instantaneous
          if (teleportitis_level > 0 && one_chance_in(100 / teleportitis_level))
              you_teleport_now(true);
 -        else if (you.level_type == LEVEL_ABYSS && one_chance_in(80))
 +        else if (player_in_branch(BRANCH_ABYSS) && one_chance_in(80))
+         {
+             mpr("You are suddenly pulled into a different region of the Abyss!",
+                 MSGCH_BANISHMENT);
              you_teleport_now(false, true); // to new area of the Abyss
+         }
      }
  
      actor_apply_cloud(&you);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1305,23 -1299,21 +1299,21 @@@ static void _establish_connection(int t
              mgen_data(connector_type, SAME_ATTITUDE(main), main,
                        0, 0, last->pos, main->foe,
                        MG_FORCE_PLACE, main->god, MONS_NO_MONSTER, tentacle,
-                       main->colour, -1, PROX_CLOSE_TO_PLAYER));
-         if (connect < 0)
-         {
-             // Big failure mode.
-             return;
-         }
-         else
 -                      main->colour, you.absdepth0, PROX_CLOSE_TO_PLAYER)))
++                      main->colour, -1, PROX_CLOSE_TO_PLAYER)))
          {
-             menv[connect].props["inwards"].get_int()  = -1;
-             menv[connect].props["outwards"].get_int() = -1;
+             connect->props["inwards"].get_int()  = -1;
+             connect->props["outwards"].get_int() = -1;
  
              if (main->holiness() == MH_UNDEAD)
-                 menv[connect].flags |= MF_FAKE_UNDEAD;
+                 connect->flags |= MF_FAKE_UNDEAD;
  
-             menv[connect].max_hit_points = menv[tentacle].max_hit_points;
-             menv[connect].hit_points = menv[tentacle].hit_points;
+             connect->max_hit_points = menv[tentacle].max_hit_points;
+             connect->hit_points = menv[tentacle].hit_points;
+         }
+         else
+         {
+             // Big failure mode.
+             return;
          }
      }
  
              mgen_data(connector_type, SAME_ATTITUDE(main), main,
                        0, 0, current->pos, main->foe,
                        MG_FORCE_PLACE, main->god, MONS_NO_MONSTER, tentacle,
-                       main->colour, -1, PROX_CLOSE_TO_PLAYER));
-         if (connect >= 0)
 -                      main->colour, you.absdepth0, PROX_CLOSE_TO_PLAYER)))
++                      main->colour, -1, PROX_CLOSE_TO_PLAYER)))
          {
-             menv[connect].max_hit_points = menv[tentacle].max_hit_points;
-             menv[connect].hit_points = menv[tentacle].hit_points;
+             connect->max_hit_points = menv[tentacle].max_hit_points;
+             connect->hit_points = menv[tentacle].hit_points;
  
-             menv[connect].props["inwards"].get_int() = last_mon_idx;
-             menv[connect].props["outwards"].get_int() = -1;
+             connect->props["inwards"].get_int() = last_mon_idx;
+             connect->props["outwards"].get_int() = -1;
  
              if (last_mon->type == connector_type)
-                 menv[last_mon_idx].props["outwards"].get_int() = connect;
+                 menv[last_mon_idx].props["outwards"].get_int() = connect->mindex();
  
              if (main->holiness() == MH_UNDEAD)
-                 menv[connect].flags |= MF_FAKE_UNDEAD;
+                 connect->flags |= MF_FAKE_UNDEAD;
  
-             if (monster_can_submerge(&menv[connect], env.grid(menv[connect].pos())))
-                 menv[connect].add_ench(ENCH_SUBMERGED);
+             if (monster_can_submerge(connect, env.grid(connect->pos())))
+                 connect->add_ench(ENCH_SUBMERGED);
          }
          else
          {
Simple merge
@@@ -2139,7 -2139,7 +2139,7 @@@ void mons_cast_spectral_orcs(monster* m
              orc->number = (int) mon;
  
              // give gear using the base type
-             give_item(created, env.absdepth0, true, true);
 -            give_item(orc, you.absdepth0, true, true);
++            give_item(orc, env.absdepth0, true, true);
  
              // set gear as summoned
              orc->mark_summoned(abj, true, SPELL_SUMMON_SPECTRAL_ORCS);
@@@ -2908,15 -2915,13 +2915,13 @@@ void mons_cast(monster* mons, bolt &pbo
                  mgen_data(MONS_KRAKEN_TENTACLE, SAME_ATTITUDE(mons), mons,
                            0, 0, adj_squares[i], mons->foe,
                            MG_FORCE_PLACE, god, MONS_NO_MONSTER, kraken_index,
-                           mons->colour, -1, PROX_CLOSE_TO_PLAYER));
-             if (tentacle != -1)
 -                          mons->colour, you.absdepth0, PROX_CLOSE_TO_PLAYER)))
++                          mons->colour, -1, PROX_CLOSE_TO_PLAYER)))
              {
                  created_count++;
-                 menv[tentacle].props["inwards"].get_int() = kraken_index;
+                 tentacle->props["inwards"].get_int() = kraken_index;
  
                  if (mons->holiness() == MH_UNDEAD)
-                     menv[tentacle].flags |= MF_FAKE_UNDEAD;
+                     tentacle->flags |= MF_FAKE_UNDEAD;
              }
          }
  
@@@ -2130,13 -2136,8 +2136,10 @@@ void give_weapon(monster *mons, int lev
      _give_weapon(mons, level_number, false, true, spectral_orcs);
  }
  
- void give_item(int mid, int level_number, bool mons_summoned, bool spectral_orcs)
+ void give_item(monster *mons, int level_number, bool mons_summoned, bool spectral_orcs)
  {
 +    ASSERT(level_number > -1); // debugging absdepth0 changes
 +
-     monster* mons = &menv[mid];
      if (mons->type == MONS_MAURICE || mons->type == MONS_DEEP_DWARF_SCION)
          _give_gold(mons, level_number);
  
Simple merge
@@@ -956,10 -963,10 +956,10 @@@ static bool _valid_monster_generation_l
  // OOD packs, based on depth and time spent on-level.
  static bool _in_ood_pack_protected_place()
  {
 -    return (env.turns_on_level < 1400 - you.absdepth0 * 117);
 +    return (env.turns_on_level < 1400 - env.absdepth0 * 117);
  }
  
- int place_monster(mgen_data mg, bool force_pos, bool dont_place)
+ monster* place_monster(mgen_data mg, bool force_pos, bool dont_place)
  {
  #ifdef DEBUG_MON_CREATION
      mpr("in place_monster()", MSGCH_DIAGNOSTICS);
  
      // (1) Early out (summoned to occupied grid).
      if (mg.use_position() && monster_at(mg.pos))
-         return (-1);
+         return 0;
  
 +    if (mg.power == -1)
 +        mg.power = env.absdepth0;
 +
      bool chose_ood_monster = false;
      mg.cls = _resolve_monster_type(mg.cls, mg.proximity, mg.base_type,
                                     mg.pos, mg.map_mask,
Simple merge
@@@ -240,33 -240,48 +240,29 @@@ void follower::load_mons_items(
  
  bool follower::place(bool near_player)
  {
-     for (int i = 0; i < MAX_MONSTERS - 5; ++i)
-     {
-         // Find first empty slot in menv and copy monster into it.
-         monster& m = menv[i];
-         if (m.alive())
-             continue;
-         m = mons;
-         // Shafts no longer retain the position, if anything else would
-         // want to request a specific one, it should do so here if !near_player
-         if (m.find_place_to_live(near_player))
-         {
-             dprf("Placed follower: %s", m.name(DESC_PLAIN).c_str());
-             m.target.reset();
+     monster *m = get_free_monster();
+     if (!m)
+         return false;
  
-             m.flags &= ~MF_TAKING_STAIRS & ~MF_BANISHED;
-             m.flags |= MF_JUST_SUMMONED;
+     // Copy the saved data.
+     *m = mons;
  
-             restore_mons_items(m);
-             return (true);
-         }
 -    bool placed = false;
++    // Shafts no longer retain the position, if anything else would
++    // want to request a specific one, it should do so here if !near_player
  
-         m.reset();
-         break;
 -    // In certain instances (currently, falling through a shaft)
 -    // try to place monster as close as possible to its previous
 -    // <x,y> coordinates.
 -    if (!near_player && you.level_type == LEVEL_DUNGEON
 -        && in_bounds(m->pos()))
 -    {
 -        const coord_def where_to_go =
 -            dgn_find_nearby_stair(DNGN_ESCAPE_HATCH_DOWN,
 -                                  m->pos(), true);
 -
 -        if (where_to_go == you.pos())
 -            near_player = true;
 -        else if (m->find_home_near_place(where_to_go))
 -            placed = true;
 -    }
 -
 -    if (!placed)
 -        placed = m->find_place_to_live(near_player);
 -
 -    if (placed)
++    if (m->find_place_to_live(near_player))
+     {
+         dprf("Placed follower: %s", m->name(DESC_PLAIN).c_str());
+         m->target.reset();
 -        m->flags &= ~MF_TAKING_STAIRS;
++        m->flags &= ~MF_TAKING_STAIRS & ~MF_BANISHED;
+         m->flags |= MF_JUST_SUMMONED;
 -
+         restore_mons_items(*m);
+         env.mid_cache[m->mid] = m->mindex();
+         return (true);
      }
  
+     m->reset();
      return (false);
  }
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -118,13 -118,15 +118,13 @@@ bool g_Slime_Wall_Check = true
  
  static uint8_t curr_waypoints[GXM][GYM];
  
- const int8_t TRAVERSABLE = 1;
- const int8_t IMPASSABLE  = 0;
- const int8_t FORBIDDEN   = -1;
+ // If true, feat_is_traversable_now() returns the same as feat_is_traversable().
+ // FIXME: eliminate this.  It's needed for RMODE_CONNECTIVITY.
+ static bool ignore_player_traversability = false;
  
- // Map of terrain types that are traversable.
- static FixedVector<int8_t,NUM_FEATURES> traversable_terrain;
+ // Map of terrain types that are forbidden.
+ static FixedVector<int8_t,NUM_FEATURES> forbidden_terrain;
  
 -static std::set<std::string> portal_names;
 -
  /*
   * Warn if interlevel travel is going to take you outside levels in
   * the range [src,dest].
@@@ -2156,13 -2128,12 +2127,12 @@@ static int _prompt_travel_branch(int pr
                  if (toupper(keyin) == branches[br[i]].travel_shortcut)
                  {
  #ifdef WIZARD
 -                    Branch     &target = branches[br[i]];
 +                    const Branch &target = branches[br[i]];
                      std::string msg;
  
 -                    if (target.startdepth == -1
 +                    if (startdepth[br[i]] == -1
-                         && (i == BRANCH_SWAMP
-                             || i == BRANCH_SHOALS
-                             || i == BRANCH_SNAKE_PIT))
+                         && is_random_lair_subbranch((branch_type)i)
+                         && you.wizard) // don't leak mimics
                      {
                          msg += "Branch not generated this game. ";
                      }
Simple merge
Simple merge
@@@ -250,10 -249,10 +249,10 @@@ void wizard_create_spec_monster_name(
  
      // Wizmode users should be able to conjure up uniques even if they
      // were already created. Yay, you can meet 3 Sigmunds at once! :p
-     if (mons_is_unique(mspec.mid) && you.unique_creatures[mspec.mid])
-         you.unique_creatures[mspec.mid] = false;
+     if (mons_is_unique(mspec.type) && you.unique_creatures[mspec.type])
+         you.unique_creatures[mspec.type] = false;
  
-     if (dgn_place_monster(mspec, -1, place, true, false) == -1)
 -    if (!dgn_place_monster(mspec, you.absdepth0, place, true, false))
++    if (!dgn_place_monster(mspec, -1, place, true, false))
      {
          mpr("Unable to place monster.", MSGCH_DIAGNOSTICS);
          return;
Simple merge