Mercurial > hg > early-roguelike
comparison urogue/things.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | 5a94c9b3181e |
comparison
equal
deleted
inserted
replaced
253:d9badb9c0179 | 256:c495a4f288c6 |
---|---|
1 /* | |
2 things.c - functions for dealing with things like potions and scrolls | |
3 | |
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong | |
6 All rights reserved. | |
7 | |
8 Based on "Advanced Rogue" | |
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka | |
10 All rights reserved. | |
11 | |
12 Based on "Rogue: Exploring the Dungeons of Doom" | |
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
14 All rights reserved. | |
15 | |
16 See the file LICENSE.TXT for full copyright and licensing information. | |
17 */ | |
18 | |
19 #include <string.h> | |
20 #include <ctype.h> | |
21 #include "rogue.h" | |
22 | |
23 /* | |
24 inv_name() | |
25 return the name of something as it would appear in an inventory. | |
26 */ | |
27 | |
28 char * | |
29 inv_name(struct object *obj, int lowercase) | |
30 { | |
31 char *pb; | |
32 char buf[1024]; | |
33 | |
34 switch(obj->o_type) | |
35 { | |
36 case SCROLL: | |
37 if (obj->o_count == 1) | |
38 sprintf(prbuf, "A %s%sscroll ", | |
39 obj->o_flags & CANRETURN ? "claimed " : "", | |
40 blesscurse(obj->o_flags)); | |
41 else | |
42 sprintf(prbuf, "%d %s%sscrolls ", | |
43 obj->o_count, | |
44 obj->o_flags & CANRETURN ? "claimed " : "", | |
45 blesscurse(obj->o_flags)); | |
46 | |
47 pb = &prbuf[strlen(prbuf)]; | |
48 | |
49 if (know_items[TYP_SCROLL][obj->o_which]) | |
50 sprintf(pb, "of %s", s_magic[obj->o_which].mi_name); | |
51 else if (guess_items[TYP_SCROLL][obj->o_which]) | |
52 sprintf(pb, "called %s", guess_items[TYP_SCROLL][obj->o_which]); | |
53 else | |
54 sprintf(pb, "titled '%s'", s_names[obj->o_which]); | |
55 break; | |
56 | |
57 case POTION: | |
58 if (obj->o_count == 1) | |
59 sprintf(prbuf, "A %s%spotion ", | |
60 obj->o_flags & CANRETURN ? "claimed " : "", | |
61 blesscurse(obj->o_flags)); | |
62 else | |
63 sprintf(prbuf, "%d %s%spotions ", | |
64 obj->o_count, | |
65 obj->o_flags & CANRETURN ? "claimed " : "", | |
66 blesscurse(obj->o_flags)); | |
67 | |
68 pb = &prbuf[strlen(prbuf)]; | |
69 | |
70 if (know_items[TYP_POTION][obj->o_which]) | |
71 sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name, | |
72 p_colors[obj->o_which]); | |
73 else if (guess_items[TYP_POTION][obj->o_which]) | |
74 sprintf(pb, "called %s(%s)", guess_items[TYP_POTION][obj->o_which], | |
75 p_colors[obj->o_which]); | |
76 else | |
77 { | |
78 if (obj->o_count == 1) | |
79 sprintf(prbuf, "A%s %s potion", | |
80 obj->o_flags & CANRETURN ? " claimed" : | |
81 (char *) vowelstr(p_colors[obj->o_which]), | |
82 p_colors[obj->o_which]); | |
83 else | |
84 sprintf(prbuf, "%d %s%s potions", | |
85 obj->o_count, | |
86 obj->o_flags & CANRETURN ? "claimed " : "", | |
87 (char *) p_colors[obj->o_which]); | |
88 } | |
89 break; | |
90 | |
91 case FOOD: | |
92 if (obj->o_count == 1) | |
93 sprintf(prbuf, "A%s %s", | |
94 obj->o_flags & CANRETURN ? " claimed" : | |
95 (char *) vowelstr(fd_data[obj->o_which].mi_name), | |
96 fd_data[obj->o_which].mi_name); | |
97 else | |
98 sprintf(prbuf, "%d %s%ss", obj->o_count, | |
99 obj->o_flags & CANRETURN ? "claimed " : "", | |
100 fd_data[obj->o_which].mi_name); | |
101 break; | |
102 | |
103 case WEAPON: | |
104 if (obj->o_count > 1) | |
105 sprintf(prbuf, "%d ", obj->o_count); | |
106 else if ((obj->o_flags & (ISZAPPED | CANRETURN | ISPOISON | ISSILVER | ISTWOH)) || | |
107 ((obj->o_flags & (ISKNOW | ISZAPPED)) == (ISKNOW | ISZAPPED))) | |
108 strcpy(prbuf, "A "); | |
109 else | |
110 sprintf(prbuf, "A%s ", vowelstr(weaps[obj->o_which].w_name)); | |
111 | |
112 pb = &prbuf[strlen(prbuf)]; | |
113 | |
114 if ((obj->o_flags & ISKNOW) && (obj->o_flags & ISZAPPED)) | |
115 sprintf(pb, "charged%s ", charge_str(obj,buf)); | |
116 | |
117 pb = &prbuf[strlen(prbuf)]; | |
118 | |
119 if (obj->o_flags & CANRETURN) | |
120 sprintf(pb, "claimed "); | |
121 | |
122 pb = &prbuf[strlen(prbuf)]; | |
123 | |
124 if (obj->o_flags & ISPOISON) | |
125 sprintf(pb, "poisoned "); | |
126 | |
127 pb = &prbuf[strlen(prbuf)]; | |
128 | |
129 if (obj->o_flags & ISSILVER) | |
130 sprintf(pb, "silver "); | |
131 | |
132 if (obj->o_flags & ISTWOH) | |
133 sprintf(pb, "two-handed "); | |
134 | |
135 pb = &prbuf[strlen(prbuf)]; | |
136 | |
137 if (obj->o_flags & ISKNOW) | |
138 sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, buf), | |
139 weaps[obj->o_which].w_name); | |
140 else | |
141 sprintf(pb, "%s", weaps[obj->o_which].w_name); | |
142 | |
143 if (obj->o_count > 1) | |
144 strcat(prbuf, "s"); | |
145 | |
146 break; | |
147 | |
148 case ARMOR: | |
149 if (obj->o_flags & ISKNOW) | |
150 sprintf(prbuf, "%s%s %s", | |
151 obj->o_flags & CANRETURN ? "claimed " : "", | |
152 num(armors[obj->o_which].a_class - obj->o_ac, 0, buf), | |
153 armors[obj->o_which].a_name); | |
154 else | |
155 sprintf(prbuf, "%s%s", | |
156 obj->o_flags & CANRETURN ? "claimed " : "", | |
157 armors[obj->o_which].a_name); | |
158 | |
159 break; | |
160 | |
161 case ARTIFACT: | |
162 sprintf(prbuf, "the %s", arts[obj->o_which].ar_name); | |
163 | |
164 if (obj->o_flags & CANRETURN) | |
165 strcat(prbuf, " (claimed)"); | |
166 | |
167 break; | |
168 | |
169 case STICK: | |
170 sprintf(prbuf, "A %s%s%s ", | |
171 obj->o_flags & CANRETURN ? "claimed " : "", | |
172 blesscurse(obj->o_flags), ws_type[obj->o_which]); | |
173 | |
174 pb = &prbuf[strlen(prbuf)]; | |
175 | |
176 if (know_items[TYP_STICK][obj->o_which]) | |
177 sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name, | |
178 charge_str(obj,buf), ws_made[obj->o_which]); | |
179 else if (guess_items[TYP_STICK][obj->o_which]) | |
180 sprintf(pb, "called %s(%s)", guess_items[TYP_STICK][obj->o_which], | |
181 ws_made[obj->o_which]); | |
182 else | |
183 sprintf(&prbuf[2], "%s%s %s", | |
184 obj->o_flags & CANRETURN ? "claimed " : "", | |
185 ws_made[obj->o_which], | |
186 ws_type[obj->o_which]); | |
187 | |
188 break; | |
189 | |
190 case RING: | |
191 if (know_items[TYP_RING][obj->o_which]) | |
192 sprintf(prbuf, "A%s%s ring of %s(%s)", | |
193 obj->o_flags & CANRETURN ? " claimed" : "", ring_num(obj,buf), | |
194 r_magic[obj->o_which].mi_name, r_stones[obj->o_which]); | |
195 else if (guess_items[TYP_RING][obj->o_which]) | |
196 sprintf(prbuf, "A %sring called %s(%s)", | |
197 obj->o_flags & CANRETURN ? "claimed " : "", | |
198 guess_items[TYP_RING][obj->o_which], r_stones[obj->o_which]); | |
199 else | |
200 sprintf(prbuf, "A%s %s ring", | |
201 obj->o_flags & CANRETURN ? "claimed " : | |
202 (char *)vowelstr(r_stones[obj->o_which]), | |
203 r_stones[obj->o_which]); | |
204 break; | |
205 | |
206 case GOLD: | |
207 sprintf(prbuf, "%d gold pieces", obj->o_count); | |
208 break; | |
209 | |
210 default: | |
211 debug("Picked up something funny."); | |
212 sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type)); | |
213 break; | |
214 } | |
215 | |
216 /* Is it marked? */ | |
217 | |
218 if (obj->o_mark[0]) | |
219 { | |
220 pb = &prbuf[strlen(prbuf)]; | |
221 sprintf(pb, " <%s>", obj->o_mark); | |
222 } | |
223 | |
224 if (obj == cur_armor) | |
225 strcat(prbuf, " (being worn)"); | |
226 | |
227 if (obj == cur_weapon) | |
228 strcat(prbuf, " (weapon in hand)"); | |
229 | |
230 if (obj == cur_ring[LEFT_1]) | |
231 strcat(prbuf, " (on left hand)"); | |
232 else if (obj == cur_ring[LEFT_2]) | |
233 strcat(prbuf, " (on left hand)"); | |
234 else if (obj == cur_ring[LEFT_3]) | |
235 strcat(prbuf, " (on left hand)"); | |
236 else if (obj == cur_ring[LEFT_4]) | |
237 strcat(prbuf, " (on left hand)"); | |
238 else if (obj == cur_ring[LEFT_5]) | |
239 strcat(prbuf, " (on left hand)"); | |
240 else if (obj == cur_ring[RIGHT_1]) | |
241 strcat(prbuf, " (on right hand)"); | |
242 else if (obj == cur_ring[RIGHT_2]) | |
243 strcat(prbuf, " (on right hand)"); | |
244 else if (obj == cur_ring[RIGHT_3]) | |
245 strcat(prbuf, " (on right hand)"); | |
246 else if (obj == cur_ring[RIGHT_4]) | |
247 strcat(prbuf, " (on right hand)"); | |
248 else if (obj == cur_ring[RIGHT_5]) | |
249 strcat(prbuf, " (on right hand)"); | |
250 | |
251 if (obj->o_flags & ISPROT) | |
252 strcat(prbuf, " [protected]"); | |
253 | |
254 if (lowercase && isupper(prbuf[0])) | |
255 prbuf[0] = (char) tolower(prbuf[0]); | |
256 else if (!lowercase && islower(*prbuf)) | |
257 *prbuf = (char) toupper(*prbuf); | |
258 | |
259 if (!lowercase) | |
260 strcat(prbuf, "."); | |
261 | |
262 return(prbuf); | |
263 } | |
264 | |
265 /* | |
266 rem_obj() | |
267 Remove an object from the level. | |
268 */ | |
269 | |
270 void | |
271 rem_obj(struct linked_list *item, int dis) | |
272 { | |
273 struct linked_list *llptr; | |
274 struct object *objptr, *op; | |
275 int x, y; | |
276 | |
277 if (item == NULL) | |
278 return; | |
279 | |
280 detach(lvl_obj, item); | |
281 objptr = OBJPTR(item); | |
282 | |
283 if ( (llptr = objptr->next_obj) != NULL ) | |
284 { | |
285 detach((objptr->next_obj), llptr); | |
286 attach(lvl_obj, llptr); | |
287 | |
288 op = OBJPTR(llptr); | |
289 | |
290 op->next_obj = objptr->next_obj; | |
291 | |
292 if (op->next_obj) | |
293 objptr->next_obj->l_prev = NULL; | |
294 | |
295 y = op->o_pos.y; | |
296 x = op->o_pos.x; | |
297 | |
298 if (cansee(y, x)) | |
299 mvwaddch(cw, y, x, op->o_type); | |
300 | |
301 mvaddch(y, x, op->o_type); | |
302 } | |
303 else | |
304 { | |
305 y = objptr->o_pos.y; | |
306 x = objptr->o_pos.x; | |
307 | |
308 /* problems if dropped in rock */ | |
309 | |
310 mvaddch(y,x,(roomin((objptr->o_pos)) == NULL ? PASSAGE : FLOOR)); | |
311 } | |
312 | |
313 if (dis) | |
314 discard(item); | |
315 } | |
316 | |
317 /* | |
318 add_obj() | |
319 adds an object to the level | |
320 */ | |
321 | |
322 void | |
323 add_obj(struct linked_list *item, int y, int x) | |
324 { | |
325 struct linked_list *llptr; | |
326 struct object*objptr; | |
327 | |
328 llptr = find_obj(y, x); | |
329 | |
330 if (llptr) | |
331 { | |
332 objptr = OBJPTR(llptr); | |
333 attach((objptr->next_obj), item); | |
334 } | |
335 else | |
336 { | |
337 attach(lvl_obj, item); | |
338 objptr = OBJPTR(item); | |
339 objptr->next_obj = NULL; | |
340 objptr->o_pos.y = y; | |
341 objptr->o_pos.x = x; | |
342 mvaddch(y, x, objptr->o_type); | |
343 } | |
344 } | |
345 | |
346 /* | |
347 drop() | |
348 put something down | |
349 */ | |
350 | |
351 int | |
352 drop(struct linked_list *item) | |
353 { | |
354 char ch = CCHAR( mvwinch(stdscr, hero.y, hero.x) ); | |
355 struct object *obj; | |
356 | |
357 switch (ch) | |
358 { | |
359 case GOLD: | |
360 case POTION: | |
361 case SCROLL: | |
362 case FOOD: | |
363 case WEAPON: | |
364 case ARMOR: | |
365 case RING: | |
366 case STICK: | |
367 case FLOOR: | |
368 case PASSAGE: | |
369 case POOL: | |
370 case ARTIFACT: | |
371 if (item == NULL && (item = get_item("drop", 0)) == NULL) | |
372 return(FALSE); | |
373 break; | |
374 | |
375 default: | |
376 msg("You can't drop something here."); | |
377 return(FALSE); | |
378 } | |
379 | |
380 obj = OBJPTR(item); | |
381 | |
382 if (!dropcheck(obj)) | |
383 return(FALSE); | |
384 | |
385 /* Curse a dropped scare monster scroll */ | |
386 | |
387 if (obj->o_type == SCROLL && obj->o_which == S_SCARE) | |
388 { | |
389 if (obj->o_flags & ISBLESSED) | |
390 obj->o_flags &= ~ISBLESSED; | |
391 else | |
392 obj->o_flags |= ISCURSED; | |
393 } | |
394 | |
395 /* Take it out of the pack */ | |
396 | |
397 if (obj->o_count >= 2 && obj->o_group == 0) | |
398 { | |
399 struct linked_list *nitem = new_item(sizeof *obj); | |
400 | |
401 obj->o_count--; | |
402 obj = OBJPTR(nitem); | |
403 *obj = *(OBJPTR(item)); | |
404 obj->o_count = 1; | |
405 item = nitem; | |
406 } | |
407 else | |
408 rem_pack(obj); | |
409 | |
410 if (ch == POOL) | |
411 { | |
412 msg("The pool bubbles briefly as your %s sinks out of sight.", | |
413 inv_name(obj, TRUE)); | |
414 discard(item); | |
415 item = NULL; | |
416 } | |
417 else /* Link it into the level object list */ | |
418 { | |
419 add_obj(item, hero.y, hero.x); | |
420 mvaddch(hero.y, hero.x, obj->o_type); | |
421 } | |
422 | |
423 if (obj->o_type == ARTIFACT) | |
424 has_artifact &= ~(1 << obj->o_which); | |
425 | |
426 updpack(); | |
427 return(TRUE); | |
428 } | |
429 | |
430 /* | |
431 dropcheck() | |
432 do special checks for dropping or unweilding|unwearing|unringing | |
433 */ | |
434 | |
435 int | |
436 dropcheck(struct object *op) | |
437 { | |
438 if (op == NULL) | |
439 return(TRUE); | |
440 | |
441 if (op != cur_armor && op != cur_weapon && | |
442 op != cur_ring[LEFT_1] && op != cur_ring[LEFT_2] && | |
443 op != cur_ring[LEFT_3] && op != cur_ring[LEFT_4] && | |
444 op != cur_ring[LEFT_5] && | |
445 op != cur_ring[RIGHT_1] && op != cur_ring[RIGHT_2] && | |
446 op != cur_ring[RIGHT_3] && op != cur_ring[RIGHT_4] && | |
447 op != cur_ring[RIGHT_5]) | |
448 return(TRUE); | |
449 | |
450 if (op->o_flags & ISCURSED) | |
451 { | |
452 msg("You can't. It appears to be cursed."); | |
453 return(FALSE); | |
454 } | |
455 | |
456 if (op == cur_weapon) | |
457 cur_weapon = NULL; | |
458 else if (op == cur_armor) | |
459 { | |
460 waste_time(); | |
461 cur_armor = NULL; | |
462 } | |
463 else if (op == cur_ring[LEFT_1] || op == cur_ring[LEFT_2] || | |
464 op == cur_ring[LEFT_3] || op == cur_ring[LEFT_4] || | |
465 op == cur_ring[LEFT_5] || | |
466 op == cur_ring[RIGHT_1] || op == cur_ring[RIGHT_2] || | |
467 op == cur_ring[RIGHT_3] || op == cur_ring[RIGHT_4] || | |
468 op == cur_ring[RIGHT_5]) | |
469 { | |
470 if (op == cur_ring[LEFT_1]) | |
471 cur_ring[LEFT_1] = NULL; | |
472 else if (op == cur_ring[LEFT_2]) | |
473 cur_ring[LEFT_2] = NULL; | |
474 else if (op == cur_ring[LEFT_3]) | |
475 cur_ring[LEFT_3] = NULL; | |
476 else if (op == cur_ring[LEFT_4]) | |
477 cur_ring[LEFT_4] = NULL; | |
478 else if (op == cur_ring[LEFT_5]) | |
479 cur_ring[LEFT_5] = NULL; | |
480 else if (op == cur_ring[RIGHT_1]) | |
481 cur_ring[RIGHT_1] = NULL; | |
482 else if (op == cur_ring[RIGHT_2]) | |
483 cur_ring[RIGHT_2] = NULL; | |
484 else if (op == cur_ring[RIGHT_3]) | |
485 cur_ring[RIGHT_3] = NULL; | |
486 else if (op == cur_ring[RIGHT_4]) | |
487 cur_ring[RIGHT_4] = NULL; | |
488 else if (op == cur_ring[RIGHT_5]) | |
489 cur_ring[RIGHT_5] = NULL; | |
490 | |
491 switch (op->o_which) | |
492 { | |
493 case R_ADDSTR: | |
494 chg_str(-op->o_ac, FALSE, FALSE); | |
495 break; | |
496 case R_ADDHIT: | |
497 chg_dext(-op->o_ac, FALSE, FALSE); | |
498 break; | |
499 case R_ADDINTEL: | |
500 pstats.s_intel -= op->o_ac; | |
501 break; | |
502 case R_ADDWISDOM: | |
503 pstats.s_wisdom -= op->o_ac; | |
504 break; | |
505 | |
506 case R_SEEINVIS: | |
507 if (find_slot(FUSE_UNSEE,FUSE) == NULL) | |
508 { | |
509 turn_off(player, CANSEE); | |
510 msg("The tingling feeling leaves your eyes."); | |
511 } | |
512 | |
513 light(&hero); | |
514 mvwaddch(cw, hero.y, hero.x, PLAYER); | |
515 break; | |
516 | |
517 case R_LIGHT: | |
518 if (roomin(hero) != NULL) | |
519 { | |
520 light(&hero); | |
521 mvwaddch(cw, hero.y, hero.x, PLAYER); | |
522 } | |
523 break; | |
524 } | |
525 } | |
526 return(TRUE); | |
527 } | |
528 | |
529 /* | |
530 new_thing() | |
531 return a new thing | |
532 */ | |
533 | |
534 struct linked_list * | |
535 new_thing(void) | |
536 { | |
537 int j, k; | |
538 struct linked_list *item; | |
539 struct object *cur; | |
540 short blesschance = srnd(100); | |
541 short cursechance = srnd(100); | |
542 | |
543 item = new_item(sizeof *cur); | |
544 cur = OBJPTR(item); | |
545 cur->o_hplus = cur->o_dplus = 0; | |
546 cur->o_damage = cur->o_hurldmg = "0d0"; | |
547 cur->o_ac = 11; | |
548 cur->o_count = 1; | |
549 cur->o_group = 0; | |
550 cur->o_flags = 0; | |
551 cur->o_weight = 0; | |
552 cur->o_mark[0] = '\0'; | |
553 | |
554 /* | |
555 * Decide what kind of object it will be If we haven't had food for a | |
556 * while, let it be food. | |
557 */ | |
558 | |
559 switch (no_food > 3 ? TYP_FOOD : pick_one(things, numthings)) | |
560 { | |
561 case TYP_POTION: | |
562 cur->o_type = POTION; | |
563 cur->o_which = pick_one(p_magic, maxpotions); | |
564 cur->o_weight = things[TYP_POTION].mi_wght; | |
565 | |
566 if (cursechance < p_magic[cur->o_which].mi_curse) | |
567 cur->o_flags |= ISCURSED; | |
568 else if (blesschance < p_magic[cur->o_which].mi_bless) | |
569 cur->o_flags |= ISBLESSED; | |
570 break; | |
571 | |
572 case TYP_SCROLL: | |
573 cur->o_type = SCROLL; | |
574 cur->o_which = pick_one(s_magic, maxscrolls); | |
575 cur->o_weight = things[TYP_SCROLL].mi_wght; | |
576 | |
577 if (cursechance < s_magic[cur->o_which].mi_curse) | |
578 cur->o_flags |= ISCURSED; | |
579 else if (blesschance < s_magic[cur->o_which].mi_bless) | |
580 cur->o_flags |= ISBLESSED; | |
581 break; | |
582 | |
583 case TYP_FOOD: | |
584 no_food = 0; | |
585 cur->o_type = FOOD; | |
586 cur->o_which = pick_one(fd_data, maxfoods); | |
587 cur->o_weight = 2; | |
588 cur->o_count += extras(); | |
589 break; | |
590 | |
591 case TYP_WEAPON: | |
592 cur->o_type = WEAPON; | |
593 cur->o_which = rnd(maxweapons); | |
594 init_weapon(cur, cur->o_which); | |
595 | |
596 if (cursechance < 10) | |
597 { | |
598 short bad = (rnd(10) < 1) ? 2 : 1; | |
599 | |
600 cur->o_flags |= ISCURSED; | |
601 cur->o_hplus -= bad; | |
602 cur->o_dplus -= bad; | |
603 } | |
604 else if (blesschance < 15) | |
605 { | |
606 short good = (rnd(10) < 1) ? 2 : 1; | |
607 | |
608 cur->o_hplus += good; | |
609 cur->o_dplus += good; | |
610 } | |
611 break; | |
612 | |
613 case TYP_ARMOR: | |
614 cur->o_type = ARMOR; | |
615 | |
616 for (j = 0; j < maxarmors; j++) | |
617 if (blesschance < armors[j].a_prob) | |
618 break; | |
619 | |
620 if (j == maxarmors) | |
621 { | |
622 debug("Picked a bad armor %d", blesschance); | |
623 j = 0; | |
624 } | |
625 | |
626 cur->o_which = j; | |
627 cur->o_ac = armors[j].a_class; | |
628 | |
629 if (((k = rnd(100)) < 20) && j != MITHRIL) | |
630 { | |
631 cur->o_flags |= ISCURSED; | |
632 cur->o_ac += rnd(3) + 1; | |
633 } | |
634 else if (k < 28 || j == MITHRIL) | |
635 cur->o_ac -= rnd(3) + 1; | |
636 | |
637 if (j == MITHRIL) | |
638 cur->o_flags |= ISPROT; | |
639 | |
640 cur->o_weight = armors[j].a_wght; | |
641 | |
642 break; | |
643 | |
644 case TYP_RING: | |
645 cur->o_type = RING; | |
646 cur->o_which = pick_one(r_magic, maxrings); | |
647 cur->o_weight = things[TYP_RING].mi_wght; | |
648 | |
649 if (cursechance < r_magic[cur->o_which].mi_curse) | |
650 cur->o_flags |= ISCURSED; | |
651 else if (blesschance < r_magic[cur->o_which].mi_bless) | |
652 cur->o_flags |= ISBLESSED; | |
653 | |
654 switch (cur->o_which) | |
655 { | |
656 case R_ADDSTR: | |
657 case R_ADDWISDOM: | |
658 case R_ADDINTEL: | |
659 case R_PROTECT: | |
660 case R_ADDHIT: | |
661 case R_ADDDAM: | |
662 case R_CARRYING: | |
663 cur->o_ac = rnd(2) + 1; /* From 1 to 3 */ | |
664 | |
665 if (cur->o_flags & ISCURSED) | |
666 cur->o_ac = -cur->o_ac; | |
667 | |
668 if (cur->o_flags & ISBLESSED) | |
669 cur->o_ac++; | |
670 | |
671 break; | |
672 | |
673 case R_RESURRECT: | |
674 case R_TELCONTROL: | |
675 case R_VREGEN: | |
676 case R_REGEN: | |
677 case R_PIETY: | |
678 case R_WIZARD: | |
679 cur->o_ac = 0; | |
680 | |
681 if (cur->o_flags & ISCURSED) | |
682 cur->o_ac = -1; | |
683 | |
684 if (cur->o_flags & ISBLESSED) | |
685 cur->o_ac = 1; | |
686 | |
687 break; | |
688 | |
689 case R_DIGEST: | |
690 | |
691 if (cur->o_flags & ISCURSED) | |
692 cur->o_ac = -1; | |
693 else if (cur->o_flags & ISBLESSED) | |
694 cur->o_ac = 2; | |
695 else | |
696 cur->o_ac = 1; | |
697 break; | |
698 | |
699 default: | |
700 cur->o_ac = 0; | |
701 break; | |
702 } | |
703 break; | |
704 | |
705 case TYP_STICK: | |
706 cur->o_type = STICK; | |
707 cur->o_which = pick_one(ws_magic, maxsticks); | |
708 fix_stick(cur); | |
709 | |
710 if (cursechance < ws_magic[cur->o_which].mi_curse) | |
711 cur->o_flags |= ISCURSED; | |
712 else if (blesschance < ws_magic[cur->o_which].mi_bless) | |
713 cur->o_flags |= ISBLESSED; | |
714 | |
715 break; | |
716 | |
717 default: | |
718 debug("Picked a bad kind of object"); | |
719 wait_for(' '); | |
720 } | |
721 | |
722 return(item); | |
723 } | |
724 | |
725 /* | |
726 spec_item() | |
727 provide a new item tailored to specification | |
728 */ | |
729 | |
730 struct linked_list * | |
731 spec_item(char type, int which, int hitp, int damage) | |
732 { | |
733 struct linked_list *item; | |
734 struct object *obj; | |
735 | |
736 item = new_item(sizeof *obj); | |
737 obj = OBJPTR(item); | |
738 | |
739 obj->o_count = 1; | |
740 obj->o_group = 0; | |
741 obj->o_type = type; | |
742 obj->o_which = which; | |
743 obj->o_damage = obj->o_hurldmg = "0d0"; | |
744 obj->o_hplus = 0; | |
745 obj->o_dplus = 0; | |
746 obj->o_flags = 0; | |
747 obj->o_mark[0] = '\0'; | |
748 obj->o_text = NULL; | |
749 obj->o_launch = 0; | |
750 obj->o_weight = 0; | |
751 | |
752 switch(type) /* Handle special characteristics */ | |
753 { | |
754 case WEAPON: | |
755 init_weapon(obj, which); | |
756 obj->o_hplus = hitp; | |
757 obj->o_dplus = damage; | |
758 obj->o_ac = 10; | |
759 break; | |
760 | |
761 case ARMOR: | |
762 obj->o_ac = armors[which].a_class - hitp; | |
763 break; | |
764 | |
765 case RING: | |
766 obj->o_ac = hitp; | |
767 break; | |
768 | |
769 case STICK: | |
770 fix_stick(obj); | |
771 obj->o_charges = hitp; | |
772 break; | |
773 | |
774 case GOLD: | |
775 obj->o_type = GOLD; | |
776 obj->o_count = GOLDCALC; | |
777 obj->o_ac = 11; | |
778 break; | |
779 } | |
780 | |
781 if (hitp > 0 || damage > 0) | |
782 obj->o_flags |= ISBLESSED; | |
783 else if (hitp < 0 || damage < 0) | |
784 obj->o_flags |= ISCURSED; | |
785 | |
786 return(item); | |
787 } | |
788 | |
789 /* | |
790 pick_one() | |
791 pick an item out of a list of nitems possible magic items | |
792 */ | |
793 | |
794 int | |
795 pick_one(struct magic_item *magic, int nitems) | |
796 { | |
797 int i; | |
798 struct magic_item *end; | |
799 struct magic_item *start = magic; | |
800 | |
801 for (end = &magic[nitems], i = rnd(1000); magic < end; magic++) | |
802 if (i <= magic->mi_prob) | |
803 break; | |
804 | |
805 if (magic == end) | |
806 { | |
807 if (wizard) | |
808 { | |
809 add_line("Bad pick_one: %d from %d items", i, nitems); | |
810 | |
811 for (magic = start; magic < end; magic++) | |
812 add_line("%s: %d%%", magic->mi_name, magic->mi_prob); | |
813 | |
814 end_line(); | |
815 } | |
816 magic = start; | |
817 } | |
818 | |
819 return((int)(magic - start)); | |
820 } | |
821 | |
822 | |
823 /* | |
824 blesscurse() | |
825 returns whether the object is blessed or cursed | |
826 */ | |
827 | |
828 char * | |
829 blesscurse(long flags) | |
830 { | |
831 if (flags & ISKNOW) | |
832 { | |
833 if (flags & ISCURSED) | |
834 return("cursed "); | |
835 | |
836 if (flags & ISBLESSED) | |
837 return("blessed "); | |
838 | |
839 return("normal "); | |
840 } | |
841 | |
842 return(""); | |
843 } | |
844 | |
845 /* | |
846 extras() | |
847 Return the number of extra food items to be created | |
848 */ | |
849 | |
850 int | |
851 extras(void) | |
852 { | |
853 int i = rnd(100); | |
854 | |
855 if (i < 10) | |
856 return(2); | |
857 else if (i < 20) | |
858 return(1); | |
859 else | |
860 return(0); | |
861 } | |
862 | |
863 /* | |
864 name_type() | |
865 Returns a string identifying a pack item's type | |
866 */ | |
867 | |
868 char * | |
869 name_type(int type) | |
870 { | |
871 switch(type) | |
872 { | |
873 case ARMOR: | |
874 return ("armor"); | |
875 | |
876 case WEAPON: | |
877 return ("weapons"); | |
878 | |
879 case SCROLL: | |
880 return ("scrolls"); | |
881 | |
882 case RING: | |
883 return ("rings"); | |
884 | |
885 case STICK: | |
886 return ("staffs"); | |
887 | |
888 case POTION: | |
889 return ("potions"); | |
890 | |
891 case FOOD: | |
892 return ("food"); | |
893 | |
894 case GOLD: | |
895 return ("gold"); | |
896 | |
897 default: | |
898 return ("items"); | |
899 } | |
900 } | |
901 | |
902 /* | |
903 make_item() | |
904 adds a linked_list structure to the top of an object for interfacing | |
905 with other routines | |
906 */ | |
907 | |
908 linked_list * | |
909 make_item(object *obj_p) | |
910 { | |
911 linked_list *item_p = new_list(); | |
912 | |
913 item_p->l_next = item_p->l_prev = NULL; | |
914 | |
915 item_p->data.obj = obj_p; | |
916 | |
917 return(item_p); | |
918 } | |
919 | |
920 /* | |
921 is_member() | |
922 Checks to see if a character is a member of an array | |
923 */ | |
924 | |
925 int | |
926 is_member(char *list_p, int member) | |
927 { | |
928 while (*list_p != 0) | |
929 { | |
930 if (*list_p++ == member) | |
931 return(TRUE); | |
932 } | |
933 | |
934 return(FALSE); | |
935 } |