Difference between revisions of "Source:NetHack 3.6.0/src/shknam.c"

From NetHackWiki
Jump to navigation Jump to search
 
Line 24: Line 24:
 
  <span id="line17">17. #define VEGETARIAN_CLASS (MAXOCLASSES + 1)</span>
 
  <span id="line17">17. #define VEGETARIAN_CLASS (MAXOCLASSES + 1)</span>
 
  <span id="line18">18. </span>
 
  <span id="line18">18. </span>
 +
 +
== Shopkeeper names ==
 +
   
 
  <span id="line19">19. /*</span>
 
  <span id="line19">19. /*</span>
 
  <span id="line20">20.  *  Name prefix codes:</span>
 
  <span id="line20">20.  *  Name prefix codes:</span>
Line 35: Line 38:
 
  <span id="line28">28.  */</span>
 
  <span id="line28">28.  */</span>
 
  <span id="line29">29. </span>
 
  <span id="line29">29. </span>
 +
 +
=== Liquor shop ===
 +
   
 
  <span id="line30">30. static const char *const shkliquors[] = {</span>
 
  <span id="line30">30. static const char *const shkliquors[] = {</span>
 
  <span id="line31">31.     /* Ukraine */</span>
 
  <span id="line31">31.     /* Ukraine */</span>
Line 50: Line 56:
 
  <span id="line43">43. };</span>
 
  <span id="line43">43. };</span>
 
  <span id="line44">44. </span>
 
  <span id="line44">44. </span>
 +
 +
=== Book shop ===
 +
   
 
  <span id="line45">45. static const char *const shkbooks[] = {</span>
 
  <span id="line45">45. static const char *const shkbooks[] = {</span>
 
  <span id="line46">46.     /* Eire */</span>
 
  <span id="line46">46.     /* Eire */</span>
Line 61: Line 70:
 
  <span id="line54">54. };</span>
 
  <span id="line54">54. };</span>
 
  <span id="line55">55. </span>
 
  <span id="line55">55. </span>
 +
 +
=== Armor shop ===
 +
   
 
  <span id="line56">56. static const char *const shkarmors[] = {</span>
 
  <span id="line56">56. static const char *const shkarmors[] = {</span>
 
  <span id="line57">57.     /* Turquie */</span>
 
  <span id="line57">57.     /* Turquie */</span>
Line 72: Line 84:
 
  <span id="line65">65. };</span>
 
  <span id="line65">65. };</span>
 
  <span id="line66">66. </span>
 
  <span id="line66">66. </span>
 +
 +
=== Wand shop ===
 +
   
 
  <span id="line67">67. static const char *const shkwands[] = {</span>
 
  <span id="line67">67. static const char *const shkwands[] = {</span>
 
  <span id="line68">68.     /* Wales */</span>
 
  <span id="line68">68.     /* Wales */</span>
Line 83: Line 98:
 
  <span id="line76">76. };</span>
 
  <span id="line76">76. };</span>
 
  <span id="line77">77. </span>
 
  <span id="line77">77. </span>
 +
 +
=== Ring shop ===
 +
   
 
  <span id="line78">78. static const char *const shkrings[] = {</span>
 
  <span id="line78">78. static const char *const shkrings[] = {</span>
 
  <span id="line79">79.     /* Hollandse familienamen */</span>
 
  <span id="line79">79.     /* Hollandse familienamen */</span>
Line 95: Line 113:
 
  <span id="line88">88. };</span>
 
  <span id="line88">88. };</span>
 
  <span id="line89">89. </span>
 
  <span id="line89">89. </span>
 +
 +
=== Food shop ===
 +
   
 
  <span id="line90">90. static const char *const shkfoods[] = {</span>
 
  <span id="line90">90. static const char *const shkfoods[] = {</span>
 
  <span id="line91">91.     /* Indonesia */</span>
 
  <span id="line91">91.     /* Indonesia */</span>
Line 108: Line 129:
 
  <span id="line101">101. };</span>
 
  <span id="line101">101. };</span>
 
  <span id="line102">102. </span>
 
  <span id="line102">102. </span>
 +
 +
=== Weapon shop ===
 +
   
 
  <span id="line103">103. static const char *const shkweapons[] = {</span>
 
  <span id="line103">103. static const char *const shkweapons[] = {</span>
 
  <span id="line104">104.     /* Perigord */</span>
 
  <span id="line104">104.     /* Perigord */</span>
Line 119: Line 143:
 
  <span id="line112">112. };</span>
 
  <span id="line112">112. };</span>
 
  <span id="line113">113. </span>
 
  <span id="line113">113. </span>
 +
 +
=== Tool shop ===
 +
   
 
  <span id="line114">114. static const char *const shktools[] = {</span>
 
  <span id="line114">114. static const char *const shktools[] = {</span>
 
  <span id="line115">115.     /* Spmi */</span>
 
  <span id="line115">115.     /* Spmi */</span>
Line 153: Line 180:
 
  <span id="line146">146. };</span>
 
  <span id="line146">146. };</span>
 
  <span id="line147">147. </span>
 
  <span id="line147">147. </span>
 +
 +
=== Light shop ===
 +
   
 
  <span id="line148">148. static const char *const shklight[] = {</span>
 
  <span id="line148">148. static const char *const shklight[] = {</span>
 
  <span id="line149">149.     /* Romania */</span>
 
  <span id="line149">149.     /* Romania */</span>
Line 164: Line 194:
 
  <span id="line157">157. };</span>
 
  <span id="line157">157. };</span>
 
  <span id="line158">158. </span>
 
  <span id="line158">158. </span>
 +
 +
