Source:NetHack 3.6.0/src/shknam.c

From NetHackWiki
(Redirected from Shknam.c)
Jump to: navigation, search

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

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

Shopkeeper names

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

Liquor shop

  1.  static const char *const shkliquors[] = {
  2.      /* Ukraine */
  3.      "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
  4.      /* Belarus */
  5.      "Gomel",
  6.      /* N. Russia */
  7.      "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", "Narodnaja", "Kyzyl",
  8.      /* Silezie */
  9.      "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", "Brzeg",
  10.      "Krnov", "Hradec Kralove",
  11.      /* Schweiz */
  12.      "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", "Flims",
  13.      "Vals", "Schuls", "Zum Loch", 0
  14.  };
  15.  

Book shop

  1.  static const char *const shkbooks[] = {
  2.      /* Eire */
  3.      "Skibbereen",  "Kanturk",   "Rath Luirc",     "Ennistymon",
  4.      "Lahinch",     "Kinnegad",  "Lugnaquillia",   "Enniscorthy",
  5.      "Gweebarra",   "Kittamagh", "Nenagh",         "Sneem",
  6.      "Ballingeary", "Kilgarvan", "Cahersiveen",    "Glenbeigh",
  7.      "Kilmihil",    "Kiltamagh", "Droichead Atha", "Inniscrone",
  8.      "Clonegal",    "Lisnaskea", "Culdaff",        "Dunfanaghy",
  9.      "Inishbofin",  "Kesh",      0
  10.  };
  11.  

Armor shop

  1.  static const char *const shkarmors[] = {
  2.      /* Turquie */
  3.      "Demirci",    "Kalecik",    "Boyabai",    "Yildizeli", "Gaziantep",
  4.      "Siirt",      "Akhalataki", "Tirebolu",   "Aksaray",   "Ermenak",
  5.      "Iskenderun", "Kadirli",    "Siverek",    "Pervari",   "Malasgirt",
  6.      "Bayburt",    "Ayancik",    "Zonguldak",  "Balya",     "Tefenni",
  7.      "Artvin",     "Kars",       "Makharadze", "Malazgirt", "Midyat",
  8.      "Birecik",    "Kirikkale",  "Alaca",      "Polatli",   "Nallihan",
  9.      0
  10.  };
  11.  

Wand shop

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

Ring shop

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

Food shop

  1.  static const char *const shkfoods[] = {
  2.      /* Indonesia */
  3.      "Djasinga",    "Tjibarusa",   "Tjiwidej",      "Pengalengan",
  4.      "Bandjar",     "Parbalingga", "Bojolali",      "Sarangan",
  5.      "Ngebel",      "Djombang",    "Ardjawinangun", "Berbek",
  6.      "Papar",       "Baliga",      "Tjisolok",      "Siboga",
  7.      "Banjoewangi", "Trenggalek",  "Karangkobar",   "Njalindoeng",
  8.      "Pasawahan",   "Pameunpeuk",  "Patjitan",      "Kediri",
  9.      "Pemboeang",   "Tringanoe",   "Makin",         "Tipor",
  10.      "Semai",       "Berhala",     "Tegal",         "Samoe",
  11.      0
  12.  };
  13.  

Weapon shop

  1.  static const char *const shkweapons[] = {
  2.      /* Perigord */
  3.      "Voulgezac",   "Rouffiac",   "Lerignac",   "Touverac",  "Guizengeard",
  4.      "Melac",       "Neuvicq",    "Vanzac",     "Picq",      "Urignac",
  5.      "Corignac",    "Fleac",      "Lonzac",     "Vergt",     "Queyssac",
  6.      "Liorac",      "Echourgnac", "Cazelon",    "Eypau",     "Carignan",
  7.      "Monbazillac", "Jonzac",     "Pons",       "Jumilhac",  "Fenouilledes",
  8.      "Laguiolet",   "Saujon",     "Eymoutiers", "Eygurande", "Eauze",
  9.      "Labouheyre",  0
  10.  };
  11.  

