1 /* 2 * Contains functions for dealing with things like potions, scrolls, 3 * and other items. 4 * 5 * things.c 1.4 (AI Design) 12/14/84 6 */ 7 8 #include "rogue.h" 9 #include "curses.h" 10 11 /* 12 * inv_name: 13 * Return the name of something as it would appear in an 14 * inventory. 15 */ 16 char * 17 inv_name(obj, drop) 18 register THING *obj; 19 bool drop; 20 { 21 register int which = obj->o_which; 22 register char *pb; 23 24 pb = prbuf; 25 switch (obj->o_type) 26 { 27 when SCROLL: 28 if (obj->o_count == 1) { 29 strcpy(pb, "A scroll "); 30 pb = &prbuf[9]; 31 } else { 32 sprintf(pb, "%d scrolls ", obj->o_count); 33 pb = &prbuf[strlen(prbuf)]; 34 } 35 if (s_know[which]) 36 sprintf(pb, "of %s", s_magic[which].mi_name); 37 else if (*s_guess[which]) 38 sprintf(pb, "called %s", s_guess[which]); 39 else 40 chopmsg(pb, "titled '%.17s'","titled '%s'", &s_names[which]); 41 when POTION: 42 if (obj->o_count == 1) 43 { 44 strcpy(pb, "A potion "); 45 pb = &prbuf[9]; 46 } 47 else 48 { 49 sprintf(pb, "%d potions ", obj->o_count); 50 pb = &pb[strlen(prbuf)]; 51 } 52 if (p_know[which]) { 53 chopmsg(pb, "of %s", "of %s(%s)", 54 p_magic[which].mi_name, p_colors[which]); 55 } 56 else if (*p_guess[which]) { 57 chopmsg(pb, "called %s","called %s(%s)", p_guess[which], 58 p_colors[which]); 59 } 60 else if (obj->o_count == 1) 61 sprintf(prbuf, "A%s %s potion", vowelstr(p_colors[which]), 62 p_colors[which]); 63 else 64 sprintf(prbuf, "%d %s potions", obj->o_count, 65 p_colors[which]); 66 when FOOD: 67 if (which == 1) 68 if (obj->o_count == 1) 69 sprintf(pb, "A%s %s", vowelstr(fruit), fruit); 70 else 71 sprintf(pb, "%d %ss", obj->o_count, fruit); 72 else 73 if (obj->o_count == 1) 74 strcpy(pb, "Some food"); 75 else 76 sprintf(pb, "%d rations of food", obj->o_count); 77 when WEAPON: 78 if (obj->o_count > 1) 79 sprintf(pb, "%d ", obj->o_count); 80 else 81 sprintf(pb, "A%s ", vowelstr(w_names[which])); 82 pb = &prbuf[strlen(prbuf)]; 83 if (obj->o_flags & ISKNOW) 84 sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, WEAPON), 85 w_names[which]); 86 else 87 sprintf(pb, "%s", w_names[which]); 88 if (obj->o_count > 1) 89 strcat(pb, "s"); 90 if (obj->o_enemy && obj->o_flags & ISREVEAL) 91 { 92 strcat(pb, " of "); 93 strcat(pb, monsters[obj->o_enemy-'A'].m_name); 94 strcat(pb, " slaying"); 95 } 96 when ARMOR: 97 if (obj->o_flags & ISKNOW) 98 chopmsg(pb, "%s %s","%s %s [armor class %d]", 99 num(a_class[which] - obj->o_ac, 0, ARMOR), 100 a_names[which], -(obj->o_ac-11)); 101 else 102 sprintf(pb, "%s", a_names[which]); 103 when AMULET: 104 strcpy(pb, "The Amulet of Yendor"); 105 when STICK: 106 sprintf(pb, "A%s %s ", vowelstr(ws_type[which]), 107 ws_type[which]); 108 pb = &prbuf[strlen(prbuf)]; 109 if (ws_know[which]) 110 chopmsg(pb, "of %s%s", "of %s%s(%s)", 111 ws_magic[which].mi_name, 112 charge_str(obj), ws_made[which]); 113 else if (*ws_guess[which]) 114 chopmsg(pb, "called %s", "called %s(%s)", ws_guess[which], 115 ws_made[which]); 116 else 117 sprintf(pb = &prbuf[2], "%s %s", ws_made[which], 118 ws_type[which]); 119 when RING: 120 if (r_know[which]) 121 chopmsg(pb, "A%s ring of %s", "A%s ring of %s(%s)", ring_num(obj), 122 r_magic[which].mi_name, r_stones[which]); 123 else if (*r_guess[which]) 124 chopmsg(pb, "A ring called %s", "A ring called %s(%s)", 125 r_guess[which], r_stones[which]); 126 else 127 sprintf(pb, "A%s %s ring", vowelstr(r_stones[which]), 128 r_stones[which]); 129 #ifdef DEBUG 130 when GOLD: 131 sprintf(pb, "Gold at %d,%d", obj->o_pos.y, obj->o_pos.x); 132 otherwise: 133 debug("Picked up someting bizzare %s", unctrl(obj->o_type)); 134 sprintf(pb, "Something bizarre %c(%d)", obj->o_type, obj->o_type); 135 #endif 136 } 137 if (obj == cur_armor) 138 strcat(pb, " (being worn)"); 139 if (obj == cur_weapon) 140 strcat(pb, " (weapon in hand)"); 141 if (obj == cur_ring[LEFT]) 142 strcat(pb, " (on left hand)"); 143 else if (obj == cur_ring[RIGHT]) 144 strcat(pb, " (on right hand)"); 145 if (drop && isupper(prbuf[0])) 146 prbuf[0] = tolower(prbuf[0]); 147 else if (!drop && islower(*prbuf)) 148 *prbuf = toupper(*prbuf); 149 return prbuf; 150 } 151 152 chopmsg(s,shmsg,lnmsg,arg1,arg2,arg3) 153 char *s, *shmsg, *lnmsg; 154 int arg1, arg2, arg3; 155 { 156 sprintf(s,lnmsg,arg1,arg2,arg3); 157 if (terse || expert) 158 sprintf(s,shmsg,arg1,arg2,arg3); 159 } 160 161 /* 162 * drop: 163 * Put something down 164 */ 165 drop() 166 { 167 register byte ch; 168 register THING *nobj, *op; 169 170 ch = chat(hero.y, hero.x); 171 if (ch != FLOOR && ch != PASSAGE) 172 { 173 msg("there is something there already"); 174 return; 175 } 176 if ((op = get_item("drop", 0)) == NULL) 177 return; 178 if (!can_drop(op)) 179 return; 180 /* 181 * Take it out of the pack 182 */ 183 if (op->o_count >= 2 && op->o_type != WEAPON) 184 { 185 if ((nobj = new_item()) == NULL) 186 { 187 msg("%sit appears to be stuck in your pack!",noterse("can't drop it, ")); 188 return; 189 } 190 op->o_count--; 191 bcopy(*nobj,*op); 192 nobj->o_count = 1; 193 op = nobj; 194 if (op->o_group != 0) 195 inpack++; 196 } 197 else 198 detach(pack, op); 199 inpack--; 200 /* 201 * Link it into the level object list 202 */ 203 attach(lvl_obj, op); 204 chat(hero.y, hero.x) = op->o_type; 205 bcopy(op->o_pos,hero); 206 if (op->o_type == AMULET) 207 amulet = FALSE; 208 msg("dropped %s", inv_name(op, TRUE)); 209 } 210 211 /* 212 * can_drop: 213 * Do special checks for dropping or unweilding|unwearing|unringing 214 */ 215 can_drop(op) 216 register THING *op; 217 { 218 if (op == NULL) 219 return TRUE; 220 if (op != cur_armor && op != cur_weapon 221 && op != cur_ring[LEFT] && op != cur_ring[RIGHT]) 222 return TRUE; 223 if (op->o_flags & ISCURSED) { 224 msg("you can't. It appears to be cursed"); 225 return FALSE; 226 } 227 if (op == cur_weapon) 228 cur_weapon = NULL; 229 else if (op == cur_armor) { 230 waste_time(); 231 cur_armor = NULL; 232 } else { 233 register int hand; 234 235 if (op != cur_ring[hand = LEFT]) 236 if (op != cur_ring[hand = RIGHT]) { 237 #ifdef DEBUG 238 debug("Candrop called with funny thing"); 239 #endif 240 return TRUE; 241 } 242 cur_ring[hand] = NULL; 243 switch (op->o_which) { 244 case R_ADDSTR: 245 chg_str(-op->o_ac); 246 break; 247 case R_SEEINVIS: 248 unsee(); 249 extinguish(unsee); 250 break; 251 } 252 } 253 return TRUE; 254 } 255 256 /* 257 * new_thing: 258 * Return a new thing 259 */ 260 THING * 261 new_thing() 262 { 263 register THING *cur; 264 register int j, k; 265 266 if ((cur = new_item()) == NULL) 267 return NULL; 268 cur->o_hplus = cur->o_dplus = 0; 269 cur->o_damage = cur->o_hurldmg = "0d0"; 270 cur->o_ac = 11; 271 cur->o_count = 1; 272 cur->o_group = 0; 273 cur->o_flags = 0; 274 cur->o_enemy = 0; 275 /* 276 * Decide what kind of object it will be 277 * If we haven't had food for a while, let it be food. 278 */ 279 switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS)) 280 { 281 when 0: 282 cur->o_type = POTION; 283 cur->o_which = pick_one(p_magic, MAXPOTIONS); 284 when 1: 285 cur->o_type = SCROLL; 286 cur->o_which = pick_one(s_magic, MAXSCROLLS); 287 when 2: 288 no_food = 0; 289 cur->o_type = FOOD; 290 if (rnd(10) != 0) 291 cur->o_which = 0; 292 else 293 cur->o_which = 1; 294 when 3: 295 cur->o_type = WEAPON; 296 cur->o_which = rnd(MAXWEAPONS); 297 init_weapon(cur, cur->o_which); 298 if ((k = rnd(100)) < 10) 299 { 300 cur->o_flags |= ISCURSED; 301 cur->o_hplus -= rnd(3) + 1; 302 } 303 else if (k < 15) 304 cur->o_hplus += rnd(3) + 1; 305 when 4: 306 cur->o_type = ARMOR; 307 for (j = 0, k = rnd(100); j < MAXARMORS; j++) 308 if (k < a_chances[j]) 309 break; 310 #ifdef DEBUG 311 if (j == MAXARMORS) 312 { 313 debug("Picked a bad armor %d", k); 314 j = 0; 315 } 316 #endif 317 cur->o_which = j; 318 cur->o_ac = a_class[j]; 319 if ((k = rnd(100)) < 20) 320 { 321 cur->o_flags |= ISCURSED; 322 cur->o_ac += rnd(3) + 1; 323 } 324 else if (k < 28) 325 cur->o_ac -= rnd(3) + 1; 326 when 5: 327 cur->o_type = RING; 328 cur->o_which = pick_one(r_magic, MAXRINGS); 329 switch (cur->o_which) 330 { 331 when R_ADDSTR: 332 case R_PROTECT: 333 case R_ADDHIT: 334 case R_ADDDAM: 335 if ((cur->o_ac = rnd(3)) == 0) 336 { 337 cur->o_ac = -1; 338 cur->o_flags |= ISCURSED; 339 } 340 when R_AGGR: 341 case R_TELEPORT: 342 cur->o_flags |= ISCURSED; 343 } 344 when 6: 345 cur->o_type = STICK; 346 cur->o_which = pick_one(ws_magic, MAXSTICKS); 347 fix_stick(cur); 348 #ifdef DEBUG 349 otherwise: 350 debug("Picked a bad kind of object"); 351 wait_for(' '); 352 #endif 353 } 354 return cur; 355 } 356 357 /* 358 * pick_one: 359 * Pick an item out of a list of nitems possible magic items 360 */ 361 pick_one(magic, nitems) 362 register struct magic_item *magic; 363 int nitems; 364 { 365 register struct magic_item *end; 366 register int i; 367 register struct magic_item *start; 368 369 start = magic; 370 for (end = &magic[nitems], i = rnd(100); magic < end; magic++) 371 if (i < magic->mi_prob) 372 break; 373 if (magic == end) 374 { 375 #ifdef DEBUG 376 if (wizard) 377 { 378 msg("bad pick_one: %d from %d items", i, nitems); 379 for (magic = start; magic < end; magic++) 380 msg("%s: %d%%", magic->mi_name, magic->mi_prob); 381 } 382 #endif 383 magic = start; 384 } 385 return magic - start; 386 } 387 388 /* 389 * discovered: 390 * list what the player has discovered in this game of a certain type 391 */ 392 static int line_cnt = 0; 393 394 static bool newpage = FALSE; 395 396 static char *lastfmt, *lastarg; 397 398 discovered() 399 { 400 print_disc(POTION); 401 add_line(nullstr, " "); 402 print_disc(SCROLL); 403 add_line(nullstr, " "); 404 print_disc(RING); 405 add_line(nullstr, " "); 406 print_disc(STICK); 407 end_line(nullstr); 408 } 409 410 /* 411 * print_disc: 412 * Print what we've discovered of type 'type' 413 */ 414 415 #define MAX(a,b,c,d) (a>b?(a>c?(a>d?a:d):(c>d?c:d)):(b>c?(b>d?b:d):(c>d?c:d))) 416 417 print_disc(type) 418 byte type; 419 { 420 register bool *know; 421 register char **guess; 422 register int i, maxnum, num_found; 423 static THING obj; 424 static short order[MAX(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)]; 425 426 switch (type) 427 { 428 case SCROLL: 429 maxnum = MAXSCROLLS; 430 know = s_know; 431 guess = s_guess; 432 break; 433 case POTION: 434 maxnum = MAXPOTIONS; 435 know = p_know; 436 guess = p_guess; 437 break; 438 case RING: 439 maxnum = MAXRINGS; 440 know = r_know; 441 guess = r_guess; 442 break; 443 case STICK: 444 maxnum = MAXSTICKS; 445 know = ws_know; 446 guess = ws_guess; 447 break; 448 } 449 set_order(order, maxnum); 450 obj.o_count = 1; 451 obj.o_flags = 0; 452 num_found = 0; 453 for (i = 0; i < maxnum; i++) 454 if (know[order[i]] || *guess[order[i]]) 455 { 456 obj.o_type = type; 457 obj.o_which = order[i]; 458 add_line(nullstr, "%s", inv_name(&obj, FALSE)); 459 num_found++; 460 } 461 if (num_found == 0) 462 add_line(nullstr, nothing(type)); 463 } 464 465 /* 466 * set_order: 467 * Set up order for list 468 */ 469 set_order(order, numthings) 470 short *order; 471 int numthings; 472 { 473 register int i, r, t; 474 475 for (i = 0; i< numthings; i++) 476 order[i] = i; 477 478 for (i = numthings; i > 0; i--) 479 { 480 r = rnd(i); 481 t = order[i - 1]; 482 order[i - 1] = order[r]; 483 order[r] = t; 484 } 485 } 486 487 /* 488 * add_line: 489 * Add a line to the list of discoveries 490 */ 491 /* VARARGS1 */ 492 add_line(use, fmt, arg) 493 char *use, *fmt, *arg; 494 { 495 int x, y; 496 register int retchar = ' '; 497 if (line_cnt == 0) 498 { 499 wdump(0); 500 clear(); 501 } 502 if (line_cnt >= LINES - 1 || fmt == NULL) 503 { 504 move(LINES-1, 0); 505 if (*use) 506 printw("-Select item to %s. Esc to cancel-", use); 507 else 508 addstr("-Press space to continue-"); 509 do 510 retchar = readchar(); 511 while (retchar != ESCAPE && retchar != ' ' && (!islower(retchar))) ; 512 clear(); 513 newpage = TRUE; 514 line_cnt = 0; 515 } 516 if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0')) 517 { 518 move(line_cnt, 0); 519 printw(fmt, arg); 520 getxy(&x,&y); 521 /* 522 * if the line wrapped but nothing was printed on this 523 * line you might as well use it for the next item 524 */ 525 if (y!=0) 526 line_cnt = x + 1; 527 lastfmt = fmt; 528 lastarg = arg; 529 } 530 return(retchar); 531 } 532 533 /* 534 * end_line: 535 * End the list of lines 536 */ 537 end_line(use) 538 char *use; 539 { 540 register int retchar; 541 542 retchar = add_line(use, NULL); 543 wrestor(0); 544 line_cnt = 0; 545 newpage = FALSE; 546 return(retchar); 547 } 548 549 /* 550 * nothing: 551 * Set up prbuf so that message for "nothing found" is there 552 */ 553 char * 554 nothing(type) 555 register byte type; 556 { 557 register char *sp, *tystr; 558 559 sprintf(prbuf, "Haven't discovered anything"); 560 if (terse) 561 sprintf(prbuf,"Nothing"); 562 sp = &prbuf[strlen(prbuf)]; 563 switch (type) 564 { 565 when POTION: tystr = "potion"; 566 when SCROLL: tystr = "scroll"; 567 when RING: tystr = "ring"; 568 when STICK: tystr = "stick"; 569 } 570 sprintf(sp, " about any %ss", tystr); 571 return prbuf; 572 } 573 ÿ