=== General shop ===
 +
   
 
  <span id="line159">159. static const char *const shkgeneral[] = {</span>
 
  <span id="line159">159. static const char *const shkgeneral[] = {</span>
 
  <span id="line160">160.     /* Suriname */</span>
 
  <span id="line160">160.     /* Suriname */</span>
Line 180: Line 213:
 
  <span id="line173">173. };</span>
 
  <span id="line173">173. };</span>
 
  <span id="line174">174. </span>
 
  <span id="line174">174. </span>
 +
 +
=== Health food shop ===
 +
   
 
  <span id="line175">175. static const char *const shkhealthfoods[] = {</span>
 
  <span id="line175">175. static const char *const shkhealthfoods[] = {</span>
 
  <span id="line176">176.     /* Tibet */</span>
 
  <span id="line176">176.     /* Tibet */</span>
Line 192: Line 228:
 
  <span id="line185">185. };</span>
 
  <span id="line185">185. };</span>
 
  <span id="line186">186. </span>
 
  <span id="line186">186. </span>
 +
 +
== Shop types ==
 +
   
 
  <span id="line187">187. /*</span>
 
  <span id="line187">187. /*</span>
 
  <span id="line188">188.  * To add new shop types, all that is necessary is to edit the shtypes[]</span>
 
  <span id="line188">188.  * To add new shop types, all that is necessary is to edit the shtypes[]</span>
Line 351: Line 390:
 
  <span id="line344">344. };</span>
 
  <span id="line344">344. };</span>
 
  <span id="line345">345. </span>
 
  <span id="line345">345. </span>
 +
 +
== init_shop_selection ==
 +
   
 
  <span id="line346">346. #if 0</span>
 
  <span id="line346">346. #if 0</span>
 
  <span id="line347">347. /* validate shop probabilities; otherwise incorrect local changes could</span>
 
  <span id="line347">347. /* validate shop probabilities; otherwise incorrect local changes could</span>
Line 372: Line 414:
 
  <span id="line365">365. #endif /*0*/</span>
 
  <span id="line365">365. #endif /*0*/</span>
 
  <span id="line366">366. </span>
 
  <span id="line366">366. </span>
 +
 +
== veggy_item ==
 +
   
 
  <span id="line367">367. /* decide whether an object or object type is considered vegetarian;</span>
 
  <span id="line367">367. /* decide whether an object or object type is considered vegetarian;</span>
 
  <span id="line368">368.   for types, items which might go either way are assumed to be veggy */</span>
 
  <span id="line368">368.   for types, items which might go either way are assumed to be veggy */</span>
Line 405: Line 450:
 
  <span id="line398">398. }</span>
 
  <span id="line398">398. }</span>
 
  <span id="line399">399. </span>
 
  <span id="line399">399. </span>
 +
 +
== shkveg ==
 +
   
 
  <span id="line400">400. STATIC_OVL int</span>
 
  <span id="line400">400. STATIC_OVL int</span>
 
  <span id="line401">401. shkveg()</span>
 
  <span id="line401">401. shkveg()</span>
Line 439: Line 487:
 
  <span id="line432">432. }</span>
 
  <span id="line432">432. }</span>
 
  <span id="line433">433. </span>
 
  <span id="line433">433. </span>
 +
 +
== mkveggy_at ==
 +
   
 
  <span id="line434">434. /* make a random item for health food store */</span>
 
  <span id="line434">434. /* make a random item for health food store */</span>
 
  <span id="line435">435. STATIC_OVL void</span>
 
  <span id="line435">435. STATIC_OVL void</span>
Line 451: Line 502:
 
  <span id="line444">444. }</span>
 
  <span id="line444">444. }</span>
 
  <span id="line445">445. </span>
 
  <span id="line445">445. </span>
 +
 +
== mkshobj_at ==
 +
   
 
  <span id="line446">446. /* make an object of the appropriate type for a shop square */</span>
 
  <span id="line446">446. /* make an object of the appropriate type for a shop square */</span>
 
  <span id="line447">447. STATIC_OVL void</span>
 
  <span id="line447">447. STATIC_OVL void</span>
Line 491: Line 545:
 
  <span id="line484">484. }</span>
 
  <span id="line484">484. }</span>
 
  <span id="line485">485. </span>
 
  <span id="line485">485. </span>
 +
 +
== nameshk ==
 +
   
 
  <span id="line486">486. /* extract a shopkeeper name for the given shop type */</span>
 
  <span id="line486">486. /* extract a shopkeeper name for the given shop type */</span>
 
  <span id="line487">487. STATIC_OVL void</span>
 
  <span id="line487">487. STATIC_OVL void</span>
Line 566: Line 623:
 
  <span id="line559">559. }</span>
 
  <span id="line559">559. }</span>
 
  <span id="line560">560. </span>
 
  <span id="line560">560. </span>
 +
 +
== neweshk ==
 +
   
 
  <span id="line561">561. void</span>
 
  <span id="line561">561. void</span>
 
  <span id="line562">562. neweshk(mtmp)</span>
 
  <span id="line562">562. neweshk(mtmp)</span>
Line 578: Line 638:
 
  <span id="line571">571. }</span>
 
  <span id="line571">571. }</span>
 
  <span id="line572">572. </span>
 
  <span id="line572">572. </span>
 +
 +
== free_eshk ==
 +
   
 
  <span id="line573">573. void</span>
 
  <span id="line573">573. void</span>
 
  <span id="line574">574. free_eshk(mtmp)</span>
 
  <span id="line574">574. free_eshk(mtmp)</span>
Line 589: Line 652:
 
  <span id="line582">582. }</span>
 
  <span id="line582">582. }</span>
 
  <span id="line583">583. </span>
 
  <span id="line583">583. </span>
 +
 +
