Difference between revisions of "Source:NetHack 3.4.3/src/sp lev.c"

From NetHackWiki
Jump to navigation Jump to search
(Automated source code upload)
 
m (Add headers.)
Line 1: Line 1:
 +
Below is the full text to src/sp_lev.c from NetHack 3.4.3. To link to a particular line, write [[sp_lev.c#line123|<nowiki>[[sp_lev.c#line123]]</nowiki>]], for example.
 +
 +
== Top of file ==
  
Below is the full text to src/sp_lev.c from NetHack 3.4.3. To link to a particular line, write [[sp_lev.c#line123|<nowiki>[[sp_lev.c#line123]]</nowiki>]], for example.
 
 
  <span id="line1">1.    /* SCCS Id: @(#)sp_lev.c 3.4 2001/09/06 */</span>
 
  <span id="line1">1.    /* SCCS Id: @(#)sp_lev.c 3.4 2001/09/06 */</span>
 
  <span id="line2">2.    /* Copyright (c) 1989 by Jean-Christophe Collet */</span>
 
  <span id="line2">2.    /* Copyright (c) 1989 by Jean-Christophe Collet */</span>
Line 102: Line 104:
 
  <span id="line97">97.  lev_init init_lev;</span>
 
  <span id="line97">97.  lev_init init_lev;</span>
 
  <span id="line98">98.  </span>
 
  <span id="line98">98.  </span>
 +
 +
== set_wall_property ==
 +
 
  <span id="line99">99.  /*</span>
 
  <span id="line99">99.  /*</span>
 
  <span id="line100">100.  * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able</span>
 
  <span id="line100">100.  * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able</span>
Line 119: Line 124:
 
  <span id="line114">114.  }</span>
 
  <span id="line114">114.  }</span>
 
  <span id="line115">115.  </span>
 
  <span id="line115">115.  </span>
 +
 +
== rnddoor ==
 +
 
  <span id="line116">116.  /*</span>
 
  <span id="line116">116.  /*</span>
 
  <span id="line117">117.  * Choose randomly the state (nodoor, open, closed or locked) for a door</span>
 
  <span id="line117">117.  * Choose randomly the state (nodoor, open, closed or locked) for a door</span>
Line 130: Line 138:
 
  <span id="line125">125.  }</span>
 
  <span id="line125">125.  }</span>
 
  <span id="line126">126.  </span>
 
  <span id="line126">126.  </span>
 +
 +
== rndtrap ==
 +
 
  <span id="line127">127.  /*</span>
 
  <span id="line127">127.  /*</span>
 
  <span id="line128">128.  * Select a random trap</span>
 
  <span id="line128">128.  * Select a random trap</span>
Line 157: Line 168:
 
  <span id="line152">152.  }</span>
 
  <span id="line152">152.  }</span>
 
  <span id="line153">153.  </span>
 
  <span id="line153">153.  </span>
 +
 +
== get_location ==
 +
 
  <span id="line154">154.  /*</span>
 
  <span id="line154">154.  /*</span>
 
  <span id="line155">155.  * Coordinates in special level files are handled specially:</span>
 
  <span id="line155">155.  * Coordinates in special level files are handled specially:</span>
Line 212: Line 226:
 
  <span id="line207">207.  }</span>
 
  <span id="line207">207.  }</span>
 
  <span id="line208">208.  </span>
 
  <span id="line208">208.  </span>
 +
 +
== is_ok_location ==
 +
 
  <span id="line209">209.  STATIC_OVL boolean</span>
 
  <span id="line209">209.  STATIC_OVL boolean</span>
 
  <span id="line210">210.  is_ok_location(x, y, humidity)</span>
 
  <span id="line210">210.  is_ok_location(x, y, humidity)</span>
Line 234: Line 251:
 
  <span id="line229">229.  }</span>
 
  <span id="line229">229.  }</span>
 
  <span id="line230">230.  </span>
 
  <span id="line230">230.  </span>
 +
 +
== sp_lev_shuffle ==
 +
 
  <span id="line231">231.  /*</span>
 
  <span id="line231">231.  /*</span>
 
  <span id="line232">232.  * Shuffle the registers for locations, objects or monsters</span>
 
  <span id="line232">232.  * Shuffle the registers for locations, objects or monsters</span>
Line 259: Line 279:
 
  <span id="line254">254.  }</span>
 
  <span id="line254">254.  }</span>
 
  <span id="line255">255.  </span>
 
  <span id="line255">255.  </span>
 +
 +
== get_room_loc ==
 +
 
  <span id="line256">256.  /*</span>
 
  <span id="line256">256.  /*</span>
 
  <span id="line257">257.  * Get a relative position inside a room.</span>
 
  <span id="line257">257.  * Get a relative position inside a room.</span>
Line 287: Line 310:
 
  <span id="line282">282.  }</span>
 
  <span id="line282">282.  }</span>
 
  <span id="line283">283.  </span>
 
  <span id="line283">283.  </span>
 +
 +
== get_free_room_loc ==
 +
 
  <span id="line284">284.  /*</span>
 
  <span id="line284">284.  /*</span>
 
  <span id="line285">285.  * Get a relative position inside a room.</span>
 
  <span id="line285">285.  * Get a relative position inside a room.</span>
Line 310: Line 336:
 
  <span id="line305">305.  }</span>
 
  <span id="line305">305.  }</span>
 
  <span id="line306">306.  </span>
 
  <span id="line306">306.  </span>
 +
 +
== check_room ==
 +
 
  <span id="line307">307.  boolean</span>
 
  <span id="line307">307.  boolean</span>
 
  <span id="line308">308.  check_room(lowx, ddx, lowy, ddy, vault)</span>
 
  <span id="line308">308.  check_room(lowx, ddx, lowy, ddy, vault)</span>
Line 360: Line 389:
 
  <span id="line355">355.  }</span>
 
  <span id="line355">355.  }</span>
 
  <span id="line356">356.  </span>
 
  <span id="line356">356.  </span>
 +
 +
== create_room ==
 +
 
  <span id="line357">357.  /*</span>
 
  <span id="line357">357.  /*</span>
 
  <span id="line358">358.  * Create a new room.</span>
 
  <span id="line358">358.  * Create a new room.</span>
Line 530: Line 562:
 
  <span id="line525">525.  }</span>
 
  <span id="line525">525.  }</span>
 
  <span id="line526">526.  </span>
 
  <span id="line526">526.  </span>
 +
 +
== create_subroom ==
 +
 
  <span id="line527">527.  /*</span>
 
  <span id="line527">527.  /*</span>
 
  <span id="line528">528.  * Create a subroom in room proom at pos x,y with width w & height h.</span>
 
  <span id="line528">528.  * Create a subroom in room proom at pos x,y with width w & height h.</span>
Line 579: Line 614:
 
  <span id="line574">574.  }</span>
 
  <span id="line574">574.  }</span>
 
  <span id="line575">575.  </span>
 
  <span id="line575">575.  </span>
 +
 +
== create_door ==
 +
 
  <span id="line576">576.  /*</span>
 
  <span id="line576">576.  /*</span>
 
  <span id="line577">577.  * Create a new door in a room.</span>
 
  <span id="line577">577.  * Create a new door in a room.</span>
Line 665: Line 703:
 
  <span id="line660">660.  }</span>
 
  <span id="line660">660.  }</span>
 
  <span id="line661">661.  </span>
 
  <span id="line661">661.  </span>
 +
 +
== create_secret_door ==
 +
 
  <span id="line662">662.  /*</span>
 
  <span id="line662">662.  /*</span>
 
  <span id="line663">663.  * Create a secret door in croom on any one of the specified walls.</span>
 
  <span id="line663">663.  * Create a secret door in croom on any one of the specified walls.</span>
Line 706: Line 747:
 
  <span id="line701">701.  }</span>
 
  <span id="line701">701.  }</span>
 
  <span id="line702">702.  </span>
 
  <span id="line702">702.  </span>
 +
 +
== create_trap ==
 +
 
  <span id="line703">703.  /*</span>
 
  <span id="line703">703.  /*</span>
 
  <span id="line704">704.  * Create a trap in a room.</span>
 
  <span id="line704">704.  * Create a trap in a room.</span>
Line 733: Line 777:
 
  <span id="line728">728.  }</span>
 
  <span id="line728">728.  }</span>
 
  <span id="line729">729.  </span>
 
  <span id="line729">729.  </span>
 +
 +
== noncoalignment ==
 +
 
  <span id="line730">730.  /*</span>
 
  <span id="line730">730.  /*</span>
 
  <span id="line731">731.  * Create a monster in a room.</span>
 
  <span id="line731">731.  * Create a monster in a room.</span>
Line 749: Line 796:
 
  <span id="line744">744.  }</span>
 
  <span id="line744">744.  }</span>
 
  <span id="line745">745.  </span>
 
  <span id="line745">745.  </span>
 +
 +
== create_monster ==
 +
 
  <span id="line746">746.  STATIC_OVL void</span>
 
  <span id="line746">746.  STATIC_OVL void</span>
 
  <span id="line747">747.  create_monster(m,croom)</span>
 
  <span id="line747">747.  create_monster(m,croom)</span>
Line 906: Line 956:
 
  <span id="line901">901.  }</span>
 
  <span id="line901">901.  }</span>
 
  <span id="line902">902.  </span>
 
  <span id="line902">902.  </span>
 +
 +
== create_object ==
 +
 
  <span id="line903">903.  /*</span>
 
  <span id="line903">903.  /*</span>
 
  <span id="line904">904.  * Create an object in a room.</span>
 
  <span id="line904">904.  * Create an object in a room.</span>
Line 1,045: Line 1,098:
 
  <span id="line1040">1040. }</span>
 
  <span id="line1040">1040. }</span>
 
  <span id="line1041">1041. </span>
 
  <span id="line1041">1041. </span>
 +
 +
== create_engraving ==
 +
 
  <span id="line1042">1042. /*</span>
 
  <span id="line1042">1042. /*</span>
 
  <span id="line1043">1043.  * Randomly place a specific engraving, then release its memory.</span>
 
  <span id="line1043">1043.  * Randomly place a specific engraving, then release its memory.</span>
Line 1,065: Line 1,121:
 
  <span id="line1060">1060. }</span>
 
  <span id="line1060">1060. }</span>
 
  <span id="line1061">1061. </span>
 
  <span id="line1061">1061. </span>
 +
 +
== create_stairs ==
 +
 
  <span id="line1062">1062. /*</span>
 
  <span id="line1062">1062. /*</span>
 
  <span id="line1063">1063.  * Create stairs in a room.</span>
 
  <span id="line1063">1063.  * Create stairs in a room.</span>
Line 1,082: Line 1,141:
 
  <span id="line1077">1077. }</span>
 
  <span id="line1077">1077. }</span>
 
  <span id="line1078">1078. </span>
 
  <span id="line1078">1078. </span>
 +
 +
== create_altar ==
 +
 
  <span id="line1079">1079. /*</span>
 
  <span id="line1079">1079. /*</span>
 
  <span id="line1080">1080.  * Create an altar in a room.</span>
 
  <span id="line1080">1080.  * Create an altar in a room.</span>
Line 1,152: Line 1,214:
 
  <span id="line1147">1147. }</span>
 
  <span id="line1147">1147. }</span>
 
  <span id="line1148">1148. </span>
 
  <span id="line1148">1148. </span>
 +
 +
== create_gold ==
 +
 
  <span id="line1149">1149. /*</span>
 
  <span id="line1149">1149. /*</span>
 
  <span id="line1150">1150.  * Create a gold pile in a room.</span>
 
  <span id="line1150">1150.  * Create a gold pile in a room.</span>
Line 1,174: Line 1,239:
 
  <span id="line1169">1169. }</span>
 
  <span id="line1169">1169. }</span>
 
  <span id="line1170">1170. </span>
 
  <span id="line1170">1170. </span>
 +
 +
== create_feature ==
 +
 
  <span id="line1171">1171. /*</span>
 
  <span id="line1171">1171. /*</span>
 
  <span id="line1172">1172.  * Create a feature (e.g a fountain) in a room.</span>
 
  <span id="line1172">1172.  * Create a feature (e.g a fountain) in a room.</span>
Line 1,215: Line 1,283:
 
  <span id="line1210">1210. }</span>
 
  <span id="line1210">1210. }</span>
 
  <span id="line1211">1211. </span>
 
  <span id="line1211">1211. </span>
 +
 +
== search_door ==
 +
 
  <span id="line1212">1212. /*</span>
 
  <span id="line1212">1212. /*</span>
 
  <span id="line1213">1213.  * Search for a door in a room on a specified wall.</span>
 
  <span id="line1213">1213.  * Search for a door in a room on a specified wall.</span>
Line 1,268: Line 1,339:
 
  <span id="line1263">1263. }</span>
 
  <span id="line1263">1263. }</span>
 
  <span id="line1264">1264. </span>
 
  <span id="line1264">1264. </span>
 +
 +
== dig_corridor ==
 +
 
  <span id="line1265">1265. /*</span>
 
  <span id="line1265">1265. /*</span>
 
  <span id="line1266">1266.  * Dig a corridor between two points.</span>
 
  <span id="line1266">1266.  * Dig a corridor between two points.</span>
Line 1,374: Line 1,448:
 
  <span id="line1369">1369. }</span>
 
  <span id="line1369">1369. }</span>
 
  <span id="line1370">1370. </span>
 
  <span id="line1370">1370. </span>
 +
 +
== fix_stair_rooms ==
 +
 
  <span id="line1371">1371. /*</span>
 
  <span id="line1371">1371. /*</span>
 
  <span id="line1372">1372.  * Disgusting hack: since special levels have their rooms filled before</span>
 
  <span id="line1372">1372.  * Disgusting hack: since special levels have their rooms filled before</span>
Line 1,416: Line 1,493:
 
  <span id="line1411">1411. }</span>
 
  <span id="line1411">1411. }</span>
 
  <span id="line1412">1412. </span>
 
  <span id="line1412">1412. </span>
 +
 +
== create_corridor ==
 +
 
  <span id="line1413">1413. /*</span>
 
  <span id="line1413">1413. /*</span>
 
  <span id="line1414">1414.  * Corridors always start from a door. But it can end anywhere...</span>
 
  <span id="line1414">1414.  * Corridors always start from a door. But it can end anywhere...</span>
Line 1,460: Line 1,540:
 
  <span id="line1455">1455. </span>
 
  <span id="line1455">1455. </span>
 
  <span id="line1456">1456. </span>
 
  <span id="line1456">1456. </span>
 +
 +
== fill_room ==
 +
 
  <span id="line1457">1457. /*</span>
 
  <span id="line1457">1457. /*</span>
 
  <span id="line1458">1458.  * Fill a room (shop, zoo, etc...) with appropriate stuff.</span>
 
  <span id="line1458">1458.  * Fill a room (shop, zoo, etc...) with appropriate stuff.</span>
Line 1,525: Line 1,608:
 
  <span id="line1520">1520. }</span>
 
  <span id="line1520">1520. }</span>
 
  <span id="line1521">1521. </span>
 
  <span id="line1521">1521. </span>
 +
 +
== free_rooms ==
 +
 
  <span id="line1522">1522. STATIC_OVL void</span>
 
  <span id="line1522">1522. STATIC_OVL void</span>
 
  <span id="line1523">1523. free_rooms(ro, n)</span>
 
  <span id="line1523">1523. free_rooms(ro, n)</span>
Line 1,597: Line 1,683:
 
  <span id="line1592">1592. }</span>
 
  <span id="line1592">1592. }</span>
 
  <span id="line1593">1593. </span>
 
  <span id="line1593">1593. </span>
 +
 +
== build_room ==
 +
 
  <span id="line1594">1594. STATIC_OVL void</span>
 
  <span id="line1594">1594. STATIC_OVL void</span>
 
  <span id="line1595">1595. build_room(r, pr)</span>
 
  <span id="line1595">1595. build_room(r, pr)</span>
Line 1,675: Line 1,764:
 
  <span id="line1670">1670. }</span>
 
  <span id="line1670">1670. }</span>
 
  <span id="line1671">1671. </span>
 
  <span id="line1671">1671. </span>
 +
 +
== light_region ==
 +
 
  <span id="line1672">1672. /*</span>
 
  <span id="line1672">1672. /*</span>
 
  <span id="line1673">1673.  * set lighting in a region that will not become a room.</span>
 
  <span id="line1673">1673.  * set lighting in a region that will not become a room.</span>
Line 1,706: Line 1,798:
 
  <span id="line1701">1701. }</span>
 
  <span id="line1701">1701. }</span>
 
  <span id="line1702">1702. </span>
 
  <span id="line1702">1702. </span>
 +
 +
== load_common_data ==
 +
 
  <span id="line1703">1703. /* initialization common to all special levels */</span>
 
  <span id="line1703">1703. /* initialization common to all special levels */</span>
 
  <span id="line1704">1704. STATIC_OVL void</span>
 
  <span id="line1704">1704. STATIC_OVL void</span>
Line 1,755: Line 1,850:
 
  <span id="line1750">1750. }</span>
 
  <span id="line1750">1750. }</span>
 
  <span id="line1751">1751. </span>
 
  <span id="line1751">1751. </span>
 +
 +
== load_one_monster ==
 +
 
  <span id="line1752">1752. STATIC_OVL void</span>
 
  <span id="line1752">1752. STATIC_OVL void</span>
 
  <span id="line1753">1753. load_one_monster(fd, m)</span>
 
  <span id="line1753">1753. load_one_monster(fd, m)</span>
Line 1,777: Line 1,875:
 
  <span id="line1772">1772. }</span>
 
  <span id="line1772">1772. }</span>
 
  <span id="line1773">1773. </span>
 
  <span id="line1773">1773. </span>
 +
 +
