|
|
1.1 root 1: /*
2: * Copyright (c) 1988 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Timothy C. Stoehr.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: static char sccsid[] = "@(#)move.c 5.3 (Berkeley) 6/1/90";
25: #endif /* not lint */
26:
27: /*
28: * move.c
29: *
30: * This source herein may be modified and/or distributed by anybody who
31: * so desires, with the following restrictions:
32: * 1.) No portion of this notice shall be removed.
33: * 2.) Credit shall not be taken for the creation of this source.
34: * 3.) This code is not to be traded, sold, or used for personal
35: * gain or profit.
36: *
37: */
38:
39: #include "rogue.h"
40:
41: short m_moves = 0;
42: boolean jump = 0;
43: char *you_can_move_again = "you can move again";
44:
45: extern short cur_room, halluc, blind, levitate;
46: extern short cur_level, max_level;
47: extern short bear_trap, haste_self, confused;
48: extern short e_rings, regeneration, auto_search;
49: extern char hunger_str[];
50: extern boolean being_held, interrupted, r_teleport, passgo;
51:
52: one_move_rogue(dirch, pickup)
53: short dirch, pickup;
54: {
55: short row, col;
56: object *obj;
57: char desc[DCOLS];
58: short n, status, d;
59:
60: row = rogue.row;
61: col = rogue.col;
62:
63: if (confused) {
64: dirch = gr_dir();
65: }
66: (void) is_direction(dirch, &d);
67: get_dir_rc(d, &row, &col, 1);
68:
69: if (!can_move(rogue.row, rogue.col, row, col)) {
70: return(MOVE_FAILED);
71: }
72: if (being_held || bear_trap) {
73: if (!(dungeon[row][col] & MONSTER)) {
74: if (being_held) {
75: message("you are being held", 1);
76: } else {
77: message("you are still stuck in the bear trap", 0);
78: (void) reg_move();
79: }
80: return(MOVE_FAILED);
81: }
82: }
83: if (r_teleport) {
84: if (rand_percent(R_TELE_PERCENT)) {
85: tele();
86: return(STOPPED_ON_SOMETHING);
87: }
88: }
89: if (dungeon[row][col] & MONSTER) {
90: rogue_hit(object_at(&level_monsters, row, col), 0);
91: (void) reg_move();
92: return(MOVE_FAILED);
93: }
94: if (dungeon[row][col] & DOOR) {
95: if (cur_room == PASSAGE) {
96: cur_room = get_room_number(row, col);
97: light_up_room(cur_room);
98: wake_room(cur_room, 1, row, col);
99: } else {
100: light_passage(row, col);
101: }
102: } else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
103: (dungeon[row][col] & TUNNEL)) {
104: light_passage(row, col);
105: wake_room(cur_room, 0, rogue.row, rogue.col);
106: darken_room(cur_room);
107: cur_room = PASSAGE;
108: } else if (dungeon[row][col] & TUNNEL) {
109: light_passage(row, col);
110: }
111: mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
112: mvaddch(row, col, rogue.fchar);
113:
114: if (!jump) {
115: refresh();
116: }
117: rogue.row = row;
118: rogue.col = col;
119: if (dungeon[row][col] & OBJECT) {
120: if (levitate && pickup) {
121: return(STOPPED_ON_SOMETHING);
122: }
123: if (pickup && !levitate) {
124: if (obj = pick_up(row, col, &status)) {
125: get_desc(obj, desc);
126: if (obj->what_is == GOLD) {
127: free_object(obj);
128: goto NOT_IN_PACK;
129: }
130: } else if (!status) {
131: goto MVED;
132: } else {
133: goto MOVE_ON;
134: }
135: } else {
136: MOVE_ON:
137: obj = object_at(&level_objects, row, col);
138: (void) strcpy(desc, "moved onto ");
139: get_desc(obj, desc+11);
140: goto NOT_IN_PACK;
141: }
142: n = strlen(desc);
143: desc[n] = '(';
144: desc[n+1] = obj->ichar;
145: desc[n+2] = ')';
146: desc[n+3] = 0;
147: NOT_IN_PACK:
148: message(desc, 1);
149: (void) reg_move();
150: return(STOPPED_ON_SOMETHING);
151: }
152: if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
153: if ((!levitate) && (dungeon[row][col] & TRAP)) {
154: trap_player(row, col);
155: }
156: (void) reg_move();
157: return(STOPPED_ON_SOMETHING);
158: }
159: MVED: if (reg_move()) { /* fainted from hunger */
160: return(STOPPED_ON_SOMETHING);
161: }
162: return((confused ? STOPPED_ON_SOMETHING : MOVED));
163: }
164:
165: multiple_move_rogue(dirch)
166: short dirch;
167: {
168: short row, col;
169: short m;
170:
171: switch(dirch) {
172: case '\010':
173: case '\012':
174: case '\013':
175: case '\014':
176: case '\031':
177: case '\025':
178: case '\016':
179: case '\002':
180: do {
181: row = rogue.row;
182: col = rogue.col;
183: if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
184: (m == STOPPED_ON_SOMETHING) ||
185: interrupted) {
186: break;
187: }
188: } while (!next_to_something(row, col));
189: if ( (!interrupted) && passgo && (m == MOVE_FAILED) &&
190: (dungeon[rogue.row][rogue.col] & TUNNEL)) {
191: turn_passage(dirch + 96, 0);
192: }
193: break;
194: case 'H':
195: case 'J':
196: case 'K':
197: case 'L':
198: case 'B':
199: case 'Y':
200: case 'U':
201: case 'N':
202: while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ;
203:
204: if ( (!interrupted) && passgo &&
205: (dungeon[rogue.row][rogue.col] & TUNNEL)) {
206: turn_passage(dirch + 32, 1);
207: }
208: break;
209: }
210: }
211:
212: is_passable(row, col)
213: register row, col;
214: {
215: if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
216: (col > (DCOLS-1))) {
217: return(0);
218: }
219: if (dungeon[row][col] & HIDDEN) {
220: return((dungeon[row][col] & TRAP) ? 1 : 0);
221: }
222: return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
223: }
224:
225: next_to_something(drow, dcol)
226: register drow, dcol;
227: {
228: short i, j, i_end, j_end, row, col;
229: short pass_count = 0;
230: unsigned short s;
231:
232: if (confused) {
233: return(1);
234: }
235: if (blind) {
236: return(0);
237: }
238: i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
239: j_end = (rogue.col < (DCOLS-1)) ? 1 : 0;
240:
241: for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
242: for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
243: if ((i == 0) && (j == 0)) {
244: continue;
245: }
246: if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) {
247: continue;
248: }
249: row = rogue.row + i;
250: col = rogue.col + j;
251: s = dungeon[row][col];
252: if (s & HIDDEN) {
253: continue;
254: }
255: /* If the rogue used to be right, up, left, down, or right of
256: * row,col, and now isn't, then don't stop */
257: if (s & (MONSTER | OBJECT | STAIRS)) {
258: if (((row == drow) || (col == dcol)) &&
259: (!((row == rogue.row) || (col == rogue.col)))) {
260: continue;
261: }
262: return(1);
263: }
264: if (s & TRAP) {
265: if (!(s & HIDDEN)) {
266: if (((row == drow) || (col == dcol)) &&
267: (!((row == rogue.row) || (col == rogue.col)))) {
268: continue;
269: }
270: return(1);
271: }
272: }
273: if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
274: if (++pass_count > 1) {
275: return(1);
276: }
277: }
278: if ((s & DOOR) && ((i == 0) || (j == 0))) {
279: return(1);
280: }
281: }
282: }
283: return(0);
284: }
285:
286: can_move(row1, col1, row2, col2)
287: {
288: if (!is_passable(row2, col2)) {
289: return(0);
290: }
291: if ((row1 != row2) && (col1 != col2)) {
292: if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
293: return(0);
294: }
295: if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
296: return(0);
297: }
298: }
299: return(1);
300: }
301:
302: move_onto()
303: {
304: short ch, d;
305: boolean first_miss = 1;
306:
307: while (!is_direction(ch = rgetchar(), &d)) {
308: sound_bell();
309: if (first_miss) {
310: message("direction? ", 0);
311: first_miss = 0;
312: }
313: }
314: check_message();
315: if (ch != CANCEL) {
316: (void) one_move_rogue(ch, 0);
317: }
318: }
319:
320: boolean
321: is_direction(c, d)
322: short c;
323: short *d;
324: {
325: switch(c) {
326: case 'h':
327: *d = LEFT;
328: break;
329: case 'j':
330: *d = DOWN;
331: break;
332: case 'k':
333: *d = UPWARD;
334: break;
335: case 'l':
336: *d = RIGHT;
337: break;
338: case 'b':
339: *d = DOWNLEFT;
340: break;
341: case 'y':
342: *d = UPLEFT;
343: break;
344: case 'u':
345: *d = UPRIGHT;
346: break;
347: case 'n':
348: *d = DOWNRIGHT;
349: break;
350: case CANCEL:
351: break;
352: default:
353: return(0);
354: }
355: return(1);
356: }
357:
358: boolean
359: check_hunger(msg_only)
360: boolean msg_only;
361: {
362: register short i, n;
363: boolean fainted = 0;
364:
365: if (rogue.moves_left == HUNGRY) {
366: (void) strcpy(hunger_str, "hungry");
367: message(hunger_str, 0);
368: print_stats(STAT_HUNGER);
369: }
370: if (rogue.moves_left == WEAK) {
371: (void) strcpy(hunger_str, "weak");
372: message(hunger_str, 1);
373: print_stats(STAT_HUNGER);
374: }
375: if (rogue.moves_left <= FAINT) {
376: if (rogue.moves_left == FAINT) {
377: (void) strcpy(hunger_str, "faint");
378: message(hunger_str, 1);
379: print_stats(STAT_HUNGER);
380: }
381: n = get_rand(0, (FAINT - rogue.moves_left));
382: if (n > 0) {
383: fainted = 1;
384: if (rand_percent(40)) {
385: rogue.moves_left++;
386: }
387: message("you faint", 1);
388: for (i = 0; i < n; i++) {
389: if (coin_toss()) {
390: mv_mons();
391: }
392: }
393: message(you_can_move_again, 1);
394: }
395: }
396: if (msg_only) {
397: return(fainted);
398: }
399: if (rogue.moves_left <= STARVE) {
400: killed_by((object *) 0, STARVATION);
401: }
402:
403: switch(e_rings) {
404: /*case -2:
405: Subtract 0, i.e. do nothing.
406: break;*/
407: case -1:
408: rogue.moves_left -= (rogue.moves_left % 2);
409: break;
410: case 0:
411: rogue.moves_left--;
412: break;
413: case 1:
414: rogue.moves_left--;
415: (void) check_hunger(1);
416: rogue.moves_left -= (rogue.moves_left % 2);
417: break;
418: case 2:
419: rogue.moves_left--;
420: (void) check_hunger(1);
421: rogue.moves_left--;
422: break;
423: }
424: return(fainted);
425: }
426:
427: boolean
428: reg_move()
429: {
430: boolean fainted;
431:
432: if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
433: fainted = check_hunger(0);
434: } else {
435: fainted = 0;
436: }
437:
438: mv_mons();
439:
440: if (++m_moves >= 120) {
441: m_moves = 0;
442: wanderer();
443: }
444: if (halluc) {
445: if (!(--halluc)) {
446: unhallucinate();
447: } else {
448: hallucinate();
449: }
450: }
451: if (blind) {
452: if (!(--blind)) {
453: unblind();
454: }
455: }
456: if (confused) {
457: if (!(--confused)) {
458: unconfuse();
459: }
460: }
461: if (bear_trap) {
462: bear_trap--;
463: }
464: if (levitate) {
465: if (!(--levitate)) {
466: message("you float gently to the ground", 1);
467: if (dungeon[rogue.row][rogue.col] & TRAP) {
468: trap_player(rogue.row, rogue.col);
469: }
470: }
471: }
472: if (haste_self) {
473: if (!(--haste_self)) {
474: message("you feel yourself slowing down", 0);
475: }
476: }
477: heal();
478: if (auto_search > 0) {
479: search(auto_search, auto_search);
480: }
481: return(fainted);
482: }
483:
484: rest(count)
485: {
486: int i;
487:
488: interrupted = 0;
489:
490: for (i = 0; i < count; i++) {
491: if (interrupted) {
492: break;
493: }
494: (void) reg_move();
495: }
496: }
497:
498: gr_dir()
499: {
500: short d;
501:
502: d = get_rand(1, 8);
503:
504: switch(d) {
505: case 1:
506: d = 'j';
507: break;
508: case 2:
509: d = 'k';
510: break;
511: case 3:
512: d = 'l';
513: break;
514: case 4:
515: d = 'h';
516: break;
517: case 5:
518: d = 'y';
519: break;
520: case 6:
521: d = 'u';
522: break;
523: case 7:
524: d = 'b';
525: break;
526: case 8:
527: d = 'n';
528: break;
529: }
530: return(d);
531: }
532:
533: heal()
534: {
535: static short heal_exp = -1, n, c = 0;
536: static boolean alt;
537:
538: if (rogue.hp_current == rogue.hp_max) {
539: c = 0;
540: return;
541: }
542: if (rogue.exp != heal_exp) {
543: heal_exp = rogue.exp;
544:
545: switch(heal_exp) {
546: case 1:
547: n = 20;
548: break;
549: case 2:
550: n = 18;
551: break;
552: case 3:
553: n = 17;
554: break;
555: case 4:
556: n = 14;
557: break;
558: case 5:
559: n = 13;
560: break;
561: case 6:
562: n = 10;
563: break;
564: case 7:
565: n = 9;
566: break;
567: case 8:
568: n = 8;
569: break;
570: case 9:
571: n = 7;
572: break;
573: case 10:
574: n = 4;
575: break;
576: case 11:
577: n = 3;
578: break;
579: case 12:
580: default:
581: n = 2;
582: }
583: }
584: if (++c >= n) {
585: c = 0;
586: rogue.hp_current++;
587: if (alt = !alt) {
588: rogue.hp_current++;
589: }
590: if ((rogue.hp_current += regeneration) > rogue.hp_max) {
591: rogue.hp_current = rogue.hp_max;
592: }
593: print_stats(STAT_HP);
594: }
595: }
596:
597: static boolean
598: can_turn(nrow, ncol)
599: short nrow, ncol;
600: {
601: if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
602: return(1);
603: }
604: return(0);
605: }
606:
607: turn_passage(dir, fast)
608: short dir;
609: boolean fast;
610: {
611: short crow = rogue.row, ccol = rogue.col, turns = 0;
612: short ndir;
613:
614: if ((dir != 'h') && can_turn(crow, ccol + 1)) {
615: turns++;
616: ndir = 'l';
617: }
618: if ((dir != 'l') && can_turn(crow, ccol - 1)) {
619: turns++;
620: ndir = 'h';
621: }
622: if ((dir != 'k') && can_turn(crow + 1, ccol)) {
623: turns++;
624: ndir = 'j';
625: }
626: if ((dir != 'j') && can_turn(crow - 1, ccol)) {
627: turns++;
628: ndir = 'k';
629: }
630: if (turns == 1) {
631: multiple_move_rogue(ndir - (fast ? 32 : 96));
632: }
633: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.