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 /* 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", "Elan Lapinski", "Cubask", "Nieb", "Bnowr Falr",
117 "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
118 "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar", "Yelpur",
119 "Nosnehpets", "Stewe", "Renrut", "Senna Hut", "-Zlaw", "Nosalnef",
120 "Rewuorb", "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah",
121 "Corsh", "Aned", "Dark Eery", "Niknar", "Lapu", "Lechaim",
122 "Rebrol-nek", "AlliWar Wickson", "Oguhmk", "Telloc Cyaj",
124 "Erreip", "Nehpets", "Mron", "Snivek", "Kahztiy",
130 "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", "Yao-hang",
131 "Tonbar", "Kivenhoug", "Llardom",
134 "Falo", "Nosid-da\'r", "Ekim-p", "Noslo", "Yl-rednow", "Mured-oog",
144 "Lez-tneg", "Ytnu-haled",
149 static const char *const shklight
[] = {
151 "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
152 "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
153 "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
155 "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli", "Pernik",
156 "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo", "Troyan",
157 "Lovech", "Sliven", 0
160 static const char *const shkgeneral
[] = {
162 "Hebiwerie", "Possogroenoe", "Asidonhopo", "Manlobbi",
163 "Adjama", "Pakka Pakka", "Kabalebo", "Wonotobo",
164 "Akalapi", "Sipaliwini",
166 "Annootok", "Upernavik", "Angmagssalik",
168 "Aklavik", "Inuvik", "Tuktoyaktuk", "Chicoutimi",
169 "Ouiatchouane", "Chibougamau", "Matagami", "Kipawa",
170 "Kinojevis", "Abitibi", "Maganasipi",
172 "Akureyri", "Kopasker", "Budereyri", "Akranes",
173 "Bordeyri", "Holmavik", 0
176 static const char *const shkhealthfoods
[] = {
178 "Ga'er", "Zhangmu", "Rikaze", "Jiangji", "Changdu",
179 "Linzhi", "Shigatse", "Gyantse", "Ganden", "Tsurphu",
180 "Lhasa", "Tsedong", "Drepung",
182 "=Azura", "=Blaze", "=Breanna", "=Breezy", "=Dharma",
183 "=Feather", "=Jasmine", "=Luna", "=Melody", "=Moonjava",
184 "=Petal", "=Rhiannon", "=Starla", "=Tranquilla", "=Windsong",
185 "=Zennia", "=Zoe", "=Zora", 0
189 * To add new shop types, all that is necessary is to edit the shtypes[]
190 * array. See mkroom.h for the structure definition. Typically, you'll
191 * have to lower some or all of the probability fields in old entries to
192 * free up some percentage for the new type.
194 * The placement type field is not yet used but will be in the near future.
196 * The iprobs array in each entry defines the probabilities for various kinds
197 * of objects to be present in the given shop type. You can associate with
198 * each percentage either a generic object type (represented by one of the
199 * *_CLASS macros) or a specific object (represented by an onames.h define).
200 * In the latter case, prepend it with a unary minus so the code can know
201 * (by testing the sign) whether to use mkobj() or mksobj().
203 const struct shclass shtypes
[] = {
208 { { 100, RANDOM_CLASS
},
215 { "used armor dealership",
219 { { 90, ARMOR_CLASS
},
220 { 10, WEAPON_CLASS
},
226 { "second-hand bookstore",
230 { { 90, SCROLL_CLASS
},
231 { 10, SPBOOK_CLASS
},
241 { { 100, POTION_CLASS
},
248 { "antique weapons outlet",
252 { { 90, WEAPON_CLASS
},
263 { { 83, FOOD_CLASS
},
264 { 5, -POT_FRUIT_JUICE
},
274 { { 85, RING_CLASS
},
281 { "quality apparel and accessories",
285 { { 90, WAND_CLASS
},
286 { 5, -LEATHER_GLOVES
},
294 { { 100, TOOL_CLASS
},
305 { { 90, SPBOOK_CLASS
},
306 { 10, SCROLL_CLASS
},
312 { "health food store",
316 { { 70, VEGETARIAN_CLASS
},
317 { 20, -POT_FRUIT_JUICE
},
319 { 3, -POT_FULL_HEALING
},
320 { 2, -SCR_FOOD_DETECTION
},
321 { 1, -LUMP_OF_ROYAL_JELLY
} },
323 /* Shops below this point are "unique". That is they must all have a
324 * probability of zero. They are only created via the special level
331 { { 30, -WAX_CANDLE
},
332 { 48, -TALLOW_CANDLE
},
333 { 5, -BRASS_LANTERN
},
343 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
348 /* validate shop probabilities; otherwise incorrect local changes could
349 end up provoking infinite loops or wild subscripts fetching garbage */
351 init_shop_selection()
353 register int i
, j
, item_prob
, shop_prob
;
355 for (shop_prob
= 0, i
= 0; i
< SIZE(shtypes
); i
++) {
356 shop_prob
+= shtypes
[i
].prob
;
357 for (item_prob
= 0, j
= 0; j
< SIZE(shtypes
[0].iprobs
); j
++)
358 item_prob
+= shtypes
[i
].iprobs
[j
].iprob
;
359 if (item_prob
!= 100)
360 panic("item probabilities total to %d for %s shops!",
361 item_prob
, shtypes
[i
].name
);
363 if (shop_prob
!= 100)
364 panic("shop probabilities total to %d!", shop_prob
);
368 /* decide whether an object or object type is considered vegetarian;
369 for types, items which might go either way are assumed to be veggy */
371 veggy_item(obj
, otyp
)
373 int otyp
; /* used iff obj is null */
379 /* actual object; will check tin content and corpse species */
380 otyp
= (int) obj
->otyp
;
381 oclass
= obj
->oclass
;
382 corpsenm
= obj
->corpsenm
;
384 /* just a type; caller will have to handle tins and corpses */
385 oclass
= objects
[otyp
].oc_class
;
386 corpsenm
= PM_LICHEN
; /* veggy standin */
389 if (oclass
== FOOD_CLASS
) {
390 if (objects
[otyp
].oc_material
== VEGGY
|| otyp
== EGG
)
392 if (otyp
== TIN
&& corpsenm
== NON_PM
) /* implies obj is non-null */
393 return (boolean
) (obj
->spe
== 1); /* 0 = empty, 1 = spinach */
394 if (otyp
== TIN
|| otyp
== CORPSE
)
395 return (boolean
) (corpsenm
>= LOW_PM
396 && vegetarian(&mons
[corpsenm
]));
404 int i
, j
, maxprob
, prob
;
405 char oclass
= FOOD_CLASS
;
409 ok
[0] = 0; /* lint suppression */
410 for (i
= bases
[(int) oclass
]; i
< NUM_OBJECTS
; ++i
) {
411 if (objects
[i
].oc_class
!= oclass
)
414 if (veggy_item((struct obj
*) 0, i
)) {
416 maxprob
+= objects
[i
].oc_prob
;
420 panic("shkveg no veggy objects");
425 while ((prob
-= objects
[i
].oc_prob
) > 0) {
430 if (objects
[i
].oc_class
!= oclass
|| !OBJ_NAME(objects
[i
]))
431 panic("shkveg probtype error, oclass=%d i=%d", (int) oclass
, i
);
435 /* make a random item for health food store */
440 struct obj
*obj
= mksobj_at(shkveg(), sx
, sy
, TRUE
, TRUE
);
442 if (obj
&& obj
->otyp
== TIN
)
443 set_tin_variety(obj
, HEALTHY_TIN
);
447 /* make an object of the appropriate type for a shop square */
449 mkshobj_at(shp
, sx
, sy
, mkspecl
)
450 const struct shclass
*shp
;
455 struct permonst
*ptr
;
459 if (mkspecl
&& (!strcmp(shp
->name
, "rare books")
460 || !strcmp(shp
->name
, "second-hand bookstore"))) {
461 struct obj
*novel
= mksobj_at(SPE_NOVEL
, sx
, sy
, FALSE
, FALSE
);
464 context
.tribute
.bookstock
= TRUE
;
468 if (rn2(100) < depth(&u
.uz
) && !MON_AT(sx
, sy
)
469 && (ptr
= mkclass(S_MIMIC
, 0)) != 0
470 && (mtmp
= makemon(ptr
, sx
, sy
, NO_MM_FLAGS
)) != 0) {
471 /* note: makemon will set the mimic symbol to a shop item */
472 if (rn2(10) >= depth(&u
.uz
)) {
473 mtmp
->m_ap_type
= M_AP_OBJECT
;
474 mtmp
->mappearance
= STRANGE_OBJECT
;
477 atype
= get_shop_item((int) (shp
- shtypes
));
478 if (atype
== VEGETARIAN_CLASS
)
481 (void) mksobj_at(-atype
, sx
, sy
, TRUE
, TRUE
);
483 (void) mkobj_at(atype
, sx
, sy
, TRUE
);
487 /* extract a shopkeeper name for the given shop type */
491 const char *const *nlp
;
493 int i
, trycnt
, names_avail
;
494 const char *shname
= 0;
499 if (nlp
== shkfoods
&& In_mines(&u
.uz
) && Role_if(PM_MONK
)
500 && (sptr
= Is_special(&u
.uz
)) != 0 && sptr
->flags
.town
) {
501 /* special-case override for minetown food store for monks */
502 nlp
= shkhealthfoods
;
505 if (nlp
== shklight
&& In_mines(&u
.uz
) && (sptr
= Is_special(&u
.uz
)) != 0
506 && sptr
->flags
.town
) {
507 /* special-case minetown lighting shk */
511 /* We want variation from game to game, without needing the save
512 and restore support which would be necessary for randomization;
513 try not to make too many assumptions about time_t's internals;
514 use ledger_no rather than depth to keep mine town distinct. */
515 int nseed
= (int) ((long) ubirthday
/ 257L);
517 name_wanted
= ledger_no(&u
.uz
) + (nseed
% 13) - (nseed
% 5);
519 name_wanted
+= (13 + 5);
520 shk
->female
= name_wanted
& 1;
522 for (names_avail
= 0; nlp
[names_avail
]; names_avail
++)
525 for (trycnt
= 0; trycnt
< 50; trycnt
++) {
526 if (nlp
== shktools
) {
527 shname
= shktools
[rn2(names_avail
)];
528 shk
->female
= 0; /* reversed below for '_' prefix */
529 } else if (name_wanted
< names_avail
) {
530 shname
= nlp
[name_wanted
];
531 } else if ((i
= rn2(names_avail
)) != 0) {
533 } else if (nlp
!= shkgeneral
) {
534 nlp
= shkgeneral
; /* try general names */
535 for (names_avail
= 0; nlp
[names_avail
]; names_avail
++)
537 continue; /* next `trycnt' iteration */
539 shname
= shk
->female
? "-Lucrezia" : "+Dirk";
541 if (*shname
== '_' || *shname
== '-')
543 else if (*shname
== '|' || *shname
== '+')
546 /* is name already in use on this level? */
547 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
548 if (DEADMONSTER(mtmp
) || (mtmp
== shk
) || !mtmp
->isshk
)
550 if (strcmp(ESHK(mtmp
)->shknam
, shname
))
555 break; /* new name */
558 (void) strncpy(ESHK(shk
)->shknam
, shname
, PL_NSIZ
);
559 ESHK(shk
)->shknam
[PL_NSIZ
- 1] = 0;
567 mtmp
->mextra
= newmextra();
569 ESHK(mtmp
) = (struct eshk
*) alloc(sizeof(struct eshk
));
570 (void) memset((genericptr_t
) ESHK(mtmp
), 0, sizeof(struct eshk
));
571 ESHK(mtmp
)->bill_p
= (struct bill_x
*) 0;
578 if (mtmp
->mextra
&& ESHK(mtmp
)) {
579 free((genericptr_t
) ESHK(mtmp
));
580 ESHK(mtmp
) = (struct eshk
*) 0;
585 /* create a new shopkeeper in the given room */
588 const struct shclass
*shp
;
589 struct mkroom
*sroom
;
591 register int sh
, sx
, sy
;
595 /* place the shopkeeper in the given room */
600 /* check that the shopkeeper placement is sane */
601 if (sroom
->irregular
) {
602 int rmno
= (int) ((sroom
- rooms
) + ROOMOFFSET
);
603 if (isok(sx
- 1, sy
) && !levl
[sx
- 1][sy
].edge
604 && (int) levl
[sx
- 1][sy
].roomno
== rmno
)
606 else if (isok(sx
+ 1, sy
) && !levl
[sx
+ 1][sy
].edge
607 && (int) levl
[sx
+ 1][sy
].roomno
== rmno
)
609 else if (isok(sx
, sy
- 1) && !levl
[sx
][sy
- 1].edge
610 && (int) levl
[sx
][sy
- 1].roomno
== rmno
)
612 else if (isok(sx
, sy
+ 1) && !levl
[sx
][sy
+ 1].edge
613 && (int) levl
[sx
][sy
+ 1].roomno
== rmno
)
617 } else if (sx
== sroom
->lx
- 1)
619 else if (sx
== sroom
->hx
+ 1)
621 else if (sy
== sroom
->ly
- 1)
623 else if (sy
== sroom
->hy
+ 1)
628 /* Said to happen sometimes, but I have never seen it. */
629 /* Supposedly fixed by fdoor change in mklev.c */
631 register int j
= sroom
->doorct
;
633 pline("Where is shopdoor?");
634 pline("Room at (%d,%d),(%d,%d).", sroom
->lx
, sroom
->ly
, sroom
->hx
,
636 pline("doormax=%d doorct=%d fdoor=%d", doorindex
, sroom
->doorct
,
639 pline("door [%d,%d]", doors
[sh
].x
, doors
[sh
].y
);
642 display_nhwindow(WIN_MESSAGE
, FALSE
);
649 (void) rloc(m_at(sx
, sy
), FALSE
); /* insurance */
651 /* now initialize the shopkeeper monster structure */
652 if (!(shk
= makemon(&mons
[PM_SHOPKEEPER
], sx
, sy
, MM_ESHK
)))
654 eshkp
= ESHK(shk
); /* makemon(...,MM_ESHK) allocates this */
655 shk
->isshk
= shk
->mpeaceful
= 1;
658 shk
->mtrapseen
= ~0; /* we know all the traps already */
659 eshkp
->shoproom
= (schar
) ((sroom
- rooms
) + ROOMOFFSET
);
660 sroom
->resident
= shk
;
661 eshkp
->shoptype
= sroom
->rtype
;
662 assign_level(&eshkp
->shoplevel
, &u
.uz
);
663 eshkp
->shd
= doors
[sh
];
666 eshkp
->robbed
= eshkp
->credit
= eshkp
->debit
= eshkp
->loan
= 0L;
667 eshkp
->following
= eshkp
->surcharge
= eshkp
->dismiss_kops
= FALSE
;
668 eshkp
->billct
= eshkp
->visitct
= 0;
669 eshkp
->bill_p
= (struct bill_x
*) 0;
670 eshkp
->customer
[0] = '\0';
671 mkmonmoney(shk
, 1000L + 30L * (long) rnd(100)); /* initial capital */
672 if (shp
->shknms
== shkrings
)
673 (void) mongets(shk
, TOUCHSTONE
);
674 nameshk(shk
, shp
->shknms
);
679 /* stock a newly-created room with objects */
681 stock_room(shp_indx
, sroom
)
683 register struct mkroom
*sroom
;
686 * Someday soon we'll dispatch on the shdist field of shclass to do
687 * different placements in this routine. Currently it only supports
688 * shop-style placement (all squares except a row nearest the first
692 int stockcount
= 0, specialspot
= 0;
694 int rmno
= (int) ((sroom
- rooms
) + ROOMOFFSET
);
695 const struct shclass
*shp
= &shtypes
[shp_indx
];
697 /* first, try to place a shopkeeper in the room */
698 if ((sh
= shkinit(shp
, sroom
)) < 0)
701 /* make sure no doorways without doors, and no trapped doors, in shops */
702 sx
= doors
[sroom
->fdoor
].x
;
703 sy
= doors
[sroom
->fdoor
].y
;
704 if (levl
[sx
][sy
].doormask
== D_NODOOR
) {
705 levl
[sx
][sy
].doormask
= D_ISOPEN
;
708 if (levl
[sx
][sy
].typ
== SDOOR
) {
709 cvt_sdoor_to_door(&levl
[sx
][sy
]); /* .typ = DOOR */
712 if (levl
[sx
][sy
].doormask
& D_TRAPPED
)
713 levl
[sx
][sy
].doormask
= D_LOCKED
;
715 if (levl
[sx
][sy
].doormask
== D_LOCKED
) {
716 register int m
= sx
, n
= sy
;
718 if (inside_shop(sx
+ 1, sy
))
720 else if (inside_shop(sx
- 1, sy
))
722 if (inside_shop(sx
, sy
+ 1))
724 else if (inside_shop(sx
, sy
- 1))
726 Sprintf(buf
, "Closed for inventory");
727 make_engr_at(m
, n
, buf
, 0L, DUST
);
730 if (context
.tribute
.enabled
&& !context
.tribute
.bookstock
) {
732 * Out of the number of spots where we're actually
733 * going to put stuff, randomly single out one in particular.
735 for (sx
= sroom
->lx
; sx
<= sroom
->hx
; sx
++)
736 for (sy
= sroom
->ly
; sy
<= sroom
->hy
; sy
++) {
737 if (sroom
->irregular
) {
738 if (levl
[sx
][sy
].edge
739 || (int) levl
[sx
][sy
].roomno
!= rmno
740 || distmin(sx
, sy
, doors
[sh
].x
, doors
[sh
].y
) <= 1)
742 } else if ((sx
== sroom
->lx
&& doors
[sh
].x
== sx
- 1)
743 || (sx
== sroom
->hx
&& doors
[sh
].x
== sx
+ 1)
744 || (sy
== sroom
->ly
&& doors
[sh
].y
== sy
- 1)
745 || (sy
== sroom
->hy
&& doors
[sh
].y
== sy
+ 1))
749 specialspot
= rnd(stockcount
);
753 for (sx
= sroom
->lx
; sx
<= sroom
->hx
; sx
++)
754 for (sy
= sroom
->ly
; sy
<= sroom
->hy
; sy
++) {
755 if (sroom
->irregular
) {
756 if (levl
[sx
][sy
].edge
757 || (int) levl
[sx
][sy
].roomno
!= rmno
758 || distmin(sx
, sy
, doors
[sh
].x
, doors
[sh
].y
) <= 1)
760 } else if ((sx
== sroom
->lx
&& doors
[sh
].x
== sx
- 1)
761 || (sx
== sroom
->hx
&& doors
[sh
].x
== sx
+ 1)
762 || (sy
== sroom
->ly
&& doors
[sh
].y
== sy
- 1)
763 || (sy
== sroom
->hy
&& doors
[sh
].y
== sy
+ 1))
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");