comparison rogue4/things.c @ 12:9535a08ddc39

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