Annotation of early-roguelike/arogue5/move.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * Hero movement commands
3: *
4: * Advanced Rogue
5: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
6: * All rights reserved.
7: *
8: * Based on "Super-Rogue"
9: * Copyright (C) 1984 Robert D. Kindelberger
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 "rogue.h"
22:
23: /*
24: * Used to hold the new hero position
25: */
26:
27: static coord nh;
28:
29: static const char Moves[3][3] = {
30: { 'y', 'k', 'u' },
31: { 'h', '\0', 'l' },
32: { 'b', 'j', 'n' }
33: };
34:
35: /*
36: * be_trapped:
37: * The guy stepped on a trap.... Make him pay.
38: */
39:
40: char
41: be_trapped(struct thing *th, coord *tc)
42: {
43: register struct trap *tp;
44: register char ch;
45: register const char *mname = NULL;
46: register bool is_player = (th == &player),
47: can_see;
48: register struct linked_list *mitem = NULL;
49:
50:
51: /* Can the player see the creature? */
52: can_see = (cansee(tc->y, tc->x) && (is_player || !invisible(th)));
53:
54: tp = trap_at(tc->y, tc->x);
55: /*
56: * if he's wearing boots of elvenkind, he won't set off the trap
57: * unless its a magic pool (they're not really traps)
58: */
59: if (is_player &&
60: cur_misc[WEAR_BOOTS] != NULL &&
61: cur_misc[WEAR_BOOTS]->o_which == MM_ELF_BOOTS &&
62: tp->tr_type != POOL)
63: return '\0';
64:
65: /*
66: * if the creature is flying then it won't set off the trap
67: */
68: if (on(*th, ISFLY))
69: return '\0';
70:
71: tp->tr_flags |= ISFOUND;
72:
73: if (!is_player) {
74: mitem = find_mons(th->t_pos.y, th->t_pos.x);
75: mname = monsters[th->t_index].m_name;
76: }
77: else {
78: count = running = FALSE;
79: mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
80: }
81: switch (ch = tp->tr_type) {
82: case TRAPDOOR:
83: if (is_player) {
84: level++;
85: pstats.s_hpt -= roll(1, 10);
86: if (pstats.s_hpt <= 0) death(D_FALL);
87: new_level(NORMLEV);
88: msg("You fell into a trap!");
89: }
90: else {
91: if (can_see) msg("The %s fell into a trap!", mname);
92:
93: /* See if the fall killed the monster */
94: if ((th->t_stats.s_hpt -= roll(1, 10)) <= 0) {
95: killed(mitem, FALSE, FALSE);
96: }
97: else { /* Just move monster to next level */
98: check_residue(th);
99:
100: /* Erase the monster from the old position */
101: if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
102: mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
103: mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
104: turn_on(*th, ISELSEWHERE);
105: detach(mlist, mitem);
106: attach(tlist, mitem); /* remember him next level */
107: }
108: }
109: when BEARTRAP:
110: if (is_stealth(th)) {
111: if (is_player) msg("You pass a bear trap.");
112: else if (can_see) msg("The %s passes a bear trap.", mname);
113: }
114: else {
115: th->t_no_move += BEARTIME;
116: if (is_player) msg("You are caught in a bear trap.");
117: else if (can_see) msg("The %s is caught in a bear trap.",
118: mname);
119: }
120: when SLEEPTRAP:
121: if (is_player) {
122: msg("A strange white mist envelops you.");
123: if (!ISWEARING(R_ALERT)) {
124: msg("You fall asleep.");
125: no_command += SLEEPTIME;
126: }
127: }
128: else {
129: if (can_see)
130: msg("A strange white mist envelops the %s.",mname);
131: if (on(*th, ISUNDEAD)) {
132: if (can_see)
133: msg("The mist doesn't seem to affect the %s.",mname);
134: }
135: else {
136: th->t_no_move += SLEEPTIME;
137: }
138: }
139: when ARROWTRAP:
140: if (swing(th->t_ctype, th->t_stats.s_lvl-1, th->t_stats.s_arm, 1))
141: {
142: if (is_player) {
143: msg("Oh no! An arrow shot you.");
144: if ((pstats.s_hpt -= roll(1, 6)) <= 0) {
145: msg("The arrow killed you.");
146: death(D_ARROW);
147: }
148: }
149: else {
150: if (can_see) msg("An arrow shot the %s.", mname);
151: if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0) {
152: if (can_see) msg("The arrow killed the %s.", mname);
153: killed(mitem, FALSE, FALSE);
154: }
155: }
156: }
157: else
158: {
159: register struct linked_list *item;
160: register struct object *arrow;
161:
162: if (is_player) msg("An arrow shoots past you.");
163: else if (can_see) msg("An arrow shoots by the %s.", mname);
164: item = new_item(sizeof *arrow);
165: arrow = OBJPTR(item);
166: arrow->o_type = WEAPON;
167: arrow->contents = NULL;
168: arrow->o_which = ARROW;
169: arrow->o_hplus = rnd(3) - 1;
170: arrow->o_dplus = rnd(3) - 1;
171: init_weapon(arrow, ARROW);
172: arrow->o_count = 1;
173: arrow->o_pos = *tc;
174: arrow->o_mark[0] = '\0';
175: fall(item, FALSE);
176: }
177: when TELTRAP:
178: if (is_player) teleport();
179: else {
180: register int rm;
181: struct room *old_room; /* old room of monster */
182:
183: /*
184: * Erase the monster from the old position
185: */
186: if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
187: mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
188: mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
189: /*
190: * check to see if room should go dark
191: */
192: if (on(*th, HASFIRE)) {
193: old_room=roomin(&th->t_pos);
194: if (old_room != NULL) {
195: register struct linked_list *fire_item;
196:
197: for (fire_item = old_room->r_fires; fire_item != NULL;
198: fire_item = next(fire_item)) {
199: if (THINGPTR(fire_item) == th) {
200: detach(old_room->r_fires, fire_item);
201: destroy_item(fire_item);
202:
203: if (old_room->r_fires == NULL) {
204: old_room->r_flags &= ~HASFIRE;
205: if (can_see) light(&hero);
206: }
207: }
208: }
209: }
210: }
211:
212: /* Get a new position */
213: do {
214: rm = rnd_room();
215: rnd_pos(&rooms[rm], &th->t_pos);
216: } until(winat(th->t_pos.y, th->t_pos.x) == FLOOR);
217:
218: /* Put it there */
219: mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
220: th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
221: /*
222: * check to see if room that creature appears in should
223: * light up
224: */
225: if (on(*th, HASFIRE)) {
226: register struct linked_list *fire_item;
227:
228: fire_item = creat_item();
229: ldata(fire_item) = (char *) th;
230: attach(rooms[rm].r_fires, fire_item);
231:
232: rooms[rm].r_flags |= HASFIRE;
233: if(cansee(th->t_pos.y, th->t_pos.x) &&
234: next(rooms[rm].r_fires) == NULL)
235: light(&hero);
236: }
237: if (can_see) msg("The %s seems to have disappeared!", mname);
238: }
239: when DARTTRAP:
240: if (swing(th->t_ctype, th->t_stats.s_lvl+1, th->t_stats.s_arm, 1)) {
241: if (is_player) {
242: msg("A small dart just hit you in the shoulder.");
243: if ((pstats.s_hpt -= roll(1, 4)) <= 0) {
244: msg("The dart killed you.");
245: death(D_DART);
246: }
247:
248: /* Now the poison */
249: if (!save(VS_POISON, &player, 0)) {
250: /* 75% chance it will do point damage - else strength */
251: if (rnd(100) < 75) {
252: pstats.s_hpt /= 2;
253: if (pstats.s_hpt == 0) death(D_POISON);
254: }
255: else if (!ISWEARING(R_SUSABILITY))
256: chg_str(-1);
257: }
258: }
259: else {
260: if (can_see)
261: msg("A small dart just hit the %s in the shoulder.",
262: mname);
263: if ((th->t_stats.s_hpt -= roll(1,4)) <= 0) {
264: if (can_see) msg("The dart killed the %s.", mname);
265: killed(mitem, FALSE, FALSE);
266: }
267: if (!save(VS_POISON, th, 0)) {
268: th->t_stats.s_hpt /= 2;
269: if (th->t_stats.s_hpt <= 0) {
270: if (can_see) msg("The dart killed the %s.", mname);
271: killed(mitem, FALSE, FALSE);
272: }
273: }
274: }
275: }
276: else {
277: if (is_player)
278: msg("A small dart whizzes by your ear and vanishes.");
279: else if (can_see)
280: msg("A small dart whizzes by the %s's ear and vanishes.",
281: mname);
282: }
283: when POOL: {
284: register int i;
285:
286: i = rnd(100);
287: if (is_player) {
288: if ((tp->tr_flags & ISGONE)) {
289: if (i < 30) {
290: teleport(); /* teleport away */
291: pool_teleport = TRUE;
292: }
293: else if((i < 45) && level > 2) {
294: level -= rnd(2) + 1;
295: cur_max = level;
296: new_level(NORMLEV);
297: pool_teleport = TRUE;
298: msg("You here a faint groan from below.");
299: }
300: else if(i < 70) {
301: level += rnd(4) + 1;
302: new_level(NORMLEV);
303: pool_teleport = TRUE;
304: msg("You find yourself in strange surroundings.");
305: }
306: else if(i > 95) {
307: msg("Oh no!!! You drown in the pool!!! --More--");
308: wait_for(cw,' ');
309: death(D_DROWN);
310: }
311: }
312: }
313: else {
314: if (i < 60) {
315: if (can_see) {
316: /* Drowns */
317: if (i < 30) msg("The %s drowned in the pool!", mname);
318:
319: /* Teleported to another level */
320: else msg("The %s disappeared!", mname);
321: }
322: killed(mitem, FALSE, FALSE);
323: }
324: }
325: }
326: when MAZETRAP:
327: if (is_player) {
328: pstats.s_hpt -= roll(1, 10);
329: level++;
330: msg("You fell through a trap door!");
331: if (pstats.s_hpt <= 0) death(D_FALL);
332: new_level(MAZELEV);
333: msg("You are surrounded by twisty passages!");
334: }
335: else {
336: if (can_see) msg("The %s fell into a trap!", mname);
337: killed(mitem, FALSE, FALSE);
338: }
339: }
340:
341: /* Move the cursor back onto the hero */
342: wmove(cw, hero.y, hero.x);
343:
344: md_flushinp(); /* flush typeahead */
345:
346: return(ch);
347: }
348:
349: /*
350: * blue_light:
351: * magically light up a room (or level or make it dark)
352: */
353:
354: bool
355: blue_light(bool blessed, bool cursed)
356: {
357: register struct room *rp;
358: bool ret_val=FALSE; /* Whether or not affect is known */
359:
360: rp = roomin(&hero); /* What room is hero in? */
361:
362: /* Darken the room if the magic is cursed */
363: if (cursed) {
364: if ((rp == NULL) || !lit_room(rp)) msg(nothing);
365: else {
366: rp->r_flags |= ISDARK;
367: if (!lit_room(rp) && (levtype != OUTSIDE || !daytime))
368: msg("The %s suddenly goes dark.",
369: levtype == OUTSIDE ? "area" : "room");
370: else msg(nothing);
371: ret_val = TRUE;
372: }
373: }
374: else {
375: ret_val = TRUE;
376: if (rp && !lit_room(rp) &&
377: (levtype != OUTSIDE || !daytime)) {
378: addmsg("The %s is lit", levtype == OUTSIDE ? "area" : "room");
379: if (!terse)
380: addmsg(" by a %s blue light.",
381: blessed ? "bright" : "shimmering");
382: endmsg();
383: }
384: else if (winat(hero.y, hero.x) == PASSAGE)
385: msg("The corridor glows %sand then fades",
386: blessed ? "brightly " : "");
387: else {
388: ret_val = FALSE;
389: msg(nothing);
390: }
391: if (blessed) {
392: register int i; /* Index through rooms */
393:
394: for (i=0; i<MAXROOMS; i++)
395: rooms[i].r_flags &= ~ISDARK;
396: }
397: else if (rp) rp->r_flags &= ~ISDARK;
398: }
399:
400: /*
401: * Light the room and put the player back up
402: */
403: light(&hero);
404: mvwaddch(cw, hero.y, hero.x, PLAYER);
405: return(ret_val);
406: }
407:
408: /*
409: * corr_move:
410: * Check to see that a move is legal. If so, return correct character.
411: * If not, if player came from a legal place, then try to turn him.
412: */
413:
414: void
415: corr_move(int dy, int dx)
416: {
417: int legal=0; /* Number of legal alternatives */
418: register int y, x, /* Indexes though possible positions */
419: locy = 0, locx = 0; /* Hold delta of chosen location */
420:
421: /* New position */
422: nh.y = hero.y + dy;
423: nh.x = hero.x + dx;
424:
425: /* If it is a legal move, just return */
426: if (nh.x >= 0 && nh.x < COLS && nh.y > 0 && nh.y < LINES - 2) {
427:
428: switch (winat(nh.y, nh.x)) {
429: case WALL:
430: case '|':
431: case '-':
432: break;
433: default:
434: if (diag_ok(&hero, &nh, &player))
435: return;
436: }
437: }
438:
439: /* Check legal places surrounding the player -- ignore previous position */
440: for (y = hero.y - 1; y <= hero.y + 1; y++) {
441: if (y < 1 || y > LINES - 3)
442: continue;
443: for (x = hero.x - 1; x <= hero.x + 1; x++) {
444: /* Ignore borders of the screen */
445: if (x < 0 || x > COLS - 1)
446: continue;
447:
448: /*
449: * Ignore where we came from, where we are, and where we couldn't go
450: */
451: if ((x == hero.x - dx && y == hero.y - dy) ||
452: (x == hero.x + dx && y == hero.y + dy) ||
453: (x == hero.x && y == hero.y))
454: continue;
455:
456: switch (winat(y, x)) {
457: case WALL:
458: case '|':
459: case '-':
460: break;
461: default:
462: nh.y = y;
463: nh.x = x;
464: if (diag_ok(&hero, &nh, &player)) {
465: legal++;
466: locy = y - (hero.y - 1);
467: locx = x - (hero.x - 1);
468: }
469: }
470: }
471: }
472:
473: /* If we have 2 or more legal moves, make no change */
474: if (legal != 1) {
475: return;
476: }
477:
478: runch = Moves[locy][locx];
479:
480: /*
481: * For mazes, pretend like it is the beginning of a new run at each turn
482: * in order to get the lighting correct.
483: */
484: if (levtype == MAZELEV) firstmove = TRUE;
485: return;
486: }
487:
488: /*
489: * dip_it:
490: * Dip an object into a magic pool
491: */
492: void
493: dip_it(void)
494: {
495: reg struct linked_list *what;
496: reg struct object *ob;
497: reg struct trap *tp;
498: reg int wh, i;
499:
500: tp = trap_at(hero.y,hero.x);
501: if (tp == NULL || tp->tr_type != POOL) {
502: msg("I see no shimmering pool here");
503: return;
504: }
505: if (tp->tr_flags & ISGONE) {
506: msg("This shimmering pool appears to have used once already");
507: return;
508: }
509: if ((what = get_item(pack, "dip", ALL)) == NULL) {
510: msg("");
511: after = FALSE;
512: return;
513: }
514: ob = OBJPTR(what);
515: mpos = 0;
516: if (ob == cur_armor ||
517: ob == cur_misc[WEAR_BOOTS] || ob == cur_misc[WEAR_JEWEL] ||
518: ob == cur_misc[WEAR_GAUNTLET]|| ob == cur_misc[WEAR_CLOAK] ||
519: ob == cur_misc[WEAR_BRACERS] || ob == cur_misc[WEAR_NECKLACE]||
520: ob == cur_ring[LEFT_1] || ob == cur_ring[LEFT_2] ||
521: ob == cur_ring[LEFT_3] || ob == cur_ring[LEFT_4] ||
522: ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
523: ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4]) {
524: msg("You'll have to take it off first.");
525: return;
526: }
527: tp->tr_flags |= ISGONE;
528: if (ob != NULL) {
529: wh = ob->o_which;
530: ob->o_flags |= ISKNOW;
531: i = rnd(100);
532: switch(ob->o_type) {
533: case WEAPON:
534: if(i < 50) { /* enchant weapon here */
535: if ((ob->o_flags & ISCURSED) == 0) {
536: ob->o_hplus += 1;
537: ob->o_dplus += 1;
538: }
539: else { /* weapon was prev cursed here */
540: ob->o_hplus = rnd(2);
541: ob->o_dplus = rnd(2);
542: }
543: ob->o_flags &= ~ISCURSED;
544: msg("The %s glows blue for a moment.",weaps[wh].w_name);
545: }
546: else if(i < 70) { /* curse weapon here */
547: if ((ob->o_flags & ISCURSED) == 0) {
548: ob->o_hplus = -(rnd(2)+1);
549: ob->o_dplus = -(rnd(2)+1);
550: }
551: else { /* if already cursed */
552: ob->o_hplus--;
553: ob->o_dplus--;
554: }
555: ob->o_flags |= ISCURSED;
556: msg("The %s glows red for a moment.",weaps[wh].w_name);
557: }
558: else
559: msg(nothing);
560: when ARMOR:
561: if (i < 50) { /* enchant armor */
562: if((ob->o_flags & ISCURSED) == 0)
563: ob->o_ac -= rnd(2) + 1;
564: else
565: ob->o_ac = -rnd(3)+ armors[wh].a_class;
566: ob->o_flags &= ~ISCURSED;
567: msg("The %s glows blue for a moment",armors[wh].a_name);
568: }
569: else if(i < 75){ /* curse armor */
570: if ((ob->o_flags & ISCURSED) == 0)
571: ob->o_ac = rnd(3)+ armors[wh].a_class;
572: else
573: ob->o_ac += rnd(2) + 1;
574: ob->o_flags |= ISCURSED;
575: msg("The %s glows red for a moment.",armors[wh].a_name);
576: }
577: else
578: msg(nothing);
579: when STICK: {
580: int j;
581: j = rnd(8) + 1;
582: if(i < 50) { /* add charges */
583: ob->o_charges += j;
584: ws_know[wh] = TRUE;
585: if (ob->o_flags & ISCURSED)
586: ob->o_flags &= ~ISCURSED;
587: sprintf(outstring,"The %s %s glows blue for a moment.",
588: ws_made[wh],ws_type[wh]);
589: msg(outstring);
590: }
591: else if(i < 65) { /* remove charges */
592: if ((ob->o_charges -= i) < 0)
593: ob->o_charges = 0;
594: ws_know[wh] = TRUE;
595: if (ob->o_flags & ISBLESSED)
596: ob->o_flags &= ~ISBLESSED;
597: else
598: ob->o_flags |= ISCURSED;
599: sprintf(outstring,"The %s %s glows red for a moment.",
600: ws_made[wh],ws_type[wh]);
601: msg(outstring);
602: }
603: else
604: msg(nothing);
605: }
606: when SCROLL:
607: s_know[wh] = TRUE;
608: msg("The '%s' scroll unfurls.",s_names[wh]);
609: when POTION:
610: p_know[wh] = TRUE;
611: msg("The %s potion bubbles for a moment.",p_colors[wh]);
612: when RING:
613: if(i < 50) { /* enchant ring */
614: if ((ob->o_flags & ISCURSED) == 0)
615: ob->o_ac += rnd(2) + 1;
616: else
617: ob->o_ac = rnd(2) + 1;
618: ob->o_flags &= ~ISCURSED;
619: }
620: else if(i < 80) { /* curse ring */
621: if ((ob->o_flags & ISCURSED) == 0)
622: ob->o_ac = -(rnd(2) + 1);
623: else
624: ob->o_ac -= (rnd(2) + 1);
625: ob->o_flags |= ISCURSED;
626: }
627: r_know[wh] = TRUE;
628: msg("The %s ring vibrates for a moment.",r_stones[wh]);
629: when MM:
630: m_know[wh] = TRUE;
631: switch (ob->o_which) {
632: case MM_BRACERS:
633: case MM_PROTECT:
634: if(i < 50) { /* enchant item */
635: if ((ob->o_flags & ISCURSED) == 0)
636: ob->o_ac += rnd(2) + 1;
637: else
638: ob->o_ac = rnd(2) + 1;
639: ob->o_flags &= ~ISCURSED;
640: }
641: else if(i < 80) { /* curse item */
642: if ((ob->o_flags & ISCURSED) == 0)
643: ob->o_ac = -(rnd(2) + 1);
644: else
645: ob->o_ac -= (rnd(2) + 1);
646: ob->o_flags |= ISCURSED;
647: }
648: msg("The item vibrates for a moment.");
649: when MM_CHOKE:
650: case MM_DISAPPEAR:
651: ob->o_ac = 0;
652: msg ("The dust dissolves in the pool!");
653: }
654: otherwise:
655: msg("The pool bubbles for a moment.");
656: }
657: updpack(FALSE);
658: }
659: else
660: msg(nothing);
661: }
662:
663: /*
664: * do_move:
665: * Check to see that a move is legal. If it is handle the
666: * consequences (fighting, picking up, etc.)
667: */
668:
669: void
670: do_move(int dy, int dx)
671: {
672: register struct room *rp, *orp;
673: register char ch;
674: coord old_hero;
675: int i, wasfirstmove;
676:
677: wasfirstmove = firstmove;
678: firstmove = FALSE;
679: curprice = -1; /* if in trading post, we've moved off obj */
680: if (player.t_no_move) {
681: player.t_no_move--;
682: msg("You are still stuck in the bear trap");
683: return;
684: }
685: /*
686: * Do a confused move (maybe)
687: */
688: if ((on(player, ISHUH) && rnd(100) < 80) ||
689: (on(player, ISDANCE) && rnd(100) < 80) ||
690: (ISWEARING(R_DELUSION) && rnd(100) < 25))
691: nh = *rndmove(&player);
692: else {
693: nh.y = hero.y + dy;
694: nh.x = hero.x + dx;
695: }
696:
697: /*
698: * Check if he tried to move off the screen or make an illegal
699: * diagonal move, and stop him if he did.
700: */
701: if (nh.x < 0 || nh.x > COLS-1 || nh.y < 1 || nh.y >= LINES - 2
702: || !diag_ok(&hero, &nh, &player))
703: {
704: after = running = FALSE;
705: return;
706: }
707: if (running && ce(hero, nh))
708: after = running = FALSE;
709: ch = CCHAR( winat(nh.y, nh.x) );
710:
711: /* Take care of hero trying to move close to something frightening */
712: if (on(player, ISFLEE)) {
713: if (rnd(100) < 10) {
714: turn_off(player, ISFLEE);
715: msg("You regain your composure.");
716: }
717: else if (DISTANCE(nh.y, nh.x, player.t_dest->y, player.t_dest->x) <
718: DISTANCE(hero.y, hero.x, player.t_dest->y, player.t_dest->x))
719: return;
720: }
721:
722: /* Take care of hero being held */
723: if (on(player, ISHELD) && !isalpha(ch))
724: {
725: msg("You are being held");
726: return;
727: }
728:
729: /* assume he's not in a wall */
730: if (!isalpha(ch)) turn_off(player, ISINWALL);
731:
732: switch(ch) {
733: case '|':
734: case '-':
735: if (levtype == OUTSIDE) {
736: hero = nh;
737: new_level(OUTSIDE);
738: return;
739: }
740: case WALL:
741: case SECRETDOOR:
742: if (off(player, CANINWALL) || running) {
743: after = running = FALSE;
744:
745: /* Light if finishing run */
746: if (levtype == MAZELEV && lit_room(&rooms[0]))
747: look(FALSE, TRUE);
748:
749: after = running = FALSE;
750:
751: return;
752: }
753: turn_on(player, ISINWALL);
754: break;
755: case POOL:
756: if (levtype == OUTSIDE) {
757: lake_check(&nh);
758: running = FALSE;
759: break;
760: }
761: case MAZETRAP:
762: if (levtype == OUTSIDE) {
763: running = FALSE;
764: break;
765: }
766: case TRAPDOOR:
767: case TELTRAP:
768: case BEARTRAP:
769: case SLEEPTRAP:
770: case ARROWTRAP:
771: case DARTTRAP:
772: ch = be_trapped(&player, &nh);
773: if (ch == TRAPDOOR || ch == TELTRAP ||
774: pool_teleport || ch == MAZETRAP) {
775: pool_teleport = FALSE;
776: return;
777: }
778: break;
779: case GOLD:
780: case POTION:
781: case SCROLL:
782: case FOOD:
783: case WEAPON:
784: case ARMOR:
785: case RING:
786: case MM:
787: case RELIC:
788: case STICK:
789: running = FALSE;
790: take = ch;
791: break;
792: case DOOR:
793: case STAIRS:
794: running = FALSE;
795: break;
796: case POST:
797: running = FALSE;
798: new_level(POSTLEV);
799: return;
800: default:
801: break;
802: }
803:
804: if (isalpha(ch)) { /* if its a monster then fight it */
805: running = FALSE;
806: i = 1;
807: if (player.t_ctype == C_FIGHTER)
808: i += pstats.s_lvl/10;
809: while (i--)
810: fight(&nh, cur_weapon, FALSE);
811: return;
812: }
813:
814: /*
815: * if not fighting then move the hero
816: */
817: old_hero = hero; /* Save hero's old position */
818: hero = nh; /* Move the hero */
819: rp = roomin(&hero);
820: orp = roomin(&old_hero);
821:
822: /* Unlight any possible cross-corridor */
823: if (levtype == MAZELEV) {
824: register bool call_light = FALSE;
825: register char wall_check;
826:
827: if (wasfirstmove && lit_room(&rooms[0])) {
828: /* Are we moving out of a corridor? */
829: switch (runch) {
830: case 'h':
831: case 'l':
832: if (old_hero.y + 1 < LINES - 2) {
833: wall_check = CCHAR( winat(old_hero.y + 1, old_hero.x) );
834: if (!isrock(wall_check)) call_light = TRUE;
835: }
836: if (old_hero.y - 1 > 0) {
837: wall_check = CCHAR( winat(old_hero.y - 1, old_hero.x) );
838: if (!isrock(wall_check)) call_light = TRUE;
839: }
840: break;
841: case 'j':
842: case 'k':
843: if (old_hero.x + 1 < COLS) {
844: wall_check = CCHAR( winat(old_hero.y, old_hero.x + 1) );
845: if (!isrock(wall_check)) call_light = TRUE;
846: }
847: if (old_hero.x - 1 >= 0) {
848: wall_check = CCHAR( winat(old_hero.y, old_hero.x - 1) );
849: if (!isrock(wall_check)) call_light = TRUE;
850: }
851: break;
852: default:
853: call_light = TRUE;
854: }
855: player.t_oldpos = old_hero;
856: if (call_light) light(&old_hero);
857: }
858: }
859:
860: else if (orp != NULL && rp == NULL) { /* Leaving a room -- darken it */
861: orp->r_flags |= FORCEDARK; /* Fake darkness */
862: light(&old_hero);
863: orp->r_flags &= ~FORCEDARK; /* Restore light state */
864: }
865: else if (rp != NULL && orp == NULL){/* Entering a room */
866: light(&hero);
867: }
868: ch = CCHAR( winat(old_hero.y, old_hero.x) );
869: wmove(cw, unc(old_hero));
870: waddch(cw, ch);
871: wmove(cw, unc(hero));
872: waddch(cw, PLAYER);
873: }
874:
875: /*
876: * do_run:
877: * Start the hero running
878: */
879:
880: void
881: do_run(char ch)
882: {
883: firstmove = TRUE;
884: running = TRUE;
885: after = FALSE;
886: runch = ch;
887: }
888:
889: /*
890: * getdelta:
891: * Takes a movement character (eg. h, j, k, l) and returns the
892: * y and x delta corresponding to it in the remaining arguments.
893: * Returns TRUE if it could find it, FALSE otherwise.
894: */
895: bool
896: getdelta(char match, int *dy, int *dx)
897: {
898: int y, x;
899:
900: for (y = 0; y < 3; y++)
901: for (x = 0; x < 3; x++)
902: if (Moves[y][x] == match) {
903: *dy = y - 1;
904: *dx = x - 1;
905: return(TRUE);
906: }
907:
908: return(FALSE);
909: }
910:
911: /*
912: * isatrap:
913: * Returns TRUE if this character is some kind of trap
914: */
915: bool
916: isatrap(char ch)
917: {
918: switch(ch) {
919: case DARTTRAP:
920: case TELTRAP:
921: case TRAPDOOR:
922: case ARROWTRAP:
923: case SLEEPTRAP:
924: case BEARTRAP: return(TRUE);
925: case MAZETRAP:
926: case POOL: return(levtype != OUTSIDE);
927: default: return(FALSE);
928: }
929: }
930:
931: /*
932: * Called to illuminate a room.
933: * If it is dark, remove anything that might move.
934: */
935:
936: void
937: light(coord *cp)
938: {
939: register struct room *rp;
940: register int j, k, x, y;
941: register char ch, rch, sch;
942: register struct linked_list *item;
943: int jlow, jhigh, klow, khigh; /* Boundaries of lit area */
944:
945: if ((rp = roomin(cp)) != NULL) {
946: /*
947: * is he wearing ring of illumination?
948: */
949: if (&hero == cp && ISWEARING(R_LIGHT)) /* Must be hero's room */
950: rp->r_flags &= ~ISDARK;
951:
952: /* If we are in a maze, don't look at the whole room (level) */
953: if (levtype == MAZELEV) {
954: int see_radius;
955:
956: see_radius = 1;
957:
958: /* If we are looking at the hero in a rock, broaden our sights */
959: if (&hero == cp || &player.t_oldpos == cp) {
960: ch = CCHAR( winat(hero.y, hero.x) );
961: if (isrock(ch)) see_radius = 2;
962: ch = CCHAR( winat(player.t_oldpos.y, player.t_oldpos.x) );
963: if (isrock(ch)) see_radius = 2;
964: }
965:
966: jlow = max(0, cp->y - see_radius - rp->r_pos.y);
967: jhigh = min(rp->r_max.y, cp->y + see_radius + 1 - rp->r_pos.y);
968: klow = max(0, cp->x - see_radius - rp->r_pos.x);
969: khigh = min(rp->r_max.x, cp->x + see_radius + 1 - rp->r_pos.x);
970: }
971: else {
972: jlow = klow = 0;
973: jhigh = rp->r_max.y;
974: khigh = rp->r_max.x;
975: }
976: for (j = 0; j < rp->r_max.y; j++)
977: {
978: for (k = 0; k < rp->r_max.x; k++)
979: {
980: bool see_here = 0, see_before = 0;
981:
982: /* Is this in the give area -- needed for maze */
983: if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
984: continue;
985:
986: y = rp->r_pos.y + j;
987: x = rp->r_pos.x + k;
988:
989: /*
990: * If we are in a maze do not look at this area unless
991: * we can see it from where we are or where we last were
992: * (for erasing purposes).
993: */
994: if (levtype == MAZELEV) {
995: /* If we can't see it from here, could we see it before? */
996: if ((see_here = maze_view(y, x)) == FALSE) {
997: coord savhero;
998:
999: /* Could we see it from where we were? */
1000: savhero = hero;
1001: hero = player.t_oldpos;
1002: see_before = maze_view(y, x);
1003: hero = savhero;
1004:
1005: if (!see_before) continue;
1006: }
1007: }
1008:
1009: ch = show(y, x);
1010: wmove(cw, y, x);
1011: /*
1012: * Figure out how to display a secret door
1013: */
1014: if (ch == SECRETDOOR) {
1015: if (j == 0 || j == rp->r_max.y - 1)
1016: ch = '-';
1017: else
1018: ch = '|';
1019: }
1020: /* For monsters, if they were previously not seen and
1021: * now can be seen, or vice-versa, make sure that will
1022: * happen. This is for dark rooms as opposed to invisibility.
1023: *
1024: * Call winat() in the test because ch will not reveal
1025: * invisible monsters.
1026: */
1027: if (isalpha(winat(y, x))) {
1028: struct thing *tp; /* The monster */
1029:
1030: item = wake_monster(y, x);
1031: tp = THINGPTR(item);
1032:
1033: /* Previously not seen -- now can see it */
1034: if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x))
1035: tp->t_oldch = CCHAR( mvinch(y, x) );
1036:
1037: /* Previously seen -- now can't see it */
1038: else if (!cansee(tp->t_pos.y, tp->t_pos.x) &&
1039: roomin(&tp->t_pos) != NULL)
1040: switch (tp->t_oldch) {
1041: /*
1042: * Only blank it out if it is in a room and not
1043: * the border (or other wall) of the room.
1044: */
1045: case DOOR:
1046: case SECRETDOOR:
1047: case '-':
1048: case '|':
1049: break;
1050:
1051: otherwise:
1052: tp->t_oldch = ' ';
1053: }
1054: }
1055:
1056: /*
1057: * If the room is a dark room, we might want to remove
1058: * monsters and the like from it (since they might
1059: * move).
1060: * A dark room.
1061: */
1062: if ((!lit_room(rp) && (levtype != OUTSIDE)) ||
1063: (levtype == OUTSIDE && !daytime) ||
1064: on(player, ISBLIND) ||
1065: (rp->r_flags & FORCEDARK) ||
1066: (levtype == MAZELEV && !see_here && see_before)) {
1067: sch = CCHAR( mvwinch(cw, y, x) ); /* What's seen */
1068: rch = CCHAR( mvinch(y, x) ); /* What's really there */
1069: switch (rch) {
1070: case DOOR:
1071: case SECRETDOOR:
1072: case STAIRS:
1073: case TRAPDOOR:
1074: case TELTRAP:
1075: case BEARTRAP:
1076: case SLEEPTRAP:
1077: case ARROWTRAP:
1078: case DARTTRAP:
1079: case MAZETRAP:
1080: case POOL:
1081: case POST:
1082: case '|':
1083: case '-':
1084: case WALL:
1085: if (isalpha(sch)) ch = rch;
1086: else if (sch != FLOOR) ch = sch;
1087: else ch = ' '; /* Hide undiscoverd things */
1088: when FLOOR:
1089: ch = ' ';
1090: otherwise:
1091: ch = ' ';
1092: }
1093: /* Take care of our magic bookkeeping. */
1094: switch (sch) {
1095: case MAGIC:
1096: case BMAGIC:
1097: case CMAGIC:
1098: ch = sch;
1099: }
1100: }
1101: mvwaddch(cw, y, x, ch);
1102: }
1103: }
1104: }
1105: }
1106:
1107: /*
1108: * lit_room:
1109: * Called to see if the specified room is lit up or not.
1110: */
1111:
1112: bool
1113: lit_room(struct room *rp)
1114: {
1115: register struct linked_list *fire_item;
1116: register struct thing *fire_creature;
1117:
1118: if (!(rp->r_flags & ISDARK)) return(TRUE); /* A definitely lit room */
1119:
1120: /* Is it lit by fire light? */
1121: if (rp->r_flags & HASFIRE) {
1122: switch (levtype) {
1123: case MAZELEV:
1124: /* See if a fire creature is in line of sight */
1125: for (fire_item = rp->r_fires; fire_item != NULL;
1126: fire_item = next(fire_item)) {
1127: fire_creature = THINGPTR(fire_item);
1128: if (maze_view(fire_creature->t_pos.y,
1129: fire_creature->t_pos.x)) return(TRUE);
1130: }
1131:
1132: /* Couldn't find any in line-of-sight */
1133: return(FALSE);
1134:
1135: /* We should probably do something special for the outside */
1136: otherwise:
1137: return TRUE;
1138: }
1139: }
1140: return(FALSE);
1141: }
1142:
1143: /*
1144: * rndmove:
1145: * move in a random direction if the monster/person is confused
1146: */
1147:
1148: coord *
1149: rndmove(struct thing *who)
1150: {
1151: register int x, y;
1152: register int ex, ey, nopen = 0;
1153: static coord ret; /* what we will be returning */
1154: static coord dest;
1155:
1156: ret = who->t_pos;
1157: /*
1158: * Now go through the spaces surrounding the player and
1159: * set that place in the array to true if the space can be
1160: * moved into
1161: */
1162: ey = ret.y + 1;
1163: ex = ret.x + 1;
1164: for (y = who->t_pos.y - 1; y <= ey; y++)
1165: if (y > 0 && y < LINES - 2)
1166: for (x = who->t_pos.x - 1; x <= ex; x++)
1167: {
1168: if (x < 0 || x >= COLS)
1169: continue;
1170: if (step_ok(y, x, NOMONST, who) == TRUE)
1171: {
1172: dest.y = y;
1173: dest.x = x;
1174: if (!diag_ok(&who->t_pos, &dest, who))
1175: continue;
1176: if (rnd(++nopen) == 0)
1177: ret = dest;
1178: }
1179: }
1180: return &ret;
1181: }
1182:
1183:
1184:
1185: /*
1186: * set_trap:
1187: * set a trap at (y, x) on screen.
1188: */
1189:
1190: void
1191: set_trap(struct thing *tp, int y, int x)
1192: {
1193: register bool is_player = (tp == &player);
1194: register char selection = rnd(7) + '1';
1195: register char ch = 0, och;
1196: int thief_bonus = 0;
1197: int s_dext;
1198:
1199: switch (och = CCHAR( mvinch(y, x) )) {
1200: case WALL:
1201: case FLOOR:
1202: case PASSAGE:
1203: break;
1204: default:
1205: msg("The trap failed!");
1206: return;
1207: }
1208:
1209: if (is_player && player.t_ctype == C_THIEF) thief_bonus = 30;
1210:
1211: s_dext = (tp == &player) ? dex_compute() : tp->t_stats.s_dext;
1212:
1213: if (ntraps >= MAXTRAPS || ++trap_tries >= MAXTRPTRY || levtype == POSTLEV ||
1214: rnd(80) >= (s_dext + tp->t_stats.s_lvl/2 + thief_bonus)) {
1215: if (is_player) msg("The trap failed!");
1216: return;
1217: }
1218:
1219:
1220: if (is_player) {
1221: int state = 0; /* 0 -> current screen, 1 -> prompt screen, 2 -> done */
1222:
1223: msg("Which kind of trap do you wish to set? (* for a list): ");
1224: do {
1225: selection = tolower(readchar());
1226: switch (selection) {
1227: case '*':
1228: if (state != 1) {
1229: wclear(hw);
1230: touchwin(hw);
1231: mvwaddstr(hw, 2, 0, "[1] Trap Door\n[2] Bear Trap\n");
1232: waddstr(hw, "[3] Sleep Trap\n[4] Arrow Trap\n");
1233: waddstr(hw, "[5] Teleport Trap\n[6] Dart Trap\n");
1234: if (wizard) {
1235: waddstr(hw, "[7] Magic pool\n[8] Maze Trap\n");
1236: waddstr(hw, "[9] Trading Post\n");
1237: }
1238: mvwaddstr(hw, 0, 0, "Which kind of trap do you wish to set? ");
1239: draw(hw);
1240: state = 1; /* Now in prompt window */
1241: }
1242: break;
1243:
1244: case ESCAPE:
1245: if (state == 1) {
1246: clearok(cw, TRUE); /* Set up for redraw */
1247: touchwin(cw);
1248: }
1249: msg("");
1250:
1251: trap_tries--; /* Don't count this one */
1252: after = FALSE;
1253: return;
1254:
1255: case '1':
1256: case '2':
1257: case '3':
1258: case '4':
1259: case '5':
1260: case '6':
1261: case '7':
1262: case '8':
1263: case '9':
1264: if (selection < '7' || wizard) {
1265: if (state == 1) { /* In prompt window */
1266: clearok(cw, TRUE); /* Set up for redraw */
1267: touchwin(cw);
1268: }
1269:
1270: msg("");
1271:
1272: /* Make sure there is a floor below us for trap doors */
1273: if (selection == '1' && level >= nfloors) {
1274: if (state == 1) draw(cw);
1275: msg("There is no level below this one.");
1276: return;
1277: }
1278: state = 2; /* Finished */
1279: break;
1280: }
1281:
1282: /* Fall through for non-wizard, unusual trap case */
1283: default:
1284: if (state == 1) { /* In the prompt window */
1285: mvwaddstr(hw, 0, 0, "Please enter a selection between 1 and 6: ");
1286: draw(hw);
1287: }
1288: else { /* Normal window */
1289: mpos = 0;
1290: msg("Please enter a selection between 1 and 6: ");
1291: }
1292: }
1293: } while (state != 2);
1294: }
1295:
1296: switch (selection) {
1297: case '1': ch = TRAPDOOR;
1298: when '2': ch = BEARTRAP;
1299: when '3': ch = SLEEPTRAP;
1300: when '4': ch = ARROWTRAP;
1301: when '5': ch = TELTRAP;
1302: when '6': ch = DARTTRAP;
1303: when '7': ch = POOL;
1304: when '8': ch = MAZETRAP;
1305: when '9': ch = POST;
1306: }
1307:
1308: mvaddch(y, x, ch);
1309: traps[ntraps].tr_show = och;
1310: traps[ntraps].tr_type = ch;
1311: traps[ntraps].tr_pos.y = y;
1312: traps[ntraps].tr_pos.x = x;
1313: if (is_player)
1314: traps[ntraps].tr_flags = ISTHIEFSET;
1315: if (ch == POOL || ch == POST) {
1316: traps[ntraps].tr_flags |= ISFOUND;
1317: }
1318:
1319: ntraps++;
1320: }
1321:
1322: /*
1323: * show:
1324: * returns what a certain thing will display as to the un-initiated
1325: */
1326:
1327: char
1328: show(int y, int x)
1329: {
1330: register char ch = CCHAR( winat(y, x) );
1331: register struct linked_list *it;
1332: register struct thing *tp;
1333:
1334: if (isatrap(ch)) {
1335: register struct trap *trp = trap_at(y, x);
1336:
1337: return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
1338: }
1339: else if (isalpha(ch)) {
1340: if ((it = find_mons(y, x)) == NULL) {
1341: msg("Can't find monster in show");
1342: return(mvwinch(stdscr, y, x));
1343: }
1344: tp = THINGPTR(it);
1345:
1346: if (on(*tp, ISDISGUISE)) ch = tp->t_disguise; /* As a mimic */
1347:
1348: /* Hide invisible creatures */
1349: else if (invisible(tp)) {
1350: /* We can't see surprise-type creatures through "see invisible" */
1351: if (off(player,CANSEE) || on(*tp,CANSURPRISE))
1352: ch = CCHAR( mvwinch(stdscr, y, x) ); /* Invisible */
1353: }
1354: else if (on(*tp, CANINWALL)) {
1355: if (isrock(mvwinch(stdscr, y, x))) ch = CCHAR( winch(stdscr) ); /* As Xorn */
1356: }
1357: }
1358: return ch;
1359: }
1360:
1361:
1362: /*
1363: * trap_at:
1364: * find the trap at (y,x) on screen.
1365: */
1366:
1367: struct trap *
1368: trap_at(int y, int x)
1369: {
1370: register struct trap *tp, *ep;
1371:
1372: ep = &traps[ntraps];
1373: for (tp = traps; tp < ep; tp++)
1374: if (tp->tr_pos.y == y && tp->tr_pos.x == x)
1375: break;
1376: if (tp == ep)
1377: debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
1378: return tp;
1379: }
CVSweb