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