Annotation of early-roguelike/srogue/move.c, Revision 1.1.1.1
1.1 rubenllo 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 <string.h>
18: #include <ctype.h>
19: #include "rogue.h"
20: #include "rogue.ext"
21:
22: /*
23: * Used to hold the new hero position
24: */
25:
26: struct coord nh;
27:
28: /*
29: * do_run:
30: * Start the hero running
31: */
32:
33: void
34: do_run(char ch)
35: {
36: running = TRUE;
37: after = FALSE;
38: runch = ch;
39: }
40:
41: /*
42: * do_move:
43: * Check to see that a move is legal. If it is handle the
44: * consequences (fighting, picking up, etc.)
45: */
46:
47: void
48: do_move(int dy, int dx)
49: {
50: reg int ch;
51: reg struct room *rp;
52:
53: firstmove = FALSE;
54: curprice = -1;
55: inpool = FALSE;
56:
57: if (player.t_nomove > 0) {
58: player.t_nomove -= 1;
59: msg("You are still stuck in the bear trap.");
60: return;
61: }
62: /*
63: * Do a confused move (maybe)
64: */
65: if ((rnd(100) < 80 && pl_on(ISHUH)) ||
66: (iswearing(R_DELUS) && rnd(100) < 25))
67: nh = *rndmove(&player);
68: else {
69: nh.y = hero.y + dy;
70: nh.x = hero.x + dx;
71: }
72: /*
73: * Check if he tried to move off the screen or make
74: * an illegal diagonal move, and stop him if he did.
75: */
76: if (!cordok(nh.y, nh.x) ||
77: (pl_off(ISETHER) && !diag_ok(&hero, &nh))) {
78: after = running = FALSE;
79: return;
80: }
81: if (running) {
82: ch = winat(nh.y, nh.x);
83: if (dead_end(ch)) {
84: reg int gox, goy, apsg, whichway;
85:
86: gox = goy = apsg = 0;
87: if (dy == 0) {
88: ch = show(hero.y+1,hero.x);
89: if (ch == PASSAGE) {
90: apsg += 1;
91: goy = 1;
92: }
93: ch = show(hero.y-1,hero.x);
94: if (ch == PASSAGE) {
95: apsg += 1;
96: goy = -1;
97: }
98: }
99: else if (dx == 0) {
100: ch = show(hero.y,hero.x+1);
101: if (ch == PASSAGE) {
102: gox = 1;
103: apsg += 1;
104: }
105: ch = show(hero.y,hero.x-1);
106: if (ch == PASSAGE) {
107: gox = -1;
108: apsg += 1;
109: }
110: }
111: if (apsg != 1) {
112: running = after = FALSE;
113: return;
114: }
115: else { /* can still run here */
116: nh.y = hero.y + goy;
117: nh.x = hero.x + gox;
118: whichway = (goy + 1) * 3 + gox + 1;
119: switch(whichway) {
120: case 0: runch = 'y';
121: when 1: runch = 'k';
122: when 2: runch = 'u';
123: when 3: runch = 'h';
124: when 4: runch = '.'; /* shouldn't do */
125: when 5: runch = 'l';
126: when 6: runch = 'b';
127: when 7: runch = 'j';
128: when 8: runch = 'n';
129: }
130: }
131: }
132: }
133: if (running && ce(hero, nh))
134: after = running = FALSE;
135: ch = winat(nh.y, nh.x);
136: if (pl_on(ISHELD) && ch != 'F' && ch != 'd') {
137: msg("You are being held.");
138: return;
139: }
140: if (pl_off(ISETHER)) {
141: if (isatrap(ch)) {
142: ch = be_trapped(&nh, &player);
143: if (nlmove) {
144: nlmove = FALSE;
145: return;
146: }
147: else if (ch == POOL)
148: inpool = TRUE;
149: }
150: else if (dead_end(ch)) {
151: after = running = FALSE;
152: return;
153: }
154: else {
155: switch(ch) {
156: case GOLD: case POTION: case SCROLL:
157: case FOOD: case WEAPON: case ARMOR:
158: case RING: case AMULET: case STICK:
159: running = FALSE;
160: take = ch;
161: default:
162: if (illeg_ch(ch)) {
163: running = FALSE;
164: mvaddch(nh.y, nh.x, FLOOR);
165: teleport(rndspot, &player);
166: light(&nh);
167: msg("The spatial warp disappears !");
168: return;
169: }
170: }
171: }
172: }
173: rp = roomin(&nh);
174: if (ch == DOOR) { /* just stepped on a door */
175: running = FALSE;
176: if (rp != NULL && rf_on(rp, ISTREAS)) {
177: struct linked_list *item;
178: struct thing *tp;
179:
180: for (item = mlist; item != NULL; item = next(item)) {
181: tp = THINGPTR(item);
182: if (tp->t_room == rp)
183: runto(&tp->t_pos, &hero);
184: }
185: }
186: }
187: else if (ch == STAIRS && pl_off(ISETHER))
188: running = FALSE;
189: else if (isalpha(ch) && pl_off(ISETHER)) {
190: running = FALSE;
191: fight(&nh, cur_weapon, FALSE);
192: return;
193: }
194: if (rp == NULL && player.t_room != NULL)
195: light(&hero); /* exiting a room */
196: else if (rp != NULL && player.t_room == NULL)
197: light(&nh); /* just entering a room */
198: if (pl_on(ISBLIND))
199: ch = ' ';
200: else
201: ch = player.t_oldch;
202: mvwaddch(cw, hero.y, hero.x, ch);
203: mvwaddch(cw, nh.y, nh.x, PLAYER);
204: hero = nh;
205: player.t_room = rp;
206: player.t_oldch = mvinch(hero.y, hero.x);
207: }
208:
209: /*
210: * Called to illuminate a room.
211: * If it is dark, remove anything that might move.
212: */
213: void
214: light(struct coord *cp)
215: {
216: reg struct room *rp;
217: reg int j, k, x, y;
218: reg char ch, rch;
219: reg struct linked_list *item;
220:
221: rp = roomin(cp);
222: if (rp == NULL)
223: return;
224: if (pl_on(ISBLIND)) {
225: for (j = 0; j < rp->r_max.y; j += 1) {
226: for (k = 0; k < rp->r_max.x; k += 1) {
227: y = rp->r_pos.y + j;
228: x = rp->r_pos.x + k;
229: mvwaddch(cw, y, x, ' ');
230: }
231: }
232: look(FALSE);
233: return;
234: }
235: if (iswearing(R_LIGHT))
236: rp->r_flags &= ~ISDARK;
237: for (j = 0; j < rp->r_max.y; j += 1) {
238: for (k = 0; k < rp->r_max.x; k += 1) {
239: y = rp->r_pos.y + j;
240: x = rp->r_pos.x + k;
241: if (levtype == MAZELEV && !cansee(y, x))
242: continue;
243: ch = show(y, x);
244: wmove(cw, y, x);
245: /*
246: * Figure out how to display a secret door
247: */
248: if (ch == SECRETDOOR) {
249: if (j == 0 || j == rp->r_max.y - 1)
250: ch = '-';
251: else
252: ch = '|';
253: }
254: if (isalpha(ch)) {
255: struct thing *mit;
256:
257: item = wake_monster(y, x);
258: if (item == NULL) {
259: ch = FLOOR;
260: mvaddch(y, x, ch);
261: }
262: else {
263: mit = THINGPTR(item);
264: if (mit->t_oldch == ' ')
265: if (!rf_on(rp,ISDARK))
266: mit->t_oldch = mvinch(y, x);
267: if (levtype == MAZELEV)
268: ch = mvinch(y, x);
269: }
270: }
271: if (rf_on(rp,ISDARK)) {
272: rch = mvwinch(cw, y, x);
273: if (isatrap(rch)) {
274: ch = rch; /* if its a trap */
275: }
276: else { /* try other things */
277: switch (rch) {
278: case DOOR: case STAIRS: case '|':
279: case '-':
280: ch = rch;
281: otherwise:
282: ch = ' ';
283: }
284: }
285: }
286: mvwaddch(cw, y, x, ch);
287: }
288: }
289: }
290:
291: /*
292: * show:
293: * returns what a certain thing will display as to the un-initiated
294: */
295: char
296: show(int y, int x)
297: {
298: reg char ch = winat(y, x);
299: reg struct linked_list *it;
300: reg struct thing *tp;
301: reg struct trap *ta;
302:
303: if (isatrap(ch)) {
304: if ((ta = trap_at(y, x)) == NULL)
305: return FLOOR;
306: if (iswearing(R_FTRAPS))
307: ta->tr_flags |= ISFOUND;
308: return ((ta->tr_flags & ISFOUND) ? ta->tr_type : FLOOR);
309: }
310: if (ch == SECRETDOOR && iswearing(R_FTRAPS)) {
311: mvaddch(y,x,DOOR);
312: return DOOR;
313: }
314: if ((it = find_mons(y, x)) != NULL) { /* maybe a monster */
315: tp = THINGPTR(it);
316: if (ch == 'M' || (tp->t_flags & ISINVIS)) {
317: if (ch == 'M')
318: ch = tp->t_disguise;
319: else if (pl_off(CANSEE)) {
320: if (ch == 's')
321: ch = ' '; /* shadows show as a blank */
322: else
323: ch = mvinch(y, x); /* hide invisibles */
324: }
325: }
326: }
327: return ch;
328: }
329:
330: /*
331: * be_trapped:
332: * Hero or monster stepped on a trap.
333: */
334: int
335: be_trapped(struct coord *tc, struct thing *th)
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 0;
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, th); /* 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: void
523: dip_it(void)
524: {
525: reg struct linked_list *what;
526: reg struct object *ob;
527: reg struct trap *tp;
528: reg int wh;
529:
530: tp = trap_at(hero.y,hero.x);
531: if (tp == NULL || inpool == FALSE || (tp->tr_flags & ISGONE))
532: return;
533:
534: if ((what = get_item("dip",0)) == NULL)
535: return;
536: ob = OBJPTR(what);
537: mpos = 0;
538: /*
539: * If hero is trying to dip an object OTHER than his
540: * current weapon, make sure that he could drop his
541: * current weapon
542: */
543: if (ob != cur_weapon) {
544: if (cur_weapon != NULL && o_on(cur_weapon, ISCURSED)) {
545: msg("You are unable to release your weapon.");
546: after = FALSE;
547: return;
548: }
549: }
550: if (ob == cur_armor) {
551: msg("You have to take off your armor before you can dip it.");
552: after = FALSE;
553: return;
554: }
555: else if (ob == cur_ring[LEFT] || ob == cur_ring[RIGHT]) {
556: msg("You have to take that ring off before you can dip it.");
557: after = FALSE;
558: return;
559: }
560: wh = ob->o_which;
561: tp->tr_flags |= ISGONE;
562: if (ob != NULL && o_off(ob,ISPROT)) {
563: setoflg(ob,ISKNOW);
564: switch(ob->o_type) {
565: case WEAPON:
566: if(rnd(100) < 20) { /* enchant weapon here */
567: if (o_off(ob,ISCURSED)) {
568: ob->o_hplus += 1;
569: ob->o_dplus += 1;
570: }
571: else { /* weapon was prev cursed here */
572: ob->o_hplus = rnd(2);
573: ob->o_dplus = rnd(2);
574: }
575: resoflg(ob,ISCURSED);
576: }
577: else if(rnd(100) < 10) { /* curse weapon here */
578: if (o_off(ob,ISCURSED)) {
579: ob->o_hplus = -(rnd(2)+1);
580: ob->o_dplus = -(rnd(2)+1);
581: }
582: else { /* if already cursed */
583: ob->o_hplus--;
584: ob->o_dplus--;
585: }
586: setoflg(ob,ISCURSED);
587: }
588: msg("The %s glows for a moment.",w_magic[wh].mi_name);
589: when ARMOR:
590: if (rnd(100) < 30) { /* enchant armor */
591: if(o_off(ob,ISCURSED))
592: ob->o_ac -= rnd(2) + 1;
593: else
594: ob->o_ac = -rnd(3)+ armors[wh].a_class;
595: resoflg(ob,ISCURSED);
596: }
597: else if(rnd(100) < 15){ /* curse armor */
598: if (o_off(ob,ISCURSED))
599: ob->o_ac = rnd(3)+ armors[wh].a_class;
600: else
601: ob->o_ac += rnd(2) + 1;
602: setoflg(ob,ISCURSED);
603: }
604: msg("The %s glows for a moment.",a_magic[wh].mi_name);
605: when STICK: {
606: int i;
607: struct rod *rd;
608:
609: i = rnd(8) + 1;
610: if(rnd(100) < 25) /* add charges */
611: ob->o_charges += i;
612: else if(rnd(100) < 10) { /* remove charges */
613: if ((ob->o_charges -= i) < 0)
614: ob->o_charges = 0;
615: }
616: ws_know[wh] = TRUE;
617: rd = &ws_stuff[wh];
618: msg("The %s %s glows for a moment.",rd->ws_made,rd->ws_type);
619: }
620: when SCROLL:
621: s_know[wh] = TRUE;
622: msg("The '%s' scroll unfurls.",s_names[wh]);
623: when POTION:
624: p_know[wh] = TRUE;
625: msg("The %s potion bubbles for a moment.",p_colors[wh]);
626: when RING:
627: r_know[wh] = TRUE;
628: if (magring(ob)) {
629: if(rnd(100) < 25) { /* enchant ring */
630: if (o_off(ob,ISCURSED))
631: ob->o_ac += rnd(2) + 1;
632: else
633: ob->o_ac = rnd(2) + 1;
634: resoflg(ob,ISCURSED);
635: }
636: else if(rnd(100) < 10) { /* curse ring */
637: if (o_off(ob,ISCURSED))
638: ob->o_ac = -(rnd(2) + 1);
639: else
640: ob->o_ac -= (rnd(2) + 1);
641: setoflg(ob,ISCURSED);
642: }
643: }
644: msg("The %s ring vibrates for a moment.",r_stones[wh]);
645: otherwise:
646: msg("The pool bubbles for a moment.");
647: }
648: }
649: cur_weapon = ob; /* hero has to weild item to dip it */
650: }
651:
652:
653: /*
654: * trap_at:
655: * Find the trap at (y,x) on screen.
656: */
657: struct trap *
658: trap_at(int y, int 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(struct thing *who)
677: {
678: reg int x, y, ex, ey, ch;
679: int nopen = 0;
680: struct linked_list *item;
681: static struct coord ret; /* what we will be returning */
682: static struct coord dest;
683:
684: ret = who->t_pos;
685: /*
686: * Now go through the spaces surrounding the player and
687: * set that place in the array to true if the space can be
688: * moved into
689: */
690: ey = ret.y + 1;
691: ex = ret.x + 1;
692: for (y = who->t_pos.y - 1; y <= ey; y += 1) {
693: for (x = who->t_pos.x - 1; x <= ex; x += 1) {
694: if (!cordok(y, x))
695: continue;
696: ch = winat(y, x);
697: if (step_ok(ch)) {
698: dest.y = y;
699: dest.x = x;
700: if (!diag_ok(&who->t_pos, &dest))
701: continue;
702: if (ch == SCROLL && who != &player) {
703: /*
704: * check for scare monster scrolls
705: */
706: item = find_obj(y, x);
707: if (item != NULL && (OBJPTR(item))->o_which == S_SCARE)
708: continue;
709: }
710: if (rnd(++nopen) == 0)
711: ret = dest;
712: }
713: }
714: }
715: return &ret;
716: }
717:
718: /*
719: * isatrap:
720: * Returns TRUE if this character is some kind of trap
721: */
722: bool
723: isatrap(char ch)
724: {
725: switch(ch) {
726: case POST:
727: case DARTTRAP:
728: case POOL:
729: case TELTRAP:
730: case TRAPDOOR:
731: case ARROWTRAP:
732: case SLEEPTRAP:
733: case BEARTRAP:
734: case MAZETRAP:
735: return TRUE;
736: default:
737: return FALSE;
738: }
739: }
CVSweb