== load_one_object ==
 +
 
  <span id="line1774">1774. STATIC_OVL void</span>
 
  <span id="line1774">1774. STATIC_OVL void</span>
 
  <span id="line1775">1775. load_one_object(fd, o)</span>
 
  <span id="line1775">1775. load_one_object(fd, o)</span>
Line 1,793: Line 1,894:
 
  <span id="line1788">1788. }</span>
 
  <span id="line1788">1788. }</span>
 
  <span id="line1789">1789. </span>
 
  <span id="line1789">1789. </span>
 +
 +
== load_one_engraving ==
 +
 
  <span id="line1790">1790. STATIC_OVL void</span>
 
  <span id="line1790">1790. STATIC_OVL void</span>
 
  <span id="line1791">1791. load_one_engraving(fd, e)</span>
 
  <span id="line1791">1791. load_one_engraving(fd, e)</span>
Line 1,807: Line 1,911:
 
  <span id="line1802">1802. }</span>
 
  <span id="line1802">1802. }</span>
 
  <span id="line1803">1803. </span>
 
  <span id="line1803">1803. </span>
 +
 +
== load_rooms ==
 +
 
  <span id="line1804">1804. STATIC_OVL boolean</span>
 
  <span id="line1804">1804. STATIC_OVL boolean</span>
 
  <span id="line1805">1805. load_rooms(fd)</span>
 
  <span id="line1805">1805. load_rooms(fd)</span>
Line 2,030: Line 2,137:
 
  <span id="line2025">2025. }</span>
 
  <span id="line2025">2025. }</span>
 
  <span id="line2026">2026. </span>
 
  <span id="line2026">2026. </span>
 +
 +
== maze1xy ==
 +
 
  <span id="line2027">2027. /*</span>
 
  <span id="line2027">2027. /*</span>
 
  <span id="line2028">2028.  * Select a random coordinate in the maze.</span>
 
  <span id="line2028">2028.  * Select a random coordinate in the maze.</span>
Line 2,057: Line 2,167:
 
  <span id="line2052">2052. }</span>
 
  <span id="line2052">2052. }</span>
 
  <span id="line2053">2053. </span>
 
  <span id="line2053">2053. </span>
 +
 +
== load_maze ==
 +
 
  <span id="line2054">2054. /*</span>
 
  <span id="line2054">2054. /*</span>
 
  <span id="line2055">2055.  * The Big Thing: special maze loader</span>
 
  <span id="line2055">2055.  * The Big Thing: special maze loader</span>
Line 2,629: Line 2,742:
 
  <span id="line2624">2624. }</span>
 
  <span id="line2624">2624. }</span>
 
  <span id="line2625">2625. </span>
 
  <span id="line2625">2625. </span>
 +
 +
== load_special ==
 +
 
  <span id="line2626">2626. /*</span>
 
  <span id="line2626">2626. /*</span>
 
  <span id="line2627">2627.  * General loader</span>
 
  <span id="line2627">2627.  * General loader</span>

Revision as of 20:59, 3 September 2006

Below is the full text to src/sp_lev.c from NetHack 3.4.3. To link to a particular line, write [[sp_lev.c#line123]], for example.

Top of file

1.    /*	SCCS Id: @(#)sp_lev.c	3.4	2001/09/06	*/
2.    /*	Copyright (c) 1989 by Jean-Christophe Collet */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    

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.

5.    /*
6.     * This file contains the various functions that are related to the special
7.     * levels.
8.     * It contains also the special level loader.
9.     *
10.    */
11.   
12.   #include "hack.h"
13.   #include "dlb.h"
14.   /* #define DEBUG */	/* uncomment to enable code debugging */
15.   
16.   #ifdef DEBUG
17.   # ifdef WIZARD
18.   #define debugpline	if (wizard) pline
19.   # else
20.   #define debugpline	pline
21.   # endif
22.   #endif
23.   
24.   #include "sp_lev.h"
25.   #include "rect.h"
26.   
27.   extern void FDECL(mkmap, (lev_init *));
28.   
29.   STATIC_DCL void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
30.   STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *));
31.   STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *));
32.   STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P));
33.   STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *));
34.   STATIC_DCL void FDECL(create_object, (object *, struct mkroom *));
35.   STATIC_DCL void FDECL(create_engraving, (engraving *,struct mkroom *));
36.   STATIC_DCL void FDECL(create_stairs, (stair *, struct mkroom *));
37.   STATIC_DCL void FDECL(create_altar, (altar *, struct mkroom *));
38.   STATIC_DCL void FDECL(create_gold, (gold *, struct mkroom *));
39.   STATIC_DCL void FDECL(create_feature, (int,int,struct mkroom *,int));
40.   STATIC_DCL boolean FDECL(search_door, (struct mkroom *, xchar *, xchar *,
41.   					XCHAR_P, int));
42.   STATIC_DCL void NDECL(fix_stair_rooms);
43.   STATIC_DCL void FDECL(create_corridor, (corridor *));
44.   
45.   STATIC_DCL boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
46.   					XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P));
47.   
48.   #define LEFT	1
49.   #define H_LEFT	2
50.   #define CENTER	3
51.   #define H_RIGHT	4
52.   #define RIGHT	5
53.   
54.   #define TOP	1
55.   #define BOTTOM	5
56.   
57.   #define sq(x) ((x)*(x))
58.   
59.   #define XLIM	4
60.   #define YLIM	3
61.   
62.   #define Fread	(void)dlb_fread
63.   #define Fgetc	(schar)dlb_fgetc
64.   #define New(type)		(type *) alloc(sizeof(type))
65.   #define NewTab(type, size)	(type **) alloc(sizeof(type *) * (unsigned)size)
66.   #define Free(ptr)		if(ptr) free((genericptr_t) (ptr))
67.   
68.   static NEARDATA walk walklist[50];
69.   extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
70.   
71.   static char Map[COLNO][ROWNO];
72.   static char robjects[10], rloc_x[10], rloc_y[10], rmonst[10];
73.   static aligntyp	ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
74.   static NEARDATA xchar xstart, ystart;
75.   static NEARDATA char xsize, ysize;
76.   
77.   STATIC_DCL void FDECL(set_wall_property, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,int));
78.   STATIC_DCL int NDECL(rnddoor);
79.   STATIC_DCL int NDECL(rndtrap);
80.   STATIC_DCL void FDECL(get_location, (schar *,schar *,int));
81.   STATIC_DCL void FDECL(sp_lev_shuffle, (char *,char *,int));
82.   STATIC_DCL void FDECL(light_region, (region *));
83.   STATIC_DCL void FDECL(load_common_data, (dlb *,int));
84.   STATIC_DCL void FDECL(load_one_monster, (dlb *,monster *));
85.   STATIC_DCL void FDECL(load_one_object, (dlb *,object *));
86.   STATIC_DCL void FDECL(load_one_engraving, (dlb *,engraving *));
87.   STATIC_DCL boolean FDECL(load_rooms, (dlb *));
88.   STATIC_DCL void FDECL(maze1xy, (coord *,int));
89.   STATIC_DCL boolean FDECL(load_maze, (dlb *));
90.   STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
91.   STATIC_DCL void FDECL(free_rooms,(room **, int));
92.   STATIC_DCL void FDECL(build_room, (room *, room*));
93.   
94.   char *lev_message = 0;
95.   lev_region *lregions = 0;
96.   int num_lregions = 0;
97.   lev_init init_lev;
98.   

set_wall_property

99.   /*
100.   * Make walls of the area (x1, y1, x2, y2) non diggable/non passwall-able
101.   */
102.  
103.  STATIC_OVL void
104.  set_wall_property(x1,y1,x2,y2, prop)
105.  xchar x1, y1, x2, y2;
106.  int prop;
107.  {
108.  	register xchar x, y;
109.  
110.  	for(y = y1; y <= y2; y++)
111.  	    for(x = x1; x <= x2; x++)
112.  		if(IS_STWALL(levl[x][y].typ))
113.  		    levl[x][y].wall_info |= prop;
114.  }
115.  

rnddoor

116.  /*
117.   * Choose randomly the state (nodoor, open, closed or locked) for a door
118.   */
119.  STATIC_OVL int
120.  rnddoor()
121.  {
122.  	int i = 1 << rn2(5);
123.  	i >>= 1;
124.  	return i;
125.  }
126.  

rndtrap

127.  /*
128.   * Select a random trap
129.   */
130.  STATIC_OVL int
131.  rndtrap()
132.  {
133.  	int rtrap;
134.  
135.  	do {
136.  	    rtrap = rnd(TRAPNUM-1);
137.  	    switch (rtrap) {
138.  	     case HOLE:		/* no random holes on special levels */
139.  	     case MAGIC_PORTAL:	rtrap = NO_TRAP;
140.  				break;
141.  	     case TRAPDOOR:	if (!Can_dig_down(&u.uz)) rtrap = NO_TRAP;
142.  				break;
143.  	     case LEVEL_TELEP:
144.  	     case TELEP_TRAP:	if (level.flags.noteleport) rtrap = NO_TRAP;
145.  				break;
146.  	     case ROLLING_BOULDER_TRAP:
147.  	     case ROCKTRAP:	if (In_endgame(&u.uz)) rtrap = NO_TRAP;
148.  				break;
149.  	    }
150.  	} while (rtrap == NO_TRAP);
151.  	return rtrap;
152.  }
153.  

get_location

154.  /*
155.   * Coordinates in special level files are handled specially:
156.   *
157.   *	if x or y is -11, we generate a random coordinate.
158.   *	if x or y is between -1 and -10, we read one from the corresponding
159.   *	register (x0, x1, ... x9).
160.   *	if x or y is nonnegative, we convert it from relative to the local map
161.   *	to global coordinates.
162.   *	The "humidity" flag is used to insure that engravings aren't
163.   *	created underwater, or eels on dry land.
164.   */
165.  #define DRY	0x1
166.  #define WET	0x2
167.  
168.  STATIC_DCL boolean FDECL(is_ok_location, (SCHAR_P, SCHAR_P, int));
169.  
170.  STATIC_OVL void
171.  get_location(x, y, humidity)
172.  schar *x, *y;
173.  int humidity;
174.  {
175.  	int cpt = 0;
176.  
177.  	if (*x >= 0) {			/* normal locations */
178.  		*x += xstart;
179.  		*y += ystart;
180.  	} else if (*x > -11) {		/* special locations */
181.  		*y = ystart + rloc_y[ - *y - 1];
182.  		*x = xstart + rloc_x[ - *x - 1];
183.  	} else {			/* random location */
184.  	    do {
185.  		*x = xstart + rn2((int)xsize);
186.  		*y = ystart + rn2((int)ysize);
187.  		if (is_ok_location(*x,*y,humidity)) break;
188.  	    } while (++cpt < 100);
189.  	    if (cpt >= 100) {
190.  		register int xx, yy;
191.  		/* last try */
192.  		for (xx = 0; xx < xsize; xx++)
193.  		    for (yy = 0; yy < ysize; yy++) {
194.  			*x = xstart + xx;
195.  			*y = ystart + yy;
196.  			if (is_ok_location(*x,*y,humidity)) goto found_it;
197.  		    }
198.  		panic("get_location:  can't find a place!");
199.  	    }
200.  	}
201.  found_it:;
202.  
203.  	if (!isok(*x,*y)) {
204.  	    impossible("get_location:  (%d,%d) out of bounds", *x, *y);
205.  	    *x = x_maze_max; *y = y_maze_max;
206.  	}
207.  }
208.  

is_ok_location

209.  STATIC_OVL boolean
210.  is_ok_location(x, y, humidity)
211.  register schar x, y;
212.  register int humidity;
213.  {
214.  	register int typ;
215.  
216.  	if (Is_waterlevel(&u.uz)) return TRUE;	/* accept any spot */
217.  
218.  	if (humidity & DRY) {
219.  	    typ = levl[x][y].typ;
220.  	    if (typ == ROOM || typ == AIR ||
221.  		    typ == CLOUD || typ == ICE || typ == CORR)
222.  		return TRUE;
223.  	}
224.  	if (humidity & WET) {
225.  	    if (is_pool(x,y) || is_lava(x,y))
226.  		return TRUE;
227.  	}
228.  	return FALSE;
229.  }
230.  

sp_lev_shuffle

