Annotation of early-roguelike/srogue/sticks.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * Functions to deal with the various sticks one
3: * might find while wandering around the dungeon.
4: *
5: * @(#)sticks.c 9.0 (rdk) 7/17/84
6: *
7: * Super-Rogue
8: * Copyright (C) 1984 Robert D. Kindelberger
9: * All rights reserved.
10: *
11: * Based on "Rogue: Exploring the Dungeons of Doom"
12: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
13: * All rights reserved.
14: *
15: * See the file LICENSE.TXT for full copyright and licensing information.
16: */
17:
18: #include <ctype.h>
19: #include <string.h>
20: #include "rogue.h"
21: #include "rogue.ext"
22:
23: void drain(int ymin, int ymax, int xmin, int xmax);
24:
25: /*
26: * fix_stick:
27: * Init a stick for the hero
28: */
29: void
30: fix_stick(struct object *cur)
31: {
32: struct rod *rd;
33:
34: cur->o_type = STICK;
35: cur->o_charges = 4 + rnd(5);
36: strcpy(cur->o_hurldmg, "1d1");
37: rd = &ws_stuff[cur->o_which];
38: cur->o_weight = rd->ws_wght;
39: cur->o_vol = rd->ws_vol;
40: if (strcmp(rd->ws_type, "staff") == 0) {
41: strcpy(cur->o_damage, "2d3");
42: cur->o_charges += rnd(5) + 3;
43: }
44: else {
45: strcpy(cur->o_damage, "1d1");
46: }
47: switch (cur->o_which) {
48: case WS_HIT:
49: if(rnd(100) < 15) {
50: cur->o_hplus = 9;
51: cur->o_dplus = 9;
52: strcpy(cur->o_damage,"3d8");
53: }
54: else {
55: cur->o_hplus = 3;
56: cur->o_dplus = 3;
57: strcpy(cur->o_damage,"1d8");
58: }
59: when WS_LIGHT:
60: cur->o_charges += 7 + rnd(9);
61: }
62: }
63:
64: /*
65: * do_zap:
66: * Zap a stick at something
67: */
68: void
69: do_zap(bool gotdir)
70: {
71: reg struct linked_list *item;
72: reg struct object *obj;
73: reg struct thing *tp;
74: reg int y, x, wh;
75: struct room *rp;
76: bool bless, curse;
77: int better = 0;
78:
79: if ((item = get_item("zap with", STICK)) == NULL)
80: return;
81: obj = OBJPTR(item);
82: wh = obj->o_which;
83: bless = o_on(obj, ISBLESS);
84: curse = o_on(obj, ISCURSED);
85: if (obj->o_type != STICK) {
86: msg("You can't zap with that!");
87: after = FALSE;
88: return;
89: }
90: if (obj->o_charges == 0) {
91: msg("Nothing happens.");
92: return;
93: }
94: if (!gotdir)
95: do {
96: delta.y = rnd(3) - 1;
97: delta.x = rnd(3) - 1;
98: } while (delta.y == 0 && delta.x == 0);
99: rp = player.t_room;
100: if (bless)
101: better = 3;
102: else if (curse)
103: better = -3;
104: switch (wh) {
105: case WS_SAPLIFE:
106: if (!bless) {
107: if (him->s_hpt > 1)
108: him->s_hpt /= 2; /* zap half his hit points */
109: }
110: when WS_CURE:
111: if (!curse) {
112: ws_know[WS_CURE] = TRUE;
113: heal_self(6, FALSE);
114: unconfuse(FALSE);
115: notslow(FALSE);
116: sight(FALSE);
117: }
118: when WS_PYRO:
119: if (!bless) {
120: msg("The rod explodes !!!");
121: chg_hpt(-roll(6,6), FALSE, K_ROD);
122: ws_know[WS_PYRO] = TRUE;
123: del_pack(item); /* throw it away */
124: }
125: when WS_HUNGER:
126: if (!bless) {
127: struct linked_list *ip;
128: struct object *lb;
129:
130: food_left /= 3;
131: if ((ip = pack) != NULL) {
132: lb = OBJPTR(ip);
133: if (lb->o_type == FOOD) {
134: if ((lb->o_count -= roll(1,4)) < 1)
135: del_pack(ip);
136: }
137: }
138: }
139: when WS_PARZ:
140: case WS_MREG:
141: case WS_MDEG:
142: case WS_ANNIH: {
143: struct linked_list *mitem;
144: struct thing *it;
145: reg int i,j;
146:
147: for (i = hero.y - 3; i <= hero.y + 3; i++) {
148: for (j = hero.x - 3; j <= hero.x + 3; j++) {
149: if (!cordok(i, j))
150: continue;
151: if (isalpha(mvwinch(mw,i,j))) {
152: mitem = find_mons(i, j);
153: if (mitem == NULL)
154: continue;
155: it = THINGPTR(mitem);
156: switch(wh) {
157: case WS_ANNIH:
158: if (!curse)
159: killed(mitem,FALSE);
160: when WS_MREG:
161: if (!bless)
162: it->t_stats.s_hpt *= 2;
163: when WS_MDEG:
164: if (!curse) {
165: it->t_stats.s_hpt /= 2;
166: if (it->t_stats.s_hpt < 2)
167: killed(mitem,FALSE);
168: }
169: when WS_PARZ:
170: if (!curse) {
171: it->t_flags |= ISPARA;
172: it->t_flags &= ~ISRUN;
173: }
174: }
175: }
176: }
177: }
178: }
179: when WS_LIGHT:
180: if (!curse) {
181: ws_know[WS_LIGHT] = TRUE;
182: if (rp == NULL)
183: msg("The corridor glows and then fades.");
184: else {
185: msg("The room is lit.");
186: rp->r_flags &= ~ISDARK;
187: light(&hero);
188: mvwaddch(cw, hero.y, hero.x, PLAYER);
189: }
190: }
191: when WS_DRAIN:
192: /*
193: * Take away 1/2 of hero's hit points, then take it away
194: * evenly from the monsters in the room (or next to hero
195: * if he is in a passage)
196: */
197: if (him->s_hpt < 2) {
198: msg("You are too weak to use it.");
199: return;
200: }
201: else if (!curse) {
202: if (rp == NULL)
203: drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
204: else
205: drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
206: rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
207: }
208: when WS_POLYM:
209: case WS_TELAWAY:
210: case WS_TELTO:
211: case WS_CANCEL:
212: case WS_MINVIS:
213: {
214: reg char monster, oldch;
215:
216: y = hero.y;
217: x = hero.x;
218: do {
219: y += delta.y;
220: x += delta.x;
221: } while (step_ok(winat(y, x)));
222: if (isalpha(monster = mvwinch(mw, y, x))) {
223: int omonst;
224:
225: if (wh != WS_MINVIS)
226: unhold(monster);
227: item = find_mons(y, x);
228: if (item == NULL)
229: break;
230: tp = THINGPTR(item);
231: omonst = tp->t_indx;
232: if (wh == WS_POLYM && !curse) {
233: detach(mlist, item);
234: discard(item);
235: oldch = tp->t_oldch;
236: delta.y = y;
237: delta.x = x;
238: monster = rnd_mon(FALSE, TRUE);
239: item = new_monster(monster, &delta, FALSE);
240: if (!(tp->t_flags & ISRUN))
241: runto(&delta, &hero);
242: if (isalpha(mvwinch(cw, y, x)))
243: mvwaddch(cw, y, x, monsters[monster].m_show);
244: tp->t_oldch = oldch;
245: ws_know[WS_POLYM] |= (monster != omonst);
246: }
247: else if (wh == WS_MINVIS && !bless) {
248: tp->t_flags |= ISINVIS;
249: mvwaddch(cw,y,x,tp->t_oldch); /* hide em */
250: runto(&tp->t_pos, &hero);
251: }
252: else if (wh == WS_CANCEL && !curse) {
253: tp->t_flags |= ISCANC;
254: tp->t_flags &= ~ISINVIS;
255: }
256: else {
257: if (wh == WS_TELAWAY) {
258: if (curse)
259: break;
260: tp->t_pos = *rnd_pos(&rooms[rnd_room()]);
261: }
262: else { /* WS_TELTO */
263: if (bless)
264: break;
265: tp->t_pos.y = hero.y + delta.y;
266: tp->t_pos.x = hero.x + delta.x;
267: }
268: if (isalpha(mvwinch(cw, y, x)))
269: mvwaddch(cw, y, x, tp->t_oldch);
270: tp->t_dest = &hero;
271: tp->t_flags |= ISRUN;
272: mvwaddch(mw, y, x, ' ');
273: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
274: tp->t_oldch = mvwinch(cw,tp->t_pos.y,tp->t_pos.x);
275: }
276: }
277: }
278: when WS_MISSILE:
279: {
280: struct coord *whe;
281: static struct object bolt = {
282: {0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
283: };
284:
285: if (curse)
286: strcpy(bolt.o_hurldmg,"3d3");
287: else if (bless)
288: strcpy(bolt.o_hurldmg,"9d9");
289: ws_know[WS_MISSILE] = TRUE;
290: do_motion(&bolt, delta.y, delta.x);
291: whe = &bolt.o_pos;
292: if (isalpha(mvwinch(mw, whe->y, whe->x))) {
293: struct linked_list *it;
294:
295: runto(whe, &hero);
296: it = find_mons(whe->y, whe->x);
297: if (it != NULL) {
298: if (!save_throw(VS_MAGIC + better, THINGPTR(it))) {
299: hit_monster(whe, &bolt);
300: break;
301: }
302: }
303: }
304: msg("Missle vanishes.");
305: }
306: when WS_NOP:
307: msg("Your %s flickers momentarily and then fades",
308: ws_stuff[wh].ws_type);
309: when WS_HIT: {
310: char ch;
311:
312: delta.y += hero.y;
313: delta.x += hero.x;
314: ch = winat(delta.y, delta.x);
315: if (curse) { /* decrease for cursed */
316: strcpy(obj->o_damage,"1d1");
317: obj->o_hplus = obj->o_dplus = 0;
318: }
319: else if (bless) { /* increase for blessed */
320: strcpy(obj->o_damage,"5d8");
321: obj->o_hplus = obj->o_dplus = 12;
322: }
323: if (isalpha(ch))
324: fight(&delta, obj, FALSE);
325: }
326: when WS_HASTE_M:
327: case WS_CONFMON:
328: case WS_SLOW_M:
329: case WS_MOREMON: {
330: reg int m1,m2;
331: struct coord mp;
332: struct linked_list *titem;
333:
334: y = hero.y;
335: x = hero.x;
336: do {
337: y += delta.y;
338: x += delta.x;
339: } while (step_ok(winat(y, x)));
340: if (isalpha(mvwinch(mw, y, x))) {
341: item = find_mons(y, x);
342: if (item == NULL)
343: break;
344: tp = THINGPTR(item);
345: if (wh == WS_HASTE_M && !bless) { /* haste it */
346: if (on(*tp, ISSLOW))
347: tp->t_flags &= ~ISSLOW;
348: else
349: tp->t_flags |= ISHASTE;
350: }
351: else if (wh == WS_CONFMON && !curse) { /* confuse it */
352: tp->t_flags |= ISHUH;
353: if (pl_on(ISHELD) && tp->t_type == 'd')
354: player.t_flags &= ~ISHELD;
355: }
356: else if (wh == WS_SLOW_M && !curse) { /* slow it */
357: if (on(*tp, ISHASTE))
358: tp->t_flags &= ~ISHASTE;
359: else
360: tp->t_flags |= ISSLOW;
361: tp->t_turn = TRUE;
362: }
363: else if (!bless) { /* WS_MOREMON: multiply it */
364: char ch;
365: struct thing *th;
366:
367: for (m1 = tp->t_pos.x-1; m1 <= tp->t_pos.x+1; m1++) {
368: for(m2 = tp->t_pos.y-1; m2 <= tp->t_pos.y+1; m2++) {
369: if (hero.x == m1 && hero.y == m2)
370: continue;
371: ch = winat(m2,m1);
372: if (step_ok(ch)) {
373: mp.x = m1; /* create it */
374: mp.y = m2;
375: titem = new_monster(tp->t_indx, &mp, FALSE);
376: th = THINGPTR(titem);
377: th->t_flags |= ISMEAN;
378: runto(&mp, &hero);
379: }
380: }
381: }
382: }
383: delta.y = y;
384: delta.x = x;
385: runto(&delta, &hero);
386: }
387: }
388: when WS_ELECT:
389: case WS_FIRE:
390: case WS_COLD: {
391: reg char dirch, ch, *name;
392: reg bool bounced, used;
393: int boingcnt, boltlen;
394: struct coord pos;
395: struct coord spotpos[BOLT_LENGTH * 2];
396: static struct object bolt = {
397: {0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
398: };
399:
400: boltlen = BOLT_LENGTH;
401: if (curse) {
402: strcpy(bolt.o_hurldmg,"3d3");
403: boltlen -= 3;
404: }
405: else if (bless) {
406: strcpy(bolt.o_hurldmg,"9d9");
407: boltlen += 3;
408: }
409: switch (delta.y + delta.x) {
410: case 0: dirch = '/';
411: when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
412: when 2: case -2: dirch = '\\';
413: }
414: pos = hero;
415: bounced = FALSE;
416: boingcnt = 0;
417: used = FALSE;
418: if (wh == WS_ELECT)
419: name = "bolt";
420: else if (wh == WS_FIRE)
421: name = "flame";
422: else
423: name = "ice";
424: for (y = 0; y < boltlen && !used; y++) {
425: ch = winat(pos.y, pos.x);
426: spotpos[y] = pos;
427: switch (ch) {
428: case SECRETDOOR:
429: case '|':
430: case '-':
431: case ' ':
432: bounced = TRUE;
433: if (++boingcnt > 6)
434: used = TRUE; /* only so many bounces */
435: delta.y = -delta.y;
436: delta.x = -delta.x;
437: y--;
438: msg("The bolt bounces");
439: break;
440: default:
441: if (isalpha(ch)) {
442: struct linked_list *it;
443:
444: it = find_mons(pos.y, pos.x);
445: runto(&pos, &hero);
446: if (it != NULL) {
447: if (!save_throw(VS_MAGIC+better,THINGPTR(it))) {
448: bolt.o_pos = pos;
449: hit_monster(&pos, &bolt);
450: used = TRUE;
451: }
452: else if(ch != 'M' || show(pos.y,pos.x)=='M') {
453: msg("%s misses", name);
454: }
455: }
456: }
457: else if(bounced && pos.y==hero.y && pos.x==hero.x) {
458: bounced = FALSE;
459: if (!save(VS_MAGIC + better)) {
460: msg("The %s hits you.", name);
461: chg_hpt(-roll(6, 6),FALSE,K_BOLT);
462: used = TRUE;
463: }
464: else
465: msg("The %s whizzes by you.", name);
466: }
467: mvwaddch(cw, pos.y, pos.x, dirch);
468: draw(cw);
469: }
470: pos.y += delta.y;
471: pos.x += delta.x;
472: }
473: for (x = 0; x < y; x++)
474: mvwaddch(cw, spotpos[x].y, spotpos[x].x,
475: show(spotpos[x].y, spotpos[x].x));
476: ws_know[wh] = TRUE;
477: }
478: when WS_ANTIM: {
479: reg int m1, m2, x1, y1;
480: struct linked_list *ll;
481: struct thing *lt;
482: int ch, radius;
483:
484: y1 = hero.y;
485: x1 = hero.x;
486: do {
487: y1 += delta.y;
488: x1 += delta.x;
489: ch = winat(y1, x1);
490: } while (ch == PASSAGE || ch == FLOOR);
491: if (curse)
492: radius = 2;
493: else if (bless)
494: radius = 0;
495: else
496: radius = 1;
497: for (m1 = x1 - radius; m1 <= x1 + radius; m1++) {
498: for (m2 = y1 - radius; m2 <= y1 + radius; m2++) {
499: if (!cordok(m2, m1))
500: continue;
501: ch = winat(m2, m1);
502: if (m1 == hero.x && m2 == hero.y)
503: continue;
504: if (ch == ' ')
505: continue;
506: ll = find_obj(m2,m1);
507: if (ll != NULL) {
508: detach(lvl_obj,ll);
509: discard(ll);
510: }
511: ll = find_mons(m2,m1);
512: if (ll != NULL) {
513: lt = THINGPTR(ll);
514: him->s_exp += lt->t_stats.s_exp;
515: unhold(lt->t_type);
516: /*
517: * throw away anything that the monster
518: * was carrying in its pack
519: */
520: free_list(lt->t_pack);
521: detach(mlist,ll);
522: discard(ll);
523: mvwaddch(mw,m2,m1,' ');
524: }
525: mvaddch(m2,m1,' ');
526: mvwaddch(cw,m2,m1,' ');
527: }
528: }
529: touchwin(cw);
530: touchwin(mw);
531: check_level();
532: }
533: otherwise:
534: msg("What a bizarre schtick!");
535: }
536: obj->o_charges--;
537: }
538:
539: /*
540: * drain:
541: * Do drain hit points from player stick
542: */
543: void
544: drain(int ymin, int ymax, int xmin, int xmax)
545: {
546: reg int i, j, cnt;
547: reg struct thing *ick;
548: reg struct linked_list *item;
549:
550: /*
551: * First count how many things we need to spread the hit points among
552: */
553: cnt = 0;
554: for (i = ymin; i <= ymax; i++)
555: for (j = xmin; j <= xmax; j++)
556: if (isalpha(mvwinch(mw, i, j)))
557: cnt++;
558: if (cnt == 0) {
559: msg("You have a tingling feeling.");
560: return;
561: }
562: cnt = him->s_hpt / cnt;
563: him->s_hpt /= 2;
564: /*
565: * Now zot all of the monsters
566: */
567: for (i = ymin; i <= ymax; i++) {
568: for (j = xmin; j <= xmax; j++) {
569: if(isalpha(mvwinch(mw, i, j))) {
570: item = find_mons(i, j);
571: if (item == NULL)
572: continue;
573: ick = THINGPTR(item);
574: if ((ick->t_stats.s_hpt -= cnt) < 1)
575: killed(item,cansee(i,j) && !(ick->t_flags & ISINVIS));
576: }
577: }
578: }
579: }
580:
581: /*
582: * charge_str:
583: * Return number of charges left in a stick
584: */
585: char *
586: charge_str(struct object *obj)
587: {
588: static char buf[20];
589:
590: buf[0] = '\0';
591: if (o_on(obj,ISKNOW) || o_on(obj,ISPOST))
592: sprintf(buf, " [%d]", obj->o_charges);
593: return buf;
594: }
CVSweb