comparison srogue/move.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 * Hero movement commands
3 *
4 * @(#)move.c 9.0 (rdk) 7/17/84
5 *
6 * Super-Rogue
7 * Copyright (C) 1984 Robert D. Kindelberger
8 * All rights reserved.
9 *
10 * Based on "Rogue: Exploring the Dungeons of Doom"
11 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
12 * All rights reserved.
13 *
14 * See the file LICENSE.TXT for full copyright and licensing information.
15 */
16
17 #include <ctype.h>
18 #include "rogue.h"
19 #include "rogue.ext"
20
21 /*
22 * Used to hold the new hero position
23 */
24
25 struct coord nh;
26
27 /*
28 * do_run:
29 * Start the hero running
30 */
31
32 do_run(ch)
33 char ch;
34 {
35 running = TRUE;
36 after = FALSE;
37 runch = ch;
38 }
39
40 /*
41 * do_move:
42 * Check to see that a move is legal. If it is handle the
43 * consequences (fighting, picking up, etc.)
44 */
45
46 do_move(dy, dx)
47 int dy, dx;
48 {
49 reg int ch;
50 reg struct room *rp;
51
52 firstmove = FALSE;
53 curprice = -1;
54 inpool = FALSE;
55
56 if (player.t_nomove > 0) {
57 player.t_nomove -= 1;
58 msg("You are still stuck in the bear trap.");
59 return;
60 }
61 /*
62 * Do a confused move (maybe)
63 */
64 if ((rnd(100) < 80 && pl_on(ISHUH)) ||
65 (iswearing(R_DELUS) && rnd(100) < 25))
66 nh = *rndmove(&player);
67 else {
68 nh.y = hero.y + dy;
69 nh.x = hero.x + dx;
70 }
71 /*
72 * Check if he tried to move off the screen or make
73 * an illegal diagonal move, and stop him if he did.
74 */
75 if (!cordok(nh.y, nh.x) ||
76 (pl_off(ISETHER) && !diag_ok(&hero, &nh))) {
77 after = running = FALSE;
78 return;
79 }
80 if (running) {
81 ch = winat(nh.y, nh.x);
82 if (dead_end(ch)) {
83 reg int gox, goy, apsg, whichway;
84
85 gox = goy = apsg = 0;
86 if (dy == 0) {
87 ch = show(hero.y+1,hero.x);
88 if (ch == PASSAGE) {
89 apsg += 1;
90 goy = 1;
91 }
92 ch = show(hero.y-1,hero.x);
93 if (ch == PASSAGE) {
94 apsg += 1;
95 goy = -1;
96 }
97 }
98 else if (dx == 0) {
99 ch = show(hero.y,hero.x+1);
100 if (ch == PASSAGE) {
101 gox = 1;
102 apsg += 1;
103 }
104 ch = show(hero.y,hero.x-1);
105 if (ch == PASSAGE) {
106 gox = -1;
107 apsg += 1;
108 }
109 }
110 if (apsg != 1) {
111 running = after = FALSE;
112 return;
113 }
114 else { /* can still run here */
115 nh.y = hero.y + goy;
116 nh.x = hero.x + gox;
117 whichway = (goy + 1) * 3 + gox + 1;
118 switch(whichway) {
119 case 0: runch = 'y';
120 when 1: runch = 'k';
121 when 2: runch = 'u';
122 when 3: runch = 'h';
123 when 4: runch = '.'; /* shouldn't do */
124 when 5: runch = 'l';
125 when 6: runch = 'b';
126 when 7: runch = 'j';
127 when 8: runch = 'n';
128 }
129 }
130 }
131 }
132 if (running && ce(hero, nh))
133 after = running = FALSE;
134 ch = winat(nh.y, nh.x);
135 if (pl_on(ISHELD) && ch != 'F' && ch != 'd') {
136 msg("You are being held.");
137 return;
138 }
139 if (pl_off(ISETHER)) {
140 if (isatrap(ch)) {
141 ch = be_trapped(&nh, &player);
142 if (nlmove) {
143 nlmove = FALSE;
144 return;
145 }
146 else if (ch == POOL)
147 inpool = TRUE;
148 }
149 else if (dead_end(ch)) {
150 after = running = FALSE;
151 return;
152 }
153 else {
154 switch(ch) {
155 case GOLD: case POTION: case SCROLL:
156 case FOOD: case WEAPON: case ARMOR:
157 case RING: case AMULET: case STICK:
158 running = FALSE;
159 take = ch;
160 default:
161 if (illeg_ch(ch)) {
162 running = FALSE;
163 mvaddch(nh.y, nh.x, FLOOR);
164 teleport(rndspot, &player);
165 light(&nh);
166 msg("The spatial warp disappears !");
167 return;
168 }
169 }
170 }
171 }
172 rp = roomin(&nh);
173 if (ch == DOOR) { /* just stepped on a door */
174 running = FALSE;
175 if (rp != NULL && rf_on(rp, ISTREAS)) {
176 struct linked_list *item;
177 struct thing *tp;
178
179 for (item = mlist; item != NULL; item = next(item)) {
180 tp = THINGPTR(item);
181 if (tp->t_room == rp)
182 runto(&tp->t_pos, &hero);
183 }
184 }
185 }
186 else if (ch == STAIRS && pl_off(ISETHER))
187 running = FALSE;
188 else if (isalpha(ch) && pl_off(ISETHER)) {
189 running = FALSE;
190 fight(&nh, cur_weapon, FALSE);
191 return;
192 }
193 if (rp == NULL && player.t_room != NULL)
194 light(&hero); /* exiting a room */
195 else if (rp != NULL && player.t_room == NULL)
196 light(&nh); /* just entering a room */
197 if (pl_on(ISBLIND))
198 ch = ' ';
199 else
200 ch = player.t_oldch;
201 mvwaddch(cw, hero.y, hero.x, ch);
202 mvwaddch(cw, nh.y, nh.x, PLAYER);
203 hero = nh;
204 player.t_room = rp;
205 player.t_oldch = mvinch(hero.y, hero.x);
206 }
207
208 /*
209 * Called to illuminate a room.
210 * If it is dark, remove anything that might move.
211 */
212 light(cp)
213 struct coord *cp;
214 {
215 reg struct room *rp;
216 reg int j, k, x, y;
217 reg char ch, rch;
218 reg struct linked_list *item;
219
220 rp = roomin(cp);
221 if (rp == NULL)
222 return;
223 if (pl_on(ISBLIND)) {
224 for (j = 0; j < rp->r_max.y; j += 1) {
225 for (k = 0; k < rp->r_max.x; k += 1) {
226 y = rp->r_pos.y + j;
227 x = rp->r_pos.x + k;
228 mvwaddch(cw, y, x, ' ');
229 }
230 }
231 look(FALSE);
232 return;
233 }
234 if (iswearing(R_LIGHT))
235 rp->r_flags &= ~ISDARK;
236 for (j = 0; j < rp->r_max.y; j += 1) {
237 for (k = 0; k < rp->r_max.x; k += 1) {
238 y = rp->r_pos.y + j;
239 x = rp->r_pos.x + k;
240 if (levtype == MAZELEV && !cansee(y, x))
241 continue;
242 ch = show(y, x);
243 wmove(cw, y, x);
244 /*
245 * Figure out how to display a secret door
246 */
247 if (ch == SECRETDOOR) {
248 if (j == 0 || j == rp->r_max.y - 1)
249 ch = '-';
250 else
251 ch = '|';
252 }
253 if (isalpha(ch)) {
254 struct thing *mit;
255
256 item = wake_monster(y, x);
257 if (item == NULL) {
258 ch = FLOOR;
259 mvaddch(y, x, ch);
260 }
261 else {
262 mit = THINGPTR(item);
263 if (mit->t_oldch == ' ')
264 if (!rf_on(rp,ISDARK))
265 mit->t_oldch = mvinch(y, x);
266 if (levtype == MAZELEV)
267 ch = mvinch(y, x);
268 }
269 }
270 if (rf_on(rp,ISDARK)) {
271 rch = mvwinch(cw, y, x);
272 if (isatrap(rch)) {
273 ch = rch; /* if its a trap */
274 }
275 else { /* try other things */
276 switch (rch) {
277 case DOOR: case STAIRS: case '|':
278 case '-':
279 ch = rch;
280 otherwise:
281 ch = ' ';
282 }
283 }
284 }
285 mvwaddch(cw, y, x, ch);
286 }
287 }
288 }
289
290 /*
291 * show:
292 * returns what a certain thing will display as to the un-initiated
293 */
294 show(y, x)
295 int y, x;
296 {
297 reg char ch = winat(y, x);
298 reg struct linked_list *it;
299 reg struct thing *tp;
300 reg struct trap *ta;
301
302 if (isatrap(ch)) {
303 if ((ta = trap_at(y, x)) == NULL)
304 return FLOOR;
305 if (iswearing(R_FTRAPS))
306 ta->tr_flags |= ISFOUND;
307 return ((ta->tr_flags & ISFOUND) ? ta->tr_type : FLOOR);
308 }
309 if (ch == SECRETDOOR && iswearing(R_FTRAPS)) {
310 mvaddch(y,x,DOOR);
311 return DOOR;
312 }
313 if ((it = find_mons(y, x)) != NULL) { /* maybe a monster */
314 tp = THINGPTR(it);
315 if (ch == 'M' || (tp->t_flags & ISINVIS)) {
316 if (ch == 'M')
317 ch = tp->t_disguise;
318 else if (pl_off(CANSEE)) {
319 if (ch == 's')
320 ch = ' '; /* shadows show as a blank */
321 else
322 ch = mvinch(y, x); /* hide invisibles */
323 }
324 }
325 }
326 return ch;
327 }
328
329 /*
330 * be_trapped:
331 * Hero or monster stepped on a trap.
332 */
333 be_trapped(tc, th)
334 struct thing *th;
335 struct coord *tc;
336 {
337 reg struct trap *trp;
338 reg int ch, ishero;
339 struct linked_list *mon;
340 char stuckee[35], seeit, sayso;
341
342 if ((trp = trap_at(tc->y, tc->x)) == NULL)
343 return;
344 ishero = (th == &player);
345 if (ishero) {
346 strcpy(stuckee, "You");
347 count = running = FALSE;
348 }
349 else {
350 sprintf(stuckee, "The %s", monsters[th->t_indx].m_name);
351 }
352 seeit = cansee(tc->y, tc->x);
353 if (seeit)
354 mvwaddch(cw, tc->y, tc->x, trp->tr_type);
355 trp->tr_flags |= ISFOUND;
356 sayso = TRUE;
357 switch (ch = trp->tr_type) {
358 case POST:
359 if (ishero) {
360 nlmove = TRUE;
361 new_level(POSTLEV);
362 }
363 else
364 goto goner;
365 when MAZETRAP:
366 if (ishero) {
367 nlmove = TRUE;
368 level += 1;
369 new_level(MAZELEV);
370 msg("You are surrounded by twisty passages!");
371 }
372 else
373 goto goner;
374 when TELTRAP:
375 nlmove = TRUE;
376 teleport(trp->tr_goto, th);
377 when TRAPDOOR:
378 if (ishero) {
379 level += 1;
380 new_level(NORMLEV);
381 }
382 else { /* monsters get lost */
383 goner:
384 ch = GONER;
385 }
386 nlmove = TRUE;
387 if (seeit && sayso)
388 msg("%s fell into a trap!", stuckee);
389 when BEARTRAP:
390 th->t_nomove += BEARTIME;
391 if (seeit) {
392 strcat(stuckee, (ishero ? " are" : " is"));
393 msg("%s caught in a bear trap.", stuckee);
394 }
395 when SLEEPTRAP:
396 if (ishero && pl_on(ISINVINC))
397 msg("You feel momentarily dizzy.");
398 else {
399 if (ishero)
400 th->t_nocmd += SLEEPTIME;
401 else
402 th->t_nomove += SLEEPTIME;
403 if (seeit)
404 msg("%s fall%s asleep in a strange white mist.",
405 stuckee, (ishero ? "":"s"));
406 }
407 when ARROWTRAP: {
408 int resist, ac;
409 struct stats *it;
410
411 stuckee[0] = tolower(stuckee[0]);
412 it = &th->t_stats;
413 if (ishero && cur_armor != NULL)
414 ac = cur_armor->o_ac;
415 else
416 ac = it->s_arm;
417 resist = ac + getpdex(it, FALSE);
418 if (ishero && pl_on(ISINVINC))
419 resist = -100; /* invincible is impossible to hit */
420 if (swing(3 + (level / 4), resist, 1)) {
421 if (seeit)
422 msg("%sAn arrow shot %s.", (ishero ? "Oh no! " : ""),
423 stuckee);
424 if (ishero)
425 chg_hpt(-roll(1,6),FALSE,K_ARROW);
426 else {
427 it->s_hpt -= roll(1,6);
428 if (it->s_hpt < 1) {
429 sayso = FALSE;
430 goto goner;
431 }
432 }
433 }
434 else {
435 struct linked_list *item;
436 struct object *arrow;
437
438 if (seeit)
439 msg("An arrow shoots past %s.", stuckee);
440 item = new_thing(FALSE, WEAPON, ARROW);
441 arrow = OBJPTR(item);
442 arrow->o_hplus = 3;
443 arrow->o_dplus = rnd(2);
444 arrow->o_count = 1;
445 arrow->o_pos = th->t_pos;
446 fall(item, FALSE);
447 }
448 }
449 when DARTTRAP: {
450 int resist, ac;
451 struct stats *it;
452
453 stuckee[0] = tolower(stuckee[0]);
454 it = &th->t_stats;
455 if (ishero && cur_armor != NULL)
456 ac = cur_armor->o_ac;
457 else
458 ac = it->s_arm;
459 resist = ac + getpdex(it, FALSE);
460 if (ishero && pl_on(ISINVINC))
461 resist = -100; /* invincible is impossible to hit */
462 if (swing(3 + (level / 4), resist, 0)) {
463 if (seeit)
464 msg("A small dart just hit %s.", stuckee);
465 if (ishero) {
466 if (!save(VS_POISON))
467 chg_abil(CON,-1,TRUE);
468 if (!iswearing(R_SUSTSTR))
469 chg_abil(STR,-1,TRUE);
470 chg_hpt(-roll(1, 4),FALSE,K_DART);
471 }
472 else {
473 if (!save_throw(VS_POISON, th))
474 it->s_ef.a_str -= 1;
475 it->s_hpt -= roll(1, 4);
476 if (it->s_hpt < 1) {
477 sayso = FALSE;
478 goto goner;
479 }
480 }
481 }
482 else if (seeit)
483 msg("A small dart whizzes by %s.", stuckee);
484 }
485 when POOL:
486 if (!ishero && rnd(100) < 10) {
487 if (seeit)
488 msg("The %s drowns !!", stuckee);
489 goto goner;
490 }
491 if ((trp->tr_flags & ISGONE) && rnd(100) < 10) {
492 nlmove = TRUE;
493 if (rnd(100) < 15)
494 teleport(rndspot); /* teleport away */
495 else if(rnd(100) < 15 && level > 2) {
496 level -= rnd(2) + 1;
497 new_level(NORMLEV);
498 msg("You here a faint groan from below.");
499 }
500 else if(rnd(100) < 40) {
501 level += rnd(4);
502 new_level(NORMLEV);
503 msg("You find yourself in strange surroundings.");
504 }
505 else if(rnd(100) < 6 && pl_off(ISINVINC)) {
506 msg("Oh no!!! You drown in the pool!!! --More--");
507 wait_for(cw, ' ');
508 death(K_POOL);
509 }
510 else
511 nlmove = FALSE;
512 }
513 }
514 flushinp(); /* flush typeahead */
515 return ch;
516 }
517
518 /*
519 * dip_it:
520 * Dip an object into a magic pool
521 */
522 dip_it()
523 {
524 reg struct linked_list *what;
525 reg struct object *ob;
526 reg struct trap *tp;
527 reg int wh;
528
529 tp = trap_at(hero.y,hero.x);
530 if (tp == NULL || inpool == FALSE || (tp->tr_flags & ISGONE))
531 return;
532
533 if ((what = get_item("dip",0)) == NULL)
534 return;
535 ob = OBJPTR(what);
536 mpos = 0;
537 /*
538 * If hero is trying to dip an object OTHER than his
539 * current weapon, make sure that he could drop his
540 * current weapon
541 */
542 if (ob != cur_weapon) {
543 if (cur_weapon != NULL && o_on(cur_weapon, ISCURSED)) {
544 msg("You are unable to release your weapon.");
545 after = FALSE;
546 return;
547 }
548 }
549 if (ob == cur_armor) {
550 msg("You have to take off your armor before you can dip it.");
551 after = FALSE;
552 return;
553 }
554 else if (ob == cur_ring[LEFT] || ob == cur_ring[RIGHT]) {
555 msg("You have to take that ring off before you can dip it.");
556 after = FALSE;
557 return;
558 }
559 wh = ob->o_which;
560 tp->tr_flags |= ISGONE;
561 if (ob != NULL && o_off(ob,ISPROT)) {
562 setoflg(ob,ISKNOW);
563 switch(ob->o_type) {
564 case WEAPON:
565 if(rnd(100) < 20) { /* enchant weapon here */
566 if (o_off(ob,ISCURSED)) {
567 ob->o_hplus += 1;
568 ob->o_dplus += 1;
569 }
570 else { /* weapon was prev cursed here */
571 ob->o_hplus = rnd(2);
572 ob->o_dplus = rnd(2);
573 }
574 resoflg(ob,ISCURSED);
575 }
576 else if(rnd(100) < 10) { /* curse weapon here */
577 if (o_off(ob,ISCURSED)) {
578 ob->o_hplus = -(rnd(2)+1);
579 ob->o_dplus = -(rnd(2)+1);
580 }
581 else { /* if already cursed */
582 ob->o_hplus--;
583 ob->o_dplus--;
584 }
585 setoflg(ob,ISCURSED);
586 }
587 msg("The %s glows for a moment.",w_magic[wh].mi_name);
588 when ARMOR:
589 if (rnd(100) < 30) { /* enchant armor */
590 if(o_off(ob,ISCURSED))
591 ob->o_ac -= rnd(2) + 1;
592 else
593 ob->o_ac = -rnd(3)+ armors[wh].a_class;
594 resoflg(ob,ISCURSED);
595 }
596 else if(rnd(100) < 15){ /* curse armor */
597 if (o_off(ob,ISCURSED))
598 ob->o_ac = rnd(3)+ armors[wh].a_class;
599 else
600 ob->o_ac += rnd(2) + 1;
601 setoflg(ob,ISCURSED);
602 }
603 msg("The %s glows for a moment.",a_magic[wh].mi_name);
604 when STICK: {
605 int i;
606 struct rod *rd;
607
608 i = rnd(8) + 1;
609 if(rnd(100) < 25) /* add charges */
610 ob->o_charges += i;
611 else if(rnd(100) < 10) { /* remove charges */
612 if ((ob->o_charges -= i) < 0)
613 ob->o_charges = 0;
614 }
615 ws_know[wh] = TRUE;
616 rd = &ws_stuff[wh];
617 msg("The %s %s glows for a moment.",rd->ws_made,rd->ws_type);
618 }
619 when SCROLL:
620 s_know[wh] = TRUE;
621 msg("The '%s' scroll unfurls.",s_names[wh]);
622 when POTION:
623 p_know[wh] = TRUE;
624 msg("The %s potion bubbles for a moment.",p_colors[wh]);
625 when RING:
626 r_know[wh] = TRUE;
627 if (magring(ob)) {
628 if(rnd(100) < 25) { /* enchant ring */
629 if (o_off(ob,ISCURSED))
630 ob->o_ac += rnd(2) + 1;
631 else
632 ob->o_ac = rnd(2) + 1;
633 resoflg(ob,ISCURSED);
634 }
635 else if(rnd(100) < 10) { /* curse ring */
636 if (o_off(ob,ISCURSED))
637 ob->o_ac = -(rnd(2) + 1);
638 else
639 ob->o_ac -= (rnd(2) + 1);
640 setoflg(ob,ISCURSED);
641 }
642 }
643 msg("The %s ring vibrates for a moment.",r_stones[wh]);
644 otherwise:
645 msg("The pool bubbles for a moment.");
646 }
647 }
648 cur_weapon = ob; /* hero has to weild item to dip it */
649 }
650
651
652 /*
653 * trap_at:
654 * Find the trap at (y,x) on screen.
655 */
656 struct trap *
657 trap_at(y, x)
658 int y, x;
659 {
660 reg struct trap *tp, *ep;
661
662 ep = &traps[ntraps];
663 for (tp = traps; tp < ep; tp += 1)
664 if (tp->tr_pos.y == y && tp->tr_pos.x == x)
665 break;
666 if (tp >= ep)
667 tp = NULL;
668 return tp;
669 }
670
671 /*
672 * rndmove:
673 * move in a random direction if the monster/person is confused
674 */
675 struct coord *
676 rndmove(who)
677 struct thing *who;
678 {
679 reg int x, y, ex, ey, ch;
680 int nopen = 0;
681 struct linked_list *item;
682 static struct coord ret; /* what we will be returning */
683 static struct coord dest;
684
685 ret = who->t_pos;
686 /*
687 * Now go through the spaces surrounding the player and
688 * set that place in the array to true if the space can be
689 * moved into
690 */
691 ey = ret.y + 1;
692 ex = ret.x + 1;
693 for (y = who->t_pos.y - 1; y <= ey; y += 1) {
694 for (x = who->t_pos.x - 1; x <= ex; x += 1) {
695 if (!cordok(y, x))
696 continue;
697 ch = winat(y, x);
698 if (step_ok(ch)) {
699 dest.y = y;
700 dest.x = x;
701 if (!diag_ok(&who->t_pos, &dest))
702 continue;
703 if (ch == SCROLL && who != &player) {
704 /*
705 * check for scare monster scrolls
706 */
707 item = find_obj(y, x);
708 if (item != NULL && (OBJPTR(item))->o_which == S_SCARE)
709 continue;
710 }
711 if (rnd(++nopen) == 0)
712 ret = dest;
713 }
714 }
715 }
716 return &ret;
717 }
718
719 /*
720 * isatrap:
721 * Returns TRUE if this character is some kind of trap
722 */
723 isatrap(ch)
724 char ch;
725 {
726 switch(ch) {
727 case POST:
728 case DARTTRAP:
729 case POOL:
730 case TELTRAP:
731 case TRAPDOOR:
732 case ARROWTRAP:
733 case SLEEPTRAP:
734 case BEARTRAP:
735 case MAZETRAP:
736 return TRUE;
737 default:
738 return FALSE;
739 }
740 }