Tool shop

  1.  static const char *const shktools[] = {
  2.      /* Spmi */
  3.      "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj",
  4.      "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
  5.      "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
  6.      "Nosnehpets", "Stewe", "Renrut", "-Zlaw", "Nosalnef", "Rewuorb",
  7.      "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah", "Corsh", "Aned",
  8.      "Niknar", "Lapu", "Lechaim", "Rebrol-nek", "AlliWar Wickson", "Oguhmk",
  9.  #ifdef OVERLAY
  10.      "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
  11.  #endif
  12.  #ifdef WIN32
  13.      "Lexa", "Niod",
  14.  #endif
  15.  #ifdef MAC
  16.      "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
  17.      "Tonbar", "Kivenhoug", "Llardom",
  18.  #endif
  19.  #ifdef AMIGA
  20.      "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
  21.      "Ivrajimsal",
  22.  #endif
  23.  #ifdef TOS
  24.      "Nivram",
  25.  #endif
  26.  #ifdef OS2
  27.      "Nedraawi-nav",
  28.  #endif
  29.  #ifdef VMS
  30.      "Lez-tneg", "Ytnu-haled",
  31.  #endif
  32.      0
  33.  };
  34.  

Light shop

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

General shop

  1.  static const char *const shkgeneral[] = {
  2.      /* Suriname */
  3.      "Hebiwerie",    "Possogroenoe", "Asidonhopo",   "Manlobbi",
  4.      "Adjama",       "Pakka Pakka",  "Kabalebo",     "Wonotobo",
  5.      "Akalapi",      "Sipaliwini",
  6.      /* Greenland */
  7.      "Annootok",     "Upernavik",    "Angmagssalik",
  8.      /* N. Canada */
  9.      "Aklavik",      "Inuvik",       "Tuktoyaktuk",  "Chicoutimi",
  10.      "Ouiatchouane", "Chibougamau",  "Matagami",     "Kipawa",
  11.      "Kinojevis",    "Abitibi",      "Maganasipi",
  12.      /* Iceland */
  13.      "Akureyri",     "Kopasker",     "Budereyri",    "Akranes",
  14.      "Bordeyri",     "Holmavik",     0
  15.  };
  16.  

Health food shop

  1.  static const char *const shkhealthfoods[] = {
  2.      /* Tibet */
  3.      "Ga'er",    "Zhangmu",   "Rikaze",   "Jiangji",     "Changdu",
  4.      "Linzhi",   "Shigatse",  "Gyantse",  "Ganden",      "Tsurphu",
  5.      "Lhasa",    "Tsedong",   "Drepung",
  6.      /* Hippie names */
  7.      "=Azura",   "=Blaze",    "=Breanna", "=Breezy",     "=Dharma",
  8.      "=Feather", "=Jasmine",  "=Luna",    "=Melody",     "=Moonjava",
  9.      "=Petal",   "=Rhiannon", "=Starla",  "=Tranquilla", "=Windsong",
  10.      "=Zennia",  "=Zoe",      "=Zora",    0
  11.  };
  12.  