== shkinit ==
 +
   
 
  <span id="line584">584. /* create a new shopkeeper in the given room */</span>
 
  <span id="line584">584. /* create a new shopkeeper in the given room */</span>
 
  <span id="line585">585. STATIC_OVL int</span>
 
  <span id="line585">585. STATIC_OVL int</span>
Line 683: Line 749:
 
  <span id="line676">676. }</span>
 
  <span id="line676">676. }</span>
 
  <span id="line677">677. </span>
 
  <span id="line677">677. </span>
 +
 +
== stock_room ==
 +
   
 
  <span id="line678">678. /* stock a newly-created room with objects */</span>
 
  <span id="line678">678. /* stock a newly-created room with objects */</span>
 
  <span id="line679">679. void</span>
 
  <span id="line679">679. void</span>
Line 782: Line 851:
 
  <span id="line775">775. }</span>
 
  <span id="line775">775. }</span>
 
  <span id="line776">776. </span>
 
  <span id="line776">776. </span>
 +
 +
== saleable ==
 +
   
 
  <span id="line777">777. /* does shkp's shop stock this item type? */</span>
 
  <span id="line777">777. /* does shkp's shop stock this item type? */</span>
 
  <span id="line778">778. boolean</span>
 
  <span id="line778">778. boolean</span>
Line 807: Line 879:
 
  <span id="line800">800. }</span>
 
  <span id="line800">800. }</span>
 
  <span id="line801">801. </span>
 
  <span id="line801">801. </span>
 +
 +
== get_shop_item ==
 +
   
 
  <span id="line802">802. /* positive value: class; negative value: specific object type */</span>
 
  <span id="line802">802. /* positive value: class; negative value: specific object type */</span>
 
  <span id="line803">803. int</span>
 
  <span id="line803">803. int</span>
Line 822: Line 897:
 
  <span id="line815">815. }</span>
 
  <span id="line815">815. }</span>
 
  <span id="line816">816. </span>
 
  <span id="line816">816. </span>
 +
 +
== shkname ==
 +
   
 
  <span id="line817">817. const char *</span>
 
  <span id="line817">817. const char *</span>
 
  <span id="line818">818. shkname(mtmp)</span>
 
  <span id="line818">818. shkname(mtmp)</span>
Line 853: Line 931:
 
  <span id="line846">846. }</span>
 
  <span id="line846">846. }</span>
 
  <span id="line847">847. </span>
 
  <span id="line847">847. </span>
 +
 +
== shkname_is_pname ==
 +
   
 
  <span id="line848">848. boolean</span>
 
  <span id="line848">848. boolean</span>
 
  <span id="line849">849. shkname_is_pname(mtmp)</span>
 
  <span id="line849">849. shkname_is_pname(mtmp)</span>
Line 862: Line 943:
 
  <span id="line855">855. }</span>
 
  <span id="line855">855. }</span>
 
  <span id="line856">856. </span>
 
  <span id="line856">856. </span>
 +
 +
== is_izchak ==
 +
   
 
  <span id="line857">857. boolean</span>
 
  <span id="line857">857. boolean</span>
 
  <span id="line858">858. is_izchak(shkp, override_hallucination)</span>
 
  <span id="line858">858. is_izchak(shkp, override_hallucination)</span>

Latest revision as of 22:13, 3 January 2016

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

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

Top of file

 /* NetHack 3.6	shknam.c	$NHDT-Date: 1448094342 2015/11/21 08:25:42 $  $NHDT-Branch: master $:$NHDT-Revision: 1.38 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* shknam.c -- initialize a shop */
 
 #include "hack.h"
 
 STATIC_DCL boolean FDECL(veggy_item, (struct obj * obj, int));
 STATIC_DCL int NDECL(shkveg);
 STATIC_DCL void FDECL(mkveggy_at, (int, int));
 STATIC_DCL void FDECL(mkshobj_at, (const struct shclass *, int, int,
                                    BOOLEAN_P));
 STATIC_DCL void FDECL(nameshk, (struct monst *, const char *const *));
 STATIC_DCL int FDECL(shkinit, (const struct shclass *, struct mkroom *));
 
 #define VEGETARIAN_CLASS (MAXOCLASSES + 1)
 

Shopkeeper names

 /*
  *  Name prefix codes:
  *      dash          -  female, personal name
  *      underscore    _  female, general name
  *      plus          +  male, personal name
  *      vertical bar  |  male, general name (implied for most of shktools)
  *      equals        =  gender not specified, personal name
  *
  *  Personal names do not receive the honorific prefix "Mr." or "Ms.".
  */
 

Liquor shop

 static const char *const shkliquors[] = {
     /* Ukraine */
     "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
     /* Belarus */
     "Gomel",
     /* N. Russia */
     "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", "Narodnaja", "Kyzyl",
     /* Silezie */
     "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", "Brzeg",
     "Krnov", "Hradec Kralove",
     /* Schweiz */
     "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", "Flims",
     "Vals", "Schuls", "Zum Loch", 0
 };
 

Book shop

 static const char *const shkbooks[] = {
     /* Eire */
     "Skibbereen",  "Kanturk",   "Rath Luirc",     "Ennistymon",
     "Lahinch",     "Kinnegad",  "Lugnaquillia",   "Enniscorthy",
     "Gweebarra",   "Kittamagh", "Nenagh",         "Sneem",
     "Ballingeary", "Kilgarvan", "Cahersiveen",    "Glenbeigh",
     "Kilmihil",    "Kiltamagh", "Droichead Atha", "Inniscrone",
     "Clonegal",    "Lisnaskea", "Culdaff",        "Dunfanaghy",
     "Inishbofin",  "Kesh",      0
 };
 