231.  /*
232.   * Shuffle the registers for locations, objects or monsters
233.   */
234.  
235.  STATIC_OVL void
236.  sp_lev_shuffle(list1, list2, n)
237.  char list1[], list2[];
238.  int n;
239.  {
240.  	register int i, j;
241.  	register char k;
242.  
243.  	for (i = n - 1; i > 0; i--) {
244.  		if ((j = rn2(i + 1)) == i) continue;
245.  		k = list1[j];
246.  		list1[j] = list1[i];
247.  		list1[i] = k;
248.  		if (list2) {
249.  			k = list2[j];
250.  			list2[j] = list2[i];
251.  			list2[i] = k;
252.  		}
253.  	}
254.  }
255.  

get_room_loc

256.  /*
257.   * Get a relative position inside a room.
258.   * negative values for x or y means RANDOM!
259.   */
260.  
261.  STATIC_OVL void
262.  get_room_loc(x,y, croom)
263.  schar		*x, *y;
264.  struct mkroom	*croom;
265.  {
266.  	coord c;
267.  
268.  	if (*x <0 && *y <0) {
269.  		if (somexy(croom, &c)) {
270.  			*x = c.x;
271.  			*y = c.y;
272.  		} else
273.  		    panic("get_room_loc : can't find a place!");
274.  	} else {
275.  		if (*x < 0)
276.  		    *x = rn2(croom->hx - croom->lx + 1);
277.  		if (*y < 0)
278.  		    *y = rn2(croom->hy - croom->ly + 1);
279.  		*x += croom->lx;
280.  		*y += croom->ly;
281.  	}
282.  }
283.  

get_free_room_loc

284.  /*
285.   * Get a relative position inside a room.
286.   * negative values for x or y means RANDOM!
287.   */
288.  
289.  STATIC_OVL void
290.  get_free_room_loc(x,y, croom)
291.  schar		*x, *y;
292.  struct mkroom	*croom;
293.  {
294.  	schar try_x, try_y;
295.  	register int trycnt = 0;
296.  
297.  	do {
298.  	    try_x = *x,  try_y = *y;
299.  	    get_room_loc(&try_x, &try_y, croom);
300.  	} while (levl[try_x][try_y].typ != ROOM && ++trycnt <= 100);
301.  
302.  	if (trycnt > 100)
303.  	    panic("get_free_room_loc:  can't find a place!");
304.  	*x = try_x,  *y = try_y;
305.  }
306.  

check_room

307.  boolean
308.  check_room(lowx, ddx, lowy, ddy, vault)
309.  xchar *lowx, *ddx, *lowy, *ddy;
310.  boolean vault;
311.  {
312.  	register int x,y,hix = *lowx + *ddx, hiy = *lowy + *ddy;
313.  	register struct rm *lev;
314.  	int xlim, ylim, ymax;
315.  
316.  	xlim = XLIM + (vault ? 1 : 0);
317.  	ylim = YLIM + (vault ? 1 : 0);
318.  
319.  	if (*lowx < 3)		*lowx = 3;
320.  	if (*lowy < 2)		*lowy = 2;
321.  	if (hix > COLNO-3)	hix = COLNO-3;
322.  	if (hiy > ROWNO-3)	hiy = ROWNO-3;
323.  chk:
324.  	if (hix <= *lowx || hiy <= *lowy)	return FALSE;
325.  
326.  	/* check area around room (and make room smaller if necessary) */
327.  	for (x = *lowx - xlim; x<= hix + xlim; x++) {
328.  		if(x <= 0 || x >= COLNO) continue;
329.  		y = *lowy - ylim;	ymax = hiy + ylim;
330.  		if(y < 0) y = 0;
331.  		if(ymax >= ROWNO) ymax = (ROWNO-1);
332.  		lev = &levl[x][y];
333.  		for (; y <= ymax; y++) {
334.  			if (lev++->typ) {
335.  #ifdef DEBUG
336.  				if(!vault)
337.  				    debugpline("strange area [%d,%d] in check_room.",x,y);
338.  #endif
339.  				if (!rn2(3))	return FALSE;
340.  				if (x < *lowx)
341.  				    *lowx = x + xlim + 1;
342.  				else
343.  				    hix = x - xlim - 1;
344.  				if (y < *lowy)
345.  				    *lowy = y + ylim + 1;
346.  				else
347.  				    hiy = y - ylim - 1;
348.  				goto chk;
349.  			}
350.  		}
351.  	}
352.  	*ddx = hix - *lowx;
353.  	*ddy = hiy - *lowy;
354.  	return TRUE;
355.  }
356.  

create_room

357.  /*
358.   * Create a new room.
359.   * This is still very incomplete...
360.   */
361.  
362.  boolean
363.  create_room(x,y,w,h,xal,yal,rtype,rlit)
364.  xchar	x,y;
365.  xchar	w,h;
366.  xchar	xal,yal;
367.  xchar	rtype, rlit;
368.  {
369.  	xchar	xabs, yabs;
370.  	int	wtmp, htmp, xaltmp, yaltmp, xtmp, ytmp;
371.  	NhRect	*r1 = 0, r2;
372.  	int	trycnt = 0;
373.  	boolean	vault = FALSE;
374.  	int	xlim = XLIM, ylim = YLIM;
375.  
376.  	if (rtype == -1)	/* Is the type random ? */
377.  	    rtype = OROOM;
378.  
379.  	if (rtype == VAULT) {
380.  		vault = TRUE;
381.  		xlim++;
382.  		ylim++;
383.  	}
384.  
385.  	/* on low levels the room is lit (usually) */
386.  	/* some other rooms may require lighting */
387.  
388.  	/* is light state random ? */
389.  	if (rlit == -1)
390.  	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
391.  
392.  	/*
393.  	 * Here we will try to create a room. If some parameters are
394.  	 * random we are willing to make several try before we give
395.  	 * it up.
396.  	 */
397.  	do {
398.  		xchar xborder, yborder;
399.  		wtmp = w; htmp = h;
400.  		xtmp = x; ytmp = y;
401.  		xaltmp = xal; yaltmp = yal;
402.  
403.  		/* First case : a totaly random room */
404.  
405.  		if((xtmp < 0 && ytmp <0 && wtmp < 0 && xaltmp < 0 &&
406.  		   yaltmp < 0) || vault) {
407.  			xchar hx, hy, lx, ly, dx, dy;
408.  			r1 = rnd_rect(); /* Get a random rectangle */
409.  
410.  			if (!r1) { /* No more free rectangles ! */
411.  #ifdef DEBUG
412.  				debugpline("No more rects...");
413.  #endif
414.  				return FALSE;
415.  			}
416.  			hx = r1->hx;
417.  			hy = r1->hy;
418.  			lx = r1->lx;
419.  			ly = r1->ly;
420.  			if (vault)
421.  			    dx = dy = 1;
422.  			else {
423.  				dx = 2 + rn2((hx-lx > 28) ? 12 : 8);
424.  				dy = 2 + rn2(4);
425.  				if(dx*dy > 50)
426.  				    dy = 50/dx;
427.  			}
428.  			xborder = (lx > 0 && hx < COLNO -1) ? 2*xlim : xlim+1;
429.  			yborder = (ly > 0 && hy < ROWNO -1) ? 2*ylim : ylim+1;
430.  			if(hx-lx < dx + 3 + xborder ||
431.  			   hy-ly < dy + 3 + yborder) {
432.  				r1 = 0;
433.  				continue;
434.  			}
435.  			xabs = lx + (lx > 0 ? xlim : 3)
436.  			    + rn2(hx - (lx>0?lx : 3) - dx - xborder + 1);
437.  			yabs = ly + (ly > 0 ? ylim : 2)
438.  			    + rn2(hy - (ly>0?ly : 2) - dy - yborder + 1);
439.  			if (ly == 0 && hy >= (ROWNO-1) &&
440.  			    (!nroom || !rn2(nroom)) && (yabs+dy > ROWNO/2)) {
441.  			    yabs = rn1(3, 2);
442.  			    if(nroom < 4 && dy>1) dy--;
443.  		        }
444.  			if (!check_room(&xabs, &dx, &yabs, &dy, vault)) {
445.  				r1 = 0;
446.  				continue;
447.  			}
448.  			wtmp = dx+1;
449.  			htmp = dy+1;
450.  			r2.lx = xabs-1; r2.ly = yabs-1;
451.  			r2.hx = xabs + wtmp;
452.  			r2.hy = yabs + htmp;
453.  		} else {	/* Only some parameters are random */
454.  			int rndpos = 0;
455.  			if (xtmp < 0 && ytmp < 0) { /* Position is RANDOM */
456.  				xtmp = rnd(5);
457.  				ytmp = rnd(5);
458.  				rndpos = 1;
459.  			}
460.  			if (wtmp < 0 || htmp < 0) { /* Size is RANDOM */
461.  				wtmp = rn1(15, 3);
462.  				htmp = rn1(8, 2);
463.  			}
464.  			if (xaltmp == -1) /* Horizontal alignment is RANDOM */
465.  			    xaltmp = rnd(3);
466.  			if (yaltmp == -1) /* Vertical alignment is RANDOM */
467.  			    yaltmp = rnd(3);
468.  
469.  			/* Try to generate real (absolute) coordinates here! */
470.  
471.  			xabs = (((xtmp-1) * COLNO) / 5) + 1;
472.  			yabs = (((ytmp-1) * ROWNO) / 5) + 1;
473.  			switch (xaltmp) {
474.  			      case LEFT:
475.  				break;
476.  			      case RIGHT:
477.  				xabs += (COLNO / 5) - wtmp;
478.  				break;
479.  			      case CENTER:
480.  				xabs += ((COLNO / 5) - wtmp) / 2;
481.  				break;
482.  			}
483.  			switch (yaltmp) {
484.  			      case TOP:
485.  				break;
486.  			      case BOTTOM:
487.  				yabs += (ROWNO / 5) - htmp;
488.  				break;
489.  			      case CENTER:
490.  				yabs += ((ROWNO / 5) - htmp) / 2;
491.  				break;
492.  			}
493.  
494.  			if (xabs + wtmp - 1 > COLNO - 2)
495.  			    xabs = COLNO - wtmp - 3;
496.  			if (xabs < 2)
497.  			    xabs = 2;
498.  			if (yabs + htmp - 1> ROWNO - 2)
499.  			    yabs = ROWNO - htmp - 3;
500.  			if (yabs < 2)
501.  			    yabs = 2;
502.  
503.  			/* Try to find a rectangle that fit our room ! */
504.  
505.  			r2.lx = xabs-1; r2.ly = yabs-1;
506.  			r2.hx = xabs + wtmp + rndpos;
507.  			r2.hy = yabs + htmp + rndpos;
508.  			r1 = get_rect(&r2);
509.  		}
510.  	} while (++trycnt <= 100 && !r1);
511.  	if (!r1) {	/* creation of room failed ? */
512.  		return FALSE;
513.  	}
514.  	split_rects(r1, &r2);
515.  
516.  	if (!vault) {
517.  		smeq[nroom] = nroom;
518.  		add_room(xabs, yabs, xabs+wtmp-1, yabs+htmp-1,
519.  			 rlit, rtype, FALSE);
520.  	} else {
521.  		rooms[nroom].lx = xabs;
522.  		rooms[nroom].ly = yabs;
523.  	}
524.  	return TRUE;
525.  }
526.  

create_subroom

527.  /*
528.   * Create a subroom in room proom at pos x,y with width w & height h.
529.   * x & y are relative to the parent room.
530.   */
531.  
532.  STATIC_OVL boolean
533.  create_subroom(proom, x, y, w,  h, rtype, rlit)
534.  struct mkroom *proom;
535.  xchar x,y;
536.  xchar w,h;
537.  xchar rtype, rlit;
538.  {
539.  	xchar width, height;
540.  
541.  	width = proom->hx - proom->lx + 1;
542.  	height = proom->hy - proom->ly + 1;
543.  
544.  	/* There is a minimum size for the parent room */
545.  	if (width < 4 || height < 4)
546.  	    return FALSE;
547.  
548.  	/* Check for random position, size, etc... */
549.  
550.  	if (w == -1)
551.  	    w = rnd(width - 3);
552.  	if (h == -1)
553.  	    h = rnd(height - 3);
554.  	if (x == -1)
555.  	    x = rnd(width - w - 1) - 1;
556.  	if (y == -1)
557.  	    y = rnd(height - h - 1) - 1;
558.  	if (x == 1)
559.  	    x = 0;
560.  	if (y == 1)
561.  	    y = 0;
562.  	if ((x + w + 1) == width)
563.  	    x++;
564.  	if ((y + h + 1) == height)
565.  	    y++;
566.  	if (rtype == -1)
567.  	    rtype = OROOM;
568.  	if (rlit == -1)
569.  	    rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
570.  	add_subroom(proom, proom->lx + x, proom->ly + y,
571.  		    proom->lx + x + w - 1, proom->ly + y + h - 1,
572.  		    rlit, rtype, FALSE);
573.  	return TRUE;
574.  }
575.  

create_door

576.  /*
577.   * Create a new door in a room.
578.   * It's placed on a wall (north, south, east or west).
579.   */
580.  
581.  STATIC_OVL void
582.  create_door(dd, broom)
583.  room_door *dd;
584.  struct mkroom *broom;
585.  {
586.  	int	x, y;
587.  	int	trycnt = 0;
588.  
589.  	if (dd->secret == -1)
590.  	    dd->secret = rn2(2);
591.  
592.  	if (dd->mask == -1) {
593.  		/* is it a locked door, closed, or a doorway? */
594.  		if (!dd->secret) {
595.  			if(!rn2(3)) {
596.  				if(!rn2(5))
597.  				    dd->mask = D_ISOPEN;
598.  				else if(!rn2(6))
599.  				    dd->mask = D_LOCKED;
600.  				else
601.  				    dd->mask = D_CLOSED;
602.  				if (dd->mask != D_ISOPEN && !rn2(25))
603.  				    dd->mask |= D_TRAPPED;
604.  			} else
605.  			    dd->mask = D_NODOOR;
606.  		} else {
607.  			if(!rn2(5))	dd->mask = D_LOCKED;
608.  			else		dd->mask = D_CLOSED;
609.  
610.  			if(!rn2(20)) dd->mask |= D_TRAPPED;
611.  		}
612.  	}
613.  
614.  	do {
615.  		register int dwall, dpos;
616.  
617.  		dwall = dd->wall;
618.  		if (dwall == -1)	/* The wall is RANDOM */
619.  		    dwall = 1 << rn2(4);
620.  
621.  		dpos = dd->pos;
622.  		if (dpos == -1)	/* The position is RANDOM */
623.  		    dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?
624.  			    (broom->hy - broom->ly) : (broom->hx - broom->lx));
625.  
626.  		/* Convert wall and pos into an absolute coordinate! */
627.  
628.  		switch (dwall) {
629.  		      case W_NORTH:
630.  			y = broom->ly - 1;
631.  			x = broom->lx + dpos;
632.  			break;
633.  		      case W_SOUTH:
634.  			y = broom->hy + 1;
635.  			x = broom->lx + dpos;
636.  			break;
637.  		      case W_WEST:
638.  			x = broom->lx - 1;
639.  			y = broom->ly + dpos;
640.  			break;
641.  		      case W_EAST:
642.  			x = broom->hx + 1;
643.  			y = broom->ly + dpos;
644.  			break;
645.  		      default:
646.  			x = y = 0;
647.  			panic("create_door: No wall for door!");
648.  			break;
649.  		}
650.  		if (okdoor(x,y))
651.  		    break;
652.  	} while (++trycnt <= 100);
653.  	if (trycnt > 100) {
654.  		impossible("create_door: Can't find a proper place!");
655.  		return;
656.  	}
657.  	add_door(x,y,broom);
658.  	levl[x][y].typ = (dd->secret ? SDOOR : DOOR);
659.  	levl[x][y].doormask = dd->mask;
660.  }
661.  

