1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Timothy C. Stoehr. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)pack.c 8.1 (Berkeley) 05/31/93"; 13 #endif /* not lint */ 14 15 /* 16 * pack.c 17 * 18 * This source herein may be modified and/or distributed by anybody who 19 * so desires, with the following restrictions: 20 * 1.) No portion of this notice shall be removed. 21 * 2.) Credit shall not be taken for the creation of this source. 22 * 3.) This code is not to be traded, sold, or used for personal 23 * gain or profit. 24 * 25 */ 26 27 #include "rogue.h" 28 29 char *curse_message = "you can't, it appears to be cursed"; 30 31 extern short levitate; 32 33 object * 34 add_to_pack(obj, pack, condense) 35 object *obj, *pack; 36 { 37 object *op; 38 39 if (condense) { 40 if (op = check_duplicate(obj, pack)) { 41 free_object(obj); 42 return(op); 43 } else { 44 obj->ichar = next_avail_ichar(); 45 } 46 } 47 if (pack->next_object == 0) { 48 pack->next_object = obj; 49 } else { 50 op = pack->next_object; 51 52 while (op->next_object) { 53 op = op->next_object; 54 } 55 op->next_object = obj; 56 } 57 obj->next_object = 0; 58 return(obj); 59 } 60 61 take_from_pack(obj, pack) 62 object *obj, *pack; 63 { 64 while (pack->next_object != obj) { 65 pack = pack->next_object; 66 } 67 pack->next_object = pack->next_object->next_object; 68 } 69 70 /* Note: *status is set to 0 if the rogue attempts to pick up a scroll 71 * of scare-monster and it turns to dust. *status is otherwise set to 1. 72 */ 73 74 object * 75 pick_up(row, col, status) 76 short *status; 77 { 78 object *obj; 79 80 *status = 1; 81 82 if (levitate) { 83 message("you're floating in the air!", 0); 84 return((object *) 0); 85 } 86 obj = object_at(&level_objects, row, col); 87 if (!obj) { 88 message("pick_up(): inconsistent", 1); 89 return(obj); 90 } 91 if ( (obj->what_is == SCROL) && 92 (obj->which_kind == SCARE_MONSTER) && 93 obj->picked_up) { 94 message("the scroll turns to dust as you pick it up", 0); 95 dungeon[row][col] &= (~OBJECT); 96 vanish(obj, 0, &level_objects); 97 *status = 0; 98 if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) { 99 id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED; 100 } 101 return((object *) 0); 102 } 103 if (obj->what_is == GOLD) { 104 rogue.gold += obj->quantity; 105 dungeon[row][col] &= ~(OBJECT); 106 take_from_pack(obj, &level_objects); 107 print_stats(STAT_GOLD); 108 return(obj); /* obj will be free_object()ed in caller */ 109 } 110 if (pack_count(obj) >= MAX_PACK_COUNT) { 111 message("pack too full", 1); 112 return((object *) 0); 113 } 114 dungeon[row][col] &= ~(OBJECT); 115 take_from_pack(obj, &level_objects); 116 obj = add_to_pack(obj, &rogue.pack, 1); 117 obj->picked_up = 1; 118 return(obj); 119 } 120 121 drop() 122 { 123 object *obj, *new; 124 short ch; 125 char desc[DCOLS]; 126 127 if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) { 128 message("there's already something there", 0); 129 return; 130 } 131 if (!rogue.pack.next_object) { 132 message("you have nothing to drop", 0); 133 return; 134 } 135 if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) { 136 return; 137 } 138 if (!(obj = get_letter_object(ch))) { 139 message("no such item.", 0); 140 return; 141 } 142 if (obj->in_use_flags & BEING_WIELDED) { 143 if (obj->is_cursed) { 144 message(curse_message, 0); 145 return; 146 } 147 unwield(rogue.weapon); 148 } else if (obj->in_use_flags & BEING_WORN) { 149 if (obj->is_cursed) { 150 message(curse_message, 0); 151 return; 152 } 153 mv_aquatars(); 154 unwear(rogue.armor); 155 print_stats(STAT_ARMOR); 156 } else if (obj->in_use_flags & ON_EITHER_HAND) { 157 if (obj->is_cursed) { 158 message(curse_message, 0); 159 return; 160 } 161 un_put_on(obj); 162 } 163 obj->row = rogue.row; 164 obj->col = rogue.col; 165 166 if ((obj->quantity > 1) && (obj->what_is != WEAPON)) { 167 obj->quantity--; 168 new = alloc_object(); 169 *new = *obj; 170 new->quantity = 1; 171 obj = new; 172 } else { 173 obj->ichar = 'L'; 174 take_from_pack(obj, &rogue.pack); 175 } 176 place_at(obj, rogue.row, rogue.col); 177 (void) strcpy(desc, "dropped "); 178 get_desc(obj, desc+8); 179 message(desc, 0); 180 (void) reg_move(); 181 } 182 183 object * 184 check_duplicate(obj, pack) 185 object *obj, *pack; 186 { 187 object *op; 188 189 if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) { 190 return(0); 191 } 192 if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) { 193 return(0); 194 } 195 op = pack->next_object; 196 197 while (op) { 198 if ((op->what_is == obj->what_is) && 199 (op->which_kind == obj->which_kind)) { 200 201 if ((obj->what_is != WEAPON) || 202 ((obj->what_is == WEAPON) && 203 ((obj->which_kind == ARROW) || 204 (obj->which_kind == DAGGER) || 205 (obj->which_kind == DART) || 206 (obj->which_kind == SHURIKEN)) && 207 (obj->quiver == op->quiver))) { 208 op->quantity += obj->quantity; 209 return(op); 210 } 211 } 212 op = op->next_object; 213 } 214 return(0); 215 } 216 217 next_avail_ichar() 218 { 219 register object *obj; 220 register i; 221 boolean ichars[26]; 222 223 for (i = 0; i < 26; i++) { 224 ichars[i] = 0; 225 } 226 obj = rogue.pack.next_object; 227 while (obj) { 228 ichars[(obj->ichar - 'a')] = 1; 229 obj = obj->next_object; 230 } 231 for (i = 0; i < 26; i++) { 232 if (!ichars[i]) { 233 return(i + 'a'); 234 } 235 } 236 return('?'); 237 } 238 239 wait_for_ack() 240 { 241 while (rgetchar() != ' ') ; 242 } 243 244 pack_letter(prompt, mask) 245 char *prompt; 246 unsigned short mask; 247 { 248 short ch; 249 unsigned short tmask = mask; 250 251 if (!mask_pack(&rogue.pack, mask)) { 252 message("nothing appropriate", 0); 253 return(CANCEL); 254 } 255 for (;;) { 256 257 message(prompt, 0); 258 259 for (;;) { 260 ch = rgetchar(); 261 if (!is_pack_letter(&ch, &mask)) { 262 sound_bell(); 263 } else { 264 break; 265 } 266 } 267 268 if (ch == LIST) { 269 check_message(); 270 mask = tmask; 271 inventory(&rogue.pack, mask); 272 } else { 273 break; 274 } 275 mask = tmask; 276 } 277 check_message(); 278 return(ch); 279 } 280 281 take_off() 282 { 283 char desc[DCOLS]; 284 object *obj; 285 286 if (rogue.armor) { 287 if (rogue.armor->is_cursed) { 288 message(curse_message, 0); 289 } else { 290 mv_aquatars(); 291 obj = rogue.armor; 292 unwear(rogue.armor); 293 (void) strcpy(desc, "was wearing "); 294 get_desc(obj, desc+12); 295 message(desc, 0); 296 print_stats(STAT_ARMOR); 297 (void) reg_move(); 298 } 299 } else { 300 message("not wearing any", 0); 301 } 302 } 303 304 wear() 305 { 306 short ch; 307 register object *obj; 308 char desc[DCOLS]; 309 310 if (rogue.armor) { 311 message("your already wearing some", 0); 312 return; 313 } 314 ch = pack_letter("wear what?", ARMOR); 315 316 if (ch == CANCEL) { 317 return; 318 } 319 if (!(obj = get_letter_object(ch))) { 320 message("no such item.", 0); 321 return; 322 } 323 if (obj->what_is != ARMOR) { 324 message("you can't wear that", 0); 325 return; 326 } 327 obj->identified = 1; 328 (void) strcpy(desc, "wearing "); 329 get_desc(obj, desc + 8); 330 message(desc, 0); 331 do_wear(obj); 332 print_stats(STAT_ARMOR); 333 (void) reg_move(); 334 } 335 336 unwear(obj) 337 object *obj; 338 { 339 if (obj) { 340 obj->in_use_flags &= (~BEING_WORN); 341 } 342 rogue.armor = (object *) 0; 343 } 344 345 do_wear(obj) 346 object *obj; 347 { 348 rogue.armor = obj; 349 obj->in_use_flags |= BEING_WORN; 350 obj->identified = 1; 351 } 352 353 wield() 354 { 355 short ch; 356 register object *obj; 357 char desc[DCOLS]; 358 359 if (rogue.weapon && rogue.weapon->is_cursed) { 360 message(curse_message, 0); 361 return; 362 } 363 ch = pack_letter("wield what?", WEAPON); 364 365 if (ch == CANCEL) { 366 return; 367 } 368 if (!(obj = get_letter_object(ch))) { 369 message("No such item.", 0); 370 return; 371 } 372 if (obj->what_is & (ARMOR | RING)) { 373 sprintf(desc, "you can't wield %s", 374 ((obj->what_is == ARMOR) ? "armor" : "rings")); 375 message(desc, 0); 376 return; 377 } 378 if (obj->in_use_flags & BEING_WIELDED) { 379 message("in use", 0); 380 } else { 381 unwield(rogue.weapon); 382 (void) strcpy(desc, "wielding "); 383 get_desc(obj, desc + 9); 384 message(desc, 0); 385 do_wield(obj); 386 (void) reg_move(); 387 } 388 } 389 390 do_wield(obj) 391 object *obj; 392 { 393 rogue.weapon = obj; 394 obj->in_use_flags |= BEING_WIELDED; 395 } 396 397 unwield(obj) 398 object *obj; 399 { 400 if (obj) { 401 obj->in_use_flags &= (~BEING_WIELDED); 402 } 403 rogue.weapon = (object *) 0; 404 } 405 406 call_it() 407 { 408 short ch; 409 register object *obj; 410 struct id *id_table; 411 char buf[MAX_TITLE_LENGTH+2]; 412 413 ch = pack_letter("call what?", (SCROL | POTION | WAND | RING)); 414 415 if (ch == CANCEL) { 416 return; 417 } 418 if (!(obj = get_letter_object(ch))) { 419 message("no such item.", 0); 420 return; 421 } 422 if (!(obj->what_is & (SCROL | POTION | WAND | RING))) { 423 message("surely you already know what that's called", 0); 424 return; 425 } 426 id_table = get_id_table(obj); 427 428 if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) { 429 id_table[obj->which_kind].id_status = CALLED; 430 (void) strcpy(id_table[obj->which_kind].title, buf); 431 } 432 } 433 434 pack_count(new_obj) 435 object *new_obj; 436 { 437 object *obj; 438 short count = 0; 439 440 obj = rogue.pack.next_object; 441 442 while (obj) { 443 if (obj->what_is != WEAPON) { 444 count += obj->quantity; 445 } else if (!new_obj) { 446 count++; 447 } else if ((new_obj->what_is != WEAPON) || 448 ((obj->which_kind != ARROW) && 449 (obj->which_kind != DAGGER) && 450 (obj->which_kind != DART) && 451 (obj->which_kind != SHURIKEN)) || 452 (new_obj->which_kind != obj->which_kind) || 453 (obj->quiver != new_obj->quiver)) { 454 count++; 455 } 456 obj = obj->next_object; 457 } 458 return(count); 459 } 460 461 boolean 462 mask_pack(pack, mask) 463 object *pack; 464 unsigned short mask; 465 { 466 while (pack->next_object) { 467 pack = pack->next_object; 468 if (pack->what_is & mask) { 469 return(1); 470 } 471 } 472 return(0); 473 } 474 475 is_pack_letter(c, mask) 476 short *c; 477 unsigned short *mask; 478 { 479 if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') || 480 (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) { 481 switch(*c) { 482 case '?': 483 *mask = SCROL; 484 break; 485 case '!': 486 *mask = POTION; 487 break; 488 case ':': 489 *mask = FOOD; 490 break; 491 case ')': 492 *mask = WEAPON; 493 break; 494 case ']': 495 *mask = ARMOR; 496 break; 497 case '/': 498 *mask = WAND; 499 break; 500 case '=': 501 *mask = RING; 502 break; 503 case ',': 504 *mask = AMULET; 505 break; 506 } 507 *c = LIST; 508 return(1); 509 } 510 return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST)); 511 } 512 513 has_amulet() 514 { 515 return(mask_pack(&rogue.pack, AMULET)); 516 } 517 518 kick_into_pack() 519 { 520 object *obj; 521 char desc[DCOLS]; 522 short n, stat; 523 524 if (!(dungeon[rogue.row][rogue.col] & OBJECT)) { 525 message("nothing here", 0); 526 } else { 527 if (obj = pick_up(rogue.row, rogue.col, &stat)) { 528 get_desc(obj, desc); 529 if (obj->what_is == GOLD) { 530 message(desc, 0); 531 free_object(obj); 532 } else { 533 n = strlen(desc); 534 desc[n] = '('; 535 desc[n+1] = obj->ichar; 536 desc[n+2] = ')'; 537 desc[n+3] = 0; 538 message(desc, 0); 539 } 540 } 541 if (obj || (!stat)) { 542 (void) reg_move(); 543 } 544 } 545 } 546