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