create_secret_door

662.  /*
663.   * Create a secret door in croom on any one of the specified walls.
664.   */
665.  void
666.  create_secret_door(croom, walls)
667.      struct mkroom *croom;
668.      xchar walls; /* any of W_NORTH | W_SOUTH | W_EAST | W_WEST (or W_ANY) */
669.  {
670.      xchar sx, sy; /* location of the secret door */
671.      int count;
672.  
673.      for(count = 0; count < 100; count++) {
674.  	sx = rn1(croom->hx - croom->lx + 1, croom->lx);
675.  	sy = rn1(croom->hy - croom->ly + 1, croom->ly);
676.  
677.  	switch(rn2(4)) {
678.  	case 0:  /* top */
679.  	    if(!(walls & W_NORTH)) continue;
680.  	    sy = croom->ly-1; break;
681.  	case 1: /* bottom */
682.  	    if(!(walls & W_SOUTH)) continue;
683.  	    sy = croom->hy+1; break;
684.  	case 2: /* left */
685.  	    if(!(walls & W_EAST)) continue;
686.  	    sx = croom->lx-1; break;
687.  	case 3: /* right */
688.  	    if(!(walls & W_WEST)) continue;
689.  	    sx = croom->hx+1; break;
690.  	}
691.  
692.  	if(okdoor(sx,sy)) {
693.  	    levl[sx][sy].typ = SDOOR;
694.  	    levl[sx][sy].doormask = D_CLOSED;
695.  	    add_door(sx,sy,croom);
696.  	    return;
697.  	}
698.      }
699.  
700.      impossible("couldn't create secret door on any walls 0x%x", walls);
701.  }
702.  

create_trap

703.  /*
704.   * Create a trap in a room.
705.   */
706.  
707.  STATIC_OVL void
708.  create_trap(t,croom)
709.  trap	*t;
710.  struct mkroom	*croom;
711.  {
712.      schar	x,y;
713.      coord	tm;
714.  
715.      if (rn2(100) < t->chance) {
716.  	x = t->x;
717.  	y = t->y;
718.  	if (croom)
719.  	    get_free_room_loc(&x, &y, croom);
720.  	else
721.  	    get_location(&x, &y, DRY);
722.  
723.  	tm.x = x;
724.  	tm.y = y;
725.  
726.  	mktrap(t->type, 1, (struct mkroom*) 0, &tm);
727.      }
728.  }
729.  

noncoalignment

730.  /*
731.   * Create a monster in a room.
732.   */
733.  
734.  STATIC_OVL int
735.  noncoalignment(alignment)
736.  aligntyp alignment;
737.  {
738.  	int k;
739.  
740.  	k = rn2(2);
741.  	if (!alignment)
742.  		return(k ? -1 : 1);
743.  	return(k ? -alignment : 0);
744.  }
745.  

create_monster

746.  STATIC_OVL void
747.  create_monster(m,croom)
748.  monster	*m;
749.  struct mkroom	*croom;
750.  {
751.      struct monst *mtmp;
752.      schar x, y;
753.      char class;
754.      aligntyp amask;
755.      coord cc;
756.      struct permonst *pm;
757.      unsigned g_mvflags;
758.  
759.      if (rn2(100) < m->chance) {
760.  
761.  	if (m->class >= 0)
762.  	    class = (char) def_char_to_monclass((char)m->class);
763.  	else if (m->class > -11)
764.  	    class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
765.  	else
766.  	    class = 0;
767.  
768.  	if (class == MAXMCLASSES)
769.  	    panic("create_monster: unknown monster class '%c'", m->class);
770.  
771.  	amask = (m->align == AM_SPLEV_CO) ?
772.  			Align2amask(u.ualignbase[A_ORIGINAL]) :
773.  		(m->align == AM_SPLEV_NONCO) ?
774.  			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) :
775.  		(m->align <= -11) ? induced_align(80) :
776.  		(m->align < 0 ? ralign[-m->align-1] : m->align);
777.  
778.  	if (!class)
779.  	    pm = (struct permonst *) 0;
780.  	else if (m->id != NON_PM) {
781.  	    pm = &mons[m->id];
782.  	    g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
783.  	    if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT))
784.  		goto m_done;
785.  	    else if (g_mvflags & G_GONE)	/* genocided or extinct */
786.  		pm = (struct permonst *) 0;	/* make random monster */
787.  	} else {
788.  	    pm = mkclass(class,G_NOGEN);
789.  	    /* if we can't get a specific monster type (pm == 0) then the
790.  	       class has been genocided, so settle for a random monster */
791.  	}
792.  	if (In_mines(&u.uz) && pm && your_race(pm) &&
793.  			(Race_if(PM_DWARF) || Race_if(PM_GNOME)) && rn2(3))
794.  	    pm = (struct permonst *) 0;
795.  
796.  	x = m->x;
797.  	y = m->y;
798.  	if (croom)
799.  	    get_room_loc(&x, &y, croom);
800.  	else {
801.  	    if (!pm || !is_swimmer(pm))
802.  		get_location(&x, &y, DRY);
803.  	    else if (pm->mlet == S_EEL)
804.  		get_location(&x, &y, WET);
805.  	    else
806.  		get_location(&x, &y, DRY|WET);
807.  	}
808.  	/* try to find a close place if someone else is already there */
809.  	if (MON_AT(x,y) && enexto(&cc, x, y, pm))
810.  	    x = cc.x,  y = cc.y;
811.  
812.  	if(m->align != -12)
813.  	    mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
814.  	else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
815.  	         mtmp = mk_mplayer(pm, x, y, FALSE);
816.  	else mtmp = makemon(pm, x, y, NO_MM_FLAGS);
817.  
818.  	if (mtmp) {
819.  	    /* handle specific attributes for some special monsters */
820.  	    if (m->name.str) mtmp = christen_monst(mtmp, m->name.str);
821.  
822.  	    /*
823.  	     * This is currently hardwired for mimics only.  It should
824.  	     * eventually be expanded.
825.  	     */
826.  	    if (m->appear_as.str && mtmp->data->mlet == S_MIMIC) {
827.  		int i;
828.  
829.  		switch (m->appear) {
830.  		    case M_AP_NOTHING:
831.  			impossible(
832.  		"create_monster: mon has an appearance, \"%s\", but no type",
833.  				m->appear_as.str);
834.  			break;
835.  
836.  		    case M_AP_FURNITURE:
837.  			for (i = 0; i < MAXPCHARS; i++)
838.  			    if (!strcmp(defsyms[i].explanation,
839.  					m->appear_as.str))
840.  				break;
841.  			if (i == MAXPCHARS) {
842.  			    impossible(
843.  				"create_monster: can't find feature \"%s\"",
844.  				m->appear_as.str);
845.  			} else {
846.  			    mtmp->m_ap_type = M_AP_FURNITURE;
847.  			    mtmp->mappearance = i;
848.  			}
849.  			break;
850.  
851.  		    case M_AP_OBJECT:
852.  			for (i = 0; i < NUM_OBJECTS; i++)
853.  			    if (OBJ_NAME(objects[i]) &&
854.  				!strcmp(OBJ_NAME(objects[i]),m->appear_as.str))
855.  				break;
856.  			if (i == NUM_OBJECTS) {
857.  			    impossible(
858.  				"create_monster: can't find object \"%s\"",
859.  				m->appear_as.str);
860.  			} else {
861.  			    mtmp->m_ap_type = M_AP_OBJECT;
862.  			    mtmp->mappearance = i;
863.  			}
864.  			break;
865.  
866.  		    case M_AP_MONSTER:
867.  			/* note: mimics don't appear as monsters! */
868.  			/*	 (but chameleons can :-)	  */
869.  		    default:
870.  			impossible(
871.  		"create_monster: unimplemented mon appear type [%d,\"%s\"]",
872.  				m->appear, m->appear_as.str);
873.  			break;
874.  		}
875.  		if (does_block(x, y, &levl[x][y]))
876.  		    block_point(x, y);
877.  	    }
878.  
879.  	    if (m->peaceful >= 0) {
880.  		mtmp->mpeaceful = m->peaceful;
881.  		/* changed mpeaceful again; have to reset malign */
882.  		set_malign(mtmp);
883.  	    }
884.  	    if (m->asleep >= 0) {
885.  #ifdef UNIXPC
886.  		/* optimizer bug strikes again */
887.  		if (m->asleep)
888.  			mtmp->msleeping = 1;
889.  		else
890.  			mtmp->msleeping = 0;
891.  #else
892.  		mtmp->msleeping = m->asleep;
893.  #endif
894.  	    }
895.  	}
896.  
897.      }		/* if (rn2(100) < m->chance) */
898.   m_done:
899.      Free(m->name.str);
900.      Free(m->appear_as.str);
901.  }
902.  

create_object

903.  /*
904.   * Create an object in a room.
905.   */
906.  
907.  STATIC_OVL void
908.  create_object(o,croom)
909.  object	*o;
910.  struct mkroom	*croom;
911.  {
912.      struct obj *otmp;
913.      schar x, y;
914.      char c;
915.      boolean named;	/* has a name been supplied in level description? */
916.  
917.      if (rn2(100) < o->chance) {
918.  	named = o->name.str ? TRUE : FALSE;
919.  
920.  	x = o->x; y = o->y;
921.  	if (croom)
922.  	    get_room_loc(&x, &y, croom);
923.  	else
924.  	    get_location(&x, &y, DRY);
925.  
926.  	if (o->class >= 0)
927.  	    c = o->class;
928.  	else if (o->class > -11)
929.  	    c = robjects[ -(o->class+1)];
930.  	else
931.  	    c = 0;
932.  
933.  	if (!c)
934.  	    otmp = mkobj_at(RANDOM_CLASS, x, y, !named);
935.  	else if (o->id != -1)
936.  	    otmp = mksobj_at(o->id, x, y, TRUE, !named);
937.  	else {
938.  	    /*
939.  	     * The special levels are compiled with the default "text" object
940.  	     * class characters.  We must convert them to the internal format.
941.  	     */
942.  	    char oclass = (char) def_char_to_objclass(c);
943.  
944.  	    if (oclass == MAXOCLASSES)
945.  		panic("create_object:  unexpected object class '%c'",c);
946.  
947.  	    /* KMH -- Create piles of gold properly */
948.  	    if (oclass == COIN_CLASS)
949.  		otmp = mkgold(0L, x, y);
950.  	    else
951.  		otmp = mkobj_at(oclass, x, y, !named);
952.  	}
953.  
954.  	if (o->spe != -127)	/* That means NOT RANDOM! */
955.  	    otmp->spe = (schar)o->spe;
956.  
957.  	switch (o->curse_state) {
958.  	      case 1:	bless(otmp); break; /* BLESSED */
959.  	      case 2:	unbless(otmp); uncurse(otmp); break; /* uncursed */
960.  	      case 3:	curse(otmp); break; /* CURSED */
961.  	      default:	break;	/* Otherwise it's random and we're happy
962.  				 * with what mkobj gave us! */
963.  	}
964.  
965.  	/*	corpsenm is "empty" if -1, random if -2, otherwise specific */
966.  	if (o->corpsenm == NON_PM - 1) otmp->corpsenm = rndmonnum();
967.  	else if (o->corpsenm != NON_PM) otmp->corpsenm = o->corpsenm;
968.  
969.  	/* assume we wouldn't be given an egg corpsenm unless it was
970.  	   hatchable */
971.  	if (otmp->otyp == EGG && otmp->corpsenm != NON_PM) {
972.  	    if (dead_species(otmp->otyp, TRUE))
973.  		kill_egg(otmp);	/* make sure nothing hatches */
974.  	    else
975.  		attach_egg_hatch_timeout(otmp);	/* attach new hatch timeout */
976.  	}
977.  
978.  	if (named)
979.  	    otmp = oname(otmp, o->name.str);
980.  
981.  	switch(o->containment) {
982.  	    static struct obj *container = 0;
983.  
984.  	    /* contents */
985.  	    case 1:
986.  		if (!container) {
987.  		    impossible("create_object: no container");
988.  		    break;
989.  		}
990.  		remove_object(otmp);
991.  		(void) add_to_container(container, otmp);
992.  		goto o_done;		/* don't stack, but do other cleanup */
993.  	    /* container */
994.  	    case 2:
995.  		delete_contents(otmp);
996.  		container = otmp;
997.  		break;
998.  	    /* nothing */
999.  	    case 0: break;
1000. 
1001. 	    default: impossible("containment type %d?", (int) o->containment);
1002. 	}
1003. 
1004. 	/* Medusa level special case: statues are petrified monsters, so they
1005. 	 * are not stone-resistant and have monster inventory.  They also lack
1006. 	 * other contents, but that can be specified as an empty container.
1007. 	 */
1008. 	if (o->id == STATUE && Is_medusa_level(&u.uz) &&
1009. 		    o->corpsenm == NON_PM) {
1010. 	    struct monst *was;
1011. 	    struct obj *obj;
1012. 	    int wastyp;
1013. 
1014. 	    /* Named random statues are of player types, and aren't stone-
1015. 	     * resistant (if they were, we'd have to reset the name as well as
1016. 	     * setting corpsenm).
1017. 	     */
1018. 	    for (wastyp = otmp->corpsenm; ; wastyp = rndmonnum()) {
1019. 		/* makemon without rndmonst() might create a group */
1020. 		was = makemon(&mons[wastyp], 0, 0, NO_MM_FLAGS);
1021. 		if (!resists_ston(was)) break;
1022. 		mongone(was);
1023. 	    }
1024. 	    otmp->corpsenm = wastyp;
1025. 	    while(was->minvent) {
1026. 		obj = was->minvent;
1027. 		obj->owornmask = 0;
1028. 		obj_extract_self(obj);
1029. 		(void) add_to_container(otmp, obj);
1030. 	    }
1031. 	    otmp->owt = weight(otmp);
1032. 	    mongone(was);
1033. 	}
1034. 
1035. 	stackobj(otmp);
1036. 
1037.     }		/* if (rn2(100) < o->chance) */
1038.  o_done:
1039.     Free(o->name.str);
1040. }
1041. 

create_engraving

1042. /*
1043.  * Randomly place a specific engraving, then release its memory.
1044.  */
1045. STATIC_OVL void
1046. create_engraving(e, croom)
1047. engraving *e;
1048. struct mkroom *croom;
1049. {
1050. 	xchar x, y;
1051. 
1052. 	x = e->x,  y = e->y;
1053. 	if (croom)
1054. 	    get_room_loc(&x, &y, croom);
1055. 	else
1056. 	    get_location(&x, &y, DRY);
1057. 
1058. 	make_engr_at(x, y, e->engr.str, 0L, e->etype);
1059. 	free((genericptr_t) e->engr.str);
1060. }
1061. 

