OSDN Git Service

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