Shop types

  1.  /*
  2.   * To add new shop types, all that is necessary is to edit the shtypes[]
  3.   * array.  See mkroom.h for the structure definition.  Typically, you'll
  4.   * have to lower some or all of the probability fields in old entries to
  5.   * free up some percentage for the new type.
  6.   *
  7.   * The placement type field is not yet used but will be in the near future.
  8.   *
  9.   * The iprobs array in each entry defines the probabilities for various kinds
  10.   * of objects to be present in the given shop type.  You can associate with
  11.   * each percentage either a generic object type (represented by one of the
  12.   * *_CLASS macros) or a specific object (represented by an onames.h define).
  13.   * In the latter case, prepend it with a unary minus so the code can know
  14.   * (by testing the sign) whether to use mkobj() or mksobj().
  15.   */
  16.  const struct shclass shtypes[] = {
  17.      { "general store",
  18.        RANDOM_CLASS,
  19.        42,
  20.        D_SHOP,
  21.        { { 100, RANDOM_CLASS },
  22.          { 0, 0 },
  23.          { 0, 0 },
  24.          { 0, 0 },
  25.          { 0, 0 },
  26.          { 0, 0 } },
  27.        shkgeneral },
  28.      { "used armor dealership",
  29.        ARMOR_CLASS,
  30.        14,
  31.        D_SHOP,
  32.        { { 90, ARMOR_CLASS },
  33.          { 10, WEAPON_CLASS },
  34.          { 0, 0 },
  35.          { 0, 0 },
  36.          { 0, 0 },
  37.          { 0, 0 } },
  38.        shkarmors },
  39.      { "second-hand bookstore",
  40.        SCROLL_CLASS,
  41.        10,
  42.        D_SHOP,
  43.        { { 90, SCROLL_CLASS },
  44.          { 10, SPBOOK_CLASS },
  45.          { 0, 0 },
  46.          { 0, 0 },
  47.          { 0, 0 },
  48.          { 0, 0 } },
  49.        shkbooks },
  50.      { "liquor emporium",
  51.        POTION_CLASS,
  52.        10,
  53.        D_SHOP,
  54.        { { 100, POTION_CLASS },
  55.          { 0, 0 },
  56.          { 0, 0 },
  57.          { 0, 0 },
  58.          { 0, 0 },
  59.          { 0, 0 } },
  60.        shkliquors },
  61.      { "antique weapons outlet",
  62.        WEAPON_CLASS,
  63.        5,
  64.        D_SHOP,
  65.        { { 90, WEAPON_CLASS },
  66.          { 10, ARMOR_CLASS },
  67.          { 0, 0 },
  68.          { 0, 0 },
  69.          { 0, 0 },
  70.          { 0, 0 } },
  71.        shkweapons },
  72.      { "delicatessen",
  73.        FOOD_CLASS,
  74.        5,
  75.        D_SHOP,
  76.        { { 83, FOOD_CLASS },
  77.          { 5, -POT_FRUIT_JUICE },
  78.          { 4, -POT_BOOZE },
  79.          { 5, -POT_WATER },
  80.          { 3, -ICE_BOX },
  81.          { 0, 0 } },
  82.        shkfoods },
  83.      { "jewelers",
  84.        RING_CLASS,
  85.        3,
  86.        D_SHOP,
  87.        { { 85, RING_CLASS },
  88.          { 10, GEM_CLASS },
  89.          { 5, AMULET_CLASS },
  90.          { 0, 0 },
  91.          { 0, 0 },
  92.          { 0, 0 } },
  93.        shkrings },
  94.      { "quality apparel and accessories",
  95.        WAND_CLASS,
  96.        3,
  97.        D_SHOP,
  98.        { { 90, WAND_CLASS },
  99.          { 5, -LEATHER_GLOVES },
  100.          { 5, -ELVEN_CLOAK },
  101.          { 0, 0 } },
  102.        shkwands },
  103.      { "hardware store",
  104.        TOOL_CLASS,
  105.        3,
  106.        D_SHOP,
  107.        { { 100, TOOL_CLASS },
  108.          { 0, 0 },
  109.          { 0, 0 },
  110.          { 0, 0 },
  111.          { 0, 0 },
  112.          { 0, 0 } },
  113.        shktools },
  114.      { "rare books",
  115.        SPBOOK_CLASS,
  116.        3,
  117.        D_SHOP,
  118.        { { 90, SPBOOK_CLASS },
  119.          { 10, SCROLL_CLASS },
  120.          { 0, 0 },
  121.          { 0, 0 },
  122.          { 0, 0 },
  123.          { 0, 0 } },
  124.        shkbooks },
  125.      { "health food store",
  126.        FOOD_CLASS,
  127.        2,
  128.        D_SHOP,
  129.        { { 70, VEGETARIAN_CLASS },
  130.          { 20, -POT_FRUIT_JUICE },
  131.          { 4, -POT_HEALING },
  132.          { 3, -POT_FULL_HEALING },
  133.          { 2, -SCR_FOOD_DETECTION },
  134.          { 1, -LUMP_OF_ROYAL_JELLY } },
  135.        shkhealthfoods },
  136.      /* Shops below this point are "unique".  That is they must all have a
  137.       * probability of zero.  They are only created via the special level
  138.       * loader.
  139.       */
  140.      { "lighting store",
  141.        TOOL_CLASS,
  142.        0,
  143.        D_SHOP,
  144.        { { 30, -WAX_CANDLE },
  145.          { 48, -TALLOW_CANDLE },
  146.          { 5, -BRASS_LANTERN },
  147.          { 9, -OIL_LAMP },
  148.          { 3, -MAGIC_LAMP },
  149.          { 5, -POT_OIL } },
  150.        shklight },
  151.      /* sentinel */
  152.      { (char *) 0,
  153.        0,
  154.        0,
  155.        0,
  156.        { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  157.        0 }
  158.  };
  159.  

init_shop_selection

  1.  #if 0
  2.  /* validate shop probabilities; otherwise incorrect local changes could
  3.     end up provoking infinite loops or wild subscripts fetching garbage */
  4.  void
  5.  init_shop_selection()
  6.  {
  7.      register int i, j, item_prob, shop_prob;
  8.  
  9.      for (shop_prob = 0, i = 0; i < SIZE(shtypes); i++) {
  10.          shop_prob += shtypes[i].prob;
  11.          for (item_prob = 0, j = 0; j < SIZE(shtypes[0].iprobs); j++)
  12.              item_prob += shtypes[i].iprobs[j].iprob;
  13.          if (item_prob != 100)
  14.              panic("item probabilities total to %d for %s shops!",
  15.                    item_prob, shtypes[i].name);
  16.      }
  17.      if (shop_prob != 100)
  18.          panic("shop probabilities total to %d!", shop_prob);
  19.  }
  20.  #endif /*0*/
  21.  

veggy_item

  1.  /* decide whether an object or object type is considered vegetarian;
  2.     for types, items which might go either way are assumed to be veggy */
  3.  STATIC_OVL boolean
  4.  veggy_item(obj, otyp)
  5.  struct obj *obj;
  6.  int otyp; /* used iff obj is null */
  7.  {
  8.      int corpsenm;
  9.      char oclass;
  10.  
  11.      if (obj) {
  12.          /* actual object; will check tin content and corpse species */
  13.          otyp = (int) obj->otyp;
  14.          oclass = obj->oclass;
  15.          corpsenm = obj->corpsenm;
  16.      } else {
  17.          /* just a type; caller will have to handle tins and corpses */
  18.          oclass = objects[otyp].oc_class;
  19.          corpsenm = PM_LICHEN; /* veggy standin */
  20.      }
  21.  
  22.      if (oclass == FOOD_CLASS) {
  23.          if (objects[otyp].oc_material == VEGGY || otyp == EGG)
  24.              return TRUE;
  25.          if (otyp == TIN && corpsenm == NON_PM) /* implies obj is non-null */
  26.              return (boolean) (obj->spe == 1); /* 0 = empty, 1 = spinach */
  27.          if (otyp == TIN || otyp == CORPSE)
  28.              return (boolean) (corpsenm >= LOW_PM
  29.                                && vegetarian(&mons[corpsenm]));
  30.      }
  31.      return FALSE;
  32.  }
  33.  

shkveg

  1.  STATIC_OVL int
  2.  shkveg()
  3.  {
  4.      int i, j, maxprob, prob;
  5.      char oclass = FOOD_CLASS;
  6.      int ok[NUM_OBJECTS];
  7.  
  8.      j = maxprob = 0;
  9.      ok[0] = 0; /* lint suppression */
  10.      for (i = bases[(int) oclass]; i < NUM_OBJECTS; ++i) {
  11.          if (objects[i].oc_class != oclass)
  12.              break;
  13.  
  14.          if (veggy_item((struct obj *) 0, i)) {
  15.              ok[j++] = i;
  16.              maxprob += objects[i].oc_prob;
  17.          }
  18.      }
  19.      if (maxprob < 1)
  20.          panic("shkveg no veggy objects");
  21.      prob = rnd(maxprob);
  22.  
  23.      j = 0;
  24.      i = ok[0];
  25.      while ((prob -= objects[i].oc_prob) > 0) {
  26.          j++;
  27.          i = ok[j];
  28.      }
  29.  
  30.      if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
  31.          panic("shkveg probtype error, oclass=%d i=%d", (int) oclass, i);
  32.      return i;
  33.  }
  34.  

mkveggy_at

  1.  /* make a random item for health food store */
  2.  STATIC_OVL void
  3.  mkveggy_at(sx, sy)
  4.  int sx, sy;
  5.  {
  6.      struct obj *obj = mksobj_at(shkveg(), sx, sy, TRUE, TRUE);
  7.  
  8.      if (obj && obj->otyp == TIN)
  9.          set_tin_variety(obj, HEALTHY_TIN);
  10.      return;
  11.  }
  12.  

mkshobj_at

  1.  /* make an object of the appropriate type for a shop square */
  2.  STATIC_OVL void
  3.  mkshobj_at(shp, sx, sy, mkspecl)
  4.  const struct shclass *shp;
  5.  int sx, sy;
  6.  boolean mkspecl;
  7.  {
  8.      struct monst *mtmp;
  9.      struct permonst *ptr;
  10.      int atype;
  11.  
  12.      /* 3.6.0 tribute */
  13.      if (mkspecl && (!strcmp(shp->name, "rare books")
  14.                      || !strcmp(shp->name, "second-hand bookstore"))) {
  15.          struct obj *novel = mksobj_at(SPE_NOVEL, sx, sy, FALSE, FALSE);
  16.  
  17.          if (novel)
  18.              context.tribute.bookstock = TRUE;
  19.          return;
  20.      }
  21.  
  22.      if (rn2(100) < depth(&u.uz) && !MON_AT(sx, sy)
  23.          && (ptr = mkclass(S_MIMIC, 0)) != 0
  24.          && (mtmp = makemon(ptr, sx, sy, NO_MM_FLAGS)) != 0) {
  25.          /* note: makemon will set the mimic symbol to a shop item */
  26.          if (rn2(10) >= depth(&u.uz)) {
  27.              mtmp->m_ap_type = M_AP_OBJECT;
  28.              mtmp->mappearance = STRANGE_OBJECT;
  29.          }
  30.      } else {
  31.          atype = get_shop_item((int) (shp - shtypes));
  32.          if (atype == VEGETARIAN_CLASS)
  33.              mkveggy_at(sx, sy);
  34.          else if (atype < 0)
  35.              (void) mksobj_at(-atype, sx, sy, TRUE, TRUE);
  36.          else
  37.              (void) mkobj_at(atype, sx, sy, TRUE);
  38.      }
  39.  }
  40.  

nameshk

  1.  /* extract a shopkeeper name for the given shop type */
  2.  STATIC_OVL void
  3.  nameshk(shk, nlp)
  4.  struct monst *shk;
  5.  const char *const *nlp;
  6.  {
  7.      int i, trycnt, names_avail;
  8.      const char *shname = 0;
  9.      struct monst *mtmp;
  10.      int name_wanted;
  11.      s_level *sptr;
  12.  
  13.      if (nlp == shkfoods && In_mines(&u.uz) && Role_if(PM_MONK)
  14.          && (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
  15.          /* special-case override for minetown food store for monks */
  16.          nlp = shkhealthfoods;
  17.      }
  18.  
  19.      if (nlp == shklight && In_mines(&u.uz) && (sptr = Is_special(&u.uz)) != 0
  20.          && sptr->flags.town) {
  21.          /* special-case minetown lighting shk */
  22.          shname = "+Izchak";
  23.          shk->female = FALSE;
  24.      } else {
  25.          /* We want variation from game to game, without needing the save
  26.             and restore support which would be necessary for randomization;
  27.             try not to make too many assumptions about time_t's internals;
  28.             use ledger_no rather than depth to keep mine town distinct. */
  29.          int nseed = (int) ((long) ubirthday / 257L);
  30.  
  31.          name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
  32.          if (name_wanted < 0)
  33.              name_wanted += (13 + 5);
  34.          shk->female = name_wanted & 1;
  35.  
  36.          for (names_avail = 0; nlp[names_avail]; names_avail++)
  37.              continue;
  38.  
  39.          for (trycnt = 0; trycnt < 50; trycnt++) {
  40.              if (nlp == shktools) {
  41.                  shname = shktools[rn2(names_avail)];
  42.                  shk->female = 0; /* reversed below for '_' prefix */
  43.              } else if (name_wanted < names_avail) {
  44.                  shname = nlp[name_wanted];
  45.              } else if ((i = rn2(names_avail)) != 0) {
  46.                  shname = nlp[i - 1];
  47.              } else if (nlp != shkgeneral) {
  48.                  nlp = shkgeneral; /* try general names */
  49.                  for (names_avail = 0; nlp[names_avail]; names_avail++)
  50.                      continue;
  51.                  continue; /* next `trycnt' iteration */
  52.              } else {
  53.                  shname = shk->female ? "-Lucrezia" : "+Dirk";
  54.              }
  55.              if (*shname == '_' || *shname == '-')
  56.                  shk->female = 1;
  57.              else if (*shname == '|' || *shname == '+')
  58.                  shk->female = 0;
  59.  
  60.              /* is name already in use on this level? */
  61.              for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  62.                  if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk)
  63.                      continue;
  64.                  if (strcmp(ESHK(mtmp)->shknam, shname))
  65.                      continue;
  66.                  break;
  67.              }
  68.              if (!mtmp)
  69.                  break; /* new name */
  70.          }
  71.      }
  72.      (void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
  73.      ESHK(shk)->shknam[PL_NSIZ - 1] = 0;
  74.  }
  75.  

neweshk

  1.  void
  2.  neweshk(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      if (!mtmp->mextra)
  6.          mtmp->mextra = newmextra();
  7.      if (!ESHK(mtmp))
  8.          ESHK(mtmp) = (struct eshk *) alloc(sizeof(struct eshk));
  9.      (void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk));
  10.      ESHK(mtmp)->bill_p = (struct bill_x *) 0;
  11.  }
  12.  

