1 /* NetHack 3.6 shknam.c $NHDT-Date: 1450306213 2015/12/16 22:50:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.39 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* shknam.c -- initialize a shop */
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,
14 STATIC_DCL
void FDECL(nameshk
, (struct monst
*, const char *const *));
15 STATIC_DCL
int FDECL(shkinit
, (const struct shclass
*, struct mkroom
*));
17 #define VEGETARIAN_CLASS (MAXOCLASSES + 1)
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
27 * Personal names do not receive the honorific prefix "Mr." or "Ms.".
30 static const char *const shkliquors
[] = {
32 "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
36 "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", "Narodnaja", "Kyzyl",
38 "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", "Brzeg",
39 "Krnov", "Hradec Kralove",
41 "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", "Flims",
42 "Vals", "Schuls", "Zum Loch", 0
45 static const char *const shkbooks
[] = {
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
56 static const char *const shkarmors
[] = {
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",
67 static const char *const shkwands
[] = {
69 "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach", "Rhaeader",
70 "Llandrindod", "Llanfair-ym-muallt", "Y-Fenni", "Maesteg", "Rhydaman",
71 "Beddgelert", "Curig", "Llanrwst", "Llanerchymedd", "Caergybi",
73 "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar", "Kerloch",
74 "Beinn a Ghlo", "Drumnadrochit", "Morven", "Uist", "Storr",
75 "Sgurr na Ciche", "Cannich", "Gairloch", "Kyleakin", "Dunvegan", 0
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
90 static const char *const shkfoods
[] = {
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",
103 static const char *const shkweapons
[] = {
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",
114 static const char *const shktools
[] = {
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",
123 "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
129 "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
130 "Tonbar", "Kivenhoug", "Llardom",
133 "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
143 "Lez-tneg", "Ytnu-haled",
148 static const char *const shklight
[] = {
150 "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
151 "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
152 "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
154 "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli", "Pernik",
155 "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo", "Troyan",
156 "Lovech", "Sliven", 0
159 static const char *const shkgeneral
[] = {
161 "Hebiwerie", "Possogroenoe", "Asidonhopo", "Manlobbi",
162 "Adjama", "Pakka Pakka", "Kabalebo", "Wonotobo",
163 "Akalapi", "Sipaliwini",
165 "Annootok", "Upernavik", "Angmagssalik",
167 "Aklavik", "Inuvik", "Tuktoyaktuk", "Chicoutimi",
168 "Ouiatchouane", "Chibougamau", "Matagami", "Kipawa",
169 "Kinojevis", "Abitibi", "Maganasipi",
171 "Akureyri", "Kopasker", "Budereyri", "Akranes",
172 "Bordeyri", "Holmavik", 0
175 static const char *const shkhealthfoods
[] = {
177 "Ga'er", "Zhangmu", "Rikaze", "Jiangji", "Changdu",
178 "Linzhi", "Shigatse", "Gyantse", "Ganden", "Tsurphu",
179 "Lhasa", "Tsedong", "Drepung",
181 "=Azura", "=Blaze", "=Breanna", "=Breezy", "=Dharma",
182 "=Feather", "=Jasmine", "=Luna", "=Melody", "=Moonjava",
183 "=Petal", "=Rhiannon", "=Starla", "=Tranquilla", "=Windsong",
184 "=Zennia", "=Zoe", "=Zora", 0
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.
193 * The placement type field is not yet used but will be in the near future.
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().
202 const struct shclass shtypes
[] = {
207 { { 100, RANDOM_CLASS
},
214 { "used armor dealership",
218 { { 90, ARMOR_CLASS
},
219 { 10, WEAPON_CLASS
},
225 { "second-hand bookstore",
229 { { 90, SCROLL_CLASS
},
230 { 10, SPBOOK_CLASS
},
240 { { 100, POTION_CLASS
},
247 { "antique weapons outlet",
251 { { 90, WEAPON_CLASS
},
262 { { 83, FOOD_CLASS
},
263 { 5, -POT_FRUIT_JUICE
},
273 { { 85, RING_CLASS
},
280 { "quality apparel and accessories",
284 { { 90, WAND_CLASS
},
285 { 5, -LEATHER_GLOVES
},
293 { { 100, TOOL_CLASS
},
304 { { 90, SPBOOK_CLASS
},
305 { 10, SCROLL_CLASS
},
311 { "health food store",
315 { { 70, VEGETARIAN_CLASS
},
316 { 20, -POT_FRUIT_JUICE
},
318 { 3, -POT_FULL_HEALING
},
319 { 2, -SCR_FOOD_DETECTION
},
320 { 1, -LUMP_OF_ROYAL_JELLY
} },
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
330 { { 30, -WAX_CANDLE
},
331 { 48, -TALLOW_CANDLE
},
332 { 5, -BRASS_LANTERN
},
342 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
347 /* validate shop probabilities; otherwise incorrect local changes could
348 end up provoking infinite loops or wild subscripts fetching garbage */
350 init_shop_selection()
352 register int i
, j
, item_prob
, shop_prob
;
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
);
362 if (shop_prob
!= 100)
363 panic("shop probabilities total to %d!", shop_prob
);
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 */
370 veggy_item(obj
, otyp
)
372 int otyp
; /* used iff obj is null */
378 /* actual object; will check tin content and corpse species */
379 otyp
= (int) obj
->otyp
;
380 oclass
= obj
->oclass
;
381 corpsenm
= obj
->corpsenm
;
383 /* just a type; caller will have to handle tins and corpses */
384 oclass
= objects
[otyp
].oc_class
;
385 corpsenm
= PM_LICHEN
; /* veggy standin */
388 if (oclass
== FOOD_CLASS
) {
389 if (objects
[otyp
].oc_material
== VEGGY
|| otyp
== EGG
)
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
]));
403 int i
, j
, maxprob
, prob
;
404 char oclass
= FOOD_CLASS
;
408 ok
[0] = 0; /* lint suppression */
409 for (i
= bases
[(int) oclass
]; i
< NUM_OBJECTS
; ++i
) {
410 if (objects
[i
].oc_class
!= oclass
)
413 if (veggy_item((struct obj
*) 0, i
)) {
415 maxprob
+= objects
[i
].oc_prob
;
419 panic("shkveg no veggy objects");
424 while ((prob
-= objects
[i
].oc_prob
) > 0) {
429 if (objects
[i
].oc_class
!= oclass
|| !OBJ_NAME(objects
[i
]))
430 panic("shkveg probtype error, oclass=%d i=%d", (int) oclass
, i
);
434 /* make a random item for health food store */
439 struct obj
*obj
= mksobj_at(shkveg(), sx
, sy
, TRUE
, TRUE
);
441 if (obj
&& obj
->otyp
== TIN
)
442 set_tin_variety(obj
, HEALTHY_TIN
);
446 /* make an object of the appropriate type for a shop square */
448 mkshobj_at(shp
, sx
, sy
, mkspecl
)
449 const struct shclass
*shp
;
454 struct permonst
*ptr
;
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
);
463 context
.tribute
.bookstock
= TRUE
;
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
;
476 atype
= get_shop_item((int) (shp
- shtypes
));
477 if (atype
== VEGETARIAN_CLASS
)
480 (void) mksobj_at(-atype
, sx
, sy
, TRUE
, TRUE
);
482 (void) mkobj_at(atype
, sx
, sy
, TRUE
);
486 /* extract a shopkeeper name for the given shop type */
490 const char *const *nlp
;
492 int i
, trycnt
, names_avail
;
493 const char *shname
= 0;
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
;
504 if (nlp
== shklight
&& In_mines(&u
.uz
) && (sptr
= Is_special(&u
.uz
)) != 0
505 && sptr
->flags
.town
) {
506 /* special-case minetown lighting shk */
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);
516 name_wanted
= ledger_no(&u
.uz
) + (nseed
% 13) - (nseed
% 5);
518 name_wanted
+= (13 + 5);
519 shk
->female
= name_wanted
& 1;
521 for (names_avail
= 0; nlp
[names_avail
]; names_avail
++)
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) {
532 } else if (nlp
!= shkgeneral
) {
533 nlp
= shkgeneral
; /* try general names */
534 for (names_avail
= 0; nlp
[names_avail
]; names_avail
++)
536 continue; /* next `trycnt' iteration */
538 shname
= shk
->female
? "-Lucrezia" : "+Dirk";
540 if (*shname
== '_' || *shname
== '-')
542 else if (*shname
== '|' || *shname
== '+')
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
)
549 if (strcmp(ESHK(mtmp
)->shknam
, shname
))
554 break; /* new name */
557 (void) strncpy(ESHK(shk
)->shknam
, shname
, PL_NSIZ
);
558 ESHK(shk
)->shknam
[PL_NSIZ
- 1] = 0;
566 mtmp
->mextra
= newmextra();
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;
577 if (mtmp
->mextra
&& ESHK(mtmp
)) {
578 free((genericptr_t
) ESHK(mtmp
));
579 ESHK(mtmp
) = (struct eshk
*) 0;
584 /* create a new shopkeeper in the given room */
587 const struct shclass
*shp
;
588 struct mkroom
*sroom
;
590 register int sh
, sx
, sy
;
594 /* place the shopkeeper in the given room */
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
)
605 else if (isok(sx
+ 1, sy
) && !levl
[sx
+ 1][sy
].edge
606 && (int) levl
[sx
+ 1][sy
].roomno
== rmno
)
608 else if (isok(sx
, sy
- 1) && !levl
[sx
][sy
- 1].edge
609 && (int) levl
[sx
][sy
- 1].roomno
== rmno
)
611 else if (isok(sx
, sy
+ 1) && !levl
[sx
][sy
+ 1].edge
612 && (int) levl
[sx
][sy
+ 1].roomno
== rmno
)
616 } else if (sx
== sroom
->lx
- 1)
618 else if (sx
== sroom
->hx
+ 1)
620 else if (sy
== sroom
->ly
- 1)
622 else if (sy
== sroom
->hy
+ 1)
627 /* Said to happen sometimes, but I have never seen it. */
628 /* Supposedly fixed by fdoor change in mklev.c */
630 register int j
= sroom
->doorct
;
632 pline("Where is shopdoor?");
633 pline("Room at (%d,%d),(%d,%d).", sroom
->lx
, sroom
->ly
, sroom
->hx
,
635 pline("doormax=%d doorct=%d fdoor=%d", doorindex
, sroom
->doorct
,
638 pline("door [%d,%d]", doors
[sh
].x
, doors
[sh
].y
);
641 display_nhwindow(WIN_MESSAGE
, FALSE
);
648 (void) rloc(m_at(sx
, sy
), FALSE
); /* insurance */
650 /* now initialize the shopkeeper monster structure */
651 if (!(shk
= makemon(&mons
[PM_SHOPKEEPER
], sx
, sy
, MM_ESHK
)))
653 eshkp
= ESHK(shk
); /* makemon(...,MM_ESHK) allocates this */
654 shk
->isshk
= shk
->mpeaceful
= 1;
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
];
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
);
678 /* stock a newly-created room with objects */
680 stock_room(shp_indx
, sroom
)
682 register struct mkroom
*sroom
;
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
691 int stockcount
= 0, specialspot
= 0;
693 int rmno
= (int) ((sroom
- rooms
) + ROOMOFFSET
);
694 const struct shclass
*shp
= &shtypes
[shp_indx
];
696 /* first, try to place a shopkeeper in the room */
697 if ((sh
= shkinit(shp
, sroom
)) < 0)
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
;
707 if (levl
[sx
][sy
].typ
== SDOOR
) {
708 cvt_sdoor_to_door(&levl
[sx
][sy
]); /* .typ = DOOR */
711 if (levl
[sx
][sy
].doormask
& D_TRAPPED
)
712 levl
[sx
][sy
].doormask
= D_LOCKED
;
714 if (levl
[sx
][sy
].doormask
== D_LOCKED
) {
715 register int m
= sx
, n
= sy
;
717 if (inside_shop(sx
+ 1, sy
))
719 else if (inside_shop(sx
- 1, sy
))
721 if (inside_shop(sx
, sy
+ 1))
723 else if (inside_shop(sx
, sy
- 1))
725 Sprintf(buf
, "Closed for inventory");
726 make_engr_at(m
, n
, buf
, 0L, DUST
);
729 if (context
.tribute
.enabled
&& !context
.tribute
.bookstock
) {
731 * Out of the number of spots where we're actually
732 * going to put stuff, randomly single out one in particular.
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)
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))
748 specialspot
= rnd(stockcount
);
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)
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))
765 mkshobj_at(shp
, sx
, sy
,
766 ((stockcount
) && (stockcount
== specialspot
)));
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.
774 level
.flags
.has_shop
= TRUE
;
777 /* does shkp's shop stock this item type? */
783 int i
, shp_indx
= ESHK(shkp
)->shoptype
- SHOPBASE
;
784 const struct shclass
*shp
= &shtypes
[shp_indx
];
786 if (shp
->symb
== RANDOM_CLASS
)
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))
793 } else if ((shp
->iprobs
[i
].itype
< 0)
794 ? shp
->iprobs
[i
].itype
== -obj
->otyp
795 : shp
->iprobs
[i
].itype
== obj
->oclass
)
802 /* positive value: class; negative value: specific object type */
807 const struct shclass
*shp
= shtypes
+ type
;
810 /* select an appropriate object type at random */
811 for (j
= rnd(100), i
= 0; (j
-= shp
->iprobs
[i
].iprob
) > 0; i
++)
814 return shp
->iprobs
[i
].itype
;
821 const char *shknm
= ESHK(mtmp
)->shknam
;
823 if (Hallucination
&& !program_state
.gameover
) {
824 const char *const *nlp
;
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)
834 nlp
= shtypes
[rn2(num
)].shknms
;
835 for (num
= 0; nlp
[num
]; num
++)
838 shknm
= nlp
[rn2(num
)];
842 /* strip prefix if present */
849 shkname_is_pname(mtmp
)
852 const char *shknm
= ESHK(mtmp
)->shknam
;
854 return (boolean
) (*shknm
== '-' || *shknm
== '+' || *shknm
== '=');
858 is_izchak(shkp
, override_hallucination
)
860 boolean override_hallucination
;
864 if (Hallucination
&& !override_hallucination
)
868 /* outside of town, Izchak becomes just an ordinary shopkeeper */
869 if (!in_town(shkp
->mx
, shkp
->my
))
871 shknm
= ESHK(shkp
)->shknam
;
872 /* skip "+" prefix */
875 return (boolean
) !strcmp(shknm
, "Izchak");