create_stairs

1062. /*
1063.  * Create stairs in a room.
1064.  *
1065.  */
1066. 
1067. STATIC_OVL void
1068. create_stairs(s,croom)
1069. stair	*s;
1070. struct mkroom	*croom;
1071. {
1072. 	schar		x,y;
1073. 
1074. 	x = s->x; y = s->y;
1075. 	get_free_room_loc(&x, &y, croom);
1076. 	mkstairs(x,y,(char)s->up, croom);
1077. }
1078. 

create_altar

1079. /*
1080.  * Create an altar in a room.
1081.  */
1082. 
1083. STATIC_OVL void
1084. create_altar(a, croom)
1085. 	altar		*a;
1086. 	struct mkroom	*croom;
1087. {
1088. 	schar		sproom,x,y;
1089. 	aligntyp	amask;
1090. 	boolean		croom_is_temple = TRUE;
1091. 	int oldtyp; 
1092. 
1093. 	x = a->x; y = a->y;
1094. 
1095. 	if (croom) {
1096. 	    get_free_room_loc(&x, &y, croom);
1097. 	    if (croom->rtype != TEMPLE)
1098. 		croom_is_temple = FALSE;
1099. 	} else {
1100. 	    get_location(&x, &y, DRY);
1101. 	    if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
1102. 		croom = &rooms[sproom - ROOMOFFSET];
1103. 	    else
1104. 		croom_is_temple = FALSE;
1105. 	}
1106. 
1107. 	/* check for existing features */
1108. 	oldtyp = levl[x][y].typ;
1109. 	if (oldtyp == STAIRS || oldtyp == LADDER)
1110. 	    return;
1111. 
1112. 	a->x = x;
1113. 	a->y = y;
1114. 
1115. 	/* Is the alignment random ?
1116. 	 * If so, it's an 80% chance that the altar will be co-aligned.
1117. 	 *
1118. 	 * The alignment is encoded as amask values instead of alignment
1119. 	 * values to avoid conflicting with the rest of the encoding,
1120. 	 * shared by many other parts of the special level code.
1121. 	 */
1122. 
1123. 	amask = (a->align == AM_SPLEV_CO) ?
1124. 			Align2amask(u.ualignbase[A_ORIGINAL]) :
1125. 		(a->align == AM_SPLEV_NONCO) ?
1126. 			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) :
1127. 		(a->align == -11) ? induced_align(80) :
1128. 		(a->align < 0 ? ralign[-a->align-1] : a->align);
1129. 
1130. 	levl[x][y].typ = ALTAR;
1131. 	levl[x][y].altarmask = amask;
1132. 
1133. 	if (a->shrine < 0) a->shrine = rn2(2);	/* handle random case */
1134. 
1135. 	if (oldtyp == FOUNTAIN)
1136. 	    level.flags.nfountains--;
1137. 	else if (oldtyp == SINK)
1138. 	    level.flags.nsinks--;
1139. 
1140. 	if (!croom_is_temple || !a->shrine) return;
1141. 
1142. 	if (a->shrine) {	/* Is it a shrine  or sanctum? */
1143. 	    priestini(&u.uz, croom, x, y, (a->shrine > 1));
1144. 	    levl[x][y].altarmask |= AM_SHRINE;
1145. 	    level.flags.has_temple = TRUE;
1146. 	}
1147. }
1148. 

create_gold

1149. /*
1150.  * Create a gold pile in a room.
1151.  */
1152. 
1153. STATIC_OVL void
1154. create_gold(g,croom)
1155. gold *g;
1156. struct mkroom	*croom;
1157. {
1158. 	schar		x,y;
1159. 
1160. 	x = g->x; y= g->y;
1161. 	if (croom)
1162. 	    get_room_loc(&x, &y, croom);
1163. 	else
1164. 	    get_location(&x, &y, DRY);
1165. 
1166. 	if (g->amount == -1)
1167. 	    g->amount = rnd(200);
1168. 	(void) mkgold((long) g->amount, x, y);
1169. }
1170. 

create_feature

1171. /*
1172.  * Create a feature (e.g a fountain) in a room.
1173.  */
1174. 
1175. STATIC_OVL void
1176. create_feature(fx, fy, croom, typ)
1177. int		fx, fy;
1178. struct mkroom	*croom;
1179. int		typ;
1180. {
1181. 	schar		x,y;
1182. 	int		trycnt = 0;
1183. 
1184. 	x = fx;  y = fy;
1185. 	if (croom) {
1186. 	    if (x < 0 && y < 0)
1187. 		do {
1188. 		    x = -1;  y = -1;
1189. 		    get_room_loc(&x, &y, croom);
1190. 		} while (++trycnt <= 200 && occupied(x,y));
1191. 	    else
1192. 		get_room_loc(&x, &y, croom);
1193. 	    if(trycnt > 200)
1194. 		return;
1195. 	} else {
1196. 	    get_location(&x, &y, DRY);
1197. 	}
1198. 	/* Don't cover up an existing feature (particularly randomly
1199. 	   placed stairs).  However, if the _same_ feature is already
1200. 	   here, it came from the map drawing and we still need to
1201. 	   update the special counters. */
1202. 	if (IS_FURNITURE(levl[x][y].typ) && levl[x][y].typ != typ)
1203. 	    return;
1204. 
1205. 	levl[x][y].typ = typ;
1206. 	if (typ == FOUNTAIN)
1207. 	    level.flags.nfountains++;
1208. 	else if (typ == SINK)
1209. 	    level.flags.nsinks++;
1210. }
1211. 

search_door

1212. /*
1213.  * Search for a door in a room on a specified wall.
1214.  */
1215. 
1216. STATIC_OVL boolean
1217. search_door(croom,x,y,wall,cnt)
1218. struct mkroom *croom;
1219. xchar *x, *y;
1220. xchar wall;
1221. int cnt;
1222. {
1223. 	int dx, dy;
1224. 	int xx,yy;
1225. 
1226. 	switch(wall) {
1227. 	      case W_NORTH:
1228. 		dy = 0; dx = 1;
1229. 		xx = croom->lx;
1230. 		yy = croom->hy + 1;
1231. 		break;
1232. 	      case W_SOUTH:
1233. 		dy = 0; dx = 1;
1234. 		xx = croom->lx;
1235. 		yy = croom->ly - 1;
1236. 		break;
1237. 	      case W_EAST:
1238. 		dy = 1; dx = 0;
1239. 		xx = croom->hx + 1;
1240. 		yy = croom->ly;
1241. 		break;
1242. 	      case W_WEST:
1243. 		dy = 1; dx = 0;
1244. 		xx = croom->lx - 1;
1245. 		yy = croom->ly;
1246. 		break;
1247. 	      default:
1248. 		dx = dy = xx = yy = 0;
1249. 		panic("search_door: Bad wall!");
1250. 		break;
1251. 	}
1252. 	while (xx <= croom->hx+1 && yy <= croom->hy+1) {
1253. 		if (IS_DOOR(levl[xx][yy].typ) || levl[xx][yy].typ == SDOOR) {
1254. 			*x = xx;
1255. 			*y = yy;
1256. 			if (cnt-- <= 0)
1257. 			    return TRUE;
1258. 		}
1259. 		xx += dx;
1260. 		yy += dy;
1261. 	}
1262. 	return FALSE;
1263. }
1264. 

dig_corridor

1265. /*
1266.  * Dig a corridor between two points.
1267.  */
1268. 
1269. boolean
1270. dig_corridor(org,dest,nxcor,ftyp,btyp)
1271. coord *org, *dest;
1272. boolean nxcor;
1273. schar ftyp, btyp;
1274. {
1275. 	register int dx=0, dy=0, dix, diy, cct;
1276. 	register struct rm *crm;
1277. 	register int tx, ty, xx, yy;
1278. 
1279. 	xx = org->x;  yy = org->y;
1280. 	tx = dest->x; ty = dest->y;
1281. 	if (xx <= 0 || yy <= 0 || tx <= 0 || ty <= 0 ||
1282. 	    xx > COLNO-1 || tx > COLNO-1 ||
1283. 	    yy > ROWNO-1 || ty > ROWNO-1) {
1284. #ifdef DEBUG
1285. 		debugpline("dig_corridor: bad coords : (%d,%d) (%d,%d).",
1286. 			   xx,yy,tx,ty);
1287. #endif
1288. 		return FALSE;
1289. 	}
1290. 	if (tx > xx)		dx = 1;
1291. 	else if (ty > yy)	dy = 1;
1292. 	else if (tx < xx)	dx = -1;
1293. 	else			dy = -1;
1294. 
1295. 	xx -= dx;
1296. 	yy -= dy;
1297. 	cct = 0;
1298. 	while(xx != tx || yy != ty) {
1299. 	    /* loop: dig corridor at [xx,yy] and find new [xx,yy] */
1300. 	    if(cct++ > 500 || (nxcor && !rn2(35)))
1301. 		return FALSE;
1302. 
1303. 	    xx += dx;
1304. 	    yy += dy;
1305. 
1306. 	    if(xx >= COLNO-1 || xx <= 0 || yy <= 0 || yy >= ROWNO-1)
1307. 		return FALSE;		/* impossible */
1308. 
1309. 	    crm = &levl[xx][yy];
1310. 	    if(crm->typ == btyp) {
1311. 		if(ftyp != CORR || rn2(100)) {
1312. 			crm->typ = ftyp;
1313. 			if(nxcor && !rn2(50))
1314. 				(void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE);
1315. 		} else {
1316. 			crm->typ = SCORR;
1317. 		}
1318. 	    } else
1319. 	    if(crm->typ != ftyp && crm->typ != SCORR) {
1320. 		/* strange ... */
1321. 		return FALSE;
1322. 	    }
1323. 
1324. 	    /* find next corridor position */
1325. 	    dix = abs(xx-tx);
1326. 	    diy = abs(yy-ty);
1327. 
1328. 	    /* do we have to change direction ? */
1329. 	    if(dy && dix > diy) {
1330. 		register int ddx = (xx > tx) ? -1 : 1;
1331. 
1332. 		crm = &levl[xx+ddx][yy];
1333. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
1334. 		    dx = ddx;
1335. 		    dy = 0;
1336. 		    continue;
1337. 		}
1338. 	    } else if(dx && diy > dix) {
1339. 		register int ddy = (yy > ty) ? -1 : 1;
1340. 
1341. 		crm = &levl[xx][yy+ddy];
1342. 		if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR) {
1343. 		    dy = ddy;
1344. 		    dx = 0;
1345. 		    continue;
1346. 		}
1347. 	    }
1348. 
1349. 	    /* continue straight on? */
1350. 	    crm = &levl[xx+dx][yy+dy];
1351. 	    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
1352. 		continue;
1353. 
1354. 	    /* no, what must we do now?? */
1355. 	    if(dx) {
1356. 		dx = 0;
1357. 		dy = (ty < yy) ? -1 : 1;
1358. 	    } else {
1359. 		dy = 0;
1360. 		dx = (tx < xx) ? -1 : 1;
1361. 	    }
1362. 	    crm = &levl[xx+dx][yy+dy];
1363. 	    if(crm->typ == btyp || crm->typ == ftyp || crm->typ == SCORR)
1364. 		continue;
1365. 	    dy = -dy;
1366. 	    dx = -dx;
1367. 	}
1368. 	return TRUE;
1369. }
1370. 

fix_stair_rooms