Armor shop

 static const char *const shkarmors[] = {
     /* Turquie */
     "Demirci",    "Kalecik",    "Boyabai",    "Yildizeli", "Gaziantep",
     "Siirt",      "Akhalataki", "Tirebolu",   "Aksaray",   "Ermenak",
     "Iskenderun", "Kadirli",    "Siverek",    "Pervari",   "Malasgirt",
     "Bayburt",    "Ayancik",    "Zonguldak",  "Balya",     "Tefenni",
     "Artvin",     "Kars",       "Makharadze", "Malazgirt", "Midyat",
     "Birecik",    "Kirikkale",  "Alaca",      "Polatli",   "Nallihan",
     0
 };
 

Wand shop

 static const char *const shkwands[] = {
     /* Wales */
     "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach", "Rhaeader",
     "Llandrindod", "Llanfair-ym-muallt", "Y-Fenni", "Maesteg", "Rhydaman",
     "Beddgelert", "Curig", "Llanrwst", "Llanerchymedd", "Caergybi",
     /* Scotland */
     "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar", "Kerloch",
     "Beinn a Ghlo", "Drumnadrochit", "Morven", "Uist", "Storr",
     "Sgurr na Ciche", "Cannich", "Gairloch", "Kyleakin", "Dunvegan", 0
 };
 

Ring shop

 static const char *const shkrings[] = {
     /* Hollandse familienamen */
     "Feyfer",     "Flugi",         "Gheel",      "Havic",   "Haynin",
     "Hoboken",    "Imbyze",        "Juyn",       "Kinsky",  "Massis",
     "Matray",     "Moy",           "Olycan",     "Sadelin", "Svaving",
     "Tapper",     "Terwen",        "Wirix",      "Ypey",
     /* Skandinaviske navne */
     "Rastegaisa", "Varjag Njarga", "Kautekeino", "Abisko",  "Enontekis",
     "Rovaniemi",  "Avasaksa",      "Haparanda",  "Lulea",   "Gellivare",
     "Oeloe",      "Kajaani",       "Fauske",     0
 };
 

Food shop

 static const char *const shkfoods[] = {
     /* Indonesia */
     "Djasinga",    "Tjibarusa",   "Tjiwidej",      "Pengalengan",
     "Bandjar",     "Parbalingga", "Bojolali",      "Sarangan",
     "Ngebel",      "Djombang",    "Ardjawinangun", "Berbek",
     "Papar",       "Baliga",      "Tjisolok",      "Siboga",
     "Banjoewangi", "Trenggalek",  "Karangkobar",   "Njalindoeng",
     "Pasawahan",   "Pameunpeuk",  "Patjitan",      "Kediri",
     "Pemboeang",   "Tringanoe",   "Makin",         "Tipor",
     "Semai",       "Berhala",     "Tegal",         "Samoe",
     0
 };
 

Weapon shop

 static const char *const shkweapons[] = {
     /* Perigord */
     "Voulgezac",   "Rouffiac",   "Lerignac",   "Touverac",  "Guizengeard",
     "Melac",       "Neuvicq",    "Vanzac",     "Picq",      "Urignac",
     "Corignac",    "Fleac",      "Lonzac",     "Vergt",     "Queyssac",
     "Liorac",      "Echourgnac", "Cazelon",    "Eypau",     "Carignan",
     "Monbazillac", "Jonzac",     "Pons",       "Jumilhac",  "Fenouilledes",
     "Laguiolet",   "Saujon",     "Eymoutiers", "Eygurande", "Eauze",
     "Labouheyre",  0
 };
 

Tool shop

 static const char *const shktools[] = {
     /* Spmi */
     "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj",
     "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
     "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
     "Nosnehpets", "Stewe", "Renrut", "-Zlaw", "Nosalnef", "Rewuorb",
     "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah", "Corsh", "Aned",
     "Niknar", "Lapu", "Lechaim", "Rebrol-nek", "AlliWar Wickson", "Oguhmk",
 #ifdef OVERLAY
     "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
 #endif
 #ifdef WIN32
     "Lexa", "Niod",
 #endif
 #ifdef MAC
     "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
     "Tonbar", "Kivenhoug", "Llardom",
 #endif
 #ifdef AMIGA
     "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
     "Ivrajimsal",
 #endif
 #ifdef TOS
     "Nivram",
 #endif
 #ifdef OS2
     "Nedraawi-nav",
 #endif
 #ifdef VMS
     "Lez-tneg", "Ytnu-haled",
 #endif
     0
 };
 

Light shop

 static const char *const shklight[] = {
     /* Romania */
     "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
     "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
     "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
     /* Bulgaria */
     "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli", "Pernik",
     "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo", "Troyan",
     "Lovech", "Sliven", 0
 };
 

General shop

 static const char *const shkgeneral[] = {
     /* Suriname */
     "Hebiwerie",    "Possogroenoe", "Asidonhopo",   "Manlobbi",
     "Adjama",       "Pakka Pakka",  "Kabalebo",     "Wonotobo",
     "Akalapi",      "Sipaliwini",
     /* Greenland */
     "Annootok",     "Upernavik",    "Angmagssalik",
     /* N. Canada */
     "Aklavik",      "Inuvik",       "Tuktoyaktuk",  "Chicoutimi",
     "Ouiatchouane", "Chibougamau",  "Matagami",     "Kipawa",
     "Kinojevis",    "Abitibi",      "Maganasipi",
     /* Iceland */
     "Akureyri",     "Kopasker",     "Budereyri",    "Akranes",
     "Bordeyri",     "Holmavik",     0
 };
 

