comparison srogue/sticks.c @ 36:2128c7dc8a40

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