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