1 /* $NetBSD: hack.u_init.c,v 1.12 2010/02/03 15:34:39 roy 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.12 2010/02/03 15:34:39 roy 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 char pl_character[PL_CSIZ]; 81 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" 87 }; 88 #define NR_OF_ROLES SIZE(roles) 89 static char rolesyms[NR_OF_ROLES + 1]; /* filled by u_init() */ 90 91 struct trobj { 92 uchar trotyp; 93 schar trspe; 94 char trolet; 95 Bitfield(trquan, 6); 96 Bitfield(trknown, 1); 97 }; 98 99 #ifdef WIZARD 100 static struct trobj Extra_objs[] = { 101 {0, 0, 0, 0, 0}, 102 {0, 0, 0, 0, 0} 103 }; 104 #endif /* WIZARD */ 105 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} 112 }; 113 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} 118 }; 119 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} 128 }; 129 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} 137 }; 138 139 static struct trobj Tinopener[] = { 140 {CAN_OPENER, 0, TOOL_SYM, 1, 1}, 141 {0, 0, 0, 0, 0} 142 }; 143 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} 150 }; 151 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} 159 }; 160 161 static void ini_inv(struct trobj *); 162 static void wiz_inv(void); 163 static int role_index(int); 164 165 void 166 u_init(void) 167 { 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; 175 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; 183 } 184 printf("\nAre you an experienced player? [ny] "); 185 186 while (!strchr("ynYN \n\004", (exper = readchar()))) 187 sound_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; 194 } 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"); 205 } 206 printf("? [%s] ", rolesyms); 207 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; 215 } 216 if (pc == '\n') 217 break; 218 if (pc == '\004') /* Give him the opportunity to get 219 * out */ 220 end_of_input(); 221 sound_bell(); 222 } 223 if (pc == '\n') 224 pc = 0; 225 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); 238 } 239 #if 0 240 /* 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 243 */ 244 if (exper) { 245 roles[i][0] = pc; 246 } 247 #endif 248 249 got_suffix: 250 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; 263 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; 316 } 317 find_ac(); 318 if (!rn2(20)) { 319 int dr = rn2(7) - 2; /* biased variation */ 320 u.ustr += dr; 321 u.ustrmax += dr; 322 } 323 #ifdef WIZARD 324 if (wizard) 325 wiz_inv(); 326 #endif /* WIZARD */ 327 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++; 331 } 332 333 void 334 ini_inv(struct trobj *trop) 335 { 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; 345 } 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); 375 } 376 } 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 */ 388 } 389 #endif /* PYRAMID_BUG */ 390 trop++; 391 } 392 } 393 394 #ifdef WIZARD 395 void 396 wiz_inv(void) 397 { 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); 415 } 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); 423 } 424 #endif /* WIZARD */ 425 426 void 427 plnamesuffix(void) 428 { 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(); 437 } 438 } 439 } 440 441 int 442 role_index(int pc) 443 { /* must be called only from u_init() */ 444 /* so that rolesyms[] is defined */ 445 char *cp; 446 447 if ((cp = strchr(rolesyms, pc)) != NULL) 448 return (cp - rolesyms); 449 return (-1); 450 } 451