1 /*	SCCS Id: @(#)shknam.c	3.4	2003/01/09	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /* shknam.c -- initialize a shop */
6 
7 #include "hack.h"
8 #include "eshk.h"
9 
10 #ifndef OVLB
11 extern const struct shclass shtypes[];
12 
13 #else
14 
15 STATIC_DCL void FDECL(mkshobj_at, (const struct shclass *,int,int));
16 STATIC_DCL void FDECL(nameshk, (struct monst *,const char * const *));
17 STATIC_DCL int  FDECL(shkinit, (const struct shclass *,struct mkroom *));
18 #ifdef BLACKMARKET
19 STATIC_DCL void FDECL(stock_blkmar,
20 		  (const struct shclass *, struct mkroom *, int));
21 #endif /* BLACKMARKET */
22 
23 static const char * const shkliquors[] = {
24     /* Ukraine */
25     "Njezjin", "Tsjernigof", "Ossipewsk", "Gorlowka",
26     /* Belarus */
27     "Gomel",
28     /* N. Russia */
29     "Konosja", "Weliki Oestjoeg", "Syktywkar", "Sablja",
30     "Narodnaja", "Kyzyl",
31     /* Silezie */
32     "Walbrzych", "Swidnica", "Klodzko", "Raciborz", "Gliwice",
33     "Brzeg", "Krnov", "Hradec Kralove",
34     /* Schweiz */
35     "Leuk", "Brig", "Brienz", "Thun", "Sarnen", "Burglen", "Elm",
36     "Flims", "Vals", "Scuol",
37     "Chur", "Pagig",
38     0
39 };
40 
41 static const char * const shkbooks[] = {
42     /* Eire */
43     "Skibbereen", "Kanturk", "Rath Luirc", "Ennistymon", "Lahinch",
44     "Kinnegad", "Lugnaquillia", "Enniscorthy", "Gweebarra",
45     "Kittamagh", "Nenagh", "Sneem", "Ballingeary", "Kilgarvan",
46     "Cahersiveen", "Glenbeigh", "Kilmihil", "Kiltamagh",
47     "Droichead Atha", "Inniscrone", "Clonegal", "Lisnaskea",
48     "Culdaff", "Dunfanaghy", "Inishbofin", "Kesh",
49     0
50 };
51 
52 static const char * const shkarmors[] = {
53     /* Turquie */
54     "Demirci", "Kalecik", "Boyabai", "Yildizeli", "Gaziantep",
55     "Siirt", "Akhalataki", "Tirebolu", "Aksaray", "Ermenak",
56     "Iskenderun", "Kadirli", "Siverek", "Pervari", "Malasgirt",
57     "Bayburt", "Ayancik", "Zonguldak", "Balya", "Tefenni",
58     "Artvin", "Kars", "Makharadze", "Malazgirt", "Midyat",
59     "Birecik", "Kirikkale", "Alaca", "Polatli", "Nallihan",
60     0
61 };
62 
63 static const char * const shkwands[] = {
64     /* Wales */
65     "Yr Wyddgrug", "Trallwng", "Mallwyd", "Pontarfynach",
66     "Rhaeader", "Llandrindod", "Llanfair-ym-muallt",
67     "Y-Fenni", "Maesteg", "Rhydaman", "Beddgelert",
68     "Curig", "Llanrwst", "Llanerchymedd", "Caergybi",
69     /* Scotland */
70     "Nairn", "Turriff", "Inverurie", "Braemar", "Lochnagar",
71     "Kerloch", "Beinn a Ghlo", "Drumnadrochit", "Morven",
72     "Uist", "Storr", "Sgurr na Ciche", "Cannich", "Gairloch",
73     "Kyleakin", "Dunvegan",
74     0
75 };
76 
77 static const char * const shkrings[] = {
78     /* Hollandse familienamen */
79     "Feyfer", "Flugi", "Gheel", "Havic", "Haynin", "Hoboken",
80     "Imbyze", "Juyn", "Kinsky", "Massis", "Matray", "Moy",
81     "Olycan", "Sadelin", "Svaving", "Tapper", "Terwen", "Wirix",
82     "Ypey",
83     /* Skandinaviske navne */
84     "Rastegaisa", "Varjag Njarga", "Kautekeino", "Abisko",
85     "Enontekis", "Rovaniemi", "Avasaksa", "Haparanda",
86     "Lulea", "Gellivare", "Oeloe", "Kajaani", "Fauske",
87     0
88 };
89 
90 static const char * const shkfoods[] = {
91     /* Indonesia */
92     "Djasinga", "Tjibarusa", "Tjiwidej", "Pengalengan",
93     "Bandjar", "Parbalingga", "Bojolali", "Sarangan",
94     "Ngebel", "Djombang", "Ardjawinangun", "Berbek",
95     "Papar", "Baliga", "Tjisolok", "Siboga", "Banjoewangi",
96     "Trenggalek", "Karangkobar", "Njalindoeng", "Pasawahan",
97     "Pameunpeuk", "Patjitan", "Kediri", "Pemboeang", "Tringanoe",
98     "Makin", "Tipor", "Semai", "Berhala", "Tegal", "Samoe",
99     0
100 };
101 
102 static const char * const shkweapons[] = {
103     /* Perigord */
104     "Voulgezac", "Rouffiac", "Lerignac", "Touverac", "Guizengeard",
105     "Melac", "Neuvicq", "Vanzac", "Picq", "Urignac", "Corignac",
106     "Fleac", "Lonzac", "Vergt", "Queyssac", "Liorac", "Echourgnac",
107     "Cazelon", "Eypau", "Carignan", "Monbazillac", "Jonzac",
108     "Pons", "Jumilhac", "Fenouilledes", "Laguiolet", "Saujon",
109     "Eymoutiers", "Eygurande", "Eauze", "Labouheyre",
110     0
111 };
112 
113 static const char * const shktools[] = {
114     /* Spmi */
115     "Ymla", "Eed-morra", "Cubask", "Nieb", "Bnowr Falr", "Telloc Cyaj",
116     "Sperc", "Noskcirdneh", "Yawolloh", "Hyeghu", "Niskal", "Trahnil",
117     "Htargcm", "Enrobwem", "Kachzi Rellim", "Regien", "Donmyar",
118     "Yelpur", "Nosnehpets", "Stewe", "Renrut", "_Zlaw", "Nosalnef",
119     "Rewuorb", "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah",
120     "Corsh", "Aned",
121 #ifdef OVERLAY
122     "Erreip", "Nehpets", "Mron", "Snivek", "Lapu", "Kahztiy",
123 #endif
124 #ifdef WIN32
125     "Lechaim", "Lexa", "Niod",
126 #endif
127 #ifdef MAC
128     "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s",
129     "Yao-hang", "Tonbar", "Kivenhoug",
130 #endif
131 #ifdef AMIGA
132     "Falo", "Nosid-da\'r", "Ekim-p", "Rebrol-nek", "Noslo", "Yl-rednow",
133     "Mured-oog", "Ivrajimsal",
134 #endif
135 #ifdef TOS
136     "Nivram",
137 #endif
138 #ifdef VMS
139     "Lez-tneg", "Ytnu-haled", "Niknar",
140 #endif
141     0
142 };
143 
144 static const char * const shklight[] = {
145     /* Romania */
146     "Zarnesti", "Slanic", "Nehoiasu", "Ludus", "Sighisoara", "Nisipitu",
147     "Razboieni", "Bicaz", "Dorohoi", "Vaslui", "Fetesti", "Tirgu Neamt",
148     "Babadag", "Zimnicea", "Zlatna", "Jiu", "Eforie", "Mamaia",
149     /* Bulgaria */
150     "Silistra", "Tulovo", "Panagyuritshte", "Smolyan", "Kirklareli",
151     "Pernik", "Lom", "Haskovo", "Dobrinishte", "Varvara", "Oryahovo",
152     "Troyan", "Lovech", "Sliven",
153     0
154 };
155 
156 static const char * const shkgeneral[] = {
157     /* Suriname */
158     "Hebiwerie", "Possogroenoe", "Asidonhopo", "Manlobbi",
159     "Adjama", "Pakka Pakka", "Kabalebo", "Wonotobo",
160     "Akalapi", "Sipaliwini",
161     /* Greenland */
162     "Annootok", "Upernavik", "Angmagssalik",
163     /* N. Canada */
164     "Aklavik", "Inuvik", "Tuktoyaktuk",
165     "Chicoutimi", "Ouiatchouane", "Chibougamau",
166     "Matagami", "Kipawa", "Kinojevis",
167     "Abitibi", "Maganasipi",
168     /* Iceland */
169     "Akureyri", "Kopasker", "Budereyri", "Akranes", "Bordeyri",
170     "Holmavik",
171     0
172 };
173 
174 static const char *shkmusic[] = {
175     "John", "Paul", "George", "Ringo"
176     "Elvis", "Mick", "Keith", "Ron", "Charlie"
177     "Joseph", "Franz", "Richard", "Ludwig", "Wolfgang Amadeus",
178     "Johann Sebastian",
179     "Karlheinz", "Gyorgy",
180     "Luciano", "Placido", "Jose", "Enrico",
181     "Falco", "_Britney", "_Christina", "_Toni", "_Brandy",
182     0
183 };
184 
185 #ifdef BLACKMARKET
186 static const char *shkblack[] = {
187   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
188   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
189   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
190   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
191   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
192   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
193   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
194   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
195   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
196   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
197   "One-eyed Sam", "One-eyed Sam", "One-eyed Sam",
198   0
199 };
200 #endif /* BLACKMARKET */
201 
202 static const char *shkpet[] = {
203     /* Albania */
204     "Elbasan", "Vlore", "Shkoder", "Berat", "Kavaje", "Pogradec",
205     "Sarande", "Peshkopi", "Shijak", "Librazhd", "Tepelene",
206     "Fushe-Kruje", "Rreshen",
207     0
208 };
209 
210 static const char *shktins[] = {
211     /* Sweden */
212     "Trosa", "Torshalla", "Morgongava", "Uppsala", "Norrkoping",
213     "Nybro", "Alingsas", "Vadstena", "Fagersta", "Skelleftea",
214     "Solleftea", "Ystad", "Avesta", "Sala", "Norrt�lje",
215     0
216 };
217 
218 /*
219  * To add new shop types, all that is necessary is to edit the shtypes[] array.
220  * See mkroom.h for the structure definition.  Typically, you'll have to lower
221  * some or all of the probability fields in old entries to free up some
222  * percentage for the new type.
223  *
224  * The placement type field is not yet used but will be in the near future.
225  *
226  * The iprobs array in each entry defines the probabilities for various kinds
227  * of objects to be present in the given shop type.  You can associate with
228  * each percentage either a generic object type (represented by one of the
229  * *_CLASS macros) or a specific object (represented by an onames.h define).
230  * In the latter case, prepend it with a unary minus so the code can know
231  * (by testing the sign) whether to use mkobj() or mksobj().
232  */
233 
234 const struct shclass shtypes[] = {
235 	{"general store", RANDOM_CLASS, 41,
236 	    D_SHOP, {{100, RANDOM_CLASS}, {0, 0}, {0, 0}}, shkgeneral},
237 	{"used armor dealership", ARMOR_CLASS, 14,
238 	    D_SHOP, {{90, ARMOR_CLASS}, {10, WEAPON_CLASS}, {0, 0}},
239 	     shkarmors},
240 	{"second-hand bookstore", SCROLL_CLASS, 10, D_SHOP,
241 	    {{90, SCROLL_CLASS}, {10, SPBOOK_CLASS}, {0, 0}}, shkbooks},
242 	{"liquor emporium", POTION_CLASS, 10, D_SHOP,
243 	    {{100, POTION_CLASS}, {0, 0}, {0, 0}}, shkliquors},
244 	{"antique weapons outlet", WEAPON_CLASS, 5, D_SHOP,
245 	    {{90, WEAPON_CLASS}, {10, ARMOR_CLASS}, {0, 0}}, shkweapons},
246 	{"delicatessen", FOOD_CLASS, 5, D_SHOP,
247 	    {{83, FOOD_CLASS}, {5, -POT_FRUIT_JUICE}, {4, -POT_BOOZE},
248 	     {5, -POT_WATER}, {3, -ICE_BOX}}, shkfoods},
249 	{"jewelers", RING_CLASS, 3, D_SHOP,
250 	    {{85, RING_CLASS}, {10, GEM_CLASS}, {5, AMULET_CLASS}, {0, 0}},
251 	    shkrings},
252 	{"quality apparel and accessories", WAND_CLASS, 3, D_SHOP,
253 	    {{90, WAND_CLASS}, {5, -LEATHER_GLOVES}, {5, -ELVEN_CLOAK}, {0, 0}},
254 	     shkwands},
255 	{"hardware store", TOOL_CLASS, 3, D_SHOP,
256 	    {{100, TOOL_CLASS}, {0, 0}, {0, 0}}, shktools},
257 	/* Actually shktools is ignored; the code specifically chooses a
258 	 * random implementor name (along with candle shops having
259 	 * random shopkeepers)
260 	 */
261 	{"rare books", SPBOOK_CLASS, 3, D_SHOP,
262 	    {{90, SPBOOK_CLASS}, {10, SCROLL_CLASS}, {0, 0}}, shkbooks},
263 	{"canned food factory", FOOD_CLASS, 1, D_SHOP,
264 		{{10, -ICE_BOX}, {90, -TIN},
265 		/* shopkeeper will pay for corpses, but they aren't generated */
266 		/* on the shop floor */
267 		{0, -CORPSE}, {0, 0}}, shktins},
268 	{"rare instruments", TOOL_CLASS, 1, D_SHOP,
269 	    {{10, -TIN_WHISTLE	}, { 3, -MAGIC_WHISTLE	},
270 	     {10, -WOODEN_FLUTE	}, { 3, -MAGIC_FLUTE	},
271 	     {10, -TOOLED_HORN	}, { 3, -FROST_HORN	},
272 	     { 3, -FIRE_HORN	}, { 3, -HORN_OF_PLENTY	},
273 	     {10, -WOODEN_HARP	}, { 3, -MAGIC_HARP	},
274 	     {10, -BELL		}, {10, -BUGLE		},
275 	     {10, -LEATHER_DRUM	}, { 2, -DRUM_OF_EARTHQUAKE},
276 #ifdef TOURIST
277 	     { 5, -T_SHIRT	}, { 5, -LOCK_PICK	},
278 #else
279 	     { 5, -TIN_WHISTLE	}, { 5, -LOCK_PICK	},
280 #endif
281 	     {0, 0}} , shkmusic},
282 	{"pet store", FOOD_CLASS, 1, D_SHOP, {
283 #ifdef STEED
284 	    {67, -FIGURINE}, {5, -LEASH},{10, -TRIPE_RATION}, {5, -SADDLE},
285 #else
286 	    {72, -FIGURINE}, {5, -LEASH},{10, -TRIPE_RATION},
287 #endif
288 	    {10, -TIN_WHISTLE}, {3, -MAGIC_WHISTLE}}, shkpet},
289 	/* Shops below this point are "unique".  That is they must all have a
290 	 * probability of zero.  They are only created via the special level
291 	 * loader.
292 	 */
293 	{"lighting store", TOOL_CLASS, 0, D_SHOP,
294 	    {{32, -WAX_CANDLE}, {50, -TALLOW_CANDLE},
295 	     {5, -BRASS_LANTERN}, {10, -OIL_LAMP}, {3, -MAGIC_LAMP}}, shklight},
296 #ifdef BLACKMARKET
297 	{"black market", RANDOM_CLASS, 0, D_SHOP,
298 	   {{100, RANDOM_CLASS}, {0, 0}, {0, 0}}, shkblack},
299 #endif /* BLACKMARKET */
300 	{(char *)0, 0, 0, 0, {{0, 0}, {0, 0}, {0, 0}}, 0}
301 };
302 
303 /* validate shop probabilities; otherwise incorrect local changes could
304    end up provoking infinite loops or wild subscripts fetching garbage */
305 void
shop_selection_init()306 shop_selection_init()
307 {
308 	register int i, j, item_prob, shop_prob;
309 
310 	for (shop_prob = 0, i = 0; i < SIZE(shtypes)-1; i++) {
311 		shop_prob += shtypes[i].prob;
312 		for (item_prob = 0, j = 0; j < SIZE(shtypes[0].iprobs); j++)
313 			item_prob += shtypes[i].iprobs[j].iprob;
314 		if (item_prob != 100)
315 			panic("item probabilities total to %d for %s shops!",
316 				item_prob, shtypes[i].name);
317 	}
318 	if (shop_prob != 100)
319 		panic("shop probabilities total to %d!", shop_prob);
320 }
321 
322 STATIC_OVL void
mkshobj_at(shp,sx,sy)323 mkshobj_at(shp, sx, sy)
324 /* make an object of the appropriate type for a shop square */
325 const struct shclass *shp;
326 int sx, sy;
327 {
328 	struct monst *mtmp;
329 	int atype;
330 	struct permonst *ptr;
331 
332 	if (rn2(100) < depth(&u.uz) &&
333 		!MON_AT(sx, sy) && (ptr = mkclass(S_MIMIC,0)) &&
334 		(mtmp = makemon(ptr,sx,sy,NO_MM_FLAGS)) != 0) {
335 	    /* note: makemon will set the mimic symbol to a shop item */
336 	    if (rn2(10) >= depth(&u.uz)) {
337 		mtmp->m_ap_type = M_AP_OBJECT;
338 		mtmp->mappearance = STRANGE_OBJECT;
339 	    }
340 	} else {
341 	    atype = get_shop_item(shp - shtypes);
342 	    if (atype < 0)
343 		(void) mksobj_at(-atype, sx, sy, TRUE, TRUE);
344 	    else
345 		(void) mkobj_at(atype, sx, sy, TRUE);
346 	}
347 }
348 
349 /* extract a shopkeeper name for the given shop type */
350 STATIC_OVL void
nameshk(shk,nlp)351 nameshk(shk, nlp)
352 struct monst *shk;
353 const char * const *nlp;
354 {
355 	int i, trycnt, names_avail;
356 	const char *shname = 0;
357 	struct monst *mtmp;
358 	int name_wanted;
359 	s_level *sptr;
360 
361 	if (nlp == shklight && In_mines(&u.uz)
362 		&& (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
363 	    /* special-case minetown lighting shk */
364 	    shname = "Izchak";
365 	    shk->female = FALSE;
366 #ifdef BLACKMARKET
367 	} else if (nlp == shkblack) {
368 	    /* special-case black marketeer */
369 	    shname = "One-eyed Sam";
370 	    shk->female = TRUE;
371 #endif /* BLACKMARKET */
372 	} else {
373 	    /* We want variation from game to game, without needing the save
374 	       and restore support which would be necessary for randomization;
375 	       try not to make too many assumptions about time_t's internals;
376 	       use ledger_no rather than depth to keep mine town distinct. */
377 	    int nseed = (int)((long)u.ubirthday / 257L);
378 
379 	    name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
380 	    if (name_wanted < 0) name_wanted += (13 + 5);
381 	    shk->female = name_wanted & 1;
382 
383 	    for (names_avail = 0; nlp[names_avail]; names_avail++)
384 		continue;
385 
386 	    for (trycnt = 0; trycnt < 50; trycnt++) {
387 		if (nlp == shktools) {
388 		    shname = shktools[rn2(names_avail)];
389 		    shk->female = (*shname == '_');
390 		    if (shk->female) shname++;
391 		} else if (nlp == shkmusic) {
392 		    shname = shkmusic[rn2(names_avail)];
393 		    shk->female = (*shname == '_');
394 		    if (shk->female) shname++;
395 		} else if (name_wanted < names_avail) {
396 		    shname = nlp[name_wanted];
397 		} else if ((i = rn2(names_avail)) != 0) {
398 		    shname = nlp[i - 1];
399 		} else if (nlp != shkgeneral) {
400 		    nlp = shkgeneral;	/* try general names */
401 		    for (names_avail = 0; nlp[names_avail]; names_avail++)
402 			continue;
403 		    continue;		/* next `trycnt' iteration */
404 		} else {
405 		    shname = shk->female ? "Lucrezia" : "Dirk";
406 		}
407 
408 		/* is name already in use on this level? */
409 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
410 		    if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk) continue;
411 		    if (strcmp(ESHK(mtmp)->shknam, shname)) continue;
412 		    break;
413 		}
414 		if (!mtmp) break;	/* new name */
415 	    }
416 	}
417 	(void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
418 	ESHK(shk)->shknam[PL_NSIZ-1] = 0;
419 }
420 
421 STATIC_OVL int
shkinit(shp,sroom)422 shkinit(shp, sroom)	/* create a new shopkeeper in the given room */
423 const struct shclass	*shp;
424 struct mkroom	*sroom;
425 {
426 	register int sh, sx, sy;
427 	struct monst *shk;
428 	long shkmoney; /* Temporary placeholder for Shopkeeper's initial capital */
429 
430 	/* place the shopkeeper in the given room */
431 	sh = sroom->fdoor;
432 	sx = doors[sh].x;
433 	sy = doors[sh].y;
434 
435 	/* check that the shopkeeper placement is sane */
436 	if(sroom->irregular) {
437 	    int rmno = (sroom - rooms) + ROOMOFFSET;
438 	    if (isok(sx-1,sy) && !levl[sx-1][sy].edge &&
439 		(int) levl[sx-1][sy].roomno == rmno) sx--;
440 	    else if (isok(sx+1,sy) && !levl[sx+1][sy].edge &&
441 		(int) levl[sx+1][sy].roomno == rmno) sx++;
442 	    else if (isok(sx,sy-1) && !levl[sx][sy-1].edge &&
443 		(int) levl[sx][sy-1].roomno == rmno) sy--;
444 	    else if (isok(sx,sy+1) && !levl[sx][sy+1].edge &&
445 		(int) levl[sx][sy+1].roomno == rmno) sx++;
446 	    else goto shk_failed;
447 	}
448 	else if(sx == sroom->lx-1) sx++;
449 	else if(sx == sroom->hx+1) sx--;
450 	else if(sy == sroom->ly-1) sy++;
451 	else if(sy == sroom->hy+1) sy--; else {
452 	shk_failed:
453 #ifdef DEBUG
454 # ifdef WIZARD
455 	    /* Said to happen sometimes, but I have never seen it. */
456 	    /* Supposedly fixed by fdoor change in mklev.c */
457 	    if(wizard) {
458 		register int j = sroom->doorct;
459 
460 		pline("Where is shopdoor?");
461 		pline("Room at (%d,%d),(%d,%d).",
462 		      sroom->lx, sroom->ly, sroom->hx, sroom->hy);
463 		pline("doormax=%d doorct=%d fdoor=%d",
464 		      doorindex, sroom->doorct, sh);
465 		while(j--) {
466 		    pline("door [%d,%d]", doors[sh].x, doors[sh].y);
467 		    sh++;
468 		}
469 		display_nhwindow(WIN_MESSAGE, FALSE);
470 	    }
471 # endif
472 #endif
473 	    return(-1);
474 	}
475 
476 	if(MON_AT(sx, sy)) (void) rloc(m_at(sx, sy), FALSE); /* insurance */
477 
478 	/* now initialize the shopkeeper monster structure */
479 
480 #ifdef BLACKMARKET
481 	shk = 0;
482 	if (Is_blackmarket(&u.uz)) {
483 	  shk = makemon(&mons[PM_BLACK_MARKETEER], sx, sy, NO_MM_FLAGS);
484 	}
485 	if (!shk) {
486 	  if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS)))
487 		return(-1);
488 	}
489 #else  /* BLACKMARKET */
490 	if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS)))
491 		return(-1);
492 #endif /* BLACKMARKET */
493 
494 	shk->isshk = shk->mpeaceful = 1;
495 	set_malign(shk);
496 	shk->msleeping = 0;
497 	shk->mtrapseen = ~0;	/* we know all the traps already */
498 	ESHK(shk)->shoproom = (sroom - rooms) + ROOMOFFSET;
499 	sroom->resident = shk;
500 	ESHK(shk)->shoptype = sroom->rtype;
501 	assign_level(&(ESHK(shk)->shoplevel), &u.uz);
502 	ESHK(shk)->shd = doors[sh];
503 	ESHK(shk)->shk.x = sx;
504 	ESHK(shk)->shk.y = sy;
505 	ESHK(shk)->robbed = 0L;
506 	ESHK(shk)->credit = 0L;
507 	ESHK(shk)->debit = 0L;
508 	ESHK(shk)->loan = 0L;
509 	ESHK(shk)->visitct = 0;
510 	ESHK(shk)->following = 0;
511 	ESHK(shk)->cheapskate = (rn2(3)==0) ? TRUE : FALSE;
512 	ESHK(shk)->billct = 0;
513 	ESHK(shk)->bill_p = &ESHK(shk)->bill[0];
514 
515   shkmoney = 1000L + 30L*(long)rnd(100);	/* initial capital */
516   						/* [CWC] Lets not create the money yet until we see if the
517   							 shk is a black marketeer, else we'll have to create
518   						   another money object, if GOLDOBJ is defined */
519 
520 	if (shp->shknms == shkrings)
521 	    (void) mongets(shk, TOUCHSTONE);
522 	nameshk(shk, shp->shknms);
523 
524 #ifdef BLACKMARKET
525 	if (Is_blackmarket(&u.uz))
526     shkmoney = 7*shkmoney + rn2(3*shkmoney);
527 #endif
528 	/* it's a poor town */
529 	if (Is_town_level(&u.uz))
530 		shkmoney /= 4;
531 
532 #ifndef GOLDOBJ
533 	shk->mgold = shkmoney;
534 #else
535   mkmonmoney(shk, shkmoney);
536 #endif
537 
538 #ifdef BLACKMARKET
539 	if (Is_blackmarket(&u.uz)) {
540 	  register struct obj *otmp;
541 /* make sure black marketeer can wield Thiefbane */
542 	  shk->data->maligntyp = -1;
543 /* black marketeer's equipment */
544 	  otmp = mksobj(TWO_HANDED_SWORD, FALSE, FALSE);
545 	  otmp = oname(otmp, artiname(ART_THIEFBANE));
546 	  mpickobj(shk, otmp);
547 	  if (otmp->spe < 5) otmp->spe += rnd(5);
548 	  otmp = mksobj(SHIELD_OF_REFLECTION, FALSE, FALSE);
549 	  mpickobj(shk, otmp);
550 	  if (otmp->spe < 5) otmp->spe += rnd(5);
551 	  otmp = mksobj(GRAY_DRAGON_SCALE_MAIL, FALSE, FALSE);
552 	  mpickobj(shk, otmp);
553 	  if (otmp->spe < 5) otmp->spe += rnd(5);
554 	  otmp = mksobj(SPEED_BOOTS, FALSE, FALSE);
555 	  mpickobj(shk, otmp);
556 	  if (otmp->spe < 5) otmp->spe += rnd(5);
557 	  otmp = mksobj(AMULET_OF_LIFE_SAVING, FALSE, FALSE);
558 	  mpickobj(shk, otmp);
559 /* wear armor and amulet */
560 	  m_dowear(shk, TRUE);
561 	  otmp = mksobj(SKELETON_KEY, FALSE, FALSE);
562 	  mpickobj(shk, otmp);
563 	}
564 #endif /* BLACKMARKET */
565 
566 	return(sh);
567 }
568 
569 /* stock a newly-created room with objects */
570 void
stock_room(shp_indx,sroom)571 stock_room(shp_indx, sroom)
572 int shp_indx;
573 register struct mkroom *sroom;
574 {
575     /*
576      * Someday soon we'll dispatch on the shdist field of shclass to do
577      * different placements in this routine. Currently it only supports
578      * shop-style placement (all squares except a row nearest the first
579      * door get objects).
580      */
581     register int sx, sy, sh;
582     char buf[BUFSZ];
583     int rmno = (sroom - rooms) + ROOMOFFSET;
584     const struct shclass *shp = &shtypes[shp_indx];
585 
586     /* first, try to place a shopkeeper in the room */
587     if ((sh = shkinit(shp, sroom)) < 0)
588 	return;
589 
590     /* make sure no doorways without doors, and no */
591     /* trapped doors, in shops.			   */
592     sx = doors[sroom->fdoor].x;
593     sy = doors[sroom->fdoor].y;
594 
595     if(levl[sx][sy].doormask == D_NODOOR) {
596 	    levl[sx][sy].doormask = D_ISOPEN;
597 	    newsym(sx,sy);
598     }
599     if(levl[sx][sy].typ == SDOOR) {
600 	    cvt_sdoor_to_door(&levl[sx][sy]);	/* .typ = DOOR */
601 	    newsym(sx,sy);
602     }
603     if(levl[sx][sy].doormask & D_TRAPPED)
604 	    levl[sx][sy].doormask = D_LOCKED;
605 
606     if(levl[sx][sy].doormask == D_LOCKED) {
607 	    register int m = sx, n = sy;
608 
609 	    if(inside_shop(sx+1,sy)) m--;
610 	    else if(inside_shop(sx-1,sy)) m++;
611 	    if(inside_shop(sx,sy+1)) n--;
612 	    else if(inside_shop(sx,sy-1)) n++;
613 	    Sprintf(buf, "Closed for inventory");
614 	    make_engr_at(m, n, buf, 0L, DUST);
615     }
616 
617 #ifdef BLACKMARKET
618     if (Is_blackmarket(&u.uz)) {
619       stock_blkmar(shp, sroom, sh);
620       level.flags.has_shop = TRUE;
621       return;
622     }
623 #endif /* BLACKMARKET */
624 
625     for(sx = sroom->lx; sx <= sroom->hx; sx++)
626 	for(sy = sroom->ly; sy <= sroom->hy; sy++) {
627 	    if(sroom->irregular) {
628 		if (levl[sx][sy].edge || (int) levl[sx][sy].roomno != rmno ||
629 		   distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)
630 		    continue;
631 	    } else if((sx == sroom->lx && doors[sh].x == sx-1) ||
632 		      (sx == sroom->hx && doors[sh].x == sx+1) ||
633 		      (sy == sroom->ly && doors[sh].y == sy-1) ||
634 		      (sy == sroom->hy && doors[sh].y == sy+1)) continue;
635 	    mkshobj_at(shp, sx, sy);
636 	}
637 
638     /*
639      * Special monster placements (if any) should go here: that way,
640      * monsters will sit on top of objects and not the other way around.
641      */
642 
643     level.flags.has_shop = TRUE;
644 }
645 
646 #ifdef BLACKMARKET
647 /* stock a newly-created black market with objects */
648 static void
stock_blkmar(shp,sroom,sh)649 stock_blkmar(shp, sroom, sh)
650 const struct shclass *shp;
651 register struct mkroom *sroom;
652 register int sh;
653 {
654     /*
655      * Someday soon we'll dispatch on the shdist field of shclass to do
656      * different placements in this routine. Currently it only supports
657      * shop-style placement (all squares except a row nearest the first
658      * door get objects).
659      */
660     /* [max] removed register int cl,  char buf[bufsz] */
661     int i, sx, sy, first = 0, next = 0, total, partial, typ;
662     struct obj *otmp;
663     int blkmar_gen[NUM_OBJECTS+2];
664     int *clp, *lastclp;
665     int goodcl[12];
666 
667     goodcl[ 0] = WEAPON_CLASS;
668     goodcl[ 1] = ARMOR_CLASS;
669     goodcl[ 2] = RING_CLASS;
670     goodcl[ 3] = AMULET_CLASS;
671     goodcl[ 4] = TOOL_CLASS;
672     goodcl[ 5] = FOOD_CLASS;
673     goodcl[ 6] = POTION_CLASS;
674     goodcl[ 7] = SCROLL_CLASS;
675     goodcl[ 8] = SPBOOK_CLASS;
676     goodcl[ 9] = WAND_CLASS;
677     goodcl[10] = GEM_CLASS;
678     goodcl[11] = 0;
679 
680     for (i=0; i < NUM_OBJECTS; i++) {
681       blkmar_gen[i] = 0;
682     }
683 
684     total = 0;
685     for (clp=goodcl; *clp!=0; clp++)  {
686       lastclp = clp;
687       first = bases[*clp];
688 /* this assumes that luckstone & loadstone comes just after the gems */
689       next = (*clp==GEM_CLASS) ? (LOADSTONE+1) : bases[(*clp)+1];
690       total += next-first;
691     }
692     if (total==0)  return;
693 
694     if (sroom->hx-sroom->lx<2)  return;
695     clp = goodcl-1;
696     partial = 0;
697     for(sx = sroom->lx+1; sx <= sroom->hx; sx++) {
698       if (sx==sroom->lx+1 ||
699 	  ((sx-sroom->lx-2)*total)/(sroom->hx-sroom->lx-1)>partial) {
700 	clp++;
701 	if (clp>lastclp)  clp = lastclp;
702 	first = bases[*clp];
703 	next = (*clp==GEM_CLASS) ? (LOADSTONE+1) : bases[(*clp)+1];
704 	partial += next-first;
705       }
706 
707       for(sy = sroom->ly; sy <= sroom->hy; sy++) {
708 	if((sx == sroom->lx && doors[sh].x == sx-1) ||
709 	   (sx == sroom->hx && doors[sh].x == sx+1) ||
710 	   (sy == sroom->ly && doors[sh].y == sy-1) ||
711 	   (sy == sroom->hy && doors[sh].y == sy+1) || (rn2(3)))
712 	  continue;
713 
714 	for (i=0; i<50; i++) {
715 	  typ = rn2(next-first) + first;
716 
717 /* forbidden objects  */
718 	  if (typ==AMULET_OF_YENDOR || typ==CANDELABRUM_OF_INVOCATION ||
719 	      typ==BELL_OF_OPENING  || typ==SPE_BOOK_OF_THE_DEAD ||
720 	      objects[typ].oc_nowish || typ==0)
721 	    continue;
722 
723 	  otmp = mkobj_at(RANDOM_CLASS,sx,sy,TRUE);
724 /* generate multiple copies with decreasing probabilities */
725 /*        if (rn2(blkmar_gen[typ]+1) && i<49)  continue; */
726 
727 /*        otmp = mksobj_at(typ, sx, sy, TRUE, TRUE);
728 	  blkmar_gen[typ]++;*/
729 
730 /* prevent wishing abuse */
731 	  if (typ==WAN_WISHING) {
732 	    otmp->spe = 0;
733 	    otmp->recharged = 1;
734 	  }
735 	  if (typ==MAGIC_LAMP) {
736 	    otmp->spe = 0;
737 	  }
738 
739 	  break;
740 	}
741 
742       }
743     }
744 
745     /*
746      * Special monster placements (if any) should go here: that way,
747      * monsters will sit on top of objects and not the other way around.
748      */
749 }
750 #endif /* BLACKMARKET */
751 
752 #endif /* OVLB */
753 #ifdef OVL0
754 
755 /* does shkp's shop stock this item type? */
756 boolean
saleable(shkp,obj)757 saleable(shkp, obj)
758 struct monst *shkp;
759 struct obj *obj;
760 {
761     int i, shp_indx = ESHK(shkp)->shoptype - SHOPBASE;
762     const struct shclass *shp = &shtypes[shp_indx];
763 
764     if (shp->symb == RANDOM_CLASS) return TRUE;
765     else for (i = 0; i < SIZE(shtypes[0].iprobs) && shp->iprobs[i].iprob; i++)
766 		if (shp->iprobs[i].itype < 0 ?
767 			shp->iprobs[i].itype == - obj->otyp :
768 			shp->iprobs[i].itype == obj->oclass) return TRUE;
769     /* not found */
770     return FALSE;
771 }
772 
773 /* positive value: class; negative value: specific object type */
774 int
get_shop_item(type)775 get_shop_item(type)
776 int type;
777 {
778 	const struct shclass *shp = shtypes+type;
779 	register int i,j;
780 
781 	/* select an appropriate object type at random */
782 	for(j = rnd(100), i = 0; (j -= shp->iprobs[i].iprob) > 0; i++)
783 		continue;
784 
785 	return shp->iprobs[i].itype;
786 }
787 
788 #endif /* OVL0 */
789 
790 /*shknam.c*/
791