1371. /*
1372.  * Disgusting hack: since special levels have their rooms filled before
1373.  * sorting the rooms, we have to re-arrange the speed values upstairs_room
1374.  * and dnstairs_room after the rooms have been sorted.  On normal levels,
1375.  * stairs don't get created until _after_ sorting takes place.
1376.  */
1377. STATIC_OVL void
1378. fix_stair_rooms()
1379. {
1380.     int i;
1381.     struct mkroom *croom;
1382. 
1383.     if(xdnstair &&
1384.        !((dnstairs_room->lx <= xdnstair && xdnstair <= dnstairs_room->hx) &&
1385. 	 (dnstairs_room->ly <= ydnstair && ydnstair <= dnstairs_room->hy))) {
1386. 	for(i=0; i < nroom; i++) {
1387. 	    croom = &rooms[i];
1388. 	    if((croom->lx <= xdnstair && xdnstair <= croom->hx) &&
1389. 	       (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
1390. 		dnstairs_room = croom;
1391. 		break;
1392. 	    }
1393. 	}
1394. 	if(i == nroom)
1395. 	    panic("Couldn't find dnstair room in fix_stair_rooms!");
1396.     }
1397.     if(xupstair &&
1398.        !((upstairs_room->lx <= xupstair && xupstair <= upstairs_room->hx) &&
1399. 	 (upstairs_room->ly <= yupstair && yupstair <= upstairs_room->hy))) {
1400. 	for(i=0; i < nroom; i++) {
1401. 	    croom = &rooms[i];
1402. 	    if((croom->lx <= xupstair && xupstair <= croom->hx) &&
1403. 	       (croom->ly <= yupstair && yupstair <= croom->hy)) {
1404. 		upstairs_room = croom;
1405. 		break;
1406. 	    }
1407. 	}
1408. 	if(i == nroom)
1409. 	    panic("Couldn't find upstair room in fix_stair_rooms!");
1410.     }
1411. }
1412. 

create_corridor

1413. /*
1414.  * Corridors always start from a door. But it can end anywhere...
1415.  * Basically we search for door coordinates or for endpoints coordinates
1416.  * (from a distance).
1417.  */
1418. 
1419. STATIC_OVL void
1420. create_corridor(c)
1421. corridor	*c;
1422. {
1423. 	coord org, dest;
1424. 
1425. 	if (c->src.room == -1) {
1426. 		sort_rooms();
1427. 		fix_stair_rooms();
1428. 		makecorridors();
1429. 		return;
1430. 	}
1431. 
1432. 	if( !search_door(&rooms[c->src.room], &org.x, &org.y, c->src.wall,
1433. 			 c->src.door))
1434. 	    return;
1435. 
1436. 	if (c->dest.room != -1) {
1437. 		if(!search_door(&rooms[c->dest.room], &dest.x, &dest.y,
1438. 				c->dest.wall, c->dest.door))
1439. 		    return;
1440. 		switch(c->src.wall) {
1441. 		      case W_NORTH: org.y--; break;
1442. 		      case W_SOUTH: org.y++; break;
1443. 		      case W_WEST:  org.x--; break;
1444. 		      case W_EAST:  org.x++; break;
1445. 		}
1446. 		switch(c->dest.wall) {
1447. 		      case W_NORTH: dest.y--; break;
1448. 		      case W_SOUTH: dest.y++; break;
1449. 		      case W_WEST:  dest.x--; break;
1450. 		      case W_EAST:  dest.x++; break;
1451. 		}
1452. 		(void) dig_corridor(&org, &dest, FALSE, CORR, STONE);
1453. 	}
1454. }
1455. 
1456. 

fill_room

1457. /*
1458.  * Fill a room (shop, zoo, etc...) with appropriate stuff.
1459.  */
1460. 
1461. void
1462. fill_room(croom, prefilled)
1463. struct mkroom *croom;
1464. boolean prefilled;
1465. {
1466. 	if (!croom || croom->rtype == OROOM)
1467. 	    return;
1468. 
1469. 	if (!prefilled) {
1470. 	    int x,y;
1471. 
1472. 	    /* Shop ? */
1473. 	    if (croom->rtype >= SHOPBASE) {
1474. 		    stock_room(croom->rtype - SHOPBASE, croom);
1475. 		    level.flags.has_shop = TRUE;
1476. 		    return;
1477. 	    }
1478. 
1479. 	    switch (croom->rtype) {
1480. 		case VAULT:
1481. 		    for (x=croom->lx;x<=croom->hx;x++)
1482. 			for (y=croom->ly;y<=croom->hy;y++)
1483. 			    (void) mkgold((long)rn1(abs(depth(&u.uz))*100, 51), x, y);
1484. 		    break;
1485. 		case COURT:
1486. 		case ZOO:
1487. 		case BEEHIVE:
1488. 		case MORGUE:
1489. 		case BARRACKS:
1490. 		    fill_zoo(croom);
1491. 		    break;
1492. 	    }
1493. 	}
1494. 	switch (croom->rtype) {
1495. 	    case VAULT:
1496. 		level.flags.has_vault = TRUE;
1497. 		break;
1498. 	    case ZOO:
1499. 		level.flags.has_zoo = TRUE;
1500. 		break;
1501. 	    case COURT:
1502. 		level.flags.has_court = TRUE;
1503. 		break;
1504. 	    case MORGUE:
1505. 		level.flags.has_morgue = TRUE;
1506. 		break;
1507. 	    case BEEHIVE:
1508. 		level.flags.has_beehive = TRUE;
1509. 		break;
1510. 	    case BARRACKS:
1511. 		level.flags.has_barracks = TRUE;
1512. 		break;
1513. 	    case TEMPLE:
1514. 		level.flags.has_temple = TRUE;
1515. 		break;
1516. 	    case SWAMP:
1517. 		level.flags.has_swamp = TRUE;
1518. 		break;
1519. 	}
1520. }
1521. 

free_rooms

1522. STATIC_OVL void
1523. free_rooms(ro, n)
1524. room **ro;
1525. int n;
1526. {
1527. 	short j;
1528. 	room *r;
1529. 
1530. 	while(n--) {
1531. 		r = ro[n];
1532. 		Free(r->name);
1533. 		Free(r->parent);
1534. 		if ((j = r->ndoor) != 0) {
1535. 			while(j--)
1536. 			    Free(r->doors[j]);
1537. 			Free(r->doors);
1538. 		}
1539. 		if ((j = r->nstair) != 0) {
1540. 			while(j--)
1541. 			    Free(r->stairs[j]);
1542. 			Free(r->stairs);
1543. 		}
1544. 		if ((j = r->naltar) != 0) {
1545. 			while (j--)
1546. 			    Free(r->altars[j]);
1547. 			Free(r->altars);
1548. 		}
1549. 		if ((j = r->nfountain) != 0) {
1550. 			while(j--)
1551. 			    Free(r->fountains[j]);
1552. 			Free(r->fountains);
1553. 		}
1554. 		if ((j = r->nsink) != 0) {
1555. 			while(j--)
1556. 			    Free(r->sinks[j]);
1557. 			Free(r->sinks);
1558. 		}
1559. 		if ((j = r->npool) != 0) {
1560. 			while(j--)
1561. 			    Free(r->pools[j]);
1562. 			Free(r->pools);
1563. 		}
1564. 		if ((j = r->ntrap) != 0) {
1565. 			while (j--)
1566. 			    Free(r->traps[j]);
1567. 			Free(r->traps);
1568. 		}
1569. 		if ((j = r->nmonster) != 0) {
1570. 			while (j--)
1571. 				Free(r->monsters[j]);
1572. 			Free(r->monsters);
1573. 		}
1574. 		if ((j = r->nobject) != 0) {
1575. 			while (j--)
1576. 				Free(r->objects[j]);
1577. 			Free(r->objects);
1578. 		}
1579. 		if ((j = r->ngold) != 0) {
1580. 			while(j--)
1581. 			    Free(r->golds[j]);
1582. 			Free(r->golds);
1583. 		}
1584. 		if ((j = r->nengraving) != 0) {
1585. 			while (j--)
1586. 				Free(r->engravings[j]);
1587. 			Free(r->engravings);
1588. 		}
1589. 		Free(r);
1590. 	}
1591. 	Free(ro);
1592. }
1593. 

build_room

1594. STATIC_OVL void
1595. build_room(r, pr)
1596. room *r, *pr;
1597. {
1598. 	boolean okroom;
1599. 	struct mkroom	*aroom;
1600. 	short i;
1601. 	xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
1602. 
1603. 	if(pr) {
1604. 		aroom = &subrooms[nsubroom];
1605. 		okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h,
1606. 					rtype, r->rlit);
1607. 	} else {
1608. 		aroom = &rooms[nroom];
1609. 		okroom = create_room(r->x, r->y, r->w, r->h, r->xalign,
1610. 				     r->yalign, rtype, r->rlit);
1611. 		r->mkr = aroom;
1612. 	}
1613. 
1614. 	if (okroom) {
1615. 		/* Create subrooms if necessary... */
1616. 		for(i=0; i < r->nsubroom; i++)
1617. 		    build_room(r->subrooms[i], r);
1618. 		/* And now we can fill the room! */
1619. 
1620. 		/* Priority to the stairs */
1621. 
1622. 		for(i=0; i <r->nstair; i++)
1623. 		    create_stairs(r->stairs[i], aroom);
1624. 
1625. 		/* Then to the various elements (sinks, etc..) */
1626. 		for(i = 0; i<r->nsink; i++)
1627. 		    create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK);
1628. 		for(i = 0; i<r->npool; i++)
1629. 		    create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL);
1630. 		for(i = 0; i<r->nfountain; i++)
1631. 		    create_feature(r->fountains[i]->x, r->fountains[i]->y,
1632. 				   aroom, FOUNTAIN);
1633. 		for(i = 0; i<r->naltar; i++)
1634. 		    create_altar(r->altars[i], aroom);
1635. 		for(i = 0; i<r->ndoor; i++)
1636. 		    create_door(r->doors[i], aroom);
1637. 
1638. 		/* The traps */
1639. 		for(i = 0; i<r->ntrap; i++)
1640. 		    create_trap(r->traps[i], aroom);
1641. 
1642. 		/* The monsters */
1643. 		for(i = 0; i<r->nmonster; i++)
1644. 		    create_monster(r->monsters[i], aroom);
1645. 
1646. 		/* The objects */
1647. 		for(i = 0; i<r->nobject; i++)
1648. 		    create_object(r->objects[i], aroom);
1649. 
1650. 		/* The gold piles */
1651. 		for(i = 0; i<r->ngold; i++)
1652. 		    create_gold(r->golds[i], aroom);
1653. 
1654. 		/* The engravings */
1655. 		for (i = 0; i < r->nengraving; i++)
1656. 		    create_engraving(r->engravings[i], aroom);
1657. 
1658. #ifdef SPECIALIZATION
1659. 		topologize(aroom,FALSE);		/* set roomno */
1660. #else
1661. 		topologize(aroom);			/* set roomno */
1662. #endif
1663. 		/* MRS - 07/04/91 - This is temporary but should result
1664. 		 * in proper filling of shops, etc.
1665. 		 * DLC - this can fail if corridors are added to this room
1666. 		 * at a later point.  Currently no good way to fix this.
1667. 		 */
1668. 		if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE);
1669. 	}
1670. }
1671. 

light_region

1672. /*
1673.  * set lighting in a region that will not become a room.
1674.  */
1675. STATIC_OVL void
1676. light_region(tmpregion)
1677.     region  *tmpregion;
1678. {
1679.     register boolean litstate = tmpregion->rlit ? 1 : 0;
1680.     register int hiy = tmpregion->y2;
1681.     register int x, y;
1682.     register struct rm *lev;
1683.     int lowy = tmpregion->y1;
1684.     int lowx = tmpregion->x1, hix = tmpregion->x2;
1685. 
1686.     if(litstate) {
1687. 	/* adjust region size for walls, but only if lighted */
1688. 	lowx = max(lowx-1,1);
1689. 	hix = min(hix+1,COLNO-1);
1690. 	lowy = max(lowy-1,0);
1691. 	hiy = min(hiy+1, ROWNO-1);
1692.     }
1693.     for(x = lowx; x <= hix; x++) {
1694. 	lev = &levl[x][lowy];
1695. 	for(y = lowy; y <= hiy; y++) {
1696. 	    if (lev->typ != LAVAPOOL) /* this overrides normal lighting */
1697. 		lev->lit = litstate;
1698. 	    lev++;
1699. 	}
1700.     }
1701. }
1702. 

load_common_data

1703. /* initialization common to all special levels */
1704. STATIC_OVL void
1705. load_common_data(fd, typ)
1706. dlb *fd;
1707. int typ;
1708. {
1709. 	uchar	n;
1710. 	long	lev_flags;
1711. 	int	i;
1712. 
1713.       {
1714. 	aligntyp atmp;
1715. 	/* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */
1716. 	i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
1717. 	if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
1718.       }
1719. 
1720. 	level.flags.is_maze_lev = typ == SP_LEV_MAZE;
1721. 
1722. 	/* Read the level initialization data */
1723. 	Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd);
1724. 	if(init_lev.init_present) {
1725. 	    if(init_lev.lit < 0)
1726. 		init_lev.lit = rn2(2);
1727. 	    mkmap(&init_lev);
1728. 	}
1729. 
1730. 	/* Read the per level flags */
1731. 	Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd);
1732. 	if (lev_flags & NOTELEPORT)
1733. 	    level.flags.noteleport = 1;
1734. 	if (lev_flags & HARDFLOOR)
1735. 	    level.flags.hardfloor = 1;
1736. 	if (lev_flags & NOMMAP)
1737. 	    level.flags.nommap = 1;
1738. 	if (lev_flags & SHORTSIGHTED)
1739. 	    level.flags.shortsighted = 1;
1740. 	if (lev_flags & ARBOREAL)
1741. 	    level.flags.arboreal = 1;
1742. 
1743. 	/* Read message */
1744. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
1745. 	if (n) {
1746. 	    lev_message = (char *) alloc(n + 1);
1747. 	    Fread((genericptr_t) lev_message, 1, (int) n, fd);
1748. 	    lev_message[n] = 0;
1749. 	}
1750. }
1751. 

load_one_monster

1752. STATIC_OVL void
1753. load_one_monster(fd, m)
1754. dlb *fd;
1755. monster *m;
1756. {
1757. 	int size;
1758. 
1759. 	Fread((genericptr_t) m, 1, sizeof *m, fd);
1760. 	if ((size = m->name.len) != 0) {
1761. 	    m->name.str = (char *) alloc((unsigned)size + 1);
1762. 	    Fread((genericptr_t) m->name.str, 1, size, fd);
1763. 	    m->name.str[size] = '\0';
1764. 	} else
1765. 	    m->name.str = (char *) 0;
1766. 	if ((size = m->appear_as.len) != 0) {
1767. 	    m->appear_as.str = (char *) alloc((unsigned)size + 1);
1768. 	    Fread((genericptr_t) m->appear_as.str, 1, size, fd);
1769. 	    m->appear_as.str[size] = '\0';
1770. 	} else
1771. 	    m->appear_as.str = (char *) 0;
1772. }
1773. 

load_one_object

1774. STATIC_OVL void
1775. load_one_object(fd, o)
1776. dlb *fd;
1777. object *o;
1778. {
1779. 	int size;
1780. 
1781. 	Fread((genericptr_t) o, 1, sizeof *o, fd);
1782. 	if ((size = o->name.len) != 0) {
1783. 	    o->name.str = (char *) alloc((unsigned)size + 1);
1784. 	    Fread((genericptr_t) o->name.str, 1, size, fd);
1785. 	    o->name.str[size] = '\0';
1786. 	} else
1787. 	    o->name.str = (char *) 0;
1788. }
1789. 

load_one_engraving

1790. STATIC_OVL void
1791. load_one_engraving(fd, e)
1792. dlb *fd;
1793. engraving *e;
1794. {
1795. 	int size;
1796. 
1797. 	Fread((genericptr_t) e, 1, sizeof *e, fd);
1798. 	size = e->engr.len;
1799. 	e->engr.str = (char *) alloc((unsigned)size+1);
1800. 	Fread((genericptr_t) e->engr.str, 1, size, fd);
1801. 	e->engr.str[size] = '\0';
1802. }
1803. 

load_rooms

