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. */
5 /* shknam.c -- initialize a shop */
7 /* JNetHack Copyright */
8 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
9 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
10 /* JNetHack may be freely redistributed. See license for details. */
14 STATIC_DCL boolean FDECL(veggy_item, (struct obj * obj, int));
15 STATIC_DCL int NDECL(shkveg);
16 STATIC_DCL void FDECL(mkveggy_at, (int, int));
17 STATIC_DCL void FDECL(mkshobj_at, (const struct shclass *, int, int,
19 STATIC_DCL void FDECL(nameshk, (struct monst *, const char *const *));
20 STATIC_DCL int FDECL(shkinit, (const struct shclass *, struct mkroom *));
22 #define VEGETARIAN_CLASS (MAXOCLASSES + 1)
26 * dash - female, personal name
27 * underscore _ female, general name
28 * plus + male, personal name
29 * vertical bar | male, general name (implied for most of shktools)
30 * equals = gender not specified, personal name
32 * Personal names do not receive the honorific prefix "Mr." or "Ms.".
35 static const char *const shkliquors[] = {
37 "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
41 "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", "Narodnaja", "Kyzyl",
43 "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", "Brzeg",
44 "Krnov", "Hradec Kralove",
46 "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", "Flims",
47 "Vals", "Schuls", "Zum Loch", 0
50 static const char *const shkbooks[] = {
52 "Skibbereen", "Kanturk", "Rath Luirc", "Ennistymon",
53 "Lahinch", "Kinnegad", "Lugnaquillia", "Enniscorthy",
54 "Gweebarra", "Kittamagh", "Nenagh", "Sneem",
55 "Ballingeary", "Kilgarvan", "Cahersiveen", "Glenbeigh",
56 "Kilmihil", "Kiltamagh", "Droichead Atha", "Inniscrone",
57 "Clonegal", "Lisnaskea", "Culdaff", "Dunfanaghy",
58 "Inishbofin", "Kesh", 0
61 static const char *const shkarmors[] = {
63 "Demirci", "Kalecik", "Boyabai", "Yildizeli", "Gaziantep",
64 "Siirt", "Akhalataki", "Tirebolu", "Aksaray", "Ermenak",
65 "Iskenderun", "Kadirli", "Siverek", "Pervari", "Malasgirt",
66 "Bayburt", "Ayancik", "Zonguldak", "Balya", "Tefenni",
67 "Artvin", "Kars", "Makharadze", "Malazgirt", "Midyat",
68 "Birecik", "Kirikkale", "Alaca", "Polatli", "Nallihan",
72 static const char *const shkwands[] = {
74 "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach", "Rhaeader",
75 "Llandrindod", "Llanfair-ym-muallt", "Y-Fenni", "Maesteg", "Rhydaman",
76 "Beddgelert", "Curig", "Llanrwst", "Llanerchymedd", "Caergybi",
78 "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar", "Kerloch",
79 "Beinn a Ghlo", "Drumnadrochit", "Morven", "Uist", "Storr",
80 "Sgurr na Ciche", "Cannich", "Gairloch", "Kyleakin", "Dunvegan", 0
83 static const char *const shkrings[] = {
84 /* Hollandse familienamen */
85 "Feyfer", "Flugi", "Gheel", "Havic", "Haynin",
86 "Hoboken", "Imbyze", "Juyn", "Kinsky", "Massis",
87 "Matray", "Moy", "Olycan", "Sadelin", "Svaving",
88 "Tapper", "Terwen", "Wirix", "Ypey",
89 /* Skandinaviske navne */
90 "Rastegaisa", "Varjag Njarga", "Kautekeino", "Abisko", "Enontekis",
91 "Rovaniemi", "Avasaksa", "Haparanda", "Lulea", "Gellivare",
92 "Oeloe", "Kajaani", "Fauske", 0
95 static const char *const shkfoods[] = {
97 "Djasinga", "Tjibarusa", "Tjiwidej", "Pengalengan",
98 "Bandjar", "Parbalingga", "Bojolali", "Sarangan",
99 "Ngebel", "Djombang", "Ardjawinangun", "Berbek",
100 "Papar", "Baliga", "Tjisolok", "Siboga",
101 "Banjoewangi", "Trenggalek", "Karangkobar", "Njalindoeng",
102 "Pasawahan", "Pameunpeuk", "Patjitan", "Kediri",
103 "Pemboeang", "Tringanoe", "Makin", "Tipor",
104 "Semai", "Berhala", "Tegal", "Samoe",
108 static const char *const shkweapons[] = {
110 "Voulgezac", "Rouffiac", "Lerignac", "Touverac", "Guizengeard",
111 "Melac", "Neuvicq", "Vanzac", "Picq", "Urignac",
112 "Corignac", "Fleac", "Lonzac", "Vergt", "Queyssac",
113 "Liorac", "Echourgnac", "Cazelon", "Eypau", "Carignan",
114 "Monbazillac", "Jonzac", "Pons", "Jumilhac", "Fenouilledes",
115 "Laguiolet", "Saujon", "Eymoutiers", "Eygurande", "Eauze",
119 static const char *const shktools[] = {
121 "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj",
122 "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
123 "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
124 "Nosnehpets", "Stewe", "Renrut", "-Zlaw", "Nosalnef", "Rewuorb",
125 "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah", "Corsh", "Aned",
126 "Niknar", "Lapu", "Lechaim", "Rebrol-nek", "AlliWar Wickson", "Oguhmk",
128 "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
134 "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
135 "Tonbar", "Kivenhoug", "Llardom",
138 "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
148 "Lez-tneg", "Ytnu-haled",
153 static const char *const shklight[] = {
155 "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
156 "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
157 "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
159 "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli", "Pernik",
160 "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo", "Troyan",
161 "Lovech", "Sliven", 0
164 static const char *const shkgeneral[] = {
166 "Hebiwerie", "Possogroenoe", "Asidonhopo", "Manlobbi",
167 "Adjama", "Pakka Pakka", "Kabalebo", "Wonotobo",
168 "Akalapi", "Sipaliwini",
170 "Annootok", "Upernavik", "Angmagssalik",
172 "Aklavik", "Inuvik", "Tuktoyaktuk", "Chicoutimi",
173 "Ouiatchouane", "Chibougamau", "Matagami", "Kipawa",
174 "Kinojevis", "Abitibi", "Maganasipi",
176 "Akureyri", "Kopasker", "Budereyri", "Akranes",
177 "Bordeyri", "Holmavik", 0
180 static const char *const shkhealthfoods[] = {
182 "Ga'er", "Zhangmu", "Rikaze", "Jiangji", "Changdu",
183 "Linzhi", "Shigatse", "Gyantse", "Ganden", "Tsurphu",
184 "Lhasa", "Tsedong", "Drepung",
186 "=Azura", "=Blaze", "=Breanna", "=Breezy", "=Dharma",
187 "=Feather", "=Jasmine", "=Luna", "=Melody", "=Moonjava",
188 "=Petal", "=Rhiannon", "=Starla", "=Tranquilla", "=Windsong",
189 "=Zennia", "=Zoe", "=Zora", 0
193 * To add new shop types, all that is necessary is to edit the shtypes[]
194 * array. See mkroom.h for the structure definition. Typically, you'll
195 * have to lower some or all of the probability fields in old entries to
196 * free up some percentage for the new type.
198 * The placement type field is not yet used but will be in the near future.
200 * The iprobs array in each entry defines the probabilities for various kinds
201 * of objects to be present in the given shop type. You can associate with
202 * each percentage either a generic object type (represented by one of the
203 * *_CLASS macros) or a specific object (represented by an onames.h define).
204 * In the latter case, prepend it with a unary minus so the code can know
205 * (by testing the sign) whether to use mkobj() or mksobj().
207 const struct shclass shtypes[] = {
215 { { 100, RANDOM_CLASS },
223 { "used armor dealership",
225 { "
\92\86\8cÃ
\8aZ
\8f¤
\89ï",
229 { { 90, ARMOR_CLASS },
230 { 10, WEAPON_CLASS },
237 { "second-hand bookstore",
243 { { 90, SCROLL_CLASS },
244 { 10, SPBOOK_CLASS },
253 {"
\82¨
\8eð
\82Ì
\95S
\89Ý
\93X",
257 { { 100, POTION_CLASS },
265 { "antique weapons outlet",
267 { "
\8cÃ
\95\90\8aí
\90ê
\96å
\8f¬
\94\84\93X",
271 { { 90, WEAPON_CLASS },
285 { { 83, FOOD_CLASS },
286 { 5, -POT_FRUIT_JUICE },
299 { { 85, RING_CLASS },
307 { "quality apparel and accessories",
309 { "
\82¨
\83V
\83\83\83\8c\82È
\97m
\95i
\93X",
313 { { 90, WAND_CLASS },
314 { 5, -LEATHER_GLOVES },
325 { { 100, TOOL_CLASS },
335 { "
\8c¶
\82Ì
\96{
\89®",
339 { { 90, SPBOOK_CLASS },
340 { 10, SCROLL_CLASS },
347 { "health food store",
349 { "
\8c\92\8dN
\90H
\95i
\82Ì
\93X",
353 { { 70, VEGETARIAN_CLASS },
354 { 20, -POT_FRUIT_JUICE },
356 { 3, -POT_FULL_HEALING },
357 { 2, -SCR_FOOD_DETECTION },
358 { 1, -LUMP_OF_ROYAL_JELLY } },
360 /* Shops below this point are "unique". That is they must all have a
361 * probability of zero. They are only created via the special level
371 { { 30, -WAX_CANDLE },
372 { 48, -TALLOW_CANDLE },
373 { 5, -BRASS_LANTERN },
383 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
388 /* validate shop probabilities; otherwise incorrect local changes could
389 end up provoking infinite loops or wild subscripts fetching garbage */
391 init_shop_selection()
393 register int i, j, item_prob, shop_prob;
395 for (shop_prob = 0, i = 0; i < SIZE(shtypes); i++) {
396 shop_prob += shtypes[i].prob;
397 for (item_prob = 0, j = 0; j < SIZE(shtypes[0].iprobs); j++)
398 item_prob += shtypes[i].iprobs[j].iprob;
399 if (item_prob != 100)
400 panic("item probabilities total to %d for %s shops!",
401 item_prob, shtypes[i].name);
403 if (shop_prob != 100)
404 panic("shop probabilities total to %d!", shop_prob);
408 /* decide whether an object or object type is considered vegetarian;
409 for types, items which might go either way are assumed to be veggy */
411 veggy_item(obj, otyp)
413 int otyp; /* used iff obj is null */
419 /* actual object; will check tin content and corpse species */
420 otyp = (int) obj->otyp;
421 oclass = obj->oclass;
422 corpsenm = obj->corpsenm;
424 /* just a type; caller will have to handle tins and corpses */
425 oclass = objects[otyp].oc_class;
426 corpsenm = PM_LICHEN; /* veggy standin */
429 if (oclass == FOOD_CLASS) {
430 if (objects[otyp].oc_material == VEGGY || otyp == EGG)
432 if (otyp == TIN && corpsenm == NON_PM) /* implies obj is non-null */
433 return (boolean) (obj->spe == 1); /* 0 = empty, 1 = spinach */
434 if (otyp == TIN || otyp == CORPSE)
435 return (boolean) (corpsenm >= LOW_PM
436 && vegetarian(&mons[corpsenm]));
444 int i, j, maxprob, prob;
445 char oclass = FOOD_CLASS;
449 ok[0] = 0; /* lint suppression */
450 for (i = bases[(int) oclass]; i < NUM_OBJECTS; ++i) {
451 if (objects[i].oc_class != oclass)
454 if (veggy_item((struct obj *) 0, i)) {
456 maxprob += objects[i].oc_prob;
460 panic("shkveg no veggy objects");
465 while ((prob -= objects[i].oc_prob) > 0) {
470 if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
471 panic("shkveg probtype error, oclass=%d i=%d", (int) oclass, i);
475 /* make a random item for health food store */
480 struct obj *obj = mksobj_at(shkveg(), sx, sy, TRUE, TRUE);
482 if (obj && obj->otyp == TIN)
483 set_tin_variety(obj, HEALTHY_TIN);
487 /* make an object of the appropriate type for a shop square */
489 mkshobj_at(shp, sx, sy, mkspecl)
490 const struct shclass *shp;
495 struct permonst *ptr;
500 if (mkspecl && (!strcmp(shp->name, "rare books")
501 || !strcmp(shp->name, "second-hand bookstore"))) {
503 if (mkspecl && (!strcmp(shp->name, "
\8c¶
\82Ì
\96{
\89®")
504 || !strcmp(shp->name, "
\8cÃ
\8f\91\93X"))) {
506 struct obj *novel = mksobj_at(SPE_NOVEL, sx, sy, FALSE, FALSE);
509 context.tribute.bookstock = TRUE;
513 if (rn2(100) < depth(&u.uz) && !MON_AT(sx, sy)
514 && (ptr = mkclass(S_MIMIC, 0)) != 0
515 && (mtmp = makemon(ptr, sx, sy, NO_MM_FLAGS)) != 0) {
516 /* note: makemon will set the mimic symbol to a shop item */
517 if (rn2(10) >= depth(&u.uz)) {
518 mtmp->m_ap_type = M_AP_OBJECT;
519 mtmp->mappearance = STRANGE_OBJECT;
522 atype = get_shop_item((int) (shp - shtypes));
523 if (atype == VEGETARIAN_CLASS)
526 (void) mksobj_at(-atype, sx, sy, TRUE, TRUE);
528 (void) mkobj_at(atype, sx, sy, TRUE);
532 /* extract a shopkeeper name for the given shop type */
536 const char *const *nlp;
538 int i, trycnt, names_avail;
539 const char *shname = 0;
544 if (nlp == shkfoods && In_mines(&u.uz) && Role_if(PM_MONK)
545 && (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
546 /* special-case override for minetown food store for monks */
547 nlp = shkhealthfoods;
550 if (nlp == shklight && In_mines(&u.uz) && (sptr = Is_special(&u.uz)) != 0
551 && sptr->flags.town) {
552 /* special-case minetown lighting shk */
556 /* We want variation from game to game, without needing the save
557 and restore support which would be necessary for randomization;
558 try not to make too many assumptions about time_t's internals;
559 use ledger_no rather than depth to keep mine town distinct. */
560 int nseed = (int) ((long) ubirthday / 257L);
562 name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
564 name_wanted += (13 + 5);
565 shk->female = name_wanted & 1;
567 for (names_avail = 0; nlp[names_avail]; names_avail++)
570 for (trycnt = 0; trycnt < 50; trycnt++) {
571 if (nlp == shktools) {
572 shname = shktools[rn2(names_avail)];
573 shk->female = 0; /* reversed below for '_' prefix */
574 } else if (name_wanted < names_avail) {
575 shname = nlp[name_wanted];
576 } else if ((i = rn2(names_avail)) != 0) {
578 } else if (nlp != shkgeneral) {
579 nlp = shkgeneral; /* try general names */
580 for (names_avail = 0; nlp[names_avail]; names_avail++)
582 continue; /* next `trycnt' iteration */
584 shname = shk->female ? "-Lucrezia" : "+Dirk";
586 if (*shname == '_' || *shname == '-')
588 else if (*shname == '|' || *shname == '+')
591 /* is name already in use on this level? */
592 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
593 if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk)
595 if (strcmp(ESHK(mtmp)->shknam, shname))
600 break; /* new name */
603 (void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
604 ESHK(shk)->shknam[PL_NSIZ - 1] = 0;
612 mtmp->mextra = newmextra();
614 ESHK(mtmp) = (struct eshk *) alloc(sizeof(struct eshk));
615 (void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk));
616 ESHK(mtmp)->bill_p = (struct bill_x *) 0;
623 if (mtmp->mextra && ESHK(mtmp)) {
624 free((genericptr_t) ESHK(mtmp));
625 ESHK(mtmp) = (struct eshk *) 0;
630 /* create a new shopkeeper in the given room */
633 const struct shclass *shp;
634 struct mkroom *sroom;
636 register int sh, sx, sy;
640 /* place the shopkeeper in the given room */
645 /* check that the shopkeeper placement is sane */
646 if (sroom->irregular) {
647 int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
648 if (isok(sx - 1, sy) && !levl[sx - 1][sy].edge
649 && (int) levl[sx - 1][sy].roomno == rmno)
651 else if (isok(sx + 1, sy) && !levl[sx + 1][sy].edge
652 && (int) levl[sx + 1][sy].roomno == rmno)
654 else if (isok(sx, sy - 1) && !levl[sx][sy - 1].edge
655 && (int) levl[sx][sy - 1].roomno == rmno)
657 else if (isok(sx, sy + 1) && !levl[sx][sy + 1].edge
658 && (int) levl[sx][sy + 1].roomno == rmno)
662 } else if (sx == sroom->lx - 1)
664 else if (sx == sroom->hx + 1)
666 else if (sy == sroom->ly - 1)
668 else if (sy == sroom->hy + 1)
673 /* Said to happen sometimes, but I have never seen it. */
674 /* Supposedly fixed by fdoor change in mklev.c */
676 register int j = sroom->doorct;
678 pline("Where is shopdoor?");
679 pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly, sroom->hx,
681 pline("doormax=%d doorct=%d fdoor=%d", doorindex, sroom->doorct,
684 pline("door [%d,%d]", doors[sh].x, doors[sh].y);
687 display_nhwindow(WIN_MESSAGE, FALSE);
694 (void) rloc(m_at(sx, sy), FALSE); /* insurance */
696 /* now initialize the shopkeeper monster structure */
697 if (!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK)))
699 eshkp = ESHK(shk); /* makemon(...,MM_ESHK) allocates this */
700 shk->isshk = shk->mpeaceful = 1;
703 shk->mtrapseen = ~0; /* we know all the traps already */
704 eshkp->shoproom = (schar) ((sroom - rooms) + ROOMOFFSET);
705 sroom->resident = shk;
706 eshkp->shoptype = sroom->rtype;
707 assign_level(&eshkp->shoplevel, &u.uz);
708 eshkp->shd = doors[sh];
711 eshkp->robbed = eshkp->credit = eshkp->debit = eshkp->loan = 0L;
712 eshkp->following = eshkp->surcharge = eshkp->dismiss_kops = FALSE;
713 eshkp->billct = eshkp->visitct = 0;
714 eshkp->bill_p = (struct bill_x *) 0;
715 eshkp->customer[0] = '\0';
716 mkmonmoney(shk, 1000L + 30L * (long) rnd(100)); /* initial capital */
717 if (shp->shknms == shkrings)
718 (void) mongets(shk, TOUCHSTONE);
719 nameshk(shk, shp->shknms);
724 /* stock a newly-created room with objects */
726 stock_room(shp_indx, sroom)
728 register struct mkroom *sroom;
731 * Someday soon we'll dispatch on the shdist field of shclass to do
732 * different placements in this routine. Currently it only supports
733 * shop-style placement (all squares except a row nearest the first
737 int stockcount = 0, specialspot = 0;
739 int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
740 const struct shclass *shp = &shtypes[shp_indx];
742 /* first, try to place a shopkeeper in the room */
743 if ((sh = shkinit(shp, sroom)) < 0)
746 /* make sure no doorways without doors, and no trapped doors, in shops */
747 sx = doors[sroom->fdoor].x;
748 sy = doors[sroom->fdoor].y;
749 if (levl[sx][sy].doormask == D_NODOOR) {
750 levl[sx][sy].doormask = D_ISOPEN;
753 if (levl[sx][sy].typ == SDOOR) {
754 cvt_sdoor_to_door(&levl[sx][sy]); /* .typ = DOOR */
757 if (levl[sx][sy].doormask & D_TRAPPED)
758 levl[sx][sy].doormask = D_LOCKED;
760 if (levl[sx][sy].doormask == D_LOCKED) {
761 register int m = sx, n = sy;
763 if (inside_shop(sx + 1, sy))
765 else if (inside_shop(sx - 1, sy))
767 if (inside_shop(sx, sy + 1))
769 else if (inside_shop(sx, sy - 1))
772 Sprintf(buf, "Closed for inventory");
774 Sprintf(buf, "
\92I
\89µ
\82µ
\82Ì
\82½
\82ß
\95Â
\93X");
775 make_engr_at(m, n, buf, 0L, DUST);
778 if (context.tribute.enabled && !context.tribute.bookstock) {
780 * Out of the number of spots where we're actually
781 * going to put stuff, randomly single out one in particular.
783 for (sx = sroom->lx; sx <= sroom->hx; sx++)
784 for (sy = sroom->ly; sy <= sroom->hy; sy++) {
785 if (sroom->irregular) {
786 if (levl[sx][sy].edge
787 || (int) levl[sx][sy].roomno != rmno
788 || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
790 } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
791 || (sx == sroom->hx && doors[sh].x == sx + 1)
792 || (sy == sroom->ly && doors[sh].y == sy - 1)
793 || (sy == sroom->hy && doors[sh].y == sy + 1))
797 specialspot = rnd(stockcount);
801 for (sx = sroom->lx; sx <= sroom->hx; sx++)
802 for (sy = sroom->ly; sy <= sroom->hy; sy++) {
803 if (sroom->irregular) {
804 if (levl[sx][sy].edge
805 || (int) levl[sx][sy].roomno != rmno
806 || distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
808 } else if ((sx == sroom->lx && doors[sh].x == sx - 1)
809 || (sx == sroom->hx && doors[sh].x == sx + 1)
810 || (sy == sroom->ly && doors[sh].y == sy - 1)
811 || (sy == sroom->hy && doors[sh].y == sy + 1))
814 mkshobj_at(shp, sx, sy,
815 ((stockcount) && (stockcount == specialspot)));
819 * Special monster placements (if any) should go here: that way,
820 * monsters will sit on top of objects and not the other way around.
823 level.flags.has_shop = TRUE;
826 /* does shkp's shop stock this item type? */
832 int i, shp_indx = ESHK(shkp)->shoptype - SHOPBASE;
833 const struct shclass *shp = &shtypes[shp_indx];
835 if (shp->symb == RANDOM_CLASS)
837 for (i = 0; i < SIZE(shtypes[0].iprobs) && shp->iprobs[i].iprob; i++) {
838 /* pseudo-class needs special handling */
839 if (shp->iprobs[i].itype == VEGETARIAN_CLASS) {
840 if (veggy_item(obj, 0))
842 } else if ((shp->iprobs[i].itype < 0)
843 ? shp->iprobs[i].itype == -obj->otyp
844 : shp->iprobs[i].itype == obj->oclass)
851 /* positive value: class; negative value: specific object type */
856 const struct shclass *shp = shtypes + type;
859 /* select an appropriate object type at random */
860 for (j = rnd(100), i = 0; (j -= shp->iprobs[i].iprob) > 0; i++)
863 return shp->iprobs[i].itype;
870 const char *shknm = ESHK(mtmp)->shknam;
872 if (Hallucination && !program_state.gameover) {
873 const char *const *nlp;
876 /* count the number of non-unique shop types;
877 pick one randomly, ignoring shop generation probabilities;
878 pick a name at random from that shop type's list */
879 for (num = 0; num < SIZE(shtypes); num++)
880 if (shtypes[num].prob == 0)
883 nlp = shtypes[rn2(num)].shknms;
884 for (num = 0; nlp[num]; num++)
887 shknm = nlp[rn2(num)];
891 /* strip prefix if present */
898 shkname_is_pname(mtmp)
901 const char *shknm = ESHK(mtmp)->shknam;
903 return (boolean) (*shknm == '-' || *shknm == '+' || *shknm == '=');
907 is_izchak(shkp, override_hallucination)
909 boolean override_hallucination;
913 if (Hallucination && !override_hallucination)
917 /* outside of town, Izchak becomes just an ordinary shopkeeper */
918 if (!in_town(shkp->mx, shkp->my))
920 shknm = ESHK(shkp)->shknam;
921 /* skip "+" prefix */
924 return (boolean) !strcmp(shknm, "Izchak");