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