1804. STATIC_OVL boolean
1805. load_rooms(fd)
1806. dlb *fd;
1807. {
1808. 	xchar		nrooms, ncorr;
1809. 	char		n;
1810. 	short		size;
1811. 	corridor	tmpcor;
1812. 	room**		tmproom;
1813. 	int		i, j;
1814. 
1815. 	load_common_data(fd, SP_LEV_ROOMS);
1816. 
1817. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */
1818. 	if (n) {
1819. 		Fread((genericptr_t)robjects, sizeof(*robjects), n, fd);
1820. 		sp_lev_shuffle(robjects, (char *)0, (int)n);
1821. 	}
1822. 
1823. 	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */
1824. 	if (n) {
1825. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd);
1826. 		sp_lev_shuffle(rmonst, (char *)0, (int)n);
1827. 	}
1828. 
1829. 	Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd);
1830. 						/* Number of rooms to read */
1831. 	tmproom = NewTab(room,nrooms);
1832. 	for (i=0;i<nrooms;i++) {
1833. 		room *r;
1834. 
1835. 		r = tmproom[i] = New(room);
1836. 
1837. 		/* Let's see if this room has a name */
1838. 		Fread((genericptr_t) &size, 1, sizeof(size), fd);
1839. 		if (size > 0) {	/* Yup, it does! */
1840. 			r->name = (char *) alloc((unsigned)size + 1);
1841. 			Fread((genericptr_t) r->name, 1, size, fd);
1842. 			r->name[size] = 0;
1843. 		} else
1844. 		    r->name = (char *) 0;
1845. 
1846. 		/* Let's see if this room has a parent */
1847. 		Fread((genericptr_t) &size, 1, sizeof(size), fd);
1848. 		if (size > 0) {	/* Yup, it does! */
1849. 			r->parent = (char *) alloc((unsigned)size + 1);
1850. 			Fread((genericptr_t) r->parent, 1, size, fd);
1851. 			r->parent[size] = 0;
1852. 		} else
1853. 		    r->parent = (char *) 0;
1854. 
1855. 		Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd);
1856. 					/* x pos on the grid (1-5) */
1857. 		Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd);
1858. 					 /* y pos on the grid (1-5) */
1859. 		Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd);
1860. 					 /* width of the room */
1861. 		Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd);
1862. 					 /* height of the room */
1863. 		Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd);
1864. 					 /* horizontal alignment */
1865. 		Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd);
1866. 					 /* vertical alignment */
1867. 		Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd);
1868. 					 /* type of room (zoo, shop, etc.) */
1869. 		Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd);
1870. 					 /* chance of room being special. */
1871. 		Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd);
1872. 					 /* lit or not ? */
1873. 		Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd);
1874. 					 /* to be filled? */
1875. 		r->nsubroom= 0;
1876. 
1877. 		/* read the doors */
1878. 		Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd);
1879. 		if ((n = r->ndoor) != 0)
1880. 		    r->doors = NewTab(room_door, n);
1881. 		while(n--) {
1882. 			r->doors[(int)n] = New(room_door);
1883. 			Fread((genericptr_t) r->doors[(int)n], 1,
1884. 				sizeof(room_door), fd);
1885. 		}
1886. 
1887. 		/* read the stairs */
1888. 		Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd);
1889. 		if ((n = r->nstair) != 0)
1890. 		    r->stairs = NewTab(stair, n);
1891. 		while (n--) {
1892. 			r->stairs[(int)n] = New(stair);
1893. 			Fread((genericptr_t) r->stairs[(int)n], 1,
1894. 				sizeof(stair), fd);
1895. 		}
1896. 
1897. 		/* read the altars */
1898. 		Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd);
1899. 		if ((n = r->naltar) != 0)
1900. 		    r->altars = NewTab(altar, n);
1901. 		while (n--) {
1902. 			r->altars[(int)n] = New(altar);
1903. 			Fread((genericptr_t) r->altars[(int)n], 1,
1904. 				sizeof(altar), fd);
1905. 		}
1906. 
1907. 		/* read the fountains */
1908. 		Fread((genericptr_t) &r->nfountain, 1,
1909. 			sizeof(r->nfountain), fd);
1910. 		if ((n = r->nfountain) != 0)
1911. 		    r->fountains = NewTab(fountain, n);
1912. 		while (n--) {
1913. 			r->fountains[(int)n] = New(fountain);
1914. 			Fread((genericptr_t) r->fountains[(int)n], 1,
1915. 				sizeof(fountain), fd);
1916. 		}
1917. 
1918. 		/* read the sinks */
1919. 		Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd);
1920. 		if ((n = r->nsink) != 0)
1921. 		    r->sinks = NewTab(sink, n);
1922. 		while (n--) {
1923. 			r->sinks[(int)n] = New(sink);
1924. 			Fread((genericptr_t) r->sinks[(int)n], 1, sizeof(sink), fd);
1925. 		}
1926. 
1927. 		/* read the pools */
1928. 		Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd);
1929. 		if ((n = r->npool) != 0)
1930. 		    r->pools = NewTab(pool,n);
1931. 		while (n--) {
1932. 			r->pools[(int)n] = New(pool);
1933. 			Fread((genericptr_t) r->pools[(int)n], 1, sizeof(pool), fd);
1934. 		}
1935. 
1936. 		/* read the traps */
1937. 		Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd);
1938. 		if ((n = r->ntrap) != 0)
1939. 		    r->traps = NewTab(trap, n);
1940. 		while(n--) {
1941. 			r->traps[(int)n] = New(trap);
1942. 			Fread((genericptr_t) r->traps[(int)n], 1, sizeof(trap), fd);
1943. 		}
1944. 
1945. 		/* read the monsters */
1946. 		Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd);
1947. 		if ((n = r->nmonster) != 0) {
1948. 		    r->monsters = NewTab(monster, n);
1949. 		    while(n--) {
1950. 			r->monsters[(int)n] = New(monster);
1951. 			load_one_monster(fd, r->monsters[(int)n]);
1952. 		    }
1953. 		} else
1954. 		    r->monsters = 0;
1955. 
1956. 		/* read the objects, in same order as mazes */
1957. 		Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd);
1958. 		if ((n = r->nobject) != 0) {
1959. 		    r->objects = NewTab(object, n);
1960. 		    for (j = 0; j < n; ++j) {
1961. 			r->objects[j] = New(object);
1962. 			load_one_object(fd, r->objects[j]);
1963. 		    }
1964. 		} else
1965. 		    r->objects = 0;
1966. 
1967. 		/* read the gold piles */
1968. 		Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd);
1969. 		if ((n = r->ngold) != 0)
1970. 		    r->golds = NewTab(gold, n);
1971. 		while (n--) {
1972. 			r->golds[(int)n] = New(gold);
1973. 			Fread((genericptr_t) r->golds[(int)n], 1, sizeof(gold), fd);
1974. 		}
1975. 
1976. 		/* read the engravings */
1977. 		Fread((genericptr_t) &r->nengraving, 1,
1978. 			sizeof(r->nengraving), fd);
1979. 		if ((n = r->nengraving) != 0) {
1980. 		    r->engravings = NewTab(engraving,n);
1981. 		    while (n--) {
1982. 			r->engravings[(int)n] = New(engraving);
1983. 			load_one_engraving(fd, r->engravings[(int)n]);
1984. 		    }
1985. 		} else
1986. 		    r->engravings = 0;
1987. 
1988. 	}
1989. 
1990. 	/* Now that we have loaded all the rooms, search the
1991. 	 * subrooms and create the links.
1992. 	 */
1993. 
1994. 	for (i = 0; i<nrooms; i++)
1995. 	    if (tmproom[i]->parent) {
1996. 		    /* Search the parent room */
1997. 		    for(j=0; j<nrooms; j++)
1998. 			if (tmproom[j]->name && !strcmp(tmproom[j]->name,
1999. 						       tmproom[i]->parent)) {
2000. 				n = tmproom[j]->nsubroom++;
2001. 				tmproom[j]->subrooms[(int)n] = tmproom[i];
2002. 				break;
2003. 			}
2004. 	    }
2005. 
2006. 	/*
2007. 	 * Create the rooms now...
2008. 	 */
2009. 
2010. 	for (i=0; i < nrooms; i++)
2011. 	    if(!tmproom[i]->parent)
2012. 		build_room(tmproom[i], (room *) 0);
2013. 
2014. 	free_rooms(tmproom, nrooms);
2015. 
2016. 	/* read the corridors */
2017. 
2018. 	Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd);
2019. 	for (i=0; i<ncorr; i++) {
2020. 		Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd);
2021. 		create_corridor(&tmpcor);
2022. 	}
2023. 
2024. 	return TRUE;
2025. }
2026. 

maze1xy

2027. /*
2028.  * Select a random coordinate in the maze.
2029.  *
2030.  * We want a place not 'touched' by the loader.  That is, a place in
2031.  * the maze outside every part of the special level.
2032.  */
2033. 
2034. STATIC_OVL void
2035. maze1xy(m, humidity)
2036. coord *m;
2037. int humidity;
2038. {
2039. 	register int x, y, tryct = 2000;
2040. 	/* tryct:  normally it won't take more than ten or so tries due
2041. 	   to the circumstances under which we'll be called, but the
2042. 	   `humidity' screening might drastically change the chances */
2043. 
2044. 	do {
2045. 	    x = rn1(x_maze_max - 3, 3);
2046. 	    y = rn1(y_maze_max - 3, 3);
2047. 	    if (--tryct < 0) break;	/* give up */
2048. 	} while (!(x % 2) || !(y % 2) || Map[x][y] ||
2049. 		 !is_ok_location((schar)x, (schar)y, humidity));
2050. 
2051. 	m->x = (xchar)x,  m->y = (xchar)y;
2052. }
2053. 

load_maze

