Expand PMF_FN_* macros.
[netbsd-mini2440.git] / games / hack / hack.u_init.c
blob24efcf09a7defafe3f8face0697f5c47dba97a22
1 /* $NetBSD: hack.u_init.c,v 1.10 2009/06/07 18:30:39 dholland Exp $ */
3 /*
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 * Amsterdam
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.u_init.c,v 1.10 2009/06/07 18:30:39 dholland Exp $");
67 #endif /* not lint */
69 #include <ctype.h>
70 #include <signal.h>
71 #include <stdlib.h>
72 #include "hack.h"
73 #include "extern.h"
75 #define Strcpy (void) strcpy
76 #define Strcat (void) strcat
77 #define UNDEF_TYP 0
78 #define UNDEF_SPE '\177'
80 char pl_character[PL_CSIZ];
82 static const struct you zerou;
83 static const char *(roles[]) = { /* must all have distinct first letter */
84 /* roles[4] may be changed to -woman */
85 "Tourist", "Speleologist", "Fighter", "Knight",
86 "Cave-man", "Wizard"
88 #define NR_OF_ROLES SIZE(roles)
89 static char rolesyms[NR_OF_ROLES + 1]; /* filled by u_init() */
91 struct trobj {
92 uchar trotyp;
93 schar trspe;
94 char trolet;
95 Bitfield(trquan, 6);
96 Bitfield(trknown, 1);
99 #ifdef WIZARD
100 static struct trobj Extra_objs[] = {
101 {0, 0, 0, 0, 0},
102 {0, 0, 0, 0, 0}
104 #endif /* WIZARD */
106 static struct trobj Cave_man[] = {
107 {MACE, 1, WEAPON_SYM, 1, 1},
108 {BOW, 1, WEAPON_SYM, 1, 1},
109 {ARROW, 0, WEAPON_SYM, 25, 1}, /* quan is variable */
110 {LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1},
111 {0, 0, 0, 0, 0}
114 static struct trobj Fighter[] = {
115 {TWO_HANDED_SWORD, 0, WEAPON_SYM, 1, 1},
116 {RING_MAIL, 0, ARMOR_SYM, 1, 1},
117 {0, 0, 0, 0, 0}
120 static struct trobj Knight[] = {
121 {LONG_SWORD, 0, WEAPON_SYM, 1, 1},
122 {SPEAR, 2, WEAPON_SYM, 1, 1},
123 {RING_MAIL, 1, ARMOR_SYM, 1, 1},
124 {HELMET, 0, ARMOR_SYM, 1, 1},
125 {SHIELD, 0, ARMOR_SYM, 1, 1},
126 {PAIR_OF_GLOVES, 0, ARMOR_SYM, 1, 1},
127 {0, 0, 0, 0, 0}
130 static struct trobj Speleologist[] = {
131 {STUDDED_LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1},
132 {UNDEF_TYP, 0, POTION_SYM, 2, 0},
133 {FOOD_RATION, 0, FOOD_SYM, 3, 1},
134 {PICK_AXE, UNDEF_SPE, TOOL_SYM, 1, 0},
135 {ICE_BOX, 0, TOOL_SYM, 1, 0},
136 {0, 0, 0, 0, 0}
139 static struct trobj Tinopener[] = {
140 {CAN_OPENER, 0, TOOL_SYM, 1, 1},
141 {0, 0, 0, 0, 0}
144 static struct trobj Tourist[] = {
145 {UNDEF_TYP, 0, FOOD_SYM, 10, 1},
146 {POT_EXTRA_HEALING, 0, POTION_SYM, 2, 0},
147 {EXPENSIVE_CAMERA, 0, TOOL_SYM, 1, 1},
148 {DART, 2, WEAPON_SYM, 25, 1}, /* quan is variable */
149 {0, 0, 0, 0, 0}
152 static struct trobj Wizard[] = {
153 {ELVEN_CLOAK, 0, ARMOR_SYM, 1, 1},
154 {UNDEF_TYP, UNDEF_SPE, WAND_SYM, 2, 0},
155 {UNDEF_TYP, UNDEF_SPE, RING_SYM, 2, 0},
156 {UNDEF_TYP, UNDEF_SPE, POTION_SYM, 2, 0},
157 {UNDEF_TYP, UNDEF_SPE, SCROLL_SYM, 3, 0},
158 {0, 0, 0, 0, 0}
161 static void ini_inv(struct trobj *);
162 static void wiz_inv(void);
163 static int role_index(int);
165 void
166 u_init(void)
168 int i;
169 char exper = 'y', pc;
170 if (flags.female) /* should have been set in HACKOPTIONS */
171 roles[4] = "Cave-woman";
172 for (i = 0; i < NR_OF_ROLES; i++)
173 rolesyms[i] = roles[i][0];
174 rolesyms[i] = 0;
176 if ((pc = pl_character[0]) != '\0') {
177 if (islower((unsigned char)pc))
178 pc = toupper((unsigned char)pc);
179 if ((i = role_index(pc)) >= 0)
180 goto got_suffix; /* implies experienced */
181 printf("\nUnknown role: %c\n", pc);
182 pl_character[0] = pc = 0;
184 printf("\nAre you an experienced player? [ny] ");
186 while (!strchr("ynYN \n\004", (exper = readchar())))
187 bell();
188 if (exper == '\004') /* Give him an opportunity to get out */
189 end_of_input();
190 printf("%c\n", exper); /* echo */
191 if (strchr("Nn \n", exper)) {
192 exper = 0;
193 goto beginner;
195 printf("\nTell me what kind of character you are:\n");
196 printf("Are you");
197 for (i = 0; i < NR_OF_ROLES; i++) {
198 printf(" a %s", roles[i]);
199 if (i == 2) /* %% */
200 printf(",\n\t");
201 else if (i < NR_OF_ROLES - 2)
202 printf(",");
203 else if (i == NR_OF_ROLES - 2)
204 printf(" or");
206 printf("? [%s] ", rolesyms);
208 while ((pc = readchar()) != '\0') {
209 if (islower((unsigned char)pc))
210 pc = toupper((unsigned char)pc);
211 if ((i = role_index(pc)) >= 0) {
212 printf("%c\n", pc); /* echo */
213 (void) fflush(stdout); /* should be seen */
214 break;
216 if (pc == '\n')
217 break;
218 if (pc == '\004') /* Give him the opportunity to get
219 * out */
220 end_of_input();
221 bell();
223 if (pc == '\n')
224 pc = 0;
226 beginner:
227 if (!pc) {
228 printf("\nI'll choose a character for you.\n");
229 i = rn2(NR_OF_ROLES);
230 pc = rolesyms[i];
231 printf("This game you will be a%s %s.\n",
232 exper ? "n experienced" : "",
233 roles[i]);
234 getret();
235 /* give him some feedback in case mklev takes much time */
236 (void) putchar('\n');
237 (void) fflush(stdout);
239 #if 0
241 * Given the above code, I can't see why this would ever change
242 * anything; it does core pretty well, though. - cmh 4/20/93
244 if (exper) {
245 roles[i][0] = pc;
247 #endif
249 got_suffix:
251 (void) strncpy(pl_character, roles[i], PL_CSIZ - 1);
252 pl_character[PL_CSIZ - 1] = 0;
253 flags.beginner = 1;
254 u = zerou;
255 u.usym = '@';
256 u.ulevel = 1;
257 init_uhunger();
258 #ifdef QUEST
259 u.uhorizon = 6;
260 #endif /* QUEST */
261 uarm = uarm2 = uarmh = uarms = uarmg = uwep = uball = uchain =
262 uleft = uright = 0;
264 switch (pc) {
265 case 'c':
266 case 'C':
267 Cave_man[2].trquan = 12 + rnd(9) * rnd(9);
268 u.uhp = u.uhpmax = 16;
269 u.ustr = u.ustrmax = 18;
270 ini_inv(Cave_man);
271 break;
272 case 't':
273 case 'T':
274 Tourist[3].trquan = 20 + rnd(20);
275 u.ugold = u.ugold0 = rnd(1000);
276 u.uhp = u.uhpmax = 10;
277 u.ustr = u.ustrmax = 8;
278 ini_inv(Tourist);
279 if (!rn2(25))
280 ini_inv(Tinopener);
281 break;
282 case 'w':
283 case 'W':
284 for (i = 1; i <= 4; i++)
285 if (!rn2(5))
286 Wizard[i].trquan += rn2(3) - 1;
287 u.uhp = u.uhpmax = 15;
288 u.ustr = u.ustrmax = 16;
289 ini_inv(Wizard);
290 break;
291 case 's':
292 case 'S':
293 Fast = INTRINSIC;
294 Stealth = INTRINSIC;
295 u.uhp = u.uhpmax = 12;
296 u.ustr = u.ustrmax = 10;
297 ini_inv(Speleologist);
298 if (!rn2(10))
299 ini_inv(Tinopener);
300 break;
301 case 'k':
302 case 'K':
303 u.uhp = u.uhpmax = 12;
304 u.ustr = u.ustrmax = 10;
305 ini_inv(Knight);
306 break;
307 case 'f':
308 case 'F':
309 u.uhp = u.uhpmax = 14;
310 u.ustr = u.ustrmax = 17;
311 ini_inv(Fighter);
312 break;
313 default: /* impossible */
314 u.uhp = u.uhpmax = 12;
315 u.ustr = u.ustrmax = 16;
317 find_ac();
318 if (!rn2(20)) {
319 int dr = rn2(7) - 2; /* biased variation */
320 u.ustr += dr;
321 u.ustrmax += dr;
323 #ifdef WIZARD
324 if (wizard)
325 wiz_inv();
326 #endif /* WIZARD */
328 /* make sure he can carry all he has - especially for T's */
329 while (inv_weight() > 0 && u.ustr < 118)
330 u.ustr++, u.ustrmax++;
333 void
334 ini_inv(struct trobj *trop)
336 struct obj *obj;
337 while (trop->trolet) {
338 obj = mkobj(trop->trolet);
339 obj->known = trop->trknown;
340 /* not obj->dknown = 1; - let him look at it at least once */
341 obj->cursed = 0;
342 if (obj->olet == WEAPON_SYM) {
343 obj->quan = trop->trquan;
344 trop->trquan = 1;
346 if (trop->trspe != UNDEF_SPE)
347 obj->spe = trop->trspe;
348 if (trop->trotyp != UNDEF_TYP)
349 obj->otyp = trop->trotyp;
350 else if (obj->otyp == WAN_WISHING) /* gitpyr!robert */
351 obj->otyp = WAN_DEATH;
352 obj->owt = weight(obj); /* defined after setting otyp+quan */
353 obj = addinv(obj);
354 if (obj->olet == ARMOR_SYM) {
355 switch (obj->otyp) {
356 case SHIELD:
357 if (!uarms)
358 setworn(obj, W_ARMS);
359 break;
360 case HELMET:
361 if (!uarmh)
362 setworn(obj, W_ARMH);
363 break;
364 case PAIR_OF_GLOVES:
365 if (!uarmg)
366 setworn(obj, W_ARMG);
367 break;
368 case ELVEN_CLOAK:
369 if (!uarm2)
370 setworn(obj, W_ARM);
371 break;
372 default:
373 if (!uarm)
374 setworn(obj, W_ARM);
377 if (obj->olet == WEAPON_SYM)
378 if (!uwep)
379 setuwep(obj);
380 #ifndef PYRAMID_BUG
381 if (--trop->trquan)
382 continue; /* make a similar object */
383 #else
384 if (trop->trquan) { /* check if zero first */
385 --trop->trquan;
386 if (trop->trquan)
387 continue; /* make a similar object */
389 #endif /* PYRAMID_BUG */
390 trop++;
394 #ifdef WIZARD
395 void
396 wiz_inv(void)
398 struct trobj *trop = &Extra_objs[0];
399 char *ep = getenv("INVENT");
400 int type;
401 while (ep && *ep) {
402 type = atoi(ep);
403 ep = strchr(ep, ',');
404 if (ep)
405 while (*ep == ',' || *ep == ' ')
406 ep++;
407 if (type <= 0 || type > NROFOBJECTS)
408 continue;
409 trop->trotyp = type;
410 trop->trolet = objects[type].oc_olet;
411 trop->trspe = 4;
412 trop->trknown = 1;
413 trop->trquan = 1;
414 ini_inv(trop);
416 /* give him a wand of wishing by default */
417 trop->trotyp = WAN_WISHING;
418 trop->trolet = WAND_SYM;
419 trop->trspe = 20;
420 trop->trknown = 1;
421 trop->trquan = 1;
422 ini_inv(trop);
424 #endif /* WIZARD */
426 void
427 plnamesuffix(void)
429 char *p;
430 if ((p = strrchr(plname, '-')) != NULL) {
431 *p = 0;
432 pl_character[0] = p[1];
433 pl_character[1] = 0;
434 if (!plname[0]) {
435 askname();
436 plnamesuffix();
442 role_index(int pc)
443 { /* must be called only from u_init() */
444 /* so that rolesyms[] is defined */
445 char *cp;
447 if ((cp = strchr(rolesyms, pc)) != NULL)
448 return (cp - rolesyms);
449 return (-1);