Health food shop

 static const char *const shkhealthfoods[] = {
     /* Tibet */
     "Ga'er",    "Zhangmu",   "Rikaze",   "Jiangji",     "Changdu",
     "Linzhi",   "Shigatse",  "Gyantse",  "Ganden",      "Tsurphu",
     "Lhasa",    "Tsedong",   "Drepung",
     /* Hippie names */
     "=Azura",   "=Blaze",    "=Breanna", "=Breezy",     "=Dharma",
     "=Feather", "=Jasmine",  "=Luna",    "=Melody",     "=Moonjava",
     "=Petal",   "=Rhiannon", "=Starla",  "=Tranquilla", "=Windsong",
     "=Zennia",  "=Zoe",      "=Zora",    0
 };
 

Shop types

 /*
  * To add new shop types, all that is necessary is to edit the shtypes[]
  * array.  See mkroom.h for the structure definition.  Typically, you'll
  * have to lower some or all of the probability fields in old entries to
  * free up some percentage for the new type.
  *
  * The placement type field is not yet used but will be in the near future.
  *
  * The iprobs array in each entry defines the probabilities for various kinds
  * of objects to be present in the given shop type.  You can associate with
  * each percentage either a generic object type (represented by one of the
  * *_CLASS macros) or a specific object (represented by an onames.h define).
  * In the latter case, prepend it with a unary minus so the code can know
  * (by testing the sign) whether to use mkobj() or mksobj().
  */
 const struct shclass shtypes[] = {
     { "general store",
       RANDOM_CLASS,
       42,
       D_SHOP,
       { { 100, RANDOM_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkgeneral },
     { "used armor dealership",
       ARMOR_CLASS,
       14,
       D_SHOP,
       { { 90, ARMOR_CLASS },
         { 10, WEAPON_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkarmors },
     { "second-hand bookstore",
       SCROLL_CLASS,
       10,
       D_SHOP,
       { { 90, SCROLL_CLASS },
         { 10, SPBOOK_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkbooks },
     { "liquor emporium",
       POTION_CLASS,
       10,
       D_SHOP,
       { { 100, POTION_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkliquors },
     { "antique weapons outlet",
       WEAPON_CLASS,
       5,
       D_SHOP,
       { { 90, WEAPON_CLASS },
         { 10, ARMOR_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkweapons },
     { "delicatessen",
       FOOD_CLASS,
       5,
       D_SHOP,
       { { 83, FOOD_CLASS },
         { 5, -POT_FRUIT_JUICE },
         { 4, -POT_BOOZE },
         { 5, -POT_WATER },
         { 3, -ICE_BOX },
         { 0, 0 } },
       shkfoods },
     { "jewelers",
       RING_CLASS,
       3,
       D_SHOP,
       { { 85, RING_CLASS },
         { 10, GEM_CLASS },
         { 5, AMULET_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkrings },
     { "quality apparel and accessories",
       WAND_CLASS,
       3,
       D_SHOP,
       { { 90, WAND_CLASS },
         { 5, -LEATHER_GLOVES },
         { 5, -ELVEN_CLOAK },
         { 0, 0 } },
       shkwands },
     { "hardware store",
       TOOL_CLASS,
       3,
       D_SHOP,
       { { 100, TOOL_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shktools },
     { "rare books",
       SPBOOK_CLASS,
       3,
       D_SHOP,
       { { 90, SPBOOK_CLASS },
         { 10, SCROLL_CLASS },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 },
         { 0, 0 } },
       shkbooks },
     { "health food store",
       FOOD_CLASS,
       2,
       D_SHOP,
       { { 70, VEGETARIAN_CLASS },
         { 20, -POT_FRUIT_JUICE },
         { 4, -POT_HEALING },
         { 3, -POT_FULL_HEALING },
         { 2, -SCR_FOOD_DETECTION },
         { 1, -LUMP_OF_ROYAL_JELLY } },
       shkhealthfoods },
     /* Shops below this point are "unique".  That is they must all have a
      * probability of zero.  They are only created via the special level
      * loader.
      */
     { "lighting store",
       TOOL_CLASS,
       0,
       D_SHOP,
       { { 30, -WAX_CANDLE },
         { 48, -TALLOW_CANDLE },
         { 5, -BRASS_LANTERN },
         { 9, -OIL_LAMP },
         { 3, -MAGIC_LAMP },
         { 5, -POT_OIL } },
       shklight },
     /* sentinel */
     { (char *) 0,
       0,
       0,
       0,
       { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
       0 }
 };
 

init_shop_selection

 #if 0
 /* validate shop probabilities; otherwise incorrect local changes could
    end up provoking infinite loops or wild subscripts fetching garbage */
 void
 init_shop_selection()
 {
     register int i, j, item_prob, shop_prob;
 
     for (shop_prob = 0, i = 0; i < SIZE(shtypes); i++) {
         shop_prob += shtypes[i].prob;
         for (item_prob = 0, j = 0; j < SIZE(shtypes[0].iprobs); j++)
             item_prob += shtypes[i].iprobs[j].iprob;
         if (item_prob != 100)
             panic("item probabilities total to %d for %s shops!",
                   item_prob, shtypes[i].name);
     }
     if (shop_prob != 100)
         panic("shop probabilities total to %d!", shop_prob);
 }
 #endif /*0*/
 

veggy_item

 /* decide whether an object or object type is considered vegetarian;
    for types, items which might go either way are assumed to be veggy */
 STATIC_OVL boolean
 veggy_item(obj, otyp)
 struct obj *obj;
 int otyp; /* used iff obj is null */
 {
     int corpsenm;
     char oclass;
 
     if (obj) {
         /* actual object; will check tin content and corpse species */
         otyp = (int) obj->otyp;
         oclass = obj->oclass;
         corpsenm = obj->corpsenm;
     } else {
         /* just a type; caller will have to handle tins and corpses */
         oclass = objects[otyp].oc_class;
         corpsenm = PM_LICHEN; /* veggy standin */
     }
 
     if (oclass == FOOD_CLASS) {
         if (objects[otyp].oc_material == VEGGY || otyp == EGG)
             return TRUE;
         if (otyp == TIN && corpsenm == NON_PM) /* implies obj is non-null */
             return (boolean) (obj->spe == 1); /* 0 = empty, 1 = spinach */
         if (otyp == TIN || otyp == CORPSE)
             return (boolean) (corpsenm >= LOW_PM
                               && vegetarian(&mons[corpsenm]));
     }
     return FALSE;
 }
 

shkveg

 STATIC_OVL int
 shkveg()
 {
     int i, j, maxprob, prob;
     char oclass = FOOD_CLASS;
     int ok[NUM_OBJECTS];
 
     j = maxprob = 0;
     ok[0] = 0; /* lint suppression */
     for (i = bases[(int) oclass]; i < NUM_OBJECTS; ++i) {
         if (objects[i].oc_class != oclass)
             break;
 
         if (veggy_item((struct obj *) 0, i)) {
             ok[j++] = i;
             maxprob += objects[i].oc_prob;
         }
     }
     if (maxprob < 1)
         panic("shkveg no veggy objects");
     prob = rnd(maxprob);
 
     j = 0;
     i = ok[0];
     while ((prob -= objects[i].oc_prob) > 0) {
         j++;
         i = ok[j];
     }
 
     if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
         panic("shkveg probtype error, oclass=%d i=%d", (int) oclass, i);
     return i;
 }
 

mkveggy_at

 /* make a random item for health food store */
 STATIC_OVL void
 mkveggy_at(sx, sy)
 int sx, sy;
 {
     struct obj *obj = mksobj_at(shkveg(), sx, sy, TRUE, TRUE);
 
     if (obj && obj->otyp == TIN)
         set_tin_variety(obj, HEALTHY_TIN);
     return;
 }
 

mkshobj_at

 /* make an object of the appropriate type for a shop square */
 STATIC_OVL void
 mkshobj_at(shp, sx, sy, mkspecl)
 const struct shclass *shp;
 int sx, sy;
 boolean mkspecl;
 {
     struct monst *mtmp;
     struct permonst *ptr;
     int atype;
 
     /* 3.6.0 tribute */
     if (mkspecl && (!strcmp(shp->name, "rare books")
                     || !strcmp(shp->name, "second-hand bookstore"))) {
         struct obj *novel = mksobj_at(SPE_NOVEL, sx, sy, FALSE, FALSE);
 
         if (novel)
             context.tribute.bookstock = TRUE;
         return;
     }
 
     if (rn2(100) < depth(&u.uz) && !MON_AT(sx, sy)
         && (ptr = mkclass(S_MIMIC, 0)) != 0
         && (mtmp = makemon(ptr, sx, sy, NO_MM_FLAGS)) != 0) {
         /* note: makemon will set the mimic symbol to a shop item */
         if (rn2(10) >= depth(&u.uz)) {
             mtmp->m_ap_type = M_AP_OBJECT;
             mtmp->mappearance = STRANGE_OBJECT;
         }
     } else {
         atype = get_shop_item((int) (shp - shtypes));
         if (atype == VEGETARIAN_CLASS)
             mkveggy_at(sx, sy);
         else if (atype < 0)
             (void) mksobj_at(-atype, sx, sy, TRUE, TRUE);
         else
             (void) mkobj_at(atype, sx, sy, TRUE);
     }
 }
 

nameshk

 /* extract a shopkeeper name for the given shop type */
 STATIC_OVL void
 nameshk(shk, nlp)
 struct monst *shk;
 const char *const *nlp;
 {
     int i, trycnt, names_avail;
     const char *shname = 0;
     struct monst *mtmp;
     int name_wanted;
     s_level *sptr;
 
     if (nlp == shkfoods && In_mines(&u.uz) && Role_if(PM_MONK)
         && (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
         /* special-case override for minetown food store for monks */
         nlp = shkhealthfoods;
     }
 
     if (nlp == shklight && In_mines(&u.uz) && (sptr = Is_special(&u.uz)) != 0
         && sptr->flags.town) {
         /* special-case minetown lighting shk */
         shname = "+Izchak";
         shk->female = FALSE;
     } else {
         /* We want variation from game to game, without needing the save
            and restore support which would be necessary for randomization;
            try not to make too many assumptions about time_t's internals;
            use ledger_no rather than depth to keep mine town distinct. */
         int nseed = (int) ((long) ubirthday / 257L);
 
         name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
         if (name_wanted < 0)
             name_wanted += (13 + 5);
         shk->female = name_wanted & 1;
 
         for (names_avail = 0; nlp[names_avail]; names_avail++)
             continue;
 
         for (trycnt = 0; trycnt < 50; trycnt++) {
             if (nlp == shktools) {
                 shname = shktools[rn2(names_avail)];
                 shk->female = 0; /* reversed below for '_' prefix */
             } else if (name_wanted < names_avail) {
                 shname = nlp[name_wanted];
             } else if ((i = rn2(names_avail)) != 0) {
                 shname = nlp[i - 1];
             } else if (nlp != shkgeneral) {
                 nlp = shkgeneral; /* try general names */
                 for (names_avail = 0; nlp[names_avail]; names_avail++)
                     continue;
                 continue; /* next `trycnt' iteration */
             } else {
                 shname = shk->female ? "-Lucrezia" : "+Dirk";
             }
             if (*shname == '_' || *shname == '-')
                 shk->female = 1;
             else if (*shname == '|' || *shname == '+')
                 shk->female = 0;
 
             /* is name already in use on this level? */
             for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                 if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk)
                     continue;
                 if (strcmp(ESHK(mtmp)->shknam, shname))
                     continue;
                 break;
             }
             if (!mtmp)
                 break; /* new name */
         }
     }
     (void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
     ESHK(shk)->shknam[PL_NSIZ - 1] = 0;
 }
 

neweshk

 void
 neweshk(mtmp)
 struct monst *mtmp;
 {
     if (!mtmp->mextra)
         mtmp->mextra = newmextra();
     if (!ESHK(mtmp))
         ESHK(mtmp) = (struct eshk *) alloc(sizeof(struct eshk));
     (void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk));
     ESHK(mtmp)->bill_p = (struct bill_x *) 0;
 }
 

free_eshk

 void
 free_eshk(mtmp)
 struct monst *mtmp;
 {
     if (mtmp->mextra && ESHK(mtmp)) {
         free((genericptr_t) ESHK(mtmp));
         ESHK(mtmp) = (struct eshk *) 0;
     }
     mtmp->isshk = 0;
 }
 

shkinit

 /* create a new shopkeeper in the given room */
 STATIC_OVL int
 shkinit(shp, sroom)
 const struct shclass *shp;
 struct mkroom *sroom;
 {
     register int sh, sx, sy;
     struct monst *shk;
     struct eshk *eshkp;
 
     /* place the shopkeeper in the given room */
     sh = sroom->fdoor;
     sx = doors[sh].x;
     sy = doors[sh].y;
 
     /* check that the shopkeeper placement is sane */
     if (sroom->irregular) {
         int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
         if (isok(sx - 1, sy) && !levl[sx - 1][sy].edge
             && (int) levl[sx - 1][sy].roomno == rmno)
             sx--;
         else if (isok(sx + 1, sy) && !levl[sx + 1][sy].edge
                  && (int) levl[sx + 1][sy].roomno == rmno)
             sx++;
         else if (isok(sx, sy - 1) && !levl[sx][sy - 1].edge
                  && (int) levl[sx][sy - 1].roomno == rmno)
             sy--;
         else if (isok(sx, sy + 1) && !levl[sx][sy + 1].edge
                  && (int) levl[sx][sy + 1].roomno == rmno)
             sx++;
         else
             goto shk_failed;
     } else if (sx == sroom->lx - 1)
         sx++;
     else if (sx == sroom->hx + 1)
         sx--;
     else if (sy == sroom->ly - 1)
         sy++;
     else if (sy == sroom->hy + 1)
         sy--;
     else {
     shk_failed:
 #ifdef DEBUG
         /* Said to happen sometimes, but I have never seen it. */
         /* Supposedly fixed by fdoor change in mklev.c */
         if (wizard) {
             register int j = sroom->doorct;
 
             pline("Where is shopdoor?");
             pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly, sroom->hx,
                   sroom->hy);
             pline("doormax=%d doorct=%d fdoor=%d", doorindex, sroom->doorct,
                   sh);
             while (j--) {
                 pline("door [%d,%d]", doors[sh].x, doors[sh].y);
                 sh++;
             }
             display_nhwindow(WIN_MESSAGE, FALSE);
         }
 #endif
         return -1;
     }
 
     if (MON_AT(sx, sy))
         (void) rloc(m_at(sx, sy), FALSE); /* insurance */
 
     /* now initialize the shopkeeper monster structure */
     if (!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK)))
         return -1;
     eshkp = ESHK(shk); /* makemon(...,MM_ESHK) allocates this */
     shk->isshk = shk->mpeaceful = 1;
     set_malign(shk);
     shk->msleeping = 0;
     shk->mtrapseen = ~0; /* we know all the traps already */
     eshkp->shoproom = (schar) ((sroom - rooms) + ROOMOFFSET);
     sroom->resident = shk;
     eshkp->shoptype = sroom->rtype;
     assign_level(&eshkp->shoplevel, &u.uz);
     eshkp->shd = doors[sh];
     eshkp->shk.x = sx;
     eshkp->shk.y = sy;
     eshkp->robbed = eshkp->credit = eshkp->debit = eshkp->loan = 0L;
     eshkp->following = eshkp->surcharge = eshkp->dismiss_kops = FALSE;
     eshkp->billct = eshkp->visitct = 0;
     eshkp->bill_p = (struct bill_x *) 0;
     eshkp->customer[0] = '\0';
     mkmonmoney(shk, 1000L + 30L * (long) rnd(100)); /* initial capital */
     if (shp->shknms == shkrings)
         (void) mongets(shk, TOUCHSTONE);
     nameshk(shk, shp->shknms);
 
     return sh;
 }
 

stock_room

 /* stock a newly-created room with objects */
 void
 stock_room(shp_indx, sroom)
 int shp_indx;
 register struct mkroom *sroom;
 {
     /*
      * Someday soon we'll dispatch on the shdist field of shclass to do
      * different placements in this routine. Currently it only supports
      * shop-style placement (all squares except a row nearest the first
      * door get objects).
      */
     int sx, sy, sh;
     int stockcount = 0, specialspot = 0;
     char buf[BUFSZ];
     int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
     const struct shclass *shp = &shtypes[shp_indx];
 
     /* first, try to place a shopkeeper in the room */
     if ((sh = shkinit(shp, sroom)) < 0)
         return;
 
     /* make sure no doorways without doors, and no trapped doors, in shops */
     sx = doors[sroom->fdoor].x;
     sy = doors[sroom->fdoor].y;
     if (levl[sx][sy].doormask == D_NODOOR) {
         levl[sx][sy].doormask = D_ISOPEN;
         newsym(sx, sy);
     }
     if (levl[sx][sy].typ == SDOOR) {
         cvt_sdoor_to_door(&levl[sx][sy]); /* .typ = DOOR */
         newsym(sx, sy);
     }
     if (levl[sx][sy].doormask & D_TRAPPED)
         levl[sx][sy].doormask = D_LOCKED;
 
     if (levl[sx][sy].doormask == D_LOCKED) {
         register int m = sx, n = sy;
 
         if (inside_shop(sx + 1, sy))
             m--;
         else if (inside_shop(sx - 1, sy))
             m++;
         if (inside_shop(sx, sy + 1))
             n--;
         else if (inside_shop(sx, sy - 1))
             n++;
         Sprintf(buf, "Closed for inventory");
         make_engr_at(m, n, buf, 0L, DUST);
     }
 
     if (context.tribute.enabled && !context.tribute.bookstock) {
         /*
          * Out of the number of spots where we're actually
          * going to put stuff, randomly single out one in particular.
          */
         for (sx = sroom->lx; sx <= sroom->hx; sx++)
             for (sy = sroom->ly; sy <= sroom->hy; sy++) {
                 if (sroom->irregular) {
                     if (levl[sx][sy].edge
                         || (int) levl[sx][sy].roomno != rmno
                         || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
                         continue;
                 } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
                            || (sx == sroom->hx && doors[sh].x == sx + 1)
                            || (sy == sroom->ly && doors[sh].y == sy - 1)
                            || (sy == sroom->hy && doors[sh].y == sy + 1))
                     continue;
                 stockcount++;
             }
         specialspot = rnd(stockcount);
         stockcount = 0;
     }
 
     for (sx = sroom->lx; sx <= sroom->hx; sx++)
         for (sy = sroom->ly; sy <= sroom->hy; sy++) {
             if (sroom->irregular) {
                 if (levl[sx][sy].edge
                     || (int) levl[sx][sy].roomno != rmno
                     || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
                     continue;
             } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
                        || (sx == sroom->hx && doors[sh].x == sx + 1)
                        || (sy == sroom->ly && doors[sh].y == sy - 1)
                        || (sy == sroom->hy && doors[sh].y == sy + 1))
                 continue;
             stockcount++;
             mkshobj_at(shp, sx, sy,
                        ((stockcount) && (stockcount == specialspot)));
         }
 
     /*
      * Special monster placements (if any) should go here: that way,
      * monsters will sit on top of objects and not the other way around.
      */
 
     level.flags.has_shop = TRUE;
 }
 

saleable

 /* does shkp's shop stock this item type? */
 boolean
 saleable(shkp, obj)
 struct monst *shkp;
 struct obj *obj;
 {
     int i, shp_indx = ESHK(shkp)->shoptype - SHOPBASE;
     const struct shclass *shp = &shtypes[shp_indx];
 
     if (shp->symb == RANDOM_CLASS)
         return TRUE;
     for (i = 0; i < SIZE(shtypes[0].iprobs) && shp->iprobs[i].iprob; i++) {
         /* pseudo-class needs special handling */
         if (shp->iprobs[i].itype == VEGETARIAN_CLASS) {
             if (veggy_item(obj, 0))
                 return TRUE;
         } else if ((shp->iprobs[i].itype < 0)
                        ? shp->iprobs[i].itype == -obj->otyp
                        : shp->iprobs[i].itype == obj->oclass)
             return TRUE;
     }
     /* not found */
     return FALSE;
 }
 

get_shop_item

 /* positive value: class; negative value: specific object type */
 int
 get_shop_item(type)
 int type;
 {
     const struct shclass *shp = shtypes + type;
     register int i, j;
 
     /* select an appropriate object type at random */
     for (j = rnd(100), i = 0; (j -= shp->iprobs[i].iprob) > 0; i++)
         continue;
 
     return shp->iprobs[i].itype;
 }
 

shkname

 const char *
 shkname(mtmp)
 struct monst *mtmp;
 {
     const char *shknm = ESHK(mtmp)->shknam;
 
     if (Hallucination && !program_state.gameover) {
         const char *const *nlp;
         int num;
 
         /* count the number of non-unique shop types;
            pick one randomly, ignoring shop generation probabilities;
            pick a name at random from that shop type's list */
         for (num = 0; num < SIZE(shtypes); num++)
             if (shtypes[num].prob == 0)
                 break;
         if (num > 0) {
             nlp = shtypes[rn2(num)].shknms;
             for (num = 0; nlp[num]; num++)
                 continue;
             if (num > 0)
                 shknm = nlp[rn2(num)];
         }
     }
 
     /* strip prefix if present */
     if (!letter(*shknm))
         ++shknm;
     return shknm;
 }
 

shkname_is_pname

 boolean
 shkname_is_pname(mtmp)
 struct monst *mtmp;
 {
     const char *shknm = ESHK(mtmp)->shknam;
 
     return (boolean) (*shknm == '-' || *shknm == '+' || *shknm == '=');
 }
 

is_izchak

 boolean
 is_izchak(shkp, override_hallucination)
 struct monst *shkp;
 boolean override_hallucination;
 {
     const char *shknm;
 
     if (Hallucination && !override_hallucination)
         return FALSE;
     if (!shkp->isshk)
         return FALSE;
     /* outside of town, Izchak becomes just an ordinary shopkeeper */
     if (!in_town(shkp->mx, shkp->my))
         return FALSE;
     shknm = ESHK(shkp)->shknam;
     /* skip "+" prefix */
     if (!letter(*shknm))
         ++shknm;
     return (boolean) !strcmp(shknm, "Izchak");
 }
 
 /*shknam.c*/