xref: /dragonfly/games/hack/hack.u_init.c (revision 4318c66eac379e15105fe145d406dfef81b795f6)
1 /*        $NetBSD: hack.u_init.c,v 1.13 2011/08/06 19:32:58 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 <ctype.h>
65 #include <signal.h>
66 #include <stdlib.h>
67 #include "hack.h"
68 #include "extern.h"
69 
70 #define Strcpy      (void) strcpy
71 #define   Strcat    (void) strcat
72 #define   UNDEF_TYP 0
73 #define   UNDEF_SPE '\177'
74 
75 char pl_character[PL_CSIZ];
76 
77 static const struct you zerou;
78 static const char *(roles[]) = {      /* must all have distinct first letter */
79           /* roles[4] may be changed to -woman */
80           "Tourist", "Speleologist", "Fighter", "Knight",
81           "Cave-man", "Wizard"
82 };
83 #define   NR_OF_ROLES         SIZE(roles)
84 static char rolesyms[NR_OF_ROLES + 1];  /* filled by u_init() */
85 
86 struct trobj {
87           uchar           trotyp;
88           schar           trspe;
89           char            trolet;
90                           Bitfield(trquan, 6);
91                           Bitfield(trknown, 1);
92 };
93 
94 #ifdef WIZARD
95 static struct trobj Extra_objs[] = {
96           {0, 0, 0, 0, 0},
97           {0, 0, 0, 0, 0}
98 };
99 #endif    /* WIZARD */
100 
101 static struct trobj Cave_man[] = {
102           {MACE, 1, WEAPON_SYM, 1, 1},
103           {BOW, 1, WEAPON_SYM, 1, 1},
104           {ARROW, 0, WEAPON_SYM, 25, 1},          /* quan is variable */
105           {LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1},
106           {0, 0, 0, 0, 0}
107 };
108 
109 static struct trobj Fighter[] = {
110           {TWO_HANDED_SWORD, 0, WEAPON_SYM, 1, 1},
111           {RING_MAIL, 0, ARMOR_SYM, 1, 1},
112           {0, 0, 0, 0, 0}
113 };
114 
115 static struct trobj Knight[] = {
116           {LONG_SWORD, 0, WEAPON_SYM, 1, 1},
117           {SPEAR, 2, WEAPON_SYM, 1, 1},
118           {RING_MAIL, 1, ARMOR_SYM, 1, 1},
119           {HELMET, 0, ARMOR_SYM, 1, 1},
120           {SHIELD, 0, ARMOR_SYM, 1, 1},
121           {PAIR_OF_GLOVES, 0, ARMOR_SYM, 1, 1},
122           {0, 0, 0, 0, 0}
123 };
124 
125 static struct trobj Speleologist[] = {
126           {STUDDED_LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1},
127           {UNDEF_TYP, 0, POTION_SYM, 2, 0},
128           {FOOD_RATION, 0, FOOD_SYM, 3, 1},
129           {PICK_AXE, UNDEF_SPE, TOOL_SYM, 1, 0},
130           {ICE_BOX, 0, TOOL_SYM, 1, 0},
131           {0, 0, 0, 0, 0}
132 };
133 
134 static struct trobj Tinopener[] = {
135           {CAN_OPENER, 0, TOOL_SYM, 1, 1},
136           {0, 0, 0, 0, 0}
137 };
138 
139 static struct trobj Tourist[] = {
140           {UNDEF_TYP, 0, FOOD_SYM, 10, 1},
141           {POT_EXTRA_HEALING, 0, POTION_SYM, 2, 0},
142           {EXPENSIVE_CAMERA, 0, TOOL_SYM, 1, 1},
143           {DART, 2, WEAPON_SYM, 25, 1}, /* quan is variable */
144           {0, 0, 0, 0, 0}
145 };
146 
147 static struct trobj Wizard[] = {
148           {ELVEN_CLOAK, 0, ARMOR_SYM, 1, 1},
149           {UNDEF_TYP, UNDEF_SPE, WAND_SYM, 2, 0},
150           {UNDEF_TYP, UNDEF_SPE, RING_SYM, 2, 0},
151           {UNDEF_TYP, UNDEF_SPE, POTION_SYM, 2, 0},
152           {UNDEF_TYP, UNDEF_SPE, SCROLL_SYM, 3, 0},
153           {0, 0, 0, 0, 0}
154 };
155 
156 static void ini_inv(struct trobj *);
157 static void wiz_inv(void);
158 static int role_index(int);
159 
160 void
u_init(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                     sound_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                     sound_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
ini_inv(struct trobj * trop)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                     if (--trop->trquan)
376                               continue; /* make a similar object */
377                     trop++;
378           }
379 }
380 
381 #ifdef WIZARD
382 void
wiz_inv(void)383 wiz_inv(void)
384 {
385           struct trobj *trop = &Extra_objs[0];
386           char  *ep = getenv("INVENT");
387           int    type;
388           while (ep && *ep) {
389                     type = atoi(ep);
390                     ep = strchr(ep, ',');
391                     if (ep)
392                               while (*ep == ',' || *ep == ' ')
393                                         ep++;
394                     if (type <= 0 || type > NROFOBJECTS)
395                               continue;
396                     trop->trotyp = type;
397                     trop->trolet = objects[type].oc_olet;
398                     trop->trspe = 4;
399                     trop->trknown = 1;
400                     trop->trquan = 1;
401                     ini_inv(trop);
402           }
403           /* give him a wand of wishing by default */
404           trop->trotyp = WAN_WISHING;
405           trop->trolet = WAND_SYM;
406           trop->trspe = 20;
407           trop->trknown = 1;
408           trop->trquan = 1;
409           ini_inv(trop);
410 }
411 #endif    /* WIZARD */
412 
413 void
plnamesuffix(void)414 plnamesuffix(void)
415 {
416           char  *p;
417           if ((p = strrchr(plname, '-')) != NULL) {
418                     *p = 0;
419                     pl_character[0] = p[1];
420                     pl_character[1] = 0;
421                     if (!plname[0]) {
422                               askname();
423                               plnamesuffix();
424                     }
425           }
426 }
427 
428 int
role_index(int pc)429 role_index(int pc)
430 {                                       /* must be called only from u_init() */
431           /* so that rolesyms[] is defined */
432           char  *cp;
433 
434           if ((cp = strchr(rolesyms, pc)) != NULL)
435                     return (cp - rolesyms);
436           return (-1);
437 }
438