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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)pack.c 5.3 (Berkeley) 06/01/90"; 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 inventory(&rogue.pack, mask); 271 } else { 272 break; 273 } 274 mask = tmask; 275 } 276 check_message(); 277 return(ch); 278 } 279 280 take_off() 281 { 282 char desc[DCOLS]; 283 object *obj; 284 285 if (rogue.armor) { 286 if (rogue.armor->is_cursed) { 287 message(curse_message, 0); 288 } else { 289 mv_aquatars(); 290 obj = rogue.armor; 291 unwear(rogue.armor); 292 (void) strcpy(desc, "was wearing "); 293 get_desc(obj, desc+12); 294 message(desc, 0); 295 print_stats(STAT_ARMOR); 296 (void) reg_move(); 297 } 298 } else { 299 message("not wearing any", 0); 300 } 301 } 302 303 wear() 304 { 305 short ch; 306 register object *obj; 307 char desc[DCOLS]; 308 309 if (rogue.armor) { 310 message("your already wearing some", 0); 311 return; 312 } 313 ch = pack_letter("wear what?", ARMOR); 314 315 if (ch == CANCEL) { 316 return; 317 } 318 if (!(obj = get_letter_object(ch))) { 319 message("no such item.", 0); 320 return; 321 } 322 if (obj->what_is != ARMOR) { 323 message("you can't wear that", 0); 324 return; 325 } 326 obj->identified = 1; 327 (void) strcpy(desc, "wearing "); 328 get_desc(obj, desc + 8); 329 message(desc, 0); 330 do_wear(obj); 331 print_stats(STAT_ARMOR); 332 (void) reg_move(); 333 } 334 335 unwear(obj) 336 object *obj; 337 { 338 if (obj) { 339 obj->in_use_flags &= (~BEING_WORN); 340 } 341 rogue.armor = (object *) 0; 342 } 343 344 do_wear(obj) 345 object *obj; 346 { 347 rogue.armor = obj; 348 obj->in_use_flags |= BEING_WORN; 349 obj->identified = 1; 350 } 351 352 wield() 353 { 354 short ch; 355 register object *obj; 356 char desc[DCOLS]; 357 358 if (rogue.weapon && rogue.weapon->is_cursed) { 359 message(curse_message, 0); 360 return; 361 } 362 ch = pack_letter("wield what?", WEAPON); 363 364 if (ch == CANCEL) { 365 return; 366 } 367 if (!(obj = get_letter_object(ch))) { 368 message("No such item.", 0); 369 return; 370 } 371 if (obj->what_is & (ARMOR | RING)) { 372 sprintf(desc, "you can't wield %s", 373 ((obj->what_is == ARMOR) ? "armor" : "rings")); 374 message(desc, 0); 375 return; 376 } 377 if (obj->in_use_flags & BEING_WIELDED) { 378 message("in use", 0); 379 } else { 380 unwield(rogue.weapon); 381 (void) strcpy(desc, "wielding "); 382 get_desc(obj, desc + 9); 383 message(desc, 0); 384 do_wield(obj); 385 (void) reg_move(); 386 } 387 } 388 389 do_wield(obj) 390 object *obj; 391 { 392 rogue.weapon = obj; 393 obj->in_use_flags |= BEING_WIELDED; 394 } 395 396 unwield(obj) 397 object *obj; 398 { 399 if (obj) { 400 obj->in_use_flags &= (~BEING_WIELDED); 401 } 402 rogue.weapon = (object *) 0; 403 } 404 405 call_it() 406 { 407 short ch; 408 register object *obj; 409 struct id *id_table; 410 char buf[MAX_TITLE_LENGTH+2]; 411 412 ch = pack_letter("call what?", (SCROL | POTION | WAND | RING)); 413 414 if (ch == CANCEL) { 415 return; 416 } 417 if (!(obj = get_letter_object(ch))) { 418 message("no such item.", 0); 419 return; 420 } 421 if (!(obj->what_is & (SCROL | POTION | WAND | RING))) { 422 message("surely you already know what that's called", 0); 423 return; 424 } 425 id_table = get_id_table(obj); 426 427 if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) { 428 id_table[obj->which_kind].id_status = CALLED; 429 (void) strcpy(id_table[obj->which_kind].title, buf); 430 } 431 } 432 433 pack_count(new_obj) 434 object *new_obj; 435 { 436 object *obj; 437 short count = 0; 438 439 obj = rogue.pack.next_object; 440 441 while (obj) { 442 if (obj->what_is != WEAPON) { 443 count += obj->quantity; 444 } else if (!new_obj) { 445 count++; 446 } else if ((new_obj->what_is != WEAPON) || 447 ((obj->which_kind != ARROW) && 448 (obj->which_kind != DAGGER) && 449 (obj->which_kind != DART) && 450 (obj->which_kind != SHURIKEN)) || 451 (new_obj->which_kind != obj->which_kind) || 452 (obj->quiver != new_obj->quiver)) { 453 count++; 454 } 455 obj = obj->next_object; 456 } 457 return(count); 458 } 459 460 boolean 461 mask_pack(pack, mask) 462 object *pack; 463 unsigned short mask; 464 { 465 while (pack->next_object) { 466 pack = pack->next_object; 467 if (pack->what_is & mask) { 468 return(1); 469 } 470 } 471 return(0); 472 } 473 474 is_pack_letter(c, mask) 475 short *c; 476 unsigned short *mask; 477 { 478 if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') || 479 (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) { 480 switch(*c) { 481 case '?': 482 *mask = SCROL; 483 break; 484 case '!': 485 *mask = POTION; 486 break; 487 case ':': 488 *mask = FOOD; 489 break; 490 case ')': 491 *mask = WEAPON; 492 break; 493 case ']': 494 *mask = ARMOR; 495 break; 496 case '/': 497 *mask = WAND; 498 break; 499 case '=': 500 *mask = RING; 501 break; 502 case ',': 503 *mask = AMULET; 504 break; 505 } 506 *c = LIST; 507 return(1); 508 } 509 return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST)); 510 } 511 512 has_amulet() 513 { 514 return(mask_pack(&rogue.pack, AMULET)); 515 } 516 517 kick_into_pack() 518 { 519 object *obj; 520 char desc[DCOLS]; 521 short n, stat; 522 523 if (!(dungeon[rogue.row][rogue.col] & OBJECT)) { 524 message("nothing here", 0); 525 } else { 526 if (obj = pick_up(rogue.row, rogue.col, &stat)) { 527 get_desc(obj, desc); 528 if (obj->what_is == GOLD) { 529 message(desc, 0); 530 free_object(obj); 531 } else { 532 n = strlen(desc); 533 desc[n] = '('; 534 desc[n+1] = obj->ichar; 535 desc[n+2] = ')'; 536 desc[n+3] = 0; 537 message(desc, 0); 538 } 539 } 540 if (obj || (!stat)) { 541 (void) reg_move(); 542 } 543 } 544 } 545