free_eshk

  1.  void
  2.  free_eshk(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      if (mtmp->mextra && ESHK(mtmp)) {
  6.          free((genericptr_t) ESHK(mtmp));
  7.          ESHK(mtmp) = (struct eshk *) 0;
  8.      }
  9.      mtmp->isshk = 0;
  10.  }
  11.  

shkinit

  1.  /* create a new shopkeeper in the given room */
  2.  STATIC_OVL int
  3.  shkinit(shp, sroom)
  4.  const struct shclass *shp;
  5.  struct mkroom *sroom;
  6.  {
  7.      register int sh, sx, sy;
  8.      struct monst *shk;
  9.      struct eshk *eshkp;
  10.  
  11.      /* place the shopkeeper in the given room */
  12.      sh = sroom->fdoor;
  13.      sx = doors[sh].x;
  14.      sy = doors[sh].y;
  15.  
  16.      /* check that the shopkeeper placement is sane */
  17.      if (sroom->irregular) {
  18.          int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
  19.          if (isok(sx - 1, sy) && !levl[sx - 1][sy].edge
  20.              && (int) levl[sx - 1][sy].roomno == rmno)
  21.              sx--;
  22.          else if (isok(sx + 1, sy) && !levl[sx + 1][sy].edge
  23.                   && (int) levl[sx + 1][sy].roomno == rmno)
  24.              sx++;
  25.          else if (isok(sx, sy - 1) && !levl[sx][sy - 1].edge
  26.                   && (int) levl[sx][sy - 1].roomno == rmno)
  27.              sy--;
  28.          else if (isok(sx, sy + 1) && !levl[sx][sy + 1].edge
  29.                   && (int) levl[sx][sy + 1].roomno == rmno)
  30.              sx++;
  31.          else
  32.              goto shk_failed;
  33.      } else if (sx == sroom->lx - 1)
  34.          sx++;
  35.      else if (sx == sroom->hx + 1)
  36.          sx--;
  37.      else if (sy == sroom->ly - 1)
  38.          sy++;
  39.      else if (sy == sroom->hy + 1)
  40.          sy--;
  41.      else {
  42.      shk_failed:
  43.  #ifdef DEBUG
  44.          /* Said to happen sometimes, but I have never seen it. */
  45.          /* Supposedly fixed by fdoor change in mklev.c */
  46.          if (wizard) {
  47.              register int j = sroom->doorct;
  48.  
  49.              pline("Where is shopdoor?");
  50.              pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly, sroom->hx,
  51.                    sroom->hy);
  52.              pline("doormax=%d doorct=%d fdoor=%d", doorindex, sroom->doorct,
  53.                    sh);
  54.              while (j--) {
  55.                  pline("door [%d,%d]", doors[sh].x, doors[sh].y);
  56.                  sh++;
  57.              }
  58.              display_nhwindow(WIN_MESSAGE, FALSE);
  59.          }
  60.  #endif
  61.          return -1;
  62.      }
  63.  
  64.      if (MON_AT(sx, sy))
  65.          (void) rloc(m_at(sx, sy), FALSE); /* insurance */
  66.  
  67.      /* now initialize the shopkeeper monster structure */
  68.      if (!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK)))
  69.          return -1;
  70.      eshkp = ESHK(shk); /* makemon(...,MM_ESHK) allocates this */
  71.      shk->isshk = shk->mpeaceful = 1;
  72.      set_malign(shk);
  73.      shk->msleeping = 0;
  74.      shk->mtrapseen = ~0; /* we know all the traps already */
  75.      eshkp->shoproom = (schar) ((sroom - rooms) + ROOMOFFSET);
  76.      sroom->resident = shk;
  77.      eshkp->shoptype = sroom->rtype;
  78.      assign_level(&eshkp->shoplevel, &u.uz);
  79.      eshkp->shd = doors[sh];
  80.      eshkp->shk.x = sx;
  81.      eshkp->shk.y = sy;
  82.      eshkp->robbed = eshkp->credit = eshkp->debit = eshkp->loan = 0L;
  83.      eshkp->following = eshkp->surcharge = eshkp->dismiss_kops = FALSE;
  84.      eshkp->billct = eshkp->visitct = 0;
  85.      eshkp->bill_p = (struct bill_x *) 0;
  86.      eshkp->customer[0] = '\0';
  87.      mkmonmoney(shk, 1000L + 30L * (long) rnd(100)); /* initial capital */
  88.      if (shp->shknms == shkrings)
  89.          (void) mongets(shk, TOUCHSTONE);
  90.      nameshk(shk, shp->shknms);
  91.  
  92.      return sh;
  93.  }
  94.  

