Annotation of early-roguelike/xrogue/sticks.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: sticks.c - Functions to implement the various sticks one might find
3:
4: XRogue: Expeditions into the Dungeons of Doom
5: Copyright (C) 1991 Robert Pietkivitch
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
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 <curses.h>
20: #include <ctype.h>
21: #include <string.h>
22: #include "rogue.h"
23:
24: void drain(int ymin, int ymax, int xmin, int xmax);
25:
26: /*
27: * zap a stick and see what happens
28: */
29:
30: void
31: do_zap(struct thing *zapper, struct object *obj, coord *direction, int which,
32: int flags)
33: {
34: register struct linked_list *item = NULL;
35: register struct thing *tp;
36: register int y = 0, x = 0, bonus;
37: struct linked_list *nitem;
38: struct object *nobj;
39: bool cursed, blessed, is_player = FALSE;
40: char *mname = NULL;
41:
42: cursed = flags & ISCURSED;
43: blessed = flags & ISBLESSED;
44:
45: if (obj && obj->o_type != RELIC) { /* all relics are chargeless */
46: if (obj->o_charges < 1) {
47: msg(nothing);
48: return;
49: }
50: obj->o_charges--;
51: }
52: if (which == WS_WONDER) {
53: switch (rnd(19)) {
54: case 0: which = WS_ELECT;
55: when 1: which = WS_FIRE;
56: when 2: which = WS_COLD;
57: when 3: which = WS_POLYMORPH;
58: when 4: which = WS_MISSILE;
59: when 5: which = WS_SLOW_M;
60: when 6: which = WS_TELMON;
61: when 7: which = WS_CANCEL;
62: when 8: which = WS_CONFMON;
63: when 9: which = WS_DISINTEGRATE;
64: when 10: which = WS_PETRIFY;
65: when 11: which = WS_PARALYZE;
66: when 12: which = WS_MDEG;
67: when 13: which = WS_FEAR;
68: when 14: which = WS_CURING;
69: when 15: which = WS_LIGHT;
70: when 16: which = WS_HIT;
71: when 17: which = WS_DRAIN;
72: when 18: which = WS_CHARGE;
73: }
74: if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){
75: cursed = TRUE;
76: blessed = FALSE;
77: }
78: }
79:
80: tp = NULL;
81: switch (which) {
82: case WS_POLYMORPH:
83: case WS_SLOW_M:
84: case WS_TELMON:
85: case WS_CANCEL:
86: case WS_CONFMON:
87: case WS_DISINTEGRATE:
88: case WS_PETRIFY:
89: case WS_PARALYZE:
90: case WS_MDEG:
91: case WS_FEAR:
92: y = zapper->t_pos.y;
93: x = zapper->t_pos.x;
94:
95: do {
96: y += direction->y;
97: x += direction->x;
98: }
99: while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x));
100:
101: if (y == hero.y && x == hero.x)
102: is_player = TRUE;
103: else if (isalpha(mvwinch(mw, y, x))) {
104: item = find_mons(y, x);
105: tp = THINGPTR(item);
106: runto(tp, &hero);
107: turn_off(*tp, CANSURPRISE);
108: mname = monster_name(tp);
109: is_player = FALSE;
110:
111: /* The monster may not like being shot at */
112: if ((zapper == &player) &&
113: on(*tp, ISCHARMED) &&
114: save(VS_MAGIC, tp, 0)) {
115: msg("The eyes of %s turn clear.", prname(mname, FALSE));
116: turn_off(*tp, ISCHARMED);
117: mname = monster_name(tp);
118: }
119: }
120: else {
121: /*
122: * if monster misses player because the player dodged then lessen
123: * the chances he will use the wand again since the player appears
124: * to be rather dextrous
125: */
126: if (zapper != &player)
127: zapper->t_wand = zapper->t_wand * 3 / 5;
128: }
129: }
130: switch (which) {
131: case WS_LIGHT:
132: /*
133: * Reddy Kilowat wand. Light up the room
134: */
135: blue_light(blessed, cursed);
136: when WS_DRAIN:
137: /*
138: * Take away 1/2 of hero's hit points, then take it away
139: * evenly from the monsters in the room or next to hero
140: * if he is in a passage (but leave the monsters alone
141: * if the stick is cursed)
142: */
143: if (pstats.s_hpt < 2) {
144: msg("You are too weak to use it.");
145: }
146: else if (cursed)
147: pstats.s_hpt /= 2;
148: if (pstats.s_hpt <= 0) {
149: pstats.s_hpt = -1;
150: msg("You drain your own life away. --More--");
151: death(D_STRENGTH);
152: }
153: else
154: drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
155:
156: when WS_POLYMORPH:
157: {
158: register char oldch;
159: register struct room *rp;
160: register struct linked_list *pitem;
161: coord delta;
162:
163: if (tp == NULL)
164: break;
165: if (save(VS_MAGIC, tp, 0)) {
166: msg(nothing);
167: break;
168: }
169: rp = roomin(&tp->t_pos);
170: check_residue(tp);
171: delta.x = x;
172: delta.y = y;
173: detach(mlist, item);
174: oldch = tp->t_oldch;
175: pitem = tp->t_pack; /* save his pack */
176: tp->t_pack = NULL;
177:
178: if (levtype == OUTSIDE)
179: new_monster(item,rnd(NUMDINOS)+NUMMONST-NUMDINOS,&delta,FALSE);
180: else
181: new_monster(item,rnd(NUMMONST-NUMUNIQUE-NUMDINOS-1)+1,&delta,FALSE);
182:
183: if (tp->t_pack != NULL)
184: o_free_list (tp->t_pack);
185: tp->t_pack = pitem;
186: if (isalpha(mvwinch(cw, y, x)))
187: mvwaddch(cw, y, x, tp->t_type);
188: tp->t_oldch = oldch;
189: /*
190: * should the room light up?
191: */
192: if (on(*tp, HASFIRE)) {
193: if (rp) {
194: register struct linked_list *fire_item;
195:
196: fire_item = creat_item();
197: ldata(fire_item) = (char *) tp;
198: attach(rp->r_fires, fire_item);
199: rp->r_flags |= HASFIRE;
200: if (cansee(tp->t_pos.y,tp->t_pos.x) &&
201: next(rp->r_fires) == NULL) light(&hero);
202: }
203: }
204: runto(tp, &hero);
205: msg(terse ? "A new %s!"
206: : "You have created a new %s!",
207: monster_name(tp));
208: }
209:
210: when WS_PETRIFY:
211: if (tp == NULL)
212: break;
213: if (save(VS_MAGIC, tp, 0)) {
214: msg(nothing);
215: break;
216: }
217: check_residue(tp);
218: turn_on(*tp, ISSTONE);
219: turn_on(*tp, NOSTONE);
220: turn_off(*tp, ISRUN);
221: turn_off(*tp, ISINVIS);
222: turn_off(*tp, CANSURPRISE);
223: turn_off(*tp, ISDISGUISE);
224: tp->t_action = A_NIL;
225: tp->t_no_move = 0;
226: msg("%s is turned to stone!",prname(mname, TRUE));
227:
228: when WS_TELMON:
229: {
230: register int rm;
231: register struct room *rp;
232:
233: if (tp == NULL)
234: break;
235: if (save(VS_MAGIC, tp, 0)) {
236: msg(nothing);
237: break;
238: }
239: rp = NULL;
240: check_residue(tp);
241: tp->t_action = A_FREEZE; /* creature is disoriented */
242: tp->t_no_move = 2;
243: if (cursed) { /* Teleport monster to player */
244: if ((y == (hero.y + direction->y)) &&
245: (x == (hero.x + direction->x)))
246: msg(nothing);
247: else {
248: tp->t_pos.y = hero.y + direction->y;
249: tp->t_pos.x = hero.x + direction->x;
250: }
251: }
252: else if (blessed) { /* Get rid of monster */
253: killed(item, FALSE, TRUE, TRUE);
254: return;
255: }
256: else {
257: register int i=0;
258:
259: do { /* Move monster to another room */
260: rm = rnd_room();
261: rnd_pos(&rooms[rm], &tp->t_pos);
262: }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500);
263: rp = &rooms[rm];
264: }
265:
266: /* Now move the monster */
267: if (isalpha(mvwinch(cw, y, x)))
268: mvwaddch(cw, y, x, tp->t_oldch);
269: mvwaddch(mw, y, x, ' ');
270: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
271: if (tp->t_pos.y != y || tp->t_pos.x != x)
272: tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
273: /*
274: * check to see if room that creature appears in should
275: * light up
276: */
277: if (on(*tp, HASFIRE)) {
278: if (rp) {
279: register struct linked_list *fire_item;
280:
281: fire_item = creat_item();
282: ldata(fire_item) = (char *) tp;
283: attach(rp->r_fires, fire_item);
284: rp->r_flags |= HASFIRE;
285: if(cansee(tp->t_pos.y, tp->t_pos.x) &&
286: next(rp->r_fires) == NULL)
287: light(&hero);
288: }
289: }
290: }
291: when WS_CANCEL:
292: if (tp == NULL)
293: break;
294: if (save(VS_MAGIC, tp, 0)) {
295: msg(nothing);
296: break;
297: }
298: check_residue(tp);
299: tp->t_flags[0] &= CANC0MASK;
300: tp->t_flags[1] &= CANC1MASK;
301: tp->t_flags[2] &= CANC2MASK;
302: tp->t_flags[3] &= CANC3MASK;
303: tp->t_flags[4] &= CANC4MASK;
304: tp->t_flags[5] &= CANC5MASK;
305: tp->t_flags[6] &= CANC6MASK;
306: tp->t_flags[7] &= CANC7MASK;
307: tp->t_flags[8] &= CANC8MASK;
308: tp->t_flags[9] &= CANC9MASK;
309: tp->t_flags[10] &= CANCAMASK;
310: tp->t_flags[11] &= CANCBMASK;
311: tp->t_flags[12] &= CANCCMASK;
312: tp->t_flags[13] &= CANCDMASK;
313: tp->t_flags[14] &= CANCEMASK;
314: tp->t_flags[15] &= CANCFMASK;
315:
316: when WS_MISSILE:
317: {
318: int dice;
319: static struct object bolt =
320: {
321: MISSILE , {0, 0}, 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
322: };
323:
324: if (!obj)
325: dice = zapper->t_stats.s_lvl;
326: if (obj->o_type == RELIC)
327: dice = 15;
328: else if (EQUAL(ws_type[which], "staff"))
329: dice = 10;
330: else
331: dice = 6;
332: sprintf(bolt.o_hurldmg, "%dd4", dice);
333: do_motion(&bolt, direction->y, direction->x, zapper);
334: if (!hit_monster(unc(bolt.o_pos), &bolt, zapper))
335: msg("The missile vanishes with a puff of smoke");
336: }
337: when WS_HIT:
338: {
339: register unsigned char ch;
340: struct object strike; /* don't want to change sticks attributes */
341:
342: direction->y += hero.y;
343: direction->x += hero.x;
344: ch = winat(direction->y, direction->x);
345: if (isalpha(ch))
346: {
347: strike = *obj;
348: strike.o_hplus = 7;
349: if (EQUAL(ws_type[which], "staff"))
350: strcpy(strike.o_damage,"3d8");
351: else
352: strcpy(strike.o_damage,"2d8");
353: fight(direction, &strike, FALSE);
354: }
355: }
356: when WS_SLOW_M:
357: if (is_player) {
358: add_slow();
359: break;
360: }
361: if (tp == NULL)
362: break;
363: if (cursed) {
364: if (on(*tp, ISSLOW))
365: turn_off(*tp, ISSLOW);
366: else
367: turn_on(*tp, ISHASTE);
368: break;
369: }
370: if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) {
371: msg(nothing);
372: break;
373: }
374: else if (blessed) {
375: turn_off(*tp, ISRUN);
376: turn_on(*tp, ISHELD);
377: }
378: /*
379: * always slow in case he breaks free of HOLD
380: */
381: if (on(*tp, ISHASTE))
382: turn_off(*tp, ISHASTE);
383: else
384: turn_on(*tp, ISSLOW);
385:
386: when WS_CHARGE:
387: if (ws_know[WS_CHARGE] != TRUE && obj)
388: msg("This is a wand of charging.");
389: nitem = get_item(pack, "charge", STICK, FALSE, FALSE);
390: if (nitem != NULL) {
391: nobj = OBJPTR(nitem);
392: if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
393: fix_stick(nobj);
394: if (blessed) ++(nobj->o_charges);
395: if (EQUAL(ws_type[nobj->o_which], "staff")) {
396: if (nobj->o_charges > 200)
397: nobj->o_charges = 200;
398: }
399: else {
400: if (nobj->o_charges > 200)
401: nobj->o_charges = 200;
402: }
403: }
404: when WS_ELECT:
405: shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
406: "lightning bolt", roll(zapper->t_stats.s_lvl,6));
407:
408: when WS_FIRE:
409: shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
410: "flame", roll(zapper->t_stats.s_lvl,6));
411:
412: when WS_COLD:
413: shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT,
414: "ice", roll(zapper->t_stats.s_lvl,6));
415:
416: when WS_CONFMON:
417: if (cursed || is_player) {
418: if (!save(VS_WAND, &player, 0)) {
419: dsrpt_player();
420: confus_player();
421: }
422: else {
423: if (zapper != &player) zapper->t_wand /= 2;
424: msg(nothing);
425: }
426: }
427: else {
428: if (tp == NULL)
429: break;
430: if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
431: msg(nothing);
432: else
433: turn_on (*tp, ISHUH);
434: }
435: when WS_PARALYZE:
436: if (is_player || cursed) {
437: if ((obj && obj->o_type==RELIC) || !save(VS_WAND, &player, 0)){
438: player.t_no_move += 2 * movement(&player) * FREEZETIME;
439: player.t_action = A_FREEZE;
440: msg("You can't move.");
441: }
442: else {
443: if (zapper != &player) zapper->t_wand /= 2;
444: msg(nothing);
445: }
446: }
447: else {
448: if (tp == NULL)
449: break;
450: bonus = 0;
451: if (blessed) bonus = -3;
452: if (((obj && obj->o_type==RELIC) || !save(VS_WAND,tp,bonus)) &&
453: off(*tp, NOPARALYZE)) {
454: tp->t_no_move += 2 * movement(tp) * FREEZETIME;
455: tp->t_action = A_FREEZE;
456: }
457: else {
458: msg(nothing);
459: }
460: }
461: when WS_FEAR:
462: if (is_player) {
463: if (!on(player, ISFLEE) ||
464: ISWEARING(R_HEROISM) ||
465: save(VS_WAND, &player, 0)) {
466: msg(nothing);
467: zapper->t_wand /= 2;
468: }
469: else {
470: turn_on(player, ISFLEE);
471: player.t_dest = &zapper->t_pos;
472: msg("The sight of %s terrifies you.", prname(mname, FALSE));
473: }
474: break;
475: }
476: if (tp == NULL)
477: break;
478: bonus = 0;
479: if (blessed) bonus = -3;
480: if(save(VS_WAND, tp,bonus) || on(*tp,ISUNDEAD) || on(*tp,NOFEAR)){
481: msg(nothing);
482: break;
483: }
484: turn_on(*tp, ISFLEE);
485: turn_on(*tp, WASTURNED);
486:
487: /* Stop it from attacking us */
488: dsrpt_monster(tp, TRUE, cansee(tp->t_pos.y, tp->t_pos.x));
489:
490: /* If monster was suffocating, stop it */
491: if (on(*tp, DIDSUFFOCATE)) {
492: turn_off(*tp, DIDSUFFOCATE);
493: extinguish(suffocate);
494: }
495:
496: /* If monster held us, stop it */
497: if (on(*tp, DIDHOLD) && (--hold_count == 0))
498: turn_off(player, ISHELD);
499: turn_off(*tp, DIDHOLD);
500:
501: /* It is okay to turn tail */
502: tp->t_oldpos = tp->t_pos;
503:
504: when WS_MDEG:
505: if (is_player) {
506: if (save(VS_WAND, &player, 0)) {
507: msg (nothing);
508: zapper->t_wand /= 2;
509: break;
510: }
511: pstats.s_hpt /= 2;
512: if (pstats.s_hpt <= 0) {
513: pstats.s_hpt = -1;
514: msg("Your life has been sucked out from you! --More--");
515: wait_for(' ');
516: death(zapper->t_index);
517: }
518: else
519: msg("You feel a great drain on your system.");
520: }
521: if (tp == NULL)
522: break;
523: if (cursed) {
524: tp->t_stats.s_hpt *= 2;
525: msg("%s appears to be stronger now!", prname(mname, TRUE));
526: }
527: else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
528: msg (nothing);
529: else {
530: tp->t_stats.s_hpt /= 2;
531: msg("%s appears to be weaker now", prname(mname, TRUE));
532: }
533: if (tp->t_stats.s_hpt < 1)
534: killed(item, TRUE, TRUE, TRUE);
535: when WS_DISINTEGRATE:
536: if (tp == NULL)
537: break;
538: if (cursed) {
539: register int m1, m2;
540: coord mp;
541: struct linked_list *titem;
542: char ch;
543: struct thing *th;
544:
545: if (on(*tp, ISUNIQUE) || on(*tp, CANSELL)) {
546: msg (nothing);
547: break;
548: }
549: for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) {
550: for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) {
551: if (m1 == hero.x && m2 == hero.y)
552: continue;
553: ch = winat(m2,m1);
554: if (shoot_ok(ch)) {
555: mp.x = m1; /* create it */
556: mp.y = m2;
557: titem = new_item(sizeof(struct thing));
558: new_monster(titem,(short)tp->t_index,&mp,FALSE);
559: th = THINGPTR(titem);
560: turn_on (*th, ISMEAN);
561: runto(th,&hero);
562: if (on(*th, HASFIRE)) {
563: register struct room *rp;
564:
565: rp = roomin(&th->t_pos);
566: if (rp) {
567: register struct linked_list *fire_item;
568:
569: fire_item = creat_item();
570: ldata(fire_item) = (char *) th;
571: attach(rp->r_fires, fire_item);
572: rp->r_flags |= HASFIRE;
573: if (cansee(th->t_pos.y, th->t_pos.x) &&
574: next(rp->r_fires) == NULL)
575: light(&hero);
576: }
577: }
578: }
579: }
580: }
581: }
582: else { /* if its a UNIQUE it might still live */
583: if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) {
584: tp->t_stats.s_hpt /= 2;
585: if (tp->t_stats.s_hpt < 1) {
586: killed(item, FALSE, TRUE, TRUE);
587: msg("You have disintegrated %s", prname(mname, FALSE));
588: }
589: else {
590: msg("%s appears wounded", prname(mname, TRUE));
591: }
592: }
593: else {
594: msg("You have disintegrated %s", prname(mname, FALSE));
595: killed (item, FALSE, TRUE, TRUE);
596: }
597: }
598: when WS_CURING:
599: if (cursed) {
600: bool sick = FALSE;
601: if (!save(VS_POISON, &player, 0)) {
602: msg("You feel extremely sick. ");
603: sick = TRUE;
604: pstats.s_hpt -= (pstats.s_hpt/3)+1;
605: if (pstats.s_hpt == 0) {
606: pstats.s_hpt = -1;
607: msg("You die! --More--");
608: wait_for(' ');
609: death (D_POISON);
610: }
611: }
612: if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) {
613: turn_on(player, HASDISEASE);
614: turn_on(player, HASINFEST);
615: turn_on(player, DOROT);
616: fuse(cure_disease, NULL, roll(HEALTIME,SICKTIME), AFTER);
617: infest_dam++;
618: }
619: else if (sick == FALSE) msg("You feel momentarily sick");
620: }
621: else {
622: if (on(player, HASDISEASE) || on(player, HASINFEST)) {
623: extinguish(cure_disease);
624: turn_off(player, HASINFEST);
625: infest_dam = 0;
626: cure_disease(); /* this prints message */
627: }
628: if (on(player, DOROT)) {
629: msg("You feel your skin returning to normal.");
630: turn_off(player, DOROT);
631: }
632: pstats.s_hpt += roll(pstats.s_lvl, blessed ? 9 : 6);
633: if (pstats.s_hpt > max_stats.s_hpt)
634: pstats.s_hpt = max_stats.s_hpt;
635: msg("You begin to feel %sbetter.", blessed ? "much " : "");
636:
637: }
638: otherwise:
639: msg("What a bizarre schtick!");
640: }
641: }
642:
643:
644: /*
645: * drain:
646: * Do drain hit points from player shtick
647: */
648:
649: void
650: drain(int ymin, int ymax, int xmin, int xmax)
651: {
652: register int i, j, count;
653: register struct thing *ick;
654: register struct linked_list *item;
655:
656: /*
657: * First count how many things we need to spread the hit points among
658: */
659: count = 0;
660: for (i = ymin; i <= ymax; i++) {
661: if (i < 1 || i > lines - 3)
662: continue;
663: for (j = xmin; j <= xmax; j++) {
664: if (j < 0 || j > cols - 1)
665: continue;
666: if (isalpha(mvwinch(mw, i, j)))
667: count++;
668: }
669: }
670: if (count == 0)
671: {
672: msg("You have a tingling feeling.");
673: return;
674: }
675: count = pstats.s_hpt / count;
676: pstats.s_hpt /= 2;
677: if (pstats.s_hpt <= 0) {
678: pstats.s_hpt = -1;
679: msg("Aarrgghhh!! --More--");
680: wait_for(' ');
681: death(D_STRENGTH);
682: }
683: /*
684: * Now zot all of the monsters
685: */
686: for (i = ymin; i <= ymax; i++) {
687: if (i < 1 || i > lines - 3)
688: continue;
689: for (j = xmin; j <= xmax; j++) {
690: if (j < 0 || j > cols - 1)
691: continue;
692: if (isalpha(mvwinch(mw, i, j)) &&
693: ((item = find_mons(i, j)) != NULL)) {
694: ick = THINGPTR(item);
695: if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0))
696: ick->t_stats.s_hpt -= count / 2;
697: else
698: ick->t_stats.s_hpt -= count;
699: if (ick->t_stats.s_hpt < 1)
700: killed(item,
701: cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)),
702: TRUE, TRUE);
703: else {
704: runto(ick, &hero);
705:
706: /*
707: * The monster may not like being shot at. Since the
708: * shot is not aimed directly at the monster, we will
709: * give him a poorer save.
710: */
711: if (on(*ick, ISCHARMED) && save(VS_MAGIC, ick, -2)) {
712: msg("The eyes of %s turn clear.",
713: prname(monster_name(ick), FALSE));
714: turn_off(*ick, ISCHARMED);
715: }
716: if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
717: msg("%s appears wounded",
718: prname(monster_name(ick), TRUE));
719: }
720: }
721: }
722: }
723: }
724:
725: /*
726: * initialize a stick
727: */
728:
729: void
730: fix_stick(struct object *cur)
731: {
732: if (EQUAL(ws_type[cur->o_which], "staff")) {
733: cur->o_weight = 100;
734: cur->o_charges = 5 + rnd(11);
735: strcpy(cur->o_damage,"3d4");
736: cur->o_hplus = 1;
737: cur->o_dplus = 0;
738: switch (cur->o_which) {
739: case WS_HIT:
740: cur->o_hplus = 3;
741: cur->o_dplus = 3;
742: strcpy(cur->o_damage,"2d8");
743: when WS_LIGHT:
744: cur->o_charges = 15 + rnd(11);
745: }
746: }
747: else {
748: strcpy(cur->o_damage,"2d3");
749: cur->o_weight = 75;
750: cur->o_hplus = 1;
751: cur->o_dplus = 0;
752: cur->o_charges = 5 + rnd(11);
753: switch (cur->o_which) {
754: case WS_HIT:
755: cur->o_hplus = 3;
756: cur->o_dplus = 3;
757: strcpy(cur->o_damage,"2d8");
758: when WS_LIGHT:
759: cur->o_charges = 15 + rnd(11);
760: }
761: }
762: strcpy(cur->o_hurldmg,"3d3");
763:
764: }
765:
766: /*
767: * Use the wand that our monster is wielding.
768: */
769:
770: void
771: m_use_wand(struct thing *monster)
772: {
773: register struct object *obj;
774:
775: /* Make sure we really have it */
776: if (monster->t_using)
777: obj = OBJPTR(monster->t_using);
778: else {
779: debug("Stick not set!");
780: monster->t_action = A_NIL;
781: return;
782: }
783:
784: if (obj->o_type != STICK) {
785: debug("Stick not selected!");
786: monster->t_action = A_NIL;
787: return;
788: }
789: /*
790: * shoot the stick!
791: * assume all blessed sticks are normal for now.
792: * Note that we don't get here if the wand is cursed.
793: */
794: msg("%s points a %s at you!", prname(monster_name(monster), TRUE),
795: ws_type[obj->o_which]);
796: do_zap(monster, obj, &monster->t_newpos, obj->o_which, 0);
797: monster->t_wand /= 2; /* chance lowers with each use */
798: }
799:
800: /*
801: * type: type of item, NULL means stick
802: * which: which item
803: */
804: bool
805: need_dir(int type, int which)
806: {
807: if (type == STICK || type == 0) {
808: switch (which) {
809: case WS_LIGHT:
810: case WS_DRAIN:
811: case WS_CHARGE:
812: case WS_CURING:
813: return(FALSE);
814: default:
815: return(TRUE);
816: }
817: }
818: else if (type == RELIC) {
819: switch (which) {
820: case MING_STAFF:
821: case ASMO_ROD:
822: case EMORI_CLOAK:
823: return(TRUE);
824: default:
825: return(FALSE);
826: }
827: }
828: return (FALSE); /* hope we don't get here */
829: }
830:
831: /*
832: * let the player zap a stick and see what happens
833: */
834:
835: bool
836: player_zap(int which, int flag)
837: {
838: register struct linked_list *item;
839: register struct object *obj;
840:
841: obj = NULL;
842: if (which == 0) {
843: /* This is a stick. It takes 2 movement periods to zap it */
844: if (player.t_action != C_ZAP) {
845: if ((item = get_item(pack,"zap with",ZAPPABLE,FALSE,FALSE)) == NULL)
846: return(FALSE);
847:
848: obj = OBJPTR(item);
849:
850: if (need_dir(obj->o_type, obj->o_which)) {
851: if (!get_dir(&player.t_newpos))
852: return(FALSE);
853: }
854: player.t_using = item; /* Remember what it is */
855: player.t_action = C_ZAP; /* We are quaffing */
856: player.t_no_move = 2 * movement(&player);
857: return(TRUE);
858: }
859:
860: item = player.t_using;
861: /* We've waited our time, let's shoot 'em up! */
862: player.t_using = NULL;
863: player.t_action = A_NIL;
864:
865: obj = OBJPTR(item);
866:
867: /* Handle relics specially here */
868: if (obj->o_type == RELIC) {
869: switch (obj->o_which) {
870: case ORCUS_WAND:
871: /* msg(nothing); */
872: read_scroll(S_PETRIFY, 0, FALSE);
873: return(TRUE);
874: when MING_STAFF:
875: which = WS_MISSILE;
876: when EMORI_CLOAK:
877: which = WS_PARALYZE;
878: obj->o_charges = 0; /* one zap/day (whatever that is) */
879: fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
880: when ASMO_ROD:
881: switch (rnd(3)) {
882: case 0: which = WS_ELECT;
883: when 1: which = WS_COLD;
884: otherwise: which = WS_FIRE;
885: }
886: }
887: }
888: else {
889: which = obj->o_which;
890: ws_know[which] = TRUE;
891: flag = obj->o_flags;
892: }
893: }
894: do_zap(&player, obj, &player.t_newpos, which, flag);
895: return(TRUE);
896: }
897:
CVSweb