1 /* $NetBSD: hack.u_init.c,v 1.8 2004/11/05 21:30:32 dsl 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.8 2004/11/05 21:30:32 dsl 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() 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 d = rn2(7) - 2; /* biased variation */ 315 u.ustr += d; 316 u.ustrmax += d; 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(trop) 330 struct trobj *trop; 331 { 332 struct obj *obj; 333 while (trop->trolet) { 334 obj = mkobj(trop->trolet); 335 obj->known = trop->trknown; 336 /* not obj->dknown = 1; - let him look at it at least once */ 337 obj->cursed = 0; 338 if (obj->olet == WEAPON_SYM) { 339 obj->quan = trop->trquan; 340 trop->trquan = 1; 341 } 342 if (trop->trspe != UNDEF_SPE) 343 obj->spe = trop->trspe; 344 if (trop->trotyp != UNDEF_TYP) 345 obj->otyp = trop->trotyp; 346 else if (obj->otyp == WAN_WISHING) /* gitpyr!robert */ 347 obj->otyp = WAN_DEATH; 348 obj->owt = weight(obj); /* defined after setting otyp+quan */ 349 obj = addinv(obj); 350 if (obj->olet == ARMOR_SYM) { 351 switch (obj->otyp) { 352 case SHIELD: 353 if (!uarms) 354 setworn(obj, W_ARMS); 355 break; 356 case HELMET: 357 if (!uarmh) 358 setworn(obj, W_ARMH); 359 break; 360 case PAIR_OF_GLOVES: 361 if (!uarmg) 362 setworn(obj, W_ARMG); 363 break; 364 case ELVEN_CLOAK: 365 if (!uarm2) 366 setworn(obj, W_ARM); 367 break; 368 default: 369 if (!uarm) 370 setworn(obj, W_ARM); 371 } 372 } 373 if (obj->olet == WEAPON_SYM) 374 if (!uwep) 375 setuwep(obj); 376 #ifndef PYRAMID_BUG 377 if (--trop->trquan) 378 continue; /* make a similar object */ 379 #else 380 if (trop->trquan) { /* check if zero first */ 381 --trop->trquan; 382 if (trop->trquan) 383 continue; /* make a similar object */ 384 } 385 #endif /* PYRAMID_BUG */ 386 trop++; 387 } 388 } 389 390 #ifdef WIZARD 391 void 392 wiz_inv() 393 { 394 struct trobj *trop = &Extra_objs[0]; 395 char *ep = getenv("INVENT"); 396 int type; 397 while (ep && *ep) { 398 type = atoi(ep); 399 ep = strchr(ep, ','); 400 if (ep) 401 while (*ep == ',' || *ep == ' ') 402 ep++; 403 if (type <= 0 || type > NROFOBJECTS) 404 continue; 405 trop->trotyp = type; 406 trop->trolet = objects[type].oc_olet; 407 trop->trspe = 4; 408 trop->trknown = 1; 409 trop->trquan = 1; 410 ini_inv(trop); 411 } 412 /* give him a wand of wishing by default */ 413 trop->trotyp = WAN_WISHING; 414 trop->trolet = WAND_SYM; 415 trop->trspe = 20; 416 trop->trknown = 1; 417 trop->trquan = 1; 418 ini_inv(trop); 419 } 420 #endif /* WIZARD */ 421 422 void 423 plnamesuffix() 424 { 425 char *p; 426 if ((p = strrchr(plname, '-')) != NULL) { 427 *p = 0; 428 pl_character[0] = p[1]; 429 pl_character[1] = 0; 430 if (!plname[0]) { 431 askname(); 432 plnamesuffix(); 433 } 434 } 435 } 436 437 int 438 role_index(pc) 439 char pc; 440 { /* must be called only from u_init() */ 441 /* so that rolesyms[] is defined */ 442 char *cp; 443 444 if ((cp = strchr(rolesyms, pc)) != NULL) 445 return (cp - rolesyms); 446 return (-1); 447 } 448