OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / shknam.c
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
19 /*
20  *  Name prefix codes:
21  *      dash          -  female, personal name
22  *      underscore    _  female, general name
23  *      plus          +  male, personal name
24  *      vertical bar  |  male, general name (implied for most of shktools)
25  *      equals        =  gender not specified, personal name
26  *
27  *  Personal names do not receive the honorific prefix "Mr." or "Ms.".
28  */
29
30 static const char *const shkliquors[] = {
31     /* Ukraine */
32     "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
33     /* Belarus */
34     "Gomel",
35     /* N. Russia */
36     "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", "Narodnaja", "Kyzyl",
37     /* Silezie */
38     "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", "Brzeg",
39     "Krnov", "Hradec Kralove",
40     /* Schweiz */
41     "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", "Flims",
42     "Vals", "Schuls", "Zum Loch", 0
43 };
44
45 static const char *const shkbooks[] = {
46     /* Eire */
47     "Skibbereen",  "Kanturk",   "Rath Luirc",     "Ennistymon",
48     "Lahinch",     "Kinnegad",  "Lugnaquillia",   "Enniscorthy",
49     "Gweebarra",   "Kittamagh", "Nenagh",         "Sneem",
50     "Ballingeary", "Kilgarvan", "Cahersiveen",    "Glenbeigh",
51     "Kilmihil",    "Kiltamagh", "Droichead Atha", "Inniscrone",
52     "Clonegal",    "Lisnaskea", "Culdaff",        "Dunfanaghy",
53     "Inishbofin",  "Kesh",      0
54 };
55
56 static const char *const shkarmors[] = {
57     /* Turquie */
58     "Demirci",    "Kalecik",    "Boyabai",    "Yildizeli", "Gaziantep",
59     "Siirt",      "Akhalataki", "Tirebolu",   "Aksaray",   "Ermenak",
60     "Iskenderun", "Kadirli",    "Siverek",    "Pervari",   "Malasgirt",
61     "Bayburt",    "Ayancik",    "Zonguldak",  "Balya",     "Tefenni",
62     "Artvin",     "Kars",       "Makharadze", "Malazgirt", "Midyat",
63     "Birecik",    "Kirikkale",  "Alaca",      "Polatli",   "Nallihan",
64     0
65 };
66
67 static const char *const shkwands[] = {
68     /* Wales */
69     "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach", "Rhaeader",
70     "Llandrindod", "Llanfair-ym-muallt", "Y-Fenni", "Maesteg", "Rhydaman",
71     "Beddgelert", "Curig", "Llanrwst", "Llanerchymedd", "Caergybi",
72     /* Scotland */
73     "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar", "Kerloch",
74     "Beinn a Ghlo", "Drumnadrochit", "Morven", "Uist", "Storr",
75     "Sgurr na Ciche", "Cannich", "Gairloch", "Kyleakin", "Dunvegan", 0
76 };
77
78 static const char *const shkrings[] = {
79     /* Hollandse familienamen */
80     "Feyfer",     "Flugi",         "Gheel",      "Havic",   "Haynin",
81     "Hoboken",    "Imbyze",        "Juyn",       "Kinsky",  "Massis",
82     "Matray",     "Moy",           "Olycan",     "Sadelin", "Svaving",
83     "Tapper",     "Terwen",        "Wirix",      "Ypey",
84     /* Skandinaviske navne */
85     "Rastegaisa", "Varjag Njarga", "Kautekeino", "Abisko",  "Enontekis",
86     "Rovaniemi",  "Avasaksa",      "Haparanda",  "Lulea",   "Gellivare",
87     "Oeloe",      "Kajaani",       "Fauske",     0
88 };
89
90 static const char *const shkfoods[] = {
91     /* Indonesia */
92     "Djasinga",    "Tjibarusa",   "Tjiwidej",      "Pengalengan",
93     "Bandjar",     "Parbalingga", "Bojolali",      "Sarangan",
94     "Ngebel",      "Djombang",    "Ardjawinangun", "Berbek",
95     "Papar",       "Baliga",      "Tjisolok",      "Siboga",
96     "Banjoewangi", "Trenggalek",  "Karangkobar",   "Njalindoeng",
97     "Pasawahan",   "Pameunpeuk",  "Patjitan",      "Kediri",
98     "Pemboeang",   "Tringanoe",   "Makin",         "Tipor",
99     "Semai",       "Berhala",     "Tegal",         "Samoe",
100     0
101 };
102
103 static const char *const shkweapons[] = {
104     /* Perigord */
105     "Voulgezac",   "Rouffiac",   "Lerignac",   "Touverac",  "Guizengeard",
106     "Melac",       "Neuvicq",    "Vanzac",     "Picq",      "Urignac",
107     "Corignac",    "Fleac",      "Lonzac",     "Vergt",     "Queyssac",
108     "Liorac",      "Echourgnac", "Cazelon",    "Eypau",     "Carignan",
109     "Monbazillac", "Jonzac",     "Pons",       "Jumilhac",  "Fenouilledes",
110     "Laguiolet",   "Saujon",     "Eymoutiers", "Eygurande", "Eauze",
111     "Labouheyre",  0
112 };
113
114 static const char *const shktools[] = {
115     /* Spmi */
116     "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj",
117     "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
118     "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
119     "Nosnehpets", "Stewe", "Renrut", "-Zlaw", "Nosalnef", "Rewuorb",
120     "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah", "Corsh", "Aned",
121     "Niknar", "Lapu", "Lechaim", "Rebrol-nek", "AlliWar Wickson", "Oguhmk",
122 #ifdef OVERLAY
123     "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
124 #endif
125 #ifdef WIN32
126     "Lexa", "Niod",
127 #endif
128 #ifdef MAC
129     "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
130     "Tonbar", "Kivenhoug", "Llardom",
131 #endif
132 #ifdef AMIGA
133     "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
134     "Ivrajimsal",
135 #endif
136 #ifdef TOS
137     "Nivram",
138 #endif
139 #ifdef OS2
140     "Nedraawi-nav",
141 #endif
142 #ifdef VMS
143     "Lez-tneg", "Ytnu-haled",
144 #endif
145     0
146 };
147
148 static const char *const shklight[] = {
149     /* Romania */
150     "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
151     "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
152     "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
153     /* Bulgaria */
154     "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli", "Pernik",
155     "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo", "Troyan",
156     "Lovech", "Sliven", 0
157 };
158
159 static const char *const shkgeneral[] = {
160     /* Suriname */
161     "Hebiwerie",    "Possogroenoe", "Asidonhopo",   "Manlobbi",
162     "Adjama",       "Pakka Pakka",  "Kabalebo",     "Wonotobo",
163     "Akalapi",      "Sipaliwini",
164     /* Greenland */
165     "Annootok",     "Upernavik",    "Angmagssalik",
166     /* N. Canada */
167     "Aklavik",      "Inuvik",       "Tuktoyaktuk",  "Chicoutimi",
168     "Ouiatchouane", "Chibougamau",  "Matagami",     "Kipawa",
169     "Kinojevis",    "Abitibi",      "Maganasipi",
170     /* Iceland */
171     "Akureyri",     "Kopasker",     "Budereyri",    "Akranes",
172     "Bordeyri",     "Holmavik",     0
173 };
174
175 static const char *const shkhealthfoods[] = {
176     /* Tibet */
177     "Ga'er",    "Zhangmu",   "Rikaze",   "Jiangji",     "Changdu",
178     "Linzhi",   "Shigatse",  "Gyantse",  "Ganden",      "Tsurphu",
179     "Lhasa",    "Tsedong",   "Drepung",
180     /* Hippie names */
181     "=Azura",   "=Blaze",    "=Breanna", "=Breezy",     "=Dharma",
182     "=Feather", "=Jasmine",  "=Luna",    "=Melody",     "=Moonjava",
183     "=Petal",   "=Rhiannon", "=Starla",  "=Tranquilla", "=Windsong",
184     "=Zennia",  "=Zoe",      "=Zora",    0
185 };
186
187 /*
188  * To add new shop types, all that is necessary is to edit the shtypes[]
189  * array.  See mkroom.h for the structure definition.  Typically, you'll
190  * have to lower some or all of the probability fields in old entries to
191  * free up some percentage for the new type.
192  *
193  * The placement type field is not yet used but will be in the near future.
194  *
195  * The iprobs array in each entry defines the probabilities for various kinds
196  * of objects to be present in the given shop type.  You can associate with
197  * each percentage either a generic object type (represented by one of the
198  * *_CLASS macros) or a specific object (represented by an onames.h define).
199  * In the latter case, prepend it with a unary minus so the code can know
200  * (by testing the sign) whether to use mkobj() or mksobj().
201  */
202 const struct shclass shtypes[] = {
203     { "general store",
204       RANDOM_CLASS,
205       42,
206       D_SHOP,
207       { { 100, RANDOM_CLASS },
208         { 0, 0 },
209         { 0, 0 },
210         { 0, 0 },
211         { 0, 0 },
212         { 0, 0 } },
213       shkgeneral },
214     { "used armor dealership",
215       ARMOR_CLASS,
216       14,
217       D_SHOP,
218       { { 90, ARMOR_CLASS },
219         { 10, WEAPON_CLASS },
220         { 0, 0 },
221         { 0, 0 },
222         { 0, 0 },
223         { 0, 0 } },
224       shkarmors },
225     { "second-hand bookstore",
226       SCROLL_CLASS,
227       10,
228       D_SHOP,
229       { { 90, SCROLL_CLASS },
230         { 10, SPBOOK_CLASS },
231         { 0, 0 },
232         { 0, 0 },
233         { 0, 0 },
234         { 0, 0 } },
235       shkbooks },
236     { "liquor emporium",
237       POTION_CLASS,
238       10,
239       D_SHOP,
240       { { 100, POTION_CLASS },
241         { 0, 0 },
242         { 0, 0 },
243         { 0, 0 },
244         { 0, 0 },
245         { 0, 0 } },
246       shkliquors },
247     { "antique weapons outlet",
248       WEAPON_CLASS,
249       5,
250       D_SHOP,
251       { { 90, WEAPON_CLASS },
252         { 10, ARMOR_CLASS },
253         { 0, 0 },
254         { 0, 0 },
255         { 0, 0 },
256         { 0, 0 } },
257       shkweapons },
258     { "delicatessen",
259       FOOD_CLASS,
260       5,
261       D_SHOP,
262       { { 83, FOOD_CLASS },
263         { 5, -POT_FRUIT_JUICE },
264         { 4, -POT_BOOZE },
265         { 5, -POT_WATER },
266         { 3, -ICE_BOX },
267         { 0, 0 } },
268       shkfoods },
269     { "jewelers",
270       RING_CLASS,
271       3,
272       D_SHOP,
273       { { 85, RING_CLASS },
274         { 10, GEM_CLASS },
275         { 5, AMULET_CLASS },
276         { 0, 0 },
277         { 0, 0 },
278         { 0, 0 } },
279       shkrings },
280     { "quality apparel and accessories",
281       WAND_CLASS,
282       3,
283       D_SHOP,
284       { { 90, WAND_CLASS },
285         { 5, -LEATHER_GLOVES },
286         { 5, -ELVEN_CLOAK },
287         { 0, 0 } },
288       shkwands },
289     { "hardware store",
290       TOOL_CLASS,
291       3,
292       D_SHOP,
293       { { 100, TOOL_CLASS },
294         { 0, 0 },
295         { 0, 0 },
296         { 0, 0 },
297         { 0, 0 },
298         { 0, 0 } },
299       shktools },
300     { "rare books",
301       SPBOOK_CLASS,
302       3,
303       D_SHOP,
304       { { 90, SPBOOK_CLASS },
305         { 10, SCROLL_CLASS },
306         { 0, 0 },
307         { 0, 0 },
308         { 0, 0 },
309         { 0, 0 } },
310       shkbooks },
311     { "health food store",
312       FOOD_CLASS,
313       2,
314       D_SHOP,
315       { { 70, VEGETARIAN_CLASS },
316         { 20, -POT_FRUIT_JUICE },
317         { 4, -POT_HEALING },
318         { 3, -POT_FULL_HEALING },
319         { 2, -SCR_FOOD_DETECTION },
320         { 1, -LUMP_OF_ROYAL_JELLY } },
321       shkhealthfoods },
322     /* Shops below this point are "unique".  That is they must all have a
323      * probability of zero.  They are only created via the special level
324      * loader.
325      */
326     { "lighting store",
327       TOOL_CLASS,
328       0,
329       D_SHOP,
330       { { 30, -WAX_CANDLE },
331         { 48, -TALLOW_CANDLE },
332         { 5, -BRASS_LANTERN },
333         { 9, -OIL_LAMP },
334         { 3, -MAGIC_LAMP },
335         { 5, -POT_OIL } },
336       shklight },
337     /* sentinel */
338     { (char *) 0,
339       0,
340       0,
341       0,
342       { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
343       0 }
344 };
345
346 #if 0
347 /* validate shop probabilities; otherwise incorrect local changes could
348    end up provoking infinite loops or wild subscripts fetching garbage */
349 void
350 init_shop_selection()
351 {
352     register int i, j, item_prob, shop_prob;
353
354     for (shop_prob = 0, i = 0; i < SIZE(shtypes); i++) {
355         shop_prob += shtypes[i].prob;
356         for (item_prob = 0, j = 0; j < SIZE(shtypes[0].iprobs); j++)
357             item_prob += shtypes[i].iprobs[j].iprob;
358         if (item_prob != 100)
359             panic("item probabilities total to %d for %s shops!",
360                   item_prob, shtypes[i].name);
361     }
362     if (shop_prob != 100)
363         panic("shop probabilities total to %d!", shop_prob);
364 }
365 #endif /*0*/
366
367 /* decide whether an object or object type is considered vegetarian;
368    for types, items which might go either way are assumed to be veggy */
369 STATIC_OVL boolean
370 veggy_item(obj, otyp)
371 struct obj *obj;
372 int otyp; /* used iff obj is null */
373 {
374     int corpsenm;
375     char oclass;
376
377     if (obj) {
378         /* actual object; will check tin content and corpse species */
379         otyp = (int) obj->otyp;
380         oclass = obj->oclass;
381         corpsenm = obj->corpsenm;
382     } else {
383         /* just a type; caller will have to handle tins and corpses */
384         oclass = objects[otyp].oc_class;
385         corpsenm = PM_LICHEN; /* veggy standin */
386     }
387
388     if (oclass == FOOD_CLASS) {
389         if (objects[otyp].oc_material == VEGGY || otyp == EGG)
390             return TRUE;
391         if (otyp == TIN && corpsenm == NON_PM) /* implies obj is non-null */
392             return (boolean) (obj->spe == 1); /* 0 = empty, 1 = spinach */
393         if (otyp == TIN || otyp == CORPSE)
394             return (boolean) (corpsenm >= LOW_PM
395                               && vegetarian(&mons[corpsenm]));
396     }
397     return FALSE;
398 }
399
400 STATIC_OVL int
401 shkveg()
402 {
403     int i, j, maxprob, prob;
404     char oclass = FOOD_CLASS;
405     int ok[NUM_OBJECTS];
406
407     j = maxprob = 0;
408     ok[0] = 0; /* lint suppression */
409     for (i = bases[(int) oclass]; i < NUM_OBJECTS; ++i) {
410         if (objects[i].oc_class != oclass)
411             break;
412
413         if (veggy_item((struct obj *) 0, i)) {
414             ok[j++] = i;
415             maxprob += objects[i].oc_prob;
416         }
417     }
418     if (maxprob < 1)
419         panic("shkveg no veggy objects");
420     prob = rnd(maxprob);
421
422     j = 0;
423     i = ok[0];
424     while ((prob -= objects[i].oc_prob) > 0) {
425         j++;
426         i = ok[j];
427     }
428
429     if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
430         panic("shkveg probtype error, oclass=%d i=%d", (int) oclass, i);
431     return i;
432 }
433
434 /* make a random item for health food store */
435 STATIC_OVL void
436 mkveggy_at(sx, sy)
437 int sx, sy;
438 {
439     struct obj *obj = mksobj_at(shkveg(), sx, sy, TRUE, TRUE);
440
441     if (obj && obj->otyp == TIN)
442         set_tin_variety(obj, HEALTHY_TIN);
443     return;
444 }
445
446 /* make an object of the appropriate type for a shop square */
447 STATIC_OVL void
448 mkshobj_at(shp, sx, sy, mkspecl)
449 const struct shclass *shp;
450 int sx, sy;
451 boolean mkspecl;
452 {
453     struct monst *mtmp;
454     struct permonst *ptr;
455     int atype;
456
457     /* 3.6.0 tribute */
458     if (mkspecl && (!strcmp(shp->name, "rare books")
459                     || !strcmp(shp->name, "second-hand bookstore"))) {
460         struct obj *novel = mksobj_at(SPE_NOVEL, sx, sy, FALSE, FALSE);
461
462         if (novel)
463             context.tribute.bookstock = TRUE;
464         return;
465     }
466
467     if (rn2(100) < depth(&u.uz) && !MON_AT(sx, sy)
468         && (ptr = mkclass(S_MIMIC, 0)) != 0
469         && (mtmp = makemon(ptr, sx, sy, NO_MM_FLAGS)) != 0) {
470         /* note: makemon will set the mimic symbol to a shop item */
471         if (rn2(10) >= depth(&u.uz)) {
472             mtmp->m_ap_type = M_AP_OBJECT;
473             mtmp->mappearance = STRANGE_OBJECT;
474         }
475     } else {
476         atype = get_shop_item((int) (shp - shtypes));
477         if (atype == VEGETARIAN_CLASS)
478             mkveggy_at(sx, sy);
479         else if (atype < 0)
480             (void) mksobj_at(-atype, sx, sy, TRUE, TRUE);
481         else
482             (void) mkobj_at(atype, sx, sy, TRUE);
483     }
484 }
485
486 /* extract a shopkeeper name for the given shop type */
487 STATIC_OVL void
488 nameshk(shk, nlp)
489 struct monst *shk;
490 const char *const *nlp;
491 {
492     int i, trycnt, names_avail;
493     const char *shname = 0;
494     struct monst *mtmp;
495     int name_wanted;
496     s_level *sptr;
497
498     if (nlp == shkfoods && In_mines(&u.uz) && Role_if(PM_MONK)
499         && (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
500         /* special-case override for minetown food store for monks */
501         nlp = shkhealthfoods;
502     }
503
504     if (nlp == shklight && In_mines(&u.uz) && (sptr = Is_special(&u.uz)) != 0
505         && sptr->flags.town) {
506         /* special-case minetown lighting shk */
507         shname = "+Izchak";
508         shk->female = FALSE;
509     } else {
510         /* We want variation from game to game, without needing the save
511            and restore support which would be necessary for randomization;
512            try not to make too many assumptions about time_t's internals;
513            use ledger_no rather than depth to keep mine town distinct. */
514         int nseed = (int) ((long) ubirthday / 257L);
515
516         name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
517         if (name_wanted < 0)
518             name_wanted += (13 + 5);
519         shk->female = name_wanted & 1;
520
521         for (names_avail = 0; nlp[names_avail]; names_avail++)
522             continue;
523
524         for (trycnt = 0; trycnt < 50; trycnt++) {
525             if (nlp == shktools) {
526                 shname = shktools[rn2(names_avail)];
527                 shk->female = 0; /* reversed below for '_' prefix */
528             } else if (name_wanted < names_avail) {
529                 shname = nlp[name_wanted];
530             } else if ((i = rn2(names_avail)) != 0) {
531                 shname = nlp[i - 1];
532             } else if (nlp != shkgeneral) {
533                 nlp = shkgeneral; /* try general names */
534                 for (names_avail = 0; nlp[names_avail]; names_avail++)
535                     continue;
536                 continue; /* next `trycnt' iteration */
537             } else {
538                 shname = shk->female ? "-Lucrezia" : "+Dirk";
539             }
540             if (*shname == '_' || *shname == '-')
541                 shk->female = 1;
542             else if (*shname == '|' || *shname == '+')
543                 shk->female = 0;
544
545             /* is name already in use on this level? */
546             for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
547                 if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk)
548                     continue;
549                 if (strcmp(ESHK(mtmp)->shknam, shname))
550                     continue;
551                 break;
552             }
553             if (!mtmp)
554                 break; /* new name */
555         }
556     }
557     (void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
558     ESHK(shk)->shknam[PL_NSIZ - 1] = 0;
559 }
560
561 void
562 neweshk(mtmp)
563 struct monst *mtmp;
564 {
565     if (!mtmp->mextra)
566         mtmp->mextra = newmextra();
567     if (!ESHK(mtmp))
568         ESHK(mtmp) = (struct eshk *) alloc(sizeof(struct eshk));
569     (void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk));
570     ESHK(mtmp)->bill_p = (struct bill_x *) 0;
571 }
572
573 void
574 free_eshk(mtmp)
575 struct monst *mtmp;
576 {
577     if (mtmp->mextra && ESHK(mtmp)) {
578         free((genericptr_t) ESHK(mtmp));
579         ESHK(mtmp) = (struct eshk *) 0;
580     }
581     mtmp->isshk = 0;
582 }
583
584 /* create a new shopkeeper in the given room */
585 STATIC_OVL int
586 shkinit(shp, sroom)
587 const struct shclass *shp;
588 struct mkroom *sroom;
589 {
590     register int sh, sx, sy;
591     struct monst *shk;
592     struct eshk *eshkp;
593
594     /* place the shopkeeper in the given room */
595     sh = sroom->fdoor;
596     sx = doors[sh].x;
597     sy = doors[sh].y;
598
599     /* check that the shopkeeper placement is sane */
600     if (sroom->irregular) {
601         int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
602         if (isok(sx - 1, sy) && !levl[sx - 1][sy].edge
603             && (int) levl[sx - 1][sy].roomno == rmno)
604             sx--;
605         else if (isok(sx + 1, sy) && !levl[sx + 1][sy].edge
606                  && (int) levl[sx + 1][sy].roomno == rmno)
607             sx++;
608         else if (isok(sx, sy - 1) && !levl[sx][sy - 1].edge
609                  && (int) levl[sx][sy - 1].roomno == rmno)
610             sy--;
611         else if (isok(sx, sy + 1) && !levl[sx][sy + 1].edge
612                  && (int) levl[sx][sy + 1].roomno == rmno)
613             sx++;
614         else
615             goto shk_failed;
616     } else if (sx == sroom->lx - 1)
617         sx++;
618     else if (sx == sroom->hx + 1)
619         sx--;
620     else if (sy == sroom->ly - 1)
621         sy++;
622     else if (sy == sroom->hy + 1)
623         sy--;
624     else {
625     shk_failed:
626 #ifdef DEBUG
627         /* Said to happen sometimes, but I have never seen it. */
628         /* Supposedly fixed by fdoor change in mklev.c */
629         if (wizard) {
630             register int j = sroom->doorct;
631
632             pline("Where is shopdoor?");
633             pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly, sroom->hx,
634                   sroom->hy);
635             pline("doormax=%d doorct=%d fdoor=%d", doorindex, sroom->doorct,
636                   sh);
637             while (j--) {
638                 pline("door [%d,%d]", doors[sh].x, doors[sh].y);
639                 sh++;
640             }
641             display_nhwindow(WIN_MESSAGE, FALSE);
642         }
643 #endif
644         return -1;
645     }
646
647     if (MON_AT(sx, sy))
648         (void) rloc(m_at(sx, sy), FALSE); /* insurance */
649
650     /* now initialize the shopkeeper monster structure */
651     if (!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK)))
652         return -1;
653     eshkp = ESHK(shk); /* makemon(...,MM_ESHK) allocates this */
654     shk->isshk = shk->mpeaceful = 1;
655     set_malign(shk);
656     shk->msleeping = 0;
657     shk->mtrapseen = ~0; /* we know all the traps already */
658     eshkp->shoproom = (schar) ((sroom - rooms) + ROOMOFFSET);
659     sroom->resident = shk;
660     eshkp->shoptype = sroom->rtype;
661     assign_level(&eshkp->shoplevel, &u.uz);
662     eshkp->shd = doors[sh];
663     eshkp->shk.x = sx;
664     eshkp->shk.y = sy;
665     eshkp->robbed = eshkp->credit = eshkp->debit = eshkp->loan = 0L;
666     eshkp->following = eshkp->surcharge = eshkp->dismiss_kops = FALSE;
667     eshkp->billct = eshkp->visitct = 0;
668     eshkp->bill_p = (struct bill_x *) 0;
669     eshkp->customer[0] = '\0';
670     mkmonmoney(shk, 1000L + 30L * (long) rnd(100)); /* initial capital */
671     if (shp->shknms == shkrings)
672         (void) mongets(shk, TOUCHSTONE);
673     nameshk(shk, shp->shknms);
674
675     return sh;
676 }
677
678 /* stock a newly-created room with objects */
679 void
680 stock_room(shp_indx, sroom)
681 int shp_indx;
682 register struct mkroom *sroom;
683 {
684     /*
685      * Someday soon we'll dispatch on the shdist field of shclass to do
686      * different placements in this routine. Currently it only supports
687      * shop-style placement (all squares except a row nearest the first
688      * door get objects).
689      */
690     int sx, sy, sh;
691     int stockcount = 0, specialspot = 0;
692     char buf[BUFSZ];
693     int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
694     const struct shclass *shp = &shtypes[shp_indx];
695
696     /* first, try to place a shopkeeper in the room */
697     if ((sh = shkinit(shp, sroom)) < 0)
698         return;
699
700     /* make sure no doorways without doors, and no trapped doors, in shops */
701     sx = doors[sroom->fdoor].x;
702     sy = doors[sroom->fdoor].y;
703     if (levl[sx][sy].doormask == D_NODOOR) {
704         levl[sx][sy].doormask = D_ISOPEN;
705         newsym(sx, sy);
706     }
707     if (levl[sx][sy].typ == SDOOR) {
708         cvt_sdoor_to_door(&levl[sx][sy]); /* .typ = DOOR */
709         newsym(sx, sy);
710     }
711     if (levl[sx][sy].doormask & D_TRAPPED)
712         levl[sx][sy].doormask = D_LOCKED;
713
714     if (levl[sx][sy].doormask == D_LOCKED) {
715         register int m = sx, n = sy;
716
717         if (inside_shop(sx + 1, sy))
718             m--;
719         else if (inside_shop(sx - 1, sy))
720             m++;
721         if (inside_shop(sx, sy + 1))
722             n--;
723         else if (inside_shop(sx, sy - 1))
724             n++;
725         Sprintf(buf, "Closed for inventory");
726         make_engr_at(m, n, buf, 0L, DUST);
727     }
728
729     if (context.tribute.enabled && !context.tribute.bookstock) {
730         /*
731          * Out of the number of spots where we're actually
732          * going to put stuff, randomly single out one in particular.
733          */
734         for (sx = sroom->lx; sx <= sroom->hx; sx++)
735             for (sy = sroom->ly; sy <= sroom->hy; sy++) {
736                 if (sroom->irregular) {
737                     if (levl[sx][sy].edge
738                         || (int) levl[sx][sy].roomno != rmno
739                         || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
740                         continue;
741                 } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
742                            || (sx == sroom->hx && doors[sh].x == sx + 1)
743                            || (sy == sroom->ly && doors[sh].y == sy - 1)
744                            || (sy == sroom->hy && doors[sh].y == sy + 1))
745                     continue;
746                 stockcount++;
747             }
748         specialspot = rnd(stockcount);
749         stockcount = 0;
750     }
751
752     for (sx = sroom->lx; sx <= sroom->hx; sx++)
753         for (sy = sroom->ly; sy <= sroom->hy; sy++) {
754             if (sroom->irregular) {
755                 if (levl[sx][sy].edge
756                     || (int) levl[sx][sy].roomno != rmno
757                     || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
758                     continue;
759             } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
760                        || (sx == sroom->hx && doors[sh].x == sx + 1)
761                        || (sy == sroom->ly && doors[sh].y == sy - 1)
762                        || (sy == sroom->hy && doors[sh].y == sy + 1))
763                 continue;
764             stockcount++;
765             mkshobj_at(shp, sx, sy,
766                        ((stockcount) && (stockcount == specialspot)));
767         }
768
769     /*
770      * Special monster placements (if any) should go here: that way,
771      * monsters will sit on top of objects and not the other way around.
772      */
773
774     level.flags.has_shop = TRUE;
775 }
776
777 /* does shkp's shop stock this item type? */
778 boolean
779 saleable(shkp, obj)
780 struct monst *shkp;
781 struct obj *obj;
782 {
783     int i, shp_indx = ESHK(shkp)->shoptype - SHOPBASE;
784     const struct shclass *shp = &shtypes[shp_indx];
785
786     if (shp->symb == RANDOM_CLASS)
787         return TRUE;
788     for (i = 0; i < SIZE(shtypes[0].iprobs) && shp->iprobs[i].iprob; i++) {
789         /* pseudo-class needs special handling */
790         if (shp->iprobs[i].itype == VEGETARIAN_CLASS) {
791             if (veggy_item(obj, 0))
792                 return TRUE;
793         } else if ((shp->iprobs[i].itype < 0)
794                        ? shp->iprobs[i].itype == -obj->otyp
795                        : shp->iprobs[i].itype == obj->oclass)
796             return TRUE;
797     }
798     /* not found */
799     return FALSE;
800 }
801
802 /* positive value: class; negative value: specific object type */
803 int
804 get_shop_item(type)
805 int type;
806 {
807     const struct shclass *shp = shtypes + type;
808     register int i, j;
809
810     /* select an appropriate object type at random */
811     for (j = rnd(100), i = 0; (j -= shp->iprobs[i].iprob) > 0; i++)
812         continue;
813
814     return shp->iprobs[i].itype;
815 }
816
817 const char *
818 shkname(mtmp)
819 struct monst *mtmp;
820 {
821     const char *shknm = ESHK(mtmp)->shknam;
822
823     if (Hallucination && !program_state.gameover) {
824         const char *const *nlp;
825         int num;
826
827         /* count the number of non-unique shop types;
828            pick one randomly, ignoring shop generation probabilities;
829            pick a name at random from that shop type's list */
830         for (num = 0; num < SIZE(shtypes); num++)
831             if (shtypes[num].prob == 0)
832                 break;
833         if (num > 0) {
834             nlp = shtypes[rn2(num)].shknms;
835             for (num = 0; nlp[num]; num++)
836                 continue;
837             if (num > 0)
838                 shknm = nlp[rn2(num)];
839         }
840     }
841
842     /* strip prefix if present */
843     if (!letter(*shknm))
844         ++shknm;
845     return shknm;
846 }
847
848 boolean
849 shkname_is_pname(mtmp)
850 struct monst *mtmp;
851 {
852     const char *shknm = ESHK(mtmp)->shknam;
853
854     return (boolean) (*shknm == '-' || *shknm == '+' || *shknm == '=');
855 }
856
857 boolean
858 is_izchak(shkp, override_hallucination)
859 struct monst *shkp;
860 boolean override_hallucination;
861 {
862     const char *shknm;
863
864     if (Hallucination && !override_hallucination)
865         return FALSE;
866     if (!shkp->isshk)
867         return FALSE;
868     /* outside of town, Izchak becomes just an ordinary shopkeeper */
869     if (!in_town(shkp->mx, shkp->my))
870         return FALSE;
871     shknm = ESHK(shkp)->shknam;
872     /* skip "+" prefix */
873     if (!letter(*shknm))
874         ++shknm;
875     return (boolean) !strcmp(shknm, "Izchak");
876 }
877
878 /*shknam.c*/