stock_room

  1.  /* stock a newly-created room with objects */
  2.  void
  3.  stock_room(shp_indx, sroom)
  4.  int shp_indx;
  5.  register struct mkroom *sroom;
  6.  {
  7.      /*
  8.       * Someday soon we'll dispatch on the shdist field of shclass to do
  9.       * different placements in this routine. Currently it only supports
  10.       * shop-style placement (all squares except a row nearest the first
  11.       * door get objects).
  12.       */
  13.      int sx, sy, sh;
  14.      int stockcount = 0, specialspot = 0;
  15.      char buf[BUFSZ];
  16.      int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
  17.      const struct shclass *shp = &shtypes[shp_indx];
  18.  
  19.      /* first, try to place a shopkeeper in the room */
  20.      if ((sh = shkinit(shp, sroom)) < 0)
  21.          return;
  22.  
  23.      /* make sure no doorways without doors, and no trapped doors, in shops */
  24.      sx = doors[sroom->fdoor].x;
  25.      sy = doors[sroom->fdoor].y;
  26.      if (levl[sx][sy].doormask == D_NODOOR) {
  27.          levl[sx][sy].doormask = D_ISOPEN;
  28.          newsym(sx, sy);
  29.      }
  30.      if (levl[sx][sy].typ == SDOOR) {
  31.          cvt_sdoor_to_door(&levl[sx][sy]); /* .typ = DOOR */
  32.          newsym(sx, sy);
  33.      }
  34.      if (levl[sx][sy].doormask & D_TRAPPED)
  35.          levl[sx][sy].doormask = D_LOCKED;
  36.  
  37.      if (levl[sx][sy].doormask == D_LOCKED) {
  38.          register int m = sx, n = sy;
  39.  
  40.          if (inside_shop(sx + 1, sy))
  41.              m--;
  42.          else if (inside_shop(sx - 1, sy))
  43.              m++;
  44.          if (inside_shop(sx, sy + 1))
  45.              n--;
  46.          else if (inside_shop(sx, sy - 1))
  47.              n++;
  48.          Sprintf(buf, "Closed for inventory");
  49.          make_engr_at(m, n, buf, 0L, DUST);
  50.      }
  51.  
  52.      if (context.tribute.enabled && !context.tribute.bookstock) {
  53.          /*
  54.           * Out of the number of spots where we're actually
  55.           * going to put stuff, randomly single out one in particular.
  56.           */
  57.          for (sx = sroom->lx; sx <= sroom->hx; sx++)
  58.              for (sy = sroom->ly; sy <= sroom->hy; sy++) {
  59.                  if (sroom->irregular) {
  60.                      if (levl[sx][sy].edge
  61.                          || (int) levl[sx][sy].roomno != rmno
  62.                          || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
  63.                          continue;
  64.                  } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
  65.                             || (sx == sroom->hx && doors[sh].x == sx + 1)
  66.                             || (sy == sroom->ly && doors[sh].y == sy - 1)
  67.                             || (sy == sroom->hy && doors[sh].y == sy + 1))
  68.                      continue;
  69.                  stockcount++;
  70.              }
  71.          specialspot = rnd(stockcount);
  72.          stockcount = 0;
  73.      }
  74.  
  75.      for (sx = sroom->lx; sx <= sroom->hx; sx++)
  76.          for (sy = sroom->ly; sy <= sroom->hy; sy++) {
  77.              if (sroom->irregular) {
  78.                  if (levl[sx][sy].edge
  79.                      || (int) levl[sx][sy].roomno != rmno
  80.                      || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
  81.                      continue;
  82.              } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
  83.                         || (sx == sroom->hx && doors[sh].x == sx + 1)
  84.                         || (sy == sroom->ly && doors[sh].y == sy - 1)
  85.                         || (sy == sroom->hy && doors[sh].y == sy + 1))
  86.                  continue;
  87.              stockcount++;
  88.              mkshobj_at(shp, sx, sy,
  89.                         ((stockcount) && (stockcount == specialspot)));
  90.          }
  91.  
  92.      /*
  93.       * Special monster placements (if any) should go here: that way,
  94.       * monsters will sit on top of objects and not the other way around.
  95.       */
  96.  
  97.      level.flags.has_shop = TRUE;
  98.  }
  99.  

saleable

  1.  /* does shkp's shop stock this item type? */
  2.  boolean
  3.  saleable(shkp, obj)
  4.  struct monst *shkp;
  5.  struct obj *obj;
  6.  {
  7.      int i, shp_indx = ESHK(shkp)->shoptype - SHOPBASE;
  8.      const struct shclass *shp = &shtypes[shp_indx];
  9.  
  10.      if (shp->symb == RANDOM_CLASS)
  11.          return TRUE;
  12.      for (i = 0; i < SIZE(shtypes[0].iprobs) && shp->iprobs[i].iprob; i++) {
  13.          /* pseudo-class needs special handling */
  14.          if (shp->iprobs[i].itype == VEGETARIAN_CLASS) {
  15.              if (veggy_item(obj, 0))
  16.                  return TRUE;
  17.          } else if ((shp->iprobs[i].itype < 0)
  18.                         ? shp->iprobs[i].itype == -obj->otyp
  19.                         : shp->iprobs[i].itype == obj->oclass)
  20.              return TRUE;
  21.      }
  22.      /* not found */
  23.      return FALSE;
  24.  }
  25.  

get_shop_item

  1.  /* positive value: class; negative value: specific object type */
  2.  int
  3.  get_shop_item(type)
  4.  int type;
  5.  {
  6.      const struct shclass *shp = shtypes + type;
  7.      register int i, j;
  8.  
  9.      /* select an appropriate object type at random */
  10.      for (j = rnd(100), i = 0; (j -= shp->iprobs[i].iprob) > 0; i++)
  11.          continue;
  12.  
  13.      return shp->iprobs[i].itype;
  14.  }
  15.  

shkname

  1.  const char *
  2.  shkname(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      const char *shknm = ESHK(mtmp)->shknam;
  6.  
  7.      if (Hallucination && !program_state.gameover) {
  8.          const char *const *nlp;
  9.          int num;
  10.  
  11.          /* count the number of non-unique shop types;
  12.             pick one randomly, ignoring shop generation probabilities;
  13.             pick a name at random from that shop type's list */
  14.          for (num = 0; num < SIZE(shtypes); num++)
  15.              if (shtypes[num].prob == 0)
  16.                  break;
  17.          if (num > 0) {
  18.              nlp = shtypes[rn2(num)].shknms;
  19.              for (num = 0; nlp[num]; num++)
  20.                  continue;
  21.              if (num > 0)
  22.                  shknm = nlp[rn2(num)];
  23.          }
  24.      }
  25.  
  26.      /* strip prefix if present */
  27.      if (!letter(*shknm))
  28.          ++shknm;
  29.      return shknm;
  30.  }
  31.  

shkname_is_pname

  1.  boolean
  2.  shkname_is_pname(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      const char *shknm = ESHK(mtmp)->shknam;
  6.  
  7.      return (boolean) (*shknm == '-' || *shknm == '+' || *shknm == '=');
  8.  }
  9.  

is_izchak

  1.  boolean
  2.  is_izchak(shkp, override_hallucination)
  3.  struct monst *shkp;
  4.  boolean override_hallucination;
  5.  {
  6.      const char *shknm;
  7.  
  8.      if (Hallucination && !override_hallucination)
  9.          return FALSE;
  10.      if (!shkp->isshk)
  11.          return FALSE;
  12.      /* outside of town, Izchak becomes just an ordinary shopkeeper */
  13.      if (!in_town(shkp->mx, shkp->my))
  14.          return FALSE;
  15.      shknm = ESHK(shkp)->shknam;
  16.      /* skip "+" prefix */
  17.      if (!letter(*shknm))
  18.          ++shknm;
  19.      return (boolean) !strcmp(shknm, "Izchak");
  20.  }
  21.  
  22.  /*shknam.c*/