]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.u_init.c
28d3fc4078a29c6bd86764fb53145491c00a72ae
[bsdgames-darwin.git] / hack / hack.u_init.c
1 /* $NetBSD: hack.u_init.c,v 1.10 2009/06/07 18:30:39 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 * Amsterdam
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
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.
18 *
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.
23 *
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.
35 */
36
37 /*
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
40 *
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.
51 *
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.
62 */
63
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 */
68
69 #include <ctype.h>
70 #include <signal.h>
71 #include <stdlib.h>
72 #include "hack.h"
73 #include "extern.h"
74
75 #define Strcpy (void) strcpy
76 #define Strcat (void) strcat
77 #define UNDEF_TYP 0
78 #define UNDEF_SPE '\177'
79
80 struct you zerou;
81 char pl_character[PL_CSIZ];
82 const char *(roles[]) = { /* must all have distinct first letter */
83 /* roles[4] may be changed to -woman */
84 "Tourist", "Speleologist", "Fighter", "Knight",
85 "Cave-man", "Wizard"
86 };
87 #define NR_OF_ROLES SIZE(roles)
88 char rolesyms[NR_OF_ROLES + 1]; /* filled by u_init() */
89
90 struct trobj {
91 uchar trotyp;
92 schar trspe;
93 char trolet;
94 Bitfield(trquan, 6);
95 Bitfield(trknown, 1);
96 };
97
98 #ifdef WIZARD
99 struct trobj Extra_objs[] = {
100 {0, 0, 0, 0, 0},
101 {0, 0, 0, 0, 0}
102 };
103 #endif /* WIZARD */
104
105 struct trobj Cave_man[] = {
106 {MACE, 1, WEAPON_SYM, 1, 1},
107 {BOW, 1, WEAPON_SYM, 1, 1},
108 {ARROW, 0, WEAPON_SYM, 25, 1}, /* quan is variable */
109 {LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1},
110 {0, 0, 0, 0, 0}
111 };
112
113 struct trobj Fighter[] = {
114 {TWO_HANDED_SWORD, 0, WEAPON_SYM, 1, 1},
115 {RING_MAIL, 0, ARMOR_SYM, 1, 1},
116 {0, 0, 0, 0, 0}
117 };
118
119 struct trobj Knight[] = {
120 {LONG_SWORD, 0, WEAPON_SYM, 1, 1},
121 {SPEAR, 2, WEAPON_SYM, 1, 1},
122 {RING_MAIL, 1, ARMOR_SYM, 1, 1},
123 {HELMET, 0, ARMOR_SYM, 1, 1},
124 {SHIELD, 0, ARMOR_SYM, 1, 1},
125 {PAIR_OF_GLOVES, 0, ARMOR_SYM, 1, 1},
126 {0, 0, 0, 0, 0}
127 };
128
129 struct trobj Speleologist[] = {
130 {STUDDED_LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1},
131 {UNDEF_TYP, 0, POTION_SYM, 2, 0},
132 {FOOD_RATION, 0, FOOD_SYM, 3, 1},
133 {PICK_AXE, UNDEF_SPE, TOOL_SYM, 1, 0},
134 {ICE_BOX, 0, TOOL_SYM, 1, 0},
135 {0, 0, 0, 0, 0}
136 };
137
138 struct trobj Tinopener[] = {
139 {CAN_OPENER, 0, TOOL_SYM, 1, 1},
140 {0, 0, 0, 0, 0}
141 };
142
143 struct trobj Tourist[] = {
144 {UNDEF_TYP, 0, FOOD_SYM, 10, 1},
145 {POT_EXTRA_HEALING, 0, POTION_SYM, 2, 0},
146 {EXPENSIVE_CAMERA, 0, TOOL_SYM, 1, 1},
147 {DART, 2, WEAPON_SYM, 25, 1}, /* quan is variable */
148 {0, 0, 0, 0, 0}
149 };
150
151 struct trobj Wizard[] = {
152 {ELVEN_CLOAK, 0, ARMOR_SYM, 1, 1},
153 {UNDEF_TYP, UNDEF_SPE, WAND_SYM, 2, 0},
154 {UNDEF_TYP, UNDEF_SPE, RING_SYM, 2, 0},
155 {UNDEF_TYP, UNDEF_SPE, POTION_SYM, 2, 0},
156 {UNDEF_TYP, UNDEF_SPE, SCROLL_SYM, 3, 0},
157 {0, 0, 0, 0, 0}
158 };
159
160 void
161 u_init(void)
162 {
163 int i;
164 char exper = 'y', pc;
165 if (flags.female) /* should have been set in HACKOPTIONS */
166 roles[4] = "Cave-woman";
167 for (i = 0; i < NR_OF_ROLES; i++)
168 rolesyms[i] = roles[i][0];
169 rolesyms[i] = 0;
170
171 if ((pc = pl_character[0]) != '\0') {
172 if (islower((unsigned char)pc))
173 pc = toupper((unsigned char)pc);
174 if ((i = role_index(pc)) >= 0)
175 goto got_suffix; /* implies experienced */
176 printf("\nUnknown role: %c\n", pc);
177 pl_character[0] = pc = 0;
178 }
179 printf("\nAre you an experienced player? [ny] ");
180
181 while (!strchr("ynYN \n\004", (exper = readchar())))
182 bell();
183 if (exper == '\004') /* Give him an opportunity to get out */
184 end_of_input();
185 printf("%c\n", exper); /* echo */
186 if (strchr("Nn \n", exper)) {
187 exper = 0;
188 goto beginner;
189 }
190 printf("\nTell me what kind of character you are:\n");
191 printf("Are you");
192 for (i = 0; i < NR_OF_ROLES; i++) {
193 printf(" a %s", roles[i]);
194 if (i == 2) /* %% */
195 printf(",\n\t");
196 else if (i < NR_OF_ROLES - 2)
197 printf(",");
198 else if (i == NR_OF_ROLES - 2)
199 printf(" or");
200 }
201 printf("? [%s] ", rolesyms);
202
203 while ((pc = readchar()) != '\0') {
204 if (islower((unsigned char)pc))
205 pc = toupper((unsigned char)pc);
206 if ((i = role_index(pc)) >= 0) {
207 printf("%c\n", pc); /* echo */
208 (void) fflush(stdout); /* should be seen */
209 break;
210 }
211 if (pc == '\n')
212 break;
213 if (pc == '\004') /* Give him the opportunity to get
214 * out */
215 end_of_input();
216 bell();
217 }
218 if (pc == '\n')
219 pc = 0;
220
221 beginner:
222 if (!pc) {
223 printf("\nI'll choose a character for you.\n");
224 i = rn2(NR_OF_ROLES);
225 pc = rolesyms[i];
226 printf("This game you will be a%s %s.\n",
227 exper ? "n experienced" : "",
228 roles[i]);
229 getret();
230 /* give him some feedback in case mklev takes much time */
231 (void) putchar('\n');
232 (void) fflush(stdout);
233 }
234 #if 0
235 /*
236 * Given the above code, I can't see why this would ever change
237 * anything; it does core pretty well, though. - cmh 4/20/93
238 */
239 if (exper) {
240 roles[i][0] = pc;
241 }
242 #endif
243
244 got_suffix:
245
246 (void) strncpy(pl_character, roles[i], PL_CSIZ - 1);
247 pl_character[PL_CSIZ - 1] = 0;
248 flags.beginner = 1;
249 u = zerou;
250 u.usym = '@';
251 u.ulevel = 1;
252 init_uhunger();
253 #ifdef QUEST
254 u.uhorizon = 6;
255 #endif /* QUEST */
256 uarm = uarm2 = uarmh = uarms = uarmg = uwep = uball = uchain =
257 uleft = uright = 0;
258
259 switch (pc) {
260 case 'c':
261 case 'C':
262 Cave_man[2].trquan = 12 + rnd(9) * rnd(9);
263 u.uhp = u.uhpmax = 16;
264 u.ustr = u.ustrmax = 18;
265 ini_inv(Cave_man);
266 break;
267 case 't':
268 case 'T':
269 Tourist[3].trquan = 20 + rnd(20);
270 u.ugold = u.ugold0 = rnd(1000);
271 u.uhp = u.uhpmax = 10;
272 u.ustr = u.ustrmax = 8;
273 ini_inv(Tourist);
274 if (!rn2(25))
275 ini_inv(Tinopener);
276 break;
277 case 'w':
278 case 'W':
279 for (i = 1; i <= 4; i++)
280 if (!rn2(5))
281 Wizard[i].trquan += rn2(3) - 1;
282 u.uhp = u.uhpmax = 15;
283 u.ustr = u.ustrmax = 16;
284 ini_inv(Wizard);
285 break;
286 case 's':
287 case 'S':
288 Fast = INTRINSIC;
289 Stealth = INTRINSIC;
290 u.uhp = u.uhpmax = 12;
291 u.ustr = u.ustrmax = 10;
292 ini_inv(Speleologist);
293 if (!rn2(10))
294 ini_inv(Tinopener);
295 break;
296 case 'k':
297 case 'K':
298 u.uhp = u.uhpmax = 12;
299 u.ustr = u.ustrmax = 10;
300 ini_inv(Knight);
301 break;
302 case 'f':
303 case 'F':
304 u.uhp = u.uhpmax = 14;
305 u.ustr = u.ustrmax = 17;
306 ini_inv(Fighter);
307 break;
308 default: /* impossible */
309 u.uhp = u.uhpmax = 12;
310 u.ustr = u.ustrmax = 16;
311 }
312 find_ac();
313 if (!rn2(20)) {
314 int dr = rn2(7) - 2; /* biased variation */
315 u.ustr += dr;
316 u.ustrmax += dr;
317 }
318 #ifdef WIZARD
319 if (wizard)
320 wiz_inv();
321 #endif /* WIZARD */
322
323 /* make sure he can carry all he has - especially for T's */
324 while (inv_weight() > 0 && u.ustr < 118)
325 u.ustr++, u.ustrmax++;
326 }
327
328 void
329 ini_inv(struct trobj *trop)
330 {
331 struct obj *obj;
332 while (trop->trolet) {
333 obj = mkobj(trop->trolet);
334 obj->known = trop->trknown;
335 /* not obj->dknown = 1; - let him look at it at least once */
336 obj->cursed = 0;
337 if (obj->olet == WEAPON_SYM) {
338 obj->quan = trop->trquan;
339 trop->trquan = 1;
340 }
341 if (trop->trspe != UNDEF_SPE)
342 obj->spe = trop->trspe;
343 if (trop->trotyp != UNDEF_TYP)
344 obj->otyp = trop->trotyp;
345 else if (obj->otyp == WAN_WISHING) /* gitpyr!robert */
346 obj->otyp = WAN_DEATH;
347 obj->owt = weight(obj); /* defined after setting otyp+quan */
348 obj = addinv(obj);
349 if (obj->olet == ARMOR_SYM) {
350 switch (obj->otyp) {
351 case SHIELD:
352 if (!uarms)
353 setworn(obj, W_ARMS);
354 break;
355 case HELMET:
356 if (!uarmh)
357 setworn(obj, W_ARMH);
358 break;
359 case PAIR_OF_GLOVES:
360 if (!uarmg)
361 setworn(obj, W_ARMG);
362 break;
363 case ELVEN_CLOAK:
364 if (!uarm2)
365 setworn(obj, W_ARM);
366 break;
367 default:
368 if (!uarm)
369 setworn(obj, W_ARM);
370 }
371 }
372 if (obj->olet == WEAPON_SYM)
373 if (!uwep)
374 setuwep(obj);
375 #ifndef PYRAMID_BUG
376 if (--trop->trquan)
377 continue; /* make a similar object */
378 #else
379 if (trop->trquan) { /* check if zero first */
380 --trop->trquan;
381 if (trop->trquan)
382 continue; /* make a similar object */
383 }
384 #endif /* PYRAMID_BUG */
385 trop++;
386 }
387 }
388
389 #ifdef WIZARD
390 void
391 wiz_inv(void)
392 {
393 struct trobj *trop = &Extra_objs[0];
394 char *ep = getenv("INVENT");
395 int type;
396 while (ep && *ep) {
397 type = atoi(ep);
398 ep = strchr(ep, ',');
399 if (ep)
400 while (*ep == ',' || *ep == ' ')
401 ep++;
402 if (type <= 0 || type > NROFOBJECTS)
403 continue;
404 trop->trotyp = type;
405 trop->trolet = objects[type].oc_olet;
406 trop->trspe = 4;
407 trop->trknown = 1;
408 trop->trquan = 1;
409 ini_inv(trop);
410 }
411 /* give him a wand of wishing by default */
412 trop->trotyp = WAN_WISHING;
413 trop->trolet = WAND_SYM;
414 trop->trspe = 20;
415 trop->trknown = 1;
416 trop->trquan = 1;
417 ini_inv(trop);
418 }
419 #endif /* WIZARD */
420
421 void
422 plnamesuffix(void)
423 {
424 char *p;
425 if ((p = strrchr(plname, '-')) != NULL) {
426 *p = 0;
427 pl_character[0] = p[1];
428 pl_character[1] = 0;
429 if (!plname[0]) {
430 askname();
431 plnamesuffix();
432 }
433 }
434 }
435
436 int
437 role_index(int pc)
438 { /* must be called only from u_init() */
439 /* so that rolesyms[] is defined */
440 char *cp;
441
442 if ((cp = strchr(rolesyms, pc)) != NULL)
443 return (cp - rolesyms);
444 return (-1);
445 }