2054. /*
2055.  * The Big Thing: special maze loader
2056.  *
2057.  * Could be cleaner, but it works.
2058.  */
2059. 
2060. STATIC_OVL boolean
2061. load_maze(fd)
2062. dlb *fd;
2063. {
2064.     xchar   x, y, typ;
2065.     boolean prefilled, room_not_needed;
2066. 
2067.     char    n, numpart = 0;
2068.     xchar   nwalk = 0, nwalk_sav;
2069.     schar   filling;
2070.     char    halign, valign;
2071. 
2072.     int     xi, dir, size;
2073.     coord   mm;
2074.     int     mapcount, mapcountmax, mapfact;
2075. 
2076.     lev_region  tmplregion;
2077.     region  tmpregion;
2078.     door    tmpdoor;
2079.     trap    tmptrap;
2080.     monster tmpmons;
2081.     object  tmpobj;
2082.     drawbridge tmpdb;
2083.     walk    tmpwalk;
2084.     digpos  tmpdig;
2085.     lad     tmplad;
2086.     stair   tmpstair, prevstair;
2087.     altar   tmpaltar;
2088.     gold    tmpgold;
2089.     fountain tmpfountain;
2090.     engraving tmpengraving;
2091.     xchar   mustfill[(MAXNROFROOMS+1)*2];
2092.     struct trap *badtrap;
2093.     boolean has_bounds;
2094. 
2095.     (void) memset((genericptr_t)&Map[0][0], 0, sizeof Map);
2096.     load_common_data(fd, SP_LEV_MAZE);
2097. 
2098.     /* Initialize map */
2099.     Fread((genericptr_t) &filling, 1, sizeof(filling), fd);
2100.     if (!init_lev.init_present) { /* don't init if mkmap() has been called */
2101.       for(x = 2; x <= x_maze_max; x++)
2102. 	for(y = 0; y <= y_maze_max; y++)
2103. 	    if (filling == -1) {
2104. #ifndef WALLIFIED_MAZE
2105. 		    levl[x][y].typ = STONE;
2106. #else
2107. 		    levl[x][y].typ =
2108. 			(y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL;
2109. #endif
2110. 	    } else {
2111. 		    levl[x][y].typ = filling;
2112. 	    }
2113.     }
2114. 
2115.     /* Start reading the file */
2116.     Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
2117. 						/* Number of parts */
2118.     if (!numpart || numpart > 9)
2119. 	panic("load_maze error: numpart = %d", (int) numpart);
2120. 
2121.     while (numpart--) {
2122. 	Fread((genericptr_t) &halign, 1, sizeof(halign), fd);
2123. 					/* Horizontal alignment */
2124. 	Fread((genericptr_t) &valign, 1, sizeof(valign), fd);
2125. 					/* Vertical alignment */
2126. 	Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd);
2127. 					/* size in X */
2128. 	Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd);
2129. 					/* size in Y */
2130. 	switch((int) halign) {
2131. 	    case LEFT:	    xstart = 3;					break;
2132. 	    case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);	break;
2133. 	    case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break;
2134. 	    case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);	break;
2135. 	    case RIGHT:     xstart = x_maze_max-xsize-1;		break;
2136. 	}
2137. 	switch((int) valign) {
2138. 	    case TOP:	    ystart = 3;					break;
2139. 	    case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break;
2140. 	    case BOTTOM:    ystart = y_maze_max-ysize-1;		break;
2141. 	}
2142. 	if (!(xstart % 2)) xstart++;
2143. 	if (!(ystart % 2)) ystart++;
2144. 	if ((ystart < 0) || (ystart + ysize > ROWNO)) {
2145. 	    /* try to move the start a bit */
2146. 	    ystart += (ystart > 0) ? -2 : 2;
2147. 	    if(ysize == ROWNO) ystart = 0;
2148. 	    if(ystart < 0 || ystart + ysize > ROWNO)
2149. 		panic("reading special level with ysize too large");
2150. 	}
2151. 
2152. 	/*
2153. 	 * If any CROSSWALLs are found, must change to ROOM after REGION's
2154. 	 * are laid out.  CROSSWALLS are used to specify "invisible"
2155. 	 * boundaries where DOOR syms look bad or aren't desirable.
2156. 	 */
2157. 	has_bounds = FALSE;
2158. 
2159. 	if(init_lev.init_present && xsize <= 1 && ysize <= 1) {
2160. 	    xstart = 1;
2161. 	    ystart = 0;
2162. 	    xsize = COLNO-1;
2163. 	    ysize = ROWNO;
2164. 	} else {
2165. 	    /* Load the map */
2166. 	    for(y = ystart; y < ystart+ysize; y++)
2167. 		for(x = xstart; x < xstart+xsize; x++) {
2168. 		    levl[x][y].typ = Fgetc(fd);
2169. 		    levl[x][y].lit = FALSE;
2170. 		    /* clear out levl: load_common_data may set them */
2171. 		    levl[x][y].flags = 0;
2172. 		    levl[x][y].horizontal = 0;
2173. 		    levl[x][y].roomno = 0;
2174. 		    levl[x][y].edge = 0;
2175. 		    /*
2176. 		     * Note: Even though levl[x][y].typ is type schar,
2177. 		     *	 lev_comp.y saves it as type char. Since schar != char
2178. 		     *	 all the time we must make this exception or hack
2179. 		     *	 through lev_comp.y to fix.
2180. 		     */
2181. 
2182. 		    /*
2183. 		     *  Set secret doors to closed (why not trapped too?).  Set
2184. 		     *  the horizontal bit.
2185. 		     */
2186. 		    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
2187. 			if(levl[x][y].typ == SDOOR)
2188. 			    levl[x][y].doormask = D_CLOSED;
2189. 			/*
2190. 			 *  If there is a wall to the left that connects to a
2191. 			 *  (secret) door, then it is horizontal.  This does
2192. 			 *  not allow (secret) doors to be corners of rooms.
2193. 			 */
2194. 			if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
2195. 					    levl[x-1][y].horizontal))
2196. 			    levl[x][y].horizontal = 1;
2197. 		    } else if(levl[x][y].typ == HWALL ||
2198. 				levl[x][y].typ == IRONBARS)
2199. 			levl[x][y].horizontal = 1;
2200. 		    else if(levl[x][y].typ == LAVAPOOL)
2201. 			levl[x][y].lit = 1;
2202. 		    else if(levl[x][y].typ == CROSSWALL)
2203. 			has_bounds = TRUE;
2204. 		    Map[x][y] = 1;
2205. 		}
2206. 	    if (init_lev.init_present && init_lev.joined)
2207. 		remove_rooms(xstart, ystart, xstart+xsize, ystart+ysize);
2208. 	}
2209. 
2210. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2211. 						/* Number of level regions */
2212. 	if(n) {
2213. 	    if(num_lregions) {
2214. 		/* realloc the lregion space to add the new ones */
2215. 		/* don't really free it up until the whole level is done */
2216. 		lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
2217. 						(unsigned)(n+num_lregions));
2218. 		(void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions,
2219. 					sizeof(lev_region) * num_lregions);
2220. 		Free(lregions);
2221. 		num_lregions += n;
2222. 		lregions = newl;
2223. 	    } else {
2224. 		num_lregions = n;
2225. 		lregions = (lev_region *)
2226. 				alloc(sizeof(lev_region) * (unsigned)n);
2227. 	    }
2228. 	}
2229. 
2230. 	while(n--) {
2231. 	    Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd);
2232. 	    if ((size = tmplregion.rname.len) != 0) {
2233. 		tmplregion.rname.str = (char *) alloc((unsigned)size + 1);
2234. 		Fread((genericptr_t) tmplregion.rname.str, size, 1, fd);
2235. 		tmplregion.rname.str[size] = '\0';
2236. 	    } else
2237. 		tmplregion.rname.str = (char *) 0;
2238. 	    if(!tmplregion.in_islev) {
2239. 		get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1,
2240. 								DRY|WET);
2241. 		get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2,
2242. 								DRY|WET);
2243. 	    }
2244. 	    if(!tmplregion.del_islev) {
2245. 		get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1,
2246. 								DRY|WET);
2247. 		get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2,
2248. 								DRY|WET);
2249. 	    }
2250. 	    lregions[(int)n] = tmplregion;
2251. 	}
2252. 
2253. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2254. 						/* Random objects */
2255. 	if(n) {
2256. 		Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd);
2257. 		sp_lev_shuffle(robjects, (char *)0, (int)n);
2258. 	}
2259. 
2260. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2261. 						/* Random locations */
2262. 	if(n) {
2263. 		Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd);
2264. 		Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd);
2265. 		sp_lev_shuffle(rloc_x, rloc_y, (int)n);
2266. 	}
2267. 
2268. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2269. 						/* Random monsters */
2270. 	if(n) {
2271. 		Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd);
2272. 		sp_lev_shuffle(rmonst, (char *)0, (int)n);
2273. 	}
2274. 
2275. 	(void) memset((genericptr_t)mustfill, 0, sizeof(mustfill));
2276. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2277. 						/* Number of subrooms */
2278. 	while(n--) {
2279. 		register struct mkroom *troom;
2280. 
2281. 		Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd);
2282. 
2283. 		if(tmpregion.rtype > MAXRTYPE) {
2284. 		    tmpregion.rtype -= MAXRTYPE+1;
2285. 		    prefilled = TRUE;
2286. 		} else
2287. 		    prefilled = FALSE;
2288. 
2289. 		if(tmpregion.rlit < 0)
2290. 		    tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
2291. 			? TRUE : FALSE;
2292. 
2293. 		get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET);
2294. 		get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET);
2295. 
2296. 		/* for an ordinary room, `prefilled' is a flag to force
2297. 		   an actual room to be created (such rooms are used to
2298. 		   control placement of migrating monster arrivals) */
2299. 		room_not_needed = (tmpregion.rtype == OROOM &&
2300. 				   !tmpregion.rirreg && !prefilled);
2301. 		if (room_not_needed || nroom >= MAXNROFROOMS) {
2302. 		    if (!room_not_needed)
2303. 			impossible("Too many rooms on new level!");
2304. 		    light_region(&tmpregion);
2305. 		    continue;
2306. 		}
2307. 
2308. 		troom = &rooms[nroom];
2309. 
2310. 		/* mark rooms that must be filled, but do it later */
2311. 		if (tmpregion.rtype != OROOM)
2312. 		    mustfill[nroom] = (prefilled ? 2 : 1);
2313. 
2314. 		if(tmpregion.rirreg) {
2315. 		    min_rx = max_rx = tmpregion.x1;
2316. 		    min_ry = max_ry = tmpregion.y1;
2317. 		    flood_fill_rm(tmpregion.x1, tmpregion.y1,
2318. 				  nroom+ROOMOFFSET, tmpregion.rlit, TRUE);
2319. 		    add_room(min_rx, min_ry, max_rx, max_ry,
2320. 			     FALSE, tmpregion.rtype, TRUE);
2321. 		    troom->rlit = tmpregion.rlit;
2322. 		    troom->irregular = TRUE;
2323. 		} else {
2324. 		    add_room(tmpregion.x1, tmpregion.y1,
2325. 			     tmpregion.x2, tmpregion.y2,
2326. 			     tmpregion.rlit, tmpregion.rtype, TRUE);
2327. #ifdef SPECIALIZATION
2328. 		    topologize(troom,FALSE);		/* set roomno */
2329. #else
2330. 		    topologize(troom);			/* set roomno */
2331. #endif
2332. 		}
2333. 	}
2334. 
2335. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2336. 						/* Number of doors */
2337. 	while(n--) {
2338. 		struct mkroom *croom = &rooms[0];
2339. 
2340. 		Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd);
2341. 
2342. 		x = tmpdoor.x;	y = tmpdoor.y;
2343. 		typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
2344. 
2345. 		get_location(&x, &y, DRY);
2346. 		if(levl[x][y].typ != SDOOR)
2347. 			levl[x][y].typ = DOOR;
2348. 		else {
2349. 			if(typ < D_CLOSED)
2350. 			    typ = D_CLOSED; /* force it to be closed */
2351. 		}
2352. 		levl[x][y].doormask = typ;
2353. 
2354. 		/* Now the complicated part, list it with each subroom */
2355. 		/* The dog move and mail daemon routines use this */
2356. 		while(croom->hx >= 0 && doorindex < DOORMAX) {
2357. 		    if(croom->hx >= x-1 && croom->lx <= x+1 &&
2358. 		       croom->hy >= y-1 && croom->ly <= y+1) {
2359. 			/* Found it */
2360. 			add_door(x, y, croom);
2361. 		    }
2362. 		    croom++;
2363. 		}
2364. 	}
2365. 
2366. 	/* now that we have rooms _and_ associated doors, fill the rooms */
2367. 	for(n = 0; n < SIZE(mustfill); n++)
2368. 	    if(mustfill[(int)n])
2369. 		fill_room(&rooms[(int)n], (mustfill[(int)n] == 2));
2370. 
2371. 	/* if special boundary syms (CROSSWALL) in map, remove them now */
2372. 	if(has_bounds) {
2373. 	    for(x = xstart; x < xstart+xsize; x++)
2374. 		for(y = ystart; y < ystart+ysize; y++)
2375. 		    if(levl[x][y].typ == CROSSWALL)
2376. 			levl[x][y].typ = ROOM;
2377. 	}
2378. 
2379. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2380. 						/* Number of drawbridges */
2381. 	while(n--) {
2382. 		Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd);
2383. 
2384. 		x = tmpdb.x;  y = tmpdb.y;
2385. 		get_location(&x, &y, DRY|WET);
2386. 
2387. 		if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open))
2388. 		    impossible("Cannot create drawbridge.");
2389. 	}
2390. 
2391. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2392. 						/* Number of mazewalks */
2393. 	while(n--) {
2394. 		Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd);
2395. 
2396. 		get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET);
2397. 
2398. 		walklist[nwalk++] = tmpwalk;
2399. 	}
2400. 
2401. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2402. 						/* Number of non_diggables */
2403. 	while(n--) {
2404. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
2405. 
2406. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
2407. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
2408. 
2409. 		set_wall_property(tmpdig.x1, tmpdig.y1,
2410. 				  tmpdig.x2, tmpdig.y2, W_NONDIGGABLE);
2411. 	}
2412. 
2413. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2414. 						/* Number of non_passables */
2415. 	while(n--) {
2416. 		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
2417. 
2418. 		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
2419. 		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
2420. 
2421. 		set_wall_property(tmpdig.x1, tmpdig.y1,
2422. 				  tmpdig.x2, tmpdig.y2, W_NONPASSWALL);
2423. 	}
2424. 
2425. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2426. 						/* Number of ladders */
2427. 	while(n--) {
2428. 		Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd);
2429. 
2430. 		x = tmplad.x;  y = tmplad.y;
2431. 		get_location(&x, &y, DRY);
2432. 
2433. 		levl[x][y].typ = LADDER;
2434. 		if (tmplad.up == 1) {
2435. 			xupladder = x;	yupladder = y;
2436. 			levl[x][y].ladder = LA_UP;
2437. 		} else {
2438. 			xdnladder = x;	ydnladder = y;
2439. 			levl[x][y].ladder = LA_DOWN;
2440. 		}
2441. 	}
2442. 
2443. 	prevstair.x = prevstair.y = 0;
2444. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2445. 						/* Number of stairs */
2446. 	while(n--) {
2447. 		Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd);
2448. 
2449. 		xi = 0;
2450. 		do {
2451. 		    x = tmpstair.x;  y = tmpstair.y;
2452. 		    get_location(&x, &y, DRY);
2453. 		} while(prevstair.x && xi++ < 100 &&
2454. 			distmin(x,y,prevstair.x,prevstair.y) <= 8);
2455. 		if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
2456. 		mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0);
2457. 		prevstair.x = x;
2458. 		prevstair.y = y;
2459. 	}
2460. 
2461. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2462. 						/* Number of altars */
2463. 	while(n--) {
2464. 		Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd);
2465. 
2466. 		create_altar(&tmpaltar, (struct mkroom *)0);
2467. 	}
2468. 
2469. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2470. 						/* Number of fountains */
2471. 	while (n--) {
2472. 		Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd);
2473. 
2474. 		create_feature(tmpfountain.x, tmpfountain.y,
2475. 			       (struct mkroom *)0, FOUNTAIN);
2476. 	}
2477. 
2478. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2479. 						/* Number of traps */
2480. 	while(n--) {
2481. 		Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd);
2482. 
2483. 		create_trap(&tmptrap, (struct mkroom *)0);
2484. 	}
2485. 
2486. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2487. 						/* Number of monsters */
2488. 	while(n--) {
2489. 		load_one_monster(fd, &tmpmons);
2490. 
2491. 		create_monster(&tmpmons, (struct mkroom *)0);
2492. 	}
2493. 
2494. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2495. 						/* Number of objects */
2496. 	while(n--) {
2497. 		load_one_object(fd, &tmpobj);
2498. 
2499. 		create_object(&tmpobj, (struct mkroom *)0);
2500. 	}
2501. 
2502. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2503. 						/* Number of gold piles */
2504. 	while (n--) {
2505. 		Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd);
2506. 
2507. 		create_gold(&tmpgold, (struct mkroom *)0);
2508. 	}
2509. 
2510. 	Fread((genericptr_t) &n, 1, sizeof(n), fd);
2511. 						/* Number of engravings */
2512. 	while(n--) {
2513. 		load_one_engraving(fd, &tmpengraving);
2514. 
2515. 		create_engraving(&tmpengraving, (struct mkroom *)0);
2516. 	}
2517. 
2518.     }		/* numpart loop */
2519. 
2520.     nwalk_sav = nwalk;
2521.     while(nwalk--) {
2522. 	    x = (xchar) walklist[nwalk].x;
2523. 	    y = (xchar) walklist[nwalk].y;
2524. 	    dir = walklist[nwalk].dir;
2525. 
2526. 	    /* don't use move() - it doesn't use W_NORTH, etc. */
2527. 	    switch (dir) {
2528. 		case W_NORTH: --y; break;
2529. 		case W_SOUTH: y++; break;
2530. 		case W_EAST:  x++; break;
2531. 		case W_WEST:  --x; break;
2532. 		default: panic("load_maze: bad MAZEWALK direction");
2533. 	    }
2534. 
2535. 	    if(!IS_DOOR(levl[x][y].typ)) {
2536. #ifndef WALLIFIED_MAZE
2537. 		levl[x][y].typ = CORR;
2538. #else
2539. 		levl[x][y].typ = ROOM;
2540. #endif
2541. 		levl[x][y].flags = 0;
2542. 	    }
2543. 
2544. 	    /*
2545. 	     * We must be sure that the parity of the coordinates for
2546. 	     * walkfrom() is odd.  But we must also take into account
2547. 	     * what direction was chosen.
2548. 	     */
2549. 	    if(!(x % 2)) {
2550. 		if (dir == W_EAST)
2551. 		    x++;
2552. 		else
2553. 		    x--;
2554. 
2555. 		/* no need for IS_DOOR check; out of map bounds */
2556. #ifndef WALLIFIED_MAZE
2557. 		levl[x][y].typ = CORR;
2558. #else
2559. 		levl[x][y].typ = ROOM;
2560. #endif
2561. 		levl[x][y].flags = 0;
2562. 	    }
2563. 
2564. 	    if (!(y % 2)) {
2565. 		if (dir == W_SOUTH)
2566. 		    y++;
2567. 		else
2568. 		    y--;
2569. 	    }
2570. 
2571. 	    walkfrom(x, y);
2572.     }
2573.     wallification(1, 0, COLNO-1, ROWNO-1);
2574. 
2575.     /*
2576.      * If there's a significant portion of maze unused by the special level,
2577.      * we don't want it empty.
2578.      *
2579.      * Makes the number of traps, monsters, etc. proportional
2580.      * to the size of the maze.
2581.      */
2582.     mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
2583. 
2584.     for(x = 2; x < x_maze_max; x++)
2585. 	for(y = 0; y < y_maze_max; y++)
2586. 	    if(Map[x][y]) mapcount--;
2587. 
2588.     if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) {
2589. 	    mapfact = (int) ((mapcount * 100L) / mapcountmax);
2590. 	    for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
2591. 		    maze1xy(&mm, DRY);
2592. 		    (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
2593. 							mm.x, mm.y, TRUE);
2594. 	    }
2595. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
2596. 		    maze1xy(&mm, DRY);
2597. 		    (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE);
2598. 	    }
2599. 	    for (x = rn2(2); x; x--) {
2600. 		maze1xy(&mm, DRY);
2601. 		(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS);
2602. 	    }
2603. 	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
2604. 		    maze1xy(&mm, WET|DRY);
2605. 		    (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS);
2606. 	    }
2607. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
2608. 		    maze1xy(&mm, DRY);
2609. 		    (void) mkgold(0L,mm.x,mm.y);
2610. 	    }
2611. 	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
2612. 		    int trytrap;
2613. 
2614. 		    maze1xy(&mm, DRY);
2615. 		    trytrap = rndtrap();
2616. 		    if (sobj_at(BOULDER, mm.x, mm.y))
2617. 			while (trytrap == PIT || trytrap == SPIKED_PIT ||
2618. 				trytrap == TRAPDOOR || trytrap == HOLE)
2619. 			    trytrap = rndtrap();
2620. 		    (void) maketrap(mm.x, mm.y, trytrap);
2621. 	    }
2622.     }
2623.     return TRUE;
2624. }
2625. 

load_special

2626. /*
2627.  * General loader
2628.  */
2629. 
2630. boolean
2631. load_special(name)
2632. const char *name;
2633. {
2634. 	dlb *fd;
2635. 	boolean result = FALSE;
2636. 	char c;
2637. 	struct version_info vers_info;
2638. 
2639. 	fd = dlb_fopen(name, RDBMODE);
2640. 	if (!fd) return FALSE;
2641. 
2642. 	Fread((genericptr_t) &vers_info, sizeof vers_info, 1, fd);
2643. 	if (!check_version(&vers_info, name, TRUE))
2644. 	    goto give_up;
2645. 
2646. 	Fread((genericptr_t) &c, sizeof c, 1, fd); /* c Header */
2647. 
2648. 	switch (c) {
2649. 		case SP_LEV_ROOMS:
2650. 		    result = load_rooms(fd);
2651. 		    break;
2652. 		case SP_LEV_MAZE:
2653. 		    result = load_maze(fd);
2654. 		    break;
2655. 		default:	/* ??? */
2656. 		    result = FALSE;
2657. 	}
2658.  give_up:
2659. 	(void)dlb_fclose(fd);
2660. 	return result;
2661. }
2662. 
2663. /*sp_lev.c*/