1 /* NetHack 3.6 shknam.c $ANH-Date: 1454485432 2016/02/03 07:43:52 $ $ANH-Branch: master $:$ANH-Revision: 1.41 $ */
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(stock_room_goodpos
, (struct mkroom
*, int, int, int, int));
10 STATIC_DCL boolean
FDECL(veggy_item
, (struct obj
* obj
, int));
11 STATIC_DCL
int NDECL(shkveg
);
12 STATIC_DCL
void FDECL(mkveggy_at
, (int, int));
13 STATIC_DCL
void FDECL(mkshobj_at
, (const struct shclass
*, int, int,
15 STATIC_DCL
void FDECL(nameshk
, (struct monst
*, const char *const *));
16 STATIC_DCL
int FDECL(shkinit
, (const struct shclass
*, struct mkroom
*));
18 #define VEGETARIAN_CLASS (MAXOCLASSES + 1)
22 * dash - female, personal name
23 * underscore _ female, general name
24 * plus + male, personal name
25 * vertical bar | male, general name (implied for most of shktools)
26 * equals = gender not specified, personal name
28 * Personal names do not receive the honorific prefix "Mr." or "Ms.".
31 static const char *const shkliquors
[] = {
33 "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
37 "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja", "Narodnaja", "Kyzyl",
39 "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice", "Brzeg",
40 "Krnov", "Hradec Kralove",
42 "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm", "Flims",
43 "Vals", "Schuls", "Zum Loch", 0
46 static const char *const shkbooks
[] = {
48 "Skibbereen", "Kanturk", "Rath Luirc", "Ennistymon",
49 "Lahinch", "Kinnegad", "Lugnaquillia", "Enniscorthy",
50 "Gweebarra", "Kittamagh", "Nenagh", "Sneem",
51 "Ballingeary", "Kilgarvan", "Cahersiveen", "Glenbeigh",
52 "Kilmihil", "Kiltamagh", "Droichead Atha", "Inniscrone",
53 "Clonegal", "Lisnaskea", "Culdaff", "Dunfanaghy",
54 "Inishbofin", "Kesh", 0
57 static const char *const shkarmors
[] = {
59 "Demirci", "Kalecik", "Boyabai", "Yildizeli", "Gaziantep",
60 "Siirt", "Akhalataki", "Tirebolu", "Aksaray", "Ermenak",
61 "Iskenderun", "Kadirli", "Siverek", "Pervari", "Malasgirt",
62 "Bayburt", "Ayancik", "Zonguldak", "Balya", "Tefenni",
63 "Artvin", "Kars", "Makharadze", "Malazgirt", "Midyat",
64 "Birecik", "Kirikkale", "Alaca", "Polatli", "Nallihan",
68 static const char *const shkwands
[] = {
70 "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach", "Rhaeader",
71 "Llandrindod", "Llanfair-ym-muallt", "Y-Fenni", "Maesteg", "Rhydaman",
72 "Beddgelert", "Curig", "Llanrwst", "Llanerchymedd", "Caergybi",
74 "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar", "Kerloch",
75 "Beinn a Ghlo", "Drumnadrochit", "Morven", "Uist", "Storr",
76 "Sgurr na Ciche", "Cannich", "Gairloch", "Kyleakin", "Dunvegan", 0
79 static const char *const shkrings
[] = {
80 /* Hollandse familienamen */
81 "Feyfer", "Flugi", "Gheel", "Havic", "Haynin",
82 "Hoboken", "Imbyze", "Juyn", "Kinsky", "Massis",
83 "Matray", "Moy", "Olycan", "Sadelin", "Svaving",
84 "Tapper", "Terwen", "Wirix", "Ypey",
85 /* Skandinaviske navne */
86 "Rastegaisa", "Varjag Njarga", "Kautekeino", "Abisko", "Enontekis",
87 "Rovaniemi", "Avasaksa", "Haparanda", "Lulea", "Gellivare",
88 "Oeloe", "Kajaani", "Fauske", 0
91 static const char *const shkfoods
[] = {
93 "Djasinga", "Tjibarusa", "Tjiwidej", "Pengalengan",
94 "Bandjar", "Parbalingga", "Bojolali", "Sarangan",
95 "Ngebel", "Djombang", "Ardjawinangun", "Berbek",
96 "Papar", "Baliga", "Tjisolok", "Siboga",
97 "Banjoewangi", "Trenggalek", "Karangkobar", "Njalindoeng",
98 "Pasawahan", "Pameunpeuk", "Patjitan", "Kediri",
99 "Pemboeang", "Tringanoe", "Makin", "Tipor",
100 "Semai", "Berhala", "Tegal", "Samoe",
104 static const char *const shkweapons
[] = {
106 "Voulgezac", "Rouffiac", "Lerignac", "Touverac", "Guizengeard",
107 "Melac", "Neuvicq", "Vanzac", "Picq", "Urignac",
108 "Corignac", "Fleac", "Lonzac", "Vergt", "Queyssac",
109 "Liorac", "Echourgnac", "Cazelon", "Eypau", "Carignan",
110 "Monbazillac", "Jonzac", "Pons", "Jumilhac", "Fenouilledes",
111 "Laguiolet", "Saujon", "Eymoutiers", "Eygurande", "Eauze",
115 static const char *const shktools
[] = {
117 "Ymla", "Eed-morra", "Elan Lapinski", "Cubask", "Nieb", "Bnowr Falr",
118 "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
119 "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
120 "Nosnehpets", "Stewe", "Renrut", "Senna Hut", "-Zlaw", "Nosalnef",
121 "Rewuorb", "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah",
122 "Corsh", "Aned", "Dark Eery", "Niknar", "Lapu", "Lechaim",
123 "Rebrol-nek", "AlliWar Wickson", "Oguhmk", "Telloc Cyaj",
125 "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
131 "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
132 "Tonbar", "Kivenhoug", "Llardom",
135 "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
145 "Lez-tneg", "Ytnu-haled",
150 static const char *const shklight
[] = {
152 "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
153 "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
154 "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
156 "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli", "Pernik",
157 "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo", "Troyan",
158 "Lovech", "Sliven", 0
161 static const char *const shkgeneral
[] = {
163 "Hebiwerie", "Possogroenoe", "Asidonhopo", "Manlobbi",
164 "Adjama", "Pakka Pakka", "Kabalebo", "Wonotobo",
165 "Akalapi", "Sipaliwini",
167 "Annootok", "Upernavik", "Angmagssalik",
169 "Aklavik", "Inuvik", "Tuktoyaktuk", "Chicoutimi",
170 "Ouiatchouane", "Chibougamau", "Matagami", "Kipawa",
171 "Kinojevis", "Abitibi", "Maganasipi",
173 "Akureyri", "Kopasker", "Budereyri", "Akranes",
174 "Bordeyri", "Holmavik", 0
177 static const char *const shkhealthfoods
[] = {
179 "Ga'er", "Zhangmu", "Rikaze", "Jiangji", "Changdu",
180 "Linzhi", "Shigatse", "Gyantse", "Ganden", "Tsurphu",
181 "Lhasa", "Tsedong", "Drepung",
183 "=Azura", "=Blaze", "=Breanna", "=Breezy", "=Dharma",
184 "=Feather", "=Jasmine", "=Luna", "=Melody", "=Moonjava",
185 "=Petal", "=Rhiannon", "=Starla", "=Tranquilla", "=Windsong",
186 "=Zennia", "=Zoe", "=Zora", 0
190 * To add new shop types, all that is necessary is to edit the shtypes[]
191 * array. See mkroom.h for the structure definition. Typically, you'll
192 * have to lower some or all of the probability fields in old entries to
193 * free up some percentage for the new type.
195 * The placement type field is not yet used but will be in the near future.
197 * The iprobs array in each entry defines the probabilities for various kinds
198 * of objects to be present in the given shop type. You can associate with
199 * each percentage either a generic object type (represented by one of the
200 * *_CLASS macros) or a specific object (represented by an onames.h define).
201 * In the latter case, prepend it with a unary minus so the code can know
202 * (by testing the sign) whether to use mkobj() or mksobj().
204 const struct shclass shtypes
[] = {
209 { { 100, RANDOM_CLASS
},
216 { "used armor dealership",
220 { { 90, ARMOR_CLASS
},
221 { 10, WEAPON_CLASS
},
227 { "second-hand bookstore",
231 { { 90, SCROLL_CLASS
},
232 { 10, SPBOOK_CLASS
},
242 { { 100, POTION_CLASS
},
249 { "antique weapons outlet",
253 { { 90, WEAPON_CLASS
},
264 { { 83, FOOD_CLASS
},
265 { 5, -POT_FRUIT_JUICE
},
275 { { 85, RING_CLASS
},
282 { "quality apparel and accessories",
286 { { 90, WAND_CLASS
},
287 { 5, -LEATHER_GLOVES
},
295 { { 100, TOOL_CLASS
},
306 { { 90, SPBOOK_CLASS
},
307 { 10, SCROLL_CLASS
},
313 { "health food store",
317 { { 70, VEGETARIAN_CLASS
},
318 { 20, -POT_FRUIT_JUICE
},
320 { 3, -POT_FULL_HEALING
},
321 { 2, -SCR_FOOD_DETECTION
},
322 { 1, -LUMP_OF_ROYAL_JELLY
} },
324 /* Shops below this point are "unique". That is they must all have a
325 * probability of zero. They are only created via the special level
332 { { 30, -WAX_CANDLE
},
333 { 48, -TALLOW_CANDLE
},
334 { 5, -BRASS_LANTERN
},
344 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
349 /* validate shop probabilities; otherwise incorrect local changes could
350 end up provoking infinite loops or wild subscripts fetching garbage */
352 init_shop_selection()
354 register int i
, j
, item_prob
, shop_prob
;
356 for (shop_prob
= 0, i
= 0; i
< SIZE(shtypes
); i
++) {
357 shop_prob
+= shtypes
[i
].prob
;
358 for (item_prob
= 0, j
= 0; j
< SIZE(shtypes
[0].iprobs
); j
++)
359 item_prob
+= shtypes
[i
].iprobs
[j
].iprob
;
360 if (item_prob
!= 100)
361 panic("item probabilities total to %d for %s shops!",
362 item_prob
, shtypes
[i
].name
);
364 if (shop_prob
!= 100)
365 panic("shop probabilities total to %d!", shop_prob
);
369 /* decide whether an object or object type is considered vegetarian;
370 for types, items which might go either way are assumed to be veggy */
372 veggy_item(obj
, otyp
)
374 int otyp
; /* used iff obj is null */
380 /* actual object; will check tin content and corpse species */
381 otyp
= (int) obj
->otyp
;
382 oclass
= obj
->oclass
;
383 corpsenm
= obj
->corpsenm
;
385 /* just a type; caller will have to handle tins and corpses */
386 oclass
= objects
[otyp
].oc_class
;
387 corpsenm
= PM_LICHEN
; /* veggy standin */
390 if (oclass
== FOOD_CLASS
) {
391 if (objects
[otyp
].oc_material
== VEGGY
|| otyp
== EGG
)
393 if (otyp
== TIN
&& corpsenm
== NON_PM
) /* implies obj is non-null */
394 return (boolean
) (obj
->spe
== 1); /* 0 = empty, 1 = spinach */
395 if (otyp
== TIN
|| otyp
== CORPSE
)
396 return (boolean
) (corpsenm
>= LOW_PM
397 && vegetarian(&mons
[corpsenm
]));
405 int i
, j
, maxprob
, prob
;
406 char oclass
= FOOD_CLASS
;
410 ok
[0] = 0; /* lint suppression */
411 for (i
= bases
[(int) oclass
]; i
< NUM_OBJECTS
; ++i
) {
412 if (objects
[i
].oc_class
!= oclass
)
415 if (veggy_item((struct obj
*) 0, i
)) {
417 maxprob
+= objects
[i
].oc_prob
;
421 panic("shkveg no veggy objects");
426 while ((prob
-= objects
[i
].oc_prob
) > 0) {
431 if (objects
[i
].oc_class
!= oclass
|| !OBJ_NAME(objects
[i
]))
432 panic("shkveg probtype error, oclass=%d i=%d", (int) oclass
, i
);
436 /* make a random item for health food store */
441 struct obj
*obj
= mksobj_at(shkveg(), sx
, sy
, TRUE
, TRUE
);
443 if (obj
&& obj
->otyp
== TIN
)
444 set_tin_variety(obj
, HEALTHY_TIN
);
448 /* make an object of the appropriate type for a shop square */
450 mkshobj_at(shp
, sx
, sy
, mkspecl
)
451 const struct shclass
*shp
;
456 struct permonst
*ptr
;
460 if (mkspecl
&& (!strcmp(shp
->name
, "rare books")
461 || !strcmp(shp
->name
, "second-hand bookstore"))) {
462 struct obj
*novel
= mksobj_at(SPE_NOVEL
, sx
, sy
, FALSE
, FALSE
);
465 context
.tribute
.bookstock
= TRUE
;
469 if (rn2(100) < depth(&u
.uz
) && !MON_AT(sx
, sy
)
470 && (ptr
= mkclass(S_MIMIC
, 0)) != 0
471 && (mtmp
= makemon(ptr
, sx
, sy
, NO_MM_FLAGS
)) != 0) {
472 /* note: makemon will set the mimic symbol to a shop item */
473 if (rn2(10) >= depth(&u
.uz
)) {
474 mtmp
->m_ap_type
= M_AP_OBJECT
;
475 mtmp
->mappearance
= STRANGE_OBJECT
;
478 atype
= get_shop_item((int) (shp
- shtypes
));
479 if (atype
== VEGETARIAN_CLASS
)
482 (void) mksobj_at(-atype
, sx
, sy
, TRUE
, TRUE
);
484 (void) mkobj_at(atype
, sx
, sy
, TRUE
);
488 /* extract a shopkeeper name for the given shop type */
492 const char *const *nlp
;
494 int i
, trycnt
, names_avail
;
495 const char *shname
= 0;
500 if (nlp
== shkfoods
&& In_mines(&u
.uz
) && Role_if(PM_MONK
)
501 && (sptr
= Is_special(&u
.uz
)) != 0 && sptr
->flags
.town
) {
502 /* special-case override for minetown food store for monks */
503 nlp
= shkhealthfoods
;
506 if (nlp
== shklight
&& In_mines(&u
.uz
) && (sptr
= Is_special(&u
.uz
)) != 0
507 && sptr
->flags
.town
) {
508 /* special-case minetown lighting shk */
512 /* We want variation from game to game, without needing the save
513 and restore support which would be necessary for randomization;
514 try not to make too many assumptions about time_t's internals;
515 use ledger_no rather than depth to keep mine town distinct. */
516 int nseed
= (int) ((long) ubirthday
/ 257L);
518 name_wanted
= ledger_no(&u
.uz
) + (nseed
% 13) - (nseed
% 5);
520 name_wanted
+= (13 + 5);
521 shk
->female
= name_wanted
& 1;
523 for (names_avail
= 0; nlp
[names_avail
]; names_avail
++)
526 for (trycnt
= 0; trycnt
< 50; trycnt
++) {
527 if (nlp
== shktools
) {
528 shname
= shktools
[rn2(names_avail
)];
529 shk
->female
= 0; /* reversed below for '_' prefix */
530 } else if (name_wanted
< names_avail
) {
531 shname
= nlp
[name_wanted
];
532 } else if ((i
= rn2(names_avail
)) != 0) {
534 } else if (nlp
!= shkgeneral
) {
535 nlp
= shkgeneral
; /* try general names */
536 for (names_avail
= 0; nlp
[names_avail
]; names_avail
++)
538 continue; /* next `trycnt' iteration */
540 shname
= shk
->female
? "-Lucrezia" : "+Dirk";
542 if (*shname
== '_' || *shname
== '-')
544 else if (*shname
== '|' || *shname
== '+')
547 /* is name already in use on this level? */
548 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
549 if (DEADMONSTER(mtmp
) || (mtmp
== shk
) || !mtmp
->isshk
)
551 if (strcmp(ESHK(mtmp
)->shknam
, shname
))
556 break; /* new name */
559 (void) strncpy(ESHK(shk
)->shknam
, shname
, PL_NSIZ
);
560 ESHK(shk
)->shknam
[PL_NSIZ
- 1] = 0;
568 mtmp
->mextra
= newmextra();
570 ESHK(mtmp
) = (struct eshk
*) alloc(sizeof(struct eshk
));
571 (void) memset((genericptr_t
) ESHK(mtmp
), 0, sizeof(struct eshk
));
572 ESHK(mtmp
)->bill_p
= (struct bill_x
*) 0;
579 if (mtmp
->mextra
&& ESHK(mtmp
)) {
580 free((genericptr_t
) ESHK(mtmp
));
581 ESHK(mtmp
) = (struct eshk
*) 0;
586 /* create a new shopkeeper in the given room */
589 const struct shclass
*shp
;
590 struct mkroom
*sroom
;
592 register int sh
, sx
, sy
;
596 /* place the shopkeeper in the given room */
601 /* check that the shopkeeper placement is sane */
602 if (sroom
->irregular
) {
603 int rmno
= (int) ((sroom
- rooms
) + ROOMOFFSET
);
604 if (isok(sx
- 1, sy
) && !levl
[sx
- 1][sy
].edge
605 && (int) levl
[sx
- 1][sy
].roomno
== rmno
)
607 else if (isok(sx
+ 1, sy
) && !levl
[sx
+ 1][sy
].edge
608 && (int) levl
[sx
+ 1][sy
].roomno
== rmno
)
610 else if (isok(sx
, sy
- 1) && !levl
[sx
][sy
- 1].edge
611 && (int) levl
[sx
][sy
- 1].roomno
== rmno
)
613 else if (isok(sx
, sy
+ 1) && !levl
[sx
][sy
+ 1].edge
614 && (int) levl
[sx
][sy
+ 1].roomno
== rmno
)
618 } else if (sx
== sroom
->lx
- 1)
620 else if (sx
== sroom
->hx
+ 1)
622 else if (sy
== sroom
->ly
- 1)
624 else if (sy
== sroom
->hy
+ 1)
629 /* Said to happen sometimes, but I have never seen it. */
630 /* Supposedly fixed by fdoor change in mklev.c */
632 register int j
= sroom
->doorct
;
634 pline("Where is shopdoor?");
635 pline("Room at (%d,%d),(%d,%d).", sroom
->lx
, sroom
->ly
, sroom
->hx
,
637 pline("doormax=%d doorct=%d fdoor=%d", doorindex
, sroom
->doorct
,
640 pline("door [%d,%d]", doors
[sh
].x
, doors
[sh
].y
);
643 display_nhwindow(WIN_MESSAGE
, FALSE
);
650 (void) rloc(m_at(sx
, sy
), FALSE
); /* insurance */
652 /* now initialize the shopkeeper monster structure */
653 if (!(shk
= makemon(&mons
[PM_SHOPKEEPER
], sx
, sy
, MM_ESHK
)))
655 eshkp
= ESHK(shk
); /* makemon(...,MM_ESHK) allocates this */
656 shk
->isshk
= shk
->mpeaceful
= 1;
659 shk
->mtrapseen
= ~0; /* we know all the traps already */
660 eshkp
->shoproom
= (schar
) ((sroom
- rooms
) + ROOMOFFSET
);
661 sroom
->resident
= shk
;
662 eshkp
->shoptype
= sroom
->rtype
;
663 assign_level(&eshkp
->shoplevel
, &u
.uz
);
664 eshkp
->shd
= doors
[sh
];
667 eshkp
->robbed
= eshkp
->credit
= eshkp
->debit
= eshkp
->loan
= 0L;
668 eshkp
->following
= eshkp
->surcharge
= eshkp
->dismiss_kops
= FALSE
;
669 eshkp
->billct
= eshkp
->visitct
= 0;
670 eshkp
->bill_p
= (struct bill_x
*) 0;
671 eshkp
->customer
[0] = '\0';
672 mkmonmoney(shk
, 1000L + 30L * (long) rnd(100)); /* initial capital */
673 if (shp
->shknms
== shkrings
)
674 (void) mongets(shk
, TOUCHSTONE
);
675 nameshk(shk
, shp
->shknms
);
681 stock_room_goodpos(sroom
, rmno
, sh
, sx
, sy
)
682 struct mkroom
*sroom
;
685 if (sroom
->irregular
) {
686 if (levl
[sx
][sy
].edge
687 || (int) levl
[sx
][sy
].roomno
!= rmno
688 || distmin(sx
, sy
, doors
[sh
].x
, doors
[sh
].y
) <= 1)
690 } else if ((sx
== sroom
->lx
&& doors
[sh
].x
== sx
- 1)
691 || (sx
== sroom
->hx
&& doors
[sh
].x
== sx
+ 1)
692 || (sy
== sroom
->ly
&& doors
[sh
].y
== sy
- 1)
693 || (sy
== sroom
->hy
&& doors
[sh
].y
== sy
+ 1))
698 /* stock a newly-created room with objects */
700 stock_room(shp_indx
, sroom
)
702 register struct mkroom
*sroom
;
705 * Someday soon we'll dispatch on the shdist field of shclass to do
706 * different placements in this routine. Currently it only supports
707 * shop-style placement (all squares except a row nearest the first
711 int stockcount
= 0, specialspot
= 0;
713 int rmno
= (int) ((sroom
- rooms
) + ROOMOFFSET
);
714 const struct shclass
*shp
= &shtypes
[shp_indx
];
716 /* first, try to place a shopkeeper in the room */
717 if ((sh
= shkinit(shp
, sroom
)) < 0)
720 /* make sure no doorways without doors, and no trapped doors, in shops */
721 sx
= doors
[sroom
->fdoor
].x
;
722 sy
= doors
[sroom
->fdoor
].y
;
723 if (levl
[sx
][sy
].doormask
== D_NODOOR
) {
724 levl
[sx
][sy
].doormask
= D_ISOPEN
;
727 if (levl
[sx
][sy
].typ
== SDOOR
) {
728 cvt_sdoor_to_door(&levl
[sx
][sy
]); /* .typ = DOOR */
731 if (levl
[sx
][sy
].doormask
& D_TRAPPED
)
732 levl
[sx
][sy
].doormask
= D_LOCKED
;
734 if (levl
[sx
][sy
].doormask
== D_LOCKED
) {
735 register int m
= sx
, n
= sy
;
737 if (inside_shop(sx
+ 1, sy
))
739 else if (inside_shop(sx
- 1, sy
))
741 if (inside_shop(sx
, sy
+ 1))
743 else if (inside_shop(sx
, sy
- 1))
745 Sprintf(buf
, "Closed for inventory");
746 make_engr_at(m
, n
, buf
, 0L, DUST
);
749 if (context
.tribute
.enabled
&& !context
.tribute
.bookstock
) {
751 * Out of the number of spots where we're actually
752 * going to put stuff, randomly single out one in particular.
754 for (sx
= sroom
->lx
; sx
<= sroom
->hx
; sx
++)
755 for (sy
= sroom
->ly
; sy
<= sroom
->hy
; sy
++)
756 if (stock_room_goodpos(sroom
, rmno
, sh
, sx
,sy
))
758 specialspot
= rnd(stockcount
);
762 for (sx
= sroom
->lx
; sx
<= sroom
->hx
; sx
++)
763 for (sy
= sroom
->ly
; sy
<= sroom
->hy
; sy
++)
764 if (stock_room_goodpos(sroom
, rmno
, sh
, sx
,sy
)) {
766 mkshobj_at(shp
, sx
, sy
,
767 ((stockcount
) && (stockcount
== specialspot
)));
771 * Special monster placements (if any) should go here: that way,
772 * monsters will sit on top of objects and not the other way around.
775 level
.flags
.has_shop
= TRUE
;
778 /* does shkp's shop stock this item type? */
784 int i
, shp_indx
= ESHK(shkp
)->shoptype
- SHOPBASE
;
785 const struct shclass
*shp
= &shtypes
[shp_indx
];
787 if (shp
->symb
== RANDOM_CLASS
)
789 for (i
= 0; i
< SIZE(shtypes
[0].iprobs
) && shp
->iprobs
[i
].iprob
; i
++) {
790 /* pseudo-class needs special handling */
791 if (shp
->iprobs
[i
].itype
== VEGETARIAN_CLASS
) {
792 if (veggy_item(obj
, 0))
794 } else if ((shp
->iprobs
[i
].itype
< 0)
795 ? shp
->iprobs
[i
].itype
== -obj
->otyp
796 : shp
->iprobs
[i
].itype
== obj
->oclass
)
803 /* positive value: class; negative value: specific object type */
808 const struct shclass
*shp
= shtypes
+ type
;
811 /* select an appropriate object type at random */
812 for (j
= rnd(100), i
= 0; (j
-= shp
->iprobs
[i
].iprob
) > 0; i
++)
815 return shp
->iprobs
[i
].itype
;
818 /* version of shkname() for beginning of sentence */
823 char *nam
= shkname(mtmp
);
825 /* 'nam[]' is almost certainly already capitalized, but be sure */
826 nam
[0] = highc(nam
[0]);
830 /* shopkeeper's name, without any visibility constraint; if hallucinating,
831 will yield some other shopkeeper's name (not necessarily one residing
832 in the current game's dungeon, or who keeps same type of shop) */
838 unsigned save_isshk
= mtmp
->isshk
;
840 mtmp
->isshk
= 0; /* don't want mon_nam() calling shkname() */
841 /* get a modifiable name buffer along with fallback result */
842 nam
= noit_mon_nam(mtmp
);
843 mtmp
->isshk
= save_isshk
;
846 impossible("shkname: \"%s\" is not a shopkeeper.", nam
);
847 } else if (!has_eshk(mtmp
)) {
848 panic("shkname: shopkeeper \"%s\" lacks 'eshk' data.", nam
);
850 const char *shknm
= ESHK(mtmp
)->shknam
;
852 if (Hallucination
&& !program_state
.gameover
) {
853 const char *const *nlp
;
856 /* count the number of non-unique shop types;
857 pick one randomly, ignoring shop generation probabilities;
858 pick a name at random from that shop type's list */
859 for (num
= 0; num
< SIZE(shtypes
); num
++)
860 if (shtypes
[num
].prob
== 0)
863 nlp
= shtypes
[rn2(num
)].shknms
;
864 for (num
= 0; nlp
[num
]; num
++)
867 shknm
= nlp
[rn2(num
)];
870 /* strip prefix if present */
879 shkname_is_pname(mtmp
)
882 const char *shknm
= ESHK(mtmp
)->shknam
;
884 return (boolean
) (*shknm
== '-' || *shknm
== '+' || *shknm
== '=');
888 is_izchak(shkp
, override_hallucination
)
890 boolean override_hallucination
;
894 if (Hallucination
&& !override_hallucination
)
898 /* outside of town, Izchak becomes just an ordinary shopkeeper */
899 if (!in_town(shkp
->mx
, shkp
->my
))
901 shknm
= ESHK(shkp
)->shknam
;
902 /* skip "+" prefix */
905 return (boolean
) !strcmp